[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: JunkFood02\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: Create a report to help us improve\nlabels: [ bug, new issue ]\nbody:\n\n\n  - type: checkboxes\n    id: checklist\n    attributes:\n      label: Checklist\n      description: |\n        Carefully read and work through this check list in order to prevent the most common mistakes and misuse of Seal/Yt-dlp:\n      options:\n        - label: I'm reporting a bug unrelated to a specific site.\n          required: false\n        - label: I've verified that I'm running the [**latest version**](https://github.com/yt-dlp/yt-dlp/releases/latest) of yt-dlp.\n          required: true\n        - label: I've verified that I'm running the latest [**stable version**](https://github.com/JunkFood02/Seal/releases/latest/) of Seal or any later [**preview versions**](https://github.com/JunkFood02/Seal/releases).\n          required: true\n        - label: I've read the [**Contributing guidelines**](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) and [**Code Of Conduct.**](https://github.com/JunkFood02/Seal/blob/main/CODE_OF_CONDUCT.md)\n          required: true\n        - label: I've checked that the site i'm trying to download from is in the [**Supported Sites**](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md) list from yt-dlp\n          required: true\n        - label: I understand that the issue will be (ignored/closed) if I intentionally remove or skip any mandatory field.\n          required: true\n\n  - type: textarea\n    attributes:\n      label: Describe the bug\n      description:\n      placeholder: |\n        A clear and concise description of what the bug is.\n    validations:\n      required: false\n\n  - type: textarea\n    attributes:\n      label: To Reproduce\n      placeholder: |\n        Steps to reproduce the behavior:\n        1.Go to '...'\n        2.Click on '....'\n        3.Scroll down to '....'\n        4.See error\n    validations:\n      required: false\n\n  - type: textarea\n    attributes:\n      label: Error reports\n      placeholder: |\n        Click on the displayed error report to copy it.\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Screenshots & Screen Records\n      placeholder: |\n        Screenshots & Screen Records can amp up bug reports.\n    validations:\n      required: false\n\n  - type: textarea\n    attributes:\n      label: Additional context\n      description:\n      placeholder: |\n        Add any other context about the problem here.      \n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "# disable blank issue creation\nblank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Suggest a new feature for the app\nlabels: [ enhancement, new issue ]\nbody:\n  - type: checkboxes\n    id: checklist\n    attributes:\n      label: Checklist\n      description: |\n        Even if you're not sure about the answer, feel free to leave it blank and provide us with more information about this request.\n      options:\n        - label: This feature I'm requesting is already implemented in yt-dlp.\n          required: false\n        - label: This feature is merely a UI/UX update.\n          required: false\n        - label: This feature is suitable for primary users with little knowledge about yt-dlp.\n          required: false\n        - label: This feature is available for most websites, not only the video platform I use.\n          required: false\n        - label: This feature is suitable for a large variety of videos.\n          required: false\n        - label: This feature is not going to conflict with many of the existing options.\n          required: false\n  - type: textarea\n    id: description_1\n    attributes:\n      label: Is your feature request related to a problem? Please describe.\n      description:\n      placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n    validations:\n      required: false\n  - type: textarea\n    id: description_2\n    attributes:\n      label: Describe the solution you'd like\n      description:\n      placeholder: A clear and concise description of what you want to happen.\n    validations:\n      required: false\n  - type: textarea\n    id: description_3\n    attributes:\n      label: Video link\n      description:\n      placeholder: Please provide us with a link to the video for which this feature might be beneficial.\n    validations:\n      required: false\n  - type: textarea\n    id: description_4\n    attributes:\n      label: Additional context\n      description:\n      placeholder: Add any other context or screenshots about the feature request here.\n    validations:\n      required: false\n      render: shell\n"
  },
  {
    "path": ".github/workflows/Issue-Handler.yaml",
    "content": "# Name of the GitHub Action\nname: Check and Close Issues\n\n# Trigger the action on issue events, specifically when an issue is opened\non:\n  issues:\n    types: [opened]\n\n# Job definitions\njobs:\n  handle-issues:\n    # Run this job only for issues\n    if: github.event_name == 'issues'\n    # Specify the runner environment\n    runs-on: ubuntu-latest\n    steps:\n      # Step 1: Check out the repository code\n      - name: Check out code\n        uses: actions/checkout@v4\n\n      # Step 2: Set up Node.js environment (version 16)\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 16\n\n      # Step 3: Custom script to check and close issues\n      - name: Check and close issues\n        id: close-issues\n        uses: actions/github-script@v7\n        with:\n          github-token: ${{secrets.GITHUB_TOKEN}}\n          script: |\n            // Define keywords and labels for issue filtering\n            const keywordsToCheck = ['instagram', 'facebook', 'twitter', 'HTTP Error 403', 'not a bot'];\n            const requiredLabel = 'new issue';\n            const referenceIssueNumber = 1399;\n            const actionClosedLabel = 'action-closed'; // Unique label to track action-closed issues\n\n            // Function to process each issue\n            async function processIssue(issue) {\n              const issueBody = issue.body.toLowerCase();\n              const issueLabels = issue.labels.map(label => label.name);\n              const wasClosedByAction = issueLabels.includes(actionClosedLabel);\n\n              // Determine if the issue should be closed\n              const shouldCloseIssue = !wasClosedByAction && \n                keywordsToCheck.some(keyword => issueBody.includes(keyword)) && issueLabels.includes(requiredLabel);\n\n              // Close the issue if it meets the criteria\n              if (shouldCloseIssue) {\n                await github.rest.issues.update({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: issue.number,\n                  state: 'closed'\n                });\n\n                // Add labels and comment to the closed issue\n                await github.rest.issues.addLabels({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: issue.number,\n                  labels: ['duplicate', actionClosedLabel]\n                });\n\n                  await github.rest.issues.removeLabel({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: issue.number,\n                  name: requiredLabel\n                });\n\n                await github.rest.issues.createComment({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: issue.number,\n                  body: `This issue has been closed and labeled as duplicate. Please see issue #${referenceIssueNumber} for more details. If you believe this is not the case, you can reopen this issue.`\n                });\n              }\n            }\n\n            // Process newly opened issues\n            if (context.payload.action === 'opened') {\n              await processIssue(context.payload.issue);\n            }\n\n"
  },
  {
    "path": ".github/workflows/android.yml",
    "content": "name: Build Release APK\n\non:\n  workflow_dispatch:\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: set up JDK 21\n      uses: actions/setup-java@v4\n      with:\n        java-version: '21'\n        distribution: 'temurin'\n        cache: 'gradle'\n\n    - name: Setup Android SDK\n      uses: android-actions/setup-android@v3\n\n    - uses: gradle/actions/setup-gradle@v3\n\n    - run: gradle assembleRelease\n\n    - name: Sign app APK\n      id: sign_app\n      uses: ilharp/sign-android-release@nightly\n      with:\n        releaseDir: app/build/outputs/apk/release\n        signingKey: ${{ secrets.SIGNING_KEY }}\n        keyAlias: ${{ secrets.ALIAS }}\n        keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}\n        keyPassword: ${{ secrets.KEY_PASSWORD }}\n\n    - name: Upload Artifact\n      uses: actions/upload-artifact@v4\n      with:\n        name: signed-apks\n        path: app/build/outputs/apk/release/*-arm64-v8a-release-signed.apk\n        if-no-files-found: error\n        retention-days: 20\n"
  },
  {
    "path": ".github/workflows/android_ci.yml",
    "content": "name: Android CI\n\non:\n  pull_request:\n    branches: [ \"main\" ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: set up JDK 21\n        uses: actions/setup-java@v3\n        with:\n          java-version: '21'\n          distribution: 'temurin'\n          cache: gradle\n\n      - name: Setup Android SDK\n        uses: android-actions/setup-android@v3\n\n      - uses: gradle/actions/setup-gradle@v3\n      - name: Grant execute permission for gradlew\n        run: chmod +x gradlew\n      - name: Build with Gradle\n        run: ./gradlew buildGenericRelease\n"
  },
  {
    "path": ".github/workflows/close-stale-issues.yml",
    "content": "name: 'Close stale issues and PRs'\non:\n  schedule:\n    - cron: '0 0 1 * *'\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/stale@v9\n        with:\n          stale-issue-message: 'This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.'\n          days-before-stale: 90\n          days-before-close: 30\n"
  },
  {
    "path": ".github/workflows/sponsor.yml",
    "content": "name: Generate Sponsors README\non:\n  workflow_dispatch:\n  schedule:\n    - cron: 30 15 25 * *\n  \njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    if: ${{ github.repository == 'JunkFood02/Seal' }}\n    steps:\n      - name: Checkout 🛎️\n        uses: actions/checkout@v2\n\n      - name: Generate Sponsors 💖\n        uses: JamesIves/github-sponsors-readme-action@v1\n        with:\n          token: ${{ secrets.PAT }}\n          file: 'README.md'\n          minimum: 500\n\n      - name: Deploy to GitHub Pages 🚀\n        uses: JamesIves/github-pages-deploy-action@v4\n        with:\n          branch: main\n          token: ${{ secrets.PAT }}\n          folder: '.'\n          commit-message: 'docs(readme): update sponsor info'\n"
  },
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n/.idea/deploymentTargetDropDown.xml\n/.idea/shelf\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\nlocal.properties\n/keystore.properties\n.kotlin"
  },
  {
    "path": ".idea/AndroidProjectSystem.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"AndroidProjectSystem\">\n    <option name=\"providerId\" value=\"com.android.tools.idea.GradleProjectSystem\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/appInsightsSettings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"AppInsightsSettings\">\n    <option name=\"tabSettings\">\n      <map>\n        <entry key=\"Firebase Crashlytics\">\n          <value>\n            <InsightsFilterSettings>\n              <option name=\"connection\">\n                <ConnectionSetting>\n                  <option name=\"appId\" value=\"PLACEHOLDER\" />\n                  <option name=\"mobileSdkAppId\" value=\"\" />\n                  <option name=\"projectId\" value=\"\" />\n                  <option name=\"projectNumber\" value=\"\" />\n                </ConnectionSetting>\n              </option>\n              <option name=\"signal\" value=\"SIGNAL_UNSPECIFIED\" />\n              <option name=\"timeIntervalDays\" value=\"THIRTY_DAYS\" />\n              <option name=\"visibilityType\" value=\"ALL\" />\n            </InsightsFilterSettings>\n          </value>\n        </entry>\n      </map>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <JetCodeStyleSettings>\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </JetCodeStyleSettings>\n    <codeStyleSettings language=\"XML\">\n      <option name=\"FORCE_REARRANGE_MODE\" value=\"1\" />\n      <indentOptions>\n        <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      </indentOptions>\n      <arrangement>\n        <rules>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:android</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:id</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>style</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>ANDROID_ATTRIBUTE_ORDER</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>.*</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n        </rules>\n      </arrangement>\n    </codeStyleSettings>\n    <codeStyleSettings language=\"kotlin\">\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </codeStyleSettings>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"USE_PER_PROJECT_SETTINGS\" value=\"true\" />\n  </state>\n</component>"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <bytecodeTargetLevel target=\"1.8\">\n      <module name=\"Seal.app\" target=\"21\" />\n      <module name=\"Seal.buildSrc\" target=\"21\" />\n      <module name=\"Seal.buildSrc.main\" target=\"21\" />\n      <module name=\"Seal.buildSrc.test\" target=\"21\" />\n    </bytecodeTargetLevel>\n  </component>\n</project>"
  },
  {
    "path": ".idea/deploymentTargetSelector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"deploymentTargetSelector\">\n    <selectionStates>\n      <SelectionState runConfigName=\"app\">\n        <option name=\"selectionMode\" value=\"DROPDOWN\" />\n        <DropdownSelection timestamp=\"2024-10-08T21:31:16.287350Z\">\n          <Target type=\"DEFAULT_BOOT\">\n            <handle>\n              <DeviceId pluginId=\"PhysicalDevice\" identifier=\"serial=29091FDH3007P1\" />\n            </handle>\n          </Target>\n        </DropdownSelection>\n        <DialogSelection />\n      </SelectionState>\n      <SelectionState runConfigName=\"BottomBarPreview\">\n        <option name=\"selectionMode\" value=\"DROPDOWN\" />\n      </SelectionState>\n      <SelectionState runConfigName=\"DownloadPagePreview\">\n        <option name=\"selectionMode\" value=\"DROPDOWN\" />\n        <DropdownSelection timestamp=\"2024-10-04T15:47:27.481595Z\">\n          <Target type=\"DEFAULT_BOOT\">\n            <handle>\n              <DeviceId pluginId=\"LocalEmulator\" identifier=\"path=/Users/junkfood/.android/avd/Resizable_Experimental_API_VanillaIceCream.avd\" />\n            </handle>\n          </Target>\n        </DropdownSelection>\n        <DialogSelection />\n      </SelectionState>\n      <SelectionState runConfigName=\"Preview\">\n        <option name=\"selectionMode\" value=\"DROPDOWN\" />\n      </SelectionState>\n      <SelectionState runConfigName=\"Preview - Light\">\n        <option name=\"selectionMode\" value=\"DROPDOWN\" />\n        <DropdownSelection timestamp=\"2024-10-07T18:32:33.710498Z\">\n          <Target type=\"DEFAULT_BOOT\">\n            <handle>\n              <DeviceId pluginId=\"LocalEmulator\" identifier=\"path=/Users/junkfood/.android/avd/Resizable_Experimental_API_VanillaIceCream.avd\" />\n            </handle>\n          </Target>\n        </DropdownSelection>\n        <DialogSelection />\n      </SelectionState>\n      <SelectionState runConfigName=\"SheetPreview - Dark\">\n        <option name=\"selectionMode\" value=\"DROPDOWN\" />\n      </SelectionState>\n    </selectionStates>\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleMigrationSettings\" migrationVersion=\"1\" />\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <compositeConfiguration>\n          <compositeBuild compositeDefinitionSource=\"SCRIPT\">\n            <builds>\n              <build path=\"$PROJECT_DIR$/buildSrc\" name=\"buildSrc\">\n                <projects>\n                  <project path=\"$PROJECT_DIR$/buildSrc\" />\n                </projects>\n              </build>\n            </builds>\n          </compositeBuild>\n        </compositeConfiguration>\n        <option name=\"testRunner\" value=\"CHOOSE_PER_TEST\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"gradleJvm\" value=\"#GRADLE_LOCAL_JAVA_HOME\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n            <option value=\"$PROJECT_DIR$/buildSrc\" />\n            <option value=\"$PROJECT_DIR$/color\" />\n          </set>\n        </option>\n        <option name=\"resolveExternalAnnotations\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/inspectionProfiles/Project_Default.xml",
    "content": "<component name=\"InspectionProjectProfileManager\">\n  <profile version=\"1.0\">\n    <option name=\"myName\" value=\"Project Default\" />\n    <inspection_tool class=\"ComposePreviewDimensionRespectsLimit\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"ComposePreviewMustBeTopLevelFunction\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"ComposePreviewNeedsComposableAnnotation\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"ComposePreviewNotSupportedInUnitTestFiles\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"GlancePreviewDimensionRespectsLimit\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"GlancePreviewMustBeTopLevelFunction\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"GlancePreviewNeedsComposableAnnotation\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"GlancePreviewNotSupportedInUnitTestFiles\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewAnnotationInFunctionWithParameters\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewApiLevelMustBeValid\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewDeviceShouldUseNewSpec\" enabled=\"true\" level=\"WEAK WARNING\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewDimensionRespectsLimit\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewFontScaleMustBeGreaterThanZero\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewMultipleParameterProviders\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewMustBeTopLevelFunction\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewNeedsComposableAnnotation\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewNotSupportedInUnitTestFiles\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n    <inspection_tool class=\"PreviewPickerAnnotation\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\">\n      <option name=\"composableFile\" value=\"true\" />\n      <option name=\"previewFile\" value=\"true\" />\n    </inspection_tool>\n  </profile>\n</component>"
  },
  {
    "path": ".idea/kotlinc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"KotlinJpsPluginSettings\">\n    <option name=\"version\" value=\"2.0.20\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/ktfmt.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"KtfmtSettings\">\n    <option name=\"enableKtfmt\" value=\"Enabled\" />\n    <option name=\"enabled\" value=\"true\" />\n    <option name=\"uiFormatterStyle\" value=\"Kotlinlang\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/migrations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectMigrations\">\n    <option name=\"MigrateToGradleLocalJavaHome\">\n      <set>\n        <option value=\"$PROJECT_DIR$\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<project version=\"4\">\n  <component name=\"DesignSurface\">\n    <option name=\"filePathToZoomLevelMap\">\n      <map>\n        <entry key=\"../../../../layout/compose-model-1651485741994.xml\" value=\"0.9422382671480144\" />\n        <entry key=\"../../../../layout/compose-model-1651732459930.xml\" value=\"0.22314814814814815\" />\n        <entry key=\"../../../../layout/compose-model-1651739120146.xml\" value=\"0.1787037037037037\" />\n        <entry key=\"../../../../layout/compose-model-1651828828315.xml\" value=\"0.25\" />\n        <entry key=\"app/src/main/java/com/junkfood/seal/ui/page/download/DownloadPage.kt\" value=\"0.375\" />\n        <entry key=\"app/src/main/java/com/junkfood/seal/ui/page/download/PlaylistSelectionDialog.kt\" value=\"0.27954545454545454\" />\n        <entry key=\"app/src/main/res/drawable-v24/ic_launcher_foreground.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/drawable/ic_dashboard_black_24dp.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/drawable/ic_home_black_24dp.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/drawable/ic_launcher_background.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/drawable/ic_launcher_foreground.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/drawable/ic_notifications_black_24dp.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/drawable/seal.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/layout/activity_main.xml\" value=\"0.19653727213541666\" />\n        <entry key=\"app/src/main/res/layout/activity_settings.xml\" value=\"0.22135416666666666\" />\n        <entry key=\"app/src/main/res/layout/content_scrolling.xml\" value=\"0.20729166666666668\" />\n        <entry key=\"app/src/main/res/layout/fragment_home.xml\" value=\"0.23585510253906253\" />\n        <entry key=\"app/src/main/res/layout/fragment_notifications.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/layout/fragment_settings.xml\" value=\"0.3098958333333333\" />\n        <entry key=\"app/src/main/res/layout/fragment_settings_list.xml\" value=\"0.32135416666666666\" />\n        <entry key=\"app/src/main/res/menu/settings_toolbar.xml\" value=\"0.22135416666666666\" />\n        <entry key=\"app/src/main/res/menu/toolbar.xml\" value=\"2.125\" />\n        <entry key=\"app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml\" value=\"0.223\" />\n        <entry key=\"app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml\" value=\"0.1\" />\n        <entry key=\"app/src/main/res/xml/root_preferences.xml\" value=\"0.3098958333333333\" />\n      </map>\n    </option>\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_8\" project-jdk-name=\"jbr-21\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/other.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"direct_access_persist.xml\">\n    <option name=\"selectedCloudProject\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer\" />\n        <option value=\"com.intellij.execution.junit.AllInPackageConfigurationProducer\" />\n        <option value=\"com.intellij.execution.junit.PatternConfigurationProducer\" />\n        <option value=\"com.intellij.execution.junit.TestInClassConfigurationProducer\" />\n        <option value=\"com.intellij.execution.junit.UniqueIdConfigurationProducer\" />\n        <option value=\"com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer\" />\n        <option value=\"org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer\" />\n        <option value=\"org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/studiobot.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"StudioBotProjectSettings\">\n    <option name=\"shareContext\" value=\"OptedIn\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes (starting from v1.7.3) to stable releases will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [v2.0.0][2.0.0] - unreleased\n\n### Notable changes from v1.13\n\n- Concurrent downloading\n- Download queue\n- User interface overhaul\n- Large screen support\n- Resume failed/canceled download\n- Backup & restore unfinished tasks in the download queue\n- Select from formats/playlists in Quick Download\n- Predictive back animation support for Android 14+\n- Bump up minimum API level to 24 (Android 7.0)\n\n## [v1.13.0][1.13.0] - 2024-08-18\n\n### Fixed\n\n- Fix the issue where exported command templates could not be imported in v1.12.x\n- Fix an unexpected behavior where multiple formats would be selected\n\n### Change\n\n- Update `youtubedl-android` to v0.16.1\n- Update translations\n\n## [v1.12.1][1.12.1] - 2024-04-17\n\n### Added\n\n* Add auto update interval for yt-dlp\n* Cookies page now shows the current count of cookies stored in the database\n\n### Fixed\n\n* Intercept non-HTTP(s) URLs opened in WebView\n* Videos are remuxed to mkv even when download subtitle is disabled\n* Use MD2 ModalBottomSheetLayout in devices on API < 30\n* Block downloads when updating yt-dlp\n\n### Known issues\n\n* TextFields(IME) fallback to plain character mode when showing a ModalBottomSheet\n* yt-dlp might be broken if you tried to download something while it was\n  updating (`bad local file header`). To fix it, you just need to update yt-dlp again\n\n## [v1.12.0][1.12.0] - 2024-04-05\n\n### Added\n\n* Search from download history\n* Search from subtitles in format selection page\n* Export download history to file/clipboard\n* Import download history from file/clipboard\n* Re-download unavailable videos\n* Download auto-translated subtitles\n* Remember subtitle selection for next downloads\n* Remux videos into mkv container for better compatibility\n* Configuration for not using the download type in the last download\n* Improve UI/UX for download error handling\n* Add splash screen\n* Haptic feedback BZZZTT!!1!\n\n### Changed\n\n* Long pressing on an item in download history now selects it\n* Use nightly builds for yt-dlp by default\n* Migrate `Slider` & `ProgressIndicator` to the new visual styles in MD3\n* Use default display name from system for locales\n* Metadata of videos is also embedded in the files now\n* A few UI changes that I forgot\n\n### Fixed\n\n* Fix a permission issue when using Seal in a different user profile or private space\n* Fix an issue where the text cannot be copied in the menu of the download history\n* Display approximate file size for formats when there's no exact value available\n* Fix an issue causes app to crash when the selected template is not available\n* Custom command now ignore empty URLs, which means you can insert URLs along with arguments in\n  command templates\n* Fix an issue where some formats may be unavailable when downloading playlists\n\n### Known issues\n\n* TextFields(IME) fallback to plain character mode when showing a ModalBottomSheet\n* ModalBottomSheet handles insets incorrectly on devices below API 30\n\n## [v1.11.3][1.11.3] - 2024-01-22\n\n### Added\n\n* Merge multiple audio streams into a single file\n* Allow downloading with cellular network temporarily\n\n### Fixed\n\n* App creates duplicated command templates on initialization\n* Cannot make video clip in FormatPage\n\n## [v1.11.2][1.11.2] - 2024-01-06\n\n### Added\n\n* Keep subtitles files after embedding into videos\n* Force all connections via ipv4\n* Prefer vp9.2 if av1 hardware decoding unavailable\n* Add system locale settings for Android 13+\n\n### Fixed\n\n* User agent gets enabled when refreshing cookies\n* Restrict filenames not working in custom commands\n\n### Changed\n\n* Transition animation should look more smooth now\n\n## [v1.11.1][1.11.1] - 2023-12-16\n\n### Added\n\n* Add `--restrict-filenames` option in yt-dlp\n* Add playlist title as an option for subdirectory\n* Add more thanks to sponsors\n\n### Fixed\n\n* Fix some minor UI bugs\n* Fix an issue causing error when parsing video info\n\n## [v1.11.0][1.11.0] - 2023-11-18\n\n### Added\n\n* Custom output template (`-o` option in yt-dlp)\n* Export cookies to a text file\n* Make embed metadata in audio files optional\n* Add the ability to record download archive, and skip duplicate downloads\n* Add cancel button to the download page\n* Add input chips for sponsorblock categories\n* Add subtitle selection dialog in format page, make auto-translated subtitles available in subtitle\n  selection\n* Add more thanks to sponsors\n\n### Changed\n\n* Move the directory for storing temporary files to external storage (`Seal/tmp`)\n* Change the default output template to `%(title)s.%(ext)s`\n* Temporary directory now are enabled by default for downloads in general mode\n* Move actions in format page to dropdown menu\n* Download subtitles are now available when downloading audio files\n* `android:enableOnBackInvokedCallback` is changed to `false` due to compatibility issues\n\n### Fixed\n\n* Fix an issue causes sharing videos to fail on certain devices\n* Fix an issue causes uploader marked as null, make uploader_id as a fallback to uploader\n* Fix an issue when a user performs multiple clicks causing duplicate navigating behaviors\n\n### Removed\n\n* Custom prefix for output template has been removed, please migrate to custom output template\n\n## [v1.10.0][1.10.0] - 2023-08-30\n\n### Added\n\n**Subtitles**\n\n* Convert subtitles to another format\n* Select subtitle language in format selection\n\n**Format selection**\n\n* Display icons(video/audio) on `FormatItem`s\n* Split video by chapters\n* Select subtitle to download by language names/codes\n\n**Custom commands**\n\n* Create custom command tasks in the Running Tasks page\n* Configure download directory separately for custom command tasks\n* Select multiple command templates to export & remove\n\n**Cookies**\n\n* Add `CookiesQuickSettingsDialog` for refreshing & configuring cookies in configuration menu\n* Add user agent header when downloading with cookies enabled\n\n**Other New Features & UI Improvements**\n\n* Show `PlainToolTip` when long-press on `PlaylistItem`\n* Add monochrome theme\n* Add proxy configuration for network connections\n* Add translations in Swedish and Portuguese\n\n### Fixed\n\n* App crashes when being opened in the system share sheet\n* Video not shown in YouTube playlist results\n* Cookies cannot be disabled after clearing cookies\n* Hide video only formats when save as audio enabled\n* Parsing error with decimal value in width/height\n* Audio codec preference not works as expected\n* Could not fetch video info when `originalUrl` is null\n\n### Changed\n\n**Notable Changes**\n\n* Upgrade target API level to 34 (Android 14)\n* Preferred video format changed to two options: Legacy and Quality\n* UI improvements to the configuration dialog\n\n**Other Changes**\n\n* Update `ColorScheme`s and components to reflect the new MD3 color roles\n* Update youtubedl-android version, added pycryptodomex to the library\n* Move Video formats to the bottom of the `FormatPage`\n* Notifications now are enabled by default\n* Minor UI improvements & changes\n\n## [v1.9.2][1.9.2] - 2023-04-27\n\n### Fixed\n\n* Fix a bug causing Incognito mode not working in v1.9.1\n* Fix misplaced quality tags in `AudioQuickSettingsDialog`\n* Fix mismatched formats when using Save as audio & Download playlist\n\n## [v1.9.1][1.9.1] - 2023-04-11\n\n### Added\n\n* Add Sponsor page: You can now support this app by sponsoring on GitHub!\n\n### Fixed\n\n* Fix a bug causing warnings not shown in logs of completed custom command tasks\n* Fix a bug causing videos not scanned into media library when private mode is enabled\n\n### Changed\n\n* Move the directory for temporary files to `cacheDir`\n\n## [v1.9.0][1.9.0] - 2023-03-12\n\n### Added\n\n* Add Preview channel for auto-updating\n* Add an option to update to Nightly builds of yt-dlp\n* Add a dialog for F-Droid builds in auto-update settings\n* Add a switch for auto-updating yt-dlp\n* Add the ability to share files in `VideoDetailDrawer`\n* Add a badge to the icon to indicate the count of running processes\n* Add a switch for disabling the temporary directory\n* Add format & quality preference for audio\n* Add custom format sorter\n* Add the ability to clip video and audio in `FormatSelectionPage` (experimental)\n* Add the ability to edit video titles in `FormatSelectionPage` before downloading\n* Add the ability to share the thumbnail url in `FormatSelectionPage`\n* Implement a new method to extract cookies from the `WebView` database\n\n### Changed\n\n- Change the operation of open link to long pressing the link button in `VideoDetailDrawer`\n- Change the thread number range of multi-threaded download to 1-24\n- Change the status bar icon to filled icon\n- Change the quick settings for media format in the configuration dialog\n\n### Fixed\n\n- Fix a bug causing high-quality audio not downloaded with YT Premium cookies & YT Music URLs\n- UI bug in `ShortcutChip` with long template\n- Fix a bug causing empty subtitle language breaks downloads\n- Fix an issue causing specific languages not visible in system settings on Android 13+\n- Fix a UI bug in the format selection page\n- Fix a bug causing app to crash when toasting in Android 5.0\n- Fix a UI bug causing LTR texts to display incorrectly in RTL locale environment\n- Add legacy app icon for API 21~25\n\n### Known issues\n\n- Cookies may not work as expected in some devices, please try to re-generate cookies after this\n  occurs. File an issue on GitHub with your device info when experience errors.\n\n## [v1.8.2][1.8.2] - 2023-02-10\n\n### Fixed\n\n- Trimmed ASCII characters filename\n- Unexpected error when downloading multiple video to SD card with quick download\n- Error when cropping vertical thumbnails as artwork\n- ID conflicts when importing custom templates\n\n### Changed\n\n- Add `horizontalScroll` to `LogPage`\n- Revert the URL intent filters\n\n## [v1.8.1][1.8.1] - 2023-02-01\n\n### Fixed\n\n- App crashes when downloading in private mode\n- Unexpected ImeActions in TextFields\n- Disable SD card download when the directory is not set\n- Localized strings for file size texts\n\n## [v1.8.0][1.8.0] - 2023-01-29\n\n### Added\n\n- Download to SD card\n- Quick download in parallel\n- Task dashboard & log page for custom commands\n- Custom shortcuts for command templates\n- Subtitle preferences\n- Apply `--embed-chapters` for video downloads by default\n- New color schemes for UI theming\n\n### Changed\n\n- New transition animation between destinations\n- Change `minSdkVersion` to 21 (Android 5.0)\n- Accessibility improvements to components\n- Revert playlist items limit in v1.7.3\n- Scan the download directory to the system media library after running commands\n- Change the LongClick operations of `FormatItem` to share the stream URLs\n\n## [v1.7.3][1.7.3] - 2023-01-10\n\n### Fixed\n\n- `Webview` captures Cookies from wrong domains\n- Notifications of custom commands remain unfinished status\n- App crashes when fails to parse video info for format selection\n- App crashes when parsing channel info for playlist download\n\n### Added\n\n- Tips about streams merging in `FormatSelectionPage`\n\n### Changed\n\n- Playlist results are limited to 200 videos\n\n[1.7.3]: https://github.com/JunkFood02/Seal/releases/tag/v1.7.3\n\n[1.8.0]: https://github.com/JunkFood02/Seal/releases/tag/v1.8.0\n\n[1.8.1]: https://github.com/JunkFood02/Seal/releases/tag/v1.8.1\n\n[1.8.2]: https://github.com/JunkFood02/Seal/releases/tag/v1.8.2\n\n[1.9.0]: https://github.com/JunkFood02/Seal/releases/tag/v1.9.0\n\n[1.9.1]: https://github.com/JunkFood02/Seal/releases/tag/v1.9.1\n\n[1.9.2]: https://github.com/JunkFood02/Seal/releases/tag/v1.9.2\n\n[1.10.0]: https://github.com/JunkFood02/Seal/releases/tag/v1.10.0\n\n[1.11.0]: https://github.com/JunkFood02/Seal/releases/tag/v1.11.0\n\n[1.11.1]: https://github.com/JunkFood02/Seal/releases/tag/v1.11.1\n\n[1.11.2]: https://github.com/JunkFood02/Seal/releases/tag/v1.11.2\n\n[1.11.3]: https://github.com/JunkFood02/Seal/releases/tag/v1.11.3\n\n[1.12.0]: https://github.com/JunkFood02/Seal/releases/tag/v1.12.0\n\n[1.12.1]: https://github.com/JunkFood02/Seal/releases/tag/v1.12.1\n\n[1.13.0]: https://github.com/JunkFood02/Seal/releases/tag/v1.13.0"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\njunkfood02@proton.me.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nBefore reading, you may know what [yt-dlp](https://github.com/yt-dlp/yt-dlp) is and what it does. In short, it's a CLI (Command Line Interface) program written in python, which lets you download videos from [1000+ websites](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md).\n\nFor bug reports and feature requests, please search in issues first (including the closed ones). If there're no duplicates, feel free to [submit an issue](https://github.com/JunkFood02/Seal/issues/new) with an issue template.\n\n**We'll probably ignore and close your issue if it's not using the existing templates or doesn't contain sufficient description.**\n\nFor questions or any other ideas to improve, you can join our official [Telegram group](https://t.me/seal_app_group) or [Matrix space](https://matrix.to/#/#seal-space:matrix.org).\n\n\n## Disclaimer\n\nThis is a toy project I use to learn Android development. Please do not have any expectations or assumptions about the quality of the code.\n\n\n## Bug Report\n\nWhen submitting a bug report, please make sure your issue contains **enough** information for reproducing the problem, including the options or the custom command being used, the link to the video, and other fields in the issue template.\n\n\n\n## Feature Request\n\nSeal is and will remain a simple GUI for yt-dlp, providing most of the functionality of yt-dlp as is, without modifications. Thus, **we'll not take requests for features that yt-dlp does not support.**\n\nThe app has two download modes: \n\n- General mode: Save as audio, download playlist, and many other options that can be used individually or combined for normal download tasks. Once the download is complete, Seal will scan the files into the system media library, and store them in the download history.\n- Custom command mode: For advanced usage of yt-dlp, a user can create and store multiple command templates in the app, then select and use one of them directly to execute the yt-dlp command like in a terminal. In this mode, all of the GUI options and features in the general mode will be disabled.\n\nSince most of the functions can be implemented in custom command mode, the \"feature request\" would be treated as adding a shortcut to the general mode. However, not all feature requests will be accepted and implemented in the app. [Why not add an option for that?](https://neugierig.org/software/blog/2018/07/options.html)\n\n\n\n## Pull Request\n\nIf you wish to contribute to the project by submitting code directly, please first leave a comment under the relevant issue or file a new issue, describe the changes you are about to make.\n\nTo avoid multiple pull requests resolving the same issue, let others know you are working on it by saying so in a comment, or ask the issue to be assigned to yourself.\n\n\n\n## New contributors\n\nScan through our [existing issues](https://github.com/JunkFood02/Seal/issues) to find one that interests you. The [👋 good first issue](https://github.com/JunkFood02/Seal/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) is a good place to start exploring issues that are up-for-grab for newcomers. (Do not hesitate to ask for more details or clarifying questions on the issue!)\n\n\n\n## Building From Source\n\nFork this project, import and compile it with the latest version of [Android Studio Canary](https://developer.android.com/studio/preview). \n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Video/Audio Downloader for Android\n\n\nEnglish\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hans.md\">简体中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hant.md\">繁體中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ar.md\">العربية</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-pt.md\">Portuguese</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ua.md\">Українська</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-th.md\">ภาษาไทย</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-fa.md\">فارسی</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-it.md\">Italiano</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-az.md\">Azərbaycanca</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ru.md\">Русский</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-sr.md\">Српски</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ja.md\">日本語</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-id.md\">Indonesia</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-hi.md\">हिंदी</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-bn.md\">বাংলা</a>\n\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIC05NjAgOTYwIDk2MCIgd2lkdGg9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0zNTQtMjQ3IDEyNi03NiAxMjYgNzctMzMtMTQ0IDExMS05Ni0xNDYtMTMtNTgtMTM2LTU4IDEzNS0xNDYgMTMgMTExIDk3LTMzIDE0M1pNMjMzLTgwbDY1LTI4MUw4MC01NTBsMjg4LTI1IDExMi0yNjUgMTEyIDI2NSAyODggMjUtMjE4IDE4OSA2NSAyODEtMjQ3LTE0OUwyMzMtODBabTI0Ny0zNTBaIiBzdHlsZT0iZmlsbDogcmdiKDI0NSwgMjI3LCA2Nik7Ii8%2BCjwvc3ZnPg%3D%3D&color=%23f8e444)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported-Sites](https://img.shields.io/badge/Sites-9cf?style=flat&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0cHgiIGZpbGw9IiNGRkZGRkYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTExLjk5IDJDNi40NyAyIDIgNi40OCAyIDEyczQuNDcgMTAgOS45OSAxMEMxNy41MiAyMiAyMiAxNy41MiAyMiAxMlMxNy41MiAyIDExLjk5IDJ6bTYuOTMgNmgtMi45NWMtLjMyLTEuMjUtLjc4LTIuNDUtMS4zOC0zLjU2IDEuODQuNjMgMy4zNyAxLjkxIDQuMzMgMy41NnpNMTIgNC4wNGMuODMgMS4yIDEuNDggMi41MyAxLjkxIDMuOTZoLTMuODJjLjQzLTEuNDMgMS4wOC0yLjc2IDEuOTEtMy45NnpNNC4yNiAxNEM0LjEgMTMuMzYgNCAxMi42OSA0IDEycy4xLTEuMzYuMjYtMmgzLjM4Yy0uMDguNjYtLjE0IDEuMzItLjE0IDJzLjA2IDEuMzQuMTQgMkg0LjI2em0uODIgMmgyLjk1Yy4zMiAxLjI1Ljc4IDIuNDUgMS4zOCAzLjU2LTEuODQtLjYzLTMuMzctMS45LTQuMzMtMy41NnptMi45NS04SDUuMDhjLjk2LTEuNjYgMi40OS0yLjkzIDQuMzMtMy41NkM4LjgxIDUuNTUgOC4zNSA2Ljc1IDguMDMgOHpNMTIgMTkuOTZjLS44My0xLjItMS40OC0yLjUzLTEuOTEtMy45NmgzLjgyYy0uNDMgMS40My0xLjA4IDIuNzYtMS45MSAzLjk2ek0xNC4zNCAxNEg5LjY2Yy0uMDktLjY2LS4xNi0xLjMyLS4xNi0ycy4wNy0xLjM1LjE2LTJoNC42OGMuMDkuNjUuMTYgMS4zMi4xNiAycy0uMDcgMS4zNC0uMTYgMnptLjI1IDUuNTZjLjYtMS4xMSAxLjA2LTIuMzEgMS4zOC0zLjU2aDIuOTVjLS45NiAxLjY1LTIuNDkgMi45My00LjMzIDMuNTZ6TTE2LjM2IDE0Yy4wOC0uNjYuMTQtMS4zMi4xNC0ycy0uMDYtMS4zNC0uMTQtMmgzLjM4Yy4xNi42NC4yNiAxLjMxLjI2IDJzLS4xIDEuMzYtLjI2IDJoLTMuMzh6IiBzdHlsZT0iZmlsbDogcmdiKDE2MiwgMTk4LCAyMzQpOyIvPgo8L3N2Zz4=&label=Supported)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix](https://img.shields.io/matrix/seal-space%3Amatrix.org?server_fqdn=matrix.org&style=flat&logo=element&label=Matrix&color=%230DBD8B)\n](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱 Screenshots\n\n<div align=\"center\">\n<div>\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 Features\n\n- Download videos and audio files from video platforms supported by [yt-dlp](https://github.com/yt-dlp/yt-dlp) (formerly youtube-dl).\n\n- Embed metadata and video thumbnail into extracted audio files supported by [mutagen](https://github.com/quodlibet/mutagen).\n\n- Download all videos in the playlist with one click.\n\n- Use embedded [aria2c](https://github.com/aria2/aria2) as external downloader for all your downloads.\n\n- Embed subtitles into the downloaded videos.\n\n- Execute custom yt-dlp commands with templates.\n\n- Manage in-app downloads and custom command templates.\n\n- Easy to use and user-friendly.\n\n- [Material Design 3](https://m3.material.io/) style UI, with dynamic color theme.\n\n- MAD: UI and logic written with pure Kotlin. Single activity, no fragments, only composable destinations.\n\n\n\n## ⬇️ Download\n\nFor most devices, it is recommended to install the **arm64-v8a** version of the apks\n\n- Download the latest stable version from [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest)\n  - Install the [pre-release](https://github.com/JunkFood02/Seal/releases/) versions to help us test out new features & changes\n\n- Stable releases are also available on [F-Droid](https://f-droid.org/packages/com.junkfood.seal/)\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 Contact\n\nJoin our [Telegram Channel](https://t.me/seal_app) or [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) for discussion, announcements, and releases!\n\n## 💖 Sponsors\n\n<p><!-- sponsors --><a href=\"https://github.com/Cook-I-T\"><img src=\"https:&#x2F;&#x2F;github.com&#x2F;Cook-I-T.png\" width=\"60px\" alt=\"User avatar: Cook I.T!\" /></a><a href=\"https://github.com/reallyrealcolby\"><img src=\"https:&#x2F;&#x2F;github.com&#x2F;reallyrealcolby.png\" width=\"60px\" alt=\"User avatar: \" /></a><a href=\"https://github.com/abelladianne458-gif\"><img src=\"https:&#x2F;&#x2F;github.com&#x2F;abelladianne458-gif.png\" width=\"60px\" alt=\"User avatar: \" /></a><a href=\"https://github.com/agusterodin\"><img src=\"https:&#x2F;&#x2F;github.com&#x2F;agusterodin.png\" width=\"60px\" alt=\"User avatar: Jeff Rosen\" /></a><!-- sponsors --></p>\n\n\nSeal will be always free and open source for everyone. If you like it, please consider [sponsoring me](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 Contributing\n\nContributions are welcome!\n\nYou can help translate Seal on [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\t\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\t\n>[!Note]\n>\n>For submitting bug reports, feature requests, questions, or any other ideas to improve, please read [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) for instructions and guidelines first.\n\n## ⭐️ Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 Credits\n\nSeal is a simple GUI of [yt-dlp](https://github.com/yt-dlp/yt-dlp), based on [youtubedl-android](https://github.com/yausername/youtubedl-android)\n\nSome of the UI designs and codes are borrowed from [Read You](https://github.com/Ashinch/ReadYou) and [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 License\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>[!Warning]\n>\n>Except for the source code licensed under the GPLv3 license,\n>all other parties are prohibited from using Seal's name as a downloader app,\n>and the same is true for Seal's derivatives.\n>Derivatives include but are not limited to forks and unofficial builds.\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Scroll to top</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build"
  },
  {
    "path": "app/build.gradle.kts",
    "content": "@file:Suppress(\"UnstableApiUsage\")\n\nimport com.android.build.api.variant.FilterConfiguration\nimport java.io.FileInputStream\nimport java.util.Properties\n\nplugins {\n    alias(libs.plugins.android.application)\n    alias(libs.plugins.kotlin.android)\n    alias(libs.plugins.kotlin.serialization)\n    alias(libs.plugins.ksp)\n    alias(libs.plugins.compose.compiler)\n    alias(libs.plugins.room)\n    alias(libs.plugins.ktfmt.gradle)\n}\n\nval keystorePropertiesFile: File = rootProject.file(\"keystore.properties\")\n\nval splitApks = !project.hasProperty(\"noSplits\")\n\nval abiFilterList = (properties[\"ABI_FILTERS\"] as String).split(';')\n\nval abiCodes = mapOf(\"armeabi-v7a\" to 1, \"arm64-v8a\" to 2, \"x86\" to 3, \"x86_64\" to 4)\n\nval baseVersionName = currentVersion.name\nval currentVersionCode = currentVersion.code.toInt()\n\nandroid {\n    compileSdk = 35\n\n    if (keystorePropertiesFile.exists()) {\n        val keystoreProperties = Properties()\n        keystoreProperties.load(FileInputStream(keystorePropertiesFile))\n        signingConfigs {\n            create(\"githubPublish\") {\n                keyAlias = keystoreProperties[\"keyAlias\"].toString()\n                keyPassword = keystoreProperties[\"keyPassword\"].toString()\n                storeFile = file(keystoreProperties[\"storeFile\"]!!)\n                storePassword = keystoreProperties[\"storePassword\"].toString()\n            }\n        }\n    }\n\n    buildFeatures { buildConfig = true }\n\n    defaultConfig {\n        applicationId = \"com.junkfood.seal\"\n        minSdk = 24\n        targetSdk = 35\n        versionCode = 200_000_150\n        check(versionCode == currentVersionCode)\n\n        versionName = baseVersionName\n        testInstrumentationRunner = \"androidx.test.runner.AndroidJUnitRunner\"\n        vectorDrawables { useSupportLibrary = true }\n\n        if (splitApks) {\n            splits {\n                abi {\n                    isEnable = true\n                    reset()\n                    include(\"arm64-v8a\", \"armeabi-v7a\", \"x86\", \"x86_64\")\n                    isUniversalApk = true\n                }\n            }\n        } else {\n            ndk { abiFilters.addAll(abiFilterList) }\n        }\n    }\n\n    room { schemaDirectory(\"$projectDir/schemas\") }\n    ksp { arg(\"room.incremental\", \"true\") }\n\n    androidComponents {\n        onVariants { variant ->\n            variant.outputs.forEach { output ->\n                val name =\n                    if (splitApks) {\n                        output.filters\n                            .find { it.filterType == FilterConfiguration.FilterType.ABI }\n                            ?.identifier\n                    } else {\n                        abiFilterList.firstOrNull()\n                    }\n\n                val baseAbiCode = abiCodes[name]\n\n                if (baseAbiCode != null) {\n                    output.versionCode.set(baseAbiCode + (output.versionCode.get() ?: 0))\n                }\n            }\n        }\n    }\n\n    buildTypes {\n        release {\n            isMinifyEnabled = true\n            isShrinkResources = true\n            proguardFiles(\n                getDefaultProguardFile(\"proguard-android-optimize.txt\"),\n                \"proguard-rules.pro\",\n            )\n            if (keystorePropertiesFile.exists()) {\n                signingConfig = signingConfigs.getByName(\"githubPublish\")\n            }\n        }\n        debug {\n            if (keystorePropertiesFile.exists()) {\n                signingConfig = signingConfigs.getByName(\"githubPublish\")\n            }\n            applicationIdSuffix = \".debug\"\n            versionNameSuffix = \"-debug\"\n            resValue(\"string\", \"app_name\", \"Seal Debug\")\n        }\n    }\n\n    flavorDimensions += \"publishChannel\"\n\n    productFlavors {\n        create(\"generic\") {\n            dimension = \"publishChannel\"\n            isDefault = true\n        }\n\n        create(\"githubPreview\") {\n            dimension = \"publishChannel\"\n            applicationIdSuffix = \".preview\"\n            resValue(\"string\", \"app_name\", \"Seal Preview\")\n        }\n\n        create(\"fdroid\") {\n            dimension = \"publishChannel\"\n            versionName = \"$baseVersionName-(F-Droid)\"\n        }\n    }\n\n    lint { disable.addAll(listOf(\"MissingTranslation\", \"ExtraTranslation\", \"MissingQuantity\")) }\n\n    applicationVariants.all {\n        outputs.all {\n            (this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName =\n                \"Seal-${defaultConfig.versionName}-${name}.apk\"\n        }\n    }\n\n    kotlinOptions { freeCompilerArgs = freeCompilerArgs + \"-opt-in=kotlin.RequiresOptIn\" }\n\n    packaging {\n        resources { excludes += \"/META-INF/{AL2.0,LGPL2.1}\" }\n        jniLibs.useLegacyPackaging = true\n    }\n    androidResources { generateLocaleConfig = true }\n\n    namespace = \"com.junkfood.seal\"\n}\n\nktfmt { kotlinLangStyle() }\n\nkotlin { jvmToolchain(21) }\n\ndependencies {\n    implementation(project(\":color\"))\n\n    implementation(libs.bundles.core)\n\n    implementation(libs.androidx.lifecycle.runtimeCompose)\n\n    implementation(platform(libs.androidx.compose.bom))\n    implementation(libs.bundles.androidxCompose)\n    implementation(libs.bundles.accompanist)\n\n    implementation(libs.coil.kt.compose)\n\n    implementation(libs.kotlinx.serialization.json)\n\n    implementation(libs.koin.android)\n    implementation(libs.koin.compose)\n\n    implementation(libs.room.runtime)\n    implementation(libs.room.ktx)\n    ksp(libs.room.compiler)\n\n    implementation(libs.okhttp)\n\n    implementation(libs.bundles.youtubedlAndroid)\n\n    implementation(libs.mmkv)\n\n    testImplementation(libs.junit4)\n    androidTestImplementation(libs.androidx.test.ext)\n    androidTestImplementation(libs.androidx.test.espresso.core)\n    implementation(libs.androidx.compose.ui.tooling)\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n\n#noinspection ShrinkerUnresolvedReference\n\n-dontobfuscate\n\n-keep class com.yausername.** { *; }\n-keep class org.apache.commons.compress.archivers.zip.** { *; }\n\n# Keep `Companion` object fields of serializable classes.\n# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.\n-if @kotlinx.serialization.Serializable class **\n-keepclassmembers class <1> {\n    static <1>$Companion Companion;\n}\n\n# Keep `serializer()` on companion objects (both default and named) of serializable classes.\n-if @kotlinx.serialization.Serializable class ** {\n    static **$* *;\n}\n-keepclassmembers class <2>$<3> {\n    kotlinx.serialization.KSerializer serializer(...);\n}\n\n# Keep `INSTANCE.serializer()` of serializable objects.\n-if @kotlinx.serialization.Serializable class ** {\n    public static ** INSTANCE;\n}\n-keepclassmembers class <1> {\n    public static <1> INSTANCE;\n    kotlinx.serialization.KSerializer serializer(...);\n}\n\n# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.\n-keepattributes RuntimeVisibleAnnotations,AnnotationDefault\n\n# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.\n# If you have any, uncomment and replace classes with those containing named companion objects.\n#-keepattributes InnerClasses # Needed for `getDeclaredClasses`.\n#-if @kotlinx.serialization.Serializable class\n#com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.\n#com.example.myapplication.HasNamedCompanion2\n#{\n#    static **$* *;\n#}\n#-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.\n#    static <1>$$serializer INSTANCE;\n#}"
  },
  {
    "path": "app/schemas/com.junkfood.seal.database.AppDatabase/1.json",
    "content": "{\n  \"formatVersion\": 1,\n  \"database\": {\n    \"version\": 1,\n    \"identityHash\": \"988509a71f29b1a28b60e346980acccb\",\n    \"entities\": [\n      {\n        \"tableName\": \"DownloadedVideoInfo\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoTitle` TEXT NOT NULL, `videoAuthor` TEXT NOT NULL, `videoUrl` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL, `videoPath` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoTitle\",\n            \"columnName\": \"videoTitle\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoAuthor\",\n            \"columnName\": \"videoAuthor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoUrl\",\n            \"columnName\": \"videoUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"thumbnailUrl\",\n            \"columnName\": \"thumbnailUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoPath\",\n            \"columnName\": \"videoPath\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"id\"\n          ],\n          \"autoGenerate\": true\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      }\n    ],\n    \"views\": [],\n    \"setupQueries\": [\n      \"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)\",\n      \"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '988509a71f29b1a28b60e346980acccb')\"\n    ]\n  }\n}"
  },
  {
    "path": "app/schemas/com.junkfood.seal.database.AppDatabase/2.json",
    "content": "{\n  \"formatVersion\": 1,\n  \"database\": {\n    \"version\": 2,\n    \"identityHash\": \"4af4e9805a6d4977cdf27c8cb419c965\",\n    \"entities\": [\n      {\n        \"tableName\": \"DownloadedVideoInfo\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoTitle` TEXT NOT NULL, `videoAuthor` TEXT NOT NULL, `videoUrl` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL, `videoPath` TEXT NOT NULL, `extractor` TEXT NOT NULL DEFAULT 'Unknown')\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoTitle\",\n            \"columnName\": \"videoTitle\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoAuthor\",\n            \"columnName\": \"videoAuthor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoUrl\",\n            \"columnName\": \"videoUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"thumbnailUrl\",\n            \"columnName\": \"thumbnailUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoPath\",\n            \"columnName\": \"videoPath\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"extractor\",\n            \"columnName\": \"extractor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true,\n            \"defaultValue\": \"'Unknown'\"\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"id\"\n          ],\n          \"autoGenerate\": true\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      }\n    ],\n    \"views\": [],\n    \"setupQueries\": [\n      \"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)\",\n      \"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4af4e9805a6d4977cdf27c8cb419c965')\"\n    ]\n  }\n}"
  },
  {
    "path": "app/schemas/com.junkfood.seal.database.AppDatabase/3.json",
    "content": "{\n  \"formatVersion\": 1,\n  \"database\": {\n    \"version\": 3,\n    \"identityHash\": \"63b1cd29253fd3dd9060188d793fa8d3\",\n    \"entities\": [\n      {\n        \"tableName\": \"DownloadedVideoInfo\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoTitle` TEXT NOT NULL, `videoAuthor` TEXT NOT NULL, `videoUrl` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL, `videoPath` TEXT NOT NULL, `extractor` TEXT NOT NULL DEFAULT 'Unknown')\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoTitle\",\n            \"columnName\": \"videoTitle\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoAuthor\",\n            \"columnName\": \"videoAuthor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoUrl\",\n            \"columnName\": \"videoUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"thumbnailUrl\",\n            \"columnName\": \"thumbnailUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoPath\",\n            \"columnName\": \"videoPath\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"extractor\",\n            \"columnName\": \"extractor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true,\n            \"defaultValue\": \"'Unknown'\"\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"id\"\n          ],\n          \"autoGenerate\": true\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"CommandTemplate\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `template` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"name\",\n            \"columnName\": \"name\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"template\",\n            \"columnName\": \"template\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"id\"\n          ],\n          \"autoGenerate\": true\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      }\n    ],\n    \"views\": [],\n    \"setupQueries\": [\n      \"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)\",\n      \"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '63b1cd29253fd3dd9060188d793fa8d3')\"\n    ]\n  }\n}"
  },
  {
    "path": "app/schemas/com.junkfood.seal.database.AppDatabase/4.json",
    "content": "{\n  \"formatVersion\": 1,\n  \"database\": {\n    \"version\": 4,\n    \"identityHash\": \"d049bb757be0d1c233c7ec34bfde51dc\",\n    \"entities\": [\n      {\n        \"tableName\": \"DownloadedVideoInfo\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoTitle` TEXT NOT NULL, `videoAuthor` TEXT NOT NULL, `videoUrl` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL, `videoPath` TEXT NOT NULL, `extractor` TEXT NOT NULL DEFAULT 'Unknown')\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoTitle\",\n            \"columnName\": \"videoTitle\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoAuthor\",\n            \"columnName\": \"videoAuthor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoUrl\",\n            \"columnName\": \"videoUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"thumbnailUrl\",\n            \"columnName\": \"thumbnailUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoPath\",\n            \"columnName\": \"videoPath\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"extractor\",\n            \"columnName\": \"extractor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true,\n            \"defaultValue\": \"'Unknown'\"\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"CommandTemplate\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `template` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"name\",\n            \"columnName\": \"name\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"template\",\n            \"columnName\": \"template\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"CookieProfile\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"url\",\n            \"columnName\": \"url\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"content\",\n            \"columnName\": \"content\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      }\n    ],\n    \"views\": [],\n    \"setupQueries\": [\n      \"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)\",\n      \"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd049bb757be0d1c233c7ec34bfde51dc')\"\n    ]\n  }\n}"
  },
  {
    "path": "app/schemas/com.junkfood.seal.database.AppDatabase/5.json",
    "content": "{\n  \"formatVersion\": 1,\n  \"database\": {\n    \"version\": 5,\n    \"identityHash\": \"5eab3a1c93713521f1197fa2e2903231\",\n    \"entities\": [\n      {\n        \"tableName\": \"DownloadedVideoInfo\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoTitle` TEXT NOT NULL, `videoAuthor` TEXT NOT NULL, `videoUrl` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL, `videoPath` TEXT NOT NULL, `extractor` TEXT NOT NULL DEFAULT 'Unknown')\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoTitle\",\n            \"columnName\": \"videoTitle\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoAuthor\",\n            \"columnName\": \"videoAuthor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoUrl\",\n            \"columnName\": \"videoUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"thumbnailUrl\",\n            \"columnName\": \"thumbnailUrl\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"videoPath\",\n            \"columnName\": \"videoPath\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"extractor\",\n            \"columnName\": \"extractor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true,\n            \"defaultValue\": \"'Unknown'\"\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"CommandTemplate\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `template` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"name\",\n            \"columnName\": \"name\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"template\",\n            \"columnName\": \"template\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"CookieProfile\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"url\",\n            \"columnName\": \"url\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"content\",\n            \"columnName\": \"content\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"OptionShortcut\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `option` TEXT NOT NULL)\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"id\",\n            \"columnName\": \"id\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"option\",\n            \"columnName\": \"option\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"autoGenerate\": true,\n          \"columnNames\": [\n            \"id\"\n          ]\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      }\n    ],\n    \"views\": [],\n    \"setupQueries\": [\n      \"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)\",\n      \"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5eab3a1c93713521f1197fa2e2903231')\"\n    ]\n  }\n}"
  },
  {
    "path": "app/src/androidTest/java/com/junkfood/seal/ExampleInstrumentedTest.kt",
    "content": "package com.junkfood.seal\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport org.junit.Assert.*\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\n@RunWith(AndroidJUnit4::class)\nclass ExampleInstrumentedTest {\n    @Test\n    fun useAppContext() {\n        // Context of the app under test.\n        val appContext = InstrumentationRegistry.getInstrumentation().targetContext\n        assertEquals(\"com.junkfood.Seal\", appContext.packageName)\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission\n        android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"\n        android:maxSdkVersion=\"29\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />\n    <uses-permission\n        android:name=\"android.permission.POST_NOTIFICATIONS\"\n        android:minSdkVersion=\"33\" />\n    <uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />\n    <uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\" />\n    <uses-permission\n        android:name=\"android.permission.MANAGE_EXTERNAL_STORAGE\"\n        tools:ignore=\"ScopedStorage\" />\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_SPECIAL_USE\" />\n\n    <queries>\n        <intent>\n            <action android:name=\"android.intent.action.VIEW\" />\n\n            <category android:name=\"android.intent.category.BROWSABLE\" />\n\n            <data android:scheme=\"https\" />\n        </intent>\n    </queries>\n\n    <application\n        android:name=\".App\"\n        android:allowBackup=\"true\"\n        android:enableOnBackInvokedCallback=\"true\"\n        android:extractNativeLibs=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:requestLegacyExternalStorage=\"true\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        tools:targetApi=\"tiramisu\">\n        <activity\n            android:name=\".CrashReportActivity\"\n            android:exported=\"false\"\n            android:label=\"CrashReportActivity\"\n            android:theme=\"@style/Theme.Seal\" />\n        <activity\n            android:name=\".QuickDownloadActivity\"\n            android:excludeFromRecents=\"true\"\n            android:exported=\"true\"\n            android:label=\"@string/title_activity_share\"\n            android:launchMode=\"singleInstance\"\n            android:theme=\"@style/Theme.Seal.Dialog\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.SEND\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n\n                <data android:mimeType=\"text/plain\" />\n            </intent-filter>\n            <intent-filter>\n                <action android:name=\"android.intent.action.VIEW\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n                <category android:name=\"android.intent.category.BROWSABLE\" />\n\n                <data android:scheme=\"http\" />\n                <data android:scheme=\"https\" />\n                <data android:mimeType=\"video/*\" />\n                <data android:mimeType=\"audio/*\" />\n            </intent-filter>\n        </activity>\n\n        <service\n            android:name=\".DownloadService\"\n            android:enabled=\"true\"\n            android:exported=\"false\"\n            android:foregroundServiceType=\"specialUse\" />\n\n        <activity\n            android:name=\".MainActivity\"\n            android:configChanges=\"orientation\"\n            android:exported=\"true\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"unspecified\"\n            android:theme=\"@style/Theme.Seal\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n            <intent-filter>\n                <action android:name=\"android.intent.action.SEND\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n\n                <data android:mimeType=\"text/plain\" />\n            </intent-filter>\n            <intent-filter>\n                <action android:name=\"android.intent.action.VIEW\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n                <category android:name=\"android.intent.category.BROWSABLE\" />\n\n                <data android:scheme=\"http\" />\n                <data android:scheme=\"https\" />\n                <data android:mimeType=\"video/*\" />\n                <data android:mimeType=\"audio/*\" />\n            </intent-filter>\n        </activity>\n\n        <service\n            android:name=\"androidx.appcompat.app.AppLocalesMetadataHolderService\"\n            android:enabled=\"false\"\n            android:exported=\"false\">\n            <meta-data\n                android:name=\"autoStoreLocales\"\n                android:value=\"true\" />\n        </service>\n\n        <provider\n            android:name=\"androidx.core.content.FileProvider\"\n            android:authorities=\"${applicationId}.provider\"\n            android:exported=\"false\"\n            android:grantUriPermissions=\"true\">\n            <meta-data\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\n                android:resource=\"@xml/provider_paths\" />\n        </provider>\n\n        <receiver android:name=\".NotificationActionReceiver\" />\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/App.kt",
    "content": "package com.junkfood.seal\n\nimport android.annotation.SuppressLint\nimport android.app.Application\nimport android.content.ClipboardManager\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.content.ServiceConnection\nimport android.content.pm.PackageInfo\nimport android.content.pm.PackageManager\nimport android.net.ConnectivityManager\nimport android.net.Uri\nimport android.os.Build\nimport android.os.IBinder\nimport androidx.core.content.getSystemService\nimport com.google.android.material.color.DynamicColors\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.download.DownloaderV2Impl\nimport com.junkfood.seal.ui.page.download.HomePageViewModel\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel\nimport com.junkfood.seal.ui.page.settings.directory.Directory\nimport com.junkfood.seal.ui.page.settings.network.CookiesViewModel\nimport com.junkfood.seal.ui.page.videolist.VideoListViewModel\nimport com.junkfood.seal.util.AUDIO_DIRECTORY\nimport com.junkfood.seal.util.COMMAND_DIRECTORY\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.FileUtil.createEmptyFile\nimport com.junkfood.seal.util.FileUtil.getCookiesFile\nimport com.junkfood.seal.util.FileUtil.getExternalDownloadDirectory\nimport com.junkfood.seal.util.FileUtil.getExternalPrivateDownloadDirectory\nimport com.junkfood.seal.util.NotificationUtil\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.SDCARD_URI\nimport com.junkfood.seal.util.UpdateUtil\nimport com.junkfood.seal.util.VIDEO_DIRECTORY\nimport com.junkfood.seal.util.YT_DLP_VERSION\nimport com.tencent.mmkv.MMKV\nimport com.yausername.aria2c.Aria2c\nimport com.yausername.ffmpeg.FFmpeg\nimport com.yausername.youtubedl_android.YoutubeDL\nimport java.io.File\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.SupervisorJob\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport org.koin.android.ext.koin.androidContext\nimport org.koin.android.ext.koin.androidLogger\nimport org.koin.core.context.startKoin\nimport org.koin.core.module.dsl.viewModel\nimport org.koin.dsl.module\n\nclass App : Application() {\n    override fun onCreate() {\n        super.onCreate()\n        MMKV.initialize(this)\n\n        startKoin {\n            androidLogger()\n            androidContext(this@App)\n            modules(\n                module {\n                    single<DownloaderV2> { DownloaderV2Impl(androidContext()) }\n                    viewModel { DownloadDialogViewModel(downloader = get()) }\n                    viewModel { HomePageViewModel() }\n                    viewModel { CookiesViewModel() }\n                    viewModel { VideoListViewModel() }\n                }\n            )\n        }\n\n        context = applicationContext\n        packageInfo =\n            packageManager.run {\n                if (Build.VERSION.SDK_INT >= 33)\n                    getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))\n                else getPackageInfo(packageName, 0)\n            }\n        applicationScope = CoroutineScope(SupervisorJob())\n        DynamicColors.applyToActivitiesIfAvailable(this)\n\n        clipboard = getSystemService()!!\n        connectivityManager = getSystemService()!!\n\n        applicationScope.launch((Dispatchers.IO)) {\n            try {\n                YoutubeDL.init(this@App)\n                FFmpeg.init(this@App)\n                Aria2c.init(this@App)\n                DownloadUtil.getCookiesContentFromDatabase().getOrNull()?.let {\n                    FileUtil.writeContentToFile(it, getCookiesFile())\n                }\n                UpdateUtil.deleteOutdatedApk()\n            } catch (th: Throwable) {\n                withContext(Dispatchers.Main) { startCrashReportActivity(th) }\n            }\n        }\n\n        videoDownloadDir = VIDEO_DIRECTORY.getString(getExternalDownloadDirectory().absolutePath)\n\n        audioDownloadDir = AUDIO_DIRECTORY.getString(File(videoDownloadDir, \"Audio\").absolutePath)\n        if (!PreferenceUtil.containsKey(COMMAND_DIRECTORY)) {\n            COMMAND_DIRECTORY.updateString(videoDownloadDir)\n        }\n        if (Build.VERSION.SDK_INT >= 26) NotificationUtil.createNotificationChannel()\n\n        Thread.setDefaultUncaughtExceptionHandler { _, e -> startCrashReportActivity(e) }\n    }\n\n    private fun startCrashReportActivity(th: Throwable) {\n        th.printStackTrace()\n        startActivity(\n            Intent(this, CrashReportActivity::class.java)\n                .setAction(\"$packageName.error_report\")\n                .apply {\n                    flags = Intent.FLAG_ACTIVITY_NEW_TASK\n                    putExtra(\"error_report\", getVersionReport() + \"\\n\" + th.stackTraceToString())\n                }\n        )\n    }\n\n    companion object {\n        lateinit var clipboard: ClipboardManager\n        lateinit var videoDownloadDir: String\n        lateinit var audioDownloadDir: String\n        lateinit var applicationScope: CoroutineScope\n        lateinit var connectivityManager: ConnectivityManager\n        lateinit var packageInfo: PackageInfo\n\n        var isServiceRunning = false\n\n        private val connection =\n            object : ServiceConnection {\n                override fun onServiceConnected(className: ComponentName, service: IBinder) {\n                    val binder = service as DownloadService.DownloadServiceBinder\n                    isServiceRunning = true\n                }\n\n                override fun onServiceDisconnected(arg0: ComponentName) {}\n            }\n\n        fun startService() {\n            if (isServiceRunning) return\n            Intent(context.applicationContext, DownloadService::class.java).also { intent ->\n                context.applicationContext.bindService(intent, connection, Context.BIND_AUTO_CREATE)\n            }\n        }\n\n        fun stopService() {\n            if (!isServiceRunning) return\n            try {\n                isServiceRunning = false\n                context.applicationContext.run { unbindService(connection) }\n            } catch (e: Exception) {\n                e.printStackTrace()\n            }\n        }\n\n        val privateDownloadDir: String\n            get() =\n                getExternalPrivateDownloadDirectory().run {\n                    createEmptyFile(\".nomedia\")\n                    absolutePath\n                }\n\n        fun updateDownloadDir(uri: Uri, directoryType: Directory) {\n            when (directoryType) {\n                Directory.AUDIO -> {\n                    val path = FileUtil.getRealPath(uri)\n                    audioDownloadDir = path\n                    PreferenceUtil.encodeString(AUDIO_DIRECTORY, path)\n                }\n\n                Directory.VIDEO -> {\n                    val path = FileUtil.getRealPath(uri)\n                    videoDownloadDir = path\n                    PreferenceUtil.encodeString(VIDEO_DIRECTORY, path)\n                }\n\n                Directory.CUSTOM_COMMAND -> {\n                    val path = FileUtil.getRealPath(uri)\n                }\n\n                Directory.SDCARD -> {\n                    context.contentResolver?.takePersistableUriPermission(\n                        uri,\n                        Intent.FLAG_GRANT_READ_URI_PERMISSION or\n                            Intent.FLAG_GRANT_WRITE_URI_PERMISSION,\n                    )\n                    PreferenceUtil.encodeString(SDCARD_URI, uri.toString())\n                }\n            }\n        }\n\n        fun getVersionReport(): String {\n            val versionName = packageInfo.versionName\n            val page = packageInfo\n            val versionCode =\n                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {\n                    packageInfo.longVersionCode\n                } else {\n                    packageInfo.versionCode.toLong()\n                }\n            val release =\n                if (Build.VERSION.SDK_INT >= 30) {\n                    Build.VERSION.RELEASE_OR_CODENAME\n                } else {\n                    Build.VERSION.RELEASE\n                }\n            return StringBuilder()\n                .append(\"App version: $versionName ($versionCode)\\n\")\n                .append(\"Device information: Android $release (API ${Build.VERSION.SDK_INT})\\n\")\n                .append(\"Supported ABIs: ${Build.SUPPORTED_ABIS.contentToString()}\\n\")\n                .append(\"Yt-dlp version: ${YT_DLP_VERSION.getString()}\\n\")\n                .toString()\n        }\n\n        fun isFDroidBuild(): Boolean = BuildConfig.FLAVOR == \"fdroid\"\n\n        fun isDebugBuild(): Boolean = BuildConfig.DEBUG\n\n        @SuppressLint(\"StaticFieldLeak\") lateinit var context: Context\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/CrashReportActivity.kt",
    "content": "package com.junkfood.seal\n\nimport android.os.Bundle\nimport androidx.activity.ComponentActivity\nimport androidx.activity.compose.setContent\nimport androidx.activity.enableEdgeToEdge\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.navigationBarsPadding\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.BugReport\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.SettingsProvider\nimport com.junkfood.seal.ui.component.FilledButtonWithIcon\nimport com.junkfood.seal.ui.theme.SealTheme\n\nclass CrashReportActivity : ComponentActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        enableEdgeToEdge()\n        val errorMessage: String = intent.getStringExtra(\"error_report\").toString()\n\n        setContent {\n            SettingsProvider(WindowWidthSizeClass.Compact) {\n                SealTheme(\n                    darkTheme = LocalDarkTheme.current.isDarkTheme(),\n                    isHighContrastModeEnabled = LocalDarkTheme.current.isHighContrastModeEnabled,\n                ) {\n                    val clipboardManager = LocalClipboardManager.current\n                    CrashReportPage(errorMessage = errorMessage) {\n                        clipboardManager.setText(AnnotatedString(errorMessage))\n                        this.finishAffinity()\n                    }\n                }\n            }\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        if (isFinishing) finishAffinity()\n    }\n}\n\n@Composable\n@Preview\nfun CrashReportPage(errorMessage: String = \"ERROR_EXAMPLE\", onClick: () -> Unit = {}) {\n    Scaffold(\n        modifier = Modifier.fillMaxSize(),\n        bottomBar = {\n            androidx.compose.material3.HorizontalDivider()\n\n            FilledButtonWithIcon(\n                modifier =\n                    Modifier.fillMaxWidth()\n                        .navigationBarsPadding()\n                        .padding(horizontal = 16.dp, vertical = 8.dp),\n                onClick = onClick,\n                icon = Icons.Outlined.BugReport,\n                text = stringResource(R.string.copy_and_exit),\n            )\n        },\n    ) {\n        Column(modifier = Modifier.padding(it).verticalScroll(rememberScrollState())) {\n            Text(\n                text = stringResource(R.string.unknown_error_title),\n                style = MaterialTheme.typography.displaySmall,\n                modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 60.dp, bottom = 12.dp),\n            )\n            Text(\n                text = errorMessage,\n                style = MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),\n                color = MaterialTheme.colorScheme.onSurfaceVariant,\n                modifier = Modifier.padding(16.dp).fillMaxWidth(),\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/DownloadService.kt",
    "content": "package com.junkfood.seal\n\nimport android.app.PendingIntent\nimport android.app.Service\nimport android.content.Intent\nimport android.os.Binder\nimport android.os.Build\nimport android.os.IBinder\nimport android.util.Log\nimport com.junkfood.seal.util.NotificationUtil\nimport com.junkfood.seal.util.NotificationUtil.SERVICE_NOTIFICATION_ID\n\nprivate const val TAG = \"DownloadService\"\n\n/** This `Service` does nothing */\nclass DownloadService : Service() {\n\n    override fun onBind(intent: Intent): IBinder {\n        val pendingIntent: PendingIntent =\n            Intent(this, MainActivity::class.java).let { notificationIntent ->\n                PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)\n            }\n        val notification = NotificationUtil.makeServiceNotification(pendingIntent)\n        startForeground(SERVICE_NOTIFICATION_ID, notification)\n        return DownloadServiceBinder()\n    }\n\n    override fun onUnbind(intent: Intent?): Boolean {\n        Log.d(TAG, \"onUnbind: \")\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n            stopForeground(STOP_FOREGROUND_REMOVE)\n        } else {\n            stopForeground(true)\n        }\n        stopSelf()\n        return super.onUnbind(intent)\n    }\n\n    inner class DownloadServiceBinder : Binder() {\n        fun getService(): DownloadService = this@DownloadService\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/Downloader.kt",
    "content": "package com.junkfood.seal\n\nimport android.app.PendingIntent\nimport android.util.Log\nimport androidx.annotation.CheckResult\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.mutableStateMapOf\nimport androidx.compose.ui.platform.ClipboardManager\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport com.junkfood.seal.App.Companion.applicationScope\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.App.Companion.startService\nimport com.junkfood.seal.App.Companion.stopService\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.util.COMMAND_DIRECTORY\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.NotificationUtil\nimport com.junkfood.seal.util.PlaylistEntry\nimport com.junkfood.seal.util.PlaylistResult\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.VideoInfo\nimport com.junkfood.seal.util.toHttpsUrl\nimport com.yausername.youtubedl_android.YoutubeDL\nimport java.util.concurrent.CancellationException\nimport kotlin.math.roundToInt\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.asStateFlow\nimport kotlinx.coroutines.flow.combine\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\n\n/** Singleton Downloader for state holder & perform downloads, used by `Activity` & `Service` */\nobject Downloader {\n\n    private const val TAG = \"Downloader\"\n\n    sealed class State {\n        data class DownloadingPlaylist(val currentItem: Int = 0, val itemCount: Int = 0) : State()\n\n        data object DownloadingVideo : State()\n\n        data object FetchingInfo : State()\n\n        data object Idle : State()\n\n        data object Updating : State()\n    }\n\n    sealed class ErrorState(open val url: String = \"\", open val report: String = \"\") {\n        data class DownloadError(override val url: String, override val report: String) :\n            ErrorState(url = url, report = report)\n\n        data class FetchInfoError(override val url: String, override val report: String) :\n            ErrorState(url = url, report = report)\n\n        data object None : ErrorState()\n\n        val title: String\n            @Composable\n            get() =\n                when (this) {\n                    is DownloadError -> stringResource(id = R.string.download_error_msg)\n                    is FetchInfoError -> stringResource(id = R.string.fetch_info_error_msg)\n                    None -> \"\"\n                }\n    }\n\n    data class CustomCommandTask(\n        val template: CommandTemplate,\n        val url: String,\n        val output: String,\n        val state: State,\n        val currentLine: String,\n    ) {\n        fun toKey() = makeKey(url, template.name)\n\n        sealed class State {\n            data class Error(val errorReport: String) : State()\n\n            object Completed : State()\n\n            object Canceled : State()\n\n            data class Running(val progress: Float) : State()\n        }\n\n        override fun hashCode(): Int {\n            return (this.url + this.template.name + this.template.template).hashCode()\n        }\n\n        override fun equals(other: Any?): Boolean {\n            if (this === other) return true\n            if (javaClass != other?.javaClass) return false\n\n            other as CustomCommandTask\n\n            if (template != other.template) return false\n            if (url != other.url) return false\n            if (output != other.output) return false\n            if (state != other.state) return false\n            if (currentLine != other.currentLine) return false\n\n            return true\n        }\n\n        fun onCopyLog(clipboardManager: ClipboardManager) {\n            clipboardManager.setText(AnnotatedString(output))\n        }\n\n        fun onRestart() {\n            applicationScope.launch(Dispatchers.IO) {\n                DownloadUtil.executeCommandInBackground(url, template)\n            }\n        }\n\n        fun onCopyError(clipboardManager: ClipboardManager) {\n            clipboardManager.setText(AnnotatedString(currentLine))\n            ToastUtil.makeToast(R.string.error_copied)\n        }\n\n        fun onCancel() {\n            toKey().run {\n                YoutubeDL.destroyProcessById(this)\n                onProcessCanceled(this)\n            }\n        }\n    }\n\n    data class DownloadTaskItem(\n        val webpageUrl: String = \"\",\n        val title: String = \"\",\n        val uploader: String = \"\",\n        val duration: Int = 0,\n        val fileSizeApprox: Double = .0,\n        val progress: Float = 0f,\n        val progressText: String = \"\",\n        val thumbnailUrl: String = \"\",\n        val taskId: String = \"\",\n        val playlistIndex: Int = 0,\n    )\n\n    private var currentJob: Job? = null\n    private var downloadResultTemp: Result<List<String>> = Result.failure(Exception())\n\n    private val mutableDownloaderState: MutableStateFlow<State> = MutableStateFlow(State.Idle)\n    private val mutableTaskState = MutableStateFlow(DownloadTaskItem())\n    private val mutablePlaylistResult = MutableStateFlow(PlaylistResult())\n    private val mutableErrorState: MutableStateFlow<ErrorState> = MutableStateFlow(ErrorState.None)\n    private val mutableProcessCount = MutableStateFlow(0)\n    private val mutableQuickDownloadCount = MutableStateFlow(0)\n\n    val mutableTaskList = mutableStateMapOf<String, CustomCommandTask>()\n\n    val taskState = mutableTaskState.asStateFlow()\n    val downloaderState = mutableDownloaderState.asStateFlow()\n    val playlistResult = mutablePlaylistResult.asStateFlow()\n    val errorState = mutableErrorState.asStateFlow()\n    val processCount = mutableProcessCount.asStateFlow()\n\n    init {\n        applicationScope.launch {\n            downloaderState\n                .combine(processCount) { state, cnt ->\n                    if (cnt > 0) true\n                    else\n                        when (state) {\n                            is State.Idle -> false\n                            else -> true\n                        }\n                }\n                .combine(mutableQuickDownloadCount) { isRunning, cnt ->\n                    if (!isRunning) cnt > 0 else true\n                }\n                .collect { if (it) startService() else stopService() }\n        }\n    }\n\n    fun isDownloaderAvailable(): Boolean {\n        return downloaderState.value is State.Idle\n    }\n\n    fun makeKey(url: String, templateName: String): String = \"${templateName}_$url\"\n\n    fun onTaskStarted(template: CommandTemplate, url: String) =\n        CustomCommandTask(\n                template = template,\n                url = url,\n                output = \"\",\n                state = CustomCommandTask.State.Running(0f),\n                currentLine = \"\",\n            )\n            .run { mutableTaskList.put(this.toKey(), this) }\n\n    fun updateTaskOutput(template: CommandTemplate, url: String, line: String, progress: Float) {\n        val key = makeKey(url, template.name)\n        val oldValue = mutableTaskList[key] ?: return\n        val newValue =\n            oldValue.run {\n                copy(\n                    output = output + line + \"\\n\",\n                    currentLine = line,\n                    state = CustomCommandTask.State.Running(progress),\n                )\n            }\n        mutableTaskList[key] = newValue\n    }\n\n    fun onTaskEnded(template: CommandTemplate, url: String, response: String? = null) {\n        val key = makeKey(url, template.name)\n        NotificationUtil.finishNotification(\n            notificationId = key.toNotificationId(),\n            title = key,\n            text = context.getString(R.string.status_completed),\n        )\n        mutableTaskList.run {\n            val oldValue = get(key) ?: return\n            val newValue =\n                oldValue.copy(state = CustomCommandTask.State.Completed).run {\n                    response?.let { copy(output = response) } ?: this\n                }\n            this[key] = newValue\n        }\n        FileUtil.scanDownloadDirectoryToMediaLibrary(COMMAND_DIRECTORY.getString())\n    }\n\n    fun onProcessEnded() = mutableProcessCount.update { it - 1 }\n\n    fun onProcessCanceled(taskId: String) =\n        mutableTaskList.run {\n            get(taskId)?.let { this.put(taskId, it.copy(state = CustomCommandTask.State.Canceled)) }\n        }\n\n    fun onTaskError(errorReport: String, template: CommandTemplate, url: String) =\n        mutableTaskList.run {\n            val key = makeKey(url, template.name)\n            NotificationUtil.notifyError(\n                title = \"\",\n                notificationId = key.toNotificationId(),\n                report = errorReport,\n            )\n            val oldValue = mutableTaskList[key] ?: return\n            mutableTaskList[key] =\n                oldValue.copy(\n                    state = CustomCommandTask.State.Error(errorReport),\n                    currentLine = errorReport,\n                    output = oldValue.output + \"\\n\" + errorReport,\n                )\n        }\n\n    private fun VideoInfo.toTask(playlistIndex: Int = 0, preferencesHash: Int): DownloadTaskItem =\n        DownloadTaskItem(\n            webpageUrl = webpageUrl.toString(),\n            title = title,\n            uploader = uploader ?: channel ?: uploaderId.toString(),\n            duration = duration?.roundToInt() ?: 0,\n            taskId = id + preferencesHash,\n            thumbnailUrl = thumbnail.toHttpsUrl(),\n            fileSizeApprox = fileSize ?: fileSizeApprox ?: .0,\n            playlistIndex = playlistIndex,\n        )\n\n    fun updateState(state: State) = mutableDownloaderState.update { state }\n\n    fun clearErrorState() {\n        mutableErrorState.update { ErrorState.None }\n    }\n\n    private fun fetchInfoError(url: String, errorReport: String) {\n        mutableErrorState.update { ErrorState.FetchInfoError(url, errorReport) }\n    }\n\n    private fun downloadError(url: String, errorReport: String) {\n        mutableErrorState.update { ErrorState.DownloadError(url, errorReport) }\n    }\n\n    private fun clearProgressState(isFinished: Boolean) {\n        mutableTaskState.update {\n            it.copy(progress = if (isFinished) 100f else 0f, progressText = \"\")\n        }\n        if (!isFinished) downloadResultTemp = Result.failure(Exception())\n    }\n\n    fun updatePlaylistResult(playlistResult: PlaylistResult = PlaylistResult()) =\n        mutablePlaylistResult.update { playlistResult }\n\n    fun getInfoAndDownload(\n        url: String,\n        preferences: DownloadUtil.DownloadPreferences =\n            DownloadUtil.DownloadPreferences.createFromPreferences(),\n    ) {\n        currentJob =\n            applicationScope.launch(Dispatchers.IO) {\n                updateState(State.FetchingInfo)\n                DownloadUtil.fetchVideoInfoFromUrl(url = url, preferences = preferences)\n                    .onFailure {\n                        manageDownloadError(\n                            th = it,\n                            url = url,\n                            isFetchingInfo = true,\n                            isTaskAborted = true,\n                        )\n                    }\n                    .onSuccess { info ->\n                        downloadResultTemp =\n                            downloadVideo(videoInfo = info, preferences = preferences)\n                    }\n            }\n    }\n\n    fun addToDownloadQueue(\n        videoInfo: VideoInfo? = null,\n        url: String = videoInfo?.originalUrl ?: \"\",\n        preferences: DownloadUtil.DownloadPreferences =\n            DownloadUtil.DownloadPreferences.createFromPreferences(),\n    ) {\n        require(url.isNotEmpty() || videoInfo != null)\n\n        if (!isDownloaderAvailable()) {\n            ToastUtil.makeToast(R.string.task_added)\n            applicationScope\n                .launch(Dispatchers.Default) {\n                    while (!isDownloaderAvailable()) {\n                        delay(3000)\n                    }\n                }\n                .invokeOnCompletion {\n                    videoInfo?.let {\n                        downloadVideoWithInfo(info = videoInfo, preferences = preferences)\n                    } ?: getInfoAndDownload(url, preferences)\n                }\n        } else {\n            videoInfo?.let { downloadVideoWithInfo(info = videoInfo, preferences = preferences) }\n                ?: getInfoAndDownload(url, preferences)\n        }\n    }\n\n    fun downloadVideoWithInfo(\n        info: VideoInfo,\n        preferences: DownloadUtil.DownloadPreferences =\n            DownloadUtil.DownloadPreferences.createFromPreferences(),\n    ) {\n        currentJob =\n            applicationScope.launch(Dispatchers.IO) {\n                downloadResultTemp = downloadVideo(videoInfo = info, preferences = preferences)\n            }\n    }\n\n    /**\n     * This method is used for download a single video and multiple videos from playlist at the same\n     * time.\n     *\n     * @see downloadVideoInPlaylistByIndexList\n     * @see getInfoAndDownload\n     */\n    @CheckResult\n    private suspend fun downloadVideo(\n        playlistIndex: Int = 0,\n        playlistUrl: String = \"\",\n        videoInfo: VideoInfo,\n        preferences: DownloadUtil.DownloadPreferences =\n            DownloadUtil.DownloadPreferences.createFromPreferences(),\n    ): Result<List<String>> {\n\n        Log.d(TAG, preferences.subtitleLanguage)\n        mutableTaskState.update { videoInfo.toTask(preferencesHash = preferences.hashCode()) }\n\n        val isDownloadingPlaylist = downloaderState.value is State.DownloadingPlaylist\n        if (!isDownloadingPlaylist) updateState(State.DownloadingVideo)\n        val taskId = videoInfo.id + preferences.hashCode()\n        val notificationId = taskId.toNotificationId()\n        Log.d(TAG, \"downloadVideo: id=${videoInfo.id} \" + videoInfo.title)\n        Log.d(TAG, \"notificationId: $notificationId\")\n\n        NotificationUtil.notifyProgress(notificationId = notificationId, title = videoInfo.title)\n        return DownloadUtil.downloadVideo(\n                videoInfo = videoInfo,\n                playlistUrl = playlistUrl,\n                playlistItem = playlistIndex,\n                downloadPreferences = preferences,\n                taskId = videoInfo.id + preferences.hashCode(),\n            ) { progress, _, line ->\n                Log.d(TAG, line)\n                mutableTaskState.update { it.copy(progress = progress, progressText = line) }\n                NotificationUtil.notifyProgress(\n                    notificationId = notificationId,\n                    progress = progress.toInt(),\n                    text = line,\n                    title = videoInfo.title,\n                    taskId = taskId,\n                )\n            }\n            .onFailure {\n                manageDownloadError(\n                    th = it,\n                    url = videoInfo.originalUrl,\n                    title = videoInfo.title,\n                    isFetchingInfo = false,\n                    notificationId = notificationId,\n                    isTaskAborted = !isDownloadingPlaylist,\n                )\n            }\n            .onSuccess {\n                if (!isDownloadingPlaylist) finishProcessing()\n                val text =\n                    context.getString(\n                        if (it.isEmpty()) R.string.status_completed\n                        else R.string.download_finish_notification\n                    )\n                FileUtil.createIntentForOpeningFile(it.firstOrNull()).run {\n                    NotificationUtil.finishNotification(\n                        notificationId,\n                        title = videoInfo.title,\n                        text = text,\n                        intent =\n                            if (this != null)\n                                PendingIntent.getActivity(\n                                    context,\n                                    0,\n                                    this,\n                                    PendingIntent.FLAG_IMMUTABLE,\n                                )\n                            else null,\n                    )\n                }\n            }\n    }\n\n    fun downloadVideoInPlaylistByIndexList(\n        url: String,\n        indexList: List<Int>,\n        playlistItemList: List<PlaylistEntry> = emptyList(),\n        preferences: DownloadUtil.DownloadPreferences =\n            DownloadUtil.DownloadPreferences.createFromPreferences(),\n    ) {\n        val itemCount = indexList.size\n\n        if (!isDownloaderAvailable()) return\n\n        mutableDownloaderState.update { State.DownloadingPlaylist() }\n\n        currentJob =\n            applicationScope.launch(Dispatchers.IO) {\n                for (i in indexList.indices) {\n                    mutableDownloaderState.update {\n                        if (it is State.DownloadingPlaylist)\n                            it.copy(currentItem = i + 1, itemCount = indexList.size)\n                        else return@launch\n                    }\n\n                    NotificationUtil.updateServiceNotificationForPlaylist(\n                        index = i + 1,\n                        itemCount = itemCount,\n                    )\n\n                    val playlistIndex = indexList[i]\n                    val playlistEntry = playlistItemList.getOrNull(i)\n\n                    Log.d(TAG, playlistEntry?.title.toString())\n\n                    val title = playlistEntry?.title\n\n                    DownloadUtil.fetchVideoInfoFromUrl(\n                            url = url,\n                            playlistIndex = playlistIndex,\n                            preferences = preferences,\n                        )\n                        .onSuccess {\n                            if (downloaderState.value !is State.DownloadingPlaylist) return@launch\n                            downloadResultTemp =\n                                downloadVideo(\n                                        videoInfo = it,\n                                        playlistIndex = playlistIndex,\n                                        playlistUrl = url,\n                                        preferences = preferences,\n                                    )\n                                    .onFailure { th ->\n                                        manageDownloadError(\n                                            th = th,\n                                            url = it.originalUrl,\n                                            title = it.title,\n                                            isFetchingInfo = false,\n                                            isTaskAborted = false,\n                                        )\n                                    }\n                        }\n                        .onFailure { th ->\n                            manageDownloadError(\n                                th = th,\n                                url = playlistEntry?.url,\n                                title = title,\n                                isFetchingInfo = true,\n                                isTaskAborted = false,\n                            )\n                        }\n                }\n                finishProcessing()\n            }\n    }\n\n    private fun finishProcessing() {\n        if (downloaderState.value is State.Idle) return\n        mutableTaskState.update { it.copy(progress = 100f, progressText = \"\") }\n        clearProgressState(isFinished = true)\n        updateState(State.Idle)\n        clearErrorState()\n    }\n\n    /**\n     * @param isTaskAborted Determines if the download task is aborted due to the given `Exception`\n     */\n    fun manageDownloadError(\n        th: Throwable,\n        url: String?,\n        title: String? = null,\n        isFetchingInfo: Boolean,\n        isTaskAborted: Boolean = true,\n        notificationId: Int? = null,\n    ) {\n        if (th is YoutubeDL.CanceledException) return\n        th.printStackTrace()\n        val resId =\n            if (isFetchingInfo) R.string.fetch_info_error_msg else R.string.download_error_msg\n        ToastUtil.makeToastSuspend(context.getString(resId))\n\n        val notificationTitle = title ?: url\n\n        if (isFetchingInfo) {\n            fetchInfoError(url = url.toString(), errorReport = th.message.toString())\n        } else {\n            downloadError(url = url.toString(), errorReport = th.message.toString())\n        }\n\n        notificationId?.let {\n            NotificationUtil.finishNotification(\n                notificationId = notificationId,\n                title = notificationTitle,\n                text = context.getString(R.string.download_error_msg),\n            )\n        }\n        if (isTaskAborted) {\n            updateState(State.Idle)\n            clearProgressState(isFinished = false)\n        }\n    }\n\n    fun cancelDownload() {\n        ToastUtil.makeToast(context.getString(R.string.task_canceled))\n        currentJob?.cancel(CancellationException(context.getString(R.string.task_canceled)))\n        updateState(State.Idle)\n        clearProgressState(isFinished = false)\n        taskState.value.taskId.run {\n            YoutubeDL.destroyProcessById(this)\n            NotificationUtil.cancelNotification(this.toNotificationId())\n        }\n    }\n\n    fun executeCommandWithUrl(url: String) =\n        applicationScope.launch(Dispatchers.IO) { DownloadUtil.executeCommandInBackground(url) }\n\n    fun openDownloadResult() {\n        if (taskState.value.progress == 100f) FileUtil.openFileFromResult(downloadResultTemp)\n    }\n\n    fun onProcessStarted() = mutableProcessCount.update { it + 1 }\n\n    fun String.toNotificationId(): Int = this.hashCode()\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/MainActivity.kt",
    "content": "package com.junkfood.seal\n\nimport android.content.Intent\nimport android.os.Build\nimport android.os.Bundle\nimport androidx.activity.compose.setContent\nimport androidx.activity.enableEdgeToEdge\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi\nimport androidx.compose.material3.windowsizeclass.calculateWindowSizeClass\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.SettingsProvider\nimport com.junkfood.seal.ui.page.AppEntry\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.matchUrlFromSharedText\nimport com.junkfood.seal.util.setLanguage\nimport kotlinx.coroutines.runBlocking\nimport org.koin.androidx.viewmodel.ext.android.viewModel\nimport org.koin.compose.KoinContext\n\nclass MainActivity : AppCompatActivity() {\n    private val dialogViewModel: DownloadDialogViewModel by viewModel()\n\n    @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        if (Build.VERSION.SDK_INT < 33) {\n            runBlocking { setLanguage(PreferenceUtil.getLocaleFromPreference()) }\n        }\n        enableEdgeToEdge()\n\n        context = this.baseContext\n        setContent {\n            KoinContext {\n                val windowSizeClass = calculateWindowSizeClass(this)\n                SettingsProvider(windowWidthSizeClass = windowSizeClass.widthSizeClass) {\n                    SealTheme(\n                        darkTheme = LocalDarkTheme.current.isDarkTheme(),\n                        isHighContrastModeEnabled = LocalDarkTheme.current.isHighContrastModeEnabled,\n                    ) {\n                        AppEntry(dialogViewModel = dialogViewModel)\n                    }\n                }\n            }\n        }\n    }\n\n    override fun onNewIntent(intent: Intent) {\n        super.onNewIntent(intent)\n        val url = intent.getSharedURL()\n        if (url != null) {\n            dialogViewModel.postAction(DownloadDialogViewModel.Action.ShowSheet(listOf(url)))\n        }\n    }\n\n    private fun Intent.getSharedURL(): String? {\n        val intent = this\n\n        return when (intent.action) {\n            Intent.ACTION_VIEW -> {\n                intent.dataString\n            }\n\n            Intent.ACTION_SEND -> {\n                intent.getStringExtra(Intent.EXTRA_TEXT)?.let { sharedContent ->\n                    intent.removeExtra(Intent.EXTRA_TEXT)\n                    matchUrlFromSharedText(sharedContent).also { matchedUrl ->\n                        if (sharedUrlCached != matchedUrl) {\n                            sharedUrlCached = matchedUrl\n                        }\n                    }\n                }\n            }\n\n            else -> {\n                null\n            }\n        }\n    }\n\n    companion object {\n        private const val TAG = \"MainActivity\"\n        private var sharedUrlCached = \"\"\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/NotificationActionReceiver.kt",
    "content": "package com.junkfood.seal\n\nimport android.content.BroadcastReceiver\nimport android.content.ClipData\nimport android.content.Context\nimport android.content.Intent\nimport android.util.Log\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.util.NotificationUtil\nimport com.junkfood.seal.util.ToastUtil\nimport com.yausername.youtubedl_android.YoutubeDL\nimport org.koin.core.component.KoinComponent\nimport org.koin.core.component.get\n\nclass NotificationActionReceiver : BroadcastReceiver(), KoinComponent {\n    val downloader = get<DownloaderV2>()\n\n    companion object {\n        private const val TAG = \"CancelReceiver\"\n        private const val PACKAGE_NAME_PREFIX = \"com.junkfood.seal.\"\n\n        const val ACTION_CANCEL_TASK = 0\n        const val ACTION_ERROR_REPORT = 1\n\n        const val ACTION_KEY = PACKAGE_NAME_PREFIX + \"action\"\n        const val TASK_ID_KEY = PACKAGE_NAME_PREFIX + \"taskId\"\n\n        const val NOTIFICATION_ID_KEY = PACKAGE_NAME_PREFIX + \"notificationId\"\n        const val ERROR_REPORT_KEY = PACKAGE_NAME_PREFIX + \"error_report\"\n    }\n\n    override fun onReceive(context: Context?, intent: Intent?) {\n        if (intent == null) return\n        val notificationId = intent.getIntExtra(NOTIFICATION_ID_KEY, 0)\n        val action = intent.getIntExtra(ACTION_KEY, ACTION_CANCEL_TASK)\n        Log.d(TAG, \"onReceive: $action\")\n        when (action) {\n            ACTION_CANCEL_TASK -> {\n                val taskId = intent.getStringExtra(TASK_ID_KEY)\n                cancelTask(taskId, notificationId)\n            }\n\n            ACTION_ERROR_REPORT -> {\n                val errorReport = intent.getStringExtra(ERROR_REPORT_KEY)\n                if (!errorReport.isNullOrEmpty()) copyErrorReport(errorReport, notificationId)\n            }\n        }\n    }\n\n    private fun cancelTask(taskId: String?, notificationId: Int) {\n        if (taskId.isNullOrEmpty()) return\n        NotificationUtil.cancelNotification(notificationId)\n        val res = downloader.cancel(taskId)\n        if (res) {\n            Log.d(TAG, \"Task (id:$taskId) was killed.\")\n        } else {\n            // todo: reserved for custom commands\n            YoutubeDL.destroyProcessById(taskId)\n            Downloader.onProcessCanceled(taskId)\n        }\n    }\n\n    private fun copyErrorReport(error: String, notificationId: Int) {\n        App.clipboard.setPrimaryClip(ClipData.newPlainText(null, error))\n        context.let { ToastUtil.makeToastSuspend(it.getString(R.string.error_copied)) }\n        NotificationUtil.cancelNotification(notificationId)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/QuickDownloadActivity.kt",
    "content": "package com.junkfood.seal\n\nimport android.content.Intent\nimport android.graphics.drawable.ColorDrawable\nimport android.os.Build\nimport android.os.Bundle\nimport android.view.WindowManager\nimport androidx.activity.ComponentActivity\nimport androidx.activity.compose.setContent\nimport androidx.activity.enableEdgeToEdge\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.rememberModalBottomSheetState\nimport androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi\nimport androidx.compose.material3.windowsizeclass.calculateWindowSizeClass\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.SettingsProvider\nimport com.junkfood.seal.ui.page.downloadv2.configure.Config\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialog\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.Action\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SelectionState\nimport com.junkfood.seal.ui.page.downloadv2.configure.FormatPage\nimport com.junkfood.seal.ui.page.downloadv2.configure.PlaylistSelectionPage\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.matchUrlFromSharedText\nimport com.junkfood.seal.util.setLanguage\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\nimport org.koin.androidx.viewmodel.ext.android.getViewModel\n\nprivate const val TAG = \"QuickDownloadActivity\"\n\nclass QuickDownloadActivity : ComponentActivity() {\n    private var sharedUrlCached: String = \"\"\n\n    private fun Intent.getSharedURL(): String? {\n        val intent = this\n\n        return when (intent.action) {\n            Intent.ACTION_VIEW -> {\n                intent.dataString\n            }\n\n            Intent.ACTION_SEND -> {\n                intent.getStringExtra(Intent.EXTRA_TEXT)?.let { sharedContent ->\n                    intent.removeExtra(Intent.EXTRA_TEXT)\n                    matchUrlFromSharedText(sharedContent)\n                }\n            }\n\n            else -> {\n                null\n            }\n        }\n    }\n\n    @OptIn(ExperimentalMaterial3WindowSizeClassApi::class, ExperimentalMaterial3Api::class)\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        intent.getSharedURL()?.let { sharedUrlCached = it }\n\n        if (sharedUrlCached.isEmpty()) {\n            finish()\n        }\n\n        App.startService()\n\n        enableEdgeToEdge()\n\n        window.run {\n            setBackgroundDrawable(ColorDrawable(0))\n            setLayout(\n                WindowManager.LayoutParams.MATCH_PARENT,\n                WindowManager.LayoutParams.MATCH_PARENT,\n            )\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n                setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)\n            } else {\n                setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)\n            }\n        }\n\n        if (Build.VERSION.SDK_INT < 33) {\n            runBlocking { setLanguage(PreferenceUtil.getLocaleFromPreference()) }\n        }\n\n        val viewModel: DownloadDialogViewModel = getViewModel()\n        viewModel.postAction(Action.ShowSheet(listOf(sharedUrlCached)))\n\n        setContent {\n            SettingsProvider(calculateWindowSizeClass(this).widthSizeClass) {\n                SealTheme(\n                    darkTheme = LocalDarkTheme.current.isDarkTheme(),\n                    isHighContrastModeEnabled = LocalDarkTheme.current.isHighContrastModeEnabled,\n                ) {\n                    var preferences by remember {\n                        mutableStateOf(DownloadUtil.DownloadPreferences.createFromPreferences())\n                    }\n\n                    val sheetValue = viewModel.sheetValueFlow.collectAsStateWithLifecycle().value\n\n                    val state = viewModel.sheetStateFlow.collectAsStateWithLifecycle().value\n\n                    val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)\n\n                    val selectionState =\n                        viewModel.selectionStateFlow.collectAsStateWithLifecycle().value\n\n                    var showDialog by remember { mutableStateOf(false) }\n\n                    LaunchedEffect(sheetValue, selectionState) {\n                        if (sheetValue == DownloadDialogViewModel.SheetValue.Expanded) {\n                            showDialog = true\n                        } else if (sheetValue == DownloadDialogViewModel.SheetValue.Hidden) {\n                            launch { sheetState.hide() }\n                                .invokeOnCompletion {\n                                    showDialog = false\n                                    if (selectionState == SelectionState.Idle) {\n                                        this@QuickDownloadActivity.finish()\n                                    }\n                                }\n                        }\n                    }\n\n                    if (showDialog) {\n                        DownloadDialog(\n                            state = state,\n                            sheetState = sheetState,\n                            config = Config(),\n                            preferences = preferences,\n                            onPreferencesUpdate = { preferences = it },\n                            onActionPost = { viewModel.postAction(it) },\n                        )\n                    }\n\n                    when (selectionState) {\n                        is SelectionState.FormatSelection ->\n                            FormatPage(\n                                state = selectionState,\n                                onDismissRequest = {\n                                    viewModel.postAction(Action.Reset)\n                                    this.finish()\n                                },\n                            )\n\n                        SelectionState.Idle -> {}\n                        is SelectionState.PlaylistSelection -> {\n                            PlaylistSelectionPage(\n                                state = selectionState,\n                                onDismissRequest = {\n                                    viewModel.postAction(Action.Reset)\n                                    this.finish()\n                                },\n                            )\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/AppDatabase.kt",
    "content": "package com.junkfood.seal.database\n\nimport androidx.room.AutoMigration\nimport androidx.room.Database\nimport androidx.room.RoomDatabase\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.CookieProfile\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.database.objects.OptionShortcut\n\n@Database(\n    entities =\n        [\n            DownloadedVideoInfo::class,\n            CommandTemplate::class,\n            CookieProfile::class,\n            OptionShortcut::class,\n        ],\n    version = 5,\n    autoMigrations =\n        [\n            AutoMigration(from = 1, to = 2),\n            AutoMigration(from = 2, to = 3),\n            AutoMigration(from = 3, to = 4),\n            AutoMigration(from = 4, to = 5),\n        ],\n)\nabstract class AppDatabase : RoomDatabase() {\n    abstract fun videoInfoDao(): VideoInfoDao\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/VideoInfoDao.kt",
    "content": "package com.junkfood.seal.database\n\nimport androidx.room.Dao\nimport androidx.room.Delete\nimport androidx.room.Insert\nimport androidx.room.Query\nimport androidx.room.Transaction\nimport androidx.room.Update\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.CookieProfile\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.database.objects.OptionShortcut\nimport kotlinx.coroutines.flow.Flow\n\n@Dao\ninterface VideoInfoDao {\n\n    @Insert suspend fun insert(info: DownloadedVideoInfo)\n\n    @Insert suspend fun insertAll(infoList: List<DownloadedVideoInfo>)\n\n    @Query(\"select * from DownloadedVideoInfo\")\n    fun getDownloadHistoryFlow(): Flow<List<DownloadedVideoInfo>>\n\n    @Query(\"select * from DownloadedVideoInfo\")\n    suspend fun getDownloadHistory(): List<DownloadedVideoInfo>\n\n    @Query(\"select * from DownloadedVideoInfo where id=:id\")\n    suspend fun getInfoById(id: Int): DownloadedVideoInfo\n\n    @Query(\"DELETE FROM DownloadedVideoInfo WHERE id = :id\") suspend fun deleteInfoById(id: Int)\n\n    @Query(\"DELETE FROM DownloadedVideoInfo WHERE videoPath = :path\")\n    suspend fun deleteInfoByPath(path: String)\n\n    @Query(\"select * from DownloadedVideoInfo where videoPath = :path\")\n    suspend fun getInfoByPath(path: String): DownloadedVideoInfo?\n\n    @Transaction\n    suspend fun insertInfoDistinctByPath(\n        videoInfo: DownloadedVideoInfo,\n        path: String = videoInfo.videoPath,\n    ) {\n        if (getInfoByPath(path) == null) insert(videoInfo)\n    }\n\n    @Delete suspend fun deleteInfo(vararg info: DownloadedVideoInfo)\n\n    @Delete @Transaction suspend fun deleteInfoList(idList: List<DownloadedVideoInfo>)\n\n    @Query(\"SELECT * FROM CommandTemplate\") fun getTemplateFlow(): Flow<List<CommandTemplate>>\n\n    @Query(\"SELECT * FROM CommandTemplate\") suspend fun getTemplateList(): List<CommandTemplate>\n\n    @Query(\"select * from CookieProfile\") fun getCookieProfileFlow(): Flow<List<CookieProfile>>\n\n    @Insert suspend fun insertTemplate(template: CommandTemplate): Long\n\n    @Insert @Transaction suspend fun importTemplates(templateList: List<CommandTemplate>)\n\n    @Update suspend fun updateTemplate(template: CommandTemplate)\n\n    @Delete suspend fun deleteTemplate(template: CommandTemplate)\n\n    @Query(\"SELECT * FROM CommandTemplate where id = :id\")\n    suspend fun getTemplateById(id: Int): CommandTemplate\n\n    @Query(\"select * from CookieProfile where id=:id\")\n    suspend fun getCookieById(id: Int): CookieProfile?\n\n    @Update suspend fun updateCookieProfile(cookieProfile: CookieProfile)\n\n    @Delete suspend fun deleteCookieProfile(cookieProfile: CookieProfile)\n\n    @Insert suspend fun insertCookieProfile(cookieProfile: CookieProfile)\n\n    @Query(\"delete from CommandTemplate where id=:id\") suspend fun deleteTemplateById(id: Int)\n\n    @Delete suspend fun deleteTemplates(templates: List<CommandTemplate>)\n\n    @Query(\"select * from OptionShortcut\") fun getOptionShortcuts(): Flow<List<OptionShortcut>>\n\n    @Query(\"select * from OptionShortcut\") suspend fun getShortcutList(): List<OptionShortcut>\n\n    @Delete suspend fun deleteShortcut(optionShortcut: OptionShortcut)\n\n    @Insert suspend fun insertShortcut(optionShortcut: OptionShortcut): Long\n\n    @Transaction @Insert suspend fun insertAllShortcuts(shortcuts: List<OptionShortcut>)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/backup/Backup.kt",
    "content": "package com.junkfood.seal.database.backup\n\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.database.objects.OptionShortcut\nimport kotlinx.serialization.Serializable\n\n@Serializable\ndata class Backup(\n    val templates: List<CommandTemplate>? = null,\n    val shortcuts: List<OptionShortcut>? = null,\n    val downloadHistory: List<DownloadedVideoInfo>? = null,\n)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/backup/BackupUtil.kt",
    "content": "package com.junkfood.seal.database.backup\n\nimport android.content.Context\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.database.objects.OptionShortcut\nimport com.junkfood.seal.util.DatabaseUtil\nimport java.util.Date\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\n\nobject BackupUtil {\n    private val format = Json {\n        prettyPrint = true\n        ignoreUnknownKeys = true\n    }\n\n    suspend fun exportTemplatesToJson() =\n        exportTemplatesToJson(\n            templates = DatabaseUtil.getTemplateList(),\n            shortcuts = DatabaseUtil.getShortcutList(),\n        )\n\n    fun exportTemplatesToJson(\n        templates: List<CommandTemplate>,\n        shortcuts: List<OptionShortcut>,\n    ): String {\n        return format.encodeToString(Backup(templates = templates, shortcuts = shortcuts))\n    }\n\n    fun List<DownloadedVideoInfo>.toJsonString(): String {\n        return format.encodeToString(Backup(downloadHistory = this))\n    }\n\n    fun List<DownloadedVideoInfo>.toURLListString(): String {\n        return this.map { it.videoUrl }.joinToString(separator = \"\\n\") { it }\n    }\n\n    fun String.decodeToBackup(): Result<Backup> {\n        return format.runCatching { decodeFromString<Backup>(this@decodeToBackup) }\n    }\n\n    fun getDownloadHistoryExportFilename(context: Context): String {\n        return listOf(\n                context.getString(R.string.app_name),\n                App.packageInfo.versionName.toString(),\n                Date().toString(),\n            )\n            .joinToString(separator = \"-\") { it }\n    }\n\n    enum class BackupDestination {\n        File,\n        Clipboard,\n    }\n\n    enum class BackupType {\n        DownloadHistory,\n        URLList,\n        CommandTemplate,\n        CommandShortcut,\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/objects/CommandTemplate.kt",
    "content": "package com.junkfood.seal.database.objects\n\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport kotlinx.serialization.Serializable\n\n@Entity\n@Serializable\ndata class CommandTemplate(\n    @PrimaryKey(autoGenerate = true) val id: Int,\n    val name: String,\n    val template: String,\n)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/objects/CookieProfile.kt",
    "content": "package com.junkfood.seal.database.objects\n\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport kotlinx.serialization.Serializable\n\n@Entity\n@Serializable\ndata class CookieProfile(\n    @PrimaryKey(autoGenerate = true) val id: Int,\n    val url: String,\n    val content: String,\n)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/objects/DownloadedVideoInfo.kt",
    "content": "package com.junkfood.seal.database.objects\n\nimport androidx.room.ColumnInfo\nimport androidx.room.Entity\nimport androidx.room.Ignore\nimport androidx.room.PrimaryKey\nimport kotlinx.serialization.Serializable\n\n@Entity\n@Serializable\ndata class DownloadedVideoInfo(\n    @PrimaryKey(autoGenerate = true) val id: Int,\n    val videoTitle: String,\n    val videoAuthor: String,\n    val videoUrl: String,\n    val thumbnailUrl: String,\n    val videoPath: String,\n    @ColumnInfo(defaultValue = \"Unknown\") val extractor: String = \"Unknown\",\n) {\n    @Ignore\n    constructor() :\n        this(\n            id = 0,\n            videoTitle = \"Video\",\n            videoAuthor = \"Author\",\n            videoUrl = \"Url\",\n            thumbnailUrl = \"Thumbnail\",\n            videoPath = \"Path\",\n            extractor = \"Unknown\",\n        )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/database/objects/OptionShortcut.kt",
    "content": "package com.junkfood.seal.database.objects\n\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport kotlinx.serialization.Serializable\n\n@Entity\n@Serializable\ndata class OptionShortcut(@PrimaryKey(autoGenerate = true) val id: Long = 0, val option: String)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/download/DownloaderV2.kt",
    "content": "package com.junkfood.seal.download\n\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.util.Log\nimport androidx.compose.runtime.mutableStateMapOf\nimport androidx.compose.runtime.snapshotFlow\nimport androidx.compose.runtime.snapshots.SnapshotStateMap\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.Task.DownloadState\nimport com.junkfood.seal.download.Task.DownloadState.Canceled\nimport com.junkfood.seal.download.Task.DownloadState.Completed\nimport com.junkfood.seal.download.Task.DownloadState.Error\nimport com.junkfood.seal.download.Task.DownloadState.FetchingInfo\nimport com.junkfood.seal.download.Task.DownloadState.Idle\nimport com.junkfood.seal.download.Task.DownloadState.ReadyWithInfo\nimport com.junkfood.seal.download.Task.DownloadState.Running\nimport com.junkfood.seal.download.Task.RestartableAction.Download\nimport com.junkfood.seal.download.Task.RestartableAction.FetchInfo\nimport com.junkfood.seal.download.Task.TypeInfo\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.NotificationUtil\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.VideoInfo\nimport com.yausername.youtubedl_android.YoutubeDL\nimport kotlin.collections.component1\nimport kotlin.collections.component2\nimport kotlin.collections.set\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.FlowPreview\nimport kotlinx.coroutines.SupervisorJob\nimport kotlinx.coroutines.flow.distinctUntilChanged\nimport kotlinx.coroutines.flow.map\nimport kotlinx.coroutines.flow.onEach\nimport kotlinx.coroutines.launch\nimport org.koin.core.component.KoinComponent\n\nprivate const val TAG = \"DownloaderV2\"\n\nprivate const val MAX_CONCURRENCY = 3\n\ninterface DownloaderV2 {\n    fun getTaskStateMap(): SnapshotStateMap<Task, Task.State>\n\n    fun cancel(task: Task): Boolean\n\n    fun cancel(taskId: String): Boolean {\n        return getTaskStateMap().keys.find { it.id == taskId }?.let { cancel(it) } ?: false\n    }\n\n    fun restart(task: Task)\n\n    /** Enqueue a [Task] with an empty [Task.State] */\n    fun enqueue(task: Task)\n\n    fun enqueue(task: Task, state: Task.State)\n\n    fun enqueue(taskWithState: TaskFactory.TaskWithState) {\n        val (task, state) = taskWithState\n        enqueue(task, state)\n    }\n\n    fun remove(task: Task): Boolean\n}\n\ninternal object FakeDownloaderV2 : DownloaderV2 {\n    override fun getTaskStateMap(): SnapshotStateMap<Task, Task.State> {\n        return mutableStateMapOf()\n    }\n\n    override fun cancel(task: Task): Boolean {\n        return false\n    }\n\n    override fun restart(task: Task) {}\n\n    override fun enqueue(task: Task) {}\n\n    override fun enqueue(task: Task, state: Task.State) {}\n\n    override fun remove(task: Task): Boolean {\n        return true\n    }\n}\n\n/**\n * TODO:\n *     - Notification\n *     - Custom commands\n *     - States for ViewModels\n */\n@OptIn(FlowPreview::class)\nclass DownloaderV2Impl(private val appContext: Context) : DownloaderV2, KoinComponent {\n    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)\n    private val taskStateMap = mutableStateMapOf<Task, Task.State>()\n    private val snapshotFlow = snapshotFlow { taskStateMap.toMap() }\n\n    init {\n        scope.launch(Dispatchers.Default) {\n            snapshotFlow\n                .onEach { doYourWork() }\n                .map { it.countRunning() }\n                .distinctUntilChanged()\n                .collect { if (it > 0) App.startService() else App.stopService() }\n        }\n\n        scope.launch(Dispatchers.IO) {\n            // don't write before we read\n            enqueueFromBackup()\n\n            snapshotFlow\n                .map { it.filter { it.value.downloadState !is Completed } }\n                .distinctUntilChanged()\n                .collect {\n                    it.forEach { Log.d(TAG, it.value.viewState.title) }\n                    PreferenceUtil.encodeTaskListBackup(it)\n                }\n        }\n    }\n\n    private fun enqueueFromBackup() {\n        val taskList =\n            PreferenceUtil.decodeTaskListBackup()\n                .filter { it.value.downloadState !is Completed }\n                .mapValues { (_, state) ->\n                    val preState = state.downloadState\n                    val downloadState =\n                        when (preState) {\n                            is FetchingInfo,\n                            Idle -> {\n                                Canceled(action = FetchInfo)\n                            }\n                            is Running -> {\n                                Canceled(action = Download, progress = preState.progress)\n                            }\n\n                            ReadyWithInfo -> {\n                                Canceled(action = Download, progress = null)\n                            }\n                            else -> {\n                                preState\n                            }\n                        }\n                    state.copy(downloadState = downloadState)\n                }\n        taskList.forEach(::enqueue)\n    }\n\n    private fun Map<Task, Task.State>.countRunning(): Int = count { (_, state) ->\n        state.downloadState is Running || state.downloadState is FetchingInfo\n    }\n\n    override fun getTaskStateMap(): SnapshotStateMap<Task, Task.State> {\n        return taskStateMap\n    }\n\n    override fun enqueue(task: Task) {\n        taskStateMap +=\n            task to Task.State(Idle, null, Task.ViewState(url = task.url, title = task.url))\n    }\n\n    override fun enqueue(task: Task, state: Task.State) {\n        taskStateMap += task to state\n    }\n\n    /**\n     * Noted the caller is responsible for stopping the [task] before removing it\n     *\n     * @return true if the task was removed\n     */\n    override fun remove(task: Task): Boolean {\n        if (taskStateMap.contains(task)) {\n            taskStateMap.remove(task)\n            return true\n        }\n        return false\n    }\n\n    override fun cancel(task: Task): Boolean = task.cancelImpl()\n\n    override fun restart(task: Task) {\n        task.restartImpl()\n    }\n\n    private var Task.state: Task.State\n        get() = taskStateMap[this]!!\n        set(value) {\n            taskStateMap[this] = value\n        }\n\n    private var Task.downloadState: DownloadState\n        get() = state.downloadState\n        set(value) {\n            val prevState = state\n            taskStateMap[this] = prevState.copy(downloadState = value)\n        }\n\n    private var Task.info: VideoInfo?\n        get() = state.videoInfo\n        set(value) {\n            val prevState = state\n            taskStateMap[this] = prevState.copy(videoInfo = value)\n        }\n\n    private var Task.viewState: Task.ViewState\n        get() = state.viewState\n        set(value) {\n            val prevState = state\n            taskStateMap[this] = prevState.copy(viewState = value)\n        }\n\n    private val Task.notificationId: Int\n        get() = id.hashCode()\n\n    /** Processes pending tasks, prioritizing downloads. */\n    private fun doYourWork() {\n        if (taskStateMap.countRunning() >= MAX_CONCURRENCY) return\n\n        taskStateMap.entries\n            .sortedBy { (_, state) -> state.downloadState }\n            .firstOrNull { (_, state) ->\n                state.downloadState == ReadyWithInfo || state.downloadState == Idle\n            }\n            ?.let { (task, state) ->\n                when (state.downloadState) {\n                    Idle -> task.prepare()\n                    ReadyWithInfo -> task.download()\n                    else -> {\n                        throw IllegalStateException()\n                    }\n                }\n            }\n    }\n\n    private fun Task.prepare() {\n        check(downloadState == Idle)\n        if (type is TypeInfo.CustomCommand) {\n            execute()\n        } else {\n            fetchInfo()\n        }\n    }\n\n    private fun Task.fetchInfo() {\n        check(downloadState == Idle)\n        val task = this\n        val taskInfo = task.type\n        val playlistIndex = if (taskInfo is TypeInfo.Playlist) taskInfo.index else null\n        scope\n            .launch(Dispatchers.Default) {\n                DownloadUtil.fetchVideoInfoFromUrl(\n                        url = url,\n                        playlistIndex = playlistIndex,\n                        preferences = preferences,\n                        taskKey = id,\n                    )\n                    .onSuccess {\n                        info = it\n                        downloadState = ReadyWithInfo\n                        viewState = Task.ViewState.fromVideoInfo(it)\n                    }\n                    .onFailure { throwable ->\n                        if (throwable is YoutubeDL.CanceledException) {\n                            return@onFailure\n                        }\n                        task.downloadState = Error(throwable = throwable, action = FetchInfo)\n                        NotificationUtil.notifyError(\n                            title = viewState.title,\n                            textId = R.string.download_error_msg,\n                            notificationId = notificationId,\n                            report = throwable.stackTraceToString(),\n                        )\n                    }\n            }\n            .also { job -> downloadState = FetchingInfo(job = job, taskId = id) }\n    }\n\n    private fun Task.download() {\n        check(downloadState == ReadyWithInfo && info != null)\n        if (type is TypeInfo.CustomCommand) {\n            execute()\n            return\n        }\n        scope\n            .launch(Dispatchers.Default) {\n                DownloadUtil.downloadVideo(\n                        videoInfo = info,\n                        taskId = id,\n                        downloadPreferences = preferences,\n                        progressCallback = { progressPercentage, _, text ->\n                            val progress = progressPercentage / 100f\n                            when (val preState = downloadState) {\n                                is Running -> {\n                                    downloadState =\n                                        preState.copy(progress = progress, progressText = text)\n                                    NotificationUtil.notifyProgress(\n                                        notificationId = notificationId,\n                                        progress = progressPercentage.toInt(),\n                                        text = text,\n                                        title = viewState.title,\n                                        taskId = id,\n                                    )\n                                }\n                                else -> {}\n                            }\n                        },\n                    )\n                    .onSuccess { pathList ->\n                        downloadState = Completed(pathList.firstOrNull())\n\n                        val text =\n                            appContext.getString(\n                                if (pathList.isEmpty()) R.string.status_completed\n                                else R.string.download_finish_notification\n                            )\n                        FileUtil.createIntentForOpeningFile(pathList.firstOrNull()).run {\n                            NotificationUtil.finishNotification(\n                                notificationId,\n                                title = viewState.title,\n                                text = text,\n                                intent =\n                                    if (this != null)\n                                        PendingIntent.getActivity(\n                                            appContext,\n                                            0,\n                                            this,\n                                            PendingIntent.FLAG_IMMUTABLE,\n                                        )\n                                    else null,\n                            )\n                        }\n                    }\n                    .onFailure { throwable ->\n                        if (throwable is YoutubeDL.CanceledException) {\n                            return@onFailure\n                        }\n                        downloadState = Error(throwable = throwable, action = Download)\n                        NotificationUtil.notifyError(\n                            title = viewState.title,\n                            textId = R.string.fetch_info_error_msg,\n                            notificationId = notificationId,\n                            report = throwable.stackTraceToString(),\n                        )\n                    }\n            }\n            .also { job -> downloadState = Running(job = job, taskId = id) }\n    }\n\n    private fun Task.cancelImpl(): Boolean {\n        when (val preState = downloadState) {\n            is DownloadState.Cancelable -> {\n                val res = YoutubeDL.destroyProcessById(preState.taskId)\n                if (res) {\n                    preState.job.cancel()\n                    val progress = if (preState is Running) preState.progress else null\n                    NotificationUtil.cancelNotification(notificationId)\n                    downloadState =\n                        DownloadState.Canceled(action = preState.action, progress = progress)\n                }\n                return res\n            }\n            Idle -> {\n                downloadState = DownloadState.Canceled(action = FetchInfo)\n            }\n            ReadyWithInfo -> {\n                downloadState = DownloadState.Canceled(action = Download)\n            }\n\n            else -> {\n                return false\n            }\n        }\n        return true\n    }\n\n    private fun Task.restartImpl() {\n        when (val preState = downloadState) {\n            is DownloadState.Restartable -> {\n                downloadState =\n                    when (preState.action) {\n                        Download -> ReadyWithInfo\n                        FetchInfo -> Idle\n                    }\n            }\n            else -> {\n                throw IllegalStateException()\n            }\n        }\n    }\n\n    /**\n     * Execute a custom command task\n     *\n     * @see Task.TypeInfo.CustomCommand\n     */\n    private fun Task.execute() {\n        check(downloadState == Idle)\n        check(type is TypeInfo.CustomCommand)\n        val template = type.template\n        scope\n            .launch {\n                DownloadUtil.executeCustomCommandTask(url, id, template, preferences) {\n                        progressPercentage,\n                        _,\n                        text ->\n                        val progress = progressPercentage / 100f\n                        when (val preState = downloadState) {\n                            is Running -> {\n                                downloadState =\n                                    preState.copy(progress = progress, progressText = text)\n                                NotificationUtil.makeNotificationForCustomCommand(\n                                    notificationId = notificationId,\n                                    taskId = id,\n                                    progress = progressPercentage.toInt(),\n                                    templateName = template.name,\n                                    taskUrl = url,\n                                    text = text,\n                                )\n                            }\n                            else -> {}\n                        }\n                    }\n                    .onFailure { throwable ->\n                        if (throwable is YoutubeDL.CanceledException) {\n                            return@onFailure\n                        }\n                        downloadState = Error(throwable = throwable, action = Download)\n                        NotificationUtil.notifyError(\n                            title = viewState.title,\n                            textId = R.string.fetch_info_error_msg,\n                            notificationId = notificationId,\n                            report = throwable.stackTraceToString(),\n                        )\n                    }\n                    .onSuccess {\n                        downloadState = Completed(null)\n\n                        val text = appContext.getString(R.string.status_completed)\n\n                        NotificationUtil.finishNotification(\n                            notificationId = notificationId,\n                            title = viewState.title,\n                            text = text,\n                            intent = null,\n                        )\n                    }\n            }\n            .also { downloadState = Running(job = it, taskId = id) }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/download/Task.kt",
    "content": "package com.junkfood.seal.download\n\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.download.Task.TypeInfo\nimport com.junkfood.seal.download.Task.ViewState\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.Format\nimport com.junkfood.seal.util.VideoInfo\nimport com.junkfood.seal.util.toHttpsUrl\nimport kotlinx.coroutines.Job\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.Transient\nimport kotlin.math.roundToInt\n\nprivate val TypeInfo.id: String\n    get() =\n        when (this) {\n            is TypeInfo.CustomCommand -> \"${template.id}_${template.name}\"\n            is TypeInfo.Playlist -> \"$index\"\n            TypeInfo.URL -> \"\"\n        }\n\nprivate fun makeId(url: String, type: TypeInfo, preferences: DownloadUtil.DownloadPreferences): String =\n    \"${url}_${type.id}_${preferences.hashCode()}\"\n\n@Serializable\ndata class Task(\n    val url: String,\n    val type: TypeInfo = TypeInfo.URL,\n    val preferences: DownloadUtil.DownloadPreferences,\n    val id: String = makeId(url, type, preferences),\n) : Comparable<Task> {\n\n    val timeCreated: Long = System.currentTimeMillis()\n\n    override fun compareTo(other: Task): Int {\n        return timeCreated.compareTo(other.timeCreated)\n    }\n\n    @Serializable\n    sealed interface TypeInfo {\n\n        @Serializable data class Playlist(val index: Int = 0) : TypeInfo\n\n        @Serializable data class CustomCommand(val template: CommandTemplate) : TypeInfo\n\n        @Serializable data object URL : TypeInfo\n    }\n\n    @Serializable\n    data class State(\n        val downloadState: DownloadState,\n        val videoInfo: VideoInfo?,\n        val viewState: ViewState,\n    )\n\n    @Serializable\n    sealed interface DownloadState : Comparable<DownloadState> {\n\n        interface Cancelable {\n            val job: Job\n            val taskId: String\n            val action: RestartableAction\n        }\n\n        interface Restartable {\n            val action: RestartableAction\n        }\n\n        @Serializable data object Idle : DownloadState\n\n        @Serializable\n        data class FetchingInfo(\n            @Transient override val job: Job = Job(),\n            override val taskId: String,\n        ) : DownloadState, Cancelable {\n            override val action: RestartableAction = RestartableAction.FetchInfo\n        }\n\n        @Serializable data object ReadyWithInfo : DownloadState\n\n        @Serializable\n        data class Running(\n            @Transient override val job: Job = Job(),\n            override val taskId: String,\n            val progress: Float = PROGRESS_INDETERMINATE,\n            val progressText: String = \"\",\n        ) : DownloadState, Cancelable {\n            override val action: RestartableAction = RestartableAction.Download\n        }\n\n        @Serializable\n        data class Canceled(override val action: RestartableAction, val progress: Float? = null) :\n            DownloadState, Restartable\n\n        @Serializable\n        data class Error(\n            @Transient val throwable: Throwable = Throwable(),\n            override val action: RestartableAction,\n        ) : DownloadState, Restartable\n\n        @Serializable data class Completed(val filePath: String?) : DownloadState\n\n        override fun compareTo(other: DownloadState): Int {\n            return ordinal - other.ordinal\n        }\n\n        private val ordinal: Int\n            get() =\n                when (this) {\n                    is Canceled -> 4\n                    is Error -> 5\n                    is Completed -> 6\n                    Idle -> 3\n                    is FetchingInfo -> 2\n                    ReadyWithInfo -> 1\n                    is Running -> 0\n                }\n    }\n\n    @Serializable\n    sealed interface RestartableAction {\n        @Serializable data object FetchInfo : RestartableAction\n\n        @Serializable data object Download : RestartableAction\n    }\n\n    @Serializable\n    data class ViewState(\n        val url: String = \"https://www.example.com\",\n        val title: String = \"\",\n        val uploader: String = \"\",\n        val extractorKey: String = \"\",\n        val duration: Int = 0,\n        val fileSizeApprox: Double = .0,\n        val thumbnailUrl: String? = null,\n        val videoFormats: List<Format>? = null,\n        val audioOnlyFormats: List<Format>? = null,\n    ) {\n        companion object {\n            fun fromVideoInfo(info: VideoInfo): ViewState {\n                val formats =\n                    info.requestedFormats\n                        ?: info.requestedDownloads?.map { it.toFormat() }\n                        ?: emptyList()\n\n                val videoFormats = formats.filter { it.containsVideo() }\n                val audioOnlyFormats = formats.filter { it.isAudioOnly() }\n\n                return ViewState(\n                    url = info.originalUrl.toString(),\n                    title = info.title,\n                    uploader = info.uploader ?: info.channel ?: info.uploaderId.toString(),\n                    extractorKey = info.extractorKey,\n                    duration = info.duration?.roundToInt() ?: 0,\n                    thumbnailUrl = info.thumbnail.toHttpsUrl(),\n                    fileSizeApprox = info.fileSize ?: info.fileSizeApprox ?: .0,\n                    videoFormats = videoFormats,\n                    audioOnlyFormats = audioOnlyFormats,\n                )\n            }\n        }\n    }\n\n    companion object {\n        private const val PROGRESS_INDETERMINATE = -1f\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/download/TaskFactory.kt",
    "content": "package com.junkfood.seal.download\n\nimport androidx.annotation.CheckResult\nimport com.junkfood.seal.download.Task.DownloadState.Idle\nimport com.junkfood.seal.download.Task.DownloadState.ReadyWithInfo\nimport com.junkfood.seal.util.DownloadUtil.DownloadPreferences\nimport com.junkfood.seal.util.Format\nimport com.junkfood.seal.util.PlaylistResult\nimport com.junkfood.seal.util.VideoClip\nimport com.junkfood.seal.util.VideoInfo\nimport kotlin.math.roundToInt\n\nobject TaskFactory {\n    /**\n     * @return A [TaskWithState] with extra configurations made by user in the custom format\n     *   selection page\n     */\n    @CheckResult\n    fun createWithConfigurations(\n        videoInfo: VideoInfo,\n        formatList: List<Format>,\n        videoClips: List<VideoClip>,\n        splitByChapter: Boolean,\n        newTitle: String,\n        selectedSubtitles: List<String>,\n        selectedAutoCaptions: List<String>,\n    ): TaskWithState {\n        val fileSize =\n            formatList.fold(.0) { acc, format ->\n                acc + (format.fileSize ?: format.fileSizeApprox ?: .0)\n            }\n\n        val info =\n            videoInfo\n                .run { if (fileSize != .0) copy(fileSize = fileSize) else this }\n                .run { if (newTitle.isNotEmpty()) copy(title = newTitle) else this }\n\n        val audioOnlyFormats = formatList.filter { it.isAudioOnly() }\n        val videoFormats = formatList.filter { it.containsVideo() }\n        val audioOnly = audioOnlyFormats.isNotEmpty() && videoFormats.isEmpty()\n        val mergeAudioStream = audioOnlyFormats.size > 1\n        val formatId = formatList.joinToString(separator = \"+\") { it.formatId.toString() }\n\n        val subtitleLanguage =\n            (selectedSubtitles + selectedAutoCaptions).joinToString(separator = \",\")\n\n        val preferences =\n            DownloadPreferences.createFromPreferences()\n                .run {\n                    copy(\n                        formatIdString = formatId,\n                        videoClips = videoClips,\n                        splitByChapter = splitByChapter,\n                        newTitle = newTitle,\n                        mergeAudioStream = mergeAudioStream,\n                        extractAudio = extractAudio || audioOnly,\n                    )\n                }\n                .run {\n                    if (subtitleLanguage.isNotEmpty()) {\n                        copy(\n                            downloadSubtitle = true,\n                            autoSubtitle = selectedAutoCaptions.isNotEmpty(),\n                            subtitleLanguage = subtitleLanguage,\n                        )\n                    } else {\n                        this\n                    }\n                }\n\n        val task = Task(url = info.originalUrl.toString(), preferences = preferences)\n        val state =\n            Task.State(\n                downloadState = ReadyWithInfo,\n                videoInfo = info,\n                viewState =\n                    Task.ViewState.fromVideoInfo(info = info)\n                        .copy(videoFormats = videoFormats, audioOnlyFormats = audioOnlyFormats),\n            )\n\n        return TaskWithState(task, state)\n    }\n\n    /** @return List of [TaskWithState]s created from playlist items */\n    @CheckResult\n    fun createWithPlaylistResult(\n        playlistUrl: String,\n        indexList: List<Int>,\n        playlistResult: PlaylistResult,\n        preferences: DownloadPreferences,\n    ): List<TaskWithState> {\n        checkNotNull(playlistResult.entries)\n        val indexEntryMap = indexList.associateWith { index -> playlistResult.entries[index - 1] }\n\n        val taskList =\n            indexEntryMap.map { (index, entry) ->\n                val viewState =\n                    Task.ViewState(\n                        url = entry.url ?: \"\",\n                        title = entry.title ?: \"${playlistResult.title} - $index\",\n                        duration = entry.duration?.roundToInt() ?: 0,\n                        uploader = entry.uploader ?: entry.channel ?: playlistResult.channel ?: \"\",\n                        thumbnailUrl = (entry.thumbnails?.lastOrNull()?.url) ?: \"\",\n                    )\n                val task = Task(url = playlistUrl, preferences = preferences, type = Task.TypeInfo.Playlist(index))\n                val state =\n                    Task.State(downloadState = Idle, videoInfo = null, viewState = viewState)\n                TaskWithState(task, state)\n            }\n\n        return taskList\n    }\n\n    data class TaskWithState(val task: Task, val state: Task.State)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/AnimatedComposable.kt",
    "content": "package com.junkfood.seal.ui.common\n\nimport android.os.Build\nimport androidx.compose.animation.AnimatedVisibilityScope\nimport androidx.compose.animation.ExperimentalAnimationApi\nimport androidx.compose.animation.core.Spring\nimport androidx.compose.animation.core.VisibilityThreshold\nimport androidx.compose.animation.core.spring\nimport androidx.compose.animation.core.tween\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.scaleIn\nimport androidx.compose.animation.scaleOut\nimport androidx.compose.animation.slideInHorizontally\nimport androidx.compose.animation.slideInVertically\nimport androidx.compose.animation.slideOutHorizontally\nimport androidx.compose.animation.slideOutVertically\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.unit.IntOffset\nimport androidx.navigation.NamedNavArgument\nimport androidx.navigation.NavBackStackEntry\nimport androidx.navigation.NavDeepLink\nimport androidx.navigation.NavGraphBuilder\nimport androidx.navigation.compose.composable\nimport com.junkfood.seal.ui.common.motion.EmphasizeEasing\nimport com.junkfood.seal.ui.common.motion.EmphasizedAccelerate\nimport com.junkfood.seal.ui.common.motion.EmphasizedDecelerate\nimport com.junkfood.seal.ui.common.motion.materialSharedAxisXIn\nimport com.junkfood.seal.ui.common.motion.materialSharedAxisXOut\n\nconst val DURATION_ENTER = 400\nconst val DURATION_EXIT = 200\nconst val initialOffset = 0.10f\n\nprivate fun <T> enterTween() = tween<T>(durationMillis = DURATION_ENTER, easing = EmphasizeEasing)\n\nprivate fun <T> exitTween() = tween<T>(durationMillis = DURATION_ENTER, easing = EmphasizeEasing)\n\nprivate val fadeSpring =\n    spring<Float>(dampingRatio = Spring.DampingRatioNoBouncy, stiffness = Spring.StiffnessMedium)\nprivate val fadeTween = tween<Float>(durationMillis = DURATION_EXIT)\n\nprivate val fadeSpec = fadeTween\n\nfun NavGraphBuilder.animatedComposable(\n    route: String,\n    arguments: List<NamedNavArgument> = emptyList(),\n    deepLinks: List<NavDeepLink> = emptyList(),\n    usePredictiveBack: Boolean = Build.VERSION.SDK_INT >= 34,\n    content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,\n) {\n    if (usePredictiveBack) {\n        animatedComposablePredictiveBack(route, arguments, deepLinks, content)\n    } else {\n        animatedComposableLegacy(route, arguments, deepLinks, content)\n    }\n}\n\nfun NavGraphBuilder.animatedComposablePredictiveBack(\n    route: String,\n    arguments: List<NamedNavArgument> = emptyList(),\n    deepLinks: List<NavDeepLink> = emptyList(),\n    content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,\n) =\n    composable(\n        route = route,\n        arguments = arguments,\n        deepLinks = deepLinks,\n        enterTransition = { materialSharedAxisXIn(initialOffsetX = { (it * 0.15f).toInt() }) },\n        exitTransition = {\n            materialSharedAxisXOut(targetOffsetX = { -(it * initialOffset).toInt() })\n        },\n        popEnterTransition = {\n            scaleIn(\n                animationSpec = tween(durationMillis = 350, easing = EmphasizedDecelerate),\n                initialScale = 0.9f,\n            ) + materialSharedAxisXIn(initialOffsetX = { -(it * initialOffset).toInt() })\n        },\n        popExitTransition = {\n            materialSharedAxisXOut(targetOffsetX = { (it * initialOffset).toInt() }) +\n                scaleOut(\n                    targetScale = 0.9f,\n                    animationSpec = tween(durationMillis = 350, easing = EmphasizedAccelerate),\n                )\n        },\n        content = content,\n    )\n\nfun NavGraphBuilder.animatedComposableLegacy(\n    route: String,\n    arguments: List<NamedNavArgument> = emptyList(),\n    deepLinks: List<NavDeepLink> = emptyList(),\n    content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,\n) =\n    composable(\n        route = route,\n        arguments = arguments,\n        deepLinks = deepLinks,\n        enterTransition = {\n            materialSharedAxisXIn(initialOffsetX = { (it * initialOffset).toInt() })\n        },\n        exitTransition = {\n            materialSharedAxisXOut(targetOffsetX = { -(it * initialOffset).toInt() })\n        },\n        popEnterTransition = {\n            materialSharedAxisXIn(initialOffsetX = { -(it * initialOffset).toInt() })\n        },\n        popExitTransition = {\n            materialSharedAxisXOut(targetOffsetX = { (it * initialOffset).toInt() })\n        },\n        content = content,\n    )\n\nfun NavGraphBuilder.animatedComposableVariant(\n    route: String,\n    arguments: List<NamedNavArgument> = emptyList(),\n    deepLinks: List<NavDeepLink> = emptyList(),\n    content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,\n) =\n    composable(\n        route = route,\n        arguments = arguments,\n        deepLinks = deepLinks,\n        enterTransition = {\n            slideInHorizontally(enterTween(), initialOffsetX = { (it * initialOffset).toInt() }) +\n                fadeIn(fadeSpec)\n        },\n        exitTransition = { fadeOut(fadeSpec) },\n        popEnterTransition = { fadeIn(fadeSpec) },\n        popExitTransition = {\n            slideOutHorizontally(exitTween(), targetOffsetX = { (it * initialOffset).toInt() }) +\n                fadeOut(fadeSpec)\n        },\n        content = content,\n    )\n\nval springSpec =\n    spring(stiffness = Spring.StiffnessMedium, visibilityThreshold = IntOffset.VisibilityThreshold)\n\n@OptIn(ExperimentalAnimationApi::class)\nfun NavGraphBuilder.slideInVerticallyComposable(\n    route: String,\n    arguments: List<NamedNavArgument> = emptyList(),\n    deepLinks: List<NavDeepLink> = emptyList(),\n    content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,\n) =\n    composable(\n        route = route,\n        arguments = arguments,\n        deepLinks = deepLinks,\n        enterTransition = {\n            slideInVertically(initialOffsetY = { it }, animationSpec = enterTween()) + fadeIn()\n        },\n        exitTransition = { slideOutVertically() },\n        popEnterTransition = { slideInVertically() },\n        popExitTransition = {\n            slideOutVertically(targetOffsetY = { it }, animationSpec = enterTween()) + fadeOut()\n        },\n        content = content,\n    )\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/AsyncImageImpl.kt",
    "content": "package com.junkfood.seal.ui.common\n\nimport androidx.compose.foundation.Image\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.ColorFilter\nimport androidx.compose.ui.graphics.DefaultAlpha\nimport androidx.compose.ui.graphics.FilterQuality\nimport androidx.compose.ui.graphics.drawscope.DrawScope\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalInspectionMode\nimport androidx.compose.ui.res.painterResource\nimport coil.compose.AsyncImagePainter\nimport coil.imageLoader\nimport coil.request.ImageRequest\nimport com.junkfood.seal.R\n\n@Composable\nfun AsyncImageImpl(\n    model: Any?,\n    contentDescription: String?,\n    modifier: Modifier = Modifier,\n    transform: (AsyncImagePainter.State) -> AsyncImagePainter.State =\n        AsyncImagePainter.DefaultTransform,\n    onState: ((AsyncImagePainter.State) -> Unit)? = null,\n    alignment: Alignment = Alignment.Center,\n    contentScale: ContentScale = ContentScale.Fit,\n    alpha: Float = DefaultAlpha,\n    colorFilter: ColorFilter? = null,\n    filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,\n    isPreview: Boolean = LocalInspectionMode.current,\n) {\n    if (isPreview)\n        Image(\n            painter = painterResource(R.drawable.sample3),\n            contentDescription = contentDescription,\n            modifier = modifier,\n            alignment = alignment,\n            contentScale = contentScale,\n            alpha = alpha,\n            colorFilter = colorFilter,\n        )\n    else\n        coil.compose.AsyncImage(\n            model = ImageRequest.Builder(LocalContext.current).data(model).crossfade(true).build(),\n            contentDescription = contentDescription,\n            imageLoader = LocalContext.current.imageLoader,\n            modifier = modifier,\n            transform = transform,\n            onState = onState,\n            alignment = alignment,\n            contentScale = contentScale,\n            alpha = alpha,\n            colorFilter = colorFilter,\n            filterQuality = filterQuality,\n        )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/CompositionLocals.kt",
    "content": "package com.junkfood.seal.ui.common\n\nimport android.os.Build\nimport androidx.compose.material3.darkColorScheme\nimport androidx.compose.material3.dynamicDarkColorScheme\nimport androidx.compose.material3.lightColorScheme\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.collectAsState\nimport androidx.compose.runtime.compositionLocalOf\nimport androidx.compose.runtime.staticCompositionLocalOf\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.platform.LocalContext\nimport com.junkfood.seal.ui.theme.DEFAULT_SEED_COLOR\nimport com.junkfood.seal.ui.theme.FixedColorRoles\nimport com.junkfood.seal.util.DarkThemePreference\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.paletteStyles\nimport com.kyant.monet.LocalTonalPalettes\nimport com.kyant.monet.PaletteStyle\nimport com.kyant.monet.TonalPalettes.Companion.toTonalPalettes\n\nval LocalDarkTheme = compositionLocalOf { DarkThemePreference() }\nval LocalSeedColor = compositionLocalOf { DEFAULT_SEED_COLOR }\nval LocalWindowWidthState = staticCompositionLocalOf { WindowWidthSizeClass.Compact }\nval LocalDynamicColorSwitch = compositionLocalOf { false }\nval LocalPaletteStyleIndex = compositionLocalOf { 0 }\nval LocalFixedColorRoles = staticCompositionLocalOf {\n    FixedColorRoles.fromColorSchemes(\n        lightColors = lightColorScheme(),\n        darkColors = darkColorScheme(),\n    )\n}\n\n@Composable\nfun SettingsProvider(windowWidthSizeClass: WindowWidthSizeClass, content: @Composable () -> Unit) {\n    PreferenceUtil.AppSettingsStateFlow.collectAsState().value.run {\n        val tonalPalettes =\n            if (isDynamicColorEnabled && Build.VERSION.SDK_INT >= 31)\n                dynamicDarkColorScheme(LocalContext.current).toTonalPalettes()\n            else\n                Color(seedColor)\n                    .toTonalPalettes(\n                        paletteStyles.getOrElse(paletteStyleIndex) { PaletteStyle.TonalSpot }\n                    )\n\n        CompositionLocalProvider(\n            LocalDarkTheme provides darkTheme,\n            LocalSeedColor provides seedColor,\n            LocalPaletteStyleIndex provides paletteStyleIndex,\n            LocalTonalPalettes provides tonalPalettes,\n            LocalWindowWidthState provides windowWidthSizeClass,\n            LocalDynamicColorSwitch provides isDynamicColorEnabled,\n            content = content,\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/Ext.kt",
    "content": "package com.junkfood.seal.ui.common\n\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.junkfood.seal.util.PreferenceUtil.getString\n\ninline val String.booleanState\n    @Composable get() = remember { mutableStateOf(this.getBoolean()) }\n\ninline val String.stringState\n    @Composable get() = remember { mutableStateOf(this.getString()) }\n\ninline val String.intState\n    @Composable get() = remember { mutableIntStateOf(this.getInt()) }\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/HapticFeedback.kt",
    "content": "package com.junkfood.seal.ui.common\n\nimport android.view.HapticFeedbackConstants\nimport android.view.View\n\nobject HapticFeedback {\n    fun View.slightHapticFeedback() = this.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)\n\n    fun View.longPressHapticFeedback() =\n        this.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/Route.kt",
    "content": "package com.junkfood.seal.ui.common\n\nobject Route {\n\n    const val HOME = \"home\"\n    const val DOWNLOADS = \"download_history\"\n    const val PLAYLIST = \"playlist\"\n    const val SETTINGS = \"settings\"\n    const val FORMAT_SELECTION = \"format\"\n    const val TASK_LIST = \"task_list\"\n    const val TASK_LOG = \"task_log\"\n\n    const val SETTINGS_PAGE = \"settings_page\"\n\n    const val APPEARANCE = \"appearance\"\n    const val INTERACTION = \"interaction\"\n    const val GENERAL_DOWNLOAD_PREFERENCES = \"general_download_preferences\"\n    const val ABOUT = \"about\"\n    const val DOWNLOAD_DIRECTORY = \"download_directory\"\n    const val CREDITS = \"credits\"\n    const val LANGUAGES = \"languages\"\n    const val TEMPLATE = \"template\"\n    const val TEMPLATE_EDIT = \"template_edit\"\n    const val DARK_THEME = \"dark_theme\"\n    const val DOWNLOAD_QUEUE = \"queue\"\n    const val DOWNLOAD_FORMAT = \"download_format\"\n    const val NETWORK_PREFERENCES = \"network_preferences\"\n    const val COOKIE_PROFILE = \"cookie_profile\"\n    const val COOKIE_GENERATOR_WEBVIEW = \"cookie_webview\"\n    const val SUBTITLE_PREFERENCES = \"subtitle_preferences\"\n    const val AUTO_UPDATE = \"auto_update\"\n    const val DONATE = \"donate\"\n    const val TROUBLESHOOTING = \"troubleshooting\"\n\n    const val TASK_HASHCODE = \"task_hashcode\"\n    const val TEMPLATE_ID = \"template_id\"\n}\n\ninfix fun String.arg(arg: String) = \"$this/{$arg}\"\n\ninfix fun String.id(id: Int) = \"$this/$id\"\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/motion/AnimationSpecs.kt",
    "content": "package com.junkfood.seal.ui.common.motion\n\nimport android.view.animation.PathInterpolator\nimport androidx.compose.animation.core.CubicBezierEasing\nimport androidx.compose.animation.core.Easing\nimport androidx.compose.animation.core.PathEasing\nimport androidx.compose.animation.core.tween\nimport androidx.compose.ui.graphics.Path\nimport com.junkfood.seal.ui.common.DURATION_ENTER\n\nfun PathInterpolator.toEasing(): Easing {\n    return Easing { f -> this.getInterpolation(f) }\n}\n\nprivate val path =\n    Path().apply {\n        moveTo(0f, 0f)\n        cubicTo(0.05F, 0F, 0.133333F, 0.06F, 0.166666F, 0.4F)\n        cubicTo(0.208333F, 0.82F, 0.25F, 1F, 1F, 1F)\n    }\n\nval EmphasizeEasing = PathEasing(path)\nval EmphasizeEasingVariant = CubicBezierEasing(.2f, 0f, 0f, 1f)\nval EmphasizedDecelerate = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)\nval EmphasizedAccelerate = CubicBezierEasing(0.3f, 0f, 1f, 1f)\n\nprivate val standardDecelerate = CubicBezierEasing(.0f, .0f, 0f, 1f)\n\nprivate val motionEasingStandard = CubicBezierEasing(0.4F, 0.0F, 0.2F, 1F)\n\nprivate val tweenSpec = tween<Float>(durationMillis = DURATION_ENTER, easing = EmphasizeEasing)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/motion/MaterialSharedAxis.kt",
    "content": "package com.junkfood.seal.ui.common.motion\n\n/*\n * Copyright 2021 SOUP\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport androidx.compose.animation.ContentTransform\nimport androidx.compose.animation.EnterTransition\nimport androidx.compose.animation.ExitTransition\nimport androidx.compose.animation.core.FastOutLinearInEasing\nimport androidx.compose.animation.core.FastOutSlowInEasing\nimport androidx.compose.animation.core.LinearOutSlowInEasing\nimport androidx.compose.animation.core.tween\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.scaleIn\nimport androidx.compose.animation.scaleOut\nimport androidx.compose.animation.slideInHorizontally\nimport androidx.compose.animation.slideInVertically\nimport androidx.compose.animation.slideOutHorizontally\nimport androidx.compose.animation.slideOutVertically\nimport androidx.compose.animation.togetherWith\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.unit.Dp\n\n/**\n * Returns the provided [Dp] as an [Int] value by the [LocalDensity].\n *\n * @param slideDistance Value to the slide distance dimension, 30dp by default.\n */\n@Composable\npublic fun rememberSlideDistance(slideDistance: Dp = MotionConstants.DefaultSlideDistance): Int {\n    val density = LocalDensity.current\n    return remember(density, slideDistance) { with(density) { slideDistance.roundToPx() } }\n}\n\nprivate const val ProgressThreshold = 0.35f\n\nprivate val Int.ForOutgoing: Int\n    get() = (this * ProgressThreshold).toInt()\n\nprivate val Int.ForIncoming: Int\n    get() = this - this.ForOutgoing\n\n/** [materialSharedAxisX] allows to switch a layout with shared X-axis transition. */\npublic fun materialSharedAxisX(\n    initialOffsetX: (fullWidth: Int) -> Int,\n    targetOffsetX: (fullWidth: Int) -> Int,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): ContentTransform =\n    materialSharedAxisXIn(\n        initialOffsetX = initialOffsetX,\n        durationMillis = durationMillis,\n    ) togetherWith\n        materialSharedAxisXOut(targetOffsetX = targetOffsetX, durationMillis = durationMillis)\n\n/** [materialSharedAxisXIn] allows to switch a layout with shared X-axis enter transition. */\npublic fun materialSharedAxisXIn(\n    initialOffsetX: (fullWidth: Int) -> Int,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): EnterTransition =\n    slideInHorizontally(\n        animationSpec = tween(durationMillis = durationMillis, easing = FastOutSlowInEasing),\n        initialOffsetX = initialOffsetX,\n    ) +\n        fadeIn(\n            animationSpec =\n                tween(\n                    durationMillis = durationMillis.ForIncoming,\n                    delayMillis = durationMillis.ForOutgoing,\n                    easing = LinearOutSlowInEasing,\n                )\n        )\n\n/** [materialSharedAxisXOut] allows to switch a layout with shared X-axis exit transition. */\npublic fun materialSharedAxisXOut(\n    targetOffsetX: (fullWidth: Int) -> Int,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): ExitTransition =\n    slideOutHorizontally(\n        animationSpec = tween(durationMillis = durationMillis, easing = FastOutSlowInEasing),\n        targetOffsetX = targetOffsetX,\n    ) +\n        fadeOut(\n            animationSpec =\n                tween(\n                    durationMillis = durationMillis.ForOutgoing,\n                    delayMillis = 0,\n                    easing = FastOutLinearInEasing,\n                )\n        )\n\n/** [materialSharedAxisY] allows to switch a layout with shared Y-axis transition. */\npublic fun materialSharedAxisY(\n    initialOffsetY: (fullWidth: Int) -> Int,\n    targetOffsetY: (fullWidth: Int) -> Int,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): ContentTransform =\n    materialSharedAxisYIn(\n        initialOffsetY = initialOffsetY,\n        durationMillis = durationMillis,\n    ) togetherWith\n        materialSharedAxisYOut(targetOffsetY = targetOffsetY, durationMillis = durationMillis)\n\n/** [materialSharedAxisYIn] allows to switch a layout with shared Y-axis enter transition. */\npublic fun materialSharedAxisYIn(\n    initialOffsetY: (fullWidth: Int) -> Int,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): EnterTransition =\n    slideInVertically(\n        animationSpec = tween(durationMillis = durationMillis, easing = FastOutSlowInEasing),\n        initialOffsetY = initialOffsetY,\n    ) +\n        fadeIn(\n            animationSpec =\n                tween(\n                    durationMillis = durationMillis.ForIncoming,\n                    delayMillis = durationMillis.ForOutgoing,\n                    easing = LinearOutSlowInEasing,\n                )\n        )\n\n/** [materialSharedAxisYOut] allows to switch a layout with shared Y-axis exit transition. */\npublic fun materialSharedAxisYOut(\n    targetOffsetY: (fullWidth: Int) -> Int,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): ExitTransition =\n    slideOutVertically(\n        animationSpec = tween(durationMillis = durationMillis, easing = FastOutSlowInEasing),\n        targetOffsetY = targetOffsetY,\n    ) +\n        fadeOut(\n            animationSpec =\n                tween(\n                    durationMillis = durationMillis.ForOutgoing,\n                    delayMillis = 0,\n                    easing = FastOutLinearInEasing,\n                )\n        )\n\n/**\n * [materialSharedAxisZ] allows to switch a layout with shared Z-axis transition.\n *\n * @param forward whether the direction of the animation is forward.\n * @param durationMillis the duration of transition.\n */\npublic fun materialSharedAxisZ(\n    forward: Boolean,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): ContentTransform =\n    materialSharedAxisZIn(forward = forward, durationMillis = durationMillis) togetherWith\n        materialSharedAxisZOut(forward = forward, durationMillis = durationMillis)\n\n/**\n * [materialSharedAxisZIn] allows to switch a layout with shared Z-axis enter transition.\n *\n * @param forward whether the direction of the animation is forward.\n * @param durationMillis the duration of the enter transition.\n */\npublic fun materialSharedAxisZIn(\n    forward: Boolean,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): EnterTransition =\n    fadeIn(\n        animationSpec =\n            tween(\n                durationMillis = durationMillis.ForIncoming,\n                delayMillis = durationMillis.ForOutgoing,\n                easing = LinearOutSlowInEasing,\n            )\n    ) +\n        scaleIn(\n            animationSpec = tween(durationMillis = durationMillis, easing = FastOutSlowInEasing),\n            initialScale = if (forward) 0.8f else 1.1f,\n        )\n\n/**\n * [materialSharedAxisZOut] allows to switch a layout with shared Z-axis exit transition.\n *\n * @param forward whether the direction of the animation is forward.\n * @param durationMillis the duration of the exit transition.\n */\npublic fun materialSharedAxisZOut(\n    forward: Boolean,\n    durationMillis: Int = MotionConstants.DefaultMotionDuration,\n): ExitTransition =\n    fadeOut(\n        animationSpec =\n            tween(\n                durationMillis = durationMillis.ForOutgoing,\n                delayMillis = 0,\n                easing = FastOutLinearInEasing,\n            )\n    ) +\n        scaleOut(\n            animationSpec = tween(durationMillis = durationMillis, easing = FastOutSlowInEasing),\n            targetScale = if (forward) 1.1f else 0.8f,\n        )\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/common/motion/MotionConstants.kt",
    "content": "package com.junkfood.seal.ui.common.motion\n\n/*\n * Copyright 2021 SOUP\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport androidx.compose.ui.unit.Dp\nimport androidx.compose.ui.unit.dp\n\npublic object MotionConstants {\n    public const val DefaultMotionDuration: Int = 300\n    public const val DefaultFadeInDuration: Int = 150\n    public const val DefaultFadeOutDuration: Int = 75\n    public val DefaultSlideDistance: Dp = 30.dp\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/ActionSheetItems.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.LocalIndication\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.border\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.combinedClickable\nimport androidx.compose.foundation.indication\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ColumnScope\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.layout.widthIn\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.isSpecified\nimport androidx.compose.ui.graphics.takeOrElse\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.unit.dp\n\n@Composable\nfun ActionSheetPrimaryButton(\n    modifier: Modifier = Modifier,\n    containerColor: Color,\n    contentColor: Color,\n    outlineColor: Color = Color.Unspecified,\n    imageVector: ImageVector,\n    text: String,\n    onClick: () -> Unit,\n) {\n    val interactionSource = remember { MutableInteractionSource() }\n    Column(\n        horizontalAlignment = Alignment.CenterHorizontally,\n        modifier =\n            modifier\n                .widthIn(min = 88.dp)\n                .clip(MaterialTheme.shapes.large)\n                .clickable(\n                    onClick = onClick,\n                    indication = null,\n                    interactionSource = interactionSource,\n                )\n                .padding(8.dp),\n    ) {\n        Box(\n            modifier =\n                Modifier.width(80.dp)\n                    .height(64.dp)\n                    .clip(CircleShape)\n                    .then(\n                        if (outlineColor.isSpecified)\n                            Modifier.border(\n                                width = 1.dp,\n                                outlineColor.takeOrElse { Color.Transparent },\n                                shape = CircleShape,\n                            )\n                        else Modifier\n                    )\n                    .background(containerColor)\n                    .indication(interactionSource, indication = LocalIndication.current)\n        ) {\n            Icon(\n                imageVector,\n                null,\n                modifier = Modifier.size(24.dp).align(Alignment.Center),\n                tint = contentColor,\n            )\n        }\n        Spacer(Modifier.height(8.dp))\n        ProvideTextStyle(LocalTextStyle.current.merge(MaterialTheme.typography.labelMedium)) {\n            Text(text)\n        }\n    }\n}\n\n@Composable\nfun ActionSheetItem(\n    modifier: Modifier = Modifier,\n    leadingIcon: @Composable (() -> Unit)? = null,\n    text: @Composable (ColumnScope.() -> Unit),\n    trailingIcon: @Composable (() -> Unit)? = null,\n    onLongClickLabel: String? = null,\n    onLongClick: (() -> Unit)? = null,\n    onClickLabel: String? = null,\n    onClick: (() -> Unit)? = null,\n) {\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .then(\n                    if (onClick == null) {\n                        Modifier\n                    } else if (onLongClick == null) {\n                        Modifier.clickable(onClickLabel = onClickLabel, onClick = onClick)\n                    } else {\n                        Modifier.combinedClickable(\n                            onClick = onClick,\n                            onLongClick = onLongClick,\n                            onClickLabel = onClickLabel,\n                            onLongClickLabel = onLongClickLabel,\n                        )\n                    }\n                )\n                .padding(vertical = 16.dp, horizontal = 20.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        leadingIcon?.invoke()\n        if (leadingIcon != null) Spacer(Modifier.width(20.dp))\n        ProvideTextStyle(LocalTextStyle.current.merge(MaterialTheme.typography.titleSmall)) {\n            Column(\n                modifier = Modifier.weight(1f),\n                verticalArrangement = Arrangement.spacedBy(4.dp),\n            ) {\n                text.invoke(this)\n            }\n        }\n        trailingIcon?.invoke()\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/Buttons.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.BorderStroke\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.combinedClickable\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.RowScope\nimport androidx.compose.foundation.layout.defaultMinSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.OpenInNew\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.ButtonColors\nimport androidx.compose.material3.ButtonDefaults\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilledTonalButton\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LocalContentColor\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.Shape\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.page.settings.general.ytdlpReference\n\n@Composable\nfun OutlinedButtonWithIcon(\n    modifier: Modifier = Modifier,\n    onClick: () -> Unit,\n    icon: ImageVector,\n    text: String,\n    contentColor: Color = MaterialTheme.colorScheme.primary,\n) {\n    OutlinedButton(\n        modifier = modifier,\n        onClick = onClick,\n        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n        colors = ButtonDefaults.outlinedButtonColors(contentColor = contentColor),\n    ) {\n        Icon(\n            modifier = Modifier.size(ButtonDefaults.IconSize),\n            imageVector = icon,\n            contentDescription = null,\n        )\n        Text(modifier = Modifier.padding(start = 8.dp), text = text)\n    }\n}\n\n@Composable\nfun TextButtonWithIcon(\n    modifier: Modifier = Modifier,\n    icon: ImageVector,\n    text: String,\n    contentColor: Color = MaterialTheme.colorScheme.primary,\n    onClick: () -> Unit,\n) {\n    TextButton(\n        modifier = modifier,\n        onClick = onClick,\n        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n        colors = ButtonDefaults.textButtonColors(contentColor = contentColor),\n    ) {\n        Row(verticalAlignment = Alignment.CenterVertically) {\n            Icon(modifier = Modifier.size(18.dp), imageVector = icon, contentDescription = null)\n            Text(modifier = Modifier.padding(start = 8.dp), text = text)\n        }\n    }\n}\n\n@Composable\nfun FilledTonalButtonWithIcon(\n    modifier: Modifier = Modifier,\n    onClick: () -> Unit,\n    icon: ImageVector,\n    text: String,\n    colors: ButtonColors = ButtonDefaults.filledTonalButtonColors(),\n) {\n    FilledTonalButton(\n        modifier = modifier,\n        onClick = onClick,\n        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n        colors = colors,\n    ) {\n        Icon(modifier = Modifier.size(18.dp), imageVector = icon, contentDescription = null)\n        Text(modifier = Modifier.padding(start = 8.dp), text = text)\n    }\n}\n\n@Composable\nfun FilledButtonWithIcon(\n    modifier: Modifier = Modifier,\n    icon: ImageVector,\n    text: String,\n    enabled: Boolean = true,\n    onClick: () -> Unit,\n) {\n    Button(\n        modifier = modifier,\n        onClick = onClick,\n        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n        enabled = enabled,\n    ) {\n        Icon(modifier = Modifier.size(18.dp), imageVector = icon, contentDescription = null)\n        Text(modifier = Modifier.padding(start = 6.dp), text = text)\n    }\n}\n\n@Composable\nfun ConfirmButton(\n    text: String = stringResource(R.string.confirm),\n    enabled: Boolean = true,\n    onClick: () -> Unit,\n) {\n    TextButton(onClick = onClick, enabled = enabled) { Text(text) }\n}\n\n@Composable\nfun DismissButton(text: String = stringResource(R.string.dismiss), onClick: () -> Unit) {\n    TextButton(onClick = onClick) { Text(text) }\n}\n\n@Composable\nfun OutlinedDismissButton(text: String = stringResource(R.string.dismiss), onClick: () -> Unit) {\n    OutlinedButton(onClick = onClick) { Text(text) }\n}\n\n@Composable\nfun FilledConfirmButton(\n    text: String = stringResource(R.string.confirm),\n    enabled: Boolean = true,\n    onClick: () -> Unit,\n) {\n    Button(onClick = onClick, enabled = enabled) { Text(text) }\n}\n\n@Composable\nfun LinkButton(\n    modifier: Modifier = Modifier,\n    text: String = stringResource(R.string.yt_dlp_docs),\n    icon: ImageVector = Icons.Outlined.OpenInNew,\n    link: String = ytdlpReference,\n) {\n    val uriHandler = LocalUriHandler.current\n    TextButtonWithIcon(\n        modifier = modifier,\n        onClick = { uriHandler.openUri(link) },\n        icon = icon,\n        text = text,\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)\n@Composable\nfun LongTapTextButton(\n    onClick: () -> Unit,\n    onClickLabel: String,\n    onLongClick: () -> Unit,\n    onLongClickLabel: String,\n    modifier: Modifier = Modifier,\n    shape: Shape = ButtonDefaults.shape,\n    border: BorderStroke? = null,\n    contentPadding: PaddingValues = ButtonDefaults.ButtonWithIconContentPadding,\n    content: @Composable RowScope.() -> Unit,\n) {\n    val contentColor = MaterialTheme.colorScheme.primary\n    Row(\n        modifier =\n            modifier\n                .clip(shape)\n                .combinedClickable(\n                    onClick = onClick,\n                    onClickLabel = onClickLabel,\n                    onLongClick = onLongClick,\n                    onLongClickLabel = onLongClickLabel,\n                )\n    ) {\n        CompositionLocalProvider(LocalContentColor provides contentColor) {\n            ProvideTextStyle(value = MaterialTheme.typography.labelLarge) {\n                Row(\n                    Modifier.defaultMinSize(\n                            minWidth = ButtonDefaults.MinWidth,\n                            minHeight = ButtonDefaults.MinHeight,\n                        )\n                        .padding(contentPadding),\n                    horizontalArrangement = Arrangement.Center,\n                    verticalAlignment = Alignment.CenterVertically,\n                    content = content,\n                )\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/Chips.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.foundation.BorderStroke\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Check\nimport androidx.compose.material.icons.outlined.Clear\nimport androidx.compose.material3.AssistChip\nimport androidx.compose.material3.AssistChipDefaults\nimport androidx.compose.material3.ElevatedAssistChip\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilterChip\nimport androidx.compose.material3.FilterChipDefaults\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.InputChipDefaults\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.SelectableChipColors\nimport androidx.compose.material3.SelectableChipElevation\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.Shape\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.theme.FixedAccentColors\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun ButtonChip(\n    modifier: Modifier = Modifier,\n    label: String,\n    enabled: Boolean = true,\n    icon: ImageVector? = null,\n    iconColor: Color = MaterialTheme.colorScheme.primary,\n    iconDescription: String? = null,\n    onClick: () -> Unit,\n) {\n    ElevatedAssistChip(\n        modifier = modifier.padding(horizontal = 4.dp),\n        onClick = onClick,\n        label = { Text(label) },\n        colors = AssistChipDefaults.elevatedAssistChipColors(leadingIconContentColor = iconColor),\n        enabled = enabled,\n        leadingIcon = {\n            if (icon != null)\n                Icon(\n                    imageVector = icon,\n                    contentDescription = iconDescription,\n                    modifier = Modifier.size(AssistChipDefaults.IconSize),\n                )\n        },\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun FlatButtonChip(\n    modifier: Modifier = Modifier,\n    icon: ImageVector,\n    label: String,\n    iconColor: Color = MaterialTheme.colorScheme.primary,\n    labelColor: Color = MaterialTheme.colorScheme.onSurface,\n    onClick: () -> Unit,\n) {\n    AssistChip(\n        modifier = modifier.padding(horizontal = 4.dp),\n        colors =\n            AssistChipDefaults.assistChipColors(\n                containerColor = MaterialTheme.colorScheme.surfaceContainerLowest,\n                labelColor = labelColor,\n                leadingIconContentColor = iconColor,\n            ),\n        border = null,\n        onClick = onClick,\n        leadingIcon = {\n            Icon(\n                imageVector = icon,\n                contentDescription = null,\n                Modifier.size(AssistChipDefaults.IconSize),\n            )\n        },\n        label = { Text(text = label) },\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun OutlinedButtonChip(\n    modifier: Modifier = Modifier,\n    icon: ImageVector? = null,\n    label: String,\n    shape: Shape = AssistChipDefaults.shape,\n    onClick: () -> Unit,\n) {\n    AssistChip(\n        modifier = modifier,\n        onClick = onClick,\n        leadingIcon = {\n            icon?.let {\n                Icon(\n                    imageVector = it,\n                    contentDescription = null,\n                    Modifier.size(AssistChipDefaults.IconSize),\n                )\n            }\n        },\n        label = { Text(text = label) },\n        shape = shape,\n    )\n}\n\n@Composable\nfun SingleChoiceChip(\n    modifier: Modifier = Modifier,\n    selected: Boolean,\n    enabled: Boolean = true,\n    label: String,\n    leadingIcon: ImageVector = Icons.Outlined.Check,\n    onClick: () -> Unit,\n) {\n    FilterChip(\n        modifier = modifier.padding(horizontal = 4.dp),\n        selected = selected,\n        onClick = onClick,\n        enabled = enabled,\n        shape = MaterialTheme.shapes.large,\n        label = { Text(text = label) },\n        leadingIcon = {\n            Row {\n                AnimatedVisibility(visible = selected) {\n                    Icon(\n                        imageVector = leadingIcon,\n                        contentDescription = null,\n                        modifier = Modifier.size(FilterChipDefaults.IconSize),\n                    )\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun VideoFilterChip(\n    modifier: Modifier = Modifier,\n    selected: Boolean,\n    enabled: Boolean = true,\n    onClick: () -> Unit,\n    label: String,\n    leadingIcon: ImageVector? = null,\n) {\n    FilterChip(\n        modifier = modifier.padding(horizontal = 4.dp),\n        selected = selected,\n        enabled = enabled,\n        onClick = onClick,\n        label = { Text(text = label) },\n        leadingIcon = { leadingIcon?.let { Icon(imageVector = it, contentDescription = null) } },\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun ShortcutChip(\n    modifier: Modifier = Modifier,\n    text: String,\n    onClick: (() -> Unit)? = null,\n    onRemove: (() -> Unit)? = null,\n) {\n    AssistChip(\n        modifier = modifier.padding(horizontal = 4.dp),\n        onClick = { onClick?.invoke() },\n        label = { Text(text = text, maxLines = 1, overflow = TextOverflow.Ellipsis) },\n        trailingIcon = {\n            onRemove?.let {\n                IconButton(\n                    onClick = onRemove,\n                    modifier = Modifier.size(InputChipDefaults.IconSize),\n                ) {\n                    Icon(\n                        imageVector = Icons.Outlined.Clear,\n                        contentDescription = stringResource(id = R.string.remove),\n                        tint = MaterialTheme.colorScheme.onSurfaceVariant,\n                        modifier = Modifier.size(InputChipDefaults.IconSize),\n                    )\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun SingleSelectChip(\n    selected: Boolean,\n    onClick: () -> Unit,\n    label: @Composable () -> Unit,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    trailingIcon: @Composable (() -> Unit)? = null,\n    colors: SelectableChipColors =\n        FilterChipDefaults.filterChipColors(\n            selectedContainerColor = FixedAccentColors.secondaryFixed,\n            selectedLabelColor = FixedAccentColors.onSecondaryFixed,\n            selectedLeadingIconColor = FixedAccentColors.onSecondaryFixed,\n            selectedTrailingIconColor = FixedAccentColors.onSecondaryFixed,\n            containerColor = MaterialTheme.colorScheme.surfaceContainer,\n            iconColor = MaterialTheme.colorScheme.onSurface,\n            labelColor = MaterialTheme.colorScheme.onSurface,\n        ),\n    border: BorderStroke? = null,\n    elevation: SelectableChipElevation? = FilterChipDefaults.filterChipElevation(),\n    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n) {\n    FilterChip(\n        selected = selected,\n        onClick = onClick,\n        label = label,\n        modifier = modifier,\n        enabled = enabled,\n        leadingIcon = {},\n        trailingIcon = trailingIcon,\n        shape = MaterialTheme.shapes.extraLarge,\n        colors = colors,\n        elevation = elevation,\n        border = border,\n        interactionSource = interactionSource,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/CommonComponents.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.WindowInsets\nimport androidx.compose.foundation.layout.asPaddingValues\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.navigationBars\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.unit.dp\n\n@Composable\nfun NavigationBarSpacer(modifier: Modifier = Modifier) {\n    Spacer(\n        modifier =\n            modifier.height(\n                with(WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()) {\n                    if (this.value > 30f) this else 0f.dp\n                }\n            )\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/DialogItems.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.LocalIndication\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.foundation.selection.toggleable\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Settings\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Switch\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.VerticalDivider\nimport androidx.compose.material3.minimumInteractiveComponentSize\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.Density\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.R\n\n@Composable\nfun DialogSingleChoiceItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    selected: Boolean,\n    onClick: () -> Unit,\n) {\n    val interactionSource = remember { MutableInteractionSource() }\n    Row(\n        modifier =\n            modifier\n                .selectable(\n                    selected = selected,\n                    enabled = true,\n                    onClick = onClick,\n                    indication = LocalIndication.current,\n                    interactionSource = interactionSource,\n                )\n                .fillMaxWidth()\n                .padding(horizontal = 8.dp),\n        verticalAlignment = Alignment.CenterVertically,\n        horizontalArrangement = Arrangement.Start,\n    ) {\n        RadioButton(\n            modifier = Modifier.minimumInteractiveComponentSize().clearAndSetSemantics {},\n            selected = selected,\n            onClick = null,\n            interactionSource = interactionSource,\n        )\n        Text(\n            text = text,\n            style = LocalTextStyle.current.copy(fontSize = 16.sp),\n            modifier = Modifier.padding(vertical = 8.dp),\n        )\n    }\n}\n\n@Preview\n@Composable\nfun SingleChoiceItemPreview() {\n    Surface {\n        Column(modifier = Modifier.width(400.dp)) {\n            DialogSingleChoiceItemVariant(\n                title = \"Better compatibility\",\n                desc = stringResource(R.string.prefer_compatibility_desc),\n                selected = false,\n            ) {}\n            DialogSingleChoiceItemVariant(\n                title = \"Better quality\",\n                desc = stringResource(R.string.prefer_quality_desc),\n                selected = true,\n            ) {}\n            DialogSingleChoiceItemVariant(\n                title = \"Better quality\",\n                desc = stringResource(R.string.prefer_quality_desc),\n                selected = true,\n                action = {\n                    Spacer(modifier = Modifier.width(8.dp))\n                    VerticalDivider(modifier = Modifier.height(32.dp))\n                    IconButton(onClick = {}) { Icon(Icons.Outlined.Settings, null) }\n                },\n            ) {}\n            DialogSingleChoiceItem(text = \"Preview\", selected = true) {}\n        }\n    }\n}\n\n@Composable\nfun DialogSingleChoiceItemVariant(\n    modifier: Modifier = Modifier,\n    title: String,\n    desc: String?,\n    selected: Boolean,\n    action: (@Composable () -> Unit)? = null,\n    onClick: () -> Unit,\n) {\n    Row(\n        modifier =\n            modifier\n                .selectable(selected = selected, enabled = true, onClick = onClick)\n                .fillMaxWidth(),\n        verticalAlignment = Alignment.CenterVertically,\n        horizontalArrangement = Arrangement.Start,\n    ) {\n        Spacer(modifier = Modifier.width(8.dp))\n        Column(modifier = Modifier.weight(1f).padding(vertical = 12.dp)) {\n            Row(verticalAlignment = Alignment.CenterVertically) {\n                RadioButton(\n                    modifier = Modifier.padding(start = 12.dp, end = 12.dp).clearAndSetSemantics {},\n                    selected = selected,\n                    onClick = null,\n                )\n                Text(text = title, style = MaterialTheme.typography.titleMedium)\n            }\n            desc?.let {\n                Text(\n                    text = it,\n                    style = MaterialTheme.typography.bodySmall,\n                    modifier = Modifier.padding(top = 4.dp, start = 48.dp),\n                )\n            }\n        }\n        action?.invoke() ?: Spacer(modifier = Modifier.width(16.dp))\n    }\n}\n\n@Composable\nfun CheckBoxItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    checked: Boolean,\n    onValueChange: (Boolean) -> Unit,\n) {\n    Row(\n        modifier =\n            Modifier.padding(top = 12.dp)\n                .fillMaxWidth()\n                .toggleable(value = checked, enabled = true, onValueChange = onValueChange)\n    ) {\n        Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {\n            Checkbox(\n                modifier = Modifier.clearAndSetSemantics {},\n                checked = checked,\n                onCheckedChange = onValueChange,\n            )\n            Text(modifier = Modifier, text = text, style = MaterialTheme.typography.bodyMedium)\n        }\n    }\n}\n\n@Composable\nfun DialogSwitchItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    value: Boolean,\n    onValueChange: (Boolean) -> Unit,\n) {\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .toggleable(value = value, onValueChange = onValueChange)\n                .padding(horizontal = 24.dp, vertical = 8.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        Text(\n            text = text,\n            style = MaterialTheme.typography.labelLarge,\n            modifier = Modifier.weight(1f),\n        )\n        val thumbContent: (@Composable () -> Unit)? = rememberThumbContent(isChecked = value)\n\n        val density = LocalDensity.current\n        CompositionLocalProvider(\n            LocalDensity provides Density(density.density * 0.8f, density.fontScale)\n        ) {\n            Switch(\n                checked = value,\n                onCheckedChange = onValueChange,\n                modifier = Modifier.clearAndSetSemantics {},\n                thumbContent = thumbContent,\n            )\n        }\n    }\n}\n\n@Preview\n@Composable\nprivate fun SwitchItemPrev() {\n    var value by remember { mutableStateOf(false) }\n    Surface { DialogSwitchItem(text = \"Use cookies\", value = value) { value = it } }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/Dialogs.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport android.content.res.Configuration\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ExperimentalLayoutApi\nimport androidx.compose.foundation.layout.FlowRow\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.shape.RoundedCornerShape\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.HelpOutline\nimport androidx.compose.material.icons.outlined.SignalCellularConnectedNoInternet4Bar\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.AlertDialogDefaults\nimport androidx.compose.material3.BasicAlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LocalContentColor\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.Shape\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.Dp\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.window.DialogProperties\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.theme.FixedAccentColors\nimport com.junkfood.seal.ui.theme.SealTheme\n\nprivate val DialogVerticalPadding = PaddingValues(vertical = 24.dp)\nprivate val IconPadding = PaddingValues(bottom = 16.dp)\nprivate val DialogHorizontalPadding = PaddingValues(horizontal = 24.dp)\nprivate val TitlePadding = PaddingValues(bottom = 16.dp)\nprivate val TextPadding = PaddingValues(bottom = 24.dp)\nprivate val ButtonsMainAxisSpacing = 8.dp\nprivate val ButtonsCrossAxisSpacing = 12.dp\n\n@Composable\nfun HelpDialog(\n    text: String,\n    onDismissRequest: () -> Unit = {},\n    dismissButton: @Composable (() -> Unit)? = null,\n    confirmButton: @Composable () -> Unit = {\n        ConfirmButton(text = stringResource(id = R.string.got_it)) { onDismissRequest() }\n    },\n) {\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(text = stringResource(id = R.string.how_does_it_work)) },\n        icon = { Icon(Icons.Outlined.HelpOutline, null) },\n        text = { Text(text = text) },\n        confirmButton = confirmButton,\n        dismissButton = dismissButton,\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)\n@Composable\nfun SealDialog(\n    modifier: Modifier = Modifier,\n    onDismissRequest: () -> Unit,\n    confirmButton: @Composable (() -> Unit)?,\n    dismissButton: @Composable (() -> Unit)? = null,\n    icon: @Composable (() -> Unit)? = null,\n    title: @Composable (() -> Unit)? = null,\n    text: @Composable (() -> Unit)? = null,\n    shape: Shape = AlertDialogDefaults.shape,\n    containerColor: Color = AlertDialogDefaults.containerColor,\n    iconContentColor: Color = AlertDialogDefaults.iconContentColor,\n    titleContentColor: Color = AlertDialogDefaults.titleContentColor,\n    textContentColor: Color = AlertDialogDefaults.textContentColor,\n    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,\n    properties: DialogProperties = DialogProperties(),\n) {\n    BasicAlertDialog(\n        onDismissRequest = onDismissRequest,\n        modifier = modifier,\n        properties = properties,\n    ) {\n        Surface(\n            modifier = modifier,\n            shape = shape,\n            color = containerColor,\n            tonalElevation = tonalElevation,\n        ) {\n            Column(modifier = Modifier.padding(DialogVerticalPadding)) {\n                icon?.let {\n                    CompositionLocalProvider(LocalContentColor provides iconContentColor) {\n                        Box(\n                            Modifier.padding(IconPadding)\n                                .padding(DialogHorizontalPadding)\n                                .align(Alignment.CenterHorizontally)\n                        ) {\n                            icon()\n                        }\n                    }\n                }\n                title?.let {\n                    CompositionLocalProvider(LocalContentColor provides titleContentColor) {\n                        val textStyle =\n                            MaterialTheme.typography.headlineSmall.copy(\n                                textAlign = TextAlign.Center\n                            )\n                        ProvideTextStyle(textStyle) {\n                            Box(\n                                // Align the title to the center when an icon is present.\n                                Modifier.padding(TitlePadding)\n                                    .padding(DialogHorizontalPadding)\n                                    .align(\n                                        if (icon == null) {\n                                            Alignment.Start\n                                        } else {\n                                            Alignment.CenterHorizontally\n                                        }\n                                    )\n                            ) {\n                                title()\n                            }\n                        }\n                    }\n                }\n                text?.let {\n                    CompositionLocalProvider(LocalContentColor provides textContentColor) {\n                        val textStyle = MaterialTheme.typography.bodyMedium\n                        ProvideTextStyle(textStyle) {\n                            Box(\n                                Modifier.weight(weight = 1f, fill = false)\n                                    .padding(TextPadding)\n                                    .align(Alignment.Start)\n                            ) {\n                                text()\n                            }\n                        }\n                    }\n                }\n                Box(modifier = Modifier.align(Alignment.End).padding(DialogHorizontalPadding)) {\n                    val textStyle = MaterialTheme.typography.labelLarge\n                    ProvideTextStyle(value = textStyle) {\n                        FlowRow(\n                            horizontalArrangement = Arrangement.spacedBy(ButtonsMainAxisSpacing),\n                            verticalArrangement = Arrangement.spacedBy(ButtonsCrossAxisSpacing),\n                        ) {\n                            dismissButton?.invoke()\n                            confirmButton?.invoke()\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun SealDialogButtonVariant(\n    modifier: Modifier = Modifier,\n    shape: Shape = MiddleButtonShape,\n    text: String,\n    onClick: () -> Unit,\n) {\n    Box() {\n        Surface(\n            modifier = modifier.clickable(onClick = onClick).fillMaxWidth().height(48.dp),\n            color = FixedAccentColors.secondaryFixed,\n            shape = shape,\n        ) {}\n        Text(\n            text = text,\n            style = MaterialTheme.typography.labelLarge,\n            color = FixedAccentColors.onSecondaryFixed,\n            modifier = Modifier.align(Alignment.Center),\n        )\n    }\n}\n\n@Preview(name = \"dark\", uiMode = Configuration.UI_MODE_NIGHT_YES)\n@Preview(name = \"light\", uiMode = Configuration.UI_MODE_NIGHT_NO)\n@Composable\nprivate fun ButtonVariantPreview() {\n    SealTheme {\n        SealDialogVariant(\n            onDismissRequest = {},\n            modifier = Modifier,\n            icon = {\n                Icon(\n                    imageVector = Icons.Outlined.SignalCellularConnectedNoInternet4Bar,\n                    contentDescription = null,\n                )\n            },\n            title = {\n                Text(\n                    text = \"Download with cellular network?\",\n                    style = MaterialTheme.typography.titleLarge,\n                    textAlign = TextAlign.Center,\n                )\n            },\n            buttons = {\n                SealDialogButtonVariant(\n                    text = stringResource(R.string.allow_always),\n                    shape = TopButtonShape,\n                ) {}\n                SealDialogButtonVariant(\n                    text = stringResource(id = R.string.allow_once),\n                    shape = MiddleButtonShape,\n                ) {}\n                SealDialogButtonVariant(\n                    text = stringResource(R.string.dont_allow),\n                    shape = BottomButtonShape,\n                ) {}\n            },\n        )\n    }\n}\n\nval TopButtonShape =\n    RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp, bottomStart = 4.dp, bottomEnd = 4.dp)\n\nval MiddleButtonShape = RoundedCornerShape(4.dp)\n\nval BottomButtonShape =\n    RoundedCornerShape(topStart = 4.dp, topEnd = 4.dp, bottomStart = 12.dp, bottomEnd = 12.dp)\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SealDialogVariant(\n    onDismissRequest: () -> Unit,\n    modifier: Modifier = Modifier,\n    buttons: @Composable (() -> Unit)? = null,\n    icon: @Composable (() -> Unit)? = null,\n    title: @Composable (() -> Unit)? = null,\n    text: @Composable (() -> Unit)? = null,\n    shape: Shape = AlertDialogDefaults.shape,\n    containerColor: Color = MaterialTheme.colorScheme.surfaceContainer,\n    iconContentColor: Color = AlertDialogDefaults.iconContentColor,\n    titleContentColor: Color = AlertDialogDefaults.titleContentColor,\n    textContentColor: Color = AlertDialogDefaults.textContentColor,\n    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,\n    properties: DialogProperties = DialogProperties(),\n) {\n    AlertDialog(onDismissRequest = onDismissRequest, modifier = modifier, properties = properties) {\n        Surface(\n            modifier = modifier,\n            shape = shape,\n            color = containerColor,\n            tonalElevation = tonalElevation,\n        ) {\n            Column(modifier = Modifier.padding(DialogVerticalPadding)) {\n                icon?.let {\n                    CompositionLocalProvider(LocalContentColor provides iconContentColor) {\n                        Box(\n                            Modifier.padding(IconPadding)\n                                .padding(DialogHorizontalPadding)\n                                .align(Alignment.CenterHorizontally)\n                        ) {\n                            icon()\n                        }\n                    }\n                }\n                title?.let {\n                    CompositionLocalProvider(LocalContentColor provides titleContentColor) {\n                        val textStyle = MaterialTheme.typography.headlineSmall\n                        ProvideTextStyle(textStyle.copy(textAlign = TextAlign.Center)) {\n                            Box(\n                                // Align the title to the center when an icon is present.\n                                Modifier.padding(TitlePadding)\n                                    .padding(DialogHorizontalPadding)\n                                    .align(\n                                        if (icon == null) {\n                                            Alignment.Start\n                                        } else {\n                                            Alignment.CenterHorizontally\n                                        }\n                                    )\n                            ) {\n                                title()\n                            }\n                        }\n                    }\n                }\n                text?.let {\n                    CompositionLocalProvider(LocalContentColor provides textContentColor) {\n                        val textStyle = MaterialTheme.typography.bodyMedium\n                        ProvideTextStyle(textStyle) {\n                            Box(\n                                Modifier.weight(weight = 1f, fill = false)\n                                    .padding(TextPadding)\n                                    .align(Alignment.Start)\n                            ) {\n                                text()\n                            }\n                        }\n                    }\n                }\n                Column(\n                    verticalArrangement = Arrangement.spacedBy(4.dp),\n                    modifier = Modifier.padding(DialogHorizontalPadding),\n                ) {\n                    buttons?.invoke()\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun DialogSubtitle(\n    modifier: Modifier = Modifier,\n    text: String,\n    color: Color = MaterialTheme.colorScheme.primary,\n) {\n    Text(\n        text = text,\n        modifier =\n            modifier.fillMaxWidth().padding(horizontal = 24.dp).padding(top = 16.dp, bottom = 4.dp),\n        color = color,\n        style = MaterialTheme.typography.labelLarge,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/DownloadQueueItem.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.animation.core.animateFloatAsState\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.filled.Cancel\nimport androidx.compose.material.icons.filled.CheckCircle\nimport androidx.compose.material.icons.filled.Error\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.ContentCopy\nimport androidx.compose.material.icons.outlined.ErrorOutline\nimport androidx.compose.material.icons.outlined.RestartAlt\nimport androidx.compose.material.icons.outlined.UnfoldMore\nimport androidx.compose.material3.CardDefaults\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.IconButtonDefaults\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ProgressIndicatorDefaults\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.semantics\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.AsyncImageImpl\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.LocalWindowWidthState\nimport com.junkfood.seal.ui.theme.PreviewThemeLight\nimport com.junkfood.seal.ui.theme.harmonizeWith\nimport com.junkfood.seal.ui.theme.harmonizeWithPrimary\nimport com.kyant.monet.LocalTonalPalettes\nimport com.kyant.monet.TonalPalettes.Companion.toTonalPalettes\nimport com.kyant.monet.dynamicColorScheme\n\n@Composable\n// @Preview\nfun PlaylistPreview() {\n    var selected by remember { mutableStateOf(false) }\n    Column() { PreviewThemeLight { PlaylistItem(selected = selected) { selected = !selected } } }\n}\n\n@Composable\nfun PlaylistItem(\n    modifier: Modifier = Modifier,\n    selected: Boolean = false,\n    imageModel: Any = R.drawable.sample,\n    title: String = \"sample title \".repeat(5),\n    author: String? = \"author sample \".repeat(5),\n    onClick: () -> Unit = {},\n) {\n    Surface(modifier = Modifier.fillMaxWidth().selectable(selected) { onClick() }) {\n        Row(modifier = modifier.fillMaxWidth().padding(vertical = 4.dp)) {\n            Checkbox(\n                modifier =\n                    Modifier.padding(start = 4.dp, end = 12.dp).align(Alignment.CenterVertically),\n                checked = selected,\n                onCheckedChange = null,\n            )\n            Box(\n                modifier =\n                    Modifier.padding(4.dp)\n                        .padding(end = 4.dp)\n                        .weight(\n                            if (LocalWindowWidthState.current == WindowWidthSizeClass.Compact) 2f\n                            else 1f\n                        )\n            ) {\n                AsyncImageImpl(\n                    modifier =\n                        Modifier.clip(MaterialTheme.shapes.extraSmall)\n                            .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true),\n                    model = imageModel,\n                    contentDescription = null,\n                    contentScale = ContentScale.Crop,\n                )\n            }\n            Column(modifier = Modifier.padding(vertical = 4.dp).weight(3f)) {\n                Text(\n                    text = title,\n                    style = MaterialTheme.typography.titleSmall,\n                    color = MaterialTheme.colorScheme.onSurface,\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                )\n                author?.let {\n                    Text(\n                        modifier = Modifier.padding(top = 2.dp),\n                        text = author,\n                        style = MaterialTheme.typography.bodySmall,\n                        color = MaterialTheme.colorScheme.onSurfaceVariant,\n                        maxLines = 1,\n                        overflow = TextOverflow.Ellipsis,\n                    )\n                }\n            }\n        }\n    }\n}\n\n@Composable\n@Preview\nfun TaskItemPreview() {\n    PreviewThemeLight {\n        Surface {\n            LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {\n                item { CustomCommandTaskItem(status = TaskStatus.RUNNING) }\n                item { CustomCommandTaskItem(status = TaskStatus.FINISHED) }\n                item { CustomCommandTaskItem(status = TaskStatus.ERROR) }\n                item { CustomCommandTaskItem(status = TaskStatus.CANCELED) }\n            }\n        }\n    }\n}\n\nenum class TaskStatus {\n    RUNNING,\n    ERROR,\n    CANCELED,\n    FINISHED,\n}\n\nval GreenTonalPalettes = Color.Green.toTonalPalettes()\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun CustomCommandTaskItem(\n    modifier: Modifier = Modifier,\n    status: TaskStatus = TaskStatus.ERROR,\n    progress: Float = .85f,\n    url: String = \"https://www.example.com\",\n    templateName: String = \"Template Example\",\n    progressText: String =\n        \"[sample] Extracting URL: https://www.example.com\\n\" +\n            \"[sample] sample: Downloading webpage\\n\" +\n            \"[sample] sample: Downloading android player API JSON\\n\" +\n            \"[info] Available automatic captions for sample:\" +\n            \"[info] Available automatic captions for sample:\",\n    onCopyLog: () -> Unit = {},\n    onCopyError: () -> Unit = {},\n    onRestart: () -> Unit = {},\n    onShowLog: () -> Unit = {},\n    onCancel: () -> Unit = {},\n) {\n    CompositionLocalProvider(LocalTonalPalettes provides GreenTonalPalettes) {\n        val greenScheme = dynamicColorScheme(!LocalDarkTheme.current.isDarkTheme())\n        val accentColor =\n            MaterialTheme.colorScheme.run {\n                when (status) {\n                    TaskStatus.FINISHED -> greenScheme.primary\n                    TaskStatus.CANCELED -> onSurfaceVariant\n                    TaskStatus.RUNNING -> primary\n                    TaskStatus.ERROR -> error.harmonizeWithPrimary()\n                }\n            }\n\n        val containerColor =\n            MaterialTheme.colorScheme\n                .run {\n                    /*            when (status) {\n                        TaskStatus.FINISHED -> greenScheme.primaryContainer\n                        TaskStatus.CANCELED -> surfaceVariant.copy(alpha = alpha)\n                        TaskStatus.RUNNING -> tertiaryContainer.copy(alpha = alpha)\n                        TaskStatus.ERROR -> errorContainer.copy(alpha = alpha)\n                    }*/\n                    surfaceContainerLow.harmonizeWith(other = accentColor)\n                }\n                .copy(alpha = 0.9f)\n        val contentColor =\n            MaterialTheme.colorScheme.run {\n                //            when (status) {\n                //                TaskStatus.FINISHED -> greenScheme.onPrimaryContainer\n                //                TaskStatus.CANCELED -> onSurfaceVariant\n                //                TaskStatus.RUNNING -> onTertiaryContainer\n                //                TaskStatus.ERROR -> onErrorContainer\n                //            }\n                onSurfaceVariant.harmonizeWith(other = accentColor)\n            }\n\n        val labelText =\n            stringResource(\n                id =\n                    when (status) {\n                        TaskStatus.FINISHED -> R.string.status_completed\n                        TaskStatus.CANCELED -> R.string.status_canceled\n                        TaskStatus.RUNNING -> R.string.status_downloading\n                        TaskStatus.ERROR -> R.string.status_error\n                    }\n            )\n        Surface(color = containerColor, shape = CardDefaults.shape) {\n            Column(modifier = Modifier.padding(16.dp)) {\n                Row(\n                    modifier = Modifier.semantics(mergeDescendants = true) {},\n                    verticalAlignment = Alignment.CenterVertically,\n                ) {\n                    when (status) {\n                        TaskStatus.FINISHED -> {\n                            Icon(\n                                modifier = Modifier.padding(8.dp).size(24.dp),\n                                imageVector = Icons.Filled.CheckCircle,\n                                tint = accentColor,\n                                contentDescription = stringResource(id = R.string.status_completed),\n                            )\n                        }\n\n                        TaskStatus.CANCELED -> {\n                            Icon(\n                                modifier = Modifier.padding(8.dp).size(24.dp),\n                                imageVector = Icons.Filled.Cancel,\n                                tint = accentColor,\n                                contentDescription = stringResource(id = R.string.status_canceled),\n                            )\n                        }\n\n                        TaskStatus.RUNNING -> {\n                            val animatedProgress by\n                                animateFloatAsState(\n                                    targetValue = progress,\n                                    animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,\n                                )\n                            if (progress < 0)\n                                CircularProgressIndicator(\n                                    modifier = Modifier.padding(8.dp).size(24.dp),\n                                    strokeWidth = 5.dp,\n                                    color = accentColor,\n                                )\n                            else\n                                CircularProgressIndicator(\n                                    modifier = Modifier.padding(8.dp).size(24.dp),\n                                    strokeWidth = 5.dp,\n                                    progress = animatedProgress,\n                                    color = accentColor,\n                                )\n                        }\n\n                        TaskStatus.ERROR -> {\n                            Icon(\n                                modifier = Modifier.padding(8.dp).size(24.dp),\n                                imageVector = Icons.Filled.Error,\n                                tint = accentColor,\n                                contentDescription = stringResource(id = R.string.status_error),\n                            )\n                        }\n                    }\n\n                    Column(Modifier.padding(horizontal = 8.dp).weight(1f)) {\n                        Text(\n                            text = templateName,\n                            style = MaterialTheme.typography.titleSmall,\n                            color = contentColor,\n                            maxLines = 1,\n                            overflow = TextOverflow.Ellipsis,\n                        )\n                        Text(\n                            text = url,\n                            style = MaterialTheme.typography.bodyMedium,\n                            maxLines = 1,\n                            color = contentColor,\n                            overflow = TextOverflow.Ellipsis,\n                        )\n                    }\n                    IconButton(\n                        modifier =\n                            Modifier.align(Alignment.Top).semantics(mergeDescendants = true) {},\n                        onClick = { onShowLog() },\n                        colors =\n                            IconButtonDefaults.iconButtonColors(\n                                containerColor = MaterialTheme.colorScheme.surfaceContainerLowest,\n                                contentColor = MaterialTheme.colorScheme.onSurfaceVariant,\n                            ),\n                    ) {\n                        Icon(\n                            imageVector = Icons.Outlined.UnfoldMore,\n                            contentDescription = stringResource(id = R.string.show_logs),\n                        )\n                    }\n                }\n                Text(\n                    modifier = Modifier.padding(8.dp).padding(top = 4.dp),\n                    text = progressText,\n                    style =\n                        MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),\n                    color =\n                        if (status == TaskStatus.ERROR) MaterialTheme.colorScheme.error\n                        else contentColor,\n                    maxLines = 3,\n                    minLines = 3,\n                    overflow = TextOverflow.Ellipsis,\n                )\n\n                Row(modifier = Modifier.horizontalScroll(rememberScrollState())) {\n                    FlatButtonChip(\n                        icon = Icons.Outlined.ContentCopy,\n                        label = stringResource(id = R.string.copy_log),\n                    ) {\n                        onCopyLog()\n                    }\n                    if (status == TaskStatus.ERROR)\n                        FlatButtonChip(\n                            icon = Icons.Outlined.ErrorOutline,\n                            label = stringResource(id = R.string.copy_error_report),\n                            iconColor = MaterialTheme.colorScheme.error,\n                        ) {\n                            onCopyError()\n                        }\n                    if (status == TaskStatus.RUNNING)\n                        FlatButtonChip(\n                            icon = Icons.Outlined.Cancel,\n                            label = stringResource(id = R.string.cancel),\n                            iconColor = contentColor,\n                        ) {\n                            onCancel()\n                        }\n                    if (status == TaskStatus.CANCELED || status == TaskStatus.ERROR)\n                        FlatButtonChip(\n                            icon = Icons.Outlined.RestartAlt,\n                            label = stringResource(id = R.string.restart),\n                        ) {\n                            onRestart()\n                        }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/FormatItem.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport android.content.res.Configuration\nimport androidx.compose.animation.animateColorAsState\nimport androidx.compose.animation.core.tween\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.border\nimport androidx.compose.foundation.combinedClickable\nimport androidx.compose.foundation.isSystemInDarkTheme\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.wrapContentHeight\nimport androidx.compose.foundation.lazy.grid.GridCells\nimport androidx.compose.foundation.lazy.grid.GridItemSpan\nimport androidx.compose.foundation.lazy.grid.LazyGridScope\nimport androidx.compose.foundation.lazy.grid.LazyVerticalGrid\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.ContentCut\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.Image\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material.icons.outlined.VerticalSplit\nimport androidx.compose.material.icons.rounded.Audiotrack\nimport androidx.compose.material.icons.rounded.QuestionMark\nimport androidx.compose.material.icons.rounded.Videocam\nimport androidx.compose.material3.DropdownMenu\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.darkColorScheme\nimport androidx.compose.material3.lightColorScheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.Format\nimport com.junkfood.seal.util.VideoInfo\nimport com.junkfood.seal.util.connectWithBlank\nimport com.junkfood.seal.util.connectWithDelimiter\nimport com.junkfood.seal.util.toBitrateText\nimport com.junkfood.seal.util.toDurationText\nimport com.junkfood.seal.util.toFileSizeText\n\n@Composable\nfun FormatVideoPreview(\n    modifier: Modifier = Modifier,\n    title: String,\n    author: String,\n    thumbnailUrl: String,\n    duration: Int,\n    isSplittingVideo: Boolean,\n    isClippingVideo: Boolean,\n    isClippingAvailable: Boolean = false,\n    isSplitByChapterAvailable: Boolean = false,\n    onRename: () -> Unit = {},\n    onOpenThumbnail: () -> Unit = {},\n    onClippingToggled: () -> Unit = {},\n    onSplittingToggled: () -> Unit = {},\n) {\n    Box(modifier = Modifier.fillMaxWidth().wrapContentHeight(Alignment.Top, unbounded = false)) {\n        Row(modifier = modifier.fillMaxWidth()) {\n            Box(modifier = Modifier) {\n                MediaImage(\n                    modifier = Modifier,\n                    imageModel = thumbnailUrl,\n                    isAudio = false,\n                    contentDescription = stringResource(id = R.string.thumbnail),\n                )\n                Surface(\n                    modifier = Modifier.padding(2.dp).align(Alignment.BottomEnd),\n                    color = Color.Black.copy(alpha = 0.68f),\n                    shape = MaterialTheme.shapes.extraSmall,\n                ) {\n                    val durationText = duration.toDurationText()\n                    Text(\n                        modifier = Modifier.padding(horizontal = 4.dp),\n                        text = durationText,\n                        style = MaterialTheme.typography.labelSmall,\n                        color = Color.White,\n                    )\n                }\n            }\n\n            Column(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.Top) {\n                Text(\n                    modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp),\n                    text = title,\n                    style = MaterialTheme.typography.titleSmall,\n                    color = MaterialTheme.colorScheme.onSurface,\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                )\n                if (author != \"playlist\" && author != \"null\")\n                    Text(\n                        modifier = Modifier.padding(horizontal = 12.dp).padding(top = 3.dp),\n                        text = author,\n                        style = MaterialTheme.typography.bodySmall,\n                        color = MaterialTheme.colorScheme.onSurfaceVariant,\n                        maxLines = 1,\n                        overflow = TextOverflow.Ellipsis,\n                    )\n            }\n        }\n        var expanded by remember { mutableStateOf(false) }\n        Box(modifier = Modifier.align(Alignment.BottomEnd)) {\n            IconButton(onClick = { expanded = true }, modifier = Modifier.size(36.dp)) {\n                Icon(\n                    imageVector = Icons.Outlined.MoreVert,\n                    stringResource(id = R.string.show_more_actions),\n                    modifier = Modifier.size(18.dp),\n                )\n            }\n\n            DropdownMenu(\n                modifier = Modifier.align(Alignment.BottomEnd),\n                expanded = expanded,\n                onDismissRequest = { expanded = false },\n                scrollState = rememberScrollState(),\n            ) {\n                DropdownMenuItem(\n                    leadingIcon = { Icon(imageVector = Icons.Outlined.Edit, null) },\n                    text = { Text(text = stringResource(id = R.string.rename)) },\n                    onClick = {\n                        onRename()\n                        expanded = false\n                    },\n                )\n                DropdownMenuItem(\n                    leadingIcon = { Icon(imageVector = Icons.Outlined.Image, null) },\n                    text = { Text(text = stringResource(id = R.string.thumbnail)) },\n                    onClick = {\n                        onOpenThumbnail()\n                        expanded = false\n                    },\n                )\n                if (isClippingAvailable && !isClippingVideo && !isSplittingVideo) {\n                    DropdownMenuItem(\n                        leadingIcon = { Icon(Icons.Outlined.ContentCut, null) },\n                        text = { Text(text = stringResource(id = R.string.clip_video)) },\n                        onClick = {\n                            onClippingToggled()\n                            expanded = false\n                        },\n                    )\n                }\n                if (isSplitByChapterAvailable && !isClippingVideo && !isSplittingVideo) {\n                    DropdownMenuItem(\n                        leadingIcon = { Icon(Icons.Outlined.VerticalSplit, null) },\n                        text = { Text(text = stringResource(id = R.string.split_video)) },\n                        onClick = {\n                            onSplittingToggled()\n                            expanded = false\n                        },\n                    )\n                }\n            }\n        }\n    }\n}\n\n@Composable\n@Preview\nfun VideoInfoPreview() {\n    SealTheme {\n        Surface {\n            Column {\n                FormatVideoPreview(\n                    title = stringResource(id = R.string.video_title_sample_text),\n                    author = stringResource(id = R.string.video_creator_sample_text),\n                    thumbnailUrl = \"\",\n                    duration = 7890,\n                    isSplittingVideo = false,\n                    isClippingVideo = false,\n                    isSplitByChapterAvailable = true,\n                    isClippingAvailable = true,\n                )\n            }\n        }\n    }\n}\n\n@Composable\nfun SuggestedFormatItem(\n    modifier: Modifier = Modifier,\n    videoInfo: VideoInfo,\n    selected: Boolean = false,\n    onClick: () -> Unit = {},\n) {\n    val requestedFormats =\n        videoInfo.requestedFormats\n            ?: videoInfo.requestedDownloads?.map { it.toFormat() }\n            ?: emptyList()\n    val duration = videoInfo.duration ?: 0.0\n\n    val containsVideo = requestedFormats.any { it.containsVideo() }\n    val containsAudio = requestedFormats.any { it.containsVideo() }\n\n    val title = requestedFormats.joinToString(separator = \" + \") { it.format.toString() }\n\n    val totalFileSize =\n        requestedFormats.fold(initial = 0.0) { acc: Double, format: Format ->\n            acc +\n                (format.fileSize ?: format.fileSizeApprox ?: (duration * (format.tbr ?: 0.0) * 125))\n            // kbps -> bytes 1000/8\n        }\n    val fileSizeText = totalFileSize.toFileSizeText()\n\n    val totalTbr =\n        requestedFormats.fold(initial = 0.0) { acc: Double, format: Format ->\n            acc + (format.tbr ?: 0.0)\n        }\n\n    val tbrText = totalTbr.toBitrateText()\n\n    val firstLineText = connectWithDelimiter(fileSizeText, tbrText, delimiter = \" \")\n\n    val vcodecText = videoInfo.vcodec?.substringBefore(delimiter = \".\") ?: \"\"\n    val acodecText = videoInfo.acodec?.substringBefore(delimiter = \".\") ?: \"\"\n\n    val codecText =\n        connectWithBlank(vcodecText, acodecText).run { if (isNotBlank()) \"($this)\" else this }\n\n    val secondLineText = connectWithDelimiter(videoInfo.ext, codecText, delimiter = \" \").uppercase()\n\n    FormatItem(\n        modifier = modifier,\n        title = title,\n        containsAudio = containsAudio,\n        containsVideo = containsVideo,\n        firstLineText = firstLineText,\n        secondLineText = secondLineText,\n        selected = selected,\n        onClick = onClick,\n    )\n}\n\n@Composable\nfun FormatItem(\n    modifier: Modifier = Modifier,\n    formatInfo: Format,\n    duration: Double,\n    selected: Boolean = false,\n    outlineColor: Color = MaterialTheme.colorScheme.primary,\n    containerColor: Color = MaterialTheme.colorScheme.primaryContainer,\n    onLongClick: (() -> Unit)? = null,\n    onClick: () -> Unit = {},\n) {\n\n    with(formatInfo) {\n        val vcodecText = vcodec?.substringBefore(delimiter = \".\") ?: \"\"\n        val acodecText = acodec?.substringBefore(delimiter = \".\") ?: \"\"\n\n        val codec =\n            connectWithBlank(vcodecText, acodecText).run { if (isNotBlank()) \"($this)\" else this }\n\n        val tbrText =\n            when {\n                tbr == null -> \"\" // i don't care\n                tbr < 1024f -> \"%.1f Kbps\".format(tbr)\n\n                else -> \"%.2f Mbps\".format(tbr / 1024f)\n            }\n\n        val fileSize = fileSize ?: fileSizeApprox ?: (tbr?.times(duration * 125))\n        val fileSizeText = fileSize.toFileSizeText()\n\n        val firstLineText = connectWithDelimiter(fileSizeText, tbrText, delimiter = \" \")\n\n        val secondLineText = connectWithDelimiter(ext, codec, delimiter = \" \").uppercase()\n\n        FormatItem(\n            modifier = modifier,\n            title = format.toString(),\n            containsAudio = formatInfo.containsAudio(),\n            containsVideo = formatInfo.containsVideo(),\n            firstLineText = firstLineText,\n            secondLineText = secondLineText,\n            outlineColor = outlineColor,\n            containerColor = containerColor,\n            selected = selected,\n            onLongClick = onLongClick,\n            onClick = onClick,\n        )\n    }\n}\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\nfun FormatItem(\n    modifier: Modifier = Modifier,\n    title: String = \"247 - 1280x720 (720p)\",\n    containsAudio: Boolean = false,\n    containsVideo: Boolean = false,\n    firstLineText: String,\n    secondLineText: String,\n    selected: Boolean = false,\n    outlineColor: Color = MaterialTheme.colorScheme.primary,\n    containerColor: Color = MaterialTheme.colorScheme.primaryContainer,\n    onLongClick: (() -> Unit)? = null,\n    onClick: () -> Unit = {},\n) {\n\n    val animatedTitleColor by\n        animateColorAsState(\n            if (selected) outlineColor else MaterialTheme.colorScheme.onSurface,\n            animationSpec = tween(100),\n            label = \"\",\n        )\n\n    val animatedContainerColor by\n        animateColorAsState(\n            if (selected) containerColor else MaterialTheme.colorScheme.surface,\n            animationSpec = tween(100),\n            label = \"\",\n        )\n\n    val animatedOutlineColor by\n        animateColorAsState(\n            targetValue = if (selected) outlineColor else MaterialTheme.colorScheme.outlineVariant,\n            animationSpec = tween(100),\n            label = \"\",\n        )\n\n    Box(\n        modifier =\n            modifier\n                .clip(MaterialTheme.shapes.medium)\n                .selectable(selected = selected) { onClick() }\n                .combinedClickable(\n                    onClick = { onClick() },\n                    onLongClick = onLongClick,\n                    onLongClickLabel = stringResource(R.string.copy_link),\n                )\n                .border(\n                    width = 1.dp,\n                    color = animatedOutlineColor,\n                    shape = MaterialTheme.shapes.medium,\n                )\n                .background(animatedContainerColor)\n    ) {\n        Column(Modifier.padding(12.dp), horizontalAlignment = Alignment.Start) {\n            Text(\n                text = title,\n                style = MaterialTheme.typography.titleSmall,\n                minLines = 2,\n                maxLines = 2,\n                color = animatedTitleColor,\n                overflow = TextOverflow.Clip,\n            )\n\n            Text(\n                text = firstLineText,\n                style = MaterialTheme.typography.labelMedium,\n                modifier = Modifier.padding(top = 6.dp),\n                color = MaterialTheme.colorScheme.onSurface,\n                maxLines = 2,\n            )\n\n            Text(\n                text = secondLineText,\n                style = MaterialTheme.typography.labelMedium,\n                modifier = Modifier.padding(top = 2.dp),\n                color = MaterialTheme.colorScheme.onSurface,\n                maxLines = 1,\n            )\n        }\n        Row(modifier = Modifier.padding(bottom = 6.dp, end = 6.dp).align(Alignment.BottomEnd)) {\n            if (containsVideo)\n                Icon(\n                    imageVector = Icons.Rounded.Videocam,\n                    tint = outlineColor,\n                    contentDescription = stringResource(id = R.string.video),\n                    modifier = Modifier.size(16.dp),\n                )\n            if (containsAudio)\n                Icon(\n                    imageVector = Icons.Rounded.Audiotrack,\n                    tint = outlineColor,\n                    contentDescription = stringResource(id = R.string.audio),\n                    modifier = Modifier.size(16.dp),\n                )\n            if (!containsVideo && !containsAudio) {\n                Icon(\n                    imageVector = Icons.Rounded.QuestionMark,\n                    tint = outlineColor,\n                    contentDescription = stringResource(id = R.string.unknown),\n                    modifier = Modifier.size(16.dp),\n                )\n            }\n        }\n    }\n}\n\n@Composable\n@Preview(\n    name = \"Dark\",\n    uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL,\n)\n@Preview(name = \"Light\")\nfun PreviewFormat() {\n    MaterialTheme(\n        colorScheme = if (isSystemInDarkTheme()) darkColorScheme() else lightColorScheme()\n    ) {\n        var selected by remember { mutableStateOf(-1) }\n        Surface {\n            Column() {\n                //                FormatSubtitle(text = stringResource(R.string.video_only))\n                LazyVerticalGrid(\n                    columns = GridCells.Adaptive(150.dp),\n                    verticalArrangement = Arrangement.spacedBy(8.dp),\n                    horizontalArrangement = Arrangement.spacedBy(8.dp),\n                ) {\n                    FormatPreviewContent(selected) { selected = it }\n                }\n            }\n        }\n    }\n}\n\nfun LazyGridScope.FormatPreviewContent(selected: Int = 0, onClick: (Int) -> Unit = {}) {\n    item(span = { GridItemSpan(maxLineSpan) }) {\n        FormatSubtitle(\n            text = \"Suggested\",\n            modifier = Modifier.padding(top = 12.dp, bottom = 4.dp).padding(horizontal = 12.dp),\n        )\n    }\n    item(span = { GridItemSpan(maxLineSpan) }) {\n        FormatItem(\n            selected = selected == 1,\n            containsAudio = true,\n            containsVideo = true,\n            firstLineText = \"? MB + 16.00 MB, (? + 200) Kbps\",\n            secondLineText = \"MKV (Unknown + OPUS)\",\n        ) {\n            onClick(1)\n        }\n    }\n\n    item(span = { GridItemSpan(maxLineSpan) }) {\n        FormatSubtitle(\n            text = stringResource(R.string.audio),\n            color = MaterialTheme.colorScheme.tertiary,\n            modifier = Modifier.padding(top = 12.dp, bottom = 4.dp).padding(horizontal = 12.dp),\n        )\n    }\n    for (i in 0..1) {\n        item {\n            FormatItem(\n                selected = selected == i,\n                outlineColor = MaterialTheme.colorScheme.tertiary,\n                containerColor = MaterialTheme.colorScheme.tertiaryContainer,\n                containsVideo = false,\n                containsAudio = true,\n                firstLineText = \"\",\n                secondLineText = \"OPUS (OPUS)\",\n            ) {\n                onClick(i)\n            }\n        }\n    }\n    item {\n        FormatItem(\n            selected = selected == 2,\n            outlineColor = MaterialTheme.colorScheme.tertiary,\n            containerColor = MaterialTheme.colorScheme.tertiaryContainer,\n            containsVideo = false,\n            containsAudio = true,\n            firstLineText = \"\",\n            secondLineText = \"Unknown (Unknown)\",\n        ) {\n            onClick(2)\n        }\n    }\n    item(span = { GridItemSpan(maxLineSpan) }) {\n        FormatSubtitle(\n            text = stringResource(R.string.video_only),\n            modifier = Modifier.padding(top = 12.dp, bottom = 4.dp).padding(horizontal = 12.dp),\n        )\n    }\n    for (i in 0..2) {\n        item {\n            FormatItem(\n                selected = selected == i,\n                containsVideo = true,\n                containsAudio = false,\n                firstLineText = \"69.00MB 745.7Kbps\",\n                secondLineText = \"MP4 (AVC1)\",\n            ) {\n                onClick(i)\n            }\n        }\n    }\n    item(span = { GridItemSpan(maxLineSpan) }) {\n        FormatSubtitle(\n            text = stringResource(R.string.video),\n            color = MaterialTheme.colorScheme.secondary,\n            modifier = Modifier.padding(top = 12.dp, bottom = 4.dp).padding(horizontal = 12.dp),\n        )\n    }\n    for (i in 0..3) {\n        item {\n            FormatItem(\n                selected = selected == i,\n                outlineColor = MaterialTheme.colorScheme.secondary,\n                containerColor = MaterialTheme.colorScheme.secondaryContainer,\n                containsVideo = true,\n                containsAudio = true,\n                firstLineText = \"\",\n                secondLineText = \"\",\n            ) {\n                onClick(i)\n            }\n        }\n    }\n}\n\n@Composable\nfun FormatSubtitle(\n    modifier: Modifier = Modifier,\n    text: String,\n    color: Color = MaterialTheme.colorScheme.primary,\n) {\n    Text(\n        text = text,\n        modifier = modifier,\n        color = color,\n        style = MaterialTheme.typography.titleSmall,\n    )\n}\n\n@Preview\n@Composable\nfun FormatItemPreview() {\n    FormatItem(formatInfo = Format(), duration = 20.0)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/IconButtons.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.ArrowBack\nimport androidx.compose.material.icons.outlined.Add\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.ContentPaste\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\n\n@Composable\nfun PasteFromClipBoardButton(onPaste: (String) -> Unit = {}) {\n    val clipboardManager = LocalClipboardManager.current\n    PasteButton(onClick = { clipboardManager.getText()?.let { onPaste(it.toString()) } })\n}\n\n@Composable\nfun PasteButton(onClick: () -> Unit = {}) {\n    IconButton(onClick = onClick) {\n        Icon(Icons.Outlined.ContentPaste, stringResource(R.string.paste))\n    }\n}\n\n@Composable\nfun AddButton(onClick: () -> Unit, enabled: Boolean = true) {\n    IconButton(onClick = onClick, enabled = enabled) {\n        Icon(imageVector = Icons.Outlined.Add, contentDescription = stringResource(R.string.add))\n    }\n}\n\n@Composable\nfun ClearButton(onClick: () -> Unit) {\n    IconButton(onClick = onClick) {\n        Icon(\n            modifier = Modifier.size(24.dp),\n            imageVector = Icons.Outlined.Cancel,\n            contentDescription = stringResource(id = R.string.clear),\n            tint = MaterialTheme.colorScheme.onSurfaceVariant,\n        )\n    }\n}\n\n@Composable\nfun BackButton(onClick: () -> Unit) {\n    val view = LocalView.current\n    IconButton(\n        modifier = Modifier,\n        onClick = {\n            onClick()\n            view.slightHapticFeedback()\n        },\n    ) {\n        Icon(\n            imageVector = Icons.AutoMirrored.Outlined.ArrowBack,\n            contentDescription = stringResource(R.string.back),\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/ModalBottomSheetM2.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ColumnScope\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.foundation.shape.RoundedCornerShape\nimport androidx.compose.material.ExperimentalMaterialApi\nimport androidx.compose.material.ModalBottomSheetDefaults\nimport androidx.compose.material.ModalBottomSheetState\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.rememberModalBottomSheetState\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.zIndex\nimport kotlinx.coroutines.launch\n\n@Composable\nfun rememberSheetState(\n    showSheet: Boolean,\n    onVisibilityChange: (isVisible: Boolean) -> Unit,\n): ModalBottomSheetState {\n    val state =\n        rememberModalBottomSheetState(\n            skipHalfExpanded = true,\n            initialValue = ModalBottomSheetValue.Hidden,\n        )\n    LaunchedEffect(showSheet) {\n        if (showSheet && state.targetValue == ModalBottomSheetValue.Hidden) {\n            state.show()\n        } else if (!showSheet && state.targetValue == ModalBottomSheetValue.Expanded) {\n            state.hide()\n        }\n    }\n\n    LaunchedEffect(state.targetValue) {\n        when (state.targetValue) {\n            ModalBottomSheetValue.Hidden -> onVisibilityChange(false)\n            ModalBottomSheetValue.Expanded -> onVisibilityChange(true)\n            else -> {}\n        }\n    }\n    return state\n}\n\n@Preview\n@Composable\nprivate fun SheetTest() {\n    var showSheet by remember { mutableStateOf(true) }\n    val sheetState = rememberSheetState(showSheet = showSheet) { showSheet = it }\n    val scope = rememberCoroutineScope()\n    Surface {\n        Column {\n            Text(\"wtf\")\n            Text(\"showSheet = $showSheet\")\n            Button(onClick = { showSheet = true }) { Text(\"show sheet!\") }\n            Button(onClick = { scope.launch { sheetState.show() } }) { Text(\"sheetState.hide()\") }\n        }\n    }\n\n    SealModalBottomSheetM2(sheetState = sheetState) {\n        Column {\n            Button(onClick = { scope.launch { sheetState.hide() } }) { Text(\"sheetState.hide()\") }\n\n            Button(onClick = { showSheet = false }) { Text(\"showSheet = false\") }\n        }\n    }\n}\n\n@Composable\nfun SealModalBottomSheetM2(\n    modifier: Modifier = Modifier,\n    sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden),\n    contentPadding: PaddingValues = PaddingValues(horizontal = 28.dp),\n    sheetGesturesEnabled: Boolean = true,\n    sheetContent: @Composable ColumnScope.() -> Unit = {},\n) {\n    androidx.compose.material.ModalBottomSheetLayout(\n        modifier = modifier,\n        sheetShape =\n            RoundedCornerShape(\n                topStart = 28.0.dp,\n                topEnd = 28.0.dp,\n                bottomEnd = 0.0.dp,\n                bottomStart = 0.0.dp,\n            ),\n        sheetState = sheetState,\n        sheetBackgroundColor = MaterialTheme.colorScheme.surfaceContainer,\n        sheetElevation = if (sheetState.isVisible) ModalBottomSheetDefaults.Elevation else 0.dp,\n        sheetGesturesEnabled = sheetGesturesEnabled,\n        sheetContent = {\n            Column {\n                Surface(color = MaterialTheme.colorScheme.surfaceContainer) {\n                    Box(modifier = Modifier.padding(contentPadding)) {\n                        Row(\n                            modifier = modifier.padding(top = 8.dp).fillMaxWidth(),\n                            horizontalArrangement = Arrangement.Center,\n                            verticalAlignment = Alignment.CenterVertically,\n                        ) {\n                            Row(\n                                modifier =\n                                    modifier\n                                        .size(32.dp, 4.dp)\n                                        .clip(CircleShape)\n                                        .background(\n                                            MaterialTheme.colorScheme.onSurfaceVariant.copy(\n                                                alpha = 0.4f\n                                            )\n                                        )\n                                        .zIndex(1f)\n                            ) {}\n                        }\n                        Column {\n                            Spacer(modifier = Modifier.height(40.dp))\n                            sheetContent()\n                            Spacer(modifier = Modifier.height(28.dp))\n                        }\n                    }\n                }\n                NavigationBarSpacer(\n                    modifier =\n                        Modifier.background(MaterialTheme.colorScheme.surfaceContainerHigh)\n                            .fillMaxWidth()\n                )\n            }\n        },\n    ) {}\n}\n\n@OptIn(ExperimentalMaterialApi::class)\n@Composable\nfun SealModalBottomSheetM2Variant(\n    modifier: Modifier = Modifier,\n    sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden),\n    sheetGesturesEnabled: Boolean = true,\n    sheetContent: @Composable ColumnScope.() -> Unit = {},\n) {\n    androidx.compose.material.ModalBottomSheetLayout(\n        modifier = modifier,\n        sheetShape =\n            RoundedCornerShape(\n                topStart = 0.dp,\n                topEnd = 0.dp,\n                bottomEnd = 0.dp,\n                bottomStart = 0.dp,\n            ),\n        sheetState = sheetState,\n        sheetBackgroundColor = Color.Transparent,\n        sheetElevation = if (sheetState.isVisible) ModalBottomSheetDefaults.Elevation else 0.dp,\n        sheetGesturesEnabled = sheetGesturesEnabled,\n        sheetContent = {\n            Column { Box(modifier = Modifier) { Column { sheetContent() } } }\n            NavigationBarSpacer(\n                modifier =\n                    Modifier.background(MaterialTheme.colorScheme.surfaceContainerHigh)\n                        .fillMaxWidth()\n            )\n        },\n    ) {}\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/ModalBottomSheetM3.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ColumnScope\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ModalBottomSheet\nimport androidx.compose.material3.ModalBottomSheetDefaults\nimport androidx.compose.material3.ModalBottomSheetProperties\nimport androidx.compose.material3.SheetState\nimport androidx.compose.material3.SheetValue\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.unit.dp\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SealModalBottomSheet(\n    modifier: Modifier = Modifier,\n    sheetState: SheetState =\n        with(LocalDensity.current) {\n            SheetState(\n                initialValue = SheetValue.Expanded,\n                skipPartiallyExpanded = true,\n                velocityThreshold = { 56.dp.toPx() },\n                positionalThreshold = { 125.dp.toPx() },\n            )\n        },\n    onDismissRequest: () -> Unit,\n    contentPadding: PaddingValues = PaddingValues(horizontal = 28.dp),\n    properties: ModalBottomSheetProperties = ModalBottomSheetDefaults.properties,\n    content: @Composable ColumnScope.() -> Unit = {},\n) {\n    ModalBottomSheet(\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        sheetState = sheetState,\n        properties = properties,\n    ) {\n        Column(modifier = Modifier.padding(paddingValues = contentPadding)) {\n            content()\n            Spacer(modifier = Modifier.height(28.dp))\n        }\n    }\n}\n\n@Composable\nfun DrawerSheetSubtitle(\n    modifier: Modifier = Modifier,\n    text: String,\n    color: Color = MaterialTheme.colorScheme.primary,\n) {\n    Text(\n        text = text,\n        modifier = modifier.fillMaxWidth().padding(start = 4.dp, top = 16.dp, bottom = 8.dp),\n        color = color,\n        style = MaterialTheme.typography.labelLarge,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/PreferenceItems.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport android.content.res.Configuration\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.LocalIndication\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.combinedClickable\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.IntrinsicSize\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.foundation.selection.toggleable\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Check\nimport androidx.compose.material.icons.outlined.Info\nimport androidx.compose.material.icons.outlined.TipsAndUpdates\nimport androidx.compose.material.icons.outlined.ToggleOn\nimport androidx.compose.material.icons.outlined.Translate\nimport androidx.compose.material.icons.outlined.Update\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Switch\nimport androidx.compose.material3.SwitchDefaults\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.VerticalDivider\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.painter.Painter\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.semantics.contentDescription\nimport androidx.compose.ui.semantics.semantics\nimport androidx.compose.ui.text.TextStyle\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.theme.FixedAccentColors\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.ui.theme.applyOpacity\nimport com.junkfood.seal.ui.theme.harmonizeWithPrimary\nimport com.kyant.monet.LocalTonalPalettes\nimport com.kyant.monet.TonalPalettes.Companion.toTonalPalettes\n\nprivate const val horizontal = 8\nprivate const val vertical = 12\n\nprivate val PreferenceTitleVariant: TextStyle\n    @Composable get() = MaterialTheme.typography.titleLarge.copy(fontSize = 20.sp)\n\nprivate val PreferenceTitle\n    @Composable get() = MaterialTheme.typography.titleMedium\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\nfun PreferenceItem(\n    title: String,\n    description: String? = null,\n    icon: Any? = null,\n    enabled: Boolean = true,\n    onLongClickLabel: String? = null,\n    onLongClick: (() -> Unit)? = null,\n    onClickLabel: String? = null,\n    leadingIcon: (@Composable () -> Unit)? = null,\n    trailingIcon: (@Composable () -> Unit)? = null,\n    onClick: () -> Unit = {},\n) {\n    Surface(\n        modifier =\n            Modifier.combinedClickable(\n                onClick = onClick,\n                onClickLabel = onClickLabel,\n                enabled = enabled,\n                onLongClickLabel = onLongClickLabel,\n                onLongClick = onLongClick,\n            )\n    ) {\n        Row(\n            modifier = Modifier.fillMaxWidth().padding(horizontal.dp, vertical.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            leadingIcon?.invoke()\n\n            when (icon) {\n                is ImageVector -> {\n                    Icon(\n                        imageVector = icon,\n                        contentDescription = null,\n                        modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                        tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                    )\n                }\n\n                is Painter -> {\n                    Icon(\n                        painter = icon,\n                        contentDescription = null,\n                        modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                        tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                    )\n                }\n            }\n\n            Column(\n                modifier =\n                    Modifier.weight(1f)\n                        .padding(\n                            horizontal = if (icon == null && leadingIcon == null) 8.dp else 0.dp\n                        )\n                        .padding(end = 8.dp)\n            ) {\n                PreferenceItemTitle(text = title, enabled = enabled)\n                if (!description.isNullOrEmpty())\n                    PreferenceItemDescription(text = description, enabled = enabled)\n            }\n            trailingIcon?.let {\n                VerticalDivider(\n                    modifier =\n                        Modifier.height(32.dp)\n                            .padding(horizontal = 8.dp)\n                            .align(Alignment.CenterVertically),\n                    color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f),\n                    thickness = 1.dp,\n                )\n                trailingIcon.invoke()\n            }\n        }\n    }\n}\n\n@Composable\n@Preview\nfun PreferenceItemPreview() {\n    SealTheme {\n        Surface {\n            Column {\n                PreferenceSubtitle(text = \"Preview\")\n                PreferenceItem(title = \"title\", description = \"description\")\n                PreferenceItem(\n                    title = \"title\",\n                    description = \"description\",\n                    icon = Icons.Outlined.Update,\n                )\n                PreferenceItemVariant(\n                    title = \"title\",\n                    description = \"description\",\n                    icon = Icons.Outlined.Update,\n                )\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\nfun PreferenceItemVariant(\n    modifier: Modifier = Modifier,\n    title: String,\n    description: String? = null,\n    icon: ImageVector? = null,\n    enabled: Boolean = true,\n    onLongClickLabel: String? = null,\n    onLongClick: () -> Unit = {},\n    onClickLabel: String? = null,\n    onClick: () -> Unit = {},\n) {\n    Surface(\n        modifier =\n            Modifier.combinedClickable(\n                enabled = enabled,\n                onClick = onClick,\n                onClickLabel = onClickLabel,\n                onLongClick = onLongClick,\n                onLongClickLabel = onLongClickLabel,\n            )\n    ) {\n        Row(\n            modifier = modifier.fillMaxWidth().padding(12.dp, 16.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            icon?.let {\n                Icon(\n                    imageVector = icon,\n                    contentDescription = null,\n                    modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                    tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                )\n            }\n            Column(\n                modifier =\n                    Modifier.weight(1f)\n                        .padding(horizontal = if (icon == null) 12.dp else 0.dp)\n                        .padding(end = 8.dp)\n            ) {\n                PreferenceItemTitle(text = title, enabled = enabled)\n                if (description != null) {\n                    PreferenceItemDescription(text = description, enabled = enabled)\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun PreferenceSingleChoiceItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    selected: Boolean,\n    contentPadding: PaddingValues = PaddingValues(horizontal = 8.dp, vertical = 16.dp),\n    onClick: () -> Unit,\n) {\n    Surface(modifier = Modifier.selectable(selected = selected, onClick = onClick)) {\n        Row(\n            modifier = modifier.fillMaxWidth().padding(contentPadding),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            Column(modifier = Modifier.weight(1f).padding(start = 8.dp)) {\n                Text(\n                    text = text,\n                    maxLines = 1,\n                    style = PreferenceTitleVariant,\n                    color = MaterialTheme.colorScheme.onSurface,\n                    overflow = TextOverflow.Ellipsis,\n                )\n            }\n            RadioButton(\n                selected = selected,\n                onClick = onClick,\n                modifier = Modifier.padding().clearAndSetSemantics {},\n            )\n        }\n    }\n}\n\n@Composable\ninternal fun PreferenceItemTitle(\n    modifier: Modifier = Modifier,\n    text: String,\n    maxLines: Int = 2,\n    style: TextStyle = PreferenceTitle,\n    enabled: Boolean,\n    color: Color = MaterialTheme.colorScheme.onBackground,\n    overflow: TextOverflow = TextOverflow.Ellipsis,\n) {\n    Text(\n        modifier = modifier,\n        text = text,\n        maxLines = maxLines,\n        style = style,\n        color = color.applyOpacity(enabled),\n        overflow = overflow,\n    )\n}\n\n@Composable\ninternal fun PreferenceItemDescription(\n    modifier: Modifier = Modifier,\n    text: String,\n    maxLines: Int = Int.MAX_VALUE,\n    style: TextStyle = MaterialTheme.typography.bodyMedium,\n    enabled: Boolean,\n    color: Color = MaterialTheme.colorScheme.onSurfaceVariant,\n    overflow: TextOverflow = TextOverflow.Ellipsis,\n) {\n    Text(\n        modifier = modifier,\n        text = text,\n        maxLines = maxLines,\n        style = style,\n        color = color.applyOpacity(enabled),\n        overflow = overflow,\n    )\n}\n\n@Composable\n@Preview\nfun PreferenceSwitchPreview() {\n    var b by remember { mutableStateOf(false) }\n    SealTheme {\n        PreferenceSwitch(\n            title = \"PreferenceSwitch\",\n            description = \"Supporting text\",\n            icon = Icons.Outlined.ToggleOn,\n            isChecked = b,\n        ) {\n            b = !b\n        }\n    }\n}\n\n@Composable\n@Preview\nfun PreferenceSwitchWithDividerPreview() {\n    PreferenceSwitchWithDivider(\n        title = \"PreferenceSwitch\",\n        description = \"Supporting text\",\n        icon = Icons.Outlined.ToggleOn,\n    )\n}\n\n@Composable\nfun rememberThumbContent(\n    isChecked: Boolean,\n    checkedIcon: ImageVector = Icons.Outlined.Check,\n): (@Composable () -> Unit)? =\n    remember(isChecked, checkedIcon) {\n        if (isChecked) {\n            {\n                Icon(\n                    imageVector = checkedIcon,\n                    contentDescription = null,\n                    modifier = Modifier.size(SwitchDefaults.IconSize),\n                )\n            }\n        } else {\n            null\n        }\n    }\n\n@Composable\nfun PreferenceSwitchVariant(\n    title: String,\n    description: String? = null,\n    icon: ImageVector? = null,\n    enabled: Boolean = true,\n    isChecked: Boolean = true,\n    thumbContent: (@Composable () -> Unit)? = rememberThumbContent(isChecked = isChecked),\n    onClick: (() -> Unit) = {},\n) {\n\n    val interactionSource = remember { MutableInteractionSource() }\n    Surface(\n        modifier =\n            Modifier.toggleable(\n                value = isChecked,\n                enabled = enabled,\n                onValueChange = { onClick() },\n                indication = LocalIndication.current,\n                interactionSource = interactionSource,\n            )\n    ) {\n        Row(\n            modifier =\n                Modifier.fillMaxWidth()\n                    .padding(horizontal.dp, vertical.dp)\n                    .padding(start = if (icon == null) 12.dp else 0.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            icon?.let {\n                Icon(\n                    imageVector = icon,\n                    contentDescription = null,\n                    modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                    tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                )\n            }\n            Column(modifier = Modifier.weight(1f)) {\n                PreferenceItemTitle(text = title, enabled = enabled, style = PreferenceTitleVariant)\n                if (!description.isNullOrEmpty())\n                    PreferenceItemDescription(text = description, enabled = enabled)\n            }\n            Switch(\n                checked = isChecked,\n                onCheckedChange = null,\n                interactionSource = interactionSource,\n                modifier = Modifier.padding(start = 20.dp, end = 6.dp),\n                enabled = enabled,\n                thumbContent = thumbContent,\n            )\n        }\n    }\n}\n\n@Composable\nfun PreferenceSwitch(\n    title: String,\n    description: String? = null,\n    icon: ImageVector? = null,\n    enabled: Boolean = true,\n    isChecked: Boolean = true,\n    thumbContent: (@Composable () -> Unit)? = rememberThumbContent(isChecked = isChecked),\n    onClick: (() -> Unit) = {},\n) {\n\n    val interactionSource = remember { MutableInteractionSource() }\n    Surface(\n        modifier =\n            Modifier.toggleable(\n                value = isChecked,\n                enabled = enabled,\n                onValueChange = { onClick() },\n                indication = LocalIndication.current,\n                interactionSource = interactionSource,\n            )\n    ) {\n        Row(\n            modifier =\n                Modifier.fillMaxWidth()\n                    .padding(horizontal.dp, vertical.dp)\n                    .padding(start = if (icon == null) 12.dp else 0.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            icon?.let {\n                Icon(\n                    imageVector = icon,\n                    contentDescription = null,\n                    modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                    tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                )\n            }\n            Column(modifier = Modifier.weight(1f)) {\n                PreferenceItemTitle(text = title, enabled = enabled)\n                if (!description.isNullOrEmpty())\n                    PreferenceItemDescription(text = description, enabled = enabled)\n            }\n            Switch(\n                checked = isChecked,\n                onCheckedChange = null,\n                interactionSource = interactionSource,\n                modifier = Modifier.padding(start = 20.dp, end = 6.dp),\n                enabled = enabled,\n                thumbContent = thumbContent,\n            )\n        }\n    }\n}\n\n@Composable\nfun PreferenceSwitchWithDivider(\n    title: String,\n    description: String? = null,\n    icon: ImageVector? = null,\n    enabled: Boolean = true,\n    isSwitchEnabled: Boolean = enabled,\n    isChecked: Boolean = true,\n    thumbContent: (@Composable () -> Unit)? = rememberThumbContent(isChecked = isChecked),\n    onClick: (() -> Unit) = {},\n    onChecked: () -> Unit = {},\n) {\n\n    Surface(\n        modifier =\n            Modifier.clickable(\n                enabled = enabled,\n                onClick = onClick,\n                onClickLabel = stringResource(id = R.string.open_settings),\n            )\n    ) {\n        Row(\n            modifier =\n                Modifier.fillMaxWidth()\n                    .padding(horizontal.dp, vertical.dp)\n                    .height(IntrinsicSize.Min),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            icon?.let {\n                Icon(\n                    imageVector = icon,\n                    contentDescription = null,\n                    modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                    tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                )\n            }\n            Column(modifier = Modifier.weight(1f)) {\n                PreferenceItemTitle(text = title, enabled = enabled)\n                if (!description.isNullOrEmpty())\n                    PreferenceItemDescription(text = description, enabled = enabled)\n            }\n            VerticalDivider(\n                modifier =\n                    Modifier.height(32.dp)\n                        .padding(horizontal = 8.dp)\n                        .width(1f.dp)\n                        .align(Alignment.CenterVertically),\n                color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f),\n            )\n            Switch(\n                checked = isChecked,\n                onCheckedChange = { onChecked() },\n                modifier =\n                    Modifier.padding(horizontal = 6.dp).semantics { contentDescription = title },\n                enabled = isSwitchEnabled,\n                thumbContent = thumbContent,\n            )\n        }\n    }\n}\n\n@Composable\nfun PreferencesCautionCard(\n    title: String,\n    description: String? = null,\n    icon: ImageVector? = null,\n    onClick: () -> Unit = {},\n) {\n\n    Row(\n        modifier =\n            Modifier.fillMaxWidth()\n                .padding(horizontal = 8.dp, vertical = 12.dp)\n                .clip(MaterialTheme.shapes.extraLarge)\n                .background(MaterialTheme.colorScheme.errorContainer.harmonizeWithPrimary())\n                .clickable { onClick() }\n                .padding(horizontal = 12.dp, vertical = 16.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        icon?.let {\n            Icon(\n                imageVector = icon,\n                contentDescription = null,\n                modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                tint = MaterialTheme.colorScheme.error.harmonizeWithPrimary(),\n            )\n        }\n        Column(\n            modifier =\n                Modifier.weight(1f).padding(start = if (icon == null) 12.dp else 0.dp, end = 12.dp)\n        ) {\n            with(MaterialTheme) {\n                Text(\n                    text = title,\n                    maxLines = 1,\n                    style = PreferenceTitleVariant,\n                    color = colorScheme.onErrorContainer.harmonizeWithPrimary(),\n                )\n                if (description != null)\n                    Text(\n                        text = description,\n                        color = colorScheme.onErrorContainer.harmonizeWithPrimary(),\n                        maxLines = 2,\n                        overflow = TextOverflow.Ellipsis,\n                        style = typography.bodyMedium,\n                    )\n            }\n        }\n    }\n}\n\n@Preview\n@Composable\nfun PreferencesHintCardPreview() {\n    CompositionLocalProvider(LocalTonalPalettes provides Color.Green.toTonalPalettes()) {\n        PreferencesHintCard(\n            title = \"Explore new features\",\n            icon = Icons.Outlined.TipsAndUpdates,\n            description = \"Find out what's new in this version\",\n            containerColor = FixedAccentColors.primaryFixed,\n            contentColor = FixedAccentColors.onPrimaryFixed,\n        )\n    }\n}\n\n@Composable\nfun PreferencesHintCard(\n    title: String = \"Title \".repeat(2),\n    description: String? = \"Description text \".repeat(3),\n    icon: ImageVector? = Icons.Outlined.Translate,\n    containerColor: Color = FixedAccentColors.secondaryFixed,\n    contentColor: Color = FixedAccentColors.onSecondaryFixed,\n    onClick: () -> Unit = {},\n) {\n    Row(\n        modifier =\n            Modifier.fillMaxWidth()\n                .padding(horizontal = 16.dp, vertical = 12.dp)\n                .clip(MaterialTheme.shapes.extraLarge)\n                .background(containerColor)\n                .clickable { onClick() }\n                .padding(horizontal = 12.dp, vertical = 16.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        icon?.let {\n            Icon(\n                imageVector = icon,\n                contentDescription = null,\n                modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                tint = contentColor,\n            )\n        }\n        Column(\n            modifier =\n                Modifier.weight(1f).padding(start = if (icon == null) 12.dp else 0.dp, end = 12.dp)\n        ) {\n            with(MaterialTheme) {\n                Text(\n                    text = title,\n                    maxLines = 1,\n                    style = PreferenceTitleVariant,\n                    color = contentColor,\n                )\n                if (description != null)\n                    Text(\n                        text = description,\n                        color = contentColor,\n                        maxLines = 2,\n                        overflow = TextOverflow.Ellipsis,\n                        style = typography.bodyMedium,\n                    )\n            }\n        }\n    }\n}\n\n@Composable\n@Preview(name = \"Light\", uiMode = Configuration.UI_MODE_NIGHT_NO)\n@Preview(name = \"Night\", uiMode = Configuration.UI_MODE_NIGHT_YES)\nprivate fun PreferenceSwitchWithContainerPreview() {\n    var isChecked by remember { mutableStateOf(false) }\n    SealTheme {\n        PreferenceSwitchWithContainer(\n            title = \"Title \".repeat(2),\n            isChecked = isChecked,\n            onClick = { isChecked = !isChecked },\n            icon = null,\n        )\n    }\n}\n\n@Composable\nfun PreferenceSwitchWithContainer(\n    title: String,\n    icon: ImageVector? = null,\n    isChecked: Boolean,\n    thumbContent: @Composable (() -> Unit)? = rememberThumbContent(isChecked = isChecked),\n    onClick: () -> Unit,\n) {\n\n    val interactionSource = remember { MutableInteractionSource() }\n    Row(\n        modifier =\n            Modifier.fillMaxWidth()\n                .padding(horizontal = 16.dp, vertical = 12.dp)\n                .clip(MaterialTheme.shapes.extraLarge)\n                .background(MaterialTheme.colorScheme.primaryContainer)\n                .toggleable(\n                    value = isChecked,\n                    onValueChange = { onClick() },\n                    interactionSource = interactionSource,\n                    indication = LocalIndication.current,\n                )\n                .padding(horizontal = 16.dp, vertical = 20.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        icon?.let {\n            Icon(\n                imageVector = icon,\n                contentDescription = null,\n                modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                tint = MaterialTheme.colorScheme.onPrimaryContainer,\n            )\n        }\n        Column(\n            modifier =\n                Modifier.weight(1f).padding(start = if (icon == null) 12.dp else 0.dp, end = 12.dp)\n        ) {\n            Text(\n                text = title,\n                maxLines = 2,\n                style = PreferenceTitleVariant,\n                color = MaterialTheme.colorScheme.onPrimaryContainer,\n            )\n        }\n        Switch(\n            checked = isChecked,\n            interactionSource = interactionSource,\n            onCheckedChange = null,\n            modifier = Modifier.padding(start = 12.dp, end = 6.dp),\n            thumbContent = thumbContent,\n        )\n    }\n}\n\n@Composable\nfun CreditItem(\n    title: String,\n    license: String? = null,\n    enabled: Boolean = true,\n    onClick: () -> Unit = {},\n) {\n    Surface(modifier = Modifier.clickable { onClick() }) {\n        Row(\n            modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 16.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            Column(modifier = Modifier.weight(1f).padding(horizontal = 10.dp)) {\n                with(MaterialTheme) {\n                    Text(\n                        text = title,\n                        maxLines = 1,\n                        style = typography.titleMedium,\n                        color = colorScheme.onSurface.applyOpacity(enabled),\n                    )\n                    license?.let {\n                        Text(\n                            text = it,\n                            color = colorScheme.onSurfaceVariant.applyOpacity(enabled),\n                            maxLines = 2,\n                            overflow = TextOverflow.Ellipsis,\n                            style = typography.bodyMedium,\n                        )\n                    }\n                }\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\n@Preview\nfun TemplateItem(\n    label: String = \"\",\n    template: String? = null,\n    selected: Boolean = false,\n    isMultiSelectEnabled: Boolean = false,\n    checked: Boolean = false,\n    onClick: () -> Unit = {},\n    onSelect: () -> Unit = {},\n    onCheckedChange: (Boolean) -> Unit = {},\n    onLongClick: () -> Unit = {},\n) {\n    Surface(\n        modifier =\n            Modifier.run {\n                if (!isMultiSelectEnabled)\n                    then(\n                        this.combinedClickable(\n                            onClick = onClick,\n                            onClickLabel = stringResource(R.string.edit),\n                            onLongClick = onLongClick,\n                            onLongClickLabel = stringResource(R.string.multiselect_mode),\n                        )\n                    )\n                else {\n                    then(this.toggleable(value = checked, onValueChange = onCheckedChange))\n                }\n            }\n    ) {\n        Row(\n            modifier = Modifier.fillMaxWidth().padding(16.dp, 16.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            AnimatedVisibility(visible = isMultiSelectEnabled) {\n                Checkbox(\n                    modifier = Modifier.clearAndSetSemantics {},\n                    checked = checked,\n                    onCheckedChange = onCheckedChange,\n                )\n            }\n\n            Column(modifier = Modifier.weight(1f).padding(horizontal = 10.dp)) {\n                with(MaterialTheme) {\n                    Text(\n                        text = label,\n                        maxLines = 1,\n                        style = typography.titleMedium,\n                        color = colorScheme.onSurface,\n                    )\n                    template?.let {\n                        Text(\n                            text = it,\n                            color = colorScheme.onSurfaceVariant,\n                            maxLines = 2,\n                            overflow = TextOverflow.Ellipsis,\n                            style = typography.bodyMedium,\n                        )\n                    }\n                }\n            }\n\n            AnimatedVisibility(!isMultiSelectEnabled) {\n                Row {\n                    VerticalDivider(\n                        modifier =\n                            Modifier.height(32.dp)\n                                .padding(horizontal = 12.dp)\n                                .align(Alignment.CenterVertically),\n                        color = MaterialTheme.colorScheme.outlineVariant,\n                        thickness = 1.dp,\n                    )\n                    RadioButton(\n                        modifier = Modifier.semantics { contentDescription = label },\n                        selected = selected,\n                        onClick = onSelect,\n                    )\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun PreferenceSubtitle(\n    text: String,\n    modifier: Modifier = Modifier,\n    contentPadding: PaddingValues = PaddingValues(start = 16.dp, top = 20.dp, bottom = 8.dp),\n    color: Color = MaterialTheme.colorScheme.primary,\n) {\n    Text(\n        text = text,\n        modifier = modifier.padding(contentPadding),\n        color = color,\n        style = MaterialTheme.typography.labelLarge,\n    )\n}\n\n@Composable\nfun PreferenceInfo(\n    modifier: Modifier = Modifier,\n    text: String,\n    icon: ImageVector = Icons.Outlined.Info,\n    applyPaddings: Boolean = true,\n) {\n    Column(\n        modifier =\n            modifier.fillMaxWidth().run {\n                if (applyPaddings) padding(horizontal = 16.dp, vertical = 16.dp) else this\n            }\n    ) {\n        Icon(modifier = Modifier.padding(), imageVector = icon, contentDescription = null)\n        Text(\n            modifier = Modifier.padding(top = 16.dp),\n            text = text,\n            style = MaterialTheme.typography.bodyMedium,\n        )\n    }\n}\n\n@Composable\n@Preview(showBackground = true)\nfun PreferenceInfoPreview() {\n    PreferenceInfo(text = stringResource(id = R.string.custom_command_enabled_hint))\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/SearchBar.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport android.view.HapticFeedbackConstants\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.layout.widthIn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Clear\nimport androidx.compose.material.icons.outlined.Search\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.theme.SealTheme\n\n@Composable\nfun SealSearchBar(\n    modifier: Modifier = Modifier,\n    text: String,\n    placeholderText: String,\n    onValueChange: (String) -> Unit,\n) {\n    val view = LocalView.current\n\n    Surface(\n        modifier = modifier.widthIn(360.dp, 720.dp),\n        shape = MaterialTheme.shapes.medium,\n        color = MaterialTheme.colorScheme.surfaceContainer,\n    ) {\n        Row(verticalAlignment = Alignment.CenterVertically) {\n            Spacer(modifier = Modifier.width(16.dp))\n            Icon(\n                imageVector = Icons.Outlined.Search,\n                contentDescription = null,\n                tint = MaterialTheme.colorScheme.onSurfaceVariant,\n            )\n            SealAutoFocusTextField(\n                value = text,\n                onValueChange = onValueChange,\n                placeholder = { Text(text = placeholderText) },\n                modifier = Modifier.weight(1f),\n                contentDescription = stringResource(id = R.string.search),\n                trailingIcon = {\n                    if (text.isNotEmpty()) {\n                        IconButton(\n                            onClick = {\n                                onValueChange(\"\")\n                                view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)\n                            }\n                        ) {\n                            Icon(\n                                modifier = Modifier.size(24.dp),\n                                imageVector = Icons.Outlined.Clear,\n                                contentDescription = stringResource(id = R.string.clear),\n                                tint = MaterialTheme.colorScheme.onSurfaceVariant,\n                            )\n                        }\n                    }\n                },\n            )\n        }\n    }\n}\n\n@Preview\n@Composable\nprivate fun SearchBarPreview() {\n    var text by remember { mutableStateOf(\"\") }\n    SealTheme {\n        Surface {\n            SealSearchBar(\n                text = text,\n                placeholderText = stringResource(R.string.search_in_downloads),\n            ) {\n                text = it\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/SegementedButton.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.material3.SegmentedButton\nimport androidx.compose.material3.SegmentedButtonColors\nimport androidx.compose.material3.SegmentedButtonDefaults\nimport androidx.compose.material3.SingleChoiceSegmentedButtonRowScope\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.Shape\n\n@Composable\nfun SingleChoiceSegmentedButtonRowScope.SingleChoiceSegmentedButton(\n    selected: Boolean,\n    onClick: () -> Unit,\n    shape: Shape,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    colors: SegmentedButtonColors =\n        SegmentedButtonDefaults.colors(inactiveContainerColor = Color.Transparent),\n    icon: @Composable () -> Unit = { SegmentedButtonDefaults.Icon(selected) },\n    label: @Composable () -> Unit,\n) {\n    SegmentedButton(\n        selected = selected,\n        onClick = onClick,\n        shape = shape,\n        modifier = modifier,\n        enabled = enabled,\n        colors = colors,\n        icon = icon,\n        label = label,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/SelectionGroup.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.animation.animateColorAsState\nimport androidx.compose.animation.core.Spring\nimport androidx.compose.animation.core.animateDpAsState\nimport androidx.compose.animation.core.spring\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.RowScope\nimport androidx.compose.foundation.layout.heightIn\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.widthIn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.selectableGroup\nimport androidx.compose.foundation.shape.RoundedCornerShape\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.Immutable\nimport androidx.compose.runtime.ReadOnlyComposable\nimport androidx.compose.runtime.Stable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.Shape\nimport androidx.compose.ui.graphics.takeOrElse\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.junkfood.seal.ui.theme.SealTheme\n\n@Composable\nfun SelectionGroupRow(\n    modifier: Modifier = Modifier,\n    content: @Composable SelectionGroupScope.() -> Unit,\n) {\n    Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = modifier.selectableGroup()) {\n        val scope = remember { SelectionGroupScope(this) }\n        content.invoke(scope)\n    }\n}\n\nclass SelectionGroupScope(rowScope: RowScope) : RowScope by rowScope\n\n@Composable\nfun SelectionGroupScope.SelectionGroupItem(\n    selected: Boolean,\n    onClick: () -> Unit,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    shape: Shape = SelectionGroupDefaults.shape(selected),\n    colors: SelectionGroupItemColors = SelectionGroupDefaults.colors(),\n    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n    contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),\n    content: @Composable RowScope.() -> Unit,\n) {\n    val containerColor by animateColorAsState(colors.containerColor(enabled, selected))\n    val contentColor by animateColorAsState(colors.contentColor(enabled, selected))\n\n    Surface(\n        selected = selected,\n        onClick = onClick,\n        modifier = modifier,\n        enabled = enabled,\n        shape = shape,\n        color = containerColor,\n        contentColor = contentColor,\n        interactionSource = interactionSource,\n    ) {\n        Row(\n            modifier = Modifier.heightIn(min = 32.dp).widthIn(min = 56.dp).padding(contentPadding),\n            verticalAlignment = Alignment.CenterVertically,\n            horizontalArrangement = Arrangement.Center,\n        ) {\n            ProvideTextStyle(MaterialTheme.typography.labelLarge) { content.invoke(this) }\n        }\n    }\n}\n\nobject SelectionGroupDefaults {\n\n    @Composable\n    fun shape(selected: Boolean): Shape {\n        val animatedRoundedCorner by\n            animateDpAsState(\n                if (selected) 28.dp else 12.dp,\n                label = \"itemShape\",\n                animationSpec = spring(stiffness = Spring.StiffnessMediumLow),\n            )\n        return RoundedCornerShape(animatedRoundedCorner)\n    }\n\n    @Composable\n    fun colors(\n        activeContainerColor: Color = Color.Unspecified,\n        activeContentColor: Color = Color.Unspecified,\n        inactiveContainerColor: Color = Color.Unspecified,\n        inactiveContentColor: Color = Color.Unspecified,\n        disabledActiveContainerColor: Color = Color.Unspecified,\n        disabledActiveContentColor: Color = Color.Unspecified,\n        disabledInactiveContainerColor: Color = Color.Unspecified,\n        disabledInactiveContentColor: Color = Color.Unspecified,\n    ): SelectionGroupItemColors {\n        return defaultSelectionGroupItemColors.run {\n            copy(\n                activeContainerColor =\n                    activeContainerColor.takeOrElse { this.activeContainerColor },\n                activeContentColor = activeContentColor.takeOrElse { this.activeContentColor },\n                inactiveContainerColor =\n                    inactiveContainerColor.takeOrElse { this.inactiveContainerColor },\n                inactiveContentColor =\n                    inactiveContentColor.takeOrElse { this.inactiveContentColor },\n                disabledActiveContainerColor =\n                    disabledActiveContainerColor.takeOrElse { this.disabledActiveContainerColor },\n                disabledActiveContentColor =\n                    disabledActiveContentColor.takeOrElse { this.disabledActiveContentColor },\n                disabledInactiveContainerColor =\n                    disabledInactiveContainerColor.takeOrElse {\n                        this.disabledInactiveContainerColor\n                    },\n                disabledInactiveContentColor =\n                    disabledInactiveContentColor.takeOrElse { this.disabledInactiveContentColor },\n            )\n        }\n    }\n\n    private val defaultSelectionGroupItemColors: SelectionGroupItemColors\n        @Composable\n        @ReadOnlyComposable\n        get() {\n            val colorScheme = MaterialTheme.colorScheme\n            val fixedColorRoles = LocalFixedColorRoles.current\n            return SelectionGroupItemColors(\n                activeContainerColor = fixedColorRoles.primaryFixed,\n                activeContentColor = fixedColorRoles.onPrimaryFixed,\n                inactiveContainerColor = colorScheme.surfaceContainer,\n                inactiveContentColor = colorScheme.onSurface,\n                disabledActiveContainerColor = colorScheme.onSurface.copy(alpha = 0.12f),\n                disabledActiveContentColor = colorScheme.onSurface.copy(alpha = 0.38f),\n                disabledInactiveContainerColor = colorScheme.onSurface.copy(alpha = 0.12f),\n                disabledInactiveContentColor = colorScheme.onSurface.copy(alpha = 0.38f),\n            )\n        }\n}\n\n@Immutable\ndata class SelectionGroupItemColors(\n    val activeContainerColor: Color,\n    val activeContentColor: Color,\n    val inactiveContainerColor: Color,\n    val inactiveContentColor: Color,\n    val disabledActiveContainerColor: Color,\n    val disabledActiveContentColor: Color,\n    val disabledInactiveContainerColor: Color,\n    val disabledInactiveContentColor: Color,\n) {\n\n    @Stable\n    internal fun contentColor(enabled: Boolean, checked: Boolean): Color {\n        return when {\n            enabled && checked -> activeContentColor\n            enabled && !checked -> inactiveContentColor\n            !enabled && checked -> disabledActiveContentColor\n            else -> disabledInactiveContentColor\n        }\n    }\n\n    @Stable\n    internal fun containerColor(enabled: Boolean, active: Boolean): Color {\n        return when {\n            enabled && active -> activeContainerColor\n            enabled && !active -> inactiveContainerColor\n            !enabled && active -> disabledActiveContainerColor\n            else -> disabledInactiveContainerColor\n        }\n    }\n}\n\n@Preview\n@Composable\nprivate fun Preview() {\n    SealTheme {\n        Surface {\n            var selected by remember { mutableIntStateOf(0) }\n            val itemSet = setOf(\"All\", \"Downloaded\", \"Canceled\", \"Finished\")\n            SelectionGroupRow(modifier = Modifier.horizontalScroll(rememberScrollState())) {\n                itemSet.forEachIndexed { index, s ->\n                    SelectionGroupItem(\n                        selected = selected == index,\n                        onClick = { selected = index },\n                    ) {\n                        Text(s, style = MaterialTheme.typography.labelLarge)\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/SettingItem.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.unit.dp\n\n@Composable\nfun SettingTitle(text: String) {\n    Text(\n        modifier = Modifier.padding(top = 32.dp).padding(horizontal = 20.dp, vertical = 16.dp),\n        text = text,\n        style = MaterialTheme.typography.displaySmall,\n    )\n}\n\n@Composable\nfun SettingItem(title: String, description: String, icon: ImageVector?, onClick: () -> Unit) {\n    Surface(modifier = Modifier.clickable { onClick() }) {\n        Row(\n            modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 20.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            icon?.let {\n                Icon(\n                    imageVector = icon,\n                    contentDescription = null,\n                    modifier = Modifier.padding(end = 16.dp).size(24.dp),\n                    tint = MaterialTheme.colorScheme.primary,\n                )\n            }\n            Column(\n                modifier = Modifier.weight(1f).padding(start = if (icon == null) 12.dp else 0.dp)\n            ) {\n                Text(\n                    text = title,\n                    maxLines = 1,\n                    style = MaterialTheme.typography.titleLarge,\n                    color = MaterialTheme.colorScheme.onSurface,\n                    overflow = TextOverflow.Ellipsis,\n                )\n                Spacer(modifier = Modifier.height(2.dp))\n                Text(\n                    text = description,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    maxLines = 2,\n                    style = MaterialTheme.typography.bodyMedium,\n                    overflow = TextOverflow.Ellipsis,\n                )\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/SponsorItem.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.widthIn\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.min\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.AsyncImageImpl\n\nfun gitHubAvatar(userLogin: String): String = \"https://github.com/${userLogin}.png\"\n\nfun gitHubProfile(userLogin: String): String = \"https://github.com/${userLogin}\"\n\n@Composable\nfun SponsorItem(\n    modifier: Modifier = Modifier,\n    userName: String?,\n    userLogin: String,\n    avatarUrl: Any = gitHubAvatar(userLogin),\n    profileUrl: String = gitHubProfile(userLogin),\n    contentPadding: PaddingValues = PaddingValues(horizontal = 0.dp, vertical = 12.dp),\n    onClick: () -> Unit = {},\n) {\n    Column() {\n        Column(\n            modifier =\n                modifier\n                    .fillMaxWidth()\n                    .clip(MaterialTheme.shapes.large)\n                    .clickable(onClick = onClick)\n                    .padding(4.dp),\n            horizontalAlignment = Alignment.CenterHorizontally,\n        ) {\n            AsyncImageImpl(\n                modifier =\n                    Modifier.widthIn(min = 48.dp, max = 108.dp)\n                        .fillMaxWidth()\n                        .aspectRatio(1f, true)\n                        .clip(CircleShape),\n                model = avatarUrl,\n                contentDescription = null,\n                contentScale = ContentScale.Crop,\n            )\n            Column(\n                modifier = Modifier.padding(contentPadding),\n                horizontalAlignment = Alignment.CenterHorizontally,\n            ) {\n                userName?.let {\n                    Text(\n                        text = it,\n                        maxLines = 1,\n                        style = MaterialTheme.typography.titleSmall,\n                        color = MaterialTheme.colorScheme.onSurface,\n                        overflow = TextOverflow.Ellipsis,\n                    )\n                }\n                Text(\n                    text = \"@$userLogin\",\n                    maxLines = 1,\n                    style = MaterialTheme.typography.bodySmall,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    overflow = TextOverflow.Ellipsis,\n                )\n            }\n        }\n    }\n}\n\n@Composable\n@Preview\nfun SponsorItemPreview() {\n    SponsorItem(\n        userName = \"junkfood\",\n        userLogin = \"JunkFood02\",\n        avatarUrl = R.drawable.sample1,\n        profileUrl = \"\",\n    ) {}\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/TextField.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.text.KeyboardActions\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextField\nimport androidx.compose.material3.TextFieldColors\nimport androidx.compose.material3.TextFieldDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.focus.FocusRequester\nimport androidx.compose.ui.focus.focusRequester\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.Shape\nimport androidx.compose.ui.platform.LocalFocusManager\nimport androidx.compose.ui.semantics.contentDescription\nimport androidx.compose.ui.semantics.semantics\nimport androidx.compose.ui.text.TextStyle\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.text.input.TextFieldValue\nimport androidx.compose.ui.text.input.VisualTransformation\nimport androidx.compose.ui.unit.dp\nimport kotlinx.coroutines.delay\n\n/** @param contentDescription Text label of the `TextField` for the accessibility service */\n@Composable\nfun SealTextField(\n    value: String,\n    onValueChange: (String) -> Unit,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    readOnly: Boolean = false,\n    textStyle: TextStyle = LocalTextStyle.current,\n    contentDescription: String? = null,\n    label: @Composable (() -> Unit)? = null,\n    placeholder: @Composable (() -> Unit)? = null,\n    leadingIcon: @Composable (() -> Unit)? = null,\n    trailingIcon: @Composable (() -> Unit)? = null,\n    prefix: @Composable (() -> Unit)? = null,\n    suffix: @Composable (() -> Unit)? = null,\n    supportingText: @Composable (() -> Unit)? = null,\n    isError: Boolean = false,\n    visualTransformation: VisualTransformation = VisualTransformation.None,\n    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,\n    keyboardActions: KeyboardActions = KeyboardActions.Default,\n    singleLine: Boolean = false,\n    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,\n    minLines: Int = 1,\n    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n    shape: Shape = TextFieldDefaults.shape,\n    colors: TextFieldColors =\n        TextFieldDefaults.colors(\n            focusedContainerColor = Color.Transparent,\n            unfocusedContainerColor = Color.Transparent,\n            disabledContainerColor = Color.Transparent,\n        ),\n) {\n    TextField(\n        value = value,\n        onValueChange = onValueChange,\n        modifier =\n            modifier.then(\n                Modifier.semantics {\n                    if (contentDescription != null) {\n                        this.contentDescription = contentDescription\n                    }\n                }\n            ),\n        enabled = enabled,\n        readOnly = readOnly,\n        textStyle = textStyle,\n        label = label,\n        placeholder = placeholder,\n        leadingIcon = leadingIcon,\n        trailingIcon = trailingIcon,\n        prefix = prefix,\n        suffix = suffix,\n        supportingText = supportingText,\n        isError = isError,\n        visualTransformation = visualTransformation,\n        keyboardOptions = keyboardOptions,\n        keyboardActions = keyboardActions,\n        singleLine = singleLine,\n        maxLines = maxLines,\n        minLines = minLines,\n        interactionSource = interactionSource,\n        shape = shape,\n        colors = colors,\n    )\n}\n\n@Composable\nfun SealAutoFocusTextField(\n    value: String,\n    onValueChange: (String) -> Unit,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    readOnly: Boolean = false,\n    textStyle: TextStyle = LocalTextStyle.current,\n    contentDescription: String? = null,\n    label: @Composable (() -> Unit)? = null,\n    placeholder: @Composable (() -> Unit)? = null,\n    leadingIcon: @Composable (() -> Unit)? = null,\n    trailingIcon: @Composable (() -> Unit)? = null,\n    prefix: @Composable (() -> Unit)? = null,\n    suffix: @Composable (() -> Unit)? = null,\n    supportingText: @Composable (() -> Unit)? = null,\n    isError: Boolean = false,\n    visualTransformation: VisualTransformation = VisualTransformation.None,\n    singleLine: Boolean = false,\n    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,\n    minLines: Int = 1,\n    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n    shape: Shape = TextFieldDefaults.shape,\n    colors: TextFieldColors =\n        TextFieldDefaults.colors(\n            unfocusedTextColor = MaterialTheme.colorScheme.onSurfaceVariant,\n            focusedContainerColor = Color.Transparent,\n            unfocusedContainerColor = Color.Transparent,\n            disabledContainerColor = Color.Transparent,\n            focusedIndicatorColor = Color.Transparent,\n            unfocusedIndicatorColor = Color.Transparent,\n        ),\n    focusRequester: FocusRequester = remember { FocusRequester() },\n) {\n    val focusManager = LocalFocusManager.current\n\n    LaunchedEffect(Unit) {\n        delay(200)\n        focusRequester.requestFocus()\n    }\n\n    TextField(\n        value = value,\n        onValueChange = onValueChange,\n        modifier =\n            modifier\n                .then(\n                    Modifier.semantics {\n                        if (contentDescription != null) {\n                            this.contentDescription = contentDescription\n                        }\n                    }\n                )\n                .focusRequester(focusRequester = focusRequester),\n        enabled = enabled,\n        readOnly = readOnly,\n        textStyle = textStyle,\n        label = label,\n        placeholder = placeholder,\n        leadingIcon = leadingIcon,\n        trailingIcon = trailingIcon,\n        prefix = prefix,\n        suffix = suffix,\n        supportingText = supportingText,\n        isError = isError,\n        visualTransformation = visualTransformation,\n        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n        keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),\n        singleLine = singleLine,\n        maxLines = maxLines,\n        minLines = minLines,\n        interactionSource = interactionSource,\n        shape = shape,\n        colors = colors,\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SealTextField(\n    value: TextFieldValue,\n    onValueChange: (TextFieldValue) -> Unit,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    readOnly: Boolean = false,\n    textStyle: TextStyle = LocalTextStyle.current,\n    label: @Composable (() -> Unit)? = null,\n    placeholder: @Composable (() -> Unit)? = null,\n    leadingIcon: @Composable (() -> Unit)? = null,\n    trailingIcon: @Composable (() -> Unit)? = null,\n    prefix: @Composable (() -> Unit)? = null,\n    suffix: @Composable (() -> Unit)? = null,\n    supportingText: @Composable (() -> Unit)? = null,\n    isError: Boolean = false,\n    visualTransformation: VisualTransformation = VisualTransformation.None,\n    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,\n    keyboardActions: KeyboardActions = KeyboardActions.Default,\n    singleLine: Boolean = false,\n    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,\n    minLines: Int = 1,\n    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n    shape: Shape = TextFieldDefaults.shape,\n    colors: TextFieldColors =\n        TextFieldDefaults.colors(\n            focusedContainerColor = Color.Transparent,\n            unfocusedContainerColor = Color.Transparent,\n            disabledContainerColor = Color.Transparent,\n        ),\n) {\n    TextField(\n        value,\n        onValueChange,\n        modifier,\n        enabled,\n        readOnly,\n        textStyle,\n        label,\n        placeholder,\n        leadingIcon,\n        trailingIcon,\n        prefix,\n        suffix,\n        supportingText,\n        isError,\n        visualTransformation,\n        keyboardOptions,\n        keyboardActions,\n        singleLine,\n        maxLines,\n        minLines,\n        interactionSource,\n        shape,\n        colors,\n    )\n}\n\n@Composable\nfun AdjacentLabel(modifier: Modifier = Modifier, text: String) {\n    Text(\n        text = text,\n        modifier = modifier.padding(bottom = 12.dp, start = 4.dp),\n        style = MaterialTheme.typography.bodySmall,\n        color = MaterialTheme.colorScheme.onSurfaceVariant,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/VideoCard.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport android.content.res.Configuration\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.Crossfade\nimport androidx.compose.animation.core.animateFloatAsState\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material3.ElevatedCard\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilledTonalIconButton\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButtonDefaults\nimport androidx.compose.material3.LinearProgressIndicator\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ProgressIndicatorDefaults\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.AsyncImageImpl\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.toDurationText\nimport com.junkfood.seal.util.toFileSizeText\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun VideoCard(\n    modifier: Modifier = Modifier,\n    title: String = stringResource(R.string.video_title_sample_text),\n    author: String = stringResource(R.string.video_creator_sample_text),\n    thumbnailUrl: Any = \"\",\n    showCancelButton: Boolean = false,\n    onCancel: () -> Unit = {},\n    onClick: () -> Unit = {},\n    progress: Float = 90f,\n    fileSizeApprox: Double = 1024 * 1024 * 69.0,\n    duration: Int = 359,\n    isPreview: Boolean = false,\n) {\n    ElevatedCard(\n        modifier = modifier.fillMaxWidth(),\n        onClick = onClick,\n        shape = MaterialTheme.shapes.small,\n    ) {\n        Column {\n            Box(Modifier.fillMaxWidth()) {\n                Crossfade(targetState = thumbnailUrl, label = \"\") {\n                    AsyncImageImpl(\n                        modifier =\n                            Modifier.padding()\n                                .fillMaxWidth()\n                                .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true)\n                                .clip(MaterialTheme.shapes.small),\n                        model = it,\n                        contentDescription = null,\n                        contentScale = ContentScale.Crop,\n                        isPreview = isPreview,\n                    )\n                }\n\n                Surface(\n                    modifier = Modifier.padding(4.dp).align(Alignment.BottomEnd),\n                    color = Color.Black.copy(alpha = 0.68f),\n                    shape = MaterialTheme.shapes.extraSmall,\n                ) {\n                    val fileSizeText = fileSizeApprox.toFileSizeText()\n                    val durationText = duration.toDurationText()\n                    Text(\n                        modifier = Modifier.padding(horizontal = 4.dp),\n                        text = \"$fileSizeText · $durationText\",\n                        style = MaterialTheme.typography.labelSmall,\n                        color = Color.White,\n                    )\n                }\n\n                Column(modifier = Modifier.align(Alignment.Center)) {\n                    AnimatedVisibility(\n                        visible = showCancelButton,\n                        enter = fadeIn(),\n                        exit = fadeOut(),\n                    ) {\n                        FilledTonalIconButton(\n                            onClick = onCancel,\n                            modifier = Modifier.size(56.dp),\n                            colors =\n                                IconButtonDefaults.filledTonalIconButtonColors(\n                                    containerColor =\n                                        MaterialTheme.colorScheme.surfaceContainerHighest.copy(\n                                            alpha = 0.68f\n                                        )\n                                ),\n                        ) {\n                            Icon(\n                                imageVector = Icons.Outlined.Cancel,\n                                contentDescription = stringResource(id = R.string.cancel),\n                                modifier = Modifier.size(32.dp),\n                            )\n                        }\n                    }\n                }\n            }\n\n            Column(\n                modifier = Modifier.fillMaxWidth().padding(12.dp),\n                horizontalAlignment = Alignment.Start,\n            ) {\n                Text(\n                    text = title,\n                    style = MaterialTheme.typography.titleMedium,\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                )\n                Text(\n                    modifier = Modifier.padding(top = 3.dp),\n                    text = author,\n                    style = MaterialTheme.typography.bodyMedium,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                )\n            }\n            val progressAnimationValue by\n                animateFloatAsState(\n                    targetValue = progress,\n                    animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,\n                    label = \"\",\n                )\n            if (progress < 0f) LinearProgressIndicator(modifier = Modifier.fillMaxWidth())\n            else\n                LinearProgressIndicator(\n                    progress = { progressAnimationValue / 100f },\n                    modifier = Modifier.fillMaxWidth(),\n                    drawStopIndicator = {},\n                )\n        }\n    }\n}\n\n@Composable\n@Preview\n@Preview(name = \"Dark Mode\", uiMode = Configuration.UI_MODE_NIGHT_YES)\nfun VideoCardPreview() {\n    SealTheme() { VideoCard(isPreview = true) }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/component/VideoListItem.kt",
    "content": "package com.junkfood.seal.ui.component\n\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.core.tween\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.combinedClickable\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.AsyncImageImpl\nimport com.junkfood.seal.util.toFileSizeText\n\nprivate const val AUDIO_REGEX = \"\\\\.(mp3|aac|opus|m4a|flac|wav)\"\n\n@Composable\n@Preview\nfun MediaListItemPreview() {\n    MaterialTheme() {\n        Surface() {\n            MediaListItem(\n                title = stringResource(id = R.string.video_title_sample_text),\n                author = stringResource(id = (R.string.video_creator_sample_text)),\n                videoFileSize = 5678 * 1024 * 1024L,\n            )\n        }\n    }\n}\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\nfun MediaListItem(\n    modifier: Modifier = Modifier,\n    title: String = \"\",\n    author: String = \"\",\n    thumbnailUrl: String = \"\",\n    videoPath: String = \"\",\n    videoUrl: String = \"\",\n    videoFileSize: Long = 0L,\n    isSelectEnabled: () -> Boolean = { false },\n    isSelected: () -> Boolean = { false },\n    onSelect: () -> Unit = {},\n    onClick: () -> Unit = {},\n    onLongClick: () -> Unit = {},\n    onShowContextMenu: () -> Unit = {},\n) {\n    val isAudio = videoPath.contains(Regex(AUDIO_REGEX))\n    val haptic = LocalHapticFeedback.current\n    val context = LocalContext.current\n    val isFileAvailable = videoFileSize != 0L\n    val fileSizeText = videoFileSize.toFileSizeText()\n\n    Box(\n        modifier =\n            with(modifier) {\n                    if (!isSelectEnabled())\n                        combinedClickable(\n                            enabled = true,\n                            onClick = { onClick() },\n                            onClickLabel = stringResource(R.string.open_file),\n                            onLongClick = {\n                                onLongClick()\n                                haptic.performHapticFeedback(HapticFeedbackType.LongPress)\n                            },\n                            onLongClickLabel = stringResource(R.string.multiselect_mode),\n                        )\n                    else selectable(selected = isSelected(), onClick = onSelect)\n                }\n                .fillMaxWidth()\n    ) {\n        Row(modifier = Modifier.fillMaxWidth().padding(12.dp)) {\n            AnimatedVisibility(\n                modifier = Modifier.align(Alignment.CenterVertically),\n                visible = isSelectEnabled(),\n            ) {\n                Checkbox(\n                    modifier = Modifier.padding(start = 4.dp, end = 16.dp),\n                    checked = isSelected(),\n                    onCheckedChange = null,\n                )\n            }\n            MediaImage(modifier = Modifier, imageModel = thumbnailUrl, isAudio = isAudio)\n            Column(\n                modifier = Modifier.padding(horizontal = 12.dp).fillMaxWidth(),\n                verticalArrangement = Arrangement.Top,\n            ) {\n                Text(\n                    text = title,\n                    style = MaterialTheme.typography.titleSmall,\n                    color = MaterialTheme.colorScheme.onSurface,\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                )\n                if (author != \"null\")\n                    Text(\n                        modifier = Modifier.padding(top = 3.dp),\n                        text = author,\n                        style = MaterialTheme.typography.bodySmall,\n                        color = MaterialTheme.colorScheme.onSurfaceVariant,\n                        maxLines = 1,\n                        overflow = TextOverflow.Ellipsis,\n                    )\n                Text(\n                    modifier = Modifier.padding(top = 3.dp),\n                    text =\n                        if (isFileAvailable) fileSizeText else stringResource(R.string.unavailable),\n                    style = MaterialTheme.typography.labelSmall,\n                    color =\n                        with(MaterialTheme.colorScheme) {\n                            if (isFileAvailable) onSurfaceVariant else error\n                        },\n                    maxLines = 1,\n                )\n            }\n        }\n        AnimatedVisibility(\n            modifier = Modifier.align(Alignment.BottomEnd),\n            visible = !isSelectEnabled(),\n            enter = fadeIn(tween(100)),\n            exit = fadeOut(tween(100)),\n        ) {\n            IconButton(modifier = Modifier.clearAndSetSemantics {}, onClick = onShowContextMenu) {\n                Icon(\n                    modifier = Modifier.size(18.dp),\n                    imageVector = Icons.Outlined.MoreVert,\n                    contentDescription = stringResource(id = R.string.show_more_actions),\n                )\n            }\n        }\n    }\n}\n\n@Composable\nfun MediaImage(\n    modifier: Modifier = Modifier,\n    imageModel: String,\n    isAudio: Boolean = false,\n    contentDescription: String? = null,\n) {\n    AsyncImageImpl(\n        modifier =\n            modifier\n                .height(90.dp)\n                .aspectRatio(if (!isAudio) 16f / 9f else 1f, matchHeightConstraintsFirst = true)\n                .clip(MaterialTheme.shapes.extraSmall),\n        model = imageModel,\n        contentDescription = contentDescription,\n        contentScale = ContentScale.Crop,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/AppEntry.kt",
    "content": "package com.junkfood.seal.ui.page\n\nimport android.webkit.CookieManager\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material3.DrawerValue\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.rememberDrawerState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.Lifecycle\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport androidx.navigation.NavGraphBuilder\nimport androidx.navigation.NavType\nimport androidx.navigation.compose.NavHost\nimport androidx.navigation.compose.currentBackStackEntryAsState\nimport androidx.navigation.compose.rememberNavController\nimport androidx.navigation.navArgument\nimport androidx.navigation.navigation\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.LocalWindowWidthState\nimport com.junkfood.seal.ui.common.Route\nimport com.junkfood.seal.ui.common.animatedComposable\nimport com.junkfood.seal.ui.common.animatedComposableVariant\nimport com.junkfood.seal.ui.common.arg\nimport com.junkfood.seal.ui.common.id\nimport com.junkfood.seal.ui.common.slideInVerticallyComposable\nimport com.junkfood.seal.ui.page.command.TaskListPage\nimport com.junkfood.seal.ui.page.command.TaskLogPage\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel\nimport com.junkfood.seal.ui.page.downloadv2.DownloadPageV2\nimport com.junkfood.seal.ui.page.settings.SettingsPage\nimport com.junkfood.seal.ui.page.settings.about.AboutPage\nimport com.junkfood.seal.ui.page.settings.about.CreditsPage\nimport com.junkfood.seal.ui.page.settings.about.SponsorsPage\nimport com.junkfood.seal.ui.page.settings.about.UpdatePage\nimport com.junkfood.seal.ui.page.settings.appearance.AppearancePreferences\nimport com.junkfood.seal.ui.page.settings.appearance.DarkThemePreferences\nimport com.junkfood.seal.ui.page.settings.appearance.LanguagePage\nimport com.junkfood.seal.ui.page.settings.command.TemplateEditPage\nimport com.junkfood.seal.ui.page.settings.command.TemplateListPage\nimport com.junkfood.seal.ui.page.settings.directory.DownloadDirectoryPreferences\nimport com.junkfood.seal.ui.page.settings.format.DownloadFormatPreferences\nimport com.junkfood.seal.ui.page.settings.format.SubtitlePreference\nimport com.junkfood.seal.ui.page.settings.general.GeneralDownloadPreferences\nimport com.junkfood.seal.ui.page.settings.interaction.InteractionPreferencePage\nimport com.junkfood.seal.ui.page.settings.network.CookieProfilePage\nimport com.junkfood.seal.ui.page.settings.network.CookiesViewModel\nimport com.junkfood.seal.ui.page.settings.network.NetworkPreferences\nimport com.junkfood.seal.ui.page.settings.network.WebViewPage\nimport com.junkfood.seal.ui.page.settings.troubleshooting.TroubleShootingPage\nimport com.junkfood.seal.ui.page.videolist.VideoListPage\nimport kotlinx.coroutines.launch\nimport org.koin.androidx.compose.koinViewModel\n\nprivate const val TAG = \"HomeEntry\"\n\nprivate val TopDestinations =\n    listOf(Route.HOME, Route.TASK_LIST, Route.SETTINGS_PAGE, Route.DOWNLOADS)\n\n@Composable\nfun AppEntry(dialogViewModel: DownloadDialogViewModel) {\n\n    val navController = rememberNavController()\n    val context = LocalContext.current\n    val view = LocalView.current\n    val windowWidth = LocalWindowWidthState.current\n    val sheetState by dialogViewModel.sheetStateFlow.collectAsStateWithLifecycle()\n    val cookiesViewModel: CookiesViewModel = koinViewModel()\n\n    val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)\n    val versionReport = App.packageInfo.versionName.toString()\n    val appName = stringResource(R.string.app_name)\n    val scope = rememberCoroutineScope()\n\n    val onNavigateBack: () -> Unit = {\n        with(navController) {\n            if (currentBackStackEntry?.lifecycle?.currentState == Lifecycle.State.RESUMED) {\n                popBackStack()\n            }\n        }\n    }\n\n    if (sheetState is DownloadDialogViewModel.SheetState.Configure) {\n        if (navController.currentDestination?.route != Route.HOME) {\n            navController.popBackStack(route = Route.HOME, inclusive = false, saveState = true)\n        }\n    }\n\n    val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route\n    var currentTopDestination by rememberSaveable { mutableStateOf(currentRoute) }\n\n    LaunchedEffect(currentRoute) {\n        if (currentRoute in TopDestinations) {\n            currentTopDestination = currentRoute\n        }\n    }\n\n    Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {\n        NavigationDrawer(\n            windowWidth = windowWidth,\n            drawerState = drawerState,\n            currentRoute = currentRoute,\n            currentTopDestination = currentTopDestination,\n            showQuickSettings = true,\n            gesturesEnabled = currentRoute == Route.HOME,\n            onDismissRequest = { drawerState.close() },\n            onNavigateToRoute = {\n                if (currentRoute != it) {\n                    navController.navigate(it) {\n                        launchSingleTop = true\n                        popUpTo(route = Route.HOME)\n                    }\n                }\n            },\n            footer = {\n                Text(\n                    appName + \"\\n\" + versionReport + \"\\n\" + currentRoute,\n                    style = MaterialTheme.typography.bodySmall,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    modifier = Modifier.padding(start = 12.dp),\n                )\n            },\n        ) {\n            NavHost(\n                modifier = Modifier.align(Alignment.Center),\n                navController = navController,\n                startDestination = Route.HOME,\n            ) {\n                animatedComposable(Route.HOME) {\n                    DownloadPageV2(\n                        dialogViewModel = dialogViewModel,\n                        onMenuOpen = {\n                            view.slightHapticFeedback()\n                            scope.launch { drawerState.open() }\n                        },\n                    )\n                }\n                animatedComposable(Route.DOWNLOADS) { VideoListPage { onNavigateBack() } }\n                animatedComposableVariant(Route.TASK_LIST) {\n                    TaskListPage(\n                        onNavigateBack = onNavigateBack,\n                        onNavigateToDetail = { navController.navigate(Route.TASK_LOG id it) },\n                    )\n                }\n                slideInVerticallyComposable(\n                    Route.TASK_LOG arg Route.TASK_HASHCODE,\n                    arguments = listOf(navArgument(Route.TASK_HASHCODE) { type = NavType.IntType }),\n                ) {\n                    TaskLogPage(\n                        onNavigateBack = onNavigateBack,\n                        taskHashCode = it.arguments?.getInt(Route.TASK_HASHCODE) ?: -1,\n                    )\n                }\n\n                settingsGraph(\n                    onNavigateBack = onNavigateBack,\n                    onNavigateTo = { route ->\n                        navController.navigate(route = route) { launchSingleTop = true }\n                    },\n                    cookiesViewModel = cookiesViewModel,\n                )\n            }\n\n            AppUpdater()\n            YtdlpUpdater()\n        }\n    }\n}\n\nfun NavGraphBuilder.settingsGraph(\n    onNavigateBack: () -> Unit,\n    onNavigateTo: (route: String) -> Unit,\n    cookiesViewModel: CookiesViewModel,\n) {\n    navigation(startDestination = Route.SETTINGS_PAGE, route = Route.SETTINGS) {\n        animatedComposable(Route.DOWNLOAD_DIRECTORY) {\n            DownloadDirectoryPreferences(onNavigateBack)\n        }\n        animatedComposable(Route.SETTINGS_PAGE) {\n            SettingsPage(onNavigateBack = onNavigateBack, onNavigateTo = onNavigateTo)\n        }\n        animatedComposable(Route.GENERAL_DOWNLOAD_PREFERENCES) {\n            GeneralDownloadPreferences(onNavigateBack = { onNavigateBack() }) {\n                onNavigateTo(Route.TEMPLATE)\n            }\n        }\n        animatedComposable(Route.DOWNLOAD_FORMAT) {\n            DownloadFormatPreferences(onNavigateBack = onNavigateBack) {\n                onNavigateTo(Route.SUBTITLE_PREFERENCES)\n            }\n        }\n        animatedComposable(Route.SUBTITLE_PREFERENCES) { SubtitlePreference { onNavigateBack() } }\n        animatedComposable(Route.ABOUT) {\n            AboutPage(\n                onNavigateBack = onNavigateBack,\n                onNavigateToCreditsPage = { onNavigateTo(Route.CREDITS) },\n                onNavigateToUpdatePage = { onNavigateTo(Route.AUTO_UPDATE) },\n                onNavigateToDonatePage = { onNavigateTo(Route.DONATE) },\n            )\n        }\n        animatedComposable(Route.DONATE) { SponsorsPage(onNavigateBack) }\n        animatedComposable(Route.CREDITS) { CreditsPage(onNavigateBack) }\n        animatedComposable(Route.AUTO_UPDATE) { UpdatePage(onNavigateBack) }\n        animatedComposable(Route.APPEARANCE) {\n            AppearancePreferences(onNavigateBack = onNavigateBack, onNavigateTo = onNavigateTo)\n        }\n        animatedComposable(Route.INTERACTION) { InteractionPreferencePage(onBack = onNavigateBack) }\n        animatedComposable(Route.LANGUAGES) { LanguagePage { onNavigateBack() } }\n        animatedComposable(Route.DOWNLOAD_DIRECTORY) {\n            DownloadDirectoryPreferences { onNavigateBack() }\n        }\n        animatedComposable(Route.TEMPLATE) {\n            TemplateListPage(onNavigateBack = onNavigateBack) {\n                onNavigateTo(Route.TEMPLATE_EDIT id it)\n            }\n        }\n        animatedComposable(\n            Route.TEMPLATE_EDIT arg Route.TEMPLATE_ID,\n            arguments = listOf(navArgument(Route.TEMPLATE_ID) { type = NavType.IntType }),\n        ) {\n            TemplateEditPage(onNavigateBack, it.arguments?.getInt(Route.TEMPLATE_ID) ?: -1)\n        }\n        animatedComposable(Route.DARK_THEME) { DarkThemePreferences { onNavigateBack() } }\n        animatedComposable(Route.NETWORK_PREFERENCES) {\n            NetworkPreferences(\n                navigateToCookieProfilePage = { onNavigateTo(Route.COOKIE_PROFILE) }\n            ) {\n                onNavigateBack()\n            }\n        }\n        animatedComposable(Route.COOKIE_PROFILE) {\n            CookieProfilePage(\n                cookiesViewModel = cookiesViewModel,\n                navigateToCookieGeneratorPage = { onNavigateTo(Route.COOKIE_GENERATOR_WEBVIEW) },\n            ) {\n                onNavigateBack()\n            }\n        }\n        animatedComposable(Route.COOKIE_GENERATOR_WEBVIEW) {\n            WebViewPage(cookiesViewModel = cookiesViewModel) {\n                onNavigateBack()\n                CookieManager.getInstance().flush()\n            }\n        }\n        animatedComposable(Route.TROUBLESHOOTING) {\n            TroubleShootingPage(onNavigateTo = onNavigateTo, onBack = onNavigateBack)\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/AppUpdater.kt",
    "content": "package com.junkfood.seal.ui.page\n\nimport android.Manifest\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Build\nimport android.provider.Settings\nimport androidx.activity.compose.rememberLauncherForActivityResult\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.platform.LocalContext\nimport com.junkfood.seal.R\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.UpdateUtil\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n@Composable\nfun AppUpdater() {\n\n    val context = LocalContext.current\n\n    var showUpdateDialog by rememberSaveable { mutableStateOf(false) }\n    var currentDownloadStatus by remember {\n        mutableStateOf(UpdateUtil.DownloadStatus.NotYet as UpdateUtil.DownloadStatus)\n    }\n    val scope = rememberCoroutineScope()\n    var updateJob: Job? = null\n    var release by remember { mutableStateOf(UpdateUtil.Release()) }\n    val settings =\n        rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n            UpdateUtil.installLatestApk()\n        }\n    val launcher =\n        rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { result ->\n            if (result) {\n                UpdateUtil.installLatestApk()\n            } else {\n                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n                    if (!context.packageManager.canRequestPackageInstalls())\n                        settings.launch(\n                            Intent(\n                                Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,\n                                Uri.parse(\"package:${context.packageName}\"),\n                            )\n                        )\n                    else UpdateUtil.installLatestApk()\n                }\n            }\n        }\n\n    LaunchedEffect(Unit) {\n        if (\n            !PreferenceUtil.isNetworkAvailableForDownload() || !PreferenceUtil.isAutoUpdateEnabled()\n        )\n            return@LaunchedEffect\n        withContext(Dispatchers.IO) {\n            runCatching {\n                    UpdateUtil.checkForUpdate()?.let {\n                        release = it\n                        showUpdateDialog = true\n                    }\n                }\n                .onFailure { it.printStackTrace() }\n        }\n    }\n\n    if (showUpdateDialog) {\n        UpdateDialogImpl(\n            onDismissRequest = {\n                showUpdateDialog = false\n                updateJob?.cancel()\n            },\n            title = release.name.toString(),\n            onConfirmUpdate = {\n                updateJob =\n                    scope.launch(Dispatchers.IO) {\n                        runCatching {\n                                UpdateUtil.downloadApk(release = release).collect { downloadStatus\n                                    ->\n                                    currentDownloadStatus = downloadStatus\n                                    if (downloadStatus is UpdateUtil.DownloadStatus.Finished) {\n                                        launcher.launch(\n                                            Manifest.permission.REQUEST_INSTALL_PACKAGES\n                                        )\n                                    }\n                                }\n                            }\n                            .onFailure {\n                                it.printStackTrace()\n                                currentDownloadStatus = UpdateUtil.DownloadStatus.NotYet\n                                ToastUtil.makeToastSuspend(\n                                    context.getString(R.string.app_update_failed)\n                                )\n                                return@launch\n                            }\n                    }\n            },\n            releaseNote = release.body.toString(),\n            downloadStatus = currentDownloadStatus,\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/NavigationDrawer.kt",
    "content": "package com.junkfood.seal.ui.page\n\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxHeight\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.systemBarsPadding\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.foundation.selection.selectableGroup\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.filled.Download\nimport androidx.compose.material.icons.filled.Settings\nimport androidx.compose.material.icons.filled.Subscriptions\nimport androidx.compose.material.icons.filled.Terminal\nimport androidx.compose.material.icons.outlined.Download\nimport androidx.compose.material.icons.outlined.Menu\nimport androidx.compose.material.icons.outlined.Settings\nimport androidx.compose.material.icons.outlined.Subscriptions\nimport androidx.compose.material.icons.outlined.Terminal\nimport androidx.compose.material.icons.outlined.VolunteerActivism\nimport androidx.compose.material.icons.rounded.BugReport\nimport androidx.compose.material.icons.rounded.Cookie\nimport androidx.compose.material.icons.rounded.Folder\nimport androidx.compose.material.icons.rounded.Info\nimport androidx.compose.material.icons.rounded.SettingsApplications\nimport androidx.compose.material3.DrawerState\nimport androidx.compose.material3.DrawerValue\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LocalContentColor\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ModalDrawerSheet\nimport androidx.compose.material3.ModalNavigationDrawer\nimport androidx.compose.material3.NavigationDrawerItem\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.rememberDrawerState\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.mutableStateMapOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.platform.LocalConfiguration\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.zIndex\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.LocalWindowWidthState\nimport com.junkfood.seal.ui.common.Route\nimport com.junkfood.seal.ui.page.downloadv2.DownloadPageImplV2\nimport kotlinx.coroutines.launch\n\n@Composable\nfun NavigationDrawer(\n    modifier: Modifier = Modifier,\n    drawerState: DrawerState,\n    windowWidth: WindowWidthSizeClass = LocalWindowWidthState.current,\n    currentRoute: String? = null,\n    currentTopDestination: String? = null,\n    showQuickSettings: Boolean = true,\n    onNavigateToRoute: (String) -> Unit,\n    onDismissRequest: suspend () -> Unit,\n    gesturesEnabled: Boolean = true,\n    footer: @Composable (() -> Unit)? = null,\n    content: @Composable () -> Unit,\n) {\n    val scope = rememberCoroutineScope()\n\n    when (windowWidth) {\n        WindowWidthSizeClass.Compact,\n        WindowWidthSizeClass.Medium -> {\n            ModalNavigationDrawer(\n                gesturesEnabled = gesturesEnabled,\n                drawerState = drawerState,\n                drawerContent = {\n                    ModalDrawerSheet(drawerState = drawerState, modifier = modifier.width(360.dp)) {\n                        NavigationDrawerSheetContent(\n                            modifier = Modifier,\n                            currentRoute = currentRoute,\n                            showQuickSettings = showQuickSettings,\n                            onNavigateToRoute = onNavigateToRoute,\n                            onDismissRequest = onDismissRequest,\n                            footer = footer,\n                        )\n                    }\n                },\n                content = content,\n            )\n        }\n        WindowWidthSizeClass.Expanded -> {\n            ModalNavigationDrawer(\n                gesturesEnabled = drawerState.isOpen,\n                drawerState = drawerState,\n                drawerContent = {\n                    ModalDrawerSheet(drawerState = drawerState, modifier = modifier.width(360.dp)) {\n                        NavigationDrawerSheetContent(\n                            modifier = Modifier,\n                            currentRoute = currentRoute,\n                            showQuickSettings = showQuickSettings,\n                            onNavigateToRoute = onNavigateToRoute,\n                            onDismissRequest = onDismissRequest,\n                            footer = footer,\n                        )\n                    }\n                },\n            ) {\n                Row {\n                    Surface(\n                        color = MaterialTheme.colorScheme.surfaceContainer,\n                        modifier = Modifier.zIndex(1f),\n                    ) {\n                        Column(\n                            verticalArrangement = Arrangement.Center,\n                            modifier = Modifier.fillMaxHeight().systemBarsPadding().width(92.dp),\n                            horizontalAlignment = Alignment.CenterHorizontally,\n                        ) {\n                            Spacer(Modifier.height(8.dp))\n                            IconButton(\n                                onClick = { scope.launch { drawerState.open() } },\n                                modifier = Modifier.align(Alignment.CenterHorizontally),\n                            ) {\n                                Icon(Icons.Outlined.Menu, null)\n                            }\n                            Spacer(Modifier.weight(1f))\n                            NavigationRailContent(\n                                modifier = Modifier,\n                                currentTopDestination = currentTopDestination,\n                                onNavigateToRoute = onNavigateToRoute,\n                            )\n                            Spacer(Modifier.weight(1f))\n                        }\n                    }\n                    content()\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun NavigationDrawerSheetContent(\n    modifier: Modifier = Modifier,\n    currentRoute: String? = null,\n    showQuickSettings: Boolean = true,\n    onNavigateToRoute: (String) -> Unit,\n    onDismissRequest: suspend () -> Unit,\n    footer: @Composable (() -> Unit)? = null,\n) {\n    val scope = rememberCoroutineScope()\n    Column(\n        modifier =\n            modifier\n                .padding(horizontal = 12.dp)\n                .fillMaxHeight()\n                .verticalScroll(rememberScrollState())\n                .systemBarsPadding()\n    ) {\n        Spacer(Modifier.height(72.dp))\n        ProvideTextStyle(MaterialTheme.typography.labelLarge) {\n            NavigationDrawerItem(\n                label = { Text(stringResource(R.string.download_queue)) },\n                icon = { Icon(Icons.Filled.Download, null) },\n                onClick = {\n                    scope\n                        .launch { onDismissRequest() }\n                        .invokeOnCompletion { onNavigateToRoute(Route.HOME) }\n                },\n                selected = currentRoute == Route.HOME,\n            )\n            NavigationDrawerItem(\n                label = { Text(stringResource(R.string.downloads_history)) },\n                icon = { Icon(Icons.Outlined.Subscriptions, null) },\n                onClick = {\n                    scope\n                        .launch { onDismissRequest() }\n                        .invokeOnCompletion { onNavigateToRoute(Route.DOWNLOADS) }\n                },\n                selected = currentRoute == Route.DOWNLOADS,\n            )\n            NavigationDrawerItem(\n                label = { Text(stringResource(R.string.custom_command)) },\n                icon = { Icon(Icons.Outlined.Terminal, null) },\n                onClick = {\n                    scope\n                        .launch { onDismissRequest() }\n                        .invokeOnCompletion { onNavigateToRoute(Route.TASK_LIST) }\n                },\n                selected = currentRoute == Route.TASK_LIST,\n            )\n            NavigationDrawerItem(\n                label = { Text(stringResource(R.string.settings)) },\n                icon = { Icon(Icons.Outlined.Settings, null) },\n                onClick = {\n                    scope\n                        .launch { onDismissRequest() }\n                        .invokeOnCompletion { onNavigateToRoute(Route.SETTINGS) }\n                },\n                selected = currentRoute == Route.SETTINGS_PAGE,\n            )\n\n            NavigationDrawerItem(\n                label = { Text(stringResource(R.string.sponsor)) },\n                icon = { Icon(Icons.Outlined.VolunteerActivism, null) },\n                onClick = {\n                    scope\n                        .launch { onDismissRequest() }\n                        .invokeOnCompletion { onNavigateToRoute(Route.DONATE) }\n                },\n                selected = currentRoute == Route.DONATE,\n            )\n\n            if (showQuickSettings) {\n                HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))\n\n                Column(\n                    modifier = Modifier.padding(start = 16.dp).padding(top = 16.dp, bottom = 12.dp),\n                    verticalArrangement = Arrangement.Center,\n                ) {\n                    Text(\n                        stringResource(R.string.settings),\n                        style = MaterialTheme.typography.labelLarge,\n                        color = MaterialTheme.colorScheme.tertiary,\n                        modifier = Modifier,\n                    )\n                }\n\n                NavigationDrawerItem(\n                    label = { Text(stringResource(R.string.general_settings)) },\n                    icon = { Icon(Icons.Rounded.SettingsApplications, null) },\n                    onClick = {\n                        scope\n                            .launch { onDismissRequest() }\n                            .invokeOnCompletion {\n                                onNavigateToRoute(Route.GENERAL_DOWNLOAD_PREFERENCES)\n                            }\n                    },\n                    selected = currentRoute == Route.GENERAL_DOWNLOAD_PREFERENCES,\n                )\n\n                NavigationDrawerItem(\n                    label = { Text(stringResource(R.string.download_directory)) },\n                    icon = { Icon(Icons.Rounded.Folder, null) },\n                    onClick = {\n                        scope\n                            .launch { onDismissRequest() }\n                            .invokeOnCompletion { onNavigateToRoute(Route.DOWNLOAD_DIRECTORY) }\n                    },\n                    selected = currentRoute == Route.DOWNLOAD_DIRECTORY,\n                )\n\n                NavigationDrawerItem(\n                    label = { Text(stringResource(R.string.cookies)) },\n                    icon = { Icon(Icons.Rounded.Cookie, null) },\n                    onClick = {\n                        scope\n                            .launch { onDismissRequest() }\n                            .invokeOnCompletion { onNavigateToRoute(Route.COOKIE_PROFILE) }\n                    },\n                    selected = currentRoute == Route.COOKIE_PROFILE,\n                )\n\n                NavigationDrawerItem(\n                    label = { Text(stringResource(R.string.trouble_shooting)) },\n                    icon = { Icon(Icons.Rounded.BugReport, null) },\n                    onClick = {\n                        scope\n                            .launch { onDismissRequest() }\n                            .invokeOnCompletion { onNavigateToRoute(Route.TROUBLESHOOTING) }\n                    },\n                    selected = currentRoute == Route.TROUBLESHOOTING,\n                )\n\n                NavigationDrawerItem(\n                    label = { Text(stringResource(R.string.about)) },\n                    icon = { Icon(Icons.Rounded.Info, null) },\n                    onClick = {\n                        scope\n                            .launch { onDismissRequest() }\n                            .invokeOnCompletion { onNavigateToRoute(Route.ABOUT) }\n                    },\n                    selected = currentRoute == Route.ABOUT,\n                )\n            }\n        }\n        Spacer(Modifier.weight(1f))\n        footer?.invoke()\n    }\n}\n\n@Composable\nfun NavigationRailItemVariant(\n    modifier: Modifier = Modifier,\n    icon: @Composable (() -> Unit),\n    selected: Boolean,\n    onClick: () -> Unit,\n) {\n    Box(\n        modifier =\n            modifier\n                .size(56.dp)\n                .clip(MaterialTheme.shapes.large)\n                .background(\n                    if (selected) MaterialTheme.colorScheme.secondaryContainer\n                    else Color.Transparent\n                )\n                .selectable(selected = selected, onClick = onClick),\n        contentAlignment = Alignment.Center,\n    ) {\n        CompositionLocalProvider(\n            LocalContentColor provides\n                if (selected) MaterialTheme.colorScheme.onSecondaryContainer\n                else MaterialTheme.colorScheme.onSurfaceVariant\n        ) {\n            icon()\n        }\n    }\n}\n\n@Composable\nfun NavigationRailContent(\n    modifier: Modifier = Modifier,\n    currentTopDestination: String? = null,\n    onNavigateToRoute: (String) -> Unit,\n) {\n    Column(\n        modifier = modifier.selectableGroup(),\n        horizontalAlignment = Alignment.CenterHorizontally,\n        verticalArrangement = Arrangement.spacedBy(4.dp),\n    ) {\n        val scope = rememberCoroutineScope()\n        NavigationRailItemVariant(\n            icon = {\n                Icon(\n                    if (currentTopDestination == Route.HOME) Icons.Filled.Download\n                    else Icons.Outlined.Download,\n                    stringResource(R.string.download_queue),\n                )\n            },\n            modifier = Modifier,\n            selected = currentTopDestination == Route.HOME,\n            onClick = { onNavigateToRoute(Route.HOME) },\n        )\n\n        NavigationRailItemVariant(\n            icon = {\n                Icon(\n                    if (currentTopDestination == Route.DOWNLOADS) Icons.Filled.Subscriptions\n                    else Icons.Outlined.Subscriptions,\n                    stringResource(R.string.downloads_history),\n                )\n            },\n            modifier = Modifier,\n            selected = currentTopDestination == Route.DOWNLOADS,\n            onClick = { onNavigateToRoute(Route.DOWNLOADS) },\n        )\n\n        NavigationRailItemVariant(\n            icon = {\n                Icon(\n                    if (currentTopDestination == Route.TASK_LIST) Icons.Filled.Terminal\n                    else Icons.Outlined.Terminal,\n                    stringResource(R.string.custom_command),\n                )\n            },\n            modifier = Modifier,\n            selected = currentTopDestination == Route.TASK_LIST,\n            onClick = { onNavigateToRoute(Route.TASK_LIST) },\n        )\n\n        NavigationRailItemVariant(\n            icon = {\n                Icon(\n                    if (currentTopDestination == Route.SETTINGS_PAGE) Icons.Filled.Settings\n                    else Icons.Outlined.Settings,\n                    stringResource(R.string.settings),\n                )\n            },\n            modifier = Modifier,\n            selected = currentTopDestination == Route.SETTINGS_PAGE,\n            onClick = { onNavigateToRoute(Route.SETTINGS_PAGE) },\n        )\n    }\n}\n\n@Preview(device = \"spec:width=673dp,height=841dp\")\n@Preview(device = \"spec:width=1280dp,height=800dp,dpi=240\")\n@Composable\nprivate fun ExpandedPreview() {\n    val widthDp = LocalConfiguration.current.screenWidthDp\n    var currentRoute = remember { mutableStateOf(Route.HOME) }\n\n    CompositionLocalProvider(\n        LocalWindowWidthState provides\n            if (widthDp > 480) WindowWidthSizeClass.Expanded\n            else if (widthDp > 360) WindowWidthSizeClass.Medium else WindowWidthSizeClass.Compact\n    ) {\n        Row {\n            val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)\n            NavigationDrawer(\n                currentRoute = currentRoute.value,\n                currentTopDestination = currentRoute.value,\n                drawerState = drawerState,\n                onNavigateToRoute = { currentRoute.value = it },\n                onDismissRequest = {},\n            ) {\n                DownloadPageImplV2(taskDownloadStateMap = remember { mutableStateMapOf() }) { _, _\n                    ->\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/UpdateDialog.kt",
    "content": "package com.junkfood.seal.ui.page\n\nimport android.os.Build\nimport androidx.compose.animation.animateContentSize\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.NewReleases\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.R\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.UpdateUtil\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\n\n@Composable\nfun UpdateDialog(onDismissRequest: () -> Unit, release: UpdateUtil.Release) {\n    var currentDownloadStatus by remember {\n        mutableStateOf(UpdateUtil.DownloadStatus.NotYet as UpdateUtil.DownloadStatus)\n    }\n    val context = LocalContext.current\n\n    val scope = rememberCoroutineScope()\n    UpdateDialogImpl(\n        onDismissRequest = onDismissRequest,\n        title = release.name.toString(),\n        onConfirmUpdate = {\n            scope.launch(Dispatchers.IO) {\n                runCatching {\n                        UpdateUtil.downloadApk(release = release).collect { downloadStatus ->\n                            currentDownloadStatus = downloadStatus\n                            if (downloadStatus is UpdateUtil.DownloadStatus.Finished) {\n                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                                    UpdateUtil.installLatestApk()\n                                }\n                            }\n                        }\n                    }\n                    .onFailure {\n                        it.printStackTrace()\n                        currentDownloadStatus = UpdateUtil.DownloadStatus.NotYet\n                        ToastUtil.makeToastSuspend(context.getString(R.string.app_update_failed))\n                        return@launch\n                    }\n            }\n        },\n        releaseNote = release.body.toString(),\n        downloadStatus = currentDownloadStatus,\n    )\n}\n\n@Composable\nfun UpdateDialogImpl(\n    onDismissRequest: () -> Unit,\n    title: String,\n    onConfirmUpdate: () -> Unit,\n    releaseNote: String,\n    downloadStatus: UpdateUtil.DownloadStatus,\n) {\n    AlertDialog(\n        onDismissRequest = {},\n        title = { Text(title) },\n        icon = { Icon(Icons.Outlined.NewReleases, null) },\n        confirmButton = {\n            Button(\n                onClick = {\n                    if (downloadStatus !is UpdateUtil.DownloadStatus.Progress) onConfirmUpdate()\n                }\n            ) {\n                Text(\n                    when (downloadStatus) {\n                        is UpdateUtil.DownloadStatus.Progress -> \"${downloadStatus.percent} %\"\n                        else -> stringResource(R.string.update)\n                    },\n                    modifier = Modifier.animateContentSize(),\n                )\n            }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) {\n                Text(text = stringResource(id = R.string.dismiss))\n            }\n        },\n        text = { Column(Modifier.verticalScroll(rememberScrollState())) { Text(releaseNote) } },\n    )\n}\n\n@Preview\n@Composable\nprivate fun Preview() {\n    var b by remember { mutableStateOf(false) }\n    val flow: MutableStateFlow<UpdateUtil.DownloadStatus> = remember {\n        MutableStateFlow(UpdateUtil.DownloadStatus.NotYet)\n    }\n\n    LaunchedEffect(b) {\n        if (b) {\n            repeat(100) { i ->\n                flow.update { UpdateUtil.DownloadStatus.Progress(percent = i) }\n                delay(50)\n            }\n        } else {\n            flow.update { UpdateUtil.DownloadStatus.NotYet }\n        }\n    }\n\n    val status by flow.collectAsStateWithLifecycle()\n\n    UpdateDialogImpl(\n        onDismissRequest = { b = false },\n        title = \"v1.12.0\",\n        onConfirmUpdate = { b = true },\n        releaseNote = \"ReleaseNoteHTML\",\n        downloadStatus = status,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/WelcomeDialog.kt",
    "content": "package com.junkfood.seal.ui.page\n\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.ContentPaste\nimport androidx.compose.material.icons.outlined.Downloading\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.SettingsSuggest\nimport androidx.compose.material.icons.outlined.Subscriptions\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.CheckBoxItem\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.junkfood.seal.util.WELCOME_DIALOG\n\n@Composable\nfun WelcomeDialog(onClick: () -> Unit) {\n    var showWelcomeDialog by rememberSaveable { mutableIntStateOf(WELCOME_DIALOG.getInt()) }\n    var disableDialog by remember { mutableStateOf(false) }\n    val onDismissRequest = {\n        PreferenceUtil.encodeInt(WELCOME_DIALOG, if (disableDialog) 0 else showWelcomeDialog + 1)\n        showWelcomeDialog = 0\n    }\n    if (showWelcomeDialog > 0)\n        AlertDialog(\n            onDismissRequest = onDismissRequest,\n            dismissButton = {\n                TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.close)) }\n            },\n            confirmButton = {\n                TextButton(\n                    onClick = {\n                        onClick()\n                        onDismissRequest()\n                    }\n                ) {\n                    Text(stringResource(R.string.open_settings))\n                }\n            },\n            title = { Text(stringResource(R.string.user_guide)) },\n            text = {\n                Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                    IconDescription(\n                        icon = Icons.Outlined.ContentPaste,\n                        description = stringResource(R.string.paste_desc),\n                    )\n                    IconDescription(\n                        icon = Icons.Outlined.FileDownload,\n                        description = stringResource(R.string.download_desc),\n                    )\n                    IconDescription(\n                        icon = Icons.Outlined.Subscriptions,\n                        description = stringResource(R.string.download_history_desc),\n                    )\n                    IconDescription(\n                        icon = Icons.Outlined.Downloading,\n                        description = stringResource(R.string.battery_settings_desc),\n                    )\n                    IconDescription(\n                        icon = Icons.Outlined.SettingsSuggest,\n                        description = stringResource(R.string.check_download_settings_desc),\n                    )\n                    if ((showWelcomeDialog > 1))\n                        CheckBoxItem(\n                            text = stringResource(id = R.string.close_never_show_again),\n                            checked = disableDialog,\n                            onValueChange = { disableDialog = !disableDialog },\n                        )\n                }\n            },\n        )\n}\n\n@Composable\nfun IconDescription(modifier: Modifier = Modifier, icon: ImageVector, description: String) {\n    Row(\n        modifier = modifier.padding(top = 12.dp, bottom = 9.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        Icon(modifier = Modifier.size(24.dp), imageVector = icon, contentDescription = null)\n        Text(modifier = Modifier.padding(start = 12.dp), text = description)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/YtdlpUpdater.kt",
    "content": "package com.junkfood.seal.ui.page\n\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.Downloader\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getLong\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.UpdateUtil\nimport com.junkfood.seal.util.YT_DLP_AUTO_UPDATE\nimport com.junkfood.seal.util.YT_DLP_UPDATE_INTERVAL\nimport com.junkfood.seal.util.YT_DLP_UPDATE_TIME\nimport com.junkfood.seal.util.YT_DLP_VERSION\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.withContext\n\n@Composable\nfun YtdlpUpdater() {\n\n    val downloaderState by Downloader.downloaderState.collectAsStateWithLifecycle()\n\n    LaunchedEffect(Unit) {\n        if (downloaderState !is Downloader.State.Idle) return@LaunchedEffect\n\n        if (!YT_DLP_AUTO_UPDATE.getBoolean() && YT_DLP_VERSION.getString().isNotEmpty())\n            return@LaunchedEffect\n\n        if (!PreferenceUtil.isNetworkAvailableForDownload()) {\n            return@LaunchedEffect\n        }\n\n        val lastUpdateTime = YT_DLP_UPDATE_TIME.getLong()\n        val currentTime = System.currentTimeMillis()\n\n        if (currentTime < lastUpdateTime + YT_DLP_UPDATE_INTERVAL.getLong()) {\n            return@LaunchedEffect\n        }\n\n        runCatching {\n                Downloader.updateState(state = Downloader.State.Updating)\n                withContext(Dispatchers.IO) { UpdateUtil.updateYtDlp() }\n            }\n            .onFailure { it.printStackTrace() }\n        Downloader.updateState(state = Downloader.State.Idle)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/command/TaskListPage.kt",
    "content": "package com.junkfood.seal.ui.page.command\n\nimport androidx.activity.compose.BackHandler\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ColumnScope\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.heightIn\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.foundation.lazy.rememberLazyListState\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Add\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.Code\nimport androidx.compose.material.icons.outlined.DownloadDone\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.NewLabel\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FloatingActionButton\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.Downloader\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ClearButton\nimport com.junkfood.seal.ui.component.CustomCommandTaskItem\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.FilledButtonWithIcon\nimport com.junkfood.seal.ui.component.OutlinedButtonChip\nimport com.junkfood.seal.ui.component.OutlinedButtonWithIcon\nimport com.junkfood.seal.ui.component.PasteFromClipBoardButton\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SealModalBottomSheetM2\nimport com.junkfood.seal.ui.component.TaskStatus\nimport com.junkfood.seal.ui.page.settings.command.CommandTemplateDialog\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.TEMPLATE_ID\nimport com.junkfood.seal.util.matchUrlFromString\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)\n@Composable\nfun TaskListPage(onNavigateBack: () -> Unit, onNavigateToDetail: (Int) -> Unit) {\n    val scope = rememberCoroutineScope()\n    val view = LocalView.current\n\n    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()\n    var showBottomSheet by remember { mutableStateOf(false) }\n    val sheetState =\n        androidx.compose.material.rememberModalBottomSheetState(\n            skipHalfExpanded = true,\n            initialValue = ModalBottomSheetValue.Hidden,\n        )\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            TopAppBar(\n                title = {\n                    Text(\n                        text = stringResource(R.string.running_tasks),\n                        style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),\n                    )\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                actions = {},\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        floatingActionButton = {\n            FloatingActionButton(\n                onClick = {\n                    scope.launch {\n                        showBottomSheet = true\n                        delay(50)\n                        sheetState.show()\n                    }\n                },\n                modifier = Modifier.padding(vertical = 18.dp, horizontal = 6.dp),\n            ) {\n                Icon(Icons.Outlined.Add, stringResource(id = R.string.new_task))\n            }\n        },\n    ) { paddings ->\n        val clipboardManager = LocalClipboardManager.current\n        LazyColumn(\n            modifier = Modifier.padding(paddings),\n            contentPadding = PaddingValues(24.dp),\n            verticalArrangement = Arrangement.spacedBy(12.dp),\n        ) {\n            items(\n                Downloader.mutableTaskList.values.toList().sortedBy { it.state.toStatus() },\n                key = { it.toKey() },\n            ) {\n                it.run {\n                    CustomCommandTaskItem(\n                        status = state.toStatus(),\n                        progress =\n                            if (state is Downloader.CustomCommandTask.State.Running)\n                                state.progress / 100f\n                            else 0f,\n                        progressText = currentLine,\n                        url = url,\n                        templateName = template.name,\n                        onCancel = { onCancel() },\n                        onCopyError = { onCopyError(clipboardManager) },\n                        onRestart = { onRestart() },\n                        onCopyLog = { onCopyLog(clipboardManager) },\n                        onShowLog = { onNavigateToDetail(hashCode()) },\n                        modifier = Modifier.animateItem(),\n                    )\n                }\n            }\n        }\n    }\n    val onDismissRequest: () -> Unit = {\n        scope.launch { sheetState.hide() }.invokeOnCompletion { showBottomSheet = false }\n    }\n\n    BackHandler(showBottomSheet) { onDismissRequest() }\n\n    if (showBottomSheet)\n        SealModalBottomSheetM2(\n            sheetState = sheetState,\n            sheetContent = {\n                val clipboardManager = LocalClipboardManager.current\n\n                var showTemplateSelectionDialog by remember { mutableStateOf(false) }\n                var showTemplateCreatorDialog by remember { mutableStateOf(false) }\n                var showTemplateEditorDialog by remember { mutableStateOf(false) }\n\n                val template by\n                    remember(\n                        showTemplateCreatorDialog,\n                        showTemplateSelectionDialog,\n                        showTemplateEditorDialog,\n                    ) {\n                        mutableStateOf(PreferenceUtil.getTemplate())\n                    }\n\n                var url by remember { mutableStateOf(\"\") }\n\n                LaunchedEffect(sheetState.targetValue) {\n                    if (sheetState.targetValue == ModalBottomSheetValue.Expanded)\n                        url = matchUrlFromString(clipboardManager.getText()?.text.toString(), true)\n                }\n\n                Column(Modifier.fillMaxWidth()) {\n                    TaskCreatorDialogContent(\n                        url = url,\n                        onValueChange = { url = it },\n                        template = template,\n                        onTemplateSelectionClicked = { showTemplateSelectionDialog = true },\n                        onNewTemplateClicked = { showTemplateCreatorDialog = true },\n                        onEditClicked = { showTemplateEditorDialog = true },\n                    )\n                    LazyRow(\n                        modifier = Modifier.fillMaxWidth().padding(top = 24.dp),\n                        horizontalArrangement = Arrangement.End,\n                    ) {\n                        item {\n                            OutlinedButtonWithIcon(\n                                modifier = Modifier.padding(horizontal = 12.dp),\n                                onClick = onDismissRequest,\n                                icon = Icons.Outlined.Cancel,\n                                text = stringResource(R.string.cancel),\n                            )\n                        }\n                        item {\n                            FilledButtonWithIcon(\n                                onClick = {\n                                    view.slightHapticFeedback()\n                                    Downloader.executeCommandWithUrl(url)\n                                    onDismissRequest()\n                                },\n                                icon = Icons.Outlined.DownloadDone,\n                                text = stringResource(R.string.start),\n                            )\n                        }\n                    }\n                }\n                if (showTemplateSelectionDialog) {\n                    TemplatePickerDialog() { showTemplateSelectionDialog = false }\n                }\n                if (showTemplateCreatorDialog) {\n                    CommandTemplateDialog(\n                        onDismissRequest = { showTemplateCreatorDialog = false },\n                        confirmationCallback = { scope.launch { TEMPLATE_ID.updateInt(it) } },\n                    )\n                }\n                if (showTemplateEditorDialog) {\n                    CommandTemplateDialog(\n                        commandTemplate = template,\n                        onDismissRequest = { showTemplateEditorDialog = false },\n                    )\n                }\n            },\n        )\n}\n\nprivate fun Downloader.CustomCommandTask.State.toStatus(): TaskStatus =\n    when (this) {\n        Downloader.CustomCommandTask.State.Canceled -> TaskStatus.CANCELED\n        Downloader.CustomCommandTask.State.Completed -> TaskStatus.FINISHED\n        is Downloader.CustomCommandTask.State.Error -> TaskStatus.ERROR\n        is Downloader.CustomCommandTask.State.Running -> TaskStatus.RUNNING\n    }\n\n@Composable\nfun ColumnScope.TaskCreatorDialogContent(\n    url: String,\n    onValueChange: (String) -> Unit = {},\n    template: CommandTemplate,\n    onTemplateSelectionClicked: () -> Unit = {},\n    onNewTemplateClicked: () -> Unit = {},\n    onEditClicked: () -> Unit = {},\n) {\n    Icon(\n        modifier = Modifier.align(Alignment.CenterHorizontally),\n        imageVector = Icons.Outlined.Add,\n        contentDescription = null,\n    )\n    Text(\n        text = stringResource(id = R.string.new_task),\n        style = MaterialTheme.typography.headlineSmall,\n        modifier = Modifier.align(Alignment.CenterHorizontally).padding(vertical = 16.dp),\n        maxLines = 2,\n        overflow = TextOverflow.Ellipsis,\n        textAlign = TextAlign.Center,\n    )\n    Text(\n        text = stringResource(R.string.custom_command_desc),\n        style = MaterialTheme.typography.bodyMedium,\n        color = MaterialTheme.colorScheme.onSurfaceVariant,\n        textAlign = TextAlign.Center,\n        modifier = Modifier.align(Alignment.CenterHorizontally).padding(bottom = 24.dp),\n    )\n\n    OutlinedTextField(\n        value = url,\n        onValueChange = onValueChange,\n        label = { Text(text = stringResource(id = R.string.video_url)) },\n        modifier = Modifier.fillMaxWidth(),\n        minLines = 3,\n        maxLines = 3,\n        trailingIcon = {\n            if (url.isNotEmpty()) {\n                ClearButton { onValueChange(\"\") }\n            } else {\n                PasteFromClipBoardButton(onPaste = onValueChange)\n            }\n        },\n        textStyle = LocalTextStyle.current.merge(fontFamily = FontFamily.Monospace),\n    )\n\n    LazyRow(\n        modifier = Modifier.padding(top = 12.dp),\n        horizontalArrangement = Arrangement.spacedBy(8.dp),\n    ) {\n        item {\n            OutlinedButtonChip(\n                icon = Icons.Outlined.Code,\n                label = template.name,\n                onClick = onTemplateSelectionClicked,\n            )\n        }\n        item {\n            OutlinedButtonChip(\n                icon = Icons.Outlined.Edit,\n                label = stringResource(id = R.string.edit_template, template.name),\n                onClick = onEditClicked,\n            )\n        }\n        item {\n            OutlinedButtonChip(\n                icon = Icons.Outlined.NewLabel,\n                label = stringResource(id = R.string.new_template),\n                onClick = onNewTemplateClicked,\n            )\n        }\n    }\n}\n\n@Composable\nfun TemplatePickerDialog(onDismissRequest: () -> Unit = {}) {\n    val templateList by PreferenceUtil.templateListStateFlow.collectAsStateWithLifecycle()\n    var selectedId by TEMPLATE_ID.intState\n    val scrollState =\n        rememberLazyListState(\n            initialFirstVisibleItemIndex =\n                templateList\n                    .indexOfFirst { it.id == selectedId }\n                    .run { if (this == -1) 0 else this }\n        )\n\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = { DismissButton(onClick = onDismissRequest) },\n        title = { Text(text = stringResource(id = R.string.template_selection)) },\n        icon = { Icon(imageVector = Icons.Outlined.Code, contentDescription = null) },\n        text = {\n            Box(modifier = Modifier.heightIn(max = 450.dp)) {\n                androidx.compose.material3.HorizontalDivider(\n                    modifier = Modifier.align(Alignment.TopCenter)\n                )\n                LazyColumn(state = scrollState) {\n                    item { Spacer(modifier = Modifier.height(4.dp)) }\n                    items(templateList) {\n                        TemplateSingleChoiceItem(\n                            text = it.name,\n                            supportingText = it.template,\n                            selected = it.id == selectedId,\n                        ) {\n                            selectedId = it.id\n                            TEMPLATE_ID.updateInt(it.id)\n                            onDismissRequest()\n                        }\n                    }\n                    item { Spacer(modifier = Modifier.height(4.dp)) }\n                }\n                androidx.compose.material3.HorizontalDivider(\n                    modifier = Modifier.align(Alignment.BottomCenter)\n                )\n            }\n        },\n    )\n}\n\n@Composable\nfun TemplateSingleChoiceItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    supportingText: String,\n    selected: Boolean,\n    onClick: () -> Unit,\n) {\n    Row(\n        modifier =\n            modifier\n                .selectable(selected = selected, enabled = true, onClick = onClick)\n                .fillMaxWidth()\n                .padding(horizontal = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n        horizontalArrangement = Arrangement.Start,\n    ) {\n        RadioButton(\n            modifier = Modifier.padding(end = 8.dp).clearAndSetSemantics {},\n            selected = selected,\n            onClick = onClick,\n        )\n        Column {\n            Text(\n                text = text,\n                style = MaterialTheme.typography.titleMedium,\n                maxLines = 1,\n                overflow = TextOverflow.Ellipsis,\n            )\n            Text(\n                text = supportingText.replace(\"\\n\", \" \"),\n                style = MaterialTheme.typography.bodySmall,\n                maxLines = 1,\n                overflow = TextOverflow.Ellipsis,\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/command/TaskLogPage.kt",
    "content": "package com.junkfood.seal.ui.page.command\n\nimport android.util.Log\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.navigationBarsPadding\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.text.selection.SelectionContainer\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.Close\nimport androidx.compose.material.icons.outlined.ContentCopy\nimport androidx.compose.material.icons.outlined.ErrorOutline\nimport androidx.compose.material.icons.outlined.RestartAlt\nimport androidx.compose.material.icons.outlined.UnfoldMore\nimport androidx.compose.material3.AssistChipDefaults\nimport androidx.compose.material3.Divider\nimport androidx.compose.material3.ElevatedAssistChip\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.rotate\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.Downloader\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ButtonChip\n\nprivate const val TAG = \"TaskLogPage\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun TaskLogPage(onNavigateBack: () -> Unit, taskHashCode: Int) {\n    Log.d(TAG, \"TaskLogPage: $taskHashCode\")\n    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()\n    val task = Downloader.mutableTaskList.values.find { it.hashCode() == taskHashCode } ?: return\n    val clipboardManager = LocalClipboardManager.current\n    var expandLog by remember { mutableStateOf(false) }\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            TopAppBar(\n                title = {\n                    Text(\n                        text = stringResource(R.string.logs),\n                        style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),\n                    )\n                },\n                navigationIcon = {\n                    IconButton(onClick = { onNavigateBack() }) {\n                        Icon(Icons.Outlined.Close, stringResource(R.string.close))\n                    }\n                },\n                actions = {},\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        bottomBar = {\n            Column(\n                modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp).navigationBarsPadding(),\n                verticalArrangement = Arrangement.Center,\n            ) {\n                Divider(modifier = Modifier.fillMaxWidth())\n                Row(\n                    Modifier.fillMaxWidth()\n                        .horizontalScroll(rememberScrollState())\n                        .padding(horizontal = 16.dp)\n                ) {\n                    task.run {\n                        ButtonChip(\n                            icon = Icons.Outlined.ContentCopy,\n                            label = stringResource(id = R.string.copy_log),\n                        ) {\n                            onCopyLog(clipboardManager)\n                        }\n                        if (state is Downloader.CustomCommandTask.State.Error)\n                            ButtonChip(\n                                icon = Icons.Outlined.ErrorOutline,\n                                label = stringResource(id = R.string.copy_error_report),\n                                iconColor = MaterialTheme.colorScheme.error,\n                            ) {\n                                onCopyError(clipboardManager)\n                            }\n                        if (state is Downloader.CustomCommandTask.State.Running)\n                            ButtonChip(\n                                icon = Icons.Outlined.Cancel,\n                                label = stringResource(id = R.string.cancel),\n                                iconColor = MaterialTheme.colorScheme.onSurfaceVariant,\n                            ) {\n                                onCancel()\n                            }\n                        if (\n                            state is Downloader.CustomCommandTask.State.Canceled ||\n                                state is Downloader.CustomCommandTask.State.Error\n                        )\n                            ButtonChip(\n                                icon = Icons.Outlined.RestartAlt,\n                                label = stringResource(id = R.string.restart),\n                            ) {\n                                onRestart()\n                            }\n                        if (!expandLog)\n                            ElevatedAssistChip(\n                                modifier = Modifier.padding(horizontal = 4.dp),\n                                onClick = { expandLog = true },\n                                label = { Text(stringResource(id = R.string.expand)) },\n                                leadingIcon = {\n                                    Icon(\n                                        imageVector = Icons.Outlined.UnfoldMore,\n                                        null,\n                                        modifier =\n                                            Modifier.size(AssistChipDefaults.IconSize).rotate(90f),\n                                    )\n                                },\n                            )\n                    }\n                }\n            }\n        },\n    ) { paddings ->\n        val scrollState = rememberScrollState()\n        LaunchedEffect(key1 = scrollState.maxValue) {\n            scrollState.animateScrollTo(scrollState.maxValue)\n        }\n\n        Column(modifier = Modifier.padding(paddings).fillMaxSize().verticalScroll(scrollState)) {\n            SelectionContainer() {\n                Text(\n                    modifier =\n                        Modifier.run {\n                                if (expandLog) horizontalScroll(rememberScrollState()) else this\n                            }\n                            .padding(top = 12.dp)\n                            .padding(horizontal = 20.dp),\n                    text = task.output,\n                    style =\n                        MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),\n                )\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/DownloadPage.kt",
    "content": "package com.junkfood.seal.ui.page.download\n\nimport android.Manifest\nimport android.os.Build\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.animateContentSize\nimport androidx.compose.animation.core.FastOutSlowInEasing\nimport androidx.compose.animation.core.animateFloatAsState\nimport androidx.compose.animation.core.tween\nimport androidx.compose.animation.expandVertically\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.shrinkVertically\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.imePadding\nimport androidx.compose.foundation.layout.offset\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.text.KeyboardActions\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.ContentPaste\nimport androidx.compose.material.icons.outlined.Error\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.Settings\nimport androidx.compose.material.icons.outlined.Subscriptions\nimport androidx.compose.material.icons.outlined.Terminal\nimport androidx.compose.material3.Badge\nimport androidx.compose.material3.BadgedBox\nimport androidx.compose.material3.ButtonDefaults\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FloatingActionButton\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LinearProgressIndicator\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.PlainTooltip\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.TooltipBox\nimport androidx.compose.material3.TooltipDefaults\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.material3.rememberModalBottomSheetState\nimport androidx.compose.material3.rememberTooltipState\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.DisposableEffect\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.ExperimentalComposeUiApi\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalSoftwareKeyboardController\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.google.accompanist.permissions.ExperimentalPermissionsApi\nimport com.google.accompanist.permissions.PermissionStatus\nimport com.google.accompanist.permissions.isGranted\nimport com.google.accompanist.permissions.rememberPermissionState\nimport com.junkfood.seal.App\nimport com.junkfood.seal.Downloader\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.ui.common.HapticFeedback.longPressHapticFeedback\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.LocalWindowWidthState\nimport com.junkfood.seal.ui.component.ClearButton\nimport com.junkfood.seal.ui.component.NavigationBarSpacer\nimport com.junkfood.seal.ui.component.OutlinedButtonWithIcon\nimport com.junkfood.seal.ui.component.VideoCard\nimport com.junkfood.seal.ui.page.downloadv2.configure.Config\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialog\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.Action\nimport com.junkfood.seal.ui.page.downloadv2.configure.FormatPage\nimport com.junkfood.seal.ui.theme.PreviewThemeLight\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.CELLULAR_DOWNLOAD\nimport com.junkfood.seal.util.CONFIGURE\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DEBUG\nimport com.junkfood.seal.util.DISABLE_PREVIEW\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.NOTIFICATION\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.matchUrlFromClipboard\nimport kotlinx.coroutines.launch\nimport org.koin.androidx.compose.koinViewModel\nimport org.koin.compose.koinInject\n\n@OptIn(ExperimentalPermissionsApi::class, ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadPage(\n    navigateToSettings: () -> Unit = {},\n    navigateToDownloads: () -> Unit = {},\n    navigateToPlaylistPage: () -> Unit = {},\n    navigateToFormatPage: () -> Unit = {},\n    onNavigateToTaskList: () -> Unit = {},\n    onNavigateToCookieGeneratorPage: (String) -> Unit = {},\n    downloader: DownloaderV2 = koinInject(),\n    homePageViewModel: HomePageViewModel = koinViewModel(),\n    dialogViewModel: DownloadDialogViewModel = koinViewModel(),\n) {\n\n    val scope = rememberCoroutineScope()\n    val downloaderState by Downloader.downloaderState.collectAsStateWithLifecycle()\n    val taskState by Downloader.taskState.collectAsStateWithLifecycle()\n    val viewState by homePageViewModel.viewStateFlow.collectAsStateWithLifecycle()\n    val playlistInfo by Downloader.playlistResult.collectAsStateWithLifecycle()\n    val videoInfo by homePageViewModel.videoInfoFlow.collectAsStateWithLifecycle()\n    val errorState by Downloader.errorState.collectAsStateWithLifecycle()\n    val processCount by Downloader.processCount.collectAsStateWithLifecycle()\n\n    var showNotificationDialog by remember { mutableStateOf(false) }\n    val notificationPermission =\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n            rememberPermissionState(permission = Manifest.permission.POST_NOTIFICATIONS) {\n                isGranted: Boolean ->\n                showNotificationDialog = false\n                if (!isGranted) {\n                    ToastUtil.makeToast(R.string.permission_denied)\n                }\n            }\n        } else null\n\n    val clipboardManager = LocalClipboardManager.current\n    val keyboardController = LocalSoftwareKeyboardController.current\n    val useDialog = LocalWindowWidthState.current != WindowWidthSizeClass.Compact\n    val view = LocalView.current\n    var showDownloadDialog by rememberSaveable { mutableStateOf(false) }\n    var showMeteredNetworkDialog by remember { mutableStateOf(false) }\n\n    val checkNetworkOrDownload = {\n        if (!PreferenceUtil.isNetworkAvailableForDownload()) {\n            showMeteredNetworkDialog = true\n        } else {\n            dialogViewModel.postAction(Action.ShowSheet(listOf(viewState.url)))\n            //            downloadViewModel.startDownloadVideo()\n        }\n    }\n\n    val storagePermission =\n        rememberPermissionState(permission = Manifest.permission.WRITE_EXTERNAL_STORAGE) {\n            b: Boolean ->\n            if (b) {\n                checkNetworkOrDownload()\n            } else {\n                ToastUtil.makeToast(R.string.permission_denied)\n            }\n        }\n\n    val checkPermissionOrDownload = {\n        if (Build.VERSION.SDK_INT > 29 || storagePermission.status == PermissionStatus.Granted) {\n            checkNetworkOrDownload()\n        } else {\n            storagePermission.launchPermissionRequest()\n        }\n    }\n\n    val downloadCallback: () -> Unit = {\n        view.slightHapticFeedback()\n        keyboardController?.hide()\n        if (NOTIFICATION.getBoolean() && notificationPermission?.status?.isGranted == false) {\n            showNotificationDialog = true\n        }\n        if (CONFIGURE.getBoolean()) {\n            showDownloadDialog = true\n        } else {\n            checkPermissionOrDownload()\n        }\n    }\n\n    if (showNotificationDialog) {\n        NotificationPermissionDialog(\n            onDismissRequest = {\n                showNotificationDialog = false\n                NOTIFICATION.updateBoolean(false)\n            },\n            onPermissionGranted = { notificationPermission?.launchPermissionRequest() },\n        )\n    }\n\n    if (showMeteredNetworkDialog) {\n        MeteredNetworkDialog(\n            onDismissRequest = { showMeteredNetworkDialog = false },\n            onAllowOnceConfirm = {\n                homePageViewModel.startDownloadVideo()\n                showMeteredNetworkDialog = false\n            },\n            onAllowAlwaysConfirm = {\n                homePageViewModel.startDownloadVideo()\n                CELLULAR_DOWNLOAD.updateBoolean(true)\n                showMeteredNetworkDialog = false\n            },\n        )\n    }\n\n    DisposableEffect(viewState.showPlaylistSelectionDialog) {\n        if (!playlistInfo.entries.isNullOrEmpty() && viewState.showPlaylistSelectionDialog)\n            navigateToPlaylistPage()\n        onDispose { homePageViewModel.hidePlaylistDialog() }\n    }\n\n    DisposableEffect(viewState.showFormatSelectionPage) {\n        if (viewState.showFormatSelectionPage) {\n            if (!videoInfo.formats.isNullOrEmpty()) navigateToFormatPage()\n        }\n        onDispose { homePageViewModel.hideFormatPage() }\n    }\n    var showOutput by remember { mutableStateOf(DEBUG.getBoolean()) }\n    LaunchedEffect(downloaderState) {\n        showOutput = DEBUG.getBoolean() && downloaderState !is Downloader.State.Idle\n    }\n    if (viewState.isUrlSharingTriggered) {\n        homePageViewModel.onShareIntentConsumed()\n        downloadCallback()\n    }\n\n    val showVideoCard by remember(downloaderState) { mutableStateOf(!DISABLE_PREVIEW.getBoolean()) }\n\n    Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {\n        DownloadPageImpl(\n            downloaderState = downloaderState,\n            taskState = taskState,\n            viewState = viewState,\n            errorState = errorState,\n            downloadCallback = { dialogViewModel.postAction(Action.ShowSheet()) },\n            navigateToSettings = navigateToSettings,\n            navigateToDownloads = navigateToDownloads,\n            onNavigateToTaskList = onNavigateToTaskList,\n            processCount = processCount,\n            showVideoCard = showVideoCard,\n            showOutput = showOutput,\n            showDownloadProgress = taskState.taskId.isNotEmpty(),\n            pasteCallback = {\n                matchUrlFromClipboard(\n                        string = clipboardManager.getText().toString(),\n                        isMatchingMultiLink = CUSTOM_COMMAND.getBoolean(),\n                    )\n                    .let { homePageViewModel.updateUrl(it) }\n            },\n            cancelCallback = { Downloader.cancelDownload() },\n            onVideoCardClicked = { Downloader.openDownloadResult() },\n            onUrlChanged = { url -> homePageViewModel.updateUrl(url) },\n        ) {\n            Column {\n                downloader.getTaskStateMap().forEach { (task, state) ->\n                    Text(state.viewState.toString(), maxLines = 2)\n                    Text(state.toString())\n                    Spacer(Modifier.height(12.dp))\n                }\n            }\n        }\n\n        var preferences by remember {\n            mutableStateOf(DownloadUtil.DownloadPreferences.createFromPreferences())\n        }\n        val sheetValue = dialogViewModel.sheetValueFlow.collectAsStateWithLifecycle().value\n        val state = dialogViewModel.sheetStateFlow.collectAsStateWithLifecycle().value\n\n        val selectionState = dialogViewModel.selectionStateFlow.collectAsStateWithLifecycle().value\n\n        var showDialog by remember { mutableStateOf(false) }\n        val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)\n\n        LaunchedEffect(sheetValue) {\n            if (sheetValue == DownloadDialogViewModel.SheetValue.Expanded) {\n                showDialog = true\n            } else {\n                launch { sheetState.hide() }.invokeOnCompletion { showDialog = false }\n            }\n        }\n\n        if (showDialog) {\n\n            DownloadDialog(\n                state = state,\n                sheetState = sheetState,\n                config = Config(),\n                preferences = preferences,\n                onPreferencesUpdate = { preferences = it },\n                onActionPost = { dialogViewModel.postAction(it) },\n            )\n        }\n        when (selectionState) {\n            is DownloadDialogViewModel.SelectionState.FormatSelection ->\n                FormatPage(\n                    state = selectionState,\n                    onDismissRequest = { dialogViewModel.postAction(Action.Reset) },\n                )\n            else -> {}\n        }\n        DownloadSettingDialog(\n            useDialog = useDialog,\n            showDialog = showDownloadDialog,\n            onNavigateToCookieGeneratorPage = onNavigateToCookieGeneratorPage,\n            onDownloadConfirm = { checkPermissionOrDownload() },\n            onDismissRequest = { showDownloadDialog = false },\n        )\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadPageImpl(\n    downloaderState: Downloader.State,\n    taskState: Downloader.DownloadTaskItem,\n    viewState: HomePageViewModel.ViewState,\n    errorState: Downloader.ErrorState,\n    showVideoCard: Boolean = false,\n    showOutput: Boolean = false,\n    showDownloadProgress: Boolean = false,\n    processCount: Int = 0,\n    downloadCallback: () -> Unit = {},\n    navigateToSettings: () -> Unit = {},\n    navigateToDownloads: () -> Unit = {},\n    onNavigateToTaskList: () -> Unit = {},\n    pasteCallback: () -> Unit = {},\n    cancelCallback: () -> Unit = {},\n    onVideoCardClicked: () -> Unit = {},\n    onUrlChanged: (String) -> Unit = {},\n    isPreview: Boolean = false,\n    content: @Composable () -> Unit,\n) {\n    val view = LocalView.current\n    val clipboardManager = LocalClipboardManager.current\n\n    val showCancelButton =\n        downloaderState is Downloader.State.DownloadingPlaylist ||\n            downloaderState is Downloader.State.DownloadingVideo\n    Scaffold(\n        modifier = Modifier.fillMaxSize(),\n        topBar = {\n            TopAppBar(\n                title = {},\n                modifier = Modifier.padding(horizontal = 8.dp),\n                navigationIcon = {\n                    TooltipBox(\n                        state = rememberTooltipState(),\n                        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),\n                        tooltip = {\n                            PlainTooltip { Text(text = stringResource(id = R.string.settings)) }\n                        },\n                    ) {\n                        IconButton(\n                            onClick = {\n                                view.slightHapticFeedback()\n                                navigateToSettings()\n                            },\n                            modifier = Modifier,\n                        ) {\n                            Icon(\n                                imageVector = Icons.Outlined.Settings,\n                                contentDescription = stringResource(id = R.string.settings),\n                            )\n                        }\n                    }\n                },\n                actions = {\n                    BadgedBox(\n                        badge = {\n                            if (processCount > 0)\n                                Badge(modifier = Modifier.offset(x = (-16).dp, y = (8).dp)) {\n                                    Text(\"$processCount\")\n                                }\n                        }\n                    ) {\n                        TooltipBox(\n                            state = rememberTooltipState(),\n                            positionProvider =\n                                TooltipDefaults.rememberTooltipPositionProvider(),\n                            tooltip = {\n                                PlainTooltip {\n                                    Text(text = stringResource(id = R.string.running_tasks))\n                                }\n                            },\n                        ) {\n                            IconButton(\n                                onClick = {\n                                    view.slightHapticFeedback()\n                                    onNavigateToTaskList()\n                                },\n                                modifier = Modifier,\n                            ) {\n                                Icon(\n                                    imageVector = Icons.Outlined.Terminal,\n                                    contentDescription = stringResource(id = R.string.running_tasks),\n                                )\n                            }\n                        }\n                    }\n                    TooltipBox(\n                        state = rememberTooltipState(),\n                        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),\n                        tooltip = {\n                            PlainTooltip {\n                                Text(text = stringResource(id = R.string.downloads_history))\n                            }\n                        },\n                    ) {\n                        IconButton(\n                            onClick = {\n                                view.slightHapticFeedback()\n                                navigateToDownloads()\n                            },\n                            modifier = Modifier,\n                        ) {\n                            Icon(\n                                imageVector = Icons.Outlined.Subscriptions,\n                                contentDescription = stringResource(id = R.string.downloads_history),\n                            )\n                        }\n                    }\n                },\n            )\n        },\n        floatingActionButton = {\n            FABs(\n                modifier =\n                    with(receiver = Modifier) {\n                        if (showDownloadProgress) this else this.imePadding()\n                    },\n                downloadCallback = downloadCallback,\n                pasteCallback = pasteCallback,\n            )\n        },\n    ) {\n        Column(\n            modifier = Modifier.padding(it).fillMaxSize().verticalScroll(rememberScrollState())\n        ) {\n            TitleWithProgressIndicator(\n                showProgressIndicator = downloaderState is Downloader.State.FetchingInfo,\n                isDownloadingPlaylist = downloaderState is Downloader.State.DownloadingPlaylist,\n                showDownloadText = showCancelButton,\n                currentIndex =\n                    downloaderState.run {\n                        if (this is Downloader.State.DownloadingPlaylist) currentItem else 0\n                    },\n                downloadItemCount =\n                    downloaderState.run {\n                        if (this is Downloader.State.DownloadingPlaylist) itemCount else 0\n                    },\n            )\n\n            Column(Modifier.padding(horizontal = 24.dp).padding(top = 24.dp)) {\n                with(taskState) {\n                    AnimatedVisibility(visible = showDownloadProgress && showVideoCard) {\n                        Box() {\n                            VideoCard(\n                                modifier = Modifier,\n                                title = title,\n                                author = uploader,\n                                thumbnailUrl = thumbnailUrl,\n                                progress = progress,\n                                showCancelButton =\n                                    downloaderState is Downloader.State.DownloadingPlaylist ||\n                                        downloaderState is Downloader.State.DownloadingVideo,\n                                onCancel = cancelCallback,\n                                fileSizeApprox = fileSizeApprox,\n                                duration = duration,\n                                onClick = onVideoCardClicked,\n                                isPreview = isPreview,\n                            )\n                        }\n                    }\n                    InputUrl(\n                        url = viewState.url,\n                        progress = progress,\n                        showDownloadProgress = showDownloadProgress && !showVideoCard,\n                        error = errorState != Downloader.ErrorState.None,\n                        showCancelButton = showCancelButton && !showVideoCard,\n                        onCancel = cancelCallback,\n                        onDone = downloadCallback,\n                    ) { url ->\n                        onUrlChanged(url)\n                    }\n                    AnimatedVisibility(\n                        modifier = Modifier.fillMaxWidth(),\n                        enter = expandVertically() + fadeIn(),\n                        exit = shrinkVertically() + fadeOut(),\n                        visible = progressText.isNotEmpty() && showOutput,\n                    ) {\n                        Text(\n                            modifier = Modifier.padding(bottom = 12.dp),\n                            text = progressText,\n                            maxLines = 3,\n                            overflow = TextOverflow.Ellipsis,\n                            style = MaterialTheme.typography.bodyMedium,\n                        )\n                    }\n                }\n                AnimatedVisibility(visible = errorState != Downloader.ErrorState.None) {\n                    ErrorMessage(title = errorState.title, errorReport = errorState.report) {\n                        view.longPressHapticFeedback()\n                        clipboardManager.setText(\n                            AnnotatedString(\n                                App.getVersionReport() +\n                                    \"\\nURL: ${errorState.url}\\n${errorState.report}\"\n                            )\n                        )\n                        ToastUtil.makeToast(R.string.error_copied)\n                    }\n                }\n                content()\n                NavigationBarSpacer()\n                Spacer(modifier = Modifier.height(160.dp))\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)\n@Composable\nfun InputUrl(\n    url: String,\n    error: Boolean,\n    showDownloadProgress: Boolean = false,\n    progress: Float,\n    onDone: () -> Unit,\n    showCancelButton: Boolean,\n    onCancel: () -> Unit,\n    onValueChange: (String) -> Unit,\n) {\n    val softwareKeyboardController = LocalSoftwareKeyboardController.current\n    OutlinedTextField(\n        value = url,\n        isError = error,\n        onValueChange = onValueChange,\n        label = { Text(stringResource(R.string.video_url)) },\n        modifier = Modifier.padding(0f.dp, 16f.dp).fillMaxWidth(),\n        textStyle = MaterialTheme.typography.bodyLarge,\n        maxLines = 3,\n        trailingIcon = {\n            if (url.isNotEmpty()) ClearButton { onValueChange(\"\") }\n            //            else PasteUrlButton { onPaste() }\n        },\n        keyboardActions = KeyboardActions(onDone = { onDone() }),\n        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n    )\n    AnimatedVisibility(visible = showDownloadProgress) {\n        Row(Modifier.padding(0.dp, 12.dp), verticalAlignment = Alignment.CenterVertically) {\n            val progressAnimationValue by\n                animateFloatAsState(\n                    targetValue = progress / 100f,\n                    animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),\n                )\n            if (progressAnimationValue < 0)\n                LinearProgressIndicator(\n                    modifier = Modifier.weight(0.75f).clip(MaterialTheme.shapes.large)\n                )\n            else\n                LinearProgressIndicator(\n                    progress = { progressAnimationValue },\n                    modifier = Modifier.weight(0.75f).clip(MaterialTheme.shapes.large),\n                )\n            Text(\n                text = if (progress < 0) \"0%\" else \"$progress%\",\n                textAlign = TextAlign.Center,\n                modifier = Modifier.weight(0.25f),\n            )\n        }\n    }\n    Column(modifier = Modifier.fillMaxWidth()) {\n        AnimatedVisibility(visible = showCancelButton) {\n            OutlinedButtonWithIcon(\n                onClick = onCancel,\n                icon = Icons.Outlined.Cancel,\n                text = stringResource(id = R.string.cancel),\n                contentColor = MaterialTheme.colorScheme.onSurfaceVariant,\n            )\n        }\n    }\n}\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\nfun TitleWithProgressIndicator(\n    showProgressIndicator: Boolean = true,\n    showDownloadText: Boolean = true,\n    isDownloadingPlaylist: Boolean = true,\n    currentIndex: Int = 1,\n    downloadItemCount: Int = 4,\n) {\n    Column(modifier = Modifier.padding(start = 12.dp, top = 24.dp)) {\n        Row(\n            modifier =\n                Modifier.clip(MaterialTheme.shapes.extraLarge)\n                    .padding(horizontal = 12.dp)\n                    .padding(top = 12.dp, bottom = 3.dp)\n        ) {\n            Text(\n                modifier = Modifier,\n                text = stringResource(R.string.app_name),\n                style = MaterialTheme.typography.displaySmall,\n            )\n            AnimatedVisibility(visible = showProgressIndicator) {\n                Column(modifier = Modifier.padding(start = 12.dp)) {\n                    CircularProgressIndicator(modifier = Modifier.size(16.dp), strokeWidth = 3.dp)\n                }\n            }\n        }\n        AnimatedVisibility(visible = showDownloadText) {\n            Text(\n                if (isDownloadingPlaylist)\n                    stringResource(R.string.playlist_indicator_text)\n                        .format(currentIndex, downloadItemCount)\n                else stringResource(R.string.downloading_indicator_text),\n                modifier = Modifier.padding(start = 12.dp, top = 3.dp),\n                style = MaterialTheme.typography.bodySmall,\n                color = MaterialTheme.colorScheme.onSurfaceVariant,\n            )\n        }\n    }\n}\n\n@Composable\nfun ErrorMessage(\n    modifier: Modifier = Modifier,\n    title: String,\n    errorReport: String,\n    onButtonClicked: () -> Unit = {},\n) {\n    val view = LocalView.current\n    Surface(\n        color = MaterialTheme.colorScheme.errorContainer,\n        shape = MaterialTheme.shapes.large,\n        modifier = Modifier.padding(vertical = 16.dp),\n    ) {\n        Column(\n            modifier = Modifier.animateContentSize().padding(horizontal = 12.dp, vertical = 16.dp)\n        ) {\n            Row(\n                modifier = modifier.fillMaxWidth().padding(horizontal = 4.dp),\n                verticalAlignment = Alignment.CenterVertically,\n            ) {\n                Icon(\n                    Icons.Outlined.Error,\n                    contentDescription = null,\n                    tint = MaterialTheme.colorScheme.error,\n                )\n                Spacer(modifier = Modifier.width(12.dp))\n                Column {\n                    Text(\n                        maxLines = 1,\n                        overflow = TextOverflow.Ellipsis,\n                        modifier = Modifier,\n                        text = title,\n                        color = MaterialTheme.colorScheme.onErrorContainer,\n                        style = MaterialTheme.typography.titleMedium,\n                    )\n                }\n            }\n\n            Spacer(modifier = Modifier.height(12.dp))\n\n            var isExpanded by remember { mutableStateOf(false) }\n\n            Text(\n                text = errorReport,\n                style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),\n                overflow = TextOverflow.Ellipsis,\n                maxLines = if (isExpanded) Int.MAX_VALUE else 8,\n                modifier =\n                    Modifier.clip(MaterialTheme.shapes.small)\n                        .clickable(\n                            enabled = !isExpanded,\n                            onClickLabel = stringResource(id = R.string.expand),\n                            onClick = {\n                                view.slightHapticFeedback()\n                                isExpanded = true\n                            },\n                        )\n                        .padding(4.dp),\n                onTextLayout = { isExpanded = !it.hasVisualOverflow },\n            )\n\n            Spacer(modifier = Modifier.height(8.dp))\n\n            Row(modifier = Modifier.align(Alignment.End)) {\n                TextButton(\n                    onClick = onButtonClicked,\n                    colors =\n                        ButtonDefaults.textButtonColors(\n                            contentColor = MaterialTheme.colorScheme.error\n                        ),\n                ) {\n                    Text(text = stringResource(id = R.string.copy_error_report))\n                }\n            }\n        }\n    }\n}\n\n@Preview\n@Composable\nprivate fun ErrorPreview() {\n    SealTheme {\n        Surface {\n            LazyColumn {\n                item {\n                    ErrorMessage(\n                        title = stringResource(id = R.string.download_error_msg),\n                        errorReport = ERROR_REPORT_SAMPLE,\n                    ) {}\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun FABs(\n    modifier: Modifier = Modifier,\n    downloadCallback: () -> Unit = {},\n    pasteCallback: () -> Unit = {},\n) {\n    Column(modifier = modifier.padding(6.dp), horizontalAlignment = Alignment.End) {\n        FloatingActionButton(\n            onClick = pasteCallback,\n            content = {\n                Icon(\n                    Icons.Outlined.ContentPaste,\n                    contentDescription = stringResource(R.string.paste),\n                )\n            },\n            modifier = Modifier.padding(vertical = 12.dp),\n        )\n        FloatingActionButton(\n            onClick = downloadCallback,\n            content = {\n                Icon(\n                    Icons.Outlined.FileDownload,\n                    contentDescription = stringResource(R.string.download),\n                )\n            },\n            modifier = Modifier.padding(vertical = 12.dp),\n        )\n    }\n}\n\n@Composable\n@Preview\nfun DownloadPagePreview() {\n    PreviewThemeLight {\n        Column() {\n            DownloadPageImpl(\n                downloaderState = Downloader.State.DownloadingVideo,\n                taskState = Downloader.DownloadTaskItem(),\n                viewState = HomePageViewModel.ViewState(),\n                errorState =\n                    Downloader.ErrorState.DownloadError(url = \"\", report = ERROR_REPORT_SAMPLE),\n                processCount = 99,\n                isPreview = true,\n                showDownloadProgress = true,\n                showVideoCard = false,\n            ) {}\n        }\n    }\n}\n\nprivate const val ERROR_REPORT_SAMPLE =\n    \"\"\"[sample] Extracting URL: https://www.example.com\n[sample] sample: Downloading webpage\n[sample] sample: Downloading android player API JSON\n[info] Available automatic captions for sample:\n[info] Available automatic captions for sample:\n[sample] sample: Downloading android player API JSON\n[info] Available automatic captions for sample:\n[info] Available automatic captions for sample:\"\"\"\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/DownloadSettingsDialog.kt",
    "content": "package com.junkfood.seal.ui.page.download\n\nimport android.os.Build\nimport androidx.activity.compose.BackHandler\nimport androidx.compose.animation.AnimatedContent\nimport androidx.compose.animation.core.tween\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.togetherWith\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.foundation.lazy.rememberLazyListState\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.AudioFile\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.Code\nimport androidx.compose.material.icons.outlined.DoneAll\nimport androidx.compose.material.icons.outlined.DownloadDone\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.HighQuality\nimport androidx.compose.material.icons.outlined.NewLabel\nimport androidx.compose.material.icons.outlined.Sync\nimport androidx.compose.material.icons.outlined.VideoFile\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilterChip\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.rememberModalBottomSheetState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.common.motion.materialSharedAxisYIn\nimport com.junkfood.seal.ui.component.ButtonChip\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.DrawerSheetSubtitle\nimport com.junkfood.seal.ui.component.FilledButtonWithIcon\nimport com.junkfood.seal.ui.component.OutlinedButtonWithIcon\nimport com.junkfood.seal.ui.component.SealModalBottomSheet\nimport com.junkfood.seal.ui.component.SealModalBottomSheetM2\nimport com.junkfood.seal.ui.component.SingleChoiceChip\nimport com.junkfood.seal.ui.component.VideoFilterChip\nimport com.junkfood.seal.ui.page.command.TemplatePickerDialog\nimport com.junkfood.seal.ui.page.settings.command.CommandTemplateDialog\nimport com.junkfood.seal.ui.page.settings.format.AudioConversionQuickSettingsDialog\nimport com.junkfood.seal.ui.page.settings.format.FormatSortingDialog\nimport com.junkfood.seal.ui.page.settings.format.VideoFormatDialog\nimport com.junkfood.seal.ui.page.settings.format.VideoQualityDialog\nimport com.junkfood.seal.ui.page.settings.network.CookiesQuickSettingsDialog\nimport com.junkfood.seal.util.AUDIO_CONVERSION_FORMAT\nimport com.junkfood.seal.util.AUDIO_CONVERT\nimport com.junkfood.seal.util.CONVERT_M4A\nimport com.junkfood.seal.util.CONVERT_MP3\nimport com.junkfood.seal.util.COOKIES\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DOWNLOAD_TYPE_INITIALIZATION\nimport com.junkfood.seal.util.DatabaseUtil\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.DownloadUtil.toFormatSorter\nimport com.junkfood.seal.util.EXTRACT_AUDIO\nimport com.junkfood.seal.util.FORMAT_SELECTION\nimport com.junkfood.seal.util.FORMAT_SORTING\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.FileUtil.getCookiesFile\nimport com.junkfood.seal.util.PLAYLIST\nimport com.junkfood.seal.util.PreferenceStrings\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.SORTING_FIELDS\nimport com.junkfood.seal.util.SUBTITLE\nimport com.junkfood.seal.util.TEMPLATE_ID\nimport com.junkfood.seal.util.THUMBNAIL\nimport com.junkfood.seal.util.USE_PREVIOUS_SELECTION\nimport com.junkfood.seal.util.VIDEO_FORMAT\nimport com.junkfood.seal.util.VIDEO_QUALITY\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\nprivate enum class DownloadType {\n    Audio,\n    Video,\n    Playlist,\n    Command,\n}\n\n@Composable\nprivate fun DownloadType.label(): String =\n    stringResource(\n        when (this) {\n            DownloadType.Audio -> R.string.audio\n            DownloadType.Video -> R.string.video\n            DownloadType.Command -> R.string.commands\n            DownloadType.Playlist -> R.string.playlist\n        }\n    )\n\nprivate fun DownloadType.updatePreference() {\n    when (this) {\n        DownloadType.Audio -> {\n            EXTRACT_AUDIO.updateBoolean(true)\n            CUSTOM_COMMAND.updateBoolean(false)\n        }\n\n        DownloadType.Video -> {\n            EXTRACT_AUDIO.updateBoolean(false)\n            CUSTOM_COMMAND.updateBoolean(false)\n        }\n\n        DownloadType.Command -> {\n            CUSTOM_COMMAND.updateBoolean(true)\n        }\n\n        DownloadType.Playlist -> {\n            PLAYLIST.updateBoolean(true)\n            CUSTOM_COMMAND.updateBoolean(false)\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadSettingDialog(\n    useDialog: Boolean = false,\n    showDialog: Boolean = false,\n    isQuickDownload: Boolean = false,\n    onNavigateToCookieGeneratorPage: (String) -> Unit = {},\n    onDownloadConfirm: () -> Unit,\n    onDismissRequest: () -> Unit,\n) {\n    //    val audio by remember { mutableStateOf(EXTRACT_AUDIO.getBoolean()) }\n\n    var thumbnail by remember { mutableStateOf(THUMBNAIL.getBoolean()) }\n    var subtitle by remember { mutableStateOf(SUBTITLE.getBoolean()) }\n    var formatSelection by FORMAT_SELECTION.booleanState\n    var videoFormatPreference by VIDEO_FORMAT.intState\n    var videoQuality by VIDEO_QUALITY.intState\n    var cookies by COOKIES.booleanState\n    var formatSorting by FORMAT_SORTING.booleanState\n\n    val downloadTypes =\n        remember(isQuickDownload) {\n            if (isQuickDownload) {\n                DownloadType.entries - DownloadType.Playlist\n            } else {\n                DownloadType.entries\n            }\n        }\n\n    var selectedType by\n        remember(showDialog) {\n            mutableStateOf(\n                when (DOWNLOAD_TYPE_INITIALIZATION.getInt()) {\n                    USE_PREVIOUS_SELECTION -> {\n                        if (CUSTOM_COMMAND.getBoolean()) {\n                            DownloadType.Command\n                        } else if (EXTRACT_AUDIO.getBoolean()) {\n                            DownloadType.Audio\n                        } else {\n                            DownloadType.Video\n                        }\n                    }\n\n                    else -> {\n                        null\n                    }\n                }\n            )\n        }\n\n    var showAudioSettingsDialog by remember { mutableStateOf(false) }\n    var showVideoQualityDialog by remember { mutableStateOf(false) }\n    var showVideoFormatDialog by remember { mutableStateOf(false) }\n    var showAudioConversionDialog by remember { mutableStateOf(false) }\n    var showFormatSortingDialog by remember { mutableStateOf(false) }\n\n    var sortingFields by\n        remember(showFormatSortingDialog) { mutableStateOf(SORTING_FIELDS.getString()) }\n\n    var showTemplateSelectionDialog by remember { mutableStateOf(false) }\n    var showTemplateCreatorDialog by remember { mutableStateOf(false) }\n    var showTemplateEditorDialog by remember { mutableStateOf(false) }\n\n    var showCookiesDialog by rememberSaveable { mutableStateOf(false) }\n\n    val cookiesProfiles by DatabaseUtil.getCookiesFlow().collectAsStateWithLifecycle(emptyList())\n\n    val template by\n        remember(showTemplateCreatorDialog, showTemplateSelectionDialog, showTemplateEditorDialog) {\n            mutableStateOf(PreferenceUtil.getTemplate())\n        }\n\n    val scope = rememberCoroutineScope()\n    val context = LocalContext.current\n\n    LaunchedEffect(showCookiesDialog) {\n        withContext(Dispatchers.IO) {\n            DownloadUtil.getCookiesContentFromDatabase().getOrNull()?.let {\n                FileUtil.writeContentToFile(it, context.getCookiesFile())\n            }\n        }\n    }\n\n    val downloadButtonCallback = {\n        onDismissRequest()\n        onDownloadConfirm()\n    }\n\n    val sheetContent: @Composable () -> Unit = {\n        Column {\n            DrawerSheetSubtitle(text = stringResource(id = R.string.download_type))\n\n            LazyRow(modifier = Modifier.fillMaxWidth()) {\n                items(downloadTypes) { type ->\n                    SingleChoiceChip(selected = type == selectedType, label = type.label()) {\n                        selectedType = type\n                        type.updatePreference()\n                    }\n                }\n            }\n\n            if (!isQuickDownload) {\n                DrawerSheetSubtitle(text = stringResource(id = R.string.format_selection))\n                Row(modifier = Modifier.horizontalScroll(rememberScrollState())) {\n                    SingleChoiceChip(\n                        selected = !formatSelection || selectedType == DownloadType.Playlist,\n                        onClick = {\n                            formatSelection = false\n                            FORMAT_SELECTION.updateBoolean(false)\n                        },\n                        enabled = selectedType != DownloadType.Command,\n                        label = stringResource(id = R.string.auto),\n                    )\n                    SingleChoiceChip(\n                        selected = formatSelection && selectedType != DownloadType.Playlist,\n                        onClick = {\n                            formatSelection = true\n                            FORMAT_SELECTION.updateBoolean(true)\n                        },\n                        enabled =\n                            selectedType != DownloadType.Command &&\n                                selectedType != DownloadType.Playlist,\n                        label = stringResource(id = R.string.custom),\n                    )\n                }\n            }\n\n            DrawerSheetSubtitle(\n                text =\n                    stringResource(\n                        id =\n                            if (selectedType == DownloadType.Command) R.string.template_selection\n                            else R.string.format_preference\n                    )\n            )\n            AnimatedContent(\n                targetState = selectedType,\n                label = \"\",\n                transitionSpec = {\n                    (materialSharedAxisYIn(initialOffsetY = { it / 4 })).togetherWith(\n                        fadeOut(tween(durationMillis = 80))\n                    )\n                },\n            ) { type ->\n                when (type) {\n                    DownloadType.Command -> {\n                        LazyRow(modifier = Modifier) {\n                            item {\n                                ButtonChip(\n                                    icon = Icons.Outlined.Code,\n                                    label = template.name,\n                                    onClick = { showTemplateSelectionDialog = true },\n                                )\n                            }\n                            item {\n                                ButtonChip(\n                                    icon = Icons.Outlined.NewLabel,\n                                    label = stringResource(id = R.string.new_template),\n                                    onClick = { showTemplateCreatorDialog = true },\n                                )\n                            }\n                            item {\n                                ButtonChip(\n                                    icon = Icons.Outlined.Edit,\n                                    label =\n                                        stringResource(id = R.string.edit_template, template.name),\n                                    onClick = { showTemplateEditorDialog = true },\n                                )\n                            }\n                        }\n                    }\n\n                    else -> {\n                        Row(\n                            modifier =\n                                Modifier.fillMaxWidth().horizontalScroll(rememberScrollState())\n                        ) {\n                            if (type != DownloadType.Audio) {\n                                ButtonChip(\n                                    onClick = { showVideoFormatDialog = true },\n                                    enabled = !formatSorting && type != null,\n                                    label =\n                                        PreferenceStrings.getVideoFormatLabel(\n                                            videoFormatPreference\n                                        ),\n                                    icon = Icons.Outlined.VideoFile,\n                                    iconDescription =\n                                        stringResource(id = R.string.video_format_preference),\n                                )\n                                ButtonChip(\n                                    label = PreferenceStrings.getVideoResolutionDesc(),\n                                    icon = Icons.Outlined.HighQuality,\n                                    enabled = !formatSorting && type != null,\n                                    iconDescription = stringResource(id = R.string.video_quality),\n                                ) {\n                                    showVideoQualityDialog = true\n                                }\n                            }\n                            ButtonChip(\n                                onClick = { showAudioSettingsDialog = true },\n                                enabled = !formatSorting && type != null,\n                                label = stringResource(R.string.audio_format),\n                                icon = Icons.Outlined.AudioFile,\n                            )\n                            val convertToMp3 = stringResource(id = R.string.convert_to, \"mp3\")\n                            val convertToM4a = stringResource(id = R.string.convert_to, \"m4a\")\n                            val notConvert = stringResource(id = R.string.not_convert)\n\n                            if (type == DownloadType.Audio) {\n                                val convertAudioLabelText by\n                                    remember(showAudioConversionDialog, type) {\n                                        derivedStateOf {\n                                            if (!AUDIO_CONVERT.getBoolean()) {\n                                                notConvert\n                                            } else {\n                                                val format = AUDIO_CONVERSION_FORMAT.getInt()\n                                                when (format) {\n                                                    CONVERT_MP3 -> convertToMp3\n                                                    CONVERT_M4A -> convertToM4a\n                                                    else -> notConvert\n                                                }\n                                            }\n                                        }\n                                    }\n                                ButtonChip(\n                                    label = convertAudioLabelText,\n                                    icon = Icons.Outlined.Sync,\n                                ) {\n                                    showAudioConversionDialog = true\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            DrawerSheetSubtitle(text = stringResource(R.string.additional_settings))\n\n            Row(modifier = Modifier.horizontalScroll(rememberScrollState())) {\n                if (cookiesProfiles.isNotEmpty()) {\n                    VideoFilterChip(\n                        selected = cookies,\n                        onClick = {\n                            if (isQuickDownload) {\n                                cookies = !cookies\n                                COOKIES.updateBoolean(cookies)\n                            } else {\n                                showCookiesDialog = true\n                            }\n                        },\n                        label = stringResource(id = R.string.cookies),\n                    )\n                }\n                if (sortingFields.isNotEmpty()) {\n                    FilterChip(\n                        modifier = Modifier.padding(horizontal = 4.dp),\n                        selected = formatSorting,\n                        enabled = selectedType != DownloadType.Command,\n                        onClick = { showFormatSortingDialog = true },\n                        label = { Text(text = stringResource(id = R.string.format_sorting)) },\n                    )\n                }\n\n                VideoFilterChip(\n                    selected = subtitle,\n                    enabled = selectedType != DownloadType.Command,\n                    onClick = {\n                        subtitle = !subtitle\n                        SUBTITLE.updateBoolean(subtitle)\n                    },\n                    label = stringResource(id = R.string.download_subtitles),\n                )\n                VideoFilterChip(\n                    selected = thumbnail,\n                    enabled = selectedType != DownloadType.Command,\n                    onClick = {\n                        thumbnail = !thumbnail\n                        THUMBNAIL.updateBoolean(thumbnail)\n                    },\n                    label = stringResource(R.string.create_thumbnail),\n                )\n            }\n        }\n    }\n    if (showDialog) {\n\n        @Composable\n        fun SheetContent(onDismissRequest: () -> Unit) {\n            Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                Icon(\n                    modifier = Modifier.align(Alignment.CenterHorizontally),\n                    imageVector = Icons.Outlined.DoneAll,\n                    contentDescription = null,\n                )\n                Text(\n                    text = stringResource(R.string.settings_before_download),\n                    style = MaterialTheme.typography.headlineSmall,\n                    modifier =\n                        Modifier.align(Alignment.CenterHorizontally).padding(vertical = 16.dp),\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                    textAlign = TextAlign.Center,\n                )\n                sheetContent()\n                val state = rememberLazyListState()\n                LazyRow(\n                    modifier = Modifier.fillMaxWidth().padding(top = 24.dp),\n                    horizontalArrangement = Arrangement.End,\n                    state = state,\n                    verticalAlignment = Alignment.CenterVertically,\n                ) {\n                    item {\n                        OutlinedButtonWithIcon(\n                            modifier = Modifier.padding(horizontal = 12.dp),\n                            onClick = onDismissRequest,\n                            icon = Icons.Outlined.Cancel,\n                            text = stringResource(R.string.cancel),\n                        )\n                    }\n                    item {\n                        FilledButtonWithIcon(\n                            onClick = downloadButtonCallback,\n                            icon = Icons.Outlined.DownloadDone,\n                            text = stringResource(R.string.start_download),\n                            enabled = selectedType != null,\n                        )\n                    }\n                }\n            }\n        }\n\n        if (!useDialog) {\n            val useMD2BottomSheet = Build.VERSION.SDK_INT < 30\n            if (useMD2BottomSheet) {\n                val sheetState =\n                    androidx.compose.material.rememberModalBottomSheetState(\n                        initialValue = ModalBottomSheetValue.Hidden,\n                        skipHalfExpanded = true,\n                    )\n\n                BackHandler(sheetState.targetValue == ModalBottomSheetValue.Expanded) {\n                    scope.launch { sheetState.hide() }\n                }\n\n                LaunchedEffect(Unit) { sheetState.show() }\n\n                LaunchedEffect(sheetState.isVisible) {\n                    if (sheetState.targetValue == ModalBottomSheetValue.Hidden) {\n                        onDismissRequest()\n                    }\n                }\n\n                SealModalBottomSheetM2(\n                    sheetState = sheetState,\n                    contentPadding = PaddingValues(horizontal = 20.dp),\n                    sheetContent = {\n                        SheetContent(onDismissRequest = { scope.launch { sheetState.hide() } })\n                    },\n                )\n            } else {\n                val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)\n                val onSheetDismiss: () -> Unit = {\n                    scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() }\n                }\n\n                SealModalBottomSheet(\n                    sheetState = sheetState,\n                    contentPadding = PaddingValues(horizontal = 20.dp),\n                    onDismissRequest = onDismissRequest,\n                    content = { SheetContent(onDismissRequest = onSheetDismiss) },\n                )\n            }\n        } else {\n            AlertDialog(\n                onDismissRequest = onDismissRequest,\n                confirmButton = {\n                    TextButton(onClick = downloadButtonCallback) {\n                        Text(text = stringResource(R.string.start_download))\n                    }\n                },\n                dismissButton = { DismissButton { onDismissRequest() } },\n                icon = { Icon(imageVector = Icons.Outlined.DoneAll, contentDescription = null) },\n                title = {\n                    Text(\n                        stringResource(R.string.settings_before_download),\n                        textAlign = TextAlign.Center,\n                    )\n                },\n                text = { Column(Modifier.verticalScroll(rememberScrollState())) { sheetContent() } },\n            )\n        }\n    }\n\n    if (showAudioSettingsDialog) {\n        //        AudioQuickSettingsDialog(onDismissRequest = { showAudioSettingsDialog = false })\n    }\n    if (showVideoFormatDialog) {\n        VideoFormatDialog(\n            videoFormatPreference = videoFormatPreference,\n            onDismissRequest = { showVideoFormatDialog = false },\n            onConfirm = {\n                videoFormatPreference = it\n                VIDEO_FORMAT.updateInt(it)\n            },\n        )\n    }\n    if (showVideoQualityDialog) {\n        VideoQualityDialog(\n            videoQuality = videoQuality,\n            onDismissRequest = { showVideoQualityDialog = false },\n            onConfirm = {\n                VIDEO_QUALITY.updateInt(it)\n                videoQuality = it\n            },\n        )\n    }\n\n    if (showTemplateSelectionDialog) {\n        TemplatePickerDialog { showTemplateSelectionDialog = false }\n    }\n    if (showTemplateCreatorDialog) {\n        CommandTemplateDialog(\n            onDismissRequest = { showTemplateCreatorDialog = false },\n            confirmationCallback = { scope.launch { TEMPLATE_ID.updateInt(it) } },\n        )\n    }\n    if (showTemplateEditorDialog) {\n        CommandTemplateDialog(\n            commandTemplate = template,\n            onDismissRequest = { showTemplateEditorDialog = false },\n        )\n    }\n    if (showCookiesDialog && cookiesProfiles.isNotEmpty()) {\n        CookiesQuickSettingsDialog(\n            onDismissRequest = { showCookiesDialog = false },\n            onConfirm = {},\n            cookieProfiles = cookiesProfiles,\n            onCookieProfileClicked = { onNavigateToCookieGeneratorPage(it.url) },\n            isCookiesEnabled = cookies,\n            onCookiesToggled = {\n                cookies = it\n                COOKIES.updateBoolean(cookies)\n            },\n        )\n    }\n    if (showAudioConversionDialog) {\n        AudioConversionQuickSettingsDialog(onDismissRequest = { showAudioConversionDialog = false })\n    }\n    if (showFormatSortingDialog) {\n        FormatSortingDialog(\n            fields = sortingFields,\n            showSwitch = true,\n            toggleableValue = formatSorting,\n            onSwitchChecked = {\n                formatSorting = it\n                FORMAT_SORTING.updateBoolean(it)\n            },\n            onImport = {\n                sortingFields =\n                    DownloadUtil.DownloadPreferences.createFromPreferences().toFormatSorter()\n            },\n            onDismissRequest = { showFormatSortingDialog = false },\n            onConfirm = {\n                sortingFields = it\n                SORTING_FIELDS.updateString(it)\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/HomePageViewModel.kt",
    "content": "@file:OptIn(ExperimentalMaterial3Api::class)\n\npackage com.junkfood.seal.ui.page.download\n\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.junkfood.seal.App.Companion.applicationScope\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.Downloader\nimport com.junkfood.seal.Downloader.State\nimport com.junkfood.seal.Downloader.manageDownloadError\nimport com.junkfood.seal.Downloader.updatePlaylistResult\nimport com.junkfood.seal.R\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FORMAT_SELECTION\nimport com.junkfood.seal.util.PLAYLIST\nimport com.junkfood.seal.util.PlaylistResult\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.VideoInfo\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.asStateFlow\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\n\n// TODO: Refactoring for introducing multitasking and download queue management\nclass HomePageViewModel : ViewModel() {\n\n    private val mutableViewStateFlow = MutableStateFlow(ViewState())\n    val viewStateFlow = mutableViewStateFlow.asStateFlow()\n\n    val videoInfoFlow = MutableStateFlow(VideoInfo())\n\n    data class ViewState(\n        val showPlaylistSelectionDialog: Boolean = false,\n        val url: String = \"\",\n        val showFormatSelectionPage: Boolean = false,\n        val isUrlSharingTriggered: Boolean = false,\n    )\n\n    fun updateUrl(url: String, isUrlSharingTriggered: Boolean = false) =\n        mutableViewStateFlow.update {\n            it.copy(url = url, isUrlSharingTriggered = isUrlSharingTriggered)\n        }\n\n    fun startDownloadVideo() {\n        val url = viewStateFlow.value.url\n        Downloader.clearErrorState()\n        if (CUSTOM_COMMAND.getBoolean()) {\n            applicationScope.launch(Dispatchers.IO) { DownloadUtil.executeCommandInBackground(url) }\n            return\n        }\n        if (!Downloader.isDownloaderAvailable()) return\n        if (url.isBlank()) {\n            ToastUtil.makeToast(context.getString(R.string.url_empty))\n            return\n        }\n        if (PLAYLIST.getBoolean()) {\n            viewModelScope.launch(Dispatchers.IO) { parsePlaylistInfo(url) }\n            return\n        }\n\n        if (FORMAT_SELECTION.getBoolean()) {\n            viewModelScope.launch(Dispatchers.IO) { fetchInfoForFormatSelection(url) }\n            return\n        }\n\n        Downloader.getInfoAndDownload(url)\n    }\n\n    private fun fetchInfoForFormatSelection(url: String) {\n        Downloader.updateState(State.FetchingInfo)\n        DownloadUtil.fetchVideoInfoFromUrl(url = url)\n            .onSuccess { showFormatSelectionPageOrDownload(it) }\n            .onFailure {\n                manageDownloadError(th = it, url = url, isFetchingInfo = true, isTaskAborted = true)\n            }\n        Downloader.updateState(State.Idle)\n    }\n\n    private fun parsePlaylistInfo(url: String): Unit =\n        Downloader.run {\n            if (!isDownloaderAvailable()) return\n            clearErrorState()\n            updateState(State.FetchingInfo)\n            DownloadUtil.getPlaylistOrVideoInfo(url)\n                .onSuccess { info ->\n                    updateState(State.Idle)\n                    when (info) {\n                        is PlaylistResult -> {\n                            showPlaylistPage(info)\n                        }\n\n                        is VideoInfo -> {\n                            if (FORMAT_SELECTION.getBoolean()) {\n\n                                showFormatSelectionPageOrDownload(info)\n                            } else if (isDownloaderAvailable()) {\n                                downloadVideoWithInfo(info = info)\n                            }\n                        }\n                    }\n                }\n                .onFailure {\n                    manageDownloadError(\n                        th = it,\n                        url = url,\n                        isFetchingInfo = true,\n                        isTaskAborted = true,\n                    )\n                }\n        }\n\n    private fun showPlaylistPage(playlistResult: PlaylistResult) {\n        updatePlaylistResult(playlistResult)\n        mutableViewStateFlow.update { it.copy(showPlaylistSelectionDialog = true) }\n    }\n\n    private fun showFormatSelectionPageOrDownload(info: VideoInfo) {\n        if (info.format.isNullOrEmpty()) Downloader.downloadVideoWithInfo(info)\n        else {\n            videoInfoFlow.update { info }\n            mutableViewStateFlow.update { it.copy(showFormatSelectionPage = true) }\n        }\n    }\n\n    fun hidePlaylistDialog() {\n        mutableViewStateFlow.update { it.copy(showPlaylistSelectionDialog = false) }\n    }\n\n    fun hideFormatPage() {\n        mutableViewStateFlow.update { it.copy(showFormatSelectionPage = false) }\n    }\n\n    fun onShareIntentConsumed() {\n        mutableViewStateFlow.update { it.copy(isUrlSharingTriggered = false) }\n    }\n\n    companion object {\n        private const val TAG = \"DownloadViewModel\"\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/MeteredNetworkDialog.kt",
    "content": "package com.junkfood.seal.ui.page.download\n\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.SignalCellularConnectedNoInternet4Bar\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.BottomButtonShape\nimport com.junkfood.seal.ui.component.MiddleButtonShape\nimport com.junkfood.seal.ui.component.SealDialogButtonVariant\nimport com.junkfood.seal.ui.component.SealDialogVariant\nimport com.junkfood.seal.ui.component.TopButtonShape\n\n@Composable\n@Preview\nfun MeteredNetworkDialog(\n    onDismissRequest: () -> Unit = {},\n    onAllowOnceConfirm: () -> Unit = {},\n    onAllowAlwaysConfirm: () -> Unit = {},\n) {\n    SealDialogVariant(\n        onDismissRequest = onDismissRequest,\n        icon = {\n            Icon(\n                imageVector = Icons.Outlined.SignalCellularConnectedNoInternet4Bar,\n                contentDescription = null,\n            )\n        },\n        //        text = {\n        //            Text(\n        //                text = stringResource(id = R.string.download_disabled_with_cellular),\n        //                modifier = Modifier.padding(horizontal = 24.dp)\n        //            )\n        //        },\n        title = { Text(text = stringResource(id = R.string.download_with_cellular_request)) },\n        buttons = {\n            SealDialogButtonVariant(\n                text = stringResource(id = R.string.allow_always),\n                shape = TopButtonShape,\n            ) {\n                onAllowAlwaysConfirm()\n            }\n            SealDialogButtonVariant(\n                text = stringResource(id = R.string.allow_once),\n                shape = MiddleButtonShape,\n            ) {\n                onAllowOnceConfirm()\n            }\n            SealDialogButtonVariant(\n                text = stringResource(id = R.string.dont_allow),\n                shape = BottomButtonShape,\n            ) {\n                onDismissRequest()\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/NotificationPermissionDialog.kt",
    "content": "package com.junkfood.seal.ui.page.download\n\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.NotificationsActive\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport com.junkfood.seal.R\n\n@Composable\n@Preview\nfun NotificationPermissionDialog(\n    onDismissRequest: () -> Unit = {},\n    onPermissionGranted: () -> Unit = {},\n) {\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        icon = {\n            Icon(imageVector = Icons.Outlined.NotificationsActive, contentDescription = null)\n        },\n        text = { Text(text = stringResource(id = R.string.enable_notifications_desc)) },\n        title = { Text(text = stringResource(id = R.string.enable_notifications)) },\n        confirmButton = {\n            Button(onClick = onPermissionGranted) {\n                Text(text = stringResource(id = R.string.okay))\n            }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) {\n                Text(text = stringResource(id = R.string.disable))\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/PlaylistSelectionDialog.kt",
    "content": "@file:OptIn(ExperimentalMaterial3Api::class)\n\npackage com.junkfood.seal.ui.page.download\n\nimport androidx.compose.foundation.focusable\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.text.KeyboardActions\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.PlaylistAdd\nimport androidx.compose.material3.*\nimport androidx.compose.runtime.*\nimport androidx.compose.ui.ExperimentalComposeUiApi\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.focus.FocusRequester\nimport androidx.compose.ui.focus.focusProperties\nimport androidx.compose.ui.focus.focusRequester\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.text.input.KeyboardType\nimport androidx.compose.ui.unit.dp\nimport androidx.core.text.isDigitsOnly\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.util.PlaylistResult\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.isNumberInRange\n\n@OptIn(ExperimentalComposeUiApi::class)\n@Composable\nfun PlaylistSelectionDialog(\n    playlistInfo: PlaylistResult,\n    onDismissRequest: () -> Unit = {},\n    onConfirm: (IntRange) -> Unit = {},\n) {\n    val playlistCount = playlistInfo.entries?.size ?: 0\n    var from by remember { mutableStateOf(1.toString()) }\n    var to by remember { mutableStateOf(playlistCount.toString()) }\n    var error by remember { mutableStateOf(false) }\n    val (item1, item2) = remember { FocusRequester.createRefs() }\n    val onDone: () -> Unit = {\n        error =\n            !from.isNumberInRange(1, playlistCount) or !to.isNumberInRange(1, playlistCount) ||\n                from.toInt() > to.toInt()\n        if (error) ToastUtil.makeToast(R.string.invalid_index_range)\n        else {\n            onConfirm(from.toInt()..to.toInt())\n            onDismissRequest()\n        }\n    }\n    AlertDialog(\n        onDismissRequest = { onDismissRequest() },\n        icon = { Icon(Icons.Outlined.PlaylistAdd, null) },\n        title = { Text(stringResource(R.string.download_range_selection)) },\n        text = {\n            Column {\n                Text(\n                    text =\n                        stringResource(R.string.download_range_desc)\n                            .format(1, playlistCount, playlistInfo.title)\n                )\n                Row(modifier = Modifier.padding(top = 12.dp)) {\n                    Column(modifier = Modifier.weight(1f).padding(end = 6.dp)) {\n                        OutlinedTextField(\n                            modifier =\n                                Modifier.focusable()\n                                    .focusProperties { next = item2 }\n                                    .focusRequester(item1),\n                            value = from,\n                            onValueChange = {\n                                if (it.isDigitsOnly()) from = it\n                                error = false\n                            },\n                            label = { Text(stringResource(R.string.from)) },\n                            keyboardOptions =\n                                KeyboardOptions(\n                                    keyboardType = KeyboardType.NumberPassword,\n                                    imeAction = ImeAction.Next,\n                                ),\n                            singleLine = true,\n                            isError = error,\n                        )\n                    }\n                    Column(modifier = Modifier.weight(1f).padding(start = 6.dp)) {\n                        OutlinedTextField(\n                            modifier =\n                                Modifier.focusable()\n                                    .focusProperties { previous = item1 }\n                                    .focusRequester(item2),\n                            value = to,\n                            onValueChange = {\n                                if (it.isDigitsOnly()) to = it\n                                error = false\n                            },\n                            label = { Text(stringResource(R.string.to)) },\n                            keyboardOptions =\n                                KeyboardOptions(\n                                    keyboardType = KeyboardType.NumberPassword,\n                                    imeAction = ImeAction.Done,\n                                ),\n                            keyboardActions = KeyboardActions(onDone = { onDone() }),\n                            singleLine = true,\n                            isError = error,\n                        )\n                    }\n                }\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = { ConfirmButton(onClick = onDone) },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/download/VideoSectionSlider.kt",
    "content": "package com.junkfood.seal.ui.page.download\n\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.foundation.text.KeyboardActions\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.ArrowRight\nimport androidx.compose.material.icons.outlined.ContentCut\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.RangeSlider\nimport androidx.compose.material3.RangeSliderState\nimport androidx.compose.material3.SliderColors\nimport androidx.compose.material3.SliderDefaults\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.DisposableEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.contentDescription\nimport androidx.compose.ui.semantics.semantics\nimport androidx.compose.ui.text.TextRange\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.text.input.KeyboardType\nimport androidx.compose.ui.text.input.TextFieldValue\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.DpSize\nimport androidx.compose.ui.unit.dp\nimport androidx.core.text.isDigitsOnly\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SealTextField\nimport com.junkfood.seal.ui.component.TextButtonWithIcon\nimport com.junkfood.seal.util.isNumberInRange\nimport com.junkfood.seal.util.toDurationText\nimport com.junkfood.seal.util.toIntRange\nimport kotlin.math.roundToInt\n\nprivate const val TAG = \"VideoSectionSlider\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun CustomRangeSlider(\n    state: RangeSliderState,\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    colors: SliderColors = SliderDefaults.colors(),\n    startInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n    endInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },\n    thumbSize: DpSize = DpSize(4.dp, 24.dp),\n) {\n    RangeSlider(\n        modifier = modifier,\n        state = state,\n        startInteractionSource = startInteractionSource,\n        endInteractionSource = endInteractionSource,\n        startThumb = {\n            Box(modifier = Modifier) {\n                SliderDefaults.Thumb(\n                    modifier = Modifier.align(Alignment.Center),\n                    interactionSource = startInteractionSource,\n                    colors = colors,\n                    enabled = enabled,\n                    thumbSize = thumbSize,\n                )\n            }\n        },\n        endThumb = {\n            Box(modifier = Modifier) {\n                SliderDefaults.Thumb(\n                    modifier = Modifier.align(Alignment.Center),\n                    interactionSource = startInteractionSource,\n                    colors = colors,\n                    enabled = enabled,\n                    thumbSize = thumbSize,\n                )\n            }\n        },\n        track = { sliderState ->\n            SliderDefaults.Track(colors = colors, enabled = enabled, rangeSliderState = sliderState)\n        },\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun VideoSelectionSlider(\n    modifier: Modifier = Modifier,\n    state: RangeSliderState,\n    onDurationClick: () -> Unit,\n    onDiscard: () -> Unit,\n) {\n\n    val startText by\n        remember(state.activeRangeStart) {\n            mutableStateOf(state.activeRangeStart.roundToInt().toDurationText())\n        }\n    val endText by\n        remember(state.activeRangeEnd) {\n            mutableStateOf(state.activeRangeEnd.roundToInt().toDurationText())\n        }\n    Column(modifier = modifier) {\n        Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {\n            CustomRangeSlider(\n                modifier = Modifier.weight(1f).padding(horizontal = 12.dp),\n                state = state,\n            )\n        }\n\n        Row(\n            modifier = Modifier.padding(bottom = 16.dp).align(Alignment.End),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            Box(\n                modifier =\n                    Modifier.height(40.dp)\n                        .clip(CircleShape)\n                        .clickable(\n                            onClick = onDurationClick,\n                            onClickLabel = stringResource(id = R.string.edit),\n                        )\n            ) {\n                Text(\n                    text = \"$startText / $endText\",\n                    style = MaterialTheme.typography.labelLarge,\n                    modifier = Modifier.align(Alignment.Center).padding(horizontal = 12.dp),\n                )\n            }\n            Spacer(modifier = Modifier.weight(1f))\n            TextButtonWithIcon(\n                onClick = onDiscard,\n                icon = Icons.Outlined.Delete,\n                text = stringResource(id = R.string.discard),\n                contentColor = MaterialTheme.colorScheme.error,\n            )\n        }\n    }\n}\n\n@Composable\nfun VideoClipDialog(\n    onDismissRequest: () -> Unit,\n    initialValue: ClosedFloatingPointRange<Float>,\n    valueRange: ClosedFloatingPointRange<Float>,\n    onConfirm: (ClosedFloatingPointRange<Float>) -> Unit,\n) {\n    var fromMin by remember {\n        mutableStateOf(\n            TextFieldValue(\n                \"%02d\".format(initialValue.start.roundToInt() / 60),\n                selection = TextRange(Int.MAX_VALUE),\n            )\n        )\n    }\n    var toMin by remember {\n        mutableStateOf(\n            TextFieldValue(\n                \"%02d\".format(initialValue.endInclusive.roundToInt() / 60),\n                selection = TextRange(Int.MAX_VALUE),\n            )\n        )\n    }\n    var fromSec by remember {\n        mutableStateOf(\n            TextFieldValue(\n                \"%02d\".format(initialValue.start.roundToInt() % 60),\n                selection = TextRange(Int.MAX_VALUE),\n            )\n        )\n    }\n    var toSec by remember {\n        mutableStateOf(\n            TextFieldValue(\n                \"%02d\".format(initialValue.endInclusive.roundToInt() % 60),\n                selection = TextRange(Int.MAX_VALUE),\n            )\n        )\n    }\n\n    var error by remember(fromMin.text, toMin, fromSec, toSec) { mutableStateOf(false) }\n    val valueIntRange = valueRange.toIntRange()\n\n    val start = stringResource(id = R.string.clip_start)\n    val end = stringResource(id = R.string.clip_end)\n    val minute = \",\" + stringResource(id = R.string.minute)\n    val second = \",\" + stringResource(id = R.string.second)\n\n    fun onDone() {\n        val startTime = convertToSecs(fromMin.text, fromSec.text)\n        val endTime = convertToSecs(toMin.text, toSec.text)\n        if (\n            startTime != -1 &&\n                endTime != -1 &&\n                startTime < endTime &&\n                valueIntRange.contains(startTime) &&\n                valueIntRange.contains(endTime)\n        ) {\n            onConfirm((startTime.toFloat())..endTime.toFloat())\n            onDismissRequest()\n        } else error = true\n    }\n\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(stringResource(id = R.string.clip_video)) },\n        icon = { Icon(Icons.Outlined.ContentCut, null) },\n        confirmButton = { ConfirmButton { onDone() } },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        text = {\n            Column() {\n                Row(\n                    modifier = Modifier.padding(horizontal = 12.dp),\n                    verticalAlignment = Alignment.CenterVertically,\n                ) {\n                    Column(modifier = Modifier.weight(1f).padding(end = 6.dp)) {\n                        Row(verticalAlignment = Alignment.CenterVertically) {\n                            SealTextField(\n                                modifier =\n                                    Modifier.weight(1f).semantics {\n                                        contentDescription = start + minute\n                                    },\n                                value = fromMin,\n                                onValueChange = { if (it.text.isDigitsOnly()) fromMin = it },\n                                keyboardOptions =\n                                    KeyboardOptions(\n                                        keyboardType = KeyboardType.NumberPassword,\n                                        imeAction = ImeAction.Next,\n                                    ),\n                                singleLine = true,\n                                isError = error,\n                            )\n                            Text(\n                                modifier = Modifier.padding(horizontal = 4.dp),\n                                text = \":\",\n                                style = MaterialTheme.typography.labelLarge,\n                            )\n                            SealTextField(\n                                modifier =\n                                    Modifier.weight(1f).semantics {\n                                        contentDescription = start + second\n                                    },\n                                value = fromSec,\n                                onValueChange = { if (it.text.isDigitsOnly()) fromSec = it },\n                                keyboardOptions =\n                                    KeyboardOptions(\n                                        keyboardType = KeyboardType.NumberPassword,\n                                        imeAction = ImeAction.Next,\n                                    ),\n                                singleLine = true,\n                                isError = error,\n                            )\n                        }\n                    }\n                    Icon(\n                        imageVector = Icons.AutoMirrored.Outlined.ArrowRight,\n                        contentDescription = null,\n                    )\n                    Row(\n                        modifier = Modifier.weight(1f).padding(start = 6.dp),\n                        verticalAlignment = Alignment.CenterVertically,\n                    ) {\n                        SealTextField(\n                            modifier =\n                                Modifier.weight(1f).semantics { contentDescription = end + minute },\n                            value = toMin,\n                            onValueChange = { if (it.text.isDigitsOnly()) toMin = it },\n                            keyboardOptions =\n                                KeyboardOptions(\n                                    keyboardType = KeyboardType.NumberPassword,\n                                    imeAction = ImeAction.Next,\n                                ),\n                            singleLine = true,\n                            isError = error,\n                        )\n                        Text(\n                            modifier = Modifier.padding(horizontal = 4.dp),\n                            text = \":\",\n                            style = MaterialTheme.typography.labelLarge,\n                        )\n                        SealTextField(\n                            modifier =\n                                Modifier.weight(1f).semantics { contentDescription = end + second },\n                            value = toSec,\n                            onValueChange = { if (it.text.isDigitsOnly()) toSec = it },\n                            keyboardOptions =\n                                KeyboardOptions(\n                                    keyboardType = KeyboardType.NumberPassword,\n                                    imeAction = ImeAction.Done,\n                                ),\n                            keyboardActions = KeyboardActions(onDone = { onDone() }),\n                            singleLine = true,\n                            isError = error,\n                        )\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Composable\n@Preview\nfun VideoClipDialogPreview() {\n    VideoClipDialog(\n        onDismissRequest = {},\n        initialValue = 0f..560f,\n        valueRange = 0f..660f,\n        onConfirm = {},\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\n@Preview\nfun SliderPreview() {\n    val time = 3700\n    var valueRange by remember { mutableStateOf(0f..time.toFloat()) }\n    var shouldUpdate by remember { mutableStateOf(false) }\n    val state = remember {\n        RangeSliderState(\n            activeRangeStart = valueRange.start,\n            activeRangeEnd = valueRange.endInclusive,\n            valueRange = 0f..time.toFloat(),\n            onValueChangeFinished = { shouldUpdate = true },\n        )\n    }\n    DisposableEffect(shouldUpdate) {\n        valueRange = state.activeRangeStart..state.activeRangeEnd\n        onDispose { shouldUpdate = false }\n    }\n    Surface() {\n        Column {\n            Text(text = \"${valueRange.toIntRange()}\")\n            VideoSelectionSlider(state = state, onDiscard = {}, onDurationClick = {})\n        }\n    }\n}\n\nprivate fun convertToSecs(min: String, sec: String): Int {\n    return if (sec.isNumberInRange(0, 60)) {\n        if (min.isNumberInRange(0, Int.MAX_VALUE)) {\n            min.toInt() * 60 + sec.toInt()\n        } else -1\n    } else -1\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/ActionSheet.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2\n\nimport android.content.res.Configuration\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.IntrinsicSize\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.LazyListScope\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.OpenInNew\nimport androidx.compose.material.icons.automirrored.outlined.TextSnippet\nimport androidx.compose.material.icons.outlined.AudioFile\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.ContentCopy\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material.icons.outlined.ErrorOutline\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.Image\nimport androidx.compose.material.icons.outlined.Link\nimport androidx.compose.material.icons.outlined.RestartAlt\nimport androidx.compose.material.icons.outlined.VideoFile\nimport androidx.compose.material.icons.rounded.PlayArrow\nimport androidx.compose.material.icons.rounded.Share\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.SheetState\nimport androidx.compose.material3.SheetValue\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.FakeDownloaderV2\nimport com.junkfood.seal.download.Task\nimport com.junkfood.seal.download.Task.*\nimport com.junkfood.seal.download.Task.DownloadState.Canceled\nimport com.junkfood.seal.download.Task.DownloadState.Completed\nimport com.junkfood.seal.download.Task.DownloadState.Error\nimport com.junkfood.seal.download.Task.DownloadState.FetchingInfo\nimport com.junkfood.seal.download.Task.DownloadState.Idle\nimport com.junkfood.seal.download.Task.DownloadState.ReadyWithInfo\nimport com.junkfood.seal.download.Task.DownloadState.Running\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.junkfood.seal.ui.component.ActionSheetItem\nimport com.junkfood.seal.ui.component.ActionSheetPrimaryButton\nimport com.junkfood.seal.ui.component.SealModalBottomSheet\nimport com.junkfood.seal.ui.page.downloadv2.configure.PreferencesMock\nimport com.junkfood.seal.ui.theme.ErrorTonalPalettes\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.Format\nimport com.junkfood.seal.util.toBitrateText\nimport com.junkfood.seal.util.toDurationText\nimport com.junkfood.seal.util.toFileSizeText\nimport com.junkfood.seal.util.toLocalizedString\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.launch\n\n@Composable\nprivate fun ShareButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = LocalFixedColorRoles.current.secondaryFixed,\n        contentColor = LocalFixedColorRoles.current.onSecondaryFixedVariant,\n        imageVector = Icons.Rounded.Share,\n        text = stringResource(R.string.share),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun PlayButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = LocalFixedColorRoles.current.primaryFixed,\n        contentColor = LocalFixedColorRoles.current.onPrimaryFixedVariant,\n        imageVector = Icons.Rounded.PlayArrow,\n        text = stringResource(R.string.open_file),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun ResumeButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = LocalFixedColorRoles.current.tertiaryFixed,\n        contentColor = LocalFixedColorRoles.current.onTertiaryFixedVariant,\n        imageVector = Icons.Outlined.RestartAlt,\n        text = stringResource(R.string.resume),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun ErrorReportButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = ErrorTonalPalettes.accent1(80.0),\n        contentColor = ErrorTonalPalettes.accent1(10.0),\n        imageVector = Icons.Outlined.ErrorOutline,\n        text = stringResource(R.string.copy_error_report),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun DeleteButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = Color.Transparent,\n        contentColor = MaterialTheme.colorScheme.onSurface,\n        imageVector = Icons.Outlined.Delete,\n        outlineColor = MaterialTheme.colorScheme.outlineVariant,\n        text = stringResource(R.string.delete),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun CancelButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = MaterialTheme.colorScheme.surfaceContainerHighest,\n        contentColor = MaterialTheme.colorScheme.onSurface,\n        imageVector = Icons.Outlined.Cancel,\n        text = stringResource(R.string.cancel),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun DownloadLogButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = LocalFixedColorRoles.current.secondaryFixed,\n        contentColor = LocalFixedColorRoles.current.onSecondaryFixedVariant,\n        imageVector = Icons.AutoMirrored.Outlined.TextSnippet,\n        text = stringResource(R.string.show_logs),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun CopyURLButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = Color.Transparent,\n        contentColor = MaterialTheme.colorScheme.onSurface,\n        outlineColor = MaterialTheme.colorScheme.outlineVariant,\n        imageVector = Icons.Outlined.ContentCopy,\n        text = stringResource(R.string.copy_link),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun OpenVideoURLButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = Color.Transparent,\n        contentColor = MaterialTheme.colorScheme.onSurface,\n        outlineColor = MaterialTheme.colorScheme.outlineVariant,\n        imageVector = Icons.AutoMirrored.Outlined.OpenInNew,\n        text = stringResource(R.string.open_url),\n        onClick = onClick,\n    )\n}\n\n@Composable\nprivate fun OpenThumbnailURLButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    ActionSheetPrimaryButton(\n        modifier = modifier,\n        containerColor = Color.Transparent,\n        contentColor = MaterialTheme.colorScheme.onSurface,\n        outlineColor = MaterialTheme.colorScheme.outlineVariant,\n        imageVector = Icons.Outlined.Image,\n        text = stringResource(R.string.thumbnail),\n        onClick = onClick,\n    )\n}\n\n@Composable\nfun Title(imageModel: Any?, title: String, author: String, downloadState: DownloadState) {\n\n    Row(\n        modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        /*        AsyncImageImpl(\n            model = imageModel,\n            modifier =\n                Modifier.height(64.dp).aspectRatio(16f / 9f, matchHeightConstraintsFirst = true),\n            contentDescription = null,\n            contentScale = ContentScale.Crop,\n        )*/\n        //        Spacer(Modifier.width(12.dp))\n\n        Column(modifier = Modifier.height(IntrinsicSize.Min)) {\n            Column(Modifier) {\n                Text(text = title, style = MaterialTheme.typography.titleSmall)\n                Spacer(Modifier.height(2.dp))\n                Text(\n                    text = author,\n                    style = MaterialTheme.typography.bodySmall,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                )\n            }\n            Spacer(modifier = Modifier.weight(1f))\n            Spacer(Modifier.height(8.dp))\n\n            ListItemStateText(downloadState = downloadState)\n        }\n    }\n}\n\n@Composable\nfun SheetContent(\n    task: Task,\n    viewState: ViewState,\n    downloadState: DownloadState,\n    onDismissRequest: () -> Unit,\n    onActionPost: (Task, UiAction) -> Unit,\n) {\n\n    LazyColumn {\n        item {\n            Title(\n                imageModel = viewState.thumbnailUrl,\n                title = viewState.title,\n                author = viewState.uploader,\n                downloadState = downloadState,\n            )\n        }\n\n        item {\n            LazyRow(\n                modifier = Modifier.padding(top = 12.dp, bottom = 24.dp),\n                contentPadding = PaddingValues(horizontal = 4.dp),\n            ) {\n                ActionButtons(\n                    task = task,\n                    downloadState = downloadState,\n                    viewState = viewState,\n                    onDismissRequest = onDismissRequest,\n                    onActionPost = onActionPost,\n                )\n            }\n        }\n\n        item { ActionSheetInfo(task = task, viewState = viewState) }\n    }\n}\n\nfun LazyListScope.ActionButtons(\n    task: Task,\n    downloadState: DownloadState,\n    viewState: ViewState,\n    onDismissRequest: () -> Unit,\n    onActionPost: (Task, UiAction) -> Unit,\n) {\n    when (downloadState) {\n        is Canceled -> {\n            item(key = \"ResumeButton\") {\n                ResumeButton(modifier = Modifier.animateItem()) {\n                    onActionPost(task, UiAction.Resume)\n                    onDismissRequest()\n                }\n            }\n        }\n        is Completed -> {\n            item(key = \"PlayButton\") {\n                PlayButton(modifier = Modifier.animateItem()) {\n                    onActionPost(task, UiAction.OpenFile(downloadState.filePath))\n                    onDismissRequest()\n                }\n            }\n            item(key = \"ShareButton\") {\n                ShareButton(modifier = Modifier.animateItem()) {\n                    onActionPost(task, UiAction.ShareFile(downloadState.filePath))\n                }\n            }\n        }\n        is Error -> {\n            item(key = \"ResumeButton\") {\n                ResumeButton(modifier = Modifier.animateItem()) {\n                    onActionPost(task, UiAction.Resume)\n                    onDismissRequest()\n                }\n            }\n            item(key = \"ErrorReportButton\") {\n                ErrorReportButton(modifier = Modifier.animateItem()) {\n                    onActionPost(task, UiAction.CopyErrorReport(downloadState.throwable))\n                }\n            }\n        }\n        is FetchingInfo,\n        ReadyWithInfo,\n        Idle,\n        is Running -> {\n            item(key = \"CancelButton\") {\n                CancelButton(modifier = Modifier.animateItem()) {\n                    onActionPost(task, UiAction.Cancel)\n                    onDismissRequest()\n                }\n            }\n        }\n    }\n    if (downloadState is DownloadState.Restartable || downloadState is Completed) {\n        item(key = \"DeleteButton\") {\n            DeleteButton(modifier = Modifier.animateItem()) {\n                onActionPost(task, UiAction.Delete)\n                onDismissRequest()\n            }\n        }\n    }\n    item(key = \"CopyURLButton\") {\n        CopyURLButton(modifier = Modifier.animateItem()) {\n            onActionPost(task, UiAction.CopyVideoURL)\n        }\n    }\n    item(key = \"OpenVideoURLButton\") {\n        OpenVideoURLButton(modifier = Modifier.animateItem()) {\n            onActionPost(task, UiAction.OpenVideoURL(viewState.url))\n        }\n    }\n    if (!viewState.thumbnailUrl.isNullOrEmpty()) {\n        item(key = \"OpenThumbnailURLButton\") {\n            OpenThumbnailURLButton(modifier = Modifier.animateItem()) {\n                onActionPost(task, UiAction.OpenThumbnailURL(viewState.thumbnailUrl))\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Preview\n@Preview(name = \"Dark\", uiMode = Configuration.UI_MODE_NIGHT_YES)\n@Composable\nprivate fun SheetPreview() {\n    val sheetState =\n        with(LocalDensity.current) {\n            SheetState(\n                initialValue = SheetValue.Expanded,\n                skipPartiallyExpanded = true,\n                velocityThreshold = { 56.dp.toPx() },\n                positionalThreshold = { 125.dp.toPx() },\n            )\n        }\n\n    var downloadState: DownloadState by remember { mutableStateOf(Running(Job(), \"\", 0.58f)) }\n\n    val fakeStateList =\n        listOf(\n            Running(Job(), \"\", 0.58f),\n            Error(throwable = Throwable(), RestartableAction.Download),\n            FetchingInfo(Job(), \"\"),\n            Canceled(RestartableAction.Download),\n            ReadyWithInfo,\n            Idle,\n            Completed(null),\n        )\n    LaunchedEffect(Unit) {\n        while (true) {\n            fakeStateList.forEach {\n                downloadState = it\n                kotlinx.coroutines.delay(1000)\n            }\n        }\n    }\n\n    val context = LocalContext.current\n    val downloader = FakeDownloaderV2\n    val scope = rememberCoroutineScope()\n\n    val viewState =\n        ViewState(\n            title = \"video title looooooooooooooooooooooooooooong title sample\",\n            uploader = \"author loooooooooooooooooooooonggggggggggggggggg\",\n            videoFormats =\n                listOf(\n                    Format(\n                        vcodec = \"vp9\",\n                        resolution = \"1280x720\",\n                        vbr = 129400.0,\n                        fileSize = 11451400.0,\n                    )\n                ),\n            audioOnlyFormats = listOf(Format(acodec = \"mp4a\", abr = 129.0, fileSize = 114514.0)),\n        )\n\n    SealTheme {\n        Surface() {\n            SealModalBottomSheet(\n                contentPadding = PaddingValues(),\n                onDismissRequest = {},\n                sheetState = sheetState,\n            ) {\n                SheetContent(\n                    task = Task(url = \"https://www.example.com\", preferences = PreferencesMock),\n                    viewState = viewState,\n                    downloadState = downloadState,\n                    onDismissRequest = { scope.launch { sheetState.hide() } },\n                ) { task, action ->\n                }\n            }\n        }\n    }\n}\n\n@Composable\nfun ActionSheetInfo(modifier: Modifier = Modifier, task: Task, viewState: ViewState) {\n    with(viewState) {\n        Column(modifier = modifier) {\n            HorizontalDivider()\n            Text(\n                stringResource(R.string.media_info),\n                style = MaterialTheme.typography.titleMedium,\n                modifier = Modifier.padding(start = 16.dp, top = 24.dp, bottom = 8.dp),\n            )\n            ActionSheetItem(\n                text = {\n                    Text(\n                        task.timeCreated.toLocalizedString(),\n                        style = MaterialTheme.typography.titleSmall,\n                    )\n                    Text(\n                        \"${duration.toDurationText()} · ${fileSizeApprox.toFileSizeText()}\",\n                        style = MaterialTheme.typography.bodySmall,\n                    )\n                },\n                leadingIcon = {\n                    Icon(imageVector = Icons.Outlined.FileDownload, contentDescription = null)\n                },\n            )\n\n            videoFormats?.forEachIndexed { _index, fmt ->\n                val index = _index + 1\n                val fileSizeText = (fmt.fileSize ?: fmt.fileSizeApprox).toFileSizeText()\n                val bitRateText = fmt.vbr.toBitrateText()\n                val codecText = fmt.vcodec?.substringBefore(delimiter = \".\") ?: \"\"\n\n                val title = \"${stringResource(R.string.video)} #$index: ${fmt.formatNote}\"\n                val details =\n                    listOf(codecText, fmt.resolution, bitRateText, fileSizeText)\n                        .filterNot { it.isNullOrBlank() }\n                        .joinToString(separator = \" · \")\n\n                ActionSheetItem(\n                    text = {\n                        Text(title, style = MaterialTheme.typography.titleSmall)\n                        Text(details, style = MaterialTheme.typography.bodySmall)\n                    },\n                    leadingIcon = {\n                        Icon(imageVector = Icons.Outlined.VideoFile, contentDescription = null)\n                    },\n                )\n            }\n\n            val audioFormats: List<Format> = buildList {\n                videoFormats?.filter { it.containsAudio() }?.let { addAll(it) }\n                audioOnlyFormats?.let { addAll(it) }\n            }\n\n            audioFormats.forEachIndexed { _index, fmt ->\n                val index = _index + 1\n                val fileSizeText = (fmt.fileSize ?: fmt.fileSizeApprox).toFileSizeText()\n                val bitRateText = fmt.abr.toBitrateText()\n                val codecText = fmt.acodec?.substringBefore(delimiter = \".\") ?: \"\"\n\n                val title = \"${stringResource(R.string.audio)} #$index: ${fmt.formatNote}\"\n                val details =\n                    listOf(codecText, bitRateText, fileSizeText)\n                        .filterNot { it.isBlank() }\n                        .joinToString(separator = \" · \")\n\n                ActionSheetItem(\n                    text = {\n                        Text(title, style = MaterialTheme.typography.titleSmall)\n                        Text(details, style = MaterialTheme.typography.bodySmall)\n                    },\n                    leadingIcon = {\n                        Icon(imageVector = Icons.Outlined.AudioFile, contentDescription = null)\n                    },\n                )\n            }\n\n            ActionSheetItem(\n                text = {\n                    Text(text = extractorKey, style = MaterialTheme.typography.titleSmall)\n                    Text(text = url, style = MaterialTheme.typography.bodySmall)\n                },\n                leadingIcon = { Icon(imageVector = Icons.Outlined.Link, contentDescription = null) },\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/DownloadPageV2.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2\n\nimport android.content.Intent\nimport android.content.res.Configuration\nimport androidx.compose.animation.core.AnimationState\nimport androidx.compose.animation.core.animateTo\nimport androidx.compose.animation.rememberSplineBasedDecay\nimport androidx.compose.foundation.Image\nimport androidx.compose.foundation.LocalOverscrollFactory\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.BoxWithConstraints\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.calculateEndPadding\nimport androidx.compose.foundation.layout.calculateStartPadding\nimport androidx.compose.foundation.layout.fillMaxHeight\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.statusBarsPadding\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.layout.widthIn\nimport androidx.compose.foundation.lazy.grid.GridCells\nimport androidx.compose.foundation.lazy.grid.GridItemSpan\nimport androidx.compose.foundation.lazy.grid.LazyVerticalGrid\nimport androidx.compose.foundation.lazy.grid.items\nimport androidx.compose.foundation.lazy.grid.rememberLazyGridState\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.List\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.GridView\nimport androidx.compose.material.icons.outlined.Menu\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilledIconButton\nimport androidx.compose.material3.FloatingActionButton\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.IconButtonDefaults\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.rememberModalBottomSheetState\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.ReadOnlyComposable\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableFloatStateOf\nimport androidx.compose.runtime.mutableStateMapOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.runtime.snapshots.Snapshot\nimport androidx.compose.runtime.snapshots.SnapshotStateMap\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.vector.rememberVectorPainter\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.platform.LocalLayoutDirection\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.pluralStringResource\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.font.FontWeight\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.Dp\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport androidx.constraintlayout.compose.ConstraintLayout\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.download.Task\nimport com.junkfood.seal.download.Task.DownloadState.Canceled\nimport com.junkfood.seal.download.Task.DownloadState.Completed\nimport com.junkfood.seal.download.Task.DownloadState.Error\nimport com.junkfood.seal.download.Task.DownloadState.FetchingInfo\nimport com.junkfood.seal.download.Task.DownloadState.Idle\nimport com.junkfood.seal.download.Task.DownloadState.ReadyWithInfo\nimport com.junkfood.seal.download.Task.DownloadState.Running\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.junkfood.seal.ui.common.LocalWindowWidthState\nimport com.junkfood.seal.ui.component.SealModalBottomSheet\nimport com.junkfood.seal.ui.component.SelectionGroupDefaults\nimport com.junkfood.seal.ui.component.SelectionGroupItem\nimport com.junkfood.seal.ui.component.SelectionGroupRow\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.Action\nimport com.junkfood.seal.ui.page.downloadv2.configure.Config\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialog\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel\nimport com.junkfood.seal.ui.page.downloadv2.configure.FormatPage\nimport com.junkfood.seal.ui.page.downloadv2.configure.PlaylistSelectionPage\nimport com.junkfood.seal.ui.page.downloadv2.configure.PreferencesMock\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\nimport com.junkfood.seal.ui.svg.drawablevectors.download\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.getErrorReport\nimport com.junkfood.seal.util.makeToast\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.SupervisorJob\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport org.koin.compose.koinInject\n\nprivate const val TAG = \"DownloadPageV2\"\n\nenum class Filter {\n    All,\n    Downloading,\n    Canceled,\n    Finished;\n\n    @Composable\n    @ReadOnlyComposable\n    fun label(): String =\n        when (this) {\n            All -> stringResource(R.string.all)\n            Downloading -> stringResource(R.string.status_downloading)\n            Canceled -> stringResource(R.string.status_canceled)\n            Finished -> stringResource(R.string.status_completed)\n        }\n\n    fun predict(entry: Pair<Task, Task.State>): Boolean {\n        if (this == All) return true\n        val state = entry.second.downloadState\n        return when (this) {\n            Downloading -> {\n                when (state) {\n                    is FetchingInfo,\n                    Idle,\n                    ReadyWithInfo,\n                    is Running -> true\n                    else -> false\n                }\n            }\n            Canceled -> {\n                state is Error || state is Task.DownloadState.Canceled\n            }\n            Finished -> {\n                state is Completed\n            }\n            else -> {\n                true\n            }\n        }\n    }\n}\n\nsealed interface UiAction {\n    data class OpenFile(val filePath: String?) : UiAction\n\n    data class ShareFile(val filePath: String?) : UiAction\n\n    data class OpenThumbnailURL(val url: String) : UiAction\n\n    data object CopyVideoURL : UiAction\n\n    data class OpenVideoURL(val url: String) : UiAction\n\n    data object Cancel : UiAction\n\n    data object Delete : UiAction\n\n    data object Resume : UiAction\n\n    data class CopyErrorReport(val throwable: Throwable) : UiAction\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadPageV2(\n    modifier: Modifier = Modifier,\n    onMenuOpen: (() -> Unit) = {},\n    dialogViewModel: DownloadDialogViewModel,\n    downloader: DownloaderV2 = koinInject(),\n) {\n    val view = LocalView.current\n    val context = LocalContext.current\n    val scope = rememberCoroutineScope()\n    val clipboardManager = LocalClipboardManager.current\n    val uriHandler = LocalUriHandler.current\n\n    DownloadPageImplV2(\n        modifier = modifier,\n        taskDownloadStateMap = downloader.getTaskStateMap(),\n        downloadCallback = {\n            view.slightHapticFeedback()\n            dialogViewModel.postAction(Action.ShowSheet())\n        },\n        onMenuOpen = onMenuOpen,\n    ) { task, action ->\n        view.slightHapticFeedback()\n        when (action) {\n            UiAction.Cancel -> downloader.cancel(task)\n            UiAction.Delete -> downloader.remove(task)\n            UiAction.Resume -> downloader.restart(task)\n            is UiAction.CopyErrorReport -> {\n                clipboardManager.setText(\n                    AnnotatedString(getErrorReport(action.throwable, task.url))\n                )\n                context.makeToast(R.string.error_copied)\n            }\n            UiAction.CopyVideoURL -> {\n                clipboardManager.setText(AnnotatedString(task.url))\n                context.makeToast(R.string.link_copied)\n            }\n            is UiAction.OpenFile -> {\n                action.filePath?.let {\n                    FileUtil.openFile(path = it) { context.makeToast(R.string.file_unavailable) }\n                }\n            }\n            is UiAction.OpenThumbnailURL -> {\n                uriHandler.openUri(action.url)\n            }\n            is UiAction.OpenVideoURL -> {\n                uriHandler.openUri(action.url)\n            }\n            is UiAction.ShareFile -> {\n                val shareTitle = context.getString(R.string.share)\n                FileUtil.createIntentForSharingFile(action.filePath)?.let {\n                    context.startActivity(Intent.createChooser(it, shareTitle))\n                }\n            }\n        }\n    }\n\n    var preferences by remember {\n        mutableStateOf(DownloadUtil.DownloadPreferences.createFromPreferences())\n    }\n    val sheetValue by dialogViewModel.sheetValueFlow.collectAsStateWithLifecycle()\n    val state by dialogViewModel.sheetStateFlow.collectAsStateWithLifecycle()\n\n    val selectionState = dialogViewModel.selectionStateFlow.collectAsStateWithLifecycle().value\n\n    var showDialog by remember { mutableStateOf(false) }\n    val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)\n\n    LaunchedEffect(sheetValue) {\n        if (sheetValue == DownloadDialogViewModel.SheetValue.Expanded) {\n            showDialog = true\n        } else {\n            launch { sheetState.hide() }.invokeOnCompletion { showDialog = false }\n        }\n    }\n\n    if (showDialog) {\n\n        DownloadDialog(\n            state = state,\n            sheetState = sheetState,\n            config = Config(),\n            preferences = preferences,\n            onPreferencesUpdate = { preferences = it },\n            onActionPost = { dialogViewModel.postAction(it) },\n        )\n    }\n    when (selectionState) {\n        is DownloadDialogViewModel.SelectionState.FormatSelection ->\n            FormatPage(\n                state = selectionState,\n                onDismissRequest = { dialogViewModel.postAction(Action.Reset) },\n            )\n\n        is DownloadDialogViewModel.SelectionState.PlaylistSelection -> {\n            PlaylistSelectionPage(\n                state = selectionState,\n                onDismissRequest = { dialogViewModel.postAction(Action.Reset) },\n            )\n        }\n\n        DownloadDialogViewModel.SelectionState.Idle -> {}\n    }\n}\n\n@Composable\nprivate operator fun PaddingValues.plus(other: PaddingValues): PaddingValues {\n    val layoutDirection = LocalLayoutDirection.current\n    return PaddingValues(\n        top = calculateTopPadding() + other.calculateTopPadding(),\n        bottom = calculateBottomPadding() + other.calculateBottomPadding(),\n        start =\n            calculateStartPadding(layoutDirection) + other.calculateStartPadding(layoutDirection),\n        end = calculateEndPadding(layoutDirection) + other.calculateEndPadding(layoutDirection),\n    )\n}\n\nprivate const val HeaderSpacingDp = 28\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadPageImplV2(\n    modifier: Modifier = Modifier,\n    taskDownloadStateMap: SnapshotStateMap<Task, Task.State>,\n    downloadCallback: () -> Unit = {},\n    onMenuOpen: (() -> Unit) = {},\n    onActionPost: (Task, UiAction) -> Unit,\n) {\n    var activeFilter by remember { mutableStateOf(Filter.All) }\n    val filteredMap by\n        remember(activeFilter) {\n            derivedStateOf { taskDownloadStateMap.filter { activeFilter.predict(it.toPair()) } }\n        }\n    val scope = rememberCoroutineScope()\n    val context = LocalContext.current\n\n    val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false)\n    var selectedTask by remember { mutableStateOf<Task?>(null) }\n    val view = LocalView.current\n\n    fun showActionSheet(task: Task) {\n        view.slightHapticFeedback()\n        scope.launch {\n            selectedTask = task\n            delay(50)\n            sheetState.show()\n        }\n    }\n\n    LaunchedEffect(selectedTask, taskDownloadStateMap.size) {\n        if (!taskDownloadStateMap.contains(selectedTask)) {\n            selectedTask == null\n        }\n    }\n\n    Scaffold(\n        modifier = modifier.fillMaxSize().statusBarsPadding(),\n        containerColor = MaterialTheme.colorScheme.surface,\n        floatingActionButton = { FABs(modifier = Modifier, downloadCallback = downloadCallback) },\n    ) { windowInsetsPadding ->\n        val lazyListState = rememberLazyGridState()\n        val windowWidthSizeClass = LocalWindowWidthState.current\n        val spacerHeight =\n            with(LocalDensity.current) {\n                if (windowWidthSizeClass != WindowWidthSizeClass.Compact) 0f\n                else HeaderSpacingDp.dp.toPx()\n            }\n        var headerOffset by remember { mutableFloatStateOf(spacerHeight) }\n        var isGridView by rememberSaveable { mutableStateOf(true) }\n\n        Column(\n            modifier =\n                Modifier.fillMaxSize()\n                    .then(\n                        if (windowWidthSizeClass != WindowWidthSizeClass.Compact) Modifier\n                        else\n                            Modifier.nestedScroll(\n                                connection =\n                                    TopBarNestedScrollConnection(\n                                        maxOffset = spacerHeight,\n                                        flingAnimationSpec = rememberSplineBasedDecay(),\n                                        offset = { headerOffset },\n                                        onOffsetUpdate = { headerOffset = it },\n                                    )\n                            )\n                    )\n        ) {\n            CompositionLocalProvider(LocalOverscrollFactory provides null) {\n                Column(modifier = Modifier.fillMaxWidth()) {\n                    Spacer(Modifier.height(with(LocalDensity.current) { headerOffset.toDp() }))\n                    Header(onMenuOpen = onMenuOpen, modifier = Modifier.padding(horizontal = 16.dp))\n                    SelectionGroupRow(\n                        modifier =\n                            Modifier.horizontalScroll(rememberScrollState())\n                                .padding(horizontal = 20.dp)\n                    ) {\n                        Filter.entries.forEach { filter ->\n                            SelectionGroupItem(\n                                colors =\n                                    SelectionGroupDefaults.colors(\n                                        activeContainerColor =\n                                            LocalFixedColorRoles.current.tertiaryFixed,\n                                        activeContentColor =\n                                            LocalFixedColorRoles.current.onTertiaryFixed,\n                                    ),\n                                selected = activeFilter == filter,\n                                onClick = {\n                                    if (activeFilter == filter) {\n                                        scope.launch { lazyListState.animateScrollToItem(0) }\n                                        scope.launch {\n                                            val initialValue = headerOffset\n                                            AnimationState(initialValue = initialValue).animateTo(\n                                                spacerHeight\n                                            ) {\n                                                headerOffset = value\n                                            }\n                                        }\n                                    } else {\n                                        activeFilter = filter\n                                    }\n                                },\n                            ) {\n                                Text(filter.label())\n                            }\n                        }\n                    }\n                    Spacer(Modifier.height(8.dp))\n                    if (headerOffset <= 0.1f && spacerHeight > 0f) {\n                        HorizontalDivider(thickness = Dp.Hairline)\n                    }\n                }\n\n                LazyVerticalGrid(\n                    modifier = Modifier,\n                    state = lazyListState,\n                    columns = GridCells.Adaptive(240.dp),\n                    contentPadding =\n                        windowInsetsPadding +\n                            PaddingValues(start = 20.dp, end = 20.dp, bottom = 80.dp),\n                    horizontalArrangement = Arrangement.spacedBy(24.dp),\n                ) {\n                    if (filteredMap.isNotEmpty()) {\n                        item(span = { GridItemSpan(maxLineSpan) }) {\n                            val videoCount =\n                                filteredMap.count {\n                                    !it.value.viewState.videoFormats.isNullOrEmpty()\n                                }\n                            SubHeader(\n                                modifier = Modifier,\n                                videoCount = videoCount,\n                                audioCount = filteredMap.size - videoCount,\n                                isGridView = isGridView,\n                                onToggleView = { isGridView = !isGridView },\n                                onShowMenu = { context.makeToast(\"Not implemented yet!\") },\n                            )\n                        }\n                    }\n\n                    if (isGridView) {\n                        items(\n                            items =\n                                filteredMap.toList().sortedBy { (_, state) -> state.downloadState },\n                            key = { (task, _) -> task.id },\n                        ) { (task, state) ->\n                            with(state.viewState) {\n                                VideoCardV2(\n                                    modifier = Modifier.padding(bottom = 20.dp).padding(),\n                                    viewState = this,\n                                    actionButton = {\n                                        ActionButton(\n                                            modifier = Modifier,\n                                            downloadState = state.downloadState,\n                                        ) {\n                                            onActionPost(task, it)\n                                        }\n                                    },\n                                    stateIndicator = {\n                                        CardStateIndicator(\n                                            modifier = Modifier,\n                                            downloadState = state.downloadState,\n                                        )\n                                    },\n                                    onButtonClick = { showActionSheet(task) },\n                                )\n                            }\n                        }\n                    } else {\n                        items(\n                            items =\n                                filteredMap.toList().sortedBy { (_, state) -> state.downloadState },\n                            key = { (task, _) -> task.id },\n                            span = { GridItemSpan(maxLineSpan) },\n                        ) { (task, state) ->\n                            VideoListItem(\n                                modifier = Modifier.padding(bottom = 16.dp),\n                                viewState = state.viewState,\n                                stateIndicator = {\n                                    ListItemStateText(\n                                        modifier = Modifier.padding(top = 3.dp),\n                                        downloadState = state.downloadState,\n                                    )\n                                },\n                                onButtonClick = { showActionSheet(task) },\n                            )\n                        }\n                    }\n                }\n            }\n        }\n        if (filteredMap.isEmpty()) {\n            Box(modifier = Modifier.fillMaxSize()) {\n                DownloadQueuePlaceholder(\n                    modifier =\n                        Modifier.fillMaxHeight(0.4f).widthIn(max = 360.dp).align(Alignment.Center)\n                )\n            }\n        }\n    }\n    if (selectedTask != null) {\n        val task = selectedTask!!\n        val (downloadState, _, viewState) = taskDownloadStateMap[task] ?: return\n        SealModalBottomSheet(\n            sheetState = sheetState,\n            contentPadding = PaddingValues(),\n            onDismissRequest = {\n                scope.launch { sheetState.hide() }.invokeOnCompletion { selectedTask = null }\n            },\n        ) {\n            SheetContent(\n                task = task,\n                downloadState = downloadState,\n                viewState = viewState,\n                onDismissRequest = {\n                    scope.launch { sheetState.hide() }.invokeOnCompletion { selectedTask = null }\n                },\n                onActionPost = onActionPost,\n            )\n        }\n    }\n}\n\n@Composable\nfun Header(modifier: Modifier = Modifier, onMenuOpen: () -> Unit = {}) {\n    val windowWidthSizeClass = LocalWindowWidthState.current\n    when (windowWidthSizeClass) {\n        WindowWidthSizeClass.Expanded -> {\n            HeaderExpanded(modifier = modifier)\n        }\n        else -> {\n            HeaderCompact(modifier = modifier, onMenuOpen = onMenuOpen)\n        }\n    }\n}\n\n@Composable\nprivate fun HeaderCompact(modifier: Modifier = Modifier, onMenuOpen: () -> Unit) {\n\n    Row(modifier = modifier.height(64.dp), verticalAlignment = Alignment.CenterVertically) {\n        IconButton(onClick = onMenuOpen, modifier = Modifier) {\n            Icon(\n                imageVector = Icons.Outlined.Menu,\n                contentDescription = stringResource(R.string.show_navigation_drawer),\n                modifier = Modifier,\n            )\n        }\n        Spacer(modifier = Modifier.width(4.dp))\n        Text(\n            stringResource(R.string.download_queue),\n            style =\n                MaterialTheme.typography.titleLarge.copy(\n                    fontSize = 20.sp,\n                    fontWeight = FontWeight.Medium,\n                ),\n        )\n    }\n}\n\n@Composable\nprivate fun HeaderExpanded(modifier: Modifier = Modifier) {\n    Row(modifier = modifier.height(64.dp), verticalAlignment = Alignment.CenterVertically) {\n        Spacer(modifier = Modifier.width(4.dp))\n        Text(\n            stringResource(R.string.download_queue),\n            style = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Medium),\n        )\n    }\n    Spacer(Modifier.height(4.dp))\n}\n\n@Composable\nfun FABs(modifier: Modifier = Modifier, downloadCallback: () -> Unit = {}) {\n    val expanded = LocalWindowWidthState.current != WindowWidthSizeClass.Compact\n    Column(modifier = modifier.padding(6.dp), horizontalAlignment = Alignment.End) {\n        FloatingActionButton(\n            onClick = downloadCallback,\n            content = {\n                if (expanded) {\n                    Row(\n                        modifier = Modifier.widthIn(min = 80.dp).padding(horizontal = 16.dp),\n                        verticalAlignment = Alignment.CenterVertically,\n                    ) {\n                        Icon(Icons.Outlined.FileDownload, contentDescription = null)\n                        Spacer(Modifier.width(12.dp))\n                        Text(stringResource(R.string.download))\n                    }\n                } else {\n                    Icon(\n                        Icons.Outlined.FileDownload,\n                        contentDescription = stringResource(R.string.download),\n                    )\n                }\n            },\n            modifier = Modifier.padding(vertical = 12.dp),\n        )\n    }\n}\n\n@Composable\n@Preview\nprivate fun DownloadQueuePlaceholder(modifier: Modifier = Modifier) {\n    BoxWithConstraints(modifier = modifier) {\n        ConstraintLayout {\n            val (image, text) = createRefs()\n            val showImage =\n                with(LocalDensity.current) {\n                    this@BoxWithConstraints.constraints.maxHeight >= 240.dp.toPx()\n                }\n            if (showImage) {\n                Image(\n                    painter = rememberVectorPainter(image = DynamicColorImageVectors.download()),\n                    contentDescription = null,\n                    modifier =\n                        Modifier.fillMaxHeight(0.5f).widthIn(max = 240.dp).constrainAs(image) {\n                            top.linkTo(parent.top)\n                            bottom.linkTo(parent.bottom)\n                            start.linkTo(parent.start)\n                            end.linkTo(parent.end)\n                        },\n                )\n            } else {\n                Spacer(Modifier.height(72.dp).constrainAs(image) { top.linkTo(parent.top) })\n            }\n            Column(\n                modifier = Modifier.constrainAs(text) { top.linkTo(image.bottom, margin = 36.dp) },\n                horizontalAlignment = Alignment.CenterHorizontally,\n            ) {\n                Text(\n                    text = stringResource(R.string.you_ll_find_your_downloads_here),\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                    style = MaterialTheme.typography.titleMedium,\n                    color = MaterialTheme.colorScheme.onSurface,\n                )\n                Text(\n                    text = stringResource(R.string.download_hint),\n                    modifier = Modifier.padding(top = 4.dp).padding(horizontal = 24.dp),\n                    style = MaterialTheme.typography.bodyMedium,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    textAlign = TextAlign.Center,\n                )\n            }\n        }\n    }\n}\n\n@Composable\nfun SubHeader(\n    modifier: Modifier = Modifier,\n    containerColor: Color =\n        MaterialTheme.colorScheme.run {\n            if (LocalDarkTheme.current.isDarkTheme()) surfaceContainer else surfaceContainerLowest\n        },\n    videoCount: Int = 0,\n    audioCount: Int = 0,\n    isGridView: Boolean = true,\n    onToggleView: () -> Unit,\n    onShowMenu: () -> Unit,\n) {\n    val text = buildString {\n        if (videoCount > 0) {\n            append(pluralStringResource(R.plurals.video_count, videoCount).format(videoCount))\n            if (audioCount > 0) {\n                append(\", \")\n            }\n        }\n        if (audioCount > 0) {\n            append(pluralStringResource(R.plurals.audio_count, audioCount).format(audioCount))\n        }\n    }\n\n    Row(\n        modifier = modifier.padding(top = 12.dp, bottom = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        Row(\n            modifier = Modifier.padding(start = 8.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            Text(text = text, style = MaterialTheme.typography.labelLarge)\n            Spacer(Modifier.width(4.dp))\n        }\n\n        Spacer(modifier = Modifier.weight(1f))\n\n        FilledIconButton(\n            onClick = onToggleView,\n            modifier = Modifier.clearAndSetSemantics {}.size(32.dp),\n            colors = IconButtonDefaults.filledIconButtonColors(containerColor = containerColor),\n        ) {\n            Icon(\n                imageVector =\n                    if (isGridView) Icons.AutoMirrored.Outlined.List else Icons.Outlined.GridView,\n                contentDescription = null,\n                modifier = Modifier.size(16.dp),\n            )\n        }\n\n        Spacer(Modifier.width(4.dp))\n\n        FilledIconButton(\n            onClick = onShowMenu,\n            modifier = Modifier.clearAndSetSemantics {}.size(32.dp),\n            colors = IconButtonDefaults.filledIconButtonColors(containerColor = containerColor),\n        ) {\n            Icon(\n                imageVector = Icons.Outlined.MoreVert,\n                contentDescription = null,\n                modifier = Modifier.size(16.dp),\n            )\n        }\n    }\n}\n\ninternal class DownloadPageV2Test {\n    private val mockDownloader =\n        object : DownloaderV2 {\n            private val map = mutableStateMapOf<Task, Task.State>()\n\n            init {\n                val viewState =\n                    Task.ViewState(title = \"Sample title\", uploader = \"dummy video uploader\")\n                val list =\n                    listOf(\n                        Task.State(Idle, null, viewState),\n                        Task.State(Canceled(Task.RestartableAction.Download), null, viewState),\n                        Task.State(Completed(null), null, viewState),\n                    )\n                map.run {\n                    repeat(9) {\n                        put(Task(url = \"$it\", preferences = PreferencesMock), list[it % 3])\n                    }\n                }\n                val scope = CoroutineScope(SupervisorJob())\n\n                scope.launch(Dispatchers.Default) {\n                    while (true) {\n                        delay(1000)\n                        val newEntries =\n                            map.toMap().map { (task, state) ->\n                                val newDownloadState =\n                                    when (state.downloadState) {\n                                        is Canceled -> Idle\n                                        is Completed -> Idle\n                                        is Error -> Idle\n                                        is FetchingInfo -> ReadyWithInfo\n                                        Idle -> FetchingInfo(Job(), task.id)\n                                        ReadyWithInfo -> Running(Job(), task.id)\n                                        is Running -> {\n                                            val preState: Running = state.downloadState\n                                            if (preState.progress >= 1f) Completed(null)\n                                            else preState.copy(progress = preState.progress + 0.1f)\n                                        }\n                                    }\n                                task to state.copy(downloadState = newDownloadState)\n                            }\n                        Snapshot.withMutableSnapshot {\n                            newEntries.forEach { (task, state) ->\n                                delay(100)\n                                map[task] = state\n                            }\n                        }\n                    }\n                }\n            }\n\n            override fun getTaskStateMap(): SnapshotStateMap<Task, Task.State> {\n                return map\n            }\n\n            override fun cancel(task: Task): Boolean {\n                return false\n            }\n\n            override fun restart(task: Task) {}\n\n            override fun enqueue(task: Task) {}\n\n            override fun enqueue(task: Task, state: Task.State) {}\n\n            override fun remove(task: Task): Boolean {\n                return true\n            }\n        }\n\n    @Composable\n    @Preview(name = \"Light\", uiMode = Configuration.UI_MODE_NIGHT_NO)\n    @Preview(name = \"Tablet\", device = \"spec:width=600dp,height=800dp,dpi=240\")\n    private fun Preview() {\n\n        val downloader: DownloaderV2 = mockDownloader\n        SealTheme {\n            Column() {\n                DownloadPageImplV2(\n                    taskDownloadStateMap = downloader.getTaskStateMap(),\n                    onActionPost = { task, state -> },\n                    onMenuOpen = {},\n                )\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/TopBarNestedScrollConnection.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2\n\nimport androidx.compose.animation.core.AnimationState\nimport androidx.compose.animation.core.DecayAnimationSpec\nimport androidx.compose.animation.core.animateDecay\nimport androidx.compose.ui.geometry.Offset\nimport androidx.compose.ui.input.nestedscroll.NestedScrollConnection\nimport androidx.compose.ui.input.nestedscroll.NestedScrollSource\nimport androidx.compose.ui.unit.Velocity\nimport kotlin.math.abs\n\nprivate const val TAG = \"TopBarNestedScrollConne\"\n\n/*\n offset < 0 = scroll down, finger & content going upward\n offset > 0 = scroll up, finger & content going downward\n*/\n\ninternal class TopBarNestedScrollConnection(\n    private val maxOffset: Float,\n    private val flingAnimationSpec: DecayAnimationSpec<Float>,\n    private val offset: () -> Float,\n    private val onOffsetUpdate: (Float) -> Unit,\n) : NestedScrollConnection {\n    override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {\n        val delta = available.y\n        if (delta < 0f) {\n            val previousOffset = offset()\n            if (previousOffset >= 0) {\n                val newOffset = (previousOffset + delta).coerceIn(0f, maxOffset)\n                onOffsetUpdate(newOffset)\n                val consumedOffset = newOffset - previousOffset\n                return Offset(x = 0f, y = consumedOffset)\n            }\n        }\n        return super.onPreScroll(available, source)\n    }\n\n    override fun onPostScroll(\n        consumed: Offset,\n        available: Offset,\n        source: NestedScrollSource,\n    ): Offset {\n        val delta = available.y\n        val consumedY = consumed.y\n        val previousOffset = offset()\n\n        if (delta < 0f || consumedY < 0f) {\n            if (previousOffset >= 0) {\n                val newOffset = (previousOffset + consumedY).coerceIn(0f, maxOffset)\n                onOffsetUpdate(newOffset)\n                val consumedOffset = newOffset - previousOffset\n                return Offset(0f, consumedOffset)\n            }\n        }\n        if (delta > 0f) {\n            val newOffset = (previousOffset + delta).coerceIn(0f, maxOffset)\n            onOffsetUpdate(newOffset)\n            val consumedOffset = newOffset - previousOffset\n            return Offset(0f, consumedOffset)\n        }\n\n        return super.onPostScroll(consumed, available, source)\n    }\n\n    override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {\n        val superConsumed = super.onPostFling(consumed, available)\n        return superConsumed + settleAppBar(available.y)\n    }\n\n    private suspend fun settleAppBar(velocity: Float): Velocity {\n        if (offset() < 0.01f) {\n            return Velocity.Zero\n        }\n        var remainingVelocity = velocity\n\n        if (abs(velocity) > 1f) {\n            var lastValue = 0f\n            AnimationState(initialValue = 0f, initialVelocity = velocity).animateDecay(\n                flingAnimationSpec\n            ) {\n                val delta = value - lastValue\n                val newOffset = (offset() + delta).coerceIn(0f, maxOffset)\n\n                onOffsetUpdate(newOffset)\n                val consumed = abs(newOffset - offset())\n                lastValue = value\n                remainingVelocity = this.velocity\n                // avoid rounding errors and stop if anything is unconsumed\n                if (abs(delta - consumed) > 0.5f) this.cancelAnimation()\n            }\n        }\n        return Velocity(0f, remainingVelocity)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/VideoCardV2.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2\n\nimport android.content.res.Configuration\nimport androidx.compose.animation.AnimatedContent\nimport androidx.compose.animation.core.animateFloatAsState\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.BoxScope\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.IntrinsicSize\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.offset\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.filled.CheckCircle\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material.icons.rounded.Download\nimport androidx.compose.material.icons.rounded.Error\nimport androidx.compose.material.icons.rounded.Pause\nimport androidx.compose.material.icons.rounded.PlayArrow\nimport androidx.compose.material.icons.rounded.RestartAlt\nimport androidx.compose.material3.Card\nimport androidx.compose.material3.CardDefaults\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.FilledIconButton\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.IconButtonDefaults\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.ProgressIndicatorDefaults\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.draw.drawBehind\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.Task\nimport com.junkfood.seal.download.Task.DownloadState.Canceled\nimport com.junkfood.seal.download.Task.DownloadState.Completed\nimport com.junkfood.seal.download.Task.DownloadState.Error\nimport com.junkfood.seal.download.Task.DownloadState.FetchingInfo\nimport com.junkfood.seal.download.Task.DownloadState.Idle\nimport com.junkfood.seal.download.Task.DownloadState.ReadyWithInfo\nimport com.junkfood.seal.download.Task.DownloadState.Running\nimport com.junkfood.seal.download.Task.RestartableAction\nimport com.junkfood.seal.ui.common.AsyncImageImpl\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.junkfood.seal.ui.common.motion.materialSharedAxisY\nimport com.junkfood.seal.ui.component.GreenTonalPalettes\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.toDurationText\nimport com.junkfood.seal.util.toFileSizeText\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.delay\n\nprivate val IconButtonSize = 64.dp\nprivate val IconSize = 36.dp\nprivate val ActionButtonContainerColor: Color\n    @Composable get() = LocalFixedColorRoles.current.onSecondaryFixed.copy(alpha = 0.68f)\nprivate val ActionButtonContentColor: Color\n    @Composable get() = LocalFixedColorRoles.current.secondaryFixed\nprivate val LabelContainerColor: Color = Color.Black.copy(alpha = 0.68f)\n\n@Composable\nfun VideoCardV2(\n    modifier: Modifier = Modifier,\n    viewState: Task.ViewState,\n    stateIndicator: @Composable (BoxScope.() -> Unit)? = null,\n    actionButton: @Composable (BoxScope.() -> Unit)? = null,\n    onButtonClick: () -> Unit,\n) {\n    with(viewState) {\n        VideoCardV2(\n            modifier = modifier,\n            thumbnailModel = thumbnailUrl,\n            title = title,\n            uploader = uploader,\n            duration = duration,\n            fileSizeApprox = fileSizeApprox,\n            stateIndicator = stateIndicator,\n            actionButton = actionButton,\n            onButtonClick = onButtonClick,\n        )\n    }\n}\n\n@Composable\nfun VideoListItem(\n    modifier: Modifier = Modifier,\n    viewState: Task.ViewState,\n    stateIndicator: @Composable (() -> Unit)? = null,\n    onButtonClick: () -> Unit,\n) {\n    with(viewState) {\n        VideoListItem(\n            modifier = modifier,\n            thumbnailModel = thumbnailUrl,\n            title = title,\n            uploader = uploader,\n            duration = duration,\n            fileSizeApprox = fileSizeApprox,\n            stateIndicator = stateIndicator,\n            onButtonClick = onButtonClick,\n        )\n    }\n}\n\n@Composable\nfun VideoListItem(\n    modifier: Modifier = Modifier,\n    thumbnailModel: Any? = null,\n    title: String = \"\",\n    uploader: String = \"\",\n    duration: Int = 0,\n    fileSizeApprox: Double = .0,\n    stateIndicator: @Composable (() -> Unit)? = null,\n    onButtonClick: () -> Unit,\n) {\n    Row(modifier = modifier.height(IntrinsicSize.Min), verticalAlignment = Alignment.Top) {\n        Box(modifier = Modifier) {\n            ListItemImage(modifier = Modifier, thumbnailModel = thumbnailModel)\n            VideoInfoLabel(\n                modifier = Modifier.align(Alignment.BottomEnd),\n                duration = duration,\n                fileSizeApprox = fileSizeApprox,\n            )\n        }\n        Box {\n            Column(modifier = Modifier.fillMaxSize().padding(horizontal = 12.dp)) {\n                TitleText(\n                    modifier = Modifier,\n                    title = title,\n                    uploader = uploader,\n                    contentPadding = PaddingValues(),\n                )\n                Spacer(modifier = Modifier.height(4.dp))\n                stateIndicator?.invoke()\n            }\n            IconButton(\n                onButtonClick,\n                modifier = Modifier.align(Alignment.BottomEnd).offset(x = 8.dp, y = 8.dp),\n            ) {\n                Icon(\n                    imageVector = Icons.Outlined.MoreVert,\n                    contentDescription = stringResource(R.string.show_more_actions),\n                    modifier = Modifier.size(20.dp),\n                )\n            }\n        }\n    }\n}\n\n@Preview\n@Composable\n@Preview(name = \"Dark Mode\", uiMode = Configuration.UI_MODE_NIGHT_YES)\nprivate fun VideoListItemPreview() {\n    SealTheme {\n        val fakeStateList =\n            listOf(\n                Running(Job(), \"\", 0.58f),\n                Error(throwable = Throwable(), RestartableAction.Download),\n                FetchingInfo(Job(), \"\"),\n                Canceled(RestartableAction.Download),\n                ReadyWithInfo,\n                Idle,\n                Completed(null),\n            )\n\n        var downloadState: Task.DownloadState by remember { mutableStateOf(Idle) }\n\n        LaunchedEffect(Unit) {\n            fakeStateList.forEach {\n                delay(2000)\n                downloadState = it\n            }\n        }\n\n        Surface {\n            VideoListItem(\n                modifier = Modifier.padding(vertical = 8.dp, horizontal = 20.dp),\n                thumbnailModel = R.drawable.sample3,\n                title = stringResource(R.string.video_title_sample_text),\n                uploader = stringResource(R.string.video_creator_sample_text),\n                stateIndicator = {\n                    ListItemStateText(\n                        modifier = Modifier.padding(top = 3.dp),\n                        downloadState = downloadState,\n                    )\n                },\n            ) {}\n        }\n    }\n}\n\n@Composable\nfun VideoCardV2(\n    modifier: Modifier = Modifier,\n    thumbnailModel: Any? = null,\n    title: String = \"\",\n    uploader: String = \"\",\n    duration: Int = 0,\n    fileSizeApprox: Double = .0,\n    stateIndicator: @Composable (BoxScope.() -> Unit)? = null,\n    actionButton: @Composable (BoxScope.() -> Unit)? = null,\n    onButtonClick: () -> Unit,\n) {\n    val containerColor =\n        MaterialTheme.colorScheme.run {\n            if (LocalDarkTheme.current.isDarkTheme()) surfaceContainer else surfaceContainerLowest\n        }\n\n    Card(\n        modifier = modifier.fillMaxWidth(),\n        colors = CardDefaults.cardColors(containerColor = containerColor),\n    ) {\n        Column {\n            Box(Modifier.fillMaxWidth()) {\n                CardImage(modifier = Modifier, thumbnailModel = thumbnailModel)\n                Box(Modifier.align(Alignment.TopStart)) { stateIndicator?.invoke(this) }\n                Box(Modifier.align(Alignment.Center)) { actionButton?.invoke(this) }\n                VideoInfoLabel(\n                    modifier = Modifier.align(Alignment.BottomEnd),\n                    duration = duration,\n                    fileSizeApprox = fileSizeApprox,\n                )\n            }\n            Row(modifier = Modifier.fillMaxWidth()) {\n                TitleText(modifier = Modifier.weight(1f), title = title, uploader = uploader)\n                IconButton(onButtonClick, modifier = Modifier.align(Alignment.CenterVertically)) {\n                    Icon(\n                        imageVector = Icons.Outlined.MoreVert,\n                        contentDescription = stringResource(R.string.show_more_actions),\n                        modifier = Modifier.size(20.dp),\n                    )\n                }\n            }\n        }\n    }\n}\n\n@Composable\n@Preview\n@Preview(name = \"Dark Mode\", uiMode = Configuration.UI_MODE_NIGHT_YES)\nfun VideoCardV2Preview() {\n    SealTheme {\n        val downloadState = Error(throwable = Throwable(), action = RestartableAction.Download)\n        VideoCardV2(\n            thumbnailModel = R.drawable.sample3,\n            title = stringResource(R.string.video_title_sample_text),\n            uploader = stringResource(R.string.video_creator_sample_text),\n            actionButton = { ActionButton(modifier = Modifier, downloadState = downloadState) {} },\n            stateIndicator = {\n                CardStateIndicator(modifier = Modifier, downloadState = downloadState)\n            },\n        ) {}\n    }\n}\n\n@Composable\nprivate fun CardImage(modifier: Modifier = Modifier, thumbnailModel: Any? = null) {\n    if (thumbnailModel != null) {\n        AsyncImageImpl(\n            modifier =\n                modifier\n                    .padding()\n                    .fillMaxWidth()\n                    .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true),\n            model = thumbnailModel,\n            contentDescription = null,\n            contentScale = ContentScale.Crop,\n        )\n    } else {\n        Surface(\n            modifier =\n                modifier\n                    .padding()\n                    .fillMaxWidth()\n                    .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true),\n            color = MaterialTheme.colorScheme.surfaceContainerHighest,\n        ) {}\n    }\n}\n\n@Composable\nprivate fun ListItemImage(modifier: Modifier = Modifier, thumbnailModel: Any? = null) {\n    if (thumbnailModel != null) {\n        AsyncImageImpl(\n            model = thumbnailModel,\n            modifier =\n                Modifier.width(160.dp)\n                    .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true)\n                    .clip(MaterialTheme.shapes.extraSmall),\n            contentScale = ContentScale.Crop,\n            contentDescription = null,\n        )\n    } else {\n        Box(\n            modifier =\n                modifier\n                    .width(160.dp)\n                    .aspectRatio(16f / 9f, matchHeightConstraintsFirst = true)\n                    .clip(MaterialTheme.shapes.extraSmall)\n                    .background(MaterialTheme.colorScheme.surfaceContainerHighest)\n        ) {}\n    }\n}\n\n@Composable\nprivate fun TitleText(\n    modifier: Modifier = Modifier,\n    title: String,\n    uploader: String,\n    contentPadding: PaddingValues = PaddingValues(12.dp),\n) {\n    Column(\n        modifier = modifier.padding(contentPadding),\n        horizontalAlignment = Alignment.Start,\n        verticalArrangement = Arrangement.Top,\n    ) {\n        Text(\n            text = title,\n            style = MaterialTheme.typography.titleSmall,\n            maxLines = 2,\n            overflow = TextOverflow.Ellipsis,\n        )\n        Text(\n            modifier = Modifier.padding(top = 3.dp),\n            text = uploader,\n            style = MaterialTheme.typography.bodySmall,\n            color = MaterialTheme.colorScheme.onSurfaceVariant,\n            maxLines = 1,\n            overflow = TextOverflow.Ellipsis,\n        )\n    }\n}\n\n@Composable\nprivate fun VideoInfoLabel(modifier: Modifier = Modifier, duration: Int, fileSizeApprox: Double) {\n    Surface(\n        modifier = modifier.padding(4.dp),\n        color = LabelContainerColor,\n        shape = MaterialTheme.shapes.extraSmall,\n    ) {\n        val fileSizeText = fileSizeApprox.toFileSizeText()\n        val durationText = duration.toDurationText()\n        Text(\n            modifier = Modifier.padding(horizontal = 4.dp),\n            text = \"$fileSizeText  $durationText\",\n            style = MaterialTheme.typography.labelSmall,\n            color = Color.White,\n        )\n    }\n}\n\n@Composable\nfun CardStateIndicator(modifier: Modifier = Modifier, downloadState: Task.DownloadState) {\n    Surface(\n        modifier = modifier.padding(vertical = 12.dp, horizontal = 8.dp),\n        color = LabelContainerColor,\n        shape = MaterialTheme.shapes.extraSmall,\n    ) {\n        CardItemStateText(\n            modifier = Modifier.padding(horizontal = 4.dp),\n            downloadState = downloadState,\n        )\n    }\n}\n\n@Composable\nfun ListItemStateText(\n    modifier: Modifier = Modifier,\n    isDarkTheme: Boolean = LocalDarkTheme.current.isDarkTheme(),\n    downloadState: Task.DownloadState,\n) {\n    val sizeModifier = Modifier.size(14.dp)\n\n    AnimatedContent(\n        downloadState,\n        transitionSpec = {\n            materialSharedAxisY(initialOffsetY = { it / 5 }, targetOffsetY = { -it / 5 })\n        },\n        contentKey = { it::class.simpleName },\n    ) { downloadState ->\n        val text =\n            when (downloadState) {\n                is Canceled -> stringResource(R.string.status_canceled)\n                is Completed -> stringResource(R.string.status_downloaded)\n                is Error -> stringResource(R.string.status_error)\n                is FetchingInfo -> stringResource(R.string.status_fetching_video_info)\n                Idle -> stringResource(R.string.status_enqueued)\n                ReadyWithInfo -> stringResource(R.string.status_enqueued)\n                is Running -> {\n                    val progress = downloadState.progress\n                    if (progress >= 0) {\n                        \"%.1f %%\".format(downloadState.progress * 100)\n                    } else {\n                        stringResource(R.string.status_downloading)\n                    }\n                }\n            }\n        Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {\n            when (downloadState) {\n                is Canceled -> {\n                    Icon(\n                        imageVector = Icons.Outlined.Cancel,\n                        contentDescription = null,\n                        tint = MaterialTheme.colorScheme.onSurfaceVariant,\n                        modifier = sizeModifier,\n                    )\n                }\n                is Completed -> {\n                    val color = GreenTonalPalettes.accent1(if (isDarkTheme) 80.0 else 40.0)\n                    Icon(\n                        imageVector = Icons.Filled.CheckCircle,\n                        contentDescription = null,\n                        tint = color,\n                        modifier = sizeModifier,\n                    )\n                }\n                is Error -> {\n                    Icon(\n                        imageVector = Icons.Rounded.Error,\n                        contentDescription = null,\n                        tint = MaterialTheme.colorScheme.error,\n                        modifier = sizeModifier,\n                    )\n                }\n                is FetchingInfo,\n                Idle,\n                ReadyWithInfo -> {\n                    CircularProgressIndicator(modifier = sizeModifier, strokeWidth = 2.5.dp)\n                }\n                is Running -> {\n                    val progress = downloadState.progress\n                    CircularProgressIndicator(\n                        progress = { progress },\n                        modifier = sizeModifier,\n                        strokeWidth = 2.5.dp,\n                    )\n                }\n            }\n\n            Spacer(Modifier.width(8.dp))\n\n            Text(\n                text = text,\n                modifier = Modifier,\n                style = MaterialTheme.typography.labelMedium.merge(letterSpacing = 0.sp),\n                color = MaterialTheme.colorScheme.onSurfaceVariant,\n            )\n        }\n    }\n}\n\n@Composable\nprivate fun CardItemStateText(modifier: Modifier = Modifier, downloadState: Task.DownloadState) {\n    val errorColor =\n        MaterialTheme.colorScheme.run {\n            if (LocalDarkTheme.current.isDarkTheme()) error else errorContainer\n        }\n    val textStyle = MaterialTheme.typography.labelSmall\n    val contentColor = Color.White\n\n    val text =\n        when (downloadState) {\n            is Canceled -> R.string.status_canceled\n            is Completed -> R.string.status_downloaded\n            is Error -> R.string.status_error\n            is FetchingInfo -> R.string.status_fetching_video_info\n            Idle -> R.string.status_enqueued\n            ReadyWithInfo -> R.string.status_enqueued\n            is Running -> R.string.status_downloading\n        }\n    Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {\n        if (downloadState is Error) {\n            Icon(\n                imageVector = Icons.Rounded.Error,\n                contentDescription = null,\n                tint = errorColor,\n                modifier = Modifier.size(12.dp),\n            )\n            Spacer(Modifier.width(4.dp))\n        }\n        Text(\n            text = stringResource(id = text),\n            modifier = Modifier,\n            style = textStyle,\n            color = contentColor,\n        )\n    }\n}\n\n@Composable\nfun ActionButton(\n    modifier: Modifier = Modifier,\n    downloadState: Task.DownloadState,\n    onActionPost: (UiAction) -> Unit,\n) =\n    when (downloadState) {\n        is Error -> {\n            RestartButton(modifier = modifier) { onActionPost(UiAction.Resume) }\n        }\n        is Canceled -> {\n            ResumeButton(modifier = modifier, downloadState.progress) {\n                onActionPost(UiAction.Resume)\n            }\n        }\n        is Completed -> {\n            PlayVideoButton(modifier = modifier) {\n                onActionPost(UiAction.OpenFile(downloadState.filePath))\n            }\n        }\n        is FetchingInfo,\n        ReadyWithInfo,\n        Idle -> {\n            ProgressButton(modifier = modifier, progress = -1f) { onActionPost(UiAction.Cancel) }\n        }\n        is Running -> {\n            ProgressButton(modifier = modifier, progress = downloadState.progress) {\n                onActionPost(UiAction.Cancel)\n            }\n        }\n    }\n\n@Composable\nprivate fun ResumeButton(\n    modifier: Modifier = Modifier,\n    progress: Float? = null,\n    onClick: () -> Unit,\n) {\n    val background = ActionButtonContainerColor\n\n    Box(\n        modifier =\n            modifier\n                .size(IconButtonSize)\n                .clip(CircleShape)\n                .drawBehind { drawCircle(background) }\n                .clickable(onClickLabel = stringResource(R.string.cancel), onClick = onClick)\n    ) {\n        if (progress != null) {\n            CircularProgressIndicator(\n                progress = { progress },\n                modifier = Modifier.size(IconButtonSize).align(Alignment.Center),\n                color = ActionButtonContentColor,\n                trackColor = Color.Transparent,\n                gapSize = 0.dp,\n            )\n        }\n        Icon(\n            imageVector = Icons.Rounded.Download,\n            contentDescription = stringResource(R.string.restart),\n            modifier = Modifier.size(IconSize).align(Alignment.Center),\n            tint = ActionButtonContentColor,\n        )\n    }\n}\n\n@Composable\nfun RestartButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    val background = ActionButtonContainerColor\n\n    Box(\n        modifier =\n            modifier\n                .size(IconButtonSize)\n                .clip(CircleShape)\n                .drawBehind { drawCircle(background) }\n                .clickable(onClickLabel = stringResource(R.string.cancel), onClick = onClick)\n    ) {\n        Icon(\n            imageVector = Icons.Rounded.RestartAlt,\n            contentDescription = stringResource(R.string.restart),\n            modifier = Modifier.size(IconSize).align(Alignment.Center),\n            tint = ActionButtonContentColor,\n        )\n    }\n}\n\n@Composable\nprivate fun PlayVideoButton(modifier: Modifier = Modifier, onClick: () -> Unit) {\n    FilledIconButton(\n        onClick = onClick,\n        modifier = modifier.size(IconButtonSize),\n        colors =\n            IconButtonDefaults.filledIconButtonColors(\n                containerColor = ActionButtonContainerColor,\n                contentColor = ActionButtonContentColor,\n            ),\n    ) {\n        Icon(\n            imageVector = Icons.Rounded.PlayArrow,\n            contentDescription = stringResource(R.string.open_file),\n            modifier = Modifier.size(IconSize),\n        )\n    }\n}\n\n@Composable\nprivate fun ProgressButton(modifier: Modifier = Modifier, progress: Float, onClick: () -> Unit) {\n    val animatedProgress by\n        animateFloatAsState(\n            progress,\n            animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,\n            label = \"progress\",\n        )\n    val background = ActionButtonContainerColor\n\n    Box(\n        modifier =\n            modifier\n                .size(IconButtonSize)\n                .clip(CircleShape)\n                .drawBehind { drawCircle(background) }\n                .clickable(onClickLabel = stringResource(R.string.cancel), onClick = onClick)\n    ) {\n        if (progress < 0) {\n            CircularProgressIndicator(\n                modifier = Modifier.size(IconButtonSize).align(Alignment.Center),\n                color = ActionButtonContentColor,\n                trackColor = Color.Transparent,\n            )\n        } else {\n            CircularProgressIndicator(\n                { animatedProgress },\n                modifier = Modifier.size(IconButtonSize).align(Alignment.Center),\n                color = ActionButtonContentColor,\n                gapSize = 0.dp,\n                trackColor = Color.Transparent,\n            )\n        }\n        Icon(\n            imageVector = Icons.Rounded.Pause,\n            contentDescription = null,\n            modifier = Modifier.align(Alignment.Center).size(IconSize),\n            tint = ActionButtonContentColor,\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/configure/DownloadDialogV2.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2.configure\n\nimport androidx.activity.compose.BackHandler\nimport androidx.compose.animation.AnimatedContent\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.Crossfade\nimport androidx.compose.animation.animateColorAsState\nimport androidx.compose.animation.animateContentSize\nimport androidx.compose.animation.core.Spring\nimport androidx.compose.animation.core.VisibilityThreshold\nimport androidx.compose.animation.core.animateDpAsState\nimport androidx.compose.animation.core.spring\nimport androidx.compose.animation.core.tween\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.togetherWith\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.heightIn\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.foundation.lazy.rememberLazyListState\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.shape.RoundedCornerShape\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.filled.ArrowForward\nimport androidx.compose.material.icons.filled.DownloadDone\nimport androidx.compose.material.icons.filled.SettingsSuggest\nimport androidx.compose.material.icons.filled.VideoFile\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.Code\nimport androidx.compose.material.icons.outlined.DoneAll\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.ErrorOutline\nimport androidx.compose.material.icons.outlined.ExpandMore\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material.icons.outlined.NewLabel\nimport androidx.compose.material.icons.outlined.SettingsSuggest\nimport androidx.compose.material.icons.outlined.VideoFile\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.ButtonDefaults\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilledTonalButton\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.SegmentedButtonDefaults\nimport androidx.compose.material3.SheetState\nimport androidx.compose.material3.SheetValue\nimport androidx.compose.material3.SingleChoiceSegmentedButtonRow\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.alpha\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.Dp\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.HapticFeedback.longPressHapticFeedback\nimport com.junkfood.seal.ui.common.motion.materialSharedAxisX\nimport com.junkfood.seal.ui.component.ButtonChip\nimport com.junkfood.seal.ui.component.DrawerSheetSubtitle\nimport com.junkfood.seal.ui.component.OutlinedButtonWithIcon\nimport com.junkfood.seal.ui.component.SealModalBottomSheet\nimport com.junkfood.seal.ui.component.SealModalBottomSheetM2Variant\nimport com.junkfood.seal.ui.component.SingleChoiceChip\nimport com.junkfood.seal.ui.component.SingleChoiceSegmentedButton\nimport com.junkfood.seal.ui.component.VideoFilterChip\nimport com.junkfood.seal.ui.page.command.TemplatePickerDialog\nimport com.junkfood.seal.ui.page.downloadv2.configure.ActionButton.Download\nimport com.junkfood.seal.ui.page.downloadv2.configure.ActionButton.FetchInfo\nimport com.junkfood.seal.ui.page.downloadv2.configure.ActionButton.StartTask\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.Action\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SelectionState\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SheetState.Configure\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SheetState.Error\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SheetState.InputUrl\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SheetState.Loading\nimport com.junkfood.seal.ui.page.settings.command.CommandTemplateDialog\nimport com.junkfood.seal.ui.page.settings.format.AudioQuickSettingsDialog\nimport com.junkfood.seal.ui.page.settings.format.VideoQuickSettingsDialog\nimport com.junkfood.seal.ui.page.settings.network.CookiesQuickSettingsDialog\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.AUDIO_CONVERSION_FORMAT\nimport com.junkfood.seal.util.AUDIO_CONVERT\nimport com.junkfood.seal.util.AUDIO_FORMAT\nimport com.junkfood.seal.util.AUDIO_QUALITY\nimport com.junkfood.seal.util.COOKIES\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DatabaseUtil\nimport com.junkfood.seal.util.DownloadType\nimport com.junkfood.seal.util.DownloadType.Audio\nimport com.junkfood.seal.util.DownloadType.Command\nimport com.junkfood.seal.util.DownloadType.Playlist\nimport com.junkfood.seal.util.DownloadType.Video\nimport com.junkfood.seal.util.DownloadType.entries\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FORMAT_SELECTION\nimport com.junkfood.seal.util.PreferenceStrings\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.SUBTITLE\nimport com.junkfood.seal.util.TEMPLATE_ID\nimport com.junkfood.seal.util.THUMBNAIL\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.USE_CUSTOM_AUDIO_PRESET\nimport com.junkfood.seal.util.VIDEO_FORMAT\nimport com.junkfood.seal.util.VIDEO_QUALITY\nimport kotlinx.coroutines.launch\n\n@Composable\nprivate fun DownloadType.label(): String =\n    stringResource(\n        when (this) {\n            Audio -> R.string.audio\n            Video -> R.string.video\n            Command -> R.string.commands\n            Playlist -> R.string.playlist\n        }\n    )\n\nval PreferencesMock = DownloadUtil.DownloadPreferences.EMPTY\n\ndata class Config(\n    val downloadType: DownloadType? = PreferenceUtil.getDownloadType(),\n    val typeEntries: List<DownloadType> =\n        when (CUSTOM_COMMAND.getBoolean()) {\n            true -> DownloadType.entries\n            false -> DownloadType.entries - Command\n        },\n    val useFormatSelection: Boolean = FORMAT_SELECTION.getBoolean(),\n    val savedLinks: Set<String> = PreferenceUtil.getSavedLinks(),\n) {\n    companion object {\n        fun updatePreferences(newValue: Config, oldValue: Config) {\n            with(newValue) {\n                if (downloadType != oldValue.downloadType) {\n                    downloadType?.let { PreferenceUtil.updateDownloadType(it) }\n                }\n                if (useFormatSelection != oldValue.useFormatSelection) {\n                    FORMAT_SELECTION.updateBoolean(useFormatSelection)\n                }\n                if (savedLinks != oldValue.savedLinks) {\n                    PreferenceUtil.updateSavedLinks(savedLinks)\n                }\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadDialog(\n    modifier: Modifier = Modifier,\n    config: Config,\n    sheetState: SheetState,\n    preferences: DownloadUtil.DownloadPreferences,\n    onPreferencesUpdate: (DownloadUtil.DownloadPreferences) -> Unit,\n    state: DownloadDialogViewModel.SheetState = InputUrl,\n    onActionPost: (Action) -> Unit = {},\n) {\n    var showVideoPresetDialog by remember { mutableStateOf(false) }\n    var showAudioPresetDialog by remember { mutableStateOf(false) }\n\n    SealModalBottomSheet(\n        sheetState = sheetState,\n        contentPadding = PaddingValues(),\n        onDismissRequest = { onActionPost(Action.HideSheet) },\n    ) {\n        DownloadDialogContent(\n            modifier = modifier,\n            state = state,\n            config = config,\n            preferences = preferences,\n            onPreferencesUpdate = onPreferencesUpdate,\n            onPresetEdit = { type ->\n                when (type) {\n                    Audio -> showAudioPresetDialog = true\n\n                    Video -> showVideoPresetDialog = true\n\n                    else -> {}\n                }\n            },\n            onActionPost = onActionPost,\n        )\n    }\n\n    if (showVideoPresetDialog) {\n        var res by remember(preferences) { mutableIntStateOf(preferences.videoResolution) }\n        var format by remember(preferences) { mutableIntStateOf(preferences.videoFormat) }\n\n        VideoQuickSettingsDialog(\n            videoResolution = res,\n            videoFormatPreference = format,\n            onResolutionSelect = { res = it },\n            onFormatSelect = { format = it },\n            onDismissRequest = { showVideoPresetDialog = false },\n            onSave = {\n                VIDEO_FORMAT.updateInt(format)\n                VIDEO_QUALITY.updateInt(res)\n                onPreferencesUpdate(DownloadUtil.DownloadPreferences.createFromPreferences())\n            },\n        )\n    }\n\n    if (showAudioPresetDialog) {\n        var quality by remember(preferences) { mutableIntStateOf(preferences.audioQuality) }\n        var customPreset by\n            remember(preferences) { mutableStateOf(preferences.useCustomAudioPreset) }\n        var conversionFmt by\n            remember(preferences) { mutableIntStateOf(preferences.audioConvertFormat) }\n        var convertAudio by remember(preferences) { mutableStateOf(preferences.convertAudio) }\n        var preferredFormat by remember(preferences) { mutableIntStateOf(preferences.audioFormat) }\n\n        AudioQuickSettingsDialog(\n            modifier = Modifier,\n            preferences = preferences,\n            audioQuality = quality,\n            onQualitySelect = { quality = it },\n            useCustomAudioPreset = customPreset,\n            onCustomPresetToggle = { customPreset = it },\n            convertAudio = convertAudio,\n            onConvertToggled = { convertAudio = it },\n            conversionFormat = conversionFmt,\n            onConversionSelect = { conversionFmt = it },\n            preferredFormat = preferredFormat,\n            onPreferredSelect = { preferredFormat = it },\n            onDismissRequest = { showAudioPresetDialog = false },\n            onSave = {\n                AUDIO_QUALITY.updateInt(quality)\n                USE_CUSTOM_AUDIO_PRESET.updateBoolean(customPreset)\n                AUDIO_CONVERSION_FORMAT.updateInt(conversionFmt)\n                AUDIO_CONVERT.updateBoolean(convertAudio)\n                AUDIO_FORMAT.updateInt(preferredFormat)\n                onPreferencesUpdate(DownloadUtil.DownloadPreferences.createFromPreferences())\n            },\n        )\n    }\n}\n\n@Composable\nprivate fun ErrorPage(modifier: Modifier = Modifier, state: Error, onActionPost: (Action) -> Unit) {\n    val view = LocalView.current\n    val clipboardManager = LocalClipboardManager.current\n    val url =\n        state.action.run {\n            when (this) {\n                is Action.FetchFormats -> url\n                is Action.FetchPlaylist -> url\n                else -> {\n                    throw IllegalArgumentException()\n                }\n            }\n        }\n    Column(modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {\n        Icon(\n            imageVector = Icons.Outlined.ErrorOutline,\n            contentDescription = null,\n            modifier = Modifier.size(40.dp),\n        )\n        Text(\n            text = stringResource(R.string.fetch_info_error_msg),\n            style = MaterialTheme.typography.titleMedium,\n            modifier = Modifier.padding(top = 12.dp),\n        )\n        Text(\n            text = state.throwable.message.toString(),\n            style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),\n            color = MaterialTheme.colorScheme.onSurfaceVariant,\n            modifier =\n                Modifier.padding(vertical = 16.dp, horizontal = 20.dp)\n                    .fillMaxWidth()\n                    .verticalScroll(rememberScrollState()),\n            maxLines = 20,\n            overflow = TextOverflow.Clip,\n        )\n\n        Row(modifier = Modifier) {\n            FilledTonalButton(onClick = { onActionPost(state.action) }) { Text(\"Retry\") }\n            Spacer(Modifier.width(8.dp))\n            Button(\n                onClick = {\n                    view.longPressHapticFeedback()\n                    clipboardManager.setText(\n                        AnnotatedString(\n                            App.getVersionReport() + \"\\nURL: ${url}\\n${state.throwable.message}\"\n                        )\n                    )\n                    ToastUtil.makeToast(R.string.error_copied)\n                }\n            ) {\n                Text(stringResource(R.string.copy_error_report))\n            }\n        }\n    }\n}\n\n@Composable\nprivate fun DownloadDialogContent(\n    modifier: Modifier = Modifier,\n    state: DownloadDialogViewModel.SheetState,\n    config: Config,\n    preferences: DownloadUtil.DownloadPreferences,\n    onPreferencesUpdate: (DownloadUtil.DownloadPreferences) -> Unit,\n    onPresetEdit: (DownloadType?) -> Unit,\n    onActionPost: (Action) -> Unit,\n) {\n    AnimatedContent(\n        modifier = modifier,\n        targetState = state,\n        label = \"\",\n        transitionSpec = {\n            materialSharedAxisX(initialOffsetX = { it / 4 }, targetOffsetX = { -it / 4 })\n        },\n    ) { state ->\n        when (state) {\n            is Configure -> {\n                check(state.urlList.isNotEmpty())\n                if (state.urlList.size == 1) {\n                    ConfigurePage(\n                        url = state.urlList.first(),\n                        config = config,\n                        preferences = preferences,\n                        onPresetEdit = onPresetEdit,\n                        onConfigSave = {\n                            Config.updatePreferences(newValue = it, oldValue = config)\n                        },\n                        settingChips = {\n                            AdditionalSettings(\n                                modifier = Modifier.padding(horizontal = 16.dp),\n                                isQuickDownload = false,\n                                preference = preferences,\n                                selectedType = config.downloadType,\n                                onPreferenceUpdate = {\n                                    onPreferencesUpdate(\n                                        DownloadUtil.DownloadPreferences.createFromPreferences()\n                                    )\n                                },\n                            )\n                        },\n                        onActionPost = { onActionPost(it) },\n                    )\n                } else {\n                    ConfigurePagePlaylistVariant(\n                        initialDownloadType = config.downloadType ?: Video,\n                        preferences = preferences,\n                        onPreferencesUpdate = onPreferencesUpdate,\n                        onPresetEdit = onPresetEdit,\n                        onDismissRequest = { onActionPost(Action.HideSheet) },\n                    ) {\n                        onActionPost(\n                            Action.DownloadWithPreset(\n                                urlList = state.urlList,\n                                preferences = preferences.copy(extractAudio = it == Audio),\n                            )\n                        )\n                    }\n                }\n            }\n\n            is Error -> {\n                ErrorPage(state = state, onActionPost = onActionPost)\n            }\n\n            is Loading -> {\n                Column(modifier = Modifier.fillMaxWidth().padding(vertical = 120.dp)) {\n                    CircularProgressIndicator(\n                        modifier = Modifier.align(Alignment.CenterHorizontally)\n                    )\n                }\n            }\n\n            InputUrl -> {\n                InputUrlPage(\n                    config = config,\n                    onConfigUpdate = { Config.updatePreferences(newValue = it, oldValue = config) },\n                    onActionPost = onActionPost,\n                )\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Preview\n@Composable\nprivate fun ErrorPreview() {\n    SealModalBottomSheet(\n        onDismissRequest = {},\n        sheetState =\n            with(LocalDensity.current) {\n                SheetState(\n                    initialValue = SheetValue.Expanded,\n                    skipPartiallyExpanded = true,\n                    velocityThreshold = { 56.dp.toPx() },\n                    positionalThreshold = { 125.dp.toPx() },\n                )\n            },\n    ) {\n        ErrorPage(\n            state =\n                Error(\n                    action =\n                        Action.FetchFormats(\n                            url = \"\",\n                            audioOnly = true,\n                            preferences = PreferencesMock,\n                        ),\n                    throwable = Exception(\"Not good\"),\n                ),\n            onActionPost = {},\n        )\n    }\n}\n\n@Composable\nfun FormatPage(\n    modifier: Modifier = Modifier,\n    state: SelectionState.FormatSelection,\n    onDismissRequest: () -> Unit,\n) {\n    val sheetState =\n        androidx.compose.material.rememberModalBottomSheetState(\n            initialValue = ModalBottomSheetValue.Hidden,\n            skipHalfExpanded = true,\n        )\n\n    LaunchedEffect(state) { sheetState.show() }\n    val scope = rememberCoroutineScope()\n    BackHandler { scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() } }\n\n    SealModalBottomSheetM2Variant(sheetState = sheetState, sheetGesturesEnabled = false) {\n        FormatPage(\n            modifier = modifier,\n            videoInfo = state.info,\n            onNavigateBack = {\n                scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() }\n            },\n        )\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n/*@Preview(name = \"Dark\", uiMode = Configuration.UI_MODE_NIGHT_YES)\n@Preview(name = \"Light\", uiMode = Configuration.UI_MODE_NIGHT_NO)*/\n@Composable\nprivate fun ConfigurePagePreview() {\n    SealTheme() {\n        SealModalBottomSheet(\n            sheetState =\n                with(LocalDensity.current) {\n                    SheetState(\n                        initialValue = SheetValue.Expanded,\n                        skipPartiallyExpanded = true,\n                        velocityThreshold = { 56.dp.toPx() },\n                        positionalThreshold = { 125.dp.toPx() },\n                    )\n                },\n            onDismissRequest = {},\n            contentPadding = PaddingValues(),\n        ) {\n            ConfigurePage(\n                config =\n                    Config(\n                        downloadType = Audio,\n                        useFormatSelection = true,\n                        typeEntries = entries - Command,\n                    ),\n                preferences = PreferencesMock,\n                onConfigSave = {},\n                settingChips = {},\n            ) {}\n        }\n    }\n}\n\n@Composable\nprivate fun ConfigurePage(\n    modifier: Modifier = Modifier,\n    url: String = \"\",\n    config: Config,\n    preferences: DownloadUtil.DownloadPreferences,\n    settingChips: @Composable () -> Unit,\n    onPresetEdit: (DownloadType?) -> Unit = {},\n    onConfigSave: (Config) -> Unit,\n    onActionPost: (Action) -> Unit,\n) {\n    val scope = rememberCoroutineScope()\n    var selectedType by remember(config) { mutableStateOf(config.downloadType) }\n    var useFormatSelection by remember(config) { mutableStateOf(config.useFormatSelection) }\n    val canProceed = selectedType in config.typeEntries\n\n    var showTemplateSelectionDialog by remember { mutableStateOf(false) }\n    var showTemplateCreatorDialog by remember { mutableStateOf(false) }\n    var showTemplateEditorDialog by remember { mutableStateOf(false) }\n    val template by\n        remember(showTemplateCreatorDialog, showTemplateSelectionDialog, showTemplateEditorDialog) {\n            mutableStateOf(PreferenceUtil.getTemplate())\n        }\n\n    LaunchedEffect(selectedType) {\n        if (selectedType == Playlist) {\n            useFormatSelection = false\n        }\n    }\n\n    Column {\n        Column(modifier = modifier.padding(horizontal = 20.dp)) {\n            Header(\n                modifier = Modifier.align(Alignment.CenterHorizontally),\n                title = stringResource(R.string.settings_before_download),\n                icon = Icons.Outlined.DoneAll,\n            )\n            DrawerSheetSubtitle(text = stringResource(id = R.string.download_type))\n            DownloadTypeSelectionGroup(\n                typeEntries = config.typeEntries,\n                selectedType = selectedType,\n                onSelect = { selectedType = it },\n            )\n            Column(modifier = Modifier.animateContentSize()) {\n                if (selectedType != Command) {\n                    DrawerSheetSubtitle(\n                        text = stringResource(id = R.string.format_selection),\n                        modifier = Modifier,\n                    )\n                    Preset(\n                        modifier = Modifier,\n                        preference = preferences,\n                        selected = !useFormatSelection,\n                        downloadType = selectedType,\n                        onClick = { useFormatSelection = false },\n                        showEditIcon = !useFormatSelection && selectedType != Playlist,\n                        onEdit = { onPresetEdit(selectedType) },\n                    )\n                    Custom(\n                        selected = useFormatSelection,\n                        enabled = selectedType != Playlist,\n                        onClick = { useFormatSelection = true },\n                    )\n                } else {\n                    if (showTemplateSelectionDialog) {\n                        TemplatePickerDialog { showTemplateSelectionDialog = false }\n                    }\n                    if (showTemplateCreatorDialog) {\n                        CommandTemplateDialog(\n                            onDismissRequest = { showTemplateCreatorDialog = false },\n                            confirmationCallback = { scope.launch { TEMPLATE_ID.updateInt(it) } },\n                        )\n                    }\n                    if (showTemplateEditorDialog) {\n                        CommandTemplateDialog(\n                            commandTemplate = template,\n                            onDismissRequest = { showTemplateEditorDialog = false },\n                        )\n                    }\n                    DrawerSheetSubtitle(\n                        text = stringResource(id = R.string.template_selection),\n                        modifier = Modifier,\n                    )\n                    LazyRow(modifier = Modifier) {\n                        item {\n                            ButtonChip(\n                                icon = Icons.Outlined.Code,\n                                label = template.name,\n                                onClick = { showTemplateSelectionDialog = true },\n                            )\n                        }\n                        item {\n                            ButtonChip(\n                                icon = Icons.Outlined.NewLabel,\n                                label = stringResource(id = R.string.new_template),\n                                onClick = { showTemplateCreatorDialog = true },\n                            )\n                        }\n                        item {\n                            ButtonChip(\n                                icon = Icons.Outlined.Edit,\n                                label = stringResource(id = R.string.edit_template, template.name),\n                                onClick = { showTemplateEditorDialog = true },\n                            )\n                        }\n                    }\n                }\n            }\n        }\n        var expanded by remember { mutableStateOf(false) }\n        ExpandableTitle(expanded = expanded, onClick = { expanded = true }) { settingChips() }\n\n        ActionButtons(\n            modifier = Modifier.padding(horizontal = 20.dp),\n            canProceed = canProceed,\n            selectedType = selectedType,\n            useFormatSelection = useFormatSelection,\n            onCancel = { onActionPost(Action.HideSheet) },\n            onDownload = {\n                onConfigSave(\n                    config.copy(\n                        useFormatSelection = useFormatSelection,\n                        downloadType = selectedType,\n                    )\n                )\n                onActionPost(\n                    Action.DownloadWithPreset(\n                        urlList = listOf(url),\n                        preferences = preferences.copy(extractAudio = selectedType == Audio),\n                    )\n                )\n            },\n            onFetchInfo = {\n                onConfigSave(\n                    config.copy(\n                        useFormatSelection = useFormatSelection,\n                        downloadType = selectedType,\n                    )\n                )\n                if (selectedType == Playlist) {\n                    onActionPost(Action.FetchPlaylist(url = url, preferences = preferences))\n                } else {\n                    onActionPost(\n                        Action.FetchFormats(\n                            url = url,\n                            audioOnly = selectedType == Audio,\n                            preferences = preferences,\n                        )\n                    )\n                }\n            },\n            onTaskStart = {\n                onConfigSave(\n                    config.copy(\n                        useFormatSelection = useFormatSelection,\n                        downloadType = selectedType,\n                    )\n                )\n                onActionPost(\n                    Action.RunCommand(url = url, template = template, preferences = preferences)\n                )\n            },\n        )\n    }\n}\n\n@Composable\nfun ConfigurePagePlaylistVariant(\n    modifier: Modifier = Modifier,\n    initialDownloadType: DownloadType,\n    preferences: DownloadUtil.DownloadPreferences,\n    onPreferencesUpdate: (DownloadUtil.DownloadPreferences) -> Unit,\n    onPresetEdit: (DownloadType?) -> Unit = {},\n    onDismissRequest: () -> Unit,\n    onDownload: (DownloadType) -> Unit,\n) {\n\n    var selectedType by remember(initialDownloadType) { mutableStateOf(initialDownloadType) }\n\n    Column {\n        Column(modifier = modifier.padding(horizontal = 20.dp)) {\n            Header(\n                modifier = Modifier.align(Alignment.CenterHorizontally),\n                title = stringResource(R.string.settings_before_download),\n                icon = Icons.Outlined.DoneAll,\n            )\n            DrawerSheetSubtitle(text = stringResource(id = R.string.download_type))\n            DownloadTypeSelectionGroup(\n                typeEntries = listOf(Video, Audio),\n                selectedType = selectedType,\n                onSelect = { selectedType = it },\n            )\n            DrawerSheetSubtitle(\n                text = stringResource(id = R.string.format_selection),\n                modifier = Modifier,\n            )\n            Preset(\n                modifier = Modifier,\n                preference = preferences,\n                selected = true,\n                downloadType = selectedType,\n                onClick = { onPresetEdit(selectedType) },\n                showEditIcon = true,\n                onEdit = { onPresetEdit(selectedType) },\n            )\n        }\n        var expanded by remember { mutableStateOf(false) }\n        ExpandableTitle(expanded = expanded, onClick = { expanded = true }) {\n            AdditionalSettings(\n                modifier = Modifier.padding(horizontal = 16.dp),\n                isQuickDownload = false,\n                preference = preferences,\n                selectedType = Audio,\n                onPreferenceUpdate = {\n                    onPreferencesUpdate(DownloadUtil.DownloadPreferences.createFromPreferences())\n                },\n            )\n        }\n\n        ActionButtons(\n            modifier = Modifier.padding(horizontal = 20.dp),\n            canProceed = true,\n            selectedType = selectedType,\n            useFormatSelection = false,\n            onCancel = onDismissRequest,\n            onDownload = {\n                onDownload(initialDownloadType)\n                onDismissRequest()\n            },\n            onFetchInfo = { throw IllegalStateException() },\n            onTaskStart = { throw IllegalStateException() },\n        )\n    }\n}\n\n@Composable\nprivate fun AdditionalSettings(\n    modifier: Modifier = Modifier,\n    isQuickDownload: Boolean,\n    selectedType: DownloadType?,\n    preference: DownloadUtil.DownloadPreferences,\n    onNavigateToCookieGeneratorPage: (String) -> Unit = {},\n    onPreferenceUpdate: () -> Unit,\n) {\n    val cookiesProfiles by DatabaseUtil.getCookiesFlow().collectAsStateWithLifecycle(emptyList())\n    var showCookiesDialog by rememberSaveable { mutableStateOf(false) }\n\n    with(preference) {\n        Row(modifier = modifier.fillMaxWidth().horizontalScroll(rememberScrollState())) {\n            if (cookiesProfiles.isNotEmpty()) {\n                VideoFilterChip(\n                    selected = preference.cookies,\n                    onClick = {\n                        if (isQuickDownload) {\n                            COOKIES.updateBoolean(!cookies)\n                            onPreferenceUpdate()\n                        } else {\n                            showCookiesDialog = true\n                        }\n                    },\n                    label = stringResource(id = R.string.cookies),\n                )\n            }\n\n            VideoFilterChip(\n                selected = downloadSubtitle,\n                enabled = selectedType != Command,\n                onClick = {\n                    SUBTITLE.updateBoolean(!downloadSubtitle)\n                    onPreferenceUpdate()\n                },\n                label = stringResource(id = R.string.download_subtitles),\n            )\n            VideoFilterChip(\n                selected = createThumbnail,\n                enabled = selectedType != Command,\n                onClick = {\n                    THUMBNAIL.updateBoolean(!createThumbnail)\n                    onPreferenceUpdate()\n                },\n                label = stringResource(R.string.create_thumbnail),\n            )\n        }\n\n        if (showCookiesDialog && cookiesProfiles.isNotEmpty()) {\n            CookiesQuickSettingsDialog(\n                onDismissRequest = { showCookiesDialog = false },\n                onConfirm = {},\n                cookieProfiles = cookiesProfiles,\n                onCookieProfileClicked = { onNavigateToCookieGeneratorPage(it.url) },\n                isCookiesEnabled = cookies,\n                onCookiesToggled = {\n                    COOKIES.updateBoolean(!cookies)\n                    onPreferenceUpdate()\n                },\n            )\n        }\n    }\n}\n\n@Composable\nfun ExpandableTitle(\n    modifier: Modifier = Modifier,\n    expanded: Boolean = false,\n    onClick: () -> Unit = {},\n    content: @Composable () -> Unit,\n) {\n    Column {\n        Spacer(Modifier.height(8.dp))\n        HorizontalDivider(thickness = Dp.Hairline, modifier = Modifier.padding(horizontal = 20.dp))\n        Column(\n            modifier =\n                modifier\n                    .clickable(\n                        onClick = onClick,\n                        onClickLabel = stringResource(R.string.show_more_actions),\n                        enabled = !expanded,\n                    )\n                    .padding(top = 12.dp, bottom = 8.dp)\n        ) {\n            Row(\n                modifier = Modifier.fillMaxWidth(),\n                verticalAlignment = Alignment.CenterVertically,\n            ) {\n                Spacer(modifier = Modifier.width(24.dp))\n                Text(\n                    text = stringResource(R.string.additional_settings),\n                    style = MaterialTheme.typography.labelLarge,\n                )\n                Spacer(modifier = Modifier.weight(1f))\n                if (!expanded) {\n                    Icon(\n                        imageVector = Icons.Outlined.ExpandMore,\n                        contentDescription = null,\n                        modifier = Modifier.size(20.dp),\n                    )\n                    Spacer(modifier = Modifier.width(32.dp))\n                }\n            }\n            AnimatedVisibility(expanded) {\n                Column {\n                    Spacer(Modifier.height(8.dp))\n                    content()\n                }\n            }\n        }\n    }\n}\n\n@Composable\nprivate fun SingleChoiceItem(\n    modifier: Modifier = Modifier,\n    title: String,\n    desc: String,\n    selected: Boolean,\n    icon: (@Composable () -> Unit)? = null,\n    action: (@Composable () -> Unit)? = null,\n    enabled: Boolean = true,\n    onClick: () -> Unit = {},\n) {\n    val corner by\n        animateDpAsState(\n            if (selected) 28.dp else 16.dp,\n            animationSpec =\n                spring(\n                    stiffness = Spring.StiffnessMedium,\n                    visibilityThreshold = Dp.VisibilityThreshold,\n                ),\n            label = \"\",\n        )\n    val color by\n        animateColorAsState(\n            if (selected) MaterialTheme.colorScheme.secondaryContainer\n            else MaterialTheme.colorScheme.surfaceContainerLow,\n            label = \"\",\n        )\n\n    Surface(\n        selected = selected,\n        onClick = onClick,\n        color = color,\n        shape = RoundedCornerShape(corner),\n        modifier = modifier.padding(vertical = 4.dp).run { if (!enabled) alpha(0.32f) else this },\n        enabled = enabled,\n    ) {\n        Row(\n            modifier = Modifier.padding(horizontal = 20.dp, vertical = 16.dp),\n            verticalAlignment = Alignment.CenterVertically,\n        ) {\n            Column(modifier = Modifier.weight(1f).heightIn(min = 48.dp)) {\n                Row(verticalAlignment = Alignment.CenterVertically) {\n                    icon?.invoke()\n                    Spacer(modifier = Modifier.width(12.dp))\n                    Text(text = title, style = MaterialTheme.typography.titleMedium)\n                }\n                Text(\n                    text = desc,\n                    style = MaterialTheme.typography.bodySmall,\n                    minLines = 2,\n                    maxLines = 2,\n                    overflow = TextOverflow.Ellipsis,\n                    modifier = Modifier.padding(start = 32.dp),\n                )\n            }\n            action?.invoke()\n        }\n    }\n}\n\n@Composable\ninternal fun Header(modifier: Modifier = Modifier, icon: ImageVector, title: String) {\n    Column(modifier = modifier) {\n        Icon(\n            modifier = Modifier.align(Alignment.CenterHorizontally),\n            imageVector = icon,\n            contentDescription = null,\n        )\n        Text(\n            text = title,\n            style = MaterialTheme.typography.headlineSmall,\n            modifier =\n                Modifier.align(Alignment.CenterHorizontally).padding(top = 16.dp, bottom = 8.dp),\n            maxLines = 2,\n            overflow = TextOverflow.Ellipsis,\n            textAlign = TextAlign.Center,\n        )\n    }\n}\n\n@Composable\nprivate fun DownloadTypeSelectionGroup(\n    modifier: Modifier = Modifier,\n    typeEntries: List<DownloadType>,\n    selectedType: DownloadType?,\n    onSelect: (DownloadType) -> Unit,\n) {\n    val typeCount = typeEntries.size\n    if (typeCount == DownloadType.entries.size) {\n        LazyRow(modifier = modifier) {\n            items(typeEntries) { type ->\n                SingleChoiceChip(\n                    selected = selectedType == type,\n                    label = type.label(),\n                    onClick = { onSelect(type) },\n                )\n            }\n        }\n    } else {\n        SingleChoiceSegmentedButtonRow(modifier = modifier.fillMaxWidth()) {\n            typeEntries.forEachIndexed { index, type ->\n                SingleChoiceSegmentedButton(\n                    selected = selectedType == type,\n                    onClick = { onSelect(type) },\n                    shape = SegmentedButtonDefaults.itemShape(index, typeCount),\n                ) {\n                    Text(text = type.label())\n                }\n            }\n        }\n    }\n}\n\n@Composable\nprivate fun Preset(\n    modifier: Modifier = Modifier,\n    preference: DownloadUtil.DownloadPreferences,\n    downloadType: DownloadType?,\n    selected: Boolean,\n    showEditIcon: Boolean,\n    onEdit: () -> Unit,\n    onClick: () -> Unit,\n) {\n    val description =\n        when (downloadType) {\n            Audio -> {\n                PreferenceStrings.getAudioPresetText(preference)\n            }\n\n            Video -> {\n                PreferenceStrings.getVideoPresetText(preference)\n            }\n\n            Playlist -> stringResource(R.string.preset_format_selection_desc)\n            else -> \"\"\n        }\n\n    SingleChoiceItem(\n        modifier = modifier,\n        title = stringResource(R.string.preset),\n        desc = description,\n        icon = {\n            Crossfade(selected, animationSpec = spring(stiffness = Spring.StiffnessMedium)) {\n                if (it) {\n                    Icon(\n                        imageVector = Icons.Filled.SettingsSuggest,\n                        null,\n                        modifier = Modifier.size(20.dp),\n                    )\n                } else {\n                    Icon(\n                        imageVector = Icons.Outlined.SettingsSuggest,\n                        null,\n                        modifier = Modifier.size(20.dp),\n                    )\n                }\n            }\n        },\n        selected = selected,\n        action = {\n            Crossfade(showEditIcon, animationSpec = spring(stiffness = Spring.StiffnessMedium)) {\n                if (it) {\n                    Icon(\n                        imageVector = Icons.Outlined.MoreVert,\n                        contentDescription = stringResource(R.string.edit),\n                        modifier = Modifier.size(20.dp),\n                    )\n                }\n            }\n        },\n        onClick = {\n            if (showEditIcon) {\n                onEdit()\n            } else {\n                onClick()\n            }\n        },\n    )\n}\n\n@Composable\nprivate fun Custom(\n    modifier: Modifier = Modifier,\n    selected: Boolean,\n    enabled: Boolean = true,\n    onClick: () -> Unit,\n) {\n    SingleChoiceItem(\n        modifier = modifier,\n        title = stringResource(R.string.custom),\n        desc = stringResource(R.string.custom_format_selection_desc),\n        icon = {\n            Crossfade(selected, animationSpec = spring(stiffness = Spring.StiffnessMedium)) {\n                if (it) {\n                    Icon(\n                        imageVector = Icons.Filled.VideoFile,\n                        null,\n                        modifier = Modifier.size(20.dp),\n                    )\n                } else {\n                    Icon(\n                        imageVector = Icons.Outlined.VideoFile,\n                        null,\n                        modifier = Modifier.size(20.dp),\n                    )\n                }\n            }\n        },\n        selected = selected,\n        enabled = enabled,\n        onClick = onClick,\n    )\n}\n\nprivate enum class ActionButton {\n    FetchInfo,\n    Download,\n    StartTask,\n}\n\n@Composable\nprivate fun ActionButton.Icon() {\n    Icon(\n        imageVector =\n            when (this) {\n                FetchInfo -> Icons.AutoMirrored.Filled.ArrowForward\n                Download -> Icons.Outlined.FileDownload\n                StartTask -> Icons.Filled.DownloadDone\n            },\n        contentDescription = null,\n        modifier = Modifier.size(18.dp),\n    )\n}\n\n@Composable\nprivate fun ActionButton.Label() {\n    Text(\n        stringResource(\n            when (this) {\n                FetchInfo -> R.string.proceed\n                Download -> R.string.download\n                StartTask -> R.string.start\n            }\n        ),\n        modifier = Modifier.padding(start = 8.dp),\n    )\n}\n\n@Composable\nprivate fun ActionButtons(\n    modifier: Modifier = Modifier,\n    canProceed: Boolean,\n    selectedType: DownloadType?,\n    useFormatSelection: Boolean,\n    onCancel: () -> Unit,\n    onFetchInfo: () -> Unit,\n    onDownload: () -> Unit,\n    onTaskStart: () -> Unit,\n) {\n    val action =\n        if (selectedType == Command) {\n            StartTask\n        } else if (selectedType == Playlist || useFormatSelection) {\n            FetchInfo\n        } else {\n            Download\n        }\n\n    val state = rememberLazyListState()\n    LazyRow(\n        modifier = modifier.fillMaxWidth().padding(top = 12.dp),\n        horizontalArrangement = Arrangement.End,\n        state = state,\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        item {\n            OutlinedButtonWithIcon(\n                modifier = Modifier.padding(horizontal = 12.dp),\n                onClick = onCancel,\n                icon = Icons.Outlined.Cancel,\n                text = stringResource(R.string.cancel),\n            )\n        }\n        item {\n            Button(\n                modifier = Modifier,\n                onClick = {\n                    when (action) {\n                        FetchInfo -> onFetchInfo()\n                        Download -> onDownload()\n                        StartTask -> onTaskStart()\n                    }\n                },\n                contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n                enabled = canProceed,\n            ) {\n                AnimatedContent(\n                    targetState = action,\n                    label = \"\",\n                    transitionSpec = {\n                        (fadeIn(animationSpec = tween(220, delayMillis = 90))).togetherWith(\n                            fadeOut(animationSpec = tween(90))\n                        )\n                    },\n                ) { action ->\n                    Row(verticalAlignment = Alignment.CenterVertically) {\n                        action.Icon()\n                        action.Label()\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/configure/DownloadDialogViewModel.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2.configure\n\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.download.Task\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.PlaylistResult\nimport com.junkfood.seal.util.VideoInfo\nimport com.yausername.youtubedl_android.YoutubeDL\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.asStateFlow\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\nprivate const val TAG = \"DownloadDialogViewModel\"\n\nclass DownloadDialogViewModel(private val downloader: DownloaderV2) : ViewModel() {\n\n    sealed interface SelectionState {\n        data object Idle : SelectionState\n\n        data class PlaylistSelection(val result: PlaylistResult) : SelectionState\n\n        data class FormatSelection(val info: VideoInfo) : SelectionState\n    }\n\n    sealed interface SheetState {\n        data object InputUrl : SheetState\n\n        data class Configure(val urlList: List<String>) : SheetState\n\n        data class Loading(val taskKey: String, val job: Job) : SheetState\n\n        data class Error(val action: Action, val throwable: Throwable) : SheetState\n    }\n\n    sealed interface SheetValue {\n        data object Expanded : SheetValue\n\n        data object Hidden : SheetValue\n    }\n\n    sealed interface Action {\n        data object HideSheet : Action\n\n        data class ShowSheet(val urlList: List<String>? = null) : Action\n\n        data class ProceedWithURLs(val urlList: List<String>) : Action\n\n        data object Reset : Action\n\n        data class FetchPlaylist(\n            val url: String,\n            val preferences: DownloadUtil.DownloadPreferences,\n        ) : Action\n\n        data class FetchFormats(\n            val url: String,\n            val audioOnly: Boolean,\n            val preferences: DownloadUtil.DownloadPreferences,\n        ) : Action\n\n        data class DownloadWithPreset(\n            val urlList: List<String>,\n            val preferences: DownloadUtil.DownloadPreferences,\n        ) : Action\n\n        data class RunCommand(\n            val url: String,\n            val template: CommandTemplate,\n            val preferences: DownloadUtil.DownloadPreferences,\n        ) : Action\n\n        data object Cancel : Action\n    }\n\n    private val mSelectionStateFlow: MutableStateFlow<SelectionState> =\n        MutableStateFlow(SelectionState.Idle)\n    private val mSheetStateFlow: MutableStateFlow<SheetState> =\n        MutableStateFlow(SheetState.InputUrl)\n    private val mSheetValueFlow: MutableStateFlow<SheetValue> = MutableStateFlow(SheetValue.Hidden)\n\n    val selectionStateFlow = mSelectionStateFlow.asStateFlow()\n    val sheetStateFlow = mSheetStateFlow.asStateFlow()\n    val sheetValueFlow = mSheetValueFlow.asStateFlow()\n\n    private val sheetState\n        get() = sheetStateFlow.value\n\n    fun postAction(action: Action) {\n        with(action) {\n            when (this) {\n                is Action.ProceedWithURLs -> proceedWithUrls(this)\n                is Action.FetchFormats -> fetchFormat(this)\n                is Action.FetchPlaylist -> fetchPlaylist(this)\n                is Action.DownloadWithPreset -> downloadWithPreset(urlList, preferences)\n                is Action.RunCommand -> runCommand(url, template, preferences)\n                Action.HideSheet -> hideDialog()\n                is Action.ShowSheet -> showDialog(this)\n                Action.Cancel -> cancel()\n                Action.Reset -> resetSelectionState()\n            }\n        }\n    }\n\n    private fun proceedWithUrls(action: Action.ProceedWithURLs) {\n        mSheetStateFlow.update { SheetState.Configure(action.urlList) }\n    }\n\n    private fun fetchPlaylist(action: Action.FetchPlaylist) {\n        val (url, preferences) = action\n\n        val job =\n            viewModelScope.launch(Dispatchers.IO) {\n                DownloadUtil.getPlaylistOrVideoInfo(\n                        playlistURL = url,\n                        downloadPreferences = preferences,\n                    )\n                    .onSuccess { info ->\n                        withContext(Dispatchers.Main) {\n                            when (info) {\n                                is PlaylistResult -> {\n                                    mSelectionStateFlow.update {\n                                        SelectionState.PlaylistSelection(result = info)\n                                    }\n                                }\n\n                                is VideoInfo -> {\n                                    mSelectionStateFlow.update {\n                                        SelectionState.FormatSelection(info = info)\n                                    }\n                                }\n                            }\n                            hideDialog()\n                        }\n                    }\n                    .onFailure { th ->\n                        mSheetStateFlow.update { SheetState.Error(action = action, throwable = th) }\n                    }\n            }\n        mSheetStateFlow.update { SheetState.Loading(taskKey = \"FetchPlaylist_$url\", job = job) }\n    }\n\n    private fun fetchFormat(action: Action.FetchFormats) {\n        val (url, audioOnly, preferences) = action\n\n        val job =\n            viewModelScope.launch(Dispatchers.IO) {\n                DownloadUtil.fetchVideoInfoFromUrl(\n                        url = url,\n                        preferences = preferences.copy(extractAudio = audioOnly),\n                        taskKey = \"FetchFormat_$url\",\n                    )\n                    .onSuccess { info ->\n                        withContext(Dispatchers.Main) {\n                            mSelectionStateFlow.update {\n                                SelectionState.FormatSelection(info = info)\n                            }\n                            hideDialog()\n                        }\n                    }\n                    .onFailure { th ->\n                        withContext(Dispatchers.Main) {\n                            mSheetStateFlow.update { SheetState.Error(action, throwable = th) }\n                        }\n                    }\n            }\n\n        mSheetStateFlow.update { SheetState.Loading(taskKey = \"FetchFormat_$url\", job = job) }\n    }\n\n    private fun downloadWithPreset(\n        urlList: List<String>,\n        preferences: DownloadUtil.DownloadPreferences,\n    ) {\n        urlList.forEach { downloader.enqueue(Task(url = it, preferences = preferences)) }\n        hideDialog()\n    }\n\n    private fun runCommand(\n        url: String,\n        template: CommandTemplate,\n        preferences: DownloadUtil.DownloadPreferences,\n    ) {\n        val task =\n            Task(\n                url = url,\n                type = Task.TypeInfo.CustomCommand(template = template),\n                preferences = preferences,\n            )\n        downloader.enqueue(task)\n    }\n\n    private fun hideDialog() {\n        mSheetValueFlow.update { SheetValue.Hidden }\n        when (sheetState) {\n            is SheetState.Loading -> {\n                cancel()\n            }\n\n            else -> {}\n        }\n    }\n\n    private fun showDialog(action: Action.ShowSheet) {\n        val urlList = action.urlList\n        if (!urlList.isNullOrEmpty()) {\n            mSheetStateFlow.update { SheetState.Configure(urlList) }\n        } else {\n            mSheetStateFlow.update { SheetState.InputUrl }\n        }\n        mSheetValueFlow.update { SheetValue.Expanded }\n    }\n\n    private fun cancel(): Boolean {\n        return when (val state = sheetState) {\n            is SheetState.Loading -> {\n                val res = YoutubeDL.destroyProcessById(id = state.taskKey)\n                if (res) {\n                    state.job.cancel()\n                }\n                return res\n            }\n            else -> false\n        }\n    }\n\n    private fun resetSelectionState() {\n        mSelectionStateFlow.update { SelectionState.Idle }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/configure/FormatPage.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2.configure\n\nimport android.content.Intent\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.core.spring\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.foundation.ExperimentalFoundationApi\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ExperimentalLayoutApi\nimport androidx.compose.foundation.layout.FlowRow\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.foundation.lazy.grid.GridCells\nimport androidx.compose.foundation.lazy.grid.GridItemSpan\nimport androidx.compose.foundation.lazy.grid.LazyVerticalGrid\nimport androidx.compose.foundation.lazy.grid.itemsIndexed\nimport androidx.compose.foundation.lazy.grid.rememberLazyGridState\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.filled.Subtitles\nimport androidx.compose.material.icons.outlined.Close\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.Subtitles\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.ExtendedFloatingActionButton\nimport androidx.compose.material3.FabPosition\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.RangeSliderState\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.DisposableEffect\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateListOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.download.TaskFactory\nimport com.junkfood.seal.ui.component.ClearButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.FormatItem\nimport com.junkfood.seal.ui.component.FormatSubtitle\nimport com.junkfood.seal.ui.component.FormatVideoPreview\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SealSearchBar\nimport com.junkfood.seal.ui.component.SuggestedFormatItem\nimport com.junkfood.seal.ui.component.TextButtonWithIcon\nimport com.junkfood.seal.ui.component.VideoFilterChip\nimport com.junkfood.seal.ui.page.download.VideoClipDialog\nimport com.junkfood.seal.ui.page.download.VideoSelectionSlider\nimport com.junkfood.seal.ui.page.settings.general.DialogCheckBoxItem\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.ui.theme.generateLabelColor\nimport com.junkfood.seal.util.EXTRACT_AUDIO\nimport com.junkfood.seal.util.Format\nimport com.junkfood.seal.util.MERGE_MULTI_AUDIO_STREAM\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.SUBTITLE\nimport com.junkfood.seal.util.SUBTITLE_LANGUAGE\nimport com.junkfood.seal.util.SubtitleFormat\nimport com.junkfood.seal.util.VIDEO_CLIP\nimport com.junkfood.seal.util.VideoClip\nimport com.junkfood.seal.util.VideoInfo\nimport com.junkfood.seal.util.toHttpsUrl\nimport kotlin.math.min\nimport kotlin.math.roundToInt\nimport kotlinx.coroutines.delay\nimport org.koin.compose.koinInject\n\nprivate const val TAG = \"FormatPage\"\n\nprivate data class FormatConfig(\n    val formatList: List<Format>,\n    val videoClips: List<VideoClip>,\n    val splitByChapter: Boolean,\n    val newTitle: String,\n    val selectedSubtitles: List<String>,\n    val selectedAutoCaptions: List<String>,\n)\n\n@Composable\nfun FormatPage(\n    modifier: Modifier = Modifier,\n    videoInfo: VideoInfo,\n    downloader: DownloaderV2 = koinInject(),\n    onNavigateBack: () -> Unit = {},\n) {\n    if (videoInfo.formats.isNullOrEmpty()) return\n    val audioOnly = EXTRACT_AUDIO.getBoolean()\n    val mergeAudioStream = MERGE_MULTI_AUDIO_STREAM.getBoolean()\n    val subtitleLanguageRegex = SUBTITLE_LANGUAGE.getString()\n    val downloadSubtitle = SUBTITLE.getBoolean()\n    val initialSelectedSubtitles =\n        if (downloadSubtitle) {\n            videoInfo\n                .run { subtitles.keys + automaticCaptions.keys }\n                .filterWithRegex(subtitleLanguageRegex)\n        } else {\n            emptySet()\n        }\n\n    var showUpdateSubtitleDialog by remember { mutableStateOf(false) }\n\n    var diffSubtitleLanguages by remember { mutableStateOf(emptySet<String>()) }\n\n    FormatPageImpl(\n        modifier = modifier,\n        videoInfo = videoInfo,\n        onNavigateBack = onNavigateBack,\n        audioOnly = audioOnly,\n        mergeAudioStream = !audioOnly && mergeAudioStream,\n        selectedSubtitleCodes = initialSelectedSubtitles,\n        isClippingAvailable = VIDEO_CLIP.getBoolean() && (videoInfo.duration ?: .0) >= 0,\n    ) { config ->\n        with(config) {\n            diffSubtitleLanguages =\n                (selectedSubtitles + selectedAutoCaptions)\n                    .run { this - this.filterWithRegex(subtitleLanguageRegex) }\n                    .toSet()\n\n            downloader.enqueue(\n                TaskFactory.createWithConfigurations(\n                    videoInfo = videoInfo,\n                    formatList = formatList,\n                    videoClips = videoClips,\n                    splitByChapter = splitByChapter,\n                    newTitle = newTitle,\n                    selectedSubtitles = selectedSubtitles,\n                    selectedAutoCaptions = selectedAutoCaptions,\n                )\n            )\n\n            if (diffSubtitleLanguages.isNotEmpty()) {\n                showUpdateSubtitleDialog = true\n            } else {\n                onNavigateBack()\n            }\n        }\n    }\n    if (showUpdateSubtitleDialog) {\n        UpdateSubtitleLanguageDialog(\n            modifier = Modifier,\n            languages = diffSubtitleLanguages,\n            onDismissRequest = {\n                showUpdateSubtitleDialog = false\n                onNavigateBack()\n            },\n            onConfirm = {\n                SUBTITLE_LANGUAGE.updateString(\n                    (diffSubtitleLanguages + subtitleLanguageRegex).joinToString(separator = \",\") {\n                        it\n                    }\n                )\n                showUpdateSubtitleDialog = false\n                onNavigateBack()\n            },\n        )\n    }\n}\n\nprivate const val NOT_SELECTED = -1\n\n@Preview\n@Composable\nfun FormatPagePreview() {\n    val captionsMap =\n        mapOf(\n            \"en-en\" to listOf(SubtitleFormat(ext = \"\", url = \"\", name = \"English from English\")),\n            \"ja-en\" to listOf(SubtitleFormat(ext = \"\", url = \"\", name = \"Japanese from English\")),\n            \"zh-Hans-en\" to\n                listOf(\n                    SubtitleFormat(ext = \"\", url = \"\", name = \"Chinese (Simplified) from English\")\n                ),\n            \"zh-Hant-en\" to\n                listOf(\n                    SubtitleFormat(ext = \"\", url = \"\", name = \"Chinese (Traditional) from English\")\n                ),\n        )\n\n    val subMap = buildMap {\n        put(\"en\", listOf(SubtitleFormat(ext = \"ass\", url = \"\", name = \"English\")))\n        put(\"ja\", listOf(SubtitleFormat(ext = \"ass\", url = \"\", name = \"Japanese\")))\n    }\n    val videoInfo =\n        VideoInfo(\n            formats =\n                buildList {\n                    repeat(7) { add(Format(formatId = \"$it\")) }\n                    repeat(7) { add(Format(formatId = \"$it\", vcodec = \"avc1\", acodec = \"none\")) }\n                    repeat(7) {\n                        add(\n                            Format(\n                                formatId = \"$it\",\n                                acodec = \"aac\",\n                                vcodec = \"none\",\n                                format = \"251 - audio only (medium)\",\n                                fileSizeApprox = 2000000.0,\n                                tbr = 128.0,\n                            )\n                        )\n                    }\n                },\n            subtitles = subMap,\n            automaticCaptions = captionsMap,\n            requestedFormats =\n                buildList {\n                    add(\n                        Format(\n                            formatId = \"616\",\n                            format = \"616 - 1920x1080 (Premium)\",\n                            acodec = \"none\",\n                            vcodec = \"vp09.00.40.08\",\n                            ext = \"webm\",\n                        )\n                    )\n                    add(\n                        Format(\n                            formatId = \"251\",\n                            format = \"251 - audio only (medium)\",\n                            acodec = \"opus\",\n                            vcodec = \"none\",\n                            ext = \"webm\",\n                        )\n                    )\n                },\n            duration = 180.0,\n        )\n    SealTheme {\n        FormatPageImpl(\n            videoInfo = videoInfo,\n            isClippingAvailable = true,\n            mergeAudioStream = true,\n            selectedSubtitleCodes = setOf(\"en\", \"ja-en\"),\n        )\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nprivate fun FormatPageImpl(\n    modifier: Modifier = Modifier,\n    videoInfo: VideoInfo = VideoInfo(),\n    audioOnly: Boolean = false,\n    mergeAudioStream: Boolean = false,\n    isClippingAvailable: Boolean = false,\n    selectedSubtitleCodes: Set<String>,\n    onNavigateBack: () -> Unit = {},\n    onDownloadPressed: (FormatConfig) -> Unit = { _ -> },\n) {\n    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()\n\n    if (videoInfo.formats.isNullOrEmpty()) return\n    val videoOnlyFormats =\n        videoInfo.formats.filter { it.vcodec != \"none\" && it.acodec == \"none\" }.reversed()\n    val audioOnlyFormats =\n        videoInfo.formats.filter { it.acodec != \"none\" && it.vcodec == \"none\" }.reversed()\n    val videoAudioFormats =\n        videoInfo.formats.filter { it.acodec != \"none\" && it.vcodec != \"none\" }.reversed()\n\n    val duration = videoInfo.duration ?: 0.0\n\n    var videoOnlyItemLimit by remember { mutableIntStateOf(6) }\n    var audioOnlyItemLimit by remember { mutableIntStateOf(6) }\n    var videoAudioItemLimit by remember { mutableIntStateOf(6) }\n\n    val isSuggestedFormatAvailable =\n        !videoInfo.requestedFormats.isNullOrEmpty() || !videoInfo.requestedDownloads.isNullOrEmpty()\n\n    var isSuggestedFormatSelected by remember { mutableStateOf(isSuggestedFormatAvailable) }\n\n    var selectedVideoAudioFormat by remember { mutableIntStateOf(NOT_SELECTED) }\n    var selectedVideoOnlyFormat by remember { mutableIntStateOf(NOT_SELECTED) }\n    val selectedAudioOnlyFormats = remember { mutableStateListOf<Int>() }\n    val context = LocalContext.current\n\n    val uriHandler = LocalUriHandler.current\n    val hapticFeedback = LocalHapticFeedback.current\n\n    fun String?.share() =\n        this?.let {\n            hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n            context.startActivity(\n                Intent.createChooser(\n                    Intent().apply {\n                        action = Intent.ACTION_SEND\n                        type = \"text/plain\"\n                        putExtra(Intent.EXTRA_TEXT, it)\n                    },\n                    null,\n                ),\n                null,\n            )\n        }\n\n    var isClippingVideo by remember { mutableStateOf(false) }\n    var isSplittingVideo by remember { mutableStateOf(false) }\n    val isSplitByChapterAvailable = !videoInfo.chapters.isNullOrEmpty()\n\n    val videoDurationRange = 0f..(videoInfo.duration?.toFloat() ?: 0f)\n    var showVideoClipDialog by remember { mutableStateOf(false) }\n    var showRenameDialog by remember { mutableStateOf(false) }\n    var showSubtitleSelectionDialog by remember { mutableStateOf(false) }\n\n    var videoClipDuration by remember { mutableStateOf(videoDurationRange) }\n    var videoTitle by remember { mutableStateOf(\"\") }\n\n    val suggestedSubtitleMap: Map<String, List<SubtitleFormat>> =\n        videoInfo.subtitles.takeIf { it.isNotEmpty() }\n            ?: videoInfo.automaticCaptions.filterKeys { it.endsWith(\"-orig\") }\n\n    val otherSubtitleMap: Map<String, List<SubtitleFormat>> =\n        videoInfo.subtitles + videoInfo.automaticCaptions - suggestedSubtitleMap.keys\n\n    LaunchedEffect(isClippingVideo) {\n        delay(200)\n        videoClipDuration = videoDurationRange\n    }\n\n    val lazyGridState = rememberLazyGridState()\n\n    val formatList: List<Format> by remember {\n        derivedStateOf {\n            mutableListOf<Format>().apply {\n                if (isSuggestedFormatSelected) {\n                    videoInfo.requestedFormats?.let { addAll(it) }\n                        ?: videoInfo.requestedDownloads?.forEach {\n                            it.requestedFormats?.let { addAll(it) }\n                        }\n                } else {\n                    selectedAudioOnlyFormats.forEach { index ->\n                        add(audioOnlyFormats.elementAt(index))\n                    }\n                    videoAudioFormats.getOrNull(selectedVideoAudioFormat)?.let { add(it) }\n                    videoOnlyFormats.getOrNull(selectedVideoOnlyFormat)?.let { add(it) }\n                }\n            }\n        }\n    }\n\n    val isFabExpanded by remember { derivedStateOf { lazyGridState.firstVisibleItemIndex > 0 } }\n\n    val selectedSubtitles = remember {\n        mutableStateListOf<String>().apply { addAll(selectedSubtitleCodes) }\n    }\n\n    val selectedAutoCaptions = remember { mutableStateListOf<String>() }\n\n    Scaffold(\n        modifier = modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            TopAppBar(\n                title = {\n                    Text(\n                        text = stringResource(R.string.format_selection),\n                        style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),\n                    )\n                },\n                scrollBehavior = scrollBehavior,\n                navigationIcon = {\n                    IconButton(onClick = { onNavigateBack() }) {\n                        Icon(Icons.Outlined.Close, stringResource(R.string.close))\n                    }\n                },\n            )\n        },\n        floatingActionButton = {\n            val isFormatSelected = isSuggestedFormatSelected || formatList.isNotEmpty()\n            if (isFormatSelected) {\n                ExtendedFloatingActionButton(\n                    onClick = {\n                        onDownloadPressed(\n                            FormatConfig(\n                                formatList = formatList,\n                                videoClips =\n                                    if (isClippingVideo) listOf(VideoClip(videoClipDuration))\n                                    else emptyList(),\n                                splitByChapter = isSplittingVideo,\n                                newTitle = videoTitle,\n                                selectedSubtitles = selectedSubtitles,\n                                selectedAutoCaptions = selectedAutoCaptions,\n                            )\n                        )\n                    },\n                    modifier = Modifier.padding(12.dp),\n                    icon = {\n                        Icon(\n                            imageVector = Icons.Outlined.FileDownload,\n                            contentDescription = null,\n                            modifier = Modifier.size(24.dp),\n                        )\n                    },\n                    text = { Text(stringResource(R.string.start_download)) },\n                    expanded = isFabExpanded,\n                )\n            }\n        },\n        floatingActionButtonPosition = FabPosition.End,\n    ) { paddingValues ->\n        LazyVerticalGrid(\n            modifier = Modifier.padding(paddingValues),\n            state = lazyGridState,\n            verticalArrangement = Arrangement.spacedBy(8.dp),\n            horizontalArrangement = Arrangement.spacedBy(8.dp),\n            columns = GridCells.Adaptive(150.dp),\n            contentPadding = PaddingValues(8.dp),\n        ) {\n            videoInfo.run {\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    FormatVideoPreview(\n                        modifier = Modifier.padding(horizontal = 8.dp),\n                        title = videoTitle.ifEmpty { title },\n                        author = uploader ?: channel ?: uploaderId.toString(),\n                        thumbnailUrl = thumbnail.toHttpsUrl(),\n                        duration = duration.roundToInt(),\n                        isClippingVideo = isClippingVideo,\n                        isSplittingVideo = isSplittingVideo,\n                        isClippingAvailable = isClippingAvailable,\n                        isSplitByChapterAvailable = isSplitByChapterAvailable,\n                        onClippingToggled = { isClippingVideo = !isClippingVideo },\n                        onSplittingToggled = { isSplittingVideo = !isSplittingVideo },\n                        onRename = { showRenameDialog = true },\n                        onOpenThumbnail = { uriHandler.openUri(thumbnail.toHttpsUrl()) },\n                    )\n                }\n            }\n\n            item(span = { GridItemSpan(maxLineSpan) }) {\n                var shouldUpdateClipDuration by remember { mutableStateOf(false) }\n\n                Column {\n                    AnimatedVisibility(visible = isClippingVideo) {\n                        Column {\n                            val state =\n                                remember(isClippingVideo, showVideoClipDialog) {\n                                    RangeSliderState(\n                                        activeRangeStart = videoClipDuration.start,\n                                        activeRangeEnd = videoClipDuration.endInclusive,\n                                        valueRange = videoDurationRange,\n                                        onValueChangeFinished = { shouldUpdateClipDuration = true },\n                                    )\n                                }\n                            DisposableEffect(shouldUpdateClipDuration) {\n                                videoClipDuration = state.activeRangeStart..state.activeRangeEnd\n                                onDispose { shouldUpdateClipDuration = false }\n                            }\n\n                            VideoSelectionSlider(\n                                modifier = Modifier.fillMaxWidth(),\n                                state = state,\n                                onDiscard = { isClippingVideo = false },\n                                onDurationClick = { showVideoClipDialog = true },\n                            )\n                            androidx.compose.material3.HorizontalDivider()\n                        }\n                    }\n\n                    AnimatedVisibility(visible = isSplittingVideo) {\n                        Column {\n                            Row(\n                                modifier = Modifier.fillMaxWidth(),\n                                verticalAlignment = Alignment.CenterVertically,\n                            ) {\n                                Text(\n                                    text =\n                                        stringResource(\n                                            id = R.string.split_video_msg,\n                                            videoInfo.chapters?.size ?: 0,\n                                        ),\n                                    style = MaterialTheme.typography.labelMedium,\n                                    modifier = Modifier.padding(horizontal = 12.dp),\n                                )\n                                Spacer(modifier = Modifier.weight(1f))\n                                TextButtonWithIcon(\n                                    onClick = { isSplittingVideo = false },\n                                    icon = Icons.Outlined.Delete,\n                                    text = stringResource(id = R.string.discard),\n                                    contentColor = MaterialTheme.colorScheme.error,\n                                )\n                            }\n                            androidx.compose.material3.HorizontalDivider()\n                        }\n                    }\n                }\n            }\n\n            if (suggestedSubtitleMap.isNotEmpty()) {\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    Column(modifier = Modifier.fillMaxWidth()) {\n                        Row(\n                            verticalAlignment = Alignment.CenterVertically,\n                            modifier = Modifier.padding(top = 12.dp).padding(horizontal = 12.dp),\n                        ) {\n                            Text(\n                                text = stringResource(id = R.string.subtitle_language),\n                                color = MaterialTheme.colorScheme.primary,\n                                style = MaterialTheme.typography.titleSmall,\n                                modifier = Modifier.weight(1f),\n                            )\n\n                            ClickableTextAction(\n                                visible = true,\n                                text =\n                                    stringResource(\n                                        id =\n                                            androidx.appcompat.R.string\n                                                .abc_activity_chooser_view_see_all\n                                    ),\n                            ) {\n                                showSubtitleSelectionDialog = true\n                            }\n                        }\n\n                        LazyRow(modifier = Modifier.padding()) {\n                            for ((code, formats) in suggestedSubtitleMap) {\n                                item {\n                                    VideoFilterChip(\n                                        selected = selectedSubtitles.contains(code),\n                                        onClick = {\n                                            if (selectedSubtitles.contains(code)) {\n                                                selectedSubtitles.remove(code)\n                                            } else {\n                                                selectedSubtitles.add(code)\n                                            }\n                                        },\n                                        label = formats.first().run { name ?: protocol ?: code },\n                                    )\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (isSuggestedFormatAvailable) {\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    Row(\n                        verticalAlignment = Alignment.CenterVertically,\n                        modifier =\n                            Modifier.padding(top = 12.dp, bottom = 4.dp).padding(horizontal = 12.dp),\n                    ) {\n                        FormatSubtitle(text = stringResource(R.string.suggested))\n                    }\n                }\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    val onClick = {\n                        isSuggestedFormatSelected = true\n                        selectedAudioOnlyFormats.clear()\n                        selectedVideoAudioFormat = NOT_SELECTED\n                        selectedVideoOnlyFormat = NOT_SELECTED\n                    }\n\n                    Row(\n                        verticalAlignment = Alignment.CenterVertically,\n                        horizontalArrangement = Arrangement.spacedBy(8.dp),\n                    ) {\n                        SuggestedFormatItem(\n                            modifier = Modifier.weight(1f),\n                            videoInfo = videoInfo,\n                            selected = isSuggestedFormatSelected,\n                            onClick = onClick,\n                        )\n                    }\n                }\n            }\n\n            if (audioOnlyFormats.isNotEmpty())\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    Row(\n                        verticalAlignment = Alignment.CenterVertically,\n                        modifier = Modifier.padding(top = 16.dp).padding(horizontal = 12.dp),\n                    ) {\n                        FormatSubtitle(\n                            text = stringResource(R.string.audio),\n                            color = MaterialTheme.colorScheme.secondary,\n                            modifier = Modifier.weight(1f).padding(vertical = 4.dp),\n                        )\n\n                        ClickableTextAction(\n                            visible = audioOnlyItemLimit < audioOnlyFormats.size,\n                            text = stringResource(R.string.show_all_items, audioOnlyFormats.size),\n                        ) {\n                            hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                            audioOnlyItemLimit = Int.MAX_VALUE\n                        }\n                    }\n                }\n\n            itemsIndexed(\n                audioOnlyFormats.subList(\n                    fromIndex = 0,\n                    toIndex = min(audioOnlyItemLimit, audioOnlyFormats.size),\n                )\n            ) { index, formatInfo ->\n                FormatItem(\n                    formatInfo = formatInfo,\n                    duration = duration,\n                    selected = selectedAudioOnlyFormats.contains(index),\n                    containerColor = MaterialTheme.colorScheme.secondaryContainer,\n                    outlineColor = MaterialTheme.colorScheme.secondary,\n                    onLongClick = { formatInfo.url.share() },\n                ) {\n                    if (selectedAudioOnlyFormats.contains(index)) {\n                        selectedAudioOnlyFormats.remove(index)\n                    } else {\n                        if (!mergeAudioStream) {\n                            selectedAudioOnlyFormats.clear()\n                        }\n                        isSuggestedFormatSelected = false\n                        selectedAudioOnlyFormats.add(index)\n                    }\n                }\n            }\n\n            if (!audioOnly) {\n                if (videoOnlyFormats.isNotEmpty())\n                    item(span = { GridItemSpan(maxLineSpan) }) {\n                        Row(\n                            verticalAlignment = Alignment.CenterVertically,\n                            modifier = Modifier.padding(top = 16.dp).padding(horizontal = 12.dp),\n                        ) {\n                            FormatSubtitle(\n                                text = stringResource(R.string.video_only),\n                                color = MaterialTheme.colorScheme.tertiary,\n                                modifier = Modifier.weight(1f).padding(vertical = 4.dp),\n                            )\n\n                            ClickableTextAction(\n                                visible = videoOnlyItemLimit < videoOnlyFormats.size,\n                                text =\n                                    stringResource(R.string.show_all_items, videoOnlyFormats.size),\n                            ) {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                                videoOnlyItemLimit = Int.MAX_VALUE\n                            }\n                        }\n                    }\n                itemsIndexed(\n                    videoOnlyFormats.subList(0, min(videoOnlyItemLimit, videoOnlyFormats.size))\n                ) { index, formatInfo ->\n                    FormatItem(\n                        formatInfo = formatInfo,\n                        duration = duration,\n                        selected = selectedVideoOnlyFormat == index,\n                        containerColor = MaterialTheme.colorScheme.tertiaryContainer,\n                        outlineColor = MaterialTheme.colorScheme.tertiary,\n                        onLongClick = { formatInfo.url.share() },\n                    ) {\n                        selectedVideoOnlyFormat =\n                            if (selectedVideoOnlyFormat == index) NOT_SELECTED\n                            else {\n                                selectedVideoAudioFormat = NOT_SELECTED\n                                isSuggestedFormatSelected = false\n                                index\n                            }\n                    }\n                }\n            }\n            if (videoAudioFormats.isNotEmpty()) {\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    Row(\n                        verticalAlignment = Alignment.CenterVertically,\n                        modifier = Modifier.padding(top = 16.dp).padding(horizontal = 12.dp),\n                    ) {\n                        FormatSubtitle(\n                            text = stringResource(R.string.video),\n                            modifier = Modifier.weight(1f).padding(vertical = 4.dp),\n                        )\n                        ClickableTextAction(\n                            visible = videoAudioItemLimit < videoAudioFormats.size,\n                            text = stringResource(R.string.show_all_items, videoAudioFormats.size),\n                        ) {\n                            hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                            videoAudioItemLimit = Int.MAX_VALUE\n                        }\n                    }\n                }\n                itemsIndexed(\n                    videoAudioFormats.subList(0, min(videoAudioItemLimit, videoAudioFormats.size))\n                ) { index, formatInfo ->\n                    FormatItem(\n                        formatInfo = formatInfo,\n                        duration = duration,\n                        selected = selectedVideoAudioFormat == index,\n                        onLongClick = { formatInfo.url.share() },\n                    ) {\n                        selectedVideoAudioFormat =\n                            if (selectedVideoAudioFormat == index) NOT_SELECTED\n                            else {\n                                selectedAudioOnlyFormats.clear()\n                                selectedVideoOnlyFormat = NOT_SELECTED\n                                isSuggestedFormatSelected = false\n                                index\n                            }\n                    }\n                }\n            }\n\n            if (!audioOnly && audioOnlyFormats.isNotEmpty() && videoOnlyFormats.isNotEmpty())\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    PreferenceInfo(\n                        modifier = Modifier.padding(horizontal = 12.dp, vertical = 12.dp),\n                        text = stringResource(R.string.abs_hint),\n                        applyPaddings = false,\n                    )\n                }\n            item { Spacer(modifier = Modifier.height(64.dp)) }\n        }\n    }\n    if (showVideoClipDialog)\n        VideoClipDialog(\n            onDismissRequest = { showVideoClipDialog = false },\n            initialValue = videoClipDuration,\n            valueRange = videoDurationRange,\n            onConfirm = { videoClipDuration = it },\n        )\n\n    if (showRenameDialog)\n        RenameDialog(\n            initialValue = videoTitle.ifEmpty { videoInfo.title },\n            onDismissRequest = { showRenameDialog = false },\n        ) {\n            videoTitle = it\n        }\n    if (showSubtitleSelectionDialog)\n        SubtitleSelectionDialog(\n            suggestedSubtitles = suggestedSubtitleMap,\n            autoCaptions = otherSubtitleMap,\n            selectedSubtitles = selectedSubtitles,\n            onDismissRequest = { showSubtitleSelectionDialog = false },\n            onConfirm = { subs, autoSubs ->\n                selectedSubtitles.run {\n                    clear()\n                    addAll(subs)\n                }\n\n                showSubtitleSelectionDialog = false\n            },\n        )\n}\n\n@Composable\nprivate fun RenameDialog(\n    initialValue: String,\n    onDismissRequest: () -> Unit,\n    onConfirm: (String) -> Unit,\n) {\n    var filename by remember { mutableStateOf(initialValue) }\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton {\n                onConfirm(filename)\n                onDismissRequest()\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        title = { Text(text = stringResource(id = R.string.rename)) },\n        icon = { Icon(imageVector = Icons.Outlined.Edit, contentDescription = null) },\n        text = {\n            Column {\n                OutlinedTextField(\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                    value = filename,\n                    onValueChange = { filename = it },\n                    label = { Text(text = stringResource(id = R.string.title)) },\n                    trailingIcon = { if (filename == initialValue) ClearButton { filename = \"\" } },\n                )\n            }\n        },\n    )\n}\n\nprivate fun (Map<String, List<SubtitleFormat>>).filterWithSearchText(\n    searchText: String\n): Map<String, List<SubtitleFormat>> {\n    return this.filter {\n        it.run {\n            searchText.isBlank() ||\n                key.contains(searchText, ignoreCase = true) ||\n                value.any { format ->\n                    format.name?.contains(searchText, ignoreCase = true) ?: false\n                }\n        }\n    }\n}\n\nprivate fun Map<String, List<SubtitleFormat>>.sortedWithSelection(\n    selectedKeys: List<String>\n): Map<String, List<SubtitleFormat>> {\n    return this.toList()\n        .sortedWith { entry1, entry2 ->\n            when {\n                entry1.first in selectedKeys && entry2.first in selectedKeys ->\n                    entry1.compareTo(entry2) // Both in selectedKeys - equal priority\n                entry1.first in selectedKeys -> -1 // str1 has priority\n                entry2.first in selectedKeys -> 1 // str2 has priority\n                else -> entry1.compareTo(entry2)\n            }\n        }\n        .toMap()\n}\n\n/**\n * Prioritizes comparison of subtitle names (via `getSubtitleName()`) if available, otherwise\n * compares the `key` portion of the pairs.\n *\n * Examples: `zh` (Chinese) should be greater than `en` (English) according to their names\n */\nprivate fun (Pair<String, List<SubtitleFormat>>).compareTo(\n    other: (Pair<String, List<SubtitleFormat>>)\n): Int {\n    val (key, list) = this\n    val (otherKey, otherList) = other\n\n    val name = list.getSubtitleName()\n    val otherName = otherList.getSubtitleName()\n\n    return if (name != null && otherName != null) {\n        name.compareTo(otherName)\n    } else {\n        key.compareTo(otherKey)\n    }\n}\n\nprivate fun (List<SubtitleFormat>).getSubtitleName(): String? = firstOrNull()?.name\n\n@OptIn(ExperimentalFoundationApi::class)\n@Composable\nprivate fun SubtitleSelectionDialog(\n    suggestedSubtitles: Map<String, List<SubtitleFormat>>,\n    autoCaptions: Map<String, List<SubtitleFormat>>,\n    selectedSubtitles: List<String>,\n    onDismissRequest: () -> Unit = {},\n    onConfirm: (subs: List<String>, autoSubs: List<String>) -> Unit = { _, _ -> },\n) {\n    var searchText by remember { mutableStateOf(\"\") }\n    val selectedSubtitles = remember {\n        mutableStateListOf<String>().apply { addAll(selectedSubtitles) }\n    }\n    val selectedAutoCaptions = remember { mutableStateListOf<String>() }\n\n    val suggestedSubtitlesFiltered =\n        suggestedSubtitles.filterWithSearchText(searchText).sortedWithSelection(selectedSubtitles)\n    val autoCaptionsFiltered =\n        autoCaptions.filterWithSearchText(searchText).sortedWithSelection(selectedSubtitles)\n\n    SealDialog(\n        containerColor = MaterialTheme.colorScheme.surfaceContainerLowest,\n        onDismissRequest = onDismissRequest,\n        confirmButton = { ConfirmButton { onConfirm(selectedSubtitles, selectedAutoCaptions) } },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        title = { Text(text = stringResource(id = R.string.subtitle_language)) },\n        icon = { Icon(imageVector = Icons.Outlined.Subtitles, contentDescription = null) },\n        text = {\n            Column {\n                if (autoCaptions.size + suggestedSubtitles.size > 5) {\n                    SealSearchBar(\n                        text = searchText,\n                        placeholderText = stringResource(R.string.search_in_subtitles),\n                        modifier = Modifier.padding(horizontal = 16.dp),\n                    ) {\n                        searchText = it\n                    }\n                }\n\n                LazyColumn(contentPadding = PaddingValues(vertical = 12.dp)) {\n                    if (suggestedSubtitlesFiltered.isNotEmpty()) {\n                        item {\n                            Text(\n                                text = stringResource(id = R.string.suggested),\n                                style = MaterialTheme.typography.titleSmall,\n                                color = MaterialTheme.colorScheme.primary,\n                                modifier = Modifier.padding(horizontal = 24.dp, vertical = 4.dp),\n                            )\n                        }\n                    }\n                    for ((code, formats) in suggestedSubtitlesFiltered) {\n                        item(key = code) {\n                            DialogCheckBoxItem(\n                                modifier = Modifier.animateItem(),\n                                checked = selectedSubtitles.contains(code),\n                                onValueChange = {\n                                    if (selectedSubtitles.contains(code)) {\n                                        selectedSubtitles.remove(code)\n                                    } else {\n                                        selectedSubtitles.add(code)\n                                    }\n                                },\n                                text = formats.first().run { name ?: protocol ?: code },\n                            )\n                        }\n                    }\n\n                    if (autoCaptionsFiltered.isNotEmpty()) {\n                        item {\n                            Text(\n                                text = stringResource(id = R.string.auto_subtitle),\n                                style = MaterialTheme.typography.titleSmall,\n                                color = MaterialTheme.colorScheme.primary,\n                                modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp),\n                            )\n                        }\n                        for ((code, formats) in autoCaptionsFiltered) {\n                            item(key = code) {\n                                DialogCheckBoxItem(\n                                    modifier = Modifier.animateItem(),\n                                    checked = selectedAutoCaptions.contains(code),\n                                    onValueChange = {\n                                        if (selectedAutoCaptions.contains(code)) {\n                                            selectedAutoCaptions.remove(code)\n                                        } else {\n                                            selectedAutoCaptions.add(code)\n                                        }\n                                    },\n                                    text = formats.first().run { name ?: protocol ?: code },\n                                )\n                            }\n                        }\n                    }\n                }\n                androidx.compose.material3.HorizontalDivider()\n            }\n        },\n    )\n}\n\n@Preview\n@Composable\nprivate fun SubtitleSelectionDialogPreview() {\n    val captionsMap =\n        mapOf(\n            \"en-en\" to listOf(SubtitleFormat(ext = \"\", url = \"\", name = \"English from English\")),\n            \"ja-en\" to listOf(SubtitleFormat(ext = \"\", url = \"\", name = \"Japanese from English\")),\n            \"zh-Hans-en\" to\n                listOf(\n                    SubtitleFormat(ext = \"\", url = \"\", name = \"Chinese (Simplified) from English\")\n                ),\n            \"zh-Hant-en\" to\n                listOf(\n                    SubtitleFormat(ext = \"\", url = \"\", name = \"Chinese (Traditional) from English\")\n                ),\n        )\n\n    val subMap = buildMap {\n        put(\"en\", listOf(SubtitleFormat(ext = \"ass\", url = \"\", name = \"English\")))\n        put(\"ja\", listOf(SubtitleFormat(ext = \"ass\", url = \"\", name = \"Japanese\")))\n    }\n\n    SealTheme {\n        SubtitleSelectionDialog(\n            suggestedSubtitles = subMap,\n            autoCaptions = captionsMap,\n            selectedSubtitles = listOf(),\n        )\n    }\n}\n\n@Composable\nprivate fun ClickableTextAction(\n    visible: Boolean,\n    text: String,\n    modifier: Modifier = Modifier,\n    onClick: () -> Unit,\n) {\n    AnimatedVisibility(visible = visible, exit = fadeOut(animationSpec = spring())) {\n        Text(\n            text = text,\n            color = MaterialTheme.colorScheme.primary,\n            style = MaterialTheme.typography.titleSmall,\n            modifier =\n                modifier\n                    .clip(CircleShape)\n                    .clickable(onClick = onClick)\n                    .padding(vertical = 4.dp, horizontal = 12.dp),\n        )\n    }\n}\n\nfun <T : Collection<String>> T.filterWithRegex(subtitleLanguageRegex: String): Set<String> {\n    val regexGroup = subtitleLanguageRegex.split(',')\n    return filter { language -> regexGroup.any { Regex(it).matchEntire(language) != null } }.toSet()\n}\n\n@OptIn(ExperimentalLayoutApi::class)\n@Composable\n@Preview\nfun UpdateSubtitleLanguageDialog(\n    modifier: Modifier = Modifier,\n    languages: Set<String> = setOf(\"en\", \"ja\"),\n    onDismissRequest: () -> Unit = {},\n    onConfirm: () -> Unit = {},\n) {\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        title = {\n            Text(\n                text = stringResource(R.string.update_subtitle_languages),\n                textAlign = TextAlign.Center,\n            )\n        },\n        icon = { Icon(imageVector = Icons.Filled.Subtitles, contentDescription = null) },\n        text = {\n            Column {\n                Text(text = stringResource(R.string.update_language_msg))\n\n                Spacer(modifier = Modifier.height(24.dp))\n\n                FlowRow(\n                    horizontalArrangement = Arrangement.spacedBy(20.dp),\n                    verticalArrangement = Arrangement.spacedBy(12.dp),\n                ) {\n                    languages.forEach {\n                        Row(modifier = Modifier, verticalAlignment = Alignment.CenterVertically) {\n                            Box(\n                                modifier =\n                                    Modifier.padding(end = 8.dp)\n                                        .size(16.dp)\n                                        .background(\n                                            color = it.hashCode().generateLabelColor(),\n                                            shape = CircleShape,\n                                        )\n                                        .clearAndSetSemantics {}\n                            ) {}\n                            Text(\n                                text = it,\n                                modifier = Modifier,\n                                style = MaterialTheme.typography.bodySmall,\n                            )\n                        }\n                    }\n                }\n                Spacer(modifier = Modifier.height(8.dp))\n            }\n        },\n        confirmButton = {\n            Button(onClick = onConfirm) { Text(text = stringResource(id = R.string.okay)) }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) {\n                Text(text = stringResource(id = R.string.no_thanks))\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/configure/InputUrlDialog.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2.configure\n\nimport androidx.compose.animation.animateColorAsState\nimport androidx.compose.animation.animateContentSize\nimport androidx.compose.foundation.LocalIndication\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.heightIn\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.foundation.lazy.itemsIndexed\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.foundation.selection.toggleable\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.ArrowForward\nimport androidx.compose.material.icons.outlined.Add\nimport androidx.compose.material.icons.outlined.AddLink\nimport androidx.compose.material.icons.outlined.Cancel\nimport androidx.compose.material.icons.outlined.ContentPaste\nimport androidx.compose.material.icons.outlined.ContentPasteGo\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material.icons.outlined.Link\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.SuggestionChip\nimport androidx.compose.material3.SuggestionChipDefaults\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.SwipeToDismissBox\nimport androidx.compose.material3.SwipeToDismissBoxValue\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TriStateCheckbox\nimport androidx.compose.material3.rememberSwipeToDismissBoxState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.DisposableEffect\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateListOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.state.ToggleableState\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.zIndex\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ClearButton\nimport com.junkfood.seal.ui.component.FilledButtonWithIcon\nimport com.junkfood.seal.ui.component.OutlinedButtonWithIcon\nimport com.junkfood.seal.ui.component.OutlinedDismissButton\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.Action\nimport com.junkfood.seal.ui.theme.ErrorTonalPalettes\nimport com.junkfood.seal.util.findURLsFromString\n\n@Composable\nfun InputUrlPage(\n    modifier: Modifier = Modifier,\n    config: Config,\n    onConfigUpdate: (Config) -> Unit,\n    onActionPost: (Action) -> Unit,\n) {\n    val clipboardManager = LocalClipboardManager.current\n    val urlList = remember { mutableStateListOf<String>() }\n    val savedLinks = remember(config) { mutableStateListOf<String>() }\n\n    LaunchedEffect(Unit) {\n        clipboardManager.getText()?.let {\n            urlList.clear()\n            urlList.addAll(findURLsFromString(it.toString()).toSet())\n        }\n    }\n\n    LaunchedEffect(config) { savedLinks.addAll(config.savedLinks) }\n\n    InputUrlPageImpl(\n        modifier = modifier,\n        urlListFromClipboard = urlList,\n        savedLinks = savedLinks,\n        onSaveLink = { savedLinks.add(it) },\n        onRemoveSavedLink = { savedLinks.remove(it) },\n        onActionPost = onActionPost,\n    )\n\n    DisposableEffect(Unit) {\n        onDispose { onConfigUpdate(config.copy(savedLinks = savedLinks.toSet())) }\n    }\n}\n\n@Preview\n@Composable\nprivate fun InputUrlPreview() {\n    val urlList = remember {\n        mutableStateListOf<String>().apply { repeat(20) { add(\"https://www.example$it.com/\") } }\n    }\n    InputUrlPageImpl(\n        urlListFromClipboard = listOf(\"https://www.example.com\"),\n        savedLinks = urlList,\n        onSaveLink = { urlList.add(it) },\n        onRemoveSavedLink = { urlList.remove(it) },\n    ) {}\n}\n\n@Composable\nprivate fun InputUrlPageImpl(\n    modifier: Modifier = Modifier,\n    urlListFromClipboard: List<String>,\n    savedLinks: List<String> = emptyList(),\n    onSaveLink: (String) -> Unit = {},\n    onRemoveSavedLink: (String) -> Unit = {},\n    onActionPost: (Action) -> Unit,\n) {\n\n    var url by remember { mutableStateOf(\"\") }\n    var showPasteDialog by remember { mutableStateOf(false) }\n    var showSavedUrlDialog by remember { mutableStateOf(false) }\n\n    Column(modifier = modifier) {\n        Header(\n            modifier = Modifier.fillMaxWidth().padding(horizontal = 32.dp),\n            title = stringResource(R.string.new_task),\n            icon = Icons.Outlined.Add,\n        )\n        OutlinedTextField(\n            value = url,\n            onValueChange = { url = it },\n            modifier = Modifier.fillMaxWidth().padding(top = 8.dp).padding(horizontal = 32.dp),\n            label = { Text(stringResource(R.string.video_url)) },\n            maxLines = 3,\n            trailingIcon = {\n                if (url.isNotEmpty()) {\n                    ClearButton { url = \"\" }\n                }\n            },\n        )\n\n        LazyRow(\n            modifier = Modifier.padding(top = 8.dp).fillMaxWidth(),\n            horizontalArrangement = Arrangement.spacedBy(8.dp),\n            contentPadding = PaddingValues(horizontal = 32.dp),\n        ) {\n            if (urlListFromClipboard.isNotEmpty()) {\n                item(key = \"paste url\") {\n                    SuggestionChip(\n                        modifier = Modifier.animateItem(),\n                        onClick = { url = urlListFromClipboard.first() },\n                        label = { Text(stringResource(R.string.paste_msg)) },\n                        icon = {\n                            Icon(\n                                imageVector = Icons.Outlined.ContentPaste,\n                                contentDescription = null,\n                                modifier = Modifier.size(SuggestionChipDefaults.IconSize),\n                            )\n                        },\n                    )\n                }\n            }\n\n            if (urlListFromClipboard.size > 1) {\n                item(key = \"paste multiple url\") {\n                    SuggestionChip(\n                        modifier = Modifier.animateItem(),\n                        onClick = { showPasteDialog = true },\n                        label = {\n                            Text(\n                                stringResource(\n                                    R.string.select_multiple_link,\n                                    urlListFromClipboard.size,\n                                )\n                            )\n                        },\n                        icon = {\n                            Icon(\n                                imageVector = Icons.Outlined.ContentPasteGo,\n                                contentDescription = null,\n                                modifier = Modifier.size(SuggestionChipDefaults.IconSize),\n                            )\n                        },\n                    )\n                }\n            }\n\n            item(key = \"saved urls\") {\n                val addToSavedLinks by remember {\n                    derivedStateOf { url.isNotBlank() && !savedLinks.contains(url) }\n                }\n                if (addToSavedLinks || savedLinks.isNotEmpty()) {\n                    SuggestionChip(\n                        modifier = Modifier.animateItem(),\n                        onClick = {\n                            if (addToSavedLinks) onSaveLink(url)\n                            else {\n                                showSavedUrlDialog = true\n                            }\n                        },\n                        label = {\n                            Row(modifier = Modifier.animateContentSize()) {\n                                if (addToSavedLinks) {\n                                    Text(\n                                        stringResource(\n                                            R.string.add_to,\n                                            stringResource(R.string.saved_urls),\n                                        )\n                                    )\n                                } else {\n                                    Text(stringResource(R.string.saved_urls))\n                                }\n                            }\n                        },\n                        icon = {\n                            Icon(\n                                imageVector = Icons.Outlined.AddLink,\n                                contentDescription = null,\n                                modifier = Modifier.size(SuggestionChipDefaults.IconSize),\n                            )\n                        },\n                    )\n                }\n            }\n        }\n\n        Row(\n            modifier =\n                Modifier.align(Alignment.End).padding(top = 24.dp).padding(horizontal = 32.dp)\n        ) {\n            OutlinedButtonWithIcon(\n                modifier = Modifier.padding(horizontal = 12.dp),\n                onClick = { onActionPost(Action.HideSheet) },\n                icon = Icons.Outlined.Cancel,\n                text = stringResource(R.string.cancel),\n            )\n            FilledButtonWithIcon(\n                icon = Icons.AutoMirrored.Outlined.ArrowForward,\n                text = stringResource(R.string.proceed),\n            ) {\n                onActionPost(Action.ProceedWithURLs(listOf(url)))\n            }\n        }\n    }\n    if (showPasteDialog) {\n        URLSelectionDialog(\n            urlListFromClipboard = urlListFromClipboard,\n            onDismissRequest = { showPasteDialog = false },\n            onConfirm = { onActionPost(Action.ProceedWithURLs(it)) },\n        )\n    }\n\n    if (showSavedUrlDialog) {\n        SavedUrlDialogImpl(\n            urls = savedLinks,\n            onRemoveLink = onRemoveSavedLink,\n            onActionPost = onActionPost,\n            onDismissRequest = { showSavedUrlDialog = false },\n        )\n    }\n}\n\n@Composable\nprivate fun URLSelectionDialog(\n    modifier: Modifier = Modifier,\n    urlListFromClipboard: List<String>,\n    onDismissRequest: () -> Unit,\n    onConfirm: (List<String>) -> Unit,\n) {\n    val indexList =\n        remember(urlListFromClipboard) {\n            mutableStateListOf<Int>().apply { addAll(urlListFromClipboard.indices) }\n        }\n\n    SealDialog(\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        title = { Text(stringResource(R.string.select_multiple_link, urlListFromClipboard.size)) },\n        icon = { Icon(Icons.Outlined.AddLink, null) },\n        confirmButton = {\n            FilledButtonWithIcon(\n                icon = Icons.AutoMirrored.Outlined.ArrowForward,\n                text = stringResource(R.string.proceed),\n                enabled = indexList.isNotEmpty(),\n            ) {\n                onConfirm(indexList.map { urlListFromClipboard[it] })\n                onDismissRequest()\n            }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) { Text(stringResource(R.string.cancel)) }\n        },\n        text = {\n            Box(modifier = Modifier.fillMaxSize()) {\n                HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))\n                LazyColumn(modifier = Modifier.padding(bottom = 48.dp).heightIn(max = 600.dp)) {\n                    itemsIndexed(urlListFromClipboard) { index, url ->\n                        DialogCheckBoxItemVariant(text = url, checked = indexList.contains(index)) {\n                            if (!it) {\n                                indexList -= index\n                            } else {\n                                indexList += index\n                            }\n                        }\n                    }\n                }\n\n                val checkBoxState =\n                    remember(indexList.size) {\n                        if (indexList.isEmpty()) {\n                            ToggleableState.Off\n                        } else if (indexList.size < urlListFromClipboard.size) {\n                            ToggleableState.Indeterminate\n                        } else {\n                            ToggleableState.On\n                        }\n                    }\n                Column(modifier = Modifier.align(Alignment.BottomCenter)) {\n                    HorizontalDivider(modifier = Modifier)\n\n                    Row(\n                        verticalAlignment = Alignment.CenterVertically,\n                        modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp).height(48.dp),\n                    ) {\n                        TriStateCheckbox(\n                            state = checkBoxState,\n                            onClick = {\n                                when (checkBoxState) {\n                                    ToggleableState.On -> indexList.clear()\n                                    ToggleableState.Off ->\n                                        indexList.addAll(urlListFromClipboard.indices)\n                                    ToggleableState.Indeterminate -> {\n                                        indexList.clear()\n                                        indexList.addAll(urlListFromClipboard.indices)\n                                    }\n                                }\n                            },\n                        )\n                        Text(stringResource(R.string.select_all))\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Composable\nprivate fun DialogCheckBoxItemVariant(\n    modifier: Modifier = Modifier,\n    text: String,\n    checked: Boolean,\n    onValueChange: (Boolean) -> Unit,\n) {\n    val interactionSource = remember { MutableInteractionSource() }\n\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .toggleable(\n                    value = checked,\n                    enabled = true,\n                    onValueChange = onValueChange,\n                    interactionSource = interactionSource,\n                    indication = LocalIndication.current,\n                )\n                .padding(horizontal = 12.dp),\n        verticalAlignment = Alignment.Top,\n    ) {\n        Checkbox(\n            modifier = Modifier.clearAndSetSemantics {},\n            checked = checked,\n            onCheckedChange = onValueChange,\n            interactionSource = interactionSource,\n        )\n        Text(\n            modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp),\n            text = text,\n            style = MaterialTheme.typography.bodyMedium,\n            maxLines = 2,\n            overflow = TextOverflow.Ellipsis,\n        )\n    }\n}\n\n@Composable\nprivate fun DialogSingleChoiceItemVariant(\n    modifier: Modifier = Modifier,\n    text: String,\n    selected: Boolean,\n    onSelect: () -> Unit,\n) {\n    val interactionSource = remember { MutableInteractionSource() }\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .selectable(\n                    selected = selected,\n                    enabled = true,\n                    onClick = onSelect,\n                    interactionSource = interactionSource,\n                    indication = LocalIndication.current,\n                )\n                .padding(horizontal = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        RadioButton(\n            selected = selected,\n            onClick = onSelect,\n            modifier = Modifier.clearAndSetSemantics {},\n            interactionSource = interactionSource,\n        )\n        Text(\n            modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp),\n            text = text,\n            style = MaterialTheme.typography.bodyMedium,\n            maxLines = 2,\n            overflow = TextOverflow.Ellipsis,\n        )\n    }\n}\n\n@Composable fun SavedURLsDialog(modifier: Modifier = Modifier) {}\n\n@Preview\n@Composable\nprivate fun SavedUrlPreview() {\n    val urls = remember {\n        mutableStateListOf<String>().apply { repeat(10) { add(\"https://www.example$it.com/\") } }\n    }\n    SavedUrlDialogImpl(urls = urls, onActionPost = {}, onRemoveLink = { urls.remove(it) }) {}\n}\n\n@Composable\nprivate fun SavedUrlDialogImpl(\n    modifier: Modifier = Modifier,\n    urls: List<String>,\n    onRemoveLink: (String) -> Unit,\n    onActionPost: (Action) -> Unit,\n    onDismissRequest: () -> Unit,\n) {\n    if (urls.isEmpty()) {\n        onDismissRequest()\n    }\n    var selectedUrl: String? by remember(urls.size) { mutableStateOf(null) }\n    val hapticFeedback = LocalHapticFeedback.current\n\n    SealDialog(\n        modifier = modifier,\n        icon = { Icon(Icons.Outlined.Link, contentDescription = null) },\n        title = { Text(stringResource(R.string.saved_urls)) },\n        onDismissRequest = onDismissRequest,\n        dismissButton = { OutlinedDismissButton(onClick = onDismissRequest) },\n        confirmButton = {\n            FilledButtonWithIcon(\n                icon = Icons.AutoMirrored.Outlined.ArrowForward,\n                text = stringResource(R.string.proceed),\n                enabled = selectedUrl != null,\n            ) {\n                onActionPost(Action.ProceedWithURLs(listOf(selectedUrl!!)))\n            }\n        },\n        text = {\n            Box(modifier = Modifier.animateContentSize()) {\n                HorizontalDivider(Modifier.align(Alignment.TopCenter).zIndex(1f))\n                HorizontalDivider(Modifier.align(Alignment.BottomCenter).zIndex(1f))\n\n                LazyColumn(modifier = Modifier.heightIn(max = 600.dp)) {\n                    items(items = urls, key = { it }) {\n                        val dismissState = rememberSwipeToDismissBoxState()\n                        LaunchedEffect(dismissState.currentValue) {\n                            when (dismissState.currentValue) {\n                                SwipeToDismissBoxValue.EndToStart -> {\n                                    hapticFeedback.performHapticFeedback(HapticFeedbackType.Confirm)\n                                    onRemoveLink(it)\n                                }\n                                else -> {}\n                            }\n                        }\n                        val containerColor by\n                            animateColorAsState(\n                                when (dismissState.targetValue) {\n                                    SwipeToDismissBoxValue.EndToStart ->\n                                        ErrorTonalPalettes.accent1(80.0)\n                                    else -> MaterialTheme.colorScheme.surfaceContainerHigh\n                                }\n                            )\n                        val contentColor by\n                            animateColorAsState(\n                                when (dismissState.targetValue) {\n                                    SwipeToDismissBoxValue.Settled ->\n                                        MaterialTheme.colorScheme.onSurface\n                                    else -> ErrorTonalPalettes.accent1(10.0)\n                                }\n                            )\n                        SwipeToDismissBox(\n                            modifier = Modifier.animateItem(),\n                            state = dismissState,\n                            enableDismissFromEndToStart = true,\n                            enableDismissFromStartToEnd = false,\n                            backgroundContent = {\n                                Box(Modifier.fillMaxSize().background(containerColor)) {\n                                    Icon(\n                                        Icons.Outlined.Delete,\n                                        null,\n                                        modifier =\n                                            Modifier.align(Alignment.CenterEnd)\n                                                .padding(end = 16.dp)\n                                                .size(28.dp),\n                                        tint = contentColor,\n                                    )\n                                }\n                            },\n                        ) {\n                            Surface(color = MaterialTheme.colorScheme.surfaceContainerHigh) {\n                                DialogSingleChoiceItemVariant(\n                                    text = it,\n                                    selected = selectedUrl == it,\n                                    onSelect = { selectedUrl = it },\n                                )\n                            }\n                        }\n                    }\n                }\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/downloadv2/configure/PlaylistSelectionPage.kt",
    "content": "package com.junkfood.seal.ui.page.downloadv2.configure\n\nimport androidx.activity.compose.BackHandler\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.navigationBarsPadding\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.itemsIndexed\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.PlaylistAdd\nimport androidx.compose.material.icons.outlined.Close\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.PlainTooltip\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.TooltipBox\nimport androidx.compose.material3.TooltipDefaults\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberModalBottomSheetState\nimport androidx.compose.material3.rememberTooltipState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateListOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.saveable.listSaver\nimport androidx.compose.runtime.saveable.rememberSaveable\nimport androidx.compose.runtime.setValue\nimport androidx.compose.runtime.toMutableStateList\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.DownloaderV2\nimport com.junkfood.seal.download.TaskFactory\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.component.PlaylistItem\nimport com.junkfood.seal.ui.component.SealModalBottomSheet\nimport com.junkfood.seal.ui.component.SealModalBottomSheetM2Variant\nimport com.junkfood.seal.ui.page.download.PlaylistSelectionDialog\nimport com.junkfood.seal.ui.page.downloadv2.configure.DownloadDialogViewModel.SelectionState\nimport com.junkfood.seal.ui.page.settings.format.AudioQuickSettingsDialog\nimport com.junkfood.seal.ui.page.settings.format.VideoQuickSettingsDialog\nimport com.junkfood.seal.util.AUDIO_CONVERSION_FORMAT\nimport com.junkfood.seal.util.AUDIO_CONVERT\nimport com.junkfood.seal.util.AUDIO_FORMAT\nimport com.junkfood.seal.util.AUDIO_QUALITY\nimport com.junkfood.seal.util.DownloadType.Audio\nimport com.junkfood.seal.util.DownloadType.Video\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.PlaylistResult\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.USE_CUSTOM_AUDIO_PRESET\nimport com.junkfood.seal.util.VIDEO_FORMAT\nimport com.junkfood.seal.util.VIDEO_QUALITY\nimport kotlinx.coroutines.launch\nimport org.koin.compose.koinInject\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun PlaylistSelectionPage(\n    state: SelectionState.PlaylistSelection,\n    downloader: DownloaderV2 = koinInject(),\n    onDismissRequest: () -> Unit = {},\n) {\n    var preferences by remember {\n        mutableStateOf(DownloadUtil.DownloadPreferences.createFromPreferences())\n    }\n    var showVideoPresetDialog by remember { mutableStateOf(false) }\n    var showAudioPresetDialog by remember { mutableStateOf(false) }\n\n    var taskList by remember { mutableStateOf(emptyList<TaskFactory.TaskWithState>()) }\n\n    val sheetState =\n        androidx.compose.material.rememberModalBottomSheetState(\n            initialValue = ModalBottomSheetValue.Hidden,\n            skipHalfExpanded = true,\n        )\n\n    LaunchedEffect(state) { sheetState.show() }\n    val scope = rememberCoroutineScope()\n    val onBack: () -> Unit = {\n        scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() }\n    }\n\n    BackHandler(onBack = onBack)\n\n    var showConfigurationSheet by remember { mutableStateOf(false) }\n\n    val configureSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)\n\n    SealModalBottomSheetM2Variant(sheetState = sheetState, sheetGesturesEnabled = false) {\n        PlaylistSelectionPageImpl(result = state.result, onDismissRequest = onBack) {\n            taskList = it\n            showConfigurationSheet = true\n        }\n    }\n\n    val onDismissConfigurationSheet: () -> Unit = {\n        scope\n            .launch { configureSheetState.hide() }\n            .invokeOnCompletion { showConfigurationSheet = false }\n    }\n\n    if (showConfigurationSheet) {\n\n        SealModalBottomSheet(\n            sheetState = configureSheetState,\n            contentPadding = PaddingValues(),\n            onDismissRequest = onDismissConfigurationSheet,\n        ) {\n            ConfigurePagePlaylistVariant(\n                modifier = Modifier,\n                initialDownloadType = Video,\n                preferences = preferences,\n                onPreferencesUpdate = { preferences = it },\n                onPresetEdit = { type ->\n                    when (type) {\n                        Audio -> showAudioPresetDialog = true\n\n                        Video -> showVideoPresetDialog = true\n\n                        else -> {}\n                    }\n                },\n                onDismissRequest = onDismissConfigurationSheet,\n                onDownload = {\n                    val preferences = preferences.copy(extractAudio = it == Audio)\n                    taskList\n                        .map { it.copy(task = it.task.copy(preferences = preferences)) }\n                        .forEach(downloader::enqueue)\n                    onDismissConfigurationSheet()\n                    onBack()\n                },\n            )\n        }\n    }\n\n    if (showVideoPresetDialog) {\n        var res by remember(preferences) { mutableIntStateOf(preferences.videoResolution) }\n        var format by remember(preferences) { mutableIntStateOf(preferences.videoFormat) }\n\n        VideoQuickSettingsDialog(\n            videoResolution = res,\n            videoFormatPreference = format,\n            onResolutionSelect = { res = it },\n            onFormatSelect = { format = it },\n            onDismissRequest = { showVideoPresetDialog = false },\n            onSave = {\n                VIDEO_FORMAT.updateInt(format)\n                VIDEO_QUALITY.updateInt(res)\n                preferences = DownloadUtil.DownloadPreferences.createFromPreferences()\n            },\n        )\n    }\n\n    if (showAudioPresetDialog) {\n        var quality by remember(preferences) { mutableIntStateOf(preferences.audioQuality) }\n        var customPreset by\n            remember(preferences) { mutableStateOf(preferences.useCustomAudioPreset) }\n        var conversionFmt by\n            remember(preferences) { mutableIntStateOf(preferences.audioConvertFormat) }\n        var convertAudio by remember(preferences) { mutableStateOf(preferences.convertAudio) }\n        var preferredFormat by remember(preferences) { mutableIntStateOf(preferences.audioFormat) }\n\n        AudioQuickSettingsDialog(\n            modifier = Modifier,\n            preferences = preferences,\n            audioQuality = quality,\n            onQualitySelect = { quality = it },\n            useCustomAudioPreset = customPreset,\n            onCustomPresetToggle = { customPreset = it },\n            convertAudio = convertAudio,\n            onConvertToggled = { convertAudio = it },\n            conversionFormat = conversionFmt,\n            onConversionSelect = { conversionFmt = it },\n            preferredFormat = preferredFormat,\n            onPreferredSelect = { preferredFormat = it },\n            onDismissRequest = { showAudioPresetDialog = false },\n            onSave = {\n                AUDIO_QUALITY.updateInt(quality)\n                USE_CUSTOM_AUDIO_PRESET.updateBoolean(customPreset)\n                AUDIO_CONVERSION_FORMAT.updateInt(conversionFmt)\n                AUDIO_CONVERT.updateBoolean(convertAudio)\n                AUDIO_FORMAT.updateInt(preferredFormat)\n                preferences = DownloadUtil.DownloadPreferences.createFromPreferences()\n            },\n        )\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun PlaylistSelectionPageImpl(\n    result: PlaylistResult,\n    onDismissRequest: () -> Unit = {},\n    onConfirmSelection: (List<TaskFactory.TaskWithState>) -> Unit,\n) {\n    val view = LocalView.current\n\n    val selectedItems =\n        rememberSaveable(\n            saver =\n                listSaver<MutableList<Int>, Int>(\n                    save = {\n                        if (it.isNotEmpty()) {\n                            it.toList()\n                        } else {\n                            emptyList()\n                        }\n                    },\n                    restore = { it.toMutableStateList() },\n                )\n        ) {\n            mutableStateListOf()\n        }\n    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()\n    var showDialog by remember { mutableStateOf(false) }\n    val playlistCount = result.entries?.size ?: 0\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            TopAppBar(\n                title = {\n                    Text(\n                        text =\n                            if (selectedItems.isEmpty())\n                                stringResource(id = R.string.download_playlist)\n                            else\n                                stringResource(id = R.string.selected_item_count)\n                                    .format(selectedItems.size),\n                        style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),\n                    )\n                },\n                navigationIcon = {\n                    IconButton(onClick = onDismissRequest) {\n                        Icon(Icons.Outlined.Close, stringResource(R.string.close))\n                    }\n                },\n                actions = {\n                    TextButton(\n                        modifier = Modifier.padding(end = 8.dp),\n                        onClick = {\n                            view.slightHapticFeedback()\n                            onConfirmSelection(\n                                TaskFactory.createWithPlaylistResult(\n                                    playlistUrl =\n                                        result.originalUrl ?: result.webpageUrl.toString(),\n                                    indexList = selectedItems,\n                                    playlistResult = result,\n                                    preferences = DownloadUtil.DownloadPreferences.EMPTY,\n                                )\n                            )\n                        },\n                        enabled = selectedItems.isNotEmpty(),\n                    ) {\n                        Text(text = stringResource(R.string.start_download))\n                    }\n                },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        bottomBar = {\n            Column(\n                modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp).navigationBarsPadding(),\n                verticalArrangement = Arrangement.Center,\n            ) {\n                HorizontalDivider(modifier = Modifier.fillMaxWidth())\n                Row(verticalAlignment = Alignment.CenterVertically) {\n                    Row(\n                        modifier =\n                            Modifier.selectable(\n                                selected =\n                                    selectedItems.size == playlistCount && selectedItems.size != 0,\n                                indication = null,\n                                interactionSource = remember { MutableInteractionSource() },\n                                onClick = {\n                                    view.slightHapticFeedback()\n                                    if (selectedItems.size == playlistCount) selectedItems.clear()\n                                    else {\n                                        selectedItems.clear()\n                                        selectedItems.addAll(1..playlistCount)\n                                    }\n                                },\n                            ),\n                        verticalAlignment = Alignment.CenterVertically,\n                    ) {\n                        Checkbox(\n                            modifier = Modifier.padding(16.dp),\n                            checked =\n                                selectedItems.size == playlistCount && selectedItems.size != 0,\n                            onCheckedChange = null,\n                        )\n                        Text(\n                            text = stringResource(R.string.select_all),\n                            style = MaterialTheme.typography.labelLarge,\n                        )\n                    }\n                    Spacer(modifier = Modifier.weight(1f))\n                    IconButton(\n                        modifier = Modifier.padding(end = 4.dp),\n                        onClick = {\n                            view.slightHapticFeedback()\n\n                            showDialog = true\n                        },\n                    ) {\n                        Icon(\n                            imageVector = Icons.AutoMirrored.Outlined.PlaylistAdd,\n                            contentDescription = stringResource(R.string.download_range_selection),\n                        )\n                    }\n                }\n            }\n        },\n    ) { paddings ->\n        Column(modifier = Modifier.padding(paddings)) {\n            LazyColumn {\n                item {\n                    Text(\n                        modifier = Modifier.padding(16.dp),\n                        text =\n                            stringResource(R.string.download_selection_desc).format(result.title),\n                        style = MaterialTheme.typography.bodySmall,\n                    )\n                }\n\n                itemsIndexed(items = result.entries ?: emptyList()) { indexFromZero, entry ->\n                    val index = indexFromZero + 1\n                    TooltipBox(\n                        state = rememberTooltipState(),\n                        positionProvider = TooltipDefaults.rememberTooltipPositionProvider(),\n                        tooltip = { PlainTooltip { Text(text = entry.title ?: index.toString()) } },\n                    ) {\n                        PlaylistItem(\n                            modifier = Modifier.padding(horizontal = 12.dp),\n                            imageModel = entry.thumbnails?.lastOrNull()?.url ?: \"\",\n                            title = entry.title ?: index.toString(),\n                            author =\n                                entry.channel\n                                    ?: entry.uploader\n                                    ?: result.channel\n                                    ?: result.uploader,\n                            selected = selectedItems.contains(index),\n                            onClick = {\n                                if (selectedItems.contains(index)) selectedItems.remove(index)\n                                else selectedItems.add(index)\n                            },\n                        )\n                    }\n                }\n            }\n        }\n    }\n    if (showDialog) {\n        PlaylistSelectionDialog(\n            playlistInfo = result,\n            onDismissRequest = { showDialog = false },\n            onConfirm = {\n                selectedItems.clear()\n                selectedItems.addAll(it)\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/BasePreferencePage.kt",
    "content": "package com.junkfood.seal.ui.page.settings\n\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.WindowInsets\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FabPosition\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.ScaffoldDefaults\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.contentColorFor\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport com.junkfood.seal.ui.component.BackButton\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun BasePreferencePage(\n    modifier: Modifier = Modifier,\n    title: String,\n    onBack: () -> Unit,\n    topBar: @Composable (() -> Unit)? = null,\n    bottomBar: @Composable (() -> Unit) = {},\n    snackbarHost: @Composable () -> Unit = {},\n    floatingActionButton: @Composable () -> Unit = {},\n    floatingActionButtonPosition: FabPosition = FabPosition.End,\n    containerColor: Color = MaterialTheme.colorScheme.background,\n    contentColor: Color = contentColorFor(containerColor),\n    contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,\n    content: @Composable (paddingValues: PaddingValues) -> Unit,\n) {\n    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()\n    val topBar =\n        topBar\n            ?: {\n                LargeTopAppBar(\n                    title = { Text(text = title) },\n                    scrollBehavior = scrollBehavior,\n                    navigationIcon = { BackButton(onClick = onBack) },\n                )\n            }\n    Scaffold(\n        modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = topBar,\n        bottomBar = bottomBar,\n        snackbarHost = snackbarHost,\n        floatingActionButton = floatingActionButton,\n        floatingActionButtonPosition = floatingActionButtonPosition,\n        containerColor = containerColor,\n        contentColor = contentColor,\n        contentWindowInsets = contentWindowInsets,\n        content = content,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/SettingsPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.content.Intent\nimport android.content.pm.PackageManager\nimport android.net.Uri\nimport android.os.Build\nimport android.os.PowerManager\nimport android.provider.Settings\nimport androidx.activity.compose.rememberLauncherForActivityResult\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.shrinkVertically\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.rounded.AudioFile\nimport androidx.compose.material.icons.rounded.BugReport\nimport androidx.compose.material.icons.rounded.EnergySavingsLeaf\nimport androidx.compose.material.icons.rounded.Folder\nimport androidx.compose.material.icons.rounded.Info\nimport androidx.compose.material.icons.rounded.Palette\nimport androidx.compose.material.icons.rounded.SettingsApplications\nimport androidx.compose.material.icons.rounded.SignalCellular4Bar\nimport androidx.compose.material.icons.rounded.SignalWifi4Bar\nimport androidx.compose.material.icons.rounded.Terminal\nimport androidx.compose.material.icons.rounded.VideoFile\nimport androidx.compose.material.icons.rounded.ViewComfy\nimport androidx.compose.material.icons.rounded.VolunteerActivism\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.Route\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferencesHintCard\nimport com.junkfood.seal.ui.component.SettingItem\nimport com.junkfood.seal.util.EXTRACT_AUDIO\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.SHOW_SPONSOR_MSG\n\n@SuppressLint(\"BatteryLife\")\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SettingsPage(onNavigateBack: () -> Unit, onNavigateTo: (String) -> Unit) {\n    val context = LocalContext.current\n    val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager\n    var showBatteryHint by remember {\n        mutableStateOf(\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                !pm.isIgnoringBatteryOptimizations(context.packageName)\n            } else {\n                false\n            }\n        )\n    }\n    val intent =\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n            Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply {\n                data = Uri.parse(\"package:${context.packageName}\")\n            }\n        } else {\n            Intent()\n        }\n    val isActivityAvailable: Boolean =\n        if (Build.VERSION.SDK_INT < 23) false\n        else if (Build.VERSION.SDK_INT < 33)\n            context.packageManager\n                .queryIntentActivities(intent, PackageManager.MATCH_ALL)\n                .isNotEmpty()\n        else\n            context.packageManager\n                .queryIntentActivities(\n                    intent,\n                    PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY.toLong()),\n                )\n                .isNotEmpty()\n\n    val launcher =\n        rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                showBatteryHint = !pm.isIgnoringBatteryOptimizations(context.packageName)\n            }\n        }\n    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()\n\n    val showSponsorMessage by SHOW_SPONSOR_MSG.intState\n\n    LaunchedEffect(Unit) { SHOW_SPONSOR_MSG.updateInt(showSponsorMessage + 1) }\n\n    val typography = MaterialTheme.typography\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            val overrideTypography =\n                remember(typography) { typography.copy(headlineMedium = typography.displaySmall) }\n\n            MaterialTheme(typography = overrideTypography) {\n                LargeTopAppBar(\n                    title = { Text(text = stringResource(id = R.string.settings)) },\n                    navigationIcon = { BackButton(onNavigateBack) },\n                    scrollBehavior = scrollBehavior,\n                    expandedHeight = TopAppBarDefaults.LargeAppBarExpandedHeight + 24.dp,\n                )\n            }\n        },\n    ) {\n        LazyColumn(modifier = Modifier, contentPadding = it) {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                item {\n                    AnimatedVisibility(\n                        visible = showBatteryHint && isActivityAvailable,\n                        exit = shrinkVertically() + fadeOut(),\n                    ) {\n                        PreferencesHintCard(\n                            title = stringResource(R.string.battery_configuration),\n                            icon = Icons.Rounded.EnergySavingsLeaf,\n                            description = stringResource(R.string.battery_configuration_desc),\n                        ) {\n                            launcher.launch(intent)\n                            showBatteryHint =\n                                !pm.isIgnoringBatteryOptimizations(context.packageName)\n                        }\n                    }\n                }\n            }\n            if (!showBatteryHint && showSponsorMessage > 30)\n                item {\n                    PreferencesHintCard(\n                        title = stringResource(id = R.string.sponsor),\n                        icon = Icons.Rounded.VolunteerActivism,\n                        description = stringResource(id = R.string.sponsor_desc),\n                    ) {\n                        onNavigateTo(Route.DONATE)\n                    }\n                }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.general_settings),\n                    description = stringResource(id = R.string.general_settings_desc),\n                    icon = Icons.Rounded.SettingsApplications,\n                ) {\n                    onNavigateTo(Route.GENERAL_DOWNLOAD_PREFERENCES)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.download_directory),\n                    description = stringResource(id = R.string.download_directory_desc),\n                    icon = Icons.Rounded.Folder,\n                ) {\n                    onNavigateTo(Route.DOWNLOAD_DIRECTORY)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.format),\n                    description = stringResource(id = R.string.format_settings_desc),\n                    icon =\n                        if (EXTRACT_AUDIO.getBoolean()) Icons.Rounded.AudioFile\n                        else Icons.Rounded.VideoFile,\n                ) {\n                    onNavigateTo(Route.DOWNLOAD_FORMAT)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.network),\n                    description = stringResource(id = R.string.network_settings_desc),\n                    icon =\n                        if (App.connectivityManager.isActiveNetworkMetered)\n                            Icons.Rounded.SignalCellular4Bar\n                        else Icons.Rounded.SignalWifi4Bar,\n                ) {\n                    onNavigateTo(Route.NETWORK_PREFERENCES)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.custom_command),\n                    description = stringResource(id = R.string.custom_command_desc),\n                    icon = Icons.Rounded.Terminal,\n                ) {\n                    onNavigateTo(Route.TEMPLATE)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.look_and_feel),\n                    description = stringResource(id = R.string.display_settings),\n                    icon = Icons.Rounded.Palette,\n                ) {\n                    onNavigateTo(Route.APPEARANCE)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.interface_and_interaction),\n                    description = stringResource(id = R.string.settings_before_download),\n                    icon = Icons.Rounded.ViewComfy,\n                ) {\n                    onNavigateTo(Route.INTERACTION)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(R.string.trouble_shooting),\n                    description = stringResource(R.string.trouble_shooting_desc),\n                    icon = Icons.Rounded.BugReport,\n                ) {\n                    onNavigateTo(Route.TROUBLESHOOTING)\n                }\n            }\n            item {\n                SettingItem(\n                    title = stringResource(id = R.string.about),\n                    description = stringResource(id = R.string.about_page),\n                    icon = Icons.Rounded.Info,\n                ) {\n                    onNavigateTo(Route.ABOUT)\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/about/AboutPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.about\n\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.text.ClickableText\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.AutoAwesome\nimport androidx.compose.material.icons.outlined.Description\nimport androidx.compose.material.icons.outlined.Info\nimport androidx.compose.material.icons.outlined.NewReleases\nimport androidx.compose.material.icons.outlined.Update\nimport androidx.compose.material.icons.outlined.UpdateDisabled\nimport androidx.compose.material.icons.outlined.VolunteerActivism\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.painterResource\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.ExperimentalTextApi\nimport androidx.compose.ui.text.SpanStyle\nimport androidx.compose.ui.text.UrlAnnotation\nimport androidx.compose.ui.text.buildAnnotatedString\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.text.style.TextDecoration\nimport androidx.compose.ui.tooling.preview.Preview\nimport com.junkfood.seal.App\nimport com.junkfood.seal.App.Companion.packageInfo\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithDivider\nimport com.junkfood.seal.util.AUTO_UPDATE\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.ToastUtil\n\nprivate const val releaseURL = \"https://github.com/JunkFood02/Seal/releases\"\nprivate const val repoUrl = \"https://github.com/JunkFood02/Seal\"\nconst val weblate = \"https://hosted.weblate.org/engage/seal/\"\nconst val YtdlpRepository = \"https://github.com/yt-dlp/yt-dlp\"\nprivate const val githubIssueUrl = \"https://github.com/JunkFood02/Seal/issues\"\nprivate const val telegramChannelUrl = \"https://t.me/seal_app\"\nprivate const val matrixSpaceUrl = \"https://matrix.to/#/#seal-space:matrix.org\"\nprivate const val githubSponsor = \"https://github.com/sponsors/JunkFood02\"\nprivate const val TAG = \"AboutPage\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun AboutPage(\n    onNavigateBack: () -> Unit,\n    onNavigateToCreditsPage: () -> Unit,\n    onNavigateToUpdatePage: () -> Unit,\n    onNavigateToDonatePage: () -> Unit,\n) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val context = LocalContext.current\n    val clipboardManager = LocalClipboardManager.current\n    //    val configuration = LocalConfiguration.current\n    //    val screenDensity = configuration.densityDpi / 160f\n    //    val screenHeight = (configuration.screenHeightDp.toFloat() * screenDensity).roundToInt()\n    //    val screenWidth = (configuration.screenWidthDp.toFloat() * screenDensity).roundToInt()\n    var isAutoUpdateEnabled by remember { mutableStateOf(PreferenceUtil.isAutoUpdateEnabled()) }\n\n    val info = App.getVersionReport()\n    val versionName = packageInfo.versionName\n\n    //        infoBuilder.append(\"App version: $versionName ($versionCode)\\n\")\n    //            .append(\"Device information: Android $release (API ${Build.VERSION.SDK_INT})\\n\")\n    //            .append(\"Supported ABIs: ${Build.SUPPORTED_ABIS.contentToString()}\\n\")\n    //            .append(\"\\nScreen resolution: $screenHeight x $screenWidth\")\n    //            .append(\"Yt-dlp Version:\n    // ${YoutubeDL.version(context.applicationContext)}\").toString()\n\n    val uriHandler = LocalUriHandler.current\n    fun openUrl(url: String) {\n        uriHandler.openUri(url)\n    }\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(modifier = Modifier, text = stringResource(id = R.string.about)) },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            LazyColumn(modifier = Modifier.padding(it)) {\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.readme),\n                        description = stringResource(R.string.readme_desc),\n                        icon = Icons.Outlined.Description,\n                    ) {\n                        openUrl(repoUrl)\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.release),\n                        description = stringResource(R.string.release_desc),\n                        icon = Icons.Outlined.NewReleases,\n                    ) {\n                        openUrl(releaseURL)\n                    }\n                }\n                /*            item {\n                    PreferenceItem(\n                        title = stringResource(R.string.github_issue),\n                        description = stringResource(R.string.github_issue_desc),\n                        icon = Icons.Outlined.ContactSupport,\n                    ) { openUrl(githubIssueUrl) }\n                }*/\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.sponsor),\n                        description = stringResource(id = R.string.sponsor_desc),\n                        icon = Icons.Outlined.VolunteerActivism,\n                    ) {\n                        //                    openUrl(githubSponsor)\n                        onNavigateToDonatePage()\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.telegram_channel),\n                        description = telegramChannelUrl,\n                        icon = painterResource(id = R.drawable.icons8_telegram_app),\n                    ) {\n                        openUrl(telegramChannelUrl)\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.matrix_space),\n                        description = matrixSpaceUrl,\n                        icon = painterResource(id = R.drawable.icons8_matrix),\n                    ) {\n                        openUrl(matrixSpaceUrl)\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.credits),\n                        description = stringResource(id = R.string.credits_desc),\n                        icon = Icons.Outlined.AutoAwesome,\n                    ) {\n                        onNavigateToCreditsPage()\n                    }\n                }\n                item {\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(R.string.auto_update),\n                        description = stringResource(R.string.check_for_updates_desc),\n                        icon =\n                            if (isAutoUpdateEnabled) Icons.Outlined.Update\n                            else Icons.Outlined.UpdateDisabled,\n                        isChecked = isAutoUpdateEnabled,\n                        isSwitchEnabled = !App.isFDroidBuild(),\n                        onClick = onNavigateToUpdatePage,\n                        onChecked = {\n                            isAutoUpdateEnabled = !isAutoUpdateEnabled\n                            PreferenceUtil.updateValue(AUTO_UPDATE, isAutoUpdateEnabled)\n                        },\n                    )\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.version),\n                        description = versionName,\n                        icon = Icons.Outlined.Info,\n                    ) {\n                        clipboardManager.setText(AnnotatedString(info))\n                        ToastUtil.makeToast(R.string.info_copied)\n                    }\n                }\n                item {\n                    PreferenceItem(title = \"Package name\", description = context.packageName) {\n                        clipboardManager.setText(AnnotatedString(context.packageName))\n                        ToastUtil.makeToast(R.string.info_copied)\n                    }\n                }\n            }\n        },\n    )\n}\n\n@OptIn(ExperimentalTextApi::class)\n@Composable\n@Preview\nfun AutoUpdateUnavailableDialog(onDismissRequest: () -> Unit = {}) {\n    val uriHandler = LocalUriHandler.current\n    val hapticFeedback = LocalHapticFeedback.current\n    val hyperLinkText = stringResource(id = R.string.switch_to_github_builds)\n    val text = stringResource(id = R.string.auto_update_disabled_msg, \"F-Droid\", hyperLinkText)\n\n    val annotatedString = buildAnnotatedString {\n        append(text)\n        val startIndex = text.indexOf(hyperLinkText)\n        val endIndex = startIndex + hyperLinkText.length\n        addUrlAnnotation(\n            UrlAnnotation(\"https://github.com/JunkFood02/Seal/releases/latest\"),\n            start = startIndex,\n            end = endIndex,\n        )\n        addStyle(\n            SpanStyle(\n                color = MaterialTheme.colorScheme.tertiary,\n                textDecoration = TextDecoration.Underline,\n            ),\n            start = startIndex,\n            end = endIndex,\n        )\n    }\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton(stringResource(id = R.string.got_it)) { onDismissRequest() }\n        },\n        icon = { Icon(Icons.Outlined.UpdateDisabled, null) },\n        title = {\n            Text(\n                text = stringResource(id = R.string.feature_unavailable),\n                textAlign = TextAlign.Center,\n            )\n        },\n        text = {\n            ClickableText(\n                text = annotatedString,\n                onClick = { index ->\n                    annotatedString.getUrlAnnotations(index, index).firstOrNull()?.let {\n                        hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                        uriHandler.openUri(it.item.url)\n                    }\n                },\n                style =\n                    MaterialTheme.typography.bodyMedium.copy(\n                        MaterialTheme.colorScheme.onSurfaceVariant\n                    ),\n            )\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/about/CreditsPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.about\n\nimport androidx.compose.foundation.Image\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.vector.rememberVectorPainter\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.CreditItem\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\nimport com.junkfood.seal.ui.svg.drawablevectors.coder\n\ndata class Credit(val title: String = \"\", val license: String? = null, val url: String = \"\")\n\nprivate const val GPL_V3 = \"GNU General Public License v3.0\"\nprivate const val GPL_V2 = \"GNU General Public License v2.0\"\nprivate const val LGPL_V2_1 = \"GNU Lesser General Public License, version 2.1\"\nprivate const val APACHE_V2 = \"Apache License, Version 2.0\"\nprivate const val UNLICENSE = \"The Unlicense\"\nprivate const val BSD = \"BSD 3-Clause License\"\n\nprivate const val youtubedlAndroidUrl = \"https://github.com/yausername/youtubedl-android\"\nprivate const val ytdlpUrl = \"https://github.com/yt-dlp/yt-dlp\"\nprivate const val readYou = \"https://github.com/Ashinch/ReadYou\"\nprivate const val dvd = \"https://github.com/yausername/dvd\"\nprivate const val icons8 = \"https://icons8.com/\"\nprivate const val materialIcon = \"https://fonts.google.com/icons\"\nprivate const val materialColor = \"https://github.com/material-foundation/material-color-utilities\"\nprivate const val monet = \"https://github.com/Kyant0/Monet\"\nprivate const val jetpack = \"https://github.com/androidx/androidx\"\nprivate const val coil = \"https://github.com/coil-kt/coil\"\nprivate const val mmkv = \"https://github.com/Tencent/MMKV\"\nprivate const val kotlin = \"https://kotlinlang.org/\"\nprivate const val okhttp = \"https://github.com/square/okhttp\"\nprivate const val accompanist = \"https://github.com/google/accompanist\"\nprivate const val aria2 = \"https://github.com/aria2/aria2\"\nprivate const val material3 = \"https://m3.material.io/\"\nprivate const val unDraw = \"https://undraw.co/\"\nprivate const val materialMotionCompose = \"https://github.com/fornewid/material-motion-compose\"\nprivate const val termux = \"https://github.com/termux/termux-app\"\nprivate const val FFmpeg = \"https://ffmpeg.org/\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun CreditsPage(onNavigateBack: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n\n    val creditsList =\n        listOf(\n            Credit(\"yt-dlp\", UNLICENSE, ytdlpUrl),\n            Credit(\"Read You\", GPL_V3, readYou),\n            Credit(\"youtubedl-android\", GPL_V3, youtubedlAndroidUrl),\n            Credit(\"Termux\", GPL_V3, termux),\n            Credit(\"FFmpeg\", GPL_V2, FFmpeg),\n            Credit(\"Android Jetpack\", APACHE_V2, jetpack),\n            Credit(\"Kotlin\", APACHE_V2, kotlin),\n            Credit(\"dvd\", GPL_V3, dvd),\n            Credit(\"Accompanist\", APACHE_V2, accompanist),\n            Credit(\"Material Design 3\", APACHE_V2, material3),\n            Credit(\"Material Icons\", APACHE_V2, materialIcon),\n            Credit(\"Monet\", APACHE_V2, monet),\n            Credit(\"Material color utilities\", APACHE_V2, materialColor),\n            Credit(\"MMKV\", BSD, mmkv),\n            Credit(\"Coil\", APACHE_V2, coil),\n            Credit(\"aria2\", GPL_V2, aria2),\n            Credit(\"OkHttp\", APACHE_V2, okhttp),\n            Credit(\"material-motion-compose\", APACHE_V2, materialMotionCompose),\n            Credit(\"unDraw\", null, unDraw),\n            Credit(\n                \"App icon by Icons8\",\n                \"Universal Multimedia Licensing Agreement for Icons8\",\n                icons8,\n            ),\n        )\n    val uriHandler = LocalUriHandler.current\n    fun openUrl(url: String) {\n        uriHandler.openUri(url)\n    }\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(modifier = Modifier, text = stringResource(id = R.string.credits)) },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            LazyColumn(modifier = Modifier.padding(it)) {\n                item {\n                    Surface(\n                        modifier =\n                            Modifier.fillParentMaxWidth()\n                                .padding(horizontal = 12.dp, vertical = 12.dp)\n                                .clip(MaterialTheme.shapes.large)\n                                .clickable {}\n                                .clearAndSetSemantics {},\n                        color = MaterialTheme.colorScheme.surfaceContainerLow,\n                    ) {\n                        val painter =\n                            rememberVectorPainter(image = DynamicColorImageVectors.coder())\n                        Image(\n                            painter = painter,\n                            contentDescription = null,\n                            modifier = Modifier.padding(horizontal = 72.dp, vertical = 48.dp),\n                        )\n                    }\n                }\n                items(creditsList) { item ->\n                    CreditItem(title = item.title, license = item.license) { openUrl(item.url) }\n                }\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/about/SponsorPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.about\n\nimport android.util.Log\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.IntrinsicSize\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.heightIn\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.grid.GridCells\nimport androidx.compose.foundation.lazy.grid.GridItemSpan\nimport androidx.compose.foundation.lazy.grid.LazyGridItemScope\nimport androidx.compose.foundation.lazy.grid.LazyVerticalGrid\nimport androidx.compose.foundation.lazy.grid.items\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.House\nimport androidx.compose.material.icons.outlined.Link\nimport androidx.compose.material.icons.outlined.VolunteerActivism\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.ButtonDefaults\nimport androidx.compose.material3.CardDefaults\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.SheetState\nimport androidx.compose.material3.SheetValue\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberModalBottomSheetState\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateListOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.layout.ContentScale\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.AsyncImageImpl\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.SealModalBottomSheet\nimport com.junkfood.seal.ui.component.SponsorItem\nimport com.junkfood.seal.ui.component.gitHubAvatar\nimport com.junkfood.seal.ui.component.gitHubProfile\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.SHOW_SPONSOR_MSG\nimport com.junkfood.seal.util.SocialAccount\nimport com.junkfood.seal.util.SocialAccounts\nimport com.junkfood.seal.util.SponsorEntity\nimport com.junkfood.seal.util.SponsorShip\nimport com.junkfood.seal.util.SponsorUtil\nimport com.junkfood.seal.util.Tier\nimport com.junkfood.seal.util.ToastUtil\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\n\nprivate const val TAG = \"SponsorPage\"\n\nprivate const val SPONSORS = \"Sponsors ☕️\"\nprivate const val BACKERS = \"Backers ❤️\"\nprivate const val SUPPORTERS = \"Supporters 💖\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SponsorsPage(onNavigateBack: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val uriHandler = LocalUriHandler.current\n    val sponsorList = remember { mutableStateListOf<SponsorShip>() }\n    val backerList = remember { mutableStateListOf<SponsorShip>() }\n    val supporterList = remember { mutableStateListOf<SponsorShip>() }\n    val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)\n    var viewingSponsorShip by remember {\n        mutableStateOf(SponsorShip(sponsorEntity = SponsorEntity(\"login\")))\n    }\n    var showSheet by remember { mutableStateOf(false) }\n    val scope = rememberCoroutineScope()\n\n    val onSponsorClick: (SponsorShip) -> Unit = {\n        viewingSponsorShip = it\n        showSheet = true\n        scope.launch {\n            delay(80)\n            sheetState.show()\n        }\n    }\n\n    LaunchedEffect(Unit) {\n        launch(Dispatchers.IO) {\n            SHOW_SPONSOR_MSG.updateInt(0)\n            SponsorUtil.getSponsors()\n                .onFailure { Log.e(TAG, \"DonatePage: \", it) }\n                .onSuccess {\n                    it.data.viewer.sponsorshipsAsMaintainer.nodes.run {\n                        sponsorList.addAll(\n                            filter { node -> (node.tier?.monthlyPriceInDollars ?: 0) in 5 until 10 }\n                        )\n\n                        backerList.addAll(\n                            filter { node ->\n                                (node.tier?.monthlyPriceInDollars ?: 0) in 10 until 25\n                            }\n                        )\n\n                        supporterList.addAll(\n                            filter { node -> (node.tier?.monthlyPriceInDollars ?: 0) >= 25 }\n                        )\n                    }\n                }\n        }\n    }\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(id = R.string.sponsors))\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = { values ->\n            LazyVerticalGrid(\n                modifier = Modifier.padding(horizontal = 12.dp),\n                columns = GridCells.Fixed(12),\n                horizontalArrangement = Arrangement.spacedBy(12.dp),\n                verticalArrangement = Arrangement.spacedBy(12.dp),\n                contentPadding = values,\n            ) {\n                if (supporterList.isNotEmpty()) {\n                    item(span = { GridItemSpan(maxLineSpan) }, key = SUPPORTERS) {\n                        PreferenceSubtitle(\n                            text = SUPPORTERS,\n                            contentPadding =\n                                PaddingValues(start = 12.dp, top = 24.dp, bottom = 12.dp),\n                        )\n                    }\n\n                    items(\n                        span = { GridItemSpan(maxLineSpan / 3) },\n                        items = supporterList,\n                        key = { it.sponsorEntity.login },\n                    ) { sponsorShip ->\n                        SponsorItem(sponsorShip = sponsorShip) { onSponsorClick(sponsorShip) }\n                    }\n                }\n\n                if (backerList.isNotEmpty()) {\n                    item(span = { GridItemSpan(maxLineSpan) }, key = BACKERS) {\n                        PreferenceSubtitle(\n                            text = BACKERS,\n                            contentPadding =\n                                PaddingValues(start = 12.dp, top = 12.dp, bottom = 12.dp),\n                        )\n                    }\n\n                    items(\n                        items = backerList,\n                        span = { GridItemSpan(maxLineSpan / 3) },\n                        key = { it.sponsorEntity.login },\n                    ) { sponsorShip ->\n                        SponsorItem(sponsorShip = sponsorShip) { onSponsorClick(sponsorShip) }\n                    }\n                }\n\n                if (sponsorList.isNotEmpty()) {\n                    item(span = { GridItemSpan(maxLineSpan) }, key = SPONSORS) {\n                        PreferenceSubtitle(\n                            text = SPONSORS,\n                            contentPadding =\n                                PaddingValues(start = 12.dp, top = 12.dp, bottom = 12.dp),\n                        )\n                    }\n\n                    items(\n                        items = sponsorList,\n                        span = { GridItemSpan(maxLineSpan / 4) },\n                        key = { it.sponsorEntity.login },\n                    ) { sponsorShip ->\n                        SponsorItem(sponsorShip = sponsorShip) { onSponsorClick(sponsorShip) }\n                    }\n                }\n\n                item(span = { GridItemSpan(maxLineSpan) }) {\n                    Surface(\n                        shape = CardDefaults.shape,\n                        modifier = Modifier.padding(vertical = 12.dp),\n                        color = MaterialTheme.colorScheme.surfaceContainerLow,\n                    ) {\n                        Column(modifier = Modifier.padding(12.dp).fillMaxWidth()) {\n                            Text(\n                                modifier =\n                                    Modifier.padding(bottom = 4.dp)\n                                        .align(Alignment.CenterHorizontally),\n                                text = stringResource(id = R.string.msg_from_developer),\n                                style = MaterialTheme.typography.labelLarge,\n                            )\n\n                            Row(\n                                modifier = Modifier.fillMaxWidth().padding(vertical = 12.dp),\n                                verticalAlignment = Alignment.Bottom,\n                            ) {\n                                AsyncImageImpl(\n                                    model = gitHubAvatar(\"JunkFood02\"),\n                                    contentDescription = null,\n                                    modifier =\n                                        Modifier.size(48.dp)\n                                            .aspectRatio(1f, true)\n                                            .clip(CircleShape),\n                                    contentScale = ContentScale.Crop,\n                                )\n                                Column {\n                                    Conversation(\n                                        modifier = Modifier.padding(bottom = 12.dp),\n                                        text = stringResource(id = R.string.sponsor_msg),\n                                    )\n                                    Conversation(\n                                        modifier = Modifier,\n                                        text = stringResource(R.string.sponsor_msg2),\n                                    )\n                                }\n                            }\n\n                            Button(\n                                onClick = {\n                                    uriHandler.openUri(\"https://github.com/sponsors/JunkFood02\")\n                                },\n                                contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n                                modifier = Modifier.align(Alignment.End),\n                            ) {\n                                Icon(\n                                    modifier =\n                                        Modifier.padding(end = 8.dp).size(ButtonDefaults.IconSize),\n                                    imageVector = Icons.Outlined.VolunteerActivism,\n                                    contentDescription = null,\n                                )\n\n                                Text(text = stringResource(id = R.string.sponsor))\n                            }\n                        }\n                    }\n                }\n            }\n            if (showSheet) {\n                SponsorDialog(sponsorShip = viewingSponsorShip, sheetState = sheetState) {\n                    scope.launch { sheetState.hide() }.invokeOnCompletion { showSheet = false }\n                }\n            }\n        },\n    )\n}\n\n@Composable\n@Preview\nfun SponsorPagePreview() {\n    SponsorsPage {}\n}\n\n@Composable\nfun Conversation(modifier: Modifier = Modifier, text: String) {\n    Row(\n        modifier =\n            modifier\n                .padding(horizontal = 12.dp)\n                .clip(MaterialTheme.shapes.extraLarge)\n                .background(MaterialTheme.colorScheme.surfaceContainerHighest)\n                .padding(horizontal = 20.dp, vertical = 16.dp)\n    ) {\n        Text(text = text, style = MaterialTheme.typography.bodyLarge)\n    }\n}\n\n@Composable\nfun LazyGridItemScope.SponsorItem(sponsorShip: SponsorShip, onClick: () -> Unit) {\n    SponsorItem(\n        modifier = Modifier,\n        userName = sponsorShip.sponsorEntity.name,\n        userLogin = sponsorShip.sponsorEntity.login,\n        onClick = onClick,\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SponsorDialog(sponsorShip: SponsorShip, sheetState: SheetState, onDismissRequest: () -> Unit) {\n    val amount = sponsorShip.tier?.monthlyPriceInDollars ?: 0\n    val tierText =\n        if (amount in 5 until 10) {\n            SPONSORS\n        } else if (amount in 10 until 25) {\n            BACKERS\n        } else if (amount > 25) {\n            SUPPORTERS\n        } else {\n            null\n        }\n\n    SealModalBottomSheet(\n        onDismissRequest = onDismissRequest,\n        sheetState = sheetState,\n        contentPadding = PaddingValues(0.dp),\n    ) {\n        SponsorDialogContent(\n            userLogin = sponsorShip.sponsorEntity.login,\n            userName = sponsorShip.sponsorEntity.name,\n            avatarUrl = gitHubAvatar(sponsorShip.sponsorEntity.login),\n            tierText = tierText,\n            website = sponsorShip.sponsorEntity.websiteUrl,\n            socialLinks = sponsorShip.sponsorEntity.socialAccounts?.nodes?.map { it.url.toString() },\n        )\n    }\n}\n\n@Composable\nfun SponsorDialogContent(\n    userLogin: String,\n    userName: String?,\n    avatarUrl: String,\n    tierText: String? = null,\n    website: String? = null,\n    socialLinks: List<String>? = null,\n) {\n    Column {\n        Row(\n            modifier =\n                Modifier.fillMaxWidth()\n                    .padding(horizontal = 12.dp)\n                    .padding(bottom = 16.dp)\n                    .height(IntrinsicSize.Min)\n        ) {\n            AsyncImageImpl(\n                modifier = Modifier.heightIn(max = 72.dp).aspectRatio(1f, true).clip(CircleShape),\n                model = avatarUrl,\n                contentDescription = null,\n                contentScale = ContentScale.Crop,\n            )\n            Column(\n                modifier = Modifier.padding(vertical = 20.dp).padding(start = 12.dp),\n                horizontalAlignment = Alignment.Start,\n            ) {\n                Text(\n                    text = userName ?: \"@$userLogin\",\n                    maxLines = 1,\n                    style = MaterialTheme.typography.titleSmall,\n                    color = MaterialTheme.colorScheme.onSurface,\n                    overflow = TextOverflow.Ellipsis,\n                )\n                Text(\n                    text = tierText.toString(),\n                    maxLines = 1,\n                    style = MaterialTheme.typography.labelSmall,\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    overflow = TextOverflow.Ellipsis,\n                    modifier = Modifier.padding(top = 2.dp),\n                )\n            }\n        }\n        Column(modifier = Modifier.fillMaxWidth()) {\n            androidx.compose.material3.HorizontalDivider()\n            LinkItem(icon = Icons.Outlined.House, link = website ?: gitHubProfile(userLogin))\n            socialLinks?.forEach { LinkItem(icon = Icons.Outlined.Link, link = it) }\n        }\n    }\n}\n\n@Composable\nprivate fun LinkItem(modifier: Modifier = Modifier, icon: ImageVector, link: String) {\n    val uriHandler = LocalUriHandler.current\n    val clipboardManager = LocalClipboardManager.current\n    val linkCopiedText = stringResource(id = R.string.link_copied)\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .clickable {\n                    uriHandler\n                        .runCatching { openUri(link) }\n                        .onFailure {\n                            clipboardManager.setText(AnnotatedString(link))\n                            ToastUtil.makeToast(linkCopiedText)\n                        }\n                }\n                .padding(vertical = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        Icon(\n            imageVector = icon,\n            contentDescription = null,\n            modifier = Modifier.padding(horizontal = 16.dp),\n            tint = MaterialTheme.colorScheme.onSurfaceVariant,\n        )\n        Text(text = link, style = MaterialTheme.typography.titleSmall)\n    }\n}\n\n@Preview\n@Composable\nprivate fun SponsorDialogContentPreview() {\n\n    val sponsorShip =\n        SponsorShip(\n            sponsorEntity =\n                SponsorEntity(\n                    \"example\",\n                    \"example\",\n                    \"https://www.example.com\",\n                    socialAccounts =\n                        SocialAccounts(\n                            buildList {\n                                repeat(4) {\n                                    add(\n                                        SocialAccount(\n                                            displayName = \"Example\",\n                                            url = \"https://www.example.com\",\n                                        )\n                                    )\n                                }\n                            }\n                        ),\n                ),\n            tier = Tier(10),\n        )\n\n    SealTheme {\n        Surface {\n            SponsorDialogContent(\n                userLogin = sponsorShip.sponsorEntity.login,\n                userName = sponsorShip.sponsorEntity.name,\n                avatarUrl = gitHubAvatar(sponsorShip.sponsorEntity.login),\n                website = sponsorShip.sponsorEntity.websiteUrl,\n                socialLinks =\n                    sponsorShip.sponsorEntity.socialAccounts?.nodes?.map { it.url.toString() },\n            )\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Preview\n@Composable\nprivate fun SponsorDialogPreview() {\n    val sheetState =\n        with(LocalDensity.current) {\n            SheetState(\n                initialValue = SheetValue.Expanded,\n                skipPartiallyExpanded = true,\n                velocityThreshold = { 56.dp.toPx() },\n                positionalThreshold = { 125.dp.toPx() },\n            )\n        }\n\n    val sponsorShip =\n        SponsorShip(\n            sponsorEntity =\n                SponsorEntity(\n                    \"example\",\n                    \"example\",\n                    \"https://www.example.com\",\n                    socialAccounts =\n                        SocialAccounts(\n                            buildList {\n                                repeat(4) {\n                                    add(\n                                        SocialAccount(\n                                            displayName = \"Example\",\n                                            url = \"https://www.example.com\",\n                                        )\n                                    )\n                                }\n                            }\n                        ),\n                ),\n            tier = Tier(10),\n        )\n\n    SponsorDialog(sponsorShip = sponsorShip, onDismissRequest = {}, sheetState = sheetState)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/about/UpdatePage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.about\n\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Update\nimport androidx.compose.material3.ButtonDefaults\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.FilledTonalButton\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceSingleChoiceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithContainer\nimport com.junkfood.seal.ui.page.UpdateDialog\nimport com.junkfood.seal.util.AUTO_UPDATE\nimport com.junkfood.seal.util.PRE_RELEASE\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.STABLE\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.UPDATE_CHANNEL\nimport com.junkfood.seal.util.UpdateUtil\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun UpdatePage(onNavigateBack: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    var autoUpdate by remember { mutableStateOf(PreferenceUtil.isAutoUpdateEnabled()) }\n    var updateChannel by UPDATE_CHANNEL.intState\n    val scope = rememberCoroutineScope()\n    val context = LocalContext.current\n\n    var release by remember { mutableStateOf(UpdateUtil.Release()) }\n    var showUpdateDialog by remember { mutableStateOf(false) }\n    var showUnavailableDialog by remember { mutableStateOf(App.isFDroidBuild()) }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(id = R.string.auto_update))\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = { paddings ->\n            LazyColumn(modifier = Modifier.padding(paddings)) {\n                item {\n                    PreferenceSwitchWithContainer(\n                        title = stringResource(id = R.string.enable_auto_update),\n                        icon = null,\n                        isChecked = autoUpdate,\n                    ) {\n                        autoUpdate = !autoUpdate\n                        AUTO_UPDATE.updateBoolean(autoUpdate)\n                    }\n                }\n                item {\n                    PreferenceSubtitle(\n                        modifier = Modifier.padding(horizontal = 4.dp),\n                        text = stringResource(id = R.string.update_channel),\n                    )\n                }\n                item {\n                    PreferenceSingleChoiceItem(\n                        text = stringResource(id = R.string.stable_channel),\n                        selected = updateChannel == STABLE,\n                        contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp),\n                    ) {\n                        updateChannel = STABLE\n                        UPDATE_CHANNEL.updateInt(updateChannel)\n                    }\n                }\n\n                item {\n                    PreferenceSingleChoiceItem(\n                        text = stringResource(id = R.string.pre_release_channel),\n                        selected = updateChannel == PRE_RELEASE,\n                        contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp),\n                    ) {\n                        updateChannel = PRE_RELEASE\n                        UPDATE_CHANNEL.updateInt(updateChannel)\n                    }\n                }\n                item {\n                    var isLoading by remember { mutableStateOf(false) }\n                    Row(\n                        horizontalArrangement = Arrangement.End,\n                        modifier = Modifier.fillMaxWidth(),\n                    ) {\n                        ProgressIndicatorButton(\n                            modifier =\n                                Modifier.padding(horizontal = 24.dp)\n                                    .padding(top = 6.dp)\n                                    .padding(bottom = 12.dp),\n                            text = stringResource(id = R.string.check_for_updates),\n                            icon = Icons.Outlined.Update,\n                            isLoading = isLoading,\n                        ) {\n                            if (!isLoading)\n                                scope.launch {\n                                    runCatching {\n                                            isLoading = true\n                                            withContext(Dispatchers.IO) {\n                                                UpdateUtil.checkForUpdate()?.let {\n                                                    release = it\n                                                    showUpdateDialog = true\n                                                }\n                                                    ?: ToastUtil.makeToastSuspend(\n                                                        context.getString(R.string.app_up_to_date)\n                                                    )\n                                            }\n                                            isLoading = false\n                                        }\n                                        .onFailure {\n                                            it.printStackTrace()\n                                            ToastUtil.makeToastSuspend(\n                                                context.getString(R.string.app_update_failed)\n                                            )\n                                            isLoading = false\n                                        }\n                                }\n                        }\n                    }\n                    androidx.compose.material3.HorizontalDivider()\n                }\n                item {\n                    PreferenceInfo(\n                        modifier = Modifier.padding(horizontal = 4.dp),\n                        text = stringResource(id = R.string.update_channel_desc),\n                    )\n                }\n            }\n        },\n    )\n    if (showUpdateDialog)\n        UpdateDialog(onDismissRequest = { showUpdateDialog = false }, release = release)\n\n    if (showUnavailableDialog) {\n        AutoUpdateUnavailableDialog {\n            showUnavailableDialog = false\n            onNavigateBack()\n        }\n    }\n}\n\n@Composable\nfun ProgressIndicatorButton(\n    modifier: Modifier = Modifier,\n    isLoading: Boolean = false,\n    text: String,\n    icon: ImageVector,\n    onClick: () -> Unit,\n) {\n    FilledTonalButton(\n        modifier = modifier,\n        onClick = onClick,\n        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,\n    ) {\n        if (isLoading)\n            Box(modifier = Modifier.size(18.dp)) {\n                CircularProgressIndicator(\n                    modifier = Modifier.size(16.dp).align(Alignment.Center),\n                    strokeWidth = 3.dp,\n                )\n            }\n        else Icon(imageVector = icon, contentDescription = null, modifier = Modifier.size(18.dp))\n        Text(text = text, modifier = Modifier.padding(start = 8.dp))\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/AppearancePreferences.kt",
    "content": "package com.junkfood.seal.ui.page.settings.appearance\n\nimport androidx.compose.animation.core.animateDpAsState\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.RowScope\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.sizeIn\nimport androidx.compose.foundation.pager.HorizontalPager\nimport androidx.compose.foundation.pager.rememberPagerState\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.foundation.shape.RoundedCornerShape\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Check\nimport androidx.compose.material.icons.outlined.Colorize\nimport androidx.compose.material.icons.outlined.DarkMode\nimport androidx.compose.material.icons.outlined.Language\nimport androidx.compose.material.icons.outlined.LightMode\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.draw.drawBehind\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.toArgb\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.unit.dp\nimport com.google.accompanist.pager.HorizontalPagerIndicator\nimport com.google.android.material.color.DynamicColors\nimport com.junkfood.seal.R\nimport com.junkfood.seal.download.Task\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.LocalDynamicColorSwitch\nimport com.junkfood.seal.ui.common.LocalPaletteStyleIndex\nimport com.junkfood.seal.ui.common.LocalSeedColor\nimport com.junkfood.seal.ui.common.Route\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithDivider\nimport com.junkfood.seal.ui.page.downloadv2.ActionButton\nimport com.junkfood.seal.ui.page.downloadv2.CardStateIndicator\nimport com.junkfood.seal.ui.page.downloadv2.VideoCardV2\nimport com.junkfood.seal.util.DarkThemePreference.Companion.OFF\nimport com.junkfood.seal.util.DarkThemePreference.Companion.ON\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.STYLE_MONOCHROME\nimport com.junkfood.seal.util.STYLE_TONAL_SPOT\nimport com.junkfood.seal.util.paletteStyles\nimport com.junkfood.seal.util.toDisplayName\nimport com.kyant.monet.LocalTonalPalettes\nimport com.kyant.monet.PaletteStyle\nimport com.kyant.monet.TonalPalettes\nimport com.kyant.monet.TonalPalettes.Companion.toTonalPalettes\nimport com.kyant.monet.a1\nimport com.kyant.monet.a2\nimport com.kyant.monet.a3\nimport io.material.hct.Hct\nimport java.util.Locale\nimport kotlinx.coroutines.Job\n\nprivate val ColorList =\n    ((4..10) + (1..3)).map { it * 35.0 }.map { Color(Hct.from(it, 40.0, 40.0).toInt()) }\n\nprivate val DrawableList =\n    listOf(R.drawable.sample, R.drawable.sample1, R.drawable.sample2, R.drawable.sample3)\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun AppearancePreferences(onNavigateBack: () -> Unit, onNavigateTo: (String) -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n\n    val index by remember { mutableIntStateOf(DrawableList.indices.random()) }\n\n    val image by remember(index) { mutableIntStateOf(DrawableList[index]) }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(id = R.string.look_and_feel))\n                },\n                navigationIcon = { BackButton(onNavigateBack) },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            Column(Modifier.verticalScroll(rememberScrollState()).padding(it)) {\n                val downloadState = Task.DownloadState.Running(Job(), \"\", 0.8f)\n                VideoCardV2(\n                    modifier = Modifier.padding(18.dp).clearAndSetSemantics {},\n                    title = stringResource(R.string.video_title_sample_text),\n                    uploader = stringResource(R.string.video_creator_sample_text),\n                    thumbnailModel = image,\n                    stateIndicator = {\n                        CardStateIndicator(modifier = Modifier, downloadState = downloadState)\n                    },\n                    actionButton = {\n                        ActionButton(modifier = Modifier, downloadState = downloadState) {}\n                    },\n                ) {}\n                val pageCount = ColorList.size + 1\n\n                val pagerState =\n                    rememberPagerState(\n                        initialPage =\n                            if (LocalPaletteStyleIndex.current == STYLE_MONOCHROME) pageCount\n                            else\n                                ColorList.indexOf(Color(LocalSeedColor.current)).run {\n                                    if (this == -1) 0 else this\n                                }\n                    ) {\n                        pageCount\n                    }\n\n                HorizontalPager(\n                    modifier = Modifier.fillMaxWidth().clearAndSetSemantics {},\n                    state = pagerState,\n                    contentPadding = PaddingValues(horizontal = 12.dp),\n                ) { page ->\n                    if (page < pageCount - 1) {\n                        Row(\n                            modifier = Modifier.fillMaxWidth(),\n                            horizontalArrangement = Arrangement.Center,\n                        ) {\n                            ColorButtons(ColorList[page])\n                        }\n                    } else {\n                        // ColorButton for Monochrome theme\n                        val isSelected =\n                            LocalPaletteStyleIndex.current == STYLE_MONOCHROME &&\n                                !LocalDynamicColorSwitch.current\n                        Row(\n                            modifier = Modifier.fillMaxWidth(),\n                            horizontalArrangement = Arrangement.Center,\n                        ) {\n                            ColorButtonImpl(\n                                modifier = Modifier,\n                                isSelected = { isSelected },\n                                tonalPalettes =\n                                    Color.Black.toTonalPalettes(PaletteStyle.Monochrome),\n                                onClick = {\n                                    PreferenceUtil.switchDynamicColor(enabled = false)\n                                    PreferenceUtil.modifyThemeSeedColor(\n                                        Color.Black.toArgb(),\n                                        STYLE_MONOCHROME,\n                                    )\n                                },\n                            )\n                        }\n                    }\n                }\n\n                HorizontalPagerIndicator(\n                    pagerState = pagerState,\n                    pageCount = pageCount,\n                    modifier =\n                        Modifier.clearAndSetSemantics {}\n                            .align(Alignment.CenterHorizontally)\n                            .padding(vertical = 12.dp),\n                    activeColor = MaterialTheme.colorScheme.primary,\n                    inactiveColor = MaterialTheme.colorScheme.outlineVariant,\n                    indicatorHeight = 6.dp,\n                    indicatorWidth = 6.dp,\n                )\n                if (DynamicColors.isDynamicColorAvailable()) {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.dynamic_color),\n                        description = stringResource(id = R.string.dynamic_color_desc),\n                        icon = Icons.Outlined.Colorize,\n                        isChecked = LocalDynamicColorSwitch.current,\n                        onClick = { PreferenceUtil.switchDynamicColor() },\n                    )\n                }\n                val isDarkTheme = LocalDarkTheme.current.isDarkTheme()\n                PreferenceSwitchWithDivider(\n                    title = stringResource(id = R.string.dark_theme),\n                    icon = if (isDarkTheme) Icons.Outlined.DarkMode else Icons.Outlined.LightMode,\n                    isChecked = isDarkTheme,\n                    description = LocalDarkTheme.current.getDarkThemeDesc(),\n                    onChecked = {\n                        PreferenceUtil.modifyDarkThemePreference(if (isDarkTheme) OFF else ON)\n                    },\n                    onClick = { onNavigateTo(Route.DARK_THEME) },\n                )\n                PreferenceItem(\n                    title = stringResource(R.string.language),\n                    icon = Icons.Outlined.Language,\n                    description = Locale.getDefault().toDisplayName(),\n                ) {\n                    onNavigateTo(Route.LANGUAGES)\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun RowScope.ColorButtons(color: Color) {\n    paletteStyles.subList(STYLE_TONAL_SPOT, STYLE_MONOCHROME).forEachIndexed { index, style ->\n        ColorButton(color = color, index = index, tonalStyle = style)\n    }\n}\n\n@Composable\nfun RowScope.ColorButton(\n    modifier: Modifier = Modifier,\n    color: Color = Color.Green,\n    index: Int = 0,\n    tonalStyle: PaletteStyle = PaletteStyle.TonalSpot,\n) {\n    val tonalPalettes by remember { mutableStateOf(color.toTonalPalettes(tonalStyle)) }\n    val isSelect =\n        !LocalDynamicColorSwitch.current &&\n            LocalSeedColor.current == color.toArgb() &&\n            LocalPaletteStyleIndex.current == index\n    ColorButtonImpl(modifier = modifier, tonalPalettes = tonalPalettes, isSelected = { isSelect }) {\n        PreferenceUtil.switchDynamicColor(enabled = false)\n        PreferenceUtil.modifyThemeSeedColor(color.toArgb(), index)\n    }\n}\n\n@Composable\nfun RowScope.ColorButtonImpl(\n    modifier: Modifier = Modifier,\n    isSelected: () -> Boolean = { false },\n    tonalPalettes: TonalPalettes,\n    cardColor: Color = MaterialTheme.colorScheme.surfaceContainer,\n    containerColor: Color = MaterialTheme.colorScheme.primaryContainer,\n    onClick: () -> Unit = {},\n) {\n\n    val containerSize by animateDpAsState(targetValue = if (isSelected.invoke()) 28.dp else 0.dp)\n    val iconSize by animateDpAsState(targetValue = if (isSelected.invoke()) 16.dp else 0.dp)\n\n    Surface(\n        modifier =\n            modifier\n                .padding(4.dp)\n                .sizeIn(maxHeight = 80.dp, maxWidth = 80.dp, minHeight = 64.dp, minWidth = 64.dp)\n                .weight(1f, false)\n                .aspectRatio(1f),\n        shape = RoundedCornerShape(16.dp),\n        color = cardColor,\n        onClick = onClick,\n    ) {\n        CompositionLocalProvider(LocalTonalPalettes provides tonalPalettes) {\n            val color1 = 80.a1\n            val color2 = 90.a2\n            val color3 = 60.a3\n            Box(Modifier.fillMaxSize()) {\n                Box(\n                    modifier =\n                        modifier\n                            .size(48.dp)\n                            .clip(CircleShape)\n                            .drawBehind { drawCircle(color1) }\n                            .align(Alignment.Center)\n                ) {\n                    Surface(\n                        color = color2,\n                        modifier = Modifier.align(Alignment.BottomStart).size(24.dp),\n                    ) {}\n                    Surface(\n                        color = color3,\n                        modifier = Modifier.align(Alignment.BottomEnd).size(24.dp),\n                    ) {}\n                    Box(\n                        modifier =\n                            Modifier.align(Alignment.Center)\n                                .clip(CircleShape)\n                                .size(containerSize)\n                                .drawBehind { drawCircle(containerColor) }\n                    ) {\n                        Icon(\n                            imageVector = Icons.Outlined.Check,\n                            contentDescription = null,\n                            modifier = Modifier.size(iconSize).align(Alignment.Center),\n                            tint = MaterialTheme.colorScheme.onPrimaryContainer,\n                        )\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/DarkThemePreferences.kt",
    "content": "package com.junkfood.seal.ui.page.settings.appearance\n\nimport android.os.Build\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Contrast\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.res.stringResource\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceSingleChoiceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitchVariant\nimport com.junkfood.seal.util.DarkThemePreference.Companion.FOLLOW_SYSTEM\nimport com.junkfood.seal.util.DarkThemePreference.Companion.OFF\nimport com.junkfood.seal.util.DarkThemePreference.Companion.ON\nimport com.junkfood.seal.util.PreferenceUtil\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DarkThemePreferences(onNavigateBack: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val darkThemePreference = LocalDarkTheme.current\n    val isHighContrastModeEnabled = darkThemePreference.isHighContrastModeEnabled\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(id = R.string.dark_theme))\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            LazyColumn(modifier = Modifier, contentPadding = it) {\n                if (Build.VERSION.SDK_INT >= 29)\n                    item {\n                        PreferenceSingleChoiceItem(\n                            text = stringResource(R.string.follow_system),\n                            selected = darkThemePreference.darkThemeValue == FOLLOW_SYSTEM,\n                        ) {\n                            PreferenceUtil.modifyDarkThemePreference(FOLLOW_SYSTEM)\n                        }\n                    }\n                item {\n                    PreferenceSingleChoiceItem(\n                        text = stringResource(R.string.on),\n                        selected = darkThemePreference.darkThemeValue == ON,\n                    ) {\n                        PreferenceUtil.modifyDarkThemePreference(ON)\n                    }\n                }\n                item {\n                    PreferenceSingleChoiceItem(\n                        text = stringResource(R.string.off),\n                        selected = darkThemePreference.darkThemeValue == OFF,\n                    ) {\n                        PreferenceUtil.modifyDarkThemePreference(OFF)\n                    }\n                }\n                item { PreferenceSubtitle(text = stringResource(R.string.additional_settings)) }\n                item {\n                    PreferenceSwitchVariant(\n                        title = stringResource(R.string.high_contrast),\n                        icon = Icons.Outlined.Contrast,\n                        isChecked = isHighContrastModeEnabled,\n                        onClick = {\n                            PreferenceUtil.modifyDarkThemePreference(\n                                isHighContrastModeEnabled = !isHighContrastModeEnabled\n                            )\n                        },\n                    )\n                }\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/appearance/LanguagesPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.appearance\n\nimport android.content.Intent\nimport android.content.pm.PackageManager\nimport android.net.Uri\nimport android.os.Build\nimport android.provider.Settings\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.ArrowForwardIos\nimport androidx.compose.material.icons.outlined.Translate\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport androidx.core.os.LocaleListCompat\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceSingleChoiceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferencesHintCard\nimport com.junkfood.seal.ui.page.settings.about.weblate\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.LocaleLanguageCodeMap\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.setLanguage\nimport com.junkfood.seal.util.toDisplayName\nimport java.util.Locale\n\n@Composable\nfun LanguagePage(onNavigateBack: () -> Unit = {}) {\n    val selectedLocale by remember { mutableStateOf(Locale.getDefault()) }\n    val scope = rememberCoroutineScope()\n    val context = LocalContext.current\n    val intent =\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n            Intent(Settings.ACTION_APP_LOCALE_SETTINGS).apply {\n                val uri = Uri.fromParts(\"package\", context.packageName, null)\n                data = uri\n            }\n        } else {\n            Intent()\n        }\n\n    val preferredLocales = remember {\n        val defaultLocaleListCompat = LocaleListCompat.getDefault()\n        val mLocaleSet = mutableSetOf<Locale>()\n\n        for (index in 0..defaultLocaleListCompat.size()) {\n            val locale = defaultLocaleListCompat[index]\n            if (locale != null) {\n                mLocaleSet.add(locale)\n            }\n        }\n\n        return@remember mLocaleSet\n    }\n\n    val supportedLocales = LocaleLanguageCodeMap.keys\n\n    val suggestedLocales =\n        remember(preferredLocales) {\n            val localeSet = mutableSetOf<Locale>()\n\n            preferredLocales.forEach { desired ->\n                val matchedLocale =\n                    supportedLocales.firstOrNull { supported ->\n                        LocaleListCompat.matchesLanguageAndScript(\n                            /* supported = */ desired,\n                            /* desired = */ supported,\n                        )\n                    }\n                if (matchedLocale != null) {\n                    localeSet.add(matchedLocale)\n                }\n            }\n\n            return@remember localeSet\n        }\n\n    val otherLocales = supportedLocales - suggestedLocales\n\n    val isSystemLocaleSettingsAvailable =\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n            context.packageManager\n                .queryIntentActivities(intent, PackageManager.MATCH_ALL)\n                .isNotEmpty()\n        } else {\n            false\n        }\n    LanguagePageImpl(\n        onNavigateBack = onNavigateBack,\n        suggestedLocales = suggestedLocales,\n        otherLocales = otherLocales,\n        isSystemLocaleSettingsAvailable = isSystemLocaleSettingsAvailable,\n        onNavigateToSystemLocaleSettings = {\n            if (isSystemLocaleSettingsAvailable) {\n                context.startActivity(intent)\n            }\n        },\n        selectedLocale = selectedLocale,\n    ) {\n        PreferenceUtil.saveLocalePreference(it)\n        setLanguage(it)\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nprivate fun LanguagePageImpl(\n    onNavigateBack: () -> Unit = {},\n    suggestedLocales: Set<Locale>,\n    otherLocales: Set<Locale>,\n    isSystemLocaleSettingsAvailable: Boolean = false,\n    onNavigateToSystemLocaleSettings: () -> Unit,\n    selectedLocale: Locale,\n    onLanguageSelected: (Locale?) -> Unit = {},\n) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val uriHandler = LocalUriHandler.current\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(id = R.string.language))\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            LazyColumn(modifier = Modifier, contentPadding = it) {\n                item {\n                    PreferencesHintCard(\n                        title = stringResource(R.string.translate),\n                        description = stringResource(R.string.translate_desc),\n                        icon = Icons.Outlined.Translate,\n                    ) {\n                        uriHandler.openUri(weblate)\n                    }\n                }\n\n                if (suggestedLocales.isNotEmpty()) {\n\n                    item { PreferenceSubtitle(text = stringResource(id = R.string.suggested)) }\n\n                    if (!suggestedLocales.contains(Locale.getDefault())) {\n                        item {\n                            PreferenceSingleChoiceItem(\n                                text = stringResource(id = R.string.follow_system),\n                                selected = !suggestedLocales.contains(selectedLocale),\n                            ) {\n                                onLanguageSelected(null)\n                            }\n                        }\n                    }\n\n                    for (locale in suggestedLocales) {\n                        item {\n                            PreferenceSingleChoiceItem(\n                                text = locale.toDisplayName(),\n                                selected = selectedLocale == locale,\n                            ) {\n                                onLanguageSelected(locale)\n                            }\n                        }\n                    }\n                }\n\n                item { PreferenceSubtitle(text = stringResource(id = R.string.all_languages)) }\n\n                for (locale in otherLocales) {\n                    item {\n                        PreferenceSingleChoiceItem(\n                            text = locale.toDisplayName(),\n                            selected = selectedLocale == locale,\n                        ) {\n                            onLanguageSelected(locale)\n                        }\n                    }\n                }\n\n                if (isSystemLocaleSettingsAvailable) {\n                    item {\n                        androidx.compose.material3.HorizontalDivider()\n                        Surface(\n                            modifier =\n                                Modifier.clickable(onClick = onNavigateToSystemLocaleSettings)\n                        ) {\n                            Row(\n                                modifier =\n                                    Modifier.fillMaxWidth()\n                                        .padding(\n                                            PaddingValues(horizontal = 8.dp, vertical = 16.dp)\n                                        ),\n                                verticalAlignment = Alignment.CenterVertically,\n                            ) {\n                                Column(modifier = Modifier.weight(1f).padding(start = 8.dp)) {\n                                    Text(\n                                        text = stringResource(R.string.system_settings),\n                                        maxLines = 1,\n                                        style =\n                                            MaterialTheme.typography.titleLarge.copy(\n                                                fontSize = 20.sp\n                                            ),\n                                        color = MaterialTheme.colorScheme.onSurface,\n                                        overflow = TextOverflow.Ellipsis,\n                                    )\n                                }\n                                Icon(\n                                    imageVector = Icons.AutoMirrored.Outlined.ArrowForwardIos,\n                                    contentDescription = null,\n                                    modifier = Modifier.padding(end = 16.dp).size(18.dp),\n                                )\n                            }\n                        }\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Preview\n@Composable\nprivate fun LanguagePagePreview() {\n    var language by remember { mutableStateOf(Locale.JAPANESE) }\n    val map = setOf(Locale.forLanguageTag(\"en-US\"))\n    SealTheme {\n        LanguagePageImpl(\n            suggestedLocales = map,\n            otherLocales = map + Locale.forLanguageTag(\"ja-JP\"),\n            isSystemLocaleSettingsAvailable = true,\n            onNavigateToSystemLocaleSettings = { /*TODO*/ },\n            selectedLocale = language,\n        ) {\n            language = it\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/command/CommandTemplateDialog.kt",
    "content": "package com.junkfood.seal.ui.page.settings.command\n\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ExperimentalLayoutApi\nimport androidx.compose.foundation.layout.FlowRow\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.requiredHeight\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.text.KeyboardActions\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Add\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.EditNote\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.collectAsState\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.ExperimentalComposeUiApi\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.focus.FocusDirection\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalFocusManager\nimport androidx.compose.ui.platform.LocalSoftwareKeyboardController\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.window.DialogProperties\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.OptionShortcut\nimport com.junkfood.seal.ui.component.AddButton\nimport com.junkfood.seal.ui.component.ClearButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.LinkButton\nimport com.junkfood.seal.ui.component.PasteFromClipBoardButton\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SealTextField\nimport com.junkfood.seal.ui.component.ShortcutChip\nimport com.junkfood.seal.util.DatabaseUtil\nimport kotlinx.coroutines.launch\n\n@Preview\n@Composable\nfun CommandTemplateDialog(\n    commandTemplate: CommandTemplate = CommandTemplate(0, \"\", \"\"),\n    newTemplate: Boolean = commandTemplate.id == 0,\n    onDismissRequest: () -> Unit = {},\n    confirmationCallback: (Int) -> Unit = {},\n) {\n    val context = LocalContext.current\n    val clipboardManager = LocalClipboardManager.current\n    val scope = rememberCoroutineScope()\n    var templateText by remember { mutableStateOf(commandTemplate.template) }\n    var templateName by remember { mutableStateOf(commandTemplate.name) }\n    var isError by remember { mutableStateOf(false) }\n    AlertDialog(\n        icon = { Icon(if (newTemplate) Icons.Outlined.Add else Icons.Outlined.EditNote, null) },\n        title = { Text(stringResource(if (newTemplate) R.string.new_template else R.string.edit)) },\n        onDismissRequest = { onDismissRequest() },\n        properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = false),\n        confirmButton = {\n            ConfirmButton {\n                if (templateName.isBlank() || templateName.isEmpty()) {\n                    isError = true\n                } else {\n                    scope.launch {\n                        val id =\n                            if (newTemplate) {\n                                DatabaseUtil.insertTemplate(\n                                        CommandTemplate(0, templateName, templateText)\n                                    )\n                                    .toInt()\n                            } else {\n                                DatabaseUtil.updateTemplate(\n                                    commandTemplate.copy(\n                                        name = templateName,\n                                        template = templateText,\n                                    )\n                                )\n                                commandTemplate.id\n                            }\n                        confirmationCallback(id)\n                        onDismissRequest()\n                    }\n                }\n            }\n        },\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dismiss)) }\n        },\n        text = {\n            val focusManager = LocalFocusManager.current\n            val softwareKeyboardController = LocalSoftwareKeyboardController.current\n            Column(modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState())) {\n                Text(\n                    text = stringResource(R.string.edit_template_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                OutlinedTextField(\n                    modifier = Modifier.fillMaxWidth().padding(top = 16.dp),\n                    value = templateName,\n                    onValueChange = {\n                        templateName = it\n                        isError = false\n                    },\n                    label = { Text(stringResource(R.string.template_label)) },\n                    maxLines = 1,\n                    isError = isError,\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                )\n                ProvideTextStyle(\n                    value = LocalTextStyle.current.merge(fontFamily = FontFamily.Monospace)\n                ) {\n                    OutlinedTextField(\n                        modifier = Modifier.fillMaxWidth().padding(vertical = 12.dp),\n                        value = templateText,\n                        onValueChange = { templateText = it },\n                        trailingIcon = {\n                            if (templateText.isEmpty())\n                                PasteFromClipBoardButton { templateText = it }\n                            else ClearButton { templateText = \"\" }\n                        },\n                        label = { Text(stringResource(R.string.custom_command_template)) },\n                        maxLines = 12,\n                        minLines = 3,\n                    )\n                }\n                LinkButton()\n            }\n        },\n    )\n}\n\n@OptIn(ExperimentalComposeUiApi::class, ExperimentalLayoutApi::class)\n@Composable\nfun OptionChipsDialog(onDismissRequest: () -> Unit = {}) {\n    val scope = rememberCoroutineScope()\n    val shortcuts by DatabaseUtil.getShortcuts().collectAsState(emptyList())\n    var text by remember { mutableStateOf(\"\") }\n    val addShortCuts = {\n        scope.launch {\n            text.removeSuffix(\" \").run {\n                if (shortcuts.find { it.option == this } == null)\n                    DatabaseUtil.insertShortcut(OptionShortcut(option = this))\n                text = \"\"\n            }\n        }\n    }\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(text = stringResource(id = R.string.edit_shortcuts)) },\n        icon = { Icon(Icons.Outlined.Edit, null) },\n        text = {\n            Column {\n                Text(\n                    text = stringResource(R.string.edit_shortcuts_desc),\n                    style = MaterialTheme.typography.bodyMedium,\n                    modifier = Modifier.padding(bottom = 12.dp).padding(horizontal = 24.dp),\n                )\n                Column(\n                    modifier =\n                        Modifier.padding(horizontal = 16.dp)\n                            .requiredHeight(400.dp)\n                            .horizontalScroll(rememberScrollState())\n                            .verticalScroll(rememberScrollState())\n                ) {\n                    FlowRow(modifier = Modifier.width(400.dp)) {\n                        shortcuts.forEach { item ->\n                            ShortcutChip(\n                                text = item.option,\n                                onRemove = { scope.launch { DatabaseUtil.deleteShortcut(item) } },\n                            )\n                        }\n                    }\n                }\n                val focusManager = LocalFocusManager.current\n                val softwareKeyboardController = LocalSoftwareKeyboardController.current\n\n                SealTextField(\n                    modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),\n                    value = text,\n                    onValueChange = { text = it },\n                    trailingIcon = {\n                        AddButton(onClick = { addShortCuts() }, enabled = text.isNotEmpty())\n                    },\n                    keyboardActions =\n                        KeyboardActions(\n                            onDone = {\n                                addShortCuts()\n                                softwareKeyboardController?.hide()\n                                focusManager.moveFocus(FocusDirection.Down)\n                            }\n                        ),\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                    maxLines = 2,\n                    contentDescription = stringResource(id = R.string.shortcuts),\n                )\n            }\n        },\n        confirmButton = {\n            TextButton(onClick = onDismissRequest) {\n                Text(text = stringResource(id = androidx.appcompat.R.string.abc_action_mode_done))\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/command/TemplateEditPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.command\n\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.ExperimentalLayoutApi\nimport androidx.compose.foundation.layout.FlowRow\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.foundation.text.KeyboardActions\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material3.DividerDefaults\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.HorizontalDivider\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.collectAsState\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.ExperimentalComposeUiApi\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.draw.clip\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalFocusManager\nimport androidx.compose.ui.platform.LocalSoftwareKeyboardController\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.unit.dp\nimport androidx.compose.ui.unit.sp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.ui.component.AdjacentLabel\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ClearButton\nimport com.junkfood.seal.ui.component.LinkButton\nimport com.junkfood.seal.ui.component.PasteFromClipBoardButton\nimport com.junkfood.seal.ui.component.ShortcutChip\nimport com.junkfood.seal.ui.component.TextButtonWithIcon\nimport com.junkfood.seal.util.DatabaseUtil\nimport com.junkfood.seal.util.PreferenceUtil\nimport kotlinx.coroutines.launch\n\n@OptIn(\n    ExperimentalMaterial3Api::class,\n    ExperimentalComposeUiApi::class,\n    ExperimentalLayoutApi::class,\n)\n@Composable\nfun TemplateEditPage(onDismissRequest: () -> Unit, templateId: Int) {\n    val scope = rememberCoroutineScope()\n\n    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()\n    val commandTemplate =\n        PreferenceUtil.templateListStateFlow.collectAsState().value.find { it.id == templateId }\n            ?: CommandTemplate(0, \"\", \"\")\n\n    var templateText by remember { mutableStateOf(commandTemplate.template) }\n    var templateName by remember { mutableStateOf(commandTemplate.name) }\n    val focusManager = LocalFocusManager.current\n    val softwareKeyboardController = LocalSoftwareKeyboardController.current\n    var isEditingShortcuts by remember { mutableStateOf(false) }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            TopAppBar(\n                title = {\n                    Text(\n                        text =\n                            stringResource(\n                                if (templateId <= 0) R.string.new_template else R.string.edit\n                            ),\n                        style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),\n                    )\n                },\n                navigationIcon = { BackButton { onDismissRequest() } },\n                actions = {\n                    TextButton(\n                        modifier = Modifier.padding(end = 8.dp),\n                        onClick = {\n                            scope.launch {\n                                commandTemplate\n                                    .copy(name = templateName, template = templateText)\n                                    .run {\n                                        if (id == 0) DatabaseUtil.insertTemplate(this)\n                                        else DatabaseUtil.updateTemplate(this)\n                                    }\n\n                                onDismissRequest()\n                            }\n                        },\n                        enabled = templateName.isNotEmpty(),\n                    ) {\n                        Text(\n                            text = stringResource(androidx.appcompat.R.string.abc_action_mode_done)\n                        )\n                    }\n                },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n    ) { paddings ->\n        LazyColumn(modifier = Modifier.padding(paddings), contentPadding = PaddingValues()) {\n            item {\n                val description = stringResource(R.string.template_label)\n\n                Column(Modifier.padding(horizontal = 24.dp)) {\n                    AdjacentLabel(text = description, modifier = Modifier.padding(top = 12.dp))\n                    OutlinedTextField(\n                        modifier = Modifier.fillMaxWidth().padding(bottom = 24.dp),\n                        value = templateName,\n                        onValueChange = { templateName = it },\n                        keyboardActions = KeyboardActions.Default,\n                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),\n                    )\n                }\n            }\n            item {\n                Column(Modifier.padding(horizontal = 24.dp)) {\n                    val description = stringResource(R.string.custom_command_template)\n                    AdjacentLabel(text = description, modifier = Modifier)\n                    ProvideTextStyle(\n                        value = LocalTextStyle.current.merge(fontFamily = FontFamily.Monospace)\n                    ) {\n                        OutlinedTextField(\n                            supportingText = {\n                                Text(text = stringResource(id = R.string.edit_template_desc))\n                            },\n                            modifier = Modifier.fillMaxWidth(),\n                            value = templateText,\n                            onValueChange = { templateText = it },\n                            trailingIcon = {\n                                if (templateText.isEmpty())\n                                    PasteFromClipBoardButton { templateText = it }\n                                else ClearButton { templateText = \"\" }\n                            },\n                            maxLines = 12,\n                            minLines = 6,\n                        )\n                    }\n                    LinkButton(modifier = Modifier.padding(vertical = 12.dp))\n                    HorizontalDivider(\n                        Modifier.fillMaxWidth()\n                            .padding(bottom = 24.dp)\n                            .size(DividerDefaults.Thickness)\n                            .clip(CircleShape),\n                        color = MaterialTheme.colorScheme.outlineVariant,\n                    )\n                }\n            }\n\n            item {\n                Row(modifier = Modifier.fillMaxWidth().padding(start = 24.dp, end = 16.dp)) {\n                    Text(\n                        text = stringResource(R.string.shortcuts),\n                        modifier = Modifier.weight(1f).align(Alignment.CenterVertically),\n                        style = MaterialTheme.typography.labelLarge,\n                        color = MaterialTheme.colorScheme.tertiary,\n                    )\n                    TextButtonWithIcon(\n                        modifier = Modifier,\n                        onClick = { isEditingShortcuts = true },\n                        icon = Icons.Outlined.Edit,\n                        text = stringResource(id = R.string.edit_shortcuts),\n                        contentColor = MaterialTheme.colorScheme.tertiary,\n                    )\n                }\n            }\n            item {\n                val shortcuts by DatabaseUtil.getShortcuts().collectAsState(emptyList())\n                Column(\n                    modifier = Modifier.fillParentMaxWidth().horizontalScroll(rememberScrollState())\n                ) {\n                    FlowRow(\n                        modifier = Modifier.padding(horizontal = 8.dp).width(500.dp),\n                        //                        mainAxisSize = SizeMode.Expand,\n                        verticalArrangement = Arrangement.spacedBy(2.dp),\n                    ) {\n                        shortcuts.forEach { item ->\n                            ShortcutChip(\n                                text = item.option,\n                                onClick = {\n                                    templateText =\n                                        templateText.run {\n                                            if (isEmpty()) item.option\n                                            else\n                                                this.removeSuffix(\" \").removeSuffix(\"\\n\") +\n                                                    \"\\n${item.option}\"\n                                        }\n                                },\n                            )\n                        }\n                    }\n                }\n            }\n        }\n    }\n    if (isEditingShortcuts) OptionChipsDialog { isEditingShortcuts = false }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/command/TemplateListPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.command\n\nimport androidx.activity.compose.BackHandler\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.expandVertically\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.shrinkVertically\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.wrapContentSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Add\nimport androidx.compose.material.icons.outlined.AssignmentReturn\nimport androidx.compose.material.icons.outlined.BookmarkAdd\nimport androidx.compose.material.icons.outlined.ContentPasteGo\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material.icons.outlined.DeleteSweep\nimport androidx.compose.material.icons.outlined.HelpOutline\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.BottomAppBar\nimport androidx.compose.material3.DropdownMenu\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.SnackbarHost\nimport androidx.compose.material3.SnackbarHostState\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.TriStateCheckbox\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateListOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.pluralStringResource\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.state.ToggleableState\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.backup.BackupUtil\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.HelpDialog\nimport com.junkfood.seal.ui.component.PreferenceItemVariant\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithContainer\nimport com.junkfood.seal.ui.component.TemplateItem\nimport com.junkfood.seal.ui.page.settings.about.YtdlpRepository\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DatabaseUtil\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.TEMPLATE_ID\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\nprivate const val TAG = \"TemplateListPage\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun TemplateListPage(onNavigateBack: () -> Unit, onNavigateToEditPage: (Int) -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val templates by PreferenceUtil.templateListStateFlow.collectAsStateWithLifecycle()\n    val scope = rememberCoroutineScope()\n    val hapticFeedback = LocalHapticFeedback.current\n    val view = LocalView.current\n    val clipboardManager = LocalClipboardManager.current\n    val context = LocalContext.current\n    var showHelpDialog by remember { mutableStateOf(false) }\n\n    var isMultiSelectEnabled by remember { mutableStateOf(false) }\n\n    val selectedTemplates = remember { mutableStateListOf<CommandTemplate>() }\n    LaunchedEffect(isMultiSelectEnabled) {\n        if (!isMultiSelectEnabled) {\n            delay(200)\n            selectedTemplates.clear()\n        }\n    }\n\n    var showDeleteDialog by remember { mutableStateOf(false) }\n    var showShortcutsDialog by remember { mutableStateOf(false) }\n    var isCustomCommandEnabled by remember { mutableStateOf(CUSTOM_COMMAND.getBoolean()) }\n\n    var selectedTemplateId by TEMPLATE_ID.intState\n    val snackbarHostState = remember { SnackbarHostState() }\n\n    BackHandler(isMultiSelectEnabled) { isMultiSelectEnabled = false }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        snackbarHost = { SnackbarHost(modifier = Modifier, hostState = snackbarHostState) },\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(\n                        modifier = Modifier,\n                        text =\n                            if (isMultiSelectEnabled)\n                                stringResource(id = R.string.custom_command_template)\n                            else stringResource(id = R.string.custom_command),\n                        maxLines = 1,\n                        overflow = TextOverflow.Ellipsis,\n                    )\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                actions = {\n                    var expanded by remember { mutableStateOf(false) }\n                    IconButton(\n                        onClick = {\n                            view.slightHapticFeedback()\n                            showHelpDialog = true\n                        }\n                    ) {\n                        Icon(\n                            imageVector = Icons.Outlined.HelpOutline,\n                            contentDescription = stringResource(id = R.string.how_does_it_work),\n                        )\n                    }\n                    if (!isMultiSelectEnabled) {\n                        Box(modifier = Modifier.wrapContentSize(Alignment.TopEnd)) {\n                            IconButton(onClick = { expanded = true }) {\n                                Icon(\n                                    Icons.Outlined.MoreVert,\n                                    contentDescription = stringResource(R.string.show_more_actions),\n                                )\n                            }\n                            DropdownMenu(\n                                expanded = expanded,\n                                onDismissRequest = { expanded = false },\n                            ) {\n                                DropdownMenuItem(\n                                    leadingIcon = { Icon(Icons.Outlined.ContentPasteGo, null) },\n                                    text = { Text(stringResource(R.string.export_to_clipboard)) },\n                                    onClick = {\n                                        scope.launch {\n                                            snackbarHostState.showSnackbar(\n                                                context\n                                                    .getString(R.string.template_exported)\n                                                    .format(templates.size)\n                                            )\n                                        }\n                                        scope.launch {\n                                            clipboardManager.setText(\n                                                AnnotatedString(BackupUtil.exportTemplatesToJson())\n                                            )\n                                            expanded = false\n                                        }\n                                    },\n                                )\n                                DropdownMenuItem(\n                                    leadingIcon = { Icon(Icons.Outlined.AssignmentReturn, null) },\n                                    text = { Text(stringResource(R.string.import_from_clipboard)) },\n                                    onClick = {\n                                        scope.launch {\n                                            expanded = false\n                                            clipboardManager.getText()?.text?.let {\n                                                if (it.isNotEmpty()) {\n                                                    val res =\n                                                        DatabaseUtil.importTemplatesFromJson(it)\n                                                    snackbarHostState.showSnackbar(\n                                                        context\n                                                            .getString(R.string.template_imported)\n                                                            .format(res)\n                                                    )\n                                                }\n                                            }\n                                        }\n                                    },\n                                )\n                            }\n                        }\n                    }\n                },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        bottomBar = {\n            val checkBoxState =\n                remember(isMultiSelectEnabled, selectedTemplates.size) {\n                    when (selectedTemplates.size) {\n                        templates.size -> ToggleableState.On\n                        in 1 until templates.size -> ToggleableState.Indeterminate\n                        else -> ToggleableState.Off\n                    }\n                }\n            AnimatedVisibility(\n                isMultiSelectEnabled,\n                enter = expandVertically() + fadeIn(),\n                exit = shrinkVertically() + fadeOut(),\n            ) {\n                BottomAppBar {\n                    Row(\n                        verticalAlignment = Alignment.CenterVertically,\n                        modifier = Modifier.fillMaxWidth(),\n                    ) {\n                        TriStateCheckbox(\n                            state = checkBoxState,\n                            onClick = {\n                                view.slightHapticFeedback()\n                                when (checkBoxState) {\n                                    ToggleableState.On -> selectedTemplates.clear()\n                                    else ->\n                                        selectedTemplates.run {\n                                            clear()\n                                            addAll(templates)\n                                        }\n                                }\n                            },\n                            modifier = Modifier.padding(start = 12.dp),\n                        )\n\n                        Text(\n                            text =\n                                stringResource(\n                                    id = R.string.selected_item_count,\n                                    selectedTemplates.size,\n                                ),\n                            style = MaterialTheme.typography.labelLarge,\n                            modifier = Modifier.weight(1f),\n                        )\n\n                        IconButton(\n                            onClick = {\n                                view.slightHapticFeedback()\n                                scope.launch {\n                                    snackbarHostState.showSnackbar(\n                                        context\n                                            .getString(R.string.template_exported)\n                                            .format(selectedTemplates.size)\n                                    )\n                                }\n                                scope.launch {\n                                    clipboardManager.setText(\n                                        AnnotatedString(\n                                            BackupUtil.exportTemplatesToJson(\n                                                templates = selectedTemplates,\n                                                shortcuts = emptyList(),\n                                            )\n                                        )\n                                    )\n                                }\n                            },\n                            enabled = selectedTemplates.isNotEmpty(),\n                        ) {\n                            Icon(\n                                imageVector = Icons.Outlined.ContentPasteGo,\n                                contentDescription =\n                                    stringResource(id = R.string.export_to_clipboard),\n                            )\n                        }\n                        IconButton(\n                            onClick = {\n                                view.slightHapticFeedback()\n                                showDeleteDialog = true\n                            },\n                            enabled = selectedTemplates.isNotEmpty(),\n                        ) {\n                            Icon(\n                                imageVector = Icons.Outlined.DeleteSweep,\n                                contentDescription = stringResource(id = R.string.remove),\n                            )\n                        }\n                    }\n                }\n            }\n        },\n    ) {\n        LazyColumn(modifier = Modifier, contentPadding = it) {\n            item {\n                PreferenceSwitchWithContainer(\n                    title = stringResource(R.string.use_custom_command),\n                    icon = null,\n                    isChecked = isCustomCommandEnabled,\n                    onClick = {\n                        isCustomCommandEnabled = !isCustomCommandEnabled\n                        PreferenceUtil.updateValue(CUSTOM_COMMAND, isCustomCommandEnabled)\n                    },\n                )\n            }\n            items(templates) { commandTemplate ->\n                TemplateItem(\n                    label = commandTemplate.name,\n                    template = commandTemplate.template,\n                    selected = selectedTemplateId == commandTemplate.id,\n                    isMultiSelectEnabled = isMultiSelectEnabled,\n                    onCheckedChange = {\n                        if (selectedTemplates.contains(commandTemplate))\n                            selectedTemplates.remove(commandTemplate)\n                        else selectedTemplates.add(commandTemplate)\n                    },\n                    checked = selectedTemplates.contains(commandTemplate),\n                    onClick = { onNavigateToEditPage(commandTemplate.id) },\n                    onSelect = {\n                        selectedTemplateId = commandTemplate.id\n                        PreferenceUtil.encodeInt(TEMPLATE_ID, selectedTemplateId)\n                    },\n                    onLongClick = {\n                        hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                        isMultiSelectEnabled = true\n                        selectedTemplates.add(commandTemplate)\n                    },\n                )\n            }\n            if (!isMultiSelectEnabled) {\n                item {\n                    PreferenceItemVariant(\n                        title = stringResource(id = R.string.new_template),\n                        icon = Icons.Outlined.Add,\n                    ) {\n                        onNavigateToEditPage(-1)\n                    }\n                }\n                item {\n                    PreferenceItemVariant(\n                        title = stringResource(id = R.string.edit_shortcuts),\n                        icon = Icons.Outlined.BookmarkAdd,\n                    ) {\n                        showShortcutsDialog = true\n                    }\n                }\n            }\n        }\n    }\n    if (showDeleteDialog) {\n        AlertDialog(\n            onDismissRequest = { showDeleteDialog = false },\n            icon = { Icon(Icons.Outlined.Delete, null) },\n            title = { Text(stringResource(R.string.remove_template)) },\n            text = {\n                Text(\n                    stringResource(\n                        R.string.remove_multiple_templates_msg,\n                        pluralStringResource(\n                            id = R.plurals.item_count,\n                            count = selectedTemplates.size,\n                            selectedTemplates.size,\n                        ),\n                    )\n                )\n            },\n            dismissButton = { DismissButton { showDeleteDialog = false } },\n            confirmButton = {\n                ConfirmButton {\n                    scope.launch {\n                        withContext(Dispatchers.IO) {\n                            DatabaseUtil.deleteTemplates(selectedTemplates)\n                        }\n                        isMultiSelectEnabled = false\n                    }\n                    showDeleteDialog = false\n                }\n            },\n        )\n    }\n\n    if (showShortcutsDialog) {\n        OptionChipsDialog { showShortcutsDialog = false }\n    }\n    val uriHandler = LocalUriHandler.current\n    if (showHelpDialog) {\n        HelpDialog(\n            text = stringResource(id = R.string.custom_command_usage_msg),\n            onDismissRequest = { showHelpDialog = false },\n            dismissButton = null,\n        ) {\n            TextButton(\n                onClick = {\n                    showHelpDialog = false\n                    uriHandler.openUri(YtdlpRepository)\n                }\n            ) {\n                Text(text = stringResource(id = R.string.learn_more))\n            }\n        }\n    }\n\n    LaunchedEffect(templates.size) {\n        if (templates.isNotEmpty() && templates.find { it.id == selectedTemplateId } == null) {\n            selectedTemplateId = templates.first().id\n            PreferenceUtil.encodeInt(TEMPLATE_ID, selectedTemplateId)\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/directory/DirectoryPreferenceDialog.kt",
    "content": "package com.junkfood.seal.ui.page.settings.directory\n\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.SnippetFolder\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.page.settings.general.DialogCheckBoxItem\n\n@Composable\nfun DirectoryPreferenceDialog(\n    onDismissRequest: () -> Unit = {},\n    isWebsiteSelected: Boolean,\n    isPlaylistTitleSelected: Boolean,\n    onConfirm: (isWebsiteSelected: Boolean, isPlaylistTitleSelected: Boolean) -> Unit = { _, _ -> },\n) {\n    var website by remember { mutableStateOf(isWebsiteSelected) }\n    var playlistTitle by remember { mutableStateOf(isPlaylistTitleSelected) }\n\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton {\n                onConfirm(website, playlistTitle)\n                onDismissRequest()\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        title = { Text(text = stringResource(id = R.string.subdirectory)) },\n        icon = { Icon(imageVector = Icons.Outlined.SnippetFolder, contentDescription = null) },\n        text = {\n            Column {\n                Text(\n                    text = stringResource(id = R.string.subdirectory_desc),\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                    //                    style = MaterialTheme.typography.bodyLarge\n                )\n                Spacer(modifier = Modifier.height(8.dp))\n                androidx.compose.material3.HorizontalDivider(\n                    modifier = Modifier.padding(horizontal = 24.dp, vertical = 4.dp)\n                )\n                DialogCheckBoxItem(\n                    text = stringResource(id = R.string.website),\n                    checked = website,\n                ) {\n                    website = !website\n                }\n                DialogCheckBoxItem(\n                    text = stringResource(id = R.string.playlist_title),\n                    checked = playlistTitle,\n                ) {\n                    playlistTitle = !playlistTitle\n                }\n                androidx.compose.material3.HorizontalDivider(\n                    modifier = Modifier.padding(horizontal = 24.dp, vertical = 4.dp)\n                )\n                Spacer(modifier = Modifier.height(4.dp))\n\n                val dirStr =\n                    StringBuilder(\".../\").run {\n                        if (website) append(\"website/\")\n                        if (playlistTitle) append(\"playlist_title/\")\n                        append(\"file_name\")\n                    }\n\n                Text(\n                    text = stringResource(R.string.subdirectory_hint) + \"\\n\" + dirStr,\n                    modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),\n                    //                    style = MaterialTheme.typography.labelMedium,\n                )\n            }\n        },\n    )\n}\n\n@Preview\n@Composable\nprivate fun DirectoryPreferenceDialogPreview() {\n    DirectoryPreferenceDialog(\n        onDismissRequest = {},\n        isWebsiteSelected = false,\n        isPlaylistTitleSelected = false,\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/directory/DownloadDirectoryPreferences.kt",
    "content": "@file:OptIn(ExperimentalPermissionsApi::class)\n\npackage com.junkfood.seal.ui.page.settings.directory\n\nimport android.Manifest\nimport android.content.Context\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Environment\nimport android.provider.Settings\nimport androidx.activity.compose.rememberLauncherForActivityResult\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.systemBarsPadding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.OpenInNew\nimport androidx.compose.material.icons.filled.SdCardAlert\nimport androidx.compose.material.icons.outlined.Folder\nimport androidx.compose.material.icons.outlined.FolderDelete\nimport androidx.compose.material.icons.outlined.FolderOpen\nimport androidx.compose.material.icons.outlined.FolderSpecial\nimport androidx.compose.material.icons.outlined.LibraryMusic\nimport androidx.compose.material.icons.outlined.SdCard\nimport androidx.compose.material.icons.outlined.SnippetFolder\nimport androidx.compose.material.icons.outlined.Spellcheck\nimport androidx.compose.material.icons.outlined.TabUnselected\nimport androidx.compose.material.icons.outlined.VideoLibrary\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.SnackbarHost\nimport androidx.compose.material3.SnackbarHostState\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.google.accompanist.permissions.ExperimentalPermissionsApi\nimport com.google.accompanist.permissions.PermissionStatus\nimport com.google.accompanist.permissions.rememberPermissionState\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.common.stringState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DialogSingleChoiceItem\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.LinkButton\nimport com.junkfood.seal.ui.component.OutlinedButtonChip\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithDivider\nimport com.junkfood.seal.ui.component.PreferencesHintCard\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.util.COMMAND_DIRECTORY\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.CUSTOM_OUTPUT_TEMPLATE\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.FileUtil.getConfigDirectory\nimport com.junkfood.seal.util.FileUtil.getExternalTempDir\nimport com.junkfood.seal.util.OUTPUT_TEMPLATE\nimport com.junkfood.seal.util.PRIVATE_DIRECTORY\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.RESTRICT_FILENAMES\nimport com.junkfood.seal.util.SDCARD_DOWNLOAD\nimport com.junkfood.seal.util.SDCARD_URI\nimport com.junkfood.seal.util.SUBDIRECTORY_EXTRACTOR\nimport com.junkfood.seal.util.SUBDIRECTORY_PLAYLIST_TITLE\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\nprivate const val ytdlpOutputTemplateReference = \"https://github.com/yt-dlp/yt-dlp#output-template\"\nprivate val PublicDownloadsDirectory =\n    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).path\nprivate val PublicDocumentDirectory =\n    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).path\nprivate const val ytdlpFilesystemReference = \"https://github.com/yt-dlp/yt-dlp#filesystem-options\"\n\nprivate fun String.isValidDirectory(): Boolean {\n    return isEmpty() || contains(PublicDownloadsDirectory) || contains(PublicDocumentDirectory)\n}\n\nenum class Directory {\n    AUDIO,\n    VIDEO,\n    SDCARD,\n    CUSTOM_COMMAND,\n}\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class)\n@Composable\nfun DownloadDirectoryPreferences(onNavigateBack: () -> Unit) {\n\n    val uriHandler = LocalUriHandler.current\n    val clipboardManager = LocalClipboardManager.current\n    val scope = rememberCoroutineScope()\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val context = LocalContext.current\n    val snackbarHostState = remember { SnackbarHostState() }\n\n    var showSubdirectoryDialog by remember { mutableStateOf(false) }\n\n    var isPrivateDirectoryEnabled by remember { mutableStateOf(PRIVATE_DIRECTORY.getBoolean()) }\n\n    var videoDirectoryText by\n        remember(isPrivateDirectoryEnabled) {\n            mutableStateOf(\n                if (!isPrivateDirectoryEnabled) App.videoDownloadDir else App.privateDownloadDir\n            )\n        }\n    var audioDirectoryText by\n        remember(isPrivateDirectoryEnabled) {\n            mutableStateOf(\n                if (!isPrivateDirectoryEnabled) App.audioDownloadDir else App.privateDownloadDir\n            )\n        }\n    var sdcardUri by remember { mutableStateOf(SDCARD_URI.getString()) }\n    var customCommandDirectory by COMMAND_DIRECTORY.stringState\n\n    var sdcardDownload by remember { mutableStateOf(SDCARD_DOWNLOAD.getBoolean()) }\n\n    var showClearTempDialog by remember { mutableStateOf(false) }\n    var showCustomCommandDirectoryDialog by remember { mutableStateOf(false) }\n\n    var editingDirectory by remember { mutableStateOf(Directory.VIDEO) }\n\n    val isCustomCommandEnabled by remember { mutableStateOf(CUSTOM_COMMAND.getBoolean()) }\n\n    var showOutputTemplateDialog by remember { mutableStateOf(false) }\n\n    val storagePermission =\n        rememberPermissionState(permission = Manifest.permission.WRITE_EXTERNAL_STORAGE)\n    val showDirectoryAlert =\n        Build.VERSION.SDK_INT >= 30 &&\n            !Environment.isExternalStorageManager() &&\n            (!audioDirectoryText.isValidDirectory() ||\n                !videoDirectoryText.isValidDirectory() ||\n                !customCommandDirectory.isValidDirectory())\n\n    val launcher =\n        rememberLauncherForActivityResult(\n            object : ActivityResultContracts.OpenDocumentTree() {\n                override fun createIntent(context: Context, input: Uri?): Intent {\n                    return (super.createIntent(context, input)).apply {\n                        flags =\n                            Intent.FLAG_GRANT_READ_URI_PERMISSION or\n                                Intent.FLAG_GRANT_WRITE_URI_PERMISSION or\n                                Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION\n                    }\n                }\n            }\n        ) {\n            it?.let { uri ->\n                App.updateDownloadDir(uri, editingDirectory)\n                if (editingDirectory != Directory.SDCARD) {\n                    val path = FileUtil.getRealPath(uri)\n                    when (editingDirectory) {\n                        Directory.AUDIO -> {\n                            audioDirectoryText = path\n                        }\n\n                        Directory.VIDEO -> {\n                            videoDirectoryText = path\n                        }\n\n                        Directory.SDCARD -> {\n                            sdcardUri = uri.toString()\n                        }\n\n                        Directory.CUSTOM_COMMAND -> {\n                            customCommandDirectory = path\n                        }\n                    }\n                }\n            }\n        }\n\n    fun openDirectoryChooser(directory: Directory = Directory.VIDEO) {\n        editingDirectory = directory\n        if (Build.VERSION.SDK_INT > 29 || storagePermission.status == PermissionStatus.Granted)\n            launcher.launch(null)\n        else storagePermission.launchPermissionRequest()\n    }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        snackbarHost = {\n            SnackbarHost(modifier = Modifier.systemBarsPadding(), hostState = snackbarHostState)\n        },\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(\n                        modifier = Modifier,\n                        text = stringResource(id = R.string.download_directory),\n                    )\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n    ) {\n        LazyColumn(modifier = Modifier, contentPadding = it) {\n            if (isCustomCommandEnabled)\n                item {\n                    PreferenceInfo(text = stringResource(id = R.string.custom_command_enabled_hint))\n                }\n\n            if (showDirectoryAlert)\n                item {\n                    PreferencesHintCard(\n                        title = stringResource(R.string.permission_issue),\n                        description = stringResource(R.string.permission_issue_desc),\n                        icon = Icons.Filled.SdCardAlert,\n                    ) {\n                        if (\n                            Build.VERSION.SDK_INT >= 30 && !Environment.isExternalStorageManager()\n                        ) {\n                            Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {\n                                flags = Intent.FLAG_ACTIVITY_NEW_TASK\n                                data = Uri.parse(\"package:\" + context.packageName)\n                                if (resolveActivity(context.packageManager) != null)\n                                    context.startActivity(this)\n                            }\n                        }\n                    }\n                }\n            item { PreferenceSubtitle(text = stringResource(R.string.general_settings)) }\n            if (!isCustomCommandEnabled) {\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.video_directory),\n                        description = videoDirectoryText,\n                        enabled = !isPrivateDirectoryEnabled && !sdcardDownload,\n                        icon = Icons.Outlined.VideoLibrary,\n                    ) {\n                        openDirectoryChooser(directory = Directory.VIDEO)\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.audio_directory),\n                        description = audioDirectoryText,\n                        enabled = !isPrivateDirectoryEnabled && !sdcardDownload,\n                        icon = Icons.Outlined.LibraryMusic,\n                    ) {\n                        openDirectoryChooser(directory = Directory.AUDIO)\n                    }\n                }\n            }\n            item {\n                PreferenceItem(\n                    title = stringResource(id = R.string.custom_command_directory),\n                    description =\n                        customCommandDirectory.ifEmpty {\n                            stringResource(id = R.string.set_directory_desc)\n                        },\n                    icon = Icons.Outlined.Folder,\n                ) {\n                    showCustomCommandDirectoryDialog = true\n                }\n            }\n            item {\n                PreferenceSwitchWithDivider(\n                    title = stringResource(id = R.string.sdcard_directory),\n                    description =\n                        sdcardUri.ifEmpty { stringResource(id = R.string.set_directory_desc) },\n                    isChecked = sdcardDownload,\n                    enabled = !isCustomCommandEnabled,\n                    isSwitchEnabled = !isCustomCommandEnabled,\n                    onChecked = {\n                        if (sdcardUri.isNotEmpty()) {\n                            sdcardDownload = !sdcardDownload\n                            PreferenceUtil.updateValue(SDCARD_DOWNLOAD, sdcardDownload)\n                        } else {\n                            openDirectoryChooser(Directory.SDCARD)\n                        }\n                    },\n                    icon = Icons.Outlined.SdCard,\n                    onClick = { openDirectoryChooser(Directory.SDCARD) },\n                )\n            }\n            item {\n                PreferenceItem(\n                    title = stringResource(id = R.string.subdirectory),\n                    description = stringResource(id = R.string.subdirectory_desc),\n                    icon = Icons.Outlined.SnippetFolder,\n                    enabled = !isCustomCommandEnabled && !sdcardDownload,\n                ) {\n                    showSubdirectoryDialog = true\n                }\n            }\n            item { PreferenceSubtitle(text = stringResource(R.string.privacy)) }\n            item {\n                PreferenceSwitch(\n                    title = stringResource(id = R.string.private_directory),\n                    description = stringResource(R.string.private_directory_desc),\n                    icon = Icons.Outlined.TabUnselected,\n                    enabled = !showDirectoryAlert && !sdcardDownload && !isCustomCommandEnabled,\n                    isChecked = isPrivateDirectoryEnabled,\n                    onClick = {\n                        isPrivateDirectoryEnabled = !isPrivateDirectoryEnabled\n                        PreferenceUtil.updateValue(PRIVATE_DIRECTORY, isPrivateDirectoryEnabled)\n                    },\n                )\n            }\n            item { PreferenceSubtitle(text = stringResource(R.string.advanced_settings)) }\n            item {\n                PreferenceItem(\n                    title = stringResource(R.string.output_template),\n                    description = stringResource(id = R.string.output_template_desc),\n                    icon = Icons.Outlined.FolderSpecial,\n                    enabled = !isCustomCommandEnabled && !sdcardDownload,\n                    onClick = { showOutputTemplateDialog = true },\n                )\n            }\n            item {\n                var restrictFilenames by RESTRICT_FILENAMES.booleanState\n                PreferenceSwitch(\n                    title = stringResource(id = R.string.restrict_filenames),\n                    icon = Icons.Outlined.Spellcheck,\n                    description = stringResource(id = R.string.restrict_filenames_desc),\n                    isChecked = restrictFilenames,\n                ) {\n                    restrictFilenames = !restrictFilenames\n                    RESTRICT_FILENAMES.updateBoolean(restrictFilenames)\n                }\n            }\n            item {\n                PreferenceItem(\n                    title = stringResource(R.string.clear_temp_files),\n                    description = stringResource(R.string.clear_temp_files_desc),\n                    icon = Icons.Outlined.FolderDelete,\n                    onClick = { showClearTempDialog = true },\n                )\n            }\n        }\n    }\n\n    if (showClearTempDialog) {\n        AlertDialog(\n            onDismissRequest = { showClearTempDialog = false },\n            icon = { Icon(Icons.Outlined.FolderDelete, null) },\n            title = { Text(stringResource(id = R.string.clear_temp_files)) },\n            dismissButton = { DismissButton { showClearTempDialog = false } },\n            text = {\n                Text(\n                    stringResource(\n                        R.string.clear_temp_files_info,\n                        getExternalTempDir().absolutePath,\n                    ),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n            },\n            confirmButton = {\n                ConfirmButton {\n                    showClearTempDialog = false\n                    scope.launch(Dispatchers.IO) {\n                        FileUtil.clearTempFiles(context.getConfigDirectory())\n                        val count =\n                            FileUtil.run {\n                                clearTempFiles(getExternalTempDir()) +\n                                    clearTempFiles(context.getSdcardTempDir(null)) +\n                                    clearTempFiles(context.getInternalTempDir())\n                            }\n\n                        withContext(Dispatchers.Main) {\n                            snackbarHostState.showSnackbar(\n                                context.getString(R.string.clear_temp_files_count).format(count)\n                            )\n                        }\n                    }\n                }\n            },\n        )\n    }\n    val outputTemplate by\n        remember(showOutputTemplateDialog) { mutableStateOf(OUTPUT_TEMPLATE.getString()) }\n    val customTemplate by\n        remember(showOutputTemplateDialog) { mutableStateOf(CUSTOM_OUTPUT_TEMPLATE.getString()) }\n    if (showOutputTemplateDialog) {\n        OutputTemplateDialog(\n            selectedTemplate = outputTemplate,\n            customTemplate = customTemplate,\n            onDismissRequest = { showOutputTemplateDialog = false },\n            onConfirm = { selected, custom ->\n                OUTPUT_TEMPLATE.updateString(selected)\n                CUSTOM_OUTPUT_TEMPLATE.updateString(custom)\n                showOutputTemplateDialog = false\n            },\n        )\n    }\n    if (showCustomCommandDirectoryDialog) {\n        AlertDialog(\n            onDismissRequest = { showCustomCommandDirectoryDialog = false },\n            icon = { Icon(imageVector = Icons.Outlined.Folder, contentDescription = null) },\n            title = {\n                Text(\n                    text = stringResource(id = R.string.custom_command_directory),\n                    textAlign = TextAlign.Center,\n                )\n            },\n            confirmButton = {\n                ConfirmButton {\n                    COMMAND_DIRECTORY.updateString(customCommandDirectory)\n                    showCustomCommandDirectoryDialog = false\n                }\n            },\n            text = {\n                Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                    Text(\n                        modifier = Modifier.fillMaxWidth().padding(bottom = 12.dp),\n                        text = stringResource(R.string.custom_command_directory_desc),\n                        style = MaterialTheme.typography.bodyLarge,\n                    )\n                    OutlinedTextField(\n                        modifier = Modifier.padding(vertical = 8.dp),\n                        value = customCommandDirectory,\n                        onValueChange = { customCommandDirectory = it },\n                        leadingIcon = { Text(text = \"-P\", fontFamily = FontFamily.Monospace) },\n                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                    )\n                    Row(modifier = Modifier.horizontalScroll(rememberScrollState())) {\n                        OutlinedButtonChip(\n                            modifier = Modifier.padding(end = 8.dp),\n                            label = stringResource(id = R.string.folder_picker),\n                            icon = Icons.Outlined.FolderOpen,\n                        ) {\n                            openDirectoryChooser(Directory.CUSTOM_COMMAND)\n                        }\n                        OutlinedButtonChip(\n                            label = stringResource(R.string.yt_dlp_docs),\n                            icon = Icons.AutoMirrored.Outlined.OpenInNew,\n                        ) {\n                            uriHandler.openUri(ytdlpFilesystemReference)\n                        }\n                    }\n                }\n            },\n            dismissButton = { DismissButton { showCustomCommandDirectoryDialog = false } },\n        )\n    }\n    if (showSubdirectoryDialog) {\n        DirectoryPreferenceDialog(\n            onDismissRequest = { showSubdirectoryDialog = false },\n            isWebsiteSelected = SUBDIRECTORY_EXTRACTOR.getBoolean(),\n            isPlaylistTitleSelected = SUBDIRECTORY_PLAYLIST_TITLE.getBoolean(),\n            onConfirm = { isWebsiteSelected, isPlaylistTitleSelected ->\n                SUBDIRECTORY_EXTRACTOR.updateBoolean(isWebsiteSelected)\n                SUBDIRECTORY_PLAYLIST_TITLE.updateBoolean(isPlaylistTitleSelected)\n            },\n        )\n    }\n}\n\n@Composable\n@Preview\nfun OutputTemplateDialog(\n    selectedTemplate: String = DownloadUtil.OUTPUT_TEMPLATE_DEFAULT,\n    customTemplate: String = DownloadUtil.OUTPUT_TEMPLATE_ID,\n    onDismissRequest: () -> Unit = {},\n    onConfirm: (String, String) -> Unit = { s, s1 -> },\n) {\n    var editingTemplate by remember { mutableStateOf(customTemplate) }\n\n    var selectedItem by remember {\n        mutableIntStateOf(\n            when (selectedTemplate) {\n                DownloadUtil.OUTPUT_TEMPLATE_DEFAULT -> 1\n                DownloadUtil.OUTPUT_TEMPLATE_ID -> 2\n                else -> 3\n            }\n        )\n    }\n\n    var error by remember { mutableIntStateOf(0) }\n\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton(enabled = error == 0) {\n                onConfirm(\n                    when (selectedItem) {\n                        1 -> DownloadUtil.OUTPUT_TEMPLATE_DEFAULT\n                        2 -> DownloadUtil.OUTPUT_TEMPLATE_ID\n                        else -> editingTemplate\n                    },\n                    editingTemplate,\n                )\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        title = { Text(text = stringResource(id = R.string.output_template)) },\n        icon = { Icon(imageVector = Icons.Outlined.FolderSpecial, contentDescription = null) },\n        text = {\n            Column {\n                Text(\n                    text = stringResource(id = R.string.output_template_desc),\n                    modifier = Modifier.padding(horizontal = 24.dp).padding(bottom = 12.dp),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n\n                Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                    CompositionLocalProvider(\n                        LocalTextStyle provides\n                            LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace)\n                    ) {\n                        DialogSingleChoiceItem(\n                            text = DownloadUtil.OUTPUT_TEMPLATE_DEFAULT,\n                            selected = selectedItem == 1,\n                        ) {\n                            selectedItem = 1\n                        }\n                        DialogSingleChoiceItem(\n                            text = DownloadUtil.OUTPUT_TEMPLATE_ID,\n                            selected = selectedItem == 2,\n                        ) {\n                            selectedItem = 2\n                        }\n                        Row(\n                            modifier =\n                                Modifier.fillMaxWidth()\n                                    .padding(horizontal = 12.dp)\n                                    .padding(vertical = 12.dp),\n                            verticalAlignment = Alignment.CenterVertically,\n                            horizontalArrangement = Arrangement.Start,\n                        ) {\n                            RadioButton(\n                                modifier = Modifier.clearAndSetSemantics {},\n                                selected = selectedItem == 3,\n                                onClick = { selectedItem = 3 },\n                            )\n                            OutlinedTextField(\n                                value = editingTemplate,\n                                onValueChange = {\n                                    error =\n                                        if (!it.contains(DownloadUtil.BASENAME)) {\n                                            1\n                                        } else if (!it.endsWith(DownloadUtil.EXTENSION)) {\n                                            2\n                                        } else {\n                                            0\n                                        }\n                                    editingTemplate = it\n                                },\n                                isError = error != 0,\n                                supportingText = {\n                                    Text(\n                                        \"Required: ${DownloadUtil.BASENAME}, ${DownloadUtil.EXTENSION}\",\n                                        fontFamily = FontFamily.Monospace,\n                                    )\n                                },\n                                label = { Text(text = stringResource(id = R.string.custom)) },\n                            )\n                        }\n                    }\n                }\n\n                LinkButton(\n                    link = ytdlpOutputTemplateReference,\n                    modifier = Modifier.padding(horizontal = 16.dp),\n                )\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/format/DownloadFormatPreferences.kt",
    "content": "package com.junkfood.seal.ui.page.settings.format\n\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.ArtTrack\nimport androidx.compose.material.icons.outlined.ContentCut\nimport androidx.compose.material.icons.outlined.Crop\nimport androidx.compose.material.icons.outlined.HighQuality\nimport androidx.compose.material.icons.outlined.Movie\nimport androidx.compose.material.icons.outlined.MusicNote\nimport androidx.compose.material.icons.outlined.Sort\nimport androidx.compose.material.icons.outlined.SpatialAudioOff\nimport androidx.compose.material.icons.outlined.Subtitles\nimport androidx.compose.material.icons.outlined.Sync\nimport androidx.compose.material.icons.outlined.VideoFile\nimport androidx.compose.material.icons.outlined.VideoSettings\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextAlign\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithDivider\nimport com.junkfood.seal.util.AUDIO_CONVERSION_FORMAT\nimport com.junkfood.seal.util.AUDIO_CONVERT\nimport com.junkfood.seal.util.CROP_ARTWORK\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.DownloadUtil.toFormatSorter\nimport com.junkfood.seal.util.EMBED_METADATA\nimport com.junkfood.seal.util.EMBED_SUBTITLE\nimport com.junkfood.seal.util.EXTRACT_AUDIO\nimport com.junkfood.seal.util.FORMAT_SELECTION\nimport com.junkfood.seal.util.FORMAT_SORTING\nimport com.junkfood.seal.util.MERGE_MULTI_AUDIO_STREAM\nimport com.junkfood.seal.util.MERGE_OUTPUT_MKV\nimport com.junkfood.seal.util.PreferenceStrings\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.SORTING_FIELDS\nimport com.junkfood.seal.util.SUBTITLE\nimport com.junkfood.seal.util.VIDEO_CLIP\nimport com.junkfood.seal.util.VIDEO_FORMAT\nimport com.junkfood.seal.util.VIDEO_QUALITY\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun DownloadFormatPreferences(onNavigateBack: () -> Unit, navigateToSubtitlePage: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n\n    var audioSwitch by remember { mutableStateOf(EXTRACT_AUDIO.getBoolean()) }\n    var isArtworkCroppingEnabled by remember { mutableStateOf(CROP_ARTWORK.getBoolean()) }\n    val downloadSubtitle by SUBTITLE.booleanState\n    val embedSubtitle by EMBED_SUBTITLE.booleanState\n    var remuxToMkv by MERGE_OUTPUT_MKV.booleanState\n    var embedMetadata by EMBED_METADATA.booleanState\n\n    var showAudioFormatDialog by remember { mutableStateOf(false) }\n    var showAudioQualityDialog by remember { mutableStateOf(false) }\n    var showAudioConvertDialog by remember { mutableStateOf(false) }\n    var showVideoQualityDialog by remember { mutableStateOf(false) }\n    var showVideoFormatDialog by remember { mutableStateOf(false) }\n    var showFormatSorterDialog by remember { mutableStateOf(false) }\n    var showVideoClipDialog by remember { mutableStateOf(false) }\n\n    var videoFormat by VIDEO_FORMAT.intState\n    var videoQuality by VIDEO_QUALITY.intState\n    var convertFormat by AUDIO_CONVERSION_FORMAT.intState\n    var sortingFields by\n        remember(showFormatSorterDialog) { mutableStateOf(SORTING_FIELDS.getString()) }\n    //    val audioFormat by remember(showAudioFormatDialog) {\n    // mutableStateOf(PreferenceStrings.getAudioFormatDesc()) }\n    var convertAudio by AUDIO_CONVERT.booleanState\n    var isFormatSortingEnabled by FORMAT_SORTING.booleanState\n    //    val audioQuality by remember(showAudioQualityDialog) {\n    // mutableStateOf(PreferenceStrings.getAudioQualityDesc()) }\n    var isVideoClipEnabled by VIDEO_CLIP.booleanState\n    var isFormatSelectionEnabled by FORMAT_SELECTION.booleanState\n    var mergeAudioStream by MERGE_MULTI_AUDIO_STREAM.booleanState\n    var showMergeAudioDialog by remember { mutableStateOf(false) }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(modifier = Modifier, text = stringResource(id = R.string.format)) },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            val isCustomCommandEnabled by remember { mutableStateOf(CUSTOM_COMMAND.getBoolean()) }\n            LazyColumn(contentPadding = it) {\n                if (isCustomCommandEnabled)\n                    item {\n                        PreferenceInfo(\n                            text = stringResource(id = R.string.custom_command_enabled_hint)\n                        )\n                    }\n                item { PreferenceSubtitle(text = stringResource(id = R.string.audio)) }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.extract_audio),\n                        description = stringResource(id = R.string.extract_audio_summary),\n                        icon = Icons.Outlined.MusicNote,\n                        isChecked = audioSwitch,\n                        enabled = !isCustomCommandEnabled,\n                        onClick = {\n                            audioSwitch = !audioSwitch\n                            PreferenceUtil.updateValue(EXTRACT_AUDIO, audioSwitch)\n                        },\n                    )\n                }\n                //                item {\n                //                    PreferenceItem(title = stringResource(id =\n                // R.string.audio_format_preference),\n                //                        description = audioFormat,\n                //                        icon = Icons.Outlined.AudioFile,\n                //                        enabled = !isCustomCommandEnabled &&\n                // !isFormatSortingEnabled,\n                //                        onClick = { showAudioFormatDialog = true })\n                //                }\n                //                item {\n                //                    PreferenceItem(\n                //                        title = stringResource(id = R.string.audio_quality),\n                //                        description = audioQuality,\n                //                        icon = Icons.Outlined.HighQuality,\n                //                        onClick = { showAudioQualityDialog = true },\n                //                        enabled = !isCustomCommandEnabled &&\n                // !isFormatSortingEnabled\n                //                    )\n                //                }\n                item {\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(R.string.convert_audio_format),\n                        description = PreferenceStrings.getAudioConvertDesc(convertFormat),\n                        icon = Icons.Outlined.Sync,\n                        enabled = audioSwitch && !isCustomCommandEnabled,\n                        onClick = { showAudioConvertDialog = true },\n                        isChecked = convertAudio,\n                        onChecked = {\n                            convertAudio = !convertAudio\n                            AUDIO_CONVERT.updateBoolean(convertAudio)\n                        },\n                    )\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.embed_metadata),\n                        description = stringResource(id = R.string.embed_metadata_desc),\n                        enabled = audioSwitch && !isCustomCommandEnabled,\n                        isChecked = embedMetadata,\n                        icon = Icons.Outlined.ArtTrack,\n                        onClick = {\n                            embedMetadata = !embedMetadata\n                            EMBED_METADATA.updateBoolean(embedMetadata)\n                        },\n                    )\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(R.string.crop_artwork),\n                        description = stringResource(R.string.crop_artwork_desc),\n                        icon = Icons.Outlined.Crop,\n                        enabled = embedMetadata && audioSwitch && !isCustomCommandEnabled,\n                        isChecked = isArtworkCroppingEnabled,\n                    ) {\n                        isArtworkCroppingEnabled = !isArtworkCroppingEnabled\n                        PreferenceUtil.updateValue(CROP_ARTWORK, isArtworkCroppingEnabled)\n                    }\n                }\n                item { PreferenceSubtitle(text = stringResource(id = R.string.video)) }\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.video_format_preference),\n                        description = PreferenceStrings.getVideoFormatLabel(videoFormat),\n                        icon = Icons.Outlined.VideoFile,\n                        enabled = !audioSwitch && !isCustomCommandEnabled && !isFormatSortingEnabled,\n                    ) {\n                        showVideoFormatDialog = true\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.video_quality),\n                        description = PreferenceStrings.getVideoResolutionDesc(videoQuality),\n                        icon = Icons.Outlined.HighQuality,\n                        enabled = !audioSwitch && !isCustomCommandEnabled && !isFormatSortingEnabled,\n                    ) {\n                        showVideoQualityDialog = true\n                    }\n                } /*                item {\n                      var embedThumbnail by EMBED_THUMBNAIL.booleanState\n\n                      PreferenceSwitch(\n                          title = stringResource(id = R.string.embed_thumbnail),\n                          description = stringResource(id = R.string.embed_thumbnail_desc),\n                          icon = Icons.Outlined.Photo,\n                          isChecked = embedThumbnail,\n                          enabled = !isCustomCommandEnabled && !audioSwitch\n                      ) {\n                          embedThumbnail = !embedThumbnail\n                          EMBED_THUMBNAIL.updateBoolean(embedThumbnail)\n                      }\n                  }*/\n\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.remux_container_mkv),\n                        description = stringResource(id = R.string.remux_container_mkv_desc),\n                        isChecked = (downloadSubtitle && embedSubtitle) || remuxToMkv,\n                        icon = Icons.Outlined.Movie,\n                        enabled =\n                            !(downloadSubtitle && embedSubtitle) &&\n                                !isCustomCommandEnabled &&\n                                !audioSwitch,\n                        onClick = {\n                            remuxToMkv = !remuxToMkv\n                            MERGE_OUTPUT_MKV.updateBoolean(remuxToMkv)\n                        },\n                    )\n                }\n                if (downloadSubtitle && embedSubtitle) {\n                    item {\n                        PreferenceInfo(text = stringResource(id = R.string.embed_subtitles_mkv_msg))\n                    }\n                }\n\n                item { PreferenceSubtitle(text = stringResource(id = R.string.advanced_settings)) }\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.subtitle),\n                        icon = Icons.Outlined.Subtitles,\n                        enabled = !isCustomCommandEnabled,\n                        description = stringResource(id = R.string.subtitle_desc),\n                    ) {\n                        navigateToSubtitlePage()\n                    }\n                }\n                item {\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(id = R.string.format_sorting),\n                        icon = Icons.Outlined.Sort,\n                        description = stringResource(id = R.string.format_sorting_desc),\n                        enabled = !isCustomCommandEnabled,\n                        isChecked = isFormatSortingEnabled,\n                        onChecked = {\n                            isFormatSortingEnabled = !isFormatSortingEnabled\n                            FORMAT_SORTING.updateBoolean(isFormatSortingEnabled)\n                        },\n                        onClick = { showFormatSorterDialog = true },\n                    )\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.format_selection),\n                        icon = Icons.Outlined.VideoSettings,\n                        enabled = !isCustomCommandEnabled,\n                        description = stringResource(id = R.string.format_selection_desc),\n                        isChecked = isFormatSelectionEnabled,\n                    ) {\n                        isFormatSelectionEnabled = !isFormatSelectionEnabled\n                        PreferenceUtil.updateValue(FORMAT_SELECTION, isFormatSelectionEnabled)\n                    }\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.clip_video),\n                        description = stringResource(id = R.string.clip_video_desc),\n                        icon = Icons.Outlined.ContentCut,\n                        isChecked = isVideoClipEnabled,\n                        enabled = !isCustomCommandEnabled && isFormatSelectionEnabled,\n                    ) {\n                        if (!isVideoClipEnabled) showVideoClipDialog = true\n                        else {\n                            isVideoClipEnabled = false\n                            VIDEO_CLIP.updateBoolean(false)\n                        }\n                    }\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.merge_audiostream),\n                        description = stringResource(id = R.string.merge_audiostream_desc),\n                        isChecked = mergeAudioStream,\n                        icon = Icons.Outlined.SpatialAudioOff,\n                        onClick = {\n                            if (mergeAudioStream) {\n                                mergeAudioStream = false\n                                MERGE_MULTI_AUDIO_STREAM.updateBoolean(false)\n                            } else {\n                                showMergeAudioDialog = true\n                            }\n                        },\n                        enabled = !isCustomCommandEnabled && isFormatSelectionEnabled,\n                    )\n                }\n            }\n        },\n    )\n    if (showAudioFormatDialog) {\n        AudioFormatDialog { showAudioFormatDialog = false }\n    }\n    if (showAudioQualityDialog) {\n        AudioQualityDialog { showAudioQualityDialog = false }\n    }\n    if (showAudioConvertDialog) {\n        AudioConversionDialog(\n            onDismissRequest = { showAudioConvertDialog = false },\n            audioFormat = convertFormat,\n            onConfirm = {\n                convertFormat = it\n                AUDIO_CONVERSION_FORMAT.updateInt(it)\n            },\n        )\n    }\n    if (showVideoQualityDialog) {\n        VideoQualityDialog(\n            videoQuality = videoQuality,\n            onDismissRequest = { showVideoQualityDialog = false },\n        ) {\n            videoQuality = it\n            VIDEO_QUALITY.updateInt(it)\n        }\n    }\n    if (showVideoFormatDialog) {\n        VideoFormatDialog(\n            videoFormatPreference = videoFormat,\n            onDismissRequest = { showVideoFormatDialog = false },\n        ) {\n            PreferenceUtil.encodeInt(VIDEO_FORMAT, it)\n            videoFormat = it\n        }\n    }\n    if (showFormatSorterDialog) {\n        FormatSortingDialog(\n            fields = sortingFields,\n            onImport = {\n                sortingFields =\n                    DownloadUtil.DownloadPreferences.createFromPreferences().toFormatSorter()\n            },\n            onDismissRequest = { showFormatSorterDialog = false },\n            showSwitch = false,\n            onConfirm = {\n                sortingFields = it\n                SORTING_FIELDS.updateString(sortingFields)\n            },\n        )\n    }\n    if (showVideoClipDialog) {\n        AlertDialog(\n            onDismissRequest = { showVideoClipDialog = false },\n            icon = { Icon(Icons.Outlined.ContentCut, null) },\n            confirmButton = {\n                ConfirmButton {\n                    isVideoClipEnabled = true\n                    VIDEO_CLIP.updateBoolean(true)\n                    showVideoClipDialog = false\n                }\n            },\n            dismissButton = { DismissButton { showVideoClipDialog = false } },\n            text = { Text(stringResource(id = R.string.clip_video_dialog_msg)) },\n            title = {\n                Text(\n                    stringResource(id = R.string.enable_experimental_feature),\n                    textAlign = TextAlign.Center,\n                )\n            },\n        )\n    }\n    if (showMergeAudioDialog) {\n        AlertDialog(\n            onDismissRequest = { showMergeAudioDialog = false },\n            icon = { Icon(Icons.Outlined.SpatialAudioOff, null) },\n            confirmButton = {\n                ConfirmButton {\n                    mergeAudioStream = true\n                    MERGE_MULTI_AUDIO_STREAM.updateBoolean(true)\n                    showMergeAudioDialog = false\n                }\n            },\n            dismissButton = { DismissButton { showMergeAudioDialog = false } },\n            text = { Text(stringResource(id = R.string.merge_audiostream_desc)) },\n            title = {\n                Text(\n                    stringResource(id = R.string.enable_experimental_feature),\n                    textAlign = TextAlign.Center,\n                )\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/format/FormatSettingDialogs.kt",
    "content": "package com.junkfood.seal.ui.page.settings.format\n\nimport androidx.compose.animation.AnimatedContent\nimport androidx.compose.animation.SizeTransform\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.OpenInNew\nimport androidx.compose.material.icons.automirrored.outlined.Sort\nimport androidx.compose.material.icons.outlined.AudioFile\nimport androidx.compose.material.icons.outlined.HighQuality\nimport androidx.compose.material.icons.outlined.Language\nimport androidx.compose.material.icons.outlined.Settings\nimport androidx.compose.material.icons.outlined.SettingsSuggest\nimport androidx.compose.material.icons.outlined.Sync\nimport androidx.compose.material.icons.outlined.VideoFile\nimport androidx.compose.material.icons.outlined.VideoSettings\nimport androidx.compose.material3.AssistChipDefaults\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.ElevatedAssistChip\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.ExposedDropdownMenuBox\nimport androidx.compose.material3.ExposedDropdownMenuDefaults\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.MenuAnchorType\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.ProvideTextStyle\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.VerticalDivider\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.common.motion.materialSharedAxisX\nimport com.junkfood.seal.ui.common.stringState\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DialogSingleChoiceItem\nimport com.junkfood.seal.ui.component.DialogSingleChoiceItemVariant\nimport com.junkfood.seal.ui.component.DialogSubtitle\nimport com.junkfood.seal.ui.component.DialogSwitchItem\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.OutlinedButtonChip\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SealTextField\nimport com.junkfood.seal.ui.page.downloadv2.configure.PreferencesMock\nimport com.junkfood.seal.util.AUDIO_CONVERSION_FORMAT\nimport com.junkfood.seal.util.AUDIO_CONVERT\nimport com.junkfood.seal.util.AUDIO_FORMAT\nimport com.junkfood.seal.util.AUDIO_QUALITY\nimport com.junkfood.seal.util.CONVERT_M4A\nimport com.junkfood.seal.util.CONVERT_MP3\nimport com.junkfood.seal.util.CONVERT_SUBTITLE\nimport com.junkfood.seal.util.CONVERT_VTT\nimport com.junkfood.seal.util.DEFAULT\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.FORMAT_COMPATIBILITY\nimport com.junkfood.seal.util.FORMAT_QUALITY\nimport com.junkfood.seal.util.M4A\nimport com.junkfood.seal.util.NOT_CONVERT\nimport com.junkfood.seal.util.NOT_SPECIFIED\nimport com.junkfood.seal.util.OPUS\nimport com.junkfood.seal.util.PreferenceStrings\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.RES_HIGHEST\nimport com.junkfood.seal.util.RES_LOWEST\nimport com.junkfood.seal.util.SUBTITLE_LANGUAGE\nimport com.junkfood.seal.util.ULTRA_LOW\nimport com.junkfood.seal.util.getStringDefault\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun VideoResolutionSelectField(\n    modifier: Modifier = Modifier,\n    videoResolution: Int,\n    onSelect: (Int) -> Unit,\n) {\n    var expanded by remember { mutableStateOf(false) }\n    val videoResolutionText = PreferenceStrings.getVideoResolutionDesc(videoResolution)\n\n    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = !expanded }) {\n        SealTextField(\n            modifier = modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),\n            value = videoResolutionText,\n            onValueChange = {},\n            readOnly = true,\n            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },\n            colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),\n            //            label = { Text(stringResource(id = R.string.video_resolution)) }\n        )\n        ExposedDropdownMenu(\n            modifier = Modifier,\n            scrollState = rememberScrollState(),\n            expanded = expanded,\n            onDismissRequest = { expanded = false },\n        ) {\n            for (i in RES_HIGHEST..RES_LOWEST) DropdownMenuItem(\n                text = { Text(PreferenceStrings.getVideoResolutionDesc(i)) },\n                onClick = {\n                    onSelect(i)\n                    expanded = false\n                },\n            )\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun VideoFormatPreferenceSelectField(\n    modifier: Modifier = Modifier,\n    videoFormatPreference: Int,\n    onSelect: (Int) -> Unit,\n) {\n    var expanded by remember { mutableStateOf(false) }\n    val videoFormatText = PreferenceStrings.getVideoFormatLabel(videoFormatPreference)\n\n    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = !expanded }) {\n        OutlinedTextField(\n            modifier = modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),\n            value = videoFormatText,\n            onValueChange = {},\n            readOnly = true,\n            leadingIcon = { Icon(Icons.Outlined.VideoFile, null) },\n            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },\n            colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),\n            label = { Text(stringResource(id = R.string.video_format_preference)) },\n        )\n        ExposedDropdownMenu(\n            modifier = Modifier.verticalScroll(rememberScrollState()),\n            expanded = expanded,\n            onDismissRequest = { expanded = false },\n        ) {\n            for (i in listOf(FORMAT_COMPATIBILITY, FORMAT_QUALITY)) DropdownMenuItem(\n                text = { Text(PreferenceStrings.getVideoFormatLabel(i)) },\n                onClick = {\n                    onSelect(i)\n                    expanded = false\n                },\n            )\n        }\n    }\n}\n\n@Composable\nfun VideoQuickSettingsDialog(\n    videoResolution: Int,\n    videoFormatPreference: Int,\n    onResolutionSelect: (Int) -> Unit,\n    onFormatSelect: (Int) -> Unit,\n    onSave: () -> Unit = {},\n    onDismissRequest: () -> Unit = {},\n) {\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        icon = { Icon(Icons.Outlined.VideoFile, null) },\n        title = { Text(text = stringResource(id = R.string.edit_preset)) },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) { Text(stringResource(R.string.cancel)) }\n        },\n        confirmButton = {\n            Button(\n                onClick = {\n                    onSave()\n                    onDismissRequest()\n                }\n            ) {\n                Text(text = stringResource(R.string.save))\n            }\n        },\n        text = {\n            Column {\n                LazyColumn() {\n                    item { DialogSubtitle(text = stringResource(R.string.video_format_preference)) }\n                    for (i in listOf(FORMAT_COMPATIBILITY, FORMAT_QUALITY)) {\n                        item {\n                            DialogSingleChoiceItemVariant(\n                                modifier = Modifier,\n                                title = PreferenceStrings.getVideoFormatLabel(i),\n                                desc = PreferenceStrings.getVideoFormatDescComp(i),\n                                selected = videoFormatPreference == i,\n                            ) {\n                                onFormatSelect(i)\n                            }\n                        }\n                    }\n                    item { DialogSubtitle(text = stringResource(R.string.video_resolution)) }\n                    item {\n                        VideoResolutionSelectField(\n                            modifier = Modifier.padding(horizontal = 12.dp),\n                            videoResolution = videoResolution,\n                            onSelect = onResolutionSelect,\n                        )\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Preview\n@Composable\nprivate fun VideoPreview() {\n    VideoQuickSettingsDialog(\n        videoResolution = RES_HIGHEST,\n        videoFormatPreference = FORMAT_QUALITY,\n        onResolutionSelect = {},\n        onFormatSelect = {},\n    ) {}\n}\n\n@Preview\n@Composable\nprivate fun AudioPreview() {\n    var b by remember { mutableStateOf(false) }\n    var b1 by remember { mutableStateOf(false) }\n\n    var i1 by remember { mutableIntStateOf(1) }\n    var i2 by remember { mutableIntStateOf(0) }\n    var i3 by remember { mutableIntStateOf(NOT_SPECIFIED) }\n\n    AudioQuickSettingsDialog(\n        preferences = PreferencesMock,\n        convertAudio = b,\n        useCustomAudioPreset = b1,\n        onCustomPresetToggle = { b1 = it },\n        preferredFormat = i1,\n        conversionFormat = i2,\n        onConvertToggled = { b = it },\n        onPreferredSelect = { i1 = it },\n        onConversionSelect = { i2 = it },\n        audioQuality = i3,\n        onQualitySelect = { i3 = it },\n        onSave = {},\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nprivate fun AudioFormatSelectField(\n    modifier: Modifier = Modifier,\n    convertAudio: Boolean,\n    preferredFormat: Int,\n    conversionFormat: Int,\n    onConvertToggled: (Boolean) -> Unit,\n    onPreferredSelect: (Int) -> Unit,\n    onConversionSelect: (Int) -> Unit,\n) {\n    var expanded by remember { mutableStateOf(false) }\n    val preferredFormatText = PreferenceStrings.getAudioFormatDesc(preferredFormat)\n    val conversionFormatText = PreferenceStrings.getAudioConvertDesc(conversionFormat)\n    val userSelectionText = if (convertAudio) conversionFormatText else preferredFormatText\n\n    PreferenceSubtitle(text = stringResource(R.string.audio_format))\n    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = !expanded }) {\n        SealTextField(\n            modifier = modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),\n            value = userSelectionText,\n            onValueChange = {},\n            readOnly = true,\n            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },\n            colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),\n        )\n        ExposedDropdownMenu(\n            modifier = Modifier,\n            scrollState = rememberScrollState(),\n            expanded = expanded,\n            onDismissRequest = { expanded = false },\n        ) {\n            for (i in OPUS..M4A) {\n                DropdownMenuItem(\n                    text = { Text(PreferenceStrings.getAudioFormatDesc(i)) },\n                    onClick = {\n                        onPreferredSelect(i)\n                        onConvertToggled(false)\n                        expanded = false\n                    },\n                )\n            }\n            for (i in CONVERT_MP3..CONVERT_M4A) {\n                DropdownMenuItem(\n                    text = { Text(PreferenceStrings.getAudioConvertDesc(i)) },\n                    onClick = {\n                        onConversionSelect(i)\n                        onConvertToggled(true)\n                        expanded = false\n                    },\n                )\n            }\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nprivate fun AudioQualitySelectField(\n    modifier: Modifier = Modifier,\n    enabled: Boolean = true,\n    audioQuality: Int,\n    onSelect: (Int) -> Unit,\n) {\n    var expanded by remember { mutableStateOf(false) }\n\n    PreferenceSubtitle(text = stringResource(R.string.audio_quality))\n    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = !expanded }) {\n        SealTextField(\n            enabled = enabled,\n            modifier =\n                modifier\n                    .fillMaxWidth()\n                    .menuAnchor(MenuAnchorType.PrimaryNotEditable, enabled = enabled),\n            value =\n                if (!enabled) stringResource(R.string.unavailable)\n                else PreferenceStrings.getAudioQualityDesc(audioQuality),\n            onValueChange = {},\n            readOnly = true,\n            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },\n            colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),\n        )\n        ExposedDropdownMenu(\n            modifier = Modifier,\n            scrollState = rememberScrollState(),\n            expanded = expanded,\n            onDismissRequest = { expanded = false },\n        ) {\n            for (i in NOT_SPECIFIED..ULTRA_LOW) {\n                DropdownMenuItem(\n                    text = { Text(PreferenceStrings.getAudioQualityDesc(i)) },\n                    onClick = {\n                        onSelect(i)\n                        expanded = false\n                    },\n                )\n            }\n        }\n    }\n}\n\n@Composable\nfun AudioQuickSettingsDialog(\n    modifier: Modifier = Modifier,\n    preferences: DownloadUtil.DownloadPreferences,\n    onDismissRequest: () -> Unit = {},\n    useCustomAudioPreset: Boolean,\n    onCustomPresetToggle: (Boolean) -> Unit,\n    convertAudio: Boolean,\n    preferredFormat: Int,\n    conversionFormat: Int,\n    onConvertToggled: (Boolean) -> Unit,\n    onPreferredSelect: (Int) -> Unit,\n    onConversionSelect: (Int) -> Unit,\n    audioQuality: Int,\n    onQualitySelect: (Int) -> Unit,\n    onSave: () -> Unit,\n) {\n    var editingPreset by remember { mutableStateOf(false) }\n    SealDialog(\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        icon = { Icon(Icons.Outlined.AudioFile, null) },\n        title = { Text(stringResource(R.string.edit_preset)) },\n        text = {\n            AnimatedContent(\n                editingPreset,\n                transitionSpec = {\n                    materialSharedAxisX(initialOffsetX = { it / 5 }, targetOffsetX = { -it / 5 })\n                        .using(SizeTransform())\n                },\n                label = \"\",\n            ) {\n                if (!it) {\n                    Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                        DialogSubtitle(text = stringResource(R.string.presets))\n                        DialogSingleChoiceItemVariant(\n                            title = stringResource(R.string.best_quality),\n                            selected = !useCustomAudioPreset,\n                            desc = stringResource(R.string.best_quality_desc),\n                            onClick = { onCustomPresetToggle(false) },\n                        )\n\n                        DialogSingleChoiceItemVariant(\n                            title = stringResource(R.string.custom),\n                            selected = useCustomAudioPreset,\n                            onClick = { onCustomPresetToggle(true) },\n                            desc =\n                                PreferenceStrings.getAudioPresetText(\n                                    preferences.copy(useCustomAudioPreset = true)\n                                ),\n                            action = {\n                                if (useCustomAudioPreset) {\n                                    Spacer(Modifier.width(8.dp))\n                                    VerticalDivider(Modifier.height(32.dp))\n                                    IconButton(onClick = { editingPreset = true }) {\n                                        Icon(\n                                            imageVector = Icons.Outlined.Settings,\n                                            contentDescription = stringResource(R.string.edit),\n                                        )\n                                    }\n                                }\n                            },\n                        )\n                    }\n                } else {\n                    Column(\n                        modifier =\n                            Modifier.verticalScroll(rememberScrollState())\n                                .padding(horizontal = 16.dp)\n                    ) {\n                        AudioFormatSelectField(\n                            convertAudio = convertAudio,\n                            preferredFormat = preferredFormat,\n                            conversionFormat = conversionFormat,\n                            onConvertToggled = onConvertToggled,\n                            onPreferredSelect = onPreferredSelect,\n                            onConversionSelect = onConversionSelect,\n                        )\n                        AudioQualitySelectField(\n                            audioQuality = audioQuality,\n                            enabled = !convertAudio,\n                            onSelect = onQualitySelect,\n                        )\n                    }\n                }\n            }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) { Text(stringResource(R.string.cancel)) }\n        },\n        confirmButton = {\n            Button(\n                onClick = {\n                    onSave()\n                    onDismissRequest()\n                }\n            ) {\n                Text(stringResource(R.string.save))\n            }\n        },\n    )\n}\n\n@Composable\nfun AudioConversionDialog(\n    onDismissRequest: () -> Unit,\n    audioFormat: Int,\n    onConfirm: (Int) -> Unit = {},\n) {\n    var audioFormat by remember { mutableIntStateOf(audioFormat) }\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dismiss)) }\n        },\n        icon = { Icon(Icons.Outlined.Sync, null) },\n        title = { Text(stringResource(R.string.convert_audio_format)) },\n        confirmButton = {\n            TextButton(\n                onClick = {\n                    AUDIO_CONVERSION_FORMAT.updateInt(audioFormat)\n                    onConfirm(audioFormat)\n                    onDismissRequest()\n                }\n            ) {\n                Text(text = stringResource(R.string.confirm))\n            }\n        },\n        text = {\n            Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                Text(\n                    modifier =\n                        Modifier.fillMaxWidth().padding(bottom = 12.dp).padding(horizontal = 24.dp),\n                    text = stringResource(R.string.convert_audio_format_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                for (i in CONVERT_MP3..CONVERT_M4A) DialogSingleChoiceItem(\n                    modifier = Modifier,\n                    text = PreferenceStrings.getAudioConvertDesc(i),\n                    selected = audioFormat == i,\n                ) {\n                    audioFormat = i\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun AudioConversionQuickSettingsDialog(onDismissRequest: () -> Unit, onConfirm: () -> Unit = {}) {\n    var audioFormat by remember { mutableIntStateOf(PreferenceUtil.getAudioConvertFormat()) }\n    var convertAudio by AUDIO_CONVERT.booleanState\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = { DismissButton { onDismissRequest() } },\n        icon = { Icon(Icons.Outlined.Sync, null) },\n        title = { Text(stringResource(R.string.convert_audio_format)) },\n        confirmButton = {\n            ConfirmButton {\n                AUDIO_CONVERT.updateBoolean(convertAudio)\n                AUDIO_CONVERSION_FORMAT.updateInt(audioFormat)\n                onConfirm()\n                onDismissRequest()\n            }\n        },\n        text = {\n            Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                Text(\n                    modifier =\n                        Modifier.fillMaxWidth().padding(bottom = 12.dp).padding(horizontal = 24.dp),\n                    text = stringResource(R.string.convert_audio_format_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                DialogSingleChoiceItem(\n                    text = stringResource(id = R.string.not_convert),\n                    selected = !convertAudio,\n                ) {\n                    convertAudio = false\n                }\n                for (i in CONVERT_MP3..CONVERT_M4A) DialogSingleChoiceItem(\n                    modifier = Modifier,\n                    text = PreferenceStrings.getAudioConvertDesc(i),\n                    selected = audioFormat == i && convertAudio,\n                ) {\n                    audioFormat = i\n                    convertAudio = true\n                }\n            }\n        },\n    )\n}\n\n@Composable\n@Preview\nfun VideoFormatDialog(\n    videoFormatPreference: Int = FORMAT_COMPATIBILITY,\n    onDismissRequest: () -> Unit = {},\n    onConfirm: (Int) -> Unit = {},\n) {\n    var preference by remember { mutableIntStateOf(videoFormatPreference) }\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dismiss)) }\n        },\n        icon = { Icon(Icons.Outlined.VideoFile, null) },\n        title = { Text(stringResource(R.string.video_format_preference)) },\n        confirmButton = {\n            TextButton(\n                onClick = {\n                    onConfirm(preference)\n                    onDismissRequest()\n                }\n            ) {\n                Text(text = stringResource(R.string.confirm))\n            }\n        },\n        text = {\n            Column {\n                androidx.compose.material3.HorizontalDivider()\n                LazyColumn(modifier = Modifier, contentPadding = PaddingValues(vertical = 8.dp)) {\n                    for (i in listOf(FORMAT_COMPATIBILITY, FORMAT_QUALITY)) item {\n                        DialogSingleChoiceItemVariant(\n                            modifier = Modifier,\n                            title = PreferenceStrings.getVideoFormatLabel(i),\n                            desc = PreferenceStrings.getVideoFormatDescComp(i),\n                            selected = preference == i,\n                        ) {\n                            preference = i\n                        }\n                    }\n                }\n                androidx.compose.material3.HorizontalDivider()\n            }\n        },\n    )\n}\n\n@Composable\nfun AudioFormatDialog(onDismissRequest: () -> Unit) {\n    var audioFormat by AUDIO_FORMAT.intState\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dismiss)) }\n        },\n        icon = { Icon(Icons.Outlined.AudioFile, null) },\n        title = { Text(stringResource(R.string.audio_format_preference)) },\n        confirmButton = {\n            ConfirmButton {\n                AUDIO_FORMAT.updateInt(audioFormat)\n                onDismissRequest()\n            }\n        },\n        text = {\n            Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                Text(\n                    modifier =\n                        Modifier.fillMaxWidth().padding(bottom = 12.dp).padding(horizontal = 24.dp),\n                    text = stringResource(R.string.preferred_format_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                for (i in DEFAULT..M4A) DialogSingleChoiceItem(\n                    modifier = Modifier,\n                    text = PreferenceStrings.getAudioFormatDesc(i),\n                    selected = audioFormat == i,\n                ) {\n                    audioFormat = i\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun AudioQualityDialog(onDismissRequest: () -> Unit) {\n    var audioQuality by AUDIO_QUALITY.intState\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = { DismissButton { onDismissRequest() } },\n        icon = { Icon(Icons.Outlined.HighQuality, null) },\n        title = { Text(stringResource(R.string.audio_quality)) },\n        confirmButton = {\n            ConfirmButton {\n                AUDIO_QUALITY.updateInt(audioQuality)\n                onDismissRequest()\n            }\n        },\n        text = {\n            Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                Text(\n                    modifier =\n                        Modifier.fillMaxWidth().padding(bottom = 12.dp).padding(horizontal = 24.dp),\n                    text = stringResource(R.string.audio_quality_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                for (i in NOT_SPECIFIED..ULTRA_LOW) DialogSingleChoiceItem(\n                    modifier = Modifier,\n                    text = PreferenceStrings.getAudioQualityDesc(i),\n                    selected = audioQuality == i,\n                ) {\n                    audioQuality = i\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun FormatSortingDialog(\n    fields: String,\n    showSwitch: Boolean = false,\n    toggleableValue: Boolean = false,\n    onSwitchChecked: (Boolean) -> Unit = {},\n    onImport: () -> Unit = {},\n    onDismissRequest: () -> Unit = {},\n    onConfirm: (String) -> Unit = {},\n) {\n    var sortingFields by remember(fields) { mutableStateOf(fields) }\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = { DismissButton { onDismissRequest() } },\n        icon = { Icon(Icons.AutoMirrored.Outlined.Sort, null) },\n        title = { Text(stringResource(R.string.format_sorting)) },\n        confirmButton = {\n            ConfirmButton(text = stringResource(id = R.string.save)) {\n                onConfirm(sortingFields)\n                onDismissRequest()\n            }\n        },\n        text = {\n            Column(modifier = Modifier.verticalScroll(rememberScrollState())) {\n                Text(\n                    modifier =\n                        Modifier.fillMaxWidth().padding(horizontal = 24.dp).padding(bottom = 12.dp),\n                    text = stringResource(R.string.format_sorting_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                OutlinedTextField(\n                    modifier = Modifier.padding(horizontal = 24.dp, vertical = 8.dp),\n                    value = sortingFields,\n                    onValueChange = { sortingFields = it },\n                    leadingIcon = { Text(text = \"-S\", fontFamily = FontFamily.Monospace) },\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                )\n                val uriHandler = LocalUriHandler.current\n                Row(\n                    modifier =\n                        Modifier.padding(horizontal = 16.dp)\n                            .horizontalScroll(rememberScrollState())\n                            .padding(horizontal = 8.dp)\n                ) {\n                    OutlinedButtonChip(\n                        modifier = Modifier.padding(end = 8.dp),\n                        label = stringResource(id = R.string.import_from_preferences),\n                        icon = Icons.Outlined.SettingsSuggest,\n                    ) {\n                        onImport()\n                    }\n                    OutlinedButtonChip(\n                        label = stringResource(R.string.yt_dlp_docs),\n                        icon = Icons.AutoMirrored.Outlined.OpenInNew,\n                    ) {\n                        uriHandler.openUri(sortingFormats)\n                    }\n                }\n                if (showSwitch) {\n                    Spacer(modifier = Modifier.height(12.dp))\n                    androidx.compose.material3.HorizontalDivider(\n                        modifier = Modifier.padding(horizontal = 24.dp)\n                    )\n                    DialogSwitchItem(\n                        text = stringResource(id = R.string.use_format_sorting),\n                        value = toggleableValue,\n                        onValueChange = onSwitchChecked,\n                    )\n                }\n            }\n        },\n    )\n}\n\n@Preview\n@Composable\nprivate fun FormatSortingDialogPreview() {\n    var value by remember { mutableStateOf(false) }\n    FormatSortingDialog(\n        fields = \"\",\n        showSwitch = true,\n        toggleableValue = value,\n        onSwitchChecked = { value = it },\n    )\n}\n\n@Composable\nfun VideoQualityDialog(\n    videoQuality: Int = 0,\n    onDismissRequest: () -> Unit = {},\n    onConfirm: (Int) -> Unit = {},\n) {\n    var videoResolution by remember { mutableIntStateOf(videoQuality) }\n\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dismiss)) }\n        },\n        icon = { Icon(Icons.Outlined.HighQuality, null) },\n        title = { Text(stringResource(R.string.video_quality)) },\n        confirmButton = {\n            TextButton(\n                onClick = {\n                    onConfirm(videoResolution)\n                    onDismissRequest()\n                }\n            ) {\n                Text(text = stringResource(R.string.confirm))\n            }\n        },\n        text = {\n            Column() {\n                Text(\n                    modifier =\n                        Modifier.fillMaxWidth().padding(bottom = 12.dp).padding(horizontal = 24.dp),\n                    text = stringResource(R.string.video_quality_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                LazyColumn() {\n                    //                    item { videoResolutionSelectField() }\n                    for (i in 0..7) {\n                        item {\n                            DialogSingleChoiceItem(\n                                text = PreferenceStrings.getVideoResolutionDesc(i),\n                                selected = videoResolution == i,\n                            ) {\n                                videoResolution = i\n                            }\n                        }\n                    }\n                }\n            }\n        },\n    )\n}\n\nprivate const val subtitleOptions = \"https://github.com/yt-dlp/yt-dlp#subtitle-options\"\nprivate const val sortingFormats = \"https://github.com/yt-dlp/yt-dlp#sorting-formats\"\n\n@Composable\nfun SubtitleLanguageDialog(onDismissRequest: () -> Unit) {\n    var languages by SUBTITLE_LANGUAGE.stringState\n    SubtitleLanguageDialogImpl(\n        onDismissRequest = onDismissRequest,\n        initialLanguages = languages,\n        onReset = {\n            SUBTITLE_LANGUAGE.let {\n                languages = it.getStringDefault()\n                it.updateString(languages)\n            }\n        },\n        onConfirm = { SUBTITLE_LANGUAGE.updateString(it) },\n    )\n}\n\n@Composable\n@Preview\nprivate fun SubtitleLanguageDialogImpl(\n    onDismissRequest: () -> Unit = {},\n    initialLanguages: String = \"en.*,.*-orig\",\n    onReset: () -> Unit = {},\n    onConfirm: (String) -> Unit = {},\n) {\n    var languages by remember(initialLanguages) { mutableStateOf(initialLanguages) }\n    val uriHandler = LocalUriHandler.current\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(stringResource(id = R.string.subtitle_language)) },\n        icon = { Icon(Icons.Outlined.Language, null) },\n        text = {\n            Column() {\n                Text(\n                    text = stringResource(id = R.string.subtitle_language_desc),\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                )\n                Spacer(modifier = Modifier.height(16.dp))\n                ProvideTextStyle(\n                    value = LocalTextStyle.current.merge(fontFamily = FontFamily.Monospace)\n                ) {\n                    OutlinedTextField(\n                        modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),\n                        value = languages,\n                        onValueChange = { languages = it },\n                        label = { Text(stringResource(id = R.string.subtitle_language)) },\n                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                    )\n                }\n                Spacer(modifier = Modifier.height(8.dp))\n\n                Row(\n                    modifier =\n                        Modifier.padding(horizontal = 16.dp)\n                            .horizontalScroll(rememberScrollState())\n                            .padding(horizontal = 8.dp)\n                ) {\n                    OutlinedButtonChip(\n                        modifier = Modifier.padding(end = 8.dp),\n                        label = stringResource(id = R.string.reset),\n                        icon = Icons.Outlined.Sync,\n                    ) {\n                        onReset()\n                    }\n                    OutlinedButtonChip(\n                        label = stringResource(R.string.yt_dlp_docs),\n                        icon = Icons.AutoMirrored.Outlined.OpenInNew,\n                    ) {\n                        uriHandler.openUri(sortingFormats)\n                    }\n                }\n            }\n        },\n        confirmButton = {\n            ConfirmButton() {\n                onConfirm(languages)\n                onDismissRequest()\n            }\n        },\n        dismissButton = { DismissButton() { onDismissRequest() } },\n    )\n}\n\n@Composable\nfun SubtitleConversionDialog(onDismissRequest: () -> Unit) {\n    var currentFormat by CONVERT_SUBTITLE.intState\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton {\n                CONVERT_SUBTITLE.updateInt(currentFormat)\n                onDismissRequest()\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        title = { Text(text = stringResource(id = R.string.convert_subtitle)) },\n        icon = { Icon(imageVector = Icons.Outlined.Sync, contentDescription = null) },\n        text = {\n            LazyColumn {\n                item {\n                    Text(\n                        text = stringResource(id = R.string.convert_subtitle_desc),\n                        modifier = Modifier.padding(horizontal = 24.dp).padding(bottom = 12.dp),\n                        style = MaterialTheme.typography.bodyLarge,\n                    )\n                }\n                for (format in NOT_CONVERT..CONVERT_VTT) {\n                    item {\n                        DialogSingleChoiceItem(\n                            text = PreferenceStrings.getSubtitleConversionFormat(format),\n                            selected = currentFormat == format,\n                        ) {\n                            currentFormat = format\n                        }\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Composable\n@Preview\nfun VideoQualityPreferenceChip(\n    modifier: Modifier = Modifier,\n    videoQualityPreference: Int = FORMAT_COMPATIBILITY,\n    enabled: Boolean = true,\n    onClick: () -> Unit = {},\n) {\n    ElevatedAssistChip(\n        modifier = modifier,\n        onClick = onClick,\n        label = { Text(text = PreferenceStrings.getVideoFormatLabel(videoQualityPreference)) },\n        leadingIcon = {\n            Icon(\n                imageVector = Icons.Outlined.VideoSettings,\n                contentDescription = null,\n                modifier = Modifier.size(AssistChipDefaults.IconSize),\n            )\n        },\n    )\n}\n\n@Composable\n@Preview\nfun VideoResolutionChip(\n    modifier: Modifier = Modifier,\n    videoResolution: Int = 0,\n    enabled: Boolean = true,\n    onClick: () -> Unit = {},\n) {\n    ElevatedAssistChip(\n        modifier = modifier,\n        onClick = onClick,\n        label = { Text(text = PreferenceStrings.getVideoResolutionDesc(videoResolution)) },\n        leadingIcon = {\n            Icon(\n                imageVector = Icons.Outlined.VideoSettings,\n                contentDescription = null,\n                modifier = Modifier.size(AssistChipDefaults.IconSize),\n            )\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/format/SubtitlePreference.kt",
    "content": "package com.junkfood.seal.ui.page.settings.format\n\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.ClosedCaption\nimport androidx.compose.material.icons.outlined.Language\nimport androidx.compose.material.icons.outlined.Save\nimport androidx.compose.material.icons.outlined.Subtitles\nimport androidx.compose.material.icons.outlined.Sync\nimport androidx.compose.material.icons.outlined.Translate\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.style.TextAlign\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithContainer\nimport com.junkfood.seal.util.AUTO_SUBTITLE\nimport com.junkfood.seal.util.AUTO_TRANSLATED_SUBTITLES\nimport com.junkfood.seal.util.EMBED_SUBTITLE\nimport com.junkfood.seal.util.EXTRACT_AUDIO\nimport com.junkfood.seal.util.KEEP_SUBTITLE_FILES\nimport com.junkfood.seal.util.PreferenceStrings\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.SPONSORBLOCK\nimport com.junkfood.seal.util.SUBTITLE\nimport com.junkfood.seal.util.SUBTITLE_LANGUAGE\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun SubtitlePreference(onNavigateBack: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    var downloadSubtitle by SUBTITLE.booleanState\n    val sponsorBlock by SPONSORBLOCK.booleanState\n    //    var keepSubtitleFile by KEEP_SUBTITLE_FILES.booleanState\n    var embedSubtitle by EMBED_SUBTITLE.booleanState\n    var autoSubtitle by AUTO_SUBTITLE.booleanState\n    var autoTranslatedSubtitle by AUTO_TRANSLATED_SUBTITLES.booleanState\n\n    var showLanguageDialog by remember { mutableStateOf(false) }\n    var showConversionDialog by remember { mutableStateOf(false) }\n    var showEmbedSubtitleDialog by remember { mutableStateOf(false) }\n    var showAutoTranslateDialog by remember { mutableStateOf(false) }\n\n    val subtitleFormatText by\n        remember(showConversionDialog) {\n            mutableStateOf(PreferenceStrings.getSubtitleConversionFormat())\n        }\n\n    val subtitleLang by\n        remember(showLanguageDialog) { mutableStateOf(SUBTITLE_LANGUAGE.getString()) }\n    val sponsorBlockText = stringResource(id = R.string.subtitle_sponsorblock)\n    val embedSubtitleText = stringResource(R.string.embed_subtitles_mkv_msg)\n\n    val hint by\n        remember(sponsorBlock, embedSubtitle) {\n            derivedStateOf {\n                StringBuilder()\n                    .apply {\n                        if (sponsorBlock) append(sponsorBlockText)\n                        if (isNotEmpty()) append(\"\\n\\n\")\n                        if (embedSubtitle) append(embedSubtitleText)\n                    }\n                    .toString()\n            }\n        }\n\n    val downloadAudio by EXTRACT_AUDIO.booleanState\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(id = R.string.subtitle))\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            LazyColumn(modifier = Modifier, contentPadding = it) {\n                item {\n                    PreferenceSwitchWithContainer(\n                        title = stringResource(id = R.string.download_subtitles),\n                        isChecked = downloadSubtitle,\n                        onClick = {\n                            downloadSubtitle = !downloadSubtitle\n                            SUBTITLE.updateBoolean(downloadSubtitle)\n                        },\n                        icon = null,\n                    )\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.subtitle_language),\n                        icon = Icons.Outlined.Language,\n                        description = subtitleLang,\n                        onClick = { showLanguageDialog = true },\n                    )\n                }\n\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.convert_subtitle),\n                        description = subtitleFormatText,\n                        icon = Icons.Outlined.Sync,\n                    ) {\n                        showConversionDialog = true\n                    }\n                }\n\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.auto_subtitle),\n                        icon = Icons.Outlined.ClosedCaption,\n                        description = stringResource(id = R.string.auto_subtitle_desc),\n                        isChecked = autoSubtitle,\n                        onClick = {\n                            autoSubtitle = !autoSubtitle\n                            AUTO_SUBTITLE.updateBoolean(autoSubtitle)\n                        },\n                    )\n                }\n\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.auto_translated_subtitles),\n                        icon = Icons.Outlined.Translate,\n                        isChecked = autoTranslatedSubtitle,\n                        enabled = autoSubtitle,\n                    ) {\n                        if (!autoTranslatedSubtitle) {\n                            showAutoTranslateDialog = true\n                        } else {\n                            autoTranslatedSubtitle = false\n                            AUTO_TRANSLATED_SUBTITLES.updateBoolean(false)\n                        }\n                    }\n                }\n\n                item {\n                    androidx.compose.material3.HorizontalDivider()\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.embed_subtitles),\n                        description = stringResource(id = R.string.embed_subtitles_desc),\n                        isChecked = embedSubtitle,\n                        enabled = !downloadAudio,\n                        onClick = {\n                            if (embedSubtitle) {\n                                embedSubtitle = false\n                                EMBED_SUBTITLE.updateBoolean(false)\n                            } else {\n                                showEmbedSubtitleDialog = true\n                            }\n                        },\n                        icon = Icons.Outlined.Subtitles,\n                    )\n                }\n\n                item {\n                    Column {\n                        var keepSubtitles by KEEP_SUBTITLE_FILES.booleanState\n                        PreferenceSwitch(\n                            title = stringResource(id = R.string.keep_subtitle_files),\n                            description = null,\n                            isChecked = keepSubtitles,\n                            enabled = !downloadAudio && embedSubtitle,\n                            onClick = {\n                                keepSubtitles = !keepSubtitles\n                                KEEP_SUBTITLE_FILES.updateBoolean(keepSubtitles)\n                            },\n                            icon = Icons.Outlined.Save,\n                        )\n                    }\n                }\n\n                item { if (hint.isNotEmpty()) PreferenceInfo(text = hint) }\n            }\n        },\n    )\n    if (showLanguageDialog) SubtitleLanguageDialog { showLanguageDialog = false }\n    if (showConversionDialog) SubtitleConversionDialog { showConversionDialog = false }\n    if (showEmbedSubtitleDialog) {\n        AlertDialog(\n            onDismissRequest = { showEmbedSubtitleDialog = false },\n            icon = { Icon(Icons.Outlined.Subtitles, null) },\n            confirmButton = {\n                ConfirmButton {\n                    embedSubtitle = true\n                    EMBED_SUBTITLE.updateBoolean(true)\n                    showEmbedSubtitleDialog = false\n                }\n            },\n            dismissButton = { DismissButton { showEmbedSubtitleDialog = false } },\n            text = { Text(stringResource(id = R.string.embed_subtitles_mkv_msg)) },\n            title = {\n                Text(\n                    stringResource(id = R.string.enable_experimental_feature),\n                    textAlign = TextAlign.Center,\n                )\n            },\n        )\n    }\n    if (showAutoTranslateDialog) {\n        AlertDialog(\n            onDismissRequest = { showAutoTranslateDialog = false },\n            icon = { Icon(Icons.Outlined.Translate, null) },\n            confirmButton = {\n                ConfirmButton {\n                    autoTranslatedSubtitle = true\n                    AUTO_TRANSLATED_SUBTITLES.updateBoolean(true)\n                    showAutoTranslateDialog = false\n                }\n            },\n            dismissButton = { DismissButton { showAutoTranslateDialog = false } },\n            text = { Text(stringResource(id = R.string.auto_translated_subtitles_msg)) },\n            title = {\n                Text(\n                    stringResource(id = R.string.enable_experimental_feature),\n                    textAlign = TextAlign.Center,\n                )\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/general/AdvancedSettingDialogs.kt",
    "content": "package com.junkfood.seal.ui.page.settings.general\n\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.MoneyOff\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.ExperimentalComposeUiApi\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalFocusManager\nimport androidx.compose.ui.platform.LocalSoftwareKeyboardController\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.LinkButton\nimport com.junkfood.seal.ui.component.OutlinedButtonChip\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.SPONSORBLOCK_CATEGORIES\n\nconst val ytdlpReference = \"https://github.com/yt-dlp/yt-dlp#usage-and-options\"\nconst val sponsorBlockReference = \"https://github.com/yt-dlp/yt-dlp#sponsorblock-options\"\n\nval sponsorBlockCategories =\n    listOf(\n        \"sponsor\",\n        \"intro\",\n        \"outro\",\n        \"selfpromo\",\n        \"preview\",\n        \"filler\",\n        \"interaction\",\n        \"music_offtopic\",\n    )\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)\n@Composable\nfun SponsorBlockDialog(onDismissRequest: () -> Unit) {\n    var categories by remember { mutableStateOf(PreferenceUtil.getSponsorBlockCategories()) }\n    val focusManager = LocalFocusManager.current\n    val softwareKeyboardController = LocalSoftwareKeyboardController.current\n\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        icon = { Icon(Icons.Outlined.MoneyOff, null) },\n        title = { Text(stringResource(R.string.sponsorblock)) },\n        text = {\n            Column {\n                Text(\n                    stringResource(R.string.sponsorblock_categories_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                OutlinedTextField(\n                    modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 12.dp),\n                    value = categories,\n                    label = { Text(stringResource(R.string.sponsorblock_categories)) },\n                    onValueChange = { categories = it },\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                )\n                LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {\n                    item { OutlinedButtonChip(label = \"default\") { categories = \"default\" } }\n                    item { OutlinedButtonChip(label = \"all\") { categories = \"all\" } }\n                    sponsorBlockCategories.forEach {\n                        if (!categories.contains(it))\n                            item {\n                                OutlinedButtonChip(label = it) {\n                                    categories =\n                                        categories.replace(regex = Regex(\"(all)|(default)\"), \"\")\n                                    categories = \"$categories,$it\"\n                                    categories = categories.removePrefix(\",\")\n                                }\n                            }\n                    }\n                }\n                LinkButton(link = sponsorBlockReference)\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = {\n            ConfirmButton {\n                onDismissRequest()\n                PreferenceUtil.encodeString(SPONSORBLOCK_CATEGORIES, categories)\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/general/GeneralDownloadPreferences.kt",
    "content": "package com.junkfood.seal.ui.page.settings.general\n\nimport android.Manifest\nimport android.os.Build\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.foundation.selection.toggleable\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Archive\nimport androidx.compose.material.icons.outlined.DoneAll\nimport androidx.compose.material.icons.outlined.Edit\nimport androidx.compose.material.icons.outlined.History\nimport androidx.compose.material.icons.outlined.HistoryToggleOff\nimport androidx.compose.material.icons.outlined.Image\nimport androidx.compose.material.icons.outlined.MoneyOff\nimport androidx.compose.material.icons.outlined.Notifications\nimport androidx.compose.material.icons.outlined.NotificationsActive\nimport androidx.compose.material.icons.outlined.NotificationsOff\nimport androidx.compose.material.icons.outlined.PlaylistAddCheck\nimport androidx.compose.material.icons.outlined.Print\nimport androidx.compose.material.icons.outlined.PrintDisabled\nimport androidx.compose.material.icons.outlined.RemoveDone\nimport androidx.compose.material.icons.outlined.Settings\nimport androidx.compose.material.icons.outlined.Update\nimport androidx.compose.material.icons.outlined.Visibility\nimport androidx.compose.material.icons.outlined.VisibilityOff\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.contentColorFor\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.font.FontFamily\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.google.accompanist.permissions.ExperimentalPermissionsApi\nimport com.google.accompanist.permissions.PermissionStatus\nimport com.google.accompanist.permissions.rememberPermissionState\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithDivider\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.page.download.NotificationPermissionDialog\nimport com.junkfood.seal.util.CONFIGURE\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.DEBUG\nimport com.junkfood.seal.util.DISABLE_PREVIEW\nimport com.junkfood.seal.util.DOWNLOAD_ARCHIVE\nimport com.junkfood.seal.util.FileUtil.getArchiveFile\nimport com.junkfood.seal.util.NOTIFICATION\nimport com.junkfood.seal.util.NotificationUtil\nimport com.junkfood.seal.util.PLAYLIST\nimport com.junkfood.seal.util.PRIVATE_MODE\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.SPONSORBLOCK\nimport com.junkfood.seal.util.SUBTITLE\nimport com.junkfood.seal.util.THUMBNAIL\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.UpdateUtil\nimport com.junkfood.seal.util.YT_DLP_VERSION\nimport com.yausername.youtubedl_android.YoutubeDL\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n@OptIn(ExperimentalPermissionsApi::class, ExperimentalMaterial3Api::class)\n@Composable\nfun GeneralDownloadPreferences(onNavigateBack: () -> Unit, navigateToTemplate: () -> Unit) {\n    val context = LocalContext.current\n    val scope = rememberCoroutineScope()\n    val hapticFeedback = LocalHapticFeedback.current\n\n    var showSponsorBlockDialog by remember { mutableStateOf(false) }\n    var showYtdlpDialog by remember { mutableStateOf(false) }\n    var isUpdating by remember { mutableStateOf(false) }\n\n    val downloadSubtitle by SUBTITLE.booleanState\n\n    var displayErrorReport by DEBUG.booleanState\n    var downloadPlaylist by remember { mutableStateOf(PLAYLIST.getBoolean()) }\n    var isSponsorBlockEnabled by remember { mutableStateOf(SPONSORBLOCK.getBoolean()) }\n    var downloadNotification by remember { mutableStateOf(NOTIFICATION.getBoolean()) }\n\n    var isPrivateModeEnabled by remember { mutableStateOf(PRIVATE_MODE.getBoolean()) }\n\n    var isPreviewDisabled by remember { mutableStateOf(DISABLE_PREVIEW.getBoolean()) }\n    var isNotificationPermissionGranted by remember {\n        mutableStateOf(NotificationUtil.areNotificationsEnabled())\n    }\n\n    val notificationPermission =\n        if (Build.VERSION.SDK_INT >= 33)\n            rememberPermissionState(permission = Manifest.permission.POST_NOTIFICATIONS) { status ->\n                if (!status) ToastUtil.makeToast(context.getString(R.string.permission_denied))\n                else isNotificationPermissionGranted = true\n            }\n        else null\n\n    var useDownloadArchive by DOWNLOAD_ARCHIVE.booleanState\n    var showClearArchiveDialog by remember { mutableStateOf(false) }\n    var showNotificationDialog by remember { mutableStateOf(false) }\n    var archiveFileContent by remember { mutableStateOf(\"\") }\n\n    val storagePermission =\n        rememberPermissionState(permission = Manifest.permission.WRITE_EXTERNAL_STORAGE)\n\n    val isPermissionGranted =\n        Build.VERSION.SDK_INT > 29 || storagePermission.status == PermissionStatus.Granted\n\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(text = stringResource(id = R.string.general_settings)) },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            val isCustomCommandEnabled by remember { mutableStateOf(CUSTOM_COMMAND.getBoolean()) }\n            LazyColumn(modifier = Modifier, contentPadding = it) {\n                //                item {\n                //                    SettingTitle(text = stringResource(id =\n                // R.string.general_settings))\n                //                }\n                if (isCustomCommandEnabled)\n                    item {\n                        PreferenceInfo(\n                            text = stringResource(id = R.string.custom_command_enabled_hint)\n                        )\n                    }\n                item {\n                    var ytdlpVersion by remember {\n                        mutableStateOf(\n                            YoutubeDL.getInstance().version(context.applicationContext)\n                                ?: context.getString(R.string.ytdlp_update)\n                        )\n                    }\n                    PreferenceItem(\n                        title = stringResource(id = R.string.ytdlp_update_action),\n                        description = ytdlpVersion,\n                        leadingIcon = {\n                            if (isUpdating) UpdateProgressIndicator()\n                            else {\n                                Icon(\n                                    imageVector = Icons.Outlined.Update,\n                                    contentDescription = null,\n                                    modifier =\n                                        Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                                    tint = MaterialTheme.colorScheme.onSurfaceVariant,\n                                )\n                            }\n                        },\n                        onClick = {\n                            scope.launch {\n                                runCatching {\n                                        isUpdating = true\n                                        UpdateUtil.updateYtDlp()\n                                        ytdlpVersion = YT_DLP_VERSION.getString()\n                                    }\n                                    .onFailure { th ->\n                                        th.printStackTrace()\n                                        ToastUtil.makeToastSuspend(\n                                            App.context.getString(R.string.yt_dlp_update_fail)\n                                        )\n                                    }\n                                    .onSuccess {\n                                        ToastUtil.makeToastSuspend(\n                                            context.getString(R.string.yt_dlp_up_to_date) +\n                                                \" (${YT_DLP_VERSION.getString()})\"\n                                        )\n                                    }\n                                isUpdating = false\n                            }\n                        },\n                        onClickLabel = stringResource(id = R.string.update),\n                        trailingIcon = {\n                            IconButton(onClick = { showYtdlpDialog = true }) {\n                                Icon(\n                                    imageVector = Icons.Outlined.Settings,\n                                    contentDescription = stringResource(id = R.string.open_settings),\n                                )\n                            }\n                        },\n                    )\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.download_notification),\n                        description =\n                            stringResource(\n                                id =\n                                    if (isNotificationPermissionGranted)\n                                        R.string.download_notification_desc\n                                    else R.string.permission_denied\n                            ),\n                        icon =\n                            if (!isNotificationPermissionGranted) Icons.Outlined.NotificationsOff\n                            else if (!downloadNotification) Icons.Outlined.Notifications\n                            else Icons.Outlined.NotificationsActive,\n                        isChecked = downloadNotification && isNotificationPermissionGranted,\n                        onClick = {\n                            if (notificationPermission?.status is PermissionStatus.Denied) {\n                                showNotificationDialog = true\n                            } else if (isNotificationPermissionGranted) {\n                                if (downloadNotification) NotificationUtil.cancelAllNotifications()\n                                downloadNotification = !downloadNotification\n                                PreferenceUtil.updateValue(NOTIFICATION, downloadNotification)\n                            }\n                        },\n                    )\n                }\n\n                item {\n                    var configureBeforeDownload by CONFIGURE.booleanState\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.settings_before_download),\n                        description = stringResource(id = R.string.settings_before_download_desc),\n                        icon =\n                            if (configureBeforeDownload) Icons.Outlined.DoneAll\n                            else Icons.Outlined.RemoveDone,\n                        isChecked = configureBeforeDownload,\n                        onClick = {\n                            configureBeforeDownload = !configureBeforeDownload\n                            PreferenceUtil.updateValue(CONFIGURE, configureBeforeDownload)\n                        },\n                    )\n                }\n\n                item {\n                    var thumbnailSwitch by remember { mutableStateOf(THUMBNAIL.getBoolean()) }\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.create_thumbnail),\n                        description = stringResource(id = R.string.create_thumbnail_summary),\n                        enabled = !isCustomCommandEnabled,\n                        icon = Icons.Outlined.Image,\n                        isChecked = thumbnailSwitch,\n                        onClick = {\n                            thumbnailSwitch = !thumbnailSwitch\n                            PreferenceUtil.updateValue(THUMBNAIL, thumbnailSwitch)\n                        },\n                    )\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(R.string.print_details),\n                        description = stringResource(R.string.print_details_desc),\n                        icon =\n                            if (displayErrorReport) Icons.Outlined.Print\n                            else Icons.Outlined.PrintDisabled,\n                        enabled = !isCustomCommandEnabled,\n                        onClick = {\n                            displayErrorReport = !displayErrorReport\n                            PreferenceUtil.updateValue(DEBUG, displayErrorReport)\n                        },\n                        isChecked = displayErrorReport,\n                    )\n                }\n\n                item { PreferenceSubtitle(text = stringResource(id = R.string.privacy)) }\n\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(R.string.private_mode),\n                        description = stringResource(R.string.private_mode_desc),\n                        icon =\n                            if (isPrivateModeEnabled) Icons.Outlined.HistoryToggleOff\n                            else Icons.Outlined.History,\n                        isChecked = isPrivateModeEnabled,\n                        enabled = !isCustomCommandEnabled,\n                        onClick = {\n                            isPrivateModeEnabled = !isPrivateModeEnabled\n                            PreferenceUtil.updateValue(PRIVATE_MODE, isPrivateModeEnabled)\n                        },\n                    )\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(R.string.disable_preview),\n                        description = stringResource(R.string.disable_preview_desc),\n                        icon =\n                            if (isPreviewDisabled) Icons.Outlined.VisibilityOff\n                            else Icons.Outlined.Visibility,\n                        isChecked = isPreviewDisabled,\n                        enabled = !isCustomCommandEnabled,\n                        onClick = {\n                            isPreviewDisabled = !isPreviewDisabled\n                            PreferenceUtil.updateValue(DISABLE_PREVIEW, isPreviewDisabled)\n                        },\n                    )\n                }\n\n                item { PreferenceSubtitle(text = stringResource(R.string.advanced_settings)) }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(id = R.string.download_playlist),\n                        onClick = {\n                            downloadPlaylist = !downloadPlaylist\n                            PreferenceUtil.updateValue(PLAYLIST, downloadPlaylist)\n                        },\n                        icon = Icons.Outlined.PlaylistAddCheck,\n                        enabled = !isCustomCommandEnabled,\n                        description = stringResource(R.string.download_playlist_desc),\n                        isChecked = downloadPlaylist,\n                    )\n                }\n\n                item {\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(id = R.string.download_archive),\n                        onClick = {\n                            scope.launch(Dispatchers.IO) {\n                                archiveFileContent = context.getArchiveFile().readText()\n                                withContext(Dispatchers.Main) { showClearArchiveDialog = true }\n                            }\n                        },\n                        icon = Icons.Outlined.Archive,\n                        description = stringResource(R.string.download_archive_desc),\n                        isChecked = useDownloadArchive,\n                        onChecked = {\n                            useDownloadArchive = !useDownloadArchive\n                            DOWNLOAD_ARCHIVE.updateBoolean(useDownloadArchive)\n                        },\n                        enabled = isPermissionGranted,\n                    )\n                }\n\n                item {\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(R.string.sponsorblock),\n                        description = stringResource(R.string.sponsorblock_desc),\n                        icon = Icons.Outlined.MoneyOff,\n                        enabled = !isCustomCommandEnabled,\n                        isChecked = isSponsorBlockEnabled,\n                        onChecked = {\n                            isSponsorBlockEnabled = !isSponsorBlockEnabled\n                            PreferenceUtil.updateValue(SPONSORBLOCK, isSponsorBlockEnabled)\n                        },\n                        onClick = { showSponsorBlockDialog = true },\n                    )\n                }\n\n                if (downloadSubtitle)\n                    item {\n                        PreferenceInfo(text = stringResource(id = R.string.subtitle_sponsorblock))\n                    }\n            }\n        },\n    )\n    if (showSponsorBlockDialog) {\n        SponsorBlockDialog { showSponsorBlockDialog = false }\n    }\n    if (showYtdlpDialog) {\n        YtdlpUpdateChannelDialog(onDismissRequest = { showYtdlpDialog = false })\n    }\n    if (showClearArchiveDialog) {\n        DownloadArchiveDialog(\n            archiveFileContent = archiveFileContent,\n            onDismissRequest = { showClearArchiveDialog = false },\n        ) { content ->\n            scope.launch(Dispatchers.IO) {\n                runCatching { context.getArchiveFile().writeText(content) }\n            }\n        }\n    }\n\n    if (showNotificationDialog) {\n        NotificationPermissionDialog(\n            onDismissRequest = { showNotificationDialog = false },\n            onPermissionGranted = {\n                notificationPermission?.launchPermissionRequest()\n                NOTIFICATION.updateBoolean(true)\n                downloadNotification = true\n                showNotificationDialog = false\n            },\n        )\n    }\n}\n\n@Composable\nprivate fun DialogSingleChoiceItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    selected: Boolean,\n    label: String,\n    labelContainerColor: Color = MaterialTheme.colorScheme.primary,\n    onClick: () -> Unit,\n) {\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .selectable(selected = selected, enabled = true, onClick = onClick)\n                .padding(horizontal = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n        horizontalArrangement = Arrangement.Start,\n    ) {\n        RadioButton(\n            modifier = Modifier.clearAndSetSemantics {},\n            selected = selected,\n            onClick = onClick,\n        )\n\n        Text(text = text, style = MaterialTheme.typography.bodyLarge)\n        Spacer(modifier = Modifier.weight(1f))\n        Surface(modifier.padding(end = 12.dp), shape = CircleShape, color = labelContainerColor) {\n            Text(\n                modifier = Modifier.padding(4.dp),\n                text = label,\n                color = MaterialTheme.colorScheme.contentColorFor(labelContainerColor),\n                style = MaterialTheme.typography.labelSmall,\n            )\n        }\n    }\n}\n\n@Composable\nfun DialogCheckBoxItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    checked: Boolean,\n    onValueChange: (Boolean) -> Unit,\n) {\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .toggleable(value = checked, enabled = true, onValueChange = onValueChange)\n                .padding(horizontal = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        Checkbox(\n            modifier = Modifier.clearAndSetSemantics {},\n            checked = checked,\n            onCheckedChange = onValueChange,\n        )\n        Text(\n            modifier = Modifier.weight(1f),\n            text = text,\n            style = MaterialTheme.typography.bodyMedium,\n        )\n    }\n}\n\n@Composable\nprivate fun UpdateProgressIndicator() {\n    CircularProgressIndicator(\n        modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp).padding(2.dp)\n    )\n}\n\n@Composable\nfun DownloadArchiveDialog(\n    archiveFileContent: String,\n    onDismissRequest: () -> Unit,\n    onSaveChangesCallback: (String) -> Unit,\n) {\n    var editContent by remember { mutableStateOf(archiveFileContent) }\n\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton(text = stringResource(id = R.string.save)) {\n                onSaveChangesCallback(editContent)\n                onDismissRequest()\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        icon = { Icon(imageVector = Icons.Outlined.Edit, contentDescription = null) },\n        title = { Text(text = stringResource(id = R.string.edit_file)) },\n        text = {\n            Column(modifier = Modifier.padding(horizontal = 24.dp)) {\n                val textStyle =\n                    MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace)\n\n                OutlinedTextField(\n                    label = { Text(text = \"archive.txt\") },\n                    value = editContent,\n                    onValueChange = { str -> editContent = str },\n                    textStyle = textStyle,\n                    minLines = 10,\n                    maxLines = 10,\n                )\n            }\n        },\n    )\n}\n\n@Composable\n@Preview\nfun DownloadArchiveDialogPreview() {\n    val strs = buildList { repeat(20) { add(\"youtube IPf4AxotvNU\") } }\n    val str = strs.fold(initial = \"\") { acc, text -> acc + text + \"\\n\" }\n    DownloadArchiveDialog(archiveFileContent = str, onDismissRequest = {}) {}\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/general/YtdlpUpdateDialog.kt",
    "content": "package com.junkfood.seal.ui.page.settings.general\n\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.selectable\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.SyncAlt\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.ExposedDropdownMenuAnchorType\nimport androidx.compose.material3.ExposedDropdownMenuBox\nimport androidx.compose.material3.ExposedDropdownMenuDefaults\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.RadioButton\nimport androidx.compose.material3.Surface\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.contentColorFor\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableLongStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.common.intState\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.util.PreferenceStrings.getUpdateIntervalText\nimport com.junkfood.seal.util.PreferenceUtil.getLong\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.PreferenceUtil.updateLong\nimport com.junkfood.seal.util.UpdateIntervalList\nimport com.junkfood.seal.util.YT_DLP_AUTO_UPDATE\nimport com.junkfood.seal.util.YT_DLP_NIGHTLY\nimport com.junkfood.seal.util.YT_DLP_STABLE\nimport com.junkfood.seal.util.YT_DLP_UPDATE_CHANNEL\nimport com.junkfood.seal.util.YT_DLP_UPDATE_INTERVAL\nimport kotlin.collections.component1\nimport kotlin.collections.component2\nimport kotlin.collections.iterator\n\n@Composable\nprivate fun DialogSingleChoiceItem(\n    modifier: Modifier = Modifier,\n    text: String,\n    selected: Boolean,\n    label: String,\n    labelContainerColor: Color = MaterialTheme.colorScheme.primary,\n    onClick: () -> Unit,\n) {\n    Row(\n        modifier =\n            modifier\n                .fillMaxWidth()\n                .selectable(selected = selected, enabled = true, onClick = onClick)\n                .padding(horizontal = 12.dp),\n        verticalAlignment = Alignment.CenterVertically,\n        horizontalArrangement = Arrangement.Start,\n    ) {\n        RadioButton(\n            modifier = Modifier.clearAndSetSemantics {},\n            selected = selected,\n            onClick = onClick,\n        )\n\n        Text(text = text, style = MaterialTheme.typography.bodyLarge)\n        Spacer(modifier = Modifier.weight(1f))\n        Surface(modifier.padding(end = 12.dp), shape = CircleShape, color = labelContainerColor) {\n            Text(\n                modifier = Modifier.padding(4.dp),\n                text = label,\n                color = MaterialTheme.colorScheme.contentColorFor(labelContainerColor),\n                style = MaterialTheme.typography.labelSmall,\n            )\n        }\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun YtdlpUpdateChannelDialog(modifier: Modifier = Modifier, onDismissRequest: () -> Unit) {\n    var ytdlpUpdateChannel by YT_DLP_UPDATE_CHANNEL.intState\n    var ytdlpAutoUpdate by YT_DLP_AUTO_UPDATE.booleanState\n    var updateInterval by remember { mutableLongStateOf(YT_DLP_UPDATE_INTERVAL.getLong()) }\n\n    SealDialog(\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton {\n                YT_DLP_AUTO_UPDATE.updateBoolean(ytdlpAutoUpdate)\n                YT_DLP_UPDATE_CHANNEL.updateInt(ytdlpUpdateChannel)\n                YT_DLP_UPDATE_INTERVAL.updateLong(updateInterval)\n                onDismissRequest()\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        title = { Text(text = stringResource(id = R.string.update)) },\n        icon = { Icon(Icons.Outlined.SyncAlt, null) },\n        text = {\n            LazyColumn() {\n                item {\n                    Text(\n                        text = stringResource(id = R.string.update_channel),\n                        modifier =\n                            Modifier.fillMaxWidth()\n                                .padding(horizontal = 24.dp)\n                                .padding(top = 16.dp, bottom = 8.dp),\n                        color = MaterialTheme.colorScheme.primary,\n                        style = MaterialTheme.typography.labelLarge,\n                    )\n                }\n                item {\n                    DialogSingleChoiceItem(\n                        text = \"yt-dlp\",\n                        selected = ytdlpUpdateChannel == YT_DLP_STABLE,\n                        label = \"Stable\",\n                    ) {\n                        ytdlpUpdateChannel = YT_DLP_STABLE\n                    }\n                }\n                item {\n                    DialogSingleChoiceItem(\n                        text = \"yt-dlp-nightly-builds\",\n                        selected = ytdlpUpdateChannel == YT_DLP_NIGHTLY,\n                        label = \"Nightly\",\n                        labelContainerColor = MaterialTheme.colorScheme.tertiary,\n                    ) {\n                        ytdlpUpdateChannel = YT_DLP_NIGHTLY\n                    }\n                }\n                item {\n                    Text(\n                        text = stringResource(id = R.string.additional_settings),\n                        modifier =\n                            Modifier.fillMaxWidth()\n                                .padding(horizontal = 24.dp)\n                                .padding(top = 16.dp, bottom = 16.dp),\n                        color = MaterialTheme.colorScheme.primary,\n                        style = MaterialTheme.typography.labelLarge,\n                    )\n                }\n                item {\n                    var expanded by remember { mutableStateOf(false) }\n\n                    ExposedDropdownMenuBox(\n                        modifier = Modifier.padding(horizontal = 20.dp),\n                        expanded = expanded,\n                        onExpandedChange = { expanded = it },\n                    ) {\n                        OutlinedTextField(\n                            value =\n                                if (!ytdlpAutoUpdate) stringResource(id = R.string.disabled)\n                                else getUpdateIntervalText(updateInterval),\n                            onValueChange = {},\n                            label = { Text(text = stringResource(id = R.string.auto_update)) },\n                            readOnly = true,\n                            modifier =\n                                Modifier.fillMaxWidth()\n                                    .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),\n                            colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),\n                            trailingIcon = {\n                                ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)\n                            },\n                        )\n                        ExposedDropdownMenu(\n                            modifier = Modifier.verticalScroll(rememberScrollState()),\n                            expanded = expanded,\n                            onDismissRequest = { expanded = false },\n                        ) {\n                            DropdownMenuItem(\n                                text = { Text(stringResource(id = R.string.disabled)) },\n                                onClick = {\n                                    ytdlpAutoUpdate = false\n                                    expanded = false\n                                },\n                            )\n                            for ((interval, stringId) in UpdateIntervalList) {\n                                DropdownMenuItem(\n                                    text = { Text(text = stringResource(id = stringId)) },\n                                    onClick = {\n                                        ytdlpAutoUpdate = true\n                                        updateInterval = interval\n                                        expanded = false\n                                    },\n                                )\n                            }\n                        }\n                    }\n                }\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/interaction/InteractionPreferencePage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.interaction\n\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.res.stringResource\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.util.DOWNLOAD_TYPE_INITIALIZATION\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.junkfood.seal.util.PreferenceUtil.updateInt\nimport com.junkfood.seal.util.USE_PREVIOUS_SELECTION\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun InteractionPreferencePage(modifier: Modifier = Modifier, onBack: () -> Unit) {\n    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()\n\n    var showDownloadTypeDialog by remember { mutableStateOf(false) }\n    val initialType by\n        remember(showDownloadTypeDialog) {\n            mutableIntStateOf(DOWNLOAD_TYPE_INITIALIZATION.getInt())\n        }\n\n    Scaffold(\n        modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(text = stringResource(id = R.string.interface_and_interaction)) },\n                scrollBehavior = scrollBehavior,\n                navigationIcon = { BackButton(onClick = onBack) },\n            )\n        },\n    ) {\n        LazyColumn(modifier = Modifier, contentPadding = it) {\n            item {\n                PreferenceSubtitle(text = stringResource(id = R.string.settings_before_download))\n            }\n\n            item {\n                PreferenceItem(\n                    title = stringResource(id = R.string.download_type),\n                    description =\n                        when (initialType) {\n                            USE_PREVIOUS_SELECTION ->\n                                stringResource(id = R.string.use_previous_selection)\n                            else -> stringResource(id = R.string.none)\n                        },\n                ) {\n                    showDownloadTypeDialog = true\n                }\n            }\n        }\n    }\n\n    if (showDownloadTypeDialog) {\n        DownloadTypeCustomizationDialog(\n            onDismissRequest = { showDownloadTypeDialog = false },\n            selectedItem = initialType,\n        ) {\n            DOWNLOAD_TYPE_INITIALIZATION.updateInt(it)\n            showDownloadTypeDialog = false\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/interaction/InterfaceCustomizationDialogs.kt",
    "content": "package com.junkfood.seal.ui.page.settings.interaction\n\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.DialogSingleChoiceItem\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.util.NONE\nimport com.junkfood.seal.util.USE_PREVIOUS_SELECTION\n\n@Composable\nfun DownloadTypeCustomizationDialog(\n    modifier: Modifier = Modifier,\n    onDismissRequest: () -> Unit,\n    selectedItem: Int,\n    onSelect: (Int) -> Unit,\n) {\n    SealDialog(\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        confirmButton = null,\n        title = { Text(text = stringResource(id = R.string.download_type)) },\n        text = {\n            LazyColumn(modifier = Modifier.padding()) {\n                item {\n                    DialogSingleChoiceItem(\n                        text = stringResource(id = R.string.use_previous_selection),\n                        selected = selectedItem == USE_PREVIOUS_SELECTION,\n                    ) {\n                        onSelect(USE_PREVIOUS_SELECTION)\n                    }\n                }\n\n                item {\n                    DialogSingleChoiceItem(\n                        text = stringResource(id = R.string.none),\n                        selected = selectedItem == NONE,\n                    ) {\n                        onSelect(NONE)\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Preview\n@Composable\nprivate fun Preview() {\n    DownloadTypeCustomizationDialog(onDismissRequest = {}, selectedItem = NONE) {}\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/network/CookieProfilesPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.network\n\nimport android.content.res.Configuration\nimport android.webkit.CookieManager\nimport androidx.activity.compose.rememberLauncherForActivityResult\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.clickable\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.items\nimport androidx.compose.foundation.lazy.itemsIndexed\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.toggleable\nimport androidx.compose.foundation.shape.CircleShape\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.foundation.verticalScroll\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Add\nimport androidx.compose.material.icons.outlined.Cookie\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material.icons.outlined.DeleteForever\nimport androidx.compose.material.icons.outlined.FileCopy\nimport androidx.compose.material.icons.outlined.GeneratingTokens\nimport androidx.compose.material.icons.outlined.HelpOutline\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.Checkbox\nimport androidx.compose.material3.DropdownMenu\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.DisposableEffect\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.collectAsState\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.clearAndSetSemantics\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.text.style.LineBreak\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CookieProfile\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DialogSwitchItem\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.HelpDialog\nimport com.junkfood.seal.ui.component.PasteFromClipBoardButton\nimport com.junkfood.seal.ui.component.PreferenceItemVariant\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithContainer\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.TextButtonWithIcon\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.ui.theme.generateLabelColor\nimport com.junkfood.seal.util.COOKIES\nimport com.junkfood.seal.util.DownloadUtil\nimport com.junkfood.seal.util.DownloadUtil.toCookiesFileContent\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.FileUtil.getCookiesFile\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.USER_AGENT\nimport com.junkfood.seal.util.matchUrlFromClipboard\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun CookieProfilePage(\n    cookiesViewModel: CookiesViewModel,\n    navigateToCookieGeneratorPage: () -> Unit = {},\n    onNavigateBack: () -> Unit = {},\n) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n    val cookies = cookiesViewModel.cookiesFlow.collectAsState(emptyList()).value\n    val scope = rememberCoroutineScope()\n    val hapticFeedback = LocalHapticFeedback.current\n    val context = LocalContext.current\n    val clipboardManager = LocalClipboardManager.current\n    val state by cookiesViewModel.stateFlow.collectAsStateWithLifecycle()\n    var showClearCookieDialog by remember { mutableStateOf(false) }\n    var isCookieEnabled by remember { mutableStateOf(COOKIES.getBoolean()) }\n    val cookieManager = CookieManager.getInstance()\n    var showHelpDialog by remember { mutableStateOf(false) }\n    val view = LocalView.current\n\n    var cookieList by remember { mutableStateOf(listOf<Cookie>()) }\n\n    var shouldUpdateCookies by remember { mutableStateOf(false) }\n\n    var showEditDialog by remember { mutableStateOf(false) }\n    var showDeleteDialog by remember { mutableStateOf(false) }\n\n    DisposableEffect(shouldUpdateCookies) {\n        scope.launch(Dispatchers.IO) {\n            DownloadUtil.getCookieListFromDatabase().getOrNull()?.let {\n                cookieList = it\n                FileUtil.writeContentToFile(it.toCookiesFileContent(), context.getCookiesFile())\n            }\n        }\n        onDispose { shouldUpdateCookies = false }\n    }\n\n    val exportLauncher =\n        rememberLauncherForActivityResult(\n            contract = ActivityResultContracts.CreateDocument(\"text/plain\")\n        ) { uri ->\n            uri?.let {\n                scope.launch(Dispatchers.IO) {\n                    context.contentResolver.openOutputStream(uri)?.use {\n                        it.write(cookieList.toCookiesFileContent().toByteArray())\n                    }\n                }\n            }\n        }\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(modifier = Modifier, text = stringResource(id = R.string.cookies)) },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                actions = {\n                    var expanded by remember { mutableStateOf(false) }\n                    IconButton(onClick = { showHelpDialog = true }) {\n                        Icon(\n                            imageVector = Icons.Outlined.HelpOutline,\n                            contentDescription = stringResource(R.string.how_does_it_work),\n                        )\n                    }\n                    IconButton(onClick = { expanded = true }) {\n                        Icon(\n                            Icons.Outlined.MoreVert,\n                            contentDescription = stringResource(R.string.show_more_actions),\n                        )\n                    }\n                    DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {\n                        var userAgent by USER_AGENT.booleanState\n                        fun toggleUserAgent(boolean: Boolean = !userAgent) {\n                            expanded = false\n                            userAgent = boolean\n                            USER_AGENT.updateBoolean(boolean)\n                        }\n                        DropdownMenuItem(\n                            modifier =\n                                Modifier.toggleable(\n                                    value = userAgent,\n                                    onValueChange = ::toggleUserAgent,\n                                ),\n                            leadingIcon = {\n                                Checkbox(\n                                    checked = userAgent,\n                                    onCheckedChange = null,\n                                    modifier = Modifier.clearAndSetSemantics {},\n                                )\n                            },\n                            text = { Text(stringResource(id = R.string.ua_header)) },\n                            onClick = ::toggleUserAgent,\n                        )\n                        DropdownMenuItem(\n                            leadingIcon = { Icon(Icons.Outlined.FileCopy, null) },\n                            text = { Text(stringResource(id = R.string.export_to_file)) },\n                            enabled = cookieList.isNotEmpty(),\n                            onClick = {\n                                expanded = false\n                                exportLauncher.launch(\n                                    \"cookies_exported${System.currentTimeMillis()}.txt\"\n                                )\n                            },\n                        )\n                        DropdownMenuItem(\n                            leadingIcon = { Icon(Icons.Outlined.DeleteForever, null) },\n                            text = { Text(stringResource(id = R.string.clear_all_cookies)) },\n                            onClick = {\n                                expanded = false\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                                showClearCookieDialog = true\n                            },\n                        )\n                    }\n                },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n    ) { paddingValues ->\n        LazyColumn(modifier = Modifier, contentPadding = paddingValues) {\n            item {\n                PreferenceSwitchWithContainer(\n                    title = stringResource(R.string.use_cookies),\n                    icon = null,\n                    isChecked = isCookieEnabled,\n                    onClick = {\n                        if (isCookieEnabled) {\n                            isCookieEnabled = false\n                            COOKIES.updateBoolean(false)\n                        } else if (\n                            (cookies.isEmpty() || !cookieManager.hasCookies()) && !isCookieEnabled\n                        ) {\n                            showHelpDialog = true\n                        } else {\n                            isCookieEnabled = true\n                            COOKIES.updateBoolean(true)\n                        }\n                    },\n                )\n            }\n            itemsIndexed(cookies) { _, item ->\n                PreferenceItemVariant(\n                    modifier = Modifier.padding(vertical = 4.dp),\n                    title = item.url,\n                    onClick = {\n                        cookiesViewModel.setEditingProfile(item)\n                        showEditDialog = true\n                    },\n                    onClickLabel = stringResource(id = R.string.edit),\n                    onLongClick = {\n                        hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                        cookiesViewModel.setEditingProfile(item)\n                        showDeleteDialog = true\n                    },\n                    onLongClickLabel = stringResource(R.string.remove),\n                )\n            }\n\n            item {\n                PreferenceItemVariant(\n                    title = stringResource(id = R.string.generate_new_cookies),\n                    icon = Icons.Outlined.Add,\n                ) {\n                    cookiesViewModel.setEditingProfile()\n                    showEditDialog = true\n                }\n            }\n            item {\n                androidx.compose.material3.HorizontalDivider()\n                val cookiesCount = cookieList.size\n                val siteCount = cookieList.distinctBy { it.domain }.size\n                Text(\n                    text = stringResource(R.string.cookies_in_database, cookiesCount, siteCount),\n                    style = MaterialTheme.typography.bodySmall,\n                    modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),\n                    color = MaterialTheme.colorScheme.onSurfaceVariant,\n                )\n            }\n        }\n    }\n    if (showEditDialog) {\n        CookieGeneratorDialog(\n            cookiesViewModel = cookiesViewModel,\n            navigateToCookieGeneratorPage = {\n                cookiesViewModel.updateCookieProfile()\n                navigateToCookieGeneratorPage()\n            },\n        ) {\n            showEditDialog = false\n            shouldUpdateCookies = true\n        }\n    }\n\n    if (showDeleteDialog) {\n        DeleteCookieDialog(cookiesViewModel) { showDeleteDialog = false }\n    }\n\n    if (showHelpDialog) {\n        HelpDialog(\n            text = stringResource(id = R.string.cookies_usage_msg),\n            onDismissRequest = { showHelpDialog = false },\n        )\n    }\n    if (showClearCookieDialog) {\n        ClearCookiesDialog(onDismissRequest = { showClearCookieDialog = false }) {\n            view.slightHapticFeedback()\n            scope\n                .launch(Dispatchers.IO) { CookieManager.getInstance().removeAllCookies(null) }\n                .invokeOnCompletion { shouldUpdateCookies = true }\n        }\n    }\n}\n\n@Composable\nfun CookieGeneratorDialog(\n    cookiesViewModel: CookiesViewModel,\n    navigateToCookieGeneratorPage: () -> Unit = {},\n    onDismissRequest: () -> Unit,\n) {\n\n    val state by cookiesViewModel.stateFlow.collectAsStateWithLifecycle()\n    val profile = state.editingCookieProfile\n    val url = profile.url\n\n    LaunchedEffect(Unit) { withContext(Dispatchers.IO) { CookieManager.getInstance().flush() } }\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        icon = { Icon(Icons.Outlined.Cookie, null) },\n        title = { Text(stringResource(R.string.cookies)) },\n        text = {\n            Column(Modifier.verticalScroll(rememberScrollState())) {\n                OutlinedTextField(\n                    modifier = Modifier.fillMaxWidth().padding(bottom = 12.dp),\n                    value = url,\n                    label = { Text(\"URL\") },\n                    onValueChange = { cookiesViewModel.updateUrl(it) },\n                    trailingIcon = {\n                        PasteFromClipBoardButton {\n                            cookiesViewModel.updateUrl(matchUrlFromClipboard(it))\n                        }\n                    },\n                    maxLines = 1,\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                )\n\n                TextButtonWithIcon(\n                    onClick = { navigateToCookieGeneratorPage() },\n                    icon = Icons.Outlined.GeneratingTokens,\n                    text = stringResource(id = R.string.generate_new_cookies),\n                )\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = {\n            ConfirmButton(enabled = url.isNotEmpty()) {\n                cookiesViewModel.updateCookieProfile()\n                onDismissRequest()\n            }\n        },\n    )\n}\n\n@Composable\nfun DeleteCookieDialog(cookiesViewModel: CookiesViewModel, onDismissRequest: () -> Unit = {}) {\n    val state by cookiesViewModel.stateFlow.collectAsState()\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(stringResource(R.string.remove)) },\n        text = {\n            Text(\n                stringResource(R.string.remove_cookie_profile_desc)\n                    .format(state.editingCookieProfile.url),\n                style = LocalTextStyle.current.copy(lineBreak = LineBreak.Paragraph),\n            )\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = {\n            ConfirmButton {\n                cookiesViewModel.deleteCookieProfile()\n                onDismissRequest()\n            }\n        },\n        icon = { Icon(Icons.Outlined.Delete, null) },\n    )\n}\n\n@Composable\nfun ClearCookiesDialog(onDismissRequest: () -> Unit = {}, onConfirm: () -> Unit) {\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(stringResource(R.string.clear_all_cookies)) },\n        text = {\n            Text(\n                stringResource(R.string.clear_all_cookies_desc),\n                style = MaterialTheme.typography.bodyLarge,\n            )\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = {\n            ConfirmButton {\n                onConfirm()\n                onDismissRequest()\n            }\n        },\n        icon = { Icon(Icons.Outlined.DeleteForever, null) },\n    )\n}\n\n@Composable\nfun CookiesQuickSettingsDialog(\n    onDismissRequest: () -> Unit = {},\n    onConfirm: () -> Unit = {},\n    cookieProfiles: List<CookieProfile> = emptyList(),\n    onCookieProfileClicked: (CookieProfile) -> Unit = {},\n    isCookiesEnabled: Boolean = false,\n    onCookiesToggled: (Boolean) -> Unit = {},\n) {\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            ConfirmButton(\n                text = stringResource(id = androidx.appcompat.R.string.abc_action_mode_done)\n            ) {\n                onDismissRequest()\n                onConfirm()\n            }\n        },\n        icon = { Icon(imageVector = Icons.Outlined.Cookie, contentDescription = null) },\n        title = {\n            Text(text = stringResource(id = R.string.cookies), textAlign = TextAlign.Center)\n        },\n        text = {\n            Column {\n                Text(\n                    text = stringResource(id = R.string.refresh_cookies_desc),\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                    //                    style = MaterialTheme.typography.labelLarge,\n                )\n                Spacer(modifier = Modifier.height(12.dp))\n                androidx.compose.material3.HorizontalDivider(\n                    modifier = Modifier.padding(horizontal = 24.dp)\n                )\n                Spacer(modifier = Modifier.height(4.dp))\n                LazyColumn() {\n                    items(items = cookieProfiles) {\n                        Row(\n                            modifier =\n                                Modifier.fillMaxWidth()\n                                    .clickable { onCookieProfileClicked(it) }\n                                    .padding(horizontal = 24.dp, vertical = 12.dp),\n                            verticalAlignment = Alignment.CenterVertically,\n                        ) {\n                            Box(\n                                modifier =\n                                    Modifier.padding(end = 12.dp)\n                                        .size(16.dp)\n                                        .background(\n                                            color = it.url.hashCode().generateLabelColor(),\n                                            shape = CircleShape,\n                                        )\n                                        .clearAndSetSemantics {}\n                            ) {}\n                            Text(\n                                text = it.url\n                                //                                , style =\n                                // MaterialTheme.typography.labelLarge\n                                ,\n                                modifier = Modifier.weight(1f),\n                            )\n                        }\n                    }\n                }\n                Spacer(modifier = Modifier.height(4.dp))\n                androidx.compose.material3.HorizontalDivider(\n                    modifier = Modifier.padding(horizontal = 24.dp)\n                )\n                DialogSwitchItem(\n                    text = stringResource(id = R.string.use_cookies),\n                    value = isCookiesEnabled,\n                    onValueChange = onCookiesToggled,\n                )\n            }\n        },\n    )\n}\n\n@Preview\n@Preview(name = \"Dark Mode\", uiMode = Configuration.UI_MODE_NIGHT_YES)\n@Composable\nprivate fun CookiesQuickSettingsDialogPreview() {\n    SealTheme {\n        var isCookiesEnabled by remember { mutableStateOf(false) }\n        CookiesQuickSettingsDialog(\n            cookieProfiles =\n                mutableListOf<CookieProfile>().apply {\n                    repeat(4) {\n                        add(\n                            CookieProfile(id = it, url = \"https://www.example$it.com\", content = \"\")\n                        )\n                    }\n                },\n            isCookiesEnabled = isCookiesEnabled,\n            onCookiesToggled = { isCookiesEnabled = it },\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/network/CookiesViewModel.kt",
    "content": "package com.junkfood.seal.ui.page.settings.network\n\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.junkfood.seal.database.objects.CookieProfile\nimport com.junkfood.seal.util.DatabaseUtil\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.asStateFlow\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\n\nclass CookiesViewModel : ViewModel() {\n    companion object {\n        const val NEW_PROFILE_ID = 0\n    }\n\n    data class ViewState(\n        val editingCookieProfile: CookieProfile =\n            CookieProfile(id = NEW_PROFILE_ID, url = \"\", content = \"\")\n    )\n\n    val cookiesFlow = DatabaseUtil.getCookiesFlow()\n\n    private val mutableStateFlow = MutableStateFlow(ViewState())\n    val stateFlow = mutableStateFlow.asStateFlow()\n    private val state\n        get() = stateFlow.value\n\n    fun setEditingProfile(\n        cookieProfile: CookieProfile =\n            CookieProfile(id = NEW_PROFILE_ID, url = \"https://\", content = \"\")\n    ) {\n        mutableStateFlow.update { it.copy(editingCookieProfile = cookieProfile) }\n    }\n\n    fun deleteCookieProfile(cookieProfile: CookieProfile = state.editingCookieProfile) {\n        viewModelScope.launch(Dispatchers.IO) { DatabaseUtil.deleteCookieProfile(cookieProfile) }\n    }\n\n    fun generateNewCookies(content: String) {\n        viewModelScope.launch(Dispatchers.IO) {\n            mutableStateFlow.update {\n                val newProfile = it.editingCookieProfile.copy(content = content)\n                DatabaseUtil.updateCookieProfile(newProfile)\n                it.copy(editingCookieProfile = newProfile)\n            }\n        }\n    }\n\n    fun updateUrl(url: String) {\n        setEditingProfile(cookieProfile = state.editingCookieProfile.copy(url = url))\n    }\n\n    fun updateContent(content: String) =\n        mutableStateFlow.update {\n            it.copy(editingCookieProfile = it.editingCookieProfile.copy(content = content))\n        }\n\n    fun updateCookieProfile(profile: CookieProfile = state.editingCookieProfile) {\n        viewModelScope.launch(Dispatchers.IO) {\n            if (profile.id == NEW_PROFILE_ID) {\n                DatabaseUtil.insertCookieProfile(profile)\n            } else {\n                DatabaseUtil.updateCookieProfile(profile)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/network/NetworkPreferences.kt",
    "content": "package com.junkfood.seal.ui.page.settings.network\n\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Bolt\nimport androidx.compose.material.icons.outlined.Cookie\nimport androidx.compose.material.icons.outlined.OfflineBolt\nimport androidx.compose.material.icons.outlined.SettingsEthernet\nimport androidx.compose.material.icons.outlined.SignalCellular4Bar\nimport androidx.compose.material.icons.outlined.SignalCellularConnectedNoInternet4Bar\nimport androidx.compose.material.icons.outlined.Speed\nimport androidx.compose.material.icons.outlined.VpnKey\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.res.stringResource\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.component.PreferenceSwitchWithDivider\nimport com.junkfood.seal.util.ARIA2C\nimport com.junkfood.seal.util.CELLULAR_DOWNLOAD\nimport com.junkfood.seal.util.COOKIES\nimport com.junkfood.seal.util.CUSTOM_COMMAND\nimport com.junkfood.seal.util.FORCE_IPV4\nimport com.junkfood.seal.util.PROXY\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.PreferenceUtil.updateValue\nimport com.junkfood.seal.util.RATE_LIMIT\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun NetworkPreferences(navigateToCookieProfilePage: () -> Unit = {}, onNavigateBack: () -> Unit) {\n    val scrollBehavior =\n        TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n            rememberTopAppBarState(),\n            canScroll = { true },\n        )\n\n    var showConcurrentDownloadDialog by remember { mutableStateOf(false) }\n    var showRateLimitDialog by remember { mutableStateOf(false) }\n    var showProxyDialog by remember { mutableStateOf(false) }\n    var aria2c by remember { mutableStateOf(ARIA2C.getBoolean()) }\n    var proxy by PROXY.booleanState\n    var isCookiesEnabled by COOKIES.booleanState\n    var forceIpv4 by FORCE_IPV4.booleanState\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = { Text(modifier = Modifier, text = stringResource(id = R.string.network)) },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        content = {\n            val isCustomCommandEnabled by CUSTOM_COMMAND.booleanState\n\n            LazyColumn(contentPadding = it) {\n                if (isCustomCommandEnabled)\n                    item {\n                        PreferenceInfo(\n                            text = stringResource(id = R.string.custom_command_enabled_hint)\n                        )\n                    }\n                item { PreferenceSubtitle(text = stringResource(R.string.general_settings)) }\n                item {\n                    var isRateLimitEnabled by remember { mutableStateOf(RATE_LIMIT.getBoolean()) }\n\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(R.string.rate_limit),\n                        description = stringResource(R.string.rate_limit_desc),\n                        icon = Icons.Outlined.Speed,\n                        enabled = !isCustomCommandEnabled,\n                        isChecked = isRateLimitEnabled,\n                        onChecked = {\n                            isRateLimitEnabled = !isRateLimitEnabled\n                            updateValue(RATE_LIMIT, isRateLimitEnabled)\n                        },\n                        onClick = { showRateLimitDialog = true },\n                    )\n                }\n                item {\n                    var isDownloadWithCellularEnabled by remember {\n                        mutableStateOf(CELLULAR_DOWNLOAD.getBoolean())\n                    }\n                    PreferenceSwitch(\n                        title = stringResource(R.string.download_with_cellular),\n                        description = stringResource(R.string.download_with_cellular_desc),\n                        icon =\n                            if (isDownloadWithCellularEnabled) Icons.Outlined.SignalCellular4Bar\n                            else Icons.Outlined.SignalCellularConnectedNoInternet4Bar,\n                        isChecked = isDownloadWithCellularEnabled,\n                        onClick = {\n                            isDownloadWithCellularEnabled = !isDownloadWithCellularEnabled\n                            updateValue(CELLULAR_DOWNLOAD, isDownloadWithCellularEnabled)\n                        },\n                    )\n                }\n\n                item { PreferenceSubtitle(text = stringResource(id = R.string.advanced_settings)) }\n\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(R.string.aria2),\n                        icon = Icons.Outlined.Bolt,\n                        description = stringResource(R.string.aria2_desc),\n                        isChecked = aria2c,\n                        onClick = {\n                            aria2c = !aria2c\n                            updateValue(ARIA2C, aria2c)\n                        },\n                    )\n                }\n                item {\n                    PreferenceSwitchWithDivider(\n                        title = stringResource(id = R.string.proxy),\n                        description = stringResource(id = R.string.proxy_desc),\n                        icon = Icons.Outlined.VpnKey,\n                        isChecked = proxy,\n                        onChecked = {\n                            proxy = !proxy\n                            PROXY.updateBoolean(proxy)\n                        },\n                        onClick = { showProxyDialog = true },\n                        enabled = !isCustomCommandEnabled,\n                    )\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(id = R.string.concurrent_download),\n                        description = stringResource(R.string.concurrent_download_desc),\n                        icon = Icons.Outlined.OfflineBolt,\n                        enabled = !aria2c && !isCustomCommandEnabled,\n                    ) {\n                        showConcurrentDownloadDialog = true\n                    }\n                }\n                item {\n                    PreferenceSwitch(\n                        title = stringResource(R.string.force_ipv4),\n                        description = stringResource(id = R.string.force_ipv4_desc),\n                        icon = Icons.Outlined.SettingsEthernet,\n                        enabled = !isCustomCommandEnabled,\n                        isChecked = forceIpv4,\n                    ) {\n                        forceIpv4 = !forceIpv4\n                        FORCE_IPV4.updateBoolean(forceIpv4)\n                    }\n                }\n                item {\n                    PreferenceItem(\n                        title = stringResource(R.string.cookies),\n                        description = stringResource(R.string.cookies_desc),\n                        icon = Icons.Outlined.Cookie,\n                        onClick = { navigateToCookieProfilePage() },\n                    )\n                }\n            }\n        },\n    )\n\n    if (showConcurrentDownloadDialog) {\n        ConcurrentDownloadDialog { showConcurrentDownloadDialog = false }\n    }\n\n    if (showRateLimitDialog) {\n        RateLimitDialog { showRateLimitDialog = false }\n    }\n    if (showProxyDialog) {\n        ProxyConfigurationDialog { showProxyDialog = false }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/network/NetworkSettingDialogs.kt",
    "content": "package com.junkfood.seal.ui.page.settings.network\n\nimport androidx.compose.foundation.interaction.MutableInteractionSource\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.text.KeyboardOptions\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.OfflineBolt\nimport androidx.compose.material.icons.outlined.Speed\nimport androidx.compose.material.icons.outlined.VpnKey\nimport androidx.compose.material3.AlertDialog\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedTextField\nimport androidx.compose.material3.Slider\nimport androidx.compose.material3.SliderDefaults\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableFloatStateOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.ExperimentalComposeUiApi\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalFocusManager\nimport androidx.compose.ui.platform.LocalSoftwareKeyboardController\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.input.ImeAction\nimport androidx.compose.ui.unit.DpSize\nimport androidx.compose.ui.unit.dp\nimport androidx.core.text.isDigitsOnly\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.util.CONCURRENT\nimport com.junkfood.seal.util.MAX_RATE\nimport com.junkfood.seal.util.PROXY_URL\nimport com.junkfood.seal.util.PreferenceUtil\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.isNumberInRange\nimport kotlin.math.roundToInt\n\n@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)\n@Composable\nfun RateLimitDialog(onDismissRequest: () -> Unit) {\n    var isError by remember { mutableStateOf(false) }\n    var maxRate by remember { mutableStateOf(PreferenceUtil.getMaxDownloadRate()) }\n    val focusManager = LocalFocusManager.current\n    val softwareKeyboardController = LocalSoftwareKeyboardController.current\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        icon = { Icon(Icons.Outlined.Speed, null) },\n        title = { Text(stringResource(R.string.rate_limit)) },\n        text = {\n            Column {\n                Text(\n                    stringResource(R.string.rate_limit_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                OutlinedTextField(\n                    modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 12.dp),\n                    isError = isError,\n                    supportingText = {\n                        Text(\n                            text = if (isError) stringResource(R.string.invalid_input) else \"\",\n                            style = MaterialTheme.typography.bodySmall,\n                            color =\n                                if (isError) MaterialTheme.colorScheme.error\n                                else MaterialTheme.colorScheme.onSurfaceVariant,\n                        )\n                    },\n                    value = maxRate,\n                    label = { Text(stringResource(R.string.max_rate)) },\n                    onValueChange = {\n                        if (it.isDigitsOnly()) maxRate = it\n                        isError = false\n                    },\n                    trailingIcon = { Text(\"K\") },\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                )\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = {\n            ConfirmButton {\n                if (maxRate.isNumberInRange(1, 100_0000)) {\n                    PreferenceUtil.encodeString(MAX_RATE, maxRate)\n                    onDismissRequest()\n                } else {\n                    isError = true\n                }\n            }\n        },\n    )\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun ConcurrentDownloadDialog(onDismissRequest: () -> Unit) {\n    var concurrentFragments by remember {\n        mutableFloatStateOf(PreferenceUtil.getConcurrentFragments())\n    }\n    val count by remember {\n        derivedStateOf {\n            if (concurrentFragments <= 0.125f) 1 else ((concurrentFragments * 3f).roundToInt()) * 8\n        }\n    }\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dismiss)) }\n        },\n        confirmButton = {\n            TextButton(\n                onClick = {\n                    onDismissRequest()\n                    PreferenceUtil.encodeInt(CONCURRENT, count)\n                }\n            ) {\n                Text(stringResource(R.string.confirm))\n            }\n        },\n        icon = { Icon(Icons.Outlined.OfflineBolt, null) },\n        title = { Text(stringResource(R.string.concurrent_download)) },\n        text = {\n            Column {\n                val interactionSource = remember { MutableInteractionSource() }\n                Text(text = stringResource(R.string.concurrent_download_num, count))\n\n                Spacer(modifier = Modifier.height(8.dp))\n\n                Slider(\n                    value = concurrentFragments,\n                    onValueChange = { concurrentFragments = it },\n                    steps = 2,\n                    valueRange = 0f..1f,\n                    thumb = {\n                        SliderDefaults.Thumb(\n                            modifier = Modifier,\n                            interactionSource = interactionSource,\n                            thumbSize = DpSize(4.dp, 32.dp),\n                        )\n                    },\n                )\n            }\n        },\n    )\n}\n\n@Composable\nfun ProxyConfigurationDialog(onDismissRequest: () -> Unit = {}) {\n    var proxyUrl by remember { mutableStateOf(PROXY_URL.getString()) }\n    AlertDialog(\n        onDismissRequest = onDismissRequest,\n        icon = { Icon(Icons.Outlined.VpnKey, null) },\n        title = { Text(stringResource(R.string.proxy)) },\n        text = {\n            Column {\n                Text(\n                    stringResource(R.string.proxy_desc),\n                    style = MaterialTheme.typography.bodyLarge,\n                )\n                OutlinedTextField(\n                    modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 24.dp),\n                    value = proxyUrl,\n                    label = { Text(stringResource(R.string.proxy)) },\n                    onValueChange = { proxyUrl = it },\n                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),\n                )\n            }\n        },\n        dismissButton = { DismissButton { onDismissRequest() } },\n        confirmButton = {\n            ConfirmButton {\n                PROXY_URL.updateString(proxyUrl)\n                onDismissRequest()\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/network/WebViewPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.network\n\nimport android.annotation.SuppressLint\nimport android.util.Log\nimport android.webkit.CookieManager\nimport android.webkit.WebResourceRequest\nimport android.webkit.WebView\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Close\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.material3.TopAppBar\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.res.stringResource\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport com.google.accompanist.web.AccompanistWebChromeClient\nimport com.google.accompanist.web.AccompanistWebViewClient\nimport com.google.accompanist.web.WebView\nimport com.google.accompanist.web.rememberWebViewState\nimport com.google.android.material.R\nimport com.junkfood.seal.util.PreferenceUtil.updateString\nimport com.junkfood.seal.util.USER_AGENT_STRING\nimport com.junkfood.seal.util.connectWithDelimiter\n\nprivate const val TAG = \"WebViewPage\"\n\ndata class Cookie(\n    val domain: String = \"\",\n    val name: String = \"\",\n    val value: String = \"\",\n    val includeSubdomains: Boolean = true,\n    val path: String = \"/\",\n    val secure: Boolean = true,\n    val expiry: Long = 0L,\n) {\n    constructor(\n        url: String,\n        name: String,\n        value: String,\n    ) : this(domain = url.toDomain(), name = name, value = value)\n\n    fun toNetscapeCookieString(): String {\n        return connectWithDelimiter(\n            domain,\n            includeSubdomains.toString().uppercase(),\n            path,\n            secure.toString().uppercase(),\n            expiry.toString(),\n            name,\n            value,\n            delimiter = \"\\u0009\",\n        )\n    }\n}\n\nprivate val domainRegex = Regex(\"\"\"http(s)?://(\\w*(www|m|account|sso))?|/.*\"\"\")\n\nprivate fun String.toDomain(): String {\n    return this.replace(domainRegex, \"\")\n}\n\nprivate fun makeCookie(url: String, cookieString: String): Cookie {\n    cookieString.split(\"=\").run {\n        return Cookie(url = url, name = first(), value = last())\n    }\n}\n\n@SuppressLint(\"SetJavaScriptEnabled\")\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun WebViewPage(cookiesViewModel: CookiesViewModel, onDismissRequest: () -> Unit) {\n\n    val state by cookiesViewModel.stateFlow.collectAsStateWithLifecycle()\n    Log.d(TAG, state.editingCookieProfile.url)\n\n    val cookieManager = CookieManager.getInstance()\n    val cookieSet = remember { mutableSetOf<Cookie>() }\n    val websiteUrl = state.editingCookieProfile.url\n    val webViewState = rememberWebViewState(websiteUrl)\n\n    Scaffold(\n        modifier = Modifier.fillMaxSize(),\n        topBar = {\n            TopAppBar(\n                title = { Text(webViewState.pageTitle.toString(), maxLines = 1) },\n                navigationIcon = {\n                    IconButton(onClick = { onDismissRequest() }) {\n                        Icon(\n                            imageVector = Icons.Outlined.Close,\n                            stringResource(id = androidx.appcompat.R.string.abc_action_mode_done),\n                        )\n                    }\n                },\n                actions = {\n                    TextButton(onClick = onDismissRequest) {\n                        Text(text = stringResource(id = R.string.abc_action_mode_done))\n                    }\n                },\n            )\n        },\n    ) { paddingValues ->\n        val webViewClient = remember {\n            object : AccompanistWebViewClient() {\n                override fun onPageFinished(view: WebView, url: String?) {\n                    super.onPageFinished(view, url)\n                    if (url.isNullOrEmpty()) return\n                }\n\n                override fun shouldOverrideUrlLoading(\n                    view: WebView?,\n                    request: WebResourceRequest?,\n                ): Boolean {\n                    return if (request?.url?.scheme?.contains(\"http\") == true)\n                        super.shouldOverrideUrlLoading(view, request)\n                    else true\n                }\n            }\n        }\n        val webViewChromeClient = remember { object : AccompanistWebChromeClient() {} }\n        WebView(\n            state = webViewState,\n            client = webViewClient,\n            chromeClient = webViewChromeClient,\n            modifier = Modifier.padding(paddingValues).fillMaxSize(),\n            captureBackPresses = true,\n            factory = { context ->\n                WebView(context).apply {\n                    settings.run {\n                        javaScriptCanOpenWindowsAutomatically = true\n                        javaScriptEnabled = true\n                        domStorageEnabled = true\n                        USER_AGENT_STRING.updateString(userAgentString)\n                    }\n                    cookieManager.setAcceptThirdPartyCookies(this, true)\n                }\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/settings/troubleshooting/TroubleshootingPage.kt",
    "content": "package com.junkfood.seal.ui.page.settings.troubleshooting\n\nimport androidx.compose.foundation.layout.Spacer\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.size\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.OpenInNew\nimport androidx.compose.material.icons.outlined.Cookie\nimport androidx.compose.material.icons.outlined.Settings\nimport androidx.compose.material.icons.outlined.Spellcheck\nimport androidx.compose.material.icons.outlined.Update\nimport androidx.compose.material3.CircularProgressIndicator\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedCard\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.ui.common.Route\nimport com.junkfood.seal.ui.common.booleanState\nimport com.junkfood.seal.ui.component.PreferenceInfo\nimport com.junkfood.seal.ui.component.PreferenceItem\nimport com.junkfood.seal.ui.component.PreferenceSubtitle\nimport com.junkfood.seal.ui.component.PreferenceSwitch\nimport com.junkfood.seal.ui.page.settings.BasePreferencePage\nimport com.junkfood.seal.ui.page.settings.general.YtdlpUpdateChannelDialog\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.junkfood.seal.util.RESTRICT_FILENAMES\nimport com.junkfood.seal.util.UpdateUtil\nimport com.junkfood.seal.util.YT_DLP_VERSION\nimport com.junkfood.seal.util.makeToast\nimport com.yausername.youtubedl_android.YoutubeDL\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\n@Composable\nfun TroubleShootingPage(\n    modifier: Modifier = Modifier,\n    onNavigateTo: (String) -> Unit,\n    onBack: () -> Unit,\n) {\n    val uriHandler = LocalUriHandler.current\n    val context = LocalContext.current\n    val scope = rememberCoroutineScope()\n\n    BasePreferencePage(\n        modifier = modifier,\n        title = stringResource(R.string.trouble_shooting),\n        onBack = onBack,\n    ) {\n        LazyColumn(contentPadding = it) {\n            item {\n                OutlinedCard(modifier = Modifier.padding(16.dp)) {\n                    PreferenceInfo(\n                        modifier = Modifier,\n                        text = stringResource(R.string.issue_tracker_hint),\n                    )\n                    val knownIssueUrlSeal = \"https://github.com/JunkFood02/Seal/issues/1399\"\n                    PreferenceItem(\n                        title = \"Seal Issue Tracker\",\n                        description = null,\n                        icon = Icons.AutoMirrored.Outlined.OpenInNew,\n                        onClick = { uriHandler.openUri(knownIssueUrlSeal) },\n                    )\n\n                    val knownIssueUrlYtdlp = \"https://github.com/yt-dlp/yt-dlp/issues/3766\"\n                    PreferenceItem(\n                        title = \"yt-dlp Issue Tracker\",\n                        description = null,\n                        icon = Icons.AutoMirrored.Outlined.OpenInNew,\n                        onClick = { uriHandler.openUri(knownIssueUrlYtdlp) },\n                    )\n\n                    Spacer(Modifier.height(8.dp))\n                }\n            }\n            item { PreferenceSubtitle(text = stringResource(R.string.update)) }\n            item {\n                var isUpdating by remember { mutableStateOf(false) }\n                var showYtdlpDialog by remember { mutableStateOf(false) }\n\n                var ytdlpVersion by remember {\n                    mutableStateOf(\n                        YoutubeDL.getInstance().version(context.applicationContext)\n                            ?: context.getString(R.string.ytdlp_update)\n                    )\n                }\n                PreferenceItem(\n                    title = stringResource(id = R.string.ytdlp_update_action),\n                    description = ytdlpVersion,\n                    leadingIcon = {\n                        if (isUpdating) {\n                            CircularProgressIndicator(\n                                modifier =\n                                    Modifier.padding(start = 8.dp, end = 16.dp)\n                                        .size(24.dp)\n                                        .padding(2.dp)\n                            )\n                        } else {\n                            Icon(\n                                imageVector = Icons.Outlined.Update,\n                                contentDescription = null,\n                                modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),\n                                tint = MaterialTheme.colorScheme.onSurfaceVariant,\n                            )\n                        }\n                    },\n                    onClick = {\n                        scope.launch(Dispatchers.IO) {\n                            runCatching {\n                                    isUpdating = true\n                                    UpdateUtil.updateYtDlp()\n                                    ytdlpVersion = YT_DLP_VERSION.getString()\n                                }\n                                .onFailure { th ->\n                                    th.printStackTrace()\n                                    withContext(Dispatchers.Main) {\n                                        context.makeToast(\n                                            App.context.getString(R.string.yt_dlp_update_fail)\n                                        )\n                                    }\n                                }\n                                .onSuccess {\n                                    withContext(Dispatchers.Main) {\n                                        context.makeToast(\n                                            context.getString(R.string.yt_dlp_up_to_date) +\n                                                \" (${YT_DLP_VERSION.getString()})\"\n                                        )\n                                    }\n                                }\n                            isUpdating = false\n                        }\n                    },\n                    onClickLabel = stringResource(id = R.string.update),\n                    trailingIcon = {\n                        IconButton(onClick = { showYtdlpDialog = true }) {\n                            Icon(\n                                imageVector = Icons.Outlined.Settings,\n                                contentDescription = stringResource(id = R.string.open_settings),\n                            )\n                        }\n                    },\n                )\n                if (showYtdlpDialog) {\n                    YtdlpUpdateChannelDialog(onDismissRequest = { showYtdlpDialog = false })\n                }\n            }\n\n            item { PreferenceSubtitle(text = stringResource(R.string.network)) }\n            item {\n                PreferenceItem(\n                    title = stringResource(R.string.cookies),\n                    description = stringResource(R.string.cookies_desc),\n                    icon = Icons.Outlined.Cookie,\n                    onClick = { onNavigateTo(Route.COOKIE_PROFILE) },\n                )\n            }\n            item { PreferenceSubtitle(text = stringResource(R.string.download_directory)) }\n            item {\n                var restrictFilenames by RESTRICT_FILENAMES.booleanState\n                PreferenceSwitch(\n                    title = stringResource(id = R.string.restrict_filenames),\n                    icon = Icons.Outlined.Spellcheck,\n                    description = stringResource(id = R.string.restrict_filenames_desc),\n                    isChecked = restrictFilenames,\n                ) {\n                    restrictFilenames = !restrictFilenames\n                    RESTRICT_FILENAMES.updateBoolean(restrictFilenames)\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/videolist/ExportImportDialog.kt",
    "content": "package com.junkfood.seal.ui.page.videolist\n\nimport android.content.res.Configuration\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.lazy.LazyRow\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.DriveFileMove\nimport androidx.compose.material.icons.outlined.Restore\nimport androidx.compose.material3.Button\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.OutlinedButton\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.res.pluralStringResource\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.backup.BackupUtil.BackupDestination\nimport com.junkfood.seal.database.backup.BackupUtil.BackupType\nimport com.junkfood.seal.ui.component.DialogSubtitle\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SingleSelectChip\nimport com.junkfood.seal.ui.theme.SealTheme\n\n@Composable\nfun ExportDialog(\n    modifier: Modifier = Modifier,\n    itemCount: Int = 0,\n    onDismissRequest: () -> Unit = {},\n    onExport: (BackupType, BackupDestination) -> Unit,\n) {\n    var type by remember { mutableStateOf(BackupType.DownloadHistory) }\n    var destination by remember { mutableStateOf(BackupDestination.File) }\n    SealDialog(\n        containerColor = MaterialTheme.colorScheme.surfaceContainerLow,\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            Button(onClick = { onExport(type, destination) }) {\n                Text(text = stringResource(id = R.string.export_backup))\n            }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) {\n                Text(text = stringResource(id = R.string.cancel))\n            }\n        },\n        title = { Text(text = stringResource(id = R.string.export_download_history)) },\n        icon = {\n            Icon(imageVector = Icons.AutoMirrored.Outlined.DriveFileMove, contentDescription = null)\n        },\n        text = {\n            Column {\n                Text(\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                    text =\n                        stringResource(R.string.export_download_history_msg)\n                            .format(\n                                pluralStringResource(id = R.plurals.item_count, count = itemCount)\n                                    .format(itemCount)\n                            ),\n                )\n                DialogSubtitle(\n                    modifier = Modifier,\n                    text = stringResource(id = R.string.backup_type),\n                )\n                LazyRow(\n                    contentPadding = PaddingValues(horizontal = 24.dp),\n                    horizontalArrangement = Arrangement.spacedBy(8.dp),\n                ) {\n                    item {\n                        SingleSelectChip(\n                            selected = type == BackupType.DownloadHistory,\n                            onClick = { type = BackupType.DownloadHistory },\n                            label = { Text(stringResource(id = R.string.full_backup)) },\n                        )\n                    }\n                    item {\n                        SingleSelectChip(\n                            selected = type == BackupType.URLList,\n                            onClick = { type = BackupType.URLList },\n                            label = { Text(text = stringResource(id = R.string.video_url)) },\n                        )\n                    }\n                }\n                DialogSubtitle(modifier = Modifier, text = stringResource(id = R.string.export_to))\n                LazyRow(\n                    contentPadding = PaddingValues(horizontal = 24.dp),\n                    horizontalArrangement = Arrangement.spacedBy(8.dp),\n                ) {\n                    item {\n                        SingleSelectChip(\n                            selected = destination == BackupDestination.File,\n                            onClick = { destination = BackupDestination.File },\n                            label = { Text(stringResource(id = R.string.file)) },\n                        )\n                    }\n                    item {\n                        SingleSelectChip(\n                            selected = destination == BackupDestination.Clipboard,\n                            onClick = { destination = BackupDestination.Clipboard },\n                            label = { Text(text = stringResource(id = R.string.clipboard)) },\n                        )\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Composable\nfun ImportDialog(\n    modifier: Modifier = Modifier,\n    onDismissRequest: () -> Unit = {},\n    onImport: (BackupDestination) -> Unit,\n) {\n    var destination by remember { mutableStateOf(BackupDestination.File) }\n\n    SealDialog(\n        containerColor = MaterialTheme.colorScheme.surfaceContainerLow,\n        modifier = modifier,\n        onDismissRequest = onDismissRequest,\n        confirmButton = {\n            Button(onClick = { onImport(destination) }) {\n                Text(text = stringResource(id = R.string.import_backup))\n            }\n        },\n        dismissButton = {\n            OutlinedButton(onClick = onDismissRequest) {\n                Text(text = stringResource(id = R.string.cancel))\n            }\n        },\n        title = { Text(text = stringResource(id = R.string.import_download_history)) },\n        icon = { Icon(imageVector = Icons.Outlined.Restore, contentDescription = null) },\n        text = {\n            Column {\n                Text(\n                    modifier = Modifier.padding(horizontal = 24.dp),\n                    text = stringResource(R.string.import_download_history_msg),\n                )\n                DialogSubtitle(\n                    modifier = Modifier,\n                    text = stringResource(id = R.string.backup_type),\n                )\n                LazyRow(\n                    contentPadding = PaddingValues(horizontal = 24.dp),\n                    horizontalArrangement = Arrangement.spacedBy(8.dp),\n                ) {\n                    item {\n                        SingleSelectChip(\n                            selected = true,\n                            onClick = {},\n                            label = { Text(stringResource(id = R.string.full_backup)) },\n                        )\n                    }\n                }\n                DialogSubtitle(\n                    modifier = Modifier,\n                    text = stringResource(id = R.string.import_from),\n                )\n                LazyRow(\n                    contentPadding = PaddingValues(horizontal = 24.dp),\n                    horizontalArrangement = Arrangement.spacedBy(8.dp),\n                ) {\n                    item {\n                        SingleSelectChip(\n                            selected = destination == BackupDestination.File,\n                            onClick = { destination = BackupDestination.File },\n                            label = { Text(stringResource(id = R.string.file)) },\n                        )\n                    }\n                    item {\n                        SingleSelectChip(\n                            selected = destination == BackupDestination.Clipboard,\n                            onClick = { destination = BackupDestination.Clipboard },\n                            label = { Text(text = stringResource(id = R.string.clipboard)) },\n                        )\n                    }\n                }\n            }\n        },\n    )\n}\n\n@Preview(locale = \"ja\")\n@Composable\nprivate fun PreviewExport() {\n    SealTheme { ExportDialog() { _, _ -> } }\n}\n\n@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = \"Dark\")\n@Composable\nprivate fun PreviewImport() {\n    SealTheme { ImportDialog() { _ -> } }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/videolist/RemoveItemDialog.kt",
    "content": "package com.junkfood.seal.ui.page.videolist\n\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TextButton\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.ui.component.CheckBoxItem\nimport com.junkfood.seal.ui.component.SealDialog\n\n@Composable\nfun RemoveItemDialog(\n    deleteFile: Boolean = false,\n    onDeleteFileToggled: (Boolean) -> Unit = {},\n    info: DownloadedVideoInfo,\n    onRemoveConfirm: (Boolean) -> Unit = {},\n    onDismissRequest: () -> Unit = {},\n) {\n    SealDialog(\n        onDismissRequest = onDismissRequest,\n        title = { Text(text = stringResource(R.string.delete_info)) },\n        icon = { Icon(Icons.Outlined.Delete, null) },\n        text = {\n            Column {\n                Text(\n                    modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),\n                    text = stringResource(R.string.delete_info_msg).format(info.videoTitle),\n                )\n                CheckBoxItem(\n                    modifier = Modifier.padding(horizontal = 12.dp),\n                    text = stringResource(R.string.delete_file),\n                    checked = deleteFile,\n                    onValueChange = onDeleteFileToggled,\n                )\n            }\n        },\n        confirmButton = {\n            TextButton(\n                onClick = {\n                    onDismissRequest()\n                    onRemoveConfirm(deleteFile)\n                }\n            ) {\n                Text(text = stringResource(R.string.confirm))\n            }\n        },\n        dismissButton = {\n            TextButton(onClick = onDismissRequest) { Text(text = stringResource(R.string.dismiss)) }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/videolist/VideoDetailDrawer.kt",
    "content": "@file:OptIn(ExperimentalMaterialApi::class)\n\npackage com.junkfood.seal.ui.page.videolist\n\nimport android.content.Intent\nimport android.content.res.Configuration\nimport androidx.activity.compose.BackHandler\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.PaddingValues\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.text.selection.SelectionContainer\nimport androidx.compose.material.ExperimentalMaterialApi\nimport androidx.compose.material.ModalBottomSheetState\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.outlined.Delete\nimport androidx.compose.material.icons.outlined.FileDownload\nimport androidx.compose.material.icons.outlined.Link\nimport androidx.compose.material.icons.outlined.Share\nimport androidx.compose.material3.ButtonDefaults\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.remember\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.hapticfeedback.HapticFeedbackType\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalDensity\nimport androidx.compose.ui.platform.LocalHapticFeedback\nimport androidx.compose.ui.platform.LocalUriHandler\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.text.style.TextOverflow\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.component.FilledTonalButtonWithIcon\nimport com.junkfood.seal.ui.component.LongTapTextButton\nimport com.junkfood.seal.ui.component.OutlinedButtonWithIcon\nimport com.junkfood.seal.ui.component.SealModalBottomSheetM2\nimport com.junkfood.seal.ui.theme.SealTheme\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.ToastUtil\n\n@Composable\nfun VideoDetailDrawer(\n    sheetState: ModalBottomSheetState,\n    info: DownloadedVideoInfo,\n    isFileAvailable: Boolean = true,\n    onDismissRequest: () -> Unit = {},\n    onDelete: () -> Unit = {},\n) {\n    val uriHandler = LocalUriHandler.current\n    val view = LocalView.current\n    val context = LocalContext.current\n    val hapticFeedback = LocalHapticFeedback.current\n    BackHandler(sheetState.targetValue == ModalBottomSheetValue.Expanded) { onDismissRequest() }\n\n    val onReDownload =\n        remember(info) {\n            {\n                context.startActivity(\n                    Intent().apply {\n                        action = Intent.ACTION_SEND\n                        setPackage(context.packageName)\n                        type = \"text/plain\"\n                        putExtra(Intent.EXTRA_TEXT, info.videoUrl)\n                    }\n                )\n            }\n        }\n\n    val shareTitle = stringResource(id = R.string.share)\n    with(info) {\n        VideoDetailDrawerImpl(\n            sheetState = sheetState,\n            title = videoTitle,\n            author = videoAuthor,\n            url = videoUrl,\n            isFileAvailable = isFileAvailable,\n            onReDownload = onReDownload,\n            onDismissRequest = onDismissRequest,\n            onDelete = {\n                view.slightHapticFeedback()\n                onDismissRequest()\n                onDelete()\n            },\n            onOpenLink = {\n                hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)\n                onDismissRequest()\n                uriHandler.openUri(videoUrl)\n            },\n            onShareFile = {\n                view.slightHapticFeedback()\n                FileUtil.createIntentForSharingFile(videoPath)?.runCatching {\n                    context.startActivity(Intent.createChooser(this, shareTitle))\n                }\n            },\n        )\n    }\n}\n\n@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)\n@Composable\nprivate fun DrawerPreview() {\n    SealTheme {\n        VideoDetailDrawerImpl(\n            sheetState =\n                ModalBottomSheetState(\n                    ModalBottomSheetValue.Expanded,\n                    density = LocalDensity.current,\n                ),\n            onReDownload = {},\n        )\n    }\n}\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun VideoDetailDrawerImpl(\n    sheetState: ModalBottomSheetState =\n        ModalBottomSheetState(ModalBottomSheetValue.Hidden, density = LocalDensity.current),\n    title: String = stringResource(id = R.string.video_title_sample_text),\n    author: String = stringResource(id = R.string.video_creator_sample_text),\n    url: String = \"https://www.example.com\",\n    onDismissRequest: () -> Unit = {},\n    isFileAvailable: Boolean = true,\n    onReDownload: (() -> Unit) = {},\n    onDelete: () -> Unit = {},\n    onOpenLink: () -> Unit = {},\n    onShareFile: () -> Unit = {},\n) {\n    val clipboardManager = LocalClipboardManager.current\n    val context = LocalContext.current\n    SealModalBottomSheetM2(\n        sheetState = sheetState,\n        contentPadding = PaddingValues(horizontal = 20.dp),\n        sheetContent = {\n            Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) {\n                SelectionContainer {\n                    Text(\n                        modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp),\n                        text = title,\n                        style = MaterialTheme.typography.titleLarge,\n                    )\n                }\n                if (author != \"playlist\" && author != \"null\")\n                    SelectionContainer {\n                        Text(\n                            modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp),\n                            text = author,\n                            style = MaterialTheme.typography.bodyLarge,\n                            color = MaterialTheme.colorScheme.onSurfaceVariant,\n                        )\n                    }\n            }\n            Row(modifier = Modifier.padding(vertical = 6.dp).fillMaxWidth()) {\n                LongTapTextButton(\n                    onClick = {\n                        clipboardManager.setText(AnnotatedString(url))\n                        ToastUtil.makeToast(context.getString(R.string.link_copied))\n                    },\n                    onClickLabel = stringResource(id = R.string.copy_link),\n                    onLongClick = onOpenLink,\n                    onLongClickLabel = stringResource(R.string.open_url),\n                ) {\n                    Icon(Icons.Outlined.Link, stringResource(R.string.video_url))\n                    Text(\n                        modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp),\n                        text = url,\n                        maxLines = 1,\n                        overflow = TextOverflow.Ellipsis,\n                    )\n                }\n            }\n\n            Row(\n                modifier =\n                    Modifier.fillMaxWidth()\n                        .horizontalScroll(rememberScrollState())\n                        .padding(top = 24.dp)\n                        .padding(horizontal = 8.dp),\n                horizontalArrangement = Arrangement.End,\n            ) {\n                OutlinedButtonWithIcon(\n                    modifier = Modifier.padding(horizontal = 12.dp),\n                    onClick = onDelete,\n                    icon = Icons.Outlined.Delete,\n                    text = stringResource(R.string.remove),\n                )\n                if (isFileAvailable) {\n                    FilledTonalButtonWithIcon(\n                        onClick = onShareFile,\n                        icon = Icons.Outlined.Share,\n                        text = stringResource(R.string.share),\n                    )\n                } else {\n                    FilledTonalButtonWithIcon(\n                        onClick = onReDownload,\n                        icon = Icons.Outlined.FileDownload,\n                        text = stringResource(R.string.redownload),\n                        colors =\n                            ButtonDefaults.filledTonalButtonColors(\n                                containerColor = MaterialTheme.colorScheme.tertiaryContainer,\n                                contentColor = MaterialTheme.colorScheme.onTertiaryContainer,\n                            ),\n                    )\n                }\n            }\n        },\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/videolist/VideoListPage.kt",
    "content": "package com.junkfood.seal.ui.page.videolist\n\nimport androidx.activity.compose.BackHandler\nimport androidx.activity.compose.rememberLauncherForActivityResult\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.compose.animation.AnimatedVisibility\nimport androidx.compose.animation.expandVertically\nimport androidx.compose.animation.fadeIn\nimport androidx.compose.animation.fadeOut\nimport androidx.compose.animation.shrinkVertically\nimport androidx.compose.foundation.Image\nimport androidx.compose.foundation.horizontalScroll\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.Row\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.height\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.layout.width\nimport androidx.compose.foundation.layout.widthIn\nimport androidx.compose.foundation.layout.wrapContentSize\nimport androidx.compose.foundation.lazy.LazyColumn\nimport androidx.compose.foundation.lazy.grid.GridItemSpan\nimport androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope\nimport androidx.compose.foundation.lazy.rememberLazyListState\nimport androidx.compose.foundation.rememberScrollState\nimport androidx.compose.foundation.selection.selectableGroup\nimport androidx.compose.material.ModalBottomSheetValue\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.automirrored.outlined.DriveFileMove\nimport androidx.compose.material.icons.outlined.DeleteSweep\nimport androidx.compose.material.icons.outlined.MoreVert\nimport androidx.compose.material.icons.outlined.Restore\nimport androidx.compose.material.icons.outlined.Search\nimport androidx.compose.material.rememberModalBottomSheetState\nimport androidx.compose.material3.BottomAppBar\nimport androidx.compose.material3.DropdownMenu\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.IconToggleButton\nimport androidx.compose.material3.LargeTopAppBar\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.SnackbarHost\nimport androidx.compose.material3.SnackbarHostState\nimport androidx.compose.material3.Text\nimport androidx.compose.material3.TopAppBarDefaults\nimport androidx.compose.material3.TriStateCheckbox\nimport androidx.compose.material3.VerticalDivider\nimport androidx.compose.material3.rememberTopAppBarState\nimport androidx.compose.material3.windowsizeclass.WindowWidthSizeClass\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.collectAsState\nimport androidx.compose.runtime.derivedStateOf\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableIntStateOf\nimport androidx.compose.runtime.mutableStateListOf\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.rememberCoroutineScope\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.vector.rememberVectorPainter\nimport androidx.compose.ui.input.nestedscroll.nestedScroll\nimport androidx.compose.ui.platform.LocalClipboardManager\nimport androidx.compose.ui.platform.LocalContext\nimport androidx.compose.ui.platform.LocalSoftwareKeyboardController\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.res.stringResource\nimport androidx.compose.ui.semantics.contentDescription\nimport androidx.compose.ui.semantics.semantics\nimport androidx.compose.ui.state.ToggleableState\nimport androidx.compose.ui.text.AnnotatedString\nimport androidx.compose.ui.unit.dp\nimport androidx.lifecycle.compose.collectAsStateWithLifecycle\nimport androidx.lifecycle.viewmodel.compose.viewModel\nimport com.junkfood.seal.App\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.backup.BackupUtil\nimport com.junkfood.seal.database.backup.BackupUtil.BackupDestination.Clipboard\nimport com.junkfood.seal.database.backup.BackupUtil.BackupDestination.File\nimport com.junkfood.seal.database.backup.BackupUtil.toJsonString\nimport com.junkfood.seal.database.backup.BackupUtil.toURLListString\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.ui.common.HapticFeedback.slightHapticFeedback\nimport com.junkfood.seal.ui.common.LocalWindowWidthState\nimport com.junkfood.seal.ui.component.BackButton\nimport com.junkfood.seal.ui.component.CheckBoxItem\nimport com.junkfood.seal.ui.component.ConfirmButton\nimport com.junkfood.seal.ui.component.DismissButton\nimport com.junkfood.seal.ui.component.MediaListItem\nimport com.junkfood.seal.ui.component.SealDialog\nimport com.junkfood.seal.ui.component.SealSearchBar\nimport com.junkfood.seal.ui.component.VideoFilterChip\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\nimport com.junkfood.seal.ui.svg.drawablevectors.videoSteaming\nimport com.junkfood.seal.util.AUDIO_REGEX\nimport com.junkfood.seal.util.FileUtil\nimport com.junkfood.seal.util.ToastUtil\nimport com.junkfood.seal.util.toFileSizeText\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport org.koin.androidx.compose.koinViewModel\n\nfun DownloadedVideoInfo.filterByType(\n    videoFilter: Boolean = false,\n    audioFilter: Boolean = true,\n): Boolean {\n    return if (!(videoFilter || audioFilter)) true\n    else if (audioFilter) this.videoPath.contains(Regex(AUDIO_REGEX))\n    else !this.videoPath.contains(Regex(AUDIO_REGEX))\n}\n\nfun DownloadedVideoInfo.filterSort(\n    viewState: VideoListViewModel.VideoListViewState,\n    filterSet: Set<String>,\n): Boolean {\n    return filterByType(videoFilter = viewState.videoFilter, audioFilter = viewState.audioFilter) &&\n        filterByExtractor(filterSet.elementAtOrNull(viewState.activeFilterIndex))\n}\n\nfun DownloadedVideoInfo.filterByExtractor(extractor: String?): Boolean {\n    return extractor.isNullOrEmpty() || (this.extractor == extractor)\n}\n\nprivate const val TAG = \"VideoListPage\"\n\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun VideoListPage(viewModel: VideoListViewModel = koinViewModel(), onNavigateBack: () -> Unit) {\n    val viewState by viewModel.stateFlow.collectAsStateWithLifecycle()\n    val fullVideoList by viewModel.videoListFlow.collectAsStateWithLifecycle(emptyList())\n    val searchedVideoList by\n        viewModel.searchedVideoListFlow.collectAsStateWithLifecycle(emptyList())\n\n    val videoList = if (viewState.isSearching) searchedVideoList else fullVideoList\n    val filterSet by viewModel.filterSetFlow.collectAsState(mutableSetOf())\n\n    val scrollBehavior =\n        if (fullVideoList.isNotEmpty())\n            TopAppBarDefaults.exitUntilCollapsedScrollBehavior(\n                rememberTopAppBarState(),\n                canScroll = { true },\n            )\n        else TopAppBarDefaults.pinnedScrollBehavior()\n\n    val scope = rememberCoroutineScope()\n    val softKeyboardController = LocalSoftwareKeyboardController.current\n    val view = LocalView.current\n    val context = LocalContext.current\n    val clipboardManager = LocalClipboardManager.current\n\n    val fileSizeMap by\n        viewModel.fileSizeMapFlow.collectAsStateWithLifecycle(initialValue = emptyMap())\n    val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)\n    val hostState = remember { SnackbarHostState() }\n\n    var currentVideoInfo by remember { mutableStateOf(DownloadedVideoInfo()) }\n\n    var isSelectEnabled by remember { mutableStateOf(false) }\n    var showRemoveMultipleItemsDialog by remember { mutableStateOf(false) }\n\n    var showExportDialog by remember { mutableStateOf(false) }\n    var showImportDialog by remember { mutableStateOf(false) }\n\n    val lazyListState = rememberLazyListState()\n\n    @Composable\n    fun FilterChips(modifier: Modifier = Modifier) {\n        Row(modifier.horizontalScroll(rememberScrollState()).selectableGroup()) {\n            Row(modifier = Modifier.padding(horizontal = 8.dp)) {\n                VideoFilterChip(\n                    selected = viewState.audioFilter,\n                    onClick = { viewModel.clickAudioFilter() },\n                    label = stringResource(id = R.string.audio),\n                )\n\n                VideoFilterChip(\n                    selected = viewState.videoFilter,\n                    onClick = { viewModel.clickVideoFilter() },\n                    label = stringResource(id = R.string.video),\n                )\n                if (filterSet.size > 1) {\n                    VerticalDivider(\n                        modifier =\n                            Modifier.padding(horizontal = 6.dp)\n                                .height(24.dp)\n                                .width(1f.dp)\n                                .align(Alignment.CenterVertically),\n                        color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f),\n                    )\n                    for (i in 0 until filterSet.size) {\n                        VideoFilterChip(\n                            selected = viewState.activeFilterIndex == i,\n                            onClick = { viewModel.clickExtractorFilter(i) },\n                            label = filterSet.elementAt(i),\n                        )\n                    }\n                }\n            }\n        }\n    }\n\n    val selectedItemIds = remember(videoList, viewState) { mutableStateListOf<Int>() }\n\n    LaunchedEffect(isSelectEnabled) {\n        if (!isSelectEnabled) {\n            delay(200)\n            selectedItemIds.clear()\n        }\n    }\n\n    val selectedVideoCount =\n        remember(selectedItemIds.size) {\n            mutableIntStateOf(\n                videoList.count { info ->\n                    selectedItemIds.contains(info.id) &&\n                        info.filterByType(videoFilter = true, audioFilter = false)\n                }\n            )\n        }\n    val selectedAudioCount =\n        remember(selectedItemIds.size) {\n            mutableIntStateOf(\n                videoList.count { info ->\n                    selectedItemIds.contains(info.id) &&\n                        info.filterByType(videoFilter = false, audioFilter = true)\n                }\n            )\n        }\n\n    val selectedFileSizeSum by\n        remember(selectedItemIds.size) {\n            derivedStateOf {\n                selectedItemIds.fold(0L) { acc: Long, id: Int ->\n                    acc + fileSizeMap.getOrElse(id) { 0L }\n                }\n            }\n        }\n\n    val visibleItemCount =\n        remember(videoList, viewState) {\n            mutableIntStateOf(videoList.count { it.filterSort(viewState, filterSet) })\n        }\n\n    val checkBoxState by\n        remember(selectedItemIds, visibleItemCount) {\n            derivedStateOf {\n                if (selectedItemIds.isEmpty()) ToggleableState.Off\n                else if (\n                    selectedItemIds.size == visibleItemCount.intValue &&\n                        selectedItemIds.isNotEmpty()\n                )\n                    ToggleableState.On\n                else ToggleableState.Indeterminate\n            }\n        }\n\n    var showRemoveDialog by remember { mutableStateOf(false) }\n    var showBottomSheet by remember { mutableStateOf(false) }\n\n    BackHandler(isSelectEnabled || viewState.isSearching) {\n        if (isSelectEnabled) {\n            isSelectEnabled = false\n        } else {\n            viewModel.toggleSearch(false)\n        }\n    }\n\n    LaunchedEffect(sheetState.targetValue, isSelectEnabled) {\n        if (showBottomSheet || isSelectEnabled) {\n            softKeyboardController?.hide()\n        }\n    }\n\n    Scaffold(\n        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),\n        topBar = {\n            LargeTopAppBar(\n                title = {\n                    Text(modifier = Modifier, text = stringResource(R.string.downloads_history))\n                },\n                navigationIcon = { BackButton { onNavigateBack() } },\n                actions = {\n                    Row {\n                        if (fullVideoList.isNotEmpty()) {\n                            IconToggleButton(\n                                modifier = Modifier,\n                                onCheckedChange = {\n                                    view.slightHapticFeedback()\n                                    viewModel.toggleSearch(it)\n                                    if (it) {\n                                        scope.launch {\n                                            delay(50)\n                                            lazyListState.animateScrollToItem(0)\n                                        }\n                                    }\n                                },\n                                checked = viewState.isSearching,\n                            ) {\n                                Icon(\n                                    imageVector = Icons.Outlined.Search,\n                                    contentDescription = stringResource(R.string.search),\n                                )\n                            }\n                        }\n                        var expanded by remember { mutableStateOf(false) }\n                        Box(modifier = Modifier.wrapContentSize(Alignment.TopEnd)) {\n                            IconButton(onClick = { expanded = true }) {\n                                Icon(\n                                    imageVector = Icons.Outlined.MoreVert,\n                                    contentDescription =\n                                        stringResource(id = R.string.show_more_actions),\n                                )\n                            }\n                            DropdownMenu(\n                                expanded = expanded,\n                                onDismissRequest = { expanded = false },\n                            ) {\n                                if (visibleItemCount.intValue > 0) {\n                                    DropdownMenuItem(\n                                        leadingIcon = {\n                                            Icon(\n                                                imageVector =\n                                                    Icons.AutoMirrored.Outlined.DriveFileMove,\n                                                contentDescription = null,\n                                            )\n                                        },\n                                        text = {\n                                            Text(text = stringResource(id = R.string.export_backup))\n                                        },\n                                        onClick = {\n                                            showExportDialog = true\n                                            expanded = false\n                                        },\n                                    )\n                                }\n                                DropdownMenuItem(\n                                    leadingIcon = {\n                                        Icon(\n                                            imageVector = Icons.Outlined.Restore,\n                                            contentDescription = null,\n                                        )\n                                    },\n                                    text = {\n                                        Text(text = stringResource(id = R.string.import_backup))\n                                    },\n                                    onClick = {\n                                        showImportDialog = true\n                                        expanded = false\n                                    },\n                                )\n                            }\n                        }\n                    }\n                },\n                scrollBehavior = scrollBehavior,\n            )\n        },\n        bottomBar = {\n            AnimatedVisibility(\n                isSelectEnabled,\n                enter = expandVertically(),\n                exit = shrinkVertically(),\n            ) {\n                BottomAppBar(modifier = Modifier) {\n                    val selectAllText = stringResource(R.string.select_all)\n                    TriStateCheckbox(\n                        modifier = Modifier.semantics { this.contentDescription = selectAllText },\n                        state = checkBoxState,\n                        onClick = {\n                            view.slightHapticFeedback()\n                            when (checkBoxState) {\n                                ToggleableState.On -> selectedItemIds.clear()\n                                else -> {\n                                    for (item in videoList) {\n                                        if (\n                                            !selectedItemIds.contains(item.id) &&\n                                                item.filterSort(viewState, filterSet)\n                                        ) {\n                                            selectedItemIds.add(item.id)\n                                        }\n                                    }\n                                }\n                            }\n                        },\n                    )\n                    Text(\n                        modifier = Modifier.weight(1f),\n                        text =\n                            stringResource(R.string.multiselect_item_count)\n                                .format(selectedVideoCount.intValue, selectedAudioCount.intValue),\n                        style = MaterialTheme.typography.labelLarge,\n                    )\n                    IconButton(\n                        onClick = {\n                            view.slightHapticFeedback()\n                            showRemoveMultipleItemsDialog = true\n                        },\n                        enabled = selectedItemIds.isNotEmpty(),\n                    ) {\n                        Icon(\n                            imageVector = Icons.Outlined.DeleteSweep,\n                            contentDescription = stringResource(id = R.string.remove),\n                        )\n                    }\n                }\n            }\n        },\n        snackbarHost = { SnackbarHost(hostState = hostState) },\n    ) { innerPadding ->\n        if (fullVideoList.isEmpty())\n            Box(modifier = Modifier.fillMaxSize()) {\n                val painter =\n                    rememberVectorPainter(image = DynamicColorImageVectors.videoSteaming())\n                Column(\n                    modifier = Modifier.align(Alignment.Center).widthIn(max = 360.dp),\n                    horizontalAlignment = Alignment.CenterHorizontally,\n                ) {\n                    Image(\n                        painter = painter,\n                        contentDescription = null,\n                        modifier =\n                            Modifier.padding(vertical = 20.dp)\n                                .fillMaxWidth(0.5f)\n                                .widthIn(max = 240.dp),\n                    )\n                    Text(\n                        text = stringResource(R.string.no_downloaded_media),\n                        style = MaterialTheme.typography.labelLarge,\n                        color = MaterialTheme.colorScheme.onSurfaceVariant,\n                    )\n                }\n            }\n\n        val cellCount =\n            when (LocalWindowWidthState.current) {\n                WindowWidthSizeClass.Expanded -> 2\n                else -> 1\n            }\n        val span: (LazyGridItemSpanScope) -> GridItemSpan = { GridItemSpan(cellCount) }\n        LazyColumn(modifier = Modifier, state = lazyListState, contentPadding = innerPadding) {\n            if (fullVideoList.isNotEmpty()) {\n                item {\n                    Column {\n                        AnimatedVisibility(visible = viewState.isSearching) {\n                            SealSearchBar(\n                                modifier =\n                                    Modifier.padding(horizontal = 12.dp).padding(vertical = 8.dp),\n                                text = viewState.searchText,\n                                placeholderText = stringResource(R.string.search_in_downloads),\n                                onValueChange = viewModel::updateSearchText,\n                            )\n                        }\n                        FilterChips(modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp))\n                    }\n                }\n            }\n            for (info in videoList) {\n\n                item(key = info.id, contentType = { info.videoPath.contains(AUDIO_REGEX) }) {\n                    with(info) {\n                        AnimatedVisibility(\n                            modifier = Modifier,\n                            visible = info.filterSort(viewState, filterSet),\n                            exit = shrinkVertically() + fadeOut(),\n                            enter = expandVertically() + fadeIn(),\n                        ) {\n                            MediaListItem(\n                                modifier = Modifier,\n                                title = videoTitle,\n                                author = videoAuthor,\n                                thumbnailUrl = thumbnailUrl,\n                                videoPath = videoPath,\n                                videoFileSize = fileSizeMap.getOrElse(id) { 0L },\n                                videoUrl = videoUrl,\n                                isSelectEnabled = { isSelectEnabled },\n                                isSelected = { selectedItemIds.contains(id) },\n                                onSelect = {\n                                    if (selectedItemIds.contains(id)) selectedItemIds.remove(id)\n                                    else selectedItemIds.add(id)\n                                },\n                                onClick = {\n                                    FileUtil.openFile(path = videoPath) {\n                                        ToastUtil.makeToastSuspend(\n                                            App.context.getString(R.string.file_unavailable)\n                                        )\n                                    }\n                                },\n                                onLongClick = {\n                                    isSelectEnabled = true\n                                    selectedItemIds.add(id)\n                                },\n                                onShowContextMenu = {\n                                    view.slightHapticFeedback()\n                                    currentVideoInfo = info\n                                    scope.launch {\n                                        showBottomSheet = true\n                                        delay(50)\n                                        sheetState.show()\n                                    }\n                                },\n                            )\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (showBottomSheet) {\n        val isFileAvailable = fileSizeMap[currentVideoInfo.id] != 0L\n        VideoDetailDrawer(\n            sheetState = sheetState,\n            info = currentVideoInfo,\n            isFileAvailable = isFileAvailable,\n            onDismissRequest = {\n                scope.launch { sheetState.hide() }.invokeOnCompletion { showBottomSheet = false }\n            },\n            onDelete = { showRemoveDialog = true },\n        )\n    }\n\n    var deleteFile by remember { mutableStateOf(false) }\n\n    if (showRemoveDialog) {\n        RemoveItemDialog(\n            info = currentVideoInfo,\n            deleteFile = deleteFile,\n            onDeleteFileToggled = { deleteFile = it },\n            onRemoveConfirm = {\n                viewModel.deleteDownloadHistory(listOf(currentVideoInfo), deleteFile = deleteFile)\n            },\n            onDismissRequest = { showRemoveDialog = false },\n        )\n    }\n\n    if (showRemoveMultipleItemsDialog) {\n        SealDialog(\n            onDismissRequest = { showRemoveMultipleItemsDialog = false },\n            icon = { Icon(Icons.Outlined.DeleteSweep, null) },\n            title = { Text(stringResource(R.string.delete_info)) },\n            text = {\n                Column {\n                    Text(\n                        modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),\n                        text =\n                            stringResource(R.string.delete_multiple_items_msg)\n                                .format(selectedItemIds.size),\n                    )\n                    CheckBoxItem(\n                        modifier = Modifier.padding(horizontal = 12.dp),\n                        text =\n                            stringResource(R.string.delete_file) +\n                                \" (${selectedFileSizeSum.toFileSizeText()})\",\n                        checked = deleteFile,\n                    ) {\n                        deleteFile = !deleteFile\n                    }\n                }\n            },\n            confirmButton = {\n                ConfirmButton {\n                    viewModel.deleteDownloadHistory(\n                        infoList = videoList.filter { selectedItemIds.contains(it.id) },\n                        deleteFile = deleteFile,\n                    )\n                    showRemoveMultipleItemsDialog = false\n                    isSelectEnabled = false\n                }\n            },\n            dismissButton = { DismissButton { showRemoveMultipleItemsDialog = false } },\n        )\n    }\n\n    var backupString by remember { mutableStateOf(\"\") }\n\n    val exportLauncher =\n        rememberLauncherForActivityResult(\n            contract = ActivityResultContracts.CreateDocument(\"text/plain\")\n        ) { uri ->\n            uri?.let {\n                scope.launch(Dispatchers.IO) {\n                    context.contentResolver.openOutputStream(uri)?.use {\n                        it.write(backupString.toByteArray())\n                    }\n                    withContext(Dispatchers.Main) { showExportDialog = false }\n                }\n            }\n        }\n\n    if (showExportDialog) {\n        val list =\n            if (selectedItemIds.isNotEmpty()) {\n                videoList.filter { selectedItemIds.contains(it.id) }\n            } else {\n                videoList.filter { it.filterSort(viewState, filterSet) }\n            }\n\n        ExportDialog(onDismissRequest = { showExportDialog = false }, itemCount = list.size) {\n            type,\n            destination ->\n            list.backupToString(type).let {\n                when (destination) {\n                    Clipboard -> clipboardManager.setText(AnnotatedString(it))\n                    File -> {\n                        backupString = it\n                        exportLauncher.launch(\n                            BackupUtil.getDownloadHistoryExportFilename(context = context)\n                        )\n                    }\n                }\n                view.slightHapticFeedback()\n                showExportDialog = false\n            }\n        }\n    }\n\n    val importLauncher =\n        rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) { uri ->\n            uri?.let {\n                viewModel.importBackupFromUri(context, uri) {\n                    viewModel.showImportedSnackbar(hostState, context, it)\n                }\n            }\n        }\n\n    if (showImportDialog) {\n\n        ImportDialog(onDismissRequest = { showImportDialog = false }) { destination ->\n            scope.launch {\n                when (destination) {\n                    Clipboard -> {\n                        clipboardManager.getText()?.text?.let { str ->\n                            viewModel.importBackupFromText(str) {\n                                viewModel.showImportedSnackbar(hostState, context, it)\n                            }\n                        }\n                    }\n\n                    File -> {\n                        importLauncher.launch(\"text/plain\")\n                    }\n                }\n            }\n            view.slightHapticFeedback()\n            showImportDialog = false\n        }\n    }\n}\n\nprivate fun List<DownloadedVideoInfo>.backupToString(type: BackupUtil.BackupType): String {\n    return when (type) {\n        BackupUtil.BackupType.DownloadHistory -> reversed().toJsonString()\n        BackupUtil.BackupType.URLList -> toURLListString()\n        else -> throw IllegalArgumentException()\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/page/videolist/VideoListViewModel.kt",
    "content": "package com.junkfood.seal.ui.page.videolist\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.compose.material3.SnackbarHostState\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.backup.BackupUtil\nimport com.junkfood.seal.database.backup.BackupUtil.decodeToBackup\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.util.DatabaseUtil\nimport com.junkfood.seal.util.FileUtil.getFileSize\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.asStateFlow\nimport kotlinx.coroutines.flow.combine\nimport kotlinx.coroutines.flow.flowOn\nimport kotlinx.coroutines.flow.map\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\n\nprivate const val TAG = \"VideoListViewModel\"\n\nclass VideoListViewModel : ViewModel() {\n\n    private val mutableStateFlow = MutableStateFlow(VideoListViewState())\n    val stateFlow = mutableStateFlow.asStateFlow()\n    private val viewState\n        get() = stateFlow.value\n\n    private val _mediaInfoFlow = DatabaseUtil.getDownloadHistoryFlow()\n\n    val videoListFlow: Flow<List<DownloadedVideoInfo>> =\n        _mediaInfoFlow.map { it.reversed().sortedBy { info -> info.filterByType() } }\n\n    val searchedVideoListFlow =\n        videoListFlow.combine(stateFlow) { list, state ->\n            if (!state.isSearching || state.searchText.isBlank()) list\n            else\n                list.filter {\n                    state.searchText.let { text ->\n                        with(it) {\n                            videoTitle.contains(text, ignoreCase = true) ||\n                                videoAuthor.contains(text, ignoreCase = true) ||\n                                extractor.contains(text, ignoreCase = true) ||\n                                videoPath.contains(text, ignoreCase = true)\n                        }\n                    }\n                }\n        }\n\n    val filterSetFlow =\n        searchedVideoListFlow.map { infoList ->\n            mutableSetOf<String>().apply { infoList.forEach { this.add(it.extractor) } }\n        }\n\n    val fileSizeMapFlow =\n        videoListFlow.flowOn(Dispatchers.IO).map { list ->\n            list.associate { it.id to it.videoPath.getFileSize() }\n        }\n\n    fun clickVideoFilter() {\n        if (mutableStateFlow.value.videoFilter)\n            mutableStateFlow.update { it.copy(videoFilter = false) }\n        else mutableStateFlow.update { it.copy(videoFilter = true, audioFilter = false) }\n    }\n\n    fun clickAudioFilter() {\n        if (mutableStateFlow.value.audioFilter)\n            mutableStateFlow.update { it.copy(audioFilter = false) }\n        else mutableStateFlow.update { it.copy(audioFilter = true, videoFilter = false) }\n    }\n\n    fun clickExtractorFilter(index: Int) {\n        if (mutableStateFlow.value.activeFilterIndex == index)\n            mutableStateFlow.update { it.copy(activeFilterIndex = -1) }\n        else mutableStateFlow.update { it.copy(activeFilterIndex = index) }\n    }\n\n    fun toggleSearch(isSearching: Boolean = !viewState.isSearching) {\n        mutableStateFlow.update { it.copy(isSearching = isSearching, searchText = \"\") }\n    }\n\n    fun updateSearchText(text: String) {\n        mutableStateFlow.update { it.copy(searchText = text) }\n    }\n\n    fun deleteDownloadHistory(infoList: List<DownloadedVideoInfo>, deleteFile: Boolean) {\n        viewModelScope.launch(Dispatchers.IO) {\n            DatabaseUtil.deleteInfoList(infoList = infoList, deleteFile = deleteFile)\n        }\n    }\n\n    fun importBackupFromUri(context: Context, uri: Uri, onComplete: suspend (Int) -> Unit) {\n        viewModelScope.launch(Dispatchers.IO) {\n            var res = 0\n            context.contentResolver.openInputStream(uri)?.use { input ->\n                input.bufferedReader(Charsets.UTF_8).readText().let {\n                    res = importBackupFromText(it)\n                }\n            }\n            withContext(Dispatchers.Main) { onComplete(res) }\n        }\n    }\n\n    fun importBackupFromText(string: String, onComplete: suspend (Int) -> Unit) {\n        viewModelScope.launch(Dispatchers.IO) {\n            val res = importBackupFromText(string)\n            withContext(Dispatchers.Main) { onComplete(res) }\n        }\n    }\n\n    private suspend fun importBackupFromText(string: String): Int {\n        string.decodeToBackup().onSuccess {\n            return DatabaseUtil.importBackup(\n                backup = it,\n                types = setOf(BackupUtil.BackupType.DownloadHistory),\n            )\n        }\n        return 0\n    }\n\n    fun showImportedSnackbar(hostState: SnackbarHostState, context: Context, importedCount: Int) {\n        viewModelScope.launch(Dispatchers.Main) {\n            hostState.showSnackbar(\n                message =\n                    context\n                        .getString(R.string.download_history_imported)\n                        .format(\n                            context.resources\n                                .getQuantityString(R.plurals.item_count, importedCount)\n                                .format(importedCount)\n                        )\n            )\n        }\n    }\n\n    data class VideoListViewState(\n        val activeFilterIndex: Int = -1,\n        val videoFilter: Boolean = false,\n        val audioFilter: Boolean = false,\n        val isSearching: Boolean = false,\n        val searchText: String = \"\",\n    )\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/svg/VectorPreviews.kt",
    "content": "package com.junkfood.seal.ui.svg\n\nimport android.content.res.Configuration\nimport androidx.compose.foundation.Image\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.aspectRatio\nimport androidx.compose.material3.Surface\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.tooling.preview.Preview\nimport com.junkfood.seal.ui.svg.drawablevectors.coder\nimport com.junkfood.seal.ui.svg.drawablevectors.download\nimport com.junkfood.seal.ui.svg.drawablevectors.videoFiles\nimport com.junkfood.seal.ui.svg.drawablevectors.videoSteaming\nimport com.junkfood.seal.ui.theme.SealTheme\n\n@Preview(name = \"Light\", uiMode = Configuration.UI_MODE_NIGHT_NO)\n@Preview(name = \"Night\", uiMode = Configuration.UI_MODE_NIGHT_YES)\n@Composable\nprivate fun Download() {\n    SealTheme {\n        Surface {\n            Column {\n                Image(\n                    imageVector = DynamicColorImageVectors.download(),\n                    contentDescription = null,\n                    modifier = Modifier.aspectRatio(16 / 9f),\n                )\n                Image(\n                    imageVector = DynamicColorImageVectors.coder(),\n                    contentDescription = null,\n                    modifier = Modifier.aspectRatio(16 / 9f),\n                )\n                Image(\n                    imageVector = DynamicColorImageVectors.videoFiles(),\n                    contentDescription = null,\n                    modifier = Modifier.aspectRatio(16 / 9f),\n                )\n                Image(\n                    imageVector = DynamicColorImageVectors.videoSteaming(),\n                    contentDescription = null,\n                    modifier = Modifier.aspectRatio(16 / 9f),\n                )\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/svg/__DrawableVectors.kt",
    "content": "package com.junkfood.seal.ui.svg\n\npublic object DynamicColorImageVectors\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/svg/drawablevectors/Coder.kt",
    "content": "package com.junkfood.seal.ui.svg.drawablevectors\n\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.PathFillType.Companion.NonZero\nimport androidx.compose.ui.graphics.SolidColor\nimport androidx.compose.ui.graphics.StrokeCap.Companion.Butt\nimport androidx.compose.ui.graphics.StrokeJoin.Companion.Miter\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.graphics.vector.ImageVector.Builder\nimport androidx.compose.ui.graphics.vector.path\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\nimport com.junkfood.seal.ui.theme.FixedAccentColors\n\n@Composable\nfun DynamicColorImageVectors.coder(): ImageVector {\n    return Builder(\n            name = \"Coder\",\n            defaultWidth = 717.67004.dp,\n            defaultHeight = 453.96432.dp,\n            viewportWidth = 717.67004f,\n            viewportHeight = 453.96432f,\n        )\n        .apply {\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(271.986f, 71.477f)\n                arcToRelative(3.827f, 3.827f, 0.0f, false, true, -4.314f, 1.257f)\n                arcToRelative(5.829f, 5.829f, 0.0f, false, true, -0.679f, -0.248f)\n                arcToRelative(28.826f, 28.826f, 0.0f, false, false, -0.367f, -7.989f)\n                arcToRelative(21.362f, 21.362f, 0.0f, false, true, -1.64f, 6.57f)\n                arcToRelative(8.911f, 8.911f, 0.0f, false, true, -1.76f, -2.513f)\n                arcToRelative(22.425f, 22.425f, 0.0f, false, true, -1.603f, -6.046f)\n                curveToRelative(-1.204f, -7.088f, -2.393f, -14.462f, -0.428f, -21.389f)\n                curveToRelative(2.879f, -10.119f, 11.957f, -17.393f, 15.749f, -27.211f)\n                lineToRelative(1.868f, -1.677f)\n                curveToRelative(3.198f, 5.445f, 3.339f, 12.212f, 2.036f, 18.387f)\n                curveToRelative(-1.297f, 6.187f, -3.909f, 11.994f, -5.975f, 17.96f)\n                reflectiveCurveToRelative(-3.613f, 12.313f, -2.655f, 18.556f)\n                curveTo(272.439f, 68.604f, 272.775f, 70.22f, 271.986f, 71.477f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb6b6)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(230.469f, 157.098f)\n                lineToRelative(-12.174f, 55.681f)\n                lineToRelative(53.174f, 17.319f)\n                lineToRelative(-7.819f, -73.0f)\n                lineToRelative(-33.181f, 0.0f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(605.699f, 452.598f)\n                horizontalLineToRelative(24.096f)\n                lineTo(629.795f, 342.129f)\n                arcTo(107.653f, 107.653f, 0.0f, false, false, 522.264f, 234.598f)\n                lineTo(298.326f, 234.598f)\n                arcTo(107.653f, 107.653f, 0.0f, false, false, 190.795f, 342.129f)\n                lineTo(190.795f, 452.598f)\n                horizontalLineToRelative(24.096f)\n                lineTo(214.89f, 377.129f)\n                arcTo(108.654f, 108.654f, 0.0f, false, true, 323.421f, 268.598f)\n                lineTo(497.168f, 268.598f)\n                arcTo(108.654f, 108.654f, 0.0f, false, true, 605.699f, 377.129f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(312.894f, 394.806f)\n                lineToRelative(-25.68f, -7.775f)\n                arcToRelative(88.484f, 88.484f, 0.0f, false, true, -2.509f, -20.963f)\n                arcToRelative(8.399f, 8.399f, 0.0f, false, true, 13.815f, -6.355f)\n                curveToRelative(13.773f, 11.814f, 33.948f, 18.118f, 46.968f, 31.58f)\n                arcToRelative(52.073f, 52.073f, 0.0f, false, true, 13.888f, 42.946f)\n                lineToRelative(5.621f, 18.181f)\n                arcToRelative(87.259f, 87.259f, 0.0f, false, true, -63.977f, -35.285f)\n                arcToRelative(84.287f, 84.287f, 0.0f, false, true, -10.122f, -18.565f)\n                curveTo(301.79f, 397.335f, 312.894f, 394.806f, 312.894f, 394.806f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(379.823f, 424.579f)\n                lineToRelative(13.098f, -3.966f)\n                quadToRelative(0.025f, -0.104f, 0.05f, -0.209f)\n                arcToRelative(8.409f, 8.409f, 0.0f, false, false, -12.483f, -9.094f)\n                curveToRelative(-5.946f, 3.532f, -12.548f, 6.573f, -17.289f, 11.476f)\n                arcToRelative(26.559f, 26.559f, 0.0f, false, false, -7.083f, 21.904f)\n                lineToRelative(-2.867f, 9.273f)\n                arcToRelative(44.505f, 44.505f, 0.0f, false, false, 32.63f, -17.996f)\n                arcToRelative(42.989f, 42.989f, 0.0f, false, false, 5.162f, -9.469f)\n                curveTo(385.487f, 425.869f, 379.823f, 424.579f, 379.823f, 424.579f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(485.849f, 153.13f)\n                lineTo(434.843f, 153.13f)\n                arcToRelative(2.721f, 2.721f, 0.0f, false, false, -2.717f, 2.724f)\n                verticalLineToRelative(80.574f)\n                horizontalLineToRelative(56.447f)\n                lineTo(488.573f, 155.854f)\n                arcTo(2.723f, 2.723f, 0.0f, false, false, 485.849f, 153.13f)\n                close()\n                moveTo(460.517f, 198.911f)\n                arcToRelative(6.051f, 6.051f, 0.0f, false, true, -6.023f, -6.023f)\n                verticalLineToRelative(-9.293f)\n                arcToRelative(6.023f, 6.023f, 0.0f, false, true, 12.046f, 0.0f)\n                verticalLineToRelative(9.293f)\n                arcToRelative(6.051f, 6.051f, 0.0f, false, true, -6.023f, 6.023f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(570.309f, 27.385f)\n                lineTo(352.28f, 27.385f)\n                arcToRelative(7.078f, 7.078f, 0.0f, false, false, -7.066f, 7.066f)\n                lineTo(345.214f, 181.579f)\n                arcToRelative(7.073f, 7.073f, 0.0f, false, false, 7.066f, 7.066f)\n                horizontalLineToRelative(218.029f)\n                arcToRelative(7.073f, 7.073f, 0.0f, false, false, 7.066f, -7.066f)\n                lineTo(577.376f, 34.452f)\n                arcTo(7.078f, 7.078f, 0.0f, false, false, 570.309f, 27.385f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surface),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(568.489f, 32.489f)\n                lineTo(354.102f, 32.489f)\n                arcToRelative(3.787f, 3.787f, 0.0f, false, false, -3.779f, 3.787f)\n                lineTo(350.323f, 179.756f)\n                arcToRelative(3.786f, 3.786f, 0.0f, false, false, 3.779f, 3.779f)\n                lineTo(568.489f, 183.536f)\n                arcToRelative(3.786f, 3.786f, 0.0f, false, false, 3.779f, -3.779f)\n                lineTo(572.268f, 36.276f)\n                arcTo(3.787f, 3.787f, 0.0f, false, false, 568.489f, 32.489f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(431.951f, 233.851f)\n                verticalLineToRelative(7.774f)\n                arcToRelative(1.523f, 1.523f, 0.0f, false, false, 1.52f, 1.52f)\n                horizontalLineToRelative(53.758f)\n                arcToRelative(1.527f, 1.527f, 0.0f, false, false, 1.52f, -1.52f)\n                lineTo(488.748f, 233.851f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(526.73f, 245.849f)\n                lineTo(399.181f, 245.849f)\n                arcToRelative(2.346f, 2.346f, 0.0f, false, true, -2.296f, -2.83f)\n                lineToRelative(1.979f, -9.4f)\n                arcToRelative(2.356f, 2.356f, 0.0f, false, true, 2.296f, -1.863f)\n                lineTo(524.752f, 231.757f)\n                arcToRelative(2.356f, 2.356f, 0.0f, false, true, 2.296f, 1.863f)\n                lineToRelative(1.979f, 9.4f)\n                arcToRelative(2.346f, 2.346f, 0.0f, false, true, -2.296f, 2.83f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(402.554f, 233.45f)\n                lineTo(405.506f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 405.994f, 233.938f)\n                lineTo(405.994f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 405.506f, 235.807f)\n                lineTo(402.554f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 402.066f, 235.318f)\n                lineTo(402.066f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 402.554f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(410.411f, 233.45f)\n                lineTo(413.363f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 413.851f, 233.938f)\n                lineTo(413.851f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 413.363f, 235.807f)\n                lineTo(410.411f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 409.923f, 235.318f)\n                lineTo(409.923f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 410.411f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(418.268f, 233.45f)\n                lineTo(421.22f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 421.708f, 233.938f)\n                lineTo(421.708f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 421.22f, 235.807f)\n                lineTo(418.268f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 417.779f, 235.318f)\n                lineTo(417.779f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 418.268f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(426.124f, 233.45f)\n                lineTo(429.076f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 429.565f, 233.938f)\n                lineTo(429.565f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 429.076f, 235.807f)\n                lineTo(426.124f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 425.636f, 235.318f)\n                lineTo(425.636f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 426.124f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(433.981f, 233.45f)\n                lineTo(436.933f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 437.421f, 233.938f)\n                lineTo(437.421f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 436.933f, 235.807f)\n                lineTo(433.981f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 433.493f, 235.318f)\n                lineTo(433.493f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 433.981f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(441.838f, 233.45f)\n                lineTo(444.79f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 445.278f, 233.938f)\n                lineTo(445.278f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 444.79f, 235.807f)\n                lineTo(441.838f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 441.35f, 235.318f)\n                lineTo(441.35f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 441.838f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(449.695f, 233.45f)\n                lineTo(452.647f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 453.135f, 233.938f)\n                lineTo(453.135f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 452.647f, 235.807f)\n                lineTo(449.695f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 449.207f, 235.318f)\n                lineTo(449.207f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 449.695f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(457.551f, 233.45f)\n                lineTo(460.503f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 460.992f, 233.938f)\n                lineTo(460.992f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 460.503f, 235.807f)\n                lineTo(457.551f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 457.063f, 235.318f)\n                lineTo(457.063f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 457.551f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(465.408f, 233.45f)\n                lineTo(468.36f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 468.848f, 233.938f)\n                lineTo(468.848f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 468.36f, 235.807f)\n                lineTo(465.408f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 464.92f, 235.318f)\n                lineTo(464.92f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 465.408f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(473.265f, 233.45f)\n                lineTo(476.217f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 476.705f, 233.938f)\n                lineTo(476.705f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 476.217f, 235.807f)\n                lineTo(473.265f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 472.777f, 235.318f)\n                lineTo(472.777f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 473.265f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(481.122f, 233.45f)\n                lineTo(484.074f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 484.562f, 233.938f)\n                lineTo(484.562f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 484.074f, 235.807f)\n                lineTo(481.122f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 480.634f, 235.318f)\n                lineTo(480.634f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 481.122f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(488.979f, 233.45f)\n                lineTo(491.931f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 492.419f, 233.938f)\n                lineTo(492.419f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 491.931f, 235.807f)\n                lineTo(488.979f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 488.49f, 235.318f)\n                lineTo(488.49f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 488.979f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(496.835f, 233.45f)\n                lineTo(499.787f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 500.275f, 233.938f)\n                lineTo(500.275f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 499.787f, 235.807f)\n                lineTo(496.835f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 496.347f, 235.318f)\n                lineTo(496.347f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 496.835f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(504.692f, 233.45f)\n                lineTo(507.644f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 508.132f, 233.938f)\n                lineTo(508.132f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 507.644f, 235.807f)\n                lineTo(504.692f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 504.204f, 235.318f)\n                lineTo(504.204f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 504.692f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(512.549f, 233.45f)\n                lineTo(515.501f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 515.989f, 233.938f)\n                lineTo(515.989f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 515.501f, 235.807f)\n                lineTo(512.549f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 512.061f, 235.318f)\n                lineTo(512.061f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 512.549f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(520.406f, 233.45f)\n                lineTo(523.358f, 233.45f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 523.846f, 233.938f)\n                lineTo(523.846f, 235.318f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 523.358f, 235.807f)\n                lineTo(520.406f, 235.807f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 519.917f, 235.318f)\n                lineTo(519.917f, 233.938f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 520.406f, 233.45f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(402.461f, 237.378f)\n                lineTo(405.413f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 405.901f, 237.866f)\n                lineTo(405.901f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 405.413f, 239.735f)\n                lineTo(402.461f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 401.973f, 239.247f)\n                lineTo(401.973f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 402.461f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(410.318f, 237.378f)\n                lineTo(413.27f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 413.758f, 237.866f)\n                lineTo(413.758f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 413.27f, 239.735f)\n                lineTo(410.318f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 409.83f, 239.247f)\n                lineTo(409.83f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 410.318f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(418.175f, 237.378f)\n                lineTo(421.127f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 421.615f, 237.866f)\n                lineTo(421.615f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 421.127f, 239.735f)\n                lineTo(418.175f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 417.687f, 239.247f)\n                lineTo(417.687f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 418.175f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(426.032f, 237.378f)\n                lineTo(428.984f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 429.472f, 237.866f)\n                lineTo(429.472f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 428.984f, 239.735f)\n                lineTo(426.032f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 425.543f, 239.247f)\n                lineTo(425.543f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 426.032f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(433.888f, 237.378f)\n                lineTo(436.84f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 437.329f, 237.866f)\n                lineTo(437.329f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 436.84f, 239.735f)\n                lineTo(433.888f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 433.4f, 239.247f)\n                lineTo(433.4f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 433.888f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(441.745f, 237.378f)\n                lineTo(444.697f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 445.185f, 237.866f)\n                lineTo(445.185f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 444.697f, 239.735f)\n                lineTo(441.745f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 441.257f, 239.247f)\n                lineTo(441.257f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 441.745f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(449.602f, 237.378f)\n                lineTo(452.554f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 453.042f, 237.866f)\n                lineTo(453.042f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 452.554f, 239.735f)\n                lineTo(449.602f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 449.114f, 239.247f)\n                lineTo(449.114f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 449.602f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(457.459f, 237.378f)\n                lineTo(460.411f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 460.899f, 237.866f)\n                lineTo(460.899f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 460.411f, 239.735f)\n                lineTo(457.459f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 456.97f, 239.247f)\n                lineTo(456.97f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 457.459f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(465.315f, 237.378f)\n                lineTo(468.267f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 468.756f, 237.866f)\n                lineTo(468.756f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 468.267f, 239.735f)\n                lineTo(465.315f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 464.827f, 239.247f)\n                lineTo(464.827f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 465.315f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(473.172f, 237.378f)\n                lineTo(476.124f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 476.612f, 237.866f)\n                lineTo(476.612f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 476.124f, 239.735f)\n                lineTo(473.172f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 472.684f, 239.247f)\n                lineTo(472.684f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 473.172f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(481.029f, 237.378f)\n                lineTo(483.981f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 484.469f, 237.866f)\n                lineTo(484.469f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 483.981f, 239.735f)\n                lineTo(481.029f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 480.541f, 239.247f)\n                lineTo(480.541f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 481.029f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(488.886f, 237.378f)\n                lineTo(491.838f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 492.326f, 237.866f)\n                lineTo(492.326f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 491.838f, 239.735f)\n                lineTo(488.886f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 488.398f, 239.247f)\n                lineTo(488.398f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 488.886f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(496.742f, 237.378f)\n                lineTo(499.694f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 500.183f, 237.866f)\n                lineTo(500.183f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 499.694f, 239.735f)\n                lineTo(496.742f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 496.254f, 239.247f)\n                lineTo(496.254f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 496.742f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(504.599f, 237.378f)\n                lineTo(507.551f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 508.039f, 237.866f)\n                lineTo(508.039f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 507.551f, 239.735f)\n                lineTo(504.599f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 504.111f, 239.247f)\n                lineTo(504.111f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 504.599f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(512.456f, 237.378f)\n                lineTo(515.408f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 515.896f, 237.866f)\n                lineTo(515.896f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 515.408f, 239.735f)\n                lineTo(512.456f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 511.968f, 239.247f)\n                lineTo(511.968f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 512.456f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(520.313f, 237.378f)\n                lineTo(523.265f, 237.378f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 523.753f, 237.866f)\n                lineTo(523.753f, 239.247f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 523.265f, 239.735f)\n                lineTo(520.313f, 239.735f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 519.825f, 239.247f)\n                lineTo(519.825f, 237.866f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 520.313f, 237.378f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(440.174f, 242.092f)\n                lineTo(470.624f, 242.092f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 471.113f, 242.58f)\n                lineTo(471.113f, 243.961f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 470.624f, 244.449f)\n                lineTo(440.174f, 244.449f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 439.686f, 243.961f)\n                lineTo(439.686f, 242.58f)\n                arcTo(0.488f, 0.488f, 0.0f, false, true, 440.174f, 242.092f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(536.523f, 68.508f)\n                verticalLineToRelative(75.52f)\n                arcToRelative(19.073f, 19.073f, 0.0f, false, true, -19.07f, 19.07f)\n                horizontalLineToRelative(-94.52f)\n                arcToRelative(19.081f, 19.081f, 0.0f, false, true, -17.51f, -11.49f)\n                arcToRelative(17.984f, 17.984f, 0.0f, false, true, -1.13f, -3.51f)\n                arcToRelative(17.367f, 17.367f, 0.0f, false, false, 6.3f, 1.17f)\n                horizontalLineToRelative(94.52f)\n                arcToRelative(17.605f, 17.605f, 0.0f, false, false, 17.58f, -17.58f)\n                verticalLineToRelative(-75.52f)\n                arcToRelative(17.368f, 17.368f, 0.0f, false, false, -1.17f, -6.3f)\n                arcToRelative(17.988f, 17.988f, 0.0f, false, true, 3.51f, 1.13f)\n                arcTo(19.081f, 19.081f, 0.0f, false, true, 536.523f, 68.508f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb6b6)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(183.897f, 368.973f)\n                lineToRelative(-9.375f, 5.805f)\n                lineToRelative(-27.619f, -33.95f)\n                lineToRelative(13.836f, -8.566f)\n                lineToRelative(23.158f, 36.711f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(191.991f, 381.099f)\n                lineToRelative(-7.541f, 3.367f)\n                lineToRelative(-4.524f, -6.519f)\n                lineToRelative(-0.269f, 8.659f)\n                lineToRelative(-20.001f, 8.929f)\n                arcToRelative(4.924f, 4.924f, 0.0f, false, true, -6.214f, -7.056f)\n                lineToRelative(11.048f, -18.162f)\n                lineToRelative(-3.213f, -7.198f)\n                lineToRelative(17.248f, -6.497f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(157.635f, 362.442f)\n                lineToRelative(15.834f, -15.344f)\n                curveToRelative(-11.764f, -29.029f, -12.704f, -47.022f, -29.012f, -82.131f)\n                curveToRelative(38.693f, 7.914f, 66.356f, 7.433f, 98.356f, 0.337f)\n                curveToRelative(10.833f, -2.365f, 38.786f, -23.956f, 36.487f, -35.027f)\n                quadToRelative(-0.161f, -0.776f, -0.381f, -1.538f)\n                curveToRelative(-3.435f, -11.711f, -1.016f, -29.646f, -8.451f, -42.642f)\n                curveToRelative(-13.755f, -5.186f, -34.653f, 12.326f, -51.0f, 23.0f)\n                curveToRelative(-7.883f, 5.147f, -2.112f, 12.161f, -8.0f, 14.0f)\n                lineToRelative(-22.569f, 7.326f)\n                lineToRelative(-55.373f, -8.943f)\n                arcToRelative(20.511f, 20.511f, 0.0f, false, false, -23.376f, 17.359f)\n                quadToRelative(-0.141f, 0.902f, -0.204f, 1.813f)\n                curveToRelative(2.548f, 14.103f, 5.204f, 27.837f, 8.063f, 40.873f)\n                curveToRelative(0.923f, 4.208f, -0.635f, 12.275f, 2.836f, 12.395f)\n                reflectiveCurveToRelative(2.073f, 8.464f, 3.154f, 12.543f)\n                curveTo(130.654f, 331.579f, 134.863f, 343.733f, 157.635f, 362.442f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb6b6)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(127.329f, 429.745f)\n                lineToRelative(-9.767f, -5.098f)\n                lineToRelative(15.453f, -40.936f)\n                lineToRelative(14.415f, 7.524f)\n                lineToRelative(-20.101f, 38.51f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(125.701f, 399.184f)\n                lineToRelative(15.661f, 10.783f)\n                curveToRelative(19.195f, -27.76f, 31.658f, -64.854f, 40.939f, -106.36f)\n                curveToRelative(36.139f, -15.765f, 67.761f, -33.801f, 89.796f, -57.993f)\n                arcToRelative(20.915f, 20.915f, 0.0f, false, false, -1.209f, -29.095f)\n                quadToRelative(-0.578f, -0.542f, -1.196f, -1.039f)\n                curveToRelative(-9.545f, -7.603f, -30.743f, -3.228f, -44.292f, -9.583f)\n                lineToRelative(-24.204f, 33.5f)\n                lineToRelative(2.782f, 7.803f)\n                lineToRelative(-8.42f, 4.099f)\n                lineToRelative(-7.109f, 3.461f)\n                lineToRelative(-8.138f, 3.962f)\n                lineTo(153.633f, 271.708f)\n                arcToRelative(20.484f, 20.484f, 0.0f, false, false, -9.089f, 27.629f)\n                quadToRelative(0.404f, 0.818f, 0.878f, 1.6f)\n                lineToRelative(-9.908f, 49.36f)\n                reflectiveCurveToRelative(2.726f, 8.593f, -1.563f, 7.789f)\n                reflectiveCurveToRelative(-1.952f, 9.725f, -1.952f, 9.725f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(121.414f, 452.305f)\n                lineToRelative(-7.321f, -3.821f)\n                lineToRelative(2.301f, -7.594f)\n                lineToRelative(-6.955f, 5.165f)\n                lineToRelative(-19.418f, -10.135f)\n                arcToRelative(4.924f, 4.924f, 0.0f, false, true, 1.673f, -9.252f)\n                lineToRelative(21.096f, -2.616f)\n                lineToRelative(3.647f, -6.988f)\n                lineToRelative(15.802f, 9.486f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb6b6)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(334.892f, 237.703f)\n                lineToRelative(-11.423f, -27.606f)\n                lineToRelative(-9.0f, 5.0f)\n                lineToRelative(5.435f, 28.082f)\n                arcToRelative(10.001f, 10.001f, 0.0f, true, false, 14.988f, -5.476f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb6b6)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(143.208f, 19.407f)\n                lineToRelative(17.381f, 24.3f)\n                lineToRelative(7.633f, -6.909f)\n                lineTo(156.565f, 10.677f)\n                arcToRelative(10.001f, 10.001f, 0.0f, true, false, -13.357f, 8.73f)\n                close()\n            }\n            path(\n                fill = SolidColor(FixedAccentColors.tertiaryFixedDim),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(221.697f, 173.421f)\n                curveToRelative(-11.274f, 17.486f, 30.028f, 55.586f, 51.772f, 46.677f)\n                curveToRelative(3.807f, -1.56f, 16.904f, -6.713f, 7.952f, -13.856f)\n                reflectiveCurveToRelative(1.038f, 0.851f, 1.274f, -3.799f)\n                curveToRelative(0.158f, -3.109f, -2.249f, -9.929f, 0.262f, -9.637f)\n                reflectiveCurveToRelative(3.953f, -6.971f, -1.517f, -8.822f)\n                arcToRelative(10.618f, 10.618f, 0.0f, false, true, -7.0f, -9.0f)\n                curveToRelative(-0.523f, -19.167f, 5.968f, -39.177f, 5.968f, -39.177f)\n                lineToRelative(26.498f, 67.735f)\n                reflectiveCurveToRelative(-0.196f, 11.719f, 3.183f, 8.137f)\n                reflectiveCurveToRelative(3.133f, 8.009f, 3.133f, 8.009f)\n                reflectiveCurveToRelative(5.025f, 3.507f, 2.135f, 5.458f)\n                reflectiveCurveToRelative(3.111f, 7.952f, 3.111f, 7.952f)\n                lineToRelative(14.0f, -1.0f)\n                reflectiveCurveToRelative(-0.219f, -10.4f, -2.61f, -12.7f)\n                reflectiveCurveToRelative(-1.216f, -5.919f, -1.216f, -5.919f)\n                reflectiveCurveToRelative(-4.928f, -4.584f, -2.051f, -9.983f)\n                reflectiveCurveToRelative(-20.951f, -101.961f, -20.951f, -101.961f)\n                arcToRelative(25.72f, 25.72f, 0.0f, false, false, -18.366f, -19.62f)\n                lineToRelative(-15.121f, -4.163f)\n                lineToRelative(-2.685f, -10.653f)\n                lineTo(248.177f, 67.098f)\n                lineToRelative(-3.709f, 7.0f)\n                lineToRelative(-34.0f, -3.0f)\n                reflectiveCurveToRelative(-33.643f, -30.61f, -32.0f, -33.0f)\n                reflectiveCurveToRelative(-3.573f, -7.986f, -3.573f, -7.986f)\n                reflectiveCurveToRelative(-4.454f, -1.458f, -1.941f, -2.236f)\n                reflectiveCurveToRelative(-2.237f, -2.578f, -2.237f, -2.578f)\n                reflectiveCurveToRelative(-4.4f, -1.156f, -2.325f, -2.678f)\n                reflectiveCurveToRelative(-6.925f, -2.522f, -6.925f, -2.522f)\n                lineToRelative(-11.677f, 9.528f)\n                lineToRelative(2.36f, 4.002f)\n                reflectiveCurveToRelative(-1.439f, 5.449f, 0.439f, 3.46f)\n                reflectiveCurveToRelative(2.232f, 3.784f, 2.232f, 3.784f)\n                reflectiveCurveToRelative(0.959f, 6.322f, 6.646f, 8.227f)\n                reflectiveCurveToRelative(10.0f, 20.0f, 10.0f, 20.0f)\n                lineToRelative(48.0f, 40.0f)\n                curveToRelative(-7.311f, 8.391f, -5.57f, 17.166f, 0.906f, 26.142f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb6b6)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(258.343f, 36.964f)\n                moveToRelative(-23.056f, 0.0f)\n                arcToRelative(23.056f, 23.056f, 0.0f, true, true, 46.111f, 0.0f)\n                arcToRelative(23.056f, 23.056f, 0.0f, true, true, -46.111f, 0.0f)\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(278.469f, 30.098f)\n                curveToRelative(-0.59f, 0.17f, -9.25f, 1.3f, -13.0f, 2.0f)\n                curveToRelative(-3.68f, 0.69f, -4.32f, -4.0f, -7.33f, -3.12f)\n                arcToRelative(0.127f, 0.127f, 0.0f, false, false, -0.01f, -0.06f)\n                arcToRelative(28.344f, 28.344f, 0.0f, false, false, -2.37f, -7.17f)\n                arcToRelative(21.178f, 21.178f, 0.0f, false, true, 0.17f, 6.6f)\n                arcToRelative(0.984f, 0.984f, 0.0f, false, true, -0.02f, 0.17f)\n                curveToRelative(-0.01f, 0.1f, -0.03f, 0.19f, -0.04f, 0.29f)\n                curveToRelative(-3.18f, -1.4f, -5.2f, -0.15f, -7.4f, 0.29f)\n                curveToRelative(-2.46f, 0.49f, -4.38f, 1.57f, -3.0f, 10.0f)\n                curveToRelative(2.83f, 17.34f, 17.55f, 23.53f, 15.0f, 35.0f)\n                curveToRelative(-0.5f, 2.27f, -1.76f, 5.11f, -3.34f, 5.82f)\n                arcToRelative(28.344f, 28.344f, 0.0f, false, false, -2.37f, -7.17f)\n                arcToRelative(21.178f, 21.178f, 0.0f, false, true, 0.17f, 6.6f)\n                curveToRelative(-2.45f, -2.65f, -4.22f, -11.91f, -12.46f, -19.25f)\n                curveToRelative(-2.03f, -1.8f, -12.2f, -12.48f, -13.42f, -15.0f)\n                arcToRelative(32.136f, 32.136f, 0.0f, false, true, 0.54f, 6.11f)\n                arcToRelative(29.416f, 29.416f, 0.0f, false, true, -0.28f, 4.1f)\n                arcToRelative(1.151f, 1.151f, 0.0f, false, true, -0.03f, 0.26f)\n                curveToRelative(-0.01f, 0.16f, -0.04f, 0.3f, -0.06f, 0.45f)\n                curveToRelative(-0.02f, 0.17f, -0.05f, 0.33f, -0.08f, 0.5f)\n                curveToRelative(-3.33f, -0.48f, -6.28f, -1.06f, -7.67f, -2.42f)\n                curveToRelative(-6.76f, -6.58f, 1.49f, -19.4f, 6.0f, -31.0f)\n                curveToRelative(6.45f, -16.61f, 25.18f, -18.82f, 27.0f, -19.0f)\n                curveToRelative(8.02f, -0.81f, 21.57f, 0.91f, 26.0f, 10.0f)\n                curveTo(283.569f, 20.468f, 281.589f, 29.198f, 278.469f, 30.098f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(229.854f, 33.847f)\n                lineToRelative(16.701f, -25.98f)\n                arcToRelative(25.612f, 25.612f, 0.0f, false, false, -13.188f, -3.46f)\n                arcToRelative(16.419f, 16.419f, 0.0f, false, false, -12.109f, 5.711f)\n                curveToRelative(-3.411f, 4.239f, -3.996f, 10.232f, -2.718f, 15.521f)\n                curveTo(218.981f, 27.466f, 227.385f, 21.039f, 225.385f, 24.039f)\n                curveToRelative(-1.642f, 2.349f, -4.327f, 12.222f, -5.0f, 15.0f)\n                curveToRelative(-1.084f, 4.472f, -4.063f, 9.062f, -1.409f, 12.821f)\n                curveToRelative(3.139f, 4.444f, 8.74f, 6.654f, 14.177f, 6.878f)\n                reflectiveCurveToRelative(10.788f, -1.282f, 15.954f, -2.989f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(236.271f, 32.822f)\n                arcToRelative(1.0f, 1.0f, 0.0f, false, true, -0.273f, -1.962f)\n                curveToRelative(0.262f, -0.433f, 0.155f, -2.253f, 0.068f, -3.725f)\n                curveToRelative(-0.325f, -5.524f, -0.87f, -14.769f, 8.106f, -21.01f)\n                arcToRelative(1.0f, 1.0f, 0.0f, false, true, 1.142f, 1.642f)\n                curveToRelative(-8.055f, 5.601f, -7.571f, 13.815f, -7.251f, 19.25f)\n                curveToRelative(0.183f, 3.107f, 0.315f, 5.352f, -1.57f, 5.779f)\n                arcTo(0.994f, 0.994f, 0.0f, false, true, 236.271f, 32.822f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF000000)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(0.0f, 451.951f)\n                arcToRelative(1.186f, 1.186f, 0.0f, false, false, 1.183f, 1.19f)\n                lineTo(716.48f, 453.141f)\n                arcToRelative(1.19f, 1.19f, 0.0f, false, false, 0.0f, -2.38f)\n                horizontalLineToRelative(-715.29f)\n                arcToRelative(1.186f, 1.186f, 0.0f, false, false, -1.19f, 1.183f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(442.535f, 94.849f)\n                lineTo(427.403f, 94.849f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, -3.026f)\n                horizontalLineToRelative(15.132f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(469.772f, 94.849f)\n                lineTo(454.64f, 94.849f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, -3.026f)\n                horizontalLineToRelative(15.132f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(483.391f, 106.955f)\n                lineTo(468.259f, 106.955f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, -3.026f)\n                horizontalLineToRelative(15.132f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(456.237f, 106.955f)\n                lineTo(427.403f, 106.955f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, -3.026f)\n                lineTo(456.237f, 103.929f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(510.713f, 94.849f)\n                lineTo(481.878f, 94.849f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, -3.026f)\n                horizontalLineToRelative(28.834f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(452.895f, 71.925f)\n                lineTo(424.06f, 71.925f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, -3.026f)\n                horizontalLineToRelative(28.834f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(455.265f, 80.766f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, true, -0.832f, -2.425f)\n                lineToRelative(7.383f, -5.739f)\n                arcToRelative(2.714f, 2.714f, 0.0f, false, false, 0.328f, -3.984f)\n                lineToRelative(-6.199f, -6.711f)\n                arcToRelative(1.355f, 1.355f, 0.0f, true, true, 1.99f, -1.839f)\n                lineToRelative(9.205f, 9.965f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, true, -0.163f, 1.99f)\n                lineToRelative(-10.881f, 8.458f)\n                arcTo(1.351f, 1.351f, 0.0f, false, true, 455.265f, 80.766f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(422.601f, 80.766f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, false, 0.832f, -2.425f)\n                lineToRelative(-7.383f, -5.739f)\n                arcToRelative(2.714f, 2.714f, 0.0f, false, true, -0.328f, -3.984f)\n                lineToRelative(6.199f, -6.711f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, false, -1.99f, -1.839f)\n                lineToRelative(-9.205f, 9.965f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, false, 0.163f, 1.99f)\n                lineToRelative(10.881f, 8.458f)\n                arcTo(1.351f, 1.351f, 0.0f, false, false, 422.601f, 80.766f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(467.801f, 132.906f)\n                lineTo(438.966f, 132.906f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, -3.026f)\n                horizontalLineToRelative(28.834f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 0.0f, 3.026f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(472.882f, 140.391f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, true, -0.832f, -2.425f)\n                lineToRelative(7.383f, -5.739f)\n                arcToRelative(2.714f, 2.714f, 0.0f, false, false, 0.328f, -3.984f)\n                lineToRelative(-6.199f, -6.711f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, true, 1.99f, -1.839f)\n                lineToRelative(9.205f, 9.965f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, true, -0.163f, 1.99f)\n                lineToRelative(-10.881f, 8.458f)\n                arcTo(1.351f, 1.351f, 0.0f, false, true, 472.882f, 140.391f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(422.601f, 140.391f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, false, 0.832f, -2.425f)\n                lineToRelative(-7.383f, -5.739f)\n                arcToRelative(2.714f, 2.714f, 0.0f, false, true, -0.328f, -3.984f)\n                lineToRelative(6.199f, -6.711f)\n                arcToRelative(1.355f, 1.355f, 0.0f, true, false, -1.99f, -1.839f)\n                lineToRelative(-9.205f, 9.965f)\n                arcToRelative(1.355f, 1.355f, 0.0f, false, false, 0.163f, 1.99f)\n                lineToRelative(10.881f, 8.458f)\n                arcTo(1.351f, 1.351f, 0.0f, false, false, 422.601f, 140.391f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(425.174f, 136.151f)\n                lineToRelative(6.061f, -13.865f)\n                arcToRelative(1.513f, 1.513f, 0.0f, false, true, 2.773f, 1.212f)\n                lineToRelative(-6.061f, 13.865f)\n                arcToRelative(1.513f, 1.513f, 0.0f, true, true, -2.773f, -1.212f)\n                close()\n            }\n        }\n        .build()\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/svg/drawablevectors/Download.kt",
    "content": "package com.junkfood.seal.ui.svg.drawablevectors\n\nimport androidx.compose.foundation.Image\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.PathFillType.Companion.NonZero\nimport androidx.compose.ui.graphics.SolidColor\nimport androidx.compose.ui.graphics.StrokeCap.Companion.Butt\nimport androidx.compose.ui.graphics.StrokeJoin.Companion.Miter\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.graphics.vector.ImageVector.Builder\nimport androidx.compose.ui.graphics.vector.path\nimport androidx.compose.ui.graphics.vector.rememberVectorPainter\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\n\n@Composable\nfun DynamicColorImageVectors.download(): ImageVector {\n    return Builder(\n            name = \"Download\",\n            defaultWidth = 765.59973.dp,\n            defaultHeight = 667.7441.dp,\n            viewportWidth = 765.59973f,\n            viewportHeight = 667.7441f,\n        )\n        .apply {\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHigh),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(713.462f, 666.985f)\n                verticalLineToRelative(-72.34f)\n                reflectiveCurveTo(741.654f, 645.931f, 713.462f, 666.985f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHigh),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(715.203f, 666.972f)\n                lineToRelative(-53.29f, -48.921f)\n                reflectiveCurveTo(718.759f, 631.966f, 715.203f, 666.972f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(270.217f, 128.781f)\n                horizontalLineToRelative(-2.978f)\n                lineTo(267.239f, 47.211f)\n                arcTo(47.211f, 47.211f, 0.0f, false, false, 220.029f, 0.0f)\n                lineTo(47.211f, 0.0f)\n                arcToRelative(47.211f, 47.211f, 0.0f, false, false, -47.211f, 47.211f)\n                lineTo(0.0f, 494.712f)\n                arcToRelative(47.211f, 47.211f, 0.0f, false, false, 47.211f, 47.211f)\n                lineTo(220.028f, 541.923f)\n                arcToRelative(47.211f, 47.211f, 0.0f, false, false, 47.211f, -47.211f)\n                verticalLineToRelative(-307.868f)\n                horizontalLineToRelative(2.978f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surface),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(221.934f, 12.283f)\n                lineTo(63.375f, 12.283f)\n                arcToRelative(16.75f, 16.75f, 0.0f, false, true, -15.508f, 23.076f)\n                lineTo(84.861f, 35.359f)\n                arcToRelative(16.75f, 16.75f, 0.0f, false, true, -15.508f, -23.076f)\n                lineTo(48.283f, 12.283f)\n                arcTo(35.256f, 35.256f, 0.0f, false, false, 13.027f, 47.539f)\n                lineTo(13.027f, 494.384f)\n                arcToRelative(35.256f, 35.256f, 0.0f, false, false, 35.256f, 35.256f)\n                lineTo(221.934f, 529.64f)\n                arcToRelative(35.256f, 35.256f, 0.0f, false, false, 35.256f, -35.256f)\n                horizontalLineToRelative(0.0f)\n                lineTo(257.19f, 47.539f)\n                arcTo(35.256f, 35.256f, 0.0f, false, false, 221.934f, 12.283f)\n                close()\n            }\n            path(\n                fill = SolidColor(LocalFixedColorRoles.current.primaryFixedDim),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(135.108f, 261.234f)\n                moveToRelative(-84.446f, 0.0f)\n                arcToRelative(84.446f, 84.446f, 0.0f, true, true, 168.892f, 0.0f)\n                arcToRelative(84.446f, 84.446f, 0.0f, true, true, -168.892f, 0.0f)\n            }\n            path(\n                fill = SolidColor(LocalFixedColorRoles.current.onPrimaryFixedVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(160.132f, 267.004f)\n                lineToRelative(-21.0f, 21.63f)\n                arcToRelative(4.774f, 4.774f, 0.0f, false, true, -3.5f, 1.41f)\n                horizontalLineToRelative(-0.07f)\n                arcToRelative(4.814f, 4.814f, 0.0f, false, true, -3.51f, -1.41f)\n                lineToRelative(-20.99f, -21.63f)\n                curveToRelative(-0.07f, -0.08f, -0.15f, -0.15f, -0.22f, -0.22f)\n                arcToRelative(4.641f, 4.641f, 0.0f, false, true, 0.22f, -6.55f)\n                arcToRelative(5.169f, 5.169f, 0.0f, false, true, 7.08f, 0.0f)\n                lineToRelative(12.44f, 13.0f)\n                verticalLineToRelative(-33.52f)\n                arcToRelative(5.02f, 5.02f, 0.0f, false, true, 10.03f, 0.0f)\n                verticalLineToRelative(33.52f)\n                lineToRelative(12.43f, -13.0f)\n                arcToRelative(5.181f, 5.181f, 0.0f, false, true, 7.09f, 0.0f)\n                curveToRelative(0.07f, 0.07f, 0.14f, 0.14f, 0.22f, 0.22f)\n                arcTo(4.65f, 4.65f, 0.0f, false, true, 160.132f, 267.004f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF9f616a)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(590.258f, 653.281f)\n                lineToRelative(-12.26f, -0.001f)\n                lineToRelative(-5.832f, -47.288f)\n                lineToRelative(18.094f, 0.001f)\n                lineToRelative(-0.002f, 47.288f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(593.384f, 665.165f)\n                lineToRelative(-39.531f, -0.001f)\n                verticalLineToRelative(-0.5f)\n                arcToRelative(15.387f, 15.387f, 0.0f, false, true, 15.386f, -15.386f)\n                horizontalLineToRelative(0.001f)\n                lineToRelative(24.144f, 0.001f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF9f616a)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(497.121f, 652.877f)\n                lineToRelative(-11.844f, -3.167f)\n                lineToRelative(6.58f, -47.19f)\n                lineToRelative(17.48f, 4.674f)\n                lineToRelative(-12.216f, 45.683f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(497.072f, 665.165f)\n                lineToRelative(-38.189f, -10.212f)\n                lineToRelative(0.129f, -0.483f)\n                arcTo(15.387f, 15.387f, 0.0f, false, true, 477.851f, 643.58f)\n                lineToRelative(0.001f, 0.0f)\n                lineToRelative(23.324f, 6.237f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.onBackground),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(597.311f, 388.269f)\n                lineToRelative(10.269f, 11.93f)\n                lineToRelative(-13.281f, 242.443f)\n                lineToRelative(-28.368f, 0.0f)\n                lineToRelative(-14.303f, -186.551f)\n                lineToRelative(-44.346f, 191.554f)\n                lineToRelative(-29.492f, -7.233f)\n                lineToRelative(26.816f, -243.299f)\n                lineToRelative(92.705f, -8.844f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(511.462f, 231.744f)\n                lineToRelative(28.246f, -14.167f)\n                lineToRelative(43.437f, 0.764f)\n                lineToRelative(37.38f, 19.127f)\n                lineTo(599.257f, 343.681f)\n                lineToRelative(9.187f, 55.38f)\n                lineToRelative(-0.0f, 0.0f)\n                arcToRelative(226.532f, 226.532f, 0.0f, false, true, -108.335f, 0.892f)\n                lineToRelative(-0.284f, -0.068f)\n                reflectiveCurveToRelative(21.114f, -74.916f, 12.126f, -97.779f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF9f616a)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(593.177f, 175.136f)\n                arcToRelative(32.002f, 32.002f, 0.0f, true, false, 0.0f, 0.237f)\n                quadTo(593.178f, 175.254f, 593.177f, 175.136f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(546.845f, 156.85f)\n                arcToRelative(9.079f, 9.079f, 0.0f, false, true, 6.117f, -2.468f)\n                curveToRelative(3.419f, -0.111f, 8.542f, 1.103f, 10.722f, 3.883f)\n                curveToRelative(1.752f, 2.234f, 1.836f, 5.307f, 1.843f, 8.147f)\n                lineToRelative(0.019f, 7.836f)\n                curveToRelative(0.005f, 2.318f, 0.034f, 4.735f, 1.087f, 6.801f)\n                reflectiveCurveToRelative(3.471f, 3.634f, 5.68f, 2.93f)\n                curveToRelative(2.62f, -0.835f, 3.772f, -4.318f, 6.45f, -4.944f)\n                curveToRelative(2.011f, -0.47f, 4.077f, 0.999f, 4.956f, 2.868f)\n                arcToRelative(12.439f, 12.439f, 0.0f, false, true, 0.716f, 6.086f)\n                curveToRelative(-0.253f, 4.103f, -6.138f, 5.731f, -6.971f, 9.756f)\n                curveToRelative(-0.482f, 2.329f, -2.169f, 6.973f, 0.0f, 6.0f)\n                curveToRelative(10.0f, -1.0f, 14.389f, -6.841f, 18.966f, -12.339f)\n                lineToRelative(10.323f, -12.401f)\n                arcToRelative(12.121f, 12.121f, 0.0f, false, false, 2.659f, -4.302f)\n                arcToRelative(11.951f, 11.951f, 0.0f, false, false, 0.273f, -3.431f)\n                quadToRelative(-0.084f, -4.623f, -0.251f, -9.244f)\n                curveToRelative(-0.097f, -2.692f, -0.774f, -6.088f, -3.41f, -6.641f)\n                curveToRelative(-1.371f, -0.288f, -3.185f, 0.214f, -3.91f, -0.985f)\n                arcToRelative(2.721f, 2.721f, 0.0f, false, true, -0.124f, -1.911f)\n                curveToRelative(0.582f, -3.076f, 1.564f, -6.294f, 0.551f, -9.257f)\n                curveToRelative(-1.527f, -4.468f, -6.785f, -6.302f, -11.431f, -7.145f)\n                reflectiveCurveToRelative(-9.862f, -1.568f, -12.778f, -5.282f)\n                arcToRelative(40.501f, 40.501f, 0.0f, false, false, -2.536f, -3.565f)\n                arcToRelative(9.956f, 9.956f, 0.0f, false, false, -4.755f, -2.398f)\n                arcToRelative(26.279f, 26.279f, 0.0f, false, false, -17.28f, 1.534f)\n                curveToRelative(-2.247f, 1.026f, -4.505f, 2.407f, -6.97f, 2.25f)\n                curveToRelative(-2.561f, -0.162f, -4.748f, -1.965f, -7.276f, -2.403f)\n                curveToRelative(-4.084f, -0.708f, -7.988f, 2.351f, -10.0f, 5.975f)\n                curveToRelative(-2.494f, 4.49f, -2.722f, 10.638f, 0.8f, 14.375f)\n                curveToRelative(1.757f, 1.864f, 4.38f, 3.145f, 5.109f, 5.601f)\n                curveToRelative(0.297f, 1.0f, 0.228f, 2.076f, 0.491f, 3.086f)\n                arcToRelative(5.57f, 5.57f, 0.0f, false, false, 4.489f, 3.884f)\n                curveTo(542.898f, 159.551f, 545.01f, 158.407f, 546.845f, 156.85f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF9f616a)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(507.563f, 309.185f)\n                arcToRelative(11.462f, 11.462f, 0.0f, false, false, 16.65f, 5.627f)\n                lineToRelative(57.353f, 30.318f)\n                lineToRelative(1.857f, -13.971f)\n                lineTo(527.695f, 298.296f)\n                arcToRelative(11.524f, 11.524f, 0.0f, false, false, -20.131f, 10.889f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF9f616a)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(583.992f, 311.6f)\n                arcToRelative(11.462f, 11.462f, 0.0f, false, true, -17.478f, 1.848f)\n                lineTo(503.917f, 330.483f)\n                lineToRelative(0.545f, -17.738f)\n                lineToRelative(62.269f, -16.174f)\n                arcToRelative(11.524f, 11.524f, 0.0f, false, true, 17.261f, 15.03f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(608.319f, 238.232f)\n                lineToRelative(12.205f, -0.765f)\n                reflectiveCurveToRelative(14.29f, 18.855f, 6.364f, 39.316f)\n                curveToRelative(0.0f, 0.0f, 1.373f, 73.499f, -30.276f, 70.48f)\n                reflectiveCurveToRelative(-41.65f, -3.019f, -41.65f, -3.019f)\n                lineToRelative(9.5f, -26.5f)\n                lineToRelative(21.253f, -6.562f)\n                reflectiveCurveToRelative(-6.55f, -28.894f, 5.849f, -40.916f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(520.187f, 237.587f)\n                lineToRelative(-1.725f, -8.843f)\n                reflectiveCurveToRelative(-25.44f, -0.598f, -30.47f, 37.951f)\n                curveToRelative(0.0f, 0.0f, -22.877f, 57.692f, -0.454f, 65.121f)\n                reflectiveCurveToRelative(47.089f, 0.0f, 47.089f, 0.0f)\n                lineToRelative(-1.858f, -25.442f)\n                lineToRelative(-24.673f, -5.035f)\n                reflectiveCurveToRelative(12.745f, -16.489f, 5.805f, -30.792f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(764.6f, 667.744f)\n                horizontalLineToRelative(-381.0f)\n                arcToRelative(1.0f, 1.0f, 0.0f, false, true, 0.0f, -2.0f)\n                horizontalLineToRelative(381.0f)\n                arcToRelative(1.0f, 1.0f, 0.0f, false, true, 0.0f, 2.0f)\n                close()\n            }\n        }\n        .build()\n}\n\n@Preview\n@Composable\nprivate fun Preview() {\n    val painter = rememberVectorPainter(DynamicColorImageVectors.download())\n    Image(painter, null)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/svg/drawablevectors/VideoFiles.kt",
    "content": "package com.junkfood.seal.ui.svg.drawablevectors\n\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.PathFillType.Companion.NonZero\nimport androidx.compose.ui.graphics.SolidColor\nimport androidx.compose.ui.graphics.StrokeCap.Companion.Butt\nimport androidx.compose.ui.graphics.StrokeJoin.Companion.Miter\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.graphics.vector.ImageVector.Builder\nimport androidx.compose.ui.graphics.vector.path\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\n\n@Composable\nfun DynamicColorImageVectors.videoFiles(): ImageVector {\n    return Builder(\n            name = \"VideoFiles\",\n            defaultWidth = 1008.9205.dp,\n            defaultHeight = 607.45.dp,\n            viewportWidth = 1008.9205f,\n            viewportHeight = 607.45f,\n        )\n        .apply {\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(1008.92f, 474.03f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, -15.26f, 15.42f)\n                lineTo(322.26f, 489.45f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, -15.26f, -15.42f)\n                lineTo(307.0f, 15.42f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, 15.26f, -15.42f)\n                lineTo(993.66f, 0.0f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, 15.26f, 15.42f)\n                verticalLineToRelative(0.0f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(1001.0f, 466.52f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, -14.91f, 14.91f)\n                lineTo(330.29f, 481.43f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, -14.91f, -14.91f)\n                lineTo(315.38f, 23.14f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, 14.91f, -14.91f)\n                horizontalLineToRelative(655.83f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, 14.88f, 14.91f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(350.43f, 27.48f)\n                horizontalLineToRelative(616.22f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, 8.85f)\n                verticalLineTo(451.61f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, 8.85f)\n                horizontalLineToRelative(-616.22f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, -8.85f)\n                verticalLineTo(36.33f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, -8.85f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(358.23f, 37.44f)\n                horizontalLineToRelative(599.95f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, 8.85f)\n                verticalLineTo(439.41f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, 8.85f)\n                horizontalLineToRelative(-599.95f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, -8.85f)\n                verticalLineTo(46.29f)\n                arcTo(8.85f, 8.85f, 0.0f, false, true, 358.23f, 37.44f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(781.84f, 310.53f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -6.85f, -1.46f)\n                arcToRelative(8.31f, 8.31f, 0.0f, false, true, -1.43f, -0.81f)\n                lineToRelative(-43.6f, -30.69f)\n                horizontalLineToRelative(0.0f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -7.16f, -13.79f)\n                lineTo(722.79f, 221.92f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, 7.16f, -13.79f)\n                lineToRelative(43.6f, -30.69f)\n                arcToRelative(8.31f, 8.31f, 0.0f, false, true, 1.43f, -0.81f)\n                arcTo(16.87f, 16.87f, 0.0f, false, true, 798.71f, 192.04f)\n                lineTo(798.71f, 293.66f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -16.87f, 16.87f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(684.26f, 318.76f)\n                lineTo(562.65f, 318.76f)\n                curveToRelative(-24.81f, -0.02f, -44.92f, -16.06f, -44.94f, -35.85f)\n                lineTo(517.71f, 202.79f)\n                curveToRelative(0.03f, -19.79f, 20.13f, -35.83f, 44.94f, -35.85f)\n                lineTo(684.57f, 166.94f)\n                curveToRelative(24.63f, 0.02f, 44.6f, 15.95f, 44.62f, 35.59f)\n                verticalLineToRelative(80.38f)\n                curveTo(729.17f, 302.7f, 709.07f, 318.74f, 684.26f, 318.76f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(900.88f, 386.81f)\n                moveToRelative(-36.17f, 0.0f)\n                arcToRelative(36.17f, 36.17f, 0.0f, true, true, 72.33f, 0.0f)\n                arcToRelative(36.17f, 36.17f, 0.0f, true, true, -72.33f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(919.66f, 386.17f)\n                lineToRelative(-28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, -1.12f, 0.65f)\n                verticalLineToRelative(33.29f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 1.12f, 0.65f)\n                lineToRelative(28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 0.0f, -1.3f)\n                lineToRelative(-28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, -1.12f, 0.65f)\n                verticalLineToRelative(33.29f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 1.12f, 0.65f)\n                lineToRelative(28.83f, -16.64f)\n                arcTo(0.75f, 0.75f, 0.0f, false, false, 919.66f, 386.17f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(853.92f, 529.03f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, -15.26f, 15.42f)\n                lineTo(167.26f, 544.45f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, -15.26f, -15.42f)\n                lineTo(152.0f, 70.42f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, 15.26f, -15.42f)\n                lineTo(838.66f, 55.0f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, 15.26f, 15.42f)\n                verticalLineToRelative(0.0f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(846.0f, 521.52f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, -14.91f, 14.91f)\n                lineTo(175.29f, 536.43f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, -14.91f, -14.91f)\n                lineTo(160.38f, 78.14f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, 14.91f, -14.91f)\n                lineTo(831.12f, 63.23f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, 14.88f, 14.91f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(195.43f, 82.48f)\n                horizontalLineToRelative(616.22f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, 8.85f)\n                verticalLineTo(506.61f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, 8.85f)\n                horizontalLineToRelative(-616.22f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, -8.85f)\n                verticalLineTo(91.33f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, -8.85f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(203.23f, 92.44f)\n                horizontalLineToRelative(599.95f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, 8.85f)\n                verticalLineTo(494.41f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, 8.85f)\n                horizontalLineToRelative(-599.95f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, -8.85f)\n                verticalLineTo(101.29f)\n                arcTo(8.85f, 8.85f, 0.0f, false, true, 203.23f, 92.44f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(626.84f, 365.53f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -6.85f, -1.46f)\n                arcToRelative(8.31f, 8.31f, 0.0f, false, true, -1.43f, -0.81f)\n                lineToRelative(-43.6f, -30.69f)\n                horizontalLineToRelative(0.0f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -7.16f, -13.79f)\n                lineTo(567.79f, 276.92f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, 7.16f, -13.79f)\n                lineToRelative(43.6f, -30.69f)\n                arcToRelative(8.31f, 8.31f, 0.0f, false, true, 1.43f, -0.81f)\n                arcTo(16.87f, 16.87f, 0.0f, false, true, 643.71f, 247.04f)\n                lineTo(643.71f, 348.66f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -16.87f, 16.87f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(529.26f, 373.76f)\n                lineTo(407.65f, 373.76f)\n                curveToRelative(-24.81f, -0.02f, -44.92f, -16.06f, -44.94f, -35.85f)\n                lineTo(362.71f, 257.79f)\n                curveToRelative(0.03f, -19.79f, 20.13f, -35.83f, 44.94f, -35.85f)\n                lineTo(529.57f, 221.94f)\n                curveToRelative(24.63f, 0.02f, 44.6f, 15.95f, 44.62f, 35.59f)\n                verticalLineToRelative(80.38f)\n                curveTo(574.17f, 357.7f, 554.07f, 373.74f, 529.26f, 373.76f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(745.88f, 441.81f)\n                moveToRelative(-36.17f, 0.0f)\n                arcToRelative(36.17f, 36.17f, 0.0f, true, true, 72.33f, 0.0f)\n                arcToRelative(36.17f, 36.17f, 0.0f, true, true, -72.33f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(764.66f, 441.17f)\n                lineToRelative(-28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, -1.12f, 0.65f)\n                verticalLineToRelative(33.29f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 1.12f, 0.65f)\n                lineTo(764.66f, 442.46f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 0.0f, -1.3f)\n                lineToRelative(-28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, -1.12f, 0.65f)\n                verticalLineToRelative(33.29f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 1.12f, 0.65f)\n                lineTo(764.66f, 442.46f)\n                arcTo(0.75f, 0.75f, 0.0f, false, false, 764.66f, 441.17f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(701.92f, 592.03f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, -15.26f, 15.42f)\n                lineTo(15.26f, 607.45f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, -15.26f, -15.42f)\n                lineTo(0.0f, 133.42f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, 15.26f, -15.42f)\n                lineTo(686.66f, 118.0f)\n                arcToRelative(15.34f, 15.34f, 0.0f, false, true, 15.26f, 15.42f)\n                verticalLineToRelative(0.0f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(694.0f, 584.52f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, -14.91f, 14.91f)\n                lineTo(23.29f, 599.43f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, -14.91f, -14.91f)\n                lineTo(8.38f, 141.14f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, 14.91f, -14.91f)\n                lineTo(679.12f, 126.23f)\n                arcToRelative(14.91f, 14.91f, 0.0f, false, true, 14.88f, 14.91f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(43.43f, 145.48f)\n                horizontalLineToRelative(616.22f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, 8.85f)\n                verticalLineTo(569.61f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, 8.85f)\n                horizontalLineToRelative(-616.22f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, -8.85f)\n                verticalLineTo(154.33f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, -8.85f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(51.23f, 155.44f)\n                horizontalLineToRelative(599.95f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, 8.85f, 8.85f)\n                verticalLineTo(557.41f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, 8.85f)\n                horizontalLineToRelative(-599.95f)\n                arcToRelative(8.85f, 8.85f, 0.0f, false, true, -8.85f, -8.85f)\n                verticalLineTo(164.29f)\n                arcTo(8.85f, 8.85f, 0.0f, false, true, 51.23f, 155.44f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(474.84f, 428.53f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -6.85f, -1.46f)\n                arcToRelative(8.31f, 8.31f, 0.0f, false, true, -1.43f, -0.81f)\n                lineToRelative(-43.6f, -30.69f)\n                horizontalLineToRelative(0.0f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -7.16f, -13.79f)\n                lineTo(415.79f, 339.92f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, 7.16f, -13.79f)\n                lineToRelative(43.6f, -30.69f)\n                arcToRelative(8.31f, 8.31f, 0.0f, false, true, 1.43f, -0.81f)\n                arcTo(16.87f, 16.87f, 0.0f, false, true, 491.71f, 310.04f)\n                lineTo(491.71f, 411.66f)\n                arcToRelative(16.87f, 16.87f, 0.0f, false, true, -16.87f, 16.87f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.inversePrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(377.26f, 436.76f)\n                lineTo(255.65f, 436.76f)\n                curveToRelative(-24.81f, -0.02f, -44.92f, -16.06f, -44.94f, -35.85f)\n                lineTo(210.71f, 320.79f)\n                curveToRelative(0.03f, -19.79f, 20.13f, -35.83f, 44.94f, -35.85f)\n                lineTo(377.57f, 284.94f)\n                curveToRelative(24.63f, 0.02f, 44.6f, 15.95f, 44.62f, 35.59f)\n                verticalLineToRelative(80.38f)\n                curveTo(422.17f, 420.7f, 402.07f, 436.74f, 377.26f, 436.76f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.outline),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(593.88f, 504.81f)\n                moveToRelative(-36.17f, 0.0f)\n                arcToRelative(36.17f, 36.17f, 0.0f, true, true, 72.33f, 0.0f)\n                arcToRelative(36.17f, 36.17f, 0.0f, true, true, -72.33f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(612.66f, 504.17f)\n                lineToRelative(-28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, -1.12f, 0.65f)\n                verticalLineToRelative(33.29f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 1.12f, 0.65f)\n                lineTo(612.66f, 505.46f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 0.0f, -1.3f)\n                lineToRelative(-28.83f, -16.64f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, -1.12f, 0.65f)\n                verticalLineToRelative(33.29f)\n                arcToRelative(0.75f, 0.75f, 0.0f, false, false, 1.12f, 0.65f)\n                lineTo(612.66f, 505.46f)\n                arcTo(0.75f, 0.75f, 0.0f, false, false, 612.66f, 504.17f)\n                close()\n            }\n        }\n        .build()\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/svg/drawablevectors/VideoSteaming.kt",
    "content": "package com.junkfood.seal.ui.svg.drawablevectors\n\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.PathFillType.Companion.NonZero\nimport androidx.compose.ui.graphics.SolidColor\nimport androidx.compose.ui.graphics.StrokeCap.Companion.Butt\nimport androidx.compose.ui.graphics.StrokeJoin.Companion.Miter\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.graphics.vector.ImageVector.Builder\nimport androidx.compose.ui.graphics.vector.path\nimport androidx.compose.ui.unit.dp\nimport com.junkfood.seal.ui.svg.DynamicColorImageVectors\n\n@Composable\nfun DynamicColorImageVectors.videoSteaming(): ImageVector {\n    return Builder(\n            name = \"VideoSteaming\",\n            defaultWidth = 766.0.dp,\n            defaultHeight = 663.78.dp,\n            viewportWidth = 766.0f,\n            viewportHeight = 663.78f,\n        )\n        .apply {\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(75.871f, 614.538f)\n                curveToRelative(-6.979f, 23.313f, 3.852f, 47.148f, 3.852f, 47.148f)\n                reflectiveCurveToRelative(22.147f, -13.963f, 29.126f, -37.276f)\n                reflectiveCurveToRelative(-3.852f, -47.148f, -3.852f, -47.148f)\n                reflectiveCurveTo(82.85f, 591.225f, 75.871f, 614.538f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(86.467f, 615.169f)\n                curveToRelative(5.874f, 23.616f, -6.068f, 46.915f, -6.068f, 46.915f)\n                reflectiveCurveToRelative(-21.465f, -14.99f, -27.339f, -38.606f)\n                reflectiveCurveToRelative(6.068f, -46.915f, 6.068f, -46.915f)\n                reflectiveCurveTo(80.594f, 591.553f, 86.467f, 615.169f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb8b8)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(435.535f, 638.619f)\n                lineToRelative(4.442f, -11.427f)\n                lineToRelative(-41.96f, -22.573f)\n                lineToRelative(-6.556f, 16.865f)\n                lineToRelative(44.074f, 17.135f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(459.337f, 608.81f)\n                arcToRelative(15.379f, 15.379f, 0.0f, false, false, -19.915f, 8.766f)\n                lineToRelative(-2.997f, 7.703f)\n                lineToRelative(-4.62f, 11.89f)\n                lineToRelative(-1.129f, 2.915f)\n                lineToRelative(14.806f, 5.76f)\n                lineToRelative(14.321f, -36.849f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(431.806f, 616.628f)\n                lineToRelative(-1.932f, 5.124f)\n                lineToRelative(-4.822f, 12.788f)\n                lineToRelative(-0.116f, 0.32f)\n                curveToRelative(-12.285f, 1.578f, -25.752f, -1.516f, -38.209f, -6.323f)\n                arcToRelative(155.312f, 155.312f, 0.0f, false, true, -14.624f, -6.526f)\n                curveToRelative(-7.044f, -3.559f, -13.352f, -7.316f, -18.383f, -10.529f)\n                curveToRelative(-7.576f, -4.862f, -12.26f, -8.513f, -12.26f, -8.513f)\n                reflectiveCurveToRelative(-1.238f, 1.118f, -3.477f, 3.036f)\n                curveToRelative(-3.002f, 2.568f, -7.798f, 6.578f, -13.873f, 11.299f)\n                quadToRelative(-3.476f, 2.72f, -7.465f, 5.69f)\n                curveToRelative(-19.601f, 14.539f, -44.756f, -24.256f, -44.756f, -24.256f)\n                reflectiveCurveToRelative(7.075f, -4.504f, 8.923f, -5.379f)\n                curveToRelative(5.951f, -2.816f, 19.932f, -9.459f, 31.994f, -15.363f)\n                curveToRelative(6.214f, -3.046f, 11.912f, -5.903f, 15.737f, -7.932f)\n                curveToRelative(13.546f, -7.212f, 30.384f, 6.435f, 30.384f, 6.435f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF000000)),\n                stroke = null,\n                fillAlpha = 0.14f,\n                strokeAlpha = 0.14f,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(431.806f, 616.628f)\n                lineToRelative(-1.932f, 5.124f)\n                lineToRelative(-4.822f, 12.788f)\n                lineToRelative(-0.116f, 0.32f)\n                curveToRelative(-12.285f, 1.578f, -25.752f, -1.516f, -38.209f, -6.323f)\n                arcToRelative(155.312f, 155.312f, 0.0f, false, true, -14.624f, -6.526f)\n                curveToRelative(-7.044f, -3.559f, -13.352f, -7.316f, -18.383f, -10.529f)\n                curveToRelative(-7.576f, -4.862f, -12.26f, -8.513f, -12.26f, -8.513f)\n                reflectiveCurveToRelative(-1.238f, 1.118f, -3.477f, 3.036f)\n                curveToRelative(-3.002f, 2.568f, -7.798f, 6.578f, -13.873f, 11.299f)\n                quadToRelative(-3.476f, 2.72f, -7.465f, 5.69f)\n                curveToRelative(-19.601f, 14.539f, -44.756f, -24.256f, -44.756f, -24.256f)\n                reflectiveCurveToRelative(7.075f, -4.504f, 8.923f, -5.379f)\n                curveToRelative(5.951f, -2.816f, 19.932f, -9.459f, 31.994f, -15.363f)\n                curveToRelative(6.214f, -3.046f, 11.912f, -5.903f, 15.737f, -7.932f)\n                curveToRelative(13.546f, -7.212f, 30.384f, 6.435f, 30.384f, 6.435f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.tertiaryContainer),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(183.579f, 172.312f)\n                moveToRelative(-172.312f, 0.0f)\n                arcToRelative(172.312f, 172.312f, 0.0f, true, true, 344.623f, 0.0f)\n                arcToRelative(172.312f, 172.312f, 0.0f, true, true, -344.623f, 0.0f)\n            }\n            path(\n                fill = SolidColor(Color(0xFF000000)),\n                stroke = null,\n                fillAlpha = 0.2f,\n                strokeAlpha = 0.2f,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(56.349f, 57.221f)\n                arcTo(172.325f, 172.325f, 0.0f, false, false, 343.472f, 239.591f)\n                arcTo(172.327f, 172.327f, 0.0f, true, true, 56.349f, 57.221f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(184.052f, 172.311f)\n                lineToRelative(0.474f, 0.0f)\n                lineToRelative(8.521f, 488.532f)\n                lineToRelative(-17.989f, 0.0f)\n                lineToRelative(8.994f, -488.532f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(153.557f, 401.412f)\n                lineToRelative(3.97f, -7.54f)\n                lineToRelative(28.484f, 14.996f)\n                lineToRelative(-3.97f, 7.54f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(765.0f, 662.788f)\n                lineTo(1.0f, 662.788f)\n                arcToRelative(1.0f, 1.0f, 0.0f, false, true, 0.0f, -2.0f)\n                lineTo(765.0f, 660.788f)\n                arcToRelative(1.0f, 1.0f, 0.0f, false, true, 0.0f, 2.0f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(235.746f, 509.077f)\n                horizontalLineToRelative(-58.0f)\n                arcToRelative(4.505f, 4.505f, 0.0f, false, true, -4.5f, -4.5f)\n                verticalLineToRelative(-25.0f)\n                arcToRelative(33.5f, 33.5f, 0.0f, false, true, 67.0f, 0.0f)\n                verticalLineToRelative(25.0f)\n                arcTo(4.505f, 4.505f, 0.0f, false, true, 235.746f, 509.077f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb8b8)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(290.904f, 540.478f)\n                arcToRelative(9.377f, 9.377f, 0.0f, false, false, -7.186f, 12.454f)\n                lineToRelative(-15.772f, 14.506f)\n                lineToRelative(6.478f, 11.734f)\n                lineToRelative(21.985f, -20.798f)\n                arcToRelative(9.428f, 9.428f, 0.0f, false, false, -5.505f, -17.897f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(243.448f, 606.43f)\n                quadToRelative(-1.069f, 0.0f, -2.14f, -0.092f)\n                arcTo(25.199f, 25.199f, 0.0f, false, true, 221.01f, 592.782f)\n                lineToRelative(-25.267f, -48.633f)\n                arcToRelative(13.954f, 13.954f, 0.0f, false, true, 24.13f, -13.965f)\n                lineToRelative(23.311f, 52.304f)\n                lineToRelative(31.719f, -25.772f)\n                lineToRelative(18.366f, 7.149f)\n                lineToRelative(-31.016f, 34.242f)\n                arcTo(25.485f, 25.485f, 0.0f, false, true, 243.448f, 606.43f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF3f3d56)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(336.913f, 531.285f)\n                lineToRelative(-28.102f, -28.102f)\n                arcToRelative(5.242f, 5.242f, 0.0f, false, false, -7.413f, 0.0f)\n                lineToRelative(-25.28f, 25.28f)\n                arcToRelative(5.242f, 5.242f, 0.0f, false, false, 0.0f, 7.413f)\n                lineToRelative(26.256f, 26.256f)\n                arcToRelative(5.242f, 5.242f, 0.0f, false, false, 7.133f, 0.26f)\n                lineToRelative(27.125f, -23.435f)\n                arcToRelative(5.242f, 5.242f, 0.0f, false, false, 0.54f, -7.393f)\n                quadTo(337.049f, 531.42f, 336.913f, 531.285f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(332.935f, 536.213f)\n                lineToRelative(-28.926f, -28.925f)\n                lineToRelative(-23.871f, 23.871f)\n                lineToRelative(27.803f, 27.802f)\n                lineToRelative(24.994f, -22.748f)\n                close()\n            }\n\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(312.209f, 533.077f)\n                moveToRelative(-0.87f, 0.0f)\n                arcToRelative(0.87f, 0.87f, 0.0f, true, true, 1.74f, 0.0f)\n                arcToRelative(0.87f, 0.87f, 0.0f, true, true, -1.74f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(312.584f, 530.935f)\n                moveToRelative(-0.435f, 0.0f)\n                arcToRelative(0.435f, 0.435f, 0.0f, true, true, 0.87f, 0.0f)\n                arcToRelative(0.435f, 0.435f, 0.0f, true, true, -0.87f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(306.328f, 524.277f)\n                moveToRelative(-0.435f, 0.0f)\n                arcToRelative(0.435f, 0.435f, 0.0f, true, true, 0.87f, 0.0f)\n                arcToRelative(0.435f, 0.435f, 0.0f, true, true, -0.87f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceContainerHighest),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(305.953f, 526.419f)\n                moveToRelative(-0.87f, 0.0f)\n                arcToRelative(0.87f, 0.87f, 0.0f, true, true, 1.74f, 0.0f)\n                arcToRelative(0.87f, 0.87f, 0.0f, true, true, -1.74f, 0.0f)\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb8b8)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(431.99f, 654.69f)\n                lineToRelative(5.307f, -11.051f)\n                lineToRelative(-40.101f, -25.73f)\n                lineToRelative(-7.833f, 16.311f)\n                lineToRelative(42.627f, 20.47f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(458.012f, 626.798f)\n                arcToRelative(15.379f, 15.379f, 0.0f, false, false, -20.53f, 7.21f)\n                lineToRelative(-3.58f, 7.45f)\n                lineToRelative(-5.52f, 11.5f)\n                lineToRelative(-1.35f, 2.82f)\n                lineToRelative(14.32f, 6.88f)\n                lineToRelative(17.11f, -35.64f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(429.962f, 632.478f)\n                lineToRelative(-2.32f, 4.96f)\n                lineToRelative(-5.79f, 12.38f)\n                lineToRelative(-0.14f, 0.31f)\n                curveToRelative(-12.37f, 0.63f, -25.56f, -3.49f, -37.61f, -9.24f)\n                arcToRelative(155.312f, 155.312f, 0.0f, false, true, -14.08f, -7.63f)\n                curveToRelative(-6.75f, -4.09f, -12.75f, -8.32f, -17.52f, -11.91f)\n                curveToRelative(-7.18f, -5.43f, -11.57f, -9.43f, -11.57f, -9.43f)\n                reflectiveCurveToRelative(-1.32f, 1.02f, -3.7f, 2.76f)\n                curveToRelative(-3.19f, 2.33f, -8.28f, 5.96f, -14.7f, 10.2f)\n                quadToRelative(-3.675f, 2.445f, -7.88f, 5.1f)\n                curveToRelative(-20.66f, 12.99f, -50.04f, 28.81f, -75.03f, 32.15f)\n                curveToRelative(-43.89f, 5.87f, -33.56f, -52.7f, -33.56f, -52.7f)\n                lineToRelative(34.93f, -18.14f)\n                lineToRelative(14.83f, 3.01f)\n                lineToRelative(16.51f, 3.34f)\n                lineToRelative(5.85f, 1.19f)\n                reflectiveCurveToRelative(1.11f, -0.42f, 3.02f, -1.15f)\n                curveToRelative(6.15f, -2.35f, 20.6f, -7.9f, 33.08f, -12.86f)\n                curveToRelative(6.43f, -2.56f, 12.33f, -4.97f, 16.3f, -6.7f)\n                curveToRelative(14.06f, -6.15f, 29.8f, 8.75f, 29.8f, 8.75f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb8b8)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(142.145f, 663.526f)\n                arcToRelative(9.377f, 9.377f, 0.0f, false, false, 6.532f, -12.809f)\n                lineToRelative(15.0f, -15.302f)\n                lineToRelative(-7.076f, -11.384f)\n                lineToRelative(-20.88f, 21.907f)\n                arcToRelative(9.428f, 9.428f, 0.0f, false, false, 6.423f, 17.588f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFFffb8b8)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(214.958f, 486.807f)\n                moveToRelative(-23.386f, 0.0f)\n                arcToRelative(23.386f, 23.386f, 0.0f, true, true, 46.772f, 0.0f)\n                arcToRelative(23.386f, 23.386f, 0.0f, true, true, -46.772f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(184.533f, 551.724f)\n                lineTo(204.905f, 609.48f)\n                lineToRelative(-0.122f, 0.202f)\n                curveToRelative(-2.833f, 4.684f, -3.76f, 8.462f, -2.678f, 10.926f)\n                arcToRelative(4.761f, 4.761f, 0.0f, false, false, 3.019f, 2.604f)\n                lineToRelative(48.209f, -33.697f)\n                lineToRelative(-1.688f, -13.505f)\n                lineToRelative(0.094f, -0.151f)\n                curveToRelative(4.66f, -7.456f, 6.168f, -14.208f, 4.485f, -20.067f)\n                curveToRelative(-2.184f, -7.604f, -9.125f, -11.056f, -9.195f, -11.09f)\n                lineToRelative(-0.168f, -0.132f)\n                lineTo(222.815f, 515.304f)\n                lineTo(190.673f, 521.014f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.surfaceVariant),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(153.553f, 653.099f)\n                lineTo(139.906f, 636.302f)\n                lineToRelative(32.899f, -54.31f)\n                lineToRelative(15.339f, -47.413f)\n                lineToRelative(0.476f, 0.154f)\n                lineToRelative(-0.476f, -0.154f)\n                arcToRelative(19.047f, 19.047f, 0.0f, true, true, 33.964f, 16.437f)\n                lineToRelative(-28.16f, 42.189f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(248.171f, 482.077f)\n                lineTo(212.706f, 482.077f)\n                lineToRelative(-0.364f, -5.092f)\n                lineToRelative(-1.818f, 5.092f)\n                horizontalLineToRelative(-5.461f)\n                lineToRelative(-0.721f, -10.092f)\n                lineToRelative(-3.604f, 10.092f)\n                lineTo(190.171f, 482.077f)\n                verticalLineToRelative(-0.5f)\n                arcToRelative(26.53f, 26.53f, 0.0f, false, true, 26.5f, -26.5f)\n                horizontalLineToRelative(5.0f)\n                arcToRelative(26.53f, 26.53f, 0.0f, false, true, 26.5f, 26.5f)\n                close()\n            }\n            path(\n                fill = SolidColor(Color(0xFF2f2e41)),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(212.415f, 513.743f)\n                arcToRelative(4.597f, 4.597f, 0.0f, false, true, -0.796f, -0.07f)\n                lineToRelative(-25.969f, -4.582f)\n                lineTo(185.65f, 466.171f)\n                lineTo(214.237f, 466.171f)\n                lineToRelative(-0.708f, 0.825f)\n                curveToRelative(-9.847f, 11.484f, -2.428f, 30.106f, 2.87f, 40.185f)\n                arcToRelative(4.433f, 4.433f, 0.0f, false, true, -0.352f, 4.707f)\n                arcTo(4.482f, 4.482f, 0.0f, false, true, 212.415f, 513.743f)\n                close()\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.primary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(588.139f, 324.689f)\n                moveToRelative(-114.0f, 0.0f)\n                arcToRelative(114.0f, 114.0f, 0.0f, true, true, 228.0f, 0.0f)\n                arcToRelative(114.0f, 114.0f, 0.0f, true, true, -228.0f, 0.0f)\n            }\n            path(\n                fill = SolidColor(MaterialTheme.colorScheme.onPrimary),\n                stroke = null,\n                strokeLineWidth = 0.0f,\n                strokeLineCap = Butt,\n                strokeLineJoin = Miter,\n                strokeLineMiter = 4.0f,\n                pathFillType = NonZero,\n            ) {\n                moveTo(558.992f, 280.378f)\n                verticalLineToRelative(96.991f)\n                arcToRelative(2.497f, 2.497f, 0.0f, false, false, 3.74f, 2.302f)\n                lineToRelative(76.883f, -48.496f)\n                arcToRelative(2.748f, 2.748f, 0.0f, false, false, 0.0f, -4.571f)\n                lineToRelative(-76.883f, -48.496f)\n                arcToRelative(2.474f, 2.474f, 0.0f, false, false, -3.74f, 2.27f)\n                close()\n            }\n        }\n        .build()\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/theme/ColorScheme.kt",
    "content": "package com.junkfood.seal.ui.theme\n\nimport androidx.compose.material3.ColorScheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.Immutable\nimport androidx.compose.runtime.ReadOnlyComposable\nimport androidx.compose.runtime.Stable\nimport androidx.compose.ui.graphics.Color\nimport com.junkfood.seal.ui.common.LocalDarkTheme\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.kyant.monet.TonalPalettes\nimport com.kyant.monet.TonalPalettes.Companion.toTonalPalettes\nimport io.material.hct.Hct\n\n@Composable\nfun Number.autoDark(isDarkTheme: Boolean = LocalDarkTheme.current.isDarkTheme()): Double =\n    if (!isDarkTheme) this.toDouble()\n    else\n        when (this.toDouble()) {\n            6.0 -> 98.0\n            10.0 -> 99.0\n            20.0 -> 95.0\n            25.0 -> 90.0\n            30.0 -> 90.0\n            40.0 -> 80.0\n            50.0 -> 60.0\n            60.0 -> 50.0\n            70.0 -> 40.0\n            80.0 -> 40.0\n            90.0 -> 30.0\n            95.0 -> 20.0\n            98.0 -> 10.0\n            99.0 -> 10.0\n            100.0 -> 20.0\n            else -> this.toDouble()\n        }\n\n@Deprecated(\n    message = \"Deprecated\",\n    replaceWith =\n        ReplaceWith(\n            \"LocalFixedColorRoles.current\",\n            imports = arrayOf(\"com.junkfood.seal.ui.common.LocalFixedColorRoles\"),\n        ),\n)\nobject FixedAccentColors {\n    val primaryFixed: Color\n        @Composable get() = LocalFixedColorRoles.current.primaryFixed\n\n    val primaryFixedDim: Color\n        @Composable get() = LocalFixedColorRoles.current.primaryFixedDim\n\n    val onPrimaryFixed: Color\n        @Composable get() = LocalFixedColorRoles.current.onPrimaryFixed\n\n    val onPrimaryFixedVariant: Color\n        @Composable get() = LocalFixedColorRoles.current.onPrimaryFixedVariant\n\n    val secondaryFixed: Color\n        @Composable get() = LocalFixedColorRoles.current.secondaryFixed\n\n    val secondaryFixedDim: Color\n        @Composable get() = LocalFixedColorRoles.current.secondaryFixedDim\n\n    val onSecondaryFixed: Color\n        @Composable get() = LocalFixedColorRoles.current.onSecondaryFixed\n\n    val onSecondaryFixedVariant: Color\n        @Composable get() = LocalFixedColorRoles.current.onSecondaryFixedVariant\n\n    val tertiaryFixed: Color\n        @Composable get() = LocalFixedColorRoles.current.tertiaryFixed\n\n    val tertiaryFixedDim: Color\n        @Composable get() = LocalFixedColorRoles.current.tertiaryFixedDim\n\n    val onTertiaryFixed: Color\n        @Composable get() = LocalFixedColorRoles.current.onTertiaryFixed\n\n    val onTertiaryFixedVariant: Color\n        @Composable get() = LocalFixedColorRoles.current.onTertiaryFixedVariant\n}\n\n@Immutable\ndata class FixedColorRoles(\n    val primaryFixed: Color,\n    val primaryFixedDim: Color,\n    val onPrimaryFixed: Color,\n    val onPrimaryFixedVariant: Color,\n    val secondaryFixed: Color,\n    val secondaryFixedDim: Color,\n    val onSecondaryFixed: Color,\n    val onSecondaryFixedVariant: Color,\n    val tertiaryFixed: Color,\n    val tertiaryFixedDim: Color,\n    val onTertiaryFixed: Color,\n    val onTertiaryFixedVariant: Color,\n) {\n    companion object {\n        internal val unspecified =\n            FixedColorRoles(\n                primaryFixed = Color.Unspecified,\n                primaryFixedDim = Color.Unspecified,\n                onPrimaryFixed = Color.Unspecified,\n                onPrimaryFixedVariant = Color.Unspecified,\n                secondaryFixed = Color.Unspecified,\n                secondaryFixedDim = Color.Unspecified,\n                onSecondaryFixed = Color.Unspecified,\n                onSecondaryFixedVariant = Color.Unspecified,\n                tertiaryFixed = Color.Unspecified,\n                tertiaryFixedDim = Color.Unspecified,\n                onTertiaryFixed = Color.Unspecified,\n                onTertiaryFixedVariant = Color.Unspecified,\n            )\n\n        @Stable\n        internal fun fromTonalPalettes(palettes: TonalPalettes): FixedColorRoles {\n            return with(palettes) {\n                FixedColorRoles(\n                    primaryFixed = accent1(90.toDouble()),\n                    primaryFixedDim = accent1(80.toDouble()),\n                    onPrimaryFixed = accent1(10.toDouble()),\n                    onPrimaryFixedVariant = accent1(30.toDouble()),\n                    secondaryFixed = accent2(90.toDouble()),\n                    secondaryFixedDim = accent2(80.toDouble()),\n                    onSecondaryFixed = accent2(10.toDouble()),\n                    onSecondaryFixedVariant = accent2(30.toDouble()),\n                    tertiaryFixed = accent3(90.toDouble()),\n                    tertiaryFixedDim = accent3(80.toDouble()),\n                    onTertiaryFixed = accent3(10.toDouble()),\n                    onTertiaryFixedVariant = accent3(30.toDouble()),\n                )\n            }\n        }\n\n        @Stable\n        internal fun fromColorSchemes(\n            lightColors: ColorScheme,\n            darkColors: ColorScheme,\n        ): FixedColorRoles {\n            return FixedColorRoles(\n                primaryFixed = lightColors.primaryContainer,\n                onPrimaryFixed = lightColors.onPrimaryContainer,\n                onPrimaryFixedVariant = darkColors.primaryContainer,\n                secondaryFixed = lightColors.secondaryContainer,\n                onSecondaryFixed = lightColors.onSecondaryContainer,\n                onSecondaryFixedVariant = darkColors.secondaryContainer,\n                tertiaryFixed = lightColors.tertiaryContainer,\n                onTertiaryFixed = lightColors.onTertiaryContainer,\n                onTertiaryFixedVariant = darkColors.tertiaryContainer,\n                primaryFixedDim = darkColors.primary,\n                secondaryFixedDim = darkColors.secondary,\n                tertiaryFixedDim = darkColors.tertiary,\n            )\n        }\n    }\n}\n\nconst val DEFAULT_SEED_COLOR = 0xa3d48d\n\n/**\n * @return a [Color] generated using [Hct] algorithm, harmonized with `primary` color\n * @receiver Seed number used for generating color\n */\n@Composable\n@ReadOnlyComposable\nfun Int.generateLabelColor(): Color =\n    Color(Hct.from(hue = (this % 360).toDouble(), chroma = 36.0, tone = 80.0).toInt())\n        .harmonizeWithPrimary()\n\n/**\n * @return a [Color] generated using [Hct] algorithm, harmonized with `primary` color\n * @receiver Seed number used for generating color\n */\n@Composable\n@ReadOnlyComposable\nfun Int.generateOnLabelColor(): Color =\n    Color(Hct.from(hue = (this % 360).toDouble(), chroma = 36.0, tone = 20.0).toInt())\n        .harmonizeWithPrimary()\n\nval ErrorTonalPalettes = Color.Red.toTonalPalettes()\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/theme/Shape.kt",
    "content": "package com.junkfood.seal.ui.theme\n\nimport androidx.compose.material3.Shapes\n\nval Shapes = Shapes()\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/theme/Theme.kt",
    "content": "package com.junkfood.seal.ui.theme\n\nimport android.os.Build\nimport android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS\nimport androidx.compose.foundation.isSystemInDarkTheme\nimport androidx.compose.material3.LocalTextStyle\nimport androidx.compose.material3.MaterialTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.CompositionLocalProvider\nimport androidx.compose.runtime.LaunchedEffect\nimport androidx.compose.runtime.ReadOnlyComposable\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.toArgb\nimport androidx.compose.ui.platform.LocalView\nimport androidx.compose.ui.text.style.LineBreak\nimport androidx.compose.ui.text.style.TextDirection\nimport com.google.android.material.color.MaterialColors\nimport com.junkfood.seal.ui.common.LocalFixedColorRoles\nimport com.kyant.monet.LocalTonalPalettes\nimport com.kyant.monet.dynamicColorScheme\n\nfun Color.applyOpacity(enabled: Boolean): Color {\n    return if (enabled) this else this.copy(alpha = 0.62f)\n}\n\n@Composable\n@ReadOnlyComposable\nfun Color.harmonizeWith(other: Color) =\n    Color(MaterialColors.harmonize(this.toArgb(), other.toArgb()))\n\n@Composable\n@ReadOnlyComposable\nfun Color.harmonizeWithPrimary(): Color =\n    this.harmonizeWith(other = MaterialTheme.colorScheme.primary)\n\n@Composable\nfun SealTheme(\n    darkTheme: Boolean = isSystemInDarkTheme(),\n    isHighContrastModeEnabled: Boolean = false,\n    content: @Composable () -> Unit,\n) {\n    val view = LocalView.current\n\n    LaunchedEffect(darkTheme) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n            if (darkTheme) {\n                view.windowInsetsController?.setSystemBarsAppearance(\n                    0,\n                    APPEARANCE_LIGHT_STATUS_BARS,\n                )\n            } else {\n                view.windowInsetsController?.setSystemBarsAppearance(\n                    APPEARANCE_LIGHT_STATUS_BARS,\n                    APPEARANCE_LIGHT_STATUS_BARS,\n                )\n            }\n        }\n    }\n\n    val colorScheme =\n        dynamicColorScheme(!darkTheme).run {\n            if (isHighContrastModeEnabled && darkTheme)\n                copy(\n                    surface = Color.Black,\n                    background = Color.Black,\n                    surfaceContainerLowest = Color.Black,\n                    surfaceContainerLow = surfaceContainerLowest,\n                    surfaceContainer = surfaceContainerLow,\n                    surfaceContainerHigh = surfaceContainerLow,\n                    surfaceContainerHighest = surfaceContainer,\n                )\n            else this\n        }\n\n    val textStyle =\n        LocalTextStyle.current.copy(\n            lineBreak = LineBreak.Paragraph,\n            textDirection = TextDirection.Content,\n        )\n\n    val tonalPalettes = LocalTonalPalettes.current\n\n    CompositionLocalProvider(\n        LocalFixedColorRoles provides FixedColorRoles.fromTonalPalettes(tonalPalettes),\n        LocalTextStyle provides textStyle,\n    ) {\n        MaterialTheme(\n            colorScheme = colorScheme,\n            typography = Typography,\n            shapes = Shapes,\n            content = content,\n        )\n    }\n}\n\n@Composable\n@Deprecated(\"Use SealTheme instead\", replaceWith = ReplaceWith(\"SealTheme(content)\"))\nfun PreviewThemeLight(content: @Composable () -> Unit) {\n    SealTheme(darkTheme = false, content = content)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/ui/theme/Type.kt",
    "content": "@file:OptIn(ExperimentalTextApi::class, ExperimentalTextApi::class, ExperimentalTextApi::class)\n\npackage com.junkfood.seal.ui.theme\n\nimport androidx.compose.material3.Typography\nimport androidx.compose.ui.text.ExperimentalTextApi\nimport androidx.compose.ui.text.TextStyle\nimport androidx.compose.ui.text.style.LineBreak\nimport androidx.compose.ui.text.style.TextDirection\n\nval Typography =\n    Typography().run {\n        copy(\n            bodyLarge = bodyLarge.applyLinebreak().applyTextDirection(),\n            bodyMedium = bodyMedium.applyLinebreak().applyTextDirection(),\n            bodySmall = bodySmall.applyLinebreak().applyTextDirection(),\n            titleLarge = titleLarge.applyTextDirection(),\n            titleMedium = titleMedium.applyTextDirection(),\n            titleSmall = titleSmall.applyTextDirection(),\n            headlineSmall = headlineSmall.applyTextDirection(),\n            headlineMedium = headlineMedium.applyTextDirection(),\n            headlineLarge = headlineLarge.applyTextDirection(),\n            displaySmall = displaySmall.applyTextDirection(),\n            displayMedium = displayMedium.applyTextDirection(),\n            displayLarge = displayLarge.applyTextDirection(),\n            labelLarge = labelLarge.applyTextDirection(),\n            labelMedium = labelMedium.applyTextDirection(),\n            labelSmall = labelSmall.applyTextDirection(),\n        )\n    }\n\nprivate fun TextStyle.applyLinebreak(): TextStyle = this.copy(lineBreak = LineBreak.Paragraph)\n\nprivate fun TextStyle.applyTextDirection(): TextStyle =\n    this.copy(textDirection = TextDirection.Content)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/DatabaseUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport androidx.room.Room\nimport com.junkfood.seal.App.Companion.applicationScope\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.database.AppDatabase\nimport com.junkfood.seal.database.backup.Backup\nimport com.junkfood.seal.database.backup.BackupUtil.BackupType\nimport com.junkfood.seal.database.backup.BackupUtil.decodeToBackup\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.CookieProfile\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.database.objects.OptionShortcut\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\n\nobject DatabaseUtil {\n    private const val DATABASE_NAME = \"app_database\"\n    private val db = Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME).build()\n    private val dao = db.videoInfoDao()\n\n    fun insertInfo(vararg infoList: DownloadedVideoInfo) {\n        applicationScope.launch(Dispatchers.IO) {\n            infoList.forEach { dao.insertInfoDistinctByPath(it) }\n        }\n    }\n\n    init {\n        applicationScope.launch {\n            getTemplateFlow().collect {\n                if (it.isEmpty()) PreferenceUtil.initializeTemplateSample()\n            }\n        }\n    }\n\n    fun getDownloadHistoryFlow() = dao.getDownloadHistoryFlow()\n\n    private suspend fun getDownloadHistory() = dao.getDownloadHistory()\n\n    fun getTemplateFlow() = dao.getTemplateFlow()\n\n    fun getCookiesFlow() = dao.getCookieProfileFlow()\n\n    fun getShortcuts() = dao.getOptionShortcuts()\n\n    suspend fun deleteShortcut(shortcut: OptionShortcut) = dao.deleteShortcut(shortcut)\n\n    suspend fun insertShortcut(shortcut: OptionShortcut) = dao.insertShortcut(shortcut)\n\n    suspend fun getCookieById(id: Int) = dao.getCookieById(id)\n\n    suspend fun deleteCookieProfile(profile: CookieProfile) = dao.deleteCookieProfile(profile)\n\n    suspend fun insertCookieProfile(profile: CookieProfile) = dao.insertCookieProfile(profile)\n\n    suspend fun updateCookieProfile(profile: CookieProfile) = dao.updateCookieProfile(profile)\n\n    suspend fun getTemplateList() = dao.getTemplateList()\n\n    suspend fun getShortcutList() = dao.getShortcutList()\n\n    suspend fun deleteInfoList(infoList: List<DownloadedVideoInfo>, deleteFile: Boolean = false) {\n        dao.deleteInfoList(infoList)\n        infoList.forEach { info -> if (deleteFile) FileUtil.deleteFile(info.videoPath) }\n    }\n\n    suspend fun getInfoById(id: Int): DownloadedVideoInfo = dao.getInfoById(id)\n\n    suspend fun deleteInfoById(id: Int) = dao.deleteInfoById(id)\n\n    suspend fun insertTemplate(commandTemplate: CommandTemplate) =\n        dao.insertTemplate(commandTemplate)\n\n    suspend fun updateTemplate(commandTemplate: CommandTemplate) {\n        dao.updateTemplate(commandTemplate)\n    }\n\n    suspend fun importBackup(backup: Backup, types: Set<BackupType>): Int {\n        var cnt = 0\n        backup.run {\n            if (types.contains(BackupType.DownloadHistory)) {\n                val itemList = getDownloadHistory()\n\n                if (!downloadHistory.isNullOrEmpty()) {\n                    dao.insertAll(\n                        downloadHistory\n                            .filterNot { itemList.contains(it) }\n                            .map { it.copy(id = 0) }\n                            .also { cnt += it.size }\n                    )\n                }\n            }\n            if (types.contains(BackupType.CommandTemplate)) {\n                if (templates != null) {\n                    val templateList = getTemplateList()\n                    dao.importTemplates(\n                        templateList\n                            .filterNot { templateList.contains(it) }\n                            .map { it.copy(id = 0) }\n                            .also { cnt += it.size }\n                    )\n                }\n            }\n            if (types.contains(BackupType.CommandShortcut)) {\n                val shortcutList = getShortcutList()\n                if (shortcuts != null) {\n                    dao.insertAllShortcuts(\n                        shortcuts\n                            .filterNot { shortcutList.contains(it) }\n                            .map { it.copy(id = 0) }\n                            .also { cnt += it.size }\n                    )\n                }\n            }\n        }\n        return cnt\n    }\n\n    suspend fun importTemplatesFromJson(json: String): Int {\n        json\n            .decodeToBackup()\n            .onSuccess { backup ->\n                return importBackup(\n                    backup = backup,\n                    types = setOf(BackupType.CommandTemplate, BackupType.CommandShortcut),\n                )\n            }\n            .onFailure { it.printStackTrace() }\n        return 0\n    }\n\n    suspend fun deleteTemplateById(id: Int) = dao.deleteTemplateById(id)\n\n    suspend fun deleteTemplates(templates: List<CommandTemplate>) = dao.deleteTemplates(templates)\n\n    private const val TAG = \"DatabaseUtil\"\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/DateTimeUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.os.Build\nimport java.text.DateFormat\nimport java.text.SimpleDateFormat\nimport java.time.Instant\nimport java.util.Date\nimport java.util.Locale\n\nprivate val SimpleDateFormat by lazy {\n    SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\", Locale.getDefault())\n}\n\nfun Long.toLocalizedString(locale: Locale = Locale.getDefault()): String {\n    return if (Build.VERSION.SDK_INT >= 26) {\n        DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, locale)\n            .format(Date.from(Instant.ofEpochMilli(this)))\n    } else {\n        SimpleDateFormat.format(Date(this))\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/DownloadUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.database.sqlite.SQLiteDatabase\nimport android.database.sqlite.SQLiteDatabase.OPEN_READONLY\nimport android.media.MediaCodecList\nimport android.os.Build\nimport android.util.Log\nimport android.webkit.CookieManager\nimport androidx.annotation.CheckResult\nimport com.junkfood.seal.App\nimport com.junkfood.seal.App.Companion.audioDownloadDir\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.App.Companion.videoDownloadDir\nimport com.junkfood.seal.Downloader\nimport com.junkfood.seal.Downloader.onProcessEnded\nimport com.junkfood.seal.Downloader.onProcessStarted\nimport com.junkfood.seal.Downloader.onTaskEnded\nimport com.junkfood.seal.Downloader.onTaskError\nimport com.junkfood.seal.Downloader.onTaskStarted\nimport com.junkfood.seal.Downloader.toNotificationId\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.database.objects.DownloadedVideoInfo\nimport com.junkfood.seal.ui.page.settings.network.Cookie\nimport com.junkfood.seal.util.FileUtil.getArchiveFile\nimport com.junkfood.seal.util.FileUtil.getConfigFile\nimport com.junkfood.seal.util.FileUtil.getCookiesFile\nimport com.junkfood.seal.util.FileUtil.getExternalTempDir\nimport com.junkfood.seal.util.FileUtil.getFileName\nimport com.junkfood.seal.util.FileUtil.getSdcardTempDir\nimport com.junkfood.seal.util.FileUtil.moveFilesToSdcard\nimport com.junkfood.seal.util.PreferenceUtil.COOKIE_HEADER\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.junkfood.seal.util.PreferenceUtil.getString\nimport com.junkfood.seal.util.PreferenceUtil.updateBoolean\nimport com.yausername.youtubedl_android.YoutubeDL\nimport com.yausername.youtubedl_android.YoutubeDLException\nimport com.yausername.youtubedl_android.YoutubeDLRequest\nimport com.yausername.youtubedl_android.YoutubeDLResponse\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.withContext\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.json.Json\nimport java.util.Locale\n\nobject DownloadUtil {\n\n    object CookieScheme {\n        const val NAME = \"name\"\n        const val VALUE = \"value\"\n        const val SECURE = \"is_secure\"\n        const val EXPIRY = \"expires_utc\"\n        const val HOST = \"host_key\"\n        const val PATH = \"path\"\n    }\n\n    private val jsonFormat = Json { ignoreUnknownKeys = true }\n\n    private const val TAG = \"DownloadUtil\"\n\n    const val BASENAME = \"%(title).200B\"\n\n    const val EXTENSION = \".%(ext)s\"\n\n    private const val ID = \"[%(id)s]\"\n\n    private const val CLIP_TIMESTAMP = \"%(section_start)d-%(section_end)d\"\n\n    const val OUTPUT_TEMPLATE_DEFAULT = BASENAME + EXTENSION\n\n    const val OUTPUT_TEMPLATE_ID = \"$BASENAME $ID$EXTENSION\"\n\n    private const val OUTPUT_TEMPLATE_CLIPS = \"$BASENAME [$CLIP_TIMESTAMP]$EXTENSION\"\n\n    private const val OUTPUT_TEMPLATE_CHAPTERS =\n        \"chapter:$BASENAME/%(section_number)d - %(section_title).200B$EXTENSION\"\n\n    private const val OUTPUT_TEMPLATE_SPLIT = \"$BASENAME/$OUTPUT_TEMPLATE_DEFAULT\"\n\n    private const val PLAYLIST_TITLE_SUBDIRECTORY_PREFIX = \"%(playlist)s/\"\n\n    private const val CROP_ARTWORK_COMMAND =\n        \"\"\"--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\"\"\"\"\n\n    @CheckResult\n    fun getPlaylistOrVideoInfo(\n        playlistURL: String,\n        downloadPreferences: DownloadPreferences = DownloadPreferences.createFromPreferences(),\n    ): Result<YoutubeDLInfo> =\n        YoutubeDL.runCatching {\n            ToastUtil.makeToastSuspend(context.getString(R.string.fetching_playlist_info))\n            val request = YoutubeDLRequest(playlistURL)\n            with(request) {\n                //            addOption(\"--compat-options\", \"no-youtube-unavailable-videos\")\n                addOption(\"--flat-playlist\")\n                addOption(\"--dump-single-json\")\n                addOption(\"-o\", BASENAME)\n                addOption(\"-R\", \"1\")\n                addOption(\"--socket-timeout\", \"5\")\n                downloadPreferences.run {\n                    if (extractAudio) {\n                        addOption(\"-x\")\n                    }\n                    applyFormatSorter(this, toFormatSorter())\n                    if (proxy) {\n                        enableProxy(proxyUrl)\n                    }\n                    if (forceIpv4) {\n                        addOption(\"-4\")\n                    }\n                    if (cookies) {\n                        enableCookies(userAgentString)\n                    }\n                    if (restrictFilenames) {\n                        addOption(\"--restrict-filenames\")\n                    }\n                }\n            }\n            execute(request, playlistURL).out.run {\n                val playlistInfo = jsonFormat.decodeFromString<PlaylistResult>(this)\n                if (playlistInfo.type != \"playlist\") {\n                    jsonFormat.decodeFromString<VideoInfo>(this)\n                } else playlistInfo\n            }\n        }\n\n    @CheckResult\n    private fun getVideoInfo(\n        request: YoutubeDLRequest,\n        taskKey: String? = null,\n    ): Result<VideoInfo> =\n        request.runCatching {\n            val response: YoutubeDLResponse =\n                YoutubeDL.getInstance().execute(request, taskKey, null)\n            jsonFormat.decodeFromString(response.out)\n        }\n\n    @CheckResult\n    fun fetchVideoInfoFromUrl(\n        url: String,\n        playlistIndex: Int? = null,\n        taskKey: String? = null,\n        preferences: DownloadPreferences = DownloadPreferences.createFromPreferences(),\n    ): Result<VideoInfo> {\n        with(preferences) {\n            val request =\n                YoutubeDLRequest(url).apply {\n                    addOption(\"-o\", BASENAME)\n                    if (restrictFilenames) {\n                        addOption(\"--restrict-filenames\")\n                    }\n                    if (extractAudio) {\n                        addOption(\"-x\")\n                    }\n                    applyFormatSorter(this@with, toFormatSorter())\n                    if (cookies) {\n                        enableCookies(userAgentString)\n                    }\n                    if (proxy) {\n                        enableProxy(proxyUrl)\n                    }\n                    if (forceIpv4) {\n                        addOption(\"-4\")\n                    }\n                    /*            if (debug) {\n                        addOption(\"-v\")\n                    }*/\n                    if (autoSubtitle) {\n                        addOption(\"--write-auto-subs\")\n                        if (!autoTranslatedSubtitles) {\n                            addOption(\"--extractor-args\", \"youtube:skip=translated_subs\")\n                        }\n                    }\n                    if (playlistIndex != null) {\n                        addOption(\"--playlist-items\", playlistIndex)\n                        addOption(\"--dump-json\")\n                    } else {\n                        addOption(\"--dump-single-json\")\n                    }\n                    addOption(\"-R\", \"1\")\n                    addOption(\"--no-playlist\")\n                    addOption(\"--socket-timeout\", \"5\")\n                }\n            return getVideoInfo(request, taskKey)\n        }\n    }\n\n    @Serializable\n    data class DownloadPreferences(\n        val extractAudio: Boolean,\n        val createThumbnail: Boolean,\n        val downloadPlaylist: Boolean,\n        val subdirectoryExtractor: Boolean,\n        val subdirectoryPlaylistTitle: Boolean,\n        val commandDirectory: String,\n        val downloadSubtitle: Boolean,\n        val embedSubtitle: Boolean,\n        val keepSubtitle: Boolean,\n        val subtitleLanguage: String,\n        val autoSubtitle: Boolean,\n        val autoTranslatedSubtitles: Boolean,\n        val convertSubtitle: Int,\n        val concurrentFragments: Int,\n        val sponsorBlock: Boolean,\n        val sponsorBlockCategory: String,\n        val cookies: Boolean,\n        val aria2c: Boolean,\n        val useCustomAudioPreset: Boolean,\n        val audioFormat: Int,\n        val audioQuality: Int,\n        val convertAudio: Boolean,\n        val formatSorting: Boolean,\n        val sortingFields: String,\n        val audioConvertFormat: Int,\n        val videoFormat: Int,\n        val formatIdString: String,\n        val videoResolution: Int,\n        val privateMode: Boolean,\n        val rateLimit: Boolean,\n        val maxDownloadRate: String,\n        val privateDirectory: Boolean,\n        val cropArtwork: Boolean,\n        val sdcard: Boolean,\n        val sdcardUri: String,\n        val embedThumbnail: Boolean,\n        val videoClips: List<VideoClip>,\n        val splitByChapter: Boolean,\n        val debug: Boolean,\n        val proxy: Boolean,\n        val proxyUrl: String,\n        val newTitle: String,\n        val userAgentString: String,\n        val outputTemplate: String,\n        val useDownloadArchive: Boolean,\n        val embedMetadata: Boolean,\n        val restrictFilenames: Boolean,\n        val supportAv1HardwareDecoding: Boolean,\n        val forceIpv4: Boolean,\n        val mergeAudioStream: Boolean,\n        val mergeToMkv: Boolean,\n    ) {\n        companion object {\n            val EMPTY =\n                DownloadPreferences(\n                    extractAudio = false,\n                    createThumbnail = false,\n                    downloadPlaylist = false,\n                    subdirectoryExtractor = false,\n                    subdirectoryPlaylistTitle = false,\n                    commandDirectory = \"\",\n                    downloadSubtitle = false,\n                    embedSubtitle = false,\n                    keepSubtitle = false,\n                    subtitleLanguage = \"\",\n                    autoSubtitle = false,\n                    autoTranslatedSubtitles = false,\n                    convertSubtitle = 0,\n                    concurrentFragments = 0,\n                    sponsorBlock = false,\n                    sponsorBlockCategory = \"\",\n                    cookies = false,\n                    aria2c = false,\n                    audioFormat = 0,\n                    audioQuality = 0,\n                    convertAudio = false,\n                    formatSorting = false,\n                    sortingFields = \"\",\n                    audioConvertFormat = 0,\n                    videoFormat = 0,\n                    formatIdString = \"\",\n                    videoResolution = 0,\n                    privateMode = false,\n                    rateLimit = false,\n                    maxDownloadRate = \"\",\n                    privateDirectory = false,\n                    cropArtwork = false,\n                    sdcard = false,\n                    sdcardUri = \"\",\n                    embedThumbnail = false,\n                    videoClips = emptyList(),\n                    splitByChapter = false,\n                    debug = false,\n                    proxy = false,\n                    proxyUrl = \"\",\n                    newTitle = \"\",\n                    userAgentString = \"\",\n                    outputTemplate = \"\",\n                    useDownloadArchive = false,\n                    embedMetadata = false,\n                    restrictFilenames = false,\n                    supportAv1HardwareDecoding = false,\n                    forceIpv4 = false,\n                    mergeAudioStream = false,\n                    mergeToMkv = false,\n                    useCustomAudioPreset = false,\n                )\n\n            fun createFromPreferences(): DownloadPreferences {\n                val downloadSubtitle = SUBTITLE.getBoolean()\n                val embedSubtitle = EMBED_SUBTITLE.getBoolean()\n                return DownloadPreferences(\n                    extractAudio = EXTRACT_AUDIO.getBoolean(),\n                    createThumbnail = THUMBNAIL.getBoolean(),\n                    downloadPlaylist = PLAYLIST.getBoolean(),\n                    subdirectoryExtractor = SUBDIRECTORY_EXTRACTOR.getBoolean(),\n                    subdirectoryPlaylistTitle = SUBDIRECTORY_PLAYLIST_TITLE.getBoolean(),\n                    commandDirectory = COMMAND_DIRECTORY.getString(),\n                    downloadSubtitle = downloadSubtitle,\n                    embedSubtitle = embedSubtitle,\n                    keepSubtitle = KEEP_SUBTITLE_FILES.getBoolean(),\n                    subtitleLanguage = SUBTITLE_LANGUAGE.getString(),\n                    autoSubtitle = AUTO_SUBTITLE.getBoolean(),\n                    autoTranslatedSubtitles = AUTO_TRANSLATED_SUBTITLES.getBoolean(),\n                    convertSubtitle = CONVERT_SUBTITLE.getInt(),\n                    concurrentFragments = CONCURRENT.getInt(),\n                    sponsorBlock = SPONSORBLOCK.getBoolean(),\n                    sponsorBlockCategory = PreferenceUtil.getSponsorBlockCategories(),\n                    cookies = COOKIES.getBoolean(),\n                    aria2c = ARIA2C.getBoolean(),\n                    useCustomAudioPreset = USE_CUSTOM_AUDIO_PRESET.getBoolean(),\n                    audioFormat = AUDIO_FORMAT.getInt(),\n                    audioQuality = AUDIO_QUALITY.getInt(),\n                    convertAudio = AUDIO_CONVERT.getBoolean(),\n                    formatSorting = FORMAT_SORTING.getBoolean(),\n                    sortingFields = SORTING_FIELDS.getString(),\n                    audioConvertFormat = PreferenceUtil.getAudioConvertFormat(),\n                    videoFormat = PreferenceUtil.getVideoFormat(),\n                    formatIdString = \"\",\n                    videoResolution = PreferenceUtil.getVideoResolution(),\n                    privateMode = PRIVATE_MODE.getBoolean(),\n                    rateLimit = RATE_LIMIT.getBoolean(),\n                    maxDownloadRate = PreferenceUtil.getMaxDownloadRate(),\n                    privateDirectory = PRIVATE_DIRECTORY.getBoolean(),\n                    cropArtwork = CROP_ARTWORK.getBoolean(),\n                    sdcard = SDCARD_DOWNLOAD.getBoolean(),\n                    sdcardUri = SDCARD_URI.getString(),\n                    embedThumbnail = EMBED_THUMBNAIL.getBoolean(),\n                    videoClips = emptyList(),\n                    splitByChapter = false,\n                    debug = DEBUG.getBoolean(),\n                    proxy = PROXY.getBoolean(),\n                    proxyUrl = PROXY_URL.getString(),\n                    newTitle = \"\",\n                    userAgentString =\n                        USER_AGENT_STRING.run { if (USER_AGENT.getBoolean()) getString() else \"\" },\n                    outputTemplate = OUTPUT_TEMPLATE.getString(),\n                    useDownloadArchive = DOWNLOAD_ARCHIVE.getBoolean(),\n                    embedMetadata = EMBED_METADATA.getBoolean(),\n                    restrictFilenames = RESTRICT_FILENAMES.getBoolean(),\n                    supportAv1HardwareDecoding = checkIfAv1HardwareAccelerated(),\n                    forceIpv4 = FORCE_IPV4.getBoolean(),\n                    mergeAudioStream = false,\n                    mergeToMkv =\n                        (downloadSubtitle && embedSubtitle) || MERGE_OUTPUT_MKV.getBoolean(),\n                )\n            }\n        }\n    }\n\n    private fun YoutubeDLRequest.enableCookies(userAgentString: String): YoutubeDLRequest =\n        this.addOption(\"--cookies\", context.getCookiesFile().absolutePath).apply {\n            if (userAgentString.isNotEmpty()) {\n                addOption(\"--add-header\", \"User-Agent:$userAgentString\")\n            }\n        }\n\n    private fun YoutubeDLRequest.enableProxy(proxyUrl: String): YoutubeDLRequest =\n        this.addOption(\"--proxy\", proxyUrl)\n\n    private fun YoutubeDLRequest.useDownloadArchive(): YoutubeDLRequest =\n        this.addOption(\"--download-archive\", context.getArchiveFile().absolutePath)\n\n    @CheckResult\n    fun getCookieListFromDatabase(): Result<List<Cookie>> = runCatching {\n        CookieManager.getInstance().run {\n            if (!hasCookies()) throw Exception(\"There is no cookies in the database!\")\n            flush()\n        }\n        SQLiteDatabase.openDatabase(\n                context.dataDir.resolve(\"app_webview/Default/Cookies\").absolutePath,\n                null,\n                OPEN_READONLY,\n            )\n            .run {\n                val projection =\n                    arrayOf(\n                        CookieScheme.HOST,\n                        CookieScheme.EXPIRY,\n                        CookieScheme.PATH,\n                        CookieScheme.NAME,\n                        CookieScheme.VALUE,\n                        CookieScheme.SECURE,\n                    )\n                val cookieList = mutableListOf<Cookie>()\n                query(\"cookies\", projection, null, null, null, null, null).run {\n                    while (moveToNext()) {\n                        val expiry = getLong(getColumnIndexOrThrow(CookieScheme.EXPIRY))\n                        val name = getString(getColumnIndexOrThrow(CookieScheme.NAME))\n                        val value = getString(getColumnIndexOrThrow(CookieScheme.VALUE))\n                        val path = getString(getColumnIndexOrThrow(CookieScheme.PATH))\n                        val secure = getLong(getColumnIndexOrThrow(CookieScheme.SECURE)) == 1L\n                        val hostKey = getString(getColumnIndexOrThrow(CookieScheme.HOST))\n\n                        val host = if (hostKey[0] != '.') \".$hostKey\" else hostKey\n                        cookieList.add(\n                            Cookie(\n                                domain = host,\n                                name = name,\n                                value = value,\n                                path = path,\n                                secure = secure,\n                                expiry = expiry,\n                            )\n                        )\n                    }\n                    close()\n                }\n                close()\n                cookieList\n            }\n    }\n\n    fun List<Cookie>.toCookiesFileContent(): String =\n        this.fold(StringBuilder(COOKIE_HEADER)) { acc, cookie ->\n                acc.append(cookie.toNetscapeCookieString()).append(\"\\n\")\n            }\n            .toString()\n\n    fun getCookiesContentFromDatabase(): Result<String> =\n        getCookieListFromDatabase().mapCatching { it.toCookiesFileContent() }\n\n    private fun YoutubeDLRequest.enableAria2c(): YoutubeDLRequest =\n        this.addOption(\"--downloader\", \"libaria2c.so\")\n\n    private fun YoutubeDLRequest.addOptionsForVideoDownloads(\n        downloadPreferences: DownloadPreferences\n    ): YoutubeDLRequest =\n        this.apply {\n            downloadPreferences.run {\n                addOption(\"--add-metadata\")\n                addOption(\"--no-embed-info-json\")\n                if (formatIdString.isNotEmpty()) {\n                    addOption(\"-f\", formatIdString)\n                    if (mergeAudioStream) {\n                        addOption(\"--audio-multistreams\")\n                    }\n                } else {\n                    applyFormatSorter(this, toFormatSorter())\n                }\n                if (downloadSubtitle) {\n                    if (autoSubtitle) {\n                        addOption(\"--write-auto-subs\")\n                        if (!autoTranslatedSubtitles) {\n                            addOption(\"--extractor-args\", \"youtube:skip=translated_subs\")\n                        }\n                    }\n                    subtitleLanguage\n                        .takeIf { it.isNotEmpty() }\n                        ?.let { addOption(\"--sub-langs\", it) }\n                    if (embedSubtitle) {\n                        addOption(\"--embed-subs\")\n                        if (keepSubtitle) {\n                            addOption(\"--write-subs\")\n                        }\n                    } else {\n                        addOption(\"--write-subs\")\n                    }\n                    when (convertSubtitle) {\n                        CONVERT_ASS -> addOption(\"--convert-subs\", \"ass\")\n                        CONVERT_SRT -> addOption(\"--convert-subs\", \"srt\")\n                        CONVERT_VTT -> addOption(\"--convert-subs\", \"vtt\")\n                        CONVERT_LRC -> addOption(\"--convert-subs\", \"lrc\")\n                        else -> {}\n                    }\n                }\n                if (mergeToMkv) {\n                    addOption(\"--remux-video\", \"mkv\")\n                    addOption(\"--merge-output-format\", \"mkv\")\n                }\n                if (embedThumbnail) {\n                    addOption(\"--embed-thumbnail\")\n                }\n                if (videoClips.isEmpty()) addOption(\"--embed-chapters\")\n            }\n        }\n\n    @CheckResult\n    private fun DownloadPreferences.toAudioFormatSorter(): String =\n        this.run {\n            if (!useCustomAudioPreset) return@run \"\"\n            val format =\n                when (audioFormat) {\n                    M4A -> \"acodec:aac\"\n                    OPUS -> \"acodec:opus\"\n                    else -> \"\"\n                }\n            val quality =\n                when (audioQuality) {\n                    HIGH -> \"abr~192\"\n                    MEDIUM -> \"abr~128\"\n                    LOW -> \"abr~64\"\n                    else -> \"\"\n                }\n            return@run connectWithDelimiter(format, quality, delimiter = \",\")\n        }\n\n    @CheckResult\n    private fun DownloadPreferences.toVideoFormatSorter(): String =\n        this.run {\n            val format =\n                when (videoFormat) {\n                    FORMAT_COMPATIBILITY -> \"proto,vcodec:h264,ext\"\n                    FORMAT_QUALITY ->\n                        if (supportAv1HardwareDecoding) {\n                            \"vcodec:av01\"\n                        } else {\n                            \"vcodec:vp9.2\"\n                        }\n\n                    else -> \"\"\n                }\n            val res =\n                when (videoResolution) {\n                    1 -> \"res:2160\"\n                    2 -> \"res:1440\"\n                    3 -> \"res:1080\"\n                    4 -> \"res:720\"\n                    5 -> \"res:480\"\n                    6 -> \"res:360\"\n                    7 -> \"+res\"\n                    else -> \"\"\n                }\n            val sorter = if (videoFormat == FORMAT_COMPATIBILITY) {\n                connectWithDelimiter(format, res, delimiter = \",\")\n            } else {\n                connectWithDelimiter(res, format, delimiter = \",\")\n            }\n            return@run sorter\n        }\n\n    private fun YoutubeDLRequest.applyFormatSorter(\n        preferences: DownloadPreferences,\n        sorter: String,\n    ) =\n        preferences.run {\n            if (formatSorting && sortingFields.isNotEmpty()) addOption(\"-S\", sortingFields)\n            else if (sorter.isNotEmpty()) addOption(\"-S\", sorter) else {}\n        }\n\n    @CheckResult\n    fun DownloadPreferences.toFormatSorter(): String =\n        connectWithDelimiter(\n            this.toVideoFormatSorter(),\n            this.toAudioFormatSorter(),\n            delimiter = \",\",\n        )\n\n    private fun YoutubeDLRequest.addOptionsForAudioDownloads(\n        id: String,\n        preferences: DownloadPreferences,\n        playlistUrl: String,\n    ): YoutubeDLRequest =\n        this.apply {\n            with(preferences) {\n                addOption(\"-x\")\n                if (downloadSubtitle) {\n                    addOption(\"--write-subs\")\n\n                    if (autoSubtitle) {\n                        addOption(\"--write-auto-subs\")\n                        if (!autoTranslatedSubtitles) {\n                            addOption(\"--extractor-args\", \"youtube:skip=translated_subs\")\n                        }\n                    }\n                    subtitleLanguage\n                        .takeIf { it.isNotEmpty() }\n                        ?.let { addOption(\"--sub-langs\", it) }\n                    when (convertSubtitle) {\n                        CONVERT_ASS -> addOption(\"--convert-subs\", \"ass\")\n                        CONVERT_SRT -> addOption(\"--convert-subs\", \"srt\")\n                        CONVERT_VTT -> addOption(\"--convert-subs\", \"vtt\")\n                        CONVERT_LRC -> addOption(\"--convert-subs\", \"lrc\")\n                        else -> {}\n                    }\n                }\n                if (formatIdString.isNotEmpty()) {\n                    addOption(\"-f\", formatIdString)\n                    if (mergeAudioStream) {\n                        addOption(\"--audio-multistreams\")\n                    }\n                } else if (convertAudio) {\n                    when (audioConvertFormat) {\n                        CONVERT_MP3 -> {\n                            addOption(\"--audio-format\", \"mp3\")\n                        }\n\n                        CONVERT_M4A -> {\n                            addOption(\"--audio-format\", \"m4a\")\n                        }\n                    }\n                } else {\n                    applyFormatSorter(preferences, toAudioFormatSorter())\n                }\n\n                if (embedMetadata) {\n                    addOption(\"--embed-metadata\")\n                    addOption(\"--embed-thumbnail\")\n                    addOption(\"--convert-thumbnails\", \"jpg\")\n\n                    if (cropArtwork) {\n                        val configFile = context.getConfigFile(id)\n                        FileUtil.writeContentToFile(CROP_ARTWORK_COMMAND, configFile)\n                        addOption(\"--config\", configFile.absolutePath)\n                    }\n                }\n                addOption(\"--parse-metadata\", \"%(release_year,upload_date)s:%(meta_date)s\")\n\n                if (playlistUrl.isNotEmpty()) {\n                    addOption(\"--parse-metadata\", \"%(album,playlist,title)s:%(meta_album)s\")\n                    addOption(\"--parse-metadata\", \"%(track_number,playlist_index)d:%(meta_track)s\")\n                } else {\n                    addOption(\"--parse-metadata\", \"%(album,title)s:%(meta_album)s\")\n                }\n            }\n        }\n\n    private fun insertInfoIntoDownloadHistory(\n        videoInfo: VideoInfo,\n        filePaths: List<String>,\n    ): List<String> =\n        filePaths.onEach {\n            DatabaseUtil.insertInfo(videoInfo.toDownloadedVideoInfo(videoPath = it))\n        }\n\n    private fun VideoInfo.toDownloadedVideoInfo(\n        id: Int = 0,\n        videoPath: String,\n    ): DownloadedVideoInfo =\n        this.run {\n            DownloadedVideoInfo(\n                id = id,\n                videoTitle = title,\n                videoAuthor = uploader ?: channel ?: uploaderId.toString(),\n                videoUrl = webpageUrl ?: originalUrl.toString(),\n                thumbnailUrl = thumbnail.toHttpsUrl(),\n                videoPath = videoPath,\n                extractor = extractorKey,\n            )\n        }\n\n    private fun insertSplitChapterIntoHistory(videoInfo: VideoInfo, filePaths: List<String>) =\n        filePaths.onEach {\n            DatabaseUtil.insertInfo(\n                videoInfo.toDownloadedVideoInfo(videoPath = it).copy(videoTitle = it.getFileName())\n            )\n        }\n\n    @CheckResult\n    fun downloadVideo(\n        videoInfo: VideoInfo? = null,\n        playlistUrl: String = \"\",\n        playlistItem: Int = 0,\n        taskId: String,\n        downloadPreferences: DownloadPreferences,\n        progressCallback: ((Float, Long, String) -> Unit)?,\n    ): Result<List<String>> {\n        if (videoInfo == null)\n            return Result.failure(Throwable(context.getString(R.string.fetch_info_error_msg)))\n\n        with(downloadPreferences) {\n            val url =\n                playlistUrl.ifEmpty {\n                    videoInfo.originalUrl\n                        ?: videoInfo.webpageUrl\n                        ?: return Result.failure(\n                            Throwable(context.getString(R.string.fetch_info_error_msg))\n                        )\n                }\n            val request = YoutubeDLRequest(url)\n            val pathBuilder = StringBuilder()\n            val outputBuilder = StringBuilder()\n\n            request\n                .apply {\n                    addOption(\"--no-mtime\")\n                    //                addOption(\"-v\")\n                    if (cookies) {\n                        enableCookies(userAgentString)\n                    }\n                    if (restrictFilenames) {\n                        addOption(\"--restrict-filenames\")\n                    }\n                    if (proxy) {\n                        enableProxy(proxyUrl)\n                    }\n                    if (forceIpv4) {\n                        addOption(\"-4\")\n                    }\n                    if (debug) {\n                        addOption(\"-v\")\n                    }\n                    if (useDownloadArchive) {\n                        val archiveFile = context.getArchiveFile()\n                        val archiveFileContent = archiveFile.readText()\n                        if (archiveFileContent.contains(\"${videoInfo.extractor} ${videoInfo.id}\")) {\n                            return Result.failure(\n                                YoutubeDLException(\n                                    context.getString(R.string.download_archive_error)\n                                )\n                            )\n                        } else {\n                            useDownloadArchive()\n                        }\n                    }\n\n                    if (rateLimit && maxDownloadRate.isNumberInRange(1, 1000000)) {\n                        addOption(\"-r\", \"${maxDownloadRate}K\")\n                    }\n\n                    if (playlistItem != 0 && downloadPlaylist) {\n                        addOption(\"--playlist-items\", playlistItem)\n                        if (subdirectoryPlaylistTitle && !videoInfo.playlist.isNullOrEmpty()) {\n                            outputBuilder.append(PLAYLIST_TITLE_SUBDIRECTORY_PREFIX)\n                        }\n                        //                    addOption(\"--compat-options\",\n                        // \"no-youtube-unavailable-videos\")\n                    } else {\n                        addOption(\"--no-playlist\")\n                    }\n\n                    if (aria2c) {\n                        enableAria2c()\n                    } else if (concurrentFragments > 1) {\n                        addOption(\"--concurrent-fragments\", concurrentFragments)\n                    }\n\n                    if (extractAudio || (videoInfo.vcodec == \"none\")) {\n                        if (privateDirectory) pathBuilder.append(App.privateDownloadDir)\n                        else pathBuilder.append(audioDownloadDir)\n                        addOptionsForAudioDownloads(\n                            id = videoInfo.id,\n                            preferences = downloadPreferences,\n                            playlistUrl = playlistUrl,\n                        )\n                    } else {\n                        if (privateDirectory) pathBuilder.append(App.privateDownloadDir)\n                        else pathBuilder.append(videoDownloadDir)\n                        addOptionsForVideoDownloads(downloadPreferences)\n                    }\n                    if (sponsorBlock) {\n                        addOption(\"--sponsorblock-remove\", sponsorBlockCategory)\n                    }\n\n                    if (createThumbnail) {\n                        addOption(\"--write-thumbnail\")\n                        addOption(\"--convert-thumbnails\", \"png\")\n                    }\n                    if (subdirectoryExtractor) {\n                        pathBuilder.append(\"/${videoInfo.extractorKey}\")\n                    }\n\n                    if (sdcard) {\n                        addOption(\"-P\", context.getSdcardTempDir(videoInfo.id).absolutePath)\n                    } else {\n                        addOption(\"-P\", pathBuilder.toString())\n                    }\n\n                    videoClips.forEach {\n                        addOption(\n                            \"--download-sections\",\n                            \"*%d-%d\".format(locale = Locale.US, it.start, it.end),\n                        )\n                    }\n                    if (newTitle.isNotEmpty()) {\n                        addCommands(listOf(\"--replace-in-metadata\", \"title\", \".+\", newTitle))\n                    }\n                    if (Build.VERSION.SDK_INT > 23 && !sdcard)\n                        addOption(\"-P\", \"temp:\" + getExternalTempDir())\n\n                    if (splitByChapter) {\n                        addOption(\"-o\", OUTPUT_TEMPLATE_CHAPTERS)\n                        addOption(\"--split-chapters\")\n                    }\n\n                    val output =\n                        if (splitByChapter) {\n                            OUTPUT_TEMPLATE_SPLIT\n                        } else if (videoClips.isEmpty()) {\n                            outputTemplate\n                        } else {\n                            OUTPUT_TEMPLATE_CLIPS\n                        }\n\n                    addOption(\"-o\", outputBuilder.append(output).toString())\n\n                    for (s in request.buildCommand()) Log.d(TAG, s)\n                }\n                .runCatching {\n                    YoutubeDL.getInstance()\n                        .execute(request = this, processId = taskId, callback = progressCallback)\n                }\n                .onFailure { th ->\n                    return if (\n                        sponsorBlock &&\n                            th.message?.contains(\"Unable to communicate with SponsorBlock API\") ==\n                                true\n                    ) {\n                        th.printStackTrace()\n                        onFinishDownloading(\n                            preferences = this,\n                            videoInfo = videoInfo,\n                            downloadPath = pathBuilder.toString(),\n                            sdcardUri = sdcardUri,\n                        )\n                    } else Result.failure(th)\n                }\n            return onFinishDownloading(\n                preferences = this,\n                videoInfo = videoInfo,\n                downloadPath = pathBuilder.toString(),\n                sdcardUri = sdcardUri,\n            )\n        }\n    }\n\n    private fun onFinishDownloading(\n        preferences: DownloadPreferences,\n        videoInfo: VideoInfo,\n        downloadPath: String,\n        sdcardUri: String,\n    ): Result<List<String>> =\n        preferences.run {\n            val fileName =\n                preferences.newTitle.ifEmpty {\n                    videoInfo.filename\n                        ?: videoInfo.requestedDownloads?.firstOrNull()?.filename\n                        ?: videoInfo.title\n                }\n\n            Log.d(TAG, \"onFinishDownloading: $fileName\")\n            if (sdcard) {\n                moveFilesToSdcard(\n                        sdcardUri = sdcardUri,\n                        tempPath = context.getSdcardTempDir(videoInfo.id),\n                    )\n                    .onSuccess {\n                        if (privateMode) {\n                            return Result.success(emptyList())\n                        } else if (splitByChapter) {\n                            insertSplitChapterIntoHistory(videoInfo, it)\n                        } else {\n                            insertInfoIntoDownloadHistory(videoInfo, it)\n                        }\n                    }\n            } else {\n                FileUtil.scanFileToMediaLibraryPostDownload(\n                        title = fileName,\n                        downloadDir = downloadPath,\n                    )\n                    .run {\n                        if (privateMode) Result.success(emptyList())\n                        else\n                            Result.success(\n                                if (splitByChapter) {\n                                    insertSplitChapterIntoHistory(videoInfo, this)\n                                } else {\n                                    insertInfoIntoDownloadHistory(videoInfo, this)\n                                }\n                            )\n                    }\n            }\n        }\n\n    @CheckResult\n    fun executeCustomCommandTask(\n        urlString: String,\n        taskId: String,\n        template: CommandTemplate,\n        preferences: DownloadPreferences,\n        progressCallback: ((Float, Long, String) -> Unit),\n    ): Result<YoutubeDLResponse> {\n        val urlList = urlString.split(Regex(\"[\\n ]\")).filter { it.isNotBlank() }\n\n        val request =\n            with(preferences) {\n                YoutubeDLRequest(urlList).apply {\n                    commandDirectory.takeIf { it.isNotEmpty() }?.let { addOption(\"-P\", it) }\n                    addOption(\"--newline\")\n                    if (aria2c) {\n                        enableAria2c()\n                    }\n                    if (useDownloadArchive) {\n                        useDownloadArchive()\n                    }\n                    if (restrictFilenames) {\n                        addOption(\"--restrict-filenames\")\n                    }\n                    addOption(\n                        \"--config-locations\",\n                        FileUtil.writeContentToFile(template.template, context.getConfigFile())\n                            .absolutePath,\n                    )\n                    if (cookies) {\n                        enableCookies(userAgentString)\n                    }\n                }\n            }\n\n        return runCatching {\n            YoutubeDL.getInstance()\n                .execute(request = request, processId = taskId, callback = progressCallback)\n        }\n    }\n\n    suspend fun executeCommandInBackground(\n        url: String,\n        template: CommandTemplate = PreferenceUtil.getTemplate(),\n        downloadPreferences: DownloadPreferences = DownloadPreferences.createFromPreferences(),\n    ) {\n        downloadPreferences.run {\n            val taskId = Downloader.makeKey(url = url, templateName = template.name)\n            val notificationId = taskId.toNotificationId()\n            val urlList = url.split(Regex(\"[\\n ]\")).filter { it.isNotBlank() }\n\n            ToastUtil.makeToastSuspend(context.getString(R.string.start_execute))\n            val request =\n                YoutubeDLRequest(urlList).apply {\n                    commandDirectory.takeIf { it.isNotEmpty() }?.let { addOption(\"-P\", it) }\n                    addOption(\"--newline\")\n                    if (aria2c) {\n                        enableAria2c()\n                    }\n                    if (useDownloadArchive) {\n                        useDownloadArchive()\n                    }\n                    if (restrictFilenames) {\n                        addOption(\"--restrict-filenames\")\n                    }\n                    addOption(\n                        \"--config-locations\",\n                        FileUtil.writeContentToFile(template.template, context.getConfigFile())\n                            .absolutePath,\n                    )\n                    if (cookies) {\n                        enableCookies(userAgentString)\n                    }\n                }\n\n            onProcessStarted()\n            withContext(Dispatchers.Main) { onTaskStarted(template, url) }\n            runCatching {\n                    val response =\n                        YoutubeDL.getInstance().execute(request = request, processId = taskId) {\n                            progress,\n                            _,\n                            text ->\n                            NotificationUtil.makeNotificationForCustomCommand(\n                                notificationId = notificationId,\n                                taskId = taskId,\n                                progress = progress.toInt(),\n                                templateName = template.name,\n                                taskUrl = url,\n                                text = text,\n                            )\n                            Downloader.updateTaskOutput(\n                                template = template,\n                                url = url,\n                                line = text,\n                                progress = progress,\n                            )\n                        }\n                    onTaskEnded(template, url, response.out + \"\\n\" + response.err)\n                }\n                .onFailure {\n                    it.printStackTrace()\n                    if (it is YoutubeDL.CanceledException) return@onFailure\n                    it.message.run {\n                        if (isNullOrEmpty()) onTaskEnded(template, url)\n                        else onTaskError(this, template, url)\n                    }\n                }\n            onProcessEnded()\n        }\n    }\n\n    private fun checkIfAv1HardwareAccelerated(): Boolean {\n        if (PreferenceUtil.containsKey(AV1_HARDWARE_ACCELERATED)) {\n            return AV1_HARDWARE_ACCELERATED.getBoolean()\n        } else {\n            val res =\n                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {\n                    false\n                } else {\n                    MediaCodecList(MediaCodecList.REGULAR_CODECS).codecInfos.any { info ->\n                        info.supportedTypes.any { it.equals(\"video/av01\", ignoreCase = true) } &&\n                            info.isHardwareAccelerated\n                    }\n                }\n            AV1_HARDWARE_ACCELERATED.updateBoolean(res)\n            return res\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/FileUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.content.ClipData\nimport android.content.Context\nimport android.content.Intent\nimport android.media.MediaScannerConnection\nimport android.net.Uri\nimport android.os.Environment\nimport android.provider.DocumentsContract\nimport android.util.Log\nimport android.webkit.MimeTypeMap\nimport androidx.annotation.CheckResult\nimport androidx.core.content.FileProvider\nimport androidx.documentfile.provider.DocumentFile\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.R\nimport java.io.File\nimport okhttp3.internal.closeQuietly\n\nconst val AUDIO_REGEX = \"(mp3|aac|opus|m4a)$\"\nconst val THUMBNAIL_REGEX = \"\\\\.(jpg|png)$\"\nconst val SUBTITLE_REGEX = \"\\\\.(lrc|vtt|srt|ass|json3|srv.|ttml)$\"\nprivate const val PRIVATE_DIRECTORY_SUFFIX = \".Seal\"\n\nobject FileUtil {\n    fun openFileFromResult(downloadResult: Result<List<String>>) {\n        val filePaths = downloadResult.getOrNull()\n        if (filePaths.isNullOrEmpty()) return\n        openFile(filePaths.first()) {\n            ToastUtil.makeToastSuspend(context.getString(R.string.file_unavailable))\n        }\n    }\n\n    inline fun openFile(path: String, onFailureCallback: (Throwable) -> Unit) =\n        path\n            .runCatching {\n                createIntentForOpeningFile(this)?.run { context.startActivity(this) }\n                    ?: throw Exception()\n            }\n            .onFailure { onFailureCallback(it) }\n\n    private fun createIntentForFile(path: String?): Intent? {\n        if (path == null) return null\n\n        val uri =\n            path\n                .runCatching {\n                    DocumentFile.fromSingleUri(context, Uri.parse(path)).run {\n                        if (this?.exists() == true) {\n                            this.uri\n                        } else if (File(this@runCatching).exists()) {\n                            FileProvider.getUriForFile(\n                                context,\n                                context.getFileProvider(),\n                                File(this@runCatching),\n                            )\n                        } else null\n                    }\n                }\n                .getOrNull() ?: return null\n\n        return Intent().apply {\n            flags = Intent.FLAG_GRANT_READ_URI_PERMISSION\n            data = uri\n        }\n    }\n\n    fun createIntentForOpeningFile(path: String?): Intent? =\n        createIntentForFile(path)?.let {\n            it.apply {\n                action = (Intent.ACTION_VIEW)\n                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)\n            }\n        }\n\n    fun createIntentForSharingFile(path: String?): Intent? =\n        createIntentForFile(path)?.apply {\n            action = Intent.ACTION_SEND\n            putExtra(Intent.EXTRA_STREAM, data)\n            val mimeType = data?.let { context.contentResolver.getType(it) } ?: \"media/*\"\n            setDataAndType(this.data, mimeType)\n            clipData = ClipData(null, arrayOf(mimeType), ClipData.Item(data))\n        }\n\n    fun Context.getFileProvider() = \"$packageName.provider\"\n\n    fun String.getFileSize(): Long =\n        this.run {\n            val length = File(this).length()\n            if (length == 0L) DocumentFile.fromSingleUri(context, Uri.parse(this))?.length() ?: 0L\n            else length\n        }\n\n    fun String.getFileName(): String =\n        this.run {\n            File(this).nameWithoutExtension.ifEmpty {\n                DocumentFile.fromSingleUri(context, Uri.parse(this))?.name ?: \"video\"\n            }\n        }\n\n    fun deleteFile(path: String) =\n        path.runCatching {\n            if (!File(path).delete()) DocumentFile.fromSingleUri(context, Uri.parse(this))?.delete()\n        }\n\n    @CheckResult\n    fun scanFileToMediaLibraryPostDownload(title: String, downloadDir: String): List<String> =\n        File(downloadDir)\n            .walkTopDown()\n            .filter { it.isFile && it.absolutePath.contains(title) }\n            .map { it.absolutePath }\n            .toMutableList()\n            .apply {\n                MediaScannerConnection.scanFile(context, this.toList().toTypedArray(), null, null)\n                removeAll {\n                    it.contains(Regex(THUMBNAIL_REGEX)) || it.contains(Regex(SUBTITLE_REGEX))\n                }\n            }\n\n    fun scanDownloadDirectoryToMediaLibrary(downloadDir: String) =\n        File(downloadDir)\n            .walkTopDown()\n            .filter { it.isFile }\n            .map { it.absolutePath }\n            .run {\n                MediaScannerConnection.scanFile(context, this.toList().toTypedArray(), null, null)\n            }\n\n    @CheckResult\n    fun moveFilesToSdcard(tempPath: File, sdcardUri: String): Result<List<String>> {\n        val uriList = mutableListOf<String>()\n        val destDir =\n            Uri.parse(sdcardUri).run {\n                DocumentsContract.buildDocumentUriUsingTree(\n                    this,\n                    DocumentsContract.getTreeDocumentId(this),\n                )\n            }\n        val res =\n            tempPath.runCatching {\n                walkTopDown().forEach {\n                    if (it.isDirectory) return@forEach\n                    val mimeType =\n                        MimeTypeMap.getSingleton().getMimeTypeFromExtension(it.extension) ?: \"*/*\"\n\n                    val destUri =\n                        DocumentsContract.createDocument(\n                            context.contentResolver,\n                            destDir,\n                            mimeType,\n                            it.name,\n                        ) ?: return@forEach\n\n                    val inputStream = it.inputStream()\n                    val outputStream =\n                        context.contentResolver.openOutputStream(destUri) ?: return@forEach\n                    inputStream.copyTo(outputStream)\n                    inputStream.closeQuietly()\n                    outputStream.closeQuietly()\n                    uriList.add(destUri.toString())\n                }\n                uriList\n            }\n        tempPath.deleteRecursively()\n        return res\n    }\n\n    fun clearTempFiles(downloadDir: File): Int {\n        var count = 0\n        downloadDir.walkTopDown().forEach {\n            if (it.isFile && !it.isHidden) {\n                if (it.delete()) count++\n            }\n        }\n        return count\n    }\n\n    fun Context.getConfigDirectory(): File = cacheDir\n\n    fun Context.getConfigFile(suffix: String = \"\") = File(getConfigDirectory(), \"config$suffix.txt\")\n\n    fun Context.getCookiesFile() = File(getConfigDirectory(), \"cookies.txt\")\n\n    fun getExternalTempDir() =\n        File(getExternalDownloadDirectory(), \"tmp\").apply {\n            mkdirs()\n            createEmptyFile(\".nomedia\")\n        }\n\n    fun Context.getSdcardTempDir(child: String?): File =\n        getExternalTempDir().run { child?.let { resolve(it) } ?: this }\n\n    fun Context.getArchiveFile(): File = filesDir.createEmptyFile(\"archive.txt\").getOrThrow()\n\n    fun Context.getInternalTempDir() = File(filesDir, \"tmp\")\n\n    internal fun getExternalDownloadDirectory() =\n        File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), \"Seal\")\n            .also { it.mkdir() }\n\n    internal fun getExternalPrivateDownloadDirectory() =\n        File(\n            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),\n            PRIVATE_DIRECTORY_SUFFIX,\n        )\n\n    fun File.createEmptyFile(fileName: String): Result<File> =\n        this.runCatching {\n                mkdirs()\n                resolve(fileName).apply { this@apply.createNewFile() }\n            }\n            .onFailure { it.printStackTrace() }\n\n    fun writeContentToFile(content: String, file: File): File = file.apply { writeText(content) }\n\n    fun getRealPath(treeUri: Uri): String {\n        val path: String = treeUri.path.toString()\n        Log.d(TAG, path)\n        if (!path.contains(\"primary:\")) {\n            ToastUtil.makeToast(\"This directory is not supported\")\n            return getExternalDownloadDirectory().absolutePath\n        }\n        val last: String = path.split(\"primary:\").last()\n        return Environment.getExternalStorageDirectory().absolutePath + \"/$last\"\n    }\n\n    private const val TAG = \"FileUtil\"\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/LanguageSettings.kt",
    "content": "package com.junkfood.seal.util\n\nimport androidx.appcompat.app.AppCompatDelegate\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.res.stringResource\nimport androidx.core.os.LocaleListCompat\nimport com.junkfood.seal.R\nimport java.util.Locale\n\n// Do not modify\nprivate const val SIMPLIFIED_CHINESE = 1\nprivate const val ENGLISH = 2\nprivate const val CZECH = 3\nprivate const val FRENCH = 4\nprivate const val GERMAN = 5\nprivate const val NORWEGIAN_BOKMAL = 6\nprivate const val DANISH = 7\nprivate const val SPANISH = 8\nprivate const val TURKISH = 9\nprivate const val UKRAINIAN = 10\nprivate const val RUSSIAN = 11\nprivate const val ARABIC = 12\nprivate const val PERSIAN = 13\nprivate const val INDONESIAN = 14\nprivate const val FILIPINO = 15\nprivate const val ITALIAN = 16\nprivate const val DUTCH = 17\nprivate const val PORTUGUESE_BRAZIL = 18\nprivate const val JAPANESE = 19\nprivate const val POLISH = 20\nprivate const val HUNGARIAN = 21\nprivate const val MALAY = 22\nprivate const val TRADITIONAL_CHINESE = 23\nprivate const val VIETNAMESE = 24\nprivate const val BELARUSIAN = 25\nprivate const val CROATIAN = 26\nprivate const val BASQUE = 27\nprivate const val HINDI = 28\nprivate const val MALAYALAM = 29\nprivate const val SINHALA = 30\nprivate const val SERBIAN = 31\nprivate const val AZERBAIJANI = 32\nprivate const val NORWEGIAN_NYNORSK = 33\nprivate const val PUNJABI = 34\nprivate const val TAMIL = 35\nprivate const val KOREAN = 36\nprivate const val SWEDISH = 37\nprivate const val PORTUGUESE_PORTUGAL = 38\nprivate const val CATALAN = 39\nprivate const val HEBREW = 40\nprivate const val PORTUGUESE = 41\nprivate const val THAI = 42\nprivate const val BENGALI = 43\nprivate const val KHMER = 44\nprivate const val KANNADA = 45\nprivate const val GREEK = 46\nprivate const val MONGOLIAN = 47\n\nval LocaleLanguageCodeMap =\n    mapOf(\n        Locale(\"ar\") to ARABIC,\n        Locale(\"az\") to AZERBAIJANI,\n        Locale(\"eu\") to BASQUE,\n        Locale(\"be\") to BELARUSIAN,\n        Locale(\"bn\") to BENGALI,\n        Locale(\"ca\") to CATALAN,\n        Locale.forLanguageTag(\"zh-Hans\") to SIMPLIFIED_CHINESE,\n        Locale.forLanguageTag(\"zh-Hant\") to TRADITIONAL_CHINESE,\n        Locale(\"hr\") to CROATIAN,\n        Locale(\"cs\") to CZECH,\n        Locale(\"da\") to DANISH,\n        Locale(\"nl\") to DUTCH,\n        Locale(\"en\", \"US\") to ENGLISH,\n        Locale(\"fil\") to FILIPINO,\n        Locale(\"fr\") to FRENCH,\n        Locale(\"de\") to GERMAN,\n        Locale(\"el\") to GREEK,\n        Locale(\"he\") to HEBREW,\n        Locale(\"hi\") to HINDI,\n        Locale(\"hu\") to HUNGARIAN,\n        Locale(\"in\") to INDONESIAN,\n        Locale(\"it\") to ITALIAN,\n        Locale(\"ja\") to JAPANESE,\n        Locale(\"kn\") to KANNADA,\n        Locale(\"km\") to KHMER,\n        Locale(\"ko\") to KOREAN,\n        Locale(\"ms\") to MALAY,\n        Locale(\"ml\") to MALAYALAM,\n        Locale(\"mn\") to MONGOLIAN,\n        Locale(\"nb\") to NORWEGIAN_BOKMAL,\n        Locale(\"nn\") to NORWEGIAN_NYNORSK,\n        Locale(\"fa\") to PERSIAN,\n        Locale(\"pl\") to POLISH,\n        Locale(\"pt\") to PORTUGUESE,\n        Locale(\"pt\", \"PT\") to PORTUGUESE_PORTUGAL,\n        Locale(\"pt\", \"BR\") to PORTUGUESE_BRAZIL,\n        Locale(\"pa\") to PUNJABI,\n        Locale(\"ru\") to RUSSIAN,\n        Locale(\"sr\") to SERBIAN,\n        Locale(\"si\") to SINHALA,\n        Locale(\"es\") to SPANISH,\n        Locale(\"sv\") to SWEDISH,\n        Locale(\"ta\") to TAMIL,\n        Locale(\"th\") to THAI,\n        Locale(\"tr\") to TURKISH,\n        Locale(\"uk\") to UKRAINIAN,\n        Locale(\"vi\") to VIETNAMESE,\n    )\n\n@Composable\nfun Locale?.toDisplayName(): String =\n    this?.getDisplayName(this) ?: stringResource(id = R.string.follow_system)\n\nfun setLanguage(locale: Locale?) {\n    val localeList =\n        locale?.let { LocaleListCompat.create(it) } ?: LocaleListCompat.getEmptyLocaleList()\n    AppCompatDelegate.setApplicationLocales(localeList)\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/NotificationUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.annotation.SuppressLint\nimport android.app.Notification\nimport android.app.NotificationChannel\nimport android.app.NotificationChannelGroup\nimport android.app.NotificationManager\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Build\nimport android.util.Log\nimport androidx.annotation.RequiresApi\nimport androidx.core.app.NotificationCompat\nimport androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.NotificationActionReceiver\nimport com.junkfood.seal.NotificationActionReceiver.Companion.ACTION_CANCEL_TASK\nimport com.junkfood.seal.NotificationActionReceiver.Companion.ACTION_ERROR_REPORT\nimport com.junkfood.seal.NotificationActionReceiver.Companion.ACTION_KEY\nimport com.junkfood.seal.NotificationActionReceiver.Companion.ERROR_REPORT_KEY\nimport com.junkfood.seal.NotificationActionReceiver.Companion.NOTIFICATION_ID_KEY\nimport com.junkfood.seal.NotificationActionReceiver.Companion.TASK_ID_KEY\nimport com.junkfood.seal.R\nimport com.junkfood.seal.util.PreferenceUtil.getBoolean\n\nprivate const val TAG = \"NotificationUtil\"\n\n@SuppressLint(\"StaticFieldLeak\")\nobject NotificationUtil {\n    private val notificationManager =\n        context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\n    private const val PROGRESS_MAX = 100\n    private const val PROGRESS_INITIAL = 0\n    private const val CHANNEL_ID = \"download_notification\"\n    private const val SERVICE_CHANNEL_ID = \"download_service\"\n    private const val NOTIFICATION_GROUP_ID = \"seal.download.notification\"\n    private const val DEFAULT_NOTIFICATION_ID = 100\n    const val SERVICE_NOTIFICATION_ID = 123\n    private lateinit var serviceNotification: Notification\n\n    //    private var builder =\n    //        NotificationCompat.Builder(context, CHANNEL_ID).setSmallIcon(R.drawable.ic_stat_seal)\n    private val commandNotificationBuilder =\n        NotificationCompat.Builder(context, CHANNEL_ID).setSmallIcon(R.drawable.ic_stat_seal)\n\n    @RequiresApi(Build.VERSION_CODES.O)\n    fun createNotificationChannel() {\n        val name = context.getString(R.string.channel_name)\n        val descriptionText = context.getString(R.string.channel_description)\n        val importance = NotificationManager.IMPORTANCE_LOW\n        val channelGroup =\n            NotificationChannelGroup(NOTIFICATION_GROUP_ID, context.getString(R.string.download))\n        val channel =\n            NotificationChannel(CHANNEL_ID, name, importance).apply {\n                description = descriptionText\n                group = NOTIFICATION_GROUP_ID\n            }\n        val serviceChannel =\n            NotificationChannel(SERVICE_CHANNEL_ID, name, importance).apply {\n                description = context.getString(R.string.service_title)\n                group = NOTIFICATION_GROUP_ID\n            }\n        notificationManager.createNotificationChannelGroup(channelGroup)\n        notificationManager.createNotificationChannel(channel)\n        notificationManager.createNotificationChannel(serviceChannel)\n    }\n\n    fun notifyProgress(\n        title: String,\n        notificationId: Int = DEFAULT_NOTIFICATION_ID,\n        progress: Int = PROGRESS_INITIAL,\n        taskId: String? = null,\n        text: String? = null,\n    ) {\n        if (!NOTIFICATION.getBoolean()) return\n        val pendingIntent =\n            taskId?.let {\n                Intent(context.applicationContext, NotificationActionReceiver::class.java)\n                    .putExtra(TASK_ID_KEY, taskId)\n                    .putExtra(NOTIFICATION_ID_KEY, notificationId)\n                    .putExtra(ACTION_KEY, ACTION_CANCEL_TASK)\n                    .run {\n                        PendingIntent.getBroadcast(\n                            context.applicationContext,\n                            notificationId,\n                            this,\n                            PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE,\n                        )\n                    }\n            }\n\n        NotificationCompat.Builder(context, CHANNEL_ID)\n            .setSmallIcon(R.drawable.ic_stat_seal)\n            .setContentTitle(title)\n            .setProgress(PROGRESS_MAX, progress, progress <= 0)\n            .setOngoing(true)\n            .setOnlyAlertOnce(true)\n            .setStyle(NotificationCompat.BigTextStyle().bigText(text))\n            .run {\n                pendingIntent?.let {\n                    addAction(R.drawable.outline_cancel_24, context.getString(R.string.cancel), it)\n                }\n                notificationManager.notify(notificationId, build())\n            }\n    }\n\n    fun finishNotification(\n        notificationId: Int = DEFAULT_NOTIFICATION_ID,\n        title: String? = null,\n        text: String? = null,\n        intent: PendingIntent? = null,\n    ) {\n        Log.d(TAG, \"finishNotification: \")\n        notificationManager.cancel(notificationId)\n        if (!NOTIFICATION.getBoolean()) return\n\n        val builder =\n            NotificationCompat.Builder(context, CHANNEL_ID)\n                .setSmallIcon(R.drawable.ic_stat_seal)\n                .setContentText(text)\n                .setOngoing(false)\n                .setAutoCancel(true)\n        title?.let { builder.setContentTitle(title) }\n        intent?.let { builder.setContentIntent(intent) }\n        notificationManager.notify(notificationId, builder.build())\n    }\n\n    fun finishNotificationForCustomCommands(\n        notificationId: Int = DEFAULT_NOTIFICATION_ID,\n        title: String? = null,\n        text: String? = null,\n    ) {\n        //        notificationManager.cancel(notificationId)\n        val builder =\n            NotificationCompat.Builder(context, CHANNEL_ID)\n                .setSmallIcon(R.drawable.ic_stat_seal)\n                .setContentText(text)\n                .setProgress(0, 0, false)\n                .setAutoCancel(true)\n                .setOngoing(false)\n                .setStyle(null)\n        title?.let { builder.setContentTitle(title) }\n\n        notificationManager.notify(notificationId, builder.build())\n    }\n\n    fun makeServiceNotification(intent: PendingIntent, text: String? = null): Notification {\n        serviceNotification =\n            NotificationCompat.Builder(context, SERVICE_CHANNEL_ID)\n                .setSmallIcon(R.drawable.ic_stat_seal)\n                .setContentTitle(context.getString(R.string.service_title))\n                .setContentText(text)\n                .setOngoing(true)\n                .setContentIntent(intent)\n                .setForegroundServiceBehavior(FOREGROUND_SERVICE_IMMEDIATE)\n                .build()\n        return serviceNotification\n    }\n\n    fun updateServiceNotificationForPlaylist(index: Int, itemCount: Int) {\n        serviceNotification =\n            NotificationCompat.Builder(context, serviceNotification)\n                .setContentTitle(context.getString(R.string.service_title) + \" ($index/$itemCount)\")\n                .build()\n        notificationManager.notify(SERVICE_NOTIFICATION_ID, serviceNotification)\n    }\n\n    fun cancelNotification(notificationId: Int) {\n        notificationManager.cancel(notificationId)\n    }\n\n    fun notifyError(\n        title: String,\n        textId: Int = R.string.download_error_msg,\n        notificationId: Int,\n        report: String,\n    ) {\n        if (!NOTIFICATION.getBoolean()) return\n\n        val intent =\n            Intent()\n                .setClass(context, NotificationActionReceiver::class.java)\n                .putExtra(NOTIFICATION_ID_KEY, notificationId)\n                .putExtra(ERROR_REPORT_KEY, report)\n                .putExtra(ACTION_KEY, ACTION_ERROR_REPORT)\n\n        val pendingIntent =\n            PendingIntent.getBroadcast(\n                context,\n                notificationId,\n                intent,\n                PendingIntent.FLAG_ONE_SHOT or\n                    PendingIntent.FLAG_IMMUTABLE or\n                    PendingIntent.FLAG_UPDATE_CURRENT,\n            )\n        NotificationCompat.Builder(context, CHANNEL_ID)\n            .setSmallIcon(R.drawable.ic_stat_seal)\n            .setContentTitle(title)\n            .setContentText(context.getString(textId))\n            .setOngoing(false)\n            .addAction(\n                R.drawable.outline_content_copy_24,\n                context.getString(R.string.copy_error_report),\n                pendingIntent,\n            )\n            .run {\n                notificationManager.cancel(notificationId)\n                notificationManager.notify(notificationId, build())\n            }\n    }\n\n    fun makeNotificationForCustomCommand(\n        notificationId: Int,\n        taskId: String,\n        progress: Int,\n        text: String? = null,\n        templateName: String,\n        taskUrl: String,\n    ) {\n        if (!NOTIFICATION.getBoolean()) return\n\n        val intent =\n            Intent(context.applicationContext, NotificationActionReceiver::class.java)\n                .putExtra(TASK_ID_KEY, taskId)\n                .putExtra(NOTIFICATION_ID_KEY, notificationId)\n                .putExtra(ACTION_KEY, ACTION_CANCEL_TASK)\n\n        val pendingIntent =\n            PendingIntent.getBroadcast(\n                context.applicationContext,\n                notificationId,\n                intent,\n                PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE,\n            )\n\n        NotificationCompat.Builder(context, CHANNEL_ID)\n            .setSmallIcon(R.drawable.ic_stat_seal)\n            .setContentTitle(\n                \"[${templateName}_${taskUrl}] \" +\n                    context.getString(R.string.execute_command_notification)\n            )\n            .setContentText(text)\n            .setOngoing(true)\n            .setProgress(PROGRESS_MAX, progress, progress == -1)\n            .addAction(\n                R.drawable.outline_cancel_24,\n                context.getString(R.string.cancel),\n                pendingIntent,\n            )\n            .run { notificationManager.notify(notificationId, build()) }\n    }\n\n    fun cancelAllNotifications() {\n        notificationManager.cancelAll()\n    }\n\n    fun areNotificationsEnabled(): Boolean {\n        return if (Build.VERSION.SDK_INT <= 24) true\n        else notificationManager.areNotificationsEnabled()\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/PreferenceUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.os.Build\nimport androidx.annotation.DeprecatedSinceApi\nimport androidx.compose.foundation.isSystemInDarkTheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.res.stringResource\nimport com.google.android.material.color.DynamicColors\nimport com.junkfood.seal.App\nimport com.junkfood.seal.App.Companion.applicationScope\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.App.Companion.isDebugBuild\nimport com.junkfood.seal.App.Companion.isFDroidBuild\nimport com.junkfood.seal.R\nimport com.junkfood.seal.database.objects.CommandTemplate\nimport com.junkfood.seal.download.Task\nimport com.junkfood.seal.ui.theme.DEFAULT_SEED_COLOR\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.kyant.monet.PaletteStyle\nimport com.tencent.mmkv.MMKV\nimport java.util.Locale\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.flow.MutableStateFlow\nimport kotlinx.coroutines.flow.SharingStarted\nimport kotlinx.coroutines.flow.StateFlow\nimport kotlinx.coroutines.flow.asStateFlow\nimport kotlinx.coroutines.flow.stateIn\nimport kotlinx.coroutines.flow.update\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\n\nconst val CUSTOM_COMMAND = \"custom_command\"\nconst val CONCURRENT = \"concurrent_fragments\"\nconst val EXTRACT_AUDIO = \"extract_audio\"\nconst val THUMBNAIL = \"create_thumbnail\"\nconst val YT_DLP_VERSION = \"yt-dlp_init\"\nconst val YT_DLP_AUTO_UPDATE = \"yt-dlp_update\"\nconst val DEBUG = \"debug\"\nconst val CONFIGURE = \"configure\"\nconst val DARK_THEME_VALUE = \"dark_theme_value\"\nconst val AUDIO_CONVERT = \"audio_convert\"\nconst val AUDIO_CONVERSION_FORMAT = \"audio_convert_format\"\nconst val AUDIO_FORMAT = \"audio_format_preferred\"\nconst val AUDIO_QUALITY = \"audio_quality\"\nconst val VIDEO_FORMAT = \"video_format\"\nconst val VIDEO_QUALITY = \"quality\"\n\nconst val FORMAT_SORTING = \"format_sorting\"\nconst val SORTING_FIELDS = \"sorting_fields\"\n\nconst val WELCOME_DIALOG = \"welcome_dialog\"\nconst val VIDEO_DIRECTORY = \"download_dir\"\nconst val AUDIO_DIRECTORY = \"audio_dir\"\nconst val COMMAND_DIRECTORY = \"command_directory\"\nconst val SDCARD_DOWNLOAD = \"sdcard_download\"\nconst val SDCARD_URI = \"sd_card_uri\"\nconst val SUBDIRECTORY_EXTRACTOR = \"sub-directory\"\nconst val SUBDIRECTORY_PLAYLIST_TITLE = \"subdirectory_playlist_title\"\nconst val PLAYLIST = \"playlist\"\nprivate const val LANGUAGE = \"language\"\nconst val NOTIFICATION = \"notification\"\nprivate const val THEME_COLOR = \"theme_color\"\nconst val PALETTE_STYLE = \"palette_style\"\nconst val SUBTITLE = \"subtitle\"\nconst val EMBED_SUBTITLE = \"embed_subtitle\"\nconst val KEEP_SUBTITLE_FILES = \"keep_subtitle\"\nconst val SUBTITLE_LANGUAGE = \"sub_lang\"\nconst val AUTO_SUBTITLE = \"auto_subtitle\"\nconst val CONVERT_SUBTITLE = \"convert_subtitle\"\nconst val AUTO_TRANSLATED_SUBTITLES = \"translated_subs\"\n\nconst val TEMPLATE_ID = \"template_id\"\nconst val MAX_FILE_SIZE = \"max_file_size\"\nconst val SPONSORBLOCK = \"sponsorblock\"\nconst val SPONSORBLOCK_CATEGORIES = \"sponsorblock_categories\"\nconst val ARIA2C = \"aria2c\"\nconst val COOKIES = \"cookies\"\nconst val USER_AGENT = \"user_agent\"\nconst val USER_AGENT_STRING = \"user_agent_string\"\nconst val AUTO_UPDATE = \"auto_update\"\nconst val UPDATE_CHANNEL = \"update_channel\"\nconst val PRIVATE_MODE = \"private_mode\"\nprivate const val DYNAMIC_COLOR = \"dynamic_color\"\nconst val CELLULAR_DOWNLOAD = \"cellular_download\"\nconst val RATE_LIMIT = \"rate_limit\"\nconst val MAX_RATE = \"max_rate\"\nprivate const val HIGH_CONTRAST = \"high_contrast\"\nconst val DISABLE_PREVIEW = \"disable_preview\"\nconst val PRIVATE_DIRECTORY = \"private_directory\"\nconst val CROP_ARTWORK = \"crop_artwork\"\nconst val EMBED_THUMBNAIL = \"embed_thumbnail\"\nconst val FORMAT_SELECTION = \"format_selection\"\nconst val VIDEO_CLIP = \"video_clip\"\nconst val SHOW_SPONSOR_MSG = \"sponsor_msg_v1\"\nconst val PROXY = \"proxy\"\nconst val PROXY_URL = \"proxy_url\"\nconst val OUTPUT_TEMPLATE = \"output_template\"\nconst val CUSTOM_OUTPUT_TEMPLATE = \"custom_output_template\"\nconst val DOWNLOAD_ARCHIVE = \"download_archive\"\nconst val EMBED_METADATA = \"embed_metadata\"\nconst val RESTRICT_FILENAMES = \"restrict_filenames\"\nconst val AV1_HARDWARE_ACCELERATED = \"av1_hardware_accelerated\"\nconst val FORCE_IPV4 = \"force_ipv4\"\nconst val MERGE_OUTPUT_MKV = \"merge_to_mkv\"\nconst val USE_CUSTOM_AUDIO_PRESET = \"custom_audio_preset\"\n\nconst val MERGE_MULTI_AUDIO_STREAM = \"multi_audio_stream\"\n\nconst val DOWNLOAD_TYPE_INITIALIZATION = \"download_type_init\"\nprivate const val DOWNLOAD_TYPE = \"download_type\"\n\nconst val YT_DLP_UPDATE_CHANNEL = \"yt-dlp_update_channel\"\nconst val YT_DLP_UPDATE_TIME = \"yt-dlp_last_update\"\nconst val YT_DLP_UPDATE_INTERVAL = \"yt-dlp_update_interval\"\n\nprivate const val INTERVAL_DAY = 86_400_000L\nprivate const val INTERVAL_WEEK = 86_400_000L * 7\nprivate const val INTERVAL_MONTH = 86_400_000L * 30\n\nconst val DEFAULT_INTERVAL = INTERVAL_WEEK // every week\n\nval UpdateIntervalList =\n    mapOf(\n        INTERVAL_DAY to R.string.every_day,\n        INTERVAL_WEEK to R.string.every_week,\n        INTERVAL_MONTH to R.string.every_month,\n    )\n\nconst val NOT_SPECIFIED = 0\nconst val DEFAULT = NOT_SPECIFIED\nconst val SYSTEM_DEFAULT = NOT_SPECIFIED\nconst val NOT_CONVERT = NOT_SPECIFIED\n\nconst val NONE = NOT_SPECIFIED\nconst val USE_PREVIOUS_SELECTION = 1\n\nenum class DownloadType {\n    Audio,\n    Video,\n    Playlist,\n    Command,\n}\n\nconst val CONVERT_ASS = 1\nconst val CONVERT_LRC = 2\nconst val CONVERT_SRT = 3\nconst val CONVERT_VTT = 4\n\nconst val STABLE = 0\nconst val PRE_RELEASE = 1\n\nconst val YT_DLP_STABLE = 0\nconst val YT_DLP_NIGHTLY = 1\n\nconst val OPUS = 1\nconst val M4A = 2\n\nconst val FORMAT_COMPATIBILITY = 1\nconst val FORMAT_QUALITY = 2\n\nconst val CONVERT_MP3 = 0\nconst val CONVERT_M4A = 1\n\nconst val HIGH = 1\nconst val MEDIUM = 2\nconst val LOW = 3\nconst val ULTRA_LOW = 4\n\nconst val RES_HIGHEST = 0\nconst val RES_2160P = 1\nconst val RES_1440P = 2\nconst val RES_1080P = 3\nconst val RES_720P = 4\nconst val RES_480P = 5\nconst val RES_360P = 6\nconst val RES_LOWEST = 7\n\nconst val TEMPLATE_EXAMPLE = \"\"\"--no-mtime -S \"ext\"\"\"\"\n\nconst val TEMPLATE_SHORTCUTS = \"template_shortcuts\"\n\nconst val TASK_LIST = \"task_list\"\nconst val SAVED_LINKS = \"saved_links\"\n\nval paletteStyles =\n    listOf(\n        PaletteStyle.TonalSpot,\n        PaletteStyle.Spritz,\n        PaletteStyle.FruitSalad,\n        PaletteStyle.Vibrant,\n        PaletteStyle.Monochrome,\n    )\n\nconst val STYLE_TONAL_SPOT = 0\nconst val STYLE_SPRITZ = 1\nconst val STYLE_FRUIT_SALAD = 2\nconst val STYLE_VIBRANT = 3\nconst val STYLE_MONOCHROME = 4\n\nprivate val StringPreferenceDefaults =\n    mapOf(\n        SPONSORBLOCK_CATEGORIES to \"default\",\n        MAX_RATE to \"1000\",\n        SUBTITLE_LANGUAGE to \"en.*,.*-orig\",\n        OUTPUT_TEMPLATE to DownloadUtil.OUTPUT_TEMPLATE_ID,\n        CUSTOM_OUTPUT_TEMPLATE to DownloadUtil.OUTPUT_TEMPLATE_ID,\n    )\n\nprivate val BooleanPreferenceDefaults =\n    mapOf(\n        FORMAT_SELECTION to true,\n        CONFIGURE to true,\n        CELLULAR_DOWNLOAD to false,\n        YT_DLP_AUTO_UPDATE to true,\n        NOTIFICATION to true,\n        EMBED_METADATA to true,\n        USE_CUSTOM_AUDIO_PRESET to false,\n    )\n\nprivate val IntPreferenceDefaults =\n    mapOf(\n        TEMPLATE_ID to 0,\n        CONCURRENT to 8,\n        LANGUAGE to SYSTEM_DEFAULT,\n        PALETTE_STYLE to 0,\n        DARK_THEME_VALUE to DarkThemePreference.FOLLOW_SYSTEM,\n        WELCOME_DIALOG to 1,\n        AUDIO_CONVERSION_FORMAT to NOT_SPECIFIED,\n        VIDEO_QUALITY to NOT_SPECIFIED,\n        VIDEO_FORMAT to FORMAT_QUALITY,\n        UPDATE_CHANNEL to STABLE,\n        SHOW_SPONSOR_MSG to 0,\n        CONVERT_SUBTITLE to NOT_SPECIFIED,\n        DOWNLOAD_TYPE_INITIALIZATION to USE_PREVIOUS_SELECTION,\n        YT_DLP_UPDATE_CHANNEL to YT_DLP_NIGHTLY,\n        DOWNLOAD_TYPE to DownloadType.Video.ordinal,\n    )\n\nprivate val LongPreferenceDefaults = mapOf(YT_DLP_UPDATE_INTERVAL to DEFAULT_INTERVAL)\n\nfun String.getStringDefault() = StringPreferenceDefaults.getOrElse(this) { \"\" }\n\nobject PreferenceUtil {\n    private val kv: MMKV = MMKV.defaultMMKV()\n    private val json = Json {\n        ignoreUnknownKeys = true\n        allowStructuredMapKeys = true\n    }\n\n    fun String.getInt(default: Int = IntPreferenceDefaults.getOrElse(this) { 0 }): Int =\n        kv.decodeInt(this, default)\n\n    fun String.getString(\n        default: String = StringPreferenceDefaults.getOrElse(this) { \"\" }\n    ): String = kv.decodeString(this) ?: default\n\n    fun String.getBoolean(\n        default: Boolean = BooleanPreferenceDefaults.getOrElse(this) { false }\n    ): Boolean = kv.decodeBool(this, default)\n\n    fun String.getLong(default: Long = LongPreferenceDefaults.getOrElse(this) { 0L }) =\n        kv.decodeLong(this, default)\n\n    fun String.updateString(newString: String) = kv.encode(this, newString)\n\n    fun String.updateInt(newInt: Int) = kv.encode(this, newInt)\n\n    fun String.updateLong(newLong: Long) = kv.encode(this, newLong)\n\n    fun String.updateBoolean(newValue: Boolean) = kv.encode(this, newValue)\n\n    fun updateValue(key: String, b: Boolean) = key.updateBoolean(b)\n\n    fun encodeInt(key: String, int: Int) = key.updateInt(int)\n\n    fun encodeString(key: String, string: String) = key.updateString(string)\n\n    fun containsKey(key: String) = kv.containsKey(key)\n\n    fun getAudioConvertFormat(): Int = AUDIO_CONVERSION_FORMAT.getInt()\n\n    fun getVideoResolution(): Int = VIDEO_QUALITY.getInt()\n\n    fun getAudioQuality(): Int = AUDIO_QUALITY.getInt()\n\n    fun getVideoFormat(): Int = VIDEO_FORMAT.getInt()\n\n    fun getAudioFormat(): Int = AUDIO_FORMAT.getInt()\n\n    fun getDownloadType(\n        usePreviousType: Boolean = DOWNLOAD_TYPE_INITIALIZATION.getInt() == USE_PREVIOUS_SELECTION\n    ): DownloadType? {\n        return if (usePreviousType) {\n            DownloadType.entries.firstOrNull { it.ordinal == DOWNLOAD_TYPE.getInt() }\n                ?: DownloadType.Video\n        } else {\n            null\n        }\n    }\n\n    fun updateDownloadType(type: DownloadType) = DOWNLOAD_TYPE.updateInt(type.ordinal)\n\n    fun isNetworkAvailableForDownload() =\n        CELLULAR_DOWNLOAD.getBoolean() || !App.connectivityManager.isActiveNetworkMetered\n\n    fun isAutoUpdateEnabled(): Boolean {\n        return when {\n            isFDroidBuild() -> false\n            isDebugBuild() -> false\n            else -> AUTO_UPDATE.getBoolean()\n        }\n    }\n\n    @DeprecatedSinceApi(api = 33)\n    fun getLocaleFromPreference(): Locale? {\n        val languageCode = LANGUAGE.getInt()\n        return LocaleLanguageCodeMap.entries.find { it.value == languageCode }?.key\n    }\n\n    fun saveLocalePreference(locale: Locale?) {\n        if (Build.VERSION.SDK_INT >= 33) {\n            // No op\n        } else {\n            LANGUAGE.updateInt(LocaleLanguageCodeMap[locale] ?: SYSTEM_DEFAULT)\n        }\n    }\n\n    fun getConcurrentFragments(level: Int = CONCURRENT.getInt()): Float {\n        return when (level) {\n            1 -> 0f\n            8 -> 0.33f\n            16 -> 0.66f\n            else -> 1f\n        }\n    }\n\n    fun getSponsorBlockCategories(): String = SPONSORBLOCK_CATEGORIES.getString()\n\n    const val COOKIE_HEADER =\n        \"# Netscape HTTP Cookie File\\n\" + \"# Auto-generated by Seal built-in WebView\\n\"\n\n    val templateListStateFlow: StateFlow<List<CommandTemplate>> =\n        DatabaseUtil.getTemplateFlow()\n            .stateIn(applicationScope, started = SharingStarted.Eagerly, emptyList())\n\n    private val List<CommandTemplate>.selectedTemplate: CommandTemplate?\n        get() = find { it.id == TEMPLATE_ID.getInt() }\n\n    fun getTemplate(): CommandTemplate {\n        var template: CommandTemplate? = null\n        runBlocking {\n            for (cnt in 1..5) {\n                template = templateListStateFlow.value.selectedTemplate\n                if (template != null) return@runBlocking\n                delay(100)\n            }\n        }\n        return template ?: throw NoSuchElementException()\n    }\n\n    suspend fun initializeTemplateSample() {\n        TEMPLATE_ID.updateInt(\n            DatabaseUtil.insertTemplate(\n                    CommandTemplate(\n                        id = 0,\n                        name = context.getString(R.string.custom_command_template),\n                        template = TEMPLATE_EXAMPLE,\n                    )\n                )\n                .toInt()\n        )\n    }\n\n    data class AppSettings(\n        val darkTheme: DarkThemePreference = DarkThemePreference(),\n        val isDynamicColorEnabled: Boolean = false,\n        val seedColor: Int = DEFAULT_SEED_COLOR,\n        val paletteStyleIndex: Int = 0,\n    )\n\n    fun getMaxDownloadRate(): String = MAX_RATE.getString()\n\n    private val mutableAppSettingsStateFlow =\n        MutableStateFlow(\n            AppSettings(\n                DarkThemePreference(\n                    darkThemeValue =\n                        kv.decodeInt(DARK_THEME_VALUE, DarkThemePreference.FOLLOW_SYSTEM),\n                    isHighContrastModeEnabled = kv.decodeBool(HIGH_CONTRAST, false),\n                ),\n                isDynamicColorEnabled =\n                    kv.decodeBool(DYNAMIC_COLOR, DynamicColors.isDynamicColorAvailable()),\n                seedColor = kv.decodeInt(THEME_COLOR, DEFAULT_SEED_COLOR),\n                paletteStyleIndex = kv.decodeInt(PALETTE_STYLE, 0),\n            )\n        )\n    val AppSettingsStateFlow = mutableAppSettingsStateFlow.asStateFlow()\n\n    fun modifyDarkThemePreference(\n        darkThemeValue: Int = AppSettingsStateFlow.value.darkTheme.darkThemeValue,\n        isHighContrastModeEnabled: Boolean =\n            AppSettingsStateFlow.value.darkTheme.isHighContrastModeEnabled,\n    ) {\n        applicationScope.launch(Dispatchers.IO) {\n            mutableAppSettingsStateFlow.update {\n                it.copy(\n                    darkTheme =\n                        AppSettingsStateFlow.value.darkTheme.copy(\n                            darkThemeValue = darkThemeValue,\n                            isHighContrastModeEnabled = isHighContrastModeEnabled,\n                        )\n                )\n            }\n            kv.encode(DARK_THEME_VALUE, darkThemeValue)\n            kv.encode(HIGH_CONTRAST, isHighContrastModeEnabled)\n        }\n    }\n\n    fun modifyThemeSeedColor(colorArgb: Int, paletteStyleIndex: Int) {\n        applicationScope.launch(Dispatchers.IO) {\n            mutableAppSettingsStateFlow.update {\n                it.copy(seedColor = colorArgb, paletteStyleIndex = paletteStyleIndex)\n            }\n            kv.encode(THEME_COLOR, colorArgb)\n            kv.encode(PALETTE_STYLE, paletteStyleIndex)\n        }\n    }\n\n    fun switchDynamicColor(\n        enabled: Boolean = !mutableAppSettingsStateFlow.value.isDynamicColorEnabled\n    ) {\n        applicationScope.launch(Dispatchers.IO) {\n            mutableAppSettingsStateFlow.update { it.copy(isDynamicColorEnabled = enabled) }\n            kv.encode(DYNAMIC_COLOR, enabled)\n        }\n    }\n\n    fun encodeTaskListBackup(map: Map<Task, Task.State>) =\n        runCatching { json.encodeToString<Map<Task, Task.State>>(map) }\n            .onSuccess { kv.encode(TASK_LIST, it) }\n            .onFailure { it.printStackTrace() }\n\n    fun decodeTaskListBackup(): Map<Task, Task.State> =\n        runCatching {\n                kv.decodeString(TASK_LIST)?.let { json.decodeFromString<Map<Task, Task.State>>(it) }\n            }\n            .onFailure { it.printStackTrace() }\n            .getOrNull() ?: emptyMap()\n\n    fun getSavedLinks(): Set<String> = kv.decodeStringSet(SAVED_LINKS) ?: emptySet()\n\n    fun updateSavedLinks(links: Set<String>) = kv.encode(SAVED_LINKS, links)\n\n    private const val TAG = \"PreferenceUtil\"\n}\n\ndata class DarkThemePreference(\n    val darkThemeValue: Int = FOLLOW_SYSTEM,\n    val isHighContrastModeEnabled: Boolean = false,\n) {\n    companion object {\n        const val FOLLOW_SYSTEM = 1\n        const val ON = 2\n        const val OFF = 3\n    }\n\n    @Composable\n    fun isDarkTheme(): Boolean {\n        return if (darkThemeValue == FOLLOW_SYSTEM) isSystemInDarkTheme() else darkThemeValue == ON\n    }\n\n    @Composable\n    fun getDarkThemeDesc(): String {\n        return when (darkThemeValue) {\n            FOLLOW_SYSTEM -> stringResource(R.string.follow_system)\n            ON -> stringResource(R.string.on)\n            else -> stringResource(R.string.off)\n        }\n    }\n}\n\nobject PreferenceStrings {\n    fun getSubtitleConversionFormat(subtitleFormat: Int = CONVERT_SUBTITLE.getInt()): String =\n        when (subtitleFormat) {\n            CONVERT_LRC -> context.getString(R.string.convert_to, \"lrc\")\n            CONVERT_ASS -> context.getString(R.string.convert_to, \"ass\")\n            CONVERT_SRT -> context.getString(R.string.convert_to, \"srt\")\n            CONVERT_VTT -> context.getString(R.string.convert_to, \"vtt\")\n            else -> context.getString(R.string.not_convert)\n        }\n\n    @Composable\n    fun getAudioFormatDesc(audioFormatCode: Int = PreferenceUtil.getAudioFormat()): String =\n        when (audioFormatCode) {\n            M4A -> \"M4A\"\n            OPUS -> \"OPUS\"\n            else -> stringResource(R.string.not_specified)\n        }\n\n    @Composable\n    fun getAudioQualityDesc(audioQualityCode: Int = PreferenceUtil.getAudioQuality()): String =\n        when (audioQualityCode) {\n            NOT_SPECIFIED -> stringResource(R.string.best_quality)\n            HIGH -> \"192 Kbps\"\n            MEDIUM -> \"128 Kbps\"\n            LOW -> \"64 Kbps\"\n            ULTRA_LOW -> \"32 Kbps\"\n            else -> stringResource(R.string.lowest_bitrate)\n        }\n\n    @Composable\n    fun getAudioConvertDesc(audioFormatCode: Int = PreferenceUtil.getAudioConvertFormat()): String {\n        return when (audioFormatCode) {\n            0 -> stringResource(R.string.convert_to).format(\"mp3\")\n            else -> stringResource(R.string.convert_to).format(\"m4a\")\n        }\n    }\n\n    @Composable\n    fun getVideoFormatDescComp(videoFormatCode: Int = PreferenceUtil.getVideoFormat()): String {\n        return when (videoFormatCode) {\n            FORMAT_COMPATIBILITY -> stringResource(R.string.prefer_compatibility_desc)\n            FORMAT_QUALITY -> stringResource(R.string.prefer_quality_desc)\n            else -> stringResource(R.string.not_specified)\n        }\n    }\n\n    @Composable\n    fun getVideoResolutionDesc(\n        videoQualityCode: Int = PreferenceUtil.getVideoResolution()\n    ): String {\n        return when (videoQualityCode) {\n            1 -> \"2160p\"\n            2 -> \"1440p\"\n            3 -> \"1080p\"\n            4 -> \"720p\"\n            5 -> \"480p\"\n            6 -> \"360p\"\n            7 -> stringResource(R.string.lowest_quality)\n            else -> stringResource(R.string.best_quality)\n        }\n    }\n\n    @Composable\n    fun getVideoFormatLabel(videoFormatPreference: Int = PreferenceUtil.getVideoFormat()): String {\n        return when (videoFormatPreference) {\n            FORMAT_COMPATIBILITY -> stringResource(id = R.string.legacy)\n            else -> stringResource(id = R.string.quality)\n        }\n    }\n\n    @Composable\n    fun getUpdateIntervalText(interval: Long): String {\n        return stringResource(\n            id =\n                when (interval) {\n                    INTERVAL_DAY -> R.string.every_day\n                    INTERVAL_WEEK -> R.string.every_week\n                    INTERVAL_MONTH -> R.string.every_month\n                    else -> R.string.disabled\n                }\n        )\n    }\n\n    @Composable\n    fun getAudioPresetText(preferences: DownloadUtil.DownloadPreferences): String {\n        return with(preferences) {\n            when {\n                formatSorting -> {\n                    sortingFields\n                }\n\n                !useCustomAudioPreset -> {\n                    stringResource(R.string.best_quality)\n                }\n\n                convertAudio -> {\n                    when (audioConvertFormat) {\n                        CONVERT_MP3 -> stringResource(R.string.convert_to, \"MP3\")\n                        else -> stringResource(R.string.convert_to, \"M4A\")\n                    }\n                }\n\n                else -> {\n                    val preferredFormat =\n                        when (audioFormat) {\n                            M4A -> stringResource(R.string.prefer_placeholder, \"M4A\")\n                            OPUS -> stringResource(R.string.prefer_placeholder, \"OPUS\")\n                            else -> null\n                        }\n                    val preferredQuality =\n                        when (audioQuality) {\n                            NOT_SPECIFIED -> stringResource(R.string.best_quality)\n                            HIGH -> \"192 Kbps\"\n                            MEDIUM -> \"128 Kbps\"\n                            LOW -> \"64 Kbps\"\n                            ULTRA_LOW -> \"32 Kbps\"\n                            else -> stringResource(R.string.lowest_bitrate)\n                        }\n                    listOfNotNull(preferredFormat, preferredQuality).joinToString(separator = \", \")\n                }\n            }\n        }\n    }\n\n    @Composable\n    fun getVideoPresetText(preferences: DownloadUtil.DownloadPreferences): String {\n        return with(preferences) {\n            when {\n                formatSorting -> {\n                    sortingFields\n                }\n\n                else -> {\n                    val preferredFormat =\n                        stringResource(\n                            id = R.string.prefer_placeholder,\n                            stringResource(\n                                id =\n                                    if (videoFormat == FORMAT_QUALITY) R.string.quality\n                                    else R.string.legacy\n                            ),\n                        )\n                    val preferredResolution = getVideoResolutionDesc(videoResolution)\n                    listOf(preferredFormat, preferredResolution).joinToString(separator = \", \")\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/SponsorData.kt",
    "content": "package com.junkfood.seal.util\n\nimport kotlinx.serialization.Serializable\n\n@Serializable data class SponsorData(val data: Data)\n\n@Serializable data class Data(val viewer: Viewer)\n\n@Serializable data class Viewer(val sponsorshipsAsMaintainer: SponsorshipsAsMaintainer)\n\n@Serializable data class SponsorshipsAsMaintainer(val nodes: List<SponsorShip>)\n\n@Serializable\ndata class SponsorEntity(\n    val login: String,\n    val name: String? = null,\n    val websiteUrl: String? = null,\n    val socialAccounts: SocialAccounts? = null,\n)\n\n@Serializable data class Tier(val monthlyPriceInDollars: Int)\n\n@Serializable data class SponsorShip(val sponsorEntity: SponsorEntity, val tier: Tier? = null)\n\n@Serializable data class SocialAccounts(val nodes: List<SocialAccount>? = null)\n\n@Serializable data class SocialAccount(val displayName: String?, val url: String?)\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/SponsorUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.util.Base64\nimport android.util.Log\nimport androidx.annotation.CheckResult\nimport kotlinx.serialization.json.Json\nimport okhttp3.MediaType.Companion.toMediaType\nimport okhttp3.OkHttpClient\nimport okhttp3.Request\nimport okhttp3.RequestBody.Companion.toRequestBody\n\nobject SponsorUtil {\n    private const val TAG = \"SponsorUtil\"\n    private const val MAGIC_STRING_0 = \"Z2hwX2F0cFlT\"\n    private const val MAGIC_STRING_1 = \"ZWtJQzFXb0JoQnBlYmlFbWI2TEZF\"\n    private const val MAGIC_STRING_2 = \"NXJDNzNvZndQVw\"\n\n    // pls don't abuse\n    private val magicString =\n        Base64.decode(MAGIC_STRING_0 + MAGIC_STRING_1 + MAGIC_STRING_2, Base64.DEFAULT)\n            .toString(Charsets.UTF_8)\n\n    private val body =\n        \"\"\"\n{ \"query\": \"query { viewer { sponsorshipsAsMaintainer(first: 100) { nodes { sponsorEntity { ... on User { login name websiteUrl socialAccounts(first: 4) { nodes { displayName url } } } ... on Organization { login name websiteUrl } } tier { monthlyPriceInDollars } } } } }\" }\n\"\"\"\n            .toRequestBody(\"application/json\".toMediaType())\n\n    private val request =\n        Request.Builder()\n            .url(\"https://api.github.com/graphql\")\n            .post(body)\n            .addHeader(\"Authorization\", \"bearer $magicString\")\n            .build()\n\n    private val client = OkHttpClient()\n    private val jsonFormat = Json { ignoreUnknownKeys = true }\n    private var sponsorData: SponsorData? = null\n\n    @CheckResult\n    fun getSponsors(): Result<SponsorData> =\n        client\n            .runCatching {\n                sponsorData\n                    ?: jsonFormat\n                        .decodeFromString<SponsorData>(\n                            newCall(request).execute().body.string().also { Log.d(TAG, it) }\n                        )\n                        .apply { sponsorData = this }\n            }\n            .onFailure { it.printStackTrace() }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/TextUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.content.Context\nimport android.widget.Toast\nimport androidx.annotation.MainThread\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.res.stringResource\nimport androidx.core.text.isDigitsOnly\nimport com.junkfood.seal.App\nimport com.junkfood.seal.App.Companion.applicationScope\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.R\nimport java.util.regex.Pattern\nimport kotlin.math.roundToInt\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\n\n@Deprecated(\"Use extension functions of Context to show a toast\")\nobject ToastUtil {\n    fun makeToast(text: String) {\n        Toast.makeText(context.applicationContext, text, Toast.LENGTH_SHORT).show()\n    }\n\n    fun makeToastSuspend(text: String) {\n        applicationScope.launch(Dispatchers.Main) { makeToast(text) }\n    }\n\n    fun makeToast(stringId: Int) {\n        Toast.makeText(context.applicationContext, context.getString(stringId), Toast.LENGTH_SHORT)\n            .show()\n    }\n}\n\n@MainThread\nfun Context.makeToast(stringId: Int) {\n    Toast.makeText(applicationContext, getString(stringId), Toast.LENGTH_SHORT).show()\n}\n\n@MainThread\nfun Context.makeToast(message: String) {\n    Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()\n}\n\nprivate const val GIGA_BYTES = 1024f * 1024f * 1024f\nprivate const val MEGA_BYTES = 1024f * 1024f\n\n@Composable\nfun Number?.toFileSizeText(): String {\n    if (this == null) return stringResource(id = R.string.unknown)\n\n    return this.toFloat().run {\n        if (this > GIGA_BYTES) stringResource(R.string.filesize_gb).format(this / GIGA_BYTES)\n        else stringResource(R.string.filesize_mb).format(this / MEGA_BYTES)\n    }\n}\n\n/** Convert time in **seconds** to `hh:mm:ss` or `mm:ss` */\nfun Int.toDurationText(): String =\n    this.run {\n        if (this > 3600) \"%d:%02d:%02d\".format(this / 3600, (this % 3600) / 60, this % 60)\n        else \"%02d:%02d\".format(this / 60, this % 60)\n    }\n\nfun String.isNumberInRange(start: Int, end: Int): Boolean {\n    return this.isNotEmpty() &&\n        this.isDigitsOnly() &&\n        this.length < 10 &&\n        this.toInt() >= start &&\n        this.toInt() <= end\n}\n\nprivate const val URL_REGEX_PATTERN =\n    \"(http|https)://[\\\\w\\\\-_]+(\\\\.[\\\\w\\\\-_]+)+([\\\\w\\\\-.,@?^=%&:/~+#]*[\\\\w\\\\-@?^=%&/~+#])?\"\n\nfun String.isNumberInRange(range: IntRange): Boolean = this.isNumberInRange(range.first, range.last)\n\nfun ClosedFloatingPointRange<Float>.toIntRange() =\n    IntRange(start.roundToInt(), endInclusive.roundToInt())\n\nfun String?.toHttpsUrl(): String =\n    this?.run { if (matches(Regex(\"^(http:).*\"))) replaceFirst(\"http\", \"https\") else this } ?: \"\"\n\nfun matchUrlFromClipboard(string: String, isMatchingMultiLink: Boolean = false): String {\n    findURLsFromString(string, !isMatchingMultiLink).joinToString(separator = \"\\n\").run {\n        if (isEmpty()) ToastUtil.makeToast(R.string.paste_fail_msg)\n        else ToastUtil.makeToast(R.string.paste_msg)\n        return this\n    }\n}\n\nfun matchUrlFromSharedText(s: String): String {\n    findURLsFromString(s, true).joinToString(separator = \"\\n\").run {\n        if (isEmpty()) ToastUtil.makeToast(R.string.share_fail_msg)\n        //            else makeToast(R.string.share_success_msg)\n        return this\n    }\n}\n\nfun Number?.toBitrateText(): String {\n    val br = this?.toFloat() ?: return \"\"\n    return when {\n        br <= 0f -> \"\" // i don't care\n        br < 1024f -> \"%.1f Kbps\".format(br)\n\n        else -> \"%.2f Mbps\".format(br / 1024f)\n    }\n}\n\nfun getErrorReport(th: Throwable, url: String): String =\n    App.getVersionReport() + \"\\nURL: ${url}\\n${th.message}\"\n\n@Deprecated(\n    \"Use findURLsFromString instead\",\n    ReplaceWith(\"findURLsFromString(s, !isMatchingMultiLink).joinToString(separator = \\\"\\\\n\\\")\"),\n)\nfun matchUrlFromString(s: String, isMatchingMultiLink: Boolean = false): String =\n    findURLsFromString(s, !isMatchingMultiLink).joinToString(separator = \"\\n\")\n\nfun findURLsFromString(input: String, firstMatchOnly: Boolean = false): List<String> {\n    val result = mutableListOf<String>()\n    val pattern = Pattern.compile(URL_REGEX_PATTERN)\n\n    with(pattern.matcher(input)) {\n        if (!firstMatchOnly) {\n            while (find()) {\n                result += group()\n            }\n        } else {\n            if (find()) result += (group())\n        }\n    }\n    return result\n}\n\nfun connectWithDelimiter(vararg strings: String?, delimiter: String): String =\n    strings\n        .toList()\n        .filter { !it.isNullOrBlank() }\n        .joinToString(separator = delimiter) { it.toString() }\n\nfun connectWithBlank(s1: String, s2: String): String {\n    val blank = if (s1.isEmpty() || s2.isEmpty()) \"\" else \" \"\n    return s1 + blank + s2\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/UpdateUtil.kt",
    "content": "package com.junkfood.seal.util\n\nimport android.content.Context\nimport android.content.Intent\nimport android.content.pm.PackageManager\nimport android.os.Build\nimport android.util.Log\nimport androidx.core.content.FileProvider\nimport com.junkfood.seal.App\nimport com.junkfood.seal.App.Companion.context\nimport com.junkfood.seal.R\nimport com.junkfood.seal.util.FileUtil.getFileProvider\nimport com.junkfood.seal.util.PreferenceUtil.getInt\nimport com.junkfood.seal.util.PreferenceUtil.updateLong\nimport com.yausername.youtubedl_android.YoutubeDL\nimport java.io.File\nimport java.util.regex.Pattern\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.distinctUntilChanged\nimport kotlinx.coroutines.flow.emptyFlow\nimport kotlinx.coroutines.flow.flow\nimport kotlinx.coroutines.flow.flowOn\nimport kotlinx.coroutines.withContext\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.json.Json\nimport okhttp3.OkHttpClient\nimport okhttp3.Request\nimport okhttp3.ResponseBody\n\nobject UpdateUtil {\n\n    private const val OWNER = \"JunkFood02\"\n    private const val REPO = \"Seal\"\n    private const val ARM64 = \"arm64-v8a\"\n    private const val ARM32 = \"armeabi-v7a\"\n    private const val X86 = \"x86\"\n    private const val X64 = \"x86_64\"\n    private const val TAG = \"UpdateUtil\"\n\n    private val client = OkHttpClient()\n    private val requestForLatestRelease =\n        Request.Builder()\n            .url(\"https://api.github.com/repos/${OWNER}/${REPO}/releases/latest\")\n            .build()\n\n    private val requestForReleases =\n        Request.Builder().url(\"https://api.github.com/repos/${OWNER}/${REPO}/releases\").build()\n\n    private const val ytdlpNightlyBuildRelease =\n        \"https://api.github.com/repos/yt-dlp/yt-dlp-nightly-builds/releases/latest\"\n\n    private val jsonFormat = Json { ignoreUnknownKeys = true }\n\n    suspend fun updateYtDlp(): YoutubeDL.UpdateStatus? =\n        withContext(Dispatchers.IO) {\n            val channel =\n                when (YT_DLP_UPDATE_CHANNEL.getInt()) {\n                    YT_DLP_NIGHTLY -> YoutubeDL.UpdateChannel.NIGHTLY\n                    else -> YoutubeDL.UpdateChannel.STABLE\n                }\n\n            YoutubeDL.getInstance()\n                .updateYoutubeDL(appContext = context, updateChannel = channel)\n                .also {\n                    if (it == YoutubeDL.UpdateStatus.DONE) {\n                        YoutubeDL.getInstance().version(context)?.let {\n                            PreferenceUtil.encodeString(YT_DLP_VERSION, it)\n                        }\n                    }\n                    val now = System.currentTimeMillis()\n                    YT_DLP_UPDATE_TIME.updateLong(now)\n                }\n        }\n\n    private fun getLatestRelease(): Release =\n        client.newCall(requestForReleases).execute().body.use {\n            val releaseList = jsonFormat.decodeFromString<List<Release>>(it.string())\n            val stable = UPDATE_CHANNEL.getInt() == STABLE\n            val latestRelease =\n                releaseList\n                    .filter { if (stable) it.name.toVersion() is Version.Stable else true }\n                    .maxByOrNull { it.name.toVersion() } ?: throw Exception(\"null response\")\n            latestRelease\n        }\n\n    fun checkForUpdate(context: Context = App.context): Release? {\n        val currentVersion = context.getCurrentVersion()\n        val latestRelease = getLatestRelease()\n        val latestVersion = latestRelease.name.toVersion()\n        return if (currentVersion < latestVersion) latestRelease else null\n    }\n\n    private fun Context.getCurrentVersion(): Version =\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n            packageManager\n                .getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))\n                .versionName\n                .toVersion()\n        } else {\n            packageManager.getPackageInfo(packageName, 0).versionName.toVersion()\n        }\n\n    private fun Context.getLatestApk() = File(getExternalFilesDir(\"apk\"), \"latest.apk\")\n\n    fun installLatestApk(context: Context = App.context) =\n        context.run {\n            kotlin\n                .runCatching {\n                    val contentUri =\n                        FileProvider.getUriForFile(this, getFileProvider(), getLatestApk())\n                    val intent =\n                        Intent(Intent.ACTION_VIEW).apply {\n                            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)\n                            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)\n                            setDataAndType(contentUri, \"application/vnd.android.package-archive\")\n                        }\n                    startActivity(intent)\n                }\n                .onFailure { throwable: Throwable ->\n                    throwable.printStackTrace()\n                    ToastUtil.makeToast(R.string.app_update_failed)\n                }\n        }\n\n    suspend fun deleteOutdatedApk(context: Context = App.context) =\n        context.runCatching {\n            val apkFile = getLatestApk()\n            if (apkFile.exists()) {\n                val apkVersion =\n                    context.packageManager\n                        .getPackageArchiveInfo(apkFile.absolutePath, 0)\n                        ?.versionName\n                        .toVersion()\n                if (apkVersion <= context.getCurrentVersion()) {\n                    apkFile.delete()\n                }\n            }\n        }\n\n    suspend fun downloadApk(\n        context: Context = App.context,\n        release: Release,\n    ): Flow<DownloadStatus> =\n        withContext(Dispatchers.IO) {\n            val apkVersion =\n                context.packageManager\n                    .getPackageArchiveInfo(context.getLatestApk().absolutePath, 0)\n                    ?.versionName\n                    .toVersion()\n\n            Log.d(TAG, apkVersion.toString())\n\n            if (apkVersion >= release.name.toVersion()) {\n                return@withContext flow<DownloadStatus> {\n                    emit(DownloadStatus.Finished(context.getLatestApk()))\n                }\n            }\n\n            val abiList = Build.SUPPORTED_ABIS\n            val preferredArch = abiList.firstOrNull() ?: return@withContext emptyFlow()\n\n            val targetUrl =\n                release.assets\n                    ?.find {\n                        return@find it.name?.contains(preferredArch) ?: false\n                    }\n                    ?.browserDownloadUrl ?: return@withContext emptyFlow()\n            val request = Request.Builder().url(targetUrl).build()\n            try {\n                val response = client.newCall(request).execute()\n                val responseBody = response.body\n                return@withContext responseBody.downloadFileWithProgress(context.getLatestApk())\n            } catch (e: Exception) {\n                e.printStackTrace()\n            }\n            emptyFlow()\n        }\n\n    private fun ResponseBody.downloadFileWithProgress(saveFile: File): Flow<DownloadStatus> =\n        flow {\n                emit(DownloadStatus.Progress(0))\n\n                var deleteFile = true\n\n                try {\n                    byteStream().use { inputStream ->\n                        saveFile.outputStream().use { outputStream ->\n                            val totalBytes = contentLength()\n                            val data = ByteArray(8_192)\n                            var progressBytes = 0L\n\n                            while (true) {\n                                val bytes = inputStream.read(data)\n\n                                if (bytes == -1) {\n                                    break\n                                }\n\n                                outputStream.channel\n                                outputStream.write(data, 0, bytes)\n                                progressBytes += bytes\n                                emit(\n                                    DownloadStatus.Progress(\n                                        percent = ((progressBytes * 100) / totalBytes).toInt()\n                                    )\n                                )\n                            }\n\n                            when {\n                                progressBytes < totalBytes -> throw Exception(\"missing bytes\")\n                                progressBytes > totalBytes -> throw Exception(\"too many bytes\")\n                                else -> deleteFile = false\n                            }\n                        }\n                    }\n\n                    emit(DownloadStatus.Finished(saveFile))\n                } finally {\n                    if (deleteFile) {\n                        saveFile.delete()\n                    }\n                }\n            }\n            .flowOn(Dispatchers.IO)\n            .distinctUntilChanged()\n\n    @Serializable\n    data class Release(\n        @SerialName(\"html_url\") val htmlUrl: String? = null,\n        @SerialName(\"tag_name\") val tagName: String? = null,\n        val name: String? = null,\n        val draft: Boolean? = null,\n        @SerialName(\"prerelease\") val preRelease: Boolean? = null,\n        @SerialName(\"created_at\") val createdAt: String? = null,\n        @SerialName(\"published_at\") val publishedAt: String? = null,\n        val assets: List<AssetsItem>? = null,\n        val body: String? = null,\n    )\n\n    @Serializable\n    data class AssetsItem(\n        val name: String? = null,\n        @SerialName(\"content_type\") val contentType: String? = null,\n        val size: Int? = null,\n        @SerialName(\"download_count\") val downloadCount: Int? = null,\n        @SerialName(\"created_at\") val createdAt: String? = null,\n        @SerialName(\"updated_at\") val updatedAt: String? = null,\n        @SerialName(\"browser_download_url\") val browserDownloadUrl: String? = null,\n    )\n\n    sealed class DownloadStatus {\n        object NotYet : DownloadStatus()\n\n        data class Progress(val percent: Int) : DownloadStatus()\n\n        data class Finished(val file: File) : DownloadStatus()\n    }\n\n    private val pattern = Pattern.compile(\"\"\"v?(\\d+)\\.(\\d+)\\.(\\d+)(-(\\w+)\\.(\\d+))?\"\"\")\n    private val EMPTY_VERSION = Version.Stable()\n\n    fun String?.toVersion(): Version =\n        this?.run {\n            val matcher = pattern.matcher(this)\n            if (matcher.find()) {\n                val major = matcher.group(1)?.toInt() ?: 0\n                val minor = matcher.group(2)?.toInt() ?: 0\n                val patch = matcher.group(3)?.toInt() ?: 0\n                val buildNumber = matcher.group(6)?.toInt() ?: 0\n                when (matcher.group(5)) {\n                    \"alpha\" -> Version.Alpha(major, minor, patch, buildNumber)\n                    \"beta\" -> Version.Beta(major, minor, patch, buildNumber)\n                    \"rc\" -> Version.ReleaseCandidate(major, minor, patch, buildNumber)\n                    else -> Version.Stable(major, minor, patch)\n                }\n            } else EMPTY_VERSION\n        } ?: EMPTY_VERSION\n\n    sealed class Version(val major: Int, val minor: Int, val patch: Int, val build: Int = 0) :\n        Comparable<Version> {\n        companion object {\n            // private const val ABI = 1L\n            private const val BUILD = 10L\n            private const val VARIANT = 100L\n            private const val PATCH = 10_000L\n            private const val MINOR = 1_000_000L\n            private const val MAJOR = 100_000_000L\n\n            private const val STABLE = VARIANT * 4\n            private const val ALPHA = VARIANT * 1\n            private const val BETA = VARIANT * 2\n            private const val RELEASE_CANDIDATE = VARIANT * 3\n        }\n\n        abstract fun toVersionName(): String\n\n        abstract fun toNumber(): Long\n\n        class Alpha(\n            versionMajor: Int = 0,\n            versionMinor: Int = 0,\n            versionPatch: Int = 0,\n            versionBuild: Int = 0,\n        ) : Version(versionMajor, versionMinor, versionPatch, versionBuild) {\n            override fun toVersionName(): String = \"${major}.${minor}.${patch}-alpha.$build\"\n\n            override fun toNumber(): Long =\n                major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + ALPHA\n        }\n\n        class Beta(versionMajor: Int, versionMinor: Int, versionPatch: Int, versionBuild: Int) :\n            Version(versionMajor, versionMinor, versionPatch, versionBuild) {\n            override fun toVersionName(): String = \"${major}.${minor}.${patch}-beta.$build\"\n\n            override fun toNumber(): Long =\n                major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + BETA\n        }\n\n        class ReleaseCandidate(\n            versionMajor: Int,\n            versionMinor: Int,\n            versionPatch: Int,\n            versionBuild: Int,\n        ) : Version(versionMajor, versionMinor, versionPatch, versionBuild) {\n            override fun toVersionName(): String = \"${major}.${minor}.${patch}-rc.$build\"\n\n            override fun toNumber(): Long =\n                major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + RELEASE_CANDIDATE\n        }\n\n        class Stable(versionMajor: Int = 0, versionMinor: Int = 0, versionPatch: Int = 0) :\n            Version(versionMajor, versionMinor, versionPatch) {\n            override fun toVersionName(): String = \"${major}.${minor}.${patch}\"\n\n            override fun toNumber(): Long =\n                major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + STABLE\n            // Prioritize stable versions\n\n        }\n\n        override operator fun compareTo(other: Version): Int =\n            this.toNumber().compareTo(other.toNumber())\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/junkfood/seal/util/VideoInfo.kt",
    "content": "package com.junkfood.seal.util\n\nimport kotlin.math.roundToInt\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Serializable\n\nsealed interface YoutubeDLInfo\n\n@Serializable\ndata class VideoInfo(\n    val id: String = \"\",\n    val title: String = \"\",\n    val formats: List<Format>? = emptyList(),\n    //    val thumbnails: List<Thumbnail> = emptyList(),\n    val thumbnail: String? = null,\n    val description: String? = null,\n    val uploader: String? = null,\n    @SerialName(\"uploader_id\") val uploaderId: String? = null,\n    val subtitles: Map<String, List<SubtitleFormat>> = emptyMap(),\n    @SerialName(\"automatic_captions\")\n    val automaticCaptions: Map<String, List<SubtitleFormat>> = emptyMap(),\n    //    @SerialName(\"uploader_id\") val uploaderId: String? = null,\n    //    @SerialName(\"uploader_url\") val uploaderUrl: String? = null,\n    //    @SerialName(\"channel_id\") val channelId: Int? = null,\n    //    @SerialName(\"channel_url\") val channelUrl: String? = null,\n    val duration: Double? = null,\n    @SerialName(\"view_count\") val viewCount: Long? = null,\n    @SerialName(\"webpage_url\") val webpageUrl: String? = null,\n    //    @SerialName(\"categories\") val categories: List<String> = emptyList(),\n    val tags: List<String>? = emptyList(),\n    @SerialName(\"live_status\") val liveStatus: String? = null,\n    //    @SerialName(\"release_timestamp\") val releaseTimestamp: Int? = null,\n    @SerialName(\"comment_count\") val commentCount: Int? = null,\n    val chapters: List<Chapter>? = null,\n    @SerialName(\"like_count\") val likeCount: Int? = null,\n    val channel: String? = null,\n    //    @SerialName(\"channel_follower_count\") val channelFollowerCount: Int? = null,\n    @SerialName(\"upload_date\") val uploadDate: String? = null,\n    val availability: String? = null,\n    @SerialName(\"original_url\") val originalUrl: String? = null,\n    @SerialName(\"webpage_url_basename\") val webpageUrlBasename: String? = null,\n    @SerialName(\"webpage_url_domain\") val webpageUrlDomain: String? = null,\n    val extractor: String? = null,\n    @SerialName(\"extractor_key\") val extractorKey: String = \"\",\n    val playlist: String? = null,\n    @SerialName(\"playlist_index\") val playlistIndex: Int? = null,\n    @SerialName(\"display_id\") val displayId: String? = null,\n    val fulltitle: String? = null,\n    @SerialName(\"duration_string\") val durationString: String? = null,\n    @SerialName(\"release_date\") val releaseDate: String? = null,\n    val format: String? = null,\n    @SerialName(\"format_id\") val formatId: String? = null,\n    val ext: String = \"\",\n    val protocol: String? = null,\n    @SerialName(\"format_note\") val formatNote: String? = null,\n    @SerialName(\"filesize_approx\") val fileSizeApprox: Double? = null,\n    @SerialName(\"filesize\") val fileSize: Double? = null,\n    val tbr: Double? = null,\n    val width: Double? = null,\n    val height: Double? = null,\n    val resolution: String? = null,\n    val fps: Double? = null,\n    @SerialName(\"dynamic_range\") val dynamicRange: String? = null,\n    val vcodec: String? = null,\n    val vbr: Double? = null,\n    val acodec: String? = null,\n    val abr: Double? = null,\n    val asr: Int? = null,\n    val epoch: Int? = null,\n    @SerialName(\"requested_downloads\") val requestedDownloads: List<RequestedDownload>? = null,\n    @SerialName(\"requested_formats\") val requestedFormats: List<Format>? = null,\n    val filename: String? = null,\n    @SerialName(\"_type\") val type: String? = null,\n) : YoutubeDLInfo\n\n@Serializable\ndata class Format(\n    @SerialName(\"format_id\") val formatId: String? = null,\n    @SerialName(\"format_note\") val formatNote: String? = null,\n    val ext: String? = null,\n    @SerialName(\"acodec\") val acodec: String? = null,\n    @SerialName(\"vcodec\") val vcodec: String? = null,\n    val url: String? = null,\n    val width: Double? = null,\n    val height: Double? = null,\n    val fps: Double? = null,\n    @SerialName(\"audio_ext\") val audioExt: String? = null,\n    @SerialName(\"video_ext\") val videoExt: String? = null,\n    val format: String? = null,\n    val resolution: String? = null,\n    val vbr: Double? = null,\n    val abr: Double? = null,\n    val tbr: Double? = null,\n    @SerialName(\"filesize\") val fileSize: Double? = null,\n    @SerialName(\"filesize_approx\") val fileSizeApprox: Double? = null,\n) {\n    fun isAudioOnly(): Boolean = vcodec == null || vcodec == \"none\"\n\n    fun isVideoOnly(): Boolean = acodec == null || acodec == \"none\"\n\n    fun containsVideo(): Boolean = vcodec != null && vcodec != \"none\"\n\n    fun containsAudio(): Boolean = acodec != null && acodec != \"none\"\n}\n\n@Serializable\ndata class VideoClip(val start: Int = 0, val end: Int = 0) {\n    constructor(\n        range: ClosedFloatingPointRange<Float>\n    ) : this(range.start.roundToInt(), range.endInclusive.roundToInt())\n}\n\n@Serializable\ndata class Chapter(\n    val title: String? = null,\n    @SerialName(\"start_time\") val startTime: Double? = null,\n    @SerialName(\"end_time\") val endTime: Double? = null,\n)\n\n@Serializable\ndata class RequestedDownload(\n    @SerialName(\"requested_formats\") val requestedFormats: List<Format>? = emptyList(),\n    @SerialName(\"format_id\") val formatId: String? = null,\n    @SerialName(\"format_note\") val formatNote: String? = null,\n    val ext: String? = null,\n    @SerialName(\"acodec\") val acodec: String? = null,\n    @SerialName(\"vcodec\") val vcodec: String? = null,\n    val url: String? = null,\n    val width: Double? = null,\n    val height: Double? = null,\n    val fps: Double? = null,\n    @SerialName(\"audio_ext\") val audioExt: String? = null,\n    @SerialName(\"video_ext\") val videoExt: String? = null,\n    val format: String? = null,\n    val resolution: String? = null,\n    val vbr: Double? = null,\n    val abr: Double? = null,\n    val tbr: Double? = null,\n    @SerialName(\"filesize\") val fileSize: Double? = null,\n    @SerialName(\"filesize_approx\") val fileSizeApprox: Double? = null,\n    val filename: String? = null,\n) {\n    fun toFormat(): Format =\n        Format(\n            formatId = formatId,\n            formatNote = formatNote,\n            ext = ext,\n            acodec = acodec,\n            vcodec = vcodec,\n            url = url,\n            width = width,\n            height = height,\n            fps = fps,\n            audioExt = audioExt,\n            videoExt = videoExt,\n            format = format,\n            resolution = resolution,\n            vbr = vbr,\n            abr = abr,\n            tbr = tbr,\n            fileSize = fileSize,\n            fileSizeApprox = fileSizeApprox,\n        )\n}\n\n@Serializable\ndata class PlaylistResult(\n    val uploader: String? = null,\n    val availability: String? = null,\n    val channel: String? = null,\n    val title: String? = null,\n    val description: String? = null,\n    @SerialName(\"_type\") val type: String? = null,\n    val entries: List<PlaylistEntry>? = emptyList(),\n    @SerialName(\"webpage_url\") val webpageUrl: String? = null,\n    @SerialName(\"original_url\") val originalUrl: String? = null,\n    @SerialName(\"extractor_key\") val extractorKey: String? = null,\n) : YoutubeDLInfo\n\n@Serializable\ndata class Thumbnail(val url: String, val height: Double = .0, val width: Double = .0)\n\n@Serializable\ndata class PlaylistEntry(\n    @SerialName(\"_type\") val type: String? = null,\n    val ieKey: String? = null,\n    val id: String? = null,\n    val url: String? = null,\n    val title: String? = null,\n    val duration: Double? = .0,\n    val uploader: String? = null,\n    val channel: String? = null,\n    val thumbnails: List<Thumbnail>? = emptyList(),\n)\n\n@Serializable\ndata class SubtitleFormat(\n    val ext: String,\n    val url: String,\n    val name: String? = null,\n    val protocol: String? = null,\n)\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <group\n        android:scaleX=\"0.14127907\"\n        android:scaleY=\"0.14127907\"\n        android:translateX=\"29.7\"\n        android:translateY=\"29.7\">\n        <path\n            android:fillColor=\"#000000\"\n            android:pathData=\"M156.8,1.9c-22.6,4.9 -42.7,18.6 -55.3,37.6 -8.5,12.7 -13.1,25.5 -15,41.8 -0.6,4.6 -1.5,6.7 -4.2,9.9 -6.8,8.2 -8.6,15.3 -5.8,22.8 3.7,9.7 3.5,10.7 -4.5,20.1 -22.5,26.5 -36.3,58.3 -38.7,89.1l-0.6,7.8 -4.2,-0c-6.8,-0 -13.8,2.6 -18.9,7.1 -9,8 -10.8,15 -8.2,32.9 4.3,29.9 13.9,50.9 25.3,55.6 1.8,0.8 3.3,1.9 3.3,2.5 0,0.5 2.1,3.2 4.6,5.9 3.2,3.4 6.3,5.6 10.2,7 5.6,2.1 15.2,2.2 77.2,1.2 0.8,-0.1 19.7,0.2 41.9,0.4 43.6,0.6 51,0.1 65.8,-4.2l8.7,-2.5 6.5,3.3 6.5,3.3 34.4,0.3c39.6,0.3 41.2,0.1 49.4,-7.6 11.6,-10.8 11.5,-27.6 -0.1,-38.5 -4.8,-4.5 -12.2,-7.7 -17.8,-7.7 -4,-0 -8.2,-2.8 -10.3,-7 -3.5,-6.9 -5,-17.6 -6.1,-42.5 -2.2,-55.2 -10.5,-96.6 -26,-129.5 -5,-10.8 -6,-13.8 -7,-22 -5.1,-42.8 -29.1,-74.8 -64.4,-86 -10.1,-3.2 -34.4,-3.8 -46.7,-1.1zM202,13.7c31,11.3 50.3,38.1 55.4,77.3 1.3,9.9 2,12.3 7.4,23.8 14.7,31.2 23.5,73.6 24.9,119.7 0.7,23.4 -0.4,31.5 -5.6,45.1 -7.9,20.3 -26.3,37.8 -48.8,46.6 -15.7,6.1 -21.8,6.8 -62.5,6.8l-36.7,-0 3.6,-5.3c8.6,-12.7 14,-31.6 15.9,-55.9l0.6,-8.8 -5.4,-0 -5.5,-0 -0.7,9.1c-2.3,30.2 -11.6,52.9 -24.1,58.8 -4.3,2 -5.9,2.1 -37.8,2.1 -33.1,-0 -33.4,-0 -36.8,-2.3 -10.2,-6.9 -10.6,-19.7 -0.9,-26.8 1.4,-1 6,-2.5 10.3,-3.4 19.9,-3.7 39.9,-20.2 40.9,-33.7l0.3,-3.3 -5.1,-0.3 -5.2,-0.3 -0.7,3.7c-0.9,5.3 -10.9,15.1 -19.5,19.2 -7.7,3.7 -7.1,4.2 -13.6,-9.3 -6.9,-14.2 -8.8,-23.3 -8.8,-40.5 0,-35 12.4,-67.1 36.4,-94.5 10.1,-11.6 12.1,-19.5 7.4,-28.8 -2.3,-4.3 -1.2,-8.7 3.4,-14.6 4.6,-5.8 5.8,-9 6.7,-18.1 0.3,-3.6 1.9,-10.3 3.5,-15 8.6,-26 29.3,-45.3 55.8,-52 10.7,-2.7 36.9,-2.3 45.2,0.7zM33.3,248.7c0.9,9.9 4.2,21.5 9.3,32.2 2.4,5.1 4.4,9.5 4.4,9.7 0,0.2 -1.7,1.1 -3.7,1.9 -6.9,2.9 -12.9,10.1 -15.7,18.8 -0.8,2.6 -2.3,1.3 -5.5,-5.1 -4,-7.9 -6.9,-17.7 -9.2,-31 -3.1,-18.2 -2.5,-23.5 3.3,-28.9 3.2,-3 6.5,-4.2 11.9,-4.2l4.6,-0.1 0.6,6.7zM299.5,290.9c3.8,5.7 7.3,7.8 16.6,9.7 11.9,2.4 16.4,6.9 16.4,16.4 0,6.3 -1.6,9.5 -6.9,13.4 -2.6,2 -4.2,2.1 -36.5,2.4 -18.5,0.1 -34.8,-0.1 -36,-0.6 -2.1,-0.7 -1.6,-1.3 5.7,-6.1 14.3,-9.4 29.1,-26.4 33.9,-38.9 1.5,-3.9 1.8,-4.3 2.7,-2.7 0.6,1 2.5,3.8 4.1,6.4z\"\n            android:strokeColor=\"#00000000\" />\n        <path\n            android:fillColor=\"#000000\"\n            android:pathData=\"M161,37.5l-3.4,3.5 5.4,5.5 5.4,5.5 3.8,-3.7 3.8,-3.7 -5.2,-5.3c-2.9,-2.9 -5.5,-5.3 -5.8,-5.3 -0.3,-0 -2.1,1.6 -4,3.5z\"\n            android:strokeColor=\"#00000000\" />\n        <path\n            android:fillColor=\"#000000\"\n            android:pathData=\"M195.2,39.3l-5.2,5.3 3.8,3.7 3.8,3.7 5.2,-5.3 5.2,-5.3 -3.8,-3.7 -3.8,-3.7 -5.2,5.3z\"\n            android:strokeColor=\"#00000000\" />\n        <path\n            android:fillColor=\"#000000\"\n            android:pathData=\"M147.2,56c-6.6,4 -9.3,12.9 -5.2,17 5.9,5.9 19,-2.2 19,-11.8 0,-6.6 -7,-9.3 -13.8,-5.2z\"\n            android:strokeColor=\"#00000000\" />\n        <path\n            android:fillColor=\"#000000\"\n            android:pathData=\"M206.2,56.5c-3.7,4.6 -2.3,9.6 4.3,15.4 4.8,4.1 10.4,4.4 13.4,0.5 2.5,-3.1 2.6,-5.5 0.7,-9.2 -2.6,-5 -7.1,-8.4 -11.9,-8.9 -3.9,-0.5 -4.6,-0.2 -6.5,2.2z\"\n            android:strokeColor=\"#00000000\" />\n        <path\n            android:fillColor=\"#000000\"\n            android:pathData=\"M172.5,71.2c-3.6,1.9 -5.5,5.2 -5.5,9.4 0,3.2 0.9,5.2 4,9.5 2.3,3 4.5,5.5 5,5.7 0.6,0.2 1,2.3 1,4.7 0,4.3 -0.2,4.5 -6.2,8.6 -3.5,2.3 -6.5,4.4 -6.7,4.5 -0.5,0.5 4.8,8.4 5.6,8.4 0.4,-0 3.5,-1.8 6.9,-4.1l6.3,-4.1 6,4.1c3.3,2.3 6.4,4.1 6.8,4.1 0.9,-0 5.3,-6.5 5.3,-7.9 0,-0.5 -2.9,-2.9 -6.5,-5.2 -5.9,-3.8 -6.5,-4.5 -6.5,-7.6 0,-2.5 1.2,-4.7 4.6,-8.9 2.5,-3.1 5,-6.8 5.5,-8.3 1.5,-3.9 0.2,-8.7 -3.2,-11.5 -2.8,-2.4 -3.9,-2.6 -11.7,-2.6 -4.8,-0 -9.6,0.6 -10.7,1.2zM187,81.7c-0.1,1 -3.6,5.3 -4.3,5.3 -0.3,-0 -1.5,-1.4 -2.7,-3l-2.1,-3 4.5,-0c2.5,-0 4.6,0.3 4.6,0.7z\"\n            android:strokeColor=\"#00000000\" />\n    </group>\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_monochrome.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"128\"\n    android:viewportHeight=\"128\">\n    <path\n        android:fillColor=\"#000000\"\n        android:fillType=\"evenOdd\"\n        android:pathData=\"M70.66,90.88C69.08,91.02 66.88,91.02 62.68,90.97C61.1,90.95 59.63,90.94 58.44,90.92C58.13,90.92 57.84,90.92 57.58,90.91C57.84,90.92 58.13,90.92 58.44,90.92L58.44,90.92C59.63,90.94 61.1,90.95 62.68,90.97C66.88,91.02 69.08,91.02 70.66,90.88ZM78.38,49.96C77.53,43.59 74.29,39.24 69.08,37.41C67.68,36.92 63.28,36.86 61.48,37.29C57.03,38.38 53.56,41.51 52.11,45.74C51.84,46.5 51.57,47.59 51.52,48.17C51.37,49.65 51.17,50.17 50.4,51.11C49.62,52.07 49.44,52.78 49.83,53.48C50.62,54.99 50.28,56.27 48.58,58.16C44.55,62.6 42.47,67.82 42.47,73.5C42.47,76.29 42.79,77.77 43.95,80.07L44.06,80.3C44.61,81.41 44.83,81.86 45.15,81.93C45.37,81.99 45.63,81.87 46.06,81.66C46.12,81.64 46.17,81.61 46.23,81.58C47.68,80.92 49.36,79.33 49.51,78.47L49.62,77.86L50.5,77.91L51.35,77.96L51.3,78.5C51.14,80.69 47.78,83.37 44.43,83.97C43.71,84.12 42.94,84.36 42.7,84.52C41.07,85.67 41.14,87.75 42.85,88.87C43.43,89.25 43.48,89.25 49.04,89.25C54.4,89.25 54.66,89.23 55.39,88.9C57.49,87.95 59.05,84.26 59.43,79.36L59.55,77.88H61.38L61.28,79.31C60.96,83.25 60.06,86.32 58.61,88.38L58.01,89.25H64.17C71.01,89.25 72.03,89.13 74.67,88.14C78.45,86.71 81.54,83.87 82.87,80.58C83.74,78.37 83.93,77.05 83.81,73.25C83.57,65.77 82.1,58.89 79.63,53.82C78.72,51.95 78.6,51.56 78.38,49.96ZM40.18,88.61C40.18,88.6 40.18,88.59 40.17,88.57C40.18,88.59 40.18,88.6 40.18,88.61M42.3,80.79C41.44,79.05 40.89,77.17 40.74,75.56L40.64,74.47L39.86,74.49C38.96,74.49 38.4,74.68 37.87,75.17C36.89,76.05 36.79,76.91 37.31,79.86C37.7,82.02 38.18,83.61 38.86,84.89C39.39,85.93 39.65,86.14 39.78,85.72C40.25,84.31 41.26,83.14 42.42,82.67C42.75,82.54 43.04,82.39 43.04,82.36C43.04,82.33 42.7,81.61 42.3,80.79ZM88.25,83.99C86.68,83.68 86.09,83.34 85.46,82.41C85.3,82.17 85.13,81.91 84.99,81.71L84.99,81.71L84.99,81.71L84.99,81.71L84.99,81.71C84.89,81.56 84.81,81.44 84.77,81.37C84.62,81.11 84.57,81.18 84.31,81.81C83.51,83.84 81.02,86.6 78.62,88.13C77.39,88.9 77.31,89 77.66,89.12C77.86,89.2 80.6,89.23 83.71,89.21C89.14,89.16 89.4,89.15 89.84,88.82C90.73,88.19 91,87.67 91,86.65C91,85.11 90.24,84.37 88.25,83.99ZM61.62,41.84L62.19,41.27C62.51,40.96 62.81,40.7 62.86,40.7C62.91,40.7 63.35,41.09 63.84,41.56L64.71,42.42L63.43,43.63L61.62,41.84ZM67.06,42.42L68.34,43.63L70.09,41.9L68.81,40.7L67.06,42.42ZM59,47.03C58.31,46.37 58.76,44.92 59.87,44.27C61.01,43.61 62.19,44.05 62.19,45.12C62.19,46.68 59.99,47.99 59,47.03ZM69.78,44.36C69.16,45.1 69.4,45.91 70.51,46.86C71.31,47.52 72.25,47.57 72.76,46.94C73.18,46.43 73.19,46.04 72.87,45.44C72.44,44.63 71.68,44.08 70.87,44C70.22,43.92 70.1,43.97 69.78,44.36ZM63.2,48.27C63.2,47.59 63.52,47.05 64.12,46.74C64.31,46.64 65.11,46.55 65.92,46.55C67.23,46.55 67.41,46.58 67.88,46.97C68.46,47.42 68.67,48.2 68.42,48.84C68.34,49.08 67.92,49.68 67.5,50.18C66.93,50.87 66.73,51.22 66.73,51.63C66.73,52.13 66.83,52.25 67.82,52.86C68.42,53.24 68.91,53.63 68.91,53.71C68.91,53.93 68.17,54.99 68.02,54.99C67.95,54.99 67.43,54.7 66.88,54.32L65.87,53.66L64.81,54.32C64.24,54.7 63.72,54.99 63.65,54.99C63.52,54.99 62.63,53.71 62.71,53.63C62.72,53.62 62.81,53.56 62.95,53.47L62.95,53.47L62.95,53.47L62.95,53.47L62.95,53.47C63.16,53.34 63.48,53.12 63.84,52.9C64.84,52.23 64.88,52.2 64.88,51.5C64.88,51.11 64.81,50.77 64.71,50.74C64.63,50.7 64.26,50.3 63.87,49.81C63.35,49.11 63.2,48.79 63.2,48.27ZM65.84,49.31C65.95,49.31 66.54,48.61 66.56,48.45C66.56,48.38 66.2,48.33 65.78,48.33H65.03L65.38,48.82C65.58,49.08 65.78,49.31 65.84,49.31Z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/icons8_matrix.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\">\n  <path\n      android:fillColor=\"#FF000000\"\n      android:pathData=\"M3,4L3,20L6,20L6,18L5,18L5,6L6,6L6,4L3,4zM18,4L18,6L19,6L19,18L18,18L18,20L21,20L21,4L18,4zM14.752,8.424C14.253,8.414 13.75,8.537 13.346,8.814C13.086,8.993 12.862,9.222 12.605,9.441C12.214,8.664 11.508,8.457 10.701,8.443C9.883,8.43 9.25,8.801 8.682,9.479L8.682,8.641L7,8.641L7,14.988L8.787,14.988C8.787,14.988 8.784,12.609 8.789,11.434C8.79,11.225 8.801,11.012 8.844,10.807C8.976,10.179 9.514,9.792 10.158,9.844C10.771,9.894 11.05,10.227 11.08,10.951C11.085,11.077 11.088,14.984 11.088,14.984L12.898,14.984C12.898,14.984 12.891,12.513 12.902,11.463C12.905,11.192 12.932,10.914 12.998,10.652C13.146,10.064 13.623,9.777 14.271,9.848C14.843,9.91 15.13,10.226 15.172,10.848L15.172,15L16.975,15C16.975,15 17.004,11.88 16.975,10.398C16.969,10.095 16.871,9.771 16.734,9.496C16.402,8.829 15.583,8.441 14.752,8.424z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/icons8_telegram_app.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\">\n  <path\n      android:fillColor=\"#FF000000\"\n      android:pathData=\"M20.572,3.012C20.24,2.976 19.879,3.028 19.516,3.172C19.066,3.349 12.014,6.315 5.441,9.082L3.27,9.996C2.429,10.337 2.004,10.892 2.004,11.639C2.004,12.162 2.225,12.871 3.281,13.289L6.947,14.758C7.264,15.709 8.001,17.917 8.186,18.504C8.296,18.852 8.573,19.729 9.275,19.934C9.419,19.983 9.57,20.008 9.723,20.008C10.166,20.008 10.485,19.802 10.641,19.682L12.971,17.711L15.801,20.328C15.91,20.439 16.487,21 17.262,21C18.229,21 18.962,20.195 19.115,19.416C19.198,18.989 21.928,5.287 21.928,5.289C22.173,4.19 21.732,3.62 21.449,3.377C21.207,3.169 20.905,3.047 20.572,3.012zM19.91,5.172C19.533,7.062 17.478,17.378 17.166,18.865L13.029,15.039L10.223,17.416L11,14.375C11,14.375 16.363,8.947 16.686,8.631C16.946,8.378 17,8.289 17,8.201C17,8.084 16.94,8 16.801,8C16.676,8 16.506,8.12 16.416,8.176C15.273,8.889 10.404,11.662 8.008,13.025L4.531,11.637L6.219,10.928C10.518,9.118 18.174,5.894 19.91,5.172z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/outline_cancel_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM15.59,7L12,10.59 8.41,7 7,8.41 10.59,12 7,15.59 8.41,17 12,13.41 15.59,17 17,15.59 13.41,12 17,8.41z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/outline_content_copy_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/seal.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"200dp\"\n    android:height=\"200dp\"\n    android:viewportWidth=\"344\"\n    android:viewportHeight=\"344\">\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M156.8,1.9c-22.6,4.9 -42.7,18.6 -55.3,37.6 -8.5,12.7 -13.1,25.5 -15,41.8 -0.6,4.6 -1.5,6.7 -4.2,9.9 -6.8,8.2 -8.6,15.3 -5.8,22.8 3.7,9.7 3.5,10.7 -4.5,20.1 -22.5,26.5 -36.3,58.3 -38.7,89.1l-0.6,7.8 -4.2,-0c-6.8,-0 -13.8,2.6 -18.9,7.1 -9,8 -10.8,15 -8.2,32.9 4.3,29.9 13.9,50.9 25.3,55.6 1.8,0.8 3.3,1.9 3.3,2.5 0,0.5 2.1,3.2 4.6,5.9 3.2,3.4 6.3,5.6 10.2,7 5.6,2.1 15.2,2.2 77.2,1.2 0.8,-0.1 19.7,0.2 41.9,0.4 43.6,0.6 51,0.1 65.8,-4.2l8.7,-2.5 6.5,3.3 6.5,3.3 34.4,0.3c39.6,0.3 41.2,0.1 49.4,-7.6 11.6,-10.8 11.5,-27.6 -0.1,-38.5 -4.8,-4.5 -12.2,-7.7 -17.8,-7.7 -4,-0 -8.2,-2.8 -10.3,-7 -3.5,-6.9 -5,-17.6 -6.1,-42.5 -2.2,-55.2 -10.5,-96.6 -26,-129.5 -5,-10.8 -6,-13.8 -7,-22 -5.1,-42.8 -29.1,-74.8 -64.4,-86 -10.1,-3.2 -34.4,-3.8 -46.7,-1.1zM202,13.7c31,11.3 50.3,38.1 55.4,77.3 1.3,9.9 2,12.3 7.4,23.8 14.7,31.2 23.5,73.6 24.9,119.7 0.7,23.4 -0.4,31.5 -5.6,45.1 -7.9,20.3 -26.3,37.8 -48.8,46.6 -15.7,6.1 -21.8,6.8 -62.5,6.8l-36.7,-0 3.6,-5.3c8.6,-12.7 14,-31.6 15.9,-55.9l0.6,-8.8 -5.4,-0 -5.5,-0 -0.7,9.1c-2.3,30.2 -11.6,52.9 -24.1,58.8 -4.3,2 -5.9,2.1 -37.8,2.1 -33.1,-0 -33.4,-0 -36.8,-2.3 -10.2,-6.9 -10.6,-19.7 -0.9,-26.8 1.4,-1 6,-2.5 10.3,-3.4 19.9,-3.7 39.9,-20.2 40.9,-33.7l0.3,-3.3 -5.1,-0.3 -5.2,-0.3 -0.7,3.7c-0.9,5.3 -10.9,15.1 -19.5,19.2 -7.7,3.7 -7.1,4.2 -13.6,-9.3 -6.9,-14.2 -8.8,-23.3 -8.8,-40.5 0,-35 12.4,-67.1 36.4,-94.5 10.1,-11.6 12.1,-19.5 7.4,-28.8 -2.3,-4.3 -1.2,-8.7 3.4,-14.6 4.6,-5.8 5.8,-9 6.7,-18.1 0.3,-3.6 1.9,-10.3 3.5,-15 8.6,-26 29.3,-45.3 55.8,-52 10.7,-2.7 36.9,-2.3 45.2,0.7zM33.3,248.7c0.9,9.9 4.2,21.5 9.3,32.2 2.4,5.1 4.4,9.5 4.4,9.7 0,0.2 -1.7,1.1 -3.7,1.9 -6.9,2.9 -12.9,10.1 -15.7,18.8 -0.8,2.6 -2.3,1.3 -5.5,-5.1 -4,-7.9 -6.9,-17.7 -9.2,-31 -3.1,-18.2 -2.5,-23.5 3.3,-28.9 3.2,-3 6.5,-4.2 11.9,-4.2l4.6,-0.1 0.6,6.7zM299.5,290.9c3.8,5.7 7.3,7.8 16.6,9.7 11.9,2.4 16.4,6.9 16.4,16.4 0,6.3 -1.6,9.5 -6.9,13.4 -2.6,2 -4.2,2.1 -36.5,2.4 -18.5,0.1 -34.8,-0.1 -36,-0.6 -2.1,-0.7 -1.6,-1.3 5.7,-6.1 14.3,-9.4 29.1,-26.4 33.9,-38.9 1.5,-3.9 1.8,-4.3 2.7,-2.7 0.6,1 2.5,3.8 4.1,6.4z\"\n        android:strokeColor=\"#00000000\" />\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M161,37.5l-3.4,3.5 5.4,5.5 5.4,5.5 3.8,-3.7 3.8,-3.7 -5.2,-5.3c-2.9,-2.9 -5.5,-5.3 -5.8,-5.3 -0.3,-0 -2.1,1.6 -4,3.5z\"\n        android:strokeColor=\"#00000000\" />\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M195.2,39.3l-5.2,5.3 3.8,3.7 3.8,3.7 5.2,-5.3 5.2,-5.3 -3.8,-3.7 -3.8,-3.7 -5.2,5.3z\"\n        android:strokeColor=\"#00000000\" />\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M147.2,56c-6.6,4 -9.3,12.9 -5.2,17 5.9,5.9 19,-2.2 19,-11.8 0,-6.6 -7,-9.3 -13.8,-5.2z\"\n        android:strokeColor=\"#00000000\" />\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M206.2,56.5c-3.7,4.6 -2.3,9.6 4.3,15.4 4.8,4.1 10.4,4.4 13.4,0.5 2.5,-3.1 2.6,-5.5 0.7,-9.2 -2.6,-5 -7.1,-8.4 -11.9,-8.9 -3.9,-0.5 -4.6,-0.2 -6.5,2.2z\"\n        android:strokeColor=\"#00000000\" />\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M172.5,71.2c-3.6,1.9 -5.5,5.2 -5.5,9.4 0,3.2 0.9,5.2 4,9.5 2.3,3 4.5,5.5 5,5.7 0.6,0.2 1,2.3 1,4.7 0,4.3 -0.2,4.5 -6.2,8.6 -3.5,2.3 -6.5,4.4 -6.7,4.5 -0.5,0.5 4.8,8.4 5.6,8.4 0.4,-0 3.5,-1.8 6.9,-4.1l6.3,-4.1 6,4.1c3.3,2.3 6.4,4.1 6.8,4.1 0.9,-0 5.3,-6.5 5.3,-7.9 0,-0.5 -2.9,-2.9 -6.5,-5.2 -5.9,-3.8 -6.5,-4.5 -6.5,-7.6 0,-2.5 1.2,-4.7 4.6,-8.9 2.5,-3.1 5,-6.8 5.5,-8.3 1.5,-3.9 0.2,-8.7 -3.2,-11.5 -2.8,-2.4 -3.9,-2.6 -11.7,-2.6 -4.8,-0 -9.6,0.6 -10.7,1.2zM187,81.7c-0.1,1 -3.6,5.3 -4.3,5.3 -0.3,-0 -1.5,-1.4 -2.7,-3l-2.1,-3 4.5,-0c2.5,-0 4.6,0.3 4.6,0.7z\"\n        android:strokeColor=\"#00000000\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-anydpi-v24/ic_stat_seal.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"128\"\n    android:viewportHeight=\"128\"\n    android:tint=\"#FFFFFF\">\n  <group android:scaleX=\"2.0219781\"\n      android:scaleY=\"2.0219781\"\n      android:translateX=\"-65.40659\"\n      android:translateY=\"-65.40659\">\n      <path\n          android:fillColor=\"#000000\"\n          android:fillType=\"evenOdd\"\n          android:pathData=\"M70.66,90.88C69.08,91.02 66.88,91.02 62.68,90.97C61.1,90.95 59.63,90.94 58.44,90.92C58.13,90.92 57.84,90.92 57.58,90.91C57.84,90.92 58.13,90.92 58.44,90.92L58.44,90.92C59.63,90.94 61.1,90.95 62.68,90.97C66.88,91.02 69.08,91.02 70.66,90.88ZM78.38,49.96C77.53,43.59 74.29,39.24 69.08,37.41C67.68,36.92 63.28,36.86 61.48,37.29C57.03,38.38 53.56,41.51 52.11,45.74C51.84,46.5 51.57,47.59 51.52,48.17C51.37,49.65 51.17,50.17 50.4,51.11C49.62,52.07 49.44,52.78 49.83,53.48C50.62,54.99 50.28,56.27 48.58,58.16C44.55,62.6 42.47,67.82 42.47,73.5C42.47,76.29 42.79,77.77 43.95,80.07L44.06,80.3C44.61,81.41 44.83,81.86 45.15,81.93C45.37,81.99 45.63,81.87 46.06,81.66C46.12,81.64 46.17,81.61 46.23,81.58C47.68,80.92 49.36,79.33 49.51,78.47L49.62,77.86L50.5,77.91L51.35,77.96L51.3,78.5C51.14,80.69 47.78,83.37 44.43,83.97C43.71,84.12 42.94,84.36 42.7,84.52C41.07,85.67 41.14,87.75 42.85,88.87C43.43,89.25 43.48,89.25 49.04,89.25C54.4,89.25 54.66,89.23 55.39,88.9C57.49,87.95 59.05,84.26 59.43,79.36L59.55,77.88H61.38L61.28,79.31C60.96,83.25 60.06,86.32 58.61,88.38L58.01,89.25H64.17C71.01,89.25 72.03,89.13 74.67,88.14C78.45,86.71 81.54,83.87 82.87,80.58C83.74,78.37 83.93,77.05 83.81,73.25C83.57,65.77 82.1,58.89 79.63,53.82C78.72,51.95 78.6,51.56 78.38,49.96ZM40.18,88.61C40.18,88.6 40.18,88.59 40.17,88.57C40.18,88.59 40.18,88.6 40.18,88.61M42.3,80.79C41.44,79.05 40.89,77.17 40.74,75.56L40.64,74.47L39.86,74.49C38.96,74.49 38.4,74.68 37.87,75.17C36.89,76.05 36.79,76.91 37.31,79.86C37.7,82.02 38.18,83.61 38.86,84.89C39.39,85.93 39.65,86.14 39.78,85.72C40.25,84.31 41.26,83.14 42.42,82.67C42.75,82.54 43.04,82.39 43.04,82.36C43.04,82.33 42.7,81.61 42.3,80.79ZM88.25,83.99C86.68,83.68 86.09,83.34 85.46,82.41C85.3,82.17 85.13,81.91 84.99,81.71L84.99,81.71L84.99,81.71L84.99,81.71L84.99,81.71C84.89,81.56 84.81,81.44 84.77,81.37C84.62,81.11 84.57,81.18 84.31,81.81C83.51,83.84 81.02,86.6 78.62,88.13C77.39,88.9 77.31,89 77.66,89.12C77.86,89.2 80.6,89.23 83.71,89.21C89.14,89.16 89.4,89.15 89.84,88.82C90.73,88.19 91,87.67 91,86.65C91,85.11 90.24,84.37 88.25,83.99ZM61.62,41.84L62.19,41.27C62.51,40.96 62.81,40.7 62.86,40.7C62.91,40.7 63.35,41.09 63.84,41.56L64.71,42.42L63.43,43.63L61.62,41.84ZM67.06,42.42L68.34,43.63L70.09,41.9L68.81,40.7L67.06,42.42ZM59,47.03C58.31,46.37 58.76,44.92 59.87,44.27C61.01,43.61 62.19,44.05 62.19,45.12C62.19,46.68 59.99,47.99 59,47.03ZM69.78,44.36C69.16,45.1 69.4,45.91 70.51,46.86C71.31,47.52 72.25,47.57 72.76,46.94C73.18,46.43 73.19,46.04 72.87,45.44C72.44,44.63 71.68,44.08 70.87,44C70.22,43.92 70.1,43.97 69.78,44.36ZM63.2,48.27C63.2,47.59 63.52,47.05 64.12,46.74C64.31,46.64 65.11,46.55 65.92,46.55C67.23,46.55 67.41,46.58 67.88,46.97C68.46,47.42 68.67,48.2 68.42,48.84C68.34,49.08 67.92,49.68 67.5,50.18C66.93,50.87 66.73,51.22 66.73,51.63C66.73,52.13 66.83,52.25 67.82,52.86C68.42,53.24 68.91,53.63 68.91,53.71C68.91,53.93 68.17,54.99 68.02,54.99C67.95,54.99 67.43,54.7 66.88,54.32L65.87,53.66L64.81,54.32C64.24,54.7 63.72,54.99 63.65,54.99C63.52,54.99 62.63,53.71 62.71,53.63C62.72,53.62 62.81,53.56 62.95,53.47L62.95,53.47L62.95,53.47L62.95,53.47L62.95,53.47C63.16,53.34 63.48,53.12 63.84,52.9C64.84,52.23 64.88,52.2 64.88,51.5C64.88,51.11 64.81,50.77 64.71,50.74C64.63,50.7 64.26,50.3 63.87,49.81C63.35,49.11 63.2,48.79 63.2,48.27ZM65.84,49.31C65.95,49.31 66.54,48.61 66.56,48.45C66.56,48.38 66.2,48.33 65.78,48.33H65.03L65.38,48.82C65.58,49.08 65.78,49.31 65.84,49.31Z\" />\n  </group>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n    <monochrome android:drawable=\"@drawable/ic_launcher_monochrome\"/>\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n    <monochrome android:drawable=\"@drawable/ic_launcher_monochrome\"/>\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/resources.properties",
    "content": "unqualifiedResLocale=en-US"
  },
  {
    "path": "app/src/main/res/values/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"ic_launcher_background\">#FFFFFF</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\" translatable=\"false\">Seal</string>\n    <string name=\"video_directory\">Video folder</string>\n    <string name=\"extract_audio\">Save as audio</string>\n    <string name=\"create_thumbnail\">Save thumbnail</string>\n    <string name=\"settings\">Settings</string>\n    <string name=\"download_settings_desc\">General, format, custom command</string>\n    <string name=\"download\">Download</string>\n    <string name=\"url_empty\">The link cannot be empty</string>\n    <string name=\"extract_audio_summary\">Download and save audio, instead of video</string>\n    <string name=\"create_thumbnail_summary\">Save video thumbnail as a file</string>\n    <string name=\"yt_dlp_up_to_date\">Using the latest version of yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Could not install the latest yt-dlp version. Please make sure you are connected to the Internet.</string>\n    <string name=\"fetching_info\">Fetching video info…</string>\n    <string name=\"permission_denied\">Permission denied</string>\n    <string name=\"download_success_msg\">Download finished</string>\n    <string name=\"download_error_msg\">Could not download file</string>\n    <string name=\"download_start_msg\">Download \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Could not fetch video info</string>\n    <string name=\"general_settings\">General</string>\n    <string name=\"language\">Display language</string>\n    <string name=\"language_settings\">Set display language</string>\n    <string name=\"task_running\">An existing download task is already running</string>\n    <string name=\"paste_msg\">Paste URL</string>\n    <string name=\"paste_fail_msg\">Could not match the URL in the clipboard</string>\n    <string name=\"ytdlp_version\">Yt-dlp version</string>\n    <string name=\"ytdlp_update\">Click to install the latest yt-dlp version</string>\n    <string name=\"ytdlp_update_action\">Update yt-dlp</string>\n    <string name=\"delete_info\">Remove?</string>\n    <string name=\"delete_info_msg\">Remove \\\"%1$s\\\" from your download history for good?\n    </string>\n    <string name=\"confirm\">Confirm</string>\n    <string name=\"dismiss\">Cancel</string>\n    <string name=\"downloads_history\">Downloads</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Link copied to clipboard</string>\n    <string name=\"open_url\">Open link</string>\n    <string name=\"remove\">Remove</string>\n    <string name=\"delete_file\">Delete file</string>\n    <string name=\"about\">About</string>\n    <string name=\"about_page\">Version, feedback, auto update</string>\n    <string name=\"back\">Back</string>\n    <string name=\"version\">Version</string>\n    <string name=\"release_desc\">Look for changelogs and new versions</string>\n    <string name=\"release\">Latest release</string>\n    <string name=\"readme_desc\">Check the GitHub repository and the README</string>\n    <string name=\"readme\" translatable=\"false\">README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Checked</string>\n    <string name=\"credits\">Credits</string>\n    <string name=\"credits_desc\">Credits and libre software</string>\n    <string name=\"custom_command\">Custom command</string>\n    <string name=\"custom_command_desc\">Run yt-dlp command with custom template</string>\n    <string name=\"custom_command_template\">Command template</string>\n    <string name=\"edit\">Edit</string>\n    <string name=\"start_execute\">Start executing command</string>\n    <string name=\"advanced_settings\">Advanced</string>\n    <string name=\"print_details\">Detailed output</string>\n    <string name=\"print_details_desc\">Print detailed messages when downloading</string>\n    <string name=\"display\">Display</string>\n    <string name=\"display_settings\">Dark theme, dynamic color, languages</string>\n    <string name=\"dark_theme\">Dark theme</string>\n    <string name=\"follow_system\">System</string>\n    <string name=\"on\">On</string>\n    <string name=\"off\">Off</string>\n    <string name=\"cancel\">Cancel</string>\n    <string name=\"settings_before_download\">Configure before download</string>\n    <string name=\"settings_before_download_desc\">Configure preferences before downloading</string>\n    <string name=\"settings_before_download_text\">Adjust this download</string>\n    <string name=\"error_copied\">Error report copied to clipboard</string>\n    <string name=\"thumbnail\">Thumbnail</string>\n    <string name=\"paste\">Paste</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp usage references</string>\n    <string name=\"edit_template_desc\">Output path and URL will be added by the app.</string>\n    <string name=\"convert_audio_format\">Convert audio format</string>\n    <string name=\"not_convert\">Unconverted</string>\n    <string name=\"convert_to\">Convert to %1$s</string>\n    <string name=\"format\">Format</string>\n    <string name=\"convert_audio_format_desc\">Re-encoding audio files will cause loss in audio quality and increase in file size.</string>\n    <string name=\"video_quality\">Video quality</string>\n    <string name=\"best_quality\">Best quality</string>\n    <string name=\"video_quality_desc\">Limit the video quality when multiple are present</string>\n    <string name=\"not_specified\">Not specified (default)</string>\n    <string name=\"video_format_preference\">Preferred video format</string>\n    <string name=\"preferred_format_desc\">Preferred format when multiple are provided</string>\n    <string name=\"video_format\">Video format</string>\n    <string name=\"convert_audio\">Convert</string>\n    <string name=\"start_download\">Download</string>\n    <string name=\"close\">Close</string>\n    <string name=\"close_never_show_again\">Don\\'t show up again</string>\n    <string name=\"user_guide\">User guide</string>\n    <string name=\"open_settings\">Open settings</string>\n    <string name=\"paste_desc\">Click \\\"Paste\\\" to get video link from your clipboard.</string>\n    <string name=\"download_desc\">Then click \\\"Download\\\" after adjusting its settings.\n    </string>\n    <string name=\"download_history_desc\">Check and manage in-app downloads, including videos and audio files.</string>\n    <string name=\"check_download_settings_desc\">Take a look at the download settings and make sure\n        you have the latest version of yt-dlp before using it.\n    </string>\n    <string name=\"download_playlist\">Download playlist</string>\n    <string name=\"download_playlist_desc\">Download multiple videos from a playlist</string>\n    <string name=\"defaults\">Default</string>\n    <string name=\"channel_name\">Download</string>\n    <string name=\"channel_description\">Notify of downloaded files and progress</string>\n    <string name=\"video_url\">Video link</string>\n    <string name=\"download_finish_notification\">Download finished. Tap to open.</string>\n    <string name=\"execute_command_notification\">Running custom commands…</string>\n    <string name=\"battery_settings_desc\">\"Please set battery usage of this app to \\\"Unrestricted\\\" in the system settings to download in the background.\"\n    </string>\n    <string name=\"concurrent_download\">Multi-threaded download</string>\n    <string name=\"concurrent_download_desc\">Download more parts of M3U8/MPD videos in parallel</string>\n    <string name=\"concurrent_download_num\">%d thread(s) would be used to download DASH/HLS native video concurrently.</string>\n    <string name=\"options\">Options</string>\n    <string name=\"additional_settings\">Additional settings</string>\n    <string name=\"share_fail_msg\">Unable to match URL from shared content</string>\n    <string name=\"share_success_msg\">Reading video link from shared content…</string>\n    <string name=\"show_more_actions\">Show more actions</string>\n    <string name=\"download_notification\">Download notification</string>\n    <string name=\"download_notification_desc\">\"Notify of downloaded files and progress\"</string>\n    <string name=\"fetching_playlist_info\">Fetching playlist info…</string>\n    <string name=\"download_range_selection\">Playlist selection</string>\n    <string name=\"download_range_desc\">\"Specify the range of videos to download from the playlist \\\"%3$s\\\" (from %1$d to %2$d).\"</string>\n    <string name=\"from\">Start</string>\n    <string name=\"to\">End</string>\n    <string name=\"invalid_index_range\">Invalid index range</string>\n    <string name=\"playlist_indicator_text\">Downloading playlist (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Audio folder</string>\n    <string name=\"download_directory\">Download directory</string>\n    <string name=\"download_directory_desc\">Select where to store videos and audio files</string>\n    <string name=\"subdirectory\">Save to subdirectory</string>\n    <string name=\"subdirectory_desc\">Save files in folders named as respective fields</string>\n    <string name=\"permission_issue\">Storage permission issue</string>\n    <string name=\"permission_issue_desc\">Directories outside Download/ and Documents/ are not supported</string>\n    <string name=\"battery_configuration\">Battery configuration</string>\n    <string name=\"battery_configuration_desc\">Ignore battery optimization for this app to download in the background</string>\n    <string name=\"service_title\">Seal is downloading…</string>\n    <string name=\"unknown_error\">Unknown error</string>\n    <string name=\"translate\">Translate</string>\n    <string name=\"translate_desc\">Help translate this app on Hosted Weblate</string>\n    <string name=\"prefix\">Prefix</string>\n    <string name=\"embed_subtitles\">Embed subtitles</string>\n    <string name=\"embed_subtitles_desc\">Embed soft-subs into videos if available</string>\n    <string name=\"new_template\">New template</string>\n    <string name=\"template_label\">Label</string>\n    <string name=\"remove_template\">Remove?</string>\n    <string name=\"remove_template_desc\">Remove \\\"%1$s\\\" from command templates for good?</string>\n    <string name=\"template_selection\">Template selection</string>\n    <string name=\"custom_command_template_desc\">Edit and manage command templates</string>\n    <string name=\"downloading_indicator_text\">Download in progress…</string>\n    <string name=\"task_canceled\">Download task canceled</string>\n    <string name=\"github_issue\">GitHub issue</string>\n    <string name=\"github_issue_desc\">Submit an issue for bug report or feature request</string>\n    <string name=\"info_copied\">Info copied to clipboard</string>\n\n    <string name=\"status_enqueued\">Enqueued</string>\n    <string name=\"status_completed\">Finished</string>\n    <string name=\"status_downloading\">Downloading</string>\n    <string name=\"status_canceled\">Canceled</string>\n    <string name=\"status_fetching_video_info\">Fetching info</string>\n    <string name=\"open_file\">Open file</string>\n    <string name=\"restart\">Restart</string>\n    <string name=\"status_error\">Error</string>\n    <string name=\"copy_link\">Copy link</string>\n    <string name=\"copy_error_report\">Copy report</string>\n    <string name=\"video_resolution\">Video resolution</string>\n    <string name=\"video_file_size\">Video file size</string>\n    <string name=\"export_to_clipboard\">Export to clipboard</string>\n    <string name=\"import_from_clipboard\">Import from clipboard</string>\n    <string name=\"template_exported\">Exported %1$d template(s)</string>\n    <string name=\"template_imported\">Imported %1$d template(s)</string>\n    <string name=\"download_task_count\">%1$d Download tasks</string>\n    <string name=\"recently_added\">Recently Added</string>\n    <string name=\"multiselect_item_count\">%1$d video(s), %2$d audio file(s)</string>\n    <string name=\"delete_multiple_items_msg\">Remove %1$d item(s) from your download history for good?</string>\n    <string name=\"sponsorblock\" translatable=\"false\">SponsorBlock</string>\n    <string name=\"sponsorblock_desc\">Remove or mark segments in videos with SponsorBlock API</string>\n    <string name=\"sponsorblock_categories_desc\">Specify the SponsorBlock categories to remove or mark in the video file</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock categories</string>\n    <string name=\"check_for_updates\">Check for updates</string>\n    <string name=\"check_for_updates_desc\">Automatically check for the latest version on GitHub</string>\n    <string name=\"app_up_to_date\">The current version is up to date</string>\n    <string name=\"app_update_failed\">Failed to update to the latest version</string>\n    <string name=\"update\">Update</string>\n    <string name=\"aria2\" translatable=\"false\">Aria2</string>\n    <string name=\"aria2_desc\">Use aria2c as the external downloader</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"cookies_desc\">Use Netscape formatted cookies for downloads</string>\n    <string name=\"cookies_file_name\" translatable=\"false\">cookies.txt</string>\n    <string name=\"clear_temp_files\">Clear temporary files</string>\n    <string name=\"clear_temp_files_desc\">Delete all temporary files from the temporary directory</string>\n    <string name=\"clear_temp_files_count\">Deleted %1$d temporary file(s)</string>\n    <string name=\"clear_temp_files_info\">Temporary files can be used to resume cancelled downloads. Are you sure to delete all of these files?\\n\\nYou can access these files in %1$s</string>\n    <string name=\"multiselect_mode\">Multiselect mode</string>\n    <string name=\"private_mode\">Incognito</string>\n    <string name=\"private_mode_desc\">Disable download history</string>\n    <string name=\"dynamic_color\">Dynamic color</string>\n    <string name=\"dynamic_color_desc\">Apply colors from wallpapers to the app theme</string>\n    <string name=\"download_with_cellular\">Download using cellular</string>\n    <string name=\"download_with_cellular_desc\">Allow downloading media when connected to metered networks</string>\n    <string name=\"download_disabled_with_cellular\">Downloading with cellular network is disabled according to your settings</string>\n    <string name=\"file_unavailable\">This file is no longer available</string>\n    <string name=\"network\">Network</string>\n    <string name=\"rate_limit\">Rate limit</string>\n    <string name=\"rate_limit_desc\">Limit the maximum download speed</string>\n    <string name=\"max_rate\">Maximum rate</string>\n    <string name=\"high_contrast\">High contrast dark theme</string>\n    <string name=\"invalid_input\">Invalid input</string>\n    <string name=\"lowest_quality\">Lowest quality</string>\n    <string name=\"download_queue\">Download queue</string>\n    <string name=\"unavailable\">Unavailable</string>\n    <string name=\"format_settings_desc\">File format, video quality, subtitles</string>\n    <string name=\"general_settings_desc\">Yt-dlp version, notification, playlist</string>\n    <string name=\"network_settings_desc\">Rate limit, downloader, cookies</string>\n    <string name=\"disable_preview\">Disable preview</string>\n    <string name=\"disable_preview_desc\">No display of thumbnails during download</string>\n    <string name=\"privacy\">Privacy</string>\n    <string name=\"use_custom_command\">Use custom command</string>\n    <string name=\"private_directory\">Private directory</string>\n    <string name=\"private_directory_desc\">Store downloads in a hidden directory</string>\n    <string name=\"crop_artwork\">Crop artwork</string>\n    <string name=\"crop_artwork_desc\">Crop embedded image into square</string>\n    <string name=\"download_selection_desc\">Select videos to download from the playlist \\\"%1$s\\\"</string>\n    <string name=\"select_all\">Select all</string>\n    <string name=\"selected_item_count\">%1$d selected</string>\n    <string name=\"video_only\">Video (no audio)</string>\n    <string name=\"suggested\">Suggested</string>\n    <string name=\"format_selection\">Format selection</string>\n    <string name=\"format_selection_desc\">Select the format to download before starting the download</string>\n    <string name=\"generate_new_cookies\">Generate new cookies</string>\n    <string name=\"use_cookies\">Use Cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Remove this entry for \\\"%1$s\\\"? Please note that the cookies stored for this site will not be cleared.</string>\n    <string name=\"custom_command_enabled_hint\">Some options are unavailable when using custom command</string>\n    <string name=\"how_does_it_work\">How does it work?</string>\n    <string name=\"cookies_usage_msg\">Downloading from some sites requires account authentication information. Click \\\"Generate new cookies\\\", enter the URL of the website and then log in with your account in the browser page, the app will generate it for you.</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp is a powerful command-line tool for downloading videos. Seal makes it easier to use yt-dlp by providing an intuitive GUI, presets for common commands, and other additional features.\\n\\nFor advanced usage of yt-dlp, Seal allows you to create, save and execute custom command templates directly, just like in a terminal.\\n\\nWhen using custom commands, most of the GUI options and features would be disabled.</string>\n    <string name=\"telegram_channel\">Telegram channel</string>\n    <string name=\"matrix_space\">Matrix space</string>\n    <string name=\"sdcard_directory\">SD card folder</string>\n    <string name=\"auto_subtitle\">Automatic captions</string>\n    <string name=\"auto_subtitle_desc\">Download auto-generated captions</string>\n    <string name=\"title_activity_share\">Quick download</string>\n    <string name=\"abs_hint\">Most video streaming platforms deliver audio and video separately, you can select and merge an audio-only format with a video-only format to a single video.</string>\n    <string name=\"video_title_sample_text\">Video title sample text</string>\n    <string name=\"video_creator_sample_text\">Video creator sample text</string>\n    <string name=\"subtitle\">Subtitle</string>\n    <string name=\"download_subtitles\">Download subtitles</string>\n    <string name=\"subtitle_language\">Subtitle languages</string>\n    <string name=\"subtitle_desc\">Languages, embed subtitles, auto captions</string>\n    <string name=\"copy_log\">Copy log</string>\n    <string name=\"clear\">Clear</string>\n    <string name=\"edit_shortcuts\">Edit shortcuts</string>\n    <string name=\"add\">Add</string>\n    <string name=\"shortcuts\">Shortcuts</string>\n    <string name=\"edit_shortcuts_desc\">Edit the custom shortcuts that can be used to compose command templates.</string>\n    <string name=\"running_tasks\">Running tasks</string>\n    <string name=\"show_logs\">Show log</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"subtitle_sponsorblock\">Subtitles may be mistimed when removing SponsorBlock segments.</string>\n    <string name=\"embed_subtitles_mkv_msg\">To embed soft subtitles, videos will be remuxed into mkv container. You can use VLC Media Player or other compatible apps to watch videos with soft subtitles.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"share\">Share</string>\n    <string name=\"stable_channel\">Stable</string>\n    <string name=\"pre_release_channel\">Preview</string>\n    <string name=\"update_channel_desc\">Install pre-release builds to preview new features and changes.\\n\\nThere will be some instability in these versions, so please don\\'t hesitate to give us feedback if you experience any problems to help us improve the app for the future.</string>\n    <string name=\"update_channel\">Update channel</string>\n    <string name=\"auto_update\">Auto update</string>\n    <string name=\"enable_auto_update\">Enable auto update</string>\n    <string name=\"discard\">Discard</string>\n    <string name=\"apply\">Apply</string>\n    <string name=\"clip_video\">Clip video</string>\n    <string name=\"clip_start\">Start</string>\n    <string name=\"clip_end\">End</string>\n    <string name=\"audio_format_preference\">Preferred audio format</string>\n    <string name=\"unlimited\">Unlimited</string>\n    <string name=\"lowest_bitrate\">Lowest bitrate</string>\n    <string name=\"audio_quality\">Audio quality</string>\n    <string name=\"audio_quality_desc\">Limit audio bitrate when multiple qualities are present</string>\n    <string name=\"format_sorting\">Format sorting</string>\n    <string name=\"format_sorting_desc\">Sorting formats with the -S option of yt-dlp</string>\n    <string name=\"import_from_preferences\">Import</string>\n    <string name=\"title\">Title</string>\n    <string name=\"rename\">Rename</string>\n    <string name=\"second\">second</string>\n    <string name=\"minute\">minute</string>\n    <string name=\"clear_all_cookies\">Clear all cookies</string>\n    <string name=\"clear_all_cookies_desc\">Delete all the cookies stored in the app for good?</string>\n    <string name=\"temporary_directory_desc\">Store temporary files in the internal directory</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">Support this app by sponsoring on GitHub</string>\n    <string name=\"sponsor_msg\">Seal will be always free and open source for everyone. If you like it, please consider sponsoring me on GitHub!</string>\n    <string name=\"feedback\">Feedback</string>\n    <string name=\"sponsors\">Sponsors</string>\n    <string name=\"audio_format\">Audio format</string>\n    <string name=\"no_downloaded_media\">No downloaded media</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Enable experimental feature?</string>\n    <string name=\"clip_video_dialog_msg\">Downloads using this feature will be delegated to FFmpeg to download selected sections of the video, this feature is still experimental and the cutting will not be completely accurate, not all formats support this feature and you may experience slower download speeds.</string>\n    <string name=\"clip_video_desc\">Make video clips in the format selection page</string>\n    <string name=\"embed_thumbnail\" translatable=\"false\">Embed thumbnail</string>\n    <string name=\"embed_thumbnail_desc\" translatable=\"false\">Embed thumbnails into videos</string>\n    <string name=\"auto_update_disabled_msg\">Auto-update is not available for %1$s builds. If you don\\'t have %1$s installed on your device, or would like to preview upcoming new features in Seal, please consider %2$s.</string>\n    <string name=\"switch_to_github_builds\">switching to GitHub builds</string>\n    <string name=\"okay\">Okay</string>\n    <string name=\"got_it\">Got it</string>\n    <string name=\"feature_unavailable\">Feature not available</string>\n    <string name=\"no_custom_command_tasks\">No custom command tasks</string>\n    <string name=\"msg_from_developer\">Message from developer</string>\n    <string name=\"sponsor_msg2\">Thank you very much!</string>\n    <string name=\"download_video_desc\">Download videos from the URL</string>\n    <string name=\"convert_subtitle\">Convert subtitles</string>\n    <string name=\"convert_subtitle_desc\">Convert the subtitles to another format</string>\n    <string name=\"split_video\">Split video</string>\n    <string name=\"split_video_msg\">Video will be split into %1$d chapters</string>\n    <string name=\"unknown_error_title\">Oops! Something went wrong</string>\n    <string name=\"copy_and_exit\">Copy and exit</string>\n    <string name=\"expand\">Expand</string>\n    <string name=\"new_task\">New download task</string>\n    <string name=\"start\">Start</string>\n    <string name=\"edit_template\">Edit \\\"%1$s\\\"</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"proxy_desc\">Use proxy for internet connections</string>\n    <string name=\"legacy\">Legacy</string>\n    <string name=\"quality\">Quality</string>\n    <string name=\"enable_notifications\">Enable notifications?</string>\n    <string name=\"enable_notifications_desc\">The app needs your permission to post notifications about download status and progress.</string>\n    <string name=\"disable\">Disable</string>\n    <string name=\"set_directory_desc\">Tap to set up directory</string>\n    <string name=\"custom_command_directory\">Custom command directory</string>\n    <string name=\"disabled\">Disabled</string>\n    <string name=\"folder_picker\">Folder picker</string>\n    <string name=\"custom_command_directory_desc\">Specify the output directory when using custom commands</string>\n    <string name=\"prefer_compatibility_desc\">Prefer MP4(H.264) formats for sharing to other apps</string>\n    <string name=\"prefer_quality_desc\">Prefer AV1, VP9 or H.265 formats for watching in compatible apps</string>\n    <string name=\"download_type\">Download type</string>\n    <string name=\"custom\">Custom</string>\n    <string name=\"auto\">Auto</string>\n    <string name=\"commands\">Commands</string>\n    <string name=\"format_preference\">Format preference</string>\n    <string name=\"learn_more\">Learn more</string>\n    <string name=\"unknown\">Unknown</string>\n    <string name=\"refresh_cookies_desc\">Tap to open webpage for generating new cookies:</string>\n    <string name=\"remove_multiple_templates_msg\">Remove %1$s from command templates for good?</string>\n    <string name=\"ua_header\">User-Agent header</string>\n    <string name=\"export_to_file\">Export to file</string>\n    <string name=\"output_template\">Output template</string>\n    <string name=\"presets\">Presets</string>\n    <string name=\"output_template_desc\">Specify the template for output file names</string>\n    <string name=\"download_archive\">Download archive</string>\n    <string name=\"download_archive_desc\">Record downloaded video IDs in an archive to avoid duplicate downloads</string>\n    <string name=\"clear_download_archive\">Clear download archive?</string>\n    <string name=\"clear_download_archive_desc\">Remove %1$s in the archive file for good?</string>\n    <string name=\"embed_metadata\">Embed metadata</string>\n    <string name=\"embed_metadata_desc\">Embed metadata and video thumbnail into the audio file</string>\n    <string name=\"required\">Required</string>\n    <string name=\"show_all_items\">Show all %1$d items</string>\n    <string name=\"edit_file\">Edit file</string>\n    <string name=\"save\">Save</string>\n    <string name=\"use_format_sorting\">Use format sorting</string>\n    <string name=\"restrict_filenames\">Restrict filenames</string>\n    <string name=\"restrict_filenames_desc\">Limit filenames to specific characters to ensure compatibility</string>\n    <string name=\"website\">Website</string>\n    <string name=\"playlist_title\">Playlist title</string>\n    <string name=\"subdirectory_hint\">Your downloads will be saved as:</string>\n    <string name=\"system_settings\">System settings</string>\n    <string name=\"force_ipv4\">Force IPv4</string>\n    <string name=\"force_ipv4_desc\">Make all connections via IPv4</string>\n    <string name=\"keep_subtitle_files\">Keep subtitle files</string>\n    <string name=\"allow_once\">Allow once</string>\n    <string name=\"allow_always\">Allow always</string>\n    <string name=\"dont_allow\">Don\\'t allow</string>\n    <string name=\"download_with_cellular_request\">Allow downloading with cellular?</string>\n    <string name=\"merge_audiostream\">Merge multiple audio stream</string>\n    <string name=\"merge_audiostream_desc\">Allow multiple audio streams to be merged into a single file</string>\n    <string name=\"search_in_downloads\">Search in downloads</string>\n    <string name=\"search\">Search</string>\n    <string name=\"auto_translated_subtitles\">Auto-translated subtitles</string>\n    <string name=\"auto_translated_subtitles_msg\">Auto-translated subtitles for all languages will be available in downloads. These subtitles may be inaccurate and difficult to understand.</string>\n    <string name=\"subtitle_language_desc\">Language of the subtitles to download in Auto format selection, separated by commas.</string>\n    <string name=\"remember_for_next_download\">Remember for next download</string>\n    <string name=\"look_and_feel\"><![CDATA[Look & feel]]></string>\n    <string name=\"interface_and_interaction\"><![CDATA[Interface & interaction]]></string>\n\n\n    <string name=\"use_previous_selection\">Use previous selection</string>\n    <string name=\"none\">None</string>\n    <string name=\"reset\">Reset</string>\n    <string name=\"search_in_subtitles\">Search in subtitles</string>\n    <string name=\"no_thanks\">No thanks</string>\n    <string name=\"update_language_msg\">The following languages will be added to your preference for future downloads:</string>\n    <string name=\"update_subtitle_languages\">Update subtitle languages?</string>\n\n    <string name=\"export_backup\">Export</string>\n    <string name=\"import_backup\">Import</string>\n    <string name=\"full_backup\">Full backup</string>\n    <string name=\"backup_type\">Backup type</string>\n    <string name=\"export_to\">Export to</string>\n    <string name=\"file\">File</string>\n    <string name=\"clipboard\">Clipboard</string>\n    <string name=\"import_from\">Import from</string>\n    <string name=\"export_download_history\">Export download history?</string>\n    <string name=\"import_download_history\">Import download history?</string>\n    <string name=\"import_download_history_msg\">Downloaded files won\\'t be imported. You\\'ll need to download them back manually</string>\n    <string name=\"export_download_history_msg\">Exporting %1$s from download history. Downloaded files and preferences won\\'t be backed up.</string>\n    <string name=\"download_history\">Download history</string>\n    <string name=\"download_history_imported\">Imported %1$s to download history</string>\n    <string name=\"redownload\">Redownload</string>\n    <string name=\"download_archive_error\">The video has been downloaded. If this is not the expected behavior, please check your download archive.</string>\n    <string name=\"remux_container_mkv\">Remux video container</string>\n    <string name=\"remux_container_mkv_desc\">Remux videos into MKV container for better compatibility</string>\n    <string name=\"cookies_in_database\">%1$d cookies from %2$d websites in total</string>\n    <string name=\"every_day\">Every day</string>\n    <string name=\"every_week\">Every week</string>\n    <string name=\"every_month\">Every month</string>\n    <string name=\"all_languages\">All languages</string>\n    <string name=\"playlist\">Playlist</string>\n    <string name=\"proceed\">Continue</string>\n    <string name=\"preset\">Preset</string>\n    <string name=\"prefer_placeholder\">Prefer %1$s</string>\n    <string name=\"custom_format_selection_desc\">Choose from formats, subtitles, and customize further</string>\n    <string name=\"preset_format_selection_desc\">Download automatically using your format preferences</string>\n    <string name=\"edit_preset\">Edit preset</string>\n    <string name=\"best_quality_desc\">Download the best available format</string>\n    <string name=\"task_added\">Task added to queue</string>\n    <string name=\"you_ll_find_your_downloads_here\">You\\'ll find your downloads here</string>\n    <string name=\"download_hint\">Tap on the download button or share a video link to this app to start a download</string>\n    <string name=\"status_downloaded\">Downloaded</string>\n    <string name=\"all\">All</string>\n    <string name=\"select_multiple_link\">Select from %1$d links</string>\n    <string name=\"show_navigation_drawer\">Show navigation drawer</string>\n    <string name=\"resume\">Resume</string>\n    <string name=\"delete\">Delete</string>\n    <string name=\"media_info\">Media info</string>\n    <string name=\"trouble_shooting\">Troubleshooting</string>\n    <string name=\"issue_tracker\">Issue tracker</string>\n    <string name=\"trouble_shooting_desc\">Fix common errors and check for known issues</string>\n    <string name=\"issue_tracker_hint\">Encountered an error? Before reporting a new issue, please search our issue tracker. Many common problems have already been addressed and documented there.</string>\n    <string name=\"saved_urls\">Saved links</string>\n    <string name=\"add_new_url\">Add new link</string>\n    <string name=\"add_to\">Add to %1$s</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d item</item>\n        <item quantity=\"other\">%d items</item>\n    </plurals>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d video</item>\n        <item quantity=\"other\">%d videos</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d audio</item>\n        <item quantity=\"other\">%d audios</item>\n    </plurals>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/themes.xml",
    "content": "<resources>\n\n    <style name=\"Theme.Seal\" parent=\"Theme.Material3.DayNight.NoActionBar\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <style name=\"Theme.Seal.Dialog\" parent=\"Theme.Material3.DayNight.NoActionBar\">\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <item name=\"android:colorBackgroundCacheHint\">@null</item>\n        <item name=\"android:windowContentOverlay\">@null</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-ar/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">حفظ كملف صوت</string>\n    <string name=\"create_thumbnail\">تنزيل الصورة المصغرة</string>\n    <string name=\"download_settings_desc\">عام، التنسيق، أمر مخصص</string>\n    <string name=\"url_empty\">لا يمكن أن يكون الحقل فارغاً</string>\n    <string name=\"extract_audio_summary\">قم بتنزيل الصوت وحفظه بدلاً من الفيديو</string>\n    <string name=\"create_thumbnail_summary\">تنزيل الصورة المصغرة للفيديو كملف</string>\n    <string name=\"fetching_info\">جارٍ جلب معلومات الفيديو…</string>\n    <string name=\"download_success_msg\">اكتمل التحميل</string>\n    <string name=\"general_settings\">عام</string>\n    <string name=\"language\">لغة العرض</string>\n    <string name=\"download_start_msg\">تحميل \\\"%1$s\\\"</string>\n    <string name=\"paste_msg\">الصق عنوان URL</string>\n    <string name=\"paste_fail_msg\">تعذر مطابقة الرابط الموجود في الحافظة</string>\n    <string name=\"ytdlp_version\">إصدار Yt-dlp</string>\n    <string name=\"delete_info\">إزالة؟</string>\n    <string name=\"delete_info_msg\">هل تريد إزالة \\\"%1$s\\\" من سجل التنزيلات بشكل دائم؟</string>\n    <string name=\"confirm\">نعم</string>\n    <string name=\"dismiss\">إلغاء</string>\n    <string name=\"downloads_history\">التحميلات</string>\n    <string name=\"open_url\">افتح الرابط</string>\n    <string name=\"remove\">إزالة</string>\n    <string name=\"delete_file\">حذف المِلَفّ</string>\n    <string name=\"about\">حول</string>\n    <string name=\"about_page\">الإصدار، التعليقات، التحديث التلقائي</string>\n    <string name=\"version\">الإصدار</string>\n    <string name=\"release_desc\">ألق نظرة على الإصدارات الجديدة وسجل التغييرات</string>\n    <string name=\"release\">أحدث إصدار</string>\n    <string name=\"video\">فيديو</string>\n    <string name=\"checked\">محدد</string>\n    <string name=\"custom_command_template\">قالب الأوامر</string>\n    <string name=\"edit\">تحرير</string>\n    <string name=\"print_details\">تقرير مفصل</string>\n    <string name=\"print_details_desc\">أظهر تقارير مفصلة عند التنزيل</string>\n    <string name=\"display\">شاشة العرض</string>\n    <string name=\"display_settings\">المظهر الداكن، اللون الديناميكي، اللغات</string>\n    <string name=\"dark_theme\">مظهر داكن</string>\n    <string name=\"follow_system\">نظام</string>\n    <string name=\"on\">تشغيل</string>\n    <string name=\"off\">إيقاف</string>\n    <string name=\"settings_before_download\">ضبط الإعدادات قبل التنزيل</string>\n    <string name=\"settings_before_download_text\">خصص هذا التحميل</string>\n    <string name=\"thumbnail\">صورة مصغرة للفيديو</string>\n    <string name=\"paste\">لصق</string>\n    <string name=\"yt_dlp_docs\">مراجع استخدام yt-dlp</string>\n    <string name=\"convert_to\">التحويل إلى %1$s</string>\n    <string name=\"format\">الصيغ</string>\n    <string name=\"convert_audio_format\">تحويل صيغة الصوت</string>\n    <string name=\"video_quality_desc\">قم بالحد من جودة الفيديو عند تواجد العديد</string>\n    <string name=\"video_format_preference\">صيغة الفيديو المفضلة</string>\n    <string name=\"preferred_format_desc\">التنسيق المُفضل في حال توفر عدة خيارات</string>\n    <string name=\"video_format\">صيغة الفيديو</string>\n    <string name=\"convert_audio\">تحويل</string>\n    <string name=\"start_download\">تحميل</string>\n    <string name=\"user_guide\">دليل المستخدم</string>\n    <string name=\"open_settings\">افتح الإعدادات</string>\n    <string name=\"paste_desc\">انقر فوق «لصق» للحصول على رابط الفيديو من الحافظة الخاصة بك.</string>\n    <string name=\"download_playlist\">تنزيل قائمة التشغيل</string>\n    <string name=\"download_playlist_desc\">قم بتنزيل مقاطع فيديو متعددة من قائمة التشغيل</string>\n    <string name=\"channel_name\">تنزيل</string>\n    <string name=\"download_finish_notification\">تم التحميل، انقر للعرض.</string>\n    <string name=\"execute_command_notification\">تشغيل الأوامر المخصصة …</string>\n    <string name=\"concurrent_download_desc\">قم بتنزيل المزيد من أجزاء مقاطع الفيديو M3U8 / MPD بالتوازي</string>\n    <string name=\"concurrent_download_num\">%d من الممكن استخدام سلسلة لتنزيل فيديو DASH / HLS الأصلي بشكل متزامن.</string>\n    <string name=\"options\">خيارات</string>\n    <string name=\"show_more_actions\">عرض مزيدٍ من الإجراءات</string>\n    <string name=\"download_notification\">إشعار التنزيل</string>\n    <string name=\"download_notification_desc\">إشعار بالملفات التي تم تنزيلها ومستوى التقدم</string>\n    <string name=\"download_range_selection\">اختيار قائمة التشغيل</string>\n    <string name=\"download_range_desc\">حدد نطاق مقاطع الفيديو المراد تنزيلها من قائمة التشغيل «%3$s» (من %1$d إلى %2$d).</string>\n    <string name=\"invalid_index_range\">نطاق الفهرس غير صالح</string>\n    <string name=\"audio_directory\">مجلد الصوت</string>\n    <string name=\"download_directory\">مدير التحميل</string>\n    <string name=\"subdirectory\">حفظ في مجلد فرعي</string>\n    <string name=\"permission_issue\">مشكلة أذونات التخزين</string>\n    <string name=\"permission_issue_desc\">المجلدات خارج «التنزيل» و«المستندات» غير مدعومة</string>\n    <string name=\"battery_configuration\">إدارة البطارية</string>\n    <string name=\"battery_configuration_desc\">تجاهل تحسين البطارية لجعل هذا التطبيق يحمل في الخلفية</string>\n    <string name=\"translate\">ترجم</string>\n    <string name=\"translate_desc\">ساعد في ترجمة هذا التطبيق على Weblate</string>\n    <string name=\"video_directory\">مجلد الفيديو</string>\n    <string name=\"settings\">الإعدادات</string>\n    <string name=\"download\">تنزيل</string>\n    <string name=\"yt_dlp_up_to_date\">أنت على أحدث إصدار من yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">تعذر تثبيت أحدث إصدار من yt-dlp. يرجى التحقق من اتصالك بالإنترنت.</string>\n    <string name=\"permission_denied\">تم رفض الإذن</string>\n    <string name=\"download_error_msg\">تعذر تحميل الملف</string>\n    <string name=\"fetch_info_error_msg\">فشل جلب معلومات الفيديو</string>\n    <string name=\"language_settings\">تعيين لغة العرض</string>\n    <string name=\"task_running\">هناك مهمة تنزيل جارية بالفعل</string>\n    <string name=\"ytdlp_update\">انقر هنا لتثبيت آخر إصدار من yt-dlp</string>\n    <string name=\"link_copied\">تم نسخ الرابط إلى الحافظة</string>\n    <string name=\"audio\">الصوت</string>\n    <string name=\"back\">رجوع</string>\n    <string name=\"readme_desc\">انظُر لمستودع GitHub وREADME</string>\n    <string name=\"custom_command_desc\">استعمِل yt-dlp بأوامرك المخصصة</string>\n    <string name=\"credits\">شكر وتقدير</string>\n    <string name=\"credits_desc\">شكر وتقدير والبرمجيات الحرة</string>\n    <string name=\"custom_command\">الأوامر المخصصة</string>\n    <string name=\"start_execute\">بدء تنفيذ الأمر</string>\n    <string name=\"advanced_settings\">إعدادات متقدمة</string>\n    <string name=\"close_never_show_again\">لا تظهر مرة أخرى</string>\n    <string name=\"not_convert\">غير محول</string>\n    <string name=\"additional_settings\">إعدادات إضافية</string>\n    <string name=\"convert_audio_format_desc\">إعادة ترميز ملفات الصوت يُخفِّضُ الجودة ويزيد الحجم.</string>\n    <string name=\"video_quality\">جودة الفيديو</string>\n    <string name=\"best_quality\">أفضل جودة</string>\n    <string name=\"not_specified\">غير محدد (افتراضي)</string>\n    <string name=\"download_desc\">ثم انقر فوق «تنزيل» بعد ضبط إعداداته.</string>\n    <string name=\"channel_description\">أظهر إشعارًا للملفات التي يتم تحميلها ومستوى التقدم</string>\n    <string name=\"battery_settings_desc\">يرجى ضبط استخدام البطارية لهذا التطبيق على «غير مقيد» في إعدادات النظام للتنزيل في الخلفية.</string>\n    <string name=\"close\">إغلاق</string>\n    <string name=\"defaults\">اِفتراضي</string>\n    <string name=\"download_history_desc\">التحقق من التنزيلات داخل التطبيق وإدارتها، بما في ذلك ملفات الفيديو والصوت.</string>\n    <string name=\"check_download_settings_desc\">ألق نظرة على إعدادات التنزيل وتأكد من أن لديك أحدث إصدار من yt-dlp قبل استخدامه.</string>\n    <string name=\"video_url\">رابط الفيديو</string>\n    <string name=\"concurrent_download\">تنزيل متعدد الأجزاء</string>\n    <string name=\"subdirectory_desc\">احفظ الملفات في مجلدات بأسماء الحقول المعنية</string>\n    <string name=\"unknown_error\">خطأ غير معروف</string>\n    <string name=\"share_fail_msg\">تعذر مطابقة عنوان URL من المحتوى المشترك</string>\n    <string name=\"share_success_msg\">جارٍ قراءة رابط الفيديو من المحتوى المشترك …</string>\n    <string name=\"from\">بداية</string>\n    <string name=\"to\">نهاية</string>\n    <string name=\"playlist_indicator_text\">جارٍ تنزيل قائمة التشغيل (%1$d/%2$d)…</string>\n    <string name=\"download_directory_desc\">حدد مكان تخزين ملفات الفيديو والصوت</string>\n    <string name=\"cancel\">إلغاء</string>\n    <string name=\"service_title\">Seal يقوم بالتنزيل…</string>\n    <string name=\"settings_before_download_desc\">اضبط التفضيلات قبل التنزيل</string>\n    <string name=\"error_copied\">نُسِخَ تقرير الخطأ إلى الحافظة</string>\n    <string name=\"edit_template_desc\">سيضيف التطبيق مسار الإخراج وعنوان الرابط.</string>\n    <string name=\"fetching_playlist_info\">جارٍ جلبُ معلومات قائمة التشغيل …</string>\n    <string name=\"prefix\">قالب المسار</string>\n    <string name=\"embed_subtitles\">دمج الترجمة</string>\n    <string name=\"embed_subtitles_desc\">تضمين الترجمة المقدمة في الفيديوهات إذا كانت متوفرة</string>\n    <string name=\"new_template\">قالب جديد</string>\n    <string name=\"template_label\">اسم القالب</string>\n    <string name=\"remove_template\">إزالة؟</string>\n    <string name=\"remove_template_desc\">هل تريد إزالة «%1$s» من قوالب الأوامر للأبد؟</string>\n    <string name=\"template_selection\">اختيار القالب</string>\n    <string name=\"custom_command_template_desc\">تحرير وإدارة قوالب الأوامر</string>\n    <string name=\"downloading_indicator_text\">التنزيل قيد التقدم…</string>\n    <string name=\"task_canceled\">تم إلغاء مهمة التنزيل</string>\n    <string name=\"github_issue\">تذكرة Github</string>\n    <string name=\"github_issue_desc\">أرسل تذكرة للإبلاغ عن خطأ أو طلب ميزة</string>\n    <string name=\"info_copied\">نُسِخَتِ المعلومات إلى الحافظة</string>\n    <string name=\"status_enqueued\">في قائمة الانتظار</string>\n    <string name=\"status_completed\">انتهى</string>\n    <string name=\"status_downloading\">جارٍ التحميل</string>\n    <string name=\"status_canceled\">تم الإلغاء</string>\n    <string name=\"status_fetching_video_info\">جارٍ إحضار المعلومات</string>\n    <string name=\"restart\">إعادة بدء</string>\n    <string name=\"open_file\">افتح الملف</string>\n    <string name=\"status_error\">خطأ</string>\n    <string name=\"copy_link\">نسخ الرابط</string>\n    <string name=\"copy_error_report\">نسخ التقرير</string>\n    <string name=\"video_file_size\">حجم ملف الفيديو</string>\n    <string name=\"video_resolution\">دقة الفيديو</string>\n    <string name=\"export_to_clipboard\">تصدير إلى الحافظة</string>\n    <string name=\"template_exported\">تم تصدير %1$d القالب(القوالب)</string>\n    <string name=\"template_imported\">تم استيراد %1$d قالب(قوالب)</string>\n    <string name=\"download_task_count\">%1$d مهام التنزيل</string>\n    <string name=\"recently_added\">أضيف مؤخراً</string>\n    <string name=\"import_from_clipboard\">الاستيراد من الحافظة</string>\n    <string name=\"delete_multiple_items_msg\">هل تريد إزالة%1$d عنصراً (عناصر) من سجل التنزيل للأبد؟</string>\n    <string name=\"multiselect_item_count\">%1$d ملف(ات) فيديو، %2$d ملف(ات) صوت</string>\n    <string name=\"sponsorblock_desc\">إزالة أو وضع علامات على الأقسام في مقاطع الفيديو باستخدام SponsorBlock API</string>\n    <string name=\"sponsorblock_categories_desc\">حدد فئات الـSponsorBlock المراد إزالتها او تعليمها في ملف الفيديو</string>\n    <string name=\"sponsorblock_categories\">تصنيفات الـSponsorBlock</string>\n    <string name=\"app_up_to_date\">انت على أحدث إصدار</string>\n    <string name=\"app_update_failed\">فشل التحديث إلى أحدث إصدار</string>\n    <string name=\"update\">تحديث</string>\n    <string name=\"check_for_updates\">البحث عن تحديثات</string>\n    <string name=\"check_for_updates_desc\">تحقق تلقائياً من أحدث إصدار متوفر على GitHub</string>\n    <string name=\"aria2_desc\">استخدم aria2c كمدير تنزيل خارجي</string>\n    <string name=\"cookies_desc\">استخدم ملفات تعريف الارتباط بتنسيق Netscape للتنزيلات</string>\n    <string name=\"clear_temp_files\">امسح الملفات المؤقتة</string>\n    <string name=\"clear_temp_files_count\">تم حذف %1$d ملف(ات) مؤقت(ة)</string>\n    <string name=\"clear_temp_files_info\">يمكن استخدام الملفات المؤقتة لاستئناف التنزيلات الملغاة. هل أنت متأكد من حذف كل هذه الملفات؟\n\\nيمكنك الوصول إلى تلك الملفات في %1$s</string>\n    <string name=\"clear_temp_files_desc\">حذف جميع الملفات المؤقتة من المجلد المؤقت</string>\n    <string name=\"multiselect_mode\">وضع التحديد المتعدد</string>\n    <string name=\"private_mode\">وضع الخصوصية</string>\n    <string name=\"private_mode_desc\">إيقاف سجل التنزيلات</string>\n    <string name=\"dynamic_color\">لون ديناميكي</string>\n    <string name=\"dynamic_color_desc\">قم بتطبيق الألوان من الخلفيات على سمة التطبيق</string>\n    <string name=\"file_unavailable\">هذا الملف لم يعد متوفرا</string>\n    <string name=\"download_with_cellular_desc\">السماح بتنزيل الوسائط عند الاتصال بشبكات محدودة</string>\n    <string name=\"download_with_cellular\">التنزيل باستخدام الشبكة الخلوية</string>\n    <string name=\"download_disabled_with_cellular\">التنزيل باستخدام الشبكة الخلوية معطل وفقًا لإعداداتك</string>\n    <string name=\"network\">شبكة</string>\n    <string name=\"rate_limit\">حدود المعدل</string>\n    <string name=\"max_rate\">أقصى معدل</string>\n    <string name=\"rate_limit_desc\">تحديد الحد الأقصى لسرعة التنزيل</string>\n    <string name=\"high_contrast\">مظهر داكن عالي التباين</string>\n    <string name=\"invalid_input\">إدخال غير صالح</string>\n    <string name=\"lowest_quality\">أدنى جودة</string>\n    <string name=\"download_selection_desc\">حدد مقاطع الفيديو لتنزيلها من قائمة التشغيل \\\"%1$s\\\"</string>\n    <string name=\"select_all\">اختيار الكل</string>\n    <string name=\"selected_item_count\">%1$d محدد</string>\n    <string name=\"unavailable\">غير متوفر</string>\n    <string name=\"format_settings_desc\">صيغة الملف، دقة الفيديو، التَرْجمات</string>\n    <string name=\"general_settings_desc\">إصدار Yt-dlp، الإشعار، قائمة التشغيل</string>\n    <string name=\"network_settings_desc\">حدود المعدل، مدير التنزيلات، ملفات تعريف الارتباط</string>\n    <string name=\"disable_preview\">تعطيل المعاينة</string>\n    <string name=\"disable_preview_desc\">عدم عرض الصور المصغرة أثناء التنزيل</string>\n    <string name=\"privacy\">الخصوصية</string>\n    <string name=\"use_custom_command\">استخدام أمر مخصص</string>\n    <string name=\"private_directory\">مجلد خاص</string>\n    <string name=\"private_directory_desc\">احفظ التحميلات في مجلد خفي</string>\n    <string name=\"crop_artwork\">قص الغلاف</string>\n    <string name=\"crop_artwork_desc\">قص الصورة المدمجة على شكل مربع</string>\n    <string name=\"suggested\">موصى به</string>\n    <string name=\"format_selection\">اختيار التنسيق</string>\n    <string name=\"format_selection_desc\">حدد التنسيق المراد تنزيله قبل بدء العملية</string>\n    <string name=\"video_only\">فيديو (بدون صوت)</string>\n    <string name=\"generate_new_cookies\">إنشاء ملفات تعريف ارتباط جديدة</string>\n    <string name=\"use_cookies\">استخدام ملفات تعريف الارتباط</string>\n    <string name=\"remove_cookie_profile_desc\">هل تريد حذف ملفات تعريف الارتباط الخاصة بـ \\\"%1$s\\\" ؟ يرجي العلم بأن ملفات تعريف الارتباط الخاصة بهذا الموقع لن تمسح.</string>\n    <string name=\"custom_command_enabled_hint\">قد لا تتوفر بعض الخيارات عند استخدام الأوامر المخصصة</string>\n    <string name=\"how_does_it_work\">كيف يعمل؟</string>\n    <string name=\"telegram_channel\">قناة Telegram</string>\n    <string name=\"cookies_usage_msg\">يتطلب التنزيل من بعض المواقع معلومات مصادقة الحساب. انقر فوق \\\"إنشاء ملفات تعريف ارتباط جديدة\\\" ، وأدخل عنوان URL لموقع الويب ، ثم قم بتسجيل الدخول باستخدام حسابك في صفحة المتصفح ، وسيقوم التطبيق بإنشائه لك.</string>\n    <string name=\"matrix_space\">مساحة Matrix</string>\n    <string name=\"cookies\">كوكيز</string>\n    <string name=\"abs_hint\">تقدم معظم منصات الفيديو، الصوت والفيديو بشكل منفصل ، يمكنك تحديد ودمج صيغة صوت فقط بصيغة فيديو في فيديو واحد.</string>\n    <string name=\"auto_subtitle_desc\">سيقوم هذا الخيار بتحميل الترجمة التلقائية ان توفرت من المصدر</string>\n    <string name=\"download_subtitles\">تنزيل الترجمات</string>\n    <string name=\"edit_shortcuts\">تعديل الاختصارات</string>\n    <string name=\"sdcard_directory\">مجلد ذاكرة SD</string>\n    <string name=\"auto_subtitle\">الترجمة التلقائية</string>\n    <string name=\"title_activity_share\">تنزيل سريع</string>\n    <string name=\"video_title_sample_text\">نص نموذجي لعنوان الفيديو</string>\n    <string name=\"subtitle_language\">لغات الترجمة</string>\n    <string name=\"subtitle_desc\">اللغات، دمج العناوين الفرعية، والترجمة التلقائية</string>\n    <string name=\"copy_log\">نسخ السجل</string>\n    <string name=\"clear\">إزالة</string>\n    <string name=\"add\">إضافة</string>\n    <string name=\"shortcuts\">اختصارات</string>\n    <string name=\"running_tasks\">المهام الجارية</string>\n    <string name=\"show_logs\">إظهار السِجل</string>\n    <string name=\"logs\">السِجل</string>\n    <string name=\"video_creator_sample_text\">نص نموذجي لمنشئ الفيديو</string>\n    <string name=\"subtitle\">الترجمة</string>\n    <string name=\"edit_shortcuts_desc\">قم بتعديل الاختصارات المخصصة التي يمكن استخدامها لإنشاء قوالب الأوامر.</string>\n    <string name=\"subtitle_sponsorblock\">قد يتم توقيت الترجمة بشكل غير صحيح عند إزالة مقاطع SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">لتضمين الترجمات، سيتم إعادة صاغية مقاطع الفيديو بصيغة mkv. يمكنك استخدام مشغل VLC أو تطبيقات متوافقة أخرى لمشاهدة مقاطع الفيديو مع الترجمة المضمنة.</string>\n    <string name=\"filesize_mb\">%.2f م.ب</string>\n    <string name=\"filesize_gb\">%.2f ج.ب</string>\n    <string name=\"share\">شارك</string>\n    <string name=\"stable_channel\">المستقرة</string>\n    <string name=\"pre_release_channel\">المعاينة</string>\n    <string name=\"update_channel_desc\">قم بتثبيت الإصدارات التجريبية لمعاينة الميزات والتغييرات الجديدة.\n\\n\n\\nقد تواجه بعض عدم الاستقرار في هذه النسخ، لذا يرجى عدم التردد في تقديم ملاحظاتك إذا واجهت أي مشاكل لمساعدتنا على تحسين التطبيق للمستقبل.</string>\n    <string name=\"update_channel\">قناة التحديث</string>\n    <string name=\"auto_update\">التحديث التلقائي</string>\n    <string name=\"enable_auto_update\">تفعيل التحديث التلقائي</string>\n    <string name=\"discard\">تجاهل</string>\n    <string name=\"apply\">استخدام</string>\n    <string name=\"clip_video\">قص الفيديو</string>\n    <string name=\"clip_start\">البداية</string>\n    <string name=\"clip_end\">النهاية</string>\n    <string name=\"second\">ثانية</string>\n    <string name=\"clear_all_cookies\">حذف جميع ملفات تعريف الارتباط</string>\n    <string name=\"audio_format_preference\">صيغة الصوت المفضلة</string>\n    <string name=\"unlimited\">غير محدود</string>\n    <string name=\"audio_quality\">جودة الصوت</string>\n    <string name=\"lowest_bitrate\">أدنى معدل بت</string>\n    <string name=\"audio_quality_desc\">حدد معدل بت الصوت في حال تواجد العديد من الدقات</string>\n    <string name=\"format_sorting\">فرز الصيغ</string>\n    <string name=\"format_sorting_desc\">فرز الصيغ باستخدام الخيار S- من yt-dlp</string>\n    <string name=\"minute\">دقيقة</string>\n    <string name=\"import_from_preferences\">استيراد</string>\n    <string name=\"title\">العنوان</string>\n    <string name=\"rename\">إعادة التسمية</string>\n    <string name=\"clear_all_cookies_desc\">هل تريد حذف جميع ملفات تعريف الارتباط المحفوظة في التطبيق؟</string>\n    <string name=\"temporary_directory_desc\">تخزين الملفات المؤقتة في الدليل الداخلي</string>\n    <string name=\"sponsor\">الراعي</string>\n    <string name=\"sponsor_desc\">ادعم هذا التطبيق من خلال الرعاية على GitHub</string>\n    <string name=\"sponsor_msg\">Seal سيبقى دائمًا مجانيًا ومفتوح المصدر للجميع. إذا أعجبك، يُرجى التفكير في دعمي كراعياً على GitHub!</string>\n    <string name=\"feedback\">التعليقات</string>\n    <string name=\"sponsors\">الرعاة</string>\n    <string name=\"audio_format\">صيغة الصوت</string>\n    <string name=\"no_downloaded_media\">لا توجد وسائط منزلة</string>\n    <string name=\"beta_features\">تجريبية</string>\n    <string name=\"enable_experimental_feature\">تفعيل الميزة التجريبية؟</string>\n    <string name=\"clip_video_dialog_msg\">سيتم تفويض التنزيلات باستخدام هذه الميزة إلى FFmpeg لتنزيل أقسام محددة من الفيديو، لا تزال هذه الميزة تجريبية ولن يكون القطع دقيقًا تمامًا، بالإضافة إلى ان هذه الميزة لا تدعم جميع التنسيقات وقد تواجه سرعات تنزيل أبطأ.</string>\n    <string name=\"clip_video_desc\">اصنع مقاطع فيديو في صفحة اختيار التنسيق</string>\n    <string name=\"auto_update_disabled_msg\">التحديث التلقائي غير متاح لنسخة%1$s. إذا لم يكن لديك %1$s مثبت على جهازك، أو ترغب في معاينة الميزات الجديدة القادمة في Seal، يرجى التفكير في%2$s.</string>\n    <string name=\"switch_to_github_builds\">التحويل إلى إصدارات GitHub</string>\n    <string name=\"okay\">حَسَنًا</string>\n    <string name=\"got_it\">فهمت</string>\n    <string name=\"feature_unavailable\">الميزة غير متوفرة</string>\n    <string name=\"no_custom_command_tasks\">لا توجد مهام أوامر مخصصة</string>\n    <string name=\"msg_from_developer\">رسالة من المطور</string>\n    <string name=\"sponsor_msg2\">شكرًا جزيلا!</string>\n    <string name=\"convert_subtitle\">تحويل الترجمة</string>\n    <string name=\"unknown_error_title\">عفواً! حدث خطأ ما</string>\n    <string name=\"copy_and_exit\">النسخ والخروج</string>\n    <string name=\"convert_subtitle_desc\">تحويل الترجمات إلى صيغة أخرى</string>\n    <string name=\"split_video\">تقسيم الفيديو</string>\n    <string name=\"split_video_msg\">سيتم تقسيم الفيديو إلى %1$d فصلاً</string>\n    <string name=\"download_video_desc\">تنزيل مقاطع الفيديو من الرابط</string>\n    <string name=\"expand\">توسيع</string>\n    <string name=\"new_task\">مهمة تحميل جديدة</string>\n    <string name=\"start\">بدأ</string>\n    <string name=\"edit_template\">تعديل \\\"%1$s\\\"</string>\n    <string name=\"ytdlp_update_action\">قم بتحديث yt-dlp</string>\n    <string name=\"proxy\">بروكسي</string>\n    <string name=\"disable\">تعطيل</string>\n    <string name=\"legacy\">قديم</string>\n    <string name=\"quality\">جودة</string>\n    <string name=\"enable_notifications\">هل ترغب في تفعيل الإشعارات؟</string>\n    <string name=\"proxy_desc\">استخدم بروكسي لاتصالات الإنترنت</string>\n    <string name=\"enable_notifications_desc\">التطبيق يحتاج إلى إذنك لنشر إشعارات حول حالة التنزيل والتقدم.</string>\n    <string name=\"refresh_cookies_desc\">اضغط لفتح صفحة الويب لتوليد ملفات تعريف الارتباط الجديدة:</string>\n    <string name=\"folder_picker\">محدد المجلدات</string>\n    <string name=\"disabled\">غير مفعل</string>\n    <string name=\"custom_command_directory_desc\">حدد مسار التحميل عند استخدام الأوامر المخصصة</string>\n    <string name=\"prefer_compatibility_desc\">تفضيل تنسيقات MP4 (H.264) للمشاركة مع تطبيقات أخرى</string>\n    <string name=\"prefer_quality_desc\">تفضيل تنسيقات AV1، VP9 أو H.265 للمشاهدة في تطبيقات متوافقة</string>\n    <string name=\"download_type\">نوع التحميل</string>\n    <string name=\"learn_more\">أقرأ المزيد</string>\n    <string name=\"unknown\">غير معروف</string>\n    <string name=\"format_preference\">تفضيل التنسيقات</string>\n    <string name=\"remove_multiple_templates_msg\">هل ترغب في إزالة %1$s من قوالب الأوامر بشكل دائم؟</string>\n    <string name=\"set_directory_desc\">اضغط لتحديد مجلد</string>\n    <string name=\"custom_command_directory\">مجلد الأوامر المخصصة</string>\n    <string name=\"custom\">مخصص</string>\n    <string name=\"auto\">تلقائي</string>\n    <string name=\"commands\">أوامر</string>\n    <string name=\"export_to_file\">تصدير إلى ملف</string>\n    <string name=\"ua_header\">Header وكيل العميل</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"zero\">%d عنصر</item>\n        <item quantity=\"one\">%d عنصر</item>\n        <item quantity=\"two\">عنصران</item>\n        <item quantity=\"few\">%d عناصر</item>\n        <item quantity=\"many\">%d عنصرًا</item>\n        <item quantity=\"other\">%d عنصر</item>\n    </plurals>\n    <string name=\"custom_command_usage_msg\">yt-dlp هي أداة سطر أوامر قوية لتنزيل مقاطع الفيديو. يجعل Seal استخدام yt-dlp أسهل من خلال توفير واجهة مستخدم بديهية، وإعدادات مسبقة للأوامر الشائعة، وميزات إضافية أخرى.\n\\n\n\\nبالنسبة للاستخدام المتقدم لـ yt-dlp، يسمح لك Seal بإنشاء قوالب أوامر مخصصة وحفظها وتنفيذها مباشرة، تمامًا كما هو الحال في الطرفية.\n\\n\n\\nعند استخدام الأوامر المخصصة، ستتم تعطيل معظم خيارات واجهة المستخدم والميزات.</string>\n    <string name=\"clear_download_archive\">هل تريد مسح أرشيف التحميل؟</string>\n    <string name=\"clear_download_archive_desc\">هل تريد إزالة %1$s من ملف الأرشيف نهائياً؟</string>\n    <string name=\"embed_metadata\">إدماج البيانات الوصفية</string>\n    <string name=\"presets\">إعدادات مسبقة</string>\n    <string name=\"required\">ضروري</string>\n    <string name=\"output_template\">قالب الإخراج</string>\n    <string name=\"output_template_desc\">حدد القالب لأسماء الملفات الناتجة</string>\n    <string name=\"download_archive_desc\">سجل معرفات الفيديو التي تم تحميلها في أرشيف لتجنب التحميل المكرر</string>\n    <string name=\"embed_metadata_desc\">أدمج البيانات الوصفية والصورة المصغرة للفيديو في ملف الصوت</string>\n    <string name=\"download_archive\">أرشيف التحميل</string>\n    <string name=\"save\">حفظ</string>\n    <string name=\"use_format_sorting\">استخدم فرز التنسيق</string>\n    <string name=\"restrict_filenames_desc\">حدد أسماء الملفات بأحرف محددة لضمان التوافق</string>\n    <string name=\"show_all_items\">عرض كل %1$d العناصر</string>\n    <string name=\"restrict_filenames\">تقييد أسماء الملفات</string>\n    <string name=\"edit_file\">تعديل الملف</string>\n    <string name=\"subdirectory_hint\">سيتم حفظ التنزيلات الخاصة بك على النحو التالي:</string>\n    <string name=\"website\">موقع إلكتروني</string>\n    <string name=\"playlist_title\">عنوان قائمة التشغيل</string>\n    <string name=\"force_ipv4\">فرض IPv4</string>\n    <string name=\"system_settings\">إعدادات النظام</string>\n    <string name=\"force_ipv4_desc\">قم بإجراء كافة الاتصالات عبر IPv4</string>\n    <string name=\"allow_once\">السماح مرة واحدة</string>\n    <string name=\"allow_always\">السماح دائماً</string>\n    <string name=\"dont_allow\">عدم السماح</string>\n    <string name=\"download_with_cellular_request\">هل تسمح بالتنزيل باستخدام بيانات الهاتف ؟</string>\n    <string name=\"merge_audiostream\">دمج بث صوتي متعدد</string>\n    <string name=\"merge_audiostream_desc\">السماح بدمج بث صوتي متعدد في ملف واحد</string>\n    <string name=\"keep_subtitle_files\">حفظ ملفات الترجمة</string>\n    <string name=\"download_archive_error\">تم تحميل الفيديو. إذا لم يكن هذا هو السلوك المتوقع، يرجى التحقق من أرشيف التحميل الخاص بك.</string>\n    <string name=\"full_backup\">حفظ احتياطي كامل</string>\n    <string name=\"backup_type\">نوع الحفظ الاحتياطي</string>\n    <string name=\"file\">ملف</string>\n    <string name=\"import_download_history\">استرداد سجل التنزيلات؟</string>\n    <string name=\"export_download_history_msg\">استخراج%1$sمن سجل التنزيلات. التنزيلات والتفضيلات لن يتم حفظهم احتياطي.</string>\n    <string name=\"export_download_history\">استخراج سجل التنزيلات؟</string>\n    <string name=\"auto_translated_subtitles\">الترجمة التلقائية</string>\n    <string name=\"auto_translated_subtitles_msg\">الترجمة الآلية لجميع اللغات ستكون متاحة للتنزيل. قد تكون هذه الترجمات غير دقيقة ويصعب فهمها.</string>\n    <string name=\"subtitle_language_desc\">لغات الترجمة الفرعية للتنزيل التلقائي بفاصلة بين كل منها.</string>\n    <string name=\"remember_for_next_download\">حفظ للتحميل القادم</string>\n    <string name=\"look_and_feel\">المظهر والشعور</string>\n    <string name=\"interface_and_interaction\">الواجهة والتفاعل</string>\n    <string name=\"use_previous_selection\">تحديد الاختيار السابق</string>\n    <string name=\"none\">لا شيء</string>\n    <string name=\"reset\">إعادة الظبط</string>\n    <string name=\"search_in_subtitles\">البحث في الترجمات</string>\n    <string name=\"no_thanks\">لا شكرا</string>\n    <string name=\"export_backup\">استخراج</string>\n    <string name=\"import_backup\">استرداد</string>\n    <string name=\"export_to\">استخراج الي</string>\n    <string name=\"clipboard\">الحافظة</string>\n    <string name=\"import_from\">استرداد من</string>\n    <string name=\"import_download_history_msg\">لا يمكن استرداد التنزيلات. يجب عليك تحميلهم يدوي</string>\n    <string name=\"download_history\">سجل التنزيلات</string>\n    <string name=\"update_language_msg\">اللغات التالية سوف تتضاف لتفضيلاتك في التنزيلات القادمة:</string>\n    <string name=\"update_subtitle_languages\">تحديث لغة الترجمة؟</string>\n    <string name=\"download_history_imported\">استرداد %1$sالي سجل التنزيلات</string>\n    <string name=\"redownload\">إعادة التحميل</string>\n    <string name=\"search_in_downloads\">البحث في التنزيلات</string>\n    <string name=\"search\">البحث</string>\n    <string name=\"remux_container_mkv_desc\">تحويل صيغة الفيديوهات إلى MKV لتوافق أفضل</string>\n    <string name=\"remux_container_mkv\">حاوية فيديو Remux</string>\n    <string name=\"cookies_in_database\">\"%1$d  ملفات تعربف إرتباط مخزنة لعدد  %2$d  موقع\"</string>\n    <string name=\"every_day\">كل يوم</string>\n    <string name=\"every_week\">كل اسبوع</string>\n    <string name=\"every_month\">كل شهر</string>\n    <string name=\"all_languages\">كل اللغات</string>\n    <string name=\"playlist\">قائمة التشغيل</string>\n    <string name=\"proceed\">متابعة</string>\n    <string name=\"preset\">الإعداد المسبق</string>\n    <string name=\"prefer_placeholder\">تفضيل %1$s</string>\n    <string name=\"best_quality_desc\">تنزيل أفضل تنسيق متاح</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"zero\">فيديو</item>\n        <item quantity=\"one\">%d فيديو</item>\n        <item quantity=\"two\">فيديوهان</item>\n        <item quantity=\"few\">%d فيديوهات</item>\n        <item quantity=\"many\">%d فيديو</item>\n        <item quantity=\"other\">%d فيديو</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"zero\">صوت</item>\n        <item quantity=\"one\">­%d صوت</item>\n        <item quantity=\"two\">صوتان</item>\n        <item quantity=\"few\">%d أصوات</item>\n        <item quantity=\"many\">%d صوت</item>\n        <item quantity=\"other\">%d صوت</item>\n    </plurals>\n    <string name=\"task_added\">تمت إضافة المهمة إلى قائمة الانتظار</string>\n    <string name=\"custom_format_selection_desc\">اختر من بين التنسيقات والترجمات وقم بتخصيصها بشكل أكبر</string>\n    <string name=\"preset_format_selection_desc\">تنزيل تلقائي باستخدام تفضيلات التنسيق الخاصة بك</string>\n    <string name=\"edit_preset\">تعديل الإعداد المسبق</string>\n    <string name=\"you_ll_find_your_downloads_here\">ستجد التنزيلات الخاصة بك هنا</string>\n    <string name=\"download_hint\">اضغط على زر التنزيل أو قم بمشاركة رابط الفيديو لهذا التطبيق لبدء التنزيل</string>\n    <string name=\"status_downloaded\">تم التنزيل</string>\n    <string name=\"all\">الجميع</string>\n    <string name=\"select_multiple_link\">اختر من %1$d رابطًا</string>\n    <string name=\"download_queue\">قائمة انتظار التنزيل</string>\n    <string name=\"show_navigation_drawer\">إظهار درج التنقل</string>\n    <string name=\"resume\">استمرار</string>\n    <string name=\"delete\">حذف</string>\n    <string name=\"trouble_shooting_desc\">إصلاح الأخطاء الشائعة والتحقق من المشاكل المعروفة</string>\n    <string name=\"trouble_shooting\">استكشاف الأخطاء وإصلاحها</string>\n    <string name=\"issue_tracker\">متتبع المشكلة</string>\n    <string name=\"issue_tracker_hint\">هل واجهت خطًأ؟ قبل الإبلاغ عن مشكلة جديدة، يرجى البحث في أداة تتبع المشاكل لدينا. لقد عولجت العديد من المشاكل الشائعة وتوثيقها بالفعل هناك.</string>\n    <string name=\"media_info\">معلومات الوسائط</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ar-rSA/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">طلع الصوت بس</string>\n    <string name=\"create_thumbnail\">احفظ صورة المقطع</string>\n    <string name=\"settings\">الاعدادات</string>\n    <string name=\"download\">نزله</string>\n    <string name=\"url_empty\">معليش المفروض الرابط مو فاضي</string>\n    <string name=\"extract_audio_summary\">نزّل الصوت بعدين احفظه, مكان المقطع</string>\n    <string name=\"yt_dlp_up_to_date\">استخدم آخر نسخة من yt-dlp</string>\n    <string name=\"fetching_info\">ترنا ندور عن معلومات الفيديو اذا ما عليك امر.</string>\n    <string name=\"permission_denied\">ماش رفضونا.</string>\n    <string name=\"download_success_msg\">خلص التحميل. تامر على شي ثاني حاضرين</string>\n    <string name=\"download_error_msg\">معليش ما قدرت انزل.</string>\n    <string name=\"download_start_msg\">تحميل \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">ما قدرت اجيب معلومات الفيديو</string>\n    <string name=\"general_settings\">عام</string>\n    <string name=\"language\">لغة العرض</string>\n    <string name=\"language_settings\">ثبتنا لغة عرضك</string>\n    <string name=\"paste_msg\">الصق الرابط</string>\n    <string name=\"paste_fail_msg\">معليش ما لقيا الرابط في الحافظة انسخ مرة ثانية لاهنت</string>\n    <string name=\"ytdlp_version\">نسخة Yt-dlp</string>\n    <string name=\"ytdlp_update_action\">حدث yt-dlp</string>\n    <string name=\"delete_info\">تبي تحذف؟</string>\n    <string name=\"delete_info_msg\">احذف \\\"%1$s\\\" من سجل التصفح افضلك؟</string>\n    <string name=\"confirm\">أكد</string>\n    <string name=\"dismiss\">الغينا</string>\n    <string name=\"downloads_history\">التحميلات</string>\n    <string name=\"download_settings_desc\">عام , الصيغة, أوامر خاصة</string>\n    <string name=\"create_thumbnail_summary\">احفظ صورة المقطع في مكان ثاني</string>\n    <string name=\"task_running\">خلاص شف قاعدين ننزله لك لا تشغلنا.</string>\n    <string name=\"ytdlp_update\">اضغط هنا عشان انزلك اخر نسخة لـ yt-dlp</string>\n    <string name=\"audio\">الصوت</string>\n    <string name=\"video_directory\">ملفات الفيديو</string>\n    <string name=\"yt_dlp_update_fail\">مقدرت انزّل اخر نسخة من yt-dlp. لاهنت تقدر تشيك على اتصال الانترنت لا يكون مفصول بس.</string>\n    <string name=\"link_copied\">تم نسخ الرابط إلى الحافظة</string>\n    <string name=\"open_url\">افتح الرابط</string>\n    <string name=\"delete_file\">حذف الملف</string>\n    <string name=\"about\">حول</string>\n    <string name=\"about_page\">الإصدار، التعليقات، التحديث التلقائي</string>\n    <string name=\"back\">تراجع</string>\n    <string name=\"version\">الإصدار</string>\n    <string name=\"release_desc\">ابحث عن سجلات التغييرات والإصدارات الجديدة</string>\n    <string name=\"release\">أحدث إصدار</string>\n    <string name=\"readme_desc\">تحقق من مستودع GitHub وملف README</string>\n    <string name=\"video\">فيديو</string>\n    <string name=\"checked\">محدد</string>\n    <string name=\"credits\">الاعتمادات</string>\n    <string name=\"custom_command\">أمر مخصص</string>\n    <string name=\"custom_command_desc\">تشغيل أمر yt-dlp باستخدام قالب مخصص</string>\n    <string name=\"custom_command_template\">قالب الأوامر</string>\n    <string name=\"edit\">تعديل</string>\n    <string name=\"credits_desc\">الاعتمادات والبرمجيات الحرة</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-az/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Video qovluq</string>\n    <string name=\"extract_audio\">Səs kimi saxla</string>\n    <string name=\"create_thumbnail\">Miniatürü saxla</string>\n    <string name=\"settings\">Tənzimləmələr</string>\n    <string name=\"download_settings_desc\">Ümumi, format, fərdi əmr</string>\n    <string name=\"download\">Yüklə</string>\n    <string name=\"url_empty\">Bağlantı boş ola bilməz</string>\n    <string name=\"extract_audio_summary\">Video əvəzində, səs yüklə və saxla</string>\n    <string name=\"create_thumbnail_summary\">Video miniatürü fayl kimi saxla</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp-nin ən son versiyası işlədilir</string>\n    <string name=\"yt_dlp_update_fail\">Ən son yt-dlp versiyasın quraşdırmaq alınmadı. Zəhmət olmasa, İnternetə qoşduğunuzdan əmin olun.</string>\n    <string name=\"fetching_info\">Video məlumatı alınır…</string>\n    <string name=\"permission_denied\">İcazə rədd edildi</string>\n    <string name=\"download_success_msg\">Yükləmə bitdi</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" faylın yüklə</string>\n    <string name=\"fetch_info_error_msg\">Video məlumatı almaq mümkün olmadı</string>\n    <string name=\"general_settings\">Ümumi</string>\n    <string name=\"language\">Göstərilmə dili</string>\n    <string name=\"language_settings\">Göstərilmə dilin təyin et</string>\n    <string name=\"task_running\">Mövcud yükləmə tapşırığı artıq idarə edilir</string>\n    <string name=\"paste_msg\">URL-ni Yapışdır</string>\n    <string name=\"paste_fail_msg\">Kəsik lövhədəki URL uyuşmadı</string>\n    <string name=\"ytdlp_update\">Ən son yt-dlp versiyasın quraşdırmaq üçün kliklə</string>\n    <string name=\"delete_info\">Silinsin\\?</string>\n    <string name=\"delete_info_msg\">\\\"%1$s\\\" yükləmə tarixçənizdən həmişəlik silinsin\\?</string>\n    <string name=\"confirm\">Təsdiqlə</string>\n    <string name=\"dismiss\">Ləğv et</string>\n    <string name=\"downloads_history\">Yüklənənlər</string>\n    <string name=\"link_copied\">Bağlantı lövhəyə köçürüldü</string>\n    <string name=\"open_url\">Bağlantını aç</string>\n    <string name=\"remove\">Təmizlə</string>\n    <string name=\"about\">Haqqında</string>\n    <string name=\"back\">Geri</string>\n    <string name=\"version\">Versiya</string>\n    <string name=\"release_desc\">Dəyişiklik jurnalları və yeni versiyaları axtar</string>\n    <string name=\"release\">Ən son buraxılış</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Yoxlanılıb</string>\n    <string name=\"credits\">Köməkçilər</string>\n    <string name=\"credits_desc\">Kreditlər və pulsuz proqram təminatı</string>\n    <string name=\"custom_command\">Fərdi əmr</string>\n    <string name=\"custom_command_desc\">yt-dlp əmrin, fərdi şablonla idarə et</string>\n    <string name=\"custom_command_template\">Əmr şablonu</string>\n    <string name=\"edit\">Redaktə et</string>\n    <string name=\"start_execute\">Əmri icra etməyə başla</string>\n    <string name=\"advanced_settings\">Qabaqcıl</string>\n    <string name=\"print_details\">Ətraflı buraxılış</string>\n    <string name=\"print_details_desc\">Yükləmə zamanı ətraflı məlumatları çap et</string>\n    <string name=\"display\">Göstərilmə</string>\n    <string name=\"display_settings\">Qaranlıq tema, dinamikalı rəng, dillər</string>\n    <string name=\"dark_theme\">Qaranlıq tema</string>\n    <string name=\"follow_system\">Sistem</string>\n    <string name=\"off\">Bağla</string>\n    <string name=\"cancel\">Ləğv et</string>\n    <string name=\"settings_before_download\">Yükləməzdən əvvəl konfiqurasiya et</string>\n    <string name=\"settings_before_download_text\">Bu yükləməni tənzimlə</string>\n    <string name=\"error_copied\">Xəta məlumatı lövhəyə köçürüldü</string>\n    <string name=\"thumbnail\">Miniatür</string>\n    <string name=\"paste\">Yapışdır</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp istifadə istinadları</string>\n    <string name=\"edit_template_desc\">Buraxılış yolu və URL tətbiq tərəfindən əlavə ediləcək.</string>\n    <string name=\"convert_audio_format\">Səs formatına döndər</string>\n    <string name=\"not_convert\">Döndərilməmiş</string>\n    <string name=\"convert_to\">%1$s-a döndər</string>\n    <string name=\"format\">Format</string>\n    <string name=\"convert_audio_format_desc\">Səs faylların yenidən kodlaşdırmaq səs keyfiyyətində itkiyə və fayl həcmində artıma səbəb olacaq.</string>\n    <string name=\"video_quality\">Video keyfiyyət</string>\n    <string name=\"best_quality\">Ən yaxşı keyfiyyət</string>\n    <string name=\"video_quality_desc\">Çoxsaylı olduqda video keyfiyyətinə məhdudiyyət qoy</string>\n    <string name=\"not_specified\">Müəyyənləşdirilməyib (standart)</string>\n    <string name=\"video_format_preference\">Üstünlük verilən video formatı</string>\n    <string name=\"preferred_format_desc\">Çoxsaylı təmin ediləndə üstünlük verilən format</string>\n    <string name=\"video_format\">Video formatı</string>\n    <string name=\"start_download\">Yüklə</string>\n    <string name=\"close\">Bağla</string>\n    <string name=\"user_guide\">İstifadəçi bələdçisi</string>\n    <string name=\"open_settings\">Tənzimləmələri aç</string>\n    <string name=\"download_desc\">Tənzimləmələrin nizamladıqdan sonra \\\"Yüklə\\\"-ni kliklə.</string>\n    <string name=\"download_history_desc\">Videolar və səs fayllar daxil olmaqla tətbiqdaxili yükləmələri yoxla və idarə et.</string>\n    <string name=\"download_playlist\">Oynatma siyahısın yüklə</string>\n    <string name=\"download_playlist_desc\">Oynatma siyahısından çoxlu video yüklə</string>\n    <string name=\"defaults\">Standart</string>\n    <string name=\"channel_name\">Yüklə</string>\n    <string name=\"channel_description\">Yüklənilmiş fayllar və irəliləyiş bildirilir</string>\n    <string name=\"video_url\">Video bağlantısı</string>\n    <string name=\"download_finish_notification\">Yükləmə bitdi. Açmaq üçün toxun.</string>\n    <string name=\"execute_command_notification\">Fərdi əmrlər icra edilir…</string>\n    <string name=\"battery_settings_desc\">Zəhmət olmasa, arxa planda yükləmək üçün bu tətbiqin batareya istifadəsin sistem seçimlərində \\\"Qeyri-məhdud\\\" kimi təyin edin.</string>\n    <string name=\"concurrent_download\">Çox yönlü yükləmə</string>\n    <string name=\"options\">Seçimlər</string>\n    <string name=\"additional_settings\">Əlavə tənzimləmələr</string>\n    <string name=\"share_fail_msg\">Paylaşılan məzmundan URL-i uyuşdurmaq mümkünsüzdür</string>\n    <string name=\"share_success_msg\">Paylaşılan məzmundan video linki oxunur…</string>\n    <string name=\"show_more_actions\">Daha çox fəaliyyət göstər</string>\n    <string name=\"download_notification\">Yükləmə bildirişi</string>\n    <string name=\"download_range_selection\">Oynatma siyahısı seçmə</string>\n    <string name=\"select_all\">Hamısın seç</string>\n    <string name=\"download_error_msg\">Faylı yükləmək mümkün olmadı</string>\n    <string name=\"ytdlp_version\">Yt-dlp versiyası</string>\n    <string name=\"audio\">Səs</string>\n    <string name=\"delete_file\">Faylı sil</string>\n    <string name=\"about_page\">Versiya, əks əlaqə, avtomatik yeniləmə</string>\n    <string name=\"readme_desc\">GitHub anbarı və README-ni yoxla</string>\n    <string name=\"on\">Aç</string>\n    <string name=\"settings_before_download_desc\">Yükləməzdən əvvəl seçimləri konfiqurasiya et</string>\n    <string name=\"convert_audio\">Döndər</string>\n    <string name=\"close_never_show_again\">Təkrar göstərmə</string>\n    <string name=\"paste_desc\">Lövhənizdən video əlaqəsin əldə etmək üçün \\\"Yapışdır\\\"-a klikləyin.</string>\n    <string name=\"check_download_settings_desc\">Yükləmə tənzimləmələrinə baxın və istifadədən əvvəl yt-dlp\\'nin ən son versiyasına sahib olduğunuzdan əmin olun.</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD videoların daha çox hissələrin yanaşı yüklə</string>\n    <string name=\"concurrent_download_num\">%d bölüm DASH/HLS yerli videosun eyni vaxtda yükləmək üçün istifadə olunacaq.</string>\n    <string name=\"download_notification_desc\">Yüklənilmiş fayllar və irəliləyiş bildirilir</string>\n    <string name=\"fetching_playlist_info\">Oynatma siyahısı məlumatı alınır…</string>\n    <string name=\"download_range_desc\">Oynatma siyahısından (%1$d-dən %2$d-a) yükləmək üçün videoların həddin müəyyənləşdir \\\"%3$s\\\".</string>\n    <string name=\"from\">Başlanğıc</string>\n    <string name=\"to\">Son</string>\n    <string name=\"invalid_index_range\">Etibarsız göstərici həddi</string>\n    <string name=\"audio_directory\">Səs qovluğu</string>\n    <string name=\"download_directory\">Yükləmə kataloqu</string>\n    <string name=\"download_directory_desc\">Video və səs faylların haradasa saxlamaq üçün seç</string>\n    <string name=\"subdirectory\">Alt kataloqda saxla</string>\n    <string name=\"permission_issue\">Saxlama icazəsi problemi</string>\n    <string name=\"service_title\">Seal yükləyir…</string>\n    <string name=\"unknown_error\">Naməlum xəta</string>\n    <string name=\"translate\">Tərcümə et</string>\n    <string name=\"translate_desc\">Hosted Weblate-də bu tətbiqi tərcümə etməyə kömək et</string>\n    <string name=\"permission_issue_desc\">Download/ və Documents/ xaricindəki kataloqlar dəstəklənmir</string>\n    <string name=\"prefix\">Ön şəkilçi</string>\n    <string name=\"downloading_indicator_text\">Yükləmə davam edir …</string>\n    <string name=\"embed_subtitles\">Titrləri yerləşdir</string>\n    <string name=\"new_template\">Yeni şablon</string>\n    <string name=\"template_label\">Etiket</string>\n    <string name=\"remove_template\">Təmizlənsin\\?</string>\n    <string name=\"remove_template_desc\">\\\"%1$s\\\" əmr şablonlarından həmişəlik silinsin?</string>\n    <string name=\"template_selection\">Şablon seçimi</string>\n    <string name=\"custom_command_template_desc\">Əmr şablonların redaktə et və idarə et</string>\n    <string name=\"task_canceled\">Yükləmə tapşırığı ləğv edildi</string>\n    <string name=\"github_issue\">GitHub problemi</string>\n    <string name=\"info_copied\">Məlumat lövhəyə köçürüldü</string>\n    <string name=\"status_completed\">Bitdi</string>\n    <string name=\"status_downloading\">Yüklənilir</string>\n    <string name=\"status_canceled\">Ləğv edildi</string>\n    <string name=\"status_fetching_video_info\">Məlumat alınır</string>\n    <string name=\"open_file\">Faylı aç</string>\n    <string name=\"restart\">Yenidən başlat</string>\n    <string name=\"copy_link\">Bağlantını köçür</string>\n    <string name=\"copy_error_report\">Məlumatı köçür</string>\n    <string name=\"video_resolution\">Video görüntü imkanı</string>\n    <string name=\"video_file_size\">Video fayl həcmi</string>\n    <string name=\"export_to_clipboard\">Lövhəyə ixrac et</string>\n    <string name=\"import_from_clipboard\">Lövhədən idxal et</string>\n    <string name=\"download_task_count\">%1$d yükləmə tapşırığı</string>\n    <string name=\"recently_added\">Yenicə Əlavə Edilib</string>\n    <string name=\"delete_multiple_items_msg\">%1$d element yükləmə tarixçənizdən həmişəlik silinsin\\?</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API ilə videolarda bölümləri təmizlə yaxud işarələ</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock kateqoriyaları</string>\n    <string name=\"check_for_updates\">Yeniləmələr üçün yoxla</string>\n    <string name=\"check_for_updates_desc\">GitHub-dakı ən son versiyanı avtomatik yoxla</string>\n    <string name=\"app_up_to_date\">Cari versiya güncəldir</string>\n    <string name=\"app_update_failed\">Ən son versiyaya yeniləmək alınmadı</string>\n    <string name=\"update\">Yenilə</string>\n    <string name=\"aria2_desc\">Xarici yükləyici kimi aria2c istifadə et</string>\n    <string name=\"clear_temp_files_count\">%1$d müvəqqəti fayl silindi</string>\n    <string name=\"private_mode\">Gizli</string>\n    <string name=\"dynamic_color\">Dinamikalı rəng</string>\n    <string name=\"dynamic_color_desc\">Rəngləri divar kağızlarından tətbiq mövzusuna tətbiq et</string>\n    <string name=\"download_with_cellular\">Mobil şəbəkə işlədərək yüklə</string>\n    <string name=\"download_disabled_with_cellular\">Mobil şəbəkə ilə yükləmə tənzimləmələrinizə uyğun olaraq qeyri-aktivdir</string>\n    <string name=\"file_unavailable\">Bu fayl artıq mövcud deyil</string>\n    <string name=\"network\">Şəbəkə</string>\n    <string name=\"rate_limit\">Sürət həddi</string>\n    <string name=\"rate_limit_desc\">Maksimum yükləmə sürətin məhdudlaşdır</string>\n    <string name=\"max_rate\">Maksimum sürət</string>\n    <string name=\"high_contrast\">Yüksək ziddiyyət, qaranlıq mövzu</string>\n    <string name=\"lowest_quality\">Ən aşağı keyfiyyət</string>\n    <string name=\"unavailable\">Əlçatmaz</string>\n    <string name=\"general_settings_desc\">Yt-dlp versiyası, bildiriş, oynatma siyahısı</string>\n    <string name=\"network_settings_desc\">Sürət həddi, yükləyici, məlumat bazası</string>\n    <string name=\"disable_preview\">Önizləməni qeyri-aktiv et</string>\n    <string name=\"disable_preview_desc\">Yükləmə əsnasında miniatürlər göstərilmir</string>\n    <string name=\"privacy\">Məxfilik</string>\n    <string name=\"private_directory\">Şəxsi kataloq</string>\n    <string name=\"private_directory_desc\">Yükləmələri gizli kataloqda saxla</string>\n    <string name=\"crop_artwork\">Şəkli kəs</string>\n    <string name=\"crop_artwork_desc\">Yerləşdirilən şəkli kvadrat şəklində kəs</string>\n    <string name=\"selected_item_count\">%1$d seçildi</string>\n    <string name=\"battery_configuration\">Batareya konfiqurasiyası</string>\n    <string name=\"battery_configuration_desc\">Arxa planda yükləmə üçün, bu tətbiqin batareya optimallaşdırılmasın istəmə</string>\n    <string name=\"playlist_indicator_text\">Oynatma siyahısı yüklənilir (%1$d/%2$d)…</string>\n    <string name=\"subdirectory_desc\">Faylları uyğun sahələr kimi adlandırılan qovluqlarda saxla</string>\n    <string name=\"github_issue_desc\">Səhv məlumatı və ya xüsusiyyət sorğusu üçün problem təqdim et</string>\n    <string name=\"embed_subtitles_desc\">Varsa, videolara titrləri yerləşdir</string>\n    <string name=\"status_enqueued\">Növbəyə salındı</string>\n    <string name=\"status_error\">Xəta</string>\n    <string name=\"multiselect_item_count\">%1$d video, %2$d səs faylı</string>\n    <string name=\"template_exported\">%1$d şablon ixrac edildi</string>\n    <string name=\"template_imported\">%1$d şablon idxal edildi</string>\n    <string name=\"cookies_desc\">Yükləmələr üçün Netscape formatlı məlumat bazası istifadə et</string>\n    <string name=\"sponsorblock_categories_desc\">Video faylda silmək və ya işarələmək üçün SponsorBlock kateqoriyaları müəyyənləşdir</string>\n    <string name=\"clear_temp_files_desc\">Müvəqqəti qovluqdan bütün müvəqqəti faylları silin</string>\n    <string name=\"multiselect_mode\">Çoxseçimli rejim</string>\n    <string name=\"clear_temp_files\">Müvəqqəti faylları təmizlə</string>\n    <string name=\"clear_temp_files_info\">Müvəqqəti fayllar imtina edilmiş yükləmələri davam etdirmək üçün istifadə edilə bilər. Bu faylların hamısın siləcəyinizə əminsiniz? \n\\n\n\\nBu fayllara %1$s ilə giriş edə bilərsiniz</string>\n    <string name=\"private_mode_desc\">Yükləmə tarixçəsin qeyri-aktiv et</string>\n    <string name=\"download_with_cellular_desc\">Ölçülmüş şəbəkələrə qoşduqda media yüklənilməsinə icazə ver</string>\n    <string name=\"use_custom_command\">Fərdi əmr istifadə et</string>\n    <string name=\"invalid_input\">Etibarsız giriş</string>\n    <string name=\"format_settings_desc\">Fayl formatı, video keyfiyyəti, titrlər</string>\n    <string name=\"download_selection_desc\">\\\"%1$s\\\" pleylistindən yükləmək üçün videoları seç</string>\n    <string name=\"video_only\">Video (səs yoxdur)</string>\n    <string name=\"format_selection\">Format seçimi</string>\n    <string name=\"suggested\">Məsləhət görülən</string>\n    <string name=\"format_selection_desc\">Yükləmə başlamazdan əvvəl yükləmək üçün format seç</string>\n    <string name=\"generate_new_cookies\">Yeni məlumat bazası yarat</string>\n    <string name=\"use_cookies\">Məlumat bazası istifadə et</string>\n    <string name=\"remove_cookie_profile_desc\">Bu giriş \\\"%1$s\\\" üçün silinsin? Nəzərə alın ki, bu sayt üçün saxlanılan məlumatlar silinməyəcək.</string>\n    <string name=\"custom_command_enabled_hint\">Fərdi əmr istifadə edərkən bəzi seçimlər əlçatmazdır</string>\n    <string name=\"how_does_it_work\">Bu necə işləyir\\?</string>\n    <string name=\"cookies_usage_msg\">Bəzi saytlardan yükləmə zamanı hesab təsdiqləmə məlumatı tələb olunur. \\\"Yeni məlumat bazası yarada\\\" kliklə, vebsayt URL-ni daxil et və sonra brauzer səhifəsində hesabınızla daxil olun, tətbiq sizin üçün bunu yaradacaq.</string>\n    <string name=\"telegram_channel\">Telegram kanalı</string>\n    <string name=\"cookies\">Məlumat bazası</string>\n    <string name=\"matrix_space\">Matrix məkanı</string>\n    <string name=\"abs_hint\">Əksər video yayım platformaları səs və videonu ayrı çatdırır, siz bir video üçün yalnız video formatı ilə yalnız səs formatın seçə və birləşdirə bilərsiniz.</string>\n    <string name=\"auto_subtitle\">Avtomatik titrlər</string>\n    <string name=\"video_title_sample_text\">Video başlıq mətn nümunəsi</string>\n    <string name=\"subtitle\">Titr</string>\n    <string name=\"download_subtitles\">Titrləri yüklə</string>\n    <string name=\"subtitle_language\">Titr dilləri</string>\n    <string name=\"subtitle_desc\">Dillər, yerləşdirilən titrlər, avtomatik titrlər</string>\n    <string name=\"copy_log\">Jurnalı köçür</string>\n    <string name=\"clear\">Təmizlə</string>\n    <string name=\"edit_shortcuts\">Qısayolları redaktə et</string>\n    <string name=\"add\">Əlavə et</string>\n    <string name=\"show_logs\">Jurnalı göstər</string>\n    <string name=\"logs\">Jurnal</string>\n    <string name=\"sdcard_directory\">SD kart qovluğu</string>\n    <string name=\"auto_subtitle_desc\">Avtomatik yaradılan titrləri yüklə</string>\n    <string name=\"title_activity_share\">Sürətli yükləmə</string>\n    <string name=\"video_creator_sample_text\">Video yaradıcı mətn nümunəsi</string>\n    <string name=\"shortcuts\">Qısayollar</string>\n    <string name=\"edit_shortcuts_desc\">Əmr şablonların tərtib etmək üçün istifadə edilən fərdi qısayolları redaktə edin.</string>\n    <string name=\"running_tasks\">İdarə edilən tapşırıqlar</string>\n    <string name=\"subtitle_sponsorblock\">SponsorBlock bölümləri silinən zaman titrlər vaxtı səhv ola bilər.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Titrləri yerləşdirmək üçün videolar mkv konteynerinə yenidən daxil ediləcək. Titrlərlə videolara baxmaq üçün VLC Media Player və ya digər, uyğun tətbiqləri istifadə edə bilərsiniz.</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"share\">Paylaş</string>\n    <string name=\"update_channel\">Yeniləmə kanalı</string>\n    <string name=\"enable_auto_update\">Avtomatik yeniləməni aktivləşdir</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"pre_release_channel\">İlkin baxış</string>\n    <string name=\"update_channel_desc\">Yeni xüsusiyyətlər və dəyişikliklərə ilkin baxış üçün ilkin buraxılış quruluşları quraşdır.\n\\n\n\\nBu versiyalarda az-çox qeyri-stabillik olacaq, beləliklə gələcəkdə tətbiqi təkmilləşdirmək,bizə kömək etmək üçün hər hansı problemlərlə qarşılaşsanız, bizə rəy bildirməyə tərəddüd etməyin.</string>\n    <string name=\"auto_update\">Avtomatik yenilənmə</string>\n    <string name=\"apply\">Tətbiq et</string>\n    <string name=\"clip_video\">Videonu kəs</string>\n    <string name=\"clip_end\">Son</string>\n    <string name=\"discard\">Rədd et</string>\n    <string name=\"clip_start\">Başlanğıc</string>\n    <string name=\"audio_format_preference\">Üstünlük verilən səs formatı</string>\n    <string name=\"format_sorting_desc\">Yt-dlp -S seçimi ilə çeşidlənən formatlar</string>\n    <string name=\"clear_all_cookies_desc\">Tətbiqdə saxlanılan bütün məlumatlar həmişəlik silinsin\\?</string>\n    <string name=\"unlimited\">Qeyri-məhdud</string>\n    <string name=\"lowest_bitrate\">Ən aşağı bit sürəti</string>\n    <string name=\"audio_quality\">Səs keyfiyyəti</string>\n    <string name=\"audio_quality_desc\">Çoxsaylı keyfiyyətlər mövcud olduqda səs bit sürətin məhdudlaşdır</string>\n    <string name=\"format_sorting\">Format çeşidlənməsi</string>\n    <string name=\"import_from_preferences\">İdxal</string>\n    <string name=\"title\">Başlıq</string>\n    <string name=\"rename\">Yenidən adlandır</string>\n    <string name=\"second\">saniyə</string>\n    <string name=\"minute\">dəqiqə</string>\n    <string name=\"clear_all_cookies\">Bütün məlumat bazaların sil</string>\n    <string name=\"temporary_directory_desc\">Müvəqqəti faylları daxili kataloqda saxla</string>\n    <string name=\"sponsor\">Himayədar</string>\n    <string name=\"feedback\">Əks əlaqə</string>\n    <string name=\"sponsors\">Himayədarlar</string>\n    <string name=\"sponsor_desc\">GitHub-da himayədarlıq edərək bu tətbiqi dəstəklə</string>\n    <string name=\"sponsor_msg\">Seal həmişə, hamı üçün pulsuz və açıq mənbə olacaqdır. Əgər bəyənirsinizsə, mənə GitHub-da himayədarlıq etməyi düşünün!</string>\n    <string name=\"audio_format\">Səs formatı</string>\n    <string name=\"no_downloaded_media\">Yüklənilən media yoxdur</string>\n    <string name=\"beta_features\">Sınaq</string>\n    <string name=\"enable_experimental_feature\">Təcrübi xüsusiyyət aktivləşdirilsin\\?</string>\n    <string name=\"clip_video_desc\">Format seçim səhifəsində video kliplər yarat</string>\n    <string name=\"clip_video_dialog_msg\">Bu xüsusiyyəti işlədən yükləmələr, videonun seçilən bölmələrin yükləmək üçün FFmpeg-yə həvalə olunacaq, bu xüsusiyyət hələ təcrübidir və kəsmə tamamilə dəqiq olmayacaq, bütün formatlar bu xüsusiyyəti dəstəkləmir və daha yavaş yükləmə sürəti görə bilərsiniz.</string>\n    <string name=\"auto_update_disabled_msg\">Avtomatik yeniləmə %1$s quruluşlar üçün əlçatan deyil. Cihazınızda quraşdırılmış %1$s yoxdursa və ya Seal-da növbəti yeni xüsusiyyətləri nəzərdən keçirmək istəyirsinizsə, zəhmət olmasa %2$s-ı nəzərdən keçirin.</string>\n    <string name=\"switch_to_github_builds\">GitHub quruluşlarına keçid</string>\n    <string name=\"okay\">Oldu</string>\n    <string name=\"got_it\">Anladım</string>\n    <string name=\"feature_unavailable\">Xüsusiyyət mövcud deyil</string>\n    <string name=\"no_custom_command_tasks\">Fərdi əmr tapşırıqları yoxdur</string>\n    <string name=\"msg_from_developer\">Tərtibatçıdan mesaj</string>\n    <string name=\"sponsor_msg2\">Çox sağ olun!</string>\n    <string name=\"download_video_desc\">Videoları URL-dən yüklə</string>\n    <string name=\"convert_subtitle\">Titrləri çevir</string>\n    <string name=\"convert_subtitle_desc\">Titrləri başqa formata çevir</string>\n    <string name=\"split_video\">Videonu böl</string>\n    <string name=\"split_video_msg\">Video %1$d bölməyə bölünəcək</string>\n    <string name=\"unknown_error_title\">Vay! Nəsə səhv oldu</string>\n    <string name=\"copy_and_exit\">Köçür və çıx</string>\n    <string name=\"expand\">Genişləndir</string>\n    <string name=\"new_task\">Yeni yükləmə tapşırığı</string>\n    <string name=\"start\">Başlat</string>\n    <string name=\"edit_template\">\\\"%1$s\\\" redaktə et</string>\n    <string name=\"remove_multiple_templates_msg\">%1$s əmr şablonlarından həmişəlik təmizlənsin\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d element</item>\n        <item quantity=\"other\">%d element</item>\n    </plurals>\n    <string name=\"refresh_cookies_desc\">Yeni bazalar yaratmaq üçün veb səhifə açmağa toxun:</string>\n    <string name=\"ytdlp_update_action\">Yt-dlp-ni yenilə</string>\n    <string name=\"proxy\">Proksi</string>\n    <string name=\"legacy\">Köhnə</string>\n    <string name=\"proxy_desc\">İnternet bağlantıları üçün proksi işlət</string>\n    <string name=\"enable_notifications\">Bildirişlər aktivləşdirilsin?</string>\n    <string name=\"enable_notifications_desc\">Tətbiqin yükləmə vəziyyəti və irəliləyiş barədə bildirişlər göndərməsi üçün icazənizə ehtiyacı var.</string>\n    <string name=\"quality\">Keyfiyyət</string>\n    <string name=\"ua_header\">İstifadəçi-Agent başlığı</string>\n    <string name=\"disable\">Qeyri-aktiv et</string>\n    <string name=\"set_directory_desc\">Kataloq yaratmaq üçün toxun</string>\n    <string name=\"custom_command_directory\">Fərdi əmr kataloqu</string>\n    <string name=\"disabled\">Qeyri-aktivdir</string>\n    <string name=\"folder_picker\">Qovluq seçici</string>\n    <string name=\"custom_command_directory_desc\">Fərdi əmrlər istifadə edərkən çıxış qovluğun təyin et</string>\n    <string name=\"prefer_compatibility_desc\">Digər tətbiqlərdə paylaşmaq üçün MP4(H.264) formatlarına üstünlük ver</string>\n    <string name=\"prefer_quality_desc\">Uyğun tətbiqlərdə baxmaq üçün AV1, VP9 və ya H.265 formatlarına üstünlük verin</string>\n    <string name=\"download_type\">Yükləmə növü</string>\n    <string name=\"custom\">Fərdi</string>\n    <string name=\"auto\">Avtomatik</string>\n    <string name=\"commands\">Əmrlər</string>\n    <string name=\"format_preference\">Format üstünlüyü</string>\n    <string name=\"learn_more\">Daha çox öyrən</string>\n    <string name=\"unknown\">Naməlum</string>\n    <string name=\"export_to_file\">Fayla ixrac et</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp videoları yükləmək üçün güclü əmr xətti alətidir. Seal intuitiv GUI, ictimai əmrlər üçün qabaqcıl tənzimləmələr və digər əlavə funksiyalar təmin etməklə yt-dlp istifadə etməsini asanlaşdırır.\n\\n\n\\nSeal sizə yt-dlp-nin qabaqcıl istifadəsi üçün terminalda olduğu kimi birbaşa fərdi əmr şablonların yaratmağa, saxlamağa və icra etməyə icazə verir.\n\\n\n\\nFərdi əmrlərdən istifadə edərkən, GUI seçimlərinin və xüsusiyyətlərinin əksəriyyəti qeyri-aktiv ediləcək.</string>\n    <string name=\"clear_download_archive\">Yükləmə arxivi təmizlənsin?</string>\n    <string name=\"clear_download_archive_desc\">%1$s arxiv faylından həmişəlik silinsin?</string>\n    <string name=\"embed_metadata\">Yerləşdirilən Əlavə Məlumat</string>\n    <string name=\"presets\">İlkin tənzimləmələr</string>\n    <string name=\"output_template\">Buraxılış şablonu</string>\n    <string name=\"output_template_desc\">Buraxılış fayl adları üçün şablonu təyin edin</string>\n    <string name=\"download_archive_desc\">Dublikat yükləmələrə əngəl olmaq üçün yüklənilmiş video ID-ləri arxivdə qeyd edin</string>\n    <string name=\"download_archive\">Yükləmə arxivi</string>\n    <string name=\"save\">Saxla</string>\n    <string name=\"subdirectory_hint\">Yükləmələriniz aşağıdakı kimi saxlanılacaq:</string>\n    <string name=\"website\">Veb sayt</string>\n    <string name=\"force_ipv4\">IPv4-ə məcbur et</string>\n    <string name=\"use_format_sorting\">Format çeşidlənməsin istifadə et</string>\n    <string name=\"restrict_filenames_desc\">Uyğunluğu təmin etmək üçün fayl adların xüsusi simvollarla məhdudlaşdır</string>\n    <string name=\"keep_subtitle_files\">Titr faylların saxla</string>\n    <string name=\"required\">Tələb olunan</string>\n    <string name=\"show_all_items\">Bütün %1$d elementi göstər</string>\n    <string name=\"system_settings\">Sistem tənzimləmələri</string>\n    <string name=\"force_ipv4_desc\">Bütün rabitələri IPv4 vasitəsilə qur</string>\n    <string name=\"restrict_filenames\">Fayl adların məhdudlaşdır</string>\n    <string name=\"edit_file\">Fayla düzəliş edin</string>\n    <string name=\"embed_metadata_desc\">Səs faylına əlavə məlumat və video miniatürü yerləşdir</string>\n    <string name=\"playlist_title\">Oynatma siyahısı başlığı (adı)</string>\n    <string name=\"allow_once\">Bir dəfə icazə ver</string>\n    <string name=\"download_with_cellular_request\">Mobil şəbəkə ilə yükləməyə icazə verilsin?</string>\n    <string name=\"merge_audiostream\">Çoxlu səs axının birləşdir</string>\n    <string name=\"merge_audiostream_desc\">Çoxlu səs axınların bir faylda birləşdirməyə icazə ver</string>\n    <string name=\"allow_always\">Həmişə icazə ver</string>\n    <string name=\"dont_allow\">İcazə vermə</string>\n    <string name=\"remux_container_mkv\">Təkrar daxil edilən video konteyner</string>\n    <string name=\"remux_container_mkv_desc\">Daha yaxşı uyğunluq üçün videoları MKV konteynerinə təkrar daxil edin</string>\n    <string name=\"download_archive_error\">Video endirilib. Bu gözlənilən davranış deyilsə, xahiş olunur yükləmə arxivinizi yoxlayın.</string>\n    <string name=\"backup_type\">Nüsxələmə növü</string>\n    <string name=\"export_to\">Bura ixrac et</string>\n    <string name=\"file\">Fayl</string>\n    <string name=\"clipboard\">Lövhə</string>\n    <string name=\"import_download_history\">Yükləmə tarixçəsi idxal edilsin?</string>\n    <string name=\"import_download_history_msg\">Yüklənilmiş fayllar idxal edilməyəcək. Onları əl ilə geri yükləməlisiniz</string>\n    <string name=\"cookies_in_database\">Ümumilikdə, %2$d vebsaytdan %1$d məlumat</string>\n    <string name=\"auto_translated_subtitles\">Avtomatik tərcümə edilmiş titrlər</string>\n    <string name=\"auto_translated_subtitles_msg\">Bütün dillər üçün avtomatik tərcümə edilmiş titrlər yükləmələrdə mövcud olacaq. Bu titrlər yanlış və anlaşılması çətin ola bilər.</string>\n    <string name=\"subtitle_language_desc\">Avtomatik format seçimində yükləmək üçün titrlərin dili, vergüllə ayrılan.</string>\n    <string name=\"look_and_feel\">Görünüş və hissiyyat</string>\n    <string name=\"remember_for_next_download\">Növbəti yükləmə üçün xatırla</string>\n    <string name=\"use_previous_selection\">Əvvəlki seçimi istifadə et</string>\n    <string name=\"interface_and_interaction\">Görünmə və qarşılıqlı təsir</string>\n    <string name=\"none\">Heç biri</string>\n    <string name=\"reset\">Sıfırla</string>\n    <string name=\"search_in_subtitles\">Titrlərdə axtar</string>\n    <string name=\"no_thanks\">Xeyr, təşəkkürlər</string>\n    <string name=\"export_backup\">İxrac et</string>\n    <string name=\"import_backup\">İdxal et</string>\n    <string name=\"full_backup\">Tam ehtiyat nüsxələmə</string>\n    <string name=\"import_from\">Burdan idxal edin</string>\n    <string name=\"export_download_history\">Yükləmə tarixçəsi ixrac edilsin?</string>\n    <string name=\"export_download_history_msg\">Yükləmə tarixçəsindən %1$s ixrac edilir. Yüklənilən fayllar və seçimlər nüsxələnməyəcək.</string>\n    <string name=\"download_history\">Yükləmə Tarixçəsi</string>\n    <string name=\"update_language_msg\">Aşağıdakı dillər gələcək yükləmələr üçün seçiminizə əlavə olunacaq:</string>\n    <string name=\"update_subtitle_languages\">Titr dilləri yenilənsin?</string>\n    <string name=\"every_day\">Hər gün</string>\n    <string name=\"every_week\">Hər həftə</string>\n    <string name=\"every_month\">Hər ay</string>\n    <string name=\"download_history_imported\">Yükləmə tarixçəsinə %1$s idxal edildi</string>\n    <string name=\"redownload\">Yenidən yüklə</string>\n    <string name=\"search_in_downloads\">Yükləmələrdə axtarış</string>\n    <string name=\"search\">Axtar</string>\n    <string name=\"all_languages\">Bütün dillər</string>\n    <string name=\"playlist\">Oynatma siyahısı</string>\n    <string name=\"preset\">İlkin tənzimləmə</string>\n    <string name=\"prefer_placeholder\">%1$s-a üstünlük ver</string>\n    <string name=\"preset_format_selection_desc\">Format seçimlərinizi istifadə edərək avtomatik yükləyin</string>\n    <string name=\"edit_preset\">İlkin seçimə düzəliş et</string>\n    <string name=\"best_quality_desc\">Mövcud ən yaxşı formatı yüklə</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d səs</item>\n        <item quantity=\"other\">%d səs</item>\n    </plurals>\n    <string name=\"task_added\">Tapşırıq növbəyə əlavə edildi</string>\n    <string name=\"proceed\">Davam et</string>\n    <string name=\"custom_format_selection_desc\">Formatlardan, titrlərdən seç və daha çox fərdiləşdir</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d video</item>\n        <item quantity=\"other\">%d video</item>\n    </plurals>\n    <string name=\"you_ll_find_your_downloads_here\">Endirmələri burada tapa bilərsiniz</string>\n    <string name=\"download_hint\">Yükləməyə başlamaq üçün yüklə düyməsinə toxun və ya bu tətbiq üçün video linkin paylaş</string>\n    <string name=\"status_downloaded\">Endirildi</string>\n    <string name=\"all\">Hamısı</string>\n    <string name=\"select_multiple_link\">­%1$d linkdən seçin</string>\n    <string name=\"download_queue\">­Yükləmə növbəsi</string>\n    <string name=\"show_navigation_drawer\">Hərəkət qutusun göstər</string>\n    <string name=\"resume\">Davam et</string>\n    <string name=\"delete\">Sil</string>\n    <string name=\"media_info\">Media məlumatı</string>\n    <string name=\"issue_tracker_hint\">Xəta göründü? Yeni problemi bildirməzdən əvvəl, lütfən problem izləyicimizi araşdırın. Bir çox ümumi problemlər artıq var və orada sənədləşdirilib.</string>\n    <string name=\"trouble_shooting\">Problemlərin həlli</string>\n    <string name=\"issue_tracker\">Problem izləyicisi</string>\n    <string name=\"trouble_shooting_desc\">Düzəlmiş ümumi səhvlər və məlum problemləri yoxla</string>\n    <string name=\"saved_urls\">Saxlanan bağlantılar</string>\n    <string name=\"add_new_url\">Yeni link əlavə et</string>\n    <string name=\"add_to\">%1$s-a əlavə et</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-be/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"download_settings_desc\">Асноўныя налады, фармат, карыстальніцкая каманда</string>\n    <string name=\"video_directory\">Папка для відэа</string>\n    <string name=\"extract_audio\">Захаваць як аўдыя</string>\n    <string name=\"create_thumbnail\">Захаваць мініяцюру</string>\n    <string name=\"download\">Спампаваць</string>\n    <string name=\"extract_audio_summary\">Спампаваць і захаваць аўдыя замест відэа</string>\n    <string name=\"create_thumbnail_summary\">Захаваць мініяцюру відэа як файл</string>\n    <string name=\"yt_dlp_up_to_date\">Выкарыстоўваецца найноўшая версія yt-dlp</string>\n    <string name=\"fetching_info\">Атрыманне інфармацыі аб відэа…</string>\n    <string name=\"permission_denied\">У доступе адмоўлена</string>\n    <string name=\"download_success_msg\">Спампоўка скончана</string>\n    <string name=\"download_error_msg\">Не атрымалася спампаваць файл</string>\n    <string name=\"download_start_msg\">Спампаваць \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Не ўдалося атрымаць інфармацыю пра відэа</string>\n    <string name=\"general_settings\">Асноўныя</string>\n    <string name=\"language\">Мова праграмы</string>\n    <string name=\"language_settings\">Усталюйце мову адлюстравання</string>\n    <string name=\"task_running\">Існуючая задача спампоўкі ўжо запушчана</string>\n    <string name=\"paste_msg\">Устаўлены URL-адрас</string>\n    <string name=\"paste_fail_msg\">Не атрымалася супаставіць URL у буферы абмену</string>\n    <string name=\"ytdlp_version\">Yt-dlp версія</string>\n    <string name=\"ytdlp_update\">Націсніце, каб усталяваць апошнюю версію yt-dlp</string>\n    <string name=\"delete_info\">Выдаліць\\?</string>\n    <string name=\"delete_info_msg\">Назаўсёды выдаліць \\\"%1$s\\\" з гісторыі спамповак\\?</string>\n    <string name=\"confirm\">Пацвердзіць</string>\n    <string name=\"dismiss\">Адмяніць</string>\n    <string name=\"downloads_history\">Спампоўкі</string>\n    <string name=\"audio\">Аўдыё</string>\n    <string name=\"open_url\">Адкрыць спасылку</string>\n    <string name=\"remove\">Выдаліць</string>\n    <string name=\"delete_file\">Выдаліць файл</string>\n    <string name=\"about\">Аб праграме</string>\n    <string name=\"about_page\">Версія, водгукі і абнаўленні</string>\n    <string name=\"back\">Назад</string>\n    <string name=\"settings\">Налады</string>\n    <string name=\"url_empty\">Спасылка не можа быць пустой</string>\n    <string name=\"yt_dlp_update_fail\">Немагчыма ўсталяваць апошнюю версію yt-dlp. Калі ласка, упэўніцеся што вы падключаны да Інтэрнэту.</string>\n    <string name=\"link_copied\">Спасылка скапіявана ў буфер абмену</string>\n    <string name=\"start_execute\">Пачаць выкананне каманды</string>\n    <string name=\"edit\">Рэдагаваць</string>\n    <string name=\"custom_command_template\">Шаблон каманды</string>\n    <string name=\"version\">Версія</string>\n    <string name=\"release_desc\">Азнаёмцеся са спісам змен і новых версій</string>\n    <string name=\"release\">Апошні рэліз</string>\n    <string name=\"readme_desc\">Праверце рэпазітар GitHub і README</string>\n    <string name=\"video\">Відэа</string>\n    <string name=\"checked\">Праверана</string>\n    <string name=\"credits\">Падзякі</string>\n    <string name=\"credits_desc\">Падзякі і бясплатнае праграмнае забеспячэнне</string>\n    <string name=\"custom_command\">Карыстальніцкая каманда</string>\n    <string name=\"custom_command_desc\">Запусціце yt-dlp з карыстальніцкім шаблонам</string>\n    <string name=\"advanced_settings\">Пашыраныя налады</string>\n    <string name=\"print_details\">Падрабязная справаздача</string>\n    <string name=\"paste_desc\">Націсніце «Уставіць», каб атрымаць спасылку на відэа з буфера абмену.</string>\n    <string name=\"download_desc\">Затым націсніце \\\"Спампаваць\\\", наладзіўшы яго параметры.</string>\n    <string name=\"download_history_desc\">Правярайце і кіруйце загрузкамі ў праграме, уключаючы відэа і аўдыяфайлы.</string>\n    <string name=\"download_playlist\">Спампаваць плэйліст</string>\n    <string name=\"channel_description\">Апавяшчаць аб запампаваных файлах і прагрэсе</string>\n    <string name=\"download_finish_notification\">Спампоўка скончана. Націсніце, каб адкрыць.</string>\n    <string name=\"channel_name\">Спампаваць</string>\n    <string name=\"video_url\">Спасылка на відэа</string>\n    <string name=\"print_details_desc\">Выводзіць падрабязныя паведамленні пры загрузцы (%)</string>\n    <string name=\"display\">Знешні выгляд</string>\n    <string name=\"display_settings\">Цёмная тэма, дынамічны колер, мовы</string>\n    <string name=\"dark_theme\">Цёмная тэма</string>\n    <string name=\"follow_system\">Як у сістэме</string>\n    <string name=\"on\">Уключана</string>\n    <string name=\"off\">Выключана</string>\n    <string name=\"cancel\">Адмяніць</string>\n    <string name=\"settings_before_download\">Наладзьце перад загрузкай</string>\n    <string name=\"settings_before_download_text\">Параметры загрузкі</string>\n    <string name=\"settings_before_download_desc\">Наладзьце параметры перад загрузкай</string>\n    <string name=\"error_copied\">Справаздача аб памылцы скапіравана ў буфер абмену</string>\n    <string name=\"thumbnail\">Мініяцюра</string>\n    <string name=\"paste\">Уставіць</string>\n    <string name=\"yt_dlp_docs\">Рэкамендацыі па выкарыстанню Yt-dlp</string>\n    <string name=\"edit_template_desc\">Шлях вываду і URL будуць дададзены праграмай.</string>\n    <string name=\"not_convert\">Не канвертаваць</string>\n    <string name=\"convert_to\">Пераўтварыць у %1$s</string>\n    <string name=\"format\">Фармат</string>\n    <string name=\"convert_audio_format_desc\">Паўторнае кадзіраванне аўдыяфайлаў прывядзе да страты якасці гуку і павелічэння памеру файла.</string>\n    <string name=\"video_quality\">Якасць відэа</string>\n    <string name=\"best_quality\">Найлепшая якасць</string>\n    <string name=\"video_quality_desc\">Абмежаваць якасць відэа, калі прысутнічае некалькі</string>\n    <string name=\"not_specified\">Не ўказана (па змаўчанні)</string>\n    <string name=\"video_format_preference\">Пераважны фармат відэа</string>\n    <string name=\"preferred_format_desc\">Выбраны фармат, калі прадастаўлена некалькі</string>\n    <string name=\"video_format\">Фармат відэа</string>\n    <string name=\"convert_audio\">Канвертаваць</string>\n    <string name=\"start_download\">Спампаваць</string>\n    <string name=\"close\">Зачыніць</string>\n    <string name=\"close_never_show_again\">Не паказваць зноў</string>\n    <string name=\"user_guide\">Інструкцыя для карыстальніка</string>\n    <string name=\"open_settings\">Адчыніць налады</string>\n    <string name=\"check_download_settings_desc\">Зірніце на налады загрузкі і пераканайцеся, што ў вас апошняя версія yt-dlp перад яе выкарыстаннем.</string>\n    <string name=\"download_playlist_desc\">Спампаваць некалькі відэа з плэйліста</string>\n    <string name=\"defaults\">Па змаўчанні</string>\n    <string name=\"execute_command_notification\">Выкананне карыстальніцкай каманды…</string>\n    <string name=\"battery_settings_desc\">Каб спампоўваць у фонавым рэжыме, усталюйце ў сістэмных наладах \\\"Неабмежаваны\\\" расход батарэі для гэтай праграмы.</string>\n    <string name=\"concurrent_download\">Шматструменная загрузка</string>\n    <string name=\"concurrent_download_desc\">Спампоўвайце больш частак відэа M3U8/MPD паралельна</string>\n    <string name=\"convert_audio_format\">Канвертаваць фармат аўдыё</string>\n    <string name=\"subdirectory\">Захаваць у падкаталог</string>\n    <string name=\"concurrent_download_num\">%d патокаў будзе выкарыстана для адначасовай спампоўкі відэа DASH/HLS.</string>\n    <string name=\"options\">Налады</string>\n    <string name=\"additional_settings\">Дадатковыя налады</string>\n    <string name=\"share_fail_msg\">Немагчыма знайсці URL з абагуленага змесціва</string>\n    <string name=\"share_success_msg\">Чытанне спасылкі на відэа з абагуленага змесціва…</string>\n    <string name=\"show_more_actions\">Паказаць больш дзеянняў</string>\n    <string name=\"download_notification\">Апавяшчэнне аб спампоўцы</string>\n    <string name=\"download_notification_desc\">Апавяшчаць аб запампаваных файлах і прагрэсе</string>\n    <string name=\"fetching_playlist_info\">Атрыманне інфармацыі аб плэйлісце…</string>\n    <string name=\"download_range_selection\">Выбар плэйліста</string>\n    <string name=\"download_range_desc\">Укажыце дыяпазон відэа для спампоўкі са спісу прайгравання «%3$s» (ад %1$d да %2$d).</string>\n    <string name=\"from\">Пачаць</string>\n    <string name=\"to\">Закончыць</string>\n    <string name=\"invalid_index_range\">Няправільны дыяпазон індэкса</string>\n    <string name=\"playlist_indicator_text\">Спампоўка плэйліста (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Папка з аўдыё</string>\n    <string name=\"download_directory\">Каталог загрузкі</string>\n    <string name=\"download_directory_desc\">Выберыце, дзе захоўваць відэа і аўдыяфайлы</string>\n    <string name=\"status_enqueued\">У чарзе</string>\n    <string name=\"status_completed\">Завершана</string>\n    <string name=\"status_downloading\">Ідзе загрузка</string>\n    <string name=\"status_canceled\">Адменена</string>\n    <string name=\"status_fetching_video_info\">Атрыманне інфармацыі</string>\n    <string name=\"open_file\">Адкрыць файл</string>\n    <string name=\"restart\">Перазапусціць</string>\n    <string name=\"status_error\">Памылка</string>\n    <string name=\"copy_link\">Скапіяваць спасылку</string>\n    <string name=\"subdirectory_desc\">Захоўвайце файлы ў папках з адпаведнымі назвамі</string>\n    <string name=\"permission_issue\">Каталог не падтрымліваецца</string>\n    <string name=\"battery_configuration_desc\">Ігнаруйце аптымізацыю акумулятара, каб спампоўваць у фоне</string>\n    <string name=\"service_title\">Seal спампоўвае…</string>\n    <string name=\"unknown_error\">Невядомая памылка</string>\n    <string name=\"translate\">Пераклад</string>\n    <string name=\"translate_desc\">Дапамажыце з перакладам на Hosted Weblate</string>\n    <string name=\"prefix\">Шаблон шляху</string>\n    <string name=\"embed_subtitles\">Убудаваць субтытры</string>\n    <string name=\"template_label\">Загаловак</string>\n    <string name=\"remove_template\">Выдаліць\\?</string>\n    <string name=\"remove_template_desc\">Назаўсёды выдаліць \\\"%1$s\\\" з шаблонаў каманд\\?</string>\n    <string name=\"custom_command_template_desc\">Рэдагаванне і кіраванне шаблонамі каманд</string>\n    <string name=\"downloading_indicator_text\">Ідзе спампоўка…</string>\n    <string name=\"task_canceled\">Спампоўка адменена</string>\n    <string name=\"github_issue\">Паведаміць пра праблему (GitHub)</string>\n    <string name=\"github_issue_desc\">Адправіць праблему для справаздачы аб памылцы або запыту функцыі</string>\n    <string name=\"info_copied\">Спасылка скапіявана ў буфер абмену</string>\n    <string name=\"permission_issue_desc\">Дырэкторыі па-за Download/ і Documents/ не падтрымліваюцца</string>\n    <string name=\"battery_configuration\">Канфігурацыя батарэі</string>\n    <string name=\"embed_subtitles_desc\">Убудоўваць у відэафайл прэрэндэрныя субтытры, калі яны даступныя</string>\n    <string name=\"new_template\">Новы шаблон</string>\n    <string name=\"template_selection\">Выбар шаблону</string>\n    <string name=\"high_contrast\">Высокакантрасная цёмная тэма</string>\n    <string name=\"invalid_input\">Няправільны ўвод</string>\n    <string name=\"lowest_quality\">Самая нізкая якасць</string>\n    <string name=\"copy_error_report\">Капіяваць справаздачу</string>\n    <string name=\"video_resolution\">Якасць відэа</string>\n    <string name=\"video_file_size\">Памер відэафайла</string>\n    <string name=\"export_to_clipboard\">Экспарт у буфер абмену</string>\n    <string name=\"import_from_clipboard\">Імпарт з буфера абмену</string>\n    <string name=\"template_exported\">Экспартаваны шаблон(ы) %1$d</string>\n    <string name=\"template_imported\">Імпартаваны шаблон(ы) %1$d</string>\n    <string name=\"download_task_count\">%1$d Загрузачных задач</string>\n    <string name=\"recently_added\">Нядаўна дададзеныя</string>\n    <string name=\"multiselect_item_count\">%1$d відэа(я), %2$d аўдыяфайл(ы)</string>\n    <string name=\"delete_multiple_items_msg\">Выдаліць %1$d элемент(ы) з вашай гісторыі спамповак назаўжды\\?</string>\n    <string name=\"sponsorblock_desc\">Выдаляйце або пазначайце сегменты ў відэа з дапамогай SponsorBlock API</string>\n    <string name=\"sponsorblock_categories_desc\">Укажыце катэгорыі SponsorBlock для выдалення або пазначэння ў відэафайле</string>\n    <string name=\"sponsorblock_categories\">Катэгорыі SponsorBlock</string>\n    <string name=\"check_for_updates\">Праверце наяўнасць абнаўленняў</string>\n    <string name=\"check_for_updates_desc\">Аўтаматычна правяраць апошнюю версію на GitHub</string>\n    <string name=\"app_up_to_date\">Бягучая версія актуальная</string>\n    <string name=\"clear_temp_files\">Ачысціць часовыя файлы</string>\n    <string name=\"clear_temp_files_desc\">Выдаліць усе часовыя файлы з часовага каталога</string>\n    <string name=\"clear_temp_files_count\">Выдалена %1$d часовых файл(ы)</string>\n    <string name=\"multiselect_mode\">Рэжым множнага выбару</string>\n    <string name=\"private_mode\">Інкогніта</string>\n    <string name=\"private_mode_desc\">Адключыць гісторыю загрузак</string>\n    <string name=\"clear_temp_files_info\">Часовыя файлы можна выкарыстоўваць для аднаўлення адмененых загрузак. Вы ўпэўненыя, што жадаеце выдаліць усе гэтыя файлы\\?\n\\n\n\\nВы можаце атрымаць доступ да гэтых файлаў у %1$s</string>\n    <string name=\"dynamic_color\">Дынамічныя колеры</string>\n    <string name=\"dynamic_color_desc\">Ужываць колеры шпалер да тэмы праграмы</string>\n    <string name=\"download_with_cellular\">Загружаць па сотавай сувязі</string>\n    <string name=\"download_with_cellular_desc\">Дазволіць спампоўку мультымедыя пры падключэнні да сетак з лімітам трафіку</string>\n    <string name=\"download_disabled_with_cellular\">Спампоўка праз сотавую сетку адключана ў адпаведнасці з вашымі наладамі</string>\n    <string name=\"file_unavailable\">Гэты файл больш не даступны</string>\n    <string name=\"network\">Сетка</string>\n    <string name=\"rate_limit\">Ліміт хуткасці</string>\n    <string name=\"rate_limit_desc\">Абмежаваць максімальную хуткасць загрузкі</string>\n    <string name=\"max_rate\">Максімальная хуткасць</string>\n    <string name=\"aria2_desc\">Выкарыстоўвайце aria2c у якасці вонкавага загрузчыка</string>\n    <string name=\"cookies_desc\">Для загрузкі выкарыстоўвайце файлы cookie ў фармаце Netscape</string>\n    <string name=\"app_update_failed\">Не ўдалося абнавіць да апошняй версіі</string>\n    <string name=\"update\">Абнавіць</string>\n    <string name=\"video_only\">Відэа (без аўдыя)</string>\n    <string name=\"suggested\">Прапанаваў</string>\n    <string name=\"format_selection_desc\">Перад пачаткам загрузкі абярыце фармат для загрузкі</string>\n    <string name=\"abs_hint\">Большасць платформаў струменевага відэа перадаюць аўдыя і відэа асобна, вы можаце выбраць і аб\\'яднаць фармат толькі аўдыя з фарматам толькі відэа ў адно відэа.</string>\n    <string name=\"video_creator_sample_text\">Прыклад аўтара відэа</string>\n    <string name=\"subtitle_desc\">Мовы, убудаваныя субтытры, аўтаматычныя субтытры</string>\n    <string name=\"format_selection\">Выбар фармату</string>\n    <string name=\"remove_cookie_profile_desc\">Выдаліць гэты запіс для \\\"%1$s\\\"? Звярніце ўвагу, што файлы cookie, захаваныя для гэтага сайта, не будуць выдалены.</string>\n    <string name=\"subtitle_language\">Мовы субтытраў</string>\n    <string name=\"selected_item_count\">%1$d выбрана</string>\n    <string name=\"private_directory\">Прыватны каталог</string>\n    <string name=\"unavailable\">Недаступны</string>\n    <string name=\"general_settings_desc\">Версія yt-dlp, апавяшчэнне, плэйліст</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"disable_preview\">Адключыць папярэдні прагляд</string>\n    <string name=\"disable_preview_desc\">Не адлюстроўваюцца мініяцюры падчас загрузкі</string>\n    <string name=\"private_directory_desc\">Захоўвайце загрузкі ў схаваным каталогу</string>\n    <string name=\"privacy\">Прыватнасць</string>\n    <string name=\"telegram_channel\">Telegram канал</string>\n    <string name=\"matrix_space\">Матрычная прастора</string>\n    <string name=\"network_settings_desc\">Абмежаванне хуткасці, загрузнік, файлы cookie</string>\n    <string name=\"use_custom_command\">Выкарыстоўвайце карыстальніцкую каманду</string>\n    <string name=\"crop_artwork\">Абрэзаць мастацкі твор</string>\n    <string name=\"crop_artwork_desc\">Абрэзаць убудаваны відарыс у квадрат</string>\n    <string name=\"format_settings_desc\">Фармат файла, якасць відэа, субтытры</string>\n    <string name=\"download_selection_desc\">Выберыце відэа для спампоўкі са плэйліста \\\"%1$s\\\"</string>\n    <string name=\"select_all\">Абраць усё</string>\n    <string name=\"generate_new_cookies\">Стварыце новыя файлы cookie</string>\n    <string name=\"use_cookies\">Выкарыстоўвайце файлы cookie</string>\n    <string name=\"custom_command_enabled_hint\">Некаторыя параметры недаступныя пры выкарыстанні карыстальніцкай каманды</string>\n    <string name=\"how_does_it_work\">Як гэта працуе\\?</string>\n    <string name=\"cookies_usage_msg\">Спампоўка з некаторых сайтаў патрабуе аўтэнтыфікацыі ўліковага запісу. Націсніце «Стварыць новыя файлы cookie», увядзіце URL вэб-сайта, а затым увайдзіце пад сваім уліковым запісам на старонцы браўзера, праграма згенеруе яго для вас.</string>\n    <string name=\"sdcard_directory\">Тэчка SD карты</string>\n    <string name=\"auto_subtitle\">Аўтаматычныя субтытры</string>\n    <string name=\"auto_subtitle_desc\">Спампаваць аўтаматычна створаныя субтытры</string>\n    <string name=\"title_activity_share\">Хуткая загрузка</string>\n    <string name=\"video_title_sample_text\">Прыклад назвы відэа</string>\n    <string name=\"subtitle\">Падзагаловак</string>\n    <string name=\"download_subtitles\">Спампаваць субтытры</string>\n    <string name=\"audio_format_preference\">Пераважны аўдыяфармат</string>\n    <string name=\"audio_quality\">Якасць гуку</string>\n    <string name=\"format_sorting\">Сартаванне па фармаце</string>\n    <string name=\"unlimited\">Неабмежаваны</string>\n    <string name=\"second\">другі</string>\n    <string name=\"rename\">Перайменаваць</string>\n    <string name=\"minute\">хвіліна</string>\n    <string name=\"audio_format\">Фармат аўдыё</string>\n    <string name=\"no_downloaded_media\">Няма спампаваных мультымедыя</string>\n    <string name=\"beta_features\">Бэта-версія</string>\n    <string name=\"enable_experimental_feature\">Уключыць эксперыментальную функцыю\\?</string>\n    <string name=\"clip_video_desc\">Зрабіце відэакліпы на старонцы выбару фармату</string>\n    <string name=\"filesize_mb\">%.2f МБ</string>\n    <string name=\"filesize_gb\">%.2f ГБ</string>\n    <string name=\"subtitle_sponsorblock\">Пры выдаленні сегментаў SponsorBlock субтытры могуць быць няправільнымі.</string>\n    <string name=\"enable_auto_update\">Уключыць аўтаматычнае абнаўленне</string>\n    <string name=\"share\">Падзяліцца</string>\n    <string name=\"stable_channel\">Стабільны</string>\n    <string name=\"pre_release_channel\">Папярэдні</string>\n    <string name=\"update_channel_desc\">Усталюйце папярэднія зборкі, каб праглядзець новыя функцыі і змены.\n\\n\n\\nУ гэтых версіях будзе назірацца некаторая нестабільнасць, таму, калі ласка, не саромейцеся дасылаць нам водгукі, калі ў вас узнікнуць праблемы, каб дапамагчы нам палепшыць прыкладанне ў будучыні.</string>\n    <string name=\"update_channel\">Абнавіць канал</string>\n    <string name=\"auto_update\">Аўтаматычнае абнаўленне</string>\n    <string name=\"logs\">Журнал</string>\n    <string name=\"auto_update_disabled_msg\">Аўтаматычнае абнаўленне недаступна для зборак %1$s. Калі ў вас на прыладзе не ўсталявана %1$s, або вы хочаце папярэдне прагледзець будучыя новыя функцыі ў Seal, звярніце ўвагу на %2$s.</string>\n    <string name=\"switch_to_github_builds\">пераход на зборкі GitHub</string>\n    <string name=\"okay\">ОК</string>\n    <string name=\"got_it\">Зразумела</string>\n    <string name=\"feature_unavailable\">Функцыя недаступная</string>\n    <string name=\"discard\">Адкідаць</string>\n    <string name=\"clip_end\">Канец</string>\n    <string name=\"clip_start\">Пачатак</string>\n    <string name=\"apply\">Ужыць</string>\n    <string name=\"clip_video\">Кліп відэа</string>\n    <string name=\"lowest_bitrate\">Самы нізкі бітрэйт</string>\n    <string name=\"clear_all_cookies\">Ачысціць усе файлы cookie</string>\n    <string name=\"clip_video_dialog_msg\">Спампоўкі з выкарыстаннем гэтай функцыі будуць дэлегаваны FFmpeg для загрузкі выбраных раздзелаў відэа, гэтая функцыя ўсё яшчэ эксперыментальная, і выразанне не будзе цалкам дакладным, не ўсе фарматы падтрымліваюць гэту функцыю, і хуткасць спампоўкі можа знізіцца.</string>\n    <string name=\"copy_log\">Скапіраваць журнал</string>\n    <string name=\"edit_shortcuts_desc\">Адрэдагуйце карыстальніцкія цэтлікі, якія можна выкарыстоўваць для стварэння шаблонаў каманд.</string>\n    <string name=\"running_tasks\">Запуск задач</string>\n    <string name=\"show_logs\">Паказаць журнал</string>\n    <string name=\"clear\">Ачысціць</string>\n    <string name=\"add\">Дадаць</string>\n    <string name=\"shortcuts\">Цэтлікі</string>\n    <string name=\"edit_shortcuts\">Рэдагаваць цэтлікі</string>\n    <string name=\"embed_subtitles_mkv_msg\">Каб убудаваць субтытры, відэа будуць рэмуксаваныя ў кантэйнер mkv. Вы можаце выкарыстоўваць VLC Media Player або іншыя сумяшчальныя праграмы для прагляду відэа з убудаванымі субтытрамі.</string>\n    <string name=\"audio_quality_desc\">Абмяжуйце бітрэйт аўдыя, калі прысутнічае некалькі якасцей</string>\n    <string name=\"format_sorting_desc\">Сартаванне фарматаў з дапамогай опцыі -S у yt-dlp</string>\n    <string name=\"import_from_preferences\">Імпарт</string>\n    <string name=\"title\">Назва</string>\n    <string name=\"clear_all_cookies_desc\">Назаўсёды выдаліць усе файлы cookie, якія захоўваюцца ў праграме\\?</string>\n    <string name=\"sponsor\">Спонсар</string>\n    <string name=\"sponsor_desc\">Падтрымайце гэтую праграму, спансіруючы яго на GitHub</string>\n    <string name=\"sponsor_msg\">Seal заўсёды будзе бясплатным і адкрытым для ўсіх. Калі вам гэта падабаецца, калі ласка, падумайце аб тым, каб стаць спонсарам мяне на GitHub!</string>\n    <string name=\"feedback\">Зваротная сувязь</string>\n    <string name=\"sponsors\">Спонсары</string>\n    <string name=\"temporary_directory_desc\">Захоўвайце часовыя файлы ва ўнутраным каталогу</string>\n    <string name=\"no_custom_command_tasks\">Няма карыстацкіх камандных задач</string>\n    <string name=\"msg_from_developer\">Паведамленне ад распрацоўніка</string>\n    <string name=\"sponsor_msg2\">Вялікі дзякуй!</string>\n    <string name=\"download_video_desc\">Спампаваць відэа з URL-адрасу</string>\n    <string name=\"convert_subtitle\">Канвертаваць субтытры</string>\n    <string name=\"convert_subtitle_desc\">Канвертаваць субтытры ў іншы фармат</string>\n    <string name=\"copy_and_exit\">Капіяваць і выйсці</string>\n    <string name=\"split_video\">Раздзяліць відэа</string>\n    <string name=\"split_video_msg\">Відэа будзе падзелена на %1$d раздзелаў</string>\n    <string name=\"unknown_error_title\">Ой! Нешта пайшло не так</string>\n    <string name=\"expand\">Разгарнуць</string>\n    <string name=\"new_task\">Новая задача загрузкі</string>\n    <string name=\"start\">Пачаць</string>\n    <string name=\"edit_template\">Рэдагаваць \\\"%1$s\\\"</string>\n    <string name=\"proxy\">Проксі</string>\n    <string name=\"proxy_desc\">Падключыцеся праз проксі</string>\n    <string name=\"set_directory_desc\">Націсніце, каб наладзіць каталог</string>\n    <string name=\"custom_command_directory_desc\">Укажыце выходны каталог пры выкарыстанні карыстальніцкіх каманд</string>\n    <string name=\"prefer_quality_desc\">Выберыце AV1, VP9 або H.265 для прагляду ў сумяшчальных праграмах</string>\n    <string name=\"custom\">Свая</string>\n    <string name=\"auto\">Аўто</string>\n    <string name=\"commands\">Каманды</string>\n    <string name=\"unknown\">Невядомы</string>\n    <string name=\"download_type\">Тып загрузкі</string>\n    <string name=\"format_preference\">Налады фармату</string>\n    <string name=\"learn_more\">Даведайцеся больш</string>\n    <string name=\"refresh_cookies_desc\">Націсніце, каб адкрыць вэб-старонку для стварэння новых файлаў cookie:</string>\n    <string name=\"ytdlp_update_action\">Абнавіць yt-dlp</string>\n    <string name=\"enable_notifications\">Уключыць апавяшчэнні\\?</string>\n    <string name=\"enable_notifications_desc\">Праграме патрабуецца ваш дазвол, каб публікаваць апавяшчэнні аб стане і прагрэсе загрузкі.</string>\n    <string name=\"disable\">Адключыць</string>\n    <string name=\"legacy\">Устарэлы</string>\n    <string name=\"quality\">Якасць</string>\n    <string name=\"custom_command_directory\">Каталог карыстацкіх каманд</string>\n    <string name=\"disabled\">Выключана</string>\n    <string name=\"folder_picker\">Выбар тэчак</string>\n    <string name=\"prefer_compatibility_desc\">Выберыце MP4 (H.264) для абмену ў іншых праграмах</string>\n    <string name=\"remove_multiple_templates_msg\">Выдаліць %1$s з камандных шаблонаў назаўжды\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d элемент</item>\n        <item quantity=\"few\">%d элементы</item>\n        <item quantity=\"many\">%d элементаў</item>\n        <item quantity=\"other\">%d элементаў</item>\n    </plurals>\n    <string name=\"ua_header\">Загаловак User-Agent</string>\n    <string name=\"export_to_file\">Экспарт у файл</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp - гэта магутны інструмент каманднага радка для спампоўкі відэа. Seal палягчае выкарыстанне yt-dlp, забяспечваючы інтуітыўна зразумелы графічны інтэрфейс, прадусталяваныя налады для агульных каманд і іншыя дадатковыя функцыі.\n\\n\n\\nДля прасунутага выкарыстання yt-dlp Seal дазваляе ствараць, захоўваць і выконваць карыстальніцкія шаблоны каманд непасрэдна, як у тэрмінале.\n\\n\n\\nПры выкарыстанні карыстальніцкіх каманд большасць опцый і функцый графічнага інтэрфейсу будуць адключаны.</string>\n    <string name=\"presets\">Прасэты</string>\n    <string name=\"output_template\">Вывад шаблону</string>\n    <string name=\"output_template_desc\">Укажыце шаблон для імёнаў выходных файлаў</string>\n    <string name=\"clear_download_archive\">Ачысціць архіў загрузак\\?</string>\n    <string name=\"clear_download_archive_desc\">Выдаліць %1$s з архіўнага файла назаўжды\\?</string>\n    <string name=\"download_archive_desc\">Запісваць ID загружаных відэа ў архіў, каб пазбегнуць дублікатаў</string>\n    <string name=\"download_archive\">Архіў загрузак</string>\n    <string name=\"embed_metadata\">Убудаваць метаданыя</string>\n    <string name=\"required\">Абавязковы</string>\n    <string name=\"embed_metadata_desc\">Устаўце метаданыя і мініяцюру відэа ў аўдыяфайл</string>\n    <string name=\"show_all_items\">Паказаць усе элементы (%1$d)</string>\n    <string name=\"save\">Захаваць</string>\n    <string name=\"use_format_sorting\">Выкарыстоўвайце сартаванне па фармаце</string>\n    <string name=\"restrict_filenames_desc\">Абмяжуйць імёны файлаў пэўнымі сімваламі, каб забяспечыць сумяшчальнасць</string>\n    <string name=\"restrict_filenames\">Абмежаваць імёны файлаў</string>\n    <string name=\"edit_file\">Рэдагаваць файл</string>\n    <string name=\"subdirectory_hint\">Вашы спампоўкі будуць захаваны як:</string>\n    <string name=\"website\">Вэб-сайт</string>\n    <string name=\"system_settings\">Налады сістэмы</string>\n    <string name=\"playlist_title\">Назва плэйліста</string>\n    <string name=\"force_ipv4\">Прымусова выкарыстоўваць IPv4</string>\n    <string name=\"force_ipv4_desc\">Выконваць усе падключэнні праз IPv4</string>\n    <string name=\"keep_subtitle_files\">Захаваць файлы субтытраў</string>\n    <string name=\"allow_once\">Дазволіць адзін раз</string>\n    <string name=\"allow_always\">Дазваляць заўсёды</string>\n    <string name=\"dont_allow\">Не дазваляць</string>\n    <string name=\"download_with_cellular_request\">Дазволіць спампоўку праз мабільную перадачу даных?</string>\n    <string name=\"merge_audiostream\">Аб\\'яднаць некалькі аўдыёпатокаў</string>\n    <string name=\"merge_audiostream_desc\">Дазволіць аб\\'ядноўваць некалькі аўдыяпатокаў у адзін файл</string>\n    <string name=\"search_in_downloads\">Пошук у загрузках</string>\n    <string name=\"search\">Пошук</string>\n    <string name=\"auto_translated_subtitles\">Субтытры з аўтаперакладам</string>\n    <string name=\"auto_translated_subtitles_msg\">У загрузках можна будзе абраць субтытры, створаныя аўтаматычна для кожнай мовы. Яны могуць быць недакладнымі і цяжкімі для разумення.</string>\n    <string name=\"subtitle_language_desc\">Мова субтытраў для загрузкі ў аўтаматычным выбары фармату, падзеленыя коскамі.</string>\n    <string name=\"remember_for_next_download\">Запомніць для будучай загрузкі</string>\n    <string name=\"look_and_feel\">Афармленне</string>\n    <string name=\"search_in_subtitles\">Пошук ў субтытрах</string>\n    <string name=\"interface_and_interaction\">Інтэрфейс і ўзаемадзеянне</string>\n    <string name=\"use_previous_selection\">Выкарыстаць папярэдні выбар</string>\n    <string name=\"no_thanks\">Не, дзякуй</string>\n    <string name=\"reset\">Скід</string>\n    <string name=\"download_queue\">Чарга загрузкі</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">адзін</item>\n        <item quantity=\"few\">некалькі</item>\n        <item quantity=\"many\">шмат</item>\n        <item quantity=\"other\">шмат</item>\n    </plurals>\n    <string name=\"download_hint\">Каб пачаць спампоўку, дакраніцеся да кнопкі спампоўкі або падзяліцеся спасылкай на відэа з гэтай праграмай</string>\n    <string name=\"all\">Усе</string>\n    <string name=\"select_multiple_link\">Выберыце з %1$d спасылак</string>\n    <string name=\"issue_tracker\">Адсочванне праблем</string>\n    <string name=\"issue_tracker_hint\">\"Сутыкнуліся з памылкай?  Перш чым паведаміць аб новай праблеме, пашукайце ў нашым трэкеры праблем.  Там ужо разгледжаны і задакументаваны многія агульныя праблемы.\"</string>\n    <string name=\"show_navigation_drawer\">Паказаць панэль навігацыі</string>\n    <string name=\"resume\">Рэзюмэ</string>\n    <string name=\"delete\">Выдаліць</string>\n    <string name=\"media_info\">Інфармацыя пра СМІ</string>\n    <string name=\"trouble_shooting\">Ліквідацыю непаладак</string>\n    <string name=\"trouble_shooting_desc\">Выпраўце распаўсюджаныя памылкі і праверце вядомыя праблемы</string>\n    <string name=\"status_downloaded\">Спампавана</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-bn/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">ভিডিও ফোল্ডার</string>\n    <string name=\"extract_audio\">অডিও আকারে সেভ করুন</string>\n    <string name=\"create_thumbnail\">থাম্বনেইল সেভ করুন</string>\n    <string name=\"settings\">সেটিংস</string>\n    <string name=\"download_settings_desc\">জেনারেল, ফরম্যাট, কাস্টম কমান্ড</string>\n    <string name=\"download\">ডাউনলোড</string>\n    <string name=\"url_empty\">লিংক ফাঁকা রাখা যাবে না</string>\n    <string name=\"extract_audio_summary\">ভিডিওর বদলে অডিও ডাউনলোড ও সেভ করুন</string>\n    <string name=\"create_thumbnail_summary\">ভিডিওর থাম্বনেইল ফাইল আকারে সেভ করুন</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp এর লেটেস্ট ভার্সন ব্যবহার করা হচ্ছে</string>\n    <string name=\"fetching_info\">ভিডিও ইনফো আনা হচ্ছে…</string>\n    <string name=\"permission_denied\">পারমিশন পাওয়া যায় নি</string>\n    <string name=\"download_success_msg\">ডাউনলোড শেষ হয়েছে</string>\n    <string name=\"download_error_msg\">ফাইল ডাউনলোড করা যায় নি</string>\n    <string name=\"fetch_info_error_msg\">ভিডিওর ইনফো আনা যায় নি</string>\n    <string name=\"general_settings\">জেনারেল</string>\n    <string name=\"language\">ভাষা</string>\n    <string name=\"task_running\">একটা ডাউনলোড চলছে</string>\n    <string name=\"paste_msg\">ক্লিপবোর্ড থেকে URL পেস্ট করুন</string>\n    <string name=\"confirm\">কনফার্ম</string>\n    <string name=\"dismiss\">বাতিল</string>\n    <string name=\"downloads_history\">ডাউনলোডেড</string>\n    <string name=\"audio\">অডিও</string>\n    <string name=\"link_copied\">লিংক ক্লিপবোর্ডে কপি করা হয়েছে</string>\n    <string name=\"open_url\">লিংক ওপেন করুন</string>\n    <string name=\"remove\">সরান</string>\n    <string name=\"delete_file\">ডিলিট ফাইল</string>\n    <string name=\"about\">সম্পর্কে</string>\n    <string name=\"about_page\">ভার্সন, ফিডব্যাক, অটোমেটিক আপডেট</string>\n    <string name=\"back\">পেছনে যান</string>\n    <string name=\"version\">ভার্সন</string>\n    <string name=\"edit\">এডিট</string>\n    <string name=\"yt_dlp_update_fail\">yt-dlp\\ এর লেটেস্ট ভার্সন ইন্সটল করা যাচ্ছে না। অনুগ্রহ করে ইন্টারনেট কানেকশন চেক করুন।</string>\n    <string name=\"delete_info_msg\">\\\"%1$s\\\" ডাউনলোড হিস্ট্রি থেকে মুছে ফেলবেন\\?</string>\n    <string name=\"print_details\">বিস্তারিত ইনফো</string>\n    <string name=\"release_desc\">নতুন ভার্সন এবং চেঞ্জলগ দেখুন</string>\n    <string name=\"custom_command\">কাস্টম কমান্ড</string>\n    <string name=\"checked\">চেক করা হয়েছে</string>\n    <string name=\"settings_before_download_text\">এই ডাউনলোডটির জন্য কনফিগার করুন</string>\n    <string name=\"settings_before_download\">ডাউনলোড করার আগে কনফিগার করুন</string>\n    <string name=\"settings_before_download_desc\">ডাউনলোড করার আগে প্রেফারেন্স সেট করুন</string>\n    <string name=\"readme_desc\">GitHub রিপোজিটরি এবং README চেক করুন</string>\n    <string name=\"credits\">ক্রেডিটস</string>\n    <string name=\"credits_desc\">ক্রেডিট এবং libre সফ্টওয়্যার</string>\n    <string name=\"custom_command_desc\">কাস্টম টেমপ্লেট সহ yt-dlp কমান্ড চালান</string>\n    <string name=\"custom_command_template\">কমান্ড টেমপ্লেট</string>\n    <string name=\"advanced_settings\">অ্যাডভান্স</string>\n    <string name=\"display_settings\">ডার্ক থিম, ডাইনামিক কালার, ভাষা</string>\n    <string name=\"error_copied\">ইরর রিপোর্ট ক্লিপবোর্ডে কপি করা হয়েছে</string>\n    <string name=\"thumbnail\">থাম্বনেইল</string>\n    <string name=\"paste\">পেস্ট করুন</string>\n    <string name=\"release\">লেটেস্ট রিলিজ</string>\n    <string name=\"ytdlp_update\">yt-dlp এর লেটেস্ট রিলিজের জন্য ক্লিক করুন</string>\n    <string name=\"video\">ভিডিও</string>\n    <string name=\"start_execute\">কমান্ড রান করুন</string>\n    <string name=\"print_details_desc\">বিস্তারিত ইনফো দেখুন যখন ডাউনলোড হবে</string>\n    <string name=\"language_settings\">ডিসপ্লের ভাষা সিলেক্ট করুন</string>\n    <string name=\"delete_info\">ডিলিট?</string>\n    <string name=\"ytdlp_update_action\">yt-dlp আপডেট করুন</string>\n    <string name=\"convert_audio_format\">অডিও ফরম্যাটে কনভার্ট করুন</string>\n    <string name=\"convert_audio\">কনভার্ট</string>\n    <string name=\"video_format\">ভিডিও ফরম্যাট</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp ব্যবহারের রেফারেন্স</string>\n    <string name=\"start_download\">ডাউনলোড</string>\n    <string name=\"best_quality\">বেস্ট কোয়ালিটি</string>\n    <string name=\"ytdlp_version\">Yt-dlp ভার্সন</string>\n    <string name=\"not_convert\">কনভার্ট করা হয়নি</string>\n    <string name=\"close\">বন্ধ করুন</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" ডাউনলোড করুন</string>\n    <string name=\"display\">ডিসপ্লে</string>\n    <string name=\"cancel\">বাতিল করুন</string>\n    <string name=\"edit_template_desc\">আউটপুট পাথ এবং URL অ্যাপ সিলেক্ট করে নিবে।</string>\n    <string name=\"video_quality\">ভিডিও কোয়ালিটি</string>\n    <string name=\"paste_desc\">ক্লিপবোর্ড থেকে ভিডিও লিংক নেবার জন্য পেস্ট ক্লিক করুন</string>\n    <string name=\"paste_fail_msg\">আপনার ক্লিপবোর্ডের সাথে URL এর মিল পাওয়া যাচ্ছে না</string>\n    <string name=\"dark_theme\">ডার্ক থিম</string>\n    <string name=\"follow_system\">সিস্টেম</string>\n    <string name=\"on\">অন</string>\n    <string name=\"off\">অফ</string>\n    <string name=\"convert_to\">কনভার্ট %1$s</string>\n    <string name=\"not_specified\">নির্দিষ্ট করা নেই (ডিফল্ট)</string>\n    <string name=\"video_format_preference\">পছন্দের ভিডিও ফরম্যাট</string>\n    <string name=\"close_never_show_again\">আবার দেখবো না</string>\n    <string name=\"open_settings\">ওপেন সেটিংস</string>\n    <string name=\"format\">ফরম্যাট</string>\n    <string name=\"convert_audio_format_desc\">অডিও ফাইল আবার এনকোড করলে অডিও কোয়ালিটি নষ্ট হবে আর ফাইল সাইজ বাড়বে।</string>\n    <string name=\"user_guide\">ইউজার গাইড</string>\n    <string name=\"video_quality_desc\">একাধিক ডাউনলোড থাকলে ভিডিওর কোয়ালিটি সেট করুন</string>\n    <string name=\"preferred_format_desc\">প্রেফারেড ফরম্যাট যখন একাধিক ডাউনলোড থাকবে</string>\n    <string name=\"check_download_settings_desc\">ব্যাবহার করার আগে ডাউনলোড সেটিংস দেখুন এবং নিশ্চিত করুন yt-dlp লেটেস্ট ভার্সনে আছে কি না।</string>\n    <string name=\"download_history_desc\">ভিডিও এবং অডিও ফাইল সহ অ্যাপ-মধ্যস্থ ডাউনলোডগুলি দেখুন এবং পরিচালনা করুন।</string>\n    <string name=\"download_desc\">এরপর সেটিংস ঠিক করে ডাউনলোড এ ক্লিক করুন।</string>\n    <string name=\"download_playlist_desc\">প্লেলিস্ট থেকে একাধিক ভিডিও ডাউনলোড করুন</string>\n    <string name=\"defaults\">ডিফল্টস</string>\n    <string name=\"channel_name\">ডাউনলোড</string>\n    <string name=\"download_playlist\">প্লে-লিস্ট ডাউনলোড করুন</string>\n    <string name=\"refresh_cookies_desc\">নতুন কুকির জন্য ওয়েবপেজ খুলতে ট্যাপ করুন:</string>\n    <string name=\"edit_file\">ফাইল এডিট করুন</string>\n    <string name=\"playlist_indicator_text\">প্লেলিস্ট ডাউনলোড করা হচ্ছে (%1$d/%2$d)…</string>\n    <string name=\"subtitle_sponsorblock\">স্পন্সরব্লক দিয়ে সেগমেন্টগুলি সরানোর সময় সাবটাইটেলগুলি এলোমেলো হতে পারে।</string>\n    <string name=\"pre_release_channel\">প্রি রিলিজ</string>\n    <string name=\"permission_issue_desc\">ডাউনলোড/ এবং ডকুমেন্টস/ এর বাইরের ডিরেক্টরিগুলি সাপোর্টেড নয়</string>\n    <string name=\"battery_configuration_desc\">ব্যাকগ্রাউন্ডে ডাউনলোডের জন্য এই অ্যাপটির ব্যাটারি অপ্টিমাইজেশন বন্ধ করুন</string>\n    <string name=\"service_title\">সিল ডাউনলোড হচ্ছে…</string>\n    <string name=\"github_issue\">GitHub ইস্যু</string>\n    <string name=\"unknown_error\">আননোন ইরর</string>\n    <string name=\"prefix\">উপসর্গ</string>\n    <string name=\"task_canceled\">ডাউনলোড টাস্ক বাতিল করা হয়েছে</string>\n    <string name=\"info_copied\">ক্লিপবোর্ডে ইনফো কপি করা হয়েছে</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API এর মাধ্যমে ভিডিওতে সেগমেন্টগুলি সরান বা চিহ্নিত করুন</string>\n    <string name=\"update\">আপডেট</string>\n    <string name=\"sponsorblock_categories\">স্পনসর ব্লক ক্যাটাগরি</string>\n    <string name=\"running_tasks\">রানিং টাস্ক</string>\n    <string name=\"clear\">ক্লিয়ার</string>\n    <string name=\"second\">দ্বিতীয়</string>\n    <string name=\"clear_all_cookies_desc\">অ্যাপে সেভ সব কুকি মুছে ফেলবেন?</string>\n    <string name=\"temporary_directory_desc\">টেম্পোরারি ডিরেক্টরিতে ফাইল সেভ করুন</string>\n    <string name=\"sponsor\">স্পন্সর</string>\n    <string name=\"feedback\">ফিডব্যাক</string>\n    <string name=\"sponsor_desc\">GitHub-এ স্পনসর করে এই অ্যাপটিকে সাপোর্ট করুন</string>\n    <string name=\"sponsors\">স্পনসর</string>\n    <string name=\"proxy_desc\">ইন্টারনেট কানেকশনের জন্য প্রক্সি ব্যবহার করুন</string>\n    <string name=\"proxy\">প্রক্সি</string>\n    <string name=\"legacy\">লেগাসি</string>\n    <string name=\"disable\">ডিসেবেল করুন</string>\n    <string name=\"enable_notifications_desc\">ডাউনলোড স্ট্যাটাস এবং প্রোগগ্রেস পোস্ট করার জন্য পারমিশন প্রয়োজন</string>\n    <string name=\"set_directory_desc\">ডিরেক্টরি সেট আপ করতে ট্যাপ করুন</string>\n    <string name=\"folder_picker\">ফোল্ডার পিকার</string>\n    <string name=\"msg_from_developer\">ডেভলপার এর বার্তা</string>\n    <string name=\"allow_always\">সবসময়ের জন্য পারমিশন দিন</string>\n    <string name=\"dont_allow\">পারমিশন দেবেন না</string>\n    <string name=\"download_with_cellular_request\">সেলুলার দিয়ে ডাউনলোড করার পারমিশন দিবেন?</string>\n    <string name=\"merge_audiostream\">একাধিক অডিও স্ট্রিম মার্জ করুন</string>\n    <string name=\"merge_audiostream_desc\">একাধিক অডিও স্ট্রিমকে একটি ফাইলে মার্জ করার পারমিশন দিন</string>\n    <string name=\"subdirectory_hint\">আপনার ডাউনলোডগুলি এইভাবে সেভ করা হবে:</string>\n    <string name=\"okay\">ঠিক আছে</string>\n    <string name=\"got_it\">বুঝেছি</string>\n    <string name=\"open_file\">ফাইল খুলুন</string>\n    <string name=\"status_downloading\">ডাউনলোড হচ্ছে</string>\n    <string name=\"template_exported\">%1$d টেমপ্লেট(গুলি) এক্সপোর্ট করা হয়েছে</string>\n    <string name=\"recently_added\">রিসেন্টলি অ্যাডেড</string>\n    <string name=\"multiselect_item_count\">%1$d টি ভিডিও, %2$d টি অডিও ফাইল</string>\n    <string name=\"app_up_to_date\">বর্তমান ভার্সন আপ টু ডেট</string>\n    <string name=\"cookies\">কুকিজ</string>\n    <string name=\"clear_temp_files\">টেম্পোরারি ফাইল ক্লিয়ার করুন</string>\n    <string name=\"clear_temp_files_desc\">টেম্পোরারি ডিরেক্টরি থেকে সব টেম্পোরারি ডিলিট করুন</string>\n    <string name=\"clear_temp_files_count\">%1$d টি টেম্পোরারি ফাইল ডিলিট হয়েছে</string>\n    <string name=\"multiselect_mode\">মাল্টি সিলেক্ট মোড</string>\n    <string name=\"max_rate\">সর্বোচ্চ স্পিড</string>\n    <string name=\"high_contrast\">হাই কনট্রাস্ট ডার্ক থিম</string>\n    <string name=\"invalid_input\">ইনভ্যালিড ইনপুট</string>\n    <string name=\"unavailable\">আনএভেলেবেল</string>\n    <string name=\"format_settings_desc\">ফাইল ফরম্যাট, ভিডিও কোয়ালিটি, সাবটাইটেল</string>\n    <string name=\"auto_subtitle_desc\">অটো-ট্রান্সলেটেড ক্যাপশন ডাউনলোড করুন</string>\n    <string name=\"sdcard_directory\">এসডি কার্ড ফোল্ডার</string>\n    <string name=\"auto_subtitle\">অটো-ট্রান্সলেটেড ক্যাপশন</string>\n    <string name=\"edit_shortcuts\">শর্টকাট এডিট করুন</string>\n    <string name=\"logs\">লগ</string>\n    <string name=\"show_logs\">লগ দেখুন</string>\n    <string name=\"share\">শেয়ার করুন</string>\n    <string name=\"stable_channel\">স্টেবল</string>\n    <string name=\"format_sorting\">ফরম্যাট সর্টিং</string>\n    <string name=\"audio_quality_desc\">একাধিক কোয়ালিটি থাকলে অডিও বিটরেট সিলেক্ট করুন</string>\n    <string name=\"minute\">মিনিট</string>\n    <string name=\"clear_all_cookies\">সব কুকিজ ক্লিয়ার করুন</string>\n    <string name=\"enable_experimental_feature\">এক্সপেরিমেন্টাল ফিচার চালু করবেন?</string>\n    <string name=\"no_downloaded_media\">কোনো মিডিয়া ডাউনলোড করা নেই</string>\n    <string name=\"auto_update_disabled_msg\">%1$s বিল্ডগুলির জন্য অটো আপডেট প্রযোজ্য নয়৷ যদি আপনার ডিভাইসে %1$s ইনস্টলড না থাকে, বা সিলের নতুন ফিচার দেখতে চান, অনুগ্রহ করে %2$s বিবেচনা করুন</string>\n    <string name=\"convert_subtitle\">সাবটাইটেল কনভার্ট করুন</string>\n    <string name=\"no_custom_command_tasks\">কোন কাস্টম কমান্ড নেই</string>\n    <string name=\"unknown_error_title\">উফ! কনো ভুল হয়েছে</string>\n    <string name=\"split_video_msg\">ভিডিওটি %1$d টি পার্টে ভাগ করা হবে</string>\n    <string name=\"copy_and_exit\">কপি করে বের হন</string>\n    <string name=\"expand\">এক্সপ্যান্ড করুন</string>\n    <string name=\"new_task\">নতুন ডাউনলোড টাস্ক</string>\n    <string name=\"ua_header\">ইউজার-এজেন্ট হেডার</string>\n    <string name=\"discard\">বাতিল হয়া</string>\n    <string name=\"clip_start\">শুরু</string>\n    <string name=\"clip_end\">শেষ</string>\n    <string name=\"keep_subtitle_files\">সাবটাইটেল ফাইল রাখুন</string>\n    <string name=\"dynamic_color\">ডাইনামিক কালার</string>\n    <string name=\"download_task_count\">%1$d টাস্ক ডাউনলোড করুন</string>\n    <string name=\"rate_limit_desc\">ডাউনলোডের জন্য সর্বোচ্চ স্পিড সিলেক্টে করুন</string>\n    <string name=\"network_settings_desc\">রেট লিমিট, ডাউনলোডার, কুকিজ</string>\n    <string name=\"selected_item_count\">%1$d সিলেক্ট করা হয়েছে</string>\n    <string name=\"custom_command_enabled_hint\">কাস্টম কমান্ড ব্যবহার করার সময় কিছু অপশন বন্ধ থাকবে</string>\n    <string name=\"network\">ইন্টারনেট</string>\n    <string name=\"rate_limit\">স্পিড লিমিট</string>\n    <string name=\"subtitle_language\">সাবটাইটেলের ভাষা</string>\n    <string name=\"subtitle_desc\">ভাষা, এম্বেড সাবটাইটেল, অটো ক্যাপশন</string>\n    <string name=\"video_creator_sample_text\">ভিডিও ক্রিয়েটরের স্যাম্পল টেক্সট</string>\n    <string name=\"download_subtitles\">সাবটাইটেল ডাউনলোড করুন</string>\n    <string name=\"update_channel\">চ্যানেল আপডেট করুন</string>\n    <string name=\"start\">শুরু করুন</string>\n    <string name=\"edit_template\">\\\"%1$s\\\" এডিট করুন</string>\n    <string name=\"split_video\">স্প্লিট ভিডিও</string>\n    <string name=\"auto\">অটো</string>\n    <string name=\"commands\">কমান্ড</string>\n    <string name=\"unknown\">আননোন</string>\n    <string name=\"format_selection_desc\">ডাউনলোড শুরু করার আগে ফরম্যাট সিলেক্ট করুন</string>\n    <string name=\"privacy\">গোপনীয়তা</string>\n    <string name=\"audio_directory\">অডিও ফোল্ডার</string>\n    <string name=\"export_to_clipboard\">ক্লিপবোর্ডে এক্সপোর্ট করুন</string>\n    <string name=\"subdirectory\">সাবডিরেক্টরিতে সেভ করুন</string>\n    <string name=\"embed_subtitles\">সাবটাইটেল এম্বেড করুন</string>\n    <string name=\"use_cookies\">কুকিজ ব্যবহার করুন</string>\n    <string name=\"embed_subtitles_desc\">ভিডিওতে সাবটাইটেল এম্বেড করুন (যদি থাকে)</string>\n    <string name=\"status_fetching_video_info\">ইনফো আনা হচ্ছে</string>\n    <string name=\"show_more_actions\">আরো অ্যাকশন দেখুন</string>\n    <string name=\"invalid_index_range\">ইনডেক্স ভ্যালিড নয়</string>\n    <string name=\"share_fail_msg\">শেয়ার করা কনটেন্ট থেকে URL ম্যাচ করা যায়নি</string>\n    <string name=\"video_url\">ভিডিও লিঙ্ক</string>\n    <string name=\"translate_desc\">হোস্টেড ওয়েবলেটে এই অ্যাপটি ট্রান্সলেট করতে সাহায্য করুন</string>\n    <string name=\"import_from_clipboard\">ক্লিপবোর্ড থেকে ইমপোর্ট করুন</string>\n    <string name=\"delete_multiple_items_msg\">আপনার ডাউনলোড হিস্ট্রি থেকে %1$d আইটেম(গুলি) সরাবেন?</string>\n    <string name=\"aria2_desc\">এক্সটারনাল ডাউনলোডার হিসাবে aria2c ব্যবহার করুন</string>\n    <string name=\"download_disabled_with_cellular\">সেলুলার নেটওয়ার্কের দিয়ে ডাউনলোড আপনার সেটিংস অনুযায়ী বন্ধ করা</string>\n    <string name=\"format_selection\">ফরম্যাট সিলেক্ট</string>\n    <string name=\"telegram_channel\">টেলিগ্রাম চ্যানেল</string>\n    <string name=\"battery_settings_desc\">ব্যাকগ্রাউন্ডে ডাউনলোড করার জন্য অনুগ্রহ করে সিস্টেম সেটিংসে এই অ্যাপের ব্যাটারি ব্যবহারকে \\\"Unrestricted\\\" এ সেট করুন।</string>\n    <string name=\"download_notification\">ডাউনলোড নোটিফিকেশন</string>\n    <string name=\"status_canceled\">বাতিল হয়েছে</string>\n    <string name=\"use_custom_command\">কাস্টম কমান্ড ব্যবহার করুন</string>\n    <string name=\"video_only\">ভিডিও (অডিও ছাড়া)</string>\n    <string name=\"suggested\">সাজেস্টেড</string>\n    <string name=\"how_does_it_work\">এটা কিভাবে কাজ করে?</string>\n    <string name=\"options\">অপশন</string>\n    <string name=\"download_with_cellular\">সেলুলার ব্যবহার করে ডাউনলোড করুন</string>\n    <string name=\"download_with_cellular_desc\">মিটারর্ড নেটওয়ার্ক ব্যাবহার করে মিডিয়া ডাউনলোড করার পারমিশন দিন</string>\n    <string name=\"select_all\">সব সিলেক্ট করুন</string>\n    <string name=\"channel_description\">ডাউনলোডেড ফাইল এবং প্রোগ্রেস দেখুন</string>\n    <string name=\"download_finish_notification\">ডাউনলোড শেষ। দেখতে ট্যাপ করুন।</string>\n    <string name=\"execute_command_notification\">কাস্টম কমান্ড রান হচ্ছে…</string>\n    <string name=\"concurrent_download\">মাল্টি-থ্রেডেড ডাউনলোড</string>\n    <string name=\"concurrent_download_num\">%d থ্রেড(গুলি) একসাথে DASH/HLS নেটিভ ভিডিও ডাউনলোড করতে ব্যবহার করা হবে।</string>\n    <string name=\"additional_settings\">অতিরিক্ত সেটিংস</string>\n    <string name=\"download_notification_desc\">ডাউনলোড করা ফাইল এবং প্রোগগ্রেস সম্পর্কে জানুন</string>\n    <string name=\"concurrent_download_desc\">একইসাথে M3U8/MPD ভিডিওর আরও পার্ট ডাউনলোড করুন</string>\n    <string name=\"share_success_msg\">শেয়ার করা কন্টেন্ট থেকে ভিডিও লিঙ্ক নেয়া হচ্ছে…</string>\n    <string name=\"fetching_playlist_info\">প্লেলিস্টের ইনফো নেয়া হচ্ছে…</string>\n    <string name=\"download_range_selection\">প্লেলিস্ট সিলেক্ট</string>\n    <string name=\"from\">শুরু</string>\n    <string name=\"to\">শেষ</string>\n    <string name=\"download_directory\">ডাউনলোড ডিরেক্টরি</string>\n    <string name=\"download_directory_desc\">ভিডিও এবং অডিও ফাইলগুলি কোথায় সেভ হবে তা সিলেক্ট করুন</string>\n    <string name=\"subdirectory_desc\">নির্দিষ্ট নামে ফোল্ডারে ফাইল সেভ করুন</string>\n    <string name=\"permission_issue\">স্টোরেজ পারমিশনে সমস্যা</string>\n    <string name=\"battery_configuration\">ব্যাটারি কনফিগারেশন</string>\n    <string name=\"translate\">ট্রান্সলেট</string>\n    <string name=\"new_template\">নতুন টেমপ্লেট</string>\n    <string name=\"disable_preview_desc\">ডাউনলোডের সময় থাম্বনেইল বন্ধ করুন</string>\n    <string name=\"generate_new_cookies\">নতুন কুকি তৈরি করুন</string>\n    <string name=\"remove_cookie_profile_desc\">\\\"%1$s\\\" এর জন্য এই এন্ট্রিটি সরাবেন? করে মনে রাখবেন যে এই সাইটের জন্য সেভড কুকিগুলি ক্লিয়ার করা হবে না</string>\n    <string name=\"required\">প্রয়োজন</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d টি আইটেম</item>\n        <item quantity=\"other\">%d টি আইটেম</item>\n    </plurals>\n    <string name=\"template_selection\">টেমপ্লেট সিলেক্ট</string>\n    <string name=\"remove_template\">রিমুভ?</string>\n    <string name=\"status_enqueued\">কিউ করা হয়েছে</string>\n    <string name=\"status_completed\">হয়ে গেছে</string>\n    <string name=\"private_mode\">প্রাইভেট মোড</string>\n    <string name=\"disable_preview\">প্রি-ভিউ বন্ধ করুন</string>\n    <string name=\"private_directory_desc\">হিডেন ডিরেক্টরিতে ডাউনলোড করুন</string>\n    <string name=\"private_mode_desc\">ডাউনলোড হিস্ট্রি বন্ধ করুন</string>\n    <string name=\"dynamic_color_desc\">ওয়ালপেপার থেকে অ্যাপ থিম সেট করুন</string>\n    <string name=\"file_unavailable\">ফাইলটি নেই</string>\n    <string name=\"crop_artwork\">ক্রপ আর্টওয়ার্ক</string>\n    <string name=\"crop_artwork_desc\">এমবেডড ছবি ক্রপ করুন</string>\n    <string name=\"download_selection_desc\">প্লেলিস্ট \\\"%1$s\\\" থেকে ডাউনলোড করতে ভিডিও সিলেক্ট করুন</string>\n    <string name=\"sponsor_msg\">সীল সর্বদা ফ্রি এবং ওবদ-সোর্স থাকবে। আপনার যদি প্রোজেক্টটি পছন্দ হয়, অনুগ্রহ করে আমাকে GitHub-এ স্পনসর করার কথা বিবেচনা করবেন</string>\n    <string name=\"download_video_desc\">URL থেকে ভিডিও ডাউনলোড করুন</string>\n    <string name=\"copy_link\">লিংক কপি করুন</string>\n    <string name=\"copy_error_report\">ইরর রিপোর্ট</string>\n    <string name=\"video_resolution\">ভিডিও রেজুলেশন</string>\n    <string name=\"video_file_size\">ভিডিও ফাইলের সাইজ</string>\n    <string name=\"filesize_mb\">\"%.2f  এমবি\"</string>\n    <string name=\"filesize_gb\">%.2f জিবি</string>\n    <string name=\"apply\">অ্যাপ্লাই</string>\n    <string name=\"clip_video\">ভিডিও ক্লিপ করুন</string>\n    <string name=\"audio_format_preference\">প্রেফারেড অডিও ফরম্যাট</string>\n    <string name=\"file\">ফাইল</string>\n    <string name=\"clipboard\">ক্লিপবোর্ড</string>\n    <string name=\"import_from\">থেকে ইমপোর্টেড</string>\n    <string name=\"import_backup\">ইমপোর্ট</string>\n    <string name=\"export_download_history\">ডাউনলোড হিস্ট্রি ইমপোর্ট করবেন?</string>\n    <string name=\"import_download_history\">ডাউনলোড হিস্ট্রি এক্সপোর্ট করবেন?</string>\n    <string name=\"full_backup\">ফুল ব্যাকআপ</string>\n    <string name=\"backup_type\">ব্যাকআপের ধরণ</string>\n    <string name=\"export_to\">এক্সপোর্ট করুন</string>\n    <string name=\"export_download_history_msg\">ডাউনলোড হিস্ট্রি থেকে %1$s এক্সপোর্ট করা হচ্ছে। ডাউনলোড করা ফাইল এবং প্রেফারেন্স ব্যাকআপ হবে না</string>\n    <string name=\"export_to_file\">ফাইল এক্সপোর্ট করুন</string>\n    <string name=\"restrict_filenames\">ফাইলের নাম রিস্ট্রিক্ট করুন</string>\n    <string name=\"restrict_filenames_desc\">কম্পিটিবিলিটি নিশ্চিত করতে নির্দিষ্ট অক্ষরে ফাইলের নাম সীমাবদ্ধ করুন</string>\n    <string name=\"downloading_indicator_text\">ডাউনলোড হচ্ছে…</string>\n    <string name=\"restart\">রিস্টার্ট</string>\n    <string name=\"status_error\">ইরর</string>\n    <string name=\"template_imported\">ইমপোর্ট করা %1$d টেমপ্লেট(গুলি)</string>\n    <string name=\"app_update_failed\">লেটেস্ট ভার্সন আপডেট করতে ব্যর্থ</string>\n    <string name=\"lowest_quality\">লোএস্ট কোয়ালিটি</string>\n    <string name=\"private_directory\">প্রাইভেট ডিরেক্টরি</string>\n    <string name=\"matrix_space\">ম্যাট্রিক্স স্পেস</string>\n    <string name=\"title_activity_share\">কুইক ডাউনলোড</string>\n    <string name=\"video_title_sample_text\">ভিডিও টাইটেলের নমুনা</string>\n    <string name=\"subtitle\">সাবটাইটেল</string>\n    <string name=\"add\">অ্যাড করুন</string>\n    <string name=\"auto_update\">অটোমেটিক আপডেট</string>\n    <string name=\"unlimited\">আনলিমিটেড</string>\n    <string name=\"lowest_bitrate\">সর্বনিম্ন বিটরেট</string>\n    <string name=\"audio_quality\">অডিও কোয়ালিটি</string>\n    <string name=\"format_sorting_desc\">yt-dlp-এর -S অপশন দিয়ে ফরম্যাট সর্টিং</string>\n    <string name=\"import_from_preferences\">ইমপোর্ট</string>\n    <string name=\"title\">টাইটেল</string>\n    <string name=\"rename\">রিনেম করুন</string>\n    <string name=\"audio_format\">অডিও ফরম্যাট</string>\n    <string name=\"clip_video_desc\">ফরম্যাট সিলেক্ট পেজে ভিডিও ক্লিপ তৈরি করুন</string>\n    <string name=\"switch_to_github_builds\">GitHub বিল্ডে স্যুইচ করা হচ্ছে</string>\n    <string name=\"feature_unavailable\">ফিচার আনএভেলেবেল</string>\n    <string name=\"sponsor_msg2\">আপনাকে অনেক ধন্যবাদ!</string>\n    <string name=\"quality\">কোয়ালিটি</string>\n    <string name=\"enable_notifications\">নোটিফিকেশন চালু করবেন?</string>\n    <string name=\"custom_command_directory\">কাস্টম কমান্ড ডিরেক্টরি</string>\n    <string name=\"disabled\">বন্ধ করা</string>\n    <string name=\"prefer_compatibility_desc\">অন্যান্য অ্যাপে শেয়ার করার জন্য MP4(H.264) ফরম্যাট সিলে করুন</string>\n    <string name=\"prefer_quality_desc\">সাপোর্টেড অ্যাপে দেখার জন্য AV1, VP9 বা H.265 ফরম্যাট সিলেক্ট করুন</string>\n    <string name=\"custom\">কাস্টম</string>\n    <string name=\"format_preference\">ফরম্যাট প্রেফারেন্স</string>\n    <string name=\"learn_more\">আরও জানুন</string>\n    <string name=\"output_template\">আউটপুট টেমপ্লেট</string>\n    <string name=\"output_template_desc\">আউটপুট ফাইলের নামের জন্য টেমপ্লেট সিলেক্ট করুন</string>\n    <string name=\"auto_translated_subtitles\">অটো-ট্রান্সলেটেড সাবটাইটেল</string>\n    <string name=\"auto_translated_subtitles_msg\">সব ভাষার জন্য অটো-ট্রান্সলেটেড সাবটাইটেল ডাউনলোডে করা যাবে। এই সাবটাইটেলগুলি বোঝা কঠিন এবং ভুল হতে পারে</string>\n    <string name=\"subtitle_language_desc\">সাবটাইটেলগুলির ভাষা (,) কমা দিয়ে আলাদা করা</string>\n    <string name=\"remember_for_next_download\">পরবর্তী ডাউনলোডের জন্য একই রাখবেন</string>\n    <string name=\"system_settings\">সিস্টেম সেটিংস</string>\n    <string name=\"look_and_feel\">লুক অ্যান্ড ফিল</string>\n    <string name=\"interface_and_interaction\">ইন্টারফেস এবং ইন্টারঅ্যাকশন</string>\n    <string name=\"use_previous_selection\">পূর্ববর্তী সিলেকশন ব্যবহার করুন</string>\n    <string name=\"none\">কোনোটাই নয়</string>\n    <string name=\"reset\">রিসেট</string>\n    <string name=\"search_in_subtitles\">সাবটাইটেল সার্চ করুন</string>\n    <string name=\"no_thanks\">না ধন্যবাদ</string>\n    <string name=\"update_subtitle_languages\">সাবটাইটেলের ভাষা আপডেট করবেন?</string>\n    <string name=\"download_history\">হিস্ট্রি ডাউনলোড করুন</string>\n    <string name=\"download_archive\">আর্কাইভে ডাউনলোড করুন</string>\n    <string name=\"clear_download_archive\">ডাউনলোড আর্কাইভে ক্লিয়ার করবেন?</string>\n    <string name=\"clear_download_archive_desc\">আর্কাইভে ফাইল থেকে %1$s রিমুভ করতে চান?</string>\n    <string name=\"force_ipv4\">IPv4 ফোর্স করুন</string>\n    <string name=\"force_ipv4_desc\">IPv4 এর মাধ্যমে সমস্ত কানেকশন রাউট করুন</string>\n    <string name=\"template_label\">লেবেল</string>\n    <string name=\"download_range_desc\">প্লেলিস্ট \\\"%3$s\\\" (%1$d থেকে %2$d পর্যন্ত) ডাউনলোড করার জন্য ভিডিওগুলির রেঞ্জ নির্দিষ্ট করুন।</string>\n    <string name=\"remove_template_desc\">কমান্ড টেমপ্লেট থেকে \\\"%1$s\\\" সরাতে চান?</string>\n    <string name=\"custom_command_template_desc\">কমান্ড টেমপ্লেট এডিট এবং পরিচালনা করুন</string>\n    <string name=\"github_issue_desc\">বাগ রিপোর্ট বা ফিচার রিকুয়েস্ট জন্য একটি ইস্যু রিপোর্ট করুন</string>\n    <string name=\"sponsorblock_categories_desc\">ভিডিও থেকে সরানোর জন্য SponsorBlock সেগমেন্টগুলি সিলেক্ট করুন</string>\n    <string name=\"check_for_updates\">আপডেট চেক করুন</string>\n    <string name=\"check_for_updates_desc\">অটোমেটিক GitHub-এর লেটেস্ট ভার্সন চেক করুন</string>\n    <string name=\"clear_temp_files_info\">বাতিল করা ডাউনলোড পুনরায় শুরু করতে টেম্পোরারি ফাইল ব্যবহার করা যেতে পারে। আপনি কি ফাইলগুলি মুছে ফেলবেন?\n\\n\n\\nআপনি %1$s-এ এই ফাইলগুলি অ্যাক্সেস করতে পারেন</string>\n    <string name=\"general_settings_desc\">Yt-dlp ভার্সন, নোটিফিকেশন, প্লেলিস্ট</string>\n    <string name=\"cookies_usage_msg\">কিছু সাইট থেকে ডাউনলোড করার জন্য অ্যাকাউন্ট আথেন্টিকেশন তথ্য প্রয়োজন \\\"নতুন কুকি তৈরি করুন\\\" ক্লিক করুন, ওয়েবসাইটের URL লিখুন এবং ব্রাউজার পেজে আপনার অ্যাকাউন্ট লগ ইন করুন</string>\n    <string name=\"abs_hint\">বেশিরভাগ ভিডিও স্ট্রিমিং প্ল্যাটফর্মগুলি আলাদাভাবে অডিও আর ভিডিও সরবরাহ করে, আপনি একটি ভিডিও (অডিও ছাড়া) ফরম্যাটের সাথে একটি অডিও মার্জ করতে পারেন</string>\n    <string name=\"copy_log\">লগ কপি করুন</string>\n    <string name=\"edit_shortcuts_desc\">কাস্টম শর্টকাটগুলি এডিট করুন যা কমান্ড টেমপ্লেট তৈরিতে ব্যবহার করা যেতে পারে</string>\n    <string name=\"cookies_desc\">ডাউনলোডের জন্য নেটস্কেপ ফরম্যাটেড কুকিজ ব্যবহার করুন</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp ভিডিও ডাউনলোড করার জন্য একটি শক্তিশালী কমান্ড-লাইন টুল, সিল একটি GUI সাধারণ কমান্ডের জন্য প্রিসেট এবং অন্যান্য অতিরিক্ত ফিচার প্রদান করে yt-dlp ব্যবহার সহজ করে তোলে \n\\n\n\\nঅ্যাভান্স</string>\n    <string name=\"shortcuts\">শর্টকাট</string>\n    <string name=\"embed_subtitles_mkv_msg\">সাবটাইটেল এম্বেড করতে, ভিডিওগুলো mkv কন্টেইনারে রিমাক্স করা হবে। এমবেডেড সাবটাইটেল সহ ভিডিও দেখতে আপনি VLC মিডিয়া প্লেয়ার বা অন্যান্য সামঞ্জস্যপূর্ণ অ্যাপ ব্যবহার করতে পারো।</string>\n    <string name=\"update_channel_desc\">নতুন ফিচার এবং পরিবর্তনের বিষয় দেখতে প্রি-রিলিজ বিল্ড ইনস্টল করুন \n\\n\n\\nএই ভার্সনগুলিতে কিছু সমস্যা থাকবে, কোনো সমস্যা দেখা দিলে আমাদের ফিডব্যাক জানাতে দ্বিধা করবেন না</string>\n    <string name=\"enable_auto_update\">আটোমেটিক আপডেট চালু করুন</string>\n    <string name=\"beta_features\">বেটা</string>\n    <string name=\"clip_video_dialog_msg\">এই ফিচার ব্যবহার করে ডাউনলোড করা ভিডিওর সিলেক্টেড সেগমেন্টগুলি ডাউনলোড করতে FFmpeg-এর ব্যাবহার করা হবে, এই ফিচার এখনও পরীক্ষামূলক এবং কাটিং পুরোপুরি ঠিক হবে না</string>\n    <string name=\"convert_subtitle_desc\">সাবটাইটেলগুলিকে অন্য ফরম্যাটে রূপান্তর করুন</string>\n    <string name=\"custom_command_directory_desc\">কাস্টম কমান্ড ব্যবহার করার সময় আউটপুট ডিরেক্টরি সিলেক্ট করুন</string>\n    <string name=\"remove_multiple_templates_msg\">কমান্ড টেমপ্লেট থেকে %1$s সরাতে চান?</string>\n    <string name=\"presets\">প্রিসেট</string>\n    <string name=\"show_all_items\">মোট %1$d টি আইটেম দেখুন</string>\n    <string name=\"website\">ওয়েবসাইট</string>\n    <string name=\"download_archive_desc\">ডুপ্লিকেট ডাউনলোড এড়াতে একটি ডাইরেক্টরিতে ডাউনলোড করা ভিডিও আইডি রেকর্ড করুন</string>\n    <string name=\"save\">সেভ</string>\n    <string name=\"playlist_title\">প্লেলিস্ট টাইটেল</string>\n    <string name=\"download_type\">ডাউনলোড টাইপ</string>\n    <string name=\"embed_metadata\">মেটাডেটা এম্বেড করুন</string>\n    <string name=\"embed_metadata_desc\">অডিও ফাইলে মেটাডেটা এবং ভিডিও থাম্বনেল এম্বেড করুন</string>\n    <string name=\"use_format_sorting\">ফরম্যাটেড সর্টিং ব্যবহার করুন</string>\n    <string name=\"update_language_msg\">নিম্নলিখিত ভাষাগুলি ভবিষ্যতে ডাউনলোডের জন্য আপনার প্রেফারেন্সে অ্যাড করা হবে:</string>\n    <string name=\"allow_once\">একবার পারমিশন দিন</string>\n    <string name=\"export_backup\">এক্সপোর্ট</string>\n    <string name=\"import_download_history_msg\">ডাউনলোড করা ফাইল ইমপোর্ট করা হবে না। আপনাকে সেগুলি ম্যানুয়ালি ডাউনলোড করতে হবে</string>\n    <string name=\"download_archive_error\">ভিডিওটি ডাউনলোড করা হয়েছে। এটি প্রত্যাশিত না হলে, আপনার ডাউনলোড ডিরেক্টরি চেক করুন।</string>\n    <string name=\"download_history_imported\">হিস্ট্রি ডাউনলোড করতে %1$s ইমপোর্ট করা হয়েছে</string>\n    <string name=\"redownload\">আবার ডাউনলোড করুন</string>\n    <string name=\"you_ll_find_your_downloads_here\">আপনার ডাউনলোডগুলি এখানে দেখানো হবে</string>\n    <string name=\"download_hint\">ডাউনলোড বাটনে ক্লিক করুন অথবা একটি ভিডিও লিঙ্ক অ্যাপে শেয়ার করে ডাউনলোড শুরু করুন</string>\n    <string name=\"search_in_downloads\">ডাউনলোড সার্চ করুন</string>\n    <string name=\"search\">সার্চ করুন</string>\n    <string name=\"download_queue\">ডাউনলোড কিউ</string>\n    <string name=\"all\">সব</string>\n    <string name=\"remux_container_mkv\"> রিমুএক্স ভিডিও কন্টেইনার</string>\n    <string name=\"every_day\">প্রতি দিন</string>\n    <string name=\"remux_container_mkv_desc\">ভালো প্লেব্যাকের জন্য ভিডিওগুলো MKV কন্টেইনারে রিমুএক্স করুন</string>\n    <string name=\"cookies_in_database\">%2$d টি ওয়েবসাইটের মোট %1$d টি কুকি</string>\n    <string name=\"every_month\">প্রতি মাসে</string>\n    <string name=\"every_week\">প্রতি সপ্তাহে</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ca/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"about\">Quant a</string>\n    <string name=\"about_page\">Versió, retroalimentació, actualització automàtica</string>\n    <string name=\"back\">Ves enrere</string>\n    <string name=\"video_directory\">Carpeta dels vídeos</string>\n    <string name=\"extract_audio\">Desa com a àudio</string>\n    <string name=\"download_settings_desc\">General, format, ordre personalitzada</string>\n    <string name=\"download\">Baixa</string>\n    <string name=\"url_empty\">L\\'enllaç no pot estar buit</string>\n    <string name=\"extract_audio_summary\">Baixa i desa l\\'àudio, en lloc del vídeo</string>\n    <string name=\"create_thumbnail_summary\">Desa la miniatura del vídeo com a fitxer</string>\n    <string name=\"yt_dlp_update_fail\">No s\\'ha pogut instal·lar la versió més recent de «yt-dlp». Assegureu-vos que esteu connectat a Internet.</string>\n    <string name=\"fetching_info\">S\\'està recuperant la informació del vídeo…</string>\n    <string name=\"download_start_msg\">Baixa «%1$s»</string>\n    <string name=\"fetch_info_error_msg\">No s\\'ha pogut obtenir la informació del vídeo</string>\n    <string name=\"language_settings\">Estableix l\\'idioma de visualització</string>\n    <string name=\"language\">Mostra l\\'idioma</string>\n    <string name=\"ytdlp_version\">Versió de yt-dlp</string>\n    <string name=\"ytdlp_update\">Feu clic per instal·lar l\\'última versió de yt-dlp</string>\n    <string name=\"ytdlp_update_action\">Actualitza el yt-dlp</string>\n    <string name=\"delete_info\">Voleu eliminar-lo?</string>\n    <string name=\"delete_info_msg\">Esteu segur que voleu eliminar «%1$s» de l\\'historial de baixades?</string>\n    <string name=\"open_url\">Obre l\\'enllaç</string>\n    <string name=\"remove\">Elimina</string>\n    <string name=\"version\">Versió</string>\n    <string name=\"release_desc\">Cerca registres de canvis i noves versions</string>\n    <string name=\"video\">Vídeo</string>\n    <string name=\"checked\">Marcat</string>\n    <string name=\"credits\">Crèdits</string>\n    <string name=\"credits_desc\">Crèdits i programari lliure</string>\n    <string name=\"custom_command\">Ordre personalitzada</string>\n    <string name=\"custom_command_desc\">Executa l\\'ordre yt-dlp amb una plantilla personalitzada</string>\n    <string name=\"custom_command_template\">Plantilla de l\\'ordre</string>\n    <string name=\"print_details_desc\">Mostra missatges detallats durant la baixada</string>\n    <string name=\"display_settings\">Tema fosc, color dinàmic, idiomes</string>\n    <string name=\"off\">Desactivat</string>\n    <string name=\"cancel\">Cancel·la</string>\n    <string name=\"settings_before_download\">Configura abans de baixar</string>\n    <string name=\"settings_before_download_desc\">Configura les preferències abans de baixar</string>\n    <string name=\"settings_before_download_text\">Ajusta aquesta baixada</string>\n    <string name=\"error_copied\">S\\'ha copiat l\\'informe d\\'error al porta-retalls</string>\n    <string name=\"paste\">Enganxa</string>\n    <string name=\"yt_dlp_docs\">Referències d\\'ús de yt-dlp</string>\n    <string name=\"edit_template_desc\">L\\'aplicació afegirà el camí de sortida i l\\'URL.</string>\n    <string name=\"convert_audio_format\">Converteix el format d\\'àudio</string>\n    <string name=\"not_convert\">Sense conversió</string>\n    <string name=\"convert_to\">Converteix a %1$s</string>\n    <string name=\"format\">Format</string>\n    <string name=\"convert_audio_format_desc\">La recodificació dels fitxers d\\'àudio provocarà pèrdues de qualitat d\\'àudio i l\\'augment de mida del fitxer.</string>\n    <string name=\"video_quality\">Qualitat del vídeo</string>\n    <string name=\"video_quality_desc\">Limita la qualitat del vídeo quan n\\'hi ha més d\\'un</string>\n    <string name=\"video_format_preference\">Format de vídeo preferit</string>\n    <string name=\"preferred_format_desc\">Format preferit quan se\\'n proporciona més d\\'un</string>\n    <string name=\"create_thumbnail\">Desa la miniatura</string>\n    <string name=\"settings\">Paràmetres</string>\n    <string name=\"yt_dlp_up_to_date\">S\\'està fent servir l\\'última versió de yt-dlp</string>\n    <string name=\"permission_denied\">Permís denegat</string>\n    <string name=\"delete_file\">Suprimeix el fitxer</string>\n    <string name=\"download_success_msg\">S\\'ha finalitzat la baixada</string>\n    <string name=\"download_error_msg\">No s\\'ha pogut baixar el fitxer</string>\n    <string name=\"general_settings\">General</string>\n    <string name=\"task_running\">Ja hi ha una tasca de baixada executant-se en aquests moments</string>\n    <string name=\"paste_msg\">Enganxa l\\'URL des del porta-retalls</string>\n    <string name=\"paste_fail_msg\">No s\\'ha pogut detectar l\\'URL del porta-retalls</string>\n    <string name=\"confirm\">Confirma</string>\n    <string name=\"downloads_history\">Baixades</string>\n    <string name=\"audio\">Àudio</string>\n    <string name=\"dismiss\">Cancel·la</string>\n    <string name=\"link_copied\">S\\'ha copiat l\\'enllaç al porta-retalls</string>\n    <string name=\"release\">Últim llançament</string>\n    <string name=\"readme_desc\">Comprova el repositori de GitHub i el README</string>\n    <string name=\"display\">Aspecte</string>\n    <string name=\"edit\">Edita</string>\n    <string name=\"start_execute\">Inicia l\\'execució de l\\'ordre</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"advanced_settings\">Avançat</string>\n    <string name=\"print_details\">Sortida detallada</string>\n    <string name=\"dark_theme\">Tema fosc</string>\n    <string name=\"on\">Activat</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"best_quality\">Millor qualitat</string>\n    <string name=\"not_specified\">No especificat (predeterminat)</string>\n    <string name=\"video_format\">Format de vídeo</string>\n    <string name=\"convert_audio\">Converteix</string>\n    <string name=\"start_download\">Baixa</string>\n    <string name=\"close\">Tanca</string>\n    <string name=\"close_never_show_again\">No ho tornis a mostrar</string>\n    <string name=\"user_guide\">Guia d\\'usuari</string>\n    <string name=\"open_settings\">Obre la configuració</string>\n    <string name=\"paste_desc\">Feu clic a «Enganxa» per a obtenir l\\'enllaç del vídeo del porta-retalls.</string>\n    <string name=\"check_download_settings_desc\">Feu un cop d\\'ull a la configuració de les baixades i assegureu-vos que teniu l\\'última versió de yt-dlp abans d\\'utilitzar l\\'aplicació.</string>\n    <string name=\"download_playlist\">Baixa una llista de reproducció</string>\n    <string name=\"defaults\">Per defecte</string>\n    <string name=\"channel_description\">Notifica els fitxers baixats i el progrés</string>\n    <string name=\"video_url\">Enllaç del vídeo</string>\n    <string name=\"download_finish_notification\">S\\'ha finalitzat la baixada. Toqueu per obrir.</string>\n    <string name=\"execute_command_notification\">S\\'estan executant les ordres personalitzades…</string>\n    <string name=\"battery_settings_desc\">Establiu l\\'ús de la bateria d\\'aquesta aplicació a \\\"Sense restriccions\\\" a la configuració del sistema per poder baixar vídeos en segon pla.</string>\n    <string name=\"concurrent_download\">Baixada multitasca</string>\n    <string name=\"download_desc\">A continuació, feu clic a «Baixa» després d\\'ajustar la configuració.</string>\n    <string name=\"download_history_desc\">Comprova i gestiona les baixades a l\\'app, inclosos els vídeos i els fitxers d\\'àudio.</string>\n    <string name=\"download_playlist_desc\">Baixa múltiples vídeos d\\'una llista de reproducció</string>\n    <string name=\"channel_name\">Baixa</string>\n    <string name=\"concurrent_download_desc\">Baixa més parts de vídeos M3U8/MPD en paral·lel</string>\n    <string name=\"concurrent_download_num\">S\\'usarien %d fils per baixar vídeo nadiu DASH/HLS concurrentment.</string>\n    <string name=\"options\">Opcions</string>\n    <string name=\"additional_settings\">Configuració addicional</string>\n    <string name=\"share_fail_msg\">No s\\'ha pogut obtenir l\\'URL del contingut compartit</string>\n    <string name=\"show_more_actions\">Mostra més accions</string>\n    <string name=\"github_issue\">Tiquet GitHub</string>\n    <string name=\"github_issue_desc\">Creeu un tiquet per a un informe d\\'error o per a una petició de nova funcionalitat</string>\n    <string name=\"info_copied\">S\\'ha copiat la informació al porta-retalls</string>\n    <string name=\"template_imported\">S\\'han importat %1$d plantilles</string>\n    <string name=\"download_task_count\">%1$d tasques de baixada</string>\n    <string name=\"delete_multiple_items_msg\">Voleu eliminar %1$d elements de l\\'historial de baixades?</string>\n    <string name=\"sponsorblock_categories\">Categories de SponsorBlock</string>\n    <string name=\"check_for_updates\">Comprova si hi ha actualitzacions</string>\n    <string name=\"check_for_updates_desc\">Comprova automàticament si hi ha una nova versió a GitHub</string>\n    <string name=\"app_up_to_date\">Ja teniu l\\'última versió</string>\n    <string name=\"update\">Actualitza</string>\n    <string name=\"download_with_cellular_desc\">Baixa dades multimèdia també quan estiguis connectat a xarxes amb control de consum</string>\n    <string name=\"download_disabled_with_cellular\">La baixada amb la xarxa mòbil està desactivada d\\'acord amb la configuració</string>\n    <string name=\"file_unavailable\">Aquest fitxer ja no està disponible</string>\n    <string name=\"network\">Xarxa</string>\n    <string name=\"rate_limit\">Límit de la velocitat de baixada</string>\n    <string name=\"rate_limit_desc\">Limita la velocitat màxima de baixada</string>\n    <string name=\"max_rate\">Velocitat màxima</string>\n    <string name=\"high_contrast\">Tema fosc d\\'alt contrast</string>\n    <string name=\"unavailable\">No disponible</string>\n    <string name=\"network_settings_desc\">Límit de baixada, eina de baixada, galetes</string>\n    <string name=\"disable_preview\">Desactiva la vista prèvia</string>\n    <string name=\"disable_preview_desc\">No es mostren les miniatures durant la baixada</string>\n    <string name=\"privacy\">Confidencialitat</string>\n    <string name=\"crop_artwork\">Escapça les cobertes</string>\n    <string name=\"crop_artwork_desc\">Escapça la imatge incrustada al quadrat</string>\n    <string name=\"use_cookies\">Utilitza galetes</string>\n    <string name=\"remove_cookie_profile_desc\">Voleu eliminar aquesta entrada per a «%1$s»? No s’esborraran les galetes emmagatzemades del lloc.</string>\n    <string name=\"custom_command_enabled_hint\">Algunes opcions no estan disponibles quan s\\'utilitza una ordre personalitzada</string>\n    <string name=\"how_does_it_work\">Com funciona?</string>\n    <string name=\"telegram_channel\">Canal Telegram</string>\n    <string name=\"sdcard_directory\">Carpeta de targetes SD</string>\n    <string name=\"abs_hint\">La majoria de plataformes de vídeo en streaming envien l\\'àudio i el vídeo per separat, podeu seleccionar i fusionar els formats de només àudio i només vídeo a un sol fitxer de vídeo.</string>\n    <string name=\"video_creator_sample_text\">Text de mostra del creador de vídeo</string>\n    <string name=\"copy_log\">Copia el registre</string>\n    <string name=\"share_success_msg\">S\\'està llegint l\\'enllaç del vídeo des del contingut compartit…</string>\n    <string name=\"download_notification\">Baixa la notificació</string>\n    <string name=\"download_range_selection\">Selecció de la llista de reproducció</string>\n    <string name=\"download_notification_desc\">Notifica sobre els fitxers baixats i el progrés</string>\n    <string name=\"fetching_playlist_info\">S\\'està recuperant la informació de la llista de reproducció…</string>\n    <string name=\"download_range_desc\">Especifiqueu l\\'interval de vídeos a baixar de la llista de reproducció «%3$s» (des de %1$d a %2$d).</string>\n    <string name=\"from\">Inici</string>\n    <string name=\"invalid_index_range\">Interval d\\'índex no vàlid</string>\n    <string name=\"to\">Final</string>\n    <string name=\"download_directory_desc\">Seleccioneu on voleu emmagatzemar els vídeos i els fitxers d\\'àudio</string>\n    <string name=\"playlist_indicator_text\">S\\'està baixant la llista de reproducció (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Carpeta d\\'àudios</string>\n    <string name=\"download_directory\">Directori de baixades</string>\n    <string name=\"subdirectory\">Desa-ho en un subdirectori</string>\n    <string name=\"subdirectory_desc\">Desa els fitxers en carpetes anomenades com als camps respectius</string>\n    <string name=\"permission_issue\">Problema de permisos d\\'emmagatzematge</string>\n    <string name=\"permission_issue_desc\">Els directoris que són fora de «Download» i «Documents» no estan suportats</string>\n    <string name=\"battery_configuration\">Configuració de la bateria</string>\n    <string name=\"battery_configuration_desc\">Ignora l\\'optimització de la bateria perquè aquesta aplicació pugui baixar vídeos en segon pla</string>\n    <string name=\"service_title\">Seal està descarregant…</string>\n    <string name=\"translate\">Tradueix</string>\n    <string name=\"translate_desc\">Ajudeu a traduir aquesta aplicació a Hosted Weblate</string>\n    <string name=\"unknown_error\">Error desconegut</string>\n    <string name=\"prefix\">Prefix</string>\n    <string name=\"embed_subtitles\">Incrusta els subtítols</string>\n    <string name=\"embed_subtitles_desc\">Incrusta els subtítols als vídeos si és possible</string>\n    <string name=\"new_template\">Nova plantilla</string>\n    <string name=\"template_label\">Etiqueta</string>\n    <string name=\"remove_template\">Ho voleu eliminar?</string>\n    <string name=\"remove_template_desc\">Voleu eliminar «%1$s» de les plantilles d\\'ordres?</string>\n    <string name=\"template_selection\">Selecció de plantilla</string>\n    <string name=\"custom_command_template_desc\">Editeu i gestioneu les plantilles d\\'ordres</string>\n    <string name=\"task_canceled\">S\\'ha cancel·lat la tasca de baixada</string>\n    <string name=\"status_enqueued\">En cua</string>\n    <string name=\"downloading_indicator_text\">Baixada en curs…</string>\n    <string name=\"status_completed\">Completat</string>\n    <string name=\"status_downloading\">S\\'està baixant</string>\n    <string name=\"status_canceled\">Cancel·lat</string>\n    <string name=\"status_fetching_video_info\">S\\'està recuperant la informació</string>\n    <string name=\"open_file\">Obre un fitxer</string>\n    <string name=\"copy_link\">Copia l\\'enllaç</string>\n    <string name=\"video_file_size\">Mida del fitxer del vídeo</string>\n    <string name=\"import_from_clipboard\">Importa des del porta-retalls</string>\n    <string name=\"restart\">Reinicia</string>\n    <string name=\"status_error\">Error</string>\n    <string name=\"copy_error_report\">Copia l\\'informe</string>\n    <string name=\"video_resolution\">Resolució del vídeo</string>\n    <string name=\"export_to_clipboard\">Exporta al porta-retalls</string>\n    <string name=\"template_exported\">S\\'han exportat %1$d plantilles</string>\n    <string name=\"multiselect_item_count\">%1$d vídeos, %2$d fitxers d\\'àudio</string>\n    <string name=\"recently_added\">Afegit recentment</string>\n    <string name=\"sponsorblock_desc\">Elimina o marca els segments dels vídeos amb l\\'API de SponsorBlock</string>\n    <string name=\"clear_temp_files_count\">S\\'han suprimit %1$d fitxers temporals</string>\n    <string name=\"sponsorblock_categories_desc\">Especifiqueu les categories SponsorBlock per a eliminar o marcar en el fitxer de vídeo</string>\n    <string name=\"cookies\">Galetes</string>\n    <string name=\"app_update_failed\">No s\\'ha pogut actualitzar a la versió més recent</string>\n    <string name=\"aria2_desc\">Utilitza l\\'aria2c com a eina de baixada externa</string>\n    <string name=\"cookies_desc\">Utilitza galetes amb format Netscape per a les baixades</string>\n    <string name=\"clear_temp_files\">Neteja els fitxers temporals</string>\n    <string name=\"clear_temp_files_info\">Els fitxers temporals poden ser útils per reprendre les baixades cancel·lades. Esteu segur que voleu suprimir tots aquests fitxers?\n\\n\n\\nPodeu accedir a aquests fitxers a %1$s</string>\n    <string name=\"clear_temp_files_desc\">Suprimeix tots els fitxers temporals del directori temporal</string>\n    <string name=\"multiselect_mode\">Mode de selecció múltiple</string>\n    <string name=\"private_mode\">Incògnit</string>\n    <string name=\"dynamic_color\">Color dinàmic</string>\n    <string name=\"private_mode_desc\">Desactiva l\\'historial de baixades</string>\n    <string name=\"dynamic_color_desc\">Aplica els colors dels fons de pantalla al tema de l\\'aplicació</string>\n    <string name=\"download_with_cellular\">Baixa utilitzant les dades mòbils</string>\n    <string name=\"invalid_input\">Entrada no vàlida</string>\n    <string name=\"use_custom_command\">Usa una ordre personalitzada</string>\n    <string name=\"private_directory\">Directori privat</string>\n    <string name=\"private_directory_desc\">Emmagatzema les baixades en un directori amagat</string>\n    <string name=\"selected_item_count\">%1$d seleccionat</string>\n    <string name=\"lowest_quality\">Qualitat més baixa</string>\n    <string name=\"format_settings_desc\">Format del fitxer, qualitat del vídeo, subtítols</string>\n    <string name=\"download_selection_desc\">Seleccioneu els vídeos a baixar de la llista de reproducció «%1$s»</string>\n    <string name=\"select_all\">Selecciona-ho tot</string>\n    <string name=\"general_settings_desc\">Versió del yt-dlp, notificacions, llistes de reproducció</string>\n    <string name=\"video_only\">Vídeo (sense àudio)</string>\n    <string name=\"suggested\">Suggerit</string>\n    <string name=\"format_selection\">Selecció del format</string>\n    <string name=\"format_selection_desc\">Seleccioneu el format a baixar abans d\\'iniciar la baixada</string>\n    <string name=\"generate_new_cookies\">Genera galetes noves</string>\n    <string name=\"cookies_usage_msg\">La baixada des d\\'alguns llocs requereix informació d\\'autenticació del compte. Feu clic a «Generar galetes noves», introduïu l\\'URL del lloc web i després inicieu sessió amb el vostre compte amb el navegador, l\\'app l\\'obrirà per tu.</string>\n    <string name=\"auto_subtitle\">Subtítols automàtics</string>\n    <string name=\"auto_subtitle_desc\">Baixa els subtítols autogenerats</string>\n    <string name=\"title_activity_share\">Baixada ràpida</string>\n    <string name=\"subtitle_language\">Idiomes dels subtítols</string>\n    <string name=\"video_title_sample_text\">Text de mostra del títol del vídeo</string>\n    <string name=\"subtitle\">Subtítol</string>\n    <string name=\"subtitle_desc\">Idiomes, subtítols incrustats, subtítols automàtics</string>\n    <string name=\"edit_shortcuts\">Edita les dreceres</string>\n    <string name=\"download_subtitles\">Baixa els subtítols</string>\n    <string name=\"clear\">Neteja</string>\n    <string name=\"add\">Afegeix</string>\n    <string name=\"shortcuts\">Dreceres</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp és una potent eina de línia d\\'ordres per baixar vídeos. Seal facilita l\\'ús de yt-dlp proporcionant una interfície gràfica intuïtiva, ordres predefinides s i altres funcions addicionals.\n\\n\n\\nPer a un ús avançat de yt-dlp, Seal permet crear, desar i executar plantilles d\\'ordres personalitzades directament, com en un terminal.\n\\n\n\\nQuan s\\'utilitzen ordres personalitzades, la majoria de les opcions i funcions de la interfície gràfica es desactivaran.</string>\n    <string name=\"edit_shortcuts_desc\">Edita les dreceres personalitzades que es poden utilitzar per a compondre plantilles d\\'ordres.</string>\n    <string name=\"running_tasks\">Tasques que s\\'estan executant</string>\n    <string name=\"show_logs\">Mostra el registre</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"stable_channel\">Estable</string>\n    <string name=\"pre_release_channel\">Previsualitza</string>\n    <string name=\"auto_update\">Actualitza automàticament</string>\n    <string name=\"enable_auto_update\">Activa l\\'actualització automàtica</string>\n    <string name=\"discard\">Descarta</string>\n    <string name=\"clip_video\">Retalla el vídeo</string>\n    <string name=\"clip_start\">Inicia</string>\n    <string name=\"clip_end\">Finalitza</string>\n    <string name=\"audio_format_preference\">Format d\\'àudio preferit</string>\n    <string name=\"unlimited\">Sense límit</string>\n    <string name=\"audio_quality\">Qualitat de l\\'àudio</string>\n    <string name=\"format_sorting\">Ordenació per format</string>\n    <string name=\"format_sorting_desc\">Ordena els formats amb l\\'opció -S de yt-dlp</string>\n    <string name=\"temporary_directory_desc\">Emmagatzema els fitxers temporals al directori intern</string>\n    <string name=\"sponsor\">Patrocina</string>\n    <string name=\"sponsor_desc\">Doneu suport a aquesta aplicació patrocinant-la a GitHub</string>\n    <string name=\"feedback\">Comentaris</string>\n    <string name=\"sponsors\">Patrocinadors</string>\n    <string name=\"no_downloaded_media\">No s\\'ha baixat cap fitxer multimèdia</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"got_it\">Entesos</string>\n    <string name=\"convert_subtitle\">Converteix els subtítols</string>\n    <string name=\"feature_unavailable\">Aquesta funcionalitat no està disponible</string>\n    <string name=\"msg_from_developer\">Missatge del desenvolupador</string>\n    <string name=\"split_video\">Divideix el vídeo</string>\n    <string name=\"new_task\">Nova tasca de baixada</string>\n    <string name=\"edit_template\">Edita \\\"%1$s\\\"</string>\n    <string name=\"quality\">Qualitat</string>\n    <string name=\"enable_notifications\">Voleu habilitar les notificacions?</string>\n    <string name=\"disabled\">Desactivat</string>\n    <string name=\"custom\">Personalitzat</string>\n    <string name=\"folder_picker\">Selector de carpetes</string>\n    <string name=\"download_type\">Tipus de baixada</string>\n    <string name=\"auto\">Automàtic</string>\n    <string name=\"commands\">Ordres</string>\n    <string name=\"format_preference\">Preferència de format</string>\n    <string name=\"learn_more\">Més informació</string>\n    <string name=\"output_template\">Plantilla de sortida</string>\n    <string name=\"download_archive\">Baixa l\\'arxiu</string>\n    <string name=\"restrict_filenames\">Restringeix els noms de fitxer</string>\n    <string name=\"force_ipv4\">Força IPv4</string>\n    <string name=\"allow_once\">Permet una vegada</string>\n    <string name=\"lowest_bitrate\">Taxa de bits més baixa</string>\n    <string name=\"clear_all_cookies\">Neteja totes les galetes</string>\n    <string name=\"clear_all_cookies_desc\">Voleu suprimir totes les galetes emmagatzemades a l\\'app per sempre?</string>\n    <string name=\"matrix_space\">Canal de Matrix</string>\n    <string name=\"logs\">Registre</string>\n    <string name=\"update_channel\">Actualitza el canal</string>\n    <string name=\"subtitle_sponsorblock\">Es poden malmetre els subtítols en eliminar els segments de SponsorBlock.</string>\n    <string name=\"update_channel_desc\">Instal·leu les versions de prellançament per provar les noves funcionalitats i canvis.\n\\n\n\\nHi haurà certa inestabilitat en aquestes versions, així que no dubteu a enviar-nos qualsevol comentari si experimenteu algun problema per ajudar-nos a millorar l\\'aplicació.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Per incrustar subtítols, els vídeos es barrejaran en un contenidor MKV. Podeu utilitzar el Reproductor VLC o altres aplicacions compatibles per veure vídeos amb subtítols incrustats.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"share\">Comparteix</string>\n    <string name=\"apply\">Aplica</string>\n    <string name=\"audio_quality_desc\">Limita la taxa de bits de l\\'àudio quan hi ha diverses qualitats</string>\n    <string name=\"import_from_preferences\">Importa</string>\n    <string name=\"title\">Títol</string>\n    <string name=\"rename\">Canvia el nom</string>\n    <string name=\"second\">segon</string>\n    <string name=\"minute\">minut</string>\n    <string name=\"embed_metadata\">Incrusta les metadades</string>\n    <string name=\"edit_file\">Edita el fitxer</string>\n    <string name=\"playlist_title\">Títol de la llista de reproducció</string>\n    <string name=\"system_settings\">Configuració del sistema</string>\n    <string name=\"allow_always\">Permet sempre</string>\n    <string name=\"dont_allow\">No permetis</string>\n    <string name=\"copy_and_exit\">Copia i surt</string>\n    <string name=\"sponsor_msg\">El Seal serà sempre lliure i de codi obert per a tothom. Si us agrada, considereu patrocinar-me a GitHub!</string>\n    <string name=\"audio_format\">Format d\\'àudio</string>\n    <string name=\"enable_experimental_feature\">Voleu habilitar la funcionalitat experimental?</string>\n    <string name=\"clip_video_desc\">Fes els videoclips a la pàgina de selecció de format</string>\n    <string name=\"expand\">Expandeix</string>\n    <string name=\"okay\">D\\'acord</string>\n    <string name=\"start\">Inicia</string>\n    <string name=\"proxy\">Servidor intermediari</string>\n    <string name=\"legacy\">Llegat</string>\n    <string name=\"ua_header\">Capçalera de l\\'agent d\\'usuari</string>\n    <string name=\"disable\">Desactiva</string>\n    <string name=\"unknown\">Desconegut</string>\n    <string name=\"website\">Lloc web</string>\n    <string name=\"presets\">Valors predefinits</string>\n    <string name=\"required\">Requerit</string>\n    <string name=\"save\">Desa</string>\n    <string name=\"switch_to_github_builds\">s\\'està canviant a les versions de GitHub</string>\n    <string name=\"no_custom_command_tasks\">No hi ha tasques d\\'ordre personalitzades</string>\n    <string name=\"sponsor_msg2\">Moltes gràcies!</string>\n    <string name=\"download_video_desc\">Baixa els vídeos de l\\'URL</string>\n    <string name=\"convert_subtitle_desc\">Converteix els subtítols a un altre format</string>\n    <string name=\"unknown_error_title\">Vaja! Alguna cosa ha anat malament</string>\n    <string name=\"split_video_msg\">El vídeo es dividirà en %1$d capítols</string>\n    <string name=\"proxy_desc\">Utilitza el servidor intermediari per a les connexions a Internet</string>\n    <string name=\"set_directory_desc\">Toqueu per configurar el directori</string>\n    <string name=\"enable_notifications_desc\">L\\'aplicació necessita el vostre permís per publicar notificacions sobre l\\'estat de baixada i el progrés.</string>\n    <string name=\"custom_command_directory\">Directori d\\'ordres personalitzat</string>\n    <string name=\"custom_command_directory_desc\">Especifiqueu el directori de sortida quan s\\'utilitzin ordres personalitzades</string>\n    <string name=\"prefer_compatibility_desc\">Prefereix els formats MP4 (H.264) per compartir fitxers amb altres aplicacions</string>\n    <string name=\"prefer_quality_desc\">Prefereix els formats AV1, VP9 o H.265 per poder reproduir-los en aplicacions compatibles</string>\n    <string name=\"refresh_cookies_desc\">Toqueu per obrir la pàgina web per generar noves galetes:</string>\n    <string name=\"export_to_file\">Exporta a un fitxer</string>\n    <string name=\"clear_download_archive\">Voleu netejar l\\'arxiu de les baixades?</string>\n    <string name=\"clear_download_archive_desc\">Voleu eliminar %1$s al fitxer d\\'arxiu per sempre?</string>\n    <string name=\"download_archive_desc\">Enregistra els identificadors dels vídeos baixats en un arxiu per evitar baixades duplicades</string>\n    <string name=\"embed_metadata_desc\">Incrusta les metadades i la miniatura del vídeo al fitxer d\\'àudio</string>\n    <string name=\"show_all_items\">Mostra tots els %1$d elements</string>\n    <string name=\"use_format_sorting\">Utilitza l\\'ordenació per format</string>\n    <string name=\"subdirectory_hint\">Les baixades es desaran com a:</string>\n    <string name=\"keep_subtitle_files\">Manté els fitxers de subtítols</string>\n    <string name=\"download_with_cellular_request\">Voleu permetre la baixada amb dades mòbils?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d element</item>\n        <item quantity=\"many\">%d elements</item>\n        <item quantity=\"other\">%d elements</item>\n    </plurals>\n    <string name=\"force_ipv4_desc\">Fes totes les connexions via IPv4</string>\n    <string name=\"merge_audiostream_desc\">Permet fusionar múltiples fluxos d\\'àudio en un sol fitxer</string>\n    <string name=\"merge_audiostream\">Fusiona múltiples fluxos d\\'àudio</string>\n    <string name=\"auto_update_disabled_msg\">L\\'actualització automàtica no està disponible per a les versions de %1$s. Si no teniu %1$s instal·lat al dispositiu, o voleu previsualitzar les futures funcionalitats del Seal, considereu %2$s.</string>\n    <string name=\"clip_video_dialog_msg\">Les baixades que utilitzin aquesta funció es delegaran a FFmpeg per baixar les seccions seleccionades del vídeo. Aquesta funció encara és experimental i el tall no serà completament precís, i no tots els formats suporten aquesta característica. És possible que experimenteu velocitats de baixada més lentes.</string>\n    <string name=\"output_template_desc\">Especifiqueu la plantilla per als noms dels fitxers de sortida</string>\n    <string name=\"remove_multiple_templates_msg\">Voleu eliminar %1$s de les plantilles d\\'ordres per sempre?</string>\n    <string name=\"restrict_filenames_desc\">Limita els noms de fitxer a caràcters específics per garantir la compatibilitat</string>\n    <string name=\"all_languages\">Totes les llengües</string>\n    <string name=\"playlist\">Llista de reproducció</string>\n    <string name=\"proceed\">Continua</string>\n    <string name=\"task_added\">S\\'ha afegit la tasca a la cua</string>\n    <string name=\"best_quality_desc\">Baixa el millor format disponible</string>\n    <string name=\"no_thanks\">No, gràcies</string>\n    <string name=\"clipboard\">Porta-retalls</string>\n    <string name=\"import_from\">Importa des de</string>\n    <string name=\"export_download_history\">Voleu exportar l\\'historial de baixades?</string>\n    <string name=\"import_download_history\">Voleu importar l\\'historial de baixades?</string>\n    <string name=\"download_history\">Baixa l\\'historial</string>\n    <string name=\"update_subtitle_languages\">Voleu actualitzar les llengües dels subtítols?</string>\n    <string name=\"import_backup\">Importa</string>\n    <string name=\"file\">Fitxer</string>\n    <string name=\"export_backup\">Exporta</string>\n    <string name=\"auto_translated_subtitles\">Subtítols traduïts automàticament</string>\n    <string name=\"remember_for_next_download\">Recorda-ho per a la pròxima baixada</string>\n    <string name=\"interface_and_interaction\">Interfície i interacció</string>\n    <string name=\"none\">Cap</string>\n    <string name=\"reset\">Reinicialitza</string>\n    <string name=\"search_in_subtitles\">Cerca als subtítols</string>\n    <string name=\"look_and_feel\">Aspecte</string>\n    <string name=\"use_previous_selection\">Usa la selecció anterior</string>\n    <string name=\"every_day\">Diàriament</string>\n    <string name=\"every_week\">Setmanalment</string>\n    <string name=\"every_month\">Mensualment</string>\n    <string name=\"redownload\">Baixa novament</string>\n    <string name=\"search\">Cerca</string>\n    <string name=\"search_in_downloads\">Cerca a les baixades</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ckb/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"advanced_settings\">پێشکەوتوو</string>\n    <string name=\"video_directory\">فۆڵدەری ڤیدیۆ</string>\n    <string name=\"extract_audio\">وەکوو دەنگ پاشەکەوتی بکە</string>\n    <string name=\"create_thumbnail\">پاشەکەوتکردنی وێنەی سەر ڤیدیۆ</string>\n    <string name=\"settings\">ڕێکخستنەکان</string>\n    <string name=\"download_settings_desc\">گشتی، شێواز، فەرمانی تایبەت</string>\n    <string name=\"download\">داگرتن</string>\n    <string name=\"url_empty\">ناکرێت بەتاڵ بێت</string>\n    <string name=\"create_thumbnail_summary\">وێنەی سەر ڤیدیۆ وەک فایلێک پاشەکەوت بکە</string>\n    <string name=\"yt_dlp_up_to_date\">بەکارهێنانی نوێترین وەشانی yt-dlp</string>\n    <string name=\"fetching_info\">وەرگرتنی زانیاریی ڤیدیۆ…</string>\n    <string name=\"download_success_msg\">داگرتن تەواو بوو</string>\n    <string name=\"download_start_msg\">داگرتنی \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">نەتواندرا زانیاریی ڤیدیۆ وەربگیرێت</string>\n    <string name=\"general_settings\">گشتی</string>\n    <string name=\"language\">زمانی ڕووکار</string>\n    <string name=\"language_settings\">زمانی ڕووکار دیاری بکە</string>\n    <string name=\"paste_msg\">بەستەری لە کلیپبۆردەوە بلکێنە</string>\n    <string name=\"paste_fail_msg\">نەتواندرا لەگەڵ بەستەری ناو کلیپبۆردەکەتدا بگونجێت</string>\n    <string name=\"ytdlp_update\">بۆ دامەزراندنی نوێترین وەشانی yt-dlp کرتە بکە</string>\n    <string name=\"ytdlp_update_action\">نوێکردنەوەی yt-dlp</string>\n    <string name=\"delete_info\">لایدەبەیت؟</string>\n    <string name=\"confirm\">دڵنیاکردنەوە</string>\n    <string name=\"dismiss\">هەڵوەشاندنەوە</string>\n    <string name=\"downloads_history\">دابەزاندنەکان</string>\n    <string name=\"audio\">دەنگ</string>\n    <string name=\"link_copied\">بەستەرەکە کۆپی کرا بۆ کلیپبۆرد</string>\n    <string name=\"open_url\">لینک بکەرەوە</string>\n    <string name=\"remove\">لایببە</string>\n    <string name=\"delete_file\">فایل بسڕەوە</string>\n    <string name=\"about\">دەربارە</string>\n    <string name=\"back\">گەڕانەوە</string>\n    <string name=\"version\">وەشان</string>\n    <string name=\"release_desc\">بەدوای گۆڕانکاری و وەشانی نوێدا بگەڕێ</string>\n    <string name=\"release\">نوێترین بڵاوکراوە</string>\n    <string name=\"credits\">مۆڵەت</string>\n    <string name=\"credits_desc\">مۆڵەت و نەرمەکاڵای لیبرێ</string>\n    <string name=\"custom_command\">فەرمانی تایبەت</string>\n    <string name=\"edit\">دەستکاری</string>\n    <string name=\"start_execute\">دەست بکە بە جێبەجێکردنی فەرمان</string>\n    <string name=\"print_details\">دەرئەنجامی ورد</string>\n    <string name=\"print_details_desc\">لە کاتی دابەزاندندا پەیامی ورد پیشان بدە</string>\n    <string name=\"display\">ڕووکار</string>\n    <string name=\"dark_theme\">ڕووکاری تاریک</string>\n    <string name=\"follow_system\">سیستەم</string>\n    <string name=\"on\">چالاک</string>\n    <string name=\"off\">ناچالاک</string>\n    <string name=\"cancel\">پاشگەزبوونەوە</string>\n    <string name=\"settings_before_download\">پێش دابەزاندن ڕێکی بخە</string>\n    <string name=\"settings_before_download_text\">ئەم دابەزاندنە ڕێک بخە</string>\n    <string name=\"error_copied\">ڕاپۆرتی کێشە کۆپی کرا بۆ کلیپبۆرد</string>\n    <string name=\"paste\">لکاندن</string>\n    <string name=\"yt_dlp_docs\">ئاماژەکانی بەکارهێنانی yt-dlp</string>\n    <string name=\"edit_template_desc\">ڕێڕەوی دەرەنجام و بەیتەر لەلایەن بەرنامەکەوە زیاد دەکرێن.</string>\n    <string name=\"convert_audio_format\">گۆڕینی فۆڕماتی دەنگی</string>\n    <string name=\"not_convert\">نەگۆڕاو</string>\n    <string name=\"format\">فۆڕمات</string>\n    <string name=\"video_quality\">کوالێتیی ڤیدیۆ</string>\n    <string name=\"best_quality\">باشترین کوالێتی</string>\n    <string name=\"video_quality_desc\">کوالێتیی ڤیدیۆکە سنووردار بکە کاتێک چەند ڤیدۆیەک هەبن</string>\n    <string name=\"not_specified\">دیارینەکراو (بچینەیی)</string>\n    <string name=\"video_format_preference\">فۆڕماتی ڤیدیۆیی خوازراو</string>\n    <string name=\"video_format\">فۆڕماتی ڤیدیۆ</string>\n    <string name=\"convert_audio\">گۆڕین</string>\n    <string name=\"start_download\">دابەزاندن</string>\n    <string name=\"close\">داخستن</string>\n    <string name=\"user_guide\">ڕێنوێنیی بەکارهێنەر</string>\n    <string name=\"paste_desc\">بەستەری ڤیدیۆکە بلکێنە باخود لە کلیپبۆردەوە بیهێنە</string>\n    <string name=\"download_history_desc\">دابەزاندنەکانی نێو بەرنامەکە بپشکنە و بەڕێوەیان ببە، بە فایلە ڤیدیۆیی و دەنگییەکانەوە.</string>\n    <string name=\"download_playlist\">پلەیلیست داببەزێنە</string>\n    <string name=\"download_playlist_desc\">کۆمەڵە ڤیدیۆیەک لە پلەیلیستێکەوە دابەزێنە</string>\n    <string name=\"defaults\">بنچینەیی</string>\n    <string name=\"channel_name\">دابەزاندن</string>\n    <string name=\"channel_description\">ئاگادارکردنەوە لە فایلە دابەزێندراوەکان و پێشکەوتنەکەیان</string>\n    <string name=\"video_url\">بەستەری ڤیدیۆ</string>\n    <string name=\"execute_command_notification\">جێبەجێکردنی فەرمانە تایبەتەکان…</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">بابەتی %d</item>\n        <item quantity=\"other\">%d بابەتە</item>\n    </plurals>\n    <string name=\"extract_audio_summary\">لەجیاتی ڤیدیۆ وەک دەنگ دایبگرە</string>\n    <string name=\"yt_dlp_update_fail\">نەتوانرا نوێترین وەشانی yt-dlp دابمەزرێنێت. تکایە دڵنیابە کە پەیوەستیت بە ئینتەرنێتەوە.</string>\n    <string name=\"permission_denied\">مۆڵەت ڕەتکرایەوە</string>\n    <string name=\"download_error_msg\">نەتواندرا فایل داببەزێندرێت</string>\n    <string name=\"task_running\">لە ئێستایا ئەرکێکی دابەزاندن کارایە</string>\n    <string name=\"delete_info_msg\">\\\"%1$s\\\" لە مێژووی دابەزاندنەکەت بۆ هەمیشە لادەبەیت؟</string>\n    <string name=\"ytdlp_version\">وەشانی yt-dlp</string>\n    <string name=\"readme_desc\">کۆگای گیتھەب و فایلی README بپشکنە</string>\n    <string name=\"video\">ڤیدیۆ</string>\n    <string name=\"about_page\">وەشان، بۆچوون، نوێکردنەوەی خۆکارانە</string>\n    <string name=\"checked\">پشکنرا</string>\n    <string name=\"custom_command_desc\">فەرمانی yt-dlp بە فەرمانی تایبەتەوە جێبەجێ بکە</string>\n    <string name=\"custom_command_template\">داڕێژەی فەرمان</string>\n    <string name=\"settings_before_download_desc\">پێش دابەزاندن هەڵبژاردنەکان ڕێک بخە</string>\n    <string name=\"thumbnail\">وێنەی سەر ڤیدیۆ</string>\n    <string name=\"display_settings\">ڕووکاری تاریک، ڕەنگی جووڵەدار، زمانەکان</string>\n    <string name=\"convert_to\">بیگۆڕە بۆ %1$s</string>\n    <string name=\"convert_audio_format_desc\">دووبارە کۆدکردنەوەی فایلە دەنگییەکان دەبێتە هۆی لەدەستدانی کوالێتیی دەنگ و زیادبوونی قەبارەی فایلەکان.</string>\n    <string name=\"preferred_format_desc\">فۆڕماتی خوازراو کاتێک چەند ڤیدیۆیەک هەبن</string>\n    <string name=\"close_never_show_again\">جارێکی تر پیشانی مەدە</string>\n    <string name=\"check_download_settings_desc\">سەیری ڕێکخستنەکانی دابەزاندن بکە و دڵنیابە کە نوێترین وەشانی yt-dlpت هەیە پێش بەکارهێنانی.</string>\n    <string name=\"open_settings\">ڕێکخستنەکان بکەرەوە</string>\n    <string name=\"download_desc\">پاشان دوای ڕێکردنی ڕێکخستنەکان کلیک لە \\\"دابەزاندن\\\" بکە.</string>\n    <string name=\"download_finish_notification\">داگرتن تەواو بوو. پەنجە بنێ بۆ کردنەوەی.</string>\n    <string name=\"battery_settings_desc\">تکایە بەکارهێنانی بارگاییی ئەم بەرنامەیە لە ڕێکخستنەکانی سیستەمدا لەسەر \\\"Unrestricted\\\" دابنێ بۆ ئەوەی لە پشتەوە دابەزاندن بکات.</string>\n    <string name=\"concurrent_download\">دابەزاندنی فرەڕەگ</string>\n    <string name=\"concurrent_download_num\">%d thread(s) بەکاردەهێنرێت بۆ دابەزاندنی ڤیدیۆی ڕەسەنی DASH/HLS لە یەک کاتدا.</string>\n    <string name=\"options\">هەڵبژاردەکان</string>\n    <string name=\"concurrent_download_desc\">بەشی زیاتری ڤیدیۆکانی M3U8/MPD بە شێوەیەکی هاوتا دابەزێنە</string>\n    <string name=\"additional_settings\">ڕێکخستنە زیادەکان</string>\n    <string name=\"share_fail_msg\">ناتوانرێت بەستەر لەگەڵ ناوەڕۆکە هاوبەشەکەوە هاوتا بکرێت</string>\n    <string name=\"share_success_msg\">خوێندنەوەی بەستەری ڤیدیۆ لە ناوەڕۆکی هاوبەشەوە…</string>\n    <string name=\"show_more_actions\">کرداری زیاتر پیشان بدە</string>\n    <string name=\"download_notification\">ئاگاداریی دابەزاندنەکان</string>\n    <string name=\"download_notification_desc\">ئاگادارم بکەوە لە فایلە دابەزێنراوەکان و دابەزاندنەکانی ئێستا</string>\n    <string name=\"fetching_playlist_info\">بەردەستخسنی زانیاریی پلەیلیست…</string>\n    <string name=\"download_range_selection\">هەڵبژاردنی پلەیلیست</string>\n    <string name=\"from\">دەستپێکردن</string>\n    <string name=\"to\">کۆتایی</string>\n    <string name=\"invalid_index_range\">مەودای پێنوێنی هەڵەیە</string>\n    <string name=\"download_directory_desc\">دیاری بکە لە کوێ ڤیدیۆ و فایلە دەنگییەکان هەڵبگیرێت</string>\n    <string name=\"subdirectory\">هەڵگرتن بۆ ڕێبەر</string>\n    <string name=\"subdirectory_desc\">فایلەکان لە فۆڵدەرەکاندا هەڵبگرە کە وەک بواری تایبەت بە خۆیان ناویان لێنراوە</string>\n    <string name=\"permission_issue\">کێشەی مۆڵەتی هەڵگرتن</string>\n    <string name=\"battery_configuration\">ڕێکخستنی پاتری</string>\n    <string name=\"battery_configuration_desc\">پشتگوێخستنی باشکردنی پاتری بۆ ئەم ئەپە بۆ ئەوەی لە پاشبنەمادا دایبەزێنیت</string>\n    <string name=\"service_title\">Seal خەریکی دابەزاندنە…</string>\n    <string name=\"unknown_error\">هەلەیەکی نەناسراوە</string>\n    <string name=\"translate\">وەرگێڕان</string>\n    <string name=\"translate_desc\">یارمەتی وەرگێڕانی ئەم ئەپە بدە لە Hosted Weblate</string>\n    <string name=\"prefix\">پێشگر</string>\n    <string name=\"embed_subtitles_desc\">ژێرنووس بخەرە ناو ڤیدیۆکانەوە، ئەگەر بەردەست بوو</string>\n    <string name=\"new_template\">قاڵبی نوێ</string>\n    <string name=\"template_label\">نیشانە</string>\n    <string name=\"download_range_desc\">مەودای ڤیدیۆکان دیاری بکە بۆ دابەزاندن لە پلەی لیستی \\\"%3$s\\\" (لە %1$d بۆ %2$d).</string>\n    <string name=\"playlist_indicator_text\">دابەزاندنی پلەی لیست (%1$d/%2$d)…</string>\n    <string name=\"permission_issue_desc\">شوێنەکانی دەرەوەی فۆڵدەرەکانی Download/ و Documents/ پشتگیری ناکرێت</string>\n    <string name=\"embed_subtitles\">ژێرنووسەکان جێگیر بکە</string>\n    <string name=\"audio_directory\">فۆڵدەری دەنگ</string>\n    <string name=\"download_directory\">شوێنی دابەزاندن</string>\n    <string name=\"remove_template\">لایدەبەیت؟</string>\n    <string name=\"remove_template_desc\">\\\"%1$s\\\" لە قاڵبی فەرمانەکان لادەبەیت بۆ هەمیشە؟</string>\n    <string name=\"template_selection\">هەڵبژاردنی قاڵب</string>\n    <string name=\"custom_command_template_desc\">دەستکاریکردن و بەڕێوەبردنی قاڵبی فەرمانەکان</string>\n    <string name=\"downloading_indicator_text\">داگرتن لە جێبەجێکردندایە…</string>\n    <string name=\"github_issue\">کێشەی GitHub</string>\n    <string name=\"github_issue_desc\">کێشەیەک پێشکەش بکە بۆ ڕاپۆرتی هەڵە یان داواکاری تایبەتمەندی</string>\n    <string name=\"info_copied\">زانیاری کۆپی کراوە بۆ کلیپبۆرد</string>\n    <string name=\"status_enqueued\">ڕیزبەندی کراوە</string>\n    <string name=\"status_completed\">تەواو بووە</string>\n    <string name=\"status_downloading\">دابەزاندن</string>\n    <string name=\"status_canceled\">هەڵوەشایەوە</string>\n    <string name=\"status_fetching_video_info\">وەرگرتنی زانیاری</string>\n    <string name=\"open_file\">فایلەکە بکەرەوە</string>\n    <string name=\"restart\">دووباره‌ هه‌لكردنووكوژانه‌وه‌</string>\n    <string name=\"status_error\">هەڵە</string>\n    <string name=\"copy_link\">کۆپی بەستەر</string>\n    <string name=\"copy_error_report\">ڕاپۆرتی هەڵە</string>\n    <string name=\"video_resolution\">ڕوونی ڤیدیۆ</string>\n    <string name=\"video_file_size\">قەبارەی فایلە ڤیدیۆییەکان</string>\n    <string name=\"template_exported\">%1$d هەناردەکراوی قاڵب(ەکان)</string>\n    <string name=\"template_imported\">هاوردەکراوی %1$d قاڵب(ەکان)</string>\n    <string name=\"recently_added\">بەم دواییە زیاد کراوە</string>\n    <string name=\"sponsorblock_desc\">لابردن یان نیشانەکردنی بەشەکان لە ڤیدیۆکاندا بە SponsorBlock API</string>\n    <string name=\"task_canceled\">ئەرکی دابەزاندن هەڵوەشایەوە</string>\n    <string name=\"export_to_clipboard\">هەناردەکردن بۆ کلیپبۆرد</string>\n    <string name=\"import_from_clipboard\">لە کلیپبۆردەوە هاوردە بکە</string>\n    <string name=\"download_task_count\">%1$d ئەرکەکانی دابەزاندن</string>\n    <string name=\"multiselect_item_count\">%1$d ڤیدیۆ(ەکان)، %2$d فایل(ەکان)ی دەنگی</string>\n    <string name=\"delete_multiple_items_msg\">%1$d item(s) لە مێژووی دابەزاندنەکەت بۆ هەمیشە لادەبەیت؟</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-cs/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">Uložit jako zvuk</string>\n    <string name=\"create_thumbnail\">Uložit miniaturu</string>\n    <string name=\"download_settings_desc\">Obecné, formát, vlastní příkaz</string>\n    <string name=\"yt_dlp_up_to_date\">Používáte nejnovější verzi yt-dlp</string>\n    <string name=\"permission_denied\">Oprávnění zamítnuto</string>\n    <string name=\"download_success_msg\">Stahování dokončeno</string>\n    <string name=\"download_error_msg\">Stahování souboru selhalo</string>\n    <string name=\"download_start_msg\">Stahování „%1$s“</string>\n    <string name=\"fetch_info_error_msg\">Získávání informací o videu selhalo</string>\n    <string name=\"task_running\">Již probíhá jiná stahovací úloha</string>\n    <string name=\"paste_msg\">Vložit adresu</string>\n    <string name=\"paste_fail_msg\">Nepodařilo se najít adresu ve schránce</string>\n    <string name=\"ytdlp_version\">Yt-dlp verze</string>\n    <string name=\"delete_info\">Odstranit\\?</string>\n    <string name=\"confirm\">Potvrdit</string>\n    <string name=\"dismiss\">Zrušit</string>\n    <string name=\"downloads_history\">Stažené soubory</string>\n    <string name=\"about_page\">Verze, zpětná vazba, automatické aktualizace</string>\n    <string name=\"back\">Zpět</string>\n    <string name=\"version\">Verze</string>\n    <string name=\"release_desc\">Otevřít seznamy změn a nové verze</string>\n    <string name=\"release\">Nejnovější vydání</string>\n    <string name=\"checked\">Zkontrolováno</string>\n    <string name=\"credits\">Poděkování</string>\n    <string name=\"custom_command\">Vlastní příkaz</string>\n    <string name=\"custom_command_desc\">Spustit příkaz yt-dlp s vlastní šablonou</string>\n    <string name=\"edit\">Upravit</string>\n    <string name=\"start_execute\">Zahájeno provádění příkazu</string>\n    <string name=\"display\">Zobrazení</string>\n    <string name=\"display_settings\">Tmavý motiv, dynamická barva, jazyk</string>\n    <string name=\"dark_theme\">Tmavý motiv</string>\n    <string name=\"follow_system\">Podle systému</string>\n    <string name=\"on\">Zapnuto</string>\n    <string name=\"off\">Vypnuto</string>\n    <string name=\"cancel\">Zrušit</string>\n    <string name=\"settings_before_download\">Konfigurace před stažením</string>\n    <string name=\"settings_before_download_desc\">Upřesnit předvolby před stažením</string>\n    <string name=\"settings_before_download_text\">Upravit tohle stahování</string>\n    <string name=\"error_copied\">Chybová zpráva zkopírována do schránky</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"paste\">Vložit</string>\n    <string name=\"yt_dlp_docs\">Návod k používání yt-dlp</string>\n    <string name=\"convert_audio_format\">Převést formát zvuku</string>\n    <string name=\"not_convert\">Nepřevedeno</string>\n    <string name=\"convert_to\">Převést na %1$s</string>\n    <string name=\"convert_audio_format_desc\">Překódování zvukových souborů zapříčiní ztrátu zvukové kvality a zvýší velikost souboru.</string>\n    <string name=\"video_quality\">Kvalita videa</string>\n    <string name=\"not_specified\">Nespecifikován (výchozí)</string>\n    <string name=\"preferred_format_desc\">Preferovaný formát při dostupnosti více formátů</string>\n    <string name=\"start_download\">Stáhnout</string>\n    <string name=\"close_never_show_again\">Již nezobrazovat</string>\n    <string name=\"user_guide\">Uživatelská příručka</string>\n    <string name=\"open_settings\">Otevřít nastavení</string>\n    <string name=\"download_history_desc\">Přehled a správa stažených souborů, včetně videí i zvukových souborů.</string>\n    <string name=\"download_playlist\">Stáhnout playlist</string>\n    <string name=\"download_playlist_desc\">Stáhnout několik videí z playlistu</string>\n    <string name=\"channel_name\">Stahování</string>\n    <string name=\"channel_description\">Oznámení o stažených souborech a průběhu stahování</string>\n    <string name=\"execute_command_notification\">Spouštění vlastních příkazů…</string>\n    <string name=\"battery_settings_desc\">Pro stahování na pozadí nastavte v systémových nastaveních využití baterie pro tuto aplikaci na „Neomezeno“.</string>\n    <string name=\"concurrent_download\">Stahování ve více vláknech</string>\n    <string name=\"options\">Možnosti</string>\n    <string name=\"additional_settings\">Další nastavení</string>\n    <string name=\"share_fail_msg\">Nelze nalézt URL ze sdíleného obsahu</string>\n    <string name=\"share_success_msg\">Hledání odkazu videa ze sdíleného obsahu…</string>\n    <string name=\"show_more_actions\">Zobrazit více akcí</string>\n    <string name=\"download_notification\">Oznámení o stahování</string>\n    <string name=\"fetching_playlist_info\">Získávání informací o playlistu…</string>\n    <string name=\"download_range_selection\">Rozmezí playlistu</string>\n    <string name=\"from\">Od</string>\n    <string name=\"to\">Do</string>\n    <string name=\"invalid_index_range\">Neplatný rozsah</string>\n    <string name=\"playlist_indicator_text\">Stahování playlistu (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Složka zvuku</string>\n    <string name=\"download_directory\">Adresář pro stahování</string>\n    <string name=\"download_directory_desc\">Vyberte, kam ukládat videa a zvukové soubory</string>\n    <string name=\"subdirectory\">Uložit do podsložky</string>\n    <string name=\"subdirectory_desc\">Ukládat soubory do složek pojmenovaných jako příslušná pole</string>\n    <string name=\"permission_issue\">Problém s oprávněním</string>\n    <string name=\"permission_issue_desc\">Složky mimo Download/ a Documents/ nejsou podporovány</string>\n    <string name=\"battery_configuration_desc\">Ignorovat optimalizaci baterie pro tuto aplikaci ke stahování na pozadí</string>\n    <string name=\"language\">Jazyk</string>\n    <string name=\"video_directory\">Složka videí</string>\n    <string name=\"settings\">Nastavení</string>\n    <string name=\"yt_dlp_update_fail\">Instalace nejnovější verze yt-dlp selhala. Zkontrolujte prosím připojení k internetu.</string>\n    <string name=\"fetching_info\">Získávání informací o videu…</string>\n    <string name=\"delete_info_msg\">Navždy odstranit „%1$s“ z historie stahování?</string>\n    <string name=\"remove\">Odstranit</string>\n    <string name=\"download\">Stahování</string>\n    <string name=\"url_empty\">Odkaz nemůže být prázdný</string>\n    <string name=\"extract_audio_summary\">Stáhnout a uložit zvuk namísto videa</string>\n    <string name=\"create_thumbnail_summary\">Uložit miniaturu videa jako soubor</string>\n    <string name=\"language_settings\">Nastavit jazyk</string>\n    <string name=\"audio\">Zvuk</string>\n    <string name=\"link_copied\">Odkaz zkopírován do schránky</string>\n    <string name=\"open_url\">Otevřít odkaz</string>\n    <string name=\"delete_file\">Odstranit soubor</string>\n    <string name=\"custom_command_template\">Šablona příkazu</string>\n    <string name=\"general_settings\">Obecné</string>\n    <string name=\"ytdlp_update\">Klikněte pro nainstalování nejnovější verze yt-dlp</string>\n    <string name=\"about\">O aplikaci</string>\n    <string name=\"readme_desc\">Otevřít repozitář na GitHubu a soubor README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"credits_desc\">Poděkování a svobodný software</string>\n    <string name=\"advanced_settings\">Pokročílé</string>\n    <string name=\"print_details\">Podrobné informace</string>\n    <string name=\"print_details_desc\">Zobrazit podrobné informace při stahování</string>\n    <string name=\"edit_template_desc\">Cesta k souboru a URL budou automaticky přidány aplikací.</string>\n    <string name=\"format\">Formát</string>\n    <string name=\"video_quality_desc\">Omezit kvalitu videa, pokud je jich přítomno více</string>\n    <string name=\"video_format\">Formát videa</string>\n    <string name=\"best_quality\">Nejlepší kvalita</string>\n    <string name=\"video_format_preference\">Preferovaný formát videa</string>\n    <string name=\"close\">Zavřít</string>\n    <string name=\"paste_desc\">Klepněte na „Vložit“ pro získání odkazu na video ze schránky.</string>\n    <string name=\"download_desc\">Po úpravě nastavení klepněte na „Stáhnout“.</string>\n    <string name=\"check_download_settings_desc\">Před používáním se podívejte se na nastavení stahování a ujistěte se, že máte nejnovější verzi yt-dlp.</string>\n    <string name=\"convert_audio\">Převést</string>\n    <string name=\"defaults\">Výchozi</string>\n    <string name=\"video_url\">Odkaz na video</string>\n    <string name=\"unknown_error\">Neznámá chyba</string>\n    <string name=\"download_finish_notification\">Stahování dokončeno. Stiskněte pro otevření.</string>\n    <string name=\"concurrent_download_desc\">Paralelně stahovat více částí videí M3U8/MPD</string>\n    <string name=\"download_notification_desc\">Oznamovat stažené soubory a postup stahování</string>\n    <string name=\"concurrent_download_num\">Počet vláken pro souběžné stahování DASH/HLS native videí je %d.</string>\n    <string name=\"download_range_desc\">Upřesněte rozsah videí ke stažení z playlistu „%3$s“ (od %1$d do %2$d).</string>\n    <string name=\"battery_configuration\">Nastavení baterie</string>\n    <string name=\"service_title\">Seal stahuje…</string>\n    <string name=\"translate\">Překlad</string>\n    <string name=\"translate_desc\">Pomozte přeložit tuto aplikaci na Hosted Weblate</string>\n    <string name=\"prefix\">Předpona</string>\n    <string name=\"status_enqueued\">Ve frontě</string>\n    <string name=\"status_completed\">Dokončeno</string>\n    <string name=\"status_downloading\">Stahuje se</string>\n    <string name=\"status_canceled\">Zrušeno</string>\n    <string name=\"status_fetching_video_info\">Získávání informací</string>\n    <string name=\"open_file\">Otevřit soubor</string>\n    <string name=\"restart\">Restartovat</string>\n    <string name=\"embed_subtitles\">Vložit titulky</string>\n    <string name=\"embed_subtitles_desc\">Vložit soubory titulků do videí, pokud jsou dostupné</string>\n    <string name=\"new_template\">Nová šablona</string>\n    <string name=\"template_label\">Štítek</string>\n    <string name=\"remove_template\">Odstranit\\?</string>\n    <string name=\"remove_template_desc\">Navždy ddstranit „%1$s“ z šablon příkazů?</string>\n    <string name=\"template_selection\">Výběr šablony</string>\n    <string name=\"custom_command_template_desc\">Upravit a spravovat šablony příkazu</string>\n    <string name=\"downloading_indicator_text\">Probíhá stahování…</string>\n    <string name=\"task_canceled\">Stahování zrušeno</string>\n    <string name=\"github_issue\">Problém na GitHubu</string>\n    <string name=\"github_issue_desc\">Vytvořit nový problém pro nahlášení chyby nebo žádost o funkci</string>\n    <string name=\"info_copied\">Informace zkopírovány do schránky</string>\n    <string name=\"general_settings_desc\">Verze yt-dlp, upozornění, playlist</string>\n    <string name=\"check_for_updates\">Zkontrolovat aktualizace</string>\n    <string name=\"app_up_to_date\">Používáte nejnovější verzi</string>\n    <string name=\"update\">Aktualizovat</string>\n    <string name=\"cookies\">Soubory cookie</string>\n    <string name=\"video_resolution\">Rozlišení videa</string>\n    <string name=\"download_disabled_with_cellular\">Stahování pomocí mobilní sítě je podle vašeho nastavení zakázáno</string>\n    <string name=\"max_rate\">Maximální rychlost</string>\n    <string name=\"dynamic_color_desc\">Použít barvy z tapety v motivu aplikace</string>\n    <string name=\"multiselect_mode\">Režim vícenásobného výběru</string>\n    <string name=\"clear_temp_files_info\">Dočasné soubory lze použít k obnovení zrušených stahování. Opravdu chcete všechny tyto soubory odstranit?\n\\n\n\\nTyto soubory se nacházejí v %1$s</string>\n    <string name=\"rate_limit_desc\">Omezit maximální rychlost stahování</string>\n    <string name=\"check_for_updates_desc\">Automaticky kontrolovat nejnovější verzi na GitHubu</string>\n    <string name=\"recently_added\">Nedávno přidané</string>\n    <string name=\"template_imported\">Importovány %1$d šablony</string>\n    <string name=\"download_task_count\">%1$d Naplánovaných stahování</string>\n    <string name=\"app_update_failed\">Aktualizace na nejnovější verzi selhala</string>\n    <string name=\"sponsorblock_categories\">Kategorie SponsorBlocku</string>\n    <string name=\"clear_temp_files\">Vymazat dočasné soubory</string>\n    <string name=\"clear_temp_files_desc\">Odstranit všechny dočasné soubory z dočasného adresáře</string>\n    <string name=\"private_mode_desc\">Zakázat historii stahování</string>\n    <string name=\"invalid_input\">Neplatné zadání</string>\n    <string name=\"unavailable\">Nedostupné</string>\n    <string name=\"template_exported\">Exportovány %1$d šablony</string>\n    <string name=\"rate_limit\">Omezení rychlosti</string>\n    <string name=\"cookies_desc\">Pro stahování používat soubory cookie ve formátu Netscape</string>\n    <string name=\"private_mode\">Soukromý režim</string>\n    <string name=\"dynamic_color\">Dynamická barva</string>\n    <string name=\"download_with_cellular_desc\">Povolit stahování médií při připojení k měřeným sítím</string>\n    <string name=\"file_unavailable\">Tento soubor již není k dispozici</string>\n    <string name=\"status_error\">Chyba</string>\n    <string name=\"export_to_clipboard\">Exportovat do schránky</string>\n    <string name=\"import_from_clipboard\">Importovat ze schránky</string>\n    <string name=\"multiselect_item_count\">%1$d video souborů, %2$d zvukových souborů</string>\n    <string name=\"delete_multiple_items_msg\">Nadobro odstranit %1$d položek z vaší historie stahování\\?</string>\n    <string name=\"sponsorblock_desc\">Odstranit nebo označit sponzorované části videí pomocí API SponsorBlock</string>\n    <string name=\"aria2_desc\">Používat aria2c jako externího správce stahování</string>\n    <string name=\"copy_link\">Kopírovat odkaz</string>\n    <string name=\"copy_error_report\">Kopírovat hlášení</string>\n    <string name=\"video_file_size\">Velikost souboru videa</string>\n    <string name=\"high_contrast\">Tmavý motiv s vysokým kontrastem</string>\n    <string name=\"format_settings_desc\">Formát souboru, kvalita videa, titulky</string>\n    <string name=\"clear_temp_files_count\">Odstraněno %1$d dočasných souborů</string>\n    <string name=\"download_with_cellular\">Stahovat pomocí mobilní sítě</string>\n    <string name=\"network\">Síť</string>\n    <string name=\"lowest_quality\">Nejnižší kvalita</string>\n    <string name=\"sponsorblock_categories_desc\">Upřesněte kategorie SponsorBlocku, které mají být odstraněny nebo označeny v souboru videa</string>\n    <string name=\"save\">Uložit</string>\n    <string name=\"restrict_filenames_desc\">Omezit názvy souborů na určité znaky pro zajištění kompatibility</string>\n    <string name=\"restrict_filenames\">Omezit názvy souborů</string>\n    <string name=\"embed_metadata\">Vložit metadata</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"show_all_items\">Zobrazit všech %1$d položek</string>\n    <string name=\"edit_file\">Upravit soubor</string>\n    <string name=\"embed_metadata_desc\">Vložit metadata a miniaturu videa do zvukového souboru</string>\n    <string name=\"switch_to_github_builds\">přechod na sestavení z GitHubu</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp je výkonný nástroj pro příkazový řádek sloužící ke stahování videí. Seal zjednodušuje jeho používání díky intuitivnímu grafickému rozhraní, přednastavením pro časté příkazy a dalším dodatečným funkcím.\n\\n\n\\nPokročilým uživatelům nástroje yt-dlp umožňuje Seal vytvářet, ukládat a přímo spouštět vlastní šablony příkazů, stejně jako v terminálu.\n\\n\n\\nPři používání vlastních příkazů bude většina možností a funkcí v grafickém rozhraní vypnuta.</string>\n    <string name=\"clear_download_archive\">Vyčistit archiv stahování?</string>\n    <string name=\"clip_start\">Začít</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"split_video_msg\">Video bude rozděleno na %1$d dílů</string>\n    <string name=\"remove_cookie_profile_desc\">Odstranit tuto položku pro „%1$s“? Soubory cookie uložené pro tuto stránku nebudou vymazány.</string>\n    <string name=\"audio_quality\">Kvalita zvuku</string>\n    <string name=\"audio_format\">Formát zvuku</string>\n    <string name=\"title\">Název</string>\n    <string name=\"use_cookies\">Použít cookies</string>\n    <string name=\"export_to_file\">Exportovat do souboru</string>\n    <string name=\"stable_channel\">Stabilní</string>\n    <string name=\"enable_notifications_desc\">Aplikace potřebuje váš souhlas pro zasílání upozornění o stavu a postupu stahování.</string>\n    <string name=\"folder_picker\">Výběr složky</string>\n    <string name=\"no_downloaded_media\">Žádná stažená média</string>\n    <string name=\"update_channel_desc\">Instalujte předběžné sestavení aplikace abyste mohli nahlédnout na nové funkce a změny.\n\\n\n\\nTato sestavení mohou být nestabilní, pokud se tedy setkáte s nějakými problémy, prosím neváhejte a poskytněte nám zpětnou vazbu pro pomoc s vylepšováním aplikace do budoucna.</string>\n    <string name=\"edit_shortcuts_desc\">Upravit vlastní zkratky, které mohou být použity pro vytváření šablon pro příkazy.</string>\n    <string name=\"video_only\">Video (bez zvuku)</string>\n    <string name=\"split_video\">Rozdělit video</string>\n    <string name=\"prefer_compatibility_desc\">Upřednostnit formáty MP4(H.264) pro sdílení v ostatních aplikacích</string>\n    <string name=\"download_video_desc\">Stáhnout videa z URL</string>\n    <string name=\"commands\">Příkazy</string>\n    <string name=\"disable_preview\">Zakázat náhled</string>\n    <string name=\"clip_video_dialog_msg\">Stahování používající tuto funkci budou předány FFmpeg ke stažení vybraných částí videa, tato funkce je stále experimentální a stříhání videa nebude naprosto přesné, některé formáty tuto funkci nepodporují a můžete se setkat s pomalejším stahováním.</string>\n    <string name=\"custom_command_enabled_hint\">Některé možnosti jsou nedostupné při používání vlastních příkazů</string>\n    <string name=\"clear_download_archive_desc\">Navždy odstranit %1$s v archivním souboru?</string>\n    <string name=\"disable_preview_desc\">Nezobrazovat náhledy při stahování</string>\n    <string name=\"format_selection_desc\">Vybrat formát souboru před zahájením stahování</string>\n    <string name=\"clip_end\">Konec</string>\n    <string name=\"edit_template\">Upravit „%1$s“</string>\n    <string name=\"auto_subtitle_desc\">Stahovat automaticky generované titulky</string>\n    <string name=\"selected_item_count\">%1$d vybráno</string>\n    <string name=\"suggested\">Doporučené</string>\n    <string name=\"clear\">Vyčistit</string>\n    <string name=\"unknown\">Neznámé</string>\n    <string name=\"download_subtitles\">Stahovat titulky</string>\n    <string name=\"learn_more\">Zjistit více</string>\n    <string name=\"rename\">Přejmenovat</string>\n    <string name=\"convert_subtitle\">Převést titulky</string>\n    <string name=\"prefer_quality_desc\">Upřednostnit formáty AV1, VP9 nebo H.265 pro sledování v kompatibilních aplikacích</string>\n    <string name=\"copy_log\">Zkopírovat log</string>\n    <string name=\"download_type\">Typ stahování</string>\n    <string name=\"apply\">Aplikovat</string>\n    <string name=\"legacy\">Starší verze</string>\n    <string name=\"clip_video_desc\">Vytvářejte klipy z videa na stránce s výběrem formátu</string>\n    <string name=\"unknown_error_title\">Jejda! Chybička se vloudila</string>\n    <string name=\"unlimited\">Neomezený</string>\n    <string name=\"edit_shortcuts\">Upravit zkratky</string>\n    <string name=\"how_does_it_work\">Jak to funguje?</string>\n    <string name=\"got_it\">Rozumím</string>\n    <string name=\"custom_command_directory\">Adresář pro vlastní příkazy</string>\n    <string name=\"format_selection\">Výběr formátu</string>\n    <string name=\"custom_command_directory_desc\">Upřesněte výstupní adresář při používání vlastních příkazů</string>\n    <string name=\"use_format_sorting\">Použít třídění formátů</string>\n    <string name=\"feedback\">Zpětná vazba</string>\n    <string name=\"network_settings_desc\">Omezení rychlosti, stahování, soubory cookie</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"clear_all_cookies\">Smazat všechny cookies</string>\n    <string name=\"presets\">Přednastavení</string>\n    <string name=\"second\">sekunda</string>\n    <string name=\"set_directory_desc\">Klikněte pro nastavení adresáře</string>\n    <string name=\"update_channel\">Kanál aktualizací</string>\n    <string name=\"sponsor_msg\">Seal bude vždy zdarma a open source pro každého. Pokud se vám aplikace líbí, prosím zvažte sponzorování na GitHubu!</string>\n    <string name=\"crop_artwork\">Oříznout obrázek</string>\n    <string name=\"subtitle_sponsorblock\">Titulky mohou mít špatné časování při odstranění SponsorBlock segmentů.</string>\n    <string name=\"start\">Začít</string>\n    <string name=\"sponsor_msg2\">Moc vám děkujeme!</string>\n    <string name=\"sponsor_desc\">Podpořte tuto aplikaci sponzorováním na GitHubu</string>\n    <string name=\"enable_experimental_feature\">Povolit experimentální funkce?</string>\n    <string name=\"running_tasks\">Běžící úlohy</string>\n    <string name=\"ua_header\">Hlavička s User-Agentem</string>\n    <string name=\"show_logs\">Ukázat log</string>\n    <string name=\"discard\">Zahodit</string>\n    <string name=\"sdcard_directory\">Složka na SD kartě</string>\n    <string name=\"audio_format_preference\">Preferovaný formát zvuku</string>\n    <string name=\"new_task\">Nová úloha pro stahování</string>\n    <string name=\"copy_and_exit\">Zkopírovat a odejít</string>\n    <string name=\"private_directory_desc\">Ukládat stažené soubory do skrytého adresáře</string>\n    <string name=\"select_all\">Vybrat vše</string>\n    <string name=\"format_sorting_desc\">Třídit formáty s možností -S v nástroji yt-dlp</string>\n    <string name=\"auto_update\">Automatické aktualizace</string>\n    <string name=\"sponsor\">Sponzor</string>\n    <string name=\"auto_subtitle\">Automatické titulky</string>\n    <string name=\"required\">Vyžadované</string>\n    <string name=\"embed_subtitles_mkv_msg\">Pro účel vložení souborů titulků budou videa převedena do kontejneru mkv. Pro přehrávání videí se soubory titulků můžete použít například VLC Media Player nebo jiné kompatibilní aplikace.</string>\n    <string name=\"abs_hint\">Většina platforem pro streamování videa poskytuje zvuk a video odděleně, můžete vybrat a sloučit zvukové a video formáty do jednoho videa.</string>\n    <string name=\"no_custom_command_tasks\">Žádná úloha s vlastními příkazy</string>\n    <string name=\"enable_auto_update\">Povolit automatické aktualizace</string>\n    <string name=\"lowest_bitrate\">Nejnižší bitrate</string>\n    <string name=\"format_preference\">Upřednostňovaný formát</string>\n    <string name=\"pre_release_channel\">Náhled</string>\n    <string name=\"convert_subtitle_desc\">Konvertovat titulky na jiný formát</string>\n    <string name=\"video_title_sample_text\">Ukázkový text pro název videa</string>\n    <string name=\"use_custom_command\">Použít vlastní příkaz</string>\n    <string name=\"output_template\">Šablona výstupu</string>\n    <string name=\"output_template_desc\">Upřesněte šablonu pro názvy souborů ve výstupu</string>\n    <string name=\"subtitle_language\">Jazyk titulků</string>\n    <string name=\"audio_quality_desc\">Omezit datový tok zvuku, když je dostupných několik různých kvalit</string>\n    <string name=\"disabled\">Zakázané</string>\n    <string name=\"private_directory\">Soukromý adresář</string>\n    <string name=\"disable\">Zakázat</string>\n    <string name=\"okay\">Dobře</string>\n    <string name=\"auto\">Automaticky</string>\n    <string name=\"shortcuts\">Zkratky</string>\n    <string name=\"download_selection_desc\">Vyberte videa ke stažení z playlistu „%1$s“</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d položka</item>\n        <item quantity=\"few\">%d položky</item>\n        <item quantity=\"other\">%d položek</item>\n    </plurals>\n    <string name=\"video_creator_sample_text\">Ukázkový text pro autora videa</string>\n    <string name=\"expand\">Rozšířit</string>\n    <string name=\"telegram_channel\">Kanál na Telegramu</string>\n    <string name=\"feature_unavailable\">Funkce není dostupná</string>\n    <string name=\"temporary_directory_desc\">Uložit dočasné soubory v interním adresáři</string>\n    <string name=\"auto_update_disabled_msg\">Automatické aktualizace nejsou dostupné pro sestavení ze služby %1$s. Pokud nemáte na zařízení nainstalovanou službu %1$s nebo pokud byste chtěli vidět nadcházející nové funkce v Sealu, zvažte prosím %2$s.</string>\n    <string name=\"cookies_usage_msg\">Stahování z některých stránek vyžaduje autentifikační informace z účtu. Klepněte na „Vygenerovat nové cookies“, zadejte adresu stránky a poté se přihlaste s vaším účtem v okně prohlížeče, aplikace se postará o vygenerování za vás.</string>\n    <string name=\"proxy_desc\">Použít proxy pro připojení k internetu</string>\n    <string name=\"generate_new_cookies\">Vygenerovat nové cookies</string>\n    <string name=\"quality\">Kvalita</string>\n    <string name=\"refresh_cookies_desc\">Klikněte pro otevření webové stránky pro generování nových cookies:</string>\n    <string name=\"matrix_space\">Prostor Matrix</string>\n    <string name=\"subtitle\">Titulky</string>\n    <string name=\"msg_from_developer\">Zpráva od vývojáře</string>\n    <string name=\"import_from_preferences\">Importovat</string>\n    <string name=\"clip_video\">Klip z videa</string>\n    <string name=\"share\">Sdílet</string>\n    <string name=\"add\">Přidat</string>\n    <string name=\"privacy\">Soukromí</string>\n    <string name=\"download_archive_desc\">Zaznamená ID stažených videí v archivu pro zamezení duplikátům</string>\n    <string name=\"custom\">Vlastní</string>\n    <string name=\"ytdlp_update_action\">Aktualizovat yt-dlp</string>\n    <string name=\"title_activity_share\">Rychlé stáhnutí</string>\n    <string name=\"crop_artwork_desc\">Oříznout vložený obrázek do čtverce</string>\n    <string name=\"download_archive\">Archiv stahování</string>\n    <string name=\"subtitle_desc\">Jazyky, vložené titulky, automatické titulky</string>\n    <string name=\"remove_multiple_templates_msg\">Navždy odstranit %1$s z šablon pro příkazy?</string>\n    <string name=\"enable_notifications\">Povolit upozornění?</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"sponsors\">Sponzoři</string>\n    <string name=\"clear_all_cookies_desc\">Chcete navždy smazat všechny cookies uložené v aplikaci?</string>\n    <string name=\"minute\">minuta</string>\n    <string name=\"format_sorting\">Třídění formátů</string>\n    <string name=\"subdirectory_hint\">Vaše stahování budou uložena jako:</string>\n    <string name=\"website\">Webová stránka</string>\n    <string name=\"playlist_title\">Název playlistu</string>\n    <string name=\"dont_allow\">Nepovolit</string>\n    <string name=\"force_ipv4\">Vynutit IPv4</string>\n    <string name=\"allow_once\">Povolit pouze jednou</string>\n    <string name=\"allow_always\">Povolit vždy</string>\n    <string name=\"download_with_cellular_request\">Povolit stahování přes datové připojení?</string>\n    <string name=\"merge_audiostream\">Sloučit několik zvukových streamů</string>\n    <string name=\"merge_audiostream_desc\">Povolit spojení několika zvukových streamů do jednoho souboru</string>\n    <string name=\"keep_subtitle_files\">Ponechat soubor s titulky</string>\n    <string name=\"system_settings\">Nastavení systému</string>\n    <string name=\"force_ipv4_desc\">Provádět veškerá připojení přes IPv4</string>\n    <string name=\"search_in_downloads\">Hledat ve stažených souborech</string>\n    <string name=\"search\">Hledat</string>\n    <string name=\"update_subtitle_languages\">Aktualizovat jazyky titulků?</string>\n    <string name=\"auto_translated_subtitles\">Automaticky přeložené titulky</string>\n    <string name=\"auto_translated_subtitles_msg\">Automaticky přeložené titulky pro všechny jazyky budou k dispozici ve Stažených. Tyto titulky mohou být nepřesné a obtížné na porozumění.</string>\n    <string name=\"remember_for_next_download\">Zapamatovat pro další stahování</string>\n    <string name=\"look_and_feel\"><![CDATA[Zobrazení a styl]]></string>\n    <string name=\"use_previous_selection\">Použít předchozí výběr</string>\n    <string name=\"none\">Žádný</string>\n    <string name=\"subtitle_language_desc\">Jazyk titulků ke stažení ve výběru Auto formátu, oddělené čárkami.</string>\n    <string name=\"reset\">Resetovat</string>\n    <string name=\"search_in_subtitles\">Vyhledat v titulcích</string>\n    <string name=\"no_thanks\">Ne, díky</string>\n    <string name=\"update_language_msg\">Následující jazyky budou přidány do vašich preferencí pro budoucí stahování:</string>\n    <string name=\"download_archive_error\">Video bylo staženo. Pokud jste tohle nechtěli, prosím, zkontrolujte váš archiv stažených souborů.</string>\n    <string name=\"file\">Soubor</string>\n    <string name=\"export_backup\">Exportovat</string>\n    <string name=\"import_backup\">Importovat</string>\n    <string name=\"full_backup\">Úplná záloha</string>\n    <string name=\"export_download_history_msg\">Exportování %1$s z historie stahování. Stažené soubory a preference nebudou zálohovány.</string>\n    <string name=\"interface_and_interaction\"><![CDATA[Rozhraní a interakce]]></string>\n    <string name=\"backup_type\">Typ zálohy</string>\n    <string name=\"export_to\">Exportovat do</string>\n    <string name=\"clipboard\">Schránka</string>\n    <string name=\"import_from\">Importovat z</string>\n    <string name=\"export_download_history\">Exportovat historii stahování?</string>\n    <string name=\"import_download_history\">Importovat historii stahování?</string>\n    <string name=\"import_download_history_msg\">Stažené soubory nebudou importovány. Budete je muset znovu stáhnout manuálně</string>\n    <string name=\"download_history\">Historie stahování</string>\n    <string name=\"download_history_imported\">Importováno %1$s do historie stahování</string>\n    <string name=\"redownload\">Stáhnout znovu</string>\n    <string name=\"remux_container_mkv\">Převést kontejner videa</string>\n    <string name=\"remux_container_mkv_desc\">Převést videa do kontejneru MKV pro lepší kompatibilitu</string>\n    <string name=\"cookies_in_database\">Celkem %1$d souborů cookie z %2$d webových stránek</string>\n    <string name=\"every_day\">Každý den</string>\n    <string name=\"every_week\">Každý týden</string>\n    <string name=\"every_month\">Každý měsíc</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d audio</item>\n        <item quantity=\"few\">%d audia</item>\n        <item quantity=\"other\">%d audií</item>\n    </plurals>\n    <string name=\"task_added\">Úloha přidána do fronty</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d video</item>\n        <item quantity=\"few\">%d videa</item>\n        <item quantity=\"other\">%d videí</item>\n    </plurals>\n    <string name=\"playlist\">Playlist</string>\n    <string name=\"all_languages\">Všechny jazyky</string>\n    <string name=\"preset\">Předvolba</string>\n    <string name=\"proceed\">Pokračovat</string>\n    <string name=\"prefer_placeholder\">Upřednostnit %1$s</string>\n    <string name=\"custom_format_selection_desc\">Vyberte si z formátů, titulků a dále si přizpůsobte aplikaci</string>\n    <string name=\"preset_format_selection_desc\">Automaticky stáhnout s použitím vašich preferencí formátů</string>\n    <string name=\"edit_preset\">Upravit předvolbu</string>\n    <string name=\"best_quality_desc\">Stáhnout nejlepší dostupný formát</string>\n    <string name=\"you_ll_find_your_downloads_here\">Zde najdete svá stahování</string>\n    <string name=\"download_hint\">Pro spuštění stahování klepněte na tlačítko stahování nebo sdílejte video do této aplikace</string>\n    <string name=\"status_downloaded\">Stažené</string>\n    <string name=\"all\">Vše</string>\n    <string name=\"select_multiple_link\">Vyberte z %1$d odkazů</string>\n    <string name=\"download_queue\">Fronta stahování</string>\n    <string name=\"show_navigation_drawer\">Zobrazit navigační lištu</string>\n    <string name=\"resume\">Pokračovat</string>\n    <string name=\"delete\">Smazat</string>\n    <string name=\"media_info\">Informace o médiu</string>\n    <string name=\"trouble_shooting\">Řešení problémů</string>\n    <string name=\"issue_tracker\">Sledování problémů</string>\n    <string name=\"trouble_shooting_desc\">Opravte běžné chyby a zjistěte známé problémy</string>\n    <string name=\"issue_tracker_hint\">Našli jste chybu? Před jejím nahlášením prosím prohledejte náš systém sledování chyb. Mnoho problémů zde již bylo řešeno a zdokumentováno.</string>\n    <string name=\"saved_urls\">Uložené odkazy</string>\n    <string name=\"add_new_url\">Přidat nový odkaz</string>\n    <string name=\"add_to\">Přidat do %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-da/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"create_thumbnail\">Lagre som miniaturbilde</string>\n    <string name=\"settings\">Indstillinger</string>\n    <string name=\"download_settings_desc\">Generelt, format, tilpasset kommando</string>\n    <string name=\"extract_audio_summary\">Last ned og gem lyd, i stedet for video</string>\n    <string name=\"yt_dlp_up_to_date\">Bruger nyeste version af yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Kunne ikke installere den seneste yt-dlp-version. Kontroller at du har forbindelse til Internet.</string>\n    <string name=\"fetching_info\">Henter videoinfo …</string>\n    <string name=\"download_success_msg\">Nedlastning fuldført</string>\n    <string name=\"download_error_msg\">Kunne ikke laste ned fil</string>\n    <string name=\"download_start_msg\">Last ned «%1$s»</string>\n    <string name=\"fetch_info_error_msg\">Kunne ikke hente videoinfo</string>\n    <string name=\"general_settings\">Generelt</string>\n    <string name=\"language\">Visningssprog</string>\n    <string name=\"language_settings\">Vælg visningssprog</string>\n    <string name=\"task_running\">En eksisterende nedlastningsopgave kører allerede</string>\n    <string name=\"paste_msg\">Lim ind URL fra udklipsholderen</string>\n    <string name=\"paste_fail_msg\">Kunne ikke matche URL\\'en i udklipsholderen</string>\n    <string name=\"ytdlp_version\">Yt-dlp-version</string>\n    <string name=\"video_directory\">Videomappe</string>\n    <string name=\"extract_audio\">Lagre som lyd</string>\n    <string name=\"url_empty\">Link til indhold kan ikke være tom</string>\n    <string name=\"download\">Last ned</string>\n    <string name=\"create_thumbnail_summary\">Gem video miniaturbilde som en fil</string>\n    <string name=\"permission_denied\">Tilgang ikke indvilget</string>\n    <string name=\"ytdlp_update\">Klik for at installere den seneste yt-dlp-versionen</string>\n    <string name=\"delete_info\">Fjern\\?</string>\n    <string name=\"start_execute\">Begynd udføring af kommando</string>\n    <string name=\"display\">Visning</string>\n    <string name=\"convert_audio\">Konverter</string>\n    <string name=\"follow_system\">System</string>\n    <string name=\"on\">På</string>\n    <string name=\"cancel\">Afbryd</string>\n    <string name=\"video_format_preference\">Foretrukket videoformat</string>\n    <string name=\"format\">Format</string>\n    <string name=\"video_format\">Videoformat</string>\n    <string name=\"start_download\">Last ned</string>\n    <string name=\"close\">Luk</string>\n    <string name=\"close_never_show_again\">Ikke vis igen</string>\n    <string name=\"open_settings\">Åbne indstillingerne</string>\n    <string name=\"additional_settings\">Flere indstillinger</string>\n    <string name=\"to\">Slut</string>\n    <string name=\"invalid_index_range\">Ugyldigt indeksområde</string>\n    <string name=\"playlist_indicator_text\">Download spilleliste (%1$d/%2$d), tryk for at stoppe.</string>\n    <string name=\"service_title\">Seal laster ned …</string>\n    <string name=\"unknown_error\">Ukendt feil</string>\n    <string name=\"translate\">Overset</string>\n    <string name=\"confirm\">Bekræft</string>\n    <string name=\"dismiss\">Afbryd</string>\n    <string name=\"downloads_history\">Nedlastninger</string>\n    <string name=\"audio\">Lyd</string>\n    <string name=\"open_url\">Åbn link</string>\n    <string name=\"remove\">Fjern</string>\n    <string name=\"about\">Om</string>\n    <string name=\"about_page\">Version, udgivelser, bidragsydere</string>\n    <string name=\"back\">Tilbage</string>\n    <string name=\"version\">Version</string>\n    <string name=\"release\">Nyeste udgivelse</string>\n    <string name=\"video\">Video</string>\n    <string name=\"credits\">Bidragsydere</string>\n    <string name=\"credits_desc\">Bidragsydere og fri programvare</string>\n    <string name=\"custom_command\">Tilpasset kommando</string>\n    <string name=\"custom_command_desc\">Kør yt-dlp-kommando med tilpasset mal</string>\n    <string name=\"custom_command_template\">Kommandomal</string>\n    <string name=\"edit\">Rediger</string>\n    <string name=\"delete_info_msg\">Fjern «%1$s» fra din nedlastningshistorik for godt\\?</string>\n    <string name=\"link_copied\">Lænke kopieret til udklipsholderen</string>\n    <string name=\"delete_file\">Slet</string>\n    <string name=\"release_desc\">Se efter ændringslister og nye versioner</string>\n    <string name=\"readme_desc\">Tjek GitHub depotet og README</string>\n    <string name=\"checked\">Tjekket</string>\n    <string name=\"advanced_settings\">Avancered</string>\n    <string name=\"off\">Af</string>\n    <string name=\"paste\">Lim ind</string>\n    <string name=\"yt_dlp_docs\">Brugsreference for yt-dlp</string>\n    <string name=\"convert_to\">Konverter til %1$s</string>\n    <string name=\"convert_audio_format_desc\">Omkodning af lydfiler vil forårsage tab i lydkvalitet og øge filstørrelsen.</string>\n    <string name=\"video_quality\">Videokvalitet</string>\n    <string name=\"not_specified\">Ikke angivet (forvalg)</string>\n    <string name=\"preferred_format_desc\">Valgt format når flere forefindes</string>\n    <string name=\"settings_before_download\">Konfigurer før download</string>\n    <string name=\"display_settings\">Mørk dragt, dynamiske farver, sprog</string>\n    <string name=\"dark_theme\">Mørk dragt</string>\n    <string name=\"print_details\">Detaljeret uddata</string>\n    <string name=\"print_details_desc\">Udskriv detaljerede meddelelser under download</string>\n    <string name=\"settings_before_download_desc\">Konfigurer præferencer før nedlastning</string>\n    <string name=\"settings_before_download_text\">Juster denne download</string>\n    <string name=\"error_copied\">Fejlrapport kopieret til udklipsholderen</string>\n    <string name=\"thumbnail\">miniaturbilde</string>\n    <string name=\"edit_template_desc\">Uddatasti og URL vil blive tillagt af programmet.</string>\n    <string name=\"convert_audio_format\">Konverter lydformat</string>\n    <string name=\"not_convert\">Ukonverteret</string>\n    <string name=\"best_quality\">Bedste kvalitet (forvalg)</string>\n    <string name=\"video_quality_desc\">Begræns videokvaliteten, når flere er tilgængelige</string>\n    <string name=\"user_guide\">Brugervejledning</string>\n    <string name=\"download_playlist\">Last ned spilleliste</string>\n    <string name=\"defaults\">Forvalg</string>\n    <string name=\"channel_name\">Last ned</string>\n    <string name=\"concurrent_download\">Download med flere tråde</string>\n    <string name=\"concurrent_download_desc\">Download flere dele af M3U8/MPD-videoer parallelt</string>\n    <string name=\"options\">Alternativer</string>\n    <string name=\"show_more_actions\">Vis flere handlinger</string>\n    <string name=\"download_range_selection\">Valg af spilleliste</string>\n    <string name=\"from\">Start</string>\n    <string name=\"download_directory_desc\">Vælg hvor videoer og lydfiler lagres</string>\n    <string name=\"audio_directory\">Lydmappe</string>\n    <string name=\"download_directory\">Downloadmappe</string>\n    <string name=\"subdirectory\">Lagre i undermappe</string>\n    <string name=\"subdirectory_desc\">Lagre filer i mapper navngivet som respektive internetsider</string>\n    <string name=\"permission_issue\">Problem med lagringstilgang</string>\n    <string name=\"paste_desc\">Klik «Lim ind» for at hente videolænke fra udklipsholderen.</string>\n    <string name=\"download_desc\">Klik så «Last ned» når du har justeret dens indstillinger.</string>\n    <string name=\"download_history_desc\">Tjek og kontroller nedlastninger i programmet, inkluderet videoer og lydfiler.</string>\n    <string name=\"check_download_settings_desc\">Kig på nedlastningsindstillingerne og sørg for at du har nyeste version af yt-dlp før du tar det i brug.</string>\n    <string name=\"download_playlist_desc\">Last ned flere videoer fra en spilleliste</string>\n    <string name=\"channel_description\">Tilby meddelelse om nedlastede filer og fremdrift</string>\n    <string name=\"video_url\">Videolænke</string>\n    <string name=\"download_finish_notification\">Download fuldført. Klik for at åbne.</string>\n    <string name=\"execute_command_notification\">Kører tilpassede kommandoer …</string>\n    <string name=\"battery_settings_desc\">Indstil batteriforbrug for dette program til «Ubegrænset» i systemindstillingerne for at laste ned i baggrunden.</string>\n    <string name=\"concurrent_download_num\">%d tråd(er) bil blive brugt samtidig for nedlastning af DASH/HLS native -video.</string>\n    <string name=\"share_fail_msg\">Kan ikke matche URL fra delt indhold</string>\n    <string name=\"share_success_msg\">Læser videolænke fra delt indhold …</string>\n    <string name=\"download_notification_desc\">Tilby meddelelse om filer og fremdrift</string>\n    <string name=\"download_range_desc\">Angiv hvilke videoer, der skal downloades fra afspilningslisten \\\"%3$s\\\" (fra %1$d til %2$d).</string>\n    <string name=\"permission_issue_desc\">Mapper udenfor Download/ og Documents/ understøttes ikke</string>\n    <string name=\"translate_desc\">Bistå oversættelsen af programmet på Hosted Weblate</string>\n    <string name=\"battery_configuration_desc\">Ignorer batterioptimering så dette program kan laste ned i baggrunden</string>\n    <string name=\"fetching_playlist_info\">Henter spillelisteinfo …</string>\n    <string name=\"download_notification\">Meddelelse om nedlastning</string>\n    <string name=\"battery_configuration\">Konfiguration af batteri</string>\n    <string name=\"prefix\">Path template</string>\n    <string name=\"audio_format_preference\">Foretrukket lydformat</string>\n    <string name=\"unlimited\">Ubegrænset</string>\n    <string name=\"lowest_bitrate\">Laveste bitrate</string>\n    <string name=\"audio_quality\">Lydkvalitet</string>\n    <string name=\"audio_quality_desc\">Begræns lydbitraten, når der er flere tilgængelige kvaliteter</string>\n    <string name=\"format_sorting\">Formatsortering</string>\n    <string name=\"format_sorting_desc\">Sortering af formater med yt-dlp\\'s -S indstilling</string>\n    <string name=\"import_from_preferences\">Importer</string>\n    <string name=\"title\">Titel</string>\n    <string name=\"rename\">Omdøb</string>\n    <string name=\"second\">Sekund</string>\n    <string name=\"minute\">Minut</string>\n    <string name=\"clear_all_cookies\">Ryd alle cookies</string>\n    <string name=\"clear_all_cookies_desc\">Vil du slette alle de cookies, der er gemt i appen\\?</string>\n    <string name=\"filesize_mb\">%.2f M</string>\n    <string name=\"filesize_gb\">%.2f G</string>\n    <string name=\"downloading_indicator_text\">Download i gang, tryk for at annullere.</string>\n    <string name=\"subtitle_sponsorblock\">Undertekster kan være forkert timet, når SponsorBlock-segmenter fjernes.</string>\n    <string name=\"share\">Del</string>\n    <string name=\"stable_channel\">Stable</string>\n    <string name=\"pre_release_channel\">Preview</string>\n    <string name=\"update_channel_desc\">Installer pre-release builds for at få vist nye funktioner og ændringer.\n\\n\n\\nDer vil være en vis ustabilitet i disse versioner, så tøv ikke med at give os feedback, hvis du oplever problemer for at hjælpe os med at forbedre appen for fremtiden.</string>\n    <string name=\"enable_auto_update\">Aktiver automatisk opdatering</string>\n    <string name=\"status_canceled\">Annulleret</string>\n    <string name=\"status_fetching_video_info\">Henter info</string>\n    <string name=\"sponsorblock_categories_desc\">Angiv SponsorBlock-kategorier, der skal fjernes fra videofilen</string>\n    <string name=\"aria2_desc\">Brug aria2c som ekstern downloader</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"video_creator_sample_text\">Eksempeltekst til video creator</string>\n    <string name=\"edit_shortcuts\">Rediger genveje</string>\n    <string name=\"download_with_cellular\">Download over mobildata</string>\n    <string name=\"download_with_cellular_desc\">Tillad download af medier over forbrugsafregnet netværk</string>\n    <string name=\"download_disabled_with_cellular\">Download med mobilnetværk er deaktiveret i henhold til dine indstillinger</string>\n    <string name=\"network\">Netværk</string>\n    <string name=\"rate_limit\">Hastighedsgrænse</string>\n    <string name=\"rate_limit_desc\">Begræns den maksimale downloadhastighed</string>\n    <string name=\"discard\">Kassér</string>\n    <string name=\"apply\">Anvend</string>\n    <string name=\"clip_video\">Klip video</string>\n    <string name=\"clip_start\">Start</string>\n    <string name=\"clip_end\">Slut</string>\n    <string name=\"embed_subtitles\">Integrer undertekster</string>\n    <string name=\"embed_subtitles_desc\">Integrer undertekster i videoer, hvis de er tilgængelige</string>\n    <string name=\"download_task_count\">%1$d Downloads</string>\n    <string name=\"app_update_failed\">Kunne ikke opdatere til nyeste version</string>\n    <string name=\"app_up_to_date\">Den aktuelle version er opdateret</string>\n    <string name=\"copy_link\">Kopier link</string>\n    <string name=\"select_all\">Vælg alle</string>\n    <string name=\"template_imported\">Importerede %1$d skabelon(er)</string>\n    <string name=\"task_canceled\">Download annulleret</string>\n    <string name=\"use_custom_command\">Brug brugerdefineret kommando</string>\n    <string name=\"private_directory_desc\">Gem downloads i en skjult mappe</string>\n    <string name=\"import_from_clipboard\">Importer fra udklipsholder</string>\n    <string name=\"cookies_desc\">Brug Netscape-formaterede cookies til downloads</string>\n    <string name=\"status_completed\">Afsluttet</string>\n    <string name=\"suggested\">Foreslået</string>\n    <string name=\"private_mode\">Privat tilstand</string>\n    <string name=\"github_issue_desc\">Indsend problem til fejlrapport eller funktionsanmodning</string>\n    <string name=\"video_resolution\">Videoopløsning</string>\n    <string name=\"how_does_it_work\">Hvordan virker det\\?</string>\n    <string name=\"info_copied\">Info kopieret til udklipsholder</string>\n    <string name=\"export_to_clipboard\">Eksporter til udklipsholder</string>\n    <string name=\"multiselect_mode\">Multiselect-tilstand</string>\n    <string name=\"private_mode_desc\">Deaktiver downloadhistorik</string>\n    <string name=\"dynamic_color_desc\">Anvend farver fra wallpapers til app-temaet</string>\n    <string name=\"dynamic_color\">Dynamisk farve</string>\n    <string name=\"crop_artwork_desc\">Beskær indlejret billede til firkant</string>\n    <string name=\"download_selection_desc\">Vælg videoer, der skal downloades fra afspilningslisten \\\"%1$s\\\"</string>\n    <string name=\"selected_item_count\">%1$d valgt</string>\n    <string name=\"status_enqueued\">I kø</string>\n    <string name=\"recently_added\">Nyligt Tilføjet</string>\n    <string name=\"multiselect_item_count\">%1$d video(er), %2$d lydfil(er)</string>\n    <string name=\"delete_multiple_items_msg\">Fjern %1$d element(er) fra din downloadhistorik for altid\\?</string>\n    <string name=\"new_template\">Ny skabelon</string>\n    <string name=\"template_label\">Etiket</string>\n    <string name=\"remove_template\">Fjern\\?</string>\n    <string name=\"remove_template_desc\">Fjern \\\"%1$s\\\" fra kommandoskabeloner for altid\\?</string>\n    <string name=\"template_selection\">Skabelonvalg</string>\n    <string name=\"custom_command_template_desc\">Rediger og administrer kommandoskabeloner</string>\n    <string name=\"status_downloading\">Downloader</string>\n    <string name=\"open_file\">Åbn fil</string>\n    <string name=\"video_file_size\">Video filstørrelse</string>\n    <string name=\"template_exported\">Eksporterede %1$d skabelon(er)</string>\n    <string name=\"check_for_updates\">Søg efter opdateringer</string>\n    <string name=\"clear_temp_files_count\">Slettede %1$d midlertidig(e) fil(er)</string>\n    <string name=\"clear_temp_files_info\">Midlertidige filer kan bruges til at genoptage annullerede downloads. Bekræft at du vil slette disse filer\\?</string>\n    <string name=\"generate_new_cookies\">Generer nye cookies</string>\n    <string name=\"format_selection_desc\">Vælg det format, der skal downloades, før du starter download</string>\n    <string name=\"use_cookies\">Brug Cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Fjern cookies for \\\"%1$s\\\"?</string>\n    <string name=\"custom_command_enabled_hint\">Nogle muligheder er utilgængelige, når brugerdefineret kommando bruges</string>\n    <string name=\"cookies_usage_msg\">Download fra nogle websteder kræver kontogodkendelse. Klik på \\\"Generer nye cookies\\\", indtast webadressen på hjemmesiden og log derefter ind med din konto på browsersiden; appen genererer den nye cookie for dig.</string>\n    <string name=\"telegram_channel\">Telegram-kanal</string>\n    <string name=\"abs_hint\">De fleste videostreamingplatforme leverer lyd og video separat, du kan vælge og flette et lydformat med et videoformat til en enkelt video.</string>\n    <string name=\"github_issue\">GitHub-problem</string>\n    <string name=\"restart\">Genstart</string>\n    <string name=\"copy_error_report\">Fejlrapport</string>\n    <string name=\"sponsorblock_desc\">Fjern segmenter fra videoer med SponsorBlock API</string>\n    <string name=\"status_error\">Fejl</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock-kategorier</string>\n    <string name=\"check_for_updates_desc\">Søg automatisk efter den nyeste version på GitHub</string>\n    <string name=\"update\">Opdater</string>\n    <string name=\"clear_temp_files\">Ryd midlertidige filer</string>\n    <string name=\"clear_temp_files_desc\">Slet alle midlertidige filer fra download-mappen</string>\n    <string name=\"file_unavailable\">Filen er ikke længere tilgængelig</string>\n    <string name=\"high_contrast\">Mørkt tema med høj kontrast</string>\n    <string name=\"invalid_input\">Ugyldigt input</string>\n    <string name=\"lowest_quality\">Laveste kvalitet</string>\n    <string name=\"unavailable\">Utilgængelig</string>\n    <string name=\"format_settings_desc\">Filformat, videokvalitet, undertekster</string>\n    <string name=\"general_settings_desc\">Yt-dlp version, notifikation, afspilningsliste</string>\n    <string name=\"disable_preview\">Deaktiver forhåndsvisning</string>\n    <string name=\"disable_preview_desc\">Deaktiver forhåndsvisning på downloads</string>\n    <string name=\"privacy\">Privatliv</string>\n    <string name=\"private_directory\">Privat mappe</string>\n    <string name=\"crop_artwork\">Beskær grafik</string>\n    <string name=\"video_only\">Video (ingen lyd)</string>\n    <string name=\"format_selection\">Formatvalg</string>\n    <string name=\"sdcard_directory\">SD-kort mappe</string>\n    <string name=\"auto_subtitle\">Automatiske undertekster</string>\n    <string name=\"auto_subtitle_desc\">Download autogenererede undertekster</string>\n    <string name=\"title_activity_share\">Hurtig download</string>\n    <string name=\"video_title_sample_text\">Eksempeltekst på videotitel</string>\n    <string name=\"subtitle\">Undertekst</string>\n    <string name=\"download_subtitles\">Download undertekster</string>\n    <string name=\"subtitle_language\">Undertekstsprog</string>\n    <string name=\"subtitle_desc\">Sprog, integrer undertekster, autoundertekster</string>\n    <string name=\"copy_log\">Kopiér log</string>\n    <string name=\"clear\">Ryd</string>\n    <string name=\"add\">Tilføj</string>\n    <string name=\"shortcuts\">Genveje</string>\n    <string name=\"edit_shortcuts_desc\">Rediger de brugerdefinerede genveje, som kan bruges til at lave kommandoskabeloner.</string>\n    <string name=\"running_tasks\">Kørende opgaver</string>\n    <string name=\"show_logs\">Vis log</string>\n    <string name=\"embed_subtitles_mkv_msg\">Ved indlejring af undertekster vil videoer blive remuxet til mkv-container.</string>\n    <string name=\"temporary_directory_desc\">Gem midlertidige filer i den interne mappe</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-de/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"create_thumbnail\">Miniaturansicht speichern</string>\n    <string name=\"url_empty\">Der Link darf nicht leer sein</string>\n    <string name=\"extract_audio_summary\">Audio herunterladen und speichern, statt Video</string>\n    <string name=\"create_thumbnail_summary\">Vorschaubild des Videos als Datei speichern</string>\n    <string name=\"yt_dlp_up_to_date\">Verwendung der neuesten Version von yt-dlp</string>\n    <string name=\"fetching_info\">Videoinformationen werden abgerufen…</string>\n    <string name=\"permission_denied\">Keine Berechtigung</string>\n    <string name=\"download_success_msg\">Download abgeschlossen</string>\n    <string name=\"download_error_msg\">Datei konnte nicht heruntergeladen werden</string>\n    <string name=\"download_start_msg\">„%1$s“ herunterladen</string>\n    <string name=\"fetch_info_error_msg\">Videoinformationen konnten nicht abgerufen werden</string>\n    <string name=\"general_settings\">Allgemein</string>\n    <string name=\"language_settings\">Anzeigesprache festlegen</string>\n    <string name=\"task_running\">Eine bestehende Download-Aufgabe wird bereits ausgeführt</string>\n    <string name=\"paste_msg\">Link einfügen</string>\n    <string name=\"delete_info\">Entfernen\\?</string>\n    <string name=\"delete_info_msg\">„%1$s“ für immer aus deinem Downloadverlauf entfernen\\?</string>\n    <string name=\"confirm\">Bestätigen</string>\n    <string name=\"dismiss\">Abbrechen</string>\n    <string name=\"downloads_history\">Downloads</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Link in die Zwischenablage kopiert</string>\n    <string name=\"open_url\">Link öffnen</string>\n    <string name=\"remove\">Entfernen</string>\n    <string name=\"about_page\">Version, Rückmeldung, Automatisches Update</string>\n    <string name=\"back\">Zurück</string>\n    <string name=\"version\">Version</string>\n    <string name=\"release_desc\">Siehe Änderungsprotokolle und neue Versionen</string>\n    <string name=\"release\">Neueste Version</string>\n    <string name=\"readme_desc\">Prüfe das GitHub-Repository und die README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Geprüft</string>\n    <string name=\"credits\">Credits</string>\n    <string name=\"credits_desc\">Credits und freie Software</string>\n    <string name=\"display\">Anzeige</string>\n    <string name=\"dark_theme\">Dunkles Farbschema</string>\n    <string name=\"settings_before_download\">Vor dem Herunterladen konfigurieren</string>\n    <string name=\"settings_before_download_desc\">Einstellungen vor dem Herunterladen konfigurieren</string>\n    <string name=\"settings_before_download_text\">Diesen Download anpassen</string>\n    <string name=\"error_copied\">Fehlerbericht in die Zwischenablage kopiert</string>\n    <string name=\"thumbnail\">Vorschaubild</string>\n    <string name=\"paste\">Einfügen</string>\n    <string name=\"channel_name\">Herunterladen</string>\n    <string name=\"defaults\">Standard</string>\n    <string name=\"video_url\">Videolink</string>\n    <string name=\"download_finish_notification\">Download beendet. Zum Öffnen antippen.</string>\n    <string name=\"download_playlist\">Wiedergabeliste herunterladen</string>\n    <string name=\"download_playlist_desc\">Mehrere Videos aus einer Wiedergabeliste herunterladen</string>\n    <string name=\"user_guide\">Benutzerhandbuch</string>\n    <string name=\"open_settings\">Einstellungen öffnen</string>\n    <string name=\"start_download\">Herunterladen</string>\n    <string name=\"video_format_preference\">Bevorzugtes Videoformat</string>\n    <string name=\"video_format\">Videoformat</string>\n    <string name=\"video_quality\">Videoqualität</string>\n    <string name=\"best_quality\">Beste Qualität</string>\n    <string name=\"video_directory\">Videoverzeichnis</string>\n    <string name=\"settings\">Einstellungen</string>\n    <string name=\"yt_dlp_update_fail\">Die neueste Version von yt-dlp konnte nicht installiert werden. Bitte stelle sicher, dass du mit dem Internet verbunden bist.</string>\n    <string name=\"language\">Angezeigte Sprache</string>\n    <string name=\"paste_fail_msg\">Link in der Zwischenablage konnte nicht gefunden werden</string>\n    <string name=\"ytdlp_version\">Yt-dlp-Version</string>\n    <string name=\"ytdlp_update\">Klicke hier, um die neueste Version von yt-dlp zu installieren</string>\n    <string name=\"options\">Optionen</string>\n    <string name=\"extract_audio\">Als Audio speichern</string>\n    <string name=\"download_settings_desc\">Allgemein, Format, benutzerdefinierter Befehl</string>\n    <string name=\"about\">Über</string>\n    <string name=\"download\">Herunterladen</string>\n    <string name=\"delete_file\">Datei Löschen</string>\n    <string name=\"display_settings\">Dunkles Farbschema, dynamische Farben, Sprachen</string>\n    <string name=\"cancel\">Abbrechen</string>\n    <string name=\"custom_command\">Benutzerdefinierter Befehl</string>\n    <string name=\"close_never_show_again\">Nicht mehr anzeigen</string>\n    <string name=\"edit\">Bearbeiten</string>\n    <string name=\"follow_system\">System</string>\n    <string name=\"on\">Ein</string>\n    <string name=\"off\">Aus</string>\n    <string name=\"close\">Schließen</string>\n    <string name=\"preferred_format_desc\">Bevorzugtes Format, wenn mehrere vorhanden sind</string>\n    <string name=\"not_specified\">Nicht angegeben (Standard)</string>\n    <string name=\"video_quality_desc\">Einschränken der Videoqualität, wenn mehrere vorhanden sind</string>\n    <string name=\"custom_command_desc\">yt-dlp-Befehl mit benutzerdefinierter Vorlage ausführen</string>\n    <string name=\"custom_command_template\">Befehlsvorlage</string>\n    <string name=\"start_execute\">Befehl ausführen</string>\n    <string name=\"advanced_settings\">Erweiterte</string>\n    <string name=\"print_details\">Detaillierte Ausgabe</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp-Verwendungshinweise</string>\n    <string name=\"convert_to\">In %1$s konvertieren</string>\n    <string name=\"convert_audio_format\">Audioformat konvertieren</string>\n    <string name=\"concurrent_download\">Multithread-Download</string>\n    <string name=\"concurrent_download_desc\">Mehrere Teile von M3U8/MPD-Videos parallel herunterladen</string>\n    <string name=\"show_more_actions\">Weitere Aktionen anzeigen</string>\n    <string name=\"download_notification\">Benachrichtigung beim Herunterladen</string>\n    <string name=\"download_notification_desc\">Benachrichtigung über heruntergeladene Dateien und den Fortschritt</string>\n    <string name=\"fetching_playlist_info\">Wiedergabeliste-Informationen werden abgerufen …</string>\n    <string name=\"download_range_selection\">Wiedergabeliste-Auswahl</string>\n    <string name=\"download_directory_desc\">Wähle den Speicherort für Videos und Audiodateien</string>\n    <string name=\"subdirectory\">In Unterordner speichern</string>\n    <string name=\"subdirectory_desc\">Dateien in Ordnern mit den Namen der jeweiligen Felder speichern</string>\n    <string name=\"permission_issue\">Problem mit der Speicherberechtigung</string>\n    <string name=\"battery_configuration\">Akkukonfiguration</string>\n    <string name=\"battery_configuration_desc\">Akku-Optimierung für diese App ignorieren, um im Hintergrund herunterzuladen</string>\n    <string name=\"service_title\">Seal lädt herunter …</string>\n    <string name=\"channel_description\">Benachrichtigung über heruntergeladene Dateien und den Fortschritt</string>\n    <string name=\"additional_settings\">Zusätzliche Einstellungen</string>\n    <string name=\"playlist_indicator_text\">Herunterladen der Wiedergabeliste (%1$d/%2$d)…</string>\n    <string name=\"format\">Format</string>\n    <string name=\"print_details_desc\">Detaillierte Meldungen beim Herunterladen drucken</string>\n    <string name=\"not_convert\">Nicht konvertieren</string>\n    <string name=\"audio_directory\">Audioordner</string>\n    <string name=\"battery_settings_desc\">Bitte setze die Akkunutzung dieser App in den Systemeinstellungen auf „Uneingeschränkt“, um im Hintergrund herunterzuladen.</string>\n    <string name=\"share_fail_msg\">URL aus geteilten Inhalt kann nicht zugeordnet werden</string>\n    <string name=\"download_directory\">Downloadordner</string>\n    <string name=\"unknown_error\">Unbekannter Fehler</string>\n    <string name=\"execute_command_notification\">Benutzerdefinierte Befehlen ausführen …</string>\n    <string name=\"translate\">Übersetzen</string>\n    <string name=\"translate_desc\">Hilf bei der Übersetzung dieser App auf Weblate</string>\n    <string name=\"edit_template_desc\">Ausgabepfad und URL werden von der App hinzugefügt.</string>\n    <string name=\"convert_audio\">Konvertieren</string>\n    <string name=\"paste_desc\">Klicke auf „Einfügen“, um den Videolink aus der Zwischenablage zu holen.</string>\n    <string name=\"download_desc\">Klicke dann auf „Herunterladen“, nachdem du die Einstellungen angepasst hast.</string>\n    <string name=\"download_history_desc\">Überprüfe und verwalte In-App-Downloads, einschließlich Videos und Audiodateien.</string>\n    <string name=\"check_download_settings_desc\">Schaue dir die Download-Einstellungen an und stelle sicher, dass du die neueste Version von yt-dlp hast, bevor du es verwendest.</string>\n    <string name=\"concurrent_download_num\">%d Thread(s) würden für das gleichzeitige Herunterladen von nativen DASH/HLS-Videos verwendet werden.</string>\n    <string name=\"share_success_msg\">Videolink von geteilten Inhalten lesen…</string>\n    <string name=\"download_range_desc\">Gib den Bereich der Videos an, die aus der Wiedergabeliste „%3$s“ heruntergeladen werden sollen (von %1$d bis %2$d).</string>\n    <string name=\"to\">Ende</string>\n    <string name=\"invalid_index_range\">Ungültiger Indexbereich</string>\n    <string name=\"permission_issue_desc\">Ordner außerhalb von Download/ und Dokumente/ werden nicht unterstützt</string>\n    <string name=\"convert_audio_format_desc\">Die Neukodierung von Audiodateien führt zu einem Verlust an Audioqualität und einer Vergrößerung der Datei.</string>\n    <string name=\"from\">Start</string>\n    <string name=\"prefix\">Ordnervorlage</string>\n    <string name=\"embed_subtitles\">Untertitel einbetten</string>\n    <string name=\"embed_subtitles_desc\">Einbetten von weichen Untertiteln in Videos, sofern verfügbar</string>\n    <string name=\"new_template\">Neue Vorlage</string>\n    <string name=\"template_label\">Label</string>\n    <string name=\"remove_template\">Entfernen\\?</string>\n    <string name=\"remove_template_desc\">„%1$s“ endgültig aus den Befehlsvorlagen entfernen\\?</string>\n    <string name=\"template_selection\">Vorlagenauswahl</string>\n    <string name=\"custom_command_template_desc\">Befehlsvorlagen bearbeiten und verwalten</string>\n    <string name=\"downloading_indicator_text\">Download läuft…</string>\n    <string name=\"task_canceled\">Download-Aufgabe wurde abgebrochen</string>\n    <string name=\"github_issue\">GitHub-Problem</string>\n    <string name=\"info_copied\">Informationen in die Zwischenablage kopiert</string>\n    <string name=\"github_issue_desc\">Einreichen eines Fehlerberichts oder einer Funktionsanfrage</string>\n    <string name=\"status_enqueued\">Eingereiht</string>\n    <string name=\"status_completed\">Fertig</string>\n    <string name=\"status_downloading\">Wird heruntergeladen</string>\n    <string name=\"status_canceled\">Abgebrochen</string>\n    <string name=\"status_fetching_video_info\">Informationen abrufen</string>\n    <string name=\"open_file\">Datei öffnen</string>\n    <string name=\"restart\">Neustarten</string>\n    <string name=\"status_error\">Fehler</string>\n    <string name=\"copy_link\">Link kopieren</string>\n    <string name=\"copy_error_report\">Bericht kopieren</string>\n    <string name=\"video_resolution\">Videoauflösung</string>\n    <string name=\"video_file_size\">Größe der Videodatei</string>\n    <string name=\"export_to_clipboard\">In Zwischenablage exportieren</string>\n    <string name=\"import_from_clipboard\">Aus Zwischenablage importieren</string>\n    <string name=\"template_exported\">Exportierte %1$d Vorlage(n)</string>\n    <string name=\"template_imported\">Importierte %1$d Vorlage(n)</string>\n    <string name=\"recently_added\">Kürzlich hinzugefügt</string>\n    <string name=\"multiselect_item_count\">%1$d Video(s), %2$d Audio-Datei(en)</string>\n    <string name=\"delete_multiple_items_msg\">%1$d für immer aus deinem Downloadverlauf entfernen\\?</string>\n    <string name=\"download_task_count\">%1$d Download-Aufgaben</string>\n    <string name=\"check_for_updates\">Nach Aktualisierungen suchen</string>\n    <string name=\"check_for_updates_desc\">Automatisch nach der neuesten Version auf GitHub suchen</string>\n    <string name=\"app_up_to_date\">Die aktuelle Version ist auf dem neuesten Stand</string>\n    <string name=\"update\">Aktualisieren</string>\n    <string name=\"aria2_desc\">Aria2c als externen Downloader verwenden</string>\n    <string name=\"app_update_failed\">Aktualisierung auf die neueste Version fehlgeschlagen</string>\n    <string name=\"sponsorblock_desc\">Segmente aus Videos mit SponsorBlock-API entfernen oder markieren</string>\n    <string name=\"sponsorblock_categories_desc\">Gib die SponsorBlock-Kategorien an, die aus der Videodatei entfernt oder markiert werden sollen</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock-Kategorien</string>\n    <string name=\"cookies_desc\">Netscape-formatierte Cookies für Downloads verwenden</string>\n    <string name=\"clear_temp_files\">Temporäre Dateien löschen</string>\n    <string name=\"clear_temp_files_desc\">Alle temporären Dateien aus dem temporären Ordner löschen</string>\n    <string name=\"clear_temp_files_info\">Temporäre Dateien können verwendet werden, um abgebrochene Downloads wieder aufzunehmen. Bist du sicher, dass du alle diese Dateien löschen willst?\n\\n\n\\nDu kannst diese Dateien zugreifen unter %1$s</string>\n    <string name=\"clear_temp_files_count\">%1$d temporäre Datei(en) gelöscht</string>\n    <string name=\"multiselect_mode\">Mehrfachauswahl-Modus</string>\n    <string name=\"private_mode_desc\">Download-Verlauf deaktivieren</string>\n    <string name=\"private_mode\">Inkognito</string>\n    <string name=\"dynamic_color\">Dynamische Farbe</string>\n    <string name=\"dynamic_color_desc\">Farben von Hintergrundbildern auf das Farbschema anwenden</string>\n    <string name=\"download_with_cellular\">Herunterladen über Mobilfunk</string>\n    <string name=\"download_with_cellular_desc\">Herunterladen von Medien erlauben, wenn du mit gebührenpflichtigen Netzwerken verbunden bist</string>\n    <string name=\"download_disabled_with_cellular\">Das Herunterladen über das Mobilfunknetz ist gemäß deinen Einstellungen deaktiviert</string>\n    <string name=\"file_unavailable\">Diese Datei ist nicht mehr verfügbar</string>\n    <string name=\"network\">Netzwerk</string>\n    <string name=\"rate_limit\">Geschwindigkeitsbegrenzung</string>\n    <string name=\"rate_limit_desc\">Maximale Downloadgeschwindigkeit limitieren</string>\n    <string name=\"max_rate\">Maximale Geschwindigkeit</string>\n    <string name=\"high_contrast\">Dunkles Farbschema mit hohem Kontrast</string>\n    <string name=\"invalid_input\">Ungültige Eingabe</string>\n    <string name=\"lowest_quality\">Niedrigste Qualität</string>\n    <string name=\"format_settings_desc\">Dateiformat, Videoqualität, Untertitel</string>\n    <string name=\"disable_preview\">Vorschau deaktivieren</string>\n    <string name=\"unavailable\">Nicht verfügbar</string>\n    <string name=\"privacy\">Datenschutz</string>\n    <string name=\"use_custom_command\">Benutzerdefinierten Befehl verwenden</string>\n    <string name=\"general_settings_desc\">Yt-dlp Version, Benachrichtigung, Wiedergabeliste</string>\n    <string name=\"network_settings_desc\">Ratenbegrenzung, Downloader, Cookies</string>\n    <string name=\"disable_preview_desc\">Keine Anzeige von Vorschaubildern während des Downloads</string>\n    <string name=\"private_directory\">Privater Ordner</string>\n    <string name=\"private_directory_desc\">Downloads in einem versteckten Ordner speichern</string>\n    <string name=\"crop_artwork\">Bild zuschneiden</string>\n    <string name=\"crop_artwork_desc\">Eingebettetes Bild auf ein Quadrat zuschneiden</string>\n    <string name=\"select_all\">Alle auswählen</string>\n    <string name=\"selected_item_count\">%1$d ausgewählt</string>\n    <string name=\"download_selection_desc\">Wähle die Videos zum Herunterladen aus der Wiedergabeliste „%1$s“</string>\n    <string name=\"video_only\">Video (kein Audio)</string>\n    <string name=\"suggested\">Vorgeschlagen</string>\n    <string name=\"format_selection\">Auswahl des Formats</string>\n    <string name=\"format_selection_desc\">Wähle das herunterzuladende Format, bevor du den Download startest</string>\n    <string name=\"generate_new_cookies\">Neue Cookies generieren</string>\n    <string name=\"use_cookies\">Cookies verwenden</string>\n    <string name=\"remove_cookie_profile_desc\">Diesen Eintrag für „%1$s“ entfernen? Bitte beachte, dass gespeicherte Cookies für diese Seite nicht gelöscht werden.</string>\n    <string name=\"custom_command_enabled_hint\">Einige Optionen sind bei Verwendung des benutzerdefinierten Befehls nicht verfügbar</string>\n    <string name=\"how_does_it_work\">Wie funktioniert das\\?</string>\n    <string name=\"cookies_usage_msg\">Für das Herunterladen von einigen Webseiten sind Informationen zur Kontoauthentifizierung erforderlich. Klicke auf „Neue Cookies generieren“, gib die URL der Webseite ein und melde dich dann mit deinem Konto auf der Browserseite an, damit die App sie für dich generieren kann.</string>\n    <string name=\"telegram_channel\">Telegram-Kanal</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"matrix_space\">Matrix-Raum</string>\n    <string name=\"abs_hint\">Die meisten Videostreaming-Plattformen liefern Audio und Video getrennt. Du kannst ein reines Audioformat auswählen und mit einem reinen Videoformat zu einem einzigen Video zusammenfügen.</string>\n    <string name=\"edit_shortcuts_desc\">Individuelle Verknüpfungen bearbeiten, die zur Erstellung von Befehlsvorlagen verwendet werden können.</string>\n    <string name=\"running_tasks\">Laufende Aufgaben</string>\n    <string name=\"auto_subtitle\">Automatische Untertitel</string>\n    <string name=\"title_activity_share\">Schnelles Herunterladen</string>\n    <string name=\"video_title_sample_text\">Videotitel Beispieltext</string>\n    <string name=\"video_creator_sample_text\">Videoersteller Beispieltext</string>\n    <string name=\"subtitle\">Untertitel</string>\n    <string name=\"download_subtitles\">Untertitel herunterladen</string>\n    <string name=\"subtitle_desc\">Sprachen, Untertitel einbetten, automatische Untertitel</string>\n    <string name=\"copy_log\">Protokoll kopieren</string>\n    <string name=\"clear\">Löschen</string>\n    <string name=\"edit_shortcuts\">Verknüpfungen bearbeiten</string>\n    <string name=\"show_logs\">Protokoll anzeigen</string>\n    <string name=\"logs\">Protokoll</string>\n    <string name=\"shortcuts\">Verknüpfungen</string>\n    <string name=\"sdcard_directory\">SD-Kartenordner</string>\n    <string name=\"auto_subtitle_desc\">Automatisch generierte Untertitel herunterladen</string>\n    <string name=\"subtitle_language\">Untertitelsprachen</string>\n    <string name=\"add\">Hinzufügen</string>\n    <string name=\"subtitle_sponsorblock\">Untertitel können beim Entfernen von SponsorBlock-Segmenten falsch synchronisiert werden.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Zum Einbetten von Untertiteln werden die Videos in einen mkv-Container zusammengefügt. Du kannst den VLC Media Player oder andere kompatible Apps verwenden, um Videos mit eingebetteten weichen Untertiteln anzusehen.</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"pre_release_channel\">Vorschau</string>\n    <string name=\"auto_update\">Automatische Aktualisierung</string>\n    <string name=\"update_channel\">Update-Kanal</string>\n    <string name=\"share\">Teilen</string>\n    <string name=\"update_channel_desc\">Installiere Vorabversionen, um eine Vorschau der neuen Funktionen und Änderungen erhalten.\n\\n\n\\nEs wird einige Instabilitäten in diesen Versionen geben, also zögere bitte nicht, uns Feedback zu geben, wenn du Probleme hast, um uns zu helfen, die App für die Zukunft zu verbessern.</string>\n    <string name=\"enable_auto_update\">Automatische Aktualisierung aktivieren</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"clip_end\">Ende</string>\n    <string name=\"discard\">Verwerfen</string>\n    <string name=\"apply\">Anwenden</string>\n    <string name=\"clip_video\">Video schneiden</string>\n    <string name=\"clip_start\">Anfang</string>\n    <string name=\"lowest_bitrate\">Niedrigste Bitrate</string>\n    <string name=\"audio_quality\">Audioqualität</string>\n    <string name=\"audio_quality_desc\">Audio-Bitrate begrenzen, wenn mehrere Qualitäten vorhanden sind</string>\n    <string name=\"format_sorting\">Formatsortierung</string>\n    <string name=\"import_from_preferences\">Importieren</string>\n    <string name=\"title\">Titel</string>\n    <string name=\"second\">Sekunde</string>\n    <string name=\"minute\">Minute</string>\n    <string name=\"clear_all_cookies_desc\">Alle in der App gespeicherten Cookies für immer löschen\\?</string>\n    <string name=\"audio_format_preference\">Bevorzugtes Audioformat</string>\n    <string name=\"unlimited\">Unbegrenzt</string>\n    <string name=\"format_sorting_desc\">Sortieren von Formaten mit der Option -S von yt-dlp</string>\n    <string name=\"rename\">Umbenennen</string>\n    <string name=\"clear_all_cookies\">Alle Cookies löschen</string>\n    <string name=\"temporary_directory_desc\">Temporäre Dateien im internen Ordner speichern</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">Unterstütze diese App durch Sponsoring auf GitHub</string>\n    <string name=\"sponsor_msg\">Seal wird immer frei und kostenlos für alle sein. Wenn du es magst, bitte denke bitte darüber nach, mich auf GitHub zu sponsern!</string>\n    <string name=\"feedback\">Rückmeldung</string>\n    <string name=\"sponsors\">Sponsoren</string>\n    <string name=\"no_downloaded_media\">Keine heruntergeladenen Medien</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Experimentelle Funktion aktivieren\\?</string>\n    <string name=\"clip_video_dialog_msg\">Downloads, die diese Funktion nutzen, werden an FFmpeg delegiert, um ausgewählte Abschnitte des Videos herunterzuladen. Diese Funktion ist noch experimentell und der Schnitt wird nicht ganz genau sein, nicht alle Formate unterstützen diese Funktion und es kann sein, dass du langsamere Downloadgeschwindigkeiten hast.</string>\n    <string name=\"audio_format\">Audioformat</string>\n    <string name=\"clip_video_desc\">Videoclips auf der Formatauswahlseite erstellen</string>\n    <string name=\"okay\">Okay</string>\n    <string name=\"feature_unavailable\">Funktion nicht verfügbar</string>\n    <string name=\"auto_update_disabled_msg\">Automatische Updates sind für %1$s Builds nicht verfügbar. Wenn du %1$s nicht auf deinem Gerät installiert hast, oder eine Vorschau kommender Funktionen in Seal möchtest, ziehe bitte %2$s in Erwägung.</string>\n    <string name=\"msg_from_developer\">Nachricht vom Entwickler</string>\n    <string name=\"sponsor_msg2\">Vielen Dank!</string>\n    <string name=\"switch_to_github_builds\">Wechseln zu GitHub-Builds</string>\n    <string name=\"no_custom_command_tasks\">Keine benutzerdefinierten Befehlsaufgaben</string>\n    <string name=\"got_it\">Verstanden</string>\n    <string name=\"download_video_desc\">Videos von der URL herunterladen</string>\n    <string name=\"convert_subtitle\">Untertitel konvertieren</string>\n    <string name=\"convert_subtitle_desc\">Konvertiert die Untertitel in ein anderes Format</string>\n    <string name=\"split_video\">Video aufteilen</string>\n    <string name=\"split_video_msg\">Video wird in %1$d Kapitel aufgeteilt</string>\n    <string name=\"unknown_error_title\">Hoppla! Etwas ist schief gelaufen</string>\n    <string name=\"copy_and_exit\">Kopieren und beenden</string>\n    <string name=\"start\">Starten</string>\n    <string name=\"edit_template\">„%1$s“ bearbeiten</string>\n    <string name=\"new_task\">Neue Download-Aufgabe</string>\n    <string name=\"expand\">Erweitern</string>\n    <string name=\"ytdlp_update_action\">yt-dlp aktualisieren</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"proxy_desc\">Proxy für Internetverbindungen verwenden</string>\n    <string name=\"disabled\">Deaktiviert</string>\n    <string name=\"prefer_compatibility_desc\">MP4(H.264)-Formate für die Weitergabe an andere Apps bevorzugen</string>\n    <string name=\"enable_notifications\">Benachrichtigungen aktivieren\\?</string>\n    <string name=\"quality\">Qualität</string>\n    <string name=\"enable_notifications_desc\">Die App benötigt deine Erlaubnis, um Benachrichtigungen über den Status und den Downloadfortschritt anzuzeigen.</string>\n    <string name=\"disable\">Deaktivieren</string>\n    <string name=\"prefer_quality_desc\">AV1-, VP9- oder H.265-Formate für die Wiedergabe in kompatiblen Apps bevorzugen</string>\n    <string name=\"export_to_file\">Export in die Datei</string>\n    <string name=\"folder_picker\">Ordnerauswahl</string>\n    <string name=\"commands\">Befehle</string>\n    <string name=\"unknown\">Unbekannt</string>\n    <string name=\"learn_more\">Mehr erfahren</string>\n    <string name=\"download_type\">Art des Herunterladens</string>\n    <string name=\"custom_command_directory\">Benutzerdefiniertes Befehlsverzeichnis</string>\n    <string name=\"custom_command_directory_desc\">Gib das Ausgabeverzeichnis an, wenn du benutzerdefinierte Befehle verwendest</string>\n    <string name=\"set_directory_desc\">Tippen, um Verzeichnis einzurichten</string>\n    <string name=\"ua_header\">User-Agent Header</string>\n    <string name=\"format_preference\">Format Präferenz</string>\n    <string name=\"auto\">Automatisch</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d Element</item>\n        <item quantity=\"other\">%d Elemente</item>\n    </plurals>\n    <string name=\"refresh_cookies_desc\">Tippen, um die Webseite für die Erstellung neuer Cookies zu öffnen:</string>\n    <string name=\"custom\">Benutzerdefiniert</string>\n    <string name=\"remove_multiple_templates_msg\">\\\"%1$s\\\" endgültig aus den Befehlsvorlagen entfernen\\?</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp ist ein mächtiges Werkzeug um Videos herunterzuladen. Seal macht es einfacher yt-dlp zu nutzten, indem es eine intuitive Benutzeroberfläche, Voreinstellungen für häufige Befehle und andere Funktionen bereitstellt.\n\\n\n\\nFür erweiterte Nutzung von yt-dlp erlaubt Seal es dir benutzerdefinierte Befehlsvorlagen zu erstellen, speichern und auszuführen, genau wie in einer Befehlszeile.\n\\n\n\\nWenn benutzerdefinierte Befehle genutzt werden sind die meisten Optionen und Funktionen in der Benutzeroberfläche deaktiviert.</string>\n    <string name=\"output_template\">Ausgabemuster</string>\n    <string name=\"clear_download_archive\">Archiv löschen?</string>\n    <string name=\"save\">Speichern</string>\n    <string name=\"subdirectory_hint\">Ihre Downloads werden gespeichert als:</string>\n    <string name=\"clear_download_archive_desc\">Soll %1$s aus der Archivdatei entfernt werden?</string>\n    <string name=\"website\">Webseite</string>\n    <string name=\"embed_metadata\">Metadaten einbetten</string>\n    <string name=\"use_format_sorting\">Format-Sortierung verwenden</string>\n    <string name=\"presets\">Voreinstellungen</string>\n    <string name=\"restrict_filenames_desc\">Dateinamen auf bestimmte Zeichen begrenzen, um die Kompatibilität zu gewährleisten</string>\n    <string name=\"required\">Erforderlich</string>\n    <string name=\"show_all_items\">Alle %1$d anzeigen</string>\n    <string name=\"output_template_desc\">Vorlage für Ausgabedateinamen angeben</string>\n    <string name=\"restrict_filenames\">Dateinamen einschränken</string>\n    <string name=\"edit_file\">Datei bearbeiten</string>\n    <string name=\"download_archive_desc\">Erfasse heruntergeladene Video-IDs in einem Archiv, um doppelte Downloads zu vermeiden</string>\n    <string name=\"embed_metadata_desc\">Metadaten und Video-Thumbnail in die Audiodatei einbetten</string>\n    <string name=\"playlist_title\">Titel der Playliste</string>\n    <string name=\"download_archive\">Archiv herunterladen</string>\n    <string name=\"force_ipv4\">IPv4 erzwingen</string>\n    <string name=\"legacy\">Legacy</string>\n    <string name=\"system_settings\">Systemeinstellungen</string>\n    <string name=\"force_ipv4_desc\">Nutze für alle Verbindungen nur IPv4</string>\n    <string name=\"allow_once\">Einmalig erlauben</string>\n    <string name=\"allow_always\">Immer erlauben</string>\n    <string name=\"dont_allow\">Nicht erlauben</string>\n    <string name=\"download_with_cellular_request\">Herunterladen über Mobilfunknetz zulassen?</string>\n    <string name=\"merge_audiostream_desc\">Zusammenführung von mehreren Audiospuren in eine einzelne Datei zulassen</string>\n    <string name=\"keep_subtitle_files\">Untertiteldateien behalten</string>\n    <string name=\"merge_audiostream\">Mehrere Audiospuren zusammenfügen</string>\n    <string name=\"search_in_downloads\">In Downloads suchen</string>\n    <string name=\"search\">Suchen</string>\n    <string name=\"subtitle_language_desc\">Sprachen der herunterzuladenen Untertitel in automatischer Formatauswahl, kommagetrennt aufgelistet.</string>\n    <string name=\"remember_for_next_download\">Für den nächsten Download speichern</string>\n    <string name=\"look_and_feel\">Aussehen &amp; Gefühl</string>\n    <string name=\"use_previous_selection\">Vorherige Auswahl übernehmen</string>\n    <string name=\"none\">Nichts</string>\n    <string name=\"auto_translated_subtitles\">Automatisch übersetzte Untertitel</string>\n    <string name=\"auto_translated_subtitles_msg\">Automatisch übersetzte Untertitel für alle Sprachen werden in den Downloads verfügbar sein. Diese Untertitel können ungenau und schwer verständlich sein.</string>\n    <string name=\"reset\">Zurücksetzen</string>\n    <string name=\"no_thanks\">Nein danke</string>\n    <string name=\"search_in_subtitles\">Suche in Untertiteln</string>\n    <string name=\"update_subtitle_languages\">Sprache der Untertitel aktualisieren?</string>\n    <string name=\"update_language_msg\">Die folgenden Sprachen werden zu deiner Präferenz für zukünftige Downloads hinzugefügt:</string>\n    <string name=\"download_archive_error\">Dieses Video wurde heruntergeladen. Wenn du dieses Verhalten nicht erwartet hast, überprüfe dein Download Archiv.</string>\n    <string name=\"backup_type\">Backup Typ</string>\n    <string name=\"file\">Datei</string>\n    <string name=\"full_backup\">Vollständiges Backup</string>\n    <string name=\"clipboard\">Zwischenablage</string>\n    <string name=\"export_download_history\">Downloadhistorie exportieren?</string>\n    <string name=\"export_backup\">Exportieren</string>\n    <string name=\"import_backup\">Importieren</string>\n    <string name=\"import_from\">Importieren von</string>\n    <string name=\"import_download_history\">Downloadhistorie importieren?</string>\n    <string name=\"import_download_history_msg\">Heruntergeladene Dateien werden nicht importiert. Du musst die manuell erneut herunterladen</string>\n    <string name=\"export_download_history_msg\">Exportiere %1$s vom Download-Verlauf. Heruntergeladen Dateien und einstellen werden nicht gesichert.</string>\n    <string name=\"download_history\">Download-Verlauf</string>\n    <string name=\"download_history_imported\">%1$s in Download-Verlauf importiert</string>\n    <string name=\"redownload\">Erneut herunterladen</string>\n    <string name=\"export_to\">Exportieren als</string>\n    <string name=\"interface_and_interaction\">Interface &amp; Bedienung</string>\n    <string name=\"remux_container_mkv\">Remux-Videocontainer</string>\n    <string name=\"remux_container_mkv_desc\">Remuxen von Videos in MKV-Container für bessere Kompatibilität</string>\n    <string name=\"cookies_in_database\">%1$d Cookies von insgesamt %2$d Websites</string>\n    <string name=\"every_day\">Jeden Tag</string>\n    <string name=\"every_week\">Jede Woche</string>\n    <string name=\"every_month\">Jeder Monat</string>\n    <string name=\"all_languages\">Alle Sprachen</string>\n    <string name=\"playlist\">Playlist</string>\n    <string name=\"proceed\">Weiter</string>\n    <string name=\"preset\">Voreinstellung</string>\n    <string name=\"custom_format_selection_desc\">Wähle aus Formaten und Untertiteln und passe sie weiter an</string>\n    <string name=\"preset_format_selection_desc\">Automatischer Download unter Verwendung deiner Formateinstellungen</string>\n    <string name=\"edit_preset\">Voreinstellung bearbeiten</string>\n    <string name=\"best_quality_desc\">Bestes verfügbare Format herunterladen</string>\n    <string name=\"task_added\">Aufgabe zur Warteschlange hinzugefügt</string>\n    <string name=\"prefer_placeholder\">%1$s bevorzugen</string>\n    <string name=\"you_ll_find_your_downloads_here\">Hier findest du deine Downloads</string>\n    <string name=\"status_downloaded\">Heruntergeladen</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d Video</item>\n        <item quantity=\"other\">%d Videos</item>\n    </plurals>\n    <string name=\"download_hint\">Tippe auf den Download Button oder teile einen Video-Link zu dieser App, um einen Download zu starten</string>\n    <string name=\"all\">Alle</string>\n    <string name=\"select_multiple_link\">Wähle aus %1$d Links</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d Audio</item>\n        <item quantity=\"other\">%d Audios</item>\n    </plurals>\n    <string name=\"trouble_shooting\">Problembehandlung</string>\n    <string name=\"issue_tracker\">Problemverfolgung</string>\n    <string name=\"trouble_shooting_desc\">Behebung häufiger Fehler und Überprüfung auf bekannte Probleme</string>\n    <string name=\"issue_tracker_hint\">Auf einen Fehler gestoßen? Bevor du ein neues Problem meldest, durchsuchen bitte unseren Issue Tracker. Viele häufige Probleme wurden dort bereits behandelt und dokumentiert.</string>\n    <string name=\"download_queue\">Warteschlange herunterladen</string>\n    <string name=\"show_navigation_drawer\">Navigationsschublade anzeigen</string>\n    <string name=\"resume\">Fortsetzen</string>\n    <string name=\"delete\">Löschen</string>\n    <string name=\"media_info\">Medien Info</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-el/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"create_thumbnail\">Αποθήκευση Εξωφύλλου</string>\n    <string name=\"settings\">Ρυθμίσεις</string>\n    <string name=\"download_settings_desc\">Γενικά, μορφή αρχείου, διαφορετική εντολή</string>\n    <string name=\"url_empty\">Ο σύνδεσμος δεν μπορεί να είναι κενός</string>\n    <string name=\"extract_audio_summary\">Λήψη και αποθήκευση ήχου, αντί για βίντεο</string>\n    <string name=\"create_thumbnail_summary\">Αποθήκευση εξωφύλλου βίντεο ως αρχείο</string>\n    <string name=\"permission_denied\">Η άδεια απορρίφθηκε</string>\n    <string name=\"download_success_msg\">Επιτυχής λήψη</string>\n    <string name=\"download_error_msg\">Αποτυχία λήψης</string>\n    <string name=\"download_start_msg\">Λήψη \\\"%1$s\\\"</string>\n    <string name=\"general_settings\">Γενικές ρυθμίσεις</string>\n    <string name=\"language\">Γλώσσα</string>\n    <string name=\"task_running\">Μια υπάρχουσα λήψης εκτελείται ήδη</string>\n    <string name=\"paste_msg\">Επικόλληση συνδέσμου</string>\n    <string name=\"ytdlp_version\">Έκδοση yt-dlp</string>\n    <string name=\"ytdlp_update_action\">Αναβάθμιση yt-dlp</string>\n    <string name=\"video_directory\">Φάκελος Βίντεο</string>\n    <string name=\"extract_audio\">Αποθήκευση ως Ήχο</string>\n    <string name=\"download\">Λήψη</string>\n    <string name=\"language_settings\">Ρυθμίσεις γλώσσας</string>\n    <string name=\"paste_fail_msg\">Μη δυνατός σύνδεσμος από πρόχειρο</string>\n    <string name=\"yt_dlp_up_to_date\">Χρήση της πιο πρόσφατης έκδοσης yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Αποτυχία εγκατάστασης καινούργιας έκδοσης yt-dlp, βεβαιωθείται πως είστε συνδεδεμένοι στο δίκτυο.</string>\n    <string name=\"delete_info_msg\">Κατάργηση \\\"%1$s\\\" από το ιστορικό λήψεων μόνιμα ;</string>\n    <string name=\"confirm\">Επιβεβαίωση</string>\n    <string name=\"dismiss\">Ακύρωση</string>\n    <string name=\"remove\">Αφαίρεση</string>\n    <string name=\"version\">Έκδοση</string>\n    <string name=\"credits\">Πιστώσεις</string>\n    <string name=\"credits_desc\">Πιστώσεις και λογισμικό libre</string>\n    <string name=\"fetch_info_error_msg\">Αποτυχία λήψη πληροφοριών βίντεο</string>\n    <string name=\"fetching_info\">Λήψη πληροφοριών βίντεο…</string>\n    <string name=\"ytdlp_update\">Πατήστε για να εγκαταστήσετε την νέα έκδοση yt-dlp</string>\n    <string name=\"delete_info\">Αφαίρεση ;</string>\n    <string name=\"downloads_history\">Λήψεις</string>\n    <string name=\"audio\">Ήχος</string>\n    <string name=\"link_copied\">Ο υπερσύνδεσμος αντιγράφτηκε στο πρόχειρο</string>\n    <string name=\"open_url\">Άνοιγμα συνδέσμου</string>\n    <string name=\"delete_file\">Διαγραφή αρχείου</string>\n    <string name=\"about\">Σχετικά με</string>\n    <string name=\"about_page\">Έκδοση, σχόλια, αυτόματη ενημέρωση</string>\n    <string name=\"back\">Πίσω</string>\n    <string name=\"release_desc\">Προβολή αλλαγών και νέων εκδόσεων</string>\n    <string name=\"release\">Νεότερη έκδοση</string>\n    <string name=\"readme_desc\">Προβολή του κώδηκα Github και του README</string>\n    <string name=\"video\">Βίντεο</string>\n    <string name=\"checked\">Ελεχγμένο</string>\n    <string name=\"custom_command\">Προσαρμοσμένη εντολή</string>\n    <string name=\"allow_once\">Επιτρέψτε μία φορά</string>\n    <string name=\"download_with_cellular_request\">Επιτρέπετε τη λήψη με κινητό;</string>\n    <string name=\"download_archive_error\">Το βίντεο έχει μεταφορτωθεί. Εάν αυτή δεν είναι η αναμενόμενη συμπεριφορά, παρακαλούμε ελέγξτε το αρχείο λήψης.</string>\n    <string name=\"remux_container_mkv\">Δοχείο βίντεο Remux</string>\n    <string name=\"remux_container_mkv_desc\">Remux βίντεο σε δοχείο MKV για καλύτερη συμβατότητα</string>\n    <string name=\"custom_command_desc\">Εκτέλεση της εντολής yt-dlp με προσαρμοσμένο πρότυπο</string>\n    <string name=\"custom_command_template\">Πρότυπο εντολών</string>\n    <string name=\"edit\">Επεξεργασία</string>\n    <string name=\"start_execute\">Έναρξη εκτέλεσης εντολής</string>\n    <string name=\"advanced_settings\">Προχωρημένο</string>\n    <string name=\"print_details\">Λεπτομερής έξοδος</string>\n    <string name=\"print_details_desc\">Εκτύπωση λεπτομερών μηνυμάτων κατά τη λήψη</string>\n    <string name=\"display\">Εμφάνιση</string>\n    <string name=\"display_settings\">Σκοτεινό θέμα, δυναμικό χρώμα, γλώσσες</string>\n    <string name=\"dark_theme\">Σκοτεινό θέμα</string>\n    <string name=\"follow_system\">Σύστημα</string>\n    <string name=\"on\">Στο</string>\n    <string name=\"cancel\">Ακύρωση</string>\n    <string name=\"settings_before_download_text\">Ρυθμίστε αυτή τη λήψη</string>\n    <string name=\"error_copied\">Αντιγραφή αναφοράς σφάλματος στο πρόχειρο</string>\n    <string name=\"thumbnail\">Μικρογραφία</string>\n    <string name=\"paste\">Επικόλληση</string>\n    <string name=\"yt_dlp_docs\">Αναφορές χρήσης Yt-dlp</string>\n    <string name=\"format\">Μορφή</string>\n    <string name=\"video_quality\">Ποιότητα βίντεο</string>\n    <string name=\"best_quality\">Καλύτερη ποιότητα</string>\n    <string name=\"not_specified\">Δεν ορίζεται (προεπιλογή)</string>\n    <string name=\"preferred_format_desc\">Προτιμώμενη μορφή όταν παρέχονται πολλαπλές</string>\n    <string name=\"open_settings\">Άνοιγμα ρυθμίσεων</string>\n    <string name=\"options\">Επιλογές</string>\n    <string name=\"additional_settings\">Πρόσθετες ρυθμίσεις</string>\n    <string name=\"share_fail_msg\">Αδυναμία αντιστοίχισης URL από κοινόχρηστο περιεχόμενο</string>\n    <string name=\"share_success_msg\">Ανάγνωση συνδέσμου βίντεο από κοινόχρηστο περιεχόμενο…</string>\n    <string name=\"show_more_actions\">Εμφάνιση περισσότερων ενεργειών</string>\n    <string name=\"download_notification\">Λήψη ειδοποίησης</string>\n    <string name=\"download_notification_desc\">Ειδοποίηση για τη λήψη αρχείων και την πρόοδο</string>\n    <string name=\"fetching_playlist_info\">Λήψη πληροφοριών λίστας αναπαραγωγής…</string>\n    <string name=\"download_range_desc\">Καθορίστε το εύρος των βίντεο για λήψη από τη λίστα αναπαραγωγής \\\"%3$s\\\" (από %1$d έως %2$d).</string>\n    <string name=\"from\">Έναρξη</string>\n    <string name=\"to\">Τέλος</string>\n    <string name=\"invalid_index_range\">Μη έγκυρο εύρος δεικτών</string>\n    <string name=\"playlist_indicator_text\">Λήψη λίστας αναπαραγωγής (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Φάκελος ήχου</string>\n    <string name=\"download_directory\">Λήψη καταλόγου</string>\n    <string name=\"download_directory_desc\">Επιλέξτε πού θα αποθηκεύσετε τα βίντεο και τα αρχεία ήχου</string>\n    <string name=\"subdirectory\">Αποθήκευση σε υποκατάλογο</string>\n    <string name=\"subdirectory_desc\">Αποθηκεύστε αρχεία σε φακέλους με το όνομα των αντίστοιχων πεδίων</string>\n    <string name=\"permission_issue\">Θέμα άδειας αποθήκευσης</string>\n    <string name=\"battery_configuration\">Διαμόρφωση μπαταρίας</string>\n    <string name=\"battery_configuration_desc\">Αγνοήστε τη βελτιστοποίηση της μπαταρίας για αυτή την εφαρμογή για λήψη στο παρασκήνιο</string>\n    <string name=\"embed_subtitles_desc\">Ενσωματώστε τους υποτίτλους που παρέχονται στα βίντεο, εάν είναι διαθέσιμοι</string>\n    <string name=\"new_template\">Νέο πρότυπο</string>\n    <string name=\"template_label\">Ετικέτα</string>\n    <string name=\"remove_template_desc\">Αφαιρέστε οριστικά το \\\"%1$s\\\" από τα πρότυπα εντολών;</string>\n    <string name=\"custom_command_template_desc\">Επεξεργασία και διαχείριση προτύπων εντολών</string>\n    <string name=\"downloading_indicator_text\">Λήψη σε εξέλιξη…</string>\n    <string name=\"task_canceled\">Λήψη εργασίας που ακυρώθηκε</string>\n    <string name=\"github_issue\">Θέμα GitHub</string>\n    <string name=\"github_issue_desc\">Υποβάλετε ένα θέμα για αναφορά σφάλματος ή αίτημα λειτουργίας</string>\n    <string name=\"info_copied\">Αντιγραφή πληροφοριών στο πρόχειρο</string>\n    <string name=\"status_enqueued\">Σε αναμονή</string>\n    <string name=\"status_completed\">Ολοκληρώθηκε</string>\n    <string name=\"status_canceled\">Ακυρώθηκε</string>\n    <string name=\"status_downloading\">Λήψη</string>\n    <string name=\"status_fetching_video_info\">Λήψη πληροφοριών</string>\n    <string name=\"open_file\">Άνοιγμα αρχείου</string>\n    <string name=\"restart\">Επανεκκίνηση</string>\n    <string name=\"status_error\">Σφάλμα</string>\n    <string name=\"copy_link\">Αντιγραφή συνδέσμου</string>\n    <string name=\"copy_error_report\">Αντιγραφή αναφοράς</string>\n    <string name=\"video_resolution\">Ανάλυση βίντεο</string>\n    <string name=\"video_file_size\">Μέγεθος αρχείου βίντεο</string>\n    <string name=\"export_to_clipboard\">Εξαγωγή στο πρόχειρο</string>\n    <string name=\"import_from_clipboard\">Εισαγωγή από το πρόχειρο</string>\n    <string name=\"template_exported\">Εξαγωγή %1$d προτύπου(-ων)</string>\n    <string name=\"template_imported\">Εισαγόμενα πρότυπα %1$d</string>\n    <string name=\"download_task_count\">%1$d Εργασίες λήψης</string>\n    <string name=\"recently_added\">Πρόσφατα προστέθηκε</string>\n    <string name=\"multiselect_item_count\">%1$d βίντεο, %2$d αρχεία ήχου</string>\n    <string name=\"delete_multiple_items_msg\">Να αφαιρέσετε οριστικά το/τα %1$d στοιχείο(α) από το ιστορικό λήψεων;</string>\n    <string name=\"sponsorblock_desc\">Αφαίρεση ή επισήμανση τμημάτων σε βίντεο με το API του SponsorBlock</string>\n    <string name=\"sponsorblock_categories_desc\">Καθορίστε τις κατηγορίες SponsorBlock που θα αφαιρεθούν ή θα επισημανθούν στο αρχείο βίντεο</string>\n    <string name=\"sponsorblock_categories\">Κατηγορίες SponsorBlock</string>\n    <string name=\"check_for_updates_desc\">Αυτόματος έλεγχος για την τελευταία έκδοση στο GitHub</string>\n    <string name=\"app_up_to_date\">Η τρέχουσα έκδοση είναι ενημερωμένη</string>\n    <string name=\"app_update_failed\">Απέτυχε η ενημέρωση στην τελευταία έκδοση</string>\n    <string name=\"update\">Ενημέρωση</string>\n    <string name=\"aria2_desc\">Χρησιμοποιήστε το aria2c ως εξωτερικό πρόγραμμα λήψης</string>\n    <string name=\"cookies\">‐Cookies</string>\n    <string name=\"cookies_desc\">Χρήση cookies με μορφοποίηση Netscape για λήψεις</string>\n    <string name=\"clear_temp_files\">Εκκαθάριση προσωρινών αρχείων</string>\n    <string name=\"clear_temp_files_desc\">Διαγραφή όλων των προσωρινών αρχείων από τον προσωρινό κατάλογο</string>\n    <string name=\"clear_temp_files_count\">Διαγράφηκαν %1$d προσωρινά αρχεία</string>\n    <string name=\"multiselect_mode\">Λειτουργία Multiselect</string>\n    <string name=\"private_mode_desc\">Απενεργοποίηση ιστορικού λήψης</string>\n    <string name=\"dynamic_color\">Δυναμικό χρώμα</string>\n    <string name=\"dynamic_color_desc\">Εφαρμόστε χρώματα από ταπετσαρίες στο θέμα της εφαρμογής</string>\n    <string name=\"download_with_cellular\">Λήψη μέσω κινητής τηλεφωνίας</string>\n    <string name=\"download_with_cellular_desc\">Επιτρέψτε τη λήψη πολυμέσων όταν είστε συνδεδεμένοι σε μετρημένα δίκτυα</string>\n    <string name=\"download_disabled_with_cellular\">Η λήψη με δίκτυο κινητής τηλεφωνίας είναι απενεργοποιημένη σύμφωνα με τις ρυθμίσεις σας</string>\n    <string name=\"file_unavailable\">Αυτό το αρχείο δεν είναι πλέον διαθέσιμο</string>\n    <string name=\"network\">Δίκτυο</string>\n    <string name=\"rate_limit\">Όριο ποσοστού</string>\n    <string name=\"rate_limit_desc\">Περιορισμός του μέγιστου ρυθμού λήψης</string>\n    <string name=\"max_rate\">Μέγιστο ποσοστό</string>\n    <string name=\"high_contrast\">Σκούρο θέμα υψηλής αντίθεσης</string>\n    <string name=\"invalid_input\">Μη έγκυρη εισαγωγή</string>\n    <string name=\"lowest_quality\">Χαμηλότερη ποιότητα</string>\n    <string name=\"unavailable\">Μη διαθέσιμο</string>\n    <string name=\"format_settings_desc\">‐Μορφή αρχείου, ποιότητα βίντεο, υπότιτλοι</string>\n    <string name=\"general_settings_desc\">Έκδοση Yt-dlp, ειδοποίηση, λίστα αναπαραγωγής</string>\n    <string name=\"network_settings_desc\">Όριο ρυθμού, downloader, cookies</string>\n    <string name=\"disable_preview\">Απενεργοποίηση προεπισκόπησης</string>\n    <string name=\"disable_preview_desc\">Δεν εμφανίζονται μικρογραφίες κατά τη λήψη</string>\n    <string name=\"privacy\">Απόρρητο</string>\n    <string name=\"use_custom_command\">Χρήση προσαρμοσμένης εντολής</string>\n    <string name=\"private_directory\">Ιδιωτικός κατάλογος</string>\n    <string name=\"private_directory_desc\">Αποθήκευση λήψεων σε έναν κρυφό κατάλογο</string>\n    <string name=\"crop_artwork\">Έργο τέχνης Crop</string>\n    <string name=\"crop_artwork_desc\">Περικοπή ενσωματωμένης εικόνας σε τετράγωνο</string>\n    <string name=\"download_selection_desc\">Επιλέξτε βίντεο για λήψη από τη λίστα αναπαραγωγής \\\"%1$s\\\"</string>\n    <string name=\"select_all\">Επιλέξτε όλα</string>\n    <string name=\"selected_item_count\">%1$d επιλεγμένο</string>\n    <string name=\"video_only\">Βίντεο (χωρίς ήχο)</string>\n    <string name=\"suggested\">Προτεινόμενο</string>\n    <string name=\"format_selection\">Επιλογή μορφής</string>\n    <string name=\"format_selection_desc\">Επιλέξτε τη μορφή λήψης πριν ξεκινήσετε τη λήψη</string>\n    <string name=\"generate_new_cookies\">Δημιουργία νέων cookies</string>\n    <string name=\"use_cookies\">Χρήση Cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Να αφαιρέσετε αυτή την καταχώρηση για το \\\"%1$s\\\"; Σημειώστε ότι τα cookies που έχουν αποθηκευτεί για αυτόν τον ιστότοπο δεν θα διαγραφούν.</string>\n    <string name=\"custom_command_enabled_hint\">Ορισμένες επιλογές δεν είναι διαθέσιμες όταν χρησιμοποιείτε προσαρμοσμένη εντολή</string>\n    <string name=\"cookies_usage_msg\">Η λήψη από ορισμένες τοποθεσίες απαιτεί πληροφορίες ελέγχου ταυτότητας λογαριασμού. Κάντε κλικ στην επιλογή \\\"Δημιουργία νέων cookies\\\", εισαγάγετε τη διεύθυνση URL του ιστότοπου και, στη συνέχεια, συνδεθείτε με το λογαριασμό σας στη σελίδα του προγράμματος περιήγησης, η εφαρμογή θα τα δημιουργήσει για εσάς.</string>\n    <string name=\"how_does_it_work\">Πώς λειτουργεί;</string>\n    <string name=\"telegram_channel\">Κανάλι Telegram</string>\n    <string name=\"matrix_space\">Χώρος μήτρας</string>\n    <string name=\"sdcard_directory\">Φάκελος κάρτας SD</string>\n    <string name=\"auto_subtitle\">Αυτόματες λεζάντες</string>\n    <string name=\"auto_subtitle_desc\">Λήψη αυτόματης δημιουργίας λεζάντες</string>\n    <string name=\"title_activity_share\">Γρήγορη λήψη</string>\n    <string name=\"abs_hint\">Οι περισσότερες πλατφόρμες ροής βίντεο παραδίδουν ήχο και βίντεο ξεχωριστά, μπορείτε να επιλέξετε και να συγχωνεύσετε μια μορφή μόνο ήχου με μια μορφή μόνο βίντεο σε ένα ενιαίο βίντεο.</string>\n    <string name=\"video_creator_sample_text\">Δείγμα κειμένου δημιουργού βίντεο</string>\n    <string name=\"subtitle\">Υπότιτλος</string>\n    <string name=\"download_subtitles\">–Λήψη υποτίτλων</string>\n    <string name=\"subtitle_desc\">Γλώσσες, ενσωμάτωση υποτίτλων, αυτόματες λεζάντες</string>\n    <string name=\"add\">Προσθέστε</string>\n    <string name=\"running_tasks\">Εκτέλεση εργασιών</string>\n    <string name=\"show_logs\">Εμφάνιση ημερολογίου</string>\n    <string name=\"logs\">Ημερολόγιο</string>\n    <string name=\"subtitle_sponsorblock\">Οι υπότιτλοι ενδέχεται να είναι λάθος χρονισμένοι κατά την αφαίρεση τμημάτων SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Για την ενσωμάτωση υποτίτλων, τα βίντεο θα μετατραπούν σε δοχείο mkv. Μπορείτε να χρησιμοποιήσετε το VLC Media Player ή άλλες συμβατές εφαρμογές για να παρακολουθήσετε βίντεο με ενσωματωμένους υπότιτλους.</string>\n    <string name=\"share\">Μοιραστείτε το</string>\n    <string name=\"stable_channel\">Σταθερό</string>\n    <string name=\"pre_release_channel\">Προεπισκόπηση</string>\n    <string name=\"update_channel\">Κανάλι ενημέρωσης</string>\n    <string name=\"auto_update\">Αυτόματη ενημέρωση</string>\n    <string name=\"discard\">Απορρίψτε το</string>\n    <string name=\"lowest_bitrate\">Χαμηλότερο bitrate</string>\n    <string name=\"format_sorting\">Ταξινόμηση μορφής</string>\n    <string name=\"format_sorting_desc\">Ταξινόμηση μορφών με την επιλογή -S του yt-dlp</string>\n    <string name=\"import_from_preferences\">Εισαγωγή</string>\n    <string name=\"title\">Τίτλος</string>\n    <string name=\"rename\">Μετονομασία</string>\n    <string name=\"minute\">λεπτό</string>\n    <string name=\"temporary_directory_desc\">Αποθήκευση προσωρινών αρχείων στον εσωτερικό κατάλογο</string>\n    <string name=\"sponsor\">Χορηγός</string>\n    <string name=\"sponsor_desc\">Υποστηρίξτε αυτή την εφαρμογή με χορηγία στο GitHub</string>\n    <string name=\"sponsor_msg\">Η Seal θα είναι πάντα δωρεάν και ανοιχτού κώδικα για όλους. Αν σας αρέσει, παρακαλώ σκεφτείτε να με χρηματοδοτήσετε στο GitHub!</string>\n    <string name=\"feedback\">Ανατροφοδότηση</string>\n    <string name=\"audio_format\">Μορφή ήχου</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"clip_video_desc\">Δημιουργήστε βίντεο κλιπ στη σελίδα επιλογής μορφής</string>\n    <string name=\"switch_to_github_builds\">μετάβαση σε GitHub builds</string>\n    <string name=\"okay\">Εντάξει</string>\n    <string name=\"got_it\">Το πήρα</string>\n    <string name=\"msg_from_developer\">Μήνυμα από τον προγραμματιστή</string>\n    <string name=\"sponsor_msg2\">Σας ευχαριστώ πολύ!</string>\n    <string name=\"convert_subtitle\">Μετατροπή υποτίτλων</string>\n    <string name=\"convert_subtitle_desc\">Μετατροπή των υποτίτλων σε άλλη μορφή</string>\n    <string name=\"split_video_msg\">Το βίντεο θα χωριστεί σε %1$d κεφάλαια</string>\n    <string name=\"unknown_error_title\">Ουπς! Κάτι πήγε στραβά</string>\n    <string name=\"copy_and_exit\">Αντιγραφή και έξοδος</string>\n    <string name=\"expand\">Επεκτείνετε το</string>\n    <string name=\"new_task\">Νέα εργασία λήψης</string>\n    <string name=\"start\">Έναρξη</string>\n    <string name=\"proxy\">Μεσολάβηση</string>\n    <string name=\"legacy\">Κληρονομιά</string>\n    <string name=\"disable\">Απενεργοποίηση</string>\n    <string name=\"set_directory_desc\">Πατήστε για να ρυθμίσετε τον κατάλογο</string>\n    <string name=\"prefer_compatibility_desc\">Προτιμήστε μορφές MP4 (H.264) για κοινή χρήση σε άλλες εφαρμογές</string>\n    <string name=\"prefer_quality_desc\">Προτιμήστε φορμά AV1, VP9 ή H.265 για παρακολούθηση σε συμβατές εφαρμογές</string>\n    <string name=\"download_type\">Λήψη τύπου</string>\n    <string name=\"custom\">Προσαρμοσμένο</string>\n    <string name=\"learn_more\">Μάθετε περισσότερα</string>\n    <string name=\"unknown\">Άγνωστος</string>\n    <string name=\"ua_header\">Κεφαλίδα User-Agent</string>\n    <string name=\"export_to_file\">Εξαγωγή σε αρχείο</string>\n    <string name=\"output_template\">Πρότυπο εξόδου</string>\n    <string name=\"output_template_desc\">Καθορίστε το πρότυπο για τα ονόματα των αρχείων εξόδου</string>\n    <string name=\"download_archive\">Λήψη αρχείου</string>\n    <string name=\"clear_download_archive\">Εκκαθάριση αρχείου λήψης;</string>\n    <string name=\"embed_metadata\">Ενσωματώστε μεταδεδομένα</string>\n    <string name=\"embed_metadata_desc\">Ενσωματώστε μεταδεδομένα και μικρογραφία βίντεο στο αρχείο ήχου</string>\n    <string name=\"required\">Απαιτούμενο</string>\n    <string name=\"show_all_items\">Εμφάνιση όλων των στοιχείων %1$d</string>\n    <string name=\"edit_file\">Επεξεργασία αρχείου</string>\n    <string name=\"restrict_filenames\">Περιορισμός των ονομάτων αρχείων</string>\n    <string name=\"website\">Ιστοσελίδα</string>\n    <string name=\"playlist_title\">Τίτλος λίστας αναπαραγωγής</string>\n    <string name=\"system_settings\">Ρυθμίσεις συστήματος</string>\n    <string name=\"force_ipv4\">Επιβολή IPv4</string>\n    <string name=\"settings_before_download\">Διαμόρφωση πριν από τη λήψη</string>\n    <string name=\"settings_before_download_desc\">Διαμορφώστε τις προτιμήσεις πριν από τη λήψη</string>\n    <string name=\"edit_template_desc\">Η διαδρομή εξόδου και η διεύθυνση URL θα προστεθούν από την εφαρμογή.</string>\n    <string name=\"convert_audio_format\">Μετατροπή μορφής ήχου</string>\n    <string name=\"not_convert\">Μη προσηλυτισμένο</string>\n    <string name=\"convert_audio_format_desc\">Η επανακωδικοποίηση αρχείων ήχου θα προκαλέσει απώλεια στην ποιότητα του ήχου και αύξηση του μεγέθους του αρχείου.</string>\n    <string name=\"video_quality_desc\">Περιορίστε την ποιότητα του βίντεο όταν υπάρχουν πολλά</string>\n    <string name=\"video_format_preference\">Προτιμώμενη μορφή βίντεο</string>\n    <string name=\"convert_audio\">Μετάτρεψε</string>\n    <string name=\"video_format\">Μορφή βίντεο</string>\n    <string name=\"start_download\">Λήψη</string>\n    <string name=\"close\">Κλείστε το</string>\n    <string name=\"video_url\">Σύνδεσμος βίντεο</string>\n    <string name=\"concurrent_download_num\">%d νήμα(τα) θα χρησιμοποιούνταν για την ταυτόχρονη λήψη εγγενών βίντεο DASH/HLS.</string>\n    <string name=\"close_never_show_again\">Μην εμφανιστείτε ξανά</string>\n    <string name=\"user_guide\">Οδηγός χρήσης</string>\n    <string name=\"download_desc\">Στη συνέχεια, κάντε κλικ στο κουμπί \\\"Λήψη\\\" αφού προσαρμόσετε τις ρυθμίσεις του.</string>\n    <string name=\"paste_desc\">Κάντε κλικ στην επιλογή \\\"Επικόλληση\\\" για να λάβετε το σύνδεσμο βίντεο από το πρόχειρο.</string>\n    <string name=\"download_history_desc\">Ελέγξτε και διαχειριστείτε τις λήψεις εντός της εφαρμογής, συμπεριλαμβανομένων των βίντεο και των αρχείων ήχου.</string>\n    <string name=\"defaults\">Προεπιλογή</string>\n    <string name=\"check_download_settings_desc\">Ρίξτε μια ματιά στις ρυθμίσεις λήψης και βεβαιωθείτε ότι έχετε την τελευταία έκδοση του yt-dlp πριν το χρησιμοποιήσετε.</string>\n    <string name=\"download_playlist\">Λήψη λίστας αναπαραγωγής</string>\n    <string name=\"download_playlist_desc\">Λήψη πολλαπλών βίντεο από μια λίστα αναπαραγωγής</string>\n    <string name=\"channel_name\">Λήψη</string>\n    <string name=\"channel_description\">Ειδοποίηση για τη λήψη αρχείων και την πρόοδο</string>\n    <string name=\"download_finish_notification\">Το κατέβασμα ολοκληρώθηκε. Πατήστε για να ανοίξετε.</string>\n    <string name=\"execute_command_notification\">Εκτέλεση προσαρμοσμένων εντολών…</string>\n    <string name=\"battery_settings_desc\">Παρακαλούμε ρυθμίστε τη χρήση της μπαταρίας αυτής της εφαρμογής σε \\\"Χωρίς περιορισμούς\\\" στις ρυθμίσεις συστήματος για λήψη στο παρασκήνιο.</string>\n    <string name=\"concurrent_download_desc\">Παράλληλη λήψη περισσότερων τμημάτων βίντεο M3U8/MPD</string>\n    <string name=\"concurrent_download\">Λήψη με πολλαπλά νήματα</string>\n    <string name=\"download_range_selection\">Επιλογή λίστας αναπαραγωγής</string>\n    <string name=\"permission_issue_desc\">Δεν υποστηρίζονται κατάλογοι εκτός των Download/ και Documents/</string>\n    <string name=\"service_title\">Η Seal κατεβάζει…</string>\n    <string name=\"unknown_error\">Άγνωστο σφάλμα</string>\n    <string name=\"translate\">Μεταφράστε</string>\n    <string name=\"translate_desc\">Βοήθεια για τη μετάφραση αυτής της εφαρμογής στο Hosted Weblate</string>\n    <string name=\"prefix\">Πρόθεμα</string>\n    <string name=\"embed_subtitles\">Ενσωματώστε υπότιτλους</string>\n    <string name=\"remove_template\">Αφαιρέστε;</string>\n    <string name=\"template_selection\">Επιλογή προτύπου</string>\n    <string name=\"check_for_updates\">Έλεγχος για ενημερώσεις</string>\n    <string name=\"clear_temp_files_info\">”Τα προσωρινά αρχεία μπορούν να χρησιμοποιηθούν για την επανάληψη των ακυρωμένων λήψεων. Είστε σίγουροι ότι διαγράψατε όλα αυτά τα αρχεία;\n\\n\n\\nΜπορείτε να έχετε πρόσβαση σε αυτά τα αρχεία στο %1$s</string>\n    <string name=\"custom_command_usage_msg\">Το yt-dlp είναι ένα ισχυρό εργαλείο γραμμής εντολών για τη λήψη βίντεο. Το Seal διευκολύνει τη χρήση του yt-dlp παρέχοντας ένα διαισθητικό γραφικό περιβάλλον, προεπιλογές για κοινές εντολές και άλλα πρόσθετα χαρακτηριστικά.\n\\n\n\\nΓια προχωρημένη χρήση του yt-dlp, το Seal σας επιτρέπει να δημιουργείτε, να αποθηκεύετε και να εκτελείτε προσαρμοσμένα πρότυπα εντολών απευθείας, ακριβώς όπως σε ένα τερματικό.\n\\n\n\\nΌταν χρησιμοποιείτε προσαρμοσμένες εντολές, οι περισσότερες επιλογές και δυνατότητες του GUI θα είναι απενεργοποιημένες.</string>\n    <string name=\"video_title_sample_text\">Δείγμα κειμένου τίτλου βίντεο</string>\n    <string name=\"subtitle_language\">Γλώσσες υποτίτλων</string>\n    <string name=\"copy_log\">Αντιγραφή ημερολογίου</string>\n    <string name=\"clear\">Σαφής</string>\n    <string name=\"edit_shortcuts\">Συντομεύσεις επεξεργασίας</string>\n    <string name=\"shortcuts\">Συντομεύσεις</string>\n    <string name=\"edit_shortcuts_desc\">Επεξεργαστείτε τις προσαρμοσμένες συντομεύσεις που μπορούν να χρησιμοποιηθούν για τη σύνθεση προτύπων εντολών.</string>\n    <string name=\"update_channel_desc\">Εγκαταστήστε pre-release builds για προεπισκόπηση νέων χαρακτηριστικών και αλλαγών.\n\\n\n\\nΘα υπάρχει κάποια αστάθεια σε αυτές τις εκδόσεις, γι\\' αυτό μη διστάσετε να μας δώσετε ανατροφοδότηση αν αντιμετωπίσετε κάποιο πρόβλημα για να μας βοηθήσετε να βελτιώσουμε την εφαρμογή στο μέλλον.</string>\n    <string name=\"enable_auto_update\">Ενεργοποίηση αυτόματης ενημέρωσης</string>\n    <string name=\"apply\">Εφαρμογή</string>\n    <string name=\"clip_video\">Βίντεο κλιπ</string>\n    <string name=\"clip_start\">Έναρξη</string>\n    <string name=\"clip_end\">‐Τέλος</string>\n    <string name=\"audio_format_preference\">Προτιμώμενη μορφή ήχου</string>\n    <string name=\"unlimited\">Απεριόριστα</string>\n    <string name=\"audio_quality\">Ποιότητα ήχου</string>\n    <string name=\"audio_quality_desc\">Περιορισμός του ρυθμού μετάδοσης ήχου όταν υπάρχουν πολλαπλές ποιότητες</string>\n    <string name=\"second\">δεύτερο</string>\n    <string name=\"clear_all_cookies\">Διαγραφή όλων των cookies</string>\n    <string name=\"clear_all_cookies_desc\">Να διαγράψετε οριστικά όλα τα cookies που είναι αποθηκευμένα στην εφαρμογή;</string>\n    <string name=\"sponsors\">Χορηγοί</string>\n    <string name=\"no_downloaded_media\">Δεν υπάρχουν κατεβασμένα πολυμέσα</string>\n    <string name=\"enable_experimental_feature\">Ενεργοποίηση πειραματικής λειτουργίας;</string>\n    <string name=\"clip_video_dialog_msg\">Οι λήψεις που χρησιμοποιούν αυτή τη λειτουργία θα ανατεθούν στο FFmpeg για να κατεβάσει επιλεγμένα τμήματα του βίντεο, αυτή η λειτουργία είναι ακόμα πειραματική και η κοπή δεν θα είναι απόλυτα ακριβής, δεν υποστηρίζουν όλες οι μορφές αυτή τη λειτουργία και ενδέχεται να έχετε χαμηλότερες ταχύτητες λήψης.</string>\n    <string name=\"auto_update_disabled_msg\">Η αυτόματη ενημέρωση δεν είναι διαθέσιμη για %1$s builds. Αν δεν έχετε εγκαταστήσει το %1$s στη συσκευή σας ή αν θέλετε να κάνετε προεπισκόπηση των επερχόμενων νέων χαρακτηριστικών στο Seal, παρακαλούμε εξετάστε το %2$s.</string>\n    <string name=\"feature_unavailable\">Χαρακτηριστικό δεν είναι διαθέσιμο</string>\n    <string name=\"no_custom_command_tasks\">Δεν υπάρχουν προσαρμοσμένες εργασίες εντολών</string>\n    <string name=\"download_video_desc\">Λήψη βίντεο από τη διεύθυνση URL</string>\n    <string name=\"split_video\">Διαχωρισμένο βίντεο</string>\n    <string name=\"edit_template\">Επεξεργασία \\\"%1$s\\\"</string>\n    <string name=\"proxy_desc\">Χρήση διακομιστή μεσολάβησης για συνδέσεις στο διαδίκτυο</string>\n    <string name=\"quality\">Ποιότητα</string>\n    <string name=\"enable_notifications\">Ενεργοποίηση ειδοποιήσεων;</string>\n    <string name=\"enable_notifications_desc\">Η εφαρμογή χρειάζεται την άδειά σας για να δημοσιεύει ειδοποιήσεις σχετικά με την κατάσταση και την πρόοδο της λήψης.</string>\n    <string name=\"custom_command_directory\">Κατάλογος προσαρμοσμένων εντολών</string>\n    <string name=\"folder_picker\">Επιλογή φακέλου</string>\n    <string name=\"disabled\">Άτομα με ειδικές ανάγκες</string>\n    <string name=\"custom_command_directory_desc\">Καθορίστε τον κατάλογο εξόδου όταν χρησιμοποιείτε προσαρμοσμένες εντολές</string>\n    <string name=\"auto\">Auto</string>\n    <string name=\"commands\">Εντολές</string>\n    <string name=\"format_preference\">Προτίμηση μορφής</string>\n    <string name=\"refresh_cookies_desc\">Πατήστε για να ανοίξετε την ιστοσελίδα για τη δημιουργία νέων cookies:</string>\n    <string name=\"remove_multiple_templates_msg\">Αφαιρέστε οριστικά το %1$s από τα πρότυπα εντολών;</string>\n    <string name=\"presets\">Προεπιλογές</string>\n    <string name=\"file\">Αρχείο</string>\n    <string name=\"export_download_history\">Εξαγωγή ιστορικού λήψης;</string>\n    <string name=\"clipboard\">Πρόχειρο</string>\n    <string name=\"import_from\">Εισαγωγή από</string>\n    <string name=\"download_archive_desc\">Καταγράψτε τα ID των βίντεο που κατεβάσατε σε ένα αρχείο για να αποφύγετε διπλές λήψεις</string>\n    <string name=\"clear_download_archive_desc\">Να αφαιρέσετε οριστικά το %1$s από το αρχείο αρχειοθέτησης;</string>\n    <string name=\"use_format_sorting\">Χρήση ταξινόμησης μορφής</string>\n    <string name=\"restrict_filenames_desc\">Περιορίστε τα ονόματα αρχείων σε συγκεκριμένους χαρακτήρες για να διασφαλίσετε τη συμβατότητα</string>\n    <string name=\"subdirectory_hint\">Οι λήψεις σας θα αποθηκευτούν ως:</string>\n    <string name=\"force_ipv4_desc\">Πραγματοποιήστε όλες τις συνδέσεις μέσω IPv4</string>\n    <string name=\"keep_subtitle_files\">Διατήρηση αρχείων υποτίτλων</string>\n    <string name=\"allow_always\">Επιτρέψτε πάντα</string>\n    <string name=\"dont_allow\">Μην επιτρέπετε</string>\n    <string name=\"merge_audiostream\">‐Συγχώνευση πολλαπλών ροών ήχου</string>\n    <string name=\"merge_audiostream_desc\">Επιτρέπει τη συγχώνευση πολλαπλών ροών ήχου σε ένα ενιαίο αρχείο</string>\n    <string name=\"search\">Αναζήτηση</string>\n    <string name=\"remember_for_next_download\">Θυμηθείτε για την επόμενη λήψη</string>\n    <string name=\"backup_type\">Τύπος αντιγράφων ασφαλείας</string>\n    <string name=\"auto_translated_subtitles\">Αυτόματα μεταφρασμένοι υπότιτλοι</string>\n    <string name=\"auto_translated_subtitles_msg\">Αυτόματα μεταφρασμένοι υπότιτλοι για όλες τις γλώσσες θα είναι διαθέσιμοι στις λήψεις. Αυτοί οι υπότιτλοι ενδέχεται να είναι ανακριβείς και δυσνόητοι.</string>\n    <string name=\"subtitle_language_desc\">Γλώσσα των υποτίτλων για λήψη στην επιλογή αυτόματης μορφής, διαχωρισμένη με κόμμα.</string>\n    <string name=\"reset\">Επαναφορά</string>\n    <string name=\"search_in_subtitles\">Αναζήτηση σε υπότιτλους</string>\n    <string name=\"no_thanks\">Όχι ευχαριστώ</string>\n    <string name=\"none\">Κανένα</string>\n    <string name=\"look_and_feel\">Εμφάνιση &amp; αίσθηση</string>\n    <string name=\"interface_and_interaction\">Διεπαφή &amp; αλληλεπίδραση</string>\n    <string name=\"use_previous_selection\">Χρήση προηγούμενης επιλογής</string>\n    <string name=\"export_backup\">Εξαγωγή</string>\n    <string name=\"import_backup\">Εισαγωγή</string>\n    <string name=\"full_backup\">Πλήρες αντίγραφο ασφαλείας</string>\n    <string name=\"export_to\">Εξαγωγή σε</string>\n    <string name=\"import_download_history\">Εισαγωγή ιστορικού λήψεων;</string>\n    <string name=\"export_download_history_msg\">Εξαγωγή %1$s από το ιστορικό λήψεων. Τα κατεβασμένα αρχεία και οι προτιμήσεις δεν θα δημιουργηθούν αντίγραφα ασφαλείας.</string>\n    <string name=\"download_history\">Λήψη ιστορικού</string>\n    <string name=\"update_language_msg\">Οι ακόλουθες γλώσσες θα προστεθούν στις προτιμήσεις σας για μελλοντικές λήψεις:</string>\n    <string name=\"update_subtitle_languages\">Ενημέρωση γλωσσών υποτίτλων;</string>\n    <string name=\"download_history_imported\">Εισήχθησαν %1$s στο ιστορικό λήψης</string>\n    <string name=\"redownload\">Επανακατέβασμα</string>\n    <string name=\"search_in_downloads\">Αναζήτηση στις λήψεις</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-es/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"paste_desc\">Haz clic en el botón de «Pegar» para obtener el enlace desde tu portapapeles.</string>\n    <string name=\"battery_settings_desc\">Para descargar en segundo plano, por favor cambia el ajuste de uso de batería en los ajustes del teléfono a «No restringir».</string>\n    <string name=\"yt_dlp_update_fail\">No se pudo instalar la última versión de yt-dlp. Por favor asegúrate de estar conectado al Internet.</string>\n    <string name=\"task_running\">Una descarga existente se está ejecutando</string>\n    <string name=\"edit_template_desc\">El directorio de salida y la URL serán añadidas por la aplicación.</string>\n    <string name=\"video_directory\">Ubicación de los vídeos</string>\n    <string name=\"extract_audio\">Guardar como audio</string>\n    <string name=\"create_thumbnail\">Guardar miniatura</string>\n    <string name=\"settings\">Ajustes</string>\n    <string name=\"download_settings_desc\">Ajustes en general, formato y comandos personalizados</string>\n    <string name=\"download\">Descargar</string>\n    <string name=\"url_empty\">El enlace no debe estar vacío</string>\n    <string name=\"extract_audio_summary\">Descargar y guardar el audio, en vez del vídeo</string>\n    <string name=\"create_thumbnail_summary\">Guardar la miniatura del vídeo como un archivo aparte</string>\n    <string name=\"yt_dlp_up_to_date\">Usando la última versión de yt-dlp</string>\n    <string name=\"permission_denied\">Permiso denegado</string>\n    <string name=\"download_success_msg\">Descarga finalizada</string>\n    <string name=\"download_error_msg\">Ocurrió un error al descargar</string>\n    <string name=\"download_start_msg\">Descargando «%1$s»</string>\n    <string name=\"fetch_info_error_msg\">No se pudo obtener la información del vídeo</string>\n    <string name=\"general_settings\">General</string>\n    <string name=\"language\">Idioma</string>\n    <string name=\"language_settings\">Seleccionar idioma</string>\n    <string name=\"paste_msg\">Pegar url</string>\n    <string name=\"ytdlp_version\">Versión de yt-dlp</string>\n    <string name=\"ytdlp_update\">Haz clic para descargar la última versión de yt-dlp</string>\n    <string name=\"delete_info\">¿Eliminar?</string>\n    <string name=\"confirm\">Confirmar</string>\n    <string name=\"dismiss\">Cancelar</string>\n    <string name=\"downloads_history\">Descargas</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Enlace copiado al portapapeles</string>\n    <string name=\"open_url\">Abrir enlace</string>\n    <string name=\"remove\">Eliminar</string>\n    <string name=\"delete_file\">Eliminar archivo</string>\n    <string name=\"about\">Acerca de</string>\n    <string name=\"about_page\">Versión, comentarios, actualización automática</string>\n    <string name=\"back\">Ir atrás</string>\n    <string name=\"version\">Versión</string>\n    <string name=\"release_desc\">Buscar actualizaciones e historial de cambios</string>\n    <string name=\"release\">Último lanzamiento</string>\n    <string name=\"readme_desc\">Ver repositorio de GitHub y README</string>\n    <string name=\"video\">Vídeo</string>\n    <string name=\"checked\">Seleccionado</string>\n    <string name=\"credits\">Créditos</string>\n    <string name=\"paste_fail_msg\">No se ha podido pegar la URL desde el portapapeles</string>\n    <string name=\"delete_info_msg\">¿Eliminar definitivamente \\\"%1$s\\\" del historial de descargas?</string>\n    <string name=\"credits_desc\">Créditos y software de código abierto</string>\n    <string name=\"custom_command\">Comandos personalizados</string>\n    <string name=\"custom_command_desc\">Ejecutar un comando de yt-dlp con un modelo personalizado</string>\n    <string name=\"custom_command_template\">Modelo de comando</string>\n    <string name=\"edit\">Editar modelo</string>\n    <string name=\"start_execute\">Iniciar la ejecución del comando</string>\n    <string name=\"advanced_settings\">Avanzado</string>\n    <string name=\"print_details\">Salida detallada</string>\n    <string name=\"print_details_desc\">Mostrar en pantalla mensajes relevantes durante la descarga</string>\n    <string name=\"display\">Aspecto</string>\n    <string name=\"display_settings\">Modo oscuro, colores dinámicos, idioma</string>\n    <string name=\"dark_theme\">Tema oscuro</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"on\">Activado</string>\n    <string name=\"off\">Desactivado</string>\n    <string name=\"cancel\">Cancelar</string>\n    <string name=\"settings_before_download\">Configurar antes de la descarga</string>\n    <string name=\"settings_before_download_desc\">Configurar ajustes antes de descargar</string>\n    <string name=\"settings_before_download_text\">Configurar esta descarga</string>\n    <string name=\"error_copied\">El error reportado ha sido copiado al portapapeles</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"paste\">Pegar enlace</string>\n    <string name=\"yt_dlp_docs\">Referencias de uso para yt-dlp</string>\n    <string name=\"convert_audio_format\">Convertir formato de audio</string>\n    <string name=\"not_convert\">No convertir</string>\n    <string name=\"convert_to\">Convertir a %1$s</string>\n    <string name=\"format\">Formato</string>\n    <string name=\"convert_audio_format_desc\">La recodificación de archivos de audio conlleva una pérdida de calidad de sonido y un aumento en el tamaño del archivo final.</string>\n    <string name=\"video_quality\">Calidad del vídeo</string>\n    <string name=\"best_quality\">Mejor calidad</string>\n    <string name=\"video_quality_desc\">Limitar la calidad de vídeo cuando hay varios</string>\n    <string name=\"not_specified\">Sin especificar (por defecto)</string>\n    <string name=\"video_format_preference\">Preferencia de formato de vídeo</string>\n    <string name=\"preferred_format_desc\">Formato preferido cuando se facilitan varios</string>\n    <string name=\"video_format\">Formato de vídeo</string>\n    <string name=\"convert_audio\">Convertir audio</string>\n    <string name=\"start_download\">Iniciar descarga</string>\n    <string name=\"close\">Cerrar</string>\n    <string name=\"close_never_show_again\">No mostrarlo otra vez</string>\n    <string name=\"user_guide\">Guía del usuario</string>\n    <string name=\"open_settings\">Abrir ajustes</string>\n    <string name=\"download_desc\">Después de realizar los ajustes pertinentes, haz clic en el botón «Descargar».</string>\n    <string name=\"download_history_desc\">Verifica y administra las descargas dentro de la aplicación, incluyendo videos y archivos de audio.</string>\n    <string name=\"check_download_settings_desc\">Se recomienda echar un vistazo rápido a los ajustes y asegurarse de tener yt-dlp antes de empezar a usar la aplicación.</string>\n    <string name=\"download_playlist\">Descargar lista de reproducción</string>\n    <string name=\"download_playlist_desc\">Descargar varios vídeos de una lista de reproducción</string>\n    <string name=\"defaults\">Predeterminado</string>\n    <string name=\"channel_name\">Descargar</string>\n    <string name=\"channel_description\">Mostrar el progreso de las descargas y un mensaje de finalización</string>\n    <string name=\"video_url\">Enlace del vídeo</string>\n    <string name=\"concurrent_download\">Descarga con múltiples hilos</string>\n    <string name=\"concurrent_download_desc\">Descargar múltiples fragmentos de vídeos m3u8/mpd en paralelo</string>\n    <string name=\"options\">Opciones</string>\n    <string name=\"additional_settings\">Ajustes adicionales</string>\n    <string name=\"share_fail_msg\">No se ha podido obtener la URL desde el contenido compartido</string>\n    <string name=\"share_success_msg\">Leyendo información del enlace compartido con Seal…</string>\n    <string name=\"show_more_actions\">Mostrar más acciones</string>\n    <string name=\"download_notification\">Notificación de descarga</string>\n    <string name=\"download_notification_desc\">Notificarme el progreso de las descargas y un mensaje de finalización</string>\n    <string name=\"download_range_selection\">Selección de la lista de reproducción</string>\n    <string name=\"from\">Inicio</string>\n    <string name=\"to\">Fin</string>\n    <string name=\"invalid_index_range\">Rango de vídeos inválido</string>\n    <string name=\"download_finish_notification\">Descarga finalizada. Pulse para abrir.</string>\n    <string name=\"concurrent_download_num\">%d subproceso(s) serían usados para descargar vídeos nativos DASH/HSL concurrentemente.</string>\n    <string name=\"fetching_playlist_info\">Adquiriendo información de la lista de reproducción…</string>\n    <string name=\"download_range_desc\">Especifica el rango de vídeos que quieres descargar desde la lista de reproducción \\\"%3$s\\\"(desde %1$d hasta %2$d ).</string>\n    <string name=\"audio_directory\">Ubicación de audios</string>\n    <string name=\"download_directory\">Directorios de descargas</string>\n    <string name=\"download_directory_desc\">Configurar ubicación de descarga de vídeos y audios</string>\n    <string name=\"subdirectory\">Guardar en subdirectorio</string>\n    <string name=\"permission_issue\">Problema con permiso de almacenamiento</string>\n    <string name=\"permission_issue_desc\">Directorios fuera de las carpetas «Download/» y «Documents/» no están soportados</string>\n    <string name=\"battery_configuration\">Configuración de la batería</string>\n    <string name=\"battery_configuration_desc\">Ignorar la optimización de la batería para esta aplicación en segundo plano</string>\n    <string name=\"service_title\">Seal está descargando…</string>\n    <string name=\"unknown_error\">Ha ocurrido un error desconocido</string>\n    <string name=\"translate\">Traducir</string>\n    <string name=\"translate_desc\">Ayuda a traducir esta aplicación en Hosted Weblate</string>\n    <string name=\"execute_command_notification\">Ejecutando comandos personalizados…</string>\n    <string name=\"playlist_indicator_text\">Descargando la lista de reproducción (%1$d/%2$d)…</string>\n    <string name=\"subdirectory_desc\">Guardar los archivos en carpetas denominadas como campos respectivos</string>\n    <string name=\"fetching_info\">Adquiriendo información del vídeo…</string>\n    <string name=\"prefix\">Plantilla de ruta</string>\n    <string name=\"embed_subtitles\">Agregar subtítulos</string>\n    <string name=\"embed_subtitles_desc\">Insertar subtítulos proporcionados en videos si están disponibles</string>\n    <string name=\"new_template\">Nueva plantilla</string>\n    <string name=\"template_label\">Etiqueta</string>\n    <string name=\"remove_template\">¿Eliminar\\?</string>\n    <string name=\"remove_template_desc\">¿Eliminar «%1$s» de las plantillas de comandos para siempre\\?</string>\n    <string name=\"template_selection\">Selección de plantillas</string>\n    <string name=\"custom_command_template_desc\">Editar y gestionar plantillas de comandos</string>\n    <string name=\"status_enqueued\">En cola</string>\n    <string name=\"status_completed\">Finalizado</string>\n    <string name=\"status_downloading\">Descargando</string>\n    <string name=\"status_canceled\">Cancelada</string>\n    <string name=\"status_fetching_video_info\">Obteniendo información</string>\n    <string name=\"open_file\">Abrir archivo</string>\n    <string name=\"restart\">Reinciar</string>\n    <string name=\"downloading_indicator_text\">Descarga en curso…</string>\n    <string name=\"task_canceled\">Tarea de descarga cancelada</string>\n    <string name=\"github_issue\">Reportar un problema en GitHub</string>\n    <string name=\"github_issue_desc\">Envía un reporte de un problema que te ha ocurrido o haz una petición de alguna funcionalidad que te gustaría que tuviera Seal</string>\n    <string name=\"info_copied\">Información copiada al portapapeles</string>\n    <string name=\"copy_link\">Copiar enlace</string>\n    <string name=\"copy_error_report\">Copiar el informe</string>\n    <string name=\"status_error\">Error</string>\n    <string name=\"video_resolution\">Resolución del vídeo</string>\n    <string name=\"video_file_size\">Tamaño del archivo del vídeo</string>\n    <string name=\"export_to_clipboard\">Exportar al portapapeles</string>\n    <string name=\"import_from_clipboard\">Importar desde el portapapeles</string>\n    <string name=\"template_exported\">%1$d plantilla(s) exportada(s)</string>\n    <string name=\"template_imported\">%1$d plantilla(s) importada(s)</string>\n    <string name=\"download_task_count\">%1$d tareas de descarga</string>\n    <string name=\"recently_added\">Añadido recientemente</string>\n    <string name=\"multiselect_item_count\">%1$d vídeo(s), %2$d archivo(s) de audio</string>\n    <string name=\"delete_multiple_items_msg\">¿Eliminar %1$d elemento(s) de tu historial de descargas para siempre\\?</string>\n    <string name=\"check_for_updates_desc\">Buscar automáticamente por la última versión disponible en GitHub</string>\n    <string name=\"app_up_to_date\">Seal ya está puesto al día</string>\n    <string name=\"update\">Actualizar</string>\n    <string name=\"check_for_updates\">Buscar actualizaciones</string>\n    <string name=\"aria2_desc\">Usa aria2c como descargador externo</string>\n    <string name=\"app_update_failed\">Fallo al actualizar a la última versión</string>\n    <string name=\"sponsorblock_desc\">Eliminar o marcar segmentos en los vídeos con la API SponsorBlock</string>\n    <string name=\"sponsorblock_categories_desc\">Especifique las categorías en SponsorBlock que deseas eliminar o marcar en el archivo de vídeo</string>\n    <string name=\"sponsorblock_categories\">Categorías de SponsorBlock</string>\n    <string name=\"cookies_desc\">Usar cookies formateadas de Netscape para las descargas</string>\n    <string name=\"clear_temp_files\">Limpiar archivos temporales</string>\n    <string name=\"clear_temp_files_count\">%1$d archivo(s) temporales eliminados</string>\n    <string name=\"clear_temp_files_info\">Los archivos temporales pueden utilizarse para reanudar las descargas canceladas. ¿Está seguro de eliminar todos estos archivos\\?\n\\n\n\\nPuede acceder a estos archivos en %1$s</string>\n    <string name=\"clear_temp_files_desc\">Eliminar todos los archivos temporales del directorio temporal</string>\n    <string name=\"multiselect_mode\">Modo de multiselección</string>\n    <string name=\"private_mode\">Incógnito</string>\n    <string name=\"private_mode_desc\">Desactiva el almacenamiento de carátulas/miniaturas</string>\n    <string name=\"dynamic_color\">Color dinámico</string>\n    <string name=\"dynamic_color_desc\">Aplicar los colores de los fondos de pantalla al tema de la aplicación</string>\n    <string name=\"download_with_cellular\">Descargar con datos móviles</string>\n    <string name=\"download_with_cellular_desc\">Permitir la descarga de medios cuando se está conectado a redes de uso medido</string>\n    <string name=\"download_disabled_with_cellular\">La descarga con la red móvil está desactivada según tu configuración</string>\n    <string name=\"file_unavailable\">Este archivo ya no está disponible</string>\n    <string name=\"rate_limit_desc\">Limitar la velocidad máxima de descarga</string>\n    <string name=\"high_contrast\">Tema de alto contraste (AMOLED)</string>\n    <string name=\"network\">Redes e Internet</string>\n    <string name=\"rate_limit\">Límite de uso de datos</string>\n    <string name=\"max_rate\">Límite máximo</string>\n    <string name=\"invalid_input\">Entrada inválida</string>\n    <string name=\"lowest_quality\">Calidad más baja</string>\n    <string name=\"unavailable\">No disponible</string>\n    <string name=\"format_settings_desc\">Formato de archivo, calidad de vídeo, subtítulos</string>\n    <string name=\"general_settings_desc\">Versión de yt-dlp, notificaciones, listas de reprodución</string>\n    <string name=\"network_settings_desc\">Límite de uso de datos, descargador, cookies</string>\n    <string name=\"privacy\">Privacidad</string>\n    <string name=\"use_custom_command\">Usar comandos personalizados</string>\n    <string name=\"private_directory_desc\">Almacena las descargas en un directorio oculto</string>\n    <string name=\"crop_artwork\">Recortar carátulas</string>\n    <string name=\"crop_artwork_desc\">Recortar la imagen incrustada en un cuadrado</string>\n    <string name=\"disable_preview\">Deshabilitar vista previa</string>\n    <string name=\"disable_preview_desc\">No se muestran miniaturas durante la descarga</string>\n    <string name=\"private_directory\">Directorio privado</string>\n    <string name=\"select_all\">Seleccionar todo</string>\n    <string name=\"download_selection_desc\">Seleccione los vídeos que desea descargar de la lista de reproducción \\\"%1$s\\\"</string>\n    <string name=\"selected_item_count\">%1$d seleccionado</string>\n    <string name=\"suggested\">Sugerido</string>\n    <string name=\"format_selection_desc\">Selecciona el formato de vídeo que quieres antes de comenzar la descarga</string>\n    <string name=\"video_only\">Vídeo (sin audio)</string>\n    <string name=\"format_selection\">Selección de formato</string>\n    <string name=\"generate_new_cookies\">Crear nuevas cookies</string>\n    <string name=\"use_cookies\">Utilizar cookies</string>\n    <string name=\"remove_cookie_profile_desc\">¿Eliminar esta entrada para \\\"%1$s\\\"? Por favor, tenga en cuenta que las cookies almacenadas para este sitio no se borrarán.</string>\n    <string name=\"custom_command_enabled_hint\">Algunas opciones no están disponibles cuando se utiliza el comando personalizado</string>\n    <string name=\"how_does_it_work\">¿Cómo funciona\\?</string>\n    <string name=\"telegram_channel\">Canal de Telegram</string>\n    <string name=\"cookies_usage_msg\">La descarga desde algunos sitios requiere información de autenticación de cuenta. Haz clic en \\\"Generar nuevas cookies\\\", introduce la URL del sitio web y, a continuación, inicia sesión con tu cuenta en la página del navegador; la aplicación la generará por ti.</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"matrix_space\">Canal de Matrix</string>\n    <string name=\"abs_hint\">La mayoría de los servicios de streaming en línea proveen el audio y el vídeo por separado. De esta forma puedes seleccionar mezclar un formato de solo vídeo con otro de solo audio para crear un único vídeo con audio, dando así una mayor personalización.</string>\n    <string name=\"sdcard_directory\">Ubicación para tarjetas SD</string>\n    <string name=\"auto_subtitle\">Subtítulos generados automáticamente</string>\n    <string name=\"auto_subtitle_desc\">Descarga subtítulos autogenerados</string>\n    <string name=\"title_activity_share\">Descarga rápida</string>\n    <string name=\"video_title_sample_text\">Texto de ejemplo en título de vídeo</string>\n    <string name=\"video_creator_sample_text\">Texto de ejemplo de creador de vídeo</string>\n    <string name=\"subtitle\">Subtítulo</string>\n    <string name=\"download_subtitles\">Descargar subtítulos</string>\n    <string name=\"subtitle_language\">Idiomas de los subtítulos</string>\n    <string name=\"subtitle_desc\">Idiomas, subtítulos incorporados, subtítulos automáticos</string>\n    <string name=\"copy_log\">Copiar reporte</string>\n    <string name=\"clear\">Limpiar</string>\n    <string name=\"edit_shortcuts\">Editar accesos directos</string>\n    <string name=\"add\">Añadir</string>\n    <string name=\"shortcuts\">Accesos directos</string>\n    <string name=\"running_tasks\">Tareas ejecutándose</string>\n    <string name=\"show_logs\">Mostrar registro</string>\n    <string name=\"logs\">Registro</string>\n    <string name=\"edit_shortcuts_desc\">Edita los accesos directos a los argumentos que puedes usar para crear plantillas de comandos.</string>\n    <string name=\"subtitle_sponsorblock\">Los subtítulos pueden estar mal sincronizados cuando se eliminan segmentos del SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Para insertar subtítulos suaves, los videos se remuxificarán en el contenedor mkv. Puede utilizar VLC Media Player u otras aplicaciones compatibles para ver vídeos con subtítulos suaves.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"share\">Compartir</string>\n    <string name=\"update_channel\">Actualizar el canal</string>\n    <string name=\"auto_update\">Actualizar automáticamente</string>\n    <string name=\"enable_auto_update\">Habilitar la actualización automática</string>\n    <string name=\"pre_release_channel\">Vista previa</string>\n    <string name=\"update_channel_desc\">Instala versiones preliminares para probar nuevas funciones y cambios.\n\\n\n\\nHabrá cierta inestabilidad en estas versiones, así que no dudes en hacernos llegar tus comentarios si experimentas algún problema para ayudarnos a mejorar la aplicación en el futuro.</string>\n    <string name=\"stable_channel\">Estable</string>\n    <string name=\"discard\">Descartar</string>\n    <string name=\"apply\">Aplicar</string>\n    <string name=\"clip_video\">Videoclip</string>\n    <string name=\"clip_start\">Iniciar</string>\n    <string name=\"clip_end\">Finalizar</string>\n    <string name=\"audio_format_preference\">Formato de audio preferido</string>\n    <string name=\"unlimited\">Ilimitado</string>\n    <string name=\"lowest_bitrate\">Tasa de bits más baja</string>\n    <string name=\"audio_quality\">Calidad del audio</string>\n    <string name=\"title\">Título</string>\n    <string name=\"format_sorting_desc\">Clasificación de formatos con la opción -S de yt-dlp</string>\n    <string name=\"clear_all_cookies\">Limpiar todas las cookies</string>\n    <string name=\"minute\">minuto</string>\n    <string name=\"rename\">Renombrar</string>\n    <string name=\"audio_quality_desc\">Limitar la velocidad de bits del audio cuando hay varias calidades disponibles</string>\n    <string name=\"format_sorting\">Clasificación por formatos</string>\n    <string name=\"import_from_preferences\">Importar</string>\n    <string name=\"second\">segundo</string>\n    <string name=\"clear_all_cookies_desc\">¿Borrar definitivamente todas las cookies almacenadas en la aplicación\\?</string>\n    <string name=\"temporary_directory_desc\">Almacena archivos temporales en el directorio seleccionado</string>\n    <string name=\"sponsor\">Patrocinador</string>\n    <string name=\"sponsor_desc\">Apoya esta aplicación patrocinando en GitHub</string>\n    <string name=\"sponsor_msg\">Seal será siempre gratuito y de código abierto para todos. Si te gusta, ¡considera la posibilidad de patrocinarme en GitHub!</string>\n    <string name=\"feedback\">Comentario</string>\n    <string name=\"sponsors\">Patrocinadores</string>\n    <string name=\"audio_format\">Formato del audio</string>\n    <string name=\"no_downloaded_media\">Ningún medio descargado</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">¿Habilitar la función experimental\\?</string>\n    <string name=\"clip_video_desc\">Hacer videoclips en la página de selección del formato</string>\n    <string name=\"clip_video_dialog_msg\">Las descargas que utilicen esta función serán delegadas a FFmpeg para que descargue las secciones seleccionadas del vídeo, esta función es todavía experimental y el corte no será completamente preciso, no todos los formatos soportan esta función y puede que experimentes velocidades de descarga más lentas.</string>\n    <string name=\"switch_to_github_builds\">cambiando a las compilaciones de GitHub</string>\n    <string name=\"okay\">De acuerdo</string>\n    <string name=\"got_it\">Entendido</string>\n    <string name=\"auto_update_disabled_msg\">La actualización automática no está disponible para %1$s builds. Si no tienes %1$s instalado en tu dispositivo, o te gustaría tener una vista previa de las próximas novedades de Seal, considera %2$s.</string>\n    <string name=\"feature_unavailable\">Característica no disponible</string>\n    <string name=\"no_custom_command_tasks\">No hay tareas de comando personalizadas</string>\n    <string name=\"msg_from_developer\">Mensaje del desarrollador</string>\n    <string name=\"sponsor_msg2\">¡Muchas gracias!</string>\n    <string name=\"download_video_desc\">Descargar los vídeos desde la URL</string>\n    <string name=\"convert_subtitle\">Convertir subtítulos</string>\n    <string name=\"split_video_msg\">El video se dividirá en %1$d capítulos</string>\n    <string name=\"convert_subtitle_desc\">Convertir los subtítulos en otro formato</string>\n    <string name=\"split_video\">Dividir video</string>\n    <string name=\"copy_and_exit\">Copiar y salir</string>\n    <string name=\"unknown_error_title\">Oops! Algo salió mal</string>\n    <string name=\"expand\">Expandir</string>\n    <string name=\"new_task\">Nueva tarea de descarga</string>\n    <string name=\"start\">Iniciar</string>\n    <string name=\"edit_template\">Editar \\\"%1$s\\\"</string>\n    <string name=\"ytdlp_update_action\">Actualizar yt-dlp</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"proxy_desc\">Utilizar un proxy para las conexiones a Internet</string>\n    <string name=\"enable_notifications_desc\">La aplicación necesita tu permiso para enviar notificaciones sobre el estado y el progreso de la descarga.</string>\n    <string name=\"disable\">Desactivar</string>\n    <string name=\"set_directory_desc\">Pulsa para configurar el directorio</string>\n    <string name=\"folder_picker\">Selector de carpetas</string>\n    <string name=\"custom_command_directory_desc\">Especifica el directorio de salida cuando utilices los comandos personalizados</string>\n    <string name=\"prefer_quality_desc\">Prefieres los formatos AV1, VP9 o H.265 para verlos en las aplicaciones compatibles</string>\n    <string name=\"legacy\">Legado</string>\n    <string name=\"quality\">Calidad</string>\n    <string name=\"enable_notifications\">¿Activar las notificaciones\\?</string>\n    <string name=\"custom_command_directory\">Directorio de comandos personalizado</string>\n    <string name=\"disabled\">Desactivado</string>\n    <string name=\"prefer_compatibility_desc\">Prefieres los formatos MP4(H.264) para compartir con otras aplicaciones</string>\n    <string name=\"refresh_cookies_desc\">Pulsa para abrir la página web para generar nuevas cookies:</string>\n    <string name=\"download_type\">Tipo de descarga</string>\n    <string name=\"custom\">Personalizada</string>\n    <string name=\"auto\">Automática</string>\n    <string name=\"unknown\">Desconocido</string>\n    <string name=\"commands\">Comandos</string>\n    <string name=\"format_preference\">Preferencia del formato</string>\n    <string name=\"learn_more\">Más información</string>\n    <string name=\"remove_multiple_templates_msg\">¿Quitar %1$s de las plantillas de los comandos para siempre\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d elemento</item>\n        <item quantity=\"many\">%d elementos</item>\n        <item quantity=\"other\">%d elementos</item>\n    </plurals>\n    <string name=\"ua_header\">Encabezado User-Agent</string>\n    <string name=\"export_to_file\">Exportar a un archivo</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp es una potente herramienta de línea de comandos para descargar vídeos. Seal facilita el uso de yt-dlp proporcionando una GUI intuitiva, preajustes para comandos comunes y otras características adicionales.\n\\n\n\\nPara un uso avanzado de yt-dlp, Seal permite crear, guardar y ejecutar plantillas de comandos personalizadas directamente, como en un terminal.\n\\n\n\\nAl utilizar comandos personalizados, la mayoría de las opciones y características de la GUI estarán desactivadas.</string>\n    <string name=\"clear_download_archive\">¿Borrar el archivo de las descargas\\?</string>\n    <string name=\"clear_download_archive_desc\">¿Eliminar %1$s del archivo de forma definitiva\\?</string>\n    <string name=\"presets\">Preajustes</string>\n    <string name=\"output_template\">Formato de salida</string>\n    <string name=\"output_template_desc\">Especifica la plantilla para los nombres de los archivos de salida</string>\n    <string name=\"download_archive_desc\">Registra los ID de los vídeos descargados en un archivo para evitar descargas duplicadas</string>\n    <string name=\"download_archive\">Descargar el archivo</string>\n    <string name=\"embed_metadata\">Insertar los metadatos</string>\n    <string name=\"embed_metadata_desc\">Insertar los metadatos y las miniaturas del vídeo en el archivo de audio</string>\n    <string name=\"required\">Requerido</string>\n    <string name=\"show_all_items\">Mostrar todos los %1$d elementos</string>\n    <string name=\"save\">Guardar</string>\n    <string name=\"edit_file\">Modificar el archivo</string>\n    <string name=\"use_format_sorting\">Utilizar la clasificación por formato</string>\n    <string name=\"restrict_filenames_desc\">Limitar los nombres de archivo a determinados caracteres para garantizar la compatibilidad</string>\n    <string name=\"restrict_filenames\">Restringir los nombres de archivo</string>\n    <string name=\"website\">Página web</string>\n    <string name=\"playlist_title\">Título de la lista de reproducción</string>\n    <string name=\"subdirectory_hint\">Tus descargas se guardarán como:</string>\n    <string name=\"force_ipv4\">Forzar IPv4</string>\n    <string name=\"system_settings\">Configuración del sistema</string>\n    <string name=\"force_ipv4_desc\">Realizar todas las conexiones a través de IPv4</string>\n    <string name=\"keep_subtitle_files\">Guardar los archivos de los subtítulos</string>\n    <string name=\"allow_once\">Permitir una vez</string>\n    <string name=\"dont_allow\">No permitir</string>\n    <string name=\"allow_always\">Permitir siempre</string>\n    <string name=\"download_with_cellular_request\">¿Permitir descargas a través de datos móviles?</string>\n    <string name=\"merge_audiostream\">Fusionar varios flujos de audio</string>\n    <string name=\"merge_audiostream_desc\">Permite fusionar varios flujos de audio en un único archivo</string>\n    <string name=\"search\">Buscar</string>\n    <string name=\"search_in_downloads\">Buscar en descargas</string>\n    <string name=\"auto_translated_subtitles\">Subtítulos traducidos automáticamente</string>\n    <string name=\"subtitle_language_desc\">Idioma de los subtítulos a descargar en la selección de formato automático, separados por comas.</string>\n    <string name=\"remember_for_next_download\">Recordar para la próxima descarga</string>\n    <string name=\"look_and_feel\"><![CDATA[Apariencia]]></string>\n    <string name=\"use_previous_selection\">Utilizar la selección anterior</string>\n    <string name=\"none\">Ninguno</string>\n    <string name=\"reset\">Restablecer</string>\n    <string name=\"search_in_subtitles\">Buscar en los subtítulos</string>\n    <string name=\"update_language_msg\">Los siguientes idiomas se añadirán a sus preferencias para futuras descargas:</string>\n    <string name=\"update_subtitle_languages\">¿Actualizar los idiomas de los subtítulos?</string>\n    <string name=\"no_thanks\">No, gracias</string>\n    <string name=\"auto_translated_subtitles_msg\">Los subtítulos traducidos automáticamente para todos los idiomas estarán disponibles en las descargas. Estos subtítulos pueden ser inexactos y difíciles de entender.</string>\n    <string name=\"import_from\">Importar desde</string>\n    <string name=\"export_download_history\">¿Exportar el historial de descargas?</string>\n    <string name=\"clipboard\">Portapapeles</string>\n    <string name=\"import_download_history\">¿Importar el historial de descargas?</string>\n    <string name=\"export_download_history_msg\">Exportando %1$s del historial de descargas. No se realizará una copia de seguridad de los archivos descargados ni de las preferencias.</string>\n    <string name=\"interface_and_interaction\"><![CDATA[Interfaz e interacción]]></string>\n    <string name=\"export_backup\">Exportar</string>\n    <string name=\"import_backup\">Importar</string>\n    <string name=\"full_backup\">Copia de seguridad completa</string>\n    <string name=\"backup_type\">Tipo de copia de seguridad</string>\n    <string name=\"export_to\">Exportar a</string>\n    <string name=\"file\">Archivo</string>\n    <string name=\"import_download_history_msg\">Los archivos descargados no se importarán. Tendrás que volver a descargarlos manualmente</string>\n    <string name=\"download_history\">Descargar el historial</string>\n    <string name=\"download_history_imported\">Importado %1$s al historial de descargas</string>\n    <string name=\"redownload\">Descargar de nuevo</string>\n    <string name=\"download_archive_error\">El vídeo se ha descargado. Si este no es el comportamiento esperado, compruebe su archivo de descargas.</string>\n    <string name=\"remux_container_mkv\">Contenedor de vídeo Remux</string>\n    <string name=\"remux_container_mkv_desc\">Remezcla vídeos en contenedores MKV para mejorar la compatibilidad</string>\n    <string name=\"every_day\">A diario</string>\n    <string name=\"every_week\">Semanalmente</string>\n    <string name=\"every_month\">Mensual</string>\n    <string name=\"cookies_in_database\">%1$d cookies de %2$d páginas web en total</string>\n    <string name=\"proceed\">Continuar</string>\n    <string name=\"preset\">Programar</string>\n    <string name=\"custom_format_selection_desc\">Elige entre formatos, subtítulos y personaliza aún más</string>\n    <string name=\"edit_preset\">Editar ajuste preestablecido</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d vídeo</item>\n        <item quantity=\"many\">%d vídeos</item>\n        <item quantity=\"other\">%d vídeos</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d audio</item>\n        <item quantity=\"many\">%d audios</item>\n        <item quantity=\"other\">%d audios</item>\n    </plurals>\n    <string name=\"all_languages\">Todos los idiomas</string>\n    <string name=\"playlist\">Lista de reproducción</string>\n    <string name=\"prefer_placeholder\">Prefiero %1$s</string>\n    <string name=\"preset_format_selection_desc\">Descargar automáticamente utilizando tus preferencias de formato</string>\n    <string name=\"best_quality_desc\">Descargar en el mejor formato disponible</string>\n    <string name=\"task_added\">Tarea añadida a la cola</string>\n    <string name=\"you_ll_find_your_downloads_here\">Encontrarás tus descargas aquí</string>\n    <string name=\"download_hint\">Pulsa el botón de descarga o comparte un enlace de vídeo en esta aplicación para iniciar la descarga</string>\n    <string name=\"status_downloaded\">Descargado</string>\n    <string name=\"all\">Todo</string>\n    <string name=\"download_queue\">Cola de descarga</string>\n    <string name=\"select_multiple_link\">Seleccione entre %1$d enlaces</string>\n    <string name=\"show_navigation_drawer\">Mostrar cajón de navegación</string>\n    <string name=\"delete\">Borrar</string>\n    <string name=\"resume\">Resumen</string>\n    <string name=\"media_info\">Información multimedia</string>\n    <string name=\"issue_tracker\">Rastreador de problemas</string>\n    <string name=\"trouble_shooting_desc\">Soluciona errores comunes y comprueba si hay errores conocidos</string>\n    <string name=\"trouble_shooting\">Diagnosticar y resolver un problema</string>\n    <string name=\"issue_tracker_hint\">¿Ha encontrado un error? Antes de reportar un nuevo problema, por favor busque en nuestro rastreador de problemas. Muchos problemas comunes ya se han solucionado y documentado allí.</string>\n    <string name=\"add_to\">Añadir a %1$s</string>\n    <string name=\"add_new_url\">Añadir nuevo enlace</string>\n    <string name=\"saved_urls\">Enlaces guardados</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-eu/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Bideoen kokapena</string>\n    <string name=\"extract_audio\">Gorde audio bezala</string>\n    <string name=\"create_thumbnail\">Gorde miniatura</string>\n    <string name=\"settings\">Ezarpenak</string>\n    <string name=\"download\">Deskargatu</string>\n    <string name=\"download_settings_desc\">Ezarpena orokorrak, formatua eta komando pertsonalizatuak</string>\n    <string name=\"url_empty\">Estekaren hutsuneak ez luke hutsik egon behar</string>\n    <string name=\"extract_audio_summary\">Audioa deskargatu eta gorde, bideoaren ordez</string>\n    <string name=\"create_thumbnail_summary\">Gorde bideoaren miniatura fitxategi bat bezala</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp osagaia eguneratuta dago</string>\n    <string name=\"yt_dlp_update_fail\">Ezin izan da yt-dlp eguneratu. Mesedez, ziurtatu Interneterako konexioa duzula.</string>\n    <string name=\"fetching_info\">Bideoari buruzko informazioa eskuratzen…</string>\n    <string name=\"permission_denied\">Baimena ukatu egin da</string>\n    <string name=\"download_success_msg\">Deskarga amaituta</string>\n    <string name=\"download_error_msg\">Errorea gertatu da deskargatzean</string>\n    <string name=\"download_start_msg\">«%1$s» deskargatzen</string>\n    <string name=\"fetch_info_error_msg\">Errorea gertatu da bideoko informazioa lortzen saiatzean</string>\n    <string name=\"general_settings\">Orokorra</string>\n    <string name=\"language\">Hizkuntza</string>\n    <string name=\"language_settings\">Hautatu hizkuntza</string>\n    <string name=\"task_running\">Deskarga bat egiten ari dira. Itxaron amaitu arte.</string>\n    <string name=\"paste_msg\">Itsatsi URLa paper-zorrotik</string>\n    <string name=\"paste_fail_msg\">Ezin izan da URLa paper-zorrotik itsatsi</string>\n    <string name=\"ytdlp_version\">yt-dlp bertsioa</string>\n    <string name=\"ytdlp_update\">Egin klik yt-dlp osagaia eguneratzeko</string>\n    <string name=\"delete_info\">Historiatik ezabatu\\?</string>\n    <string name=\"delete_info_msg\">Ziur al zaude deskargen historialetik «%1$s»-ko fitxategiak ezabatuko dituzula\\?</string>\n    <string name=\"confirm\">Baieztatu</string>\n    <string name=\"dismiss\">Ezeztatu</string>\n    <string name=\"downloads_history\">Deskargak</string>\n    <string name=\"audio\">Audioa</string>\n    <string name=\"link_copied\">Esteka paper-zorrora kopiatu da</string>\n    <string name=\"open_url\">Ireki esteka</string>\n    <string name=\"remove\">Ezabatu</string>\n    <string name=\"delete_file\">Ezabatu fitxategia</string>\n    <string name=\"about\">Honi buruz</string>\n    <string name=\"about_page\">Bertsioa, aldeketen erregistroa, kredituak</string>\n    <string name=\"back\">Atzera joan</string>\n    <string name=\"version\">Bertsioa</string>\n    <string name=\"release_desc\">Bilatu eguneratzeak eta aldaketen erregistroa</string>\n    <string name=\"release\">Azken aldaketa</string>\n    <string name=\"readme_desc\">Ikusi GitHub biltegia eta README</string>\n    <string name=\"video\">Bideoa</string>\n    <string name=\"checked\">Hautatua</string>\n    <string name=\"credits\">Kredituak</string>\n    <string name=\"credits_desc\">Kredituak eta kode irekiko softwarea</string>\n    <string name=\"custom_command\">Komando pertsonalizatuak</string>\n    <string name=\"custom_command_template\">Komando-txantiloia</string>\n    <string name=\"custom_command_desc\">Exekutatu yt-dlp komando bat txantiloi pertsonalizatu batekin</string>\n    <string name=\"edit\">Eredua editatu</string>\n    <string name=\"start_execute\">Komandoa hasi exekutatzen</string>\n    <string name=\"advanced_settings\">Aurreratua</string>\n    <string name=\"print_details\">Irteera zehatza</string>\n    <string name=\"print_details_desc\">Pantailan mezu garrantzitsuak erakutsi deskargatzean</string>\n    <string name=\"display\">Itxura</string>\n    <string name=\"display_settings\">Itxura iluna, kolore dinamikoak, hizkuntzak</string>\n    <string name=\"dark_theme\">Itxura iluna</string>\n    <string name=\"follow_system\">Sistemaren itxura</string>\n    <string name=\"on\">Aktibatuta</string>\n    <string name=\"off\">Desaktibatuta</string>\n    <string name=\"cancel\">Ezeztatu</string>\n    <string name=\"settings_before_download\">Konfiguratu deskargatu aurretik</string>\n    <string name=\"settings_before_download_desc\">Ezarpenak konfiguratu deskargatu aurretik</string>\n    <string name=\"settings_before_download_text\">Deskarga honetarako lehentasunak konfiguratu</string>\n    <string name=\"error_copied\">Errorea paperzorroan kopiatu da</string>\n    <string name=\"thumbnail\">miniatura</string>\n    <string name=\"paste\">Esteka itsatsi</string>\n    <string name=\"yt_dlp_docs\">yt-dlp-rako erabilera-erreferentziak</string>\n    <string name=\"edit_template_desc\">Irteera-direktorioa eta URLa automatikoki erantsiko ditu aplikazioak.</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-fa/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"download\">بارگیری</string>\n    <string name=\"video_directory\">پوشه ویدئو</string>\n    <string name=\"yt_dlp_up_to_date\">استفاده از آخرین نسخه yt-dlp</string>\n    <string name=\"fetching_info\">در حال دریافت اطلاعات ویدئو…</string>\n    <string name=\"permission_denied\">دسترسی رد شد</string>\n    <string name=\"download_success_msg\">بارگیری به اتمام رسید</string>\n    <string name=\"download_error_msg\">فایل بارگیری نشد</string>\n    <string name=\"language\">نمایش زبان</string>\n    <string name=\"language_settings\">تنظیم زبان</string>\n    <string name=\"task_running\">یک عملیات بارگیری در حال انجام می باشد</string>\n    <string name=\"paste_msg\">جای‌گذاری پیوند</string>\n    <string name=\"ytdlp_version\">نسخه Yt-dlp</string>\n    <string name=\"ytdlp_update\">برای نصب آخرین نسخه yt-dlp کلیک کنید</string>\n    <string name=\"delete_info\">حذف ؟</string>\n    <string name=\"delete_info_msg\">برای همیشه \\\"%1$s\\\" از سابقه دانلود شما حذف شود؟</string>\n    <string name=\"confirm\">تایید</string>\n    <string name=\"link_copied\">پیوند در کلیپ بورد کپی شد</string>\n    <string name=\"delete_file\">حذف فایل</string>\n    <string name=\"about\">درباره</string>\n    <string name=\"about_page\">نسخه ،بازخورد، بروزرسانی خودکار</string>\n    <string name=\"back\">برگشت</string>\n    <string name=\"version\">نسخه</string>\n    <string name=\"release\">آخرین نسخه</string>\n    <string name=\"readme_desc\">به مخزن برنامه در گیتهاب سر بزنید و دستورالعمل ها را مطالعه کنید</string>\n    <string name=\"video\">ویدئو</string>\n    <string name=\"checked\">بررسی شد</string>\n    <string name=\"custom_command\">دستور سفارشی</string>\n    <string name=\"custom_command_template\">قالب دستور</string>\n    <string name=\"start_execute\">اجرای دستور را شروع کنید</string>\n    <string name=\"advanced_settings\">پیشرفته</string>\n    <string name=\"print_details_desc\">هنگام دانلود ، پیام اطلاعات را نمایش دهد</string>\n    <string name=\"display\">نمایش</string>\n    <string name=\"display_settings\">تم سیاه، رنگ داینامیک ، زبان ها</string>\n    <string name=\"dark_theme\">تم تاریک</string>\n    <string name=\"follow_system\">سیستم</string>\n    <string name=\"on\">روشن</string>\n    <string name=\"cancel\">انصراف</string>\n    <string name=\"extract_audio\">ذخیره به عنوان صدا</string>\n    <string name=\"create_thumbnail\">ذخیره تصویر شاخص</string>\n    <string name=\"settings\">تنظیمات</string>\n    <string name=\"url_empty\">پیوند نمی تواند خالی باشد</string>\n    <string name=\"create_thumbnail_summary\">دخیره تصویر شاخص ویدئو به عنوان یک فایل</string>\n    <string name=\"extract_audio_summary\">بارگیری و ذخیره صدای ویدئو</string>\n    <string name=\"yt_dlp_update_fail\">آخرین نسخه yt-dlp نصب نشد ، لطفا از اتصال دستگاه خود به اینترنت اطمینان حاصل فرمایید.</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" بارگیری</string>\n    <string name=\"fetch_info_error_msg\">اطلاعات ویدئو دریافت نشد</string>\n    <string name=\"general_settings\">عمومی</string>\n    <string name=\"paste_fail_msg\">با پیوند موجود در کلیپ بورد مطابقت ندارد</string>\n    <string name=\"downloads_history\">بارگیری‌ها</string>\n    <string name=\"dismiss\">انصراف</string>\n    <string name=\"audio\">صدا</string>\n    <string name=\"open_url\">باز کردن پیوند</string>\n    <string name=\"remove\">حذف</string>\n    <string name=\"credits\">سازندگان</string>\n    <string name=\"custom_command_desc\">دستور yt-dlp را با قالب سفارشی اجرا کنید</string>\n    <string name=\"credits_desc\">سازندگان و کتابخانه نرم افزار</string>\n    <string name=\"edit\">ویرایش</string>\n    <string name=\"off\">خاموش</string>\n    <string name=\"download_settings_desc\">عمومی، فرمت، دستور سفارشی</string>\n    <string name=\"release_desc\">مشاهده تغییرات و نسخه جدید</string>\n    <string name=\"print_details\">خروجی انتخابی</string>\n    <string name=\"settings_before_download_text\">تنظیم دانلود</string>\n    <string name=\"error_copied\">کپی گزارش خطا در کلیپ بورد</string>\n    <string name=\"thumbnail\">پیش‌نمایش</string>\n    <string name=\"paste\">چسباندن</string>\n    <string name=\"yt_dlp_docs\">مراجع استفاده از Yt-dlp</string>\n    <string name=\"convert_audio_format\">تبدیل فرمت صدا</string>\n    <string name=\"convert_to\">تبدیل به %1$s</string>\n    <string name=\"format\">فرمت</string>\n    <string name=\"convert_audio_format_desc\">صدا با فرمت MP3 یا M4A در اکثر دستگاه ها کار می کند.</string>\n    <string name=\"preferred_format_desc\">فرمت ترجیحی زمانی که چندین مورد دسترس باشند</string>\n    <string name=\"close\">بستن</string>\n    <string name=\"close_never_show_again\">دوباره نمایش نده</string>\n    <string name=\"open_settings\">باز کردن تنظیمات</string>\n    <string name=\"video_format_preference\">فرمت ویدئو انتخابی</string>\n    <string name=\"download_desc\">پس از تنظیم تنظیمات آن، روی \\\"دانلود\\\" کلیک کنید.</string>\n    <string name=\"download_history_desc\">دانلودهای درون برنامه ای، از جمله فیلم ها و فایل های صوتی را بررسی و مدیریت کنید.</string>\n    <string name=\"download_playlist\">دانلود لیست پخش</string>\n    <string name=\"download_playlist_desc\">چندین ویدیو را از یک لیست پخش دانلود کنید</string>\n    <string name=\"defaults\">پیش‌فرض</string>\n    <string name=\"channel_name\">دانلود</string>\n    <string name=\"battery_settings_desc\">لطفاً برای بارگیری در پس‌زمینه، بهینه ساز باتری این برنامه را در تنظیمات سیستم روی \\\"بدون محدودیت\\\" تنظیم کنید.</string>\n    <string name=\"concurrent_download\">دانلود چند قسمتی</string>\n    <string name=\"concurrent_download_desc\">قسمت های بیشتری از ویدیوهای M3U8/MPD را به صورت موازی دانلود کنید</string>\n    <string name=\"share_success_msg\">خواندن پیوند ویدیو از محتوای اشتراک‌گذاری شده…</string>\n    <string name=\"show_more_actions\">نمایش اقدامات بیشتر</string>\n    <string name=\"download_notification\">اعلان دانلود</string>\n    <string name=\"fetching_playlist_info\">در حال دریافت اطلاعات لیست پخش…</string>\n    <string name=\"download_range_selection\">انتخاب لیست پخش</string>\n    <string name=\"download_range_desc\">محدوده ی ویدیوها را برای دانلود از لیست \\\"%3$s\\\" پخش مشخص کنید (از %1$d تا %2$d).</string>\n    <string name=\"from\">شروع از</string>\n    <string name=\"to\">پایان از</string>\n    <string name=\"playlist_indicator_text\">در حال دانلود لیست پخش (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">پوشه صدا</string>\n    <string name=\"subdirectory_desc\">فایل‌ها را در پوشه‌هایی با نام حیطه مربوطه ذخیره کنید</string>\n    <string name=\"permission_issue\">مشکل در مجوز ذخیره سازی</string>\n    <string name=\"permission_issue_desc\">دایرکتوری های خارج از Download/ و Documents/ پشتیبانی نمی شوند</string>\n    <string name=\"service_title\">Seal در حال دانلود است…</string>\n    <string name=\"best_quality\">بهترین کیفیت (پیش فرض)</string>\n    <string name=\"settings_before_download\">قبل از دانلود پیکربندی کنید</string>\n    <string name=\"settings_before_download_desc\">تنظیمات برگزیده را قبل از دانلود پیکربندی کنید</string>\n    <string name=\"edit_template_desc\">مسیر خروجی و پیوند توسط برنامه اضافه خواهد شد.</string>\n    <string name=\"not_convert\">تبدیل نشده</string>\n    <string name=\"video_quality\">کیفیت ویدئو</string>\n    <string name=\"video_quality_desc\">در صورت وجود چندگانه، کیفیت فرمت ویدئو و اندازه فایل را محدود کنید</string>\n    <string name=\"not_specified\">مشخص نشده (پیش فرض)</string>\n    <string name=\"convert_audio\">تبدیل</string>\n    <string name=\"battery_configuration_desc\">بهینه سازی باتری را برای دانلود در پس زمینه این برنامه نادیده بگیرید</string>\n    <string name=\"translate\">ترجمه</string>\n    <string name=\"video_format\">فرمت ویدئو</string>\n    <string name=\"download_notification_desc\">اطلاع از فایل های دانلود شده و پیشرفت</string>\n    <string name=\"unknown_error\">خطای ناشناخته</string>\n    <string name=\"start_download\">بارگیری</string>\n    <string name=\"user_guide\">راهنمای کاربر</string>\n    <string name=\"share_fail_msg\">مطابقت پیوند از محتوای مشترک ممکن نیست</string>\n    <string name=\"translate_desc\">به ترجمه این برنامه در Weblate میزبانی شده کمک کنید</string>\n    <string name=\"paste_desc\">برای دریافت پیوند ویدیو از کلیپ‌بورد، روی \\\"جای‌گذاری\\\" کلیک کنید.</string>\n    <string name=\"check_download_settings_desc\">به تنظیمات دانلود نگاهی بیندازید و قبل از استفاده مطمئن شوید که آخرین نسخه yt-dlp را دارید.</string>\n    <string name=\"channel_description\">اطلاع از فایل های دانلود شده و پیشرفت دانلود</string>\n    <string name=\"video_url\">پیوند ویدئو</string>\n    <string name=\"download_finish_notification\">دانلود تمام شد. برای باز کردن ضربه بزنید.</string>\n    <string name=\"execute_command_notification\">در حال اجرای دستور سفارشی …</string>\n    <string name=\"concurrent_download_num\">ا ز%d شته(های) برای دانلود همزمان ویدیوی بومی DASH/HLS استفاده می شود.</string>\n    <string name=\"download_directory\">پوشه دانلود</string>\n    <string name=\"options\">گزینه ها</string>\n    <string name=\"additional_settings\">تنظیمات اضافی</string>\n    <string name=\"download_directory_desc\">محل ذخیره فیلم ها و فایل های صوتی را انتخاب کنید</string>\n    <string name=\"subdirectory\">ذخیره در زیر شاخه پوشه</string>\n    <string name=\"invalid_index_range\">محدوده شاخص نامعتبر است</string>\n    <string name=\"battery_configuration\">پیکربندی باتری</string>\n    <string name=\"audio_format_preference\">فرمت صوتی ترجیحی</string>\n    <string name=\"unlimited\">نامحدود</string>\n    <string name=\"lowest_bitrate\">کمترین میزان بیت ریت</string>\n    <string name=\"audio_quality\">کیفیت صدا</string>\n    <string name=\"audio_quality_desc\">وقتی کیفیت های متعدد وجود دارد، میزان بیت ریت صدا را محدود کنید</string>\n    <string name=\"format_sorting\">مرتب سازی فرمت</string>\n    <string name=\"format_sorting_desc\">مرتب سازی فرمت ها با گزینه -S yt-dlp</string>\n    <string name=\"import_from_preferences\">وارد كردن</string>\n    <string name=\"title\">عنوان</string>\n    <string name=\"minute\">دقیقه</string>\n    <string name=\"second\">ثانیه</string>\n    <string name=\"clear_all_cookies\">حذف تمام کوکی ها</string>\n    <string name=\"clear_all_cookies_desc\">تمام کوکی های ذخیره شده در برنامه را برای همیشه حذف کنید؟</string>\n    <string name=\"filesize_gb\">%.2f گیگ‌بایت</string>\n    <string name=\"invalid_input\">ورودی نامعتبر</string>\n    <string name=\"suggested\">پیشنهادی</string>\n    <string name=\"subtitle_sponsorblock\">ممکن است هنگام حذف بخش‌های SponsorBlock، زیرنویس‌ها از بین بروند.</string>\n    <string name=\"share\">اشتراک</string>\n    <string name=\"stable_channel\">پایدار</string>\n    <string name=\"pre_release_channel\">پیش نمایش</string>\n    <string name=\"update_channel_desc\">برای پیش نمایش ویژگی ها و تغییرات جدید، نسخه پیش از انتشار را نصب کنید.\n\\n\n\\nدر این نسخه‌ها مقداری بی‌ثباتی وجود خواهد داشت، بنابراین لطفاً در صورت بروز هرگونه مشکل در ارائه بازخورد به ما دریغ نکنید تا به ما در بهبود برنامه برای آینده کمک کنید.</string>\n    <string name=\"update_channel\">به روز رسانی کانال</string>\n    <string name=\"auto_update\">بروزرسانی خودکار</string>\n    <string name=\"enable_auto_update\">فعال سازی بروزرسانی خودکار</string>\n    <string name=\"delete_multiple_items_msg\">%1$d مورد(ها) از سابقه بارگیری شما برای همیشه حذف شود؟</string>\n    <string name=\"show_logs\">نمایش گزارش</string>\n    <string name=\"logs\">گزارش</string>\n    <string name=\"status_enqueued\">در صف قرار گرفته است</string>\n    <string name=\"status_completed\">به پایان رسید</string>\n    <string name=\"multiselect_mode\">حالت چند انتخابی</string>\n    <string name=\"sponsorblock_desc\">حذف یا علامت گذاری بخش‌های ویدئو با کمک سرویس SponsorBlock</string>\n    <string name=\"cookies_desc\">برای دانلود از کوکی های فرمت شده Netscape استفاده کنید</string>\n    <string name=\"clear_temp_files_info\">از فایل‌های موقت می‌توان برای از سرگیری دانلودهای لغو شده استفاده کرد. آیا مطمئن هستید که همهٔ این فایل‌ها را حذف می‌کنید؟\n\\n\n\\nمی‌توانید این فایل‌ها را در %1$s ببینید</string>\n    <string name=\"rate_limit\">حد نرخ</string>\n    <string name=\"network_settings_desc\">محدودیت نرخ، دانلود کننده، کوکی ها</string>\n    <string name=\"disable_preview_desc\">غیرفعال کردن پیش نمایش هنگام دانلود</string>\n    <string name=\"crop_artwork\">برش آثار هنری</string>\n    <string name=\"private_directory_desc\">دانلودها را در یک دایرکتوری مخفی ذخیره شود</string>\n    <string name=\"crop_artwork_desc\">تصویر جاسازی شده را به مربع برش دهید</string>\n    <string name=\"video_only\">ویدئو (بدون صدا)</string>\n    <string name=\"auto_subtitle_desc\">دانلود زیرنویس های خودکار ساخته شده</string>\n    <string name=\"custom_command_enabled_hint\">برخی از گزینه ها هنگام استفاده از دستور سفارشی در دسترس نیستند</string>\n    <string name=\"cookies_usage_msg\">دانلود از برخی سایت ها به اطلاعات احراز هویت حساب کاربری نیاز دارد. روی «ایجاد کوکی‌های جدید» کلیک کنید، آدرس وب سایت را وارد کنید و سپس با حساب کاربری خود در صفحه مرورگر وارد شوید، برنامه آن را برای شما تولید می‌کند.</string>\n    <string name=\"filesize_mb\">%.2f مگابایت</string>\n    <string name=\"rename\">ویرایش نام</string>\n    <string name=\"download_with_cellular\">دانلود با استفاده از اینترنت سیم کارت</string>\n    <string name=\"download_with_cellular_desc\">هنگامی که به شبکه‌های اندازه‌گیری شده متصل می‌شوید، بارگیری رسانه را مجاز کنید</string>\n    <string name=\"download_disabled_with_cellular\">دانلود با شبکه تلفن همراه با توجه به تنظیمات شما غیرفعال است</string>\n    <string name=\"discard\">رد کردن</string>\n    <string name=\"apply\">اعمال</string>\n    <string name=\"clip_video\">کلیپ ویدیو</string>\n    <string name=\"clip_start\">شروع</string>\n    <string name=\"clip_end\">پایان</string>\n    <string name=\"check_for_updates\">بررسی بروزرسانی</string>\n    <string name=\"clear_temp_files\">فایل های موقت را پاک کنید</string>\n    <string name=\"telegram_channel\">کاناال تلگرام</string>\n    <string name=\"task_canceled\">عملیات دانلود لغو شد</string>\n    <string name=\"dynamic_color_desc\">رنگ ها را از والپیپرها به تم برنامه اعمال کنید</string>\n    <string name=\"clear_temp_files_count\">%1$d فایل(های) موقت حذف شد</string>\n    <string name=\"format_selection_desc\">قبل از شروع دانلود، فرمت مورد نظر را برای دانلود انتخاب کنید</string>\n    <string name=\"downloading_indicator_text\">دانلود در حال انجام است…</string>\n    <string name=\"private_directory\">دایرکتوری خصوصی</string>\n    <string name=\"embed_subtitles\">چسباندن زیرنویس</string>\n    <string name=\"new_template\">ساخت الگو جدید</string>\n    <string name=\"copy_link\">کپی پیوند</string>\n    <string name=\"app_up_to_date\">نسخه فعلی به روز است</string>\n    <string name=\"clear_temp_files_desc\">تمام فایل های موقت را از پوشه موقت حذف کنید</string>\n    <string name=\"disable_preview\">غیرفعال کردن پیش نمایش</string>\n    <string name=\"privacy\">حریم خصوصی</string>\n    <string name=\"use_custom_command\">انتخاب دستور سفارشی</string>\n    <string name=\"select_all\">انتخاب همه</string>\n    <string name=\"restart\">راه اندازی مجدد</string>\n    <string name=\"status_error\">خطا</string>\n    <string name=\"copy_error_report\">کپی گزارش</string>\n    <string name=\"video_resolution\">کیفیت ویدیو</string>\n    <string name=\"app_update_failed\">به آخرین نسخه به روز رسانی نشد</string>\n    <string name=\"update\">بروزرسانی</string>\n    <string name=\"check_for_updates_desc\">به طور خودکار آخرین نسخه را در GitHub بررسی کنید</string>\n    <string name=\"cookies\">کوکی ها</string>\n    <string name=\"format_selection\">انتخاب فرمت</string>\n    <string name=\"generate_new_cookies\">ساخت کوکی جدید</string>\n    <string name=\"embed_subtitles_desc\">در صورت موجود، زیرنویس‌‌های جداگانه بر روی ویدیوها نصب شوند</string>\n    <string name=\"template_label\">عنوان</string>\n    <string name=\"remove_template\">آیا حذف شود؟</string>\n    <string name=\"remove_template_desc\">برای همیشه \\\"%1$s\\\" از الگوهای خوب حذف شود؟</string>\n    <string name=\"template_selection\">انتخاب الگو</string>\n    <string name=\"custom_command_template_desc\">الگو های فرمان را ویرایش و مدیریت کنید</string>\n    <string name=\"github_issue_desc\">یک درخواست برای گزارش اشکال یا درخواست ویژگی ارسال کنید</string>\n    <string name=\"info_copied\">اطلاعات در کلیپ بورد کپی شد</string>\n    <string name=\"github_issue\">ارسال مشکل در گیتهاب</string>\n    <string name=\"status_canceled\">لغو شد</string>\n    <string name=\"status_fetching_video_info\">در حال دریافت اطلاعات</string>\n    <string name=\"open_file\">باز کردن فایل</string>\n    <string name=\"export_to_clipboard\">استخراج به کلیپ برد</string>\n    <string name=\"download_task_count\">%1$d عملیات در حال دانلود</string>\n    <string name=\"use_cookies\">انتخاب کوکی ها</string>\n    <string name=\"remove_cookie_profile_desc\">این ورودی به ازای «%1$s» حذف شود؟ لطفا بخاطر داشته باشید که کوکی‌های ذخیره شده در این سایت پاک نمی‌شوند.</string>\n    <string name=\"how_does_it_work\">چگونه کار می کند؟</string>\n    <string name=\"matrix_space\">فضای ماتریس</string>\n    <string name=\"recently_added\">به تازگی اضافه شده</string>\n    <string name=\"status_downloading\">در حال دانلود</string>\n    <string name=\"video_file_size\">اندازه فایل ویدیویی</string>\n    <string name=\"import_from_clipboard\">وارد کردن از کلیپ برد</string>\n    <string name=\"template_exported\">%1$d الگو(های) صادر شد</string>\n    <string name=\"template_imported\">%1$d الگو(های) وارد شد</string>\n    <string name=\"multiselect_item_count\">%1$d ویدیو، %2$d فایل صوتی</string>\n    <string name=\"sponsorblock_categories_desc\">دسته‌بندی‌های SponsorBlock را برای حذف از فایل ویدئو یا علامت‌گذاری در آن مشخص کنید</string>\n    <string name=\"sponsorblock_categories\">دسته های SponsorBlock</string>\n    <string name=\"aria2_desc\">از aria2c به عنوان دانلودر خارجی استفاده کنید</string>\n    <string name=\"private_mode\">حالت خصوصی</string>\n    <string name=\"private_mode_desc\">غیرفعال کردن سابقه دانلود</string>\n    <string name=\"dynamic_color\">رنگ پویا</string>\n    <string name=\"file_unavailable\">این فایل دیگر در دسترس نیست</string>\n    <string name=\"network\">شبکه</string>\n    <string name=\"rate_limit_desc\">حداکثر سرعت بارگیری را مشخص کنید</string>\n    <string name=\"max_rate\">حداکثر تعداد</string>\n    <string name=\"high_contrast\">تم تیره با کنتراست بالا</string>\n    <string name=\"lowest_quality\">پایین ترین کیفیت</string>\n    <string name=\"unavailable\">در دسترس نیست</string>\n    <string name=\"format_settings_desc\">فرمت فایل، کیفیت ویدئو، زیرنویس</string>\n    <string name=\"general_settings_desc\">نسخه Yt-dlp، اعلان، لیست پخش</string>\n    <string name=\"download_selection_desc\">ویدیوها را برای بارگیری از لیست پخش \\\"%1$s\\\" انتخاب کنید</string>\n    <string name=\"selected_item_count\">%1$d مورد انتخاب شد</string>\n    <string name=\"sdcard_directory\">پوشه حافظه خارجی</string>\n    <string name=\"auto_subtitle\">زیرنویس های خودکار</string>\n    <string name=\"title_activity_share\">دانلود سریع</string>\n    <string name=\"abs_hint\">اکثر پلتفرم‌های پخش ویدیو صدا و تصویر را به طور جداگانه ارائه می‌کنند، می‌توانید یک فرمت فقط صوتی را با یک فرمت فقط ویدیویی در یک ویدیو انتخاب و ادغام کنید.</string>\n    <string name=\"video_title_sample_text\">متن نمونه عنوان ویدیو</string>\n    <string name=\"video_creator_sample_text\">متن نمونه سازنده ویدیو</string>\n    <string name=\"subtitle\">زیرنویس</string>\n    <string name=\"download_subtitles\">دانلود زیرنویس ها</string>\n    <string name=\"subtitle_language\">زبان های زیرنویس</string>\n    <string name=\"subtitle_desc\">زبان‌ها، قرار دادن زیرنویس‌ها، زیرنویس‌های خودکار</string>\n    <string name=\"copy_log\">کپی گزارش ها</string>\n    <string name=\"clear\">پاک سازی</string>\n    <string name=\"edit_shortcuts\">ویرایش میانبر</string>\n    <string name=\"add\">افزودن</string>\n    <string name=\"shortcuts\">شورتکات ها</string>\n    <string name=\"edit_shortcuts_desc\">میانبرهای سفارشی را ویرایش کنید که می توان از آنها برای نوشتن الگوهای فرمان استفاده کرد.</string>\n    <string name=\"running_tasks\">عملیات های در حال اجرا</string>\n    <string name=\"embed_subtitles_mkv_msg\">برای جاسازی زیرنویس‌ها، فیلم‌ها به فرمتmkv تبدیل می‌شوند. شما می‌توانید از VLC Media Player یا سایر برنامه‌های سازگار برای تماشای فیلم‌ها با زیرنویس نچسبیده استفاده کنید.</string>\n    <string name=\"beta_features\">آزمایشی</string>\n    <string name=\"enable_experimental_feature\">ویژگی آزمایشی فعال شود؟</string>\n    <string name=\"clip_video_desc\">در صفحه انتخاب فرمت کلیپ های ویدیویی بسازید</string>\n    <string name=\"sponsor_msg2\">بسیار از شما متشکرم!</string>\n    <string name=\"audio_format\">فرمت صوتی</string>\n    <string name=\"no_downloaded_media\">رسانه دانلود شده ای وجود ندارد</string>\n    <string name=\"auto_update_disabled_msg\">به‌روزرسانی خودکار برای ساخت‌های %1$s در دسترس نیست. اگر %1$s را روی دستگاه خود نصب نکرده‌اید، یا می‌خواهید ویژگی‌های جدید آینده را در Seal پیش‌نمایش کنید، لطفاً %2$s را در نظر بگیرید.</string>\n    <string name=\"clip_video_dialog_msg\">دانلودهایی که از این ویژگی استفاده می کنند به FFmpeg واگذار می شود تا بخش های انتخابی ویدیو را دانلود کند، این ویژگی همچنان آزمایشی است و برش کاملاً دقیق نخواهد بود، همه فرمت ها از این ویژگی پشتیبانی نمی کنند و ممکن است سرعت دانلود پایین تری را تجربه کنید.</string>\n    <string name=\"msg_from_developer\">پیام از طرف توسعه دهنده</string>\n    <string name=\"switch_to_github_builds\">تغییر به نسخه گیتهاب</string>\n    <string name=\"okay\">بسیار خب</string>\n    <string name=\"got_it\">فهمیدم</string>\n    <string name=\"feature_unavailable\">ویژگی در دسترس نیست</string>\n    <string name=\"prefix\">پیشوند</string>\n    <string name=\"no_custom_command_tasks\">بدون وظایف دستوری سفارشی</string>\n    <string name=\"sponsor\">حامی مالی</string>\n    <string name=\"sponsor_desc\">با حمایت مالی در GitHub از این برنامه حمایت کنید</string>\n    <string name=\"sponsor_msg\">Seal همیشه رایگان و منبع باز برای همه خواهد بود. اگر دوست دارید، لطفاً در GitHub از من حمایت کنید!</string>\n    <string name=\"feedback\">بازخورد</string>\n    <string name=\"sponsors\">حامیان</string>\n    <string name=\"temporary_directory_desc\">دخیره فایل های موقت را در دایرکتوری داخلی</string>\n    <string name=\"clear_download_archive\">خالی کردن بایگانی دانلود؟</string>\n    <string name=\"save\">ذخیره</string>\n    <string name=\"split_video_msg\">ویدیو به %1$d قسمت تقسیم خواهد شد</string>\n    <string name=\"export_to_file\">خروجی به فایل</string>\n    <string name=\"enable_notifications_desc\">برای ارسال اعلان در مورد وضعیت دانلودها، اپ به اجازهٔ شما نیاز دارد.</string>\n    <string name=\"folder_picker\">انتخاب پوشه</string>\n    <string name=\"split_video\">تقسیم ویدیو</string>\n    <string name=\"prefer_compatibility_desc\">ترجیح فرمت MP4 (H.264) هنگامی که با اپ‌های دیگر به اشتراک گذاشته می‌شود</string>\n    <string name=\"download_video_desc\">دانلود ویدیو از نشانی</string>\n    <string name=\"clear_download_archive_desc\">حذف همیشگی %1$s از بایگانی؟</string>\n    <string name=\"edit_template\">ویرایش «%1$s»</string>\n    <string name=\"website\">وب‌سایت</string>\n    <string name=\"unknown\">ناشناخته</string>\n    <string name=\"learn_more\">بیشتر بدانید</string>\n    <string name=\"convert_subtitle\">تبدیل زیرنویس‌ها</string>\n    <string name=\"prefer_quality_desc\">ترجیح فرمت AV1، VP9 یا H.265 هنگام تماشا در اپ‌های همگام</string>\n    <string name=\"download_type\">نوع دانلود</string>\n    <string name=\"legacy\">قدیمی</string>\n    <string name=\"unknown_error_title\">بهه! مشکلی پیش آمد</string>\n    <string name=\"set_directory_desc\">برای معین کردن پوشه، ضربه بزنید</string>\n    <string name=\"start\">آغاز</string>\n    <string name=\"restrict_filenames_desc\">نام فایل‌ها رو محدود به کاراکترهای خاصی کنید تا از همگام بودن مطمئن شوید</string>\n    <string name=\"new_task\">دانلود جدید</string>\n    <string name=\"copy_and_exit\">کپی کن و خارج شو</string>\n    <string name=\"required\">ضروری</string>\n    <string name=\"convert_subtitle_desc\">تبدیل زیرنویس‌ها به فرمتی دیگر</string>\n    <string name=\"show_all_items\">نمایش همهٔ %1$d مورد</string>\n    <string name=\"output_template\">قالب خروجی</string>\n    <string name=\"disabled\">غیرفعال</string>\n    <string name=\"disable\">غیرفعال</string>\n    <string name=\"auto\">خودکار</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d مورد</item>\n        <item quantity=\"other\">%d مورد</item>\n    </plurals>\n    <string name=\"expand\">گسترش</string>\n    <string name=\"proxy_desc\">از پروکسی استفاده کن</string>\n    <string name=\"quality\">کیفیت</string>\n    <string name=\"restrict_filenames\">محدودکردن نام فایل‌ها</string>\n    <string name=\"edit_file\">ویرایش فایل</string>\n    <string name=\"custom\">انتخابی</string>\n    <string name=\"ytdlp_update_action\">به روزرسانی yt-dlp</string>\n    <string name=\"playlist_title\">عنوان فهرست پخش</string>\n    <string name=\"download_archive\">بایگانی دانلود</string>\n    <string name=\"enable_notifications\">فعال کردن اعلان؟</string>\n    <string name=\"proxy\">پروکسی</string>\n    <string name=\"look_and_feel\">بر و رو</string>\n    <string name=\"interface_and_interaction\">رابط و تعامل</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp یک ابزار دستور متنی برای دانلود ویدئو است. Seal، استفاده از yt-dlp را با کمک محیط گرافیک قابل‌فهم، دستورات مرسوم پیش‌فرض، و قابلیت‌های اضافی آسان می‌کند.\n\\n\n\\nSeal با کمک ساختن، ذخیره و اجرا قالب‌های دستوری مرسوم به صورت مستقیم، همانند ترمینال، به شما اجازه می‌دهد تا از قابلیت‌های پیشرفته بهره‌مند شوید.\n\\n\n\\nهنگام استفاده از دستورات، اکثر تنظیمات و قابلیت‌ها غیرفعال می‌شوند.</string>\n    <string name=\"commands\">دستورات</string>\n    <string name=\"format_preference\">فرمت ترجیحی</string>\n    <string name=\"presets\">تنظیمات پیش‌فرض</string>\n    <string name=\"embed_metadata_desc\">جاسازی مِتا دیتا و پیش‌نمایش ویدئو در فایل صوتی</string>\n    <string name=\"embed_metadata\">جاسازی مِتا دیتا</string>\n    <string name=\"allow_once\">اجازه یکباره</string>\n    <string name=\"use_format_sorting\">از مرتب‌سازی فرمت استفاده شود</string>\n    <string name=\"allow_always\">اجازه همیشگی</string>\n    <string name=\"dont_allow\">اجازه نده</string>\n    <string name=\"download_with_cellular_request\">دانلود با دیتا گوشی اجازه داده شود؟</string>\n    <string name=\"subdirectory_hint\">دانلود شما ذخیره می‌شود در:</string>\n    <string name=\"keep_subtitle_files\">فایل‌های زیرنویس نگهداری شوند</string>\n    <string name=\"output_template_desc\">قالب را برای نام‌های فایل خروجی مشخص کنید</string>\n    <string name=\"use_previous_selection\">انتخاب قبلی استفاده شود</string>\n    <string name=\"remember_for_next_download\">برای دانلود بعدی بخاطر داشته باش</string>\n    <string name=\"system_settings\">تنظیمات سیستم</string>\n    <string name=\"reset\">ریست</string>\n    <string name=\"search_in_subtitles\">جستجو در زیرنویس‌ها</string>\n    <string name=\"no_thanks\">نه ممنون</string>\n    <string name=\"import_download_history_msg\">فایل‌های دانلود شده وارد نمی‌شوند. شما باید آنها را دوباره به صورت دستی دانلود کنید</string>\n    <string name=\"import_download_history\">تاریخچه دانلود وارد شود؟</string>\n    <string name=\"export_download_history\">تاریخچه دانلود خروجی گرفته شود؟</string>\n    <string name=\"import_from\">وارد کردن از</string>\n    <string name=\"clipboard\">تایخچه کپی</string>\n    <string name=\"file\">فایل</string>\n    <string name=\"export_to\">خروجی گرفته شود به</string>\n    <string name=\"backup_type\">نوع بَک‌آپ</string>\n    <string name=\"full_backup\">بَک‌آپ کامل</string>\n    <string name=\"none\">هیچ‌ یک</string>\n    <string name=\"download_history\">تاریخچه دانلود</string>\n    <string name=\"every_month\">هر ماه</string>\n    <string name=\"every_week\">هر هفته</string>\n    <string name=\"every_day\">هر روز</string>\n    <string name=\"redownload\">دانلود دوباره</string>\n    <string name=\"import_backup\">وارد کردن</string>\n    <string name=\"export_backup\">خارج کردن</string>\n    <string name=\"update_subtitle_languages\">زبان‌های زیرنویس بروز شوند؟</string>\n    <string name=\"update_language_msg\">زبان‌های زیر برای دانلودهای بعدی به اولویت شما اضافه می‌شوند:</string>\n    <string name=\"refresh_cookies_desc\">برای باز کردن صفحه وب برای تولید کوکی‌های جدید، ضربه بزنید:</string>\n    <string name=\"custom_command_directory\">پوشه دستورات سفارشی</string>\n    <string name=\"custom_command_directory_desc\">پوشه خروجی را هنگام استفاده از دستورات سفارشی را مشخص کن</string>\n    <string name=\"all_languages\">همه زبان ها</string>\n    <string name=\"playlist\">لیست پخش</string>\n    <string name=\"proceed\">ادامه</string>\n    <string name=\"preset\">تنظیمات پیش فرض</string>\n    <string name=\"prefer_placeholder\">ترجیح دادن %1$s</string>\n    <string name=\"preset_format_selection_desc\">دانلود اتوماتیک با استفاده از تنظیمات فرمت</string>\n    <string name=\"edit_preset\">تغییر تنظیمات پیش فرض</string>\n    <string name=\"best_quality_desc\">دانلود بهترین فرمت موجود</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d صدا</item>\n        <item quantity=\"other\">%d صدا</item>\n    </plurals>\n    <string name=\"task_added\">عملیات به صف اضافه شد</string>\n    <string name=\"force_ipv4_desc\">اتصال همه از طریق IPv4</string>\n    <string name=\"remove_multiple_templates_msg\">برای همیشه %1$s از قالب های دستورات پاک شود؟</string>\n    <string name=\"custom_format_selection_desc\">از فرمت ها و زیرنویس ها انتخاب کنید و به دلخواه تنظیم کنید</string>\n    <string name=\"search\">جستجو</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d ویدئو</item>\n        <item quantity=\"other\">%d ویدئو</item>\n    </plurals>\n    <string name=\"merge_audiostream\">ترکیب چند صدا</string>\n    <string name=\"merge_audiostream_desc\">اجازه برای ترکیب کردن چند صدا به یک فایل</string>\n    <string name=\"ua_header\">سرصفحه کاربر</string>\n    <string name=\"remux_container_mkv\">مخزن ویدئو ریموکس</string>\n    <string name=\"remux_container_mkv_desc\">ورود ویدئو های ریموکس به مخزن MKV برای پشتیبانی بهتر</string>\n    <string name=\"download_archive_error\">این ویدئو دانلود شد. اگر این غیر منتظره است، لطفا بایگانی دانلودتان را چک کنید.</string>\n    <string name=\"export_download_history_msg\">در حال استخراج %1$s از تاریخچه دانلود. فایل های دانلود شده و تنظیمات نسخه پشتیبانی نخواهند داشت.</string>\n    <string name=\"cookies_in_database\">%1$d کوکی از %2$d وبسایت در کل</string>\n    <string name=\"auto_translated_subtitles\">ترجمه زیرنویس اتوماتیک</string>\n    <string name=\"auto_translated_subtitles_msg\">زیرنویس با ترجمه اتوماتیک برای همه ی زبان ها در دسترس خواهند بود. این زیرنویس ها ممکن است اشتباه یا درک کردنشان دشوار باشد.</string>\n    <string name=\"subtitle_language_desc\">زبان زیرنویس های فرمت اتوماتیک برای دانلود، جدا شده با ویرگول.</string>\n    <string name=\"download_archive_desc\">برای تکراری نشدن دانلود ها، شناسه ویدئو های دانلود شده را درون بایگانی ضبط کنید</string>\n    <string name=\"force_ipv4\">مجبور استفاده از IPv4</string>\n    <string name=\"download_history_imported\">%1$s به تاریخچه دانلود وارد شد</string>\n    <string name=\"search_in_downloads\">جستجو در دانلود ها</string>\n    <string name=\"you_ll_find_your_downloads_here\">بارگذاری‌هایتان را اینجا پیدا خواهید کرد</string>\n    <string name=\"status_downloaded\">بارگذاری شد</string>\n    <string name=\"download_hint\">بر روی گزینه بارگذاری کلیک کنید یا لینک یک ویدئو را با این نرم‌افزار اشتراک گذاری فرمایید تا یک بارگذاری شروع شود</string>\n    <string name=\"all\">همه</string>\n    <string name=\"select_multiple_link\">از پیوندهای %1$d انتخاب فرمایید</string>\n    <string name=\"download_queue\">صف بارگذاری</string>\n    <string name=\"trouble_shooting\">رفع اشکال</string>\n    <string name=\"issue_tracker\">ردیاب مشکل</string>\n    <string name=\"trouble_shooting_desc\">خطاهای رایج را حل و مشکلات شناخته شده را بررسی کنید</string>\n    <string name=\"show_navigation_drawer\">نمایش نوار ناوبری</string>\n    <string name=\"delete\">پاک کن</string>\n    <string name=\"resume\">ادامه بده</string>\n    <string name=\"media_info\">اطلاعات رسانه</string>\n    <string name=\"issue_tracker_hint\">به خطایی برخوردید؟ قبل از گزارش یک مشکل جدید، لطفاً ردیاب مشکل ما را جستجو کنید. تاکنون بسیاری از مشکلات رایج در آنجا خطاب و مستند شده‌اند.</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-fil/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">I-save bilang audio</string>\n    <string name=\"create_thumbnail\">I-save ang thumbnail</string>\n    <string name=\"settings\">Mga Setting</string>\n    <string name=\"download_settings_desc\">Pangkahalatan, format, custom na command</string>\n    <string name=\"download\">Download</string>\n    <string name=\"url_empty\">Hindi pwedeng walang laman ang link</string>\n    <string name=\"video_directory\">Folder ng video</string>\n    <string name=\"extract_audio_summary\">I-download at I-save ang audio, sa halip ng video</string>\n    <string name=\"create_thumbnail_summary\">I-save ang video thumbnail bilang isang file</string>\n    <string name=\"download_error_msg\">Hindi ma-download ang file</string>\n    <string name=\"download_start_msg\">Dina-download \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Hindi makuha ang impo ng video</string>\n    <string name=\"fetching_info\">Kumukuha ng impo mula sa video…</string>\n    <string name=\"permission_denied\">Tinanggihan ang permiso</string>\n    <string name=\"language_settings\">I-set ang wika ng pag-display</string>\n    <string name=\"task_running\">May umiiral nang gawain ng pag-download na kasalukuyang tumatakbo</string>\n    <string name=\"paste_msg\">I-paste ang URL</string>\n    <string name=\"paste_fail_msg\">Hindi magkatugma ang URL na mula sa clipboard</string>\n    <string name=\"dismiss\">Kanselahin</string>\n    <string name=\"downloads_history\">Mga download</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"open_url\">Buksan ang link</string>\n    <string name=\"back\">Bumalik</string>\n    <string name=\"credits\">Mga credit</string>\n    <string name=\"credits_desc\">Mga credit at libre software</string>\n    <string name=\"cancel\">Kanselahin</string>\n    <string name=\"settings_before_download\">I-configure bago mag-download</string>\n    <string name=\"yt_dlp_docs\">Mga reference sa paggamit ng Yt-dlp</string>\n    <string name=\"format\">Format</string>\n    <string name=\"video_quality_desc\">Limitahan ang kalidad ng video kapag marami itong naroroon</string>\n    <string name=\"not_specified\">Hindi tinukoy (default)</string>\n    <string name=\"convert_audio\">I-convert</string>\n    <string name=\"download_history_desc\">Suriin at pamahalaan ang in-app na download, kasama ang mga video at audio na file.</string>\n    <string name=\"check_download_settings_desc\">Tingnan ang mga setting ng pag-download at tiyaking mayroon kang pinakabagong bersyon ng yt-dlp bago ito gamitin.</string>\n    <string name=\"download_desc\">Tapos pindutin ang \\\"Download\\\" pagkatapos ma-ayos ang mga setting nito.</string>\n    <string name=\"download_playlist\">I-download ang playlist</string>\n    <string name=\"download_playlist_desc\">Mag-download ng maraming video mula sa isang playlist</string>\n    <string name=\"battery_settings_desc\">Mangyaring i-set ang paggamit ng baterya ng app na ito sa \\\"Unrestricted\\\" (Hindi Pinaghihigpitan) sa mga setting ng system upang mag-download sa background.</string>\n    <string name=\"options\">Mga opsiyon</string>\n    <string name=\"additional_settings\">Karagdagang mga setting</string>\n    <string name=\"download_notification\">Abiso sa pag-download</string>\n    <string name=\"concurrent_download_num\">%d (na mga) thread na gagamitin sa pag-download DASH/HLS native video ng sabay-sabay.</string>\n    <string name=\"share_fail_msg\">Hindi tugma ang URL mula sa naibahaging content</string>\n    <string name=\"download_notification_desc\">Abiso ng mga na-download na file at progress</string>\n    <string name=\"to\">Hanggang sa</string>\n    <string name=\"download_directory\">Directory ng download</string>\n    <string name=\"download_directory_desc\">Pilliin kung saan ilagay ang mga video at audio file</string>\n    <string name=\"permission_issue_desc\">Hindi sinusuportahan ang mga directory sa labas ng Download/ at Documents/</string>\n    <string name=\"translate\">Isalin</string>\n    <string name=\"translate_desc\">Tumulong sa pag translate ng app na ito sa Hosted Weblate</string>\n    <string name=\"unknown_error\">Hindi matukoy na error</string>\n    <string name=\"language\">Wika ng pag-display</string>\n    <string name=\"download_success_msg\">Tapos na ang pag-download</string>\n    <string name=\"delete_info_msg\">Alisin ang \\\"%1$s\\\" na mula sa iyong kasaysayan ng download nang tuluyan?</string>\n    <string name=\"confirm\">Kumpirmahin</string>\n    <string name=\"general_settings\">Pangkahalatan</string>\n    <string name=\"delete_info\">Alisin\\?</string>\n    <string name=\"remove\">Tanggalin</string>\n    <string name=\"ytdlp_update\">Pindutin upang ma-install ang pinakabagong bersyon ng yt-dlp</string>\n    <string name=\"about\">Tungkol rito</string>\n    <string name=\"version\">Bersyon</string>\n    <string name=\"ytdlp_version\">Bersyon ng Yt-dlp</string>\n    <string name=\"checked\">Sinuri</string>\n    <string name=\"custom_command_template\">Template ng command</string>\n    <string name=\"readme_desc\">Tignan ang GitHub repository at ang README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"close_never_show_again\">Huwag na magpakitang muli</string>\n    <string name=\"close\">Isara</string>\n    <string name=\"custom_command\">Custom na command</string>\n    <string name=\"custom_command_desc\">Patakbuhin ang yt-dlp command gamit ang custom na template</string>\n    <string name=\"edit\">I-edit</string>\n    <string name=\"start_execute\">Simulan ang magsasagawa ng command</string>\n    <string name=\"print_details\">Detalyadong output</string>\n    <string name=\"print_details_desc\">Magpakita ng detalyadong mensahe kapag nagda-download</string>\n    <string name=\"display\">Magpakita</string>\n    <string name=\"dark_theme\">Madilim na tema</string>\n    <string name=\"advanced_settings\">Iba pa</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"on\">Naka-on</string>\n    <string name=\"thumbnail\">Thumnail</string>\n    <string name=\"settings_before_download_text\">Ayusin itong download</string>\n    <string name=\"not_convert\">Walang nabago</string>\n    <string name=\"convert_audio_format\">I-convert ang audio format</string>\n    <string name=\"video_quality\">Kalidad ng video</string>\n    <string name=\"video_format_preference\">Piniling format ng video</string>\n    <string name=\"edit_template_desc\">Ang path ng output at URL ay idaragdag ng app.</string>\n    <string name=\"convert_to\">I-convert sa %1$s</string>\n    <string name=\"best_quality\">Pinakamahusay na kalidad</string>\n    <string name=\"preferred_format_desc\">Napiling format kapag marami ang naibinigay</string>\n    <string name=\"open_settings\">Buksan ang mga setting</string>\n    <string name=\"paste_desc\">Pindutin ang \\\"I-paste\\\" upang makuha ang video link na mula sa iyong clipboard.</string>\n    <string name=\"link_copied\">Ang link ay nakopya sa clipboard</string>\n    <string name=\"concurrent_download\">Multi-threaded na pag-download</string>\n    <string name=\"defaults\">Default</string>\n    <string name=\"channel_name\">Download</string>\n    <string name=\"video_url\">Link ng video</string>\n    <string name=\"channel_description\">Abiso ng mga na-download na file at progress</string>\n    <string name=\"download_finish_notification\">Tapos na ang pag-download. I-tap ito upang mabuksan.</string>\n    <string name=\"concurrent_download_desc\">Mag-download ng higit pang mga bahagi ng M3U8/MPD na video nang magkasabay</string>\n    <string name=\"execute_command_notification\">Kasalukuyang isinasagawa ang mga custom na command…</string>\n    <string name=\"share_success_msg\">Binabasa ang video link na mula sa naibahaging content…</string>\n    <string name=\"show_more_actions\">Magpakita ng higit pang mga aksyon</string>\n    <string name=\"fetching_playlist_info\">Kinukuha ang impormasyon ng playlist…</string>\n    <string name=\"download_range_selection\">Pagpili ng playlist</string>\n    <string name=\"download_range_desc\">Tukuyin ang hanay ng mga video na ida-download mula sa playlist na \\\"%3$s\\\" (mula sa %1$d hanggang sa %2$d).</string>\n    <string name=\"invalid_index_range\">Di-balidong index range</string>\n    <string name=\"yt_dlp_up_to_date\">Gumagamit ng pinakabagong bersyon ng yt-dlp</string>\n    <string name=\"audio_directory\">Folder ng audio</string>\n    <string name=\"subdirectory\">I-save sa subdirectory</string>\n    <string name=\"subdirectory_desc\">I-save ang mga file sa mga folder na may pangalan na katulad ng kanilang mga field</string>\n    <string name=\"battery_configuration_desc\">Huwag pansinin ang pag-optimize ng baterya para ma-download ang app na ito sa background</string>\n    <string name=\"yt_dlp_update_fail\">Hindi ma-install ang pinakabagong bersyon ng yt-dlp, siguraduhing naka-konekta sa internet.</string>\n    <string name=\"delete_file\">Tanggalin ang file</string>\n    <string name=\"about_page\">Bersyon, mag feedback, awtomatikong pag-update</string>\n    <string name=\"release_desc\">Tumingin ng mga changelog at mga bagong bersyon</string>\n    <string name=\"settings_before_download_desc\">I-configure ang pagsasaayos bago mag-download</string>\n    <string name=\"error_copied\">Nakopya ang ulat ng error sa clipboard</string>\n    <string name=\"paste\">I-paste</string>\n    <string name=\"convert_audio_format_desc\">Ang muling pag-encode ng mga audio file ay magdudulot ng pagkawala sa kalidad ng audio at pagtaas sa laki ng file.</string>\n    <string name=\"start_download\">Download</string>\n    <string name=\"user_guide\">Gabay para sa paggamit</string>\n    <string name=\"off\">Naka-off</string>\n    <string name=\"release\">Pinakabagong release</string>\n    <string name=\"display_settings\">Madilim na tema, paiba-ibang kulay, wika</string>\n    <string name=\"video_format\">Format ng video</string>\n    <string name=\"playlist_indicator_text\">Dina-download ang playlist (%1$d/%2$d)…</string>\n    <string name=\"from\">Mula sa</string>\n    <string name=\"permission_issue\">Isyu sa pahintulot sa storage</string>\n    <string name=\"service_title\">Nag da-download ang Seal…</string>\n    <string name=\"battery_configuration\">Pagsasaayos ng baterya</string>\n    <string name=\"prefix\">Ang prefix</string>\n    <string name=\"restart\">I-restart</string>\n    <string name=\"downloading_indicator_text\">Isinasagwa ang download…</string>\n    <string name=\"video_file_size\">Laki ng video file</string>\n    <string name=\"new_template\">Bagong template</string>\n    <string name=\"open_file\">Buksan ang file</string>\n    <string name=\"status_enqueued\">Naka-queue</string>\n    <string name=\"multiselect_item_count\">%1$d (mga) video, %2$d (mga) audio file</string>\n    <string name=\"status_fetching_video_info\">Kinukuha ang impormasyon</string>\n    <string name=\"status_completed\">Natapos na</string>\n    <string name=\"task_canceled\">Kinansela ang gawain ng pag-download</string>\n    <string name=\"embed_subtitles\">I-embed ang mga subtitle</string>\n    <string name=\"embed_subtitles_desc\">I-embed ang mga soft-sub sa mga video kung available</string>\n    <string name=\"template_label\">Label</string>\n    <string name=\"remove_template\">Tanggalin\\?</string>\n    <string name=\"remove_template_desc\">Tanggalin ang \\\"%1$s\\\" mula sa mga template ng command nang tuluyan?</string>\n    <string name=\"template_selection\">Pagpili ng Template</string>\n    <string name=\"custom_command_template_desc\">I-edit at pamahalaan ang mga template ng command</string>\n    <string name=\"github_issue\">Isyu sa GitHub</string>\n    <string name=\"github_issue_desc\">Mag-submit ng isyu para sa bug report o feature request</string>\n    <string name=\"info_copied\">Kinopya ang impo sa clipboard</string>\n    <string name=\"video_resolution\">Resolusyon ng video</string>\n    <string name=\"export_to_clipboard\">I-export sa clipboard</string>\n    <string name=\"import_from_clipboard\">I-import galing sa clipboard</string>\n    <string name=\"template_exported\">In-export ang %1$d (mga) template</string>\n    <string name=\"template_imported\">In-import ang %1$d (mga) template</string>\n    <string name=\"download_task_count\">%1$d na mga gawain ng pag-download</string>\n    <string name=\"status_downloading\">Dina-download</string>\n    <string name=\"status_canceled\">Kinansela</string>\n    <string name=\"status_error\">Na error</string>\n    <string name=\"copy_link\">Kopyahin ang link</string>\n    <string name=\"copy_error_report\">Kopyahin ang report</string>\n    <string name=\"recently_added\">Kamakailang Idinagdag</string>\n    <string name=\"share\">Ibahagi</string>\n    <string name=\"sponsor_msg2\">Maraming salamat!</string>\n    <string name=\"msg_from_developer\">Mensahe mula sa developer</string>\n    <string name=\"rename\">Baguhin ang pangalan</string>\n    <string name=\"select_all\">Lahat</string>\n    <string name=\"aria2_desc\">Gamitin ang aria2c bilang external na downloader</string>\n    <string name=\"cookies_desc\">Gamitin ang Netscape Formatted na cookie para sa mga download</string>\n    <string name=\"file_unavailable\">Ang file na ito ay hindi na pwede o nawawala</string>\n    <string name=\"copy_log\">Kopyahin ang log</string>\n    <string name=\"download_subtitles\">I download ang subtitles</string>\n    <string name=\"subtitle_language\">Wika ng mga subtitle</string>\n    <string name=\"disable_preview\">I off ang preview</string>\n    <string name=\"crop_artwork\">I crop ang artwork</string>\n    <string name=\"crop_artwork_desc\">I crop ang image at gawin itong square</string>\n    <string name=\"format_selection\">Pagpili ng format</string>\n    <string name=\"video_title_sample_text\">Title ng video</string>\n    <string name=\"use_custom_command\">Gumamit Ng custom command</string>\n    <string name=\"unavailable\">Hindi pwede</string>\n    <string name=\"use_cookies\">Gumamit ng cookies</string>\n    <string name=\"disable_preview_desc\">Huwag i-display ang thumbnail habang nag da-download</string>\n    <string name=\"generate_new_cookies\">Gumawa ng bagong cookies</string>\n    <string name=\"sponsorblock_desc\">Alisin o im-marka ang mga segment sa mga video gamit ang SponsorBlock API</string>\n    <string name=\"app_update_failed\">Nabigong i-update sa pinakabagong bersyon</string>\n    <string name=\"sponsorblock_categories_desc\">Tukuyin ang kategorya ng SponsorBlock na aalisin o i-marka sa video file</string>\n    <string name=\"sponsorblock_categories\">Mga kategorya ng SponsorBlock</string>\n    <string name=\"check_for_updates_desc\">Awtomatikong tingnan ang pinakabagong bersyon sa GitHub</string>\n    <string name=\"check_for_updates\">Tingnan kung may update</string>\n    <string name=\"app_up_to_date\">Ang bersyon na ito ay up to date</string>\n    <string name=\"clear_temp_files\">Tangalin ang Temporary files</string>\n    <string name=\"clear_temp_files_desc\">Tanggalin ang lahat ng pansamantalang file mula sa pansamantalang direktoryo</string>\n    <string name=\"clear_temp_files_info\">Maaaring gamitin ang pansamantalang mga file para magpatuloy sa mga nakanselong pag-download. Nais mo bang tanggalin ang lahat ng mga file na ito?\n\\n\n\\nMapupuntahan mo ang mga file na ito sa %1$s</string>\n    <string name=\"multiselect_mode\">Maramihang Pagpili</string>\n    <string name=\"private_mode\">Private mode</string>\n    <string name=\"private_mode_desc\">I-off ang download history</string>\n    <string name=\"lowest_quality\">Pinakamababang Quality</string>\n    <string name=\"delete_multiple_items_msg\">Tangalin %1$d aytem(s) mula sa iyong download history para sa kabutihan\\?</string>\n    <string name=\"network\">Network</string>\n    <string name=\"remove_cookie_profile_desc\">Alisin ang entry na ito para sa \\\"%1$s\\\"? Mangyaring tandaan na ang mga cookies na naka-imbak para sa site na ito ay hindi matatanggal.</string>\n    <string name=\"private_directory\">Pribado na directory</string>\n    <string name=\"private_directory_desc\">Ilagay ang mga downloads sa isang nakatagong direktoryo</string>\n    <string name=\"clear_temp_files_count\">Tinanggal na ang %1$d temporary file(s)</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"video_only\">Video lamang (Walang audio)</string>\n    <string name=\"update\">Update</string>\n    <string name=\"download_disabled_with_cellular\">Ang pag-download gamit ang cellular network ay hindi pwede ayon sa iyong mga setting</string>\n    <string name=\"download_with_cellular\">I-download gamit ang cellular</string>\n    <string name=\"rate_limit_desc\">Limitahan ang maksimum na bilis ng pag-download</string>\n    <string name=\"enable_experimental_feature\">I-on ang eksperimento feature\\?</string>\n    <string name=\"second\">Segundo</string>\n    <string name=\"minute\">minuto</string>\n    <string name=\"clear_all_cookies\">Tangalin lahat ang mga Cookies</string>\n    <string name=\"ytdlp_update_action\">I-update ang yt-dlp</string>\n    <string name=\"invalid_input\">Hindi wastong input</string>\n    <string name=\"suggested\">Iminungkahi</string>\n    <string name=\"high_contrast\">Madilim na tema na may mataas na kontrast</string>\n    <string name=\"dynamic_color\">Pabago-bago ng kulay</string>\n    <string name=\"format_selection_desc\">Piliin ang format na i-download bago magsimula ang pag-download</string>\n    <string name=\"format_settings_desc\">Format ng file, kalidad ng video, mga subtitles</string>\n    <string name=\"download_with_cellular_desc\">Payagan ang pag-download ng media kapag nakakonekta sa mga metreng network</string>\n    <string name=\"dynamic_color_desc\">Gumamit ng mga kulay mula sa mga wallpaper sa tema ng app</string>\n    <string name=\"general_settings_desc\">Bersyon ng yt-dlp, abiso, playlist</string>\n    <string name=\"network_settings_desc\">Limitahan ang dami, pampababa, mga cookies</string>\n    <string name=\"download_selection_desc\">Pumili ng mga video na i-download mula sa playlist na \\\"%1$s\\\"</string>\n    <string name=\"selected_item_count\">%1$d ang napili</string>\n    <string name=\"privacy\">Privacy</string>\n    <string name=\"rate_limit\">Limitasyon sa bilis</string>\n    <string name=\"max_rate\">Pinakamataas na Bilis</string>\n    <string name=\"subtitle_sponsorblock\">Maaaring hindi tama ang oras ng mga subtitle kapag tinanggal ang mga segment ng SponsorBlock.</string>\n    <string name=\"custom_command_enabled_hint\">Ang iba sa mga pagpipilian ay hindi magagamit kapag gumagamit ng custom command</string>\n    <string name=\"auto_subtitle_desc\">I-download ang auto-generated captions</string>\n    <string name=\"title_activity_share\">Mabilis na pag-download</string>\n    <string name=\"edit_shortcuts_desc\">I-edit ang custom shortcuts na pwedeng gamitin para gumawa ng command templates.</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"show_logs\">Ipakita ang log</string>\n    <string name=\"apply\">I-apply</string>\n    <string name=\"how_does_it_work\">Paano ito gumagana?</string>\n    <string name=\"edit_shortcuts\">i-edit ang shortcuts</string>\n    <string name=\"format_sorting_desc\">Inaayos ng mga format gamit ang -S na opsiyon ng yt-dlp</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"telegram_channel\">Channel ng telegram</string>\n    <string name=\"cookies_usage_msg\">Ang pag-download mula sa ilang site ay nangangailangan ng impormasyon sa pagpapatunay ng account. I-click ang \\\"Bumuo ng bagong cookies\\\", at i-click ang URL ng website at pagkatapos ay mag-log in gamit ang iyong account sa pahina ng browser, bubuo ito ng app para sa iyo.</string>\n    <string name=\"matrix_space\">Puwang ng matrix</string>\n    <string name=\"sdcard_directory\">Folder ng SD card</string>\n    <string name=\"auto_subtitle\">awtomatikong pag-caption</string>\n    <string name=\"abs_hint\">Karamihan sa mga video streaming platform ay naghahatid ng audio at video nang hiwalay, maaari mong piliin at pagsamahin ang isang audio lamang na format na may isang video lamang na format sa isang video.</string>\n    <string name=\"video_creator_sample_text\">sample na teksto ng tagalikha ng video</string>\n    <string name=\"subtitle\">Subtitle</string>\n    <string name=\"shortcuts\">Mga shortcut</string>\n    <string name=\"filesize_mb\">%.2f na MB</string>\n    <string name=\"filesize_gb\">%.2f na GB</string>\n    <string name=\"pre_release_channel\">Silipin</string>\n    <string name=\"title\">Pamagat</string>\n    <string name=\"temporary_directory_desc\">Mag-imbak ng mga pansamantalang file sa internal directory</string>\n    <string name=\"sponsor\">Isponsor</string>\n    <string name=\"clear_all_cookies_desc\">Tanggalin ang lahat ng cookies na nakaimbak sa app para sa kabutihan?</string>\n    <string name=\"auto_update_disabled_msg\">Hindi available ang auto-update para sa %1$s na mga build. Kung wala kang %1$s na naka-install sa iyong device, o gusto mong i-preview ang paparating na mga bagong feature sa Seal, mangyaring isaalang-alang ang %2$s.</string>\n    <string name=\"switch_to_github_builds\">Lumipat sa mga build ng GitHub</string>\n    <string name=\"enable_auto_update\">Paganahin ang automatic update</string>\n    <string name=\"auto_update\">Automatic ang update</string>\n    <string name=\"discard\">Itapon</string>\n    <string name=\"clip_end\">Wakas</string>\n    <string name=\"clip_video\">Video clip</string>\n    <string name=\"clip_start\">Simulan</string>\n    <string name=\"audio_quality\">kalidad ng tunog</string>\n    <string name=\"audio_quality_desc\">Limitahan ang bitrate ng audio kapag maraming katangian ang naroroon</string>\n    <string name=\"import_from_preferences\">Angkat</string>\n    <string name=\"no_downloaded_media\">Walang na-download na media</string>\n    <string name=\"clear\">Malinaw</string>\n    <string name=\"running_tasks\">Pagpapatakbo ng mga gawain</string>\n    <string name=\"embed_subtitles_mkv_msg\">Upang mag-embed ng soft subtitles, ang mga video ay ire-remux sa mkv container. Maaaring gamitin ang VLC Media Player o iba pang compatible na app para manood ng mga video na may soft subtitles.</string>\n    <string name=\"audio_format_preference\">Piniling format ng audio</string>\n    <string name=\"format_sorting\">Pag-uuri ng format</string>\n    <string name=\"sponsor_desc\">Suportahan ang app na ito sa pamamagitan ng pag-sponsor sa GitHub</string>\n    <string name=\"feedback\">Puna</string>\n    <string name=\"sponsors\">Mga sponsor</string>\n    <string name=\"clip_video_desc\">Gumawa ng mga video clip sa pahina ng pagpili ng format</string>\n    <string name=\"add\">Idagdag</string>\n    <string name=\"sponsor_msg\">Ang Seal ay palaging libre at open source para sa lahat. Kung gusto mo ito, mangyaring isaalang-alang ang pag-sponsor sa akin sa GitHub!</string>\n    <string name=\"subtitle_desc\">Mga wika, mag-embed ng mga subtitle, at auto captions</string>\n    <string name=\"stable_channel\">Matibay</string>\n    <string name=\"update_channel\">I-update ang channel</string>\n    <string name=\"unlimited\">Hindi limitado</string>\n    <string name=\"lowest_bitrate\">pinakamababang bitrate</string>\n    <string name=\"audio_format\">Format ng audio</string>\n    <string name=\"update_channel_desc\">Mag-install ng mga pre-release na build para silipin ang mga bagong feature at pagbabago.\n\\n\n\\nMagkakaroon ng ilang kawalang-tatag sa mga bersyong ito, kaya mangyaring huwag mag-alinlangang magbigay sa amin ng feedback kung nakakaranas ka ng anumang mga problema upang matulungan kaming mapabuti ang app para sa hinaharap.</string>\n    <string name=\"clip_video_dialog_msg\">Ide-delegate ang mga download gamit ang feature na ito sa FFmpeg para mag-download ng mga napiling seksyon ng video, experimental pa rin ang feature na ito at hindi magiging ganap na tumpak ang cutting, hindi lahat ng format ay sumusuporta sa feature na ito at maaari kang makaranas ng mas mabagal na bilis ng pag-download.</string>\n    <string name=\"edit_file\">I-edit ang file</string>\n    <string name=\"save\">I-save</string>\n    <string name=\"allow_once\">Payagan ng isang beses</string>\n    <string name=\"use_format_sorting\">Gamitin ang pagso-sort ng format</string>\n    <string name=\"allow_always\">Palaging payagan</string>\n    <string name=\"dont_allow\">Huwag payagan</string>\n    <string name=\"download_with_cellular_request\">Payagan ang pag-download gamit ang cellular?</string>\n    <string name=\"keep_subtitle_files\">Panatilhin ang mga subtitle file</string>\n    <string name=\"required\">Kailangan</string>\n    <string name=\"show_all_items\">Ipakita ang lahat ng %1$d item</string>\n    <string name=\"embed_metadata_desc\">I-embed ang metadata at thumbnail ng video sa audio file</string>\n    <string name=\"subdirectory_hint\">Ang iyong mga download ay maii-save bilang:</string>\n    <string name=\"restrict_filenames\">Higpitan ang mga pangalan ng file</string>\n    <string name=\"restrict_filenames_desc\">Limitahan ang mga pangalan ng file sa mga partikular na character upang matiyak ang compatability</string>\n    <string name=\"website\">Website</string>\n    <string name=\"playlist_title\">Pamagat ng playlist</string>\n    <string name=\"system_settings\">Mga setting ng sistema</string>\n    <string name=\"force_ipv4\">Pilitin ang IPv4</string>\n    <string name=\"force_ipv4_desc\">Gawin ang lahat ng koneksyon gamit ang IPv4</string>\n    <string name=\"every_day\">Araw-araw</string>\n    <string name=\"every_week\">Linggo-linggo</string>\n    <string name=\"every_month\">Kada buwan</string>\n    <string name=\"remux_container_mkv_desc\">I-remux ang mga video sa MKV container para sa mas mahusay na compatibility</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d na item</item>\n        <item quantity=\"other\">Mga %d na item</item>\n    </plurals>\n    <string name=\"cookies_in_database\">%1$d na mga cookie mula sa %2$d na website sa kabuuan</string>\n    <string name=\"download_video_desc\">I Download ang video gamit ang URL</string>\n    <string name=\"okay\">Sige</string>\n    <string name=\"disabled\">Hindi pinagana</string>\n    <string name=\"got_it\">Nakuha ko</string>\n    <string name=\"search_in_downloads\">Maghanap sa mga download</string>\n    <string name=\"auto_translated_subtitles_msg\">Ang mga Auto-translated na subtitle para sa lahat ng wika ay magiging available sa mga download. Maaaring hindi tama at mahirap intindihin ang mga subtitle na ito.</string>\n    <string name=\"download_history\">Kasaysayan ng download</string>\n    <string name=\"remove_multiple_templates_msg\">Alisin ang %1$s mula sa mga template ng command para nang tuluyan?</string>\n    <string name=\"refresh_cookies_desc\">I-tap para buksan ang webpage para sa pagbuo ng bagong cookie:</string>\n    <string name=\"embed_metadata\">I-embed ang metadata</string>\n    <string name=\"legacy\">pamana</string>\n    <string name=\"quality\">Kalidad</string>\n    <string name=\"enable_notifications\">Paganahin ang mga abiso?</string>\n    <string name=\"prefer_compatibility_desc\">Laging gamitin ang MP4(H.264) na format para sa pagbabahagi sa iba pang app</string>\n    <string name=\"merge_audiostream\">Pagsamahin ang maramihang audio stream</string>\n    <string name=\"merge_audiostream_desc\">Payagan ang maramihang mga audio stream na i-merge sa isang file</string>\n    <string name=\"feature_unavailable\">Hindi available ang feature</string>\n    <string name=\"split_video\">Hatiin ang video</string>\n    <string name=\"no_custom_command_tasks\">Walang custom na command task</string>\n    <string name=\"convert_subtitle\">I-convert ang mga subtitle</string>\n    <string name=\"convert_subtitle_desc\">I-convert ang mga subtitle sa ibang format</string>\n    <string name=\"split_video_msg\">Hahatiin ang video sa %1$d na mga kabanata</string>\n    <string name=\"expand\">Palawakin</string>\n    <string name=\"new_task\">Bagong gawain sa pag-download</string>\n    <string name=\"ua_header\">Header ng User-Agent</string>\n    <string name=\"edit_template\">I-edit ang \\\"%1$s\\\"</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"enable_notifications_desc\">Kailangan ng app ang iyong pahintulot na mag-post ng mga abiso tungkol sa status ng pag-download at progress.</string>\n    <string name=\"disable\">Huwag paganahin</string>\n    <string name=\"set_directory_desc\">I-tap para mag-set up ng directory</string>\n    <string name=\"custom_command_directory\">Custom na directory ng command</string>\n    <string name=\"folder_picker\">Tagapili ng folder</string>\n    <string name=\"custom_command_directory_desc\">Tukuyin ang directory ng output kapag gumagamit ng mga custom na command</string>\n    <string name=\"custom\">Custom</string>\n    <string name=\"auto\">Awto</string>\n    <string name=\"commands\">Mga command</string>\n    <string name=\"remux_container_mkv\">I-remux ang video container</string>\n    <string name=\"download_archive_error\">Ang video ay na-download na. Kung ito ay hindi ang inaasahan mong resulta, mangyaring tingnan ang iyong archive ng mga download.</string>\n    <string name=\"export_backup\">I-export</string>\n    <string name=\"file\">File</string>\n    <string name=\"clipboard\">Clipboard</string>\n    <string name=\"export_to_file\">I-export sa file</string>\n    <string name=\"export_download_history_msg\">Ini-export ang %1$s mula sa kasaysayan ng download. Hindi maba-back up ang mga na-download na file at ang kagustuhan mo.</string>\n    <string name=\"download_type\">Uri ng pag-download</string>\n    <string name=\"custom_command_usage_msg\">Ang yt-dlp ay isang mahusay na command-line tool para sa pag-download ng mga video. Pinapadali ng Seal ang paggamit ng yt-dlp sa pamamagitan ng pagbibigay ng intuitive na GUI, mga preset para sa mga karaniwang command, at iba pang karagdagang features.\n\\n\n\\nPara sa advanced na paggamit ng yt-dlp, pinapayagan ka ng Seal na lumikha, mag-save at magsagawa ng mga custom na template ng command nang direkta, tulad ng sa isang terminal.\n\\n\n\\nKapag gumagamit ng mga custom na command, karamihan sa mga opsyon at feature ng GUI ay hindi papaganahin.</string>\n    <string name=\"unknown_error_title\">Ay Naku! Nagkaoon ng problema</string>\n    <string name=\"copy_and_exit\">Kopyahin at lumabas</string>\n    <string name=\"start\">Simulan</string>\n    <string name=\"proxy_desc\">Gumamit ng proxy para sa mga koneksyon sa internet</string>\n    <string name=\"prefer_quality_desc\">Laging gamitin ang AV1, VP9 o H.265 na mga format para sa panonood sa mga compatible na app</string>\n    <string name=\"format_preference\">Kagustuhan sa format</string>\n    <string name=\"learn_more\">Matuto pa</string>\n    <string name=\"unknown\">Hindi alam</string>\n    <string name=\"output_template\">Output ng template</string>\n    <string name=\"presets\">Mga preset</string>\n    <string name=\"output_template_desc\">Tukuyin ang template para sa pangalan ng mga output file</string>\n    <string name=\"auto_translated_subtitles\">Mga subtitle na awtomatikong isinalin</string>\n    <string name=\"subtitle_language_desc\">Wika ng mga subtitle na ida-download sa pagpili ng Awto format, na pinaghihiwalay ng mga kuwit (comma).</string>\n    <string name=\"remember_for_next_download\">Tandaan para sa susunod na pag-download</string>\n    <string name=\"reset\">I-reset</string>\n    <string name=\"search_in_subtitles\">Maghanap sa mga subtitle</string>\n    <string name=\"no_thanks\">Salamat nalang</string>\n    <string name=\"look_and_feel\"><![CDATA[Tingnan at pakiramdam]]></string>\n    <string name=\"interface_and_interaction\"><![CDATA[Interface at interaksyon]]></string>\n    <string name=\"use_previous_selection\">Gamitin ang nakaraang pagpili</string>\n    <string name=\"none\">Wala</string>\n    <string name=\"update_language_msg\">Ang mga sumusunod na wika ay idadagdag sa iyong kagustuhan para sa pag-download sa hinaharap:</string>\n    <string name=\"update_subtitle_languages\">I-update ang mga wika ng subtitle?</string>\n    <string name=\"import_backup\">I-import</string>\n    <string name=\"full_backup\">Buong backup</string>\n    <string name=\"backup_type\">Uri ng backup</string>\n    <string name=\"export_to\">I-export sa</string>\n    <string name=\"import_from\">I-import mula sa</string>\n    <string name=\"export_download_history\">I-export ang kasaysayan ng download?</string>\n    <string name=\"import_download_history\">Mag-import ng kasaysayan ng download?</string>\n    <string name=\"import_download_history_msg\">Hindi mai-import ang mga na-download na file. Kakailanganin mong i-download muli ang mga ito nang manu-mano</string>\n    <string name=\"download_archive\">Archive ng mga download</string>\n    <string name=\"clear_download_archive\">Linisin ang archive ng mga download?</string>\n    <string name=\"download_archive_desc\">I-record ang mga na-download na video ID sa isang archive para maiwasan ang mga nadobleng download</string>\n    <string name=\"clear_download_archive_desc\">Alisin ang %1$s sa archive file nang tuluyan?</string>\n    <string name=\"download_history_imported\">Nag-import ng %1$s sa kasaysayan ng download</string>\n    <string name=\"redownload\">Muling i-download</string>\n    <string name=\"search\">Paghahanap</string>\n    <string name=\"all_languages\">Lahat ng mga wika</string>\n    <string name=\"preset\">Ang preset</string>\n    <string name=\"prefer_placeholder\">Piliin ang %1$s</string>\n    <string name=\"preset_format_selection_desc\">Awtomatikong mag-download gamit ang iyong mga kagustuhan sa format</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d na audio</item>\n        <item quantity=\"other\">%d na mga audio</item>\n    </plurals>\n    <string name=\"task_added\">Ang gawain ay nadagdag sa pila</string>\n    <string name=\"playlist\">Playlist</string>\n    <string name=\"proceed\">Magpatuloy</string>\n    <string name=\"custom_format_selection_desc\">Pumili mula sa mga format, subtitle, at lalong i-customize</string>\n    <string name=\"edit_preset\">I-edit ang preset</string>\n    <string name=\"best_quality_desc\">I-download ang pinakamahusay na magagamit na format</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d na video</item>\n        <item quantity=\"other\">%d na mga video</item>\n    </plurals>\n    <string name=\"you_ll_find_your_downloads_here\">Makikita mo ang iyong mga download dito</string>\n    <string name=\"download_hint\">I-tap ang button sa pag-download o magbahagi ng link ng video sa app na ito para magsimula ng pag-download</string>\n    <string name=\"status_downloaded\">Nai-download na</string>\n    <string name=\"all\">Lahat</string>\n    <string name=\"download_queue\">Queue ng pag-download</string>\n    <string name=\"select_multiple_link\">Pumili mula sa %1$d na mga link</string>\n    <string name=\"show_navigation_drawer\">Ipakita ang navigation drawer</string>\n    <string name=\"resume\">Ipagpatuloy</string>\n    <string name=\"delete\">Tanggalin</string>\n    <string name=\"media_info\">Impo ng media</string>\n    <string name=\"trouble_shooting\">Mag-troubleshoot</string>\n    <string name=\"issue_tracker\">Ang issue tracker</string>\n    <string name=\"trouble_shooting_desc\">Ayusin ang mga karaniwang error at suriin para sa mga kilalang isyu</string>\n    <string name=\"issue_tracker_hint\">Nagkaroon ba ng error? Bago mag-ulat ng bagong isyu, maaring hanapin ang aming issue tracker. Maraming karaniwang problema ang natugunan at naidokumento na doon.</string>\n    <string name=\"saved_urls\">Na-save na mga link</string>\n    <string name=\"add_new_url\">Magdagdag ng bagong link</string>\n    <string name=\"add_to\">Idagdag sa %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-fr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Dossier vidéo</string>\n    <string name=\"extract_audio\">Enregistrer en tant qu\\'audio</string>\n    <string name=\"create_thumbnail\">Enregistrer la miniature</string>\n    <string name=\"settings\">Paramètres</string>\n    <string name=\"download\">Télécharger</string>\n    <string name=\"extract_audio_summary\">Télécharger et enregistrer des fichiers audio, au lieu de vidéos</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp est à jour</string>\n    <string name=\"permission_denied\">Permission refusée</string>\n    <string name=\"download_success_msg\">Téléchargement terminé</string>\n    <string name=\"download_error_msg\">Impossible de télécharger le fichier</string>\n    <string name=\"general_settings\">Général</string>\n    <string name=\"language\">Langue d\\'affichage</string>\n    <string name=\"ytdlp_version\">Version de yt-dlp</string>\n    <string name=\"ytdlp_update\">Cliquez pour installer la dernière version de yt-dlp</string>\n    <string name=\"delete_info\">Retirer ?</string>\n    <string name=\"confirm\">Confirmer</string>\n    <string name=\"dismiss\">Annuler</string>\n    <string name=\"downloads_history\">Téléchargements</string>\n    <string name=\"delete_file\">Supprimer le fichier</string>\n    <string name=\"create_thumbnail_summary\">Enregistrer la miniature de la vidéo dans un fichier</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"release\">Dernière version</string>\n    <string name=\"video\">Vidéo</string>\n    <string name=\"checked\">Vérifié</string>\n    <string name=\"credits\">Crédits</string>\n    <string name=\"credits_desc\">Crédits et logiciels libres</string>\n    <string name=\"custom_command\">Commande personnalisée</string>\n    <string name=\"custom_command_template\">Modèle de commande</string>\n    <string name=\"edit\">Modifier</string>\n    <string name=\"start_execute\">Commencer à exécuter la commande</string>\n    <string name=\"display\">Affichage</string>\n    <string name=\"display_settings\">Thème sombre, couleur dynamique, langues</string>\n    <string name=\"dark_theme\">Thème sombre</string>\n    <string name=\"follow_system\">Système</string>\n    <string name=\"on\">Activé</string>\n    <string name=\"off\">Désactivé</string>\n    <string name=\"cancel\">Annuler</string>\n    <string name=\"settings_before_download\">Configurer avant le téléchargement</string>\n    <string name=\"settings_before_download_desc\">Configurer les préférences avant le téléchargement</string>\n    <string name=\"settings_before_download_text\">Ajuster ce téléchargement</string>\n    <string name=\"download_settings_desc\">Général, format, commande personnalisée</string>\n    <string name=\"url_empty\">Le lien ne peut pas être vide</string>\n    <string name=\"download_start_msg\">Téléchargement de « %1$s »</string>\n    <string name=\"fetching_info\">Récupération des informations vidéo…</string>\n    <string name=\"link_copied\">Lien copié dans le presse-papiers</string>\n    <string name=\"back\">Retour</string>\n    <string name=\"yt_dlp_update_fail\">Impossible d\\'installer la dernière version de yt-dlp. Veuillez vous assurer que vous êtes connecté à Internet.</string>\n    <string name=\"fetch_info_error_msg\">Impossible de récupérer les informations de la vidéo</string>\n    <string name=\"language_settings\">Définir la langue d\\'affichage</string>\n    <string name=\"paste_fail_msg\">Impossible d\\'identifier l\\'URL dans le presse-papiers</string>\n    <string name=\"open_url\">Ouvrir le lien</string>\n    <string name=\"task_running\">Une tâche de téléchargement est déjà en cours d\\'exécution</string>\n    <string name=\"paste_msg\">Coller l\\'URL</string>\n    <string name=\"delete_info_msg\">Supprimer définitivement « %1$s » de l\\'historique de vos téléchargements ?</string>\n    <string name=\"remove\">Retirer</string>\n    <string name=\"print_details\">Sortie détaillée</string>\n    <string name=\"about\">À propos</string>\n    <string name=\"about_page\">Version, remarques, mise à jour automatique</string>\n    <string name=\"readme_desc\">Consulter le dépôt GitHub et le fichier README</string>\n    <string name=\"advanced_settings\">Avancé</string>\n    <string name=\"print_details_desc\">Afficher des messages détaillés lors du téléchargement</string>\n    <string name=\"version\">Version</string>\n    <string name=\"release_desc\">Rechercher les journaux de modifications et les nouvelles versions</string>\n    <string name=\"custom_command_desc\">Exécuter la commande yt-dlp avec un modèle personnalisé</string>\n    <string name=\"paste\">Coller</string>\n    <string name=\"channel_name\">Télécharger</string>\n    <string name=\"yt_dlp_docs\">Références d\\'utilisation de Yt-dlp</string>\n    <string name=\"edit_template_desc\">Le répertoire de sortie et l\\'URL seront ajoutés par l\\'application.</string>\n    <string name=\"convert_to\">Convertir en %1$s</string>\n    <string name=\"video_quality\">Qualité de la vidéo</string>\n    <string name=\"video_format_preference\">Format vidéo préféré</string>\n    <string name=\"defaults\">Par défaut</string>\n    <string name=\"not_specified\">Non spécifié (par défaut)</string>\n    <string name=\"user_guide\">Guide de l\\'utilisateur</string>\n    <string name=\"playlist_indicator_text\">Téléchargement de la liste de lecture (%1$d/%2$d)…</string>\n    <string name=\"preferred_format_desc\">Format préféré lorsque plusieurs sont fournis</string>\n    <string name=\"close_never_show_again\">Ne plus afficher</string>\n    <string name=\"download_history_desc\">Vérifiez et gérez les téléchargements dans l\\'appli, y compris les vidéos et les fichiers audio.</string>\n    <string name=\"error_copied\">Rapport d\\'erreur copié dans le presse-papiers</string>\n    <string name=\"thumbnail\">Miniature</string>\n    <string name=\"not_convert\">Non converti</string>\n    <string name=\"format\">Format</string>\n    <string name=\"video_format\">Format vidéo</string>\n    <string name=\"convert_audio\">Convertir</string>\n    <string name=\"start_download\">Télécharger</string>\n    <string name=\"close\">Fermer</string>\n    <string name=\"paste_desc\">Cliquez sur « Coller » pour obtenir le lien vidéo à partir de votre presse-papiers.</string>\n    <string name=\"download_desc\">Cliquez ensuite sur « Télécharger » après avoir réglé ses paramètres.</string>\n    <string name=\"check_download_settings_desc\">Consultez les paramètres de téléchargement et assurez-vous que vous disposez de la dernière version de yt-dlp avant de l\\'utiliser.</string>\n    <string name=\"download_playlist\">Télécharger la liste de lecture</string>\n    <string name=\"download_playlist_desc\">Télécharger plusieurs vidéos à partir d\\'une liste de lecture</string>\n    <string name=\"options\">Options</string>\n    <string name=\"additional_settings\">Paramètres supplémentaires</string>\n    <string name=\"share_fail_msg\">Impossible de faire correspondre l\\'URL au contenu partagé</string>\n    <string name=\"share_success_msg\">Lecture d\\'un lien vidéo à partir d\\'un contenu partagé…</string>\n    <string name=\"show_more_actions\">Afficher plus d\\'actions</string>\n    <string name=\"execute_command_notification\">Exécution de commandes personnalisées…</string>\n    <string name=\"battery_settings_desc\">Veuillez régler le paramètre d\\'utilisation de la batterie de cette application sur « Sans restriction » dans les paramètres système afin de pouvoir télécharger en arrière-plan.</string>\n    <string name=\"concurrent_download\">Téléchargement multi-thread</string>\n    <string name=\"concurrent_download_desc\">Télécharger plus de parties de vidéos M3U8/MPD en parallèle</string>\n    <string name=\"concurrent_download_num\">%d processus seraient utilisés pour télécharger simultanément des vidéos natives DASH/HLS.</string>\n    <string name=\"subdirectory\">Enregistrer dans un sous-répertoire</string>\n    <string name=\"subdirectory_desc\">Enregistrer les fichiers dans des dossiers portant le nom des champs respectifs</string>\n    <string name=\"audio_directory\">Dossier audio</string>\n    <string name=\"download_directory\">Répertoire de téléchargement</string>\n    <string name=\"download_directory_desc\">Sélectionner où stocker les fichiers vidéo et audio</string>\n    <string name=\"battery_configuration\">Configuration de la batterie</string>\n    <string name=\"permission_issue\">Problème de permission de stockage</string>\n    <string name=\"permission_issue_desc\">Les répertoires autres que Download/ et Documents/ ne sont pas pris en charge</string>\n    <string name=\"battery_configuration_desc\">Ignorer l\\'optimisation de la batterie pour les téléchargements en arrière-plan</string>\n    <string name=\"service_title\">Seal est en cours de téléchargement…</string>\n    <string name=\"unknown_error\">Erreur inconnue</string>\n    <string name=\"video_url\">Lien vidéo</string>\n    <string name=\"download_finish_notification\">Téléchargement terminé. Appuyez pour ouvrir.</string>\n    <string name=\"download_notification\">Notification de téléchargement</string>\n    <string name=\"download_notification_desc\">Notification des fichiers téléchargés et de leur progression</string>\n    <string name=\"fetching_playlist_info\">Recherche d\\'informations sur la liste de lecture…</string>\n    <string name=\"download_range_selection\">Sélection de la liste de lecture</string>\n    <string name=\"download_range_desc\">Spécifiez la plage de vidéos à télécharger à partir de la liste de lecture « %3$s » (de %1$d à %2$d).</string>\n    <string name=\"from\">Début</string>\n    <string name=\"to\">Fin</string>\n    <string name=\"invalid_index_range\">Plage d\\'index invalide</string>\n    <string name=\"channel_description\">Notification des fichiers téléchargés et de leur progression</string>\n    <string name=\"convert_audio_format\">Convertir le format audio</string>\n    <string name=\"convert_audio_format_desc\">Le réencodage des fichiers audio entraîne une perte de qualité audio et une augmentation de la taille du fichier.</string>\n    <string name=\"best_quality\">Meilleure qualité</string>\n    <string name=\"video_quality_desc\">Limiter la qualité lorsque plusieurs vidéos sont présentes</string>\n    <string name=\"open_settings\">Ouvrir les paramètres</string>\n    <string name=\"translate\">Traduire</string>\n    <string name=\"translate_desc\">Aidez à traduire cette application sur Hosted Weblate</string>\n    <string name=\"prefix\">Préfixe</string>\n    <string name=\"embed_subtitles\">Sous-titres intégrés</string>\n    <string name=\"embed_subtitles_desc\">Intégrer les sous-titres dans les vidéos, si disponibles</string>\n    <string name=\"template_selection\">Sélection du modèle</string>\n    <string name=\"downloading_indicator_text\">Téléchargement en cours…</string>\n    <string name=\"github_issue_desc\">Soumettre un ticket pour signaler un bug ou suggérer une fonctionnalité</string>\n    <string name=\"new_template\">Nouveau modèle</string>\n    <string name=\"template_label\">Étiquette</string>\n    <string name=\"remove_template\">Retirer ?</string>\n    <string name=\"remove_template_desc\">Retirer définitivement « %1$s » des modèles de commande \\?</string>\n    <string name=\"custom_command_template_desc\">Modifier et gérer les modèles de commande</string>\n    <string name=\"task_canceled\">Téléchargement annulé</string>\n    <string name=\"github_issue\">Ticket GitHub</string>\n    <string name=\"open_file\">Ouvrir le fichier</string>\n    <string name=\"restart\">Redémarrer</string>\n    <string name=\"status_completed\">Terminé</string>\n    <string name=\"status_fetching_video_info\">Récupération des infos</string>\n    <string name=\"status_error\">Erreur</string>\n    <string name=\"copy_link\">Copier le lien</string>\n    <string name=\"copy_error_report\">Rapport de copie</string>\n    <string name=\"status_enqueued\">En file d\\'attente</string>\n    <string name=\"status_downloading\">Téléchargement en cours</string>\n    <string name=\"status_canceled\">Annulé</string>\n    <string name=\"info_copied\">Information copiée dans le presse papier</string>\n    <string name=\"video_resolution\">Résolution vidéo</string>\n    <string name=\"video_file_size\">Taille du fichier vidéo</string>\n    <string name=\"check_for_updates\">Rechercher les mises à jour</string>\n    <string name=\"cookies_desc\">Utiliser des cookies au format Netscape pour les téléchargements</string>\n    <string name=\"clear_temp_files\">Effacer les fichiers temporaires</string>\n    <string name=\"clear_temp_files_desc\">Supprimer tous les fichiers temporaires du répertoire temporaire</string>\n    <string name=\"clear_temp_files_count\">%1$d fichier(s) temporaire(s) supprimé(s)</string>\n    <string name=\"clear_temp_files_info\">Les fichiers temporaires peuvent être utilisés pour reprendre les téléchargements annulés. Voulez vous vraiment supprimer tous ces fichiers ?\n\\n\n\\nVous pouvez accéder à ces fichiers dans %1$s</string>\n    <string name=\"app_up_to_date\">La version actuelle est à jour</string>\n    <string name=\"recently_added\">Récemment ajouté</string>\n    <string name=\"app_update_failed\">Échec de la mise à jour vers la dernière version</string>\n    <string name=\"update\">Mettre à jour</string>\n    <string name=\"aria2_desc\">Utilisez aria2c comme gestionnaire de téléchargement externe</string>\n    <string name=\"multiselect_item_count\">%1$d fichier(s) vidéo, %2$d fichier(s) audio</string>\n    <string name=\"check_for_updates_desc\">Vérifier automatiquement la dernière version sur GitHub</string>\n    <string name=\"export_to_clipboard\">Exporter vers le Presse-papier</string>\n    <string name=\"template_exported\">%1$d modèle(s) exporté(s)</string>\n    <string name=\"download_task_count\">%1$d tâches de téléchargement</string>\n    <string name=\"import_from_clipboard\">Importer à partir du Presse-papier</string>\n    <string name=\"delete_multiple_items_msg\">Supprimer définitivement le(s) élément(s) %1$d de votre historique de téléchargement ?</string>\n    <string name=\"template_imported\">%1$d modèle(s) importé(s)</string>\n    <string name=\"sponsorblock_desc\">Supprimer ou marquer des segments de vidéos avec l\\'API SponsorBlock</string>\n    <string name=\"sponsorblock_categories_desc\">Spécifiez les catégories SponsorBlock à supprimer ou marquer dans le fichier vidéo</string>\n    <string name=\"sponsorblock_categories\">Catégories SponsorBlock</string>\n    <string name=\"multiselect_mode\">Mode multi-sélection</string>\n    <string name=\"private_mode_desc\">Désactiver l\\'historique des téléchargements</string>\n    <string name=\"private_mode\">Incognito</string>\n    <string name=\"download_with_cellular\">Télécharger via le réseau mobile</string>\n    <string name=\"download_with_cellular_desc\">Autoriser le téléchargement sur une connexion limitée</string>\n    <string name=\"dynamic_color\">Couleur dynamique</string>\n    <string name=\"download_disabled_with_cellular\">Vos paramètres empêchent le téléchargement sur un réseau mobile</string>\n    <string name=\"dynamic_color_desc\">Appliquez les couleurs des fonds d\\'écran au thème de l\\'application</string>\n    <string name=\"file_unavailable\">Ce fichier n\\'est plus disponible</string>\n    <string name=\"network\">Réseau</string>\n    <string name=\"rate_limit\">Limite de débit</string>\n    <string name=\"rate_limit_desc\">Limiter le débit maximal de téléchargement</string>\n    <string name=\"max_rate\">Débit maximal</string>\n    <string name=\"high_contrast\">Thème sombre à fort contraste</string>\n    <string name=\"invalid_input\">Entrée invalide</string>\n    <string name=\"lowest_quality\">Qualité la plus basse</string>\n    <string name=\"network_settings_desc\">Limite de débit, téléchargeur, cookies</string>\n    <string name=\"private_directory\">Répertoire privé</string>\n    <string name=\"unavailable\">Indisponible</string>\n    <string name=\"format_settings_desc\">Format de fichier, qualité vidéo, sous-titres</string>\n    <string name=\"general_settings_desc\">Version Yt-dlp, notification, liste de lecture</string>\n    <string name=\"disable_preview\">Désactiver l’aperçu</string>\n    <string name=\"disable_preview_desc\">Désactiver les images d\\'aperçu pendant le téléchargement</string>\n    <string name=\"use_custom_command\">Utiliser une commande personnalisée</string>\n    <string name=\"privacy\">Vie privée</string>\n    <string name=\"crop_artwork\">Rogner l\\'image</string>\n    <string name=\"crop_artwork_desc\">Rogner l\\'image intégrée dans un carré</string>\n    <string name=\"private_directory_desc\">Stocker les téléchargements dans un répertoire caché</string>\n    <string name=\"select_all\">Tout sélectionner</string>\n    <string name=\"download_selection_desc\">Sélectionner les vidéos à télécharger à partir de la liste de lecture « %1$s »</string>\n    <string name=\"selected_item_count\">%1$d sélectionné(s)</string>\n    <string name=\"suggested\">Suggéré</string>\n    <string name=\"video_only\">Vidéo (sans audio)</string>\n    <string name=\"format_selection\">Sélection du format</string>\n    <string name=\"format_selection_desc\">Sélectionnez le format à télécharger avant de commencer le téléchargement</string>\n    <string name=\"generate_new_cookies\">Générer de nouveaux cookies</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"cookies_usage_msg\">Le téléchargement à partir de certains sites nécessite des informations d\\'authentification du compte. Cliquez sur « Générer de nouveaux cookies », saisissez l\\'URL du site web, puis connectez-vous avec votre compte dans la page du navigateur, l\\'application les générera pour vous.</string>\n    <string name=\"telegram_channel\">Canal Telegram</string>\n    <string name=\"use_cookies\">Utiliser les cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Retirer cette entrée pour « %1$s » ? Veuillez noter que les cookies stockés pour ce site ne seront pas effacés.</string>\n    <string name=\"custom_command_enabled_hint\">Certaines options ne sont pas disponibles lors de l\\'utilisation de commande(s) personnalisée(s)</string>\n    <string name=\"how_does_it_work\">Comment ça fonctionne ?</string>\n    <string name=\"matrix_space\">Espace Matrix</string>\n    <string name=\"abs_hint\">La plupart des plateformes de streaming vidéo fournissent l\\'audio et la vidéo séparément. Vous pouvez sélectionner et fusionner un format uniquement audio avec un format uniquement vidéo pour obtenir une seule vidéo.</string>\n    <string name=\"sdcard_directory\">Dossier de la carte SD</string>\n    <string name=\"auto_subtitle\">Sous-titres automatiques</string>\n    <string name=\"auto_subtitle_desc\">Télécharger les sous-titres générés automatiquement</string>\n    <string name=\"video_creator_sample_text\">Texte type du créateur vidéo</string>\n    <string name=\"subtitle_language\">Langues des sous-titres</string>\n    <string name=\"clear\">Effacer</string>\n    <string name=\"edit_shortcuts\">Modifier les raccourcis</string>\n    <string name=\"add\">Ajouter</string>\n    <string name=\"shortcuts\">Raccourcis</string>\n    <string name=\"edit_shortcuts_desc\">Modifier les raccourcis personnalisés qui peuvent être utilisés pour composer des modèles de commande.</string>\n    <string name=\"running_tasks\">Tâches courantes</string>\n    <string name=\"show_logs\">Afficher le journal</string>\n    <string name=\"logs\">Journal</string>\n    <string name=\"download_subtitles\">Télécharger les sous-titres</string>\n    <string name=\"title_activity_share\">Téléchargement rapide</string>\n    <string name=\"video_title_sample_text\">Titre de la vidéo, exemple de texte</string>\n    <string name=\"subtitle\">Sous-titre</string>\n    <string name=\"copy_log\">Copier le journal</string>\n    <string name=\"subtitle_desc\">Langues, sous-titres intégrés, sous-titres automatiques</string>\n    <string name=\"subtitle_sponsorblock\">Les sous-titres peuvent être mal synchronisés lors de la suppression des segments du SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Pour intégrer des sous-titres, les vidéos seront remixées dans un conteneur mkv. Vous pouvez utiliser VLC Media Player ou d\\'autres applications compatibles pour regarder des vidéos avec des sous-titres intégrés.</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f M</string>\n    <string name=\"audio_format_preference\">Format audio préféré</string>\n    <string name=\"import_from_preferences\">Importer</string>\n    <string name=\"title\">Titre</string>\n    <string name=\"format_sorting_desc\">Tri des formats avec l\\'option -S de yt-dlp</string>\n    <string name=\"audio_format\">Format audio</string>\n    <string name=\"no_downloaded_media\">Aucun média téléchargé</string>\n    <string name=\"beta_features\">Bêta</string>\n    <string name=\"enable_experimental_feature\">Activer la fonction expérimentale ?</string>\n    <string name=\"clip_video_desc\">Réaliser des clips vidéo dans la page de sélection du format</string>\n    <string name=\"stable_channel\">Stable</string>\n    <string name=\"share\">Partager</string>\n    <string name=\"update_channel_desc\">Installez les préversions pour avoir un aperçu des nouvelles fonctionnalités et des modifications.\n\\n\n\\nIl y aura une certaine instabilité dans ces versions, alors n\\'hésitez pas à nous faire part de vos remarques si vous rencontrez des problèmes afin de nous aider à améliorer l\\'application à l\\'avenir.</string>\n    <string name=\"second\">seconde</string>\n    <string name=\"enable_auto_update\">Activer la mise à jour automatique</string>\n    <string name=\"audio_quality_desc\">Limiter le débit binaire audio lorsque plusieurs qualités sont présentes</string>\n    <string name=\"unlimited\">Illimité</string>\n    <string name=\"audio_quality\">Qualité audio</string>\n    <string name=\"format_sorting\">Tri des formats</string>\n    <string name=\"rename\">Renommer</string>\n    <string name=\"clip_video_dialog_msg\">Les téléchargements utilisant cette fonction seront délégués à FFmpeg pour télécharger des sections sélectionnées de la vidéo, cette fonction est encore expérimentale et la découpe ne sera pas complètement précise, tous les formats ne prennent pas cette fonction et vous pouvez constater des vitesses de téléchargement plus lentes.</string>\n    <string name=\"apply\">Appliquer</string>\n    <string name=\"pre_release_channel\">Aperçu</string>\n    <string name=\"discard\">Rejeter</string>\n    <string name=\"clip_video\">Couper la vidéo</string>\n    <string name=\"update_channel\">Canal de mise à jour</string>\n    <string name=\"auto_update\">Mise à jour automatique</string>\n    <string name=\"clip_end\">Fin</string>\n    <string name=\"lowest_bitrate\">Débit binaire le plus faible</string>\n    <string name=\"clip_start\">Début</string>\n    <string name=\"minute\">minute</string>\n    <string name=\"clear_all_cookies\">Effacer tous les cookies</string>\n    <string name=\"clear_all_cookies_desc\">Supprimer définitivement tous les cookies stockés dans l\\'application ?</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">Soutenez cette application en la parrainant sur GitHub</string>\n    <string name=\"sponsor_msg\">Seal sera toujours libre et gratuit pour tout le monde. Si vous l\\'aimez, pensez à me parrainer sur GitHub !</string>\n    <string name=\"feedback\">Remarques</string>\n    <string name=\"sponsors\">Sponsors</string>\n    <string name=\"temporary_directory_desc\">Stocker les fichiers temporaires dans le répertoire interne</string>\n    <string name=\"okay\">D\\'accord</string>\n    <string name=\"got_it\">Compris</string>\n    <string name=\"feature_unavailable\">Fonctionnalité non disponible</string>\n    <string name=\"no_custom_command_tasks\">Aucune tâche de commande personnalisée</string>\n    <string name=\"auto_update_disabled_msg\">La mise à jour automatique n\\'est pas disponible pour les versions %1$s. Si vous n\\'avez pas installé %1$s sur votre appareil, ou si vous souhaitez avoir un aperçu des nouvelles fonctionnalités de Seal, veuillez consulter %2$s.</string>\n    <string name=\"switch_to_github_builds\">passer aux moutures GitHub</string>\n    <string name=\"msg_from_developer\">Message du développeur</string>\n    <string name=\"sponsor_msg2\">Merci beaucoup !</string>\n    <string name=\"convert_subtitle\">Convertir les sous-titres</string>\n    <string name=\"convert_subtitle_desc\">Convertir les sous-titres dans un autre format</string>\n    <string name=\"split_video\">Séparer la vidéo</string>\n    <string name=\"split_video_msg\">La vidéo sera divisée en %1$d chapitres</string>\n    <string name=\"unknown_error_title\">Oups ! Quelque chose s\\'est mal passé</string>\n    <string name=\"copy_and_exit\">Copier et quitter</string>\n    <string name=\"download_video_desc\">Télécharger des vidéos depuis l\\'URL</string>\n    <string name=\"expand\">Développer</string>\n    <string name=\"edit_template\">Modifier « %1$s »</string>\n    <string name=\"new_task\">Nouvelle tâche de téléchargement</string>\n    <string name=\"start\">Commencer</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp est un puissant outil en ligne de commande pour le téléchargement de vidéos. Seal facilite l\\'utilisation de yt-dlp en fournissant une interface graphique intuitive, des préréglages pour les commandes courantes et d\\'autres fonctionnalités supplémentaires.\n\\n\n\\nPour une utilisation avancée de yt-dlp, Seal vous permet de créer, de sauvegarder et d\\'exécuter des modèles de commandes personnalisées directement, comme dans un terminal.\n\\n\n\\nLors de l\\'utilisation de commandes personnalisées, la plupart des options et fonctionnalités de l\\'interface graphique sont désactivées.</string>\n    <string name=\"export_to_file\">Exporter vers un fichier</string>\n    <string name=\"enable_notifications_desc\">L\\'application a besoin de votre autorisation pour afficher des notifications sur l\\'état et la progression du téléchargement.</string>\n    <string name=\"folder_picker\">Sélecteur de dossiers</string>\n    <string name=\"prefer_compatibility_desc\">Préférez les formats MP4 (H.264) pour partager avec d\\'autres applications</string>\n    <string name=\"commands\">Commandes</string>\n    <string name=\"unknown\">Inconnu</string>\n    <string name=\"learn_more\">En savoir plus</string>\n    <string name=\"prefer_quality_desc\">Préférez les formats AV1, VP9 ou H.265 pour la visualisation dans les applications compatibles</string>\n    <string name=\"download_type\">Type de téléchargement</string>\n    <string name=\"custom_command_directory\">Répertoire des commandes personnalisées</string>\n    <string name=\"custom_command_directory_desc\">Spécifier le répertoire de sortie lors de l\\'utilisation de commandes personnalisées</string>\n    <string name=\"set_directory_desc\">Appuyer pour configurer le répertoire</string>\n    <string name=\"ua_header\">En-tête User-Agent</string>\n    <string name=\"format_preference\">Préférence de format</string>\n    <string name=\"output_template_desc\">Spécifier le modèle pour les noms de fichiers de sortie</string>\n    <string name=\"disable\">Désactiver</string>\n    <string name=\"auto\">Automatique</string>\n    <string name=\"proxy_desc\">Utiliser un proxy pour les connexions internet</string>\n    <string name=\"quality\">Qualité</string>\n    <string name=\"refresh_cookies_desc\">Touchez pour ouvrir la page web permettant de générer de nouveaux cookies :</string>\n    <string name=\"ytdlp_update_action\">Mettre à jour yt-dlp</string>\n    <string name=\"remove_multiple_templates_msg\">Supprimer définitivement %1$s des modèles de commande ?</string>\n    <string name=\"enable_notifications\">Activer les notifications ?</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"clear_download_archive\">Effacer l\\'archive de téléchargement ?</string>\n    <string name=\"clear_download_archive_desc\">Supprimer %1$s dans le fichier d\\'archive pour de bon ?</string>\n    <string name=\"legacy\">Hérité</string>\n    <string name=\"embed_metadata\">Intégrer les métadonnées</string>\n    <string name=\"presets\">Préréglages</string>\n    <string name=\"required\">Requis</string>\n    <string name=\"output_template\">Modèle de fichier de sortie</string>\n    <string name=\"disabled\">Désactivé</string>\n    <string name=\"download_archive_desc\">Enregistrer les ID des vidéos téléchargées dans une archive pour éviter les doublons de téléchargement</string>\n    <string name=\"custom\">Personnalisé</string>\n    <string name=\"embed_metadata_desc\">Intégrer les métadonnées et la vignette de la vidéo dans le fichier audio</string>\n    <string name=\"download_archive\">Archive de téléchargement</string>\n    <string name=\"save\">Sauvegarder</string>\n    <string name=\"use_format_sorting\">Utiliser le tri par format</string>\n    <string name=\"show_all_items\">Montrer tous les %1$d éléments</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d élément</item>\n        <item quantity=\"many\">%d d\\'éléments</item>\n        <item quantity=\"other\">%d éléments</item>\n    </plurals>\n    <string name=\"edit_file\">Modifier le fichier</string>\n    <string name=\"allow_always\">Toujours autoriser</string>\n    <string name=\"dont_allow\">Ne pas autoriser</string>\n    <string name=\"download_with_cellular_request\">Autoriser l\\'utilisation des données mobiles ?</string>\n    <string name=\"merge_audiostream\">Combiner plusieurs pistes audios</string>\n    <string name=\"merge_audiostream_desc\">Autoriser plusieurs pistes audio a être fusionnées en un seule fichier</string>\n    <string name=\"subdirectory_hint\">Vos téléchargements seront enregistrés dans :</string>\n    <string name=\"keep_subtitle_files\">Garder le fichier des sous-titres</string>\n    <string name=\"restrict_filenames_desc\">Limiter les noms de fichiers à certains caractères pour assurer la compatibilité</string>\n    <string name=\"website\">Site web</string>\n    <string name=\"playlist_title\">Titre de la playlist</string>\n    <string name=\"auto_translated_subtitles\">Sous-titres automatiquement traduits</string>\n    <string name=\"remember_for_next_download\">Se souvenir pour le prochain téléchargement</string>\n    <string name=\"system_settings\">Paramètres système</string>\n    <string name=\"force_ipv4\">Forcer en IPv4</string>\n    <string name=\"force_ipv4_desc\">Établit toutes les connexions en IPv4</string>\n    <string name=\"search_in_downloads\">Rechercher dans les téléchargements</string>\n    <string name=\"search\">Rechercher</string>\n    <string name=\"auto_translated_subtitles_msg\">Des sous-titres automatiquement traduits seront disponibles pour toutes les langues dans les téléchargements. Ces sous-titres peuvent être imprécis et difficiles à comprendre.</string>\n    <string name=\"none\">Aucun</string>\n    <string name=\"no_thanks\">Non merci</string>\n    <string name=\"allow_once\">Autoriser une fois</string>\n    <string name=\"import_backup\">Importer</string>\n    <string name=\"import_download_history_msg\">Les fichiers téléchargés ne seront pas importer , vous devrais lea télécharger manuellement</string>\n    <string name=\"subtitle_language_desc\">La langue des sous-titres a télécharger en auto-sélection de format, séparée par des virgules.</string>\n    <string name=\"search_in_subtitles\">Rechercher dans sous-titres</string>\n    <string name=\"interface_and_interaction\">Interface et interactions</string>\n    <string name=\"use_previous_selection\">Utiliser la selection précédante</string>\n    <string name=\"file\">Fichier</string>\n    <string name=\"clipboard\">Presse-papier</string>\n    <string name=\"import_download_history\">Importer l\\'historique de téléchargement ?</string>\n    <string name=\"update_language_msg\">Les langues suivantes vont être ajoutées a vos préférences pour les prochains téléchargements :</string>\n    <string name=\"update_subtitle_languages\">Mettre à jour les langues des sous-titres ?</string>\n    <string name=\"restrict_filenames\">Restreindre les noms de fichiers</string>\n    <string name=\"download_archive_error\">La vidéo a été téléchargée. Si ce n\\'est pas le comportement attendu, veuillez vérifier votre archive téléchargée.</string>\n    <string name=\"export_download_history_msg\">Exportation de %1$s depuis l\\'historique de téléchargement. Les fichiers téléchargés et les préférences ne seront pas sauvegardés.</string>\n    <string name=\"export_backup\">Exporter</string>\n    <string name=\"full_backup\">Sauvegarde complète</string>\n    <string name=\"backup_type\">Type de sauvegarde</string>\n    <string name=\"reset\">Réinitialiser</string>\n    <string name=\"export_to\">Exporter vers</string>\n    <string name=\"import_from\">Importer depuis</string>\n    <string name=\"export_download_history\">Exporter l\\'historique des téléchargements ?</string>\n    <string name=\"download_history\">Historique des téléchargements</string>\n    <string name=\"download_history_imported\">Importation de %1$s dans l\\'historique des téléchargements</string>\n    <string name=\"redownload\">Retélécharger</string>\n    <string name=\"look_and_feel\">Couleur et style</string>\n    <string name=\"cookies_in_database\">%1$d cookies de %2$d sites web au total</string>\n    <string name=\"remux_container_mkv_desc\">Remuxez les vidéos dans un conteneur MKV pour une meilleure compatibilité</string>\n    <string name=\"remux_container_mkv\">Conteneur vidéo Remux</string>\n    <string name=\"every_day\">Tous les jours</string>\n    <string name=\"every_week\">Toutes les semaines</string>\n    <string name=\"every_month\">Chaque mois</string>\n    <string name=\"all_languages\">Toutes les langues</string>\n    <string name=\"preset\">Préréglage</string>\n    <string name=\"prefer_placeholder\">Préférer %1$s</string>\n    <string name=\"preset_format_selection_desc\">Télécharger automatiquement en fonction de vos préférences de format</string>\n    <string name=\"edit_preset\">Modifier le préréglage</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d vidéo</item>\n        <item quantity=\"many\">%d de vidéos</item>\n        <item quantity=\"other\">%d vidéos</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d fichier audio</item>\n        <item quantity=\"many\">%d de fichiers audio</item>\n        <item quantity=\"other\">%d fichiers audio</item>\n    </plurals>\n    <string name=\"task_added\">Tâche ajoutée à la file</string>\n    <string name=\"custom_format_selection_desc\">Choix pour les formats, les sous-titres et d\\'autres customisations</string>\n    <string name=\"playlist\">Liste de lecture</string>\n    <string name=\"proceed\">Continuer</string>\n    <string name=\"best_quality_desc\">Télécharger le meilleur format disponible</string>\n    <string name=\"you_ll_find_your_downloads_here\">Vous trouverez vos téléchargements ici</string>\n    <string name=\"download_hint\">Cliquez sur le bouton Télécharger ou partagez un lien vidéo vers cette application pour démarrer un téléchargement</string>\n    <string name=\"status_downloaded\">Téléchargé</string>\n    <string name=\"download_queue\">File d\\'attente de téléchargements</string>\n    <string name=\"all\">Tout</string>\n    <string name=\"select_multiple_link\">Sélectionner à partir de %1$d liens</string>\n    <string name=\"show_navigation_drawer\">Afficher le tiroir de navigation</string>\n    <string name=\"resume\">Continuer</string>\n    <string name=\"delete\">Supprimer</string>\n    <string name=\"media_info\">Infos média</string>\n    <string name=\"issue_tracker_hint\">Vous avez rencontré une erreur ? Avant de signaler un nouveau problème, veuillez consulter notre outil de suivi des problèmes. De nombreux problèmes courants y ont déjà été traités et documentés.</string>\n    <string name=\"trouble_shooting\">Dépannage</string>\n    <string name=\"issue_tracker\">Suivi des problèmes</string>\n    <string name=\"trouble_shooting_desc\">Corriger les erreurs courantes et vérifier les problèmes connus</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-gl/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Cartafol dos videos</string>\n    <string name=\"extract_audio\">Gardar como arquivo de sonido</string>\n    <string name=\"create_thumbnail\">Gardar carátula</string>\n    <string name=\"extract_audio_summary\">Descarga e garda como audio en vez de vídeo</string>\n    <string name=\"create_thumbnail_summary\">Gardar a carátula do vídeo como un arquivo</string>\n    <string name=\"yt_dlp_up_to_date\">Estás a usar a última versión de yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Non se pudo descargar a última versión de yt-dlp. Por favor, asegúrese de que está conectado ao internet.</string>\n    <string name=\"fetching_info\">Recibindo información do vídeo…</string>\n    <string name=\"permission_denied\">Permiso denegado</string>\n    <string name=\"settings\">Axustes</string>\n    <string name=\"download\">Descargar</string>\n    <string name=\"download_success_msg\">Descarga finalizada</string>\n    <string name=\"download_settings_desc\">Xeral, formatos e comandos personalizados</string>\n    <string name=\"download_error_msg\">Non se puido descargar o arquivo</string>\n    <string name=\"url_empty\">O enlace non pode estar vacío</string>\n    <string name=\"delete_file\">Eliminar</string>\n    <string name=\"dismiss\">Cancelar</string>\n    <string name=\"advanced_settings\">Avanzado</string>\n    <string name=\"close\">Pechar</string>\n    <string name=\"print_details\">Saída detallada</string>\n    <string name=\"user_guide\">Guía de usuario</string>\n    <string name=\"video_format_preference\">Preferencia de formato de vídeo</string>\n    <string name=\"link_copied\">Enlace copiado ao portapapeis</string>\n    <string name=\"credits_desc\">Créditos e software de código aberto</string>\n    <string name=\"readme_desc\">Vexa repositorio de GitHub e README</string>\n    <string name=\"remove\">Eliminar</string>\n    <string name=\"custom_command_desc\">Executar un comando de yt-dlp cun modelo personalizado</string>\n    <string name=\"ytdlp_update\">Fai clic para actualizar a libraría yt-dlp</string>\n    <string name=\"paste_fail_msg\">Non se puido pegar a URL dende o portapapeis</string>\n    <string name=\"preferred_format_desc\">Formato preferido cando se facilitan varios</string>\n    <string name=\"paste_desc\">Faga clic no botón de “Pegar” para obter o enlace dende o seu portapapeis.</string>\n    <string name=\"on\">Activado</string>\n    <string name=\"yt_dlp_docs\">Referencias de uso para yt-dlp</string>\n    <string name=\"edit\">Editar</string>\n    <string name=\"paste_msg\">Pegar URL dende o portapapeis</string>\n    <string name=\"convert_audio\">Converter</string>\n    <string name=\"video_quality\">Calidade do vídeo</string>\n    <string name=\"display_settings\">Modo escuro, cores dinámicas, lingua</string>\n    <string name=\"settings_before_download_desc\">Configurar axustes antes de descargar</string>\n    <string name=\"release_desc\">Procurar actualizacións e historial de cambios</string>\n    <string name=\"ytdlp_version\">Versión de yt-dlp</string>\n    <string name=\"display\">Aspecto</string>\n    <string name=\"off\">Desactivado</string>\n    <string name=\"start_download\">Descargar</string>\n    <string name=\"error_copied\">O erro reportado foi copiado ao portapapeis</string>\n    <string name=\"back\">Atrás</string>\n    <string name=\"downloads_history\">Descargas</string>\n    <string name=\"release\">Versión máis recente</string>\n    <string name=\"version\">Versión</string>\n    <string name=\"general_settings\">Xeral</string>\n    <string name=\"print_details_desc\">Mostrar en pantalla mensaxes relevantes durante a descarga</string>\n    <string name=\"open_settings\">Abrir axustes</string>\n    <string name=\"video_format\">Formato de vídeo</string>\n    <string name=\"convert_audio_format\">Converter formato de audio</string>\n    <string name=\"video_quality_desc\">Limitar a calidade do vídeo se houbese varios</string>\n    <string name=\"paste\">Pegar</string>\n    <string name=\"delete_info_msg\">Está seguro/a de eliminar «%1$s» do seu historial de descargas\\?</string>\n    <string name=\"start_execute\">Iniciar a execución do comando</string>\n    <string name=\"checked\">Verificado</string>\n    <string name=\"about\">Acerca de</string>\n    <string name=\"open_url\">Abrir enlace</string>\n    <string name=\"convert_audio_format_desc\">A recodificación de arquivos de audio causará perda de calidade de audio e aumento do tamaño do arquivo.</string>\n    <string name=\"not_convert\">Non converter</string>\n    <string name=\"about_page\">Versión, comentarios, actualización automática</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"custom_command_template\">Modelo de comando</string>\n    <string name=\"download_start_msg\">Descargando “%1$s”</string>\n    <string name=\"dark_theme\">Tema escuro</string>\n    <string name=\"cancel\">Cancelar</string>\n    <string name=\"close_never_show_again\">Non mostrar de novo</string>\n    <string name=\"settings_before_download\">Configurar antes da descarga</string>\n    <string name=\"confirm\">Confirmar</string>\n    <string name=\"language_settings\">Escoller lingua</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"delete_info\">Eliminar\\?</string>\n    <string name=\"language\">Lingua</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d elemento</item>\n        <item quantity=\"other\">%d elementos</item>\n    </plurals>\n    <string name=\"custom_command\">Comando personalizado</string>\n    <string name=\"task_running\">Xa se está realizando unha descarga</string>\n    <string name=\"settings_before_download_text\">Configurar axustes para esta descarga</string>\n    <string name=\"video\">Vídeo</string>\n    <string name=\"fetch_info_error_msg\">Houbo un erro ao obter a información do vídeo</string>\n    <string name=\"not_specified\">Sen especificar (por defecto)</string>\n    <string name=\"convert_to\">Converter a %1$s</string>\n    <string name=\"format\">Formato</string>\n    <string name=\"ytdlp_update_action\">Actualizar yt-dlp</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"edit_template_desc\">O directorio de saída e a URL serán engadidas pola app automaticamente.</string>\n    <string name=\"credits\">Créditos</string>\n    <string name=\"best_quality\">Mellor calidade</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-hi/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">वीडियो फ़ोल्डर</string>\n    <string name=\"extract_audio\">ऑडियो के रूप में सहेजें</string>\n    <string name=\"create_thumbnail\">थंबनेल सहेजें</string>\n    <string name=\"settings\">सेटिंग्स</string>\n    <string name=\"download_settings_desc\">सामान्य, प्रारूप, कस्टम कमांड</string>\n    <string name=\"download\">डाउनलोड</string>\n    <string name=\"url_empty\">लिंक खाली नहीं हो सकता</string>\n    <string name=\"download_success_msg\">डाउनलोड समाप्त</string>\n    <string name=\"download_error_msg\">फ़ाइल डाउनलोड नहीं कर सका</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" डाउनलोड करें</string>\n    <string name=\"general_settings\">सामान्य</string>\n    <string name=\"language\">भाषा प्रदर्शित करें</string>\n    <string name=\"language_settings\">प्रदर्शन भाषा सेट करें</string>\n    <string name=\"paste_msg\">URL पेस्ट करें</string>\n    <string name=\"paste_fail_msg\">क्लिपबोर्ड में URL से मेल नहीं खा सका</string>\n    <string name=\"ytdlp_version\">Yt-dlp संस्करण</string>\n    <string name=\"delete_info\">हटाएं\\?</string>\n    <string name=\"delete_info_msg\">अपने डाउनलोड इतिहास से \\\"%1$s\\\" को हमेशा के लिए हटा दें\\?</string>\n    <string name=\"dismiss\">रद्द करें</string>\n    <string name=\"downloads_history\">डाउनलोड</string>\n    <string name=\"audio\">ऑडियो</string>\n    <string name=\"link_copied\">लिंक को क्लिपबोर्ड पर कॉपी किया गया</string>\n    <string name=\"remove\">हटाएं</string>\n    <string name=\"delete_file\">फाईल मिटाएं</string>\n    <string name=\"about\">हमारे बारे में</string>\n    <string name=\"about_page\">संस्करण, प्रतिक्रिया, ऑटो अपडेट</string>\n    <string name=\"back\">पीछे</string>\n    <string name=\"version\">संस्करण</string>\n    <string name=\"release_desc\">चैंज और नए संस्करणों की तलाश करें</string>\n    <string name=\"release\">नवीनतम रिलीज़</string>\n    <string name=\"readme_desc\">GitHub रिपॉजिटरी और README की जाँच करें</string>\n    <string name=\"video\">वीडियो</string>\n    <string name=\"edit\">संपादित करें</string>\n    <string name=\"start_execute\">कमांड निष्पादित करना शुरू करें</string>\n    <string name=\"advanced_settings\">विकसित</string>\n    <string name=\"print_details\">विस्तृत आउटपुट</string>\n    <string name=\"print_details_desc\">डाउनलोड करते समय विस्तृत संदेश प्रिंट करें</string>\n    <string name=\"display\">दिखाएँ</string>\n    <string name=\"display_settings\">डार्क थीम, गतिशील रंग, भाषाएं</string>\n    <string name=\"dark_theme\">डार्क थीम</string>\n    <string name=\"follow_system\">सिस्टम</string>\n    <string name=\"on\">चालू</string>\n    <string name=\"off\">बंद</string>\n    <string name=\"cancel\">रद्द करें</string>\n    <string name=\"settings_before_download\">डाउनलोड करने से पहले सरंचना करें</string>\n    <string name=\"settings_before_download_text\">इस डाउनलोड को समायोजित करें</string>\n    <string name=\"error_copied\">त्रुटि की जानकारी सूचि मैं उतारा</string>\n    <string name=\"thumbnail\">थंमनेल</string>\n    <string name=\"paste\">चिपकाएं</string>\n    <string name=\"edit_template_desc\">आउटपुट पथ और URL ऐप द्वारा जोड़ा जाएगा।</string>\n    <string name=\"convert_audio_format\">ध्वनि प्रारूप को परिवर्तित करें</string>\n    <string name=\"high_contrast\">हाई कंट्रास्ट डार्क थीम</string>\n    <string name=\"invalid_input\">अमान्य इनपुट</string>\n    <string name=\"lowest_quality\">निम्नतम गुणवत्ता</string>\n    <string name=\"extract_audio_summary\">वीडियो के बजाय ऑडियो डाउनलोड और सेव करें</string>\n    <string name=\"permission_denied\">अनुमति नहीं मिली</string>\n    <string name=\"create_thumbnail_summary\">वीडियो थंबनेल को फ़ाइल के रूप में सहेजें</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp के नवीनतम संस्करण का उपयोग करना</string>\n    <string name=\"ytdlp_update\">नवीनतम yt-dlp संस्करण स्थापित करने के लिए क्लिक करें</string>\n    <string name=\"yt_dlp_update_fail\">नवीनतम yt-dlp संस्करण स्थापित नहीं किया जा सका। आप इंटरनेट से जुडे हैं कृपया यह सुनिश्चित कीजिए।</string>\n    <string name=\"fetching_info\">वीडियो जानकारी ली जा रही है…</string>\n    <string name=\"task_running\">एक मौजूदा डाउनलोड कार्य पहले से चल रहा है</string>\n    <string name=\"open_url\">लिंक खोलें</string>\n    <string name=\"fetch_info_error_msg\">वीडियो जानकारी नहीं ली जा सकी</string>\n    <string name=\"confirm\">पुष्टि करें</string>\n    <string name=\"checked\">चेक किए गए</string>\n    <string name=\"credits\">क्रेडिट</string>\n    <string name=\"custom_command_desc\">कस्टम टेम्पलेट के साथ yt-dlp कमांड चलाएँ</string>\n    <string name=\"credits_desc\">क्रेडिट और लिब्रे सॉफ्टवेयर</string>\n    <string name=\"custom_command\">कस्टम कमांड</string>\n    <string name=\"custom_command_template\">कमांड टेम्पलेट</string>\n    <string name=\"settings_before_download_desc\">डाउनलोड करने से पहले प्राथमिकताएं कॉन्फ़िगर करें</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp उपयोग संदर्भ</string>\n    <string name=\"not_convert\">असंशोधित</string>\n    <string name=\"convert_to\">%1$s में बदलें</string>\n    <string name=\"format\">प्रारूप</string>\n    <string name=\"convert_audio_format_desc\">ध्वनि फ़ाइलों को पुनः एनकोड करने से ध्वनि गुणवत्ता को हानि होगी और फ़ाइल का आकार बढ़ेगा।</string>\n    <string name=\"video_quality\">चलचित्र गुणवत्ता</string>\n    <string name=\"video_quality_desc\">एकाधिक मौजूद होने पर चलचित्र की गुणवत्ता सीमित करें</string>\n    <string name=\"not_specified\">अनिर्दिष्ट (मूल)</string>\n    <string name=\"video_format_preference\">पसंदीदा चलचित्र प्रारूप</string>\n    <string name=\"preferred_format_desc\">एकाधिक विकल्प दिए जाने पर पसंदीदा प्रारूप</string>\n    <string name=\"video_format\">चलचित्र प्रारूप</string>\n    <string name=\"convert_audio\">संशोध</string>\n    <string name=\"start_download\">डाउनलोड</string>\n    <string name=\"close\">बंद करें</string>\n    <string name=\"close_never_show_again\">दोबारा ना दिखाएं</string>\n    <string name=\"user_guide\">उपयोगकर्ता मार्गदर्शिका</string>\n    <string name=\"best_quality\">श्रेष्ठ गुणवत्ता</string>\n    <string name=\"open_settings\">समायोजन खोलें</string>\n    <string name=\"paste_desc\">सूचि से चलचित्र लिंक प्राप्त करने के लिए \\\"चिपकाएं\\\" दबाएं।</string>\n    <string name=\"download_desc\">समायोजन के बाद \\\"डाउनलोड\\\" दबाएं।</string>\n    <string name=\"select_all\">सभी का चयन करे</string>\n    <string name=\"selected_item_count\">%1$d चुने</string>\n    <string name=\"download_history_desc\">चलचित्र और ध्वनि फाइलों सहित ऐप में डाउनलोड की जांच और प्रबंधन करें।</string>\n    <string name=\"check_download_settings_desc\">डाउनलोड समायोजन देखें और उपयोग से पहले सुनिश्चित करें कि आपके पास yt-dlp का नवीनतम संस्करण है।</string>\n    <string name=\"defaults\">मूल</string>\n    <string name=\"channel_name\">डाउनलोड</string>\n    <string name=\"channel_description\">डाउनलोड की गई फ़ाइलें और प्रगति की सूचना दें</string>\n    <string name=\"download_playlist\">सूची डाउनलोड करें</string>\n    <string name=\"download_playlist_desc\">सूची से कई चलचित्र डाउनलोड करें</string>\n    <string name=\"video_url\">चलचित्र लिंक</string>\n    <string name=\"download_finish_notification\">डाउनलोड समाप्त। खोलने के स्पर्श करें।</string>\n    <string name=\"execute_command_notification\">अनुकूलित आदेश चल रहा है…</string>\n    <string name=\"battery_settings_desc\">कृपया पृष्ठभूमि में डाउनलोड करने के लिए सिस्टम सेटिंग्स में इस ऐप के बैटरी उपयोग को \\\"अप्रतिबंधित\\\" पर सेट करें।</string>\n    <string name=\"concurrent_download\">मल्टी थ्रेडेड डाउनलोड</string>\n    <string name=\"concurrent_download_desc\">समानांतर में M3U8/MPD वीडियो के और हिस्से डाउनलोड करें</string>\n    <string name=\"options\">विकल्प</string>\n    <string name=\"additional_settings\">अतिरिक्त सेटिंग्स</string>\n    <string name=\"share_fail_msg\">साझा सामग्री से URL का मिलान करने में असमर्थ</string>\n    <string name=\"share_success_msg\">साझा की गई सामग्री से वीडियो लिंक पढ़ना…</string>\n    <string name=\"show_more_actions\">और कार्रवाइयाँ दिखाएँ</string>\n    <string name=\"download_notification\">डाउनलोड अधिसूचना</string>\n    <string name=\"download_notification_desc\">डाउनलोड की गई फ़ाइलों और प्रगति की सूचना दें</string>\n    <string name=\"fetching_playlist_info\">प्लेलिस्ट जानकारी ला रहा है…</string>\n    <string name=\"download_range_selection\">प्लेलिस्ट चयन</string>\n    <string name=\"download_range_desc\">प्लेलिस्ट \\\"%3$s\\\" ( %1$d से %2$d तक) से डाउनलोड करने के लिए वीडियो की श्रेणी निर्दिष्ट करें।</string>\n    <string name=\"from\">शुरू</string>\n    <string name=\"to\">समाप्त</string>\n    <string name=\"invalid_index_range\">अमान्य अनुक्रमणिका श्रेणी</string>\n    <string name=\"playlist_indicator_text\">प्लेलिस्ट (%1$d/%2$d) डाउनलोड हो रही है…</string>\n    <string name=\"audio_directory\">ऑडियो फ़ोल्डर</string>\n    <string name=\"download_directory\">डाउनलोड निर्देशिका</string>\n    <string name=\"subdirectory\">उपनिर्देशिका में सहेजें</string>\n    <string name=\"subdirectory_desc\">फ़ाइलों को संबंधित फ़ील्ड के नाम वाले फ़ोल्डरों में सहेजें</string>\n    <string name=\"permission_issue\">स्टोरेज अनुमति मुद्दा</string>\n    <string name=\"permission_issue_desc\">डाउनलोड/ और दस्तावेज़/ के बाहर निर्देशिकाएँ समर्थित नहीं हैं</string>\n    <string name=\"battery_configuration\">बैटरी संरचना</string>\n    <string name=\"service_title\">सील डाउनलोड कर रही है…</string>\n    <string name=\"unknown_error\">अज्ञात त्रुटि</string>\n    <string name=\"translate\">अनुवाद करें</string>\n    <string name=\"prefix\">पथ टेम्पलेट</string>\n    <string name=\"embed_subtitles\">सबटाइटल एम्बेड करें</string>\n    <string name=\"embed_subtitles_desc\">यदि उपलब्ध हो तो वीडियोज में सॉफ्ट सबटाइटल एम्बेड करें</string>\n    <string name=\"new_template\">नया टेम्पलेट</string>\n    <string name=\"template_label\">लेबल</string>\n    <string name=\"remove_template\">हटाना है\\?</string>\n    <string name=\"remove_template_desc\">कमांड टेम्प्लेट से \\\"%1$s\\\" हमेशा के लिए हटा दें\\?</string>\n    <string name=\"template_selection\">टेम्पलेट चयन</string>\n    <string name=\"custom_command_template_desc\">कमांड टेम्प्लेट संपादित और प्रबंधित करें</string>\n    <string name=\"downloading_indicator_text\">डाउनलोड प्रगति पर है…</string>\n    <string name=\"task_canceled\">डाउनलोड कार्य रद्द किया गया</string>\n    <string name=\"github_issue_desc\">बग रिपोर्ट या सुविधा अनुरोध के लिए कोई समस्या सबमिट करें</string>\n    <string name=\"github_issue\">गिटहब अनुरोध</string>\n    <string name=\"info_copied\">जानकारी क्लिपबोर्ड पर कॉपी की गई</string>\n    <string name=\"status_enqueued\">कतारबद्ध हुआ</string>\n    <string name=\"status_completed\">पूरा हुआ</string>\n    <string name=\"status_downloading\">डाउनलोड</string>\n    <string name=\"status_canceled\">रद्द</string>\n    <string name=\"status_fetching_video_info\">जानकारी लाई जा रही है</string>\n    <string name=\"open_file\">फाइल खोलें</string>\n    <string name=\"restart\">पुनर्प्रारंभ करें</string>\n    <string name=\"status_error\">त्रुटि संदेश</string>\n    <string name=\"copy_link\">लिंक को कॉपी करें</string>\n    <string name=\"copy_error_report\">रिपोर्ट कापी करें</string>\n    <string name=\"video_resolution\">वीडियो रेजोल्यूशन</string>\n    <string name=\"video_file_size\">वीडियो फ़ाइल आकार</string>\n    <string name=\"export_to_clipboard\">क्लिपबोर्ड पर निर्यात करें</string>\n    <string name=\"import_from_clipboard\">क्लिपबोर्ड से आयात करें</string>\n    <string name=\"template_exported\">निर्यात किए %1$d टेम्प्लेट</string>\n    <string name=\"template_imported\">आयात हुए %1$d टेम्प्लेट</string>\n    <string name=\"download_task_count\">%1$d डाउनलोड कार्य</string>\n    <string name=\"recently_added\">हाल ही में जोड़ा</string>\n    <string name=\"multiselect_item_count\">%1$d वीडियो, %2$d ऑडियो फ़ाइल (फ़ाइलें)</string>\n    <string name=\"delete_multiple_items_msg\">अपने डाउनलोड इतिहास से %1$d आइटम (आइटमों) को हमेशा के लिए निकाल दें\\?</string>\n    <string name=\"sponsorblock_desc\">स्पांसर-ब्लॉक API के साथ वीडियो में सेगमेंट निकालें या चिह्नित करें</string>\n    <string name=\"sponsorblock_categories\">स्पांसर-ब्लॉक श्रेणियां</string>\n    <string name=\"sponsorblock_categories_desc\">वीडियो फ़ाइल में निकालने या चिह्नित करने के लिए स्पांसर-ब्लॉक श्रेणियाँ निर्दिष्ट करें</string>\n    <string name=\"check_for_updates\">अपडेटस के लिए जाँच करें</string>\n    <string name=\"check_for_updates_desc\">गिटहब पर स्वचालित रूप से नवीनतम संस्करण की जाँच करें</string>\n    <string name=\"app_up_to_date\">वर्तमान संस्करण अप टू डेट है</string>\n    <string name=\"app_update_failed\">नवीनतम संस्करण में अपडेट करने में विफल</string>\n    <string name=\"update\">अपडेट करें</string>\n    <string name=\"cookies_desc\">डाउनलोड के लिए नेटस्केप स्वरूपित कुकीज़ का प्रयोग करें</string>\n    <string name=\"clear_temp_files\">अस्थायी फ़ाइलें साफ़ करें</string>\n    <string name=\"clear_temp_files_desc\">अस्थायी निर्देशिका से सभी अस्थायी फ़ाइलें हटाएं</string>\n    <string name=\"clear_temp_files_count\">हटाई गई %1$d अस्थायी फ़ाइल(फ़ाइलें)</string>\n    <string name=\"clear_temp_files_info\">रद्द किए गए डाउनलोड को फिर से शुरू करने के लिए अस्थायी फ़ाइलों का उपयोग किया जा सकता है। क्या आप वाकई इन सभी फ़ाइलों को मिटाना चाहते हैं\\?\n\\n\n\\nआप इन फ़ाइलों को %1$s में एक्सेस कर सकते हैं</string>\n    <string name=\"multiselect_mode\">बहुचयन मोड</string>\n    <string name=\"private_mode\">गुमनाम</string>\n    <string name=\"dynamic_color\">गतिशील रंग</string>\n    <string name=\"download_with_cellular\">मोबाइल डेटा का उपयोग कर डाउनलोड करें</string>\n    <string name=\"download_disabled_with_cellular\">आपकी सेटिंग के अनुसार सेल्युलर नेटवर्क से डाउनलोड करना अक्षम किया है</string>\n    <string name=\"file_unavailable\">यह फाइल अब उपलब्ध नही है</string>\n    <string name=\"unavailable\">अनुपलब्ध</string>\n    <string name=\"format_settings_desc\">फ़ाइल प्रारूप, वीडियो क्वालिटी, सबटाइटल</string>\n    <string name=\"network_settings_desc\">दर सीमा, डाउनलोडर, कुकीज़</string>\n    <string name=\"disable_preview\">पूर्वावलोकन अक्षम करें</string>\n    <string name=\"privacy\">गोपनीयता</string>\n    <string name=\"use_custom_command\">कस्टम कमांड का प्रयोग करें</string>\n    <string name=\"private_directory\">निजी निर्देशिका</string>\n    <string name=\"private_directory_desc\">डाउनलोडस को एक हिडन डायरेक्टरी में स्टोर करें</string>\n    <string name=\"crop_artwork_desc\">छवि को वर्गाकार में क्रॉप करें</string>\n    <string name=\"crop_artwork\">कलाकृति क्रॉप करें</string>\n    <string name=\"network\">नेटवर्क</string>\n    <string name=\"rate_limit\">दर सीमा</string>\n    <string name=\"max_rate\">अधिकतम दर</string>\n    <string name=\"concurrent_download_num\">%d धाराओं का उपयोग DASH/HLS नेटिव वीडियो को समवर्ती रूप से डाउनलोड करने के लिए किया जाएगा।</string>\n    <string name=\"download_directory_desc\">चुनें कि वीडियो और ऑडियो फ़ाइलें कहाँ संग्रहित करनी हैं</string>\n    <string name=\"battery_configuration_desc\">इस ऐप को पृष्ठभूमि में डाउनलोड करने के लिए बैटरी ऑप्टिमाइज़ेशन को इग्नोर करें</string>\n    <string name=\"translate_desc\">होस्ट किए गए वेबलेट पर इस ऐप का अनुवाद करने में सहायता करें</string>\n    <string name=\"aria2_desc\">बाहरी डाउनलोडर के रूप में aria2c का प्रयोग करें</string>\n    <string name=\"private_mode_desc\">डाउनलोड इतिहास अक्षम करें</string>\n    <string name=\"dynamic_color_desc\">वॉलपेपर से ऐप थीम पर रंग लागू करें</string>\n    <string name=\"download_with_cellular_desc\">मीटर्ड नेटवर्क पर मीडिया को डाउनलोड करने की अनुमति दें</string>\n    <string name=\"rate_limit_desc\">अधिकतम डाउनलोड गति सीमित करें</string>\n    <string name=\"general_settings_desc\">Yt-dlp वर्शन, सूचना, प्लेलिस्ट</string>\n    <string name=\"disable_preview_desc\">डाउनलोड के समय थंमनेल ना दिखाएं</string>\n    <string name=\"download_selection_desc\">प्लेलिस्ट \\\"%1$s\\\" से डाउनलोड करने के लिए वीडियो चुनें</string>\n    <string name=\"video_only\">वीडियो (कोई ऑडियो नहीं)</string>\n    <string name=\"suggested\">सुझावित</string>\n    <string name=\"generate_new_cookies\">नई कुकीज़ उत्पन्न करें</string>\n    <string name=\"format_selection_desc\">डाउनलोड शुरू करने से पहले डाउनलोड करने के लिए प्रारूप का चयन करें</string>\n    <string name=\"format_selection\">प्रारूप चयन</string>\n    <string name=\"use_cookies\">कुकीज़ का प्रयोग करें</string>\n    <string name=\"custom_command_enabled_hint\">कस्टम आदेश का उपयोग करते समय कुछ विकल्प अनुपलब्ध होते हैं</string>\n    <string name=\"how_does_it_work\">यह कैसे काम करता है\\?</string>\n    <string name=\"telegram_channel\">टेलीग्राम चैनल</string>\n    <string name=\"cookies_usage_msg\">कुछ साइटों से डाउनलोड करने के लिए खाता प्रमाणीकरण जानकारी की आवश्यकता होती है। \\\"नई कुकी जनरेट करें\\\" पर क्लिक करें, वेबसाइट का URL दर्ज करें और फिर ब्राउज़र पेज में अपने खाते से लॉग इन करें, ऐप इसे आपके लिए जनरेट कर देगा।</string>\n    <string name=\"remove_cookie_profile_desc\">\\\"%1$s\\\" के लिए यह एंट्री हटाएँ? कृपया ध्यान दें कि इस साइट के लिए संग्रहित कुकीज़ साफ़ नहीं की जाएंगी।</string>\n    <string name=\"cookies\">कुकीज़</string>\n    <string name=\"matrix_space\">मैट्रिक्स स्पेस</string>\n    <string name=\"add\">जोड़ें</string>\n    <string name=\"title_activity_share\">शीघ्र डाउनलोड</string>\n    <string name=\"video_creator_sample_text\">वीडियो निर्माता नमूना पाठ</string>\n    <string name=\"video_title_sample_text\">वीडियो शीर्षक नमूना पाठ</string>\n    <string name=\"copy_log\">लॉग कापी करें</string>\n    <string name=\"subtitle\">सबटाइटल</string>\n    <string name=\"download_subtitles\">सबटाइटल डाउनलोड करें</string>\n    <string name=\"subtitle_language\">सबटाइटल भाषाएँ</string>\n    <string name=\"subtitle_desc\">भाषाएँ, एम्बेड किए सबटाइटल , ऑटो कैप्शन</string>\n    <string name=\"clear\">साफ़ करें</string>\n    <string name=\"edit_shortcuts\">शॉर्टकट संपादित करें</string>\n    <string name=\"show_logs\">लॉग दिखाएँ</string>\n    <string name=\"shortcuts\">शॉर्टकट</string>\n    <string name=\"edit_shortcuts_desc\">उन कस्टम शॉर्टकट को संपादित करें जिनका उपयोग कमांड टेम्प्लेट लिखने के लिए किया जा सकता है।</string>\n    <string name=\"running_tasks\">चल रहे कार्य</string>\n    <string name=\"subtitle_sponsorblock\">प्रायोजक ब्लॉक सेगमेंट को हटाते समय सबटाइटल गलत समय पर हो सकते हैं।</string>\n    <string name=\"abs_hint\">अधिकांश वीडियो स्ट्रीमिंग प्लेटफ़ॉर्म ऑडियो और वीडियो को अलग-अलग वितरित करते हैं, आप एक वीडियो-केवल प्रारूप के साथ एक ऑडियो-ओनली प्रारूप का चयन और विलय कर सकते हैं।</string>\n    <string name=\"sdcard_directory\">एसडी कार्ड फ़ोल्डर</string>\n    <string name=\"auto_subtitle\">स्वचालित कैप्शन</string>\n    <string name=\"auto_subtitle_desc\">स्वत: जनरेट किए गए कैप्शन डाउनलोड करें</string>\n    <string name=\"logs\">लॉग</string>\n    <string name=\"embed_subtitles_mkv_msg\">साफ्ट सबटाइटल एम्बेड करने के लिए, वीडियो को एमकेवी कंटेनर में फिर से जोड़ा जाएगा। आप साफ्ट सबटाइटल के साथ वीडियो देखने के लिए वीएलसी मीडिया प्लेयर या अन्य संगत ऐप्स का उपयोग कर सकते हैं।</string>\n    <string name=\"audio_format_preference\">पसंदीदा ऑडियो प्रारूप</string>\n    <string name=\"unlimited\">असीमित</string>\n    <string name=\"lowest_bitrate\">सबसे कम बिटरेट</string>\n    <string name=\"format_sorting\">प्रारूप छँटाई</string>\n    <string name=\"format_sorting_desc\">yt-dlp के -S विकल्प के साथ स्वरूपों को क्रमबद्ध करना</string>\n    <string name=\"import_from_preferences\">आयात करें</string>\n    <string name=\"title\">शीर्षक</string>\n    <string name=\"rename\">नाम बदलें</string>\n    <string name=\"second\">दूसरा</string>\n    <string name=\"minute\">मिनट</string>\n    <string name=\"clear_all_cookies\">सभी कुकी साफ़ करें</string>\n    <string name=\"clear_all_cookies_desc\">ऐप में संगृहीत सभी कुकी हमेशा के लिए हटा दें\\?</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"share\">साझा करें</string>\n    <string name=\"stable_channel\">स्थिर</string>\n    <string name=\"pre_release_channel\">पूर्व दर्शन</string>\n    <string name=\"update_channel\">अपडेट चैनल</string>\n    <string name=\"auto_update\">ऑटो अपडेट</string>\n    <string name=\"enable_auto_update\">ऑटो अपडेट सक्षम करें</string>\n    <string name=\"discard\">खारिज करें</string>\n    <string name=\"apply\">लागू करें</string>\n    <string name=\"clip_start\">शुरू</string>\n    <string name=\"clip_end\">अंत</string>\n    <string name=\"update_channel_desc\">नई सुविधाओं और परिवर्तनों का पूर्वावलोकन करने के लिए रिलीज़-पूर्व बिल्ड स्थापित करें।\n\\n\n\\n इन संस्करणों में कुछ अस्थिरता होगी, इसलिए यदि आपको कोई समस्या आती है और भविष्य के लिए ऐप को बेहतर बनाने में हमारी मदद करने के लिए कृपया हमें प्रतिक्रिया देने में संकोच न करें।</string>\n    <string name=\"clip_video\">क्लिप वीडियो</string>\n    <string name=\"audio_quality\">ऑडियो गुणवत्ता</string>\n    <string name=\"audio_quality_desc\">एकाधिक कुआलिटी मौजूद होने पर ऑडियो बिटरेट सीमित करें</string>\n    <string name=\"temporary_directory_desc\">अस्थायी फ़ाइलों को आंतरिक निर्देशिका में संग्रहीत करें</string>\n    <string name=\"audio_format\">ऑडियो प्रारूप</string>\n    <string name=\"no_downloaded_media\">कोई डाउनलोड मीडिया नहीं</string>\n    <string name=\"enable_experimental_feature\">प्रयोगात्मक सुविधा सक्षम करें\\?</string>\n    <string name=\"clip_video_desc\">प्रारूप चयन पृष्ठ में वीडियो क्लिप बनाएं</string>\n    <string name=\"switch_to_github_builds\">GitHub बिल्ड पर स्विच करना</string>\n    <string name=\"sponsor_msg\">सील हमेशा सभी के लिए स्वतंत्र और खुला स्रोत होगा। यदि आप इसे पसंद करते हैं, तो कृपया मुझे GitHub पर प्रायोजित करने पर विचार करें!</string>\n    <string name=\"got_it\">समझ गया</string>\n    <string name=\"sponsors\">प्रायोजक</string>\n    <string name=\"auto_update_disabled_msg\">%1$s बिल्ड के लिए ऑटो-अपडेट उपलब्ध नहीं है। यदि आपके डिवाइस पर %1$s स्थापित नहीं है, या सील में आने वाली नई सुविधाओं का पूर्वावलोकन करना चाहते हैं, तो कृपया %2$s पर विचार करें।</string>\n    <string name=\"clip_video_dialog_msg\">इस सुविधा का उपयोग करने वाले डाउनलोड वीडियो के चयनित अनुभागों को डाउनलोड करने के लिए FFmpeg को सौंपे जाएंगे, यह सुविधा अभी भी प्रायोगिक है और कटिंग पूरी तरह से सटीक नहीं होगी, सभी प्रारूप इस सुविधा का समर्थन नहीं करते हैं और आपको धीमी डाउनलोड गति का अनुभव हो सकता है।</string>\n    <string name=\"okay\">ठीक</string>\n    <string name=\"feature_unavailable\">सुविधा उपलब्ध नहीं है</string>\n    <string name=\"sponsor\">प्रायोजक</string>\n    <string name=\"beta_features\">बीटा</string>\n    <string name=\"no_custom_command_tasks\">कोई कस्टम कमांड कार्य नहीं</string>\n    <string name=\"sponsor_desc\">GitHub पर प्रायोजित करके इस ऐप का समर्थन करें</string>\n    <string name=\"feedback\">प्रतिक्रिया</string>\n    <string name=\"msg_from_developer\">डेवलपर से संदेश</string>\n    <string name=\"sponsor_msg2\">आपका बहुत-बहुत धन्यवाद!</string>\n    <string name=\"convert_subtitle\">सबटाइटल बदलें</string>\n    <string name=\"convert_subtitle_desc\">सबटाइटल को किसी अन्य प्रारूप में बदलें</string>\n    <string name=\"split_video\">वीडियो विभाजित करें</string>\n    <string name=\"split_video_msg\">वीडियो को %1$d अध्यायों में विभाजित किया जाएगा</string>\n    <string name=\"unknown_error_title\">उफ़! कुछ गलत हो गया</string>\n    <string name=\"copy_and_exit\">कापी करें और बाहर निकलें</string>\n    <string name=\"download_video_desc\">URL से वीडियो डाउनलोड करें</string>\n    <string name=\"start\">शुरू करें</string>\n    <string name=\"expand\">विस्तृत करें</string>\n    <string name=\"new_task\">नया डाऊनलोड कार्य</string>\n    <string name=\"edit_template\">\\\"%1$s\\\" संपादित करें</string>\n    <string name=\"proxy\">प्रॉक्सी</string>\n    <string name=\"proxy_desc\">इंटरनेट कनेक्शन के लिए प्रॉक्सी का उपयोग करें</string>\n    <string name=\"legacy\">लिगेसी</string>\n    <string name=\"quality\">क्वालिटी</string>\n    <string name=\"enable_notifications\">सूचनाएँ सक्षम करें\\?</string>\n    <string name=\"enable_notifications_desc\">ऐप को डाउनलोड स्थिति और प्रगति के बारे में सूचनाएं पोस्ट करने के लिए आपकी अनुमति की आवश्यकता है।</string>\n    <string name=\"disable\">अक्षम करें</string>\n    <string name=\"ytdlp_update_action\">yt-dlp अपडेट करें</string>\n    <string name=\"set_directory_desc\">निर्देशिका सेट करने के लिए टैप करें</string>\n    <string name=\"custom_command_directory\">कस्टम आदेश निर्देशिका</string>\n    <string name=\"disabled\">अक्षम</string>\n    <string name=\"folder_picker\">फ़ोल्डर पिकर</string>\n    <string name=\"custom_command_directory_desc\">कस्टम आदेशों का उपयोग करते समय आउटपुट निर्देशिका निर्दिष्ट करें</string>\n    <string name=\"prefer_compatibility_desc\">अन्य ऐप्स पर साझा करने के लिए MP4 (H.264) स्वरूपों को प्राथमिकता दें</string>\n    <string name=\"prefer_quality_desc\">संगत ऐप्स में देखने के लिए AV1, VP9 या H.265 स्वरूपों को प्राथमिकता दें</string>\n    <string name=\"download_type\">डाउनलोड प्रकार</string>\n    <string name=\"custom\">कस्टम</string>\n    <string name=\"auto\">ऑटो</string>\n    <string name=\"commands\">कमांडें</string>\n    <string name=\"format_preference\">फ़ॉर्मेट प्राथमिकता</string>\n    <string name=\"learn_more\">और अधिक जानें</string>\n    <string name=\"unknown\">अज्ञात</string>\n    <string name=\"refresh_cookies_desc\">नई कुकीज़ उत्पन्न करने के लिए वेबपेज खोलने के वास्ते टैप करें:</string>\n    <string name=\"ua_header\">उपयोगकर्ता-एजेंट हेडर</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d आइटम</item>\n        <item quantity=\"other\">%d आइटम्स</item>\n    </plurals>\n    <string name=\"remove_multiple_templates_msg\">कमांड टेम्प्लेट से %1$s को बेहतरी के लिए हटा दें\\?</string>\n    <string name=\"export_to_file\">फ़ाइल में निर्यात करें</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp वीडियो डाउनलोड करने के लिए एक शक्तिशाली कमांड-लाइन टूल है। सील एक सहज ज्ञान युक्त जीयूआई, सामान्य कमांड के लिए प्रीसेट और अन्य अतिरिक्त सुविधाएं प्रदान करके yt-dlp का उपयोग करना आसान बनाता है।\n\\n\n\\nYt-dlp के उन्नत उपयोग के लिए, सील आपको टर्मिनल की तरह सीधे कस्टम कमांड टेम्पलेट बनाने, सहेजने और निष्पादित करने की अनुमति देता है।\n\\n\n\\nकस्टम कमांड का उपयोग करते समय, अधिकांश GUI विकल्प और सुविधाएँ अक्षम कर दी जाएंगी।</string>\n    <string name=\"clear_download_archive\">डाउनलोड आरकाईव साफ़ करें\\?</string>\n    <string name=\"clear_download_archive_desc\">आरकाईव फ़ाइल से %1$s को हमेशा के लिए हटा दें\\?</string>\n    <string name=\"presets\">प्रीसेट</string>\n    <string name=\"output_template\">आउटपुट टेम्पलेट</string>\n    <string name=\"output_template_desc\">आउटपुट फ़ाइल नामों के लिए टेम्पलेट निर्दिष्ट करें</string>\n    <string name=\"download_archive_desc\">डुप्लिकेट डाउनलोड से बचने के लिए डाउनलोड की गई वीडियो आईडी को एक आरकाईव में रिकॉर्ड करें</string>\n    <string name=\"download_archive\">डाउनलोड आरकाईव</string>\n    <string name=\"embed_metadata\">मेटाडेटा एम्बेड करें</string>\n    <string name=\"required\">आवश्यक है</string>\n    <string name=\"embed_metadata_desc\">ऑडियो फ़ाइल में मेटाडेटा और वीडियो थंमनेल एम्बेड करें</string>\n    <string name=\"show_all_items\">सभी %1$d आइटम दिखाएं</string>\n    <string name=\"save\">सहेजें</string>\n    <string name=\"use_format_sorting\">फार्मेट छँटाई का प्रयोग करें</string>\n    <string name=\"edit_file\">फ़ाइल संपादित करें</string>\n    <string name=\"website\">वेबसाइट</string>\n    <string name=\"restrict_filenames_desc\">अनुकूलता सुनिश्चित करने के लिए फ़ाइल नामों को विशिष्ट वर्णों तक सीमित करें</string>\n    <string name=\"restrict_filenames\">फ़ाइल नाम प्रतिबंधित करें</string>\n    <string name=\"playlist_title\">प्लेलिस्ट शीर्षक</string>\n    <string name=\"subdirectory_hint\">आपके डाउनलोड इस रूप में सहेजे जाएंगे:</string>\n    <string name=\"system_settings\">सिस्टम सेटिंग्स</string>\n    <string name=\"force_ipv4\">IPv4 फोर्स करें</string>\n    <string name=\"force_ipv4_desc\">सभी कनेक्शन IPv4 के माध्यम से बनाएं</string>\n    <string name=\"keep_subtitle_files\">सबटाइटल की फ़ाइलें रखें</string>\n    <string name=\"dont_allow\">अनुमति न दें</string>\n    <string name=\"download_with_cellular_request\">मोबाइल डाटा से डाउनलोड करने की अनुमति दें?</string>\n    <string name=\"allow_always\">हमेशा की अनुमति</string>\n    <string name=\"merge_audiostream\">एकाधिक ऑडियो स्ट्रीम को मर्ज करें</string>\n    <string name=\"merge_audiostream_desc\">एकाधिक ऑडियो स्ट्रीम को एक फ़ाइल में मर्ज करने की अनुमति दें</string>\n    <string name=\"allow_once\">एक बार की अनुमति दें</string>\n    <string name=\"search_in_downloads\">डाउनलोड में खोजें</string>\n    <string name=\"search\">खोज करें</string>\n    <string name=\"auto_translated_subtitles\">आटो अनुवादित सबटाइटल</string>\n    <string name=\"auto_translated_subtitles_msg\">सभी भाषाओं के लिए स्वतः-अनुवादित सबटाइटल डाउनलोड में उपलब्ध होंगे। ये सबटाइटल ग़लत और समझने में कठिन हो सकते हैं।</string>\n    <string name=\"remember_for_next_download\">अगले डाउनलोड के लिए याद रखें</string>\n    <string name=\"look_and_feel\"><![CDATA[दिखावट और अनुभव]]></string>\n    <string name=\"use_previous_selection\">पिछले चयन का उपयोग करें</string>\n    <string name=\"none\">कोई नहीं</string>\n    <string name=\"subtitle_language_desc\">स्वचालित प्रारूप चयन में डाउनलोड करने के लिए सबटाइटल की भाषा, अल्पविराम (काॅमा) से अलग की गई है।</string>\n    <string name=\"reset\">रीसेट करें</string>\n    <string name=\"search_in_subtitles\">उपशीर्षकों में खोजें</string>\n    <string name=\"no_thanks\">जी नहीं, धन्यवाद</string>\n    <string name=\"update_language_msg\">भविष्य में डाउनलोड के लिए निम्नलिखित भाषाओं को आपकी प्राथमिकता में जोड़ा जाएगा:</string>\n    <string name=\"update_subtitle_languages\">सबटाइटलों की भाषाएँ अपडेट करें?</string>\n    <string name=\"export_backup\">निर्यात करें</string>\n    <string name=\"import_download_history_msg\">डाउनलोड की गई फ़ाइलें आयात नहीं की जाएंगी। आपको उन्हें मैन्युअल रूप से वापस डाउनलोड करना होगा</string>\n    <string name=\"interface_and_interaction\"><![CDATA[इंटरफ़ेस और इंटरैक्शन]]></string>\n    <string name=\"import_backup\">आयात करें</string>\n    <string name=\"full_backup\">पूर्ण बैकअप</string>\n    <string name=\"backup_type\">बैकअप की किसम</string>\n    <string name=\"export_to\">इस जगह निर्यात करें</string>\n    <string name=\"file\">फाईल</string>\n    <string name=\"clipboard\">क्लिपबोर्ड</string>\n    <string name=\"import_from\">से आयात करें</string>\n    <string name=\"export_download_history\">डाउनलोड इतिहास निर्यात करें?</string>\n    <string name=\"import_download_history\">डाउनलोड इतिहास आयात करें?</string>\n    <string name=\"export_download_history_msg\">डाउनलोड इतिहास से %1$s निर्यात किया जा रहा है। डाउनलोड की गई फ़ाइलों और प्राथमिकताओं का बैकअप नहीं लिया जाएगा।</string>\n    <string name=\"download_history\">डाउनलोड इतिहास</string>\n    <string name=\"redownload\">दोबारा डाउनलोड करें</string>\n    <string name=\"download_archive_error\">वीडियो डाउनलोड कर लिया गया है. यदि यह अपेक्षित व्यवहार नहीं है, तो कृपया अपने डाउनलोड संग्रह में से जांचें।</string>\n    <string name=\"download_history_imported\">डाउनलोड इतिहास के लिए %1$s आयात किया गया</string>\n    <string name=\"remux_container_mkv\">रीमक्स वीडियो कंटेनर</string>\n    <string name=\"remux_container_mkv_desc\">बेहतर अनुकूलता के लिए वीडियो को एमकेवी कंटेनर में रीमक्स करें</string>\n    <string name=\"cookies_in_database\">कुल मिलाकर %2$d वेबसाइटों से %1$d कुकीज़</string>\n    <string name=\"every_day\">हर दिन</string>\n    <string name=\"every_week\">हर हफ्ते</string>\n    <string name=\"every_month\">हर महीने</string>\n    <string name=\"all_languages\">सभी भाषाएँ</string>\n    <string name=\"playlist\">प्लेलिस्ट</string>\n    <string name=\"preset\">प्रीसेट</string>\n    <string name=\"prefer_placeholder\">%1$s को प्राथमिकता दें</string>\n    <string name=\"edit_preset\">प्रीसेट संपादित करें</string>\n    <string name=\"best_quality_desc\">सर्वोत्तम उपलब्ध फार्मेट डाउनलोड करें</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d वीडियो</item>\n        <item quantity=\"other\">%d वीडियो</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d ऑडियो</item>\n        <item quantity=\"other\">%d ऑडियो</item>\n    </plurals>\n    <string name=\"task_added\">कार्य को कतार में जोड़ा गया</string>\n    <string name=\"proceed\">जारी रखें</string>\n    <string name=\"custom_format_selection_desc\">प्रारूपों, उपशीर्षकों में से चुनें और आगे अनुकूलित करें</string>\n    <string name=\"preset_format_selection_desc\">अपनी फार्मेट प्राथमिकताओं का उपयोग करके स्वचालित रूप से डाउनलोड करें</string>\n    <string name=\"download_queue\">डाउनलोड कतार</string>\n    <string name=\"status_downloaded\">डाउनलोड किया गया</string>\n    <string name=\"download_hint\">डाउनलोड बटन पर टैप करें या डाउनलोड शुरू करने के लिए इस ऐप को वीडियो लिंक शेयर करें</string>\n    <string name=\"all\">सभी</string>\n    <string name=\"select_multiple_link\">%1$d लिंक्स में से चयन करें</string>\n    <string name=\"you_ll_find_your_downloads_here\">आपको अपने डाउनलोड यहां मिलेंगे</string>\n    <string name=\"show_navigation_drawer\">नेविगेशन ड्रॉअर दिखाएँ</string>\n    <string name=\"delete\">हटाएं</string>\n    <string name=\"resume\">फिर से शुरू करें</string>\n    <string name=\"media_info\">मीडिया जानकारी</string>\n    <string name=\"trouble_shooting_desc\">सामान्य त्रुटियों को ठीक करें और ज्ञात समस्याओं की जाँच करें</string>\n    <string name=\"issue_tracker_hint\">क्या आपको कोई त्रुटि मिली है? नई समस्या की रिपोर्ट करने से पहले, कृपया हमारे समस्या ट्रैकर को खोजें। कई सामान्य समस्याओं को पहले ही संबोधित किया जा चुका है और उनका दस्तावेज़ीकरण किया जा चुका है।</string>\n    <string name=\"trouble_shooting\">समस्या निवारण</string>\n    <string name=\"issue_tracker\">समस्या ट्रैकर</string>\n    <string name=\"saved_urls\">सहेजे गए लिंक</string>\n    <string name=\"add_new_url\">नया लिंक शामिल करें</string>\n    <string name=\"add_to\">%1$s में शामिल करें</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-hr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"settings\">Postavke</string>\n    <string name=\"download_settings_desc\">Opće, format, prilagođena naredba</string>\n    <string name=\"download\">Preuzmi</string>\n    <string name=\"url_empty\">Poveznica ne može biti prazna</string>\n    <string name=\"yt_dlp_up_to_date\">Koristite najnoviju inačicu yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Nije moguće instalirati najnoviju inačicu yt-dlp. Provjerite jeste li povezani s internetskom vezom.</string>\n    <string name=\"fetching_info\">Dobavljam informacije o videu…</string>\n    <string name=\"permission_denied\">Dopuštenje odbijeno</string>\n    <string name=\"video_directory\">Mapa videozapisa</string>\n    <string name=\"create_thumbnail_summary\">Spremite minijaturu videozapisa kao datoteku</string>\n    <string name=\"extract_audio\">Spremi kao zvučni zapis</string>\n    <string name=\"create_thumbnail\">Spremi minijaturu</string>\n    <string name=\"download_success_msg\">Preuzimanje završeno</string>\n    <string name=\"extract_audio_summary\">Preuzmite i spremite zvučni zapis, umjesto videozapisa</string>\n    <string name=\"download_error_msg\">Datoteku nije bilo moguće preuzeti</string>\n    <string name=\"download_start_msg\">Preuzimanje „%1$s“</string>\n    <string name=\"language\">Jezik</string>\n    <string name=\"task_running\">Postojeće preuzimanje je već pokrenuto</string>\n    <string name=\"paste_msg\">Zalijepljen URL iz međuspremnika</string>\n    <string name=\"ytdlp_update\">Kliknite kako biste preuzeli najnoviju inačicu yt-dlp</string>\n    <string name=\"delete_info\">Ukloniti\\?</string>\n    <string name=\"delete_info_msg\">Zauvijek ukloniti „%1$s“ iz povijesti preuzimanja?</string>\n    <string name=\"confirm\">Potvrdi</string>\n    <string name=\"dismiss\">Odustani</string>\n    <string name=\"downloads_history\">Preuzimanja</string>\n    <string name=\"delete_file\">Izbriši datoteku</string>\n    <string name=\"about\">O aplikaciji</string>\n    <string name=\"about_page\">Inačica, povratne informacije, automatsko ažuriranje</string>\n    <string name=\"back\">Natrag</string>\n    <string name=\"version\">Inačica</string>\n    <string name=\"release_desc\">Potražite bilježnike promjena i nove inačice</string>\n    <string name=\"release\">Najnovija inačica</string>\n    <string name=\"readme_desc\">Pregledajte GitHub repozitorij i README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"custom_command\">Prilagođena naredba</string>\n    <string name=\"custom_command_desc\">Pokrenite yt-dlp naredbu pomoću prilagođenog predloška</string>\n    <string name=\"custom_command_template\">Naredbeni predložak</string>\n    <string name=\"start_execute\">Započelo je izvršavanje naredbe</string>\n    <string name=\"advanced_settings\">Napredno</string>\n    <string name=\"print_details\">Detaljan izlaz informacija</string>\n    <string name=\"print_details_desc\">Prikažite detaljne informacije prilikom preuzimanja</string>\n    <string name=\"display\">Prikaz</string>\n    <string name=\"display_settings\">Tamna tema, dinamička boja, jezici</string>\n    <string name=\"follow_system\">Prati sistem</string>\n    <string name=\"on\">Omogućeno</string>\n    <string name=\"off\">Onemogućeno</string>\n    <string name=\"cancel\">Odustani</string>\n    <string name=\"settings_before_download_desc\">Konfigurirajte preference prije preuzimanja</string>\n    <string name=\"error_copied\">Izvješće o pogrešci kopirano u međuspremnik</string>\n    <string name=\"yt_dlp_docs\">Reference korištenja yt-dlp</string>\n    <string name=\"not_convert\">Nepretvoreno</string>\n    <string name=\"convert_audio_format_desc\">Ponovno kodiranje datoteka zvučnih zapisa će prouzročiti gubitak kvalitete zvuka i povećati veličinu datoteke.</string>\n    <string name=\"best_quality\">Najbolja kvaliteta</string>\n    <string name=\"video_format_preference\">Preferirani format videozapisa</string>\n    <string name=\"start_download\">Preuzmi</string>\n    <string name=\"convert_audio\">Pretvori</string>\n    <string name=\"close\">Zatvori</string>\n    <string name=\"close_never_show_again\">Ne prikazuj više</string>\n    <string name=\"paste_desc\">Kliknite „Zalijepi“ kako biste zalijepili poveznicu na videozapis iz međuspremnika.</string>\n    <string name=\"download_desc\">Tada kliknite „Preuzmi“ nakon prilagodbe postavki.</string>\n    <string name=\"check_download_settings_desc\">Pregledajte postavke preuzimanja i provjerite da li koristite najnoviju inačicu yt-dlp prije nego što počnete koristiti aplikaciju.</string>\n    <string name=\"channel_name\">Preuzimanje</string>\n    <string name=\"channel_description\">Obavijesti me o preuzetim datotekama i preuzimanjima u tijeku</string>\n    <string name=\"video_url\">Poveznica na videozapis</string>\n    <string name=\"download_finish_notification\">Preuzimanje završeno. Dodirnite kako biste otvorili.</string>\n    <string name=\"execute_command_notification\">Pokretanje prilagođene naredbe…</string>\n    <string name=\"battery_settings_desc\">Postavite potrošnju baterije ove aplikacije na „Neograničeno“ u postavkama sustava za preuzimanje u pozadini.</string>\n    <string name=\"concurrent_download\">Višenitno preuzimanje</string>\n    <string name=\"concurrent_download_num\">%d nit(i) bi bilo korišteno kako bi se istovremeno preuzeli DASH/HLS videozapisi.</string>\n    <string name=\"options\">Opcije</string>\n    <string name=\"additional_settings\">Dodatne postavke</string>\n    <string name=\"share_fail_msg\">Nije moguće podudaranje URL iz dijeljenog sadržaja</string>\n    <string name=\"share_success_msg\">Čitanje poveznice na videozapis iz dijeljenog sadržaja…</string>\n    <string name=\"show_more_actions\">Prikaži više radnji</string>\n    <string name=\"download_notification\">Obavijest o preuzimanju</string>\n    <string name=\"download_notification_desc\">Obavijesti me o preuzetim datotekama i preuzimanjima u tijeku</string>\n    <string name=\"fetching_playlist_info\">Dohvaćanje informacija o popisu za reprodukciju…</string>\n    <string name=\"download_range_selection\">Odabir popisa za reprodukciju</string>\n    <string name=\"download_range_desc\">Odredite koje videozapise želite preuzeti s popisa za reprodukciju „%3$s“ (od %1$d do %2$d).</string>\n    <string name=\"from\">Početak</string>\n    <string name=\"audio_directory\">Mapa zvučnih zapisa</string>\n    <string name=\"download_directory_desc\">Odaberite gdje će se spremati datoteke videozapisa i zvučnih zapisa</string>\n    <string name=\"subdirectory\">Spremi u poddirektorij</string>\n    <string name=\"subdirectory_desc\">Spremite datoteke u mape s nazivima odgovarajućih polja</string>\n    <string name=\"permission_issue\">Problem s dozvolom pristupa pohrani</string>\n    <string name=\"permission_issue_desc\">Direktoriji izvan Preuzimanja/ i Dokumenti/ nisu podržani</string>\n    <string name=\"battery_configuration\">Konfiguracija baterije</string>\n    <string name=\"battery_configuration_desc\">Ignorirajte optimizaciju baterije kako bi aplikacija mogla preuzimati u pozadini</string>\n    <string name=\"service_title\">Seal preuzima…</string>\n    <string name=\"unknown_error\">Nepoznata greška</string>\n    <string name=\"translate_desc\">Pomognite prevesti ovu aplikaciju pomoću Hosted Weblate</string>\n    <string name=\"prefix\">Predložak puta</string>\n    <string name=\"embed_subtitles_desc\">Ugradi titlove u videa, ako su dostupni</string>\n    <string name=\"new_template\">Novi predložak</string>\n    <string name=\"template_label\">Oznaka</string>\n    <string name=\"remove_template_desc\">Zauvijek ukloniti „%1$s“ iz naredbenih predložaka?</string>\n    <string name=\"template_selection\">Odabir predložaka</string>\n    <string name=\"github_issue\">GitHub prijava problema</string>\n    <string name=\"github_issue_desc\">Prijavite nam greške u aplikaciji i predložite slijedeću novu značajku</string>\n    <string name=\"info_copied\">Informacije kopirane u međuspremnik</string>\n    <string name=\"status_canceled\">Otkazano</string>\n    <string name=\"restart\">Ponovno pokreni</string>\n    <string name=\"status_error\">Greška</string>\n    <string name=\"copy_link\">Kopiraj poveznicu</string>\n    <string name=\"copy_error_report\">Kopiraj izvještaj</string>\n    <string name=\"export_to_clipboard\">Izvezi u međuspremnik</string>\n    <string name=\"import_from_clipboard\">Uvezi iz međuspremnika</string>\n    <string name=\"recently_added\">Nedavno Dodano</string>\n    <string name=\"multiselect_item_count\">%1$d videozapis(a), %2$d zvučni(h) zapis(a)</string>\n    <string name=\"sponsorblock_categories_desc\">Odredite koje će SponsorBlock kategorije biti uklonjene ili označene u video datoteci</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock kategorije</string>\n    <string name=\"check_for_updates\">Potraži ažuriranja</string>\n    <string name=\"check_for_updates_desc\">Automatski potraži najnovija ažuriranja na GitHub-u</string>\n    <string name=\"aria2_desc\">Koristite aria2c kao vanjski program za preuzimanje</string>\n    <string name=\"cookies_desc\">Za preuzimanja koristite kolačiće formatirane pomoću Netscape-a</string>\n    <string name=\"clear_temp_files\">Čišćenje privremenih datoteka</string>\n    <string name=\"clear_temp_files_desc\">Očistite sve privremene datoteke iz privremenog direktorija</string>\n    <string name=\"clear_temp_files_count\">%1$d privremena(ih) datoteka izbrisana(o)</string>\n    <string name=\"clear_temp_files_info\">Privremene datoteke služe kako bi se nastavila otkazana preuzimanja. Jeste li sigurni da ih želite sve izbrisati\\?\n\\n\n\\nOvim datotekama možete pristupiti u %1$s</string>\n    <string name=\"multiselect_mode\">Način višestrukog odabira</string>\n    <string name=\"private_mode\">Inkognito</string>\n    <string name=\"private_mode_desc\">Onemogućite povijest preuzimanja</string>\n    <string name=\"dynamic_color\">Dinamička boja</string>\n    <string name=\"dynamic_color_desc\">Primijenite boje s pozadina na temu aplikacije</string>\n    <string name=\"language_settings\">Odaberi jezik</string>\n    <string name=\"general_settings\">Općenito</string>\n    <string name=\"fetch_info_error_msg\">Neuspjelo dohvaćanje informacija o videu</string>\n    <string name=\"audio\">Zvučni zapis</string>\n    <string name=\"paste_fail_msg\">Greška prilikom lijepljenja URL iz međuspremnika</string>\n    <string name=\"ytdlp_version\">Yt-dlp inačica</string>\n    <string name=\"link_copied\">Poveznica kopirana u međuspremnik</string>\n    <string name=\"open_url\">Otvori poveznicu</string>\n    <string name=\"remove\">Ukloni</string>\n    <string name=\"settings_before_download_text\">Prilagodite ovo preuzimanje</string>\n    <string name=\"dark_theme\">Tamna tema</string>\n    <string name=\"credits\">Zasluge</string>\n    <string name=\"settings_before_download\">Konfiguracija prije preuzimanja</string>\n    <string name=\"checked\">Provjereno</string>\n    <string name=\"credits_desc\">Zasluge i slobodni softver</string>\n    <string name=\"edit\">Uredi</string>\n    <string name=\"paste\">Zalijepi</string>\n    <string name=\"convert_audio_format\">Konvertiraj format audio snimke</string>\n    <string name=\"convert_to\">Pretvori u %1$s</string>\n    <string name=\"thumbnail\">Minijatura</string>\n    <string name=\"edit_template_desc\">Izlazni put i URL će dodati aplikacija.</string>\n    <string name=\"format\">Format</string>\n    <string name=\"video_quality\">Kvaliteta videozapisa</string>\n    <string name=\"video_quality_desc\">Ograničite kvalitetu videozapisa, kada je dostupno više kvaliteta</string>\n    <string name=\"not_specified\">Neodređeno (zadano)</string>\n    <string name=\"preferred_format_desc\">Preferirani format kada ih je više ponuđeno</string>\n    <string name=\"download_playlist\">Preuzmi popis za reprodukciju</string>\n    <string name=\"video_format\">Format videozapisa</string>\n    <string name=\"user_guide\">Korisnički vodič</string>\n    <string name=\"open_settings\">Otvori postavke</string>\n    <string name=\"download_history_desc\">Pregledajte i upravljajte preuzimanjima, uključujući datoteke videozapisa i zvučnih zapisa.</string>\n    <string name=\"defaults\">Zadano</string>\n    <string name=\"download_playlist_desc\">Preuzmite više videozapisa s popisa za reprodukciju</string>\n    <string name=\"concurrent_download_desc\">Paralelno preuzmite više dijelova M3U8/MPD videozapisa</string>\n    <string name=\"to\">Kraj</string>\n    <string name=\"invalid_index_range\">Neispravan domet indeksa</string>\n    <string name=\"playlist_indicator_text\">Preuzimanje popisa za reprodukciju (%1$d/%2$d)…</string>\n    <string name=\"download_directory\">Direktorij preuzimanja</string>\n    <string name=\"open_file\">Otvori datoteku</string>\n    <string name=\"translate\">Prevedi</string>\n    <string name=\"custom_command_template_desc\">Uredite i upravljajte naredbenim predlošcima</string>\n    <string name=\"downloading_indicator_text\">Preuzimanje u tijeku…</string>\n    <string name=\"status_completed\">Završeno</string>\n    <string name=\"embed_subtitles\">Ugradi titlove</string>\n    <string name=\"remove_template\">Ukloniti\\?</string>\n    <string name=\"task_canceled\">Preuzimanje otkazano</string>\n    <string name=\"status_downloading\">Preuzimanje</string>\n    <string name=\"status_enqueued\">Dodano u red čekanja</string>\n    <string name=\"status_fetching_video_info\">Dobavljanje informacija</string>\n    <string name=\"video_resolution\">Rezolucija videozapisa</string>\n    <string name=\"template_exported\">Izvezen(o) %1$d predložak(a)</string>\n    <string name=\"template_imported\">Uvezen(o) %1$d predložak(a)</string>\n    <string name=\"sponsorblock_desc\">Uklonite ili označite dijelove iz videozapisa pomoću SponsorBlock API</string>\n    <string name=\"video_file_size\">Veličina video datoteke</string>\n    <string name=\"download_task_count\">%1$d zadataka preuzimanja</string>\n    <string name=\"delete_multiple_items_msg\">Zauvijek ukloniti %1$d predmet(a) iz povijesti preuzimanja\\?</string>\n    <string name=\"app_update_failed\">Ažuriranje na najnoviju inačicu nije uspjelo</string>\n    <string name=\"update\">Ažuriraj</string>\n    <string name=\"app_up_to_date\">Trenutna inačica je ažurna</string>\n    <string name=\"invalid_input\">Neispravan unos</string>\n    <string name=\"disable_preview_desc\">Nema prikaza minijature tijekom preuzimanja</string>\n    <string name=\"privacy\">Privatnost</string>\n    <string name=\"use_custom_command\">Koristi prilagođenu naredbu</string>\n    <string name=\"disable_preview\">Onemogući pregled</string>\n    <string name=\"private_directory\">Privatan direktorij</string>\n    <string name=\"private_directory_desc\">Pohranite preuzimanja u skrivenom direktoriju</string>\n    <string name=\"show_logs\">Prikaži bilježnik</string>\n    <string name=\"logs\">Bilježnik</string>\n    <string name=\"download_with_cellular\">Preuzmi koristeći mobilne podatke</string>\n    <string name=\"network\">Mreža</string>\n    <string name=\"lowest_quality\">Najniža kvaliteta</string>\n    <string name=\"network_settings_desc\">Ograničenje brzine, program za preuzimanje, kolačići</string>\n    <string name=\"crop_artwork\">Izreži ilustraciju</string>\n    <string name=\"download_selection_desc\">Odaberite videozapise koje želite preuzeti s popisa za reprodukciju „%1$s“</string>\n    <string name=\"video_only\">Video (bez zvuka)</string>\n    <string name=\"generate_new_cookies\">Generiraj nove kolačiće</string>\n    <string name=\"remove_cookie_profile_desc\">Ukloniti kolačiće za „%1$s“? Spremljeni kolačići za ovu stranicu se neće izbrisati.</string>\n    <string name=\"custom_command_enabled_hint\">Neke opcije neće biti dostupne prilikom korištenja prilagođenih naredbi</string>\n    <string name=\"format_selection_desc\">Odaberite format preuzimanja prije preuzimanja</string>\n    <string name=\"how_does_it_work\">Kako to funkcionira\\?</string>\n    <string name=\"sdcard_directory\">Mapa SD kartice</string>\n    <string name=\"auto_subtitle\">Automatski titlovi</string>\n    <string name=\"title_activity_share\">Brzo preuzimanje</string>\n    <string name=\"auto_subtitle_desc\">Preuzmi automatski generirane titlove</string>\n    <string name=\"video_creator_sample_text\">Primjer teksta videostvarača</string>\n    <string name=\"edit_shortcuts\">Uredi prečace</string>\n    <string name=\"clear\">Očisti</string>\n    <string name=\"add\">Dodaj</string>\n    <string name=\"selected_item_count\">Odabrano: %1$d</string>\n    <string name=\"suggested\">Predloženo</string>\n    <string name=\"cookies_usage_msg\">Preuzimanje s nekih internetskih stranica zahtijeva informacije o potvrdi korisničkog računa. Kliknite „Generiraj nove kolačiće“, unesite URL stranice te se prijavite sa svojim korisničkim računom. Aplikacija će ih generirati za vas.</string>\n    <string name=\"telegram_channel\">Telegram kanal</string>\n    <string name=\"video_title_sample_text\">Primjer teksta naslova videozapisa</string>\n    <string name=\"subtitle\">Titlovi</string>\n    <string name=\"download_subtitles\">Preuzmi titlove</string>\n    <string name=\"subtitle_desc\">Jezici, ugrađeni titlovi, automatski titlovi</string>\n    <string name=\"copy_log\">Kopiraj bilježnik</string>\n    <string name=\"embed_subtitles_mkv_msg\">Da bi se titlovi ugradili, videozapisi će se konvertirati u mkv kontejner. Možete koristiti VLC Media Player ili druge kompatibilne aplikacije za gledanje videozapisa s titlovima.</string>\n    <string name=\"subtitle_sponsorblock\">Titlovi mogu biti pogrešno tempirani nakon uklanjanja SponsorBlock segmenta.</string>\n    <string name=\"max_rate\">Maksimalna brzina</string>\n    <string name=\"high_contrast\">Tamna tema visokog kontrasta</string>\n    <string name=\"rate_limit_desc\">Ograničite maksimalnu brzinu preuzimanja</string>\n    <string name=\"format_selection\">Odabir formata</string>\n    <string name=\"use_cookies\">Koristi kolačiće</string>\n    <string name=\"cookies\">Kolačići</string>\n    <string name=\"download_disabled_with_cellular\">Preuzimanje putem mobilnih podataka je onemogućeno u postavkama</string>\n    <string name=\"file_unavailable\">Ova datoteka više nije dostupna</string>\n    <string name=\"format_settings_desc\">Datotečni format, kvaliteta videa, titlovi</string>\n    <string name=\"general_settings_desc\">Inačica Yt-dlp-a, obavijest, popis za reprodukciju</string>\n    <string name=\"unavailable\">Nedostupno</string>\n    <string name=\"crop_artwork_desc\">Izrežite ugrađenu sliku u kvadratni format</string>\n    <string name=\"rate_limit\">Ograničenje brzine</string>\n    <string name=\"abs_hint\">Većina platforma strujanja videozapisa dostavljaju odvojen zvučni zapis i videozapis. Možete odabrati i spojiti format koji sadrži samo zvučni zapis s formatom koji sadrži samo videozapis u jedan videozapis.</string>\n    <string name=\"matrix_space\">Matrix prostor</string>\n    <string name=\"select_all\">Odaberi sve</string>\n    <string name=\"subtitle_language\">Jezici titlova</string>\n    <string name=\"shortcuts\">Prečaci</string>\n    <string name=\"edit_shortcuts_desc\">Uredite prilagođene prečace koji se mogu koristiti kao sastavljači predložaka naredbi.</string>\n    <string name=\"running_tasks\">Radnje u tijeku</string>\n    <string name=\"download_with_cellular_desc\">Dopustite preuzimanje medija putem ograničenog interneta</string>\n    <string name=\"audio_quality\">Kvaliteta zvučnog zapisa</string>\n    <string name=\"no_downloaded_media\">Nema preuzetih medija</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"discard\">Odbaci</string>\n    <string name=\"apply\">Primjeni</string>\n    <string name=\"format_sorting_desc\">Sortiranje formata pomoću yt-dlp opcije -S</string>\n    <string name=\"import_from_preferences\">Uvezi</string>\n    <string name=\"title\">Naslov</string>\n    <string name=\"clip_video\">Izreži videozapis</string>\n    <string name=\"lowest_bitrate\">Najniži bitrate</string>\n    <string name=\"audio_quality_desc\">Ograničite bitrate zvučnog zapisa, kada je dostupno više kvaliteta</string>\n    <string name=\"format_sorting\">Sortiranje formata</string>\n    <string name=\"rename\">Preimenuj</string>\n    <string name=\"temporary_directory_desc\">Pohranite privremene datoteke u unutarnji direktorij</string>\n    <string name=\"second\">sekunda</string>\n    <string name=\"sponsor\">Sponzoriraj</string>\n    <string name=\"minute\">minuta</string>\n    <string name=\"clear_all_cookies\">Očisti sve kolačiće</string>\n    <string name=\"clip_video_dialog_msg\">Preuzimanja izvršena ovom značajkom bit će izaslani FFmpeg-u kako bi preuzeo odabrane dijelove videozapisa. Ova značajka je još u razvoju te je moguće da izrezivanje ne bude posve točno uz moguću sporiju brzinu preuzimanja.</string>\n    <string name=\"clip_video_desc\">Napravite isječke videozapisa na stranici za odabir formata</string>\n    <string name=\"switch_to_github_builds\">prebacivanje na GitHub inačice</string>\n    <string name=\"feature_unavailable\">Značajka nije dostupna</string>\n    <string name=\"no_custom_command_tasks\">Nema prilagođenih naredbenih radnji</string>\n    <string name=\"download_video_desc\">Preuzmite videozapise s URL-a</string>\n    <string name=\"convert_subtitle\">Pretvori titlove</string>\n    <string name=\"convert_subtitle_desc\">Pretvorite titlove u jedan drugi format</string>\n    <string name=\"split_video\">Razdvoji videozapis</string>\n    <string name=\"split_video_msg\">Videozapis će biti podijeljen u %1$d poglavlja</string>\n    <string name=\"unknown_error_title\">Ups! Nešto nije u redu</string>\n    <string name=\"copy_and_exit\">Kopiraj i izađi</string>\n    <string name=\"share\">Dijeli</string>\n    <string name=\"pre_release_channel\">Beta</string>\n    <string name=\"stable_channel\">Stabilan</string>\n    <string name=\"update_channel_desc\">Instalirajte beta inačice aplikacije kako biste pregledali nove značajke i promjene.\n\\n\n\\nMoguća je nestabilnost ovih inačica, molimo ne ustručavajte se dati nam povratne informacije u slučaju problema s aplikacijom. One će nam pomoći poboljšati buduće inačice aplikacije.</string>\n    <string name=\"auto_update\">Automatsko ažuriranje</string>\n    <string name=\"enable_auto_update\">Omogući automatsko ažuriranje</string>\n    <string name=\"unlimited\">Neograničeno</string>\n    <string name=\"audio_format_preference\">Preferirani format zvuka</string>\n    <string name=\"sponsor_desc\">Podržite razvoj ove aplikacije njenim sponzoriranjem na GitHub-u</string>\n    <string name=\"sponsor_msg\">Seal će uvijek biti besplatan i otvorenog koda za sve. Ako vam se sviđa, razmislite o tome da me sponzorirate na GitHub-u!</string>\n    <string name=\"audio_format\">Audio format</string>\n    <string name=\"enable_experimental_feature\">Omogućiti eksperimentalne značajke\\?</string>\n    <string name=\"auto_update_disabled_msg\">Automatsko ažuriranje nije dostupno za %1$s inačice. Ako nemate %1$s instaliran na svom uređaju ili želite pregledati nadolazeće nove značajke u Seal-u, razmislite o %2$s.</string>\n    <string name=\"okay\">U redu</string>\n    <string name=\"got_it\">Razumijem</string>\n    <string name=\"msg_from_developer\">Obavijest od razvojnog programera</string>\n    <string name=\"sponsor_msg2\">Hvala vam puno!</string>\n    <string name=\"expand\">Proširi</string>\n    <string name=\"new_task\">Novi zadatak preuzimanja</string>\n    <string name=\"start\">Pokreni</string>\n    <string name=\"edit_template\">Uredi „%1$s“</string>\n    <string name=\"clip_start\">Početak</string>\n    <string name=\"clip_end\">Kraj</string>\n    <string name=\"update_channel\">Kanal ažuriranja</string>\n    <string name=\"clear_all_cookies_desc\">Zauvijek izbrisati sve kolačiće pohranjene u aplikaciji\\?</string>\n    <string name=\"sponsors\">Sponzori</string>\n    <string name=\"feedback\">Povratne informacije</string>\n    <string name=\"ytdlp_update_action\">Ažuriraj yt-dlp</string>\n    <string name=\"disable\">Onemogući</string>\n    <string name=\"set_directory_desc\">Dodirnite za postavljanje direktorija</string>\n    <string name=\"custom_command_directory\">Direktorij prilagođenih naredbi</string>\n    <string name=\"disabled\">Onemogućeno</string>\n    <string name=\"folder_picker\">Birač mapa</string>\n    <string name=\"custom_command_directory_desc\">Navedite izlazni direktorij kada koristite prilagođene naredbe</string>\n    <string name=\"format_preference\">Postavke formata</string>\n    <string name=\"proxy_desc\">Koristite proksi za internetske veze</string>\n    <string name=\"legacy\">Zastario</string>\n    <string name=\"quality\">Kvaliteta</string>\n    <string name=\"enable_notifications\">Omogućiti obavijesti\\?</string>\n    <string name=\"enable_notifications_desc\">Aplikacija treba vaše dopuštenje za objavljivanje obavijesti o statusu i napretku preuzimanja.</string>\n    <string name=\"proxy\">Proksi</string>\n    <string name=\"download_type\">Vrsta preuzimanja</string>\n    <string name=\"custom\">Prilagođen</string>\n    <string name=\"auto\">Automatski</string>\n    <string name=\"commands\">Naredbe</string>\n    <string name=\"learn_more\">Saznaj više</string>\n    <string name=\"unknown\">Nepoznato</string>\n    <string name=\"prefer_compatibility_desc\">Preferiranje MP4(H.264) formata za dijeljenje s drugim aplikacijama</string>\n    <string name=\"prefer_quality_desc\">Preferiranje AV1, VP9 ili H.265 formata za gledanje u kompatibilnim aplikacijama</string>\n    <string name=\"refresh_cookies_desc\">Dodirnite za otvaranje web stranice za generiranje novih kolačića:</string>\n    <string name=\"remove_multiple_templates_msg\">Zauvijek ukloniti %1$s iz naredbenih predložaka\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d predmet</item>\n        <item quantity=\"few\">%d predmeta</item>\n        <item quantity=\"other\">%d predmeta</item>\n    </plurals>\n    <string name=\"export_to_file\">Izvezi u datoteku</string>\n    <string name=\"ua_header\">Zaglavlje User-Agent</string>\n    <string name=\"custom_command_usage_msg\">Yt-dlp je moćan alat naredbene linije za preuzimanje videozapisa. Seal olakšava korištenje yt-dlp-a pružajući intuitivni GUI, unaprijed postavljene postavke za uobičajene naredbe i druge dodatne značajke.\n\\n\n\\nZa napredno korištenje yt-dlp-a, Seal vam omogućuje stvaranje, spremanje i izravno izvršavanje prilagođenih naredbenih predložaka, baš kao u terminalu.\n\\n\n\\nKada koristite prilagođene naredbe, većina GUI opcija i značajki bila bi onemogućena.</string>\n    <string name=\"presets\">Unaprijed postavljeno</string>\n    <string name=\"output_template\">Izlazni predložak</string>\n    <string name=\"output_template_desc\">Navedite predložak za nazive izlaznih datoteka</string>\n    <string name=\"clear_download_archive\">Očistiti arhivu preuzimanja\\?</string>\n    <string name=\"clear_download_archive_desc\">Zauvijek ukloniti %1$s iz arhivske datoteke\\?</string>\n    <string name=\"download_archive_desc\">Snimite ID-ove preuzetih videozapisa u arhivu kako biste izbjegli dvostruka preuzimanja</string>\n    <string name=\"download_archive\">Arhiva preuzimanja</string>\n    <string name=\"embed_metadata\">Ugradi metapodatke</string>\n    <string name=\"embed_metadata_desc\">Ugradite metapodatke i minijaturu videozapisa u audio datoteku</string>\n    <string name=\"required\">Obavezno</string>\n    <string name=\"show_all_items\">Prikaži sve predmete: %1$d</string>\n    <string name=\"save\">Spremi</string>\n    <string name=\"use_format_sorting\">Koristi sortiranje formata</string>\n    <string name=\"edit_file\">Uredite datoteku</string>\n    <string name=\"restrict_filenames_desc\">Ograničite nazive datoteka na određene znakove kako biste osigurali kompatibilnost</string>\n    <string name=\"restrict_filenames\">Ograniči nazive datoteka</string>\n    <string name=\"website\">Web stranica</string>\n    <string name=\"playlist_title\">Naslov popisa za reprodukciju</string>\n    <string name=\"subdirectory_hint\">Vaša preuzimanja bit će spremljena kao:</string>\n    <string name=\"keep_subtitle_files\">Čuvaj datoteke titlova</string>\n    <string name=\"system_settings\">Postavke sustava</string>\n    <string name=\"force_ipv4\">Prisili IPv4</string>\n    <string name=\"force_ipv4_desc\">Uspostavi sve veze putem IPv4</string>\n    <string name=\"allow_once\">Dozvoli jednom</string>\n    <string name=\"dont_allow\">Nemoj dozvoliti</string>\n    <string name=\"allow_always\">Dozvoli uvijek</string>\n    <string name=\"merge_audiostream_desc\">Dozvoli sjedinjavanje audio strimova u jednu datoteku</string>\n    <string name=\"download_with_cellular_request\">Dozvoliti preuzimanje putem mobilnih podataka?</string>\n    <string name=\"merge_audiostream\">Sjedini audio strimove</string>\n    <string name=\"auto_translated_subtitles\">Automatski prevedeni titlovi</string>\n    <string name=\"auto_translated_subtitles_msg\">Automatski prevedeni titlovi za sve jezike će biti dostupni za preuzimanje. Ovi titlovi mogu biti netočni i teško razumljivi.</string>\n    <string name=\"look_and_feel\">Izgled i osjećaj</string>\n    <string name=\"use_previous_selection\">Koristi prethodni odabir</string>\n    <string name=\"none\">Ništa</string>\n    <string name=\"remember_for_next_download\">Zapamti za sljedeće preuzimanje</string>\n    <string name=\"subtitle_language_desc\">Jezik titlova za preuzimanje u odabiru automatskog formata, odvojen zarezima.</string>\n    <string name=\"reset\">Resetiraj</string>\n    <string name=\"search_in_subtitles\">Traži u titlovima</string>\n    <string name=\"no_thanks\">Ne hvala</string>\n    <string name=\"update_language_msg\">Sljedeći jezici će se dodati tvojim postavkama za buduća preuzimanja:</string>\n    <string name=\"update_subtitle_languages\">Aktualizirati jezike titlova?</string>\n    <string name=\"search\">Traži</string>\n    <string name=\"search_in_downloads\">Traži u preuzimanjima</string>\n    <string name=\"clipboard\">Međuspremnik</string>\n    <string name=\"import_from\">Uvezi iz</string>\n    <string name=\"export_download_history_msg\">Izvoz %1$s iz povijesti preuzimanja. Preuzete datoteke i postavke se neće sigurnosno kopirati.</string>\n    <string name=\"cookies_in_database\">Ukupno %1$d kolačića od %2$d web stranica</string>\n    <string name=\"interface_and_interaction\">Sučelje i interakcija</string>\n    <string name=\"export_backup\">Izvezi</string>\n    <string name=\"import_backup\">Uvezi</string>\n    <string name=\"full_backup\">Potpuna sigurnosna kopija</string>\n    <string name=\"backup_type\">Vrsta sigurnosne kopije</string>\n    <string name=\"export_to\">Izvezi u</string>\n    <string name=\"file\">Datoteka</string>\n    <string name=\"export_download_history\">Izvesti povijest preuzimanja?</string>\n    <string name=\"import_download_history\">Uvesti povijest preuzimanja?</string>\n    <string name=\"import_download_history_msg\">Preuzete datoteke se neće uvesti. Morat ćete ih ponovo preuzeti ručno</string>\n    <string name=\"download_history\">Povijest preuzimanja</string>\n    <string name=\"every_day\">Svaki dan</string>\n    <string name=\"every_week\">Svaki tjedan</string>\n    <string name=\"every_month\">Svaki mjesec</string>\n    <string name=\"download_history_imported\">%1$s uvezeno u povijest preuzimanja</string>\n    <string name=\"redownload\">Preuzmi ponovo</string>\n    <string name=\"download_archive_error\">Video je preuzet. Ako ovo nije očekivano ponašanje, provjeri svoju arhivu preuzimanja.</string>\n    <string name=\"all_languages\">Svi jezici</string>\n    <string name=\"playlist\">Popis za reprodukciju</string>\n    <string name=\"proceed\">Nastavi</string>\n    <string name=\"preset\">Postavka</string>\n    <string name=\"prefer_placeholder\">Preferiraj %1$s</string>\n    <string name=\"custom_format_selection_desc\">Biraj iz formata, titlova i dodatno ih prilagodi</string>\n    <string name=\"edit_preset\">Uredi postavku</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d video</item>\n        <item quantity=\"few\">%d videa</item>\n        <item quantity=\"other\">%d videa</item>\n    </plurals>\n    <string name=\"task_added\">Zadatak dodan u red</string>\n    <string name=\"remux_container_mkv\">Kontejner konvertiranog videa</string>\n    <string name=\"remux_container_mkv_desc\">Konvertiraj videa u MKV kontejner za bolju kompatibilnost</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d audio snimka</item>\n        <item quantity=\"few\">%d audio snimke</item>\n        <item quantity=\"other\">%d audio snimki</item>\n    </plurals>\n    <string name=\"preset_format_selection_desc\">Preuzmi automatski koristeći tvoje postavke formata</string>\n    <string name=\"best_quality_desc\">Preuzmi najbolji dostupni format</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-hu/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Video mappa</string>\n    <string name=\"create_thumbnail\">Ikon mentése</string>\n    <string name=\"settings\">Beállítások</string>\n    <string name=\"url_empty\">A link nem lehet üres</string>\n    <string name=\"extract_audio\">Mentés hangfájlként</string>\n    <string name=\"download_settings_desc\">Általános, formátum, egyéni parancs</string>\n    <string name=\"create_thumbnail_summary\">Video ikon elmentése fájlként</string>\n    <string name=\"yt_dlp_update_fail\">Nem sikerült telepíteni a legújabb yt-dlp-t. Kérlek bizonyosodj meg arról, hogy csatlakozva vagy az internethez.</string>\n    <string name=\"fetching_info\">Videó információinak lekérése…</string>\n    <string name=\"fetch_info_error_msg\">Nem sikerült lekérni a videó adatait</string>\n    <string name=\"language\">Megjelenítési nyelv</string>\n    <string name=\"language_settings\">Állítsa be a felhasználói nyelvet</string>\n    <string name=\"task_running\">Egy letöltési feladat már fut</string>\n    <string name=\"paste_msg\">URL másolása vágólapról</string>\n    <string name=\"ytdlp_update\">Kattints ide, hogy telepítsd a legújabb yt-dlp-t</string>\n    <string name=\"delete_info\">Eltávolítás\\?</string>\n    <string name=\"delete_info_msg\">Eltávolítod véglegesen a \\\"%1$s\\\" a letöltési listádból\\?</string>\n    <string name=\"paste_fail_msg\">A vágólapon lévő URL nem egyezik</string>\n    <string name=\"audio\">Hang</string>\n    <string name=\"link_copied\">A link vágólapra másolva</string>\n    <string name=\"open_url\">Link megnyitása</string>\n    <string name=\"about\">Névjegy</string>\n    <string name=\"about_page\">Verzió, visszajelzés, automatikus frissítés</string>\n    <string name=\"release\">Legújabb kiadása</string>\n    <string name=\"release_desc\">Keresd a változásnaplókat és az új verziókat</string>\n    <string name=\"readme_desc\">Keresd a GitHubon és olvasd a README-t</string>\n    <string name=\"video\">Videó</string>\n    <string name=\"checked\">Ellenőrizve</string>\n    <string name=\"credits\">Stáb</string>\n    <string name=\"credits_desc\">Stáb és libre szoftver</string>\n    <string name=\"custom_command\">Egyedi parancs</string>\n    <string name=\"custom_command_template\">Parancssablon</string>\n    <string name=\"start_execute\">Parancs futtatása</string>\n    <string name=\"display\">Kijelző</string>\n    <string name=\"display_settings\">Sötét téma, dinamikus színek, nyelvek</string>\n    <string name=\"follow_system\">Rendszer</string>\n    <string name=\"on\">Be</string>\n    <string name=\"print_details\">Részletezett kimenet</string>\n    <string name=\"off\">Ki</string>\n    <string name=\"settings_before_download\">Letöltés előtti konfiguráció</string>\n    <string name=\"settings_before_download_text\">Ezen letöltés beállítása</string>\n    <string name=\"thumbnail\">Ikon</string>\n    <string name=\"paste\">Beillesztés</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp használati hivatkozások</string>\n    <string name=\"edit_template_desc\">A kimeneti útvonalat és az URL-t az alkalmazás adja hozzá.</string>\n    <string name=\"convert_audio_format\">Hang formátum konvertálása</string>\n    <string name=\"cancel\">Mégsem</string>\n    <string name=\"format\">Formátum</string>\n    <string name=\"convert_audio_format_desc\">Az audió fájlok újrakódolása minőségbeli veszteséget és a fájlméret növekedését okozza.</string>\n    <string name=\"video_format_preference\">Előnyben részesített videó formátum</string>\n    <string name=\"preferred_format_desc\">Preferált formátum, ha több van megadva</string>\n    <string name=\"video_format\">Videó formátum</string>\n    <string name=\"convert_audio\">Konvertál</string>\n    <string name=\"start_download\">Letöltés</string>\n    <string name=\"open_settings\">Beállítások megnyitása</string>\n    <string name=\"paste_desc\">Kattintson a \\\"Beillesztés\\\" gombra, hogy a vágólapról beszúrd a videó linkjét.</string>\n    <string name=\"download_desc\">Ezután kattints a \\\"Letöltés\\\" gombra a beállítások módosítása után.</string>\n    <string name=\"check_download_settings_desc\">Vess egy pillantást a letöltési beállításokra, és győződjön meg arról, hogy az yt-dlp legfrissebb verziójával rendelkezel, mielőtt használnád.</string>\n    <string name=\"defaults\">Alapértelmezett</string>\n    <string name=\"download_finish_notification\">Letöltés befejeződött. Kattints a megnyitáshoz.</string>\n    <string name=\"execute_command_notification\">Egyéni parancsok futtatása…</string>\n    <string name=\"concurrent_download\">Többszálas letöltés</string>\n    <string name=\"concurrent_download_desc\">Töltsd le párhuzamosan több részét a M3U8/MPD videóknak</string>\n    <string name=\"options\">Beállítások</string>\n    <string name=\"additional_settings\">További beállítások</string>\n    <string name=\"share_fail_msg\">Az URL nem található a megosztott tartalomban</string>\n    <string name=\"download_notification_desc\">Értesítés a letöltött fájlokról és azok folyamatáról</string>\n    <string name=\"from\">Indítás</string>\n    <string name=\"to\">Vége</string>\n    <string name=\"invalid_index_range\">Érvénytelen indextartomány</string>\n    <string name=\"download_directory\">Letöltés mappa</string>\n    <string name=\"audio_directory\">Hangfájlok mappa</string>\n    <string name=\"permission_issue_desc\">A letöltések/ és a dokumentumok/ könyvtáron kívüli könyvtárak nem támogatottak</string>\n    <string name=\"unknown_error\">Ismeretlen hiba</string>\n    <string name=\"translate\">Fordítás</string>\n    <string name=\"translate_desc\">Segits fordítani ezt az appot a Hosted Weblate-n</string>\n    <string name=\"prefix\">Elérési út sablon</string>\n    <string name=\"download\">Letöltés</string>\n    <string name=\"download_start_msg\">Letöltés \\\"%1$s\\\"</string>\n    <string name=\"download_success_msg\">Letöltés kész</string>\n    <string name=\"permission_denied\">Hozzáférés megtagadva</string>\n    <string name=\"yt_dlp_up_to_date\">A legújabb yt-dlp használva</string>\n    <string name=\"general_settings\">Általános</string>\n    <string name=\"remove\">Eltávolítás</string>\n    <string name=\"ytdlp_version\">Yt-dlp verzió</string>\n    <string name=\"downloads_history\">Letöltések</string>\n    <string name=\"confirm\">Megerősít</string>\n    <string name=\"edit\">Szerkesztés</string>\n    <string name=\"dismiss\">Mégsem</string>\n    <string name=\"delete_file\">Fájl törlése</string>\n    <string name=\"video_url\">Videó link</string>\n    <string name=\"back\">Vissza</string>\n    <string name=\"version\">Verzió</string>\n    <string name=\"custom_command_desc\">Futtassa a yt-dlp parancsot egyéni sablonnal</string>\n    <string name=\"advanced_settings\">Haladó</string>\n    <string name=\"dark_theme\">Sötét téma</string>\n    <string name=\"settings_before_download_desc\">A letöltés előtt konfigurálja a beállításokat</string>\n    <string name=\"video_quality\">Videó minősége</string>\n    <string name=\"error_copied\">A hibajelentés a vágólapra másolva</string>\n    <string name=\"not_convert\">Nem konvertált</string>\n    <string name=\"convert_to\">Konvertálja ebbe %1$s</string>\n    <string name=\"video_quality_desc\">Korlátozza a videók minőségét, ha több is jelen van</string>\n    <string name=\"not_specified\">Nincs megadva (alapértelmezett)</string>\n    <string name=\"download_history_desc\">Kezeld az alkalmazáson belüli letöltéseket, beleértve a videókat és hangfájlokat.</string>\n    <string name=\"best_quality\">Legjobb minőség</string>\n    <string name=\"close\">Bezár</string>\n    <string name=\"close_never_show_again\">Ne jelenjen meg újra</string>\n    <string name=\"user_guide\">Felhasználói útmutató</string>\n    <string name=\"download_playlist\">Lejátszásilista letöltése</string>\n    <string name=\"download_playlist_desc\">Több videó letöltése egy lejátszási-listáról</string>\n    <string name=\"channel_name\">Letöltés</string>\n    <string name=\"extract_audio_summary\">Letöltés hangfájlként, videó helyett</string>\n    <string name=\"print_details_desc\">Részletes üzenetek megjelenítése letöltés közben</string>\n    <string name=\"battery_settings_desc\">Kérlek állítsd át az akkumulátor korlátozásokat ezen az applikáción \\\"korlátlanra\\\" a rendszerbeállításokban.</string>\n    <string name=\"concurrent_download_num\">%d szálat/kat használnának fel a DASH/HLS natív videó egyidejű letöltésére.</string>\n    <string name=\"fetching_playlist_info\">Lejátszási lista információinak lekérése…</string>\n    <string name=\"download_range_selection\">Lejátszási lista kiválasztása</string>\n    <string name=\"download_range_desc\">Adja meg a „%3$s” lejátszási listáról letöltendő videók tartományát (%1$d és %2$d között).</string>\n    <string name=\"subdirectory_desc\">Fájlok mentése az annak megfelelően elnevezett mappákba</string>\n    <string name=\"download_notification\">Letöltési értesítés</string>\n    <string name=\"playlist_indicator_text\">Lejátszási lista letöltése (%1$d/%2$d)…</string>\n    <string name=\"download_directory_desc\">Válassza ki a videók és hangfájlok tárolási helyét</string>\n    <string name=\"subdirectory\">Mentés alkönyvtárba</string>\n    <string name=\"permission_issue\">Adattár engedéllyel kapcsolatos probléma</string>\n    <string name=\"share_success_msg\">Videó link olvasása megosztott tartalomból…</string>\n    <string name=\"show_more_actions\">További műveletek megjelenítése</string>\n    <string name=\"battery_configuration_desc\">A háttérben történő letöltéshez kapcsold ki az alkalmazás akkumulátor-optimalizálását</string>\n    <string name=\"service_title\">Seal letöltése folyamatban van…</string>\n    <string name=\"download_error_msg\">A fájlt nem sikerült letölteni</string>\n    <string name=\"channel_description\">Értesítés a letöltött fájlokról és annak a folyamatról</string>\n    <string name=\"battery_configuration\">Akkumulátor beállítások</string>\n    <string name=\"open_file\">Fájl megnyitása</string>\n    <string name=\"restart\">Újraindítás</string>\n    <string name=\"status_enqueued\">Sorba állva</string>\n    <string name=\"status_completed\">Befejezve</string>\n    <string name=\"status_canceled\">Meghiúsult</string>\n    <string name=\"status_error\">Hiba</string>\n    <string name=\"copy_link\">Link másolása</string>\n    <string name=\"copy_error_report\">Hibajelentés másolása</string>\n    <string name=\"video_resolution\">Videó felbontás</string>\n    <string name=\"video_file_size\">Videó fájl mérete</string>\n    <string name=\"status_downloading\">Letöltés</string>\n    <string name=\"status_fetching_video_info\">Információk lekérése</string>\n    <string name=\"embed_subtitles\">Feliratok beágyazása</string>\n    <string name=\"embed_subtitles_desc\">Feliratok beágyazása a videókba, ha elérhetőek</string>\n    <string name=\"new_template\">Új sablon</string>\n    <string name=\"template_label\">Címke</string>\n    <string name=\"remove_template\">Eltávolítja\\?</string>\n    <string name=\"remove_template_desc\">Végleg eltávolítja a „%1$s” elemet a parancssablonokból\\?</string>\n    <string name=\"template_selection\">Sablon kiválasztása</string>\n    <string name=\"custom_command_template_desc\">Parancssablonok szerkesztése és kezelése</string>\n    <string name=\"downloading_indicator_text\">Letöltés folyamatban…</string>\n    <string name=\"task_canceled\">Letöltési feladat megszakítva</string>\n    <string name=\"github_issue\">GitHub probléma</string>\n    <string name=\"github_issue_desc\">Hibajelentés vagy új funkció kérése</string>\n    <string name=\"info_copied\">Adatok a vágólapra másolva</string>\n    <string name=\"export_to_clipboard\">Exportálás a vágólapra</string>\n    <string name=\"import_from_clipboard\">Importálás vágólapról</string>\n    <string name=\"template_exported\">%1$d sablon lett exportálva</string>\n    <string name=\"template_imported\">%1$d sablon lett importálva</string>\n    <string name=\"download_task_count\">%1$d letöltési művelet</string>\n    <string name=\"app_update_failed\">Nem sikerült frissíteni a legújabb verzióra</string>\n    <string name=\"delete_multiple_items_msg\">El akar távolítani %1$d tételt a letöltési előzmények közül\\?</string>\n    <string name=\"sponsorblock_desc\">Szekciók eltávolítása vagy jelölése videókban a SponsorBlock API használatával</string>\n    <string name=\"sponsorblock_categories_desc\">A vidóból eltávolítandó Sponsorblock szekciók megadása vagy eltávolítása</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock kategóriák</string>\n    <string name=\"check_for_updates_desc\">Frissítések automatikus keresése GitHubon</string>\n    <string name=\"app_up_to_date\">A jelenlegi verzió a legfrissebb</string>\n    <string name=\"update\">Frissítés</string>\n    <string name=\"aria2_desc\">Aria2c használata külső letöltőként</string>\n    <string name=\"private_mode\">Privát</string>\n    <string name=\"private_mode_desc\">Letöltési előzmények letiltása</string>\n    <string name=\"dynamic_color\">Dinamikus szín</string>\n    <string name=\"dynamic_color_desc\">Az app témája követi a háttérképe színét</string>\n    <string name=\"download_with_cellular\">Letöltés mobil internettel</string>\n    <string name=\"download_with_cellular_desc\">Média letöltésének engedélyezése, akkor is, ha fizetős hálózaton van</string>\n    <string name=\"download_disabled_with_cellular\">A mobil internetes letöltés le van tiltva a beállításai szerint</string>\n    <string name=\"network\">Hálózat</string>\n    <string name=\"rate_limit\">Mértékhatár</string>\n    <string name=\"rate_limit_desc\">Maximum letöltési sebesség korlátozása</string>\n    <string name=\"max_rate\">Maximum mérték</string>\n    <string name=\"high_contrast\">Magas kontrasztú sötét téma</string>\n    <string name=\"invalid_input\">Nem megfelelő bemenet</string>\n    <string name=\"unavailable\">Nem elérhető</string>\n    <string name=\"format_settings_desc\">Fájl formátum, videó minőség, feliratok</string>\n    <string name=\"general_settings_desc\">Yt-dlp verzió, értesítés, playlist</string>\n    <string name=\"network_settings_desc\">Mértékhatár, letöltő, sütik</string>\n    <string name=\"disable_preview\">Előnézet letiltása</string>\n    <string name=\"privacy\">Magánélet</string>\n    <string name=\"download_selection_desc\">Válassza ki a videókat, amiket le akar tölteni a \\\"%1$s\\\" playlistről</string>\n    <string name=\"select_all\">Minden kiválasztása</string>\n    <string name=\"selected_item_count\">%1$d kiválasztva</string>\n    <string name=\"generate_new_cookies\">Új sütik generálása</string>\n    <string name=\"lowest_quality\">Legalacsonyabb minőség</string>\n    <string name=\"video_only\">Videó (hang nélkül)</string>\n    <string name=\"suggested\">Ajánlott</string>\n    <string name=\"format_selection\">Formátum kiválasztása</string>\n    <string name=\"crop_artwork\">Album borító vágása</string>\n    <string name=\"crop_artwork_desc\">Beágyazott képet négyzetre vagása</string>\n    <string name=\"use_custom_command\">Egyéni parancs használata</string>\n    <string name=\"private_directory\">Privát mappa</string>\n    <string name=\"private_directory_desc\">Tárolja a letöltéseket egy rejtett mappában</string>\n    <string name=\"recently_added\">Legutóbb hozzáadva</string>\n    <string name=\"multiselect_item_count\">%1$d videó, %2$d audió fájl</string>\n    <string name=\"check_for_updates\">Frissítések keresése</string>\n    <string name=\"clear_temp_files\">Átmeneti fájlok törlése</string>\n    <string name=\"clear_temp_files_desc\">Minden átmeneti fájl törlése az ideiglenes mappából</string>\n    <string name=\"clear_temp_files_count\">%1$d átmeneti fájl törölve</string>\n    <string name=\"cookies_desc\">Netscape formátumú sütik használata a letöltéshez</string>\n    <string name=\"multiselect_mode\">Többválasztós mód</string>\n    <string name=\"file_unavailable\">Ez a fájl már nem elérhető</string>\n    <string name=\"clear_temp_files_info\">Az átmeneti fájlok felhasználhatóak megszakított letöltéseket folytatására. Biztosan törölni szeretné őket?\n\\n\n\\nEzek a fájlok elérhetőek itt: %1$s</string>\n    <string name=\"disable_preview_desc\">Előnézet letiltása a letöltéseknél</string>\n    <string name=\"format_selection_desc\">A letöltés megkezdése előtt válassza ki a letöltendő formátumot</string>\n    <string name=\"audio_quality\">Hangminőség</string>\n    <string name=\"minute\">perc</string>\n    <string name=\"clear_all_cookies\">Összes süti törlése</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"ytdlp_update_action\">yt-dlp frissítése</string>\n    <string name=\"cookies\">Sütik</string>\n    <string name=\"show_logs\">log mutatása</string>\n    <string name=\"subtitle\">Felirat</string>\n    <string name=\"download_subtitles\">Feliratok letöltése</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"pre_release_channel\">Előnézet</string>\n    <string name=\"clip_start\">Kezdés</string>\n    <string name=\"sdcard_directory\">SD kártya mappa</string>\n    <string name=\"subtitle_language\">Felirat nyelvei</string>\n    <string name=\"copy_log\">log másolása</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"auto_update\">Automatikus frissítés</string>\n    <string name=\"update_channel\">Csatorna frissítése</string>\n    <string name=\"enable_auto_update\">Automatikus frissítés bekapcsolása</string>\n    <string name=\"clip_end\">Vég</string>\n    <string name=\"unlimited\">Korlátlan</string>\n    <string name=\"lowest_bitrate\">Legalacsonyabb bitráta</string>\n    <string name=\"title\">Cím</string>\n    <string name=\"rename\">Átnevezés</string>\n    <string name=\"second\">második</string>\n    <string name=\"okay\">Rendben</string>\n    <string name=\"got_it\">Értem</string>\n    <string name=\"convert_subtitle\">Feliratok konvertálása</string>\n    <string name=\"copy_and_exit\">Másolás és kilépés</string>\n    <string name=\"edit_shortcuts\">Gyorsgombok szerkesztése</string>\n    <string name=\"add\">Hozzáadás</string>\n    <string name=\"shortcuts\">Gyorsgombok</string>\n    <string name=\"running_tasks\">Folyamatban lévő feladatok</string>\n    <string name=\"share\">Megosztás</string>\n    <string name=\"feedback\">Visszajelzés</string>\n    <string name=\"no_downloaded_media\">Nincs letöltött média</string>\n    <string name=\"beta_features\">Béta</string>\n    <string name=\"expand\">Kiterjesztés</string>\n    <string name=\"start\">Kezdés</string>\n    <string name=\"discard\">Elvetés</string>\n    <string name=\"telegram_channel\">Telegram csatorna</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"how_does_it_work\">Hogyan működik?</string>\n    <string name=\"title_activity_share\">Gyors letöltés</string>\n    <string name=\"sponsor\">Szponzor</string>\n    <string name=\"sponsors\">Szponzorok</string>\n    <string name=\"audio_format\">Hangformátum</string>\n    <string name=\"feature_unavailable\">Funkció nem elérhető</string>\n    <string name=\"quality\">Minőség</string>\n    <string name=\"use_cookies\">Sütik használata</string>\n    <string name=\"custom_command_enabled_hint\">Néhány opció nem elérhatő testreszabott parancsok mellett</string>\n    <string name=\"custom_command_usage_msg\">A yt-dlp egy hatékony parancssori eszköz videók letöltéséhez. A Seal megkönnyíti a yt-dlp használatát úgy, hogy egy intuitív GUI-t, előbeállításokat gyakran használt parancsokhoz és sok mást kínál.\n\\n\n\\nA yt-dlp haladó használatához a Seal lehetővé teszi egyedi parancssablonok létrehozását, elmentését és lefuttatását, akárcsak egy terminálban.\n\\n\n\\nEgyéni parancsok használatakor a legtöbb grafikus felület opció és szolgáltatás le van tiltva.</string>\n    <string name=\"auto_subtitle\">Automatikus feliratok</string>\n    <string name=\"auto_subtitle_desc\">Automatikusan generált feliratok letöltése</string>\n    <string name=\"video_title_sample_text\">Videó címének minta szövege</string>\n    <string name=\"subtitle_desc\">Nyelvek, feliratok beágyazása, automatikus feliratozás</string>\n    <string name=\"remove_cookie_profile_desc\">Eltávolítja ezt a bejegyzést a következőhöz: \\\"%1$s\\\"? Vegye figyelembe, hogy az ezen az oldalon tárolt cookie-k nem törlődnek.</string>\n    <string name=\"matrix_space\">Mátrix helye</string>\n    <string name=\"abs_hint\">A legtöbb oldal külön tárolja a hangot, és a videót. Ki tud választani csak hang, és csak videó formátumú tartalmakat, hogy aztán egybeolvassza őket.</string>\n    <string name=\"clear\">Clear</string>\n    <string name=\"cookies_usage_msg\">Bizonyos oldalakról való letöltéshez hitelesítés szükséges. Kattintson a(z) \\\"Új sütik generálása\\\" gombra, írja be az oldal címét, majd jelentkezzen be az oldalra. Ezután az alkalmazás legenerálja magától a szükséges adatokat.</string>\n    <string name=\"video_creator_sample_text\">Videó készitő példa szöveg</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-in/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"fetching_info\">Mengambil informasi video…</string>\n    <string name=\"permission_denied\">Izin ditolak</string>\n    <string name=\"download_error_msg\">Tidak dapat mengunduh berkas</string>\n    <string name=\"download_start_msg\">Mengunduh \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Tidak dapat mengambil informasi video</string>\n    <string name=\"language_settings\">Atur bahasa tampilan</string>\n    <string name=\"task_running\">Tugas pengunduhan yang ada sudah berjalan</string>\n    <string name=\"paste_msg\">Tempel URL</string>\n    <string name=\"paste_fail_msg\">Tidak dapat mencocokkan URL di papan klip</string>\n    <string name=\"ytdlp_version\">Versi yt-dlp</string>\n    <string name=\"delete_info\">Singkirkan?</string>\n    <string name=\"confirm\">Konfirmasi</string>\n    <string name=\"dismiss\">Batalkan</string>\n    <string name=\"downloads_history\">Unduhan</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"open_url\">Buka tautan</string>\n    <string name=\"remove\">Singkirkan</string>\n    <string name=\"about_page\">Versi, masukan, pembaruan otomatis</string>\n    <string name=\"back\">Kembali</string>\n    <string name=\"version\">Versi</string>\n    <string name=\"release\">Versi terbaru</string>\n    <string name=\"readme_desc\">Periksa repositori GitHub dan README</string>\n    <string name=\"credits_desc\">Kredit dan perangkat lunak bebas</string>\n    <string name=\"custom_command_template\">Templat perintah</string>\n    <string name=\"start_execute\">Mulai jalankan perintah</string>\n    <string name=\"advanced_settings\">Lanjutan</string>\n    <string name=\"print_details\">Keluaran terperinci</string>\n    <string name=\"print_details_desc\">Cetak pesan terperinci saat mengunduh</string>\n    <string name=\"on\">Nyala</string>\n    <string name=\"settings_before_download_text\">Sesuaikan unduhan ini</string>\n    <string name=\"error_copied\">Laporan kesalahan disalin ke papan klip</string>\n    <string name=\"thumbnail\">Gambar mini</string>\n    <string name=\"paste\">Tempel</string>\n    <string name=\"edit_template_desc\">Jalur keluaran dan URL akan ditambahkan oleh aplikasi.</string>\n    <string name=\"convert_audio_format\">Ubah format audio</string>\n    <string name=\"not_convert\">Tidak diubah</string>\n    <string name=\"convert_audio_format_desc\">Meng-enkode ulang berkas audio akan menyebabkan kehilangan kualitas audio dan penambahan ukuran berkas.</string>\n    <string name=\"video_quality\">Kualitas video</string>\n    <string name=\"best_quality\">Kualitas terbaik</string>\n    <string name=\"preferred_format_desc\">Format pilihan ketika beberapa disediakan</string>\n    <string name=\"video_format\">Format video</string>\n    <string name=\"convert_audio\">Ubah</string>\n    <string name=\"start_download\">Unduh</string>\n    <string name=\"user_guide\">Panduan pengguna</string>\n    <string name=\"open_settings\">Buka pengaturan</string>\n    <string name=\"download_history_desc\">Periksa dan kelola unduhan dalam aplikasi, termasuk video dan berkas audio.</string>\n    <string name=\"download_playlist\">Unduh daftar putar</string>\n    <string name=\"download_playlist_desc\">Unduh beberapa video dari daftar putar</string>\n    <string name=\"defaults\">Bawaan</string>\n    <string name=\"channel_name\">Unduhan</string>\n    <string name=\"video_url\">Tautan video</string>\n    <string name=\"download_finish_notification\">Unduhan selesai. Ketuk untuk membuka.</string>\n    <string name=\"execute_command_notification\">Menjalankan perintah khusus…</string>\n    <string name=\"battery_settings_desc\">Harap atur penggunaan baterai aplikasi ini ke \\\"Tidak dibatasi\\\" di pengaturan sistem untuk mengunduh di latar belakang.</string>\n    <string name=\"concurrent_download_desc\">Unduh lebih banyak bagian video dari M3U8/MPD secara paralel</string>\n    <string name=\"concurrent_download_num\">%d bagian akan digunakan untuk mengunduh video asli DASH/HLS secara bersamaan.</string>\n    <string name=\"options\">Pilihan</string>\n    <string name=\"channel_description\">Beritahu berkas yang diunduh dan kemajuannya</string>\n    <string name=\"show_more_actions\">Tampilkan lebih banyak tindakan</string>\n    <string name=\"download_notification_desc\">Beritahu berkas yang diunduh dan kemajuannya</string>\n    <string name=\"download_range_selection\">Pilihan daftar putar</string>\n    <string name=\"from\">Mulai</string>\n    <string name=\"invalid_index_range\">Rentang indeks tidak sah</string>\n    <string name=\"playlist_indicator_text\">Mengunduh daftar putar (%1$d/%2$d)…</string>\n    <string name=\"download_directory_desc\">Pilih tempat untuk menyimpan berkas video dan audio</string>\n    <string name=\"subdirectory\">Simpan ke subdirektori</string>\n    <string name=\"subdirectory_desc\">Simpan berkas dalam folder yang diberi nama sesuai bidang masing-masing</string>\n    <string name=\"permission_issue\">Masalah izin penyimpanan</string>\n    <string name=\"battery_configuration\">Pengaturan baterai</string>\n    <string name=\"video_directory\">Folder video</string>\n    <string name=\"yt_dlp_up_to_date\">Menggunakan versi yt-dlp terbaru</string>\n    <string name=\"yt_dlp_update_fail\">Tidak dapat memasang yt-dlp versi terbaru. Pastikan Anda terhubung ke internet.</string>\n    <string name=\"download_success_msg\">Unduhan selesai</string>\n    <string name=\"general_settings\">Umum</string>\n    <string name=\"language\">Bahasa tampilan</string>\n    <string name=\"custom_command\">Perintah khusus</string>\n    <string name=\"ytdlp_update\">Tekan untuk memasang yt-dlp versi terbaru</string>\n    <string name=\"off\">Mati</string>\n    <string name=\"about\">Tentang</string>\n    <string name=\"display_settings\">Tema gelap, warna dinamis, bahasa</string>\n    <string name=\"yt_dlp_docs\">Referensi penggunaan yt-dlp</string>\n    <string name=\"delete_info_msg\">Singkirkan \\\"%1$s\\\" dari riwayat unduhan Anda untuk selamanya?</string>\n    <string name=\"delete_file\">Hapus berkas</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Sudah diperiksa</string>\n    <string name=\"credits\">Kredit</string>\n    <string name=\"custom_command_desc\">Jalankan perintah yt-dlp menggunakan templat khusus</string>\n    <string name=\"display\">Tampilan</string>\n    <string name=\"release_desc\">Lihat log perubahan dan versi baru</string>\n    <string name=\"edit\">Sunting</string>\n    <string name=\"settings_before_download\">Atur sebelum unduh</string>\n    <string name=\"format\">Format</string>\n    <string name=\"dark_theme\">Tema gelap</string>\n    <string name=\"follow_system\">Sistem</string>\n    <string name=\"cancel\">Batalkan</string>\n    <string name=\"settings_before_download_desc\">Atur preferensi sebelum mengunduh</string>\n    <string name=\"video_format_preference\">Format video pilihan</string>\n    <string name=\"close\">Tutup</string>\n    <string name=\"convert_to\">Ubah ke %1$s</string>\n    <string name=\"video_quality_desc\">Batasi kualitas video ketika ada beberapa yang tersedia</string>\n    <string name=\"not_specified\">Tidak ditentukan (bawaan)</string>\n    <string name=\"close_never_show_again\">Jangan tampilkan lagi</string>\n    <string name=\"paste_desc\">Tekan \\\"Tempel\\\" untuk mendapatkan link video dari papan klip Anda.</string>\n    <string name=\"download_desc\">Kemudian tekan \\\"Unduh\\\" setelah menyesuaikan pengaturannya.</string>\n    <string name=\"check_download_settings_desc\">Lihat pengaturan unduhan dan pastikan Anda memiliki yt-dlp versi terbaru sebelum menggunakannya.</string>\n    <string name=\"concurrent_download\">Unduhan multi-utas</string>\n    <string name=\"additional_settings\">Pengaturan tambahan</string>\n    <string name=\"share_fail_msg\">Tidak dapat mencocokkan URL dari konten yang dibagikan</string>\n    <string name=\"share_success_msg\">Membaca tautan video dari konten yang dibagikan…</string>\n    <string name=\"download_notification\">Pemberitahuan unduhan</string>\n    <string name=\"fetching_playlist_info\">Mengambil informasi daftar putar…</string>\n    <string name=\"to\">Akhir</string>\n    <string name=\"battery_configuration_desc\">Abaikan pengoptimalan baterai pada aplikasi ini untuk mengunduh di latar belakang</string>\n    <string name=\"translate\">Terjemahkan</string>\n    <string name=\"download_range_desc\">Tentukan rentang video yang akan diunduh dari daftar putar \\\"%3$s\\\"(dari %1$d hingga %2$d).</string>\n    <string name=\"extract_audio\">Simpan sebagai audio</string>\n    <string name=\"create_thumbnail\">Simpan thumbnail</string>\n    <string name=\"settings\">Pengaturan</string>\n    <string name=\"download_settings_desc\">Umum, format, perintah khusus</string>\n    <string name=\"download\">Unduhan</string>\n    <string name=\"url_empty\">Tautan tidak boleh kosong</string>\n    <string name=\"extract_audio_summary\">Unduh dan simpan audio, daripada video</string>\n    <string name=\"create_thumbnail_summary\">Simpan thumbnail video sebagai berkas</string>\n    <string name=\"link_copied\">Tautan disalin ke papan klip</string>\n    <string name=\"audio_directory\">Folder audio</string>\n    <string name=\"download_directory\">Direktori unduhan</string>\n    <string name=\"permission_issue_desc\">Direktori di luar Unduhan/ dan Dokumen/ tidak didukung</string>\n    <string name=\"service_title\">Seal sedang mengunduh…</string>\n    <string name=\"unknown_error\">Kesalahan tidak diketahui</string>\n    <string name=\"translate_desc\">Bantu terjemahkan aplikasi ini pada Hosted Weblate</string>\n    <string name=\"prefix\">Awalan</string>\n    <string name=\"embed_subtitles\">Sematkan terjemahan</string>\n    <string name=\"embed_subtitles_desc\">Sematkan soft-sub ke dalam video jika tersedia</string>\n    <string name=\"new_template\">Templat baru</string>\n    <string name=\"template_label\">Label</string>\n    <string name=\"template_selection\">Pilihan templat</string>\n    <string name=\"remove_template\">Singkirkan?</string>\n    <string name=\"remove_template_desc\">Singkirkan \\\"%1$s\\\" dari templat perintah untuk selamanya?</string>\n    <string name=\"custom_command_template_desc\">Edit dan kelola templat perintah</string>\n    <string name=\"downloading_indicator_text\">Sedang dalam proses pengunduhan…</string>\n    <string name=\"task_canceled\">Tugas unduhan dibatalkan</string>\n    <string name=\"github_issue\">Masalah GitHub</string>\n    <string name=\"github_issue_desc\">Kirimkan masalah untuk pelaporan bug atau permintaan fitur</string>\n    <string name=\"info_copied\">Info disalin ke papan klip</string>\n    <string name=\"status_fetching_video_info\">Mengambil info</string>\n    <string name=\"open_file\">Buka berkas</string>\n    <string name=\"restart\">Ulangi</string>\n    <string name=\"status_enqueued\">Dalam antrean</string>\n    <string name=\"status_completed\">Selesai</string>\n    <string name=\"status_downloading\">Mengunduh</string>\n    <string name=\"status_canceled\">Dibatalkan</string>\n    <string name=\"copy_error_report\">Salin laporan</string>\n    <string name=\"status_error\">Kesalahan</string>\n    <string name=\"copy_link\">Salin tautan</string>\n    <string name=\"video_file_size\">Ukuran berkas video</string>\n    <string name=\"video_resolution\">Resolusi video</string>\n    <string name=\"export_to_clipboard\">Ekspor ke papan klip</string>\n    <string name=\"import_from_clipboard\">Impor dari papan klip</string>\n    <string name=\"download_task_count\">%1$d Tugas unduhan</string>\n    <string name=\"template_imported\">%1$d Template yang telah diimpor</string>\n    <string name=\"template_exported\">%1$d Template yang telah diekspor</string>\n    <string name=\"check_for_updates\">Periksa pembaruan</string>\n    <string name=\"check_for_updates_desc\">Periksa otomatis untuk versi terbaru di GitHub</string>\n    <string name=\"app_up_to_date\">Versi saat ini adalah yang terbaru</string>\n    <string name=\"app_update_failed\">Gagal memperbarui ke versi terbaru</string>\n    <string name=\"update\">Pembaruan</string>\n    <string name=\"aria2_desc\">Gunakan aria2c sebagai pengunduh eksternal</string>\n    <string name=\"cookies_desc\">Gunakan cookie berformat Netscape untuk pengunduhan</string>\n    <string name=\"clear_temp_files\">Bersihkan berkas sementara</string>\n    <string name=\"clear_temp_files_count\">%1$d berkas sementara telah dihapus</string>\n    <string name=\"clear_temp_files_desc\">Hapus semua berkas sementara dari direktori sementara</string>\n    <string name=\"clear_temp_files_info\">Berkas sementara dapat digunakan untuk melanjutkan unduhan yang dibatalkan. Apakah Anda yakin akan menghapus semua berkas sementara?\n\\n\n\\nAnda dapat mengakses berkas ini di %1$s</string>\n    <string name=\"recently_added\">Baru Ditambahkan</string>\n    <string name=\"multiselect_item_count\">%1$d video, %2$d berkas audio</string>\n    <string name=\"delete_multiple_items_msg\">Singkirkan %1$d item dari riwayat unduhan Anda untuk selamanya?</string>\n    <string name=\"sponsorblock_desc\">Singkirkan atau tandai bagian dalam video dengan API SponsorBlock</string>\n    <string name=\"sponsorblock_categories\">Kategori SponsorBlock</string>\n    <string name=\"sponsorblock_categories_desc\">Tentukan kategori SponsorBlock yang akan disingkirkan atau ditandai dalam berkas video</string>\n    <string name=\"multiselect_mode\">Mode pilih banyak</string>\n    <string name=\"rate_limit\">Batasan nilai</string>\n    <string name=\"network\">Jaringan</string>\n    <string name=\"max_rate\">Kecepatan maksimum</string>\n    <string name=\"private_mode\">Samaran</string>\n    <string name=\"private_mode_desc\">Mematikan riwayat unduhan</string>\n    <string name=\"dynamic_color\">Warna dinamis</string>\n    <string name=\"dynamic_color_desc\">Terapkan warna dari wallpaper ke tema aplikasi</string>\n    <string name=\"download_with_cellular\">Unduh menggunakan seluler</string>\n    <string name=\"download_with_cellular_desc\">Perbolehkan mengunduh media saat terhubung ke jaringan terukur</string>\n    <string name=\"download_disabled_with_cellular\">Mengunduh dengan jaringan seluler dimatikan berdasarkan pengaturan Anda</string>\n    <string name=\"file_unavailable\">Berkas ini tidak lagi tersedia</string>\n    <string name=\"rate_limit_desc\">Batasi kecepatan unduh maksimum</string>\n    <string name=\"high_contrast\">Tema gelap kontras tinggi</string>\n    <string name=\"invalid_input\">Masukan tidak sah</string>\n    <string name=\"lowest_quality\">Kualitas paling rendah</string>\n    <string name=\"unavailable\">Tidak tersedia</string>\n    <string name=\"general_settings_desc\">Versi yt-dlp, pemberitahuan, daftar putar</string>\n    <string name=\"network_settings_desc\">Batasan nilai, pengunduh, kuki</string>\n    <string name=\"disable_preview\">Matikan pratinjau</string>\n    <string name=\"use_custom_command\">Gunakan perintah khusus</string>\n    <string name=\"private_directory\">Direktori pribadi</string>\n    <string name=\"crop_artwork\">Potong gambar</string>\n    <string name=\"crop_artwork_desc\">Potong gambar tersemat menjadi kotak</string>\n    <string name=\"format_settings_desc\">Format berkas, kualitas video, terjemahan</string>\n    <string name=\"privacy\">Privasi</string>\n    <string name=\"disable_preview_desc\">Tidak ada tampilan thumbnail selama pengunduhan</string>\n    <string name=\"private_directory_desc\">Menyimpan unduhan di dalam direktori tersembunyi</string>\n    <string name=\"select_all\">Pilih semua</string>\n    <string name=\"download_selection_desc\">Pilih video untuk diunduh dari daftar putar \\\"%1$s\\\"</string>\n    <string name=\"selected_item_count\">%1$d dipilih</string>\n    <string name=\"suggested\">Disarankan</string>\n    <string name=\"format_selection\">Pemilihan format</string>\n    <string name=\"video_only\">Video (tanpa audio)</string>\n    <string name=\"format_selection_desc\">Pilih format untuk diunduh sebelum memulai unduhan</string>\n    <string name=\"generate_new_cookies\">Hasilkan kuki baru</string>\n    <string name=\"use_cookies\">Gunakan Kuki</string>\n    <string name=\"custom_command_enabled_hint\">Beberapa pilihan tidak tersedia ketika menggunakan perintah khusus</string>\n    <string name=\"how_does_it_work\">Bagaimana cara kerjanya\\?</string>\n    <string name=\"remove_cookie_profile_desc\">Singkirkan entri untuk \\\"%1$s\\\"? Perhatikan bahwa kuki yang disimpan untuk situs ini tidak akan dihapus.</string>\n    <string name=\"cookies_usage_msg\">Mengunduh dari beberapa situs memerlukan informasi autentikasi akun. Klik \\\"Hasilkan kuki baru\\\", masukkan URL situs web dan kemudian masuk dengan akun Anda di halaman browser, aplikasi akan membuatnya untuk Anda.</string>\n    <string name=\"telegram_channel\">Saluran Telegram</string>\n    <string name=\"matrix_space\">Space Matrix</string>\n    <string name=\"cookies\">Kuki</string>\n    <string name=\"abs_hint\">Sebagian besar platform streaming video mengirimkan audio dan video secara terpisah, Anda dapat memilih dan menggabungkan format audio saja dengan format video saja menjadi satu video.</string>\n    <string name=\"auto_subtitle_desc\">Unduh keterangan yang dibuat secara otomatis</string>\n    <string name=\"video_title_sample_text\">Contoh teks judul video</string>\n    <string name=\"video_creator_sample_text\">Contoh teks pembuat video</string>\n    <string name=\"subtitle\">Terjemahan</string>\n    <string name=\"subtitle_desc\">Bahasa, terjemahan tersemat, keterangan otomatis</string>\n    <string name=\"copy_log\">Salin catatan</string>\n    <string name=\"clear\">Hapus</string>\n    <string name=\"running_tasks\">Tugas yang berjalan</string>\n    <string name=\"show_logs\">Tampilkan catatan</string>\n    <string name=\"logs\">Catatan</string>\n    <string name=\"auto_subtitle\">Keterangan otomatis</string>\n    <string name=\"edit_shortcuts_desc\">Sunting pintasan khusus yang dapat digunakan untuk membuat templat perintah.</string>\n    <string name=\"download_subtitles\">Unduh terjemahan</string>\n    <string name=\"sdcard_directory\">Folder kartu SD</string>\n    <string name=\"title_activity_share\">Unduhan cepat</string>\n    <string name=\"subtitle_language\">Bahasa terjemahan</string>\n    <string name=\"edit_shortcuts\">Sunting pintasan</string>\n    <string name=\"add\">Tambahkan</string>\n    <string name=\"shortcuts\">Pintasan</string>\n    <string name=\"subtitle_sponsorblock\">Terjemahan mungkin tidak pas waktunya ketika menyingkirkan bagian SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Untuk menyematkan terjemahan, video akan di-mux ulang ke kontainer MKV. Anda dapat menggunakan Pemutar Media VLC atau aplikasi lainnya yang kompatibel untuk menonton video dengan terjemahan yang disemat.</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"update_channel\">Saluran pembaruan</string>\n    <string name=\"share\">Bagikan</string>\n    <string name=\"auto_update\">Pembaruan otomatis</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"pre_release_channel\">Pratinjau</string>\n    <string name=\"update_channel_desc\">Pasang versi prarilis untuk melihat pratinjau fitur dan perubahan baru.\n\\n\n\\nAkan ada beberapa ketidakstabilan dalam versi ini, jadi jangan ragu untuk memberi kami masukan jika Anda mengalami masalah apa pun untuk membantu kami meningkatkan aplikasi di masa mendatang.</string>\n    <string name=\"enable_auto_update\">Nyalakan pembaruan otomatis</string>\n    <string name=\"discard\">Buang</string>\n    <string name=\"clip_video\">Klip video</string>\n    <string name=\"clip_end\">Akhir</string>\n    <string name=\"clip_start\">Awal</string>\n    <string name=\"apply\">Terapkan</string>\n    <string name=\"lowest_bitrate\">Kecepatan bit terendah</string>\n    <string name=\"audio_format_preference\">Format audio yang disukai</string>\n    <string name=\"unlimited\">Tidak terbatas</string>\n    <string name=\"audio_quality\">Kualitas audio</string>\n    <string name=\"format_sorting\">Urutan format</string>\n    <string name=\"format_sorting_desc\">Mengurutkan format dengan pilihan -S dari yt-dlp</string>\n    <string name=\"title\">Judul</string>\n    <string name=\"rename\">Ubah nama</string>\n    <string name=\"second\">detik</string>\n    <string name=\"clear_all_cookies_desc\">Hapus semua kuki tersimpan dalam aplikasi selamanya\\?</string>\n    <string name=\"audio_quality_desc\">Batasi kecepatan bit audio ketika beberapa kualitas tersedia</string>\n    <string name=\"import_from_preferences\">Impor</string>\n    <string name=\"clear_all_cookies\">Hapus semua kuki</string>\n    <string name=\"minute\">menit</string>\n    <string name=\"temporary_directory_desc\">Simpan berkas sementara di direktori internal</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">Dukung aplikasi ini dengan mensponsori di GitHub</string>\n    <string name=\"sponsor_msg\">Seal akan selalu gratis dan sumbernya terbuka untuk semua orang. Jika Anda menyukainya, silakan sponsori saya di GitHub!</string>\n    <string name=\"feedback\">Masukan</string>\n    <string name=\"sponsors\">Sponsor</string>\n    <string name=\"no_downloaded_media\">Tidak ada media yang terunduh</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Nyalakan fitur percobaan?</string>\n    <string name=\"audio_format\">Format audio</string>\n    <string name=\"clip_video_desc\">Buat klip video dalam halaman pemilihan format</string>\n    <string name=\"clip_video_dialog_msg\">Pengunduhan menggunakan fitur ini akan didelegasikan ke FFmpeg untuk mengunduh bagian video yang dipilih, fitur ini masih tahap percobaan dan pemotongan tidak akan sepenuhnya akurat, tidak semua format mendukung fitur ini dan Anda mungkin mengalami kecepatan pengunduhan yang lebih lambat.</string>\n    <string name=\"got_it\">Mengerti</string>\n    <string name=\"feature_unavailable\">Fitur tidak tersedia</string>\n    <string name=\"auto_update_disabled_msg\">Pembaruan otomatis tidak tersedia untuk versi %1$s. Jika Anda belum memasang %1$s di perangkat Anda, atau ingin melihat pratinjau fitur-fitur baru yang akan datang di Seal, silahkan pertimbangkan %2$s.</string>\n    <string name=\"switch_to_github_builds\">beralih ke versi GitHub</string>\n    <string name=\"okay\">Oke</string>\n    <string name=\"no_custom_command_tasks\">Tidak ada tugas perintah khusus</string>\n    <string name=\"msg_from_developer\">Pesan dari pengembang</string>\n    <string name=\"sponsor_msg2\">Terima kasih banyak!</string>\n    <string name=\"download_video_desc\">Unduh video dari URL</string>\n    <string name=\"convert_subtitle\">Ubah terjemahan</string>\n    <string name=\"split_video\">Pisahkan video</string>\n    <string name=\"unknown_error_title\">Aduh! Ada yang salah</string>\n    <string name=\"copy_and_exit\">Salin dan keluar</string>\n    <string name=\"split_video_msg\">Video akan dipisahkan menjadi %1$d bagian</string>\n    <string name=\"convert_subtitle_desc\">Ubah terjemahan ke format lainnya</string>\n    <string name=\"expand\">Perluas</string>\n    <string name=\"start\">Mulai</string>\n    <string name=\"edit_template\">Sunting \\\"%1$s\\\"</string>\n    <string name=\"new_task\">Tugas unduhan baru</string>\n    <string name=\"ytdlp_update_action\">Perbarui yt-dlp</string>\n    <string name=\"proxy\">Proksi</string>\n    <string name=\"proxy_desc\">Gunakan proksi untuk sambungan internet</string>\n    <string name=\"legacy\">Lawas</string>\n    <string name=\"disable\">Matikan</string>\n    <string name=\"folder_picker\">Pemilih folder</string>\n    <string name=\"custom_command_directory_desc\">Tentukan direktori keluaran ketika menggunakan perintah khusus</string>\n    <string name=\"quality\">Kualitas</string>\n    <string name=\"enable_notifications\">Nyalakan pemberitahuan?</string>\n    <string name=\"enable_notifications_desc\">Aplikasi memerlukan izin Anda untuk mengirim pemberitahuan tentang status dan proses pengunduhan.</string>\n    <string name=\"set_directory_desc\">Ketuk untuk menyiapkan direktori</string>\n    <string name=\"custom_command_directory\">Direktori perintah khusus</string>\n    <string name=\"disabled\">Dimatikan</string>\n    <string name=\"prefer_compatibility_desc\">Lebih suka format MP4(H.264) untuk berbagi ke aplikasi lain</string>\n    <string name=\"prefer_quality_desc\">Lebih suka format AV1, VP9, atau H.265 untuk ditonton dalam aplikasi yang kompatibel</string>\n    <string name=\"download_type\">Jenis unduhan</string>\n    <string name=\"custom\">Khusus</string>\n    <string name=\"auto\">Otomatis</string>\n    <string name=\"learn_more\">Pelajari lebih lanjut</string>\n    <string name=\"unknown\">Tidak diketahui</string>\n    <string name=\"commands\">Perintah</string>\n    <string name=\"format_preference\">Preferensi format</string>\n    <string name=\"refresh_cookies_desc\">Ketuk untuk membuka laman web untuk menghasilkan kuki baru:</string>\n    <string name=\"remove_multiple_templates_msg\">Singkirkan %1$s dari templat perintah selamanya?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">%d item</item>\n    </plurals>\n    <string name=\"ua_header\">Tajuk User-Agent</string>\n    <string name=\"export_to_file\">Ekspor ke berkas</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp adalah alat baris perintah yang hebat untuk mengunduh video. Seal membuatnya lebih mudah untuk memakai yt-dlp dengan menyediakan GUI yang intuitif, prasetel untuk perintah umum, dan fitur tambahan lainnya.\n\\n\n\\nUntuk pengguna yt-dlp tingkat lanjut, Seal memungkinkan Anda untuk membuat, menyimpan, dan menjalankan templat perintah khusus secara langsung, seperti dalam terminal.\n\\n\n\\nKetika menggunakan perintah khusus, kebanyakan opsi dan fitur GUI akan dinonaktifkan.</string>\n    <string name=\"presets\">Prasetel</string>\n    <string name=\"output_template\">Templat keluaran</string>\n    <string name=\"output_template_desc\">Tentukan templat untuk nama berkas keluaran</string>\n    <string name=\"clear_download_archive\">Hapus arsip unduhan\\?</string>\n    <string name=\"clear_download_archive_desc\">Singkirkan %1$s dari berkas arsip selamanya?</string>\n    <string name=\"download_archive_desc\">Rekam ID video yang telah diunduh dalam arsip untuk menghindari unduhan ganda</string>\n    <string name=\"download_archive\">Unduh arsip</string>\n    <string name=\"save\">Simpan</string>\n    <string name=\"embed_metadata\">Sematkan metadata</string>\n    <string name=\"use_format_sorting\">Gunakan penyortiran format</string>\n    <string name=\"restrict_filenames_desc\">Batasi nama berkas pada karakter tertentu untuk memastikan kompatibilitas</string>\n    <string name=\"required\">Diperlukan</string>\n    <string name=\"show_all_items\">Tampilkan semua %1$d item</string>\n    <string name=\"restrict_filenames\">Batasi nama berkas</string>\n    <string name=\"edit_file\">Sunting berkas</string>\n    <string name=\"embed_metadata_desc\">Sematkan metadata dan thumbnail video ke dalam berkas audio</string>\n    <string name=\"subdirectory_hint\">Unduhan Anda akan disimpan sebagai:</string>\n    <string name=\"keep_subtitle_files\">Simpan berkas terjemahan</string>\n    <string name=\"website\">Situs web</string>\n    <string name=\"playlist_title\">Judul daftar putar</string>\n    <string name=\"system_settings\">Pengaturan sistem</string>\n    <string name=\"force_ipv4\">Paksa IPv4</string>\n    <string name=\"force_ipv4_desc\">Buat semua sambungan melalui IPv4</string>\n    <string name=\"allow_once\">Ijinkan sekali</string>\n    <string name=\"allow_always\">Selalu ijinkan</string>\n    <string name=\"dont_allow\">Jangan ijinkan</string>\n    <string name=\"download_with_cellular_request\">Ijinkan mengunduh dengan data seluler?</string>\n    <string name=\"merge_audiostream\">Gabungkan beberapa aliran audio</string>\n    <string name=\"merge_audiostream_desc\">Izinkan beberapa aliran audio untuk digabungkan menjadi satu berkas</string>\n    <string name=\"search_in_downloads\">Cari di unduhan</string>\n    <string name=\"search\">Cari</string>\n    <string name=\"auto_translated_subtitles\">Terjemahan otomatis</string>\n    <string name=\"auto_translated_subtitles_msg\">Terjemahan otomatis untuk semua bahasa akan tersedia dalam unduhan. Terjemahan ini mungkin tidak akurat dan sulit dipahami.</string>\n    <string name=\"remember_for_next_download\">Ingat untuk unduhan berikutnya</string>\n    <string name=\"look_and_feel\"><![CDATA[Tampilan & nuansa]]></string>\n    <string name=\"use_previous_selection\">Gunakan pilihan sebelumnya</string>\n    <string name=\"none\">Tidak ada</string>\n    <string name=\"subtitle_language_desc\">Bahasa terjemahan yang akan diunduh dalam pilihan format otomatis, dipisahkan dengan koma.</string>\n    <string name=\"reset\">Atur ulang</string>\n    <string name=\"search_in_subtitles\">Cari dalam terjemahan</string>\n    <string name=\"no_thanks\">Tidak, terima kasih</string>\n    <string name=\"update_subtitle_languages\">Perbarui bahasa terjemahan?</string>\n    <string name=\"update_language_msg\">Bahasa berikut akan ditambahkan ke preferensi Anda untuk unduhan di masa mendatang:</string>\n    <string name=\"export_backup\">Ekspor</string>\n    <string name=\"import_backup\">Impor</string>\n    <string name=\"full_backup\">Cadangan penuh</string>\n    <string name=\"backup_type\">Jenis pencadangan</string>\n    <string name=\"export_to\">Ekspor ke</string>\n    <string name=\"file\">Berkas</string>\n    <string name=\"clipboard\">Papan klip</string>\n    <string name=\"import_from\">Impor dari</string>\n    <string name=\"export_download_history\">Ekspor riwayat unduhan?</string>\n    <string name=\"import_download_history\">Impor riwayat unduhan?</string>\n    <string name=\"export_download_history_msg\">Mengekspor %1$s dari riwayat pengunduhan. Berkas yang terunduh dan preferensi tidak akan dicadangkan.</string>\n    <string name=\"import_download_history_msg\">Berkas yang terunduh tidak akan diimpor. Anda harus mengunduhnya lagi secara manual</string>\n    <string name=\"interface_and_interaction\"><![CDATA[Antarmuka & interaksi]]></string>\n    <string name=\"download_history\">Riwayat pengunduhan</string>\n    <string name=\"download_history_imported\">%1$s telah diimpor ke riwayat unduhan</string>\n    <string name=\"redownload\">Unduh ulang</string>\n    <string name=\"download_archive_error\">Video sudah diunduh. Jika ini bukan perilaku yang diharapkan, silakan periksa arsip unduhan Anda.</string>\n    <string name=\"remux_container_mkv\">Wadah video mux ulang</string>\n    <string name=\"remux_container_mkv_desc\">Mux ulang video ke dalam wadah MKV untuk kompatibilitas yang lebih baik</string>\n    <string name=\"cookies_in_database\">%1$d kuki dari %2$d situs web keseluruhan</string>\n    <string name=\"every_week\">Setiap minggu</string>\n    <string name=\"every_month\">Setiap bulan</string>\n    <string name=\"every_day\">Setiap hari</string>\n    <string name=\"playlist\">Daftar putar</string>\n    <string name=\"edit_preset\">Sunting prasetel</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">%d video</item>\n    </plurals>\n    <string name=\"task_added\">Tugas ditambahkan ke antrean</string>\n    <string name=\"status_downloaded\">Diunduh</string>\n    <string name=\"all_languages\">Semua bahasa</string>\n    <string name=\"preset\">Prasetel</string>\n    <string name=\"prefer_placeholder\">Lebih suka %1$s</string>\n    <string name=\"best_quality_desc\">Unduh format terbaik yang tersedia</string>\n    <string name=\"you_ll_find_your_downloads_here\">Anda dapat menemukan unduhan Anda di sini</string>\n    <string name=\"download_hint\">Ketuk tombol unduh atau bagikan tautan video ke aplikasi ini untuk memulai pengunduhan</string>\n    <string name=\"all\">Semua</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">%d suara</item>\n    </plurals>\n    <string name=\"select_multiple_link\">Pilih dari %1$d tautan</string>\n    <string name=\"custom_format_selection_desc\">Pilih dari format, terjemahan, dan sesuaikan lebih lanjut</string>\n    <string name=\"preset_format_selection_desc\">Unduh secara otomatis menggunakan preferensi format Anda</string>\n    <string name=\"proceed\">Lanjutkan</string>\n    <string name=\"download_queue\">Antrean unduhan</string>\n    <string name=\"show_navigation_drawer\">Tampilkan laci navigasi</string>\n    <string name=\"resume\">Lanjutkan</string>\n    <string name=\"delete\">Hapus</string>\n    <string name=\"media_info\">Info media</string>\n    <string name=\"trouble_shooting\">Pemecahan masalah</string>\n    <string name=\"issue_tracker_hint\">Mengalami masalah? Sebelum melaporkan isu baru, silakan cari pelacak isu kami dahulu. Banyak masalah umum telah diselesaikan dan didokumentasikan di sana.</string>\n    <string name=\"issue_tracker\">Pelacak isu</string>\n    <string name=\"trouble_shooting_desc\">Perbaiki kesalahan umum dan periksa isu yang diketahui</string>\n    <string name=\"saved_urls\">Tautan tersimpan</string>\n    <string name=\"add_new_url\">Tambahkan tautan baru</string>\n    <string name=\"add_to\">Tambahkan ke %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-it/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"delete_info_msg\">Sei sicuro/a di rimuovere «%1$s» dalla tua cronologia di scaricamento\\?</string>\n    <string name=\"url_empty\">Il link non può essere vuoto</string>\n    <string name=\"extract_audio\">Salva come audio</string>\n    <string name=\"create_thumbnail\">Salva la miniatura</string>\n    <string name=\"download\">Download</string>\n    <string name=\"extract_audio_summary\">Scarica e salva l\\'audio invece del video</string>\n    <string name=\"create_thumbnail_summary\">Salva la miniatura del video come un file</string>\n    <string name=\"yt_dlp_update_fail\">Non è possible installare l\\'ultima versione di yt-dlp. Per favore, verifica di essere connesso ad Internet.</string>\n    <string name=\"fetching_info\">Recupero delle informazioni del video…</string>\n    <string name=\"permission_denied\">Permesso negato</string>\n    <string name=\"download_success_msg\">Scaricamento completato</string>\n    <string name=\"download_start_msg\">Scarica «%1$s»</string>\n    <string name=\"fetch_info_error_msg\">Impossibile recuperare le informazioni del video</string>\n    <string name=\"task_running\">Uno scaricamento è già in esecuzione</string>\n    <string name=\"paste_msg\">Incolla URL</string>\n    <string name=\"paste_fail_msg\">Impossibile confrontare l\\'URL negli appunti</string>\n    <string name=\"ytdlp_version\">Versione yt-dlp</string>\n    <string name=\"about_page\">Versione, commenti, aggiornamento automatico</string>\n    <string name=\"back\">Indietro</string>\n    <string name=\"version\">Versione</string>\n    <string name=\"release_desc\">Scopri i changelog e le nuove versioni</string>\n    <string name=\"release\">Ultima versione</string>\n    <string name=\"readme_desc\">Controlla la repository GitHub e il README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Controllato</string>\n    <string name=\"credits\">Crediti</string>\n    <string name=\"custom_command_desc\">Esegui il comando yt-dlp con un template personalizzato</string>\n    <string name=\"advanced_settings\">Avanzate</string>\n    <string name=\"print_details\">Output dettagliato</string>\n    <string name=\"display_settings\">Tema scuro, colore dinamico, lingue</string>\n    <string name=\"dark_theme\">Tema scuro</string>\n    <string name=\"cancel\">Annulla</string>\n    <string name=\"settings_before_download\">Configura prima dello scaricamento</string>\n    <string name=\"settings_before_download_desc\">Configura le preferenze prima dello scaricamento</string>\n    <string name=\"settings_before_download_text\">Configura questo scaricamento</string>\n    <string name=\"error_copied\">Report dell\\'errore copiato negli appunti</string>\n    <string name=\"paste\">Incolla</string>\n    <string name=\"yt_dlp_docs\">Referenze di uso di yt-dlp</string>\n    <string name=\"edit_template_desc\">Il percorso di output e l\\'URL verrano aggiunti dall\\'applicazione.</string>\n    <string name=\"not_convert\">Non convertito</string>\n    <string name=\"format\">Formato</string>\n    <string name=\"convert_audio_format_desc\">La ri-codifica dei file audio comporta una perdita di qualità audio e un aumento delle dimensioni del file.</string>\n    <string name=\"best_quality\">Qualità migliore</string>\n    <string name=\"video_format_preference\">Formato video preferito</string>\n    <string name=\"video_directory\">Cartella video</string>\n    <string name=\"settings\">Impostazioni</string>\n    <string name=\"download_settings_desc\">Generale, formato, comando personalizzato</string>\n    <string name=\"yt_dlp_up_to_date\">Stai usando l\\'ultima versione di yt-dlp</string>\n    <string name=\"download_error_msg\">Impossibile scaricare il file</string>\n    <string name=\"about\">Informazioni</string>\n    <string name=\"general_settings\">Generale</string>\n    <string name=\"language\">Lingua</string>\n    <string name=\"language_settings\">Imposta lingua</string>\n    <string name=\"delete_info\">Rimuovere\\?</string>\n    <string name=\"ytdlp_update\">Clicca per installare l\\'ultima versione di yt-dlp</string>\n    <string name=\"confirm\">Conferma</string>\n    <string name=\"dismiss\">Annulla</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"downloads_history\">Scaricamenti</string>\n    <string name=\"link_copied\">Collegamento copiato negli appunti</string>\n    <string name=\"open_url\">Apri il collegamento</string>\n    <string name=\"remove\">Rimuovi</string>\n    <string name=\"delete_file\">Elimina file</string>\n    <string name=\"credits_desc\">Crediti e software liberi</string>\n    <string name=\"custom_command\">Comando personalizzato</string>\n    <string name=\"custom_command_template\">Template di comando</string>\n    <string name=\"edit\">Modifica</string>\n    <string name=\"start_execute\">Inizia l\\'esecuzione del comando</string>\n    <string name=\"print_details_desc\">Stampa messaggi dettagliati durante lo scaricamento</string>\n    <string name=\"display\">Visualizzazione</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"off\">Disattivato</string>\n    <string name=\"on\">Attivato</string>\n    <string name=\"convert_audio_format\">Converti il formato audio</string>\n    <string name=\"convert_to\">Converti in %1$s</string>\n    <string name=\"video_quality\">Qualità video</string>\n    <string name=\"not_specified\">Non specificato (predefinito)</string>\n    <string name=\"video_quality_desc\">Limita la qualità del video quando sono presenti più video</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"preferred_format_desc\">Formato predefinito quando ne sono forniti molteplici</string>\n    <string name=\"video_format\">Formato video</string>\n    <string name=\"paste_desc\">Clicca «Incolla» per ottenere il collegamento del video dai tuoi appunti.</string>\n    <string name=\"download_desc\">Poi clicca «Scarica» dopo aver aggiustato le sue impostazioni.</string>\n    <string name=\"download_playlist\">Scarica playlist</string>\n    <string name=\"download_playlist_desc\">Scarica più video da una playlist</string>\n    <string name=\"defaults\">Predefinito</string>\n    <string name=\"battery_settings_desc\">Si consiglia di impostare l\\'utilizzo della batteria su «Senza limitazioni» nelle impostazioni di sistema per scaricare in sfondo.</string>\n    <string name=\"concurrent_download_desc\">Scarica più parti di video M3U8/MPD in parallelo</string>\n    <string name=\"download_notification\">Avviso di scaricamento</string>\n    <string name=\"download_range_selection\">Selezione della playlist</string>\n    <string name=\"from\">Inizio</string>\n    <string name=\"to\">Fine</string>\n    <string name=\"invalid_index_range\">Range dell\\'indice invalido</string>\n    <string name=\"playlist_indicator_text\">Scaricando playlist (%1$d/%2$d)…</string>\n    <string name=\"channel_description\">Notifica il processo di scaricamento e i file scaricati</string>\n    <string name=\"close_never_show_again\">Non mostrare più</string>\n    <string name=\"convert_audio\">Converti</string>\n    <string name=\"start_download\">Scarica</string>\n    <string name=\"user_guide\">Guida utente</string>\n    <string name=\"close\">Chiudi</string>\n    <string name=\"open_settings\">Apri le impostazioni</string>\n    <string name=\"download_history_desc\">Controlla e organizza gli scaricamenti nell\\'app, inclusi i file video e audio.</string>\n    <string name=\"options\">Opzioni</string>\n    <string name=\"channel_name\">Scarica</string>\n    <string name=\"check_download_settings_desc\">Controlla le impostazioni di scaricamento e assicurati di avere l\\'ultima versione di yt-dlp prima di utilizzarlo.</string>\n    <string name=\"download_range_desc\">Specifica l\\'intervallo di video da scaricare dalla playlist «%3$s» (da %1$d a %2$d).</string>\n    <string name=\"video_url\">Link del video</string>\n    <string name=\"execute_command_notification\">Esecuzione del comando personalizzato…</string>\n    <string name=\"download_finish_notification\">Scaricamento terminato. Clicca per aprire.</string>\n    <string name=\"additional_settings\">Impostazioni aggiuntive</string>\n    <string name=\"fetching_playlist_info\">Recupero delle informazioni della playlist…</string>\n    <string name=\"show_more_actions\">Mostra più azioni</string>\n    <string name=\"download_notification_desc\">Notifica il processo di scaricamento e di file scaricati</string>\n    <string name=\"download_directory\">Directory degli scaricamenti</string>\n    <string name=\"download_directory_desc\">Seleziona dove conservare i file video e audio</string>\n    <string name=\"audio_directory\">Cartella audio</string>\n    <string name=\"share_success_msg\">Lettura del collegamento video da un contenuto condiviso…</string>\n    <string name=\"share_fail_msg\">Impossibile abbinare l\\'URL al contenuto condiviso</string>\n    <string name=\"subdirectory\">Salva in una sottodirectory</string>\n    <string name=\"battery_configuration\">Configurazione della batteria</string>\n    <string name=\"service_title\">Seal sta scaricando…</string>\n    <string name=\"subdirectory_desc\">Salva i file in cartelle chiamate come i rispettivi siti web</string>\n    <string name=\"permission_issue\">Problema relativo all\\'autorizzazione di archiviazione</string>\n    <string name=\"translate_desc\">Contribuisci a tradurre questa applicazione su Hosted Weblate</string>\n    <string name=\"unknown_error\">Errore sconosciuto</string>\n    <string name=\"battery_configuration_desc\">Ignora l\\'ottimizzazione della batteria per lo scaricamento dell\\'app in sfondo</string>\n    <string name=\"translate\">Traduci</string>\n    <string name=\"permission_issue_desc\">Le directory al di fuori di Download/ e Documenti/ non sono supportate</string>\n    <string name=\"concurrent_download\">Download multi-thread</string>\n    <string name=\"concurrent_download_num\">I thread %d sarebbero utilizzati per scaricare video nativi DASH/HLS in parallelo.</string>\n    <string name=\"prefix\">Modello di percorso</string>\n    <string name=\"embed_subtitles\">Incorpora i sottotitoli</string>\n    <string name=\"embed_subtitles_desc\">Incorpora i sottotitoli nel video se disponibili</string>\n    <string name=\"new_template\">Nuovo modello</string>\n    <string name=\"template_label\">Etichetta</string>\n    <string name=\"remove_template\">Rimuovere\\?</string>\n    <string name=\"remove_template_desc\">Rimuovere «%1$s» dai modelli dei comandi\\?</string>\n    <string name=\"template_selection\">Selezione del modello</string>\n    <string name=\"custom_command_template_desc\">Modifica e gestisci i modelli di comando</string>\n    <string name=\"downloading_indicator_text\">Download in corso…</string>\n    <string name=\"task_canceled\">Scaricamento annullato</string>\n    <string name=\"status_enqueued\">In coda</string>\n    <string name=\"status_completed\">Finito</string>\n    <string name=\"status_downloading\">Scaricamento</string>\n    <string name=\"status_canceled\">Annullato</string>\n    <string name=\"status_fetching_video_info\">Recupero delle informazioni</string>\n    <string name=\"open_file\">Apri il file</string>\n    <string name=\"restart\">Riavvia</string>\n    <string name=\"info_copied\">Informazioni copiate negli appunti</string>\n    <string name=\"github_issue_desc\">Invia una segnalazione di bug o una richiesta per nuove funzioni</string>\n    <string name=\"github_issue\">Segnala un problema su GitHub</string>\n    <string name=\"copy_link\">Copia il collegamento</string>\n    <string name=\"status_error\">Errore</string>\n    <string name=\"copy_error_report\">Copia il rapporto</string>\n    <string name=\"video_resolution\">Risoluzione video</string>\n    <string name=\"video_file_size\">Dimensione del file video</string>\n    <string name=\"export_to_clipboard\">Esporta negli appunti</string>\n    <string name=\"multiselect_item_count\">%1$d file video, %2$d file audio</string>\n    <string name=\"import_from_clipboard\">Importa dagli appunti</string>\n    <string name=\"template_exported\">Modello(i) %1$d esportato(i)</string>\n    <string name=\"template_imported\">Modello(i) %1$d importato(i)</string>\n    <string name=\"recently_added\">Aggiunto di recente</string>\n    <string name=\"delete_multiple_items_msg\">Sei sicuro/sicura di rimuovere %1$d elemento(i) dalla tua cronologia di scaricamento\\?</string>\n    <string name=\"clear_temp_files_count\">%1$d file temporanei eliminati</string>\n    <string name=\"aria2_desc\">Usa aria2c come downloader esterno</string>\n    <string name=\"check_for_updates\">Controlla gli aggiornamenti</string>\n    <string name=\"check_for_updates_desc\">Verifica automatica la versione più recente su GitHub</string>\n    <string name=\"clear_temp_files_info\">I file temporanei possono essere utilizzati per riprendere i download annullati. Sei sicuro/a di eliminare tutti questi file?\n\\n\n\\nPuoi accedere a questi file in %1$s</string>\n    <string name=\"app_up_to_date\">La versione attuale è aggiornata</string>\n    <string name=\"clear_temp_files\">Cancella i file temporanei</string>\n    <string name=\"clear_temp_files_desc\">Elimina tutti i file temporanei dalla directory temporanea</string>\n    <string name=\"app_update_failed\">Impossibile eseguire l\\'aggiornamento alla versione più recente</string>\n    <string name=\"update\">Aggiorna</string>\n    <string name=\"sponsorblock_categories\">Categorie SponsorBlock</string>\n    <string name=\"download_task_count\">%1$d attività di scaricamento</string>\n    <string name=\"sponsorblock_desc\">Rimuovi o segna i segmenti dei video con l\\'API SponsorBlock</string>\n    <string name=\"sponsorblock_categories_desc\">Specifica le categorie SponsorBlock da rimuovere o segnare nel file video</string>\n    <string name=\"cookies_desc\">Utilizzare i cookie formattati Netscape per i download</string>\n    <string name=\"private_mode\">Incognito</string>\n    <string name=\"private_mode_desc\">Disattiva la cronologia degli scaricamenti</string>\n    <string name=\"multiselect_mode\">Modalità multiselezione</string>\n    <string name=\"dynamic_color\">Colore dinamico</string>\n    <string name=\"dynamic_color_desc\">Applica i colori degli sfondi al tema dell\\'applicazione</string>\n    <string name=\"download_with_cellular\">Scarica con dati mobili</string>\n    <string name=\"download_with_cellular_desc\">Consenti lo scaricamento di contenuti multimediali quando si è connessi alle reti a pagamento</string>\n    <string name=\"download_disabled_with_cellular\">Lo scaricamento con la rete mobile è disabilitato in base alle impostazioni</string>\n    <string name=\"file_unavailable\">Il file non è più disponibile</string>\n    <string name=\"network\">Rete</string>\n    <string name=\"rate_limit\">Limite di velocità</string>\n    <string name=\"rate_limit_desc\">Limita la velocità massima degli scaricamenti</string>\n    <string name=\"max_rate\">Velocità massima</string>\n    <string name=\"high_contrast\">Tema scuro ad alto contrasto</string>\n    <string name=\"invalid_input\">Inserimento non valido</string>\n    <string name=\"lowest_quality\">Qualità più bassa</string>\n    <string name=\"unavailable\">Non disponibile</string>\n    <string name=\"format_settings_desc\">Formato file, qualità video, sottotitoli</string>\n    <string name=\"general_settings_desc\">Versione Yt-dlp, notifica, playlist</string>\n    <string name=\"disable_preview\">Disattiva l\\'anteprima</string>\n    <string name=\"crop_artwork\">Ritaglia immagine</string>\n    <string name=\"crop_artwork_desc\">Ritaglia l\\'immagine incorporata in un quadrato</string>\n    <string name=\"network_settings_desc\">Limite di velocità, scaricatore, cookie</string>\n    <string name=\"disable_preview_desc\">Nessuna visualizzazione delle miniature durante il download</string>\n    <string name=\"privacy\">Privacy</string>\n    <string name=\"use_custom_command\">Usa un comando personalizzato</string>\n    <string name=\"private_directory\">Directory privata</string>\n    <string name=\"private_directory_desc\">Memorizza gli scaricamenti in una directory nascosta</string>\n    <string name=\"select_all\">Seleziona tutto</string>\n    <string name=\"selected_item_count\">%1$d selezionato/i</string>\n    <string name=\"download_selection_desc\">Seleziona i video da scaricare dalla playlist «%1$s»</string>\n    <string name=\"video_only\">Video (senza audio)</string>\n    <string name=\"format_selection_desc\">Seleziona il formato da scaricare prima di avviare lo scaricamento</string>\n    <string name=\"suggested\">Suggerito</string>\n    <string name=\"format_selection\">Selezione del formato</string>\n    <string name=\"generate_new_cookies\">Genera nuovi cookie</string>\n    <string name=\"matrix_space\">Spazio Matrix</string>\n    <string name=\"cookies\">Cookie</string>\n    <string name=\"use_cookies\">Usa i cookie</string>\n    <string name=\"remove_cookie_profile_desc\">Rimuovere i cookie per «%1$s»? Nota che i cookie salvati per questo sito non saranno rimossi.</string>\n    <string name=\"custom_command_enabled_hint\">Alcune opzioni non sono disponibili quando si utilizza un comando personalizzato</string>\n    <string name=\"how_does_it_work\">Come funziona\\?</string>\n    <string name=\"telegram_channel\">Canale Telegram</string>\n    <string name=\"cookies_usage_msg\">La scaricamento da alcuni siti richiede le informazioni di autenticazione dell\\'account. Clicca su „Genera nuovi cookie“, inserisci l\\'URL del sito web e poi accedi con il tuo account nella pagina del browser: l\\'applicazione lo genererà per te.</string>\n    <string name=\"abs_hint\">La maggior parte delle piattaforme di streaming video fornisce audio e video separatamente; è possibile selezionare e unire un formato solo audio con un formato solo video in un unico video.</string>\n    <string name=\"add\">Aggiungi</string>\n    <string name=\"show_logs\">Mostra registro</string>\n    <string name=\"logs\">Registro</string>\n    <string name=\"title_activity_share\">Scaricamento rapido</string>\n    <string name=\"video_creator_sample_text\">Testo di esempio del creatore di video</string>\n    <string name=\"subtitle\">Sottotitolo</string>\n    <string name=\"subtitle_language\">Lingue dei sottotitoli</string>\n    <string name=\"copy_log\">Copia il registro</string>\n    <string name=\"edit_shortcuts\">Modifica le scorciatoie</string>\n    <string name=\"shortcuts\">Scorciatoie</string>\n    <string name=\"running_tasks\">Attività in esecuzione</string>\n    <string name=\"sdcard_directory\">Cartella della scheda SD</string>\n    <string name=\"auto_subtitle_desc\">Scarica i sottotitoli autogenerati</string>\n    <string name=\"download_subtitles\">Scarica i sottotitoli</string>\n    <string name=\"subtitle_desc\">Lingue, sottotitoli incorporati, sottotitoli automatici</string>\n    <string name=\"clear\">Cancella</string>\n    <string name=\"edit_shortcuts_desc\">Modifica le scorciatoie personalizzate che possono essere utilizzate per comporre i modelli di comando.</string>\n    <string name=\"auto_subtitle\">Sottotitoli automatici</string>\n    <string name=\"video_title_sample_text\">Titolo del video testo di esempio</string>\n    <string name=\"subtitle_sponsorblock\">I sottotitoli possono risultare non sincronizzati quando si rimuovono i segmenti SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Per incorporare i sottotitoli, i video verranno rimuxati in un contenitore mkv. Puoi usare VLC Media Player o altri programmi compatibili per guardare i video con i sottotitoli incorporati.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"lowest_bitrate\">Bitrate minore</string>\n    <string name=\"format_sorting\">Assortimento formato</string>\n    <string name=\"audio_format\">Formato audio</string>\n    <string name=\"no_downloaded_media\">Nessun media scaricato</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Attivare la funzione sperimentale\\?</string>\n    <string name=\"clip_video_dialog_msg\">I download che utilizzano questa funzione saranno delegati a FFmpeg per scaricare sezioni selezionate del video; questa funzione è ancora sperimentale e il taglio non sarà completamente accurato, non tutti i formati supportano questa funzione e si potrebbero verificare velocità di scaricamento più basse.</string>\n    <string name=\"update_channel\">Canale aggiornamento</string>\n    <string name=\"auto_update\">Aggiornamento automatico</string>\n    <string name=\"enable_auto_update\">Abilita l\\'aggiornamento automatico</string>\n    <string name=\"audio_format_preference\">Formato audio preferito</string>\n    <string name=\"rename\">Rinomina</string>\n    <string name=\"clear_all_cookies_desc\">Eliminare tutti i cookie salvati nell\\'app\\?</string>\n    <string name=\"update_channel_desc\">Installa build pre-rilascio per vedere in anteprima nuove funzioni e cambiamenti.\n\\n\n\\nPossono esserci delle instabilità in queste versioni, quindi perfavore non esitare a darci un commento se trovi qualche problema per aiutarci a migliorare l\\'applicazione in futuro.</string>\n    <string name=\"clip_start\">Inizio</string>\n    <string name=\"share\">Condividi</string>\n    <string name=\"stable_channel\">Stabile</string>\n    <string name=\"pre_release_channel\">Anteprima</string>\n    <string name=\"clip_end\">Fine</string>\n    <string name=\"unlimited\">Illimitato</string>\n    <string name=\"audio_quality_desc\">Limita bitrate audio quando multiple qualità sono presenti</string>\n    <string name=\"audio_quality\">Qualità audio</string>\n    <string name=\"format_sorting_desc\">Assortimento formati con la opzione -S di yt-dlp</string>\n    <string name=\"title\">Titolo</string>\n    <string name=\"minute\">minuto</string>\n    <string name=\"clear_all_cookies\">Cancella tutti i cookie</string>\n    <string name=\"second\">secondo</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"feedback\">Commenti</string>\n    <string name=\"sponsors\">Sponsor</string>\n    <string name=\"clip_video_desc\">Crea videoclip nella pagina di selezione del formato</string>\n    <string name=\"discard\">Scarta</string>\n    <string name=\"apply\">Applica</string>\n    <string name=\"clip_video\">Video clip</string>\n    <string name=\"sponsor_desc\">Sostieni questa applicazione sponsorizzando su GitHub</string>\n    <string name=\"sponsor_msg\">Seal sarà sempre libero e gratuito per tutti. Se ti piace, considera la possibilità di sponsorizzarmi su GitHub!</string>\n    <string name=\"import_from_preferences\">Importa</string>\n    <string name=\"temporary_directory_desc\">Salva file temporanei nella directory interna</string>\n    <string name=\"msg_from_developer\">Messaggio dello sviluppatore</string>\n    <string name=\"sponsor_msg2\">Grazie mille!</string>\n    <string name=\"auto_update_disabled_msg\">L\\'aggiornamento automatico non è disponibile per le build %1$s. Se non hai installato %1$s sul dispositivo, o se vorresti provare in anteprima le nuove funzionalità di Seal, considera %2$s.</string>\n    <string name=\"okay\">Va bene</string>\n    <string name=\"got_it\">Ho capito</string>\n    <string name=\"feature_unavailable\">Funzione non disponibile</string>\n    <string name=\"switch_to_github_builds\">passando alle build di GitHub</string>\n    <string name=\"no_custom_command_tasks\">Nessuna attività di comando personalizzata</string>\n    <string name=\"convert_subtitle_desc\">Convertisci i sottotitoli in un altro formato</string>\n    <string name=\"split_video\">Dividi il video</string>\n    <string name=\"convert_subtitle\">Converti i sottotitoli</string>\n    <string name=\"download_video_desc\">Scarica i video dall\\'URL</string>\n    <string name=\"unknown_error_title\">Ops! Qualcosa è andato storto</string>\n    <string name=\"copy_and_exit\">Copia ed esci</string>\n    <string name=\"split_video_msg\">Il video sarà diviso in capitoli %1$d</string>\n    <string name=\"expand\">Espandi</string>\n    <string name=\"new_task\">Nuova attività di scaricamento</string>\n    <string name=\"start\">Inizia</string>\n    <string name=\"edit_template\">Modifica «%1$s»</string>\n    <string name=\"ytdlp_update_action\">Aggiorna yt-dlp</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"quality\">Qualità</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp è uno strumento da riga di comando per scaricare i video. Seal permette di usare facilmente yt-dlp provvedendo un\\'intuitiva interfaccia grafica e altre funzionalità aggiuntive.\n\\n\n\\nPer un utilizzo avanzato di yt-dlp, Seal permette la creazione, l\\'esecuzione e il salvataggio di comandi personalizzati, come fosse un terminale.\n\\n\n\\nDurante l\\'utilizzo di comandi personalizzati la maggior parte delle opzioni dell\\'interfaccia grafica verranno disabilitate.</string>\n    <string name=\"enable_notifications_desc\">L\\'app ha bisogno del tuo permesso per inviare le notifiche sullo stato e progresso del download.</string>\n    <string name=\"prefer_compatibility_desc\">Preferisci il formato MP4(H.264) per la condivisione con altre app</string>\n    <string name=\"commands\">Comandi</string>\n    <string name=\"unknown\">Sconosciuto</string>\n    <string name=\"learn_more\">Impara di più</string>\n    <string name=\"download_type\">Tipo di download</string>\n    <string name=\"custom_command_directory\">Cartella dei comandi personalizzati</string>\n    <string name=\"custom_command_directory_desc\">Specifica la cartella di output quando si utilizzano comandi personalizzati</string>\n    <string name=\"set_directory_desc\">Clicca per impostare una cartella</string>\n    <string name=\"format_preference\">Formati preferiti</string>\n    <string name=\"disabled\">Disabilita</string>\n    <string name=\"disable\">Disabilita</string>\n    <string name=\"auto\">Automatico</string>\n    <string name=\"proxy_desc\">Usare il proxy per le connessioni internet</string>\n    <string name=\"refresh_cookies_desc\">Clicca per aprire una pagina web per generare nuovi cookie:</string>\n    <string name=\"enable_notifications\">Abilitare le notifiche\\?</string>\n    <string name=\"remove_multiple_templates_msg\">Rimuovere %1$s dai modelli di comando definitivamente?</string>\n    <string name=\"legacy\">Sperimentale</string>\n    <string name=\"download_archive\">Archivio dei download</string>\n    <string name=\"download_archive_desc\">Registra gli ID video scaricati in un archivio per evitare download duplicati</string>\n    <string name=\"edit_file\">Modifica file</string>\n    <string name=\"save\">Salva</string>\n    <string name=\"clear_download_archive_desc\">Rimuovere definitivamente %1$s dal file di archivio?</string>\n    <string name=\"embed_metadata_desc\">Incorpora metadati e miniatura video nel file audio</string>\n    <string name=\"use_format_sorting\">Utilizza l\\'ordinamento dei formati</string>\n    <string name=\"force_ipv4\">Forza ipv4</string>\n    <string name=\"force_ipv4_desc\">Effettuare tutte le connessioni tramite IPv4</string>\n    <string name=\"embed_metadata\">Incorpora metadati</string>\n    <string name=\"allow_once\">Consenti solo una volta</string>\n    <string name=\"allow_always\">Consenti sempre</string>\n    <string name=\"dont_allow\">Non consentire</string>\n    <string name=\"download_with_cellular_request\">Consentire il download con dati mobili?</string>\n    <string name=\"merge_audiostream\">Unisci più fonti audio</string>\n    <string name=\"merge_audiostream_desc\">Consenti l\\'unione di più fonti audio in un unico file</string>\n    <string name=\"subdirectory_hint\">I tuoi download verranno salvati come:</string>\n    <string name=\"ua_header\">Intestazione agente utente</string>\n    <string name=\"keep_subtitle_files\">Conserva i file dei sottotitoli</string>\n    <string name=\"required\">Necessario</string>\n    <string name=\"show_all_items\">Mostra tutti i %1$d elementi</string>\n    <string name=\"export_to_file\">Esporta su file</string>\n    <string name=\"custom\">Personalizzato</string>\n    <string name=\"restrict_filenames\">Limita i nomi dei file</string>\n    <string name=\"restrict_filenames_desc\">Limita i nomi dei file a caratteri specifici per garantire la compatibilità</string>\n    <string name=\"website\">Sito</string>\n    <string name=\"playlist_title\">Titolo della playlist</string>\n    <string name=\"folder_picker\">Selettore di cartelle</string>\n    <string name=\"prefer_quality_desc\">Preferisci i formati AV1, VP9 o H.265 per la visione nelle app compatibili</string>\n    <string name=\"output_template\">Modello di output</string>\n    <string name=\"presets\">Predefinite</string>\n    <string name=\"output_template_desc\">Specificare il modello per i nomi dei file di output</string>\n    <string name=\"system_settings\">Impostazioni di sistema</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d oggetto</item>\n        <item quantity=\"many\">%d oggetti</item>\n        <item quantity=\"other\">%d oggetti</item>\n    </plurals>\n    <string name=\"clear_download_archive\">Cancellare l\\'archivio dei download?</string>\n    <string name=\"download_archive_error\">Il video è stato scaricato con successo. Se questo è stato un comportamento inaspettato, controllare l\\'archivio dei download.</string>\n    <string name=\"backup_type\">Tipo di backup</string>\n    <string name=\"export_to\">Esportare in</string>\n    <string name=\"auto_translated_subtitles\">Sottotitoli tradotti automaticamente</string>\n    <string name=\"auto_translated_subtitles_msg\">I sottotitoli automaticamente tradotti saranno disponibili nei download. I sottotitoli possono essere inaccurati e difficile da capire.</string>\n    <string name=\"remember_for_next_download\">Ricorda per i prossimi download</string>\n    <string name=\"subtitle_language_desc\">Lingua dei sottotitoli da scaricare nella sezione formato automatico, separati da virgole.</string>\n    <string name=\"look_and_feel\">Aspetto</string>\n    <string name=\"interface_and_interaction\">Interfaccia ed interrogazioni</string>\n    <string name=\"use_previous_selection\">Usa selezione precedente</string>\n    <string name=\"none\">Nulla</string>\n    <string name=\"reset\">Reset</string>\n    <string name=\"search_in_subtitles\">Cerca nei sottotitoli</string>\n    <string name=\"no_thanks\">No grazie</string>\n    <string name=\"update_language_msg\">La lingua seguente verrà aggiunta alle preferenze per i download futuri:</string>\n    <string name=\"export_backup\">Esportare</string>\n    <string name=\"import_backup\">Importare</string>\n    <string name=\"full_backup\">Backup completo</string>\n    <string name=\"file\">File</string>\n    <string name=\"clipboard\">Appunti</string>\n    <string name=\"import_from\">Importare da</string>\n    <string name=\"export_download_history\">Esportare la cronologia sei download?</string>\n    <string name=\"import_download_history\">Importare la cronologia dei download?</string>\n    <string name=\"import_download_history_msg\">I file scaricati non saranno importati. Dovrai scaricarli di nuovo manualmente</string>\n    <string name=\"export_download_history_msg\">Esportazione in corso di %1$s dalla cronologia dei download. I file scaricati e le preferenze non saranno esportate nel backup.</string>\n    <string name=\"download_history\">Cronologia dei download</string>\n    <string name=\"update_subtitle_languages\">Aggiornare le lingue dei sottotitoli?</string>\n    <string name=\"download_history_imported\">%1$s importato dai download con successo</string>\n    <string name=\"redownload\">Riscarica</string>\n    <string name=\"search_in_downloads\">Cerca nei file scaricati</string>\n    <string name=\"search\">Cerca</string>\n    <string name=\"every_day\">Ogni giorno</string>\n    <string name=\"every_week\">Ogni settimana</string>\n    <string name=\"every_month\">Ogni mese</string>\n    <string name=\"all_languages\">Tutte le lingue</string>\n    <string name=\"proceed\">Continua</string>\n    <string name=\"cookies_in_database\">%1$d cookie da %2$d siti web in totale</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d video</item>\n        <item quantity=\"many\">%d video</item>\n        <item quantity=\"other\">%d video</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d audio</item>\n        <item quantity=\"many\">%d audio</item>\n        <item quantity=\"other\">%d audio</item>\n    </plurals>\n    <string name=\"playlist\">Playlist</string>\n    <string name=\"prefer_placeholder\">Preferire %1$s</string>\n    <string name=\"preset\">Preimpostazione</string>\n    <string name=\"custom_format_selection_desc\">Scegli tra i formati, i sottotitoli e le ulteriori personalizzazioni</string>\n    <string name=\"edit_preset\">Modifica preset</string>\n    <string name=\"preset_format_selection_desc\">Scarica automaticamente usando le tue preferenze di formattazione</string>\n    <string name=\"best_quality_desc\">Scarica nel formato migliore</string>\n    <string name=\"task_added\">Attività aggiunta alla coda</string>\n    <string name=\"remux_container_mkv\">Contenitore video Remux</string>\n    <string name=\"remux_container_mkv_desc\">Remux dei video in un contenitore MKV per una migliore compatibilità</string>\n    <string name=\"status_downloaded\">Scaricato</string>\n    <string name=\"you_ll_find_your_downloads_here\">Troverai qui i tuoi download</string>\n    <string name=\"all\">Tutto</string>\n    <string name=\"select_multiple_link\">Seleziona da %1$d link</string>\n    <string name=\"download_hint\">Tocca il pulsante di download o condividi un link video a questa applicazione per avviare il download</string>\n    <string name=\"download_queue\">Scarica coda</string>\n    <string name=\"show_navigation_drawer\">Mostra il cassetto di navigazione</string>\n    <string name=\"resume\">Continuare</string>\n    <string name=\"delete\">Cancellare</string>\n    <string name=\"media_info\">Info media</string>\n    <string name=\"trouble_shooting\">Risoluzione dei problemi</string>\n    <string name=\"issue_tracker\">Tracker dei problemi</string>\n    <string name=\"trouble_shooting_desc\">Correggi gli errori comuni e verifica i problemi noti</string>\n    <string name=\"issue_tracker_hint\">Hai riscontrato un errore? Prima di segnalare un nuovo problema, cerca nel nostro issue tracker. Molti problemi comuni sono già stati affrontati e documentati lì.</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-iw/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"create_thumbnail_summary\">שמור את התמונה הממוזערת של הסרטון כקובץ</string>\n    <string name=\"video_directory\">תיקיית סרטונים</string>\n    <string name=\"extract_audio\">שמור כשמע</string>\n    <string name=\"settings\">הגדרות</string>\n    <string name=\"download_settings_desc\">כללי, פורמט, פקודה מותאמת אישית</string>\n    <string name=\"download\">הורדה</string>\n    <string name=\"url_empty\">הקישור לא יכול להיות ריק</string>\n    <string name=\"extract_audio_summary\">הורד ושמור שמע במקום סרטון</string>\n    <string name=\"create_thumbnail\">שמור תמונה ממוזערת</string>\n    <string name=\"yt_dlp_up_to_date\">משתמש בגרסה העדכנית ביותר של yt-dlp</string>\n    <string name=\"fetching_info\">משיג מידע על הסרטון…</string>\n    <string name=\"back\">אחורה</string>\n    <string name=\"version\">גרסה</string>\n    <string name=\"delete_file\">מחיקת קובץ</string>\n    <string name=\"about\">אודות</string>\n    <string name=\"release_desc\">חפש יומני שינויים וגרסאות חדשות</string>\n    <string name=\"about_page\">גרסה, משוב, עדכון אוטומטי</string>\n    <string name=\"video\">וידאו</string>\n    <string name=\"release\">המהדורה האחרונה</string>\n    <string name=\"readme_desc\">בדוק את מאגר GitHub ואת ה-README</string>\n    <string name=\"audio\">אודיו</string>\n    <string name=\"dismiss\">ביטול</string>\n    <string name=\"general_settings\">כללי</string>\n    <string name=\"remove\">הסרה</string>\n    <string name=\"download_success_msg\">ההורדה הושלמה</string>\n    <string name=\"delete_info\">להסיר\\?</string>\n    <string name=\"delete_info_msg\">להסיר לצמיתות את \\\"%1$s\\\" מהיסטוריית ההורדות?</string>\n    <string name=\"confirm\">אישור</string>\n    <string name=\"downloads_history\">הורדות</string>\n    <string name=\"yt_dlp_update_fail\">שגיאה בהתקנת הגרסה החדשה ביותר של yt-dlp, אנא ודא שהמכשיר מחובר לאינטרנט.</string>\n    <string name=\"permission_denied\">הגישה נדחתה</string>\n    <string name=\"download_error_msg\">לא ניתן להוריד את הקובץ הזה</string>\n    <string name=\"download_start_msg\">מוריד את \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">לא ניתן להשיג את מידע הסרטון</string>\n    <string name=\"language\">שפת תצוגה</string>\n    <string name=\"language_settings\">הגדר שפת תצוגה</string>\n    <string name=\"task_running\">משימת הורדה כבר פועלת</string>\n    <string name=\"paste_msg\">הדבק כתובת URL</string>\n    <string name=\"paste_fail_msg\">לא נמצאה כתובת URL בלוח</string>\n    <string name=\"ytdlp_version\">גרסת yt-dlp</string>\n    <string name=\"ytdlp_update\">לחץ כדי להתקין את גרסת yt-dlp העדכנית ביותר</string>\n    <string name=\"link_copied\">הקישור הועתק ללוח</string>\n    <string name=\"open_url\">פתיחת קישור</string>\n    <string name=\"checked\">מסומן</string>\n    <string name=\"credits\">תודות</string>\n    <string name=\"credits_desc\">תודות ותוכנות תומכות</string>\n    <string name=\"custom_command\">פקודה מותאמת אישית</string>\n    <string name=\"audio_format_preference\">פורמט אודיו מועדף</string>\n    <string name=\"import_from_preferences\">ייבוא</string>\n    <string name=\"second\">שניה</string>\n    <string name=\"minute\">דקה</string>\n    <string name=\"advanced_settings\">מתקדם</string>\n    <string name=\"print_details\">פלט מפורט</string>\n    <string name=\"defaults\">ברירת מחדל</string>\n    <string name=\"channel_name\">הורדה</string>\n    <string name=\"video_url\">קישור לסרטון</string>\n    <string name=\"options\">אפשרויות</string>\n    <string name=\"no_downloaded_media\">לא הורדה מדיה</string>\n    <string name=\"enable_experimental_feature\">להפעיל תכונה ניסיונית?</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"downloading_indicator_text\">הורדה בתהליך…</string>\n    <string name=\"update_channel\">ערוץ עדכון</string>\n    <string name=\"display_settings\">ערכת נושא כהה, ערכת נושא דינאמית, שפות</string>\n    <string name=\"download_finish_notification\">ההורדה הסתיימה. הקש לפתיחה.</string>\n    <string name=\"execute_command_notification\">מפעיל פקודות מותאמות אישית…</string>\n    <string name=\"concurrent_download_desc\">הורד במקביל חלקים נוספים של סרטוני וידאו M3U8/MPD</string>\n    <string name=\"additional_settings\">הגדרות נוספות</string>\n    <string name=\"prefix\">קידומת</string>\n    <string name=\"remove_template_desc\">להסיר לצמיתות את \\\"%1$s\\\" מתבניות הפקודה?</string>\n    <string name=\"info_copied\">המידע הועתק ללוח</string>\n    <string name=\"new_template\">תבנית חדשה</string>\n    <string name=\"app_up_to_date\">הגרסה המותקנת היא העדכנית ביותר</string>\n    <string name=\"file_unavailable\">הקובץ הזה אינו זמין יותר</string>\n    <string name=\"download_task_count\">%1$d משימות הורדה</string>\n    <string name=\"quality\">איכות</string>\n    <string name=\"enable_notifications\">הפעל התראות?</string>\n    <string name=\"disable\">השבתה</string>\n    <string name=\"lowest_quality\">האיכות הנמוכה ביותר</string>\n    <string name=\"running_tasks\">משימות פועלות</string>\n    <string name=\"shortcuts\">קיצורים</string>\n    <string name=\"subtitle_desc\">שפות, הטמעת כתוביות, כתוביות אוטומטיות</string>\n    <string name=\"copy_log\">העתק לוג</string>\n    <string name=\"pre_release_channel\">תצוגה מקדימה</string>\n    <string name=\"stable_channel\">יציב</string>\n    <string name=\"enable_auto_update\">הפעלת עדכון אוטומטי</string>\n    <string name=\"discard\">השלכה</string>\n    <string name=\"sponsor\">חסות</string>\n    <string name=\"feedback\">משוב</string>\n    <string name=\"convert_subtitle\">המרת כתוביות</string>\n    <string name=\"sponsor_msg2\">תודה רבה לך!</string>\n    <string name=\"split_video\">פיצול וידאו</string>\n    <string name=\"convert_subtitle_desc\">המר את הכתוביות לפורמט אחר</string>\n    <string name=\"unknown_error_title\">אופס! משהו השתבש</string>\n    <string name=\"copy_and_exit\">העתקה ויציאה</string>\n    <string name=\"status_error\">שגיאה</string>\n    <string name=\"export_to_clipboard\">ייצוא ללוח</string>\n    <string name=\"import_from_clipboard\">ייבוא מהלוח</string>\n    <string name=\"video_file_size\">גודל קובץ וידאו</string>\n    <string name=\"template_exported\">יוצאו %1$d תבניות</string>\n    <string name=\"recently_added\">נוסף לאחרונה</string>\n    <string name=\"check_for_updates_desc\">בדוק אוטומטית את הגרסה העדכנית ביותר ב-GitHub</string>\n    <string name=\"download_selection_desc\">בחר סרטונים להורדה מהפלייליסט \\\"%1$s\\\"</string>\n    <string name=\"select_all\">בחר הכל</string>\n    <string name=\"selected_item_count\">%1$d נבחרו</string>\n    <string name=\"crop_artwork_desc\">חתוך את התמונה המוטמעת לריבוע</string>\n    <string name=\"format_selection_desc\">בחר את הפורמט להורדה לפני תחילת ההורדה</string>\n    <string name=\"title_activity_share\">הורדה מהירה</string>\n    <string name=\"video_title_sample_text\">כותרת סרטון לדוגמה</string>\n    <string name=\"download_subtitles\">הורדת כתוביות</string>\n    <string name=\"subtitle_language\">שפת כתוביות</string>\n    <string name=\"sponsors\">נותני חסות</string>\n    <string name=\"rename\">שינוי שם</string>\n    <string name=\"audio_format\">פורמט אודיו</string>\n    <string name=\"switch_to_github_builds\">מעבר ל-GitHub builds</string>\n    <string name=\"got_it\">הבנתי</string>\n    <string name=\"okay\">אישור</string>\n    <string name=\"feature_unavailable\">התכונה לא זמינה</string>\n    <string name=\"download_video_desc\">הורד סרטונים מכתובת האתר</string>\n    <string name=\"expand\">הרחבה</string>\n    <string name=\"new_task\">משימת הורדה חדשה</string>\n    <string name=\"start\">התחלה</string>\n    <string name=\"edit_template\">עריכת \\\"%1$s\\\"</string>\n    <string name=\"clip_end\">סיום</string>\n    <string name=\"status_downloading\">מוריד</string>\n    <string name=\"status_canceled\">בוטל</string>\n    <string name=\"copy_link\">העתק קישור</string>\n    <string name=\"copy_error_report\">העתק דו\\\"ח</string>\n    <string name=\"video_resolution\">רזולוציית וידאו</string>\n    <string name=\"template_imported\">יובאו %1$d תבניות</string>\n    <string name=\"clear_temp_files_count\">נמחקו %1$d קבצים זמניים</string>\n    <string name=\"clear_temp_files_info\">ניתן להשתמש בקבצים זמניים כדי לחדש הורדות שבוטלו. האם אתה בטוח שברצונך למחוק את כל הקבצים האלה?\n\\n\n\\nאתה יכול לגשת לקבצים האלה ב-%1$s</string>\n    <string name=\"private_mode_desc\">השבת היסטוריית הורדות</string>\n    <string name=\"download_with_cellular_desc\">אפשר הורדה גם כאשר אתה מחובר לרשת נמדדת</string>\n    <string name=\"high_contrast\">ערכת נושא כהה עם ניגודיות גבוהה</string>\n    <string name=\"multiselect_mode\">מצב בחירה מרובה</string>\n    <string name=\"private_mode\">מצב אנונימי</string>\n    <string name=\"suggested\">מוצע</string>\n    <string name=\"telegram_channel\">ערוץ טלגרם</string>\n    <string name=\"auto_subtitle\">כתוביות אוטומטיות</string>\n    <string name=\"show_logs\">הצג יומן</string>\n    <string name=\"logs\">לוג</string>\n    <string name=\"edit_shortcuts_desc\">ערוך את הקיצורים המותאמים אישית שניתן להשתמש בהם כדי ליצור תבניות פקודות.</string>\n    <string name=\"sponsor_msg\">Seal יהיה תמיד קוד פתוח ובחינם לכולם. אם אתה אוהב את זה, בבקשה שקול לתת לי חסות ב-GitHub!</string>\n    <string name=\"clear_all_cookies_desc\">האם למחוק לצמיתות את כל העוגיות המאוחסנות באפליקציה?</string>\n    <string name=\"clip_video_desc\">צור קטעי וידאו בדף בחירת הפורמט</string>\n    <string name=\"proxy\">פרוקסי</string>\n    <string name=\"proxy_desc\">השתמש בפרוקסי כדי להתחבר לאינטרנט</string>\n    <string name=\"legacy\">מיושן</string>\n    <string name=\"enable_notifications_desc\">היישום צריך את ההרשאה שלך כדי להציג התראות לגבי סטטוס הורדה והתקדמות.</string>\n    <string name=\"clip_video_dialog_msg\">הורדות המשתמשות בתכונה זו יואצלו ל-FFmpeg להורדת קטעים נבחרים של הסרטון, תכונה זו עדיין ניסיונית והחיתוך לא יהיה מדויק לחלוטין. לא כל הפורמטים תומכים בתכונה זו וייתכן שתחווה מהירויות הורדה איטיות יותר.</string>\n    <string name=\"edit\">עריכה</string>\n    <string name=\"custom_command_template\">תבנית פקודה</string>\n    <string name=\"format\">פורמט</string>\n    <string name=\"video_quality\">איכות וידאו</string>\n    <string name=\"to\">סיום</string>\n    <string name=\"invalid_index_range\">אינדקס לא חוקי (מחוץ לטווח)</string>\n    <string name=\"audio_directory\">תיקיית אודיו</string>\n    <string name=\"download_directory_desc\">בחר היכן לאחסן קובצי וידאו/אודיו</string>\n    <string name=\"remove_template\">אישור הסרה</string>\n    <string name=\"use_cookies\">השתמש בעוגיות</string>\n    <string name=\"error_copied\">דו\\\"ח שגיאה הועתק ללוח</string>\n    <string name=\"open_settings\">פתח הגדרות</string>\n    <string name=\"convert_to\">המרה ל-%1$s</string>\n    <string name=\"rate_limit_desc\">הגבל את מהירות ההורדה</string>\n    <string name=\"generate_new_cookies\">צור עוגיות חדשות</string>\n    <string name=\"crop_artwork\">חתוך תמונת אלבום</string>\n    <string name=\"check_for_updates\">חפש עדכונים</string>\n    <string name=\"use_custom_command\">השתמש בפקודה מותאמת אישית</string>\n    <string name=\"convert_audio\">המרה</string>\n    <string name=\"download_disabled_with_cellular\">הורדה באמצעות רשת סלולרית מושבתת בהגדרות שלך</string>\n    <string name=\"paste\">הדבק</string>\n    <string name=\"download_playlist\">הורדת פלייליסט</string>\n    <string name=\"from\">התחלה</string>\n    <string name=\"battery_configuration\">תצורת סוללה</string>\n    <string name=\"template_selection\">בחירת תבנית</string>\n    <string name=\"how_does_it_work\">איך זה עובד?</string>\n    <string name=\"follow_system\">מערכת</string>\n    <string name=\"update\">עדכון</string>\n    <string name=\"disable_preview\">השבת תצוגה מקדימה</string>\n    <string name=\"privacy\">פרטיות</string>\n    <string name=\"display\">תצוגה</string>\n    <string name=\"dark_theme\">ערכת נושא כהה</string>\n    <string name=\"on\">מופעל</string>\n    <string name=\"off\">כבוי</string>\n    <string name=\"cancel\">ביטול</string>\n    <string name=\"settings_before_download\">הגדרה לפני הורדה</string>\n    <string name=\"settings_before_download_text\">התאם הורדה זו</string>\n    <string name=\"settings_before_download_desc\">הגדר העדפות לפני הורדה</string>\n    <string name=\"thumbnail\">תמונה ממוזערת</string>\n    <string name=\"not_convert\">ללא המרה</string>\n    <string name=\"video_quality_desc\">הגבל את איכות הווידאו כאשר קיימות מספר אופציות</string>\n    <string name=\"not_specified\">לא צוין (ברירת מחדל)</string>\n    <string name=\"video_format_preference\">פורמט וידאו מועדף</string>\n    <string name=\"video_format\">פורמט וידאו</string>\n    <string name=\"start_download\">הורדה</string>\n    <string name=\"close\">סגור</string>\n    <string name=\"close_never_show_again\">אל תציג שוב</string>\n    <string name=\"user_guide\">מדריך למשתמש</string>\n    <string name=\"paste_desc\">לחץ \\\"הדבק\\\" כדי לקבל קישור לוידאו מהלוח שלך.</string>\n    <string name=\"download_desc\">ואז לחץ \\\"הורדה\\\" אחרי התאמת ההגדרות האלה.</string>\n    <string name=\"download_history_desc\">בדוק ונהל הורדות מתוך האפליקציה, כולל סרטונים וקובצי אודיו.</string>\n    <string name=\"embed_subtitles_desc\">הטמע כתוביות בסרטון אם זמינות</string>\n    <string name=\"download_playlist_desc\">הורדת מספר סרטונים מתוך פלייליסט</string>\n    <string name=\"channel_description\">הצג התראה על התקדמות והשלמת הורדות</string>\n    <string name=\"share_fail_msg\">לא נמצאה כתובת URL בתוכן ששותף</string>\n    <string name=\"share_success_msg\">קורא קישור לסרטון מתוכן משותף…</string>\n    <string name=\"show_more_actions\">הצג פעולות נוספות</string>\n    <string name=\"download_notification\">התראה על הורדה</string>\n    <string name=\"download_notification_desc\">הצג התראה על התקדמות והשלמת הורדות</string>\n    <string name=\"download_range_selection\">בחירת פלייליסט</string>\n    <string name=\"subdirectory\">שמור לתת תיקייה</string>\n    <string name=\"permission_issue\">בעיית הרשאות אחסון</string>\n    <string name=\"battery_configuration_desc\">התעלם מאופטימיזציה של סוללה כדי לאפשר לאפליקציה להוריד ברקע</string>\n    <string name=\"translate\">תרגום</string>\n    <string name=\"embed_subtitles\">כתוביות מוטמעות</string>\n    <string name=\"custom_command_template_desc\">ערוך ונהל תבניות פקודות</string>\n    <string name=\"github_issue\">בעיית GitHub</string>\n    <string name=\"github_issue_desc\">צור בעיה כדי לדווח באג או לבקש תכונה</string>\n    <string name=\"status_enqueued\">ממתין בתור</string>\n    <string name=\"status_completed\">הושלם</string>\n    <string name=\"status_fetching_video_info\">משיג מידע</string>\n    <string name=\"open_file\">פתח קובץ</string>\n    <string name=\"restart\">מתחיל מחדש</string>\n    <string name=\"cookies\">עוגיות</string>\n    <string name=\"dynamic_color\">צבע דינמי</string>\n    <string name=\"max_rate\">קצב מקסימלי</string>\n    <string name=\"unavailable\">לא זמין</string>\n    <string name=\"general_settings_desc\">גרסת yt-dlp, התראות, פלייליסט</string>\n    <string name=\"private_directory\">תיקייה פרטית</string>\n    <string name=\"sdcard_directory\">תיקיית כרטיס ה-SD</string>\n    <string name=\"clear\">ניקוי</string>\n    <string name=\"edit_shortcuts\">ערוץ קיצורים</string>\n    <string name=\"add\">הוספה</string>\n    <string name=\"playlist_indicator_text\">מוריד פלייליסט (%1$d/%2$d)…</string>\n    <string name=\"network\">רשת</string>\n    <string name=\"rate_limit\">הגבלת קצב</string>\n    <string name=\"network_settings_desc\">הגבלת קצב, הורדה, עוגיות</string>\n    <string name=\"disable_preview_desc\">לא להציג תמונה ממוזערת במהלך ההורדה</string>\n    <string name=\"video_only\">וידאו (ללא אודיו)</string>\n    <string name=\"auto_subtitle_desc\">הורד כתוביות שנוצרו באופן אוטומטי</string>\n    <string name=\"video_creator_sample_text\">יוצר וידאו לדוגמה</string>\n    <string name=\"share\">שיתוף</string>\n    <string name=\"unlimited\">לא מוגבלת</string>\n    <string name=\"audio_quality\">איכות אודיו</string>\n    <string name=\"title\">כותרת</string>\n    <string name=\"clear_all_cookies\">ניקוי כל העוגיות</string>\n    <string name=\"beta_features\">בטא</string>\n    <string name=\"split_video_msg\">הסרטון יפוצל ל-%1$d פרקים</string>\n    <string name=\"cookies_usage_msg\">הורדה מאתרים מסוימים דורשת אימות חשבון. לחץ על \\\"צור עוגיות חדשות\\\", הזן את כתובת האתר ולאחר מכן התחבר עם חשבונך בדף הדפדפן, והאפליקציה תייצר אותן עבורך.</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp הוא כלי שורת פקודה רב עוצמה להורדת סרטונים. Seal מקל על השימוש ב-yt-dlp על ידי מתן GUI אינטואיטיבי, הגדרות קבועות מראש לפקודות נפוצות ותכונות נוספות אחרות.\n\\n\n\\nלשימוש מתקדם ב-yt-dlp, אפליקציית Seal מאפשרת ליצור, לשמור ולבצע תבניות פקודות מותאמות אישית ישירות, ממש כמו בטרמינל.\n\\n\n\\nבעת שימוש בפקודות מותאמות אישית, רוב אפשרויות ה-GUI והתכונות יהיו מושבתות.</string>\n    <string name=\"abs_hint\">רוב פלטפורמות הזרמת הווידאו מספקות אודיו ווידאו בנפרד, ניתן לבחור ולמזג פורמט אודיו בלבד עם פורמט וידאו בלבד לסרטון אחד.</string>\n    <string name=\"update_channel_desc\">התקן גירסה מוקדמת לתצוגה מקדימה של תכונות ושינויים חדשים.\n\\n\n\\nתיתכן חוסר יציבות בגרסאות אלה, אז אנא אל תהסס לשלוח לנו משוב אם אתה נתקל בבעיות כלשהן, כדי לעזור לנו לשפר את האפליקציה בעתיד.</string>\n    <string name=\"auto_update\">עדכון אוטומטי</string>\n    <string name=\"sponsor_desc\">תמכו באפליקציה זו על ידי מתן חסות ב-GitHub</string>\n    <string name=\"subtitle\">כתוביות</string>\n    <string name=\"clip_video\">חיתוך וידאו</string>\n    <string name=\"clip_start\">התחלה</string>\n    <string name=\"audio_quality_desc\">הגבל את קצב סיביות השמע כאשר קיימות איכויות מרובות</string>\n    <string name=\"msg_from_developer\">הודעה מהמפתח</string>\n    <string name=\"ytdlp_update_action\">עדכון yt-dlp</string>\n    <string name=\"print_details_desc\">הדפס הודעות מפורטות בזמן הורדה</string>\n    <string name=\"disabled\">מושבת</string>\n    <string name=\"folder_picker\">בוחר תיקיה</string>\n    <string name=\"convert_audio_format_desc\">קידוד מחדש של קובצי אודיו יגרום לאובדן איכות שמע ולהגדלת גודל הקובץ.</string>\n    <string name=\"task_canceled\">משימת ההורדה בוטלה</string>\n    <string name=\"clear_temp_files\">נקה קבצים זמניים</string>\n    <string name=\"battery_settings_desc\">אנא הגדר את השימוש בסוללה של אפליקציה זו ל\\\"בלתי מוגבל\\\" בהגדרות המערכת כדי להוריד ברקע.</string>\n    <string name=\"clear_temp_files_desc\">מחק את כל הקבצים הזמניים מהתיקייה הזמנית</string>\n    <string name=\"fetching_playlist_info\">משיג מידע פלייליסט…</string>\n    <string name=\"unknown_error\">שגיאה לא ידועה</string>\n    <string name=\"translate_desc\">עזור לתרגם אפליקציה זו ב- Hosted Weblate</string>\n    <string name=\"template_label\">תווית</string>\n    <string name=\"invalid_input\">קלט לא חוקי</string>\n    <string name=\"private_directory_desc\">אחסן את ההורדות בתיקייה נסתרת</string>\n    <string name=\"format_selection\">בחירת פורמט</string>\n    <string name=\"convert_audio_format\">המר פורמט שמע</string>\n    <string name=\"best_quality\">האיכות הכי טובה</string>\n    <string name=\"concurrent_download\">הורדה באמצעות ת\\'רדים מרובים</string>\n    <string name=\"concurrent_download_num\">%d ת\\'רדים ישמשו להורדה מקבילה של וידאו DASH/HLS.</string>\n    <string name=\"allow_once\">אפשר פעם אחת</string>\n    <string name=\"allow_always\">אפשר תמיד</string>\n    <string name=\"dont_allow\">אל תאפשר</string>\n    <string name=\"delete_multiple_items_msg\">להסיר לצמיתות %1$d פריטים מהיסטוריית ההורדות?</string>\n    <string name=\"sponsorblock_categories\">קטגוריות SponsorBlock</string>\n    <string name=\"sponsorblock_categories_desc\">בחר קטגוריות SponsorBlock להסרה או סימון בקובץ הווידאו</string>\n    <string name=\"app_update_failed\">העדכון לגרסה האחרונה נכשל</string>\n    <string name=\"remove_cookie_profile_desc\">להסיר את הערך עבור \\\"%1$s\\\"? שים לב שהעוגיות המאוחסנות עבור אתר זה לא יימחקו.</string>\n    <string name=\"keep_subtitle_files\">שמור קבצי כתוביות</string>\n    <string name=\"aria2_desc\">השתמש ב-aria2c בתור מוריד חיצוני</string>\n    <string name=\"start_execute\">התחל הרצת פקודה</string>\n    <string name=\"download_range_desc\">ציין את טווח הסרטונים להורדה מהפלייליסט \\\"%3$s\\\" (מ-%1$d עד %2$d).</string>\n    <string name=\"service_title\">Seal מוריד…</string>\n    <string name=\"download_with_cellular\">הורדה באמצעות חיבור סלולרי</string>\n    <string name=\"export_to_file\">ייצוא לקובץ</string>\n    <string name=\"sponsorblock_desc\">הסר או סמן קטעים בסרטונים באמצעות SponsorBlock API</string>\n    <string name=\"auto_translated_subtitles\">כתוביות מתורגמות אוטומטית</string>\n    <string name=\"system_settings\">הגדרות מערכת</string>\n    <string name=\"look_and_feel\">מראה ותחושה</string>\n    <string name=\"use_previous_selection\">השתמש בבחירה הקודמת</string>\n    <string name=\"search_in_subtitles\">חיפוש בכתוביות</string>\n    <string name=\"interface_and_interaction\">ממשק ואינטראקציות</string>\n    <string name=\"no_thanks\">לא תודה</string>\n    <string name=\"import_from\">ייבוא מ</string>\n    <string name=\"playlist_title\">כותרת פלייליסט</string>\n    <string name=\"force_ipv4\">כפה IPv4</string>\n    <string name=\"full_backup\">גיבוי מלא</string>\n    <string name=\"backup_type\">סוג גיבוי</string>\n    <string name=\"export_to\">ייצוא אל</string>\n    <string name=\"download_history\">היסטוריית הורדות</string>\n    <string name=\"search_in_downloads\">חיפוש בהורדות</string>\n    <string name=\"download_with_cellular_request\">לאפשר הורדה באמצעות חיבור סלולרי?</string>\n    <string name=\"merge_audiostream\">מיזוג זרמי אודיו מרובים</string>\n    <string name=\"subdirectory_hint\">ההורדות שלך יישמרו בתור:</string>\n    <string name=\"show_all_items\">הצג את כל %1$d הפריטים</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">פריט אחד</item>\n        <item quantity=\"two\">שני פריטים</item>\n        <item quantity=\"other\">%d פריטים</item>\n    </plurals>\n    <string name=\"remember_for_next_download\">זכור להורדה הבאה</string>\n    <string name=\"force_ipv4_desc\">בצע את כל החיבורים באמצעות IPv4</string>\n    <string name=\"save\">שמירה</string>\n    <string name=\"apply\">החלה</string>\n    <string name=\"custom\">מותאם אישית</string>\n    <string name=\"auto\">אוטומטי</string>\n    <string name=\"commands\">פקודות</string>\n    <string name=\"unknown\">לא ידוע</string>\n    <string name=\"required\">נדרש</string>\n    <string name=\"website\">אתר אינטרנט</string>\n    <string name=\"none\">ללא</string>\n    <string name=\"reset\">איפוס</string>\n    <string name=\"import_backup\">ייבוא</string>\n    <string name=\"export_backup\">ייצוא</string>\n    <string name=\"clipboard\">לוח</string>\n    <string name=\"file\">קובץ</string>\n    <string name=\"import_download_history\">לייבא היסטוריית הורדות?</string>\n    <string name=\"export_download_history\">לייצא היסטוריית הורדות?</string>\n    <string name=\"redownload\">הורדה מחדש</string>\n    <string name=\"search\">חיפוש</string>\n    <string name=\"format_sorting_desc\">מיון פורמטים עם אפשרות -S של yt-dlp</string>\n    <string name=\"refresh_cookies_desc\">הקש כדי לפתוח דף אינטרנט ליצירת קובצי עוגיות חדשים:</string>\n    <string name=\"custom_command_directory\">ספריית פקודות מותאמות אישית</string>\n    <string name=\"prefer_quality_desc\">העדף פורמט AV1, VP9 או H.265 לצפייה באפליקציות תואמות</string>\n    <string name=\"multiselect_item_count\">%1$d סרטונים, %2$d קובצי שמע</string>\n    <string name=\"embed_subtitles_mkv_msg\">כדי להטמיע כתוביות רכות, סרטונים יבוצעו מחדש לתוך מיכל mkv. אתה יכול להשתמש ב-VLC Media Player או באפליקציות תואמות אחרות כדי לצפות בסרטונים עם כתוביות רכות.</string>\n    <string name=\"auto_update_disabled_msg\">עדכון אוטומטי אינו זמין עבור בניית %1$s. אם אין לך %1$s מותקן במכשיר שלך, או אם תרצה לקבל תצוגה מקדימה של תכונות חדשות של Seal, שקול להשתמש ב-%2$s.</string>\n    <string name=\"ua_header\">כותרת User-Agent</string>\n    <string name=\"dynamic_color_desc\">החל צבעים מהטפט על ערכת הנושא של האפליקציה</string>\n    <string name=\"custom_command_enabled_hint\">חלק מהאפשרויות אינן זמינות בעת שימוש בפקודה מותאמת אישית</string>\n    <string name=\"subtitle_sponsorblock\">כתוביות עשויות להופיע באופן שגוי לאחר הסרת קטעי חסות באמצעות SponsorBlock.</string>\n    <string name=\"temporary_directory_desc\">אחסן קבצים זמניים בספרייה הפנימית</string>\n    <string name=\"set_directory_desc\">הקש כדי להגדיר תיקייה</string>\n    <string name=\"custom_command_directory_desc\">בחר את ספריית הפלט בעת שימוש בפקודות מותאמות אישית</string>\n    <string name=\"prefer_compatibility_desc\">העדף פורמטים של MP4(H.264) לשיתוף עם אפליקציות אחרות</string>\n    <string name=\"download_type\">סוג הורדה</string>\n    <string name=\"format_preference\">העדפות פורמט</string>\n    <string name=\"learn_more\">למד עוד</string>\n    <string name=\"custom_command_desc\">הרץ פקודת yt-dlp עם תבנית מותאמת אישית</string>\n    <string name=\"check_download_settings_desc\">עיין בהגדרות ההורדה וודא שיש לך את הגרסה העדכנית ביותר של yt-dlp לפני השימוש.</string>\n    <string name=\"permission_issue_desc\">תיקיות מחוץ ל\\\"הורדות\\\" ו\\\"מסמכים\\\" אינן נתמכות</string>\n    <string name=\"cookies_desc\">השתמש בעוגיות בפורמט Netscape להורדות</string>\n    <string name=\"output_template\">תבנית פלט</string>\n    <string name=\"matrix_space\">צ\\'אט Matrix</string>\n    <string name=\"preferred_format_desc\">פורמט מועדף כאשר מרובים זמינים</string>\n    <string name=\"no_custom_command_tasks\">אין משימות פקודה מותאמת אישית</string>\n    <string name=\"remove_multiple_templates_msg\">להסיר לצמיתות את %1$s מתבניות הפקודה?</string>\n    <string name=\"edit_file\">ערוך קובץ</string>\n    <string name=\"embed_metadata\">הטמע מטא נתונים</string>\n    <string name=\"embed_metadata_desc\">הטמע מטא נתונים ותמונה ממוזערת של הסרטון בקובץ האודיו</string>\n    <string name=\"use_format_sorting\">השתמש במיון פורמטים</string>\n    <string name=\"merge_audiostream_desc\">אפשר למזג זרמי אודיו מרובים לקובץ בודד</string>\n    <string name=\"format_sorting\">מיון פורמטים</string>\n    <string name=\"download_directory\">תיקיית הורדה</string>\n    <string name=\"yt_dlp_docs\">הוראות לשימוש ב-yt-dlp</string>\n    <string name=\"edit_template_desc\">נתיב פלט וכתובת URL יתווספו על ידי האפליקציה.</string>\n    <string name=\"subdirectory_desc\">שמור קבצים בתיקיות ששמן על פי השדות המתאימים (לדוגמה שם ערוץ)</string>\n    <string name=\"format_settings_desc\">פורמט קובץ, איכות וידאו, כתוביות</string>\n    <string name=\"export_download_history_msg\">מייצא את %1$s מהיסטוריית ההורדות. קבצים שהורדו והעדפות לא יגובו.</string>\n    <string name=\"import_download_history_msg\">הקבצים שהורדו לא ייובאו. תצטרך להוריד אותם מחדש באופן ידני</string>\n    <string name=\"restrict_filenames\">הגבל שמות קבצים</string>\n    <string name=\"restrict_filenames_desc\">הגבל שמות קבצים לתווים ספציפיים כדי להבטיח תאימות</string>\n    <string name=\"lowest_bitrate\">קצב סיביות הנמוך ביותר</string>\n    <string name=\"presets\">הגדרות קבועות מראש</string>\n    <string name=\"output_template_desc\">בחר את התבנית עבור שמות קובצי הפלט</string>\n    <string name=\"subtitle_language_desc\">שפת הכתוביות להורדה בבחירת פורמט \\\"אוטומטי\\\", מופרדת בפסיקים.</string>\n    <string name=\"update_language_msg\">השפות הבאות יתווספו להעדפה שלך להורדות עתידיות:</string>\n    <string name=\"update_subtitle_languages\">לעדכן את שפות הכתוביות?</string>\n    <string name=\"clear_download_archive\">לנקות את ארכיון ההורדות?</string>\n    <string name=\"clear_download_archive_desc\">להסיר לצמיתות את %1$s מקובץ הארכיון?</string>\n    <string name=\"download_history_imported\">%1$s יובא להיסטוריית ההורדות</string>\n    <string name=\"download_archive\">ארכיון הורדות</string>\n    <string name=\"download_archive_desc\">שמור מזהי וידאו שהורדו בארכיון כדי למנוע הורדות כפולות</string>\n    <string name=\"auto_translated_subtitles_msg\">כתוביות מתורגמות אוטומטית לכל השפות יהיו זמינות בהורדות. כתוביות אלו עשויות להיות לא מדויקות וקשות להבנה.</string>\n    <string name=\"download_archive_error\">הסרטון הורד. אם התנהגות זו אינה צפויה, אנא בדוק את ארכיון ההורדות.</string>\n    <string name=\"all_languages\">כל השפות</string>\n    <string name=\"proceed\">המשך</string>\n    <string name=\"preset\">הגדרה מראש</string>\n    <string name=\"prefer_placeholder\">העדף %1$s</string>\n    <string name=\"custom_format_selection_desc\">בחירה מפורמטים, כתוביות, והתאמות נוספות</string>\n    <string name=\"preset_format_selection_desc\">הורדה אוטומטית עם שימוש בהעדפות הפורמט</string>\n    <string name=\"edit_preset\">ערוך הגדרה מראש</string>\n    <string name=\"best_quality_desc\">הורדת הפורמט הכי טוב שזמין</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d סרטון</item>\n        <item quantity=\"two\">%d סרטונים</item>\n        <item quantity=\"other\">%d סרטונים</item>\n    </plurals>\n    <string name=\"task_added\">משימה הוספה לתור</string>\n    <string name=\"remux_container_mkv\">שנה סוג קובץ הסרטון</string>\n    <string name=\"remux_container_mkv_desc\">שנה סוג קובץ סרטונים לסוג-MKV בישביל תאימות טובה יותר</string>\n    <string name=\"playlist\">פלייליסטים (רשימת שירים להשמעה)</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d אודיו</item>\n        <item quantity=\"two\">%d אודיוים</item>\n        <item quantity=\"other\">%d אודיוים</item>\n    </plurals>\n    <string name=\"cookies_in_database\">%1$d קבצי cookies מתוך %2$d אתרים בסך הכול</string>\n    <string name=\"every_day\">כל יום</string>\n    <string name=\"every_week\">כל שבוע</string>\n    <string name=\"every_month\">כל חודש</string>\n    <string name=\"you_ll_find_your_downloads_here\">תוכל למצוא את ההורדות שלך כאן</string>\n    <string name=\"download_hint\">לחץ על כפתור ההורדה או שתף קישור לסרטון על האפליקציה כדי להתחיל הורדה</string>\n    <string name=\"status_downloaded\">הורד</string>\n    <string name=\"all\">הכל</string>\n    <string name=\"select_multiple_link\">בחר מתוך %1$d קישורים</string>\n    <string name=\"download_queue\">תור ההורדות</string>\n    <string name=\"trouble_shooting\">פתרון בעיות</string>\n    <string name=\"issue_tracker\">מעקב אחר בעיות</string>\n    <string name=\"trouble_shooting_desc\">תקן שגיאות נפוצות וחפש בעיות ידועות</string>\n    <string name=\"issue_tracker_hint\">נתקלת בשגיאה? לפני דיווח על בעיה חדשה, אנא חפש במעקב הבעיות שלנו. בעיות נפוצות רבות כבר טופלו ותועדו שם.</string>\n    <string name=\"show_navigation_drawer\">הצג מגירת ניווט</string>\n    <string name=\"delete\">מחק</string>\n    <string name=\"resume\">להמשיך</string>\n    <string name=\"media_info\">מידע על המדיה</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ja/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"download_settings_desc\">一般、形式、カスタムコマンド</string>\n    <string name=\"download\">ダウンロード</string>\n    <string name=\"url_empty\">リンクを空にはできません</string>\n    <string name=\"extract_audio_summary\">動画ではなく音声をダウンロードして保存します</string>\n    <string name=\"create_thumbnail_summary\">動画のサムネイルをファイルとして保存する</string>\n    <string name=\"yt_dlp_up_to_date\">最新版の yt-dlp を使用中です</string>\n    <string name=\"yt_dlp_update_fail\">最新版の yt-dlp をインストールできませんでした。インターネットに接続されているかご確認ください。</string>\n    <string name=\"fetching_info\">動画の情報を取得中…</string>\n    <string name=\"permission_denied\">権限が拒否されました</string>\n    <string name=\"download_success_msg\">ダウンロード完了</string>\n    <string name=\"download_error_msg\">ファイルをダウンロードできませんでした</string>\n    <string name=\"download_start_msg\">「%1$s」をダウンロード</string>\n    <string name=\"fetch_info_error_msg\">動画の情報を取得できませんでした</string>\n    <string name=\"general_settings\">全般</string>\n    <string name=\"language\">表示言語</string>\n    <string name=\"language_settings\">表示言語を設定</string>\n    <string name=\"task_running\">既存のダウンロードタスクが既に実行されています</string>\n    <string name=\"paste_msg\">URL を貼り付け</string>\n    <string name=\"paste_fail_msg\">クリップボード内に URL がありません</string>\n    <string name=\"ytdlp_version\">yt-dlp バージョン</string>\n    <string name=\"ytdlp_update\">クリックして最新の yt-dlp をインストール</string>\n    <string name=\"delete_info\">除去しますか？</string>\n    <string name=\"delete_file\">ファイルも削除</string>\n    <string name=\"about\">このアプリについて</string>\n    <string name=\"custom_command\">カスタムコマンド</string>\n    <string name=\"custom_command_template\">コマンドテンプレート</string>\n    <string name=\"edit\">編集</string>\n    <string name=\"start_execute\">コマンドの実行を開始</string>\n    <string name=\"advanced_settings\">高度な設定</string>\n    <string name=\"print_details\">詳細な出力</string>\n    <string name=\"print_details_desc\">ダウンロード時に詳細なメッセージを表示します</string>\n    <string name=\"thumbnail\">サムネイル</string>\n    <string name=\"edit_template_desc\">出力パスと URL はアプリによって追加されます。</string>\n    <string name=\"convert_audio_format\">音声形式の変換</string>\n    <string name=\"video_quality\">画質</string>\n    <string name=\"best_quality\">最高品質</string>\n    <string name=\"video_quality_desc\">画質の選択肢が複数のとき画質を制限する</string>\n    <string name=\"not_specified\">指定なし (標準)</string>\n    <string name=\"video_format_preference\">優先する動画形式</string>\n    <string name=\"preferred_format_desc\">形式の選択肢が複数のとき優先する形式</string>\n    <string name=\"video_format\">動画形式</string>\n    <string name=\"start_download\">ダウンロード</string>\n    <string name=\"download_desc\">設定後、「ダウンロード」をクリックしてください。</string>\n    <string name=\"check_download_settings_desc\">利用前にダウンロードの設定と、yt-dlpが最新版であることをご確認ください。</string>\n    <string name=\"download_playlist\">再生リストからダウンロード</string>\n    <string name=\"download_playlist_desc\">再生リストから複数の動画をダウンロードします</string>\n    <string name=\"defaults\">デフォルト</string>\n    <string name=\"channel_name\">ダウンロード</string>\n    <string name=\"channel_description\">ダウンロードしたファイルや進捗状況を通知する</string>\n    <string name=\"execute_command_notification\">カスタムコマンド実行中…</string>\n    <string name=\"concurrent_download\">マルチスレッドダウンロード</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD動画の各部分を並行してダウンロード</string>\n    <string name=\"options\">オプション</string>\n    <string name=\"extract_audio\">音声として保存</string>\n    <string name=\"video_directory\">動画フォルダ</string>\n    <string name=\"create_thumbnail\">サムネイルを保存</string>\n    <string name=\"settings\">設定</string>\n    <string name=\"dismiss\">キャンセル</string>\n    <string name=\"downloads_history\">ダウンロード一覧</string>\n    <string name=\"link_copied\">リンクをクリップボードにコピーしました</string>\n    <string name=\"open_url\">リンクを開く</string>\n    <string name=\"back\">戻る</string>\n    <string name=\"readme_desc\">GitHubリポジトリとREADMEを確認する</string>\n    <string name=\"delete_info_msg\">ダウンロード履歴から「%1$s」を除去しますか？</string>\n    <string name=\"confirm\">確認</string>\n    <string name=\"audio\">音声</string>\n    <string name=\"remove\">除去</string>\n    <string name=\"yt_dlp_docs\">yt-dlp 使用法の解説</string>\n    <string name=\"about_page\">バージョン、フィードバック、自動更新</string>\n    <string name=\"version\">バージョン</string>\n    <string name=\"release\">最新リリース</string>\n    <string name=\"release_desc\">更新履歴と新しいバージョンを確認する</string>\n    <string name=\"convert_to\">%1$s に変換</string>\n    <string name=\"video\">動画</string>\n    <string name=\"checked\">確認済み</string>\n    <string name=\"credits\">クレジット</string>\n    <string name=\"off\">オフ</string>\n    <string name=\"cancel\">キャンセル</string>\n    <string name=\"display\">表示</string>\n    <string name=\"settings_before_download\">ダウンロード前の設定</string>\n    <string name=\"settings_before_download_desc\">ダウンロード前に設定を調整する</string>\n    <string name=\"credits_desc\">クレジットと自由なライセンスのソフト</string>\n    <string name=\"custom_command_desc\">カスタムテンプレートを使用して yt-dlp のコマンドを実行</string>\n    <string name=\"not_convert\">変換なし</string>\n    <string name=\"display_settings\">ダークテーマ、ダイナミックカラー、言語</string>\n    <string name=\"follow_system\">システムに従う</string>\n    <string name=\"dark_theme\">ダークテーマ</string>\n    <string name=\"on\">オン</string>\n    <string name=\"settings_before_download_text\">ダウンロードの設定</string>\n    <string name=\"paste\">貼り付け</string>\n    <string name=\"convert_audio\">変換</string>\n    <string name=\"open_settings\">設定を開く</string>\n    <string name=\"error_copied\">エラーレポートをクリップボードにコピーしました</string>\n    <string name=\"format\">形式</string>\n    <string name=\"convert_audio_format_desc\">音声ファイルを再エンコードすると、音質が低下しファイルサイズは増加します。</string>\n    <string name=\"close\">閉じる</string>\n    <string name=\"close_never_show_again\">再度表示しない</string>\n    <string name=\"user_guide\">ユーザーガイド</string>\n    <string name=\"paste_desc\">クリップボードから動画リンクを取得するには「貼り付け」をクリックします。</string>\n    <string name=\"video_url\">動画のアドレス</string>\n    <string name=\"download_history_desc\">動画や音声ファイルなど、本アプリでのダウンロード一覧を管理します。</string>\n    <string name=\"battery_settings_desc\">バックグラウンドでダウンロードを行うため、システムの設定で本アプリのバッテリー使用量を「制限なし」に設定してください。</string>\n    <string name=\"download_finish_notification\">ダウンロード完了。タップで再生します。</string>\n    <string name=\"concurrent_download_num\">同時に%d個のスレッドを用いて、DASH/HLS ネイティブ動画をダウンロードします。</string>\n    <string name=\"additional_settings\">追加の設定</string>\n    <string name=\"share_fail_msg\">共有コンテンツからのURLと一致しません</string>\n    <string name=\"show_more_actions\">ほかの操作を表示</string>\n    <string name=\"download_notification\">ダウンロードの通知</string>\n    <string name=\"fetching_playlist_info\">再生リストの情報を取得中…</string>\n    <string name=\"download_range_selection\">再生リストの選択範囲</string>\n    <string name=\"download_range_desc\">再生リスト「%3$s」からダウンロードする動画の範囲 (%1$dから%2$d) を指定します。</string>\n    <string name=\"from\">開始</string>\n    <string name=\"invalid_index_range\">通し番号の範囲が正しくありません</string>\n    <string name=\"audio_directory\">音声フォルダ</string>\n    <string name=\"download_directory\">ダウンロードフォルダ</string>\n    <string name=\"download_notification_desc\">ダウンロードしたファイルと進捗状況の通知</string>\n    <string name=\"share_success_msg\">共有されたコンテンツから動画リンクを読み込み中…</string>\n    <string name=\"to\">終了</string>\n    <string name=\"playlist_indicator_text\">再生リストからダウンロード中… (%1$d/%2$d)</string>\n    <string name=\"download_directory_desc\">動画と音声ファイルの保存先を選択</string>\n    <string name=\"permission_issue\">保存領域への権限の問題</string>\n    <string name=\"permission_issue_desc\">Download/とDocuments/配下のディレクトリ以外には対応しません</string>\n    <string name=\"battery_configuration\">バッテリー設定</string>\n    <string name=\"unknown_error\">未知のエラー</string>\n    <string name=\"translate_desc\">Hosted Weblateから本アプリの翻訳にご協力ください</string>\n    <string name=\"prefix\">パスのテンプレート</string>\n    <string name=\"embed_subtitles\">字幕を埋め込む</string>\n    <string name=\"embed_subtitles_desc\">字幕ファイルが利用できれば動画に埋め込む</string>\n    <string name=\"new_template\">新しいテンプレート</string>\n    <string name=\"template_label\">名前</string>\n    <string name=\"template_selection\">テンプレート選択</string>\n    <string name=\"custom_command_template_desc\">コマンドテンプレートを編集・管理する</string>\n    <string name=\"task_canceled\">ダウンロードタスクがキャンセルされました</string>\n    <string name=\"github_issue\">GitHubの問題報告場所</string>\n    <string name=\"github_issue_desc\">バグ報告や機能要望</string>\n    <string name=\"info_copied\">情報がクリップボードにコピーされました</string>\n    <string name=\"remove_template\">削除しますか？</string>\n    <string name=\"service_title\">Seal でダウンロード中…</string>\n    <string name=\"subdirectory\">サブフォルダに保存</string>\n    <string name=\"subdirectory_desc\">以下の項目名の各フォルダ内にファイルを保存</string>\n    <string name=\"battery_configuration_desc\">バックグラウンドでダウンロードするにはこのアプリのバッテリー最適化を無効にしてください</string>\n    <string name=\"translate\">翻訳</string>\n    <string name=\"remove_template_desc\">「%1$s」をコマンドテンプレートから削除しますか？</string>\n    <string name=\"downloading_indicator_text\">ダウンロード中…</string>\n    <string name=\"status_error\">エラー</string>\n    <string name=\"copy_error_report\">情報をコピー</string>\n    <string name=\"status_completed\">完了</string>\n    <string name=\"status_downloading\">ダウンロード中</string>\n    <string name=\"status_canceled\">キャンセルしました</string>\n    <string name=\"status_fetching_video_info\">情報の取得中</string>\n    <string name=\"status_enqueued\">キューに追加しました</string>\n    <string name=\"open_file\">ファイルを開く</string>\n    <string name=\"restart\">再開</string>\n    <string name=\"copy_link\">リンクをコピー</string>\n    <string name=\"sponsorblock_desc\">SponsorBlockで動画のシーンを削除または識別</string>\n    <string name=\"sponsorblock_categories\">SponsorBlockのカテゴリ</string>\n    <string name=\"import_from_clipboard\">クリップボードからインポート</string>\n    <string name=\"export_to_clipboard\">クリップボードにエクスポート</string>\n    <string name=\"template_exported\">%1$dつのテンプレートを出力しました</string>\n    <string name=\"template_imported\">%1$dつのテンプレートを読み込みました</string>\n    <string name=\"video_resolution\">動画の解像度</string>\n    <string name=\"video_file_size\">動画ファイルのサイズ</string>\n    <string name=\"download_task_count\">%1$d 件のダウンロードタスク</string>\n    <string name=\"recently_added\">最近追加された項目</string>\n    <string name=\"multiselect_item_count\">%1$d の動画ファイル、%2$d の音声ファイル</string>\n    <string name=\"delete_multiple_items_msg\">%1$d 項目をダウンロード履歴から除去しますか？</string>\n    <string name=\"sponsorblock_categories_desc\">動画ファイルから削除または識別する SponsorBlock のカテゴリを指定します</string>\n    <string name=\"check_for_updates\">更新を確認</string>\n    <string name=\"unavailable\">利用不可</string>\n    <string name=\"use_custom_command\">カスタムコマンドを使用する</string>\n    <string name=\"multiselect_mode\">複数選択モード</string>\n    <string name=\"download_with_cellular_desc\">従量制ネットワークに接続中でもダウンロードする</string>\n    <string name=\"download_with_cellular\">モバイルデータ通信でのダウンロード</string>\n    <string name=\"privacy\">プライバシー</string>\n    <string name=\"private_directory\">非公開フォルダ</string>\n    <string name=\"clear_temp_files_info\">一時ファイルはキャンセルしたダウンロードを再開するために利用できます。本当にすべて削除しますか？\n\\n\n\\n以下からもアクセスできます: %1$s</string>\n    <string name=\"download_disabled_with_cellular\">設定によって、モバイルデータ通信でのダウンロードは無効になっています</string>\n    <string name=\"network\">ネットワーク</string>\n    <string name=\"network_settings_desc\">速度制限、ダウンローダー、クッキー</string>\n    <string name=\"clear_temp_files\">一時ファイルを削除する</string>\n    <string name=\"file_unavailable\">このファイルはありません</string>\n    <string name=\"rate_limit\">速度制限</string>\n    <string name=\"rate_limit_desc\">最大ダウンロード速度を制限する</string>\n    <string name=\"max_rate\">最大速度</string>\n    <string name=\"high_contrast\">高コントラストのダークテーマ</string>\n    <string name=\"invalid_input\">無効な入力値です</string>\n    <string name=\"format_settings_desc\">ファイル形式、画質、字幕</string>\n    <string name=\"general_settings_desc\">yt-dlpのバージョン、通知、再生リスト</string>\n    <string name=\"private_mode_desc\">ダウンロード履歴を無効にする</string>\n    <string name=\"check_for_updates_desc\">GitHubに最新版があるか自動的に確認する</string>\n    <string name=\"app_up_to_date\">最新版です</string>\n    <string name=\"clear_temp_files_desc\">一時ディレクトリ内の一時ファイルをすべて削除</string>\n    <string name=\"clear_temp_files_count\">%1$d個の一時ファイルを削除しました</string>\n    <string name=\"private_mode\">シークレットモード</string>\n    <string name=\"dynamic_color\">ダイナミックカラー</string>\n    <string name=\"dynamic_color_desc\">壁紙の色を本アプリのテーマに反映する</string>\n    <string name=\"disable_preview\">プレビューを無効にする</string>\n    <string name=\"app_update_failed\">最新版への更新に失敗しました</string>\n    <string name=\"update\">更新</string>\n    <string name=\"aria2_desc\">外部ダウンローダーとしてaria2cを使用する</string>\n    <string name=\"cookies\">クッキー</string>\n    <string name=\"cookies_desc\">ダウンロードにネットスケープ形式のクッキーを利用する</string>\n    <string name=\"lowest_quality\">最低品質</string>\n    <string name=\"disable_preview_desc\">ダウンロード中にサムネイルを表示しない</string>\n    <string name=\"format_selection\">ファイル形式の選択</string>\n    <string name=\"format_selection_desc\">ダウンロード開始前にファイル形式を選択する</string>\n    <string name=\"private_directory_desc\">隠しフォルダに保存する</string>\n    <string name=\"suggested\">提案</string>\n    <string name=\"generate_new_cookies\">新しいクッキーを生成</string>\n    <string name=\"select_all\">すべて選択</string>\n    <string name=\"download_selection_desc\">再生リスト「%1$s」からダウンロードする動画を選択</string>\n    <string name=\"selected_item_count\">%1$d項目を選択</string>\n    <string name=\"use_cookies\">クッキーを使用する</string>\n    <string name=\"remove_cookie_profile_desc\">「%1$s」用のこの項目を削除しますか？このサイト向けに保存したクッキーは削除されません。</string>\n    <string name=\"video_only\">動画 (音声なし)</string>\n    <string name=\"crop_artwork\">アートワークを切り抜く</string>\n    <string name=\"crop_artwork_desc\">埋め込んだ画像を正方形に切り抜く</string>\n    <string name=\"logs\">ログ</string>\n    <string name=\"cookies_usage_msg\">一部のサイトからのダウンロードには、アカウントの認証情報が必要です。「新しいクッキーを生成」をクリックし、サイトのURLを入力、ブラウザのページでログインすると、本アプリがクッキーを生成します。</string>\n    <string name=\"subtitle_sponsorblock\">SponsorBlockのシーンを削除すると、字幕のタイミングがずれることがあります。</string>\n    <string name=\"custom_command_enabled_hint\">カスタムコマンドの使用中は一部の設定を利用できません</string>\n    <string name=\"abs_hint\">多くの動画配信プラットフォームは、音声と映像を別々に配信します。音声形式と映像形式を選択し、1つの動画として結合できます。</string>\n    <string name=\"how_does_it_work\">どのように機能しますか？</string>\n    <string name=\"title_activity_share\">クイックダウンロード</string>\n    <string name=\"video_title_sample_text\">動画タイトルサンプルテキスト</string>\n    <string name=\"subtitle\">字幕</string>\n    <string name=\"download_subtitles\">字幕をダウンロード</string>\n    <string name=\"subtitle_language\">字幕の言語</string>\n    <string name=\"sdcard_directory\">SDカードフォルダ</string>\n    <string name=\"auto_subtitle\">自動生成の字幕</string>\n    <string name=\"auto_subtitle_desc\">自動生成された字幕をダウンロードする</string>\n    <string name=\"video_creator_sample_text\">動画制作者サンプルテキスト</string>\n    <string name=\"clear\">クリア</string>\n    <string name=\"edit_shortcuts\">ショートカットを編集</string>\n    <string name=\"telegram_channel\">Telegram チャンネル</string>\n    <string name=\"matrix_space\">Matrix スペース</string>\n    <string name=\"subtitle_desc\">言語、字幕の埋め込み、自動字幕</string>\n    <string name=\"copy_log\">ログをコピー</string>\n    <string name=\"add\">追加</string>\n    <string name=\"shortcuts\">ショートカット</string>\n    <string name=\"edit_shortcuts_desc\">コマンドテンプレートの作成に使用できるカスタムショートカットを編集します。</string>\n    <string name=\"running_tasks\">実行中のタスク</string>\n    <string name=\"show_logs\">ログを表示</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"discard\">破棄</string>\n    <string name=\"apply\">適用</string>\n    <string name=\"embed_subtitles_mkv_msg\">字幕ファイルを埋め込むため、動画を mkv コンテナに多重化しなおします。VLC Media Player などの互換アプリから、字幕を埋め込んだ動画を視聴できます。</string>\n    <string name=\"share\">共有</string>\n    <string name=\"stable_channel\">安定版</string>\n    <string name=\"pre_release_channel\">プレビュー版</string>\n    <string name=\"update_channel_desc\">プレリリース版をインストールすると、新機能や変更を試験的に試すことができます。\n\\n\n\\nこれらのバージョンには不安定な部分がありますので、問題が発生すれば遠慮なくフィードバックを送り、アプリの改善にご協力ください。</string>\n    <string name=\"update_channel\">更新対象</string>\n    <string name=\"auto_update\">自動更新</string>\n    <string name=\"enable_auto_update\">自動更新を有効にする</string>\n    <string name=\"rename\">名前の変更</string>\n    <string name=\"minute\">分</string>\n    <string name=\"no_downloaded_media\">ダウンロード済みのメディアなし</string>\n    <string name=\"beta_features\">ベータ</string>\n    <string name=\"enable_experimental_feature\">実験的な機能を有効にしますか？</string>\n    <string name=\"clip_video_desc\">形式の選択ページでクリップ動画を作成する</string>\n    <string name=\"sponsor_msg2\">ありがとうございます！</string>\n    <string name=\"switch_to_github_builds\">GitHubビルドに切り替える</string>\n    <string name=\"okay\">了解</string>\n    <string name=\"got_it\">わかった</string>\n    <string name=\"feature_unavailable\">機能を利用できません</string>\n    <string name=\"audio_format_preference\">優先する音声形式</string>\n    <string name=\"unlimited\">上限なし</string>\n    <string name=\"lowest_bitrate\">最低ビットレート</string>\n    <string name=\"format_sorting\">形式の並び替え</string>\n    <string name=\"format_sorting_desc\">yt-dlpの-Sオプションで形式を並び替える</string>\n    <string name=\"import_from_preferences\">インポート</string>\n    <string name=\"title\">タイトル</string>\n    <string name=\"second\">秒</string>\n    <string name=\"audio_format\">音声形式</string>\n    <string name=\"clip_video_dialog_msg\">このダウンロード機能はFFmpegによるもので、選択した動画中の範囲をダウンロードします。この機能はまだ実験的で、切り抜きは完全に正確ではなく、あらゆる形式に対応したものでもなく、またダウンロード速度が遅くなる場合があります。</string>\n    <string name=\"auto_update_disabled_msg\">自動更新は%1$sビルドでは利用できません。お使いのデバイスに%1$sがインストールされていない場合、または Seal の今後の新機能をプレビューしたい場合は、%2$sを検討してください。</string>\n    <string name=\"msg_from_developer\">開発者からのメッセージ</string>\n    <string name=\"clip_video\">クリップ動画を作成</string>\n    <string name=\"clip_start\">開始</string>\n    <string name=\"clip_end\">終了</string>\n    <string name=\"no_custom_command_tasks\">カスタムコマンドのタスクなし</string>\n    <string name=\"feedback\">フィードバック</string>\n    <string name=\"sponsors\">スポンサー</string>\n    <string name=\"clear_all_cookies_desc\">アプリ内に保存したクッキーをすべて削除しますか？</string>\n    <string name=\"audio_quality_desc\">音質が複数あるときにビットレートを制限する</string>\n    <string name=\"audio_quality\">音質</string>\n    <string name=\"clear_all_cookies\">すべてのクッキーを消去</string>\n    <string name=\"sponsor\">スポンサー</string>\n    <string name=\"sponsor_desc\">GitHubでスポンサーになって本アプリを支援する</string>\n    <string name=\"sponsor_msg\">Sealはいつでも無料で、誰でも使えるオープンソースです。もし気に入っていただけたなら、GitHubで私のスポンサーになることを検討してください！</string>\n    <string name=\"temporary_directory_desc\">内部ディレクトリーに一時ファイルを保存する</string>\n    <string name=\"ytdlp_update_action\">yt-dlp を更新</string>\n    <string name=\"commands\">コマンド</string>\n    <string name=\"download_type\">ダウンロードの種類</string>\n    <string name=\"legacy\">古い形式</string>\n    <string name=\"quality\">品質</string>\n    <string name=\"set_directory_desc\">タップして設定</string>\n    <string name=\"auto\">自動</string>\n    <string name=\"custom\">カスタム</string>\n    <string name=\"custom_command_directory\">カスタムコマンド用フォルダ</string>\n    <string name=\"proxy_desc\">インターネット接続にプロキシを使用する</string>\n    <string name=\"proxy\">プロキシ</string>\n    <string name=\"format_preference\">形式の設定</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp は動画をダウンロードするための強力なコマンドラインツールです。Seal は、直感的な GUI、通常のコマンドのプリセット、その他の追加機能を提供することで、yt-dlp をより使いやすくします。\n\\n\n\\nyt-dlp の高度な使用のために、Seal ではカスタムコマンドテンプレートをターミナルと同じように直接作成、保存、実行することができます。\n\\n\n\\nカスタムコマンドを使用する場合、ほとんどの GUI オプションや機能は無効になります。</string>\n    <string name=\"split_video_msg\">動画は %1$d 個のチャプターに分割されます</string>\n    <string name=\"export_to_file\">ファイルにエクスポート</string>\n    <string name=\"enable_notifications_desc\">アプリはダウンロード状況や進捗状況に関する通知を送信するために権限の許可が必要です。</string>\n    <string name=\"folder_picker\">フォルダを選択</string>\n    <string name=\"split_video\">動画を分割</string>\n    <string name=\"prefer_compatibility_desc\">他のアプリに共有するため MP4 (H.264) 形式を優先</string>\n    <string name=\"download_video_desc\">URL から動画をダウンロード</string>\n    <string name=\"edit_template\">「%1$s」を編集</string>\n    <string name=\"unknown\">不明</string>\n    <string name=\"learn_more\">詳細</string>\n    <string name=\"convert_subtitle\">字幕を変換</string>\n    <string name=\"prefer_quality_desc\">互換性アプリで視聴するため AV1、VP9、H.265 形式を優先</string>\n    <string name=\"unknown_error_title\">おっと！問題が発生しました</string>\n    <string name=\"custom_command_directory_desc\">カスタムコマンド使用時の出力ディレクトリを指定する</string>\n    <string name=\"presets\">プリセット</string>\n    <string name=\"start\">開始</string>\n    <string name=\"ua_header\">User-Agent ヘッダー</string>\n    <string name=\"new_task\">新しいダウンロードタスク</string>\n    <string name=\"copy_and_exit\">コピーして終了</string>\n    <string name=\"convert_subtitle_desc\">字幕を別の形式に変換する</string>\n    <string name=\"output_template\">出力テンプレート</string>\n    <string name=\"output_template_desc\">出力するファイル名のテンプレートを指定します</string>\n    <string name=\"disabled\">無効</string>\n    <string name=\"disable\">無効化</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">%d 項目</item>\n    </plurals>\n    <string name=\"expand\">展開</string>\n    <string name=\"refresh_cookies_desc\">タップで新規クッキーの生成用のウェブページを開く:</string>\n    <string name=\"remove_multiple_templates_msg\">%1$sのテンプレートを削除しますか？</string>\n    <string name=\"enable_notifications\">通知を有効にしますか？</string>\n    <string name=\"clear_download_archive\">ダウンロード記録を消去しますか？</string>\n    <string name=\"download_archive_desc\">ダウンロードの重複を回避するために、ダウンロードした動画のIDを記録します</string>\n    <string name=\"download_archive\">ダウンロードを記録</string>\n    <string name=\"embed_metadata\">メタデータの埋め込み</string>\n    <string name=\"embed_metadata_desc\">メタデータと動画サムネイルを音声ファイルに埋め込む</string>\n    <string name=\"show_all_items\">%1$d 項目をすべて表示</string>\n    <string name=\"subdirectory_hint\">ここに保存されます:</string>\n    <string name=\"clear_download_archive_desc\">%1$s 項目を記録ファイルから削除しますか？</string>\n    <string name=\"restrict_filenames_desc\">互換性を確かにするため、ファイル名を特定の文字に制限する</string>\n    <string name=\"restrict_filenames\">ファイル名を制限</string>\n    <string name=\"save\">保存</string>\n    <string name=\"website\">サイト</string>\n    <string name=\"force_ipv4\">IPv4 を強制</string>\n    <string name=\"use_format_sorting\">形式の並び替えを使用</string>\n    <string name=\"system_settings\">システムの設定に従う</string>\n    <string name=\"force_ipv4_desc\">すべての接続をIPv4にします</string>\n    <string name=\"edit_file\">ファイルを編集</string>\n    <string name=\"playlist_title\">再生リストの題名</string>\n    <string name=\"required\">必須</string>\n    <string name=\"keep_subtitle_files\">字幕ファイルを保持</string>\n    <string name=\"allow_once\">1度許可</string>\n    <string name=\"allow_always\">常に許可</string>\n    <string name=\"dont_allow\">許可しない</string>\n    <string name=\"merge_audiostream_desc\">複数の音声ストリームを1つのファイルへと結合する</string>\n    <string name=\"merge_audiostream\">複数の音声ストリームを結合</string>\n    <string name=\"download_with_cellular_request\">モバイル接続でダウンロードしますか (従量課金の場合)？</string>\n    <string name=\"auto_translated_subtitles_msg\">すべての言語で自動翻訳された字幕をダウンロードできます。これらの字幕は不正確で理解しにくいことがあります。</string>\n    <string name=\"auto_translated_subtitles\">自動翻訳された字幕</string>\n    <string name=\"none\">なし</string>\n    <string name=\"use_previous_selection\">前回の選択を使用</string>\n    <string name=\"look_and_feel\">表示</string>\n    <string name=\"remember_for_next_download\">次回のダウンロード用に記憶</string>\n    <string name=\"reset\">初期化</string>\n    <string name=\"search_in_subtitles\">字幕を検索</string>\n    <string name=\"no_thanks\">いいえ</string>\n    <string name=\"update_subtitle_languages\">字幕の言語を更新しますか？</string>\n    <string name=\"update_language_msg\">以下の言語が、次回のダウンロード時の優先候補に追加されます:</string>\n    <string name=\"subtitle_language_desc\">自動で形式を選択してダウンロードする字幕の言語を指定します。カンマ区切り。</string>\n    <string name=\"search_in_downloads\">ダウンロード一覧から検索</string>\n    <string name=\"search\">検索</string>\n    <string name=\"download_archive_error\">動画がダウンロードされました。これが予期しない動作ならダウンロードアーカイブをご確認ください。</string>\n    <string name=\"download_history_imported\">ダウンロード履歴に %1$s 個をインポートしました</string>\n    <string name=\"export_backup\">エクスポート</string>\n    <string name=\"export_download_history_msg\">ダウンロード履歴から %1$s 個をエクスポート中。ダウンロードしたファイルと設定はバックアップされません。</string>\n    <string name=\"import_download_history_msg\">ダウンロード済みファイルはインポートできません。手動で再ダウンロードしてください</string>\n    <string name=\"import_backup\">インポート</string>\n    <string name=\"full_backup\">完全バックアップ</string>\n    <string name=\"interface_and_interaction\">外観と動的変化</string>\n    <string name=\"backup_type\">バックアップの種類</string>\n    <string name=\"file\">ファイル</string>\n    <string name=\"clipboard\">クリップボード</string>\n    <string name=\"download_history\">ダウンロード履歴</string>\n    <string name=\"export_to\">エクスポート先</string>\n    <string name=\"import_from\">インポート元</string>\n    <string name=\"import_download_history\">ダウンロード履歴をインポートしますか？</string>\n    <string name=\"export_download_history\">ダウンロード履歴をエクスポートしますか？</string>\n    <string name=\"redownload\">再ダウンロード</string>\n    <string name=\"remux_container_mkv_desc\">互換性改善のため動画をMKVコンテナへと再多重化</string>\n    <string name=\"remux_container_mkv\">動画コンテナを再多重化</string>\n    <string name=\"cookies_in_database\">%2$dのサイトから%1$d個のクッキーがあります</string>\n    <string name=\"every_day\">毎日</string>\n    <string name=\"every_week\">毎週</string>\n    <string name=\"every_month\">毎月</string>\n    <string name=\"all_languages\">すべての言語</string>\n    <string name=\"preset\">プリセット</string>\n    <string name=\"custom_format_selection_desc\">形式、字幕を選択し、調整</string>\n    <string name=\"prefer_placeholder\">%1$s を優先</string>\n    <string name=\"preset_format_selection_desc\">形式の設定を使い自動ダウンロード</string>\n    <string name=\"best_quality_desc\">最良の形式でダウンロード</string>\n    <string name=\"task_added\">キューにタスクを追加</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">%d本の動画</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">%d個の音声</item>\n    </plurals>\n    <string name=\"playlist\">再生リスト</string>\n    <string name=\"proceed\">続行</string>\n    <string name=\"edit_preset\">プリセットを編集</string>\n    <string name=\"download_hint\">ダウンロードボタンをタップ、またはこのアプリへの動画リンクを共有しダウンロードを開始します</string>\n    <string name=\"you_ll_find_your_downloads_here\">ここからダウンロード一覧を検索できます</string>\n    <string name=\"status_downloaded\">ダウンロード済み</string>\n    <string name=\"all\">すべて</string>\n    <string name=\"download_queue\">ダウンロードキュー</string>\n    <string name=\"resume\">再開</string>\n    <string name=\"delete\">削除</string>\n    <string name=\"media_info\">メディアの情報</string>\n    <string name=\"issue_tracker\">問題集積所</string>\n    <string name=\"trouble_shooting\">トラブルシューティング</string>\n    <string name=\"trouble_shooting_desc\">一般的なエラーの修正、既知の問題の確認</string>\n    <string name=\"issue_tracker_hint\">エラーですか？問題を報告する前に、問題集積所を検索してください。多くの一般的な問題への対処法は既に文書化済みです。</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ji/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">היט ווי אַודיאָ</string>\n    <string name=\"create_thumbnail\">היט טאַמנייל</string>\n    <string name=\"url_empty\">דער לינק קען נישט זיין ליידיק</string>\n    <string name=\"extract_audio_summary\">אראפקאפיע און היט אַודיאָ אַנשטאָט פון ווידעא</string>\n    <string name=\"create_thumbnail_summary\">היט ווידעא טאַמנייל ווי אַ טעקע</string>\n    <string name=\"yt_dlp_up_to_date\">ניצן די לעצטע ווערסיע פון yt-dlp</string>\n    <string name=\"permission_denied\">דערלויבעניש געלייקנט</string>\n    <string name=\"download_success_msg\">אראפקאפיע פאַרטיק</string>\n    <string name=\"download_error_msg\">קען נישט אראפקאפיע טעקע</string>\n    <string name=\"download_start_msg\">אראפקאפיע \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">קען נישט באַקומען ווידעא אינפֿאָרמאַציע</string>\n    <string name=\"task_running\">אַן עקסיסטירטע אראפקאפיע אַרבעט איז שוין פליסנדיק</string>\n    <string name=\"paste_msg\">פּאַפּ די URL</string>\n    <string name=\"ytdlp_version\">Yt-dlp ווערסיע</string>\n    <string name=\"ytdlp_update_action\">אַפּדייט yt-dlp</string>\n    <string name=\"delete_info\">אַראָפּנעמען?</string>\n    <string name=\"confirm\">באַשטעטיקט</string>\n    <string name=\"audio\">אַודיאָ</string>\n    <string name=\"link_copied\">לינק קאַפּיד צו די קליפּבאָרד</string>\n    <string name=\"video_directory\">ווידעא</string>\n    <string name=\"settings\">סעטטינגס</string>\n    <string name=\"download_settings_desc\">אַלגעמיינע, פֿאָרמאַט, אייגן באַפֿעל</string>\n    <string name=\"download\">אָפּלאָדירן</string>\n    <string name=\"general_settings\">אַלגעמיינע</string>\n    <string name=\"language\">ווייַז שפּראַך</string>\n    <string name=\"yt_dlp_update_fail\">קען נישט ינסטאַלירן די לעצטע yt-dlp ווערסיע. ביטע מאַכן זיכער אַז איר זענט קאָננעקטעד צו די אינטערנעט.</string>\n    <string name=\"language_settings\">באַשטעטיק ווייַז שפּראַך</string>\n    <string name=\"ytdlp_update\">דריקט צו ינסטאַלירן די לעצטע yt-dlp ווערסיע</string>\n    <string name=\"paste_fail_msg\">קען נישט גלייַכן די URL אין די קליפּבאָרד</string>\n    <string name=\"delete_info_msg\">אַראָפּנעמען \\\"%1$s\\\" פֿון דיין דאַונלאָודינג געשיכטע פֿאַר גוט?</string>\n    <string name=\"fetching_info\">באקומט ווידעא אינפארמאציע…</string>\n    <string name=\"dismiss\">ביטול</string>\n    <string name=\"downloads_history\">דאַונלאָודז</string>\n    <string name=\"version\">ווערסיע</string>\n    <string name=\"video\">ווידיאו</string>\n    <string name=\"on\">אנגעצינדן</string>\n    <string name=\"remove\">נעם אראפ</string>\n    <string name=\"back\">צירוק</string>\n    <string name=\"off\">אויסגעלאשן</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-kab/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources></resources>"
  },
  {
    "path": "app/src/main/res/values-km/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">រក្សាទុកជាអូឌីយោ</string>\n    <string name=\"settings\">ការកំណត់</string>\n    <string name=\"download\">ដោនឡូដ</string>\n    <string name=\"url_empty\">បញ្ជាប់មិនអាចទទេឡើយ</string>\n    <string name=\"extract_audio_summary\">ដោនឡូដនិងរក្សាទុកអូឌីយោ, ជួសវីដេអូ</string>\n    <string name=\"create_thumbnail_summary\">រក្សាទុករូបក្របវីដេអូជាឯកសារ</string>\n    <string name=\"video_directory\">ថតវីដេអូ</string>\n    <string name=\"create_thumbnail\">រក្សាទុករូបក្រប</string>\n    <string name=\"download_settings_desc\">ទូទៅ, ហ្វ័រម៉ាត, ឃ្លាបញ្ជាផ្ទាល់ខ្លួន</string>\n    <string name=\"yt_dlp_up_to_date\">កំពុងប្រើកំណែចុងក្រោយបំផុតនៃ yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">មិនអាចដំឡើងកំណែ yt-dlp ចុងក្រោយបង្អស់បានទេ។ សូមប្រាកដថាអ្នកបានតភ្ជាប់អ៊ីនធឺណិត។</string>\n    <string name=\"permission_denied\">សិទ្ធិអនុញ្ញាតត្រូវបានបដិសេធ</string>\n    <string name=\"download_success_msg\">ដោនឡូដសម្រេច</string>\n    <string name=\"download_error_msg\">មិនអាចដោនឡូដឯកសារ</string>\n    <string name=\"download_start_msg\">ដោនឡូដ \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">មិនអាចរួបព័ត៌មានវីដេអូទេ</string>\n    <string name=\"fetching_info\">កំពុងរួបព័ត៌មានវីដេអូ…</string>\n    <string name=\"general_settings\">ទូទៅ</string>\n    <string name=\"language\">ភាសាអេក្រង់បង្ហាញ</string>\n    <string name=\"language_settings\">កំណត់ភាសាអេក្រង់បង្ហាញ</string>\n    <string name=\"task_running\">កិច្ចការដោនឡូដមានស្រាប់កំពុងរត់ហើយ</string>\n    <string name=\"video\">វីដេអូ</string>\n    <string name=\"checked\">ឆែកឆេរ</string>\n    <string name=\"credits\">ក្រេឌីត</string>\n    <string name=\"credits_desc\">ក្រេឌីត និងសុសវែរ libre</string>\n    <string name=\"paste_msg\">បិទភ្ជាប់យូអអិលពីឃ្លីបប៊ត</string>\n    <string name=\"paste_fail_msg\">មិនអាចផ្គូផ្គងយូអអិលនៅក្នុងឃ្លីបប៊តបានទេ</string>\n    <string name=\"ytdlp_version\">កំណែនៃ Yt-dlp</string>\n    <string name=\"ytdlp_update_action\">អាប់ដេត yt-dlp</string>\n    <string name=\"delete_info\">ដកចេញឬ?</string>\n    <string name=\"delete_info_msg\">ដក \\\"%1$s\\\" ចេញពីប្រវត្តិដោនឡូដរបស់អ្នកពិតឬ?</string>\n    <string name=\"confirm\">អះអាង</string>\n    <string name=\"dismiss\">បោះបង់</string>\n    <string name=\"downloads_history\">ដោនឡូដ</string>\n    <string name=\"audio\">អូឌីយោ</string>\n    <string name=\"link_copied\">បញ្ជាប់បានចម្លងទៅឃ្លីបប៊ត</string>\n    <string name=\"open_url\">បើកបញ្ជាប់</string>\n    <string name=\"remove\">ដកចេញ</string>\n    <string name=\"delete_file\">លុបឯកសារ</string>\n    <string name=\"about\">អំពី</string>\n    <string name=\"about_page\">កំណែ, មតិកែលម្អ, ស្វ័យអាប់ដេត</string>\n    <string name=\"back\">ត្រឡប់</string>\n    <string name=\"version\">កំណែ</string>\n    <string name=\"release_desc\">ឆែកកំណត់ហេតុផ្លាស់និងកំណែថ្មី</string>\n    <string name=\"release\">ការចេញផ្សាយចុងក្រោយ</string>\n    <string name=\"readme_desc\">ឆែកឃ្លាំងផ្ទុកនៃ GitHub និងអានខ្ញុំ</string>\n    <string name=\"custom_command\">ឃ្លាបញ្ជាផ្ទាល់ខ្លួន</string>\n    <string name=\"custom_command_desc\">រត់ឃ្លាបញ្ជ yt-dlp ជាមួយនឹងពុម្ពគំរូផ្ទាល់ខ្លួន</string>\n    <string name=\"custom_command_template\">ពុម្ពគំរូឃ្លាបញ្ជា</string>\n    <string name=\"edit\">កែ</string>\n    <string name=\"error_copied\">របាយការណ៍កំហុសបានចម្លងទៅឃ្លីបប៊ត</string>\n    <string name=\"edit_template_desc\">ទីតាំងធាតុចេញនិងយូអអិលក៏នឹងត្រូវបានបន្ថែមដោយកម្មវិធី។</string>\n    <string name=\"start_execute\">ចាប់ផ្តើមប្រតិបត្តិឃ្លាបញ្ជា</string>\n    <string name=\"print_details_desc\">បោះពុម្ពសារលម្អិត នៅពេលកំពុងដោនឡូដ</string>\n    <string name=\"dark_theme\">ស្បែកងងឹត</string>\n    <string name=\"follow_system\">ប្រព័ន្ធ</string>\n    <string name=\"advanced_settings\">កម្រិតខ្ពស់</string>\n    <string name=\"print_details\">ធាតុចេញលម្អិត</string>\n    <string name=\"display\">អេក្រង់បង្ហាញ</string>\n    <string name=\"display_settings\">ស្បែកងងឹត, ពណ៌ថាមវន្ត, ភាសា</string>\n    <string name=\"on\">បើក</string>\n    <string name=\"off\">បិទ</string>\n    <string name=\"cancel\">បោះបង់</string>\n    <string name=\"settings_before_download\">កំណត់រចនាសម្ព័ន្ធមុនដោនឡូដ</string>\n    <string name=\"settings_before_download_desc\">កំណត់រចនាសម្ព័ន្ធបុរិមាចំណូលចិត្តមុនពេលដោនឡូត</string>\n    <string name=\"settings_before_download_text\">លៃតម្រូវដោនឡូដនេះ</string>\n    <string name=\"thumbnail\">រូបក្រប</string>\n    <string name=\"paste\">បិទភ្ជាប់</string>\n    <string name=\"yt_dlp_docs\">យោងទម្លាប់ Yt-dlp</string>\n    <string name=\"convert_audio_format\">បំប្លែងហ្វ័រម៉ាតអូឌីយោ</string>\n    <string name=\"not_convert\">ឥតបំប្លែងសោះ</string>\n    <string name=\"convert_to\">បំប្លែងទៅ %1$s</string>\n    <string name=\"format\">ហ្វ័រម៉ាត</string>\n    <string name=\"convert_audio_format_desc\">កូដការឯកសារអូឌីយោឡើងវិញនឹងបណ្តាលឱ្យបាត់បង់គុណភាពអូឌីយោ និងបង្កើនទំហំឯកសារ។</string>\n    <string name=\"video_quality\">គុណភាពវីដេអូ</string>\n    <string name=\"best_quality\">គុណភាពខ្ពស់</string>\n    <string name=\"video_quality_desc\">ដាក់កម្រិតគុណភាពវីដេអូនៅពេលដែលមានច្រើន</string>\n    <string name=\"not_specified\">មិនបានបញ្ជាក់ (បុរេជម្រើស)</string>\n    <string name=\"video_format_preference\">ហ្វ័រម៉ាតវីដេអូដែលបានពេញចិត្ត</string>\n    <string name=\"preferred_format_desc\">ហ្វ័រម៉ាតដែលពេញចិត្ត នៅពេលបានផ្ដល់ឱ្យច្រើនចំនួន</string>\n    <string name=\"video_format\">ហ្វ័រម៉ាតវីដេអូ</string>\n    <string name=\"convert_audio\">បំប្លែង</string>\n    <string name=\"start_download\">ដោនឡូដ</string>\n    <string name=\"close\">បិទ</string>\n    <string name=\"close_never_show_again\">កុំបង្ហាញខ្លួនម្ដងទៀត</string>\n    <string name=\"user_guide\">មគ្គុទេសក៍អត្ថជន</string>\n    <string name=\"open_settings\">បើកការកំណត់</string>\n    <string name=\"paste_desc\">ចុច “បិទភ្ជាប់” ដើម្បីយកបញ្ជាប់វីដេអូពីឃ្លីបប៊តរបស់អ្នក។</string>\n    <string name=\"download_desc\">បន្ទាប់មកចុច “ដោនឡូដ” ក្រោយពីការលៃតម្រូវការកំណត់របស់វា។</string>\n    <string name=\"execute_command_notification\">កំពុងរត់ឃ្លាបញ្ជាផ្ទាល់ខ្លួន…</string>\n    <string name=\"battery_settings_desc\">សូមកំណត់ទម្លាប់ថ្មរបស់កម្មវិធីនេះទៅជា \\\"មិនបានរឹតត្បិត\\\" នៅក្នុងការកំណត់ប្រព័ន្ធ ដើម្បីទាញយកនៅផ្ទៃខាងក្រោយ។</string>\n    <string name=\"share_fail_msg\">មិនអាចផ្គូផ្គងយូអអិលពីមាតិកាដែលបានចែករំលែក</string>\n    <string name=\"download_notification\">ការជូនដំណឹងដោនឡូដ</string>\n    <string name=\"ytdlp_update\">ចុចដើម្បីដំឡើងកំណែ yt-dlp ចុងក្រោយបំផុត</string>\n    <string name=\"download_history_desc\">ពិនិត្យនិងគ្រប់គ្រងដោនឡូដក្នុងកម្មវិធី រួមទាំងឯកសារវីដេអូនិងអូឌីយោ។</string>\n    <string name=\"check_download_settings_desc\">សូមឆែកមើលការកំណត់ដោនឡូដ ហើយត្រូវប្រាកដថាអ្នកមានកំណែចុងក្រោយបំផុតរបស់ yt-dlp មុនពេលប្រើវា។</string>\n    <string name=\"download_playlist\">ដោនឡូដបញ្ជីចាក់</string>\n    <string name=\"download_playlist_desc\">ដោនឡូដពហុវីដេអូពីបញ្ជីចាក់</string>\n    <string name=\"defaults\">បុរេជម្រើស</string>\n    <string name=\"channel_name\">ដោនឡូដ</string>\n    <string name=\"channel_description\">រម្លឹកឯកសារបានដោនឡូដនិងវឌ្ឍនភាព</string>\n    <string name=\"video_url\">បញ្ជាប់វីដេអូ</string>\n    <string name=\"download_finish_notification\">ដោនឡូដសម្រេច។ ប៉ះដើម្បីបើក។</string>\n    <string name=\"concurrent_download\">ដោនឡូដពហុសរសៃ</string>\n    <string name=\"concurrent_download_desc\">ដោនឡូដផ្នែកជាច្រើននៃវីដេអូ M3U8/MPD ស្របគ្នា</string>\n    <string name=\"concurrent_download_num\">%d សរសៃក៏នឹងត្រូវបានប្រើ ដើម្បីទាញយកវីដេអូដើម DASH/HLS ក្នុងពេលដំណាលគ្នា។</string>\n    <string name=\"options\">ជម្រើស</string>\n    <string name=\"additional_settings\">ការកំណត់បន្ថែម</string>\n    <string name=\"share_success_msg\">កំពុងអានបញ្ជាប់វីដេអូពីមាតិកាដែលបានចែករំលែក…</string>\n    <string name=\"show_more_actions\">បង្ហាញសកម្មភាពបន្ថែមទៀត</string>\n    <string name=\"download_notification_desc\">ជូនដំណឹងនៃឯកសារដែលបានដោនឡូដនិងវឌ្ឍនភាព</string>\n    <string name=\"fetching_playlist_info\">កំពុងរួបព័ត៌មានបញ្ជីចាក់…</string>\n    <string name=\"download_range_selection\">បញ្ជីចាក់ជ្រើសរើស</string>\n    <string name=\"from\">ចាប់ផ្ដើម</string>\n    <string name=\"to\">បញ្ជប់</string>\n    <string name=\"invalid_index_range\">រ៉េងសន្ទស្សន៍មិនត្រឹមត្រូវ</string>\n    <string name=\"playlist_indicator_text\">កំពុងដោនឡូដបញ្ជីចាក់ (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">ថតអូឌីយោ</string>\n    <string name=\"download_directory\">ទីតាំងផ្នែកដោនឡូដ</string>\n    <string name=\"download_range_desc\">បញ្ជាក់រ៉េងនៃវីដេអូដែលត្រូវទាញយកពីបញ្ជីចាក់ \\\"%3$s\\\" (ពី %1$d ដល់ %2$d)។</string>\n    <string name=\"download_directory_desc\">រើសទីកន្លែងទុកដាក់ឯកសារវីដេអូ និងអូឌីយោ</string>\n    <string name=\"subdirectory\">រក្សាទុកនៅទីថតរង</string>\n    <string name=\"subdirectory_desc\">រក្សាទុកឯកសារនៅក្នុងថតដែលបានឈ្មោះទីទៃគ្នា</string>\n    <string name=\"permission_issue\">បញ្ហាសិទ្ធិអនុញ្ញាតផ្ទុក</string>\n    <string name=\"permission_issue_desc\">ទីថតខាងក្រៅ Download/ និង Documents/ មិនត្រូវបានគាំទ្រទេ</string>\n    <string name=\"status_completed\">បានបញ្ចប់</string>\n    <string name=\"open_file\">បើកឯកសារ</string>\n    <string name=\"video_resolution\">កម្រិតគុណភាពវីដេអូ</string>\n    <string name=\"template_exported\">បាននាំចេញពុម្ពគំរូ %1$d</string>\n    <string name=\"multiselect_item_count\">ឯកសារវីដេអូ %1$d, អូឌីយោ %2$d</string>\n    <string name=\"sponsorblock_categories\">ចំណាត់ថ្នាក់នៃ SponsorBlock</string>\n    <string name=\"check_for_updates\">ពិនិត្យបច្ចុប្បន្នភាព</string>\n    <string name=\"battery_configuration\">ការកំណត់រចនាសម្ព័ន្ធថ្ម</string>\n    <string name=\"battery_configuration_desc\">ពុំអើពើបង្កើនប្រសិទ្ធភាពថ្ម សម្រាប់កម្មវិធីនេះដើម្បីដោនឡូដនៅផ្ទៃខាងក្រោយ</string>\n    <string name=\"service_title\">Seal គឺកំពុងតែដោនឡូដ…</string>\n    <string name=\"unknown_error\">កំហុសមិនស្គាល់</string>\n    <string name=\"translate\">បកប្រែ</string>\n    <string name=\"translate_desc\">ជួយបកប្រែកម្មវិធីនេះលើ Hosted Weblate</string>\n    <string name=\"prefix\">បុព្វបទ</string>\n    <string name=\"embed_subtitles\">បង្កប់ចំណងជើងរង</string>\n    <string name=\"status_downloading\">កំពុងដោនឡូដ</string>\n    <string name=\"status_canceled\">បានបោះបង់</string>\n    <string name=\"status_fetching_video_info\">កំពុងរួបព័ត៌មាន</string>\n    <string name=\"restart\">ចាប់ផ្ដើមឡើងវិញ</string>\n    <string name=\"status_error\">កំហុស</string>\n    <string name=\"copy_link\">ចម្លងបញ្ជាប់</string>\n    <string name=\"copy_error_report\">របាយការណ៍កំហុស</string>\n    <string name=\"video_file_size\">ទំហំឯកសារវីដេអូ</string>\n    <string name=\"export_to_clipboard\">នាំចេញទៅឃ្លីបប៊ត</string>\n    <string name=\"import_from_clipboard\">នាំចូលពីឃ្លីបប៊ត</string>\n    <string name=\"template_imported\">បាននាំចូលពុម្ពគំរូ %1$d</string>\n    <string name=\"download_task_count\">ភារកិច្ចដោនឡូដ %1$d</string>\n    <string name=\"recently_added\">ទើបតែបន្ថែម</string>\n    <string name=\"aria2_desc\">ប្រើ aria2c ជាការីដោនឡូដខាងក្រៅ</string>\n    <string name=\"embed_subtitles_desc\">បង្កប់សុសរងទៅក្នុងវីដេអូ ប្រសិនបើមាន</string>\n    <string name=\"new_template\">ពុម្ពគំរូថ្មី</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-kmr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources></resources>"
  },
  {
    "path": "app/src/main/res/values-kn/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"delete_file\">ಡಿಲೀಟ್</string>\n    <string name=\"dismiss\">ಕ್ಯಾನ್ಸಲ್</string>\n    <string name=\"advanced_settings\">ಅಡ್ವಾನ್ಸಡ್</string>\n    <string name=\"print_details\">ಡೀಟೈಲ್ಡ್ ಔಟ್ಪುಟ್</string>\n    <string name=\"link_copied\">ಲಿಂಕ್ ಕೋಪಿಎಡ್ ಟು ಕ್ಲಿಪ್ಬೋರ್ಡ್</string>\n    <string name=\"credits_desc\">ಕ್ರೆಡಿಟ್ಸ್ ಅಂಡ್ ಲಿಬ್ರೆ ಸಾಫ್ಟ್ವೇರ್</string>\n    <string name=\"readme_desc\">ಚೆಕ್ ದಿ ಗಿತುಬ್ ರೆಪೊಸಿಟರಿ ಅಂಡ್ ದಿ ರೆಡ್ಮ್</string>\n    <string name=\"remove\">ರಿಮೋವ್</string>\n    <string name=\"custom_command_desc\">ರನ್ yt-dlp ಕಮಾಂಡ್ ವಿಥ್ ಕಸ್ಟಮ್ ಟೆಂಪ್ಲೆಟ್</string>\n    <string name=\"ytdlp_update\">ಕ್ಲಿಕ್ ಟು ಇನ್ಸ್ಟಾಲ್ ದಿ ಲೇಟೆಸ್ಟ್ yt-dlp ವರ್ಷನ್</string>\n    <string name=\"extract_audio_summary\">ಡೌನ್ಲೋಡ್ ಅಂಡ್ ಸೇವ್ ಆಡಿಯೋ, ಇನ್ಸ್ಟೆಡ್ ಆಫ್ ವಿಡಿಯೋ</string>\n    <string name=\"paste_fail_msg\">ಕುಡ್ ನಾಟ್ ಮ್ಯಾಚ್ ದಿ ಯುಆರ್ಎಲ್ ಇನ್ ದಿ ಕ್ಲಿಪ್ಬೋರ್ಡ್</string>\n    <string name=\"on\">ಆನ್</string>\n    <string name=\"download_settings_desc\">ಜನರಲ್,ಫಾರ್ಮ್ಯಾಟ್,ಕಸ್ಟಮ್ ಕಮಾಂಡ್</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp ಯೂಸೇಜ್ ರೆಫೆರೆನ್ಸಸ್</string>\n    <string name=\"edit\">ಎಡಿಟ್</string>\n    <string name=\"paste_msg\">ಪೇಸ್ಟ್ ಯುಆರ್ಎಲ್ ಫ್ರಮ್ ಕ್ಲಿಪ್ಬೋರ್ಡ್</string>\n    <string name=\"video_quality\">ವಿಡಿಯೋ ಕ್ವಾಲಿಟಿ</string>\n    <string name=\"display_settings\">ಡಾರ್ಕ್ ಥೀಮ್, ಡೈನಾಮಿಕ್ ಕಲರ್,ಲ್ಯಾಂಗುವೇಜಸ್</string>\n    <string name=\"settings_before_download_desc\">ಕಾನ್ಫಿಗರ್ ಬಿಫೋರ್ ಡೌನ್ಲೋಡ್</string>\n    <string name=\"release_desc\">ಲುಕ್ ಫಾರ್ ಛಂಗೆಲೊಗ್ಸ್ ಅಂಡ್ ನ್ಯೂ ವೆರಿಸಿಯೋನ್ಸ್</string>\n    <string name=\"ytdlp_version\">Yt-dlp ವರ್ಷನ್</string>\n    <string name=\"display\">ಡಿಸ್ಪ್ಲೇ</string>\n    <string name=\"off\">ಆಫ್</string>\n    <string name=\"error_copied\">ಎರರ್ ರಿಪೋರ್ಟ್ ಕಪಿಡ್ ಟು ಕ್ಲಿಪ್ಬೋರ್ಡ್</string>\n    <string name=\"back\">ಬ್ಯಾಕ್</string>\n    <string name=\"downloads_history\">ಡೌನ್ಲೋಡ್ಸ್</string>\n    <string name=\"release\">ಲೇಟೆಸ್ಟ್ ರಿಲೀಸ್</string>\n    <string name=\"version\">ವರ್ಷನ್</string>\n    <string name=\"yt_dlp_update_fail\">ಕುಡ್ ನಾಟ್ ಇನ್ಸ್ಟಾಲ್ ದಿ ಲೇಟೆಸ್ಟ್ yt-dlp ವರ್ಷನ್. ಪ್ಲೀಸ್ ಮೇಕ್ ಸುರೆ ಯು ಆರ್ ಕನೆಕ್ಟೆಡ್ ಟು ದಿ ಇಂಟರ್ನೆಟ್.</string>\n    <string name=\"general_settings\">ಜನರಲ್</string>\n    <string name=\"print_details_desc\">ಪ್ರಿಂಟ್ ಡೀಟೈಲ್ಡ್ ಮೆಸ್ಸಗೆ ವೆನ್ ಡೌನ್ಲೋಅಡಿಂಗ್</string>\n    <string name=\"download_success_msg\">ಡೌನ್ಲೋಡ್ ಫೀನಿಶೆಡ್</string>\n    <string name=\"convert_audio_format\">ಕನ್ವರ್ಟ್ ಆಡಿಯೋ ಫಾರ್ಮ್ಯಾಟ್</string>\n    <string name=\"video_directory\">ವೀಡಿಯೊ ಫೋಲ್ಡರ್</string>\n    <string name=\"url_empty\">ದಿ ಲಿಂಕ್ ಕೆನಾಟ್ ಬಿ ಎಂಪ್ಟಿ</string>\n    <string name=\"paste\">ಪೇಸ್ಟ್</string>\n    <string name=\"delete_info_msg\">ರಿಮೋವ್ \\\"%1$s\\\" ಫ್ರಮ್ ಯುವರ್ ಡೌನ್ಲೋಡ್ ಹಿಸ್ಟರಿ ಫಾರ್ ಗುಡ್?</string>\n    <string name=\"download\">ಡೌನ್ಲೋಡ್</string>\n    <string name=\"create_thumbnail_summary\">ಸೇವ್ ವಿಡಿಯೋ ಥಂಬ್ನೇಲ್ ಆಸ್ ಆ ಫೈಲ್</string>\n    <string name=\"start_execute\">ಸ್ಟಾರ್ಟ್ ಎಕ್ಸಿಕ್ಯೂಟಿಂಗ್ ಕಮಾಂಡ್</string>\n    <string name=\"checked\">ಚೆಕಡ್</string>\n    <string name=\"about\">ಅಬೌಟ್</string>\n    <string name=\"open_url\">ಓಪನ್ ಲಿಂಕ್</string>\n    <string name=\"convert_audio_format_desc\">ರೇ-ಎನ್ಕೋಡಿಂಗ್ ಆಡಿಯೋ ಫೈಲ್ಸ್ ವಿಲ್ ಕಾಸ್ ಲೋಸ್ ಇನ್ ಆಡಿಯೋ ಕ್ವಾಲಿಟಿ ಅಂಡ್ ಇನ್ಕ್ರೀಜ್ ಇನ್ ಫೈಲ್ ಸೈಜ್.</string>\n    <string name=\"not_convert\">ಅನ್ಕನ್ವೆರ್ಟೆಡ್</string>\n    <string name=\"about_page\">ವರ್ಷನ್, ಫೀಡ್ಬ್ಯಾಕ್, ಆಟೋ ಅಪ್ಡೇಟ್</string>\n    <string name=\"thumbnail\">ತುಂಬಿನೈಲ್</string>\n    <string name=\"download_error_msg\">ಕುಡ್ ನಾಟ್ ಡೌನ್ಲೋಡ್ ಫೈಲ್</string>\n    <string name=\"custom_command_template\">ಕಮಾಂಡ್ ಟೆಂಪ್ಲೆಟ್</string>\n    <string name=\"download_start_msg\">ಡೌನ್ಲೋಡ್ \\\"%1$s\\\"</string>\n    <string name=\"dark_theme\">ಡಾರ್ಕ್ ಥೀಮ್</string>\n    <string name=\"cancel\">ಕ್ಯಾನ್ಸಲ್</string>\n    <string name=\"settings_before_download\">ಕಾನ್ಫಿಗರ್ ಬಿಫೋರ್ ಡೌನ್ಲೋಡ್</string>\n    <string name=\"confirm\">ಕನ್ಫರ್ಮ್</string>\n    <string name=\"permission_denied\">ಪರ್ಮಿಷನ್ ಡೇನಿಎಡ್</string>\n    <string name=\"language_settings\">ಸೆಟ್ ಡಿಸ್ಪ್ಲೇ ಲ್ಯಾಂಗ್ವೇಜ್</string>\n    <string name=\"follow_system\">ಸಿಸ್ಟಮ್</string>\n    <string name=\"delete_info\">ರಿಮೋವ್?</string>\n    <string name=\"language\">ಡಿಸ್ಪ್ಲೇ ಲ್ಯಾಂಗ್ವೇಜ್</string>\n    <string name=\"custom_command\">ಕಸ್ಟಮ್ ಕಮಾಂಡ್</string>\n    <string name=\"task_running\">ಎನ್ ಎಕ್ಸಿಸ್ಟಿಂಗ್ ಡೌನ್ಲೋಡ್ ಟಾಸ್ಕ್ ಇಸ್ ಆಲ್ರೆಡಿ ರನ್ನಿಂಗ್</string>\n    <string name=\"settings_before_download_text\">ಅಡ್ಜಸ್ಟ್ ದಿಸ್ ಡೌನ್ಲೋಡ್</string>\n    <string name=\"video\">ವಿಡಿಯೋ</string>\n    <string name=\"fetch_info_error_msg\">ಕುಡ್ ನಾಟ್ ಫೇತ್ಚ್ ವಿಡಿಯೋ ಇನ್ಫೋ</string>\n    <string name=\"settings\">ಸೆಟ್ಟಿಂಗ್ಸ್</string>\n    <string name=\"yt_dlp_up_to_date\">ಯೂಸಿಂಗ್ ದಿ ಲೇಟೆಸ್ಟ್ ವರ್ಷನ್ ಆ yt-dlp</string>\n    <string name=\"extract_audio\">ಸೇವ್ ಆಸ್ ಆಡಿಯೋ</string>\n    <string name=\"create_thumbnail\">ಸೇವ್ ಥಂಬ್‌ನೇಲ್</string>\n    <string name=\"convert_to\">ಕನ್ವರ್ಟ್ ಟು %1$s</string>\n    <string name=\"format\">ಫಾರ್ಮ್ಯಾಟ್</string>\n    <string name=\"ytdlp_update_action\">ಅಪ್ಡೇಟ್ yt-dlp</string>\n    <string name=\"audio\">ಆಡಿಯೋ</string>\n    <string name=\"edit_template_desc\">ಔಟ್ಪುಟ್ ಪಥ ಅಂಡ್ ಯುಆರ್ಎಲ್ ವಿಲ್ ಬಿ ಆಡೆಡ್ ಬೈ ದಿ ಅಪ್.</string>\n    <string name=\"credits\">ಕ್ರೆಡಿಟ್ಸ್</string>\n    <string name=\"fetching_info\">ಫೆಟಚಿಂಗ್ ವಿಡಿಯೋ ಇನ್ಫೋ…</string>\n    <string name=\"close\">ಕ್ಲೋಸ್</string>\n    <string name=\"user_guide\">ಯುಸರ್ ಗೈಡ್</string>\n    <string name=\"video_format_preference\">ಪ್ರಿಫರ್ಡ ವಿಡಿಯೋ ಫಾರ್ಮ್ಯಾಟ್</string>\n    <string name=\"check_download_settings_desc\">ಟೇಕ್ ಆ ಲುಕ್ ಅಟ್ ದಿ ಡೌನ್ಲೋಡ್ ಸೆಟ್ಟಿಂಗ್ಸ್ ಅಂಡ್ ಮೇಕ್ ಸುರೆ ಯು ಹಾವೇ ದಿ ಲೇಟೆಸ್ಟ್ ವರ್ಷನ್ ಆ yt-dlp ಬಿಫೋರ್ ಉಸಿಂಗ್ ಇಟ್.</string>\n    <string name=\"preferred_format_desc\">ಪ್ರಿಫರ್ಡ ಫಾರ್ಮ್ಯಾಟ್ ವೆನ್ ಮಲ್ಟಿಪಲ್ ಆರ್ ಪ್ರೊವಿಡೆಡ್</string>\n    <string name=\"download_playlist\">ಡೌನ್ಲೋಡ್ ಪ್ಲೇಲಿಸ್ಟ್</string>\n    <string name=\"paste_desc\">ಕ್ಲಿಕ್ \\\"ಪೇಸ್ಟ್\\\" ಟು ಗೆಟ್ ವಿಡಿಯೋ ಲಿಂಕ್ ಫ್ರಮ್ ಯುವರ್ ಕ್ಲಿಪ್ಬೋರ್ಡ್.</string>\n    <string name=\"convert_audio\">ಕನ್ವರ್ಟ್</string>\n    <string name=\"video_url\">ವಿಡಿಯೋ ಲಿಂಕ್</string>\n    <string name=\"channel_description\">ನೋಟಿಫ್ಯ್ ಆ ಡೌನ್ಲೋಅಡೆಡ್ ಫೈಲ್ಸ್ ಅಂಡ್ ಪ್ರೋಗ್ರೆಸ್</string>\n    <string name=\"download_notification\">ಡೌನ್ಲೋಡ್ ನೋಟಿಫಿಕೇಶನ್</string>\n    <string name=\"start_download\">ಡೌನ್ಲೋಡ್</string>\n    <string name=\"download_desc\">ಥೇನ್ ಕ್ಲಿಕ್ \\\"ಡೌನ್ಲೋಡ್\\\" ಆಫ್ಟರ್ ಅದ್ಜುಸ್ಟಿಂಗ್ ಇಟ್ಸ್ ಸೆಟ್ಟಿಂಗ್ಸ್.</string>\n    <string name=\"open_settings\">ಓಪನ್ ಸೆಟ್ಟಿಂಗ್ಸ್</string>\n    <string name=\"download_history_desc\">ಚೆಕ್ ಅಂಡ್ ಮ್ಯಾನೇಜ್ ಇನ್-ಅಪ್ಪ ಡೌನ್ಲೋಡ್ಸ್, ಇನ್ಕ್ಲೂಡಿಂಗ್ ವೀಡಿಯೋಸ್ ಅಂಡ್ ಆಡಿಯೋ ಫೈಲ್ಸ್.</string>\n    <string name=\"video_format\">ವಿಡಿಯೋ ಫಾರ್ಮ್ಯಾಟ್</string>\n    <string name=\"additional_settings\">ಅಡಿಷನಲ್ ಸೆಟ್ಟಿಂಗ್ಸ್</string>\n    <string name=\"video_quality_desc\">ಲಿಮಿಟ್ ದಿ ವಿಡಿಯೋ ಕ್ವಾಲಿಟಿ ವೆನ್ ಮಲ್ಟಿಪಲ್ ಆರ್ ಪ್ರೆಸೆಂಟ್</string>\n    <string name=\"download_playlist_desc\">ಡೌನ್ಲೋಡ್ ಮಲ್ಟಿಪಲ್ ವೀಡಿಯೋಸ್ ಫ್ರಮ್ ಆ ಪ್ಲೇಲಿಸ್ಟ್</string>\n    <string name=\"options\">ಆಪ್ಷನ್</string>\n    <string name=\"share_fail_msg\">ಅನೆಬೆಲ್ ಟು ಮ್ಯಾಚ್ ಯುಆರ್ಎಲ್ ಫ್ರಮ್ ಶಾರ್ಡ್ ಕಂಟೆಂಟ್</string>\n    <string name=\"concurrent_download\">ಮಲ್ಟಿ-ತ್ರೆಡ್ಗ್ದ್ ಡೌನ್ಲೋಡ್</string>\n    <string name=\"concurrent_download_desc\">ಡೌನ್ಲೋಡ್ ಮೋರ್ ಪಾರ್ಟ್ಸ್ ಆ ಎಂ೩ಉ೮/ಮೈಫ್ಡ್ ವೀಡಿಯೋಸ್ ಇನ್ ಪ್ಯಾರಲಲ್</string>\n    <string name=\"show_more_actions\">ಶೋ ಮೊರೆ ಆಪ್ಷನ್</string>\n    <string name=\"close_never_show_again\">ಡೋಂಟ್ ಶೋ ಅಪ್ ಅಗೈನ್</string>\n    <string name=\"download_finish_notification\">ಡೌನ್ಲೋಡ್ ಫೀನಿಶೇಡ್. ಟಾಪ್ ಟು ಓಪನ್.</string>\n    <string name=\"channel_name\">ಡೌನ್ಲೋಡ್</string>\n    <string name=\"battery_settings_desc\">ಪ್ಲೀಸ್ ಸೆಟ್ ಬ್ಯಾಟರಿ ಯೂಸೇಜ್ ಆ ದಿಸ್ ಅಪ್ಪ ಟು \\\"ಉಂರೆಸ್ಟ್ರಿಕ್ಟ್ದ್\\\" ಇನ್ ದಿ ಸಿಸ್ಟಮ್ ಸೆಟ್ಟಿಂಗ್ಸ್ ಟು ಡೌನ್ಲೋಡ್ ಇನ್ ದಿ ಬ್ಯಾಕ್ಗ್ರೌಂಡ್.</string>\n    <string name=\"not_specified\">ನಾಟ್ ಸ್ಪೆಸಿಫೈಡ್ (ಡೀಫಾಲ್ಟ್)</string>\n    <string name=\"concurrent_download_num\">%d ಥ್ರೆಡ್(ಸ್) ವಸ್ಲ್ಡ್ ಬಿ ಉಸೆದ್ ಟು ಡೌನ್ಲೋಡ್ ಡ್ಯಾಶ್/ಹ್ಲ್ಸ್ ನೇಟಿವ್ ವಿಡಿಯೋ ಕಾಂಕರೆಂಟಿಲಿ.</string>\n    <string name=\"execute_command_notification\">ರನ್ನಿಂಗ್ ಕಸ್ಟಮ್ ಕಮಂಡ್ಸ್…</string>\n    <string name=\"defaults\">ಡೀಫಾಲ್ಟ್</string>\n    <string name=\"share_success_msg\">ರೀಡಿಂಗ್ ವಿಡಿಯೋ ಲಿಂಕ್ ಫ್ರಮ್ ಶಾರ್ಡ್ ಕಂಟೆಂಟ್…</string>\n    <string name=\"best_quality\">ಬೆಸ್ಟ್ ಕ್ವಾಲಿಟಿ</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ko/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"settings\">설정</string>\n    <string name=\"download_error_msg\">파일을 다운로드할 수 없습니다</string>\n    <string name=\"yt_dlp_update_fail\">최신 yt-dlp 버전을 설치할 수 없습니다. 인터넷에 연결되어 있는지 확인해주세요.</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" 다운로드</string>\n    <string name=\"fetch_info_error_msg\">동영상 정보를 가져올 수 없습니다</string>\n    <string name=\"language\">언어</string>\n    <string name=\"paste_msg\">URL 붙여넣기</string>\n    <string name=\"audio\">오디오</string>\n    <string name=\"delete_info_msg\">다운로드 기록에서 \\\"%1$s\\\"을(를) 삭제할까요\\?</string>\n    <string name=\"yt_dlp_up_to_date\">최신 버전의 yt-dlp 사용 중</string>\n    <string name=\"create_thumbnail_summary\">동영상 썸네일을 파일로 저장</string>\n    <string name=\"extract_audio_summary\">동영상 대신 오디오 다운로드 및 저장</string>\n    <string name=\"language_settings\">언어 설정</string>\n    <string name=\"delete_info\">삭제하실 건가요\\?</string>\n    <string name=\"downloads_history\">다운로드</string>\n    <string name=\"delete_file\">파일 삭제</string>\n    <string name=\"about\">정보</string>\n    <string name=\"ytdlp_update\">yt-dlp의 최신버전을 설치하려면 클릭하세요</string>\n    <string name=\"paste_fail_msg\">클립보드의 URL을 일치시킬 수 없습니다</string>\n    <string name=\"ytdlp_version\">Yt-dlp 버전</string>\n    <string name=\"confirm\">확인</string>\n    <string name=\"dismiss\">취소</string>\n    <string name=\"open_url\">링크 열기</string>\n    <string name=\"remove\">목록에서 제거</string>\n    <string name=\"release\">최신 릴리스</string>\n    <string name=\"checked\">체크됨</string>\n    <string name=\"advanced_settings\">고급 옵션</string>\n    <string name=\"about_page\">버전, 피드백, 자동 업데이트</string>\n    <string name=\"version\">버전</string>\n    <string name=\"release_desc\">변경 로그 및 새 버전 찾기</string>\n    <string name=\"back\">뒤로</string>\n    <string name=\"readme_desc\">GitHub 저장소 및 사용방법 확인</string>\n    <string name=\"video\">동영상</string>\n    <string name=\"edit\">편집</string>\n    <string name=\"start_execute\">명령 실행 시작</string>\n    <string name=\"credits\">크레딧</string>\n    <string name=\"credits_desc\">크레딧 및 자유 소프트웨어</string>\n    <string name=\"custom_command\">사용자 지정 명령</string>\n    <string name=\"custom_command_desc\">맞춤 템플릿으로 yt-dlp 명령어 실행</string>\n    <string name=\"general_settings\">일반</string>\n    <string name=\"link_copied\">클립보드에 복사된 링크</string>\n    <string name=\"task_running\">다운로드 작업이 이미 실행 중입니다</string>\n    <string name=\"extract_audio\">오디오로 저장</string>\n    <string name=\"create_thumbnail\">썸네일 저장</string>\n    <string name=\"download_settings_desc\">일반, 서식, 사용자 지정 명령</string>\n    <string name=\"video_directory\">동영상 폴더</string>\n    <string name=\"custom_command_template\">명령 템플릿</string>\n    <string name=\"download\">다운로드</string>\n    <string name=\"url_empty\">링크는 비워둘 수 없습니다</string>\n    <string name=\"fetching_info\">동영상 정보를 가져오는 중…</string>\n    <string name=\"permission_denied\">권한이 거부되었습니다</string>\n    <string name=\"download_success_msg\">다운로드가 완료되었습니다</string>\n    <string name=\"convert_audio_format\">오디오 형식 변환</string>\n    <string name=\"preferred_format_desc\">여러 개가 제공될 때 선호하는 형식</string>\n    <string name=\"video_quality\">비디오 품질</string>\n    <string name=\"best_quality\">최고 품질</string>\n    <string name=\"video_quality_desc\">여러 개가 있는 경우 비디오 품질을 제한합니다</string>\n    <string name=\"video_url\">비디오 링크</string>\n    <string name=\"open_settings\">설정 열기</string>\n    <string name=\"download_directory_desc\">비디오 및 오디오 파일을 저장할 위치 선택</string>\n    <string name=\"subdirectory\">하위 디렉터리에 저장</string>\n    <string name=\"download_directory\">다운로드 디렉터리</string>\n    <string name=\"battery_configuration\">배터리 구성</string>\n    <string name=\"embed_subtitles_desc\">동영상에 제공되는 자막 포함 (사용 가능한 경우)</string>\n    <string name=\"paste_desc\">클립보드에서 비디오 링크를 가져오려면 \\\"붙여넣기\\\"를 클릭하세요.</string>\n    <string name=\"not_convert\">변환되지 않은</string>\n    <string name=\"on\">켜짐</string>\n    <string name=\"dark_theme\">어두운 테마</string>\n    <string name=\"concurrent_download\">다중 스레드 다운로드</string>\n    <string name=\"off\">꺼짐</string>\n    <string name=\"paste\">붙여넣기</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp 사용 참조</string>\n    <string name=\"edit_template_desc\">출력 경로와 URL은 앱에서 추가됩니다.</string>\n    <string name=\"video_format\">비디오 형식</string>\n    <string name=\"convert_audio\">변환</string>\n    <string name=\"start_download\">다운로드</string>\n    <string name=\"user_guide\">사용자 설명서</string>\n    <string name=\"close\">닫음</string>\n    <string name=\"close_never_show_again\">다시 표시하지 않음</string>\n    <string name=\"download_desc\">설정을 조정한 후 \\\"다운로드\\\"를 클릭하세요.</string>\n    <string name=\"download_history_desc\">비디오 및 오디오 파일을 포함한 앱 내 다운로드를 확인하고 관리합니다.</string>\n    <string name=\"check_download_settings_desc\">다운로드 설정을 살펴보고 yt-dlp의 최신 버전이 있는지 확인한 후 사용하십시오.</string>\n    <string name=\"concurrent_download_desc\">더 많은 M3U8/MPD 비디오 부분들을 동시에 다운로드</string>\n    <string name=\"concurrent_download_num\">%d 스레드는 DASH/HLS 기본 비디오를 동시에 다운로드하는 데 사용됩니다.</string>\n    <string name=\"embed_subtitles\">자막 포함</string>\n    <string name=\"new_template\">새 템플릿</string>\n    <string name=\"template_label\">라벨</string>\n    <string name=\"remove_template\">제거\\?</string>\n    <string name=\"remove_template_desc\">명령 템플릿에서 %1$s을(를) 제거하시겠습니까\\?</string>\n    <string name=\"download_notification\">다운로드 알림</string>\n    <string name=\"invalid_index_range\">잘못된 인덱스 범위</string>\n    <string name=\"audio_directory\">오디오 폴더</string>\n    <string name=\"unknown_error\">알수없는 오류</string>\n    <string name=\"print_details\">상세 출럭</string>\n    <string name=\"print_details_desc\">다운로드 시 자세한 메시지 출력</string>\n    <string name=\"display\">디스플레이</string>\n    <string name=\"display_settings\">어두운 테마, 동적 색상, 언어</string>\n    <string name=\"cancel\">취소</string>\n    <string name=\"settings_before_download\">다운로드하기 전 설정하기</string>\n    <string name=\"settings_before_download_desc\">다운로드 전에 설정 변경하기</string>\n    <string name=\"settings_before_download_text\">이 다운로드 조정</string>\n    <string name=\"error_copied\">클립보드에 오류 보고서가 복사됨</string>\n    <string name=\"convert_to\">%1$s 로 변환</string>\n    <string name=\"format\">형식</string>\n    <string name=\"not_specified\">지정되지 않음 (기본값)</string>\n    <string name=\"video_format_preference\">선호하는 비디오 형식</string>\n    <string name=\"download_playlist\">재생 목록 다운로드</string>\n    <string name=\"defaults\">기본</string>\n    <string name=\"channel_name\">다운로드</string>\n    <string name=\"channel_description\">다운로드한 파일 및 진행 상황 알림</string>\n    <string name=\"download_finish_notification\">다운로드가 완료되었습니다. 열려면 탭하세요.</string>\n    <string name=\"execute_command_notification\">사용자 지정 명령 실행 중…</string>\n    <string name=\"battery_settings_desc\">백그라운드에서 다운로드하려면 시스템 설정에서 이 앱의 배터리 항목을 \\\"제한없음\\\"으로 설정하세요.</string>\n    <string name=\"options\">옵션</string>\n    <string name=\"additional_settings\">추가 설정</string>\n    <string name=\"share_fail_msg\">공유 콘텐츠의 URL을 일치시킬 수 없습니다</string>\n    <string name=\"share_success_msg\">공유 콘텐츠에서 비디오 링크를 읽는 중…</string>\n    <string name=\"show_more_actions\">추가 작업 표시</string>\n    <string name=\"download_notification_desc\">다운로드한 파일 및 진행 상황 알림</string>\n    <string name=\"fetching_playlist_info\">재생목록 정보를 가져오는 중…</string>\n    <string name=\"download_range_selection\">재생 목록 선택</string>\n    <string name=\"subdirectory_desc\">각 필드 이름으로 지정된 폴더에 파일 저장</string>\n    <string name=\"permission_issue\">저장소 권한 문제</string>\n    <string name=\"permission_issue_desc\">Download/ 및 Documents/ 이외의 외부 디렉토리는 지원되지 않습니다</string>\n    <string name=\"service_title\">Seal 다운로드 중…</string>\n    <string name=\"translate\">번역</string>\n    <string name=\"translate_desc\">Hosted Weblate에서 이 앱의 번역을 도울수 있습니다</string>\n    <string name=\"prefix\">접두사</string>\n    <string name=\"to\">끝</string>\n    <string name=\"follow_system\">시스템</string>\n    <string name=\"convert_audio_format_desc\">오디오 파일을 다시 인코딩하면 오디오 품질이 저하되고 파일 크기가 커집니다.</string>\n    <string name=\"thumbnail\">썸네일</string>\n    <string name=\"download_playlist_desc\">재생 목록에서 여러 비디오 다운로드</string>\n    <string name=\"download_range_desc\">재생 목록 \\\"%3$s\\\" (%1$d ~ %2$d)에서 다운로드할 비디오 범위를 지정하십시오.</string>\n    <string name=\"from\">시작</string>\n    <string name=\"playlist_indicator_text\">재생 목록(%1$d/%2$d)을 다운로드하는 중입니다…</string>\n    <string name=\"battery_configuration_desc\">이 앱이 백그라운드에서 다운로드하려면 배터리 최적화를 해제하세요</string>\n    <string name=\"video_only\">비디오 (오디오 없음)</string>\n    <string name=\"suggested\">제안</string>\n    <string name=\"restart\">재시작</string>\n    <string name=\"template_selection\">템플릿 선택</string>\n    <string name=\"dynamic_color\">동적 색상</string>\n    <string name=\"network_settings_desc\">속도 제한, 다운로더, 쿠키</string>\n    <string name=\"download_selection_desc\">재생목록 \\\"%1$s\\\"에서 다운로드할 동영상을 선택</string>\n    <string name=\"selected_item_count\">%1$d 선택됨</string>\n    <string name=\"crop_artwork_desc\">포함된 이미지를 정사각형으로 자르기</string>\n    <string name=\"select_all\">모두 선택</string>\n    <string name=\"cookies_desc\">다운로드에 Netscape 형식의 쿠키 사용</string>\n    <string name=\"dynamic_color_desc\">배경화면의 색상을 앱 테마에 적용</string>\n    <string name=\"rate_limit\">속도 제한</string>\n    <string name=\"status_completed\">완료</string>\n    <string name=\"multiselect_mode\">다중 선택 모드</string>\n    <string name=\"clear_temp_files_count\">%1$d개의 임시 파일 삭제</string>\n    <string name=\"lowest_quality\">최저 품질</string>\n    <string name=\"cookies\">쿠키</string>\n    <string name=\"disable_preview_desc\">다운로드 중 미리 보기 표시 안 함</string>\n    <string name=\"privacy\">프라이버시</string>\n    <string name=\"downloading_indicator_text\">다운로드가 진행 중입니다…</string>\n    <string name=\"task_canceled\">다운로드 작업이 취소됨</string>\n    <string name=\"github_issue\">깃허브 이슈</string>\n    <string name=\"github_issue_desc\">버그 보고서 또는 기능 요청을 위해 문제 제출</string>\n    <string name=\"info_copied\">클립보드에 복사된 정보</string>\n    <string name=\"status_enqueued\">대기 중</string>\n    <string name=\"aria2_desc\">aria2c를 외부 다운로더로 사용</string>\n    <string name=\"update\">업데이트</string>\n    <string name=\"clear_temp_files\">임시 파일 지우기</string>\n    <string name=\"clear_temp_files_desc\">임시 디렉토리에서 모든 임시 파일 삭제</string>\n    <string name=\"clear_temp_files_info\">임시 파일을 사용하여 취소된 다운로드를 다시 시작할 수 있습니다. 이 파일들을 모두 삭제하시겠습니까?\n\\n\n\\n%1$s에서 이 파일들을 접근할 수 있습니다</string>\n    <string name=\"private_mode\">시크릿 모드</string>\n    <string name=\"private_mode_desc\">다운로드 기록 사용 안 함</string>\n    <string name=\"high_contrast\">고대비 어두운 테마</string>\n    <string name=\"invalid_input\">잘못된 입력</string>\n    <string name=\"format_settings_desc\">파일 형식, 비디오 품질, 자막</string>\n    <string name=\"unavailable\">사용할수 없음</string>\n    <string name=\"crop_artwork\">아트웍 자르기</string>\n    <string name=\"custom_command_template_desc\">명령 템플릿 편집 및 관리</string>\n    <string name=\"download_task_count\">%1$d 다운로드 작업</string>\n    <string name=\"recently_added\">최근에 추가됨</string>\n    <string name=\"multiselect_item_count\">비디오 파일 %1$d개, 오디오 파일 %2$d개</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock 범주</string>\n    <string name=\"check_for_updates\">업데이트 확인</string>\n    <string name=\"check_for_updates_desc\">GitHub에서 최신 버전 자동 확인</string>\n    <string name=\"download_with_cellular_desc\">데이터 통신 네트워크에 연결된 경우 미디어 다운로드 허용</string>\n    <string name=\"download_disabled_with_cellular\">설정에 따라 모바일 데이터로 다운로드할 수 없습니다</string>\n    <string name=\"file_unavailable\">이 파일은 더 이상 사용할 수 없습니다</string>\n    <string name=\"network\">네트워크</string>\n    <string name=\"disable_preview\">미리보기 비활성화</string>\n    <string name=\"private_directory\">개인 디렉토리</string>\n    <string name=\"use_custom_command\">사용자 지정 명령 사용</string>\n    <string name=\"private_directory_desc\">숨겨진 디렉터리에 다운로드</string>\n    <string name=\"status_canceled\">취소 됨</string>\n    <string name=\"template_exported\">%1$d개의 템플릿을 내보냈습니다</string>\n    <string name=\"template_imported\">%1$d개의 템플릿을 가져왔습니다</string>\n    <string name=\"delete_multiple_items_msg\">다운로드 기록에서 %1$d 항목을 제거하시겠습니까\\?</string>\n    <string name=\"download_with_cellular\">모바일 데이터를 사용하여 다운로드</string>\n    <string name=\"rate_limit_desc\">다운로드 최대 속도 제한</string>\n    <string name=\"status_downloading\">다운로드 중</string>\n    <string name=\"status_fetching_video_info\">정보를 가져오는 중</string>\n    <string name=\"open_file\">파일 열기</string>\n    <string name=\"status_error\">오류</string>\n    <string name=\"copy_link\">링크 복사</string>\n    <string name=\"copy_error_report\">보고서 복사하기</string>\n    <string name=\"video_resolution\">비디오 해상도</string>\n    <string name=\"video_file_size\">비디오 파일 크기</string>\n    <string name=\"export_to_clipboard\">클립보드로 내보내기</string>\n    <string name=\"import_from_clipboard\">클립보드에서 가져오기</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API를 사용하여 비디오에서 세그먼트를 제거하거나 마킹</string>\n    <string name=\"sponsorblock_categories_desc\">비디오 파일에서 제거하거나 마킹할 SponsorBlock 범주 지정</string>\n    <string name=\"app_up_to_date\">현재 버전이 최신입니다</string>\n    <string name=\"app_update_failed\">최신 버전으로 업데이트하지 못했습니다</string>\n    <string name=\"max_rate\">최대 비율</string>\n    <string name=\"general_settings_desc\">Yt-dlp 버전, 알림, 재생목록</string>\n    <string name=\"unlimited\">무제한</string>\n    <string name=\"audio_quality\">오디오 품질</string>\n    <string name=\"audio_format_preference\">선호하는 오디오 형식</string>\n    <string name=\"lowest_bitrate\">최저 전송률</string>\n    <string name=\"audio_quality_desc\">여러 품질이 존재할 때 오디오 비트 전송률 제한</string>\n    <string name=\"format_sorting_desc\">yt-dlp의 -S 옵션으로 형식 정렬</string>\n    <string name=\"format_sorting\">형식 정렬</string>\n    <string name=\"audio_format\">오디오 형식</string>\n    <string name=\"no_downloaded_media\">다운로드한 미디어 없음</string>\n    <string name=\"beta_features\">베타</string>\n    <string name=\"enable_experimental_feature\">실험 기능을 사용하시겠습니까\\?</string>\n    <string name=\"clip_video_dialog_msg\">이 기능을 사용하는 다운로드는 비디오의 선택된 섹션을 다운로드할때 FFmpeg에게 위임됩니다. 이 기능은 아직 실험적이며 자르기가 완전히 정확하지 않습니다. 또한 모든 형식이 이 기능을 지원하는 것은 아니며 다운로드 속도가 느려질 수 있습니다.</string>\n    <string name=\"clip_video_desc\">형식 선택 페이지에서 비디오 클립 만들기</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"format_selection\">형식 선택</string>\n    <string name=\"stable_channel\">안정</string>\n    <string name=\"pre_release_channel\">미리 보기</string>\n    <string name=\"update_channel\">채널 업데이트</string>\n    <string name=\"auto_update\">자동 업데이트</string>\n    <string name=\"enable_auto_update\">자동 업데이트 사용</string>\n    <string name=\"sponsor_msg\">Seal은 항상 무료이며 모든 사람을 위한 오픈 소스입니다. 마음에 드신다면 GitHub에서 저를 후원해 주세요!</string>\n    <string name=\"msg_from_developer\">개발자 메시지</string>\n    <string name=\"sponsor_msg2\">매우 감사합니다!</string>\n    <string name=\"switch_to_github_builds\">GitHub 빌드로 전환</string>\n    <string name=\"okay\">좋아요</string>\n    <string name=\"got_it\">알겠어요</string>\n    <string name=\"feature_unavailable\">사용할 수 없는 기능입니다</string>\n    <string name=\"discard\">버림</string>\n    <string name=\"clip_video\">동영상 클립</string>\n    <string name=\"clip_start\">시작</string>\n    <string name=\"clip_end\">끝</string>\n    <string name=\"apply\">적용</string>\n    <string name=\"generate_new_cookies\">새 쿠키 생성</string>\n    <string name=\"telegram_channel\">텔레그램 채널</string>\n    <string name=\"matrix_space\">행렬 공간</string>\n    <string name=\"use_cookies\">쿠키 사용</string>\n    <string name=\"remove_cookie_profile_desc\">\\\"%1$s\\\"의 항목를 제거하시겠습니까? 이 사이트를 위해 저장된 쿠키는 삭제되지 않습니다.</string>\n    <string name=\"how_does_it_work\">어떻게 작동합니까\\?</string>\n    <string name=\"cookies_usage_msg\">일부 사이트에서 다운로드하려면 계정 인증 정보가 필요합니다. \\\"새 쿠키 생성\\\"을 클릭하고 웹 사이트의 URL을 입력한 다음 브라우저 페이지에서 계정으로 로그인하면 앱에서 해당 쿠키를 생성합니다.</string>\n    <string name=\"abs_hint\">대부분의 비디오 스트리밍 플랫폼은 오디오와 비디오를 별도로 제공하므로 오디오 전용 형식을 비디오 전용 형식으로 선택하여 단일 비디오로 병합할 수 있습니다.</string>\n    <string name=\"custom_command_enabled_hint\">사용자 지정 명령을 사용하는 경우 일부 옵션을 사용할 수 없습니다</string>\n    <string name=\"subtitle\">자막</string>\n    <string name=\"title_activity_share\">빠른 다운로드</string>\n    <string name=\"video_title_sample_text\">동영상 제목 샘플 텍스트</string>\n    <string name=\"video_creator_sample_text\">동영상 제작자 샘플 텍스트</string>\n    <string name=\"download_subtitles\">자막 다운로드</string>\n    <string name=\"subtitle_language\">자막 언어</string>\n    <string name=\"subtitle_desc\">언어, 내장 자막, 자동 캡션</string>\n    <string name=\"auto_subtitle_desc\">자동 생성된 캡션 다운로드</string>\n    <string name=\"sdcard_directory\">SD 카드 폴더</string>\n    <string name=\"auto_subtitle\">자동 캡션</string>\n    <string name=\"copy_log\">로그 복사</string>\n    <string name=\"shortcuts\">바로 가기</string>\n    <string name=\"edit_shortcuts\">바로 가기 편집</string>\n    <string name=\"running_tasks\">작업 실행</string>\n    <string name=\"show_logs\">로그 표시</string>\n    <string name=\"add\">추가</string>\n    <string name=\"edit_shortcuts_desc\">명령 템플릿을 작성하는 데 사용할 수 있는 사용자 지정 바로 가기를 편집합니다.</string>\n    <string name=\"clear\">지우기</string>\n    <string name=\"embed_subtitles_mkv_msg\">자막을 삽입하기 위해 동영상은 mkv 컨테이너로 리먹스됩니다. VLC 미디어 플레이어 등 지원되는 플레이어로 재생할 수 있습니다.</string>\n    <string name=\"sponsor\">후원하기</string>\n    <string name=\"format_selection_desc\">다운로드를 시작하기 전에 다운로드할 형식 선택</string>\n    <string name=\"subtitle_sponsorblock\">SponsorBlock 세그먼트를 제거할 때 자막이 누락될 수 있습니다.</string>\n    <string name=\"update_channel_desc\">새로운 기능과 변경 사항을 미리 보기위해 시험판 빌드를 설치합니다.\n\\n\n\\n이러한 버전에는 약간의 불안정성이 있을 수 있으므로, 향후 앱을 개선하는 데 도움이 되도록 문제가 발생하면 주저하지 말고 피드백을 보내주세요.</string>\n    <string name=\"auto_update_disabled_msg\">%1$s 빌드에는 자동 업데이트를 사용할 수 없습니다. 장치에 %1$s이(가) 설치되어 있지 않거나 Seal의 향후 새 기능을 미리 보려면 %2$s를 고려하세요.</string>\n    <string name=\"no_custom_command_tasks\">사용자 지정 명령 작업 없음</string>\n    <string name=\"title\">제목</string>\n    <string name=\"download_video_desc\">URL에서 동영상 다운로드</string>\n    <string name=\"second\">초</string>\n    <string name=\"clear_all_cookies_desc\">앱에 저장된 모든 쿠키를 완전히 삭제하시겠습니까\\?</string>\n    <string name=\"logs\">로그</string>\n    <string name=\"share\">공유</string>\n    <string name=\"import_from_preferences\">불러옴</string>\n    <string name=\"rename\">이름 바꾸기</string>\n    <string name=\"minute\">분</string>\n    <string name=\"clear_all_cookies\">모든 쿠키 지우기</string>\n    <string name=\"sponsor_desc\">GitHub에서 후원하여 이 앱을 지원해주세요</string>\n    <string name=\"feedback\">피드백</string>\n    <string name=\"sponsors\">후원자</string>\n    <string name=\"temporary_directory_desc\">내부 디렉토리에 임시 파일 저장</string>\n    <string name=\"split_video_msg\">영상은 %1$d개의 장으로 분할됩니다</string>\n    <string name=\"split_video\">동영상 분할</string>\n    <string name=\"convert_subtitle_desc\">자막을 다른 포맷으로 변환</string>\n    <string name=\"convert_subtitle\">자막 변환</string>\n    <string name=\"unknown_error_title\">이런! 무언가 잘못되었습니다</string>\n    <string name=\"copy_and_exit\">복사 및 종료</string>\n    <string name=\"proxy\">프록시</string>\n    <string name=\"proxy_desc\">인터넷 연결에 프록시 사용</string>\n    <string name=\"enable_notifications\">알림을 활성화하나요\\?</string>\n    <string name=\"disable\">비활성화</string>\n    <string name=\"custom_command_directory\">커스텀 명령어 디렉토리</string>\n    <string name=\"disabled\">비활성화됨</string>\n    <string name=\"prefer_quality_desc\">지원되는 앱으로 재생 시 AV1, VP9, H.265 포맷을 선호</string>\n    <string name=\"start\">시작</string>\n    <string name=\"edit_template\">\\\"%1$s\\\" 편집</string>\n    <string name=\"ytdlp_update_action\">yt-dlp 업데이트</string>\n    <string name=\"quality\">품질</string>\n    <string name=\"enable_notifications_desc\">다운로드 상태와 진행도 알림을 표시할 권한이 필요합니다.</string>\n    <string name=\"folder_picker\">폴더 선택기</string>\n    <string name=\"prefer_compatibility_desc\">다른 앱에 공유할 때 MP4(H.264) 포맷을 선호</string>\n    <string name=\"set_directory_desc\">탭하여 디렉토리 설정</string>\n    <string name=\"custom_command_directory_desc\">커스텀 명령어를 사용할 때 출력 디렉토리를 설정합니다</string>\n    <string name=\"legacy\">레거시</string>\n    <string name=\"expand\">펼치기</string>\n    <string name=\"new_task\">새 다운로드 작업</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp는 영상 다운로드를 위한 강력한 명령줄 도구입니다. Seal은 직관적인 GUI와 일반적인 명령어들을 위한 프리셋들, 기타 추가적인 기능들을 제공함으로써 yt-dlp을 쉽게 사용할 수 있습니다.\n\\n\n\\nyt-dlp의 고급 사용을 위해 Seal은 커스텀 명령어 템플릿을 제작과 저장, 터미널에서처럼 직접 실행할 수도 있습니다.\n\\n\n\\n커스텀 명령어 사용 시, 대부분의 GUI 옵션과 기능들이 비활성화될 것입니다.</string>\n    <string name=\"clear_download_archive\">다운로드 아카이브를 비울까요?</string>\n    <string name=\"save\">저장</string>\n    <string name=\"export_to_file\">파일로 내보내기</string>\n    <string name=\"commands\">명령어</string>\n    <string name=\"clear_download_archive_desc\">정말로 %1$s를 아카이브 파일에서 삭제할까요?</string>\n    <string name=\"website\">웹사이트</string>\n    <string name=\"learn_more\">더 알아보기</string>\n    <string name=\"download_type\">다운로드 유형</string>\n    <string name=\"embed_metadata\">메타데이터 포함하기</string>\n    <string name=\"presets\">프리셋</string>\n    <string name=\"ua_header\">User-Agent 헤더</string>\n    <string name=\"restrict_filenames_desc\">호환성을 위해 파일명에 사용 가능한 문자를 제한합니다</string>\n    <string name=\"required\">필수</string>\n    <string name=\"show_all_items\">%1$d개의 항목 모두 표시</string>\n    <string name=\"output_template\">출력 템플릿</string>\n    <string name=\"auto\">자동</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">항목 %d개</item>\n    </plurals>\n    <string name=\"refresh_cookies_desc\">탭하여 새로운 쿠키 생성을 위해 웹페이지 열기:</string>\n    <string name=\"restrict_filenames\">파일명 제한</string>\n    <string name=\"edit_file\">파일 편집</string>\n    <string name=\"download_archive_desc\">중복 다운로드를 방지하기 위해 다운로드한 영상 ID들을 아카이브에 기록합니다</string>\n    <string name=\"custom\">커스텀</string>\n    <string name=\"embed_metadata_desc\">메타데이터와 영상 썸네일을 오디오 파일에 포함시킵니다</string>\n    <string name=\"playlist_title\">플레이리스트 제목</string>\n    <string name=\"download_archive\">다운로드 아카이브</string>\n    <string name=\"remove_multiple_templates_msg\">정말로 커스텀 템플릿에서 %1$s를 삭제할까요?</string>\n    <string name=\"download_with_cellular_request\">모바일 네트워크로 다운로드하는 것을 허용할까요?</string>\n    <string name=\"merge_audiostream_desc\">한 파일에 여러 오디오 스트림들을 합칠 수 있게 합니다</string>\n    <string name=\"unknown\">알 수 없음</string>\n    <string name=\"output_template_desc\">출력 파일명들을 위한 템플릿 지정</string>\n    <string name=\"allow_once\">한 번 허용하기</string>\n    <string name=\"use_format_sorting\">형식 정렬 사용하기</string>\n    <string name=\"allow_always\">항상 허용하기</string>\n    <string name=\"dont_allow\">허용하지 않기</string>\n    <string name=\"merge_audiostream\">여러 오디오 스트림 합치기</string>\n    <string name=\"subdirectory_hint\">다음과 같이 다운로드가 저장됩니다:</string>\n    <string name=\"keep_subtitle_files\">자막 파일 유지하기</string>\n    <string name=\"format_preference\">형식 선호 설정</string>\n    <string name=\"system_settings\">시스템 설정</string>\n    <string name=\"force_ipv4\">강제 IPv4</string>\n    <string name=\"force_ipv4_desc\">모든 연결을 IPv4로 연결합니다</string>\n    <string name=\"search_in_downloads\">다운로드 검색</string>\n    <string name=\"search\">검색</string>\n    <string name=\"auto_translated_subtitles\">자동 번역 자막</string>\n    <string name=\"remember_for_next_download\">다음 다운로드에도 적용하기</string>\n    <string name=\"look_and_feel\">보기 &amp; 느낌</string>\n    <string name=\"use_previous_selection\">이전 선택 사용하기</string>\n    <string name=\"none\">없음</string>\n    <string name=\"subtitle_language_desc\">자동 형식 선택으로 다운로드할 자막들의 언어, 콤마로 분리합니다.</string>\n    <string name=\"reset\">초기화</string>\n    <string name=\"search_in_subtitles\">자막에서 검색</string>\n    <string name=\"no_thanks\">괜찮아요</string>\n    <string name=\"auto_translated_subtitles_msg\">모든 언어에 대해 자동 번역된 자막들을 다운로드합니다. 이 자막들은 정확하지 않아 이해하기 어려울 수 있습니다.</string>\n    <string name=\"import_backup\">불러오기</string>\n    <string name=\"import_download_history_msg\">다운로드된 파일들은 불러오지 않으며, 수동으로 다시 다운로드해야 합니다</string>\n    <string name=\"download_archive_error\">비디오가 다운로드되었습니다. 이게 예상치 못한 현상이라면, 다운로드 아카이브를 확인해주세요.</string>\n    <string name=\"import_from\">불러오기</string>\n    <string name=\"import_download_history\">다운로드 기록을 불러올까요?</string>\n    <string name=\"interface_and_interaction\">인터페이스 &amp; 상호작용</string>\n    <string name=\"export_backup\">내보내기</string>\n    <string name=\"full_backup\">전체 백업</string>\n    <string name=\"backup_type\">백업 유형</string>\n    <string name=\"export_to\">내보내기</string>\n    <string name=\"file\">파일</string>\n    <string name=\"clipboard\">클립보드</string>\n    <string name=\"export_download_history\">다운로드 기록을 내보낼까요?</string>\n    <string name=\"export_download_history_msg\">다운로드 기록에서 %1$s를 내보내는 중입니다. 다운로드된 파일들과 설정은 백업되지 않습니다.</string>\n    <string name=\"download_history\">다운로드 기록</string>\n    <string name=\"update_language_msg\">다음 언어들이 미래의 다운로드들을 위한 설정에 추가됩니다:</string>\n    <string name=\"update_subtitle_languages\">자막 언어를 업데이트할까요?</string>\n    <string name=\"download_history_imported\">다운로드 기록에 %1$s를 불러옴</string>\n    <string name=\"redownload\">재다운로드</string>\n    <string name=\"remux_container_mkv\">비디오 컨테이너 리묵스</string>\n    <string name=\"remux_container_mkv_desc\">더 나은 호환성을 위해 비디오를 MKV 컨테이너로 리묵스하기</string>\n    <string name=\"every_week\">매주</string>\n    <string name=\"every_month\">매월</string>\n    <string name=\"every_day\">매일</string>\n    <string name=\"cookies_in_database\">%2$d개의 웹사이트의 총 %1$d개의 쿠키 저장 중</string>\n    <string name=\"all_languages\">모든 언어</string>\n    <string name=\"playlist\">재생목록</string>\n    <string name=\"proceed\">계속하기</string>\n    <string name=\"preset_format_selection_desc\">형식 설정을 사용하여 자동으로 다운로드합니다</string>\n    <string name=\"edit_preset\">프리셋 편집</string>\n    <string name=\"best_quality_desc\">가능한 최고 품질을 다운로드</string>\n    <string name=\"task_added\">대기열에 추가됨</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">영상 %d개</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">오디오 %d개</item>\n    </plurals>\n    <string name=\"preset\">프리셋</string>\n    <string name=\"custom_format_selection_desc\">형식과 자막 등을 설정합니다</string>\n    <string name=\"prefer_placeholder\">%1$s 선호</string>\n    <string name=\"you_ll_find_your_downloads_here\">여기서 다운로드를 확인할 수 있습니다</string>\n    <string name=\"download_hint\">다운로드 버튼을 누르거나 영상 링크를 이 앱으로 공유하여 다운로드를 시작해 보세요</string>\n    <string name=\"status_downloaded\">다운로드 완료</string>\n    <string name=\"all\">전체</string>\n    <string name=\"select_multiple_link\">링크 %1$d개에서 선택</string>\n    <string name=\"download_queue\">다운로드 대기열</string>\n    <string name=\"show_navigation_drawer\">내비게이션 드로어 표시</string>\n    <string name=\"resume\">재개</string>\n    <string name=\"delete\">삭제</string>\n    <string name=\"media_info\">미디어 정보</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-lt/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"you_ll_find_your_downloads_here\">Atsisiuntimus rasite čia</string>\n    <string name=\"status_downloaded\">Atsisiųsta</string>\n    <string name=\"check_for_updates\">Tikrinti, ar yra naujinimų</string>\n    <string name=\"network\">Tinklas</string>\n    <string name=\"select_all\">Pasirinkti viską</string>\n    <string name=\"selected_item_count\">%1$d pasirinkta</string>\n    <string name=\"video_only\">Vaizdo įrašas (nėra garso)</string>\n    <string name=\"privacy\">Privatumas</string>\n    <string name=\"suggested\">Siūloma</string>\n    <string name=\"stable_channel\">Stabili</string>\n    <string name=\"unlimited\">Neribota</string>\n    <string name=\"second\">sekundė</string>\n    <string name=\"minute\">minutė</string>\n    <string name=\"beta_features\">Beta versija</string>\n    <string name=\"enable_experimental_feature\">Įjungti eksperimentinę funkciją?</string>\n    <string name=\"prefer_compatibility_desc\">Pageidauti MP4 (H.264) formatus, kad būtų galima bendrinti su kitomis programėlėmis</string>\n    <string name=\"every_month\">Kas mėnesį</string>\n    <string name=\"all_languages\">Visos kalbos</string>\n    <string name=\"playlist\">Grojaraštis</string>\n    <string name=\"proceed\">Tęsti</string>\n    <string name=\"download_hint\">Palieskite atsisiuntimo mygtuką arba bendrinkite vaizdo įrašo nuorodą į šią programą, kad pradėtumėte atsisiuntimą</string>\n    <string name=\"all\">Viskas</string>\n    <string name=\"pre_release_channel\">Peržiūra</string>\n    <string name=\"clear\">Valyti</string>\n    <string name=\"playlist_title\">Grojaraščio pavadinimas</string>\n    <string name=\"got_it\">Suprantau</string>\n    <string name=\"follow_system\">Sistemos</string>\n    <string name=\"credits_desc\">Kūrėjai ir laisvoji programinė įranga</string>\n    <string name=\"video_directory\">Vaizdo įrašų aplankas</string>\n    <string name=\"extract_audio\">Išsaugoti kaip garso įrašą</string>\n    <string name=\"create_thumbnail\">Išsaugoti miniatiūrą</string>\n    <string name=\"settings\">Nustatymai</string>\n    <string name=\"download_settings_desc\">Bendrieji, formatas, pasirinktinė komanda</string>\n    <string name=\"download\">Atsisiųsti</string>\n    <string name=\"url_empty\">Nuoroda negali būti tuščia.</string>\n    <string name=\"extract_audio_summary\">Atsisiųsti ir išsaugoti garso įrašą vietoj vaizdo įrašą</string>\n    <string name=\"create_thumbnail_summary\">Išsaugoti vaizdo įrašo miniatiūrą kaip failą</string>\n    <string name=\"yt_dlp_up_to_date\">Naudojama naujausia „yt-dlp“ versija</string>\n    <string name=\"yt_dlp_update_fail\">Nepavyko įdiegti naujausios „yt-dlp“ versijos. Įsitikinkite, kad esate prisijungę prie interneto.</string>\n    <string name=\"fetching_info\">Gaunama vaizdo įrašo informacija…</string>\n    <string name=\"permission_denied\">Leidimas atmestas</string>\n    <string name=\"download_success_msg\">Baigtas atsisiuntimas</string>\n    <string name=\"download_error_msg\">Nepavyko atsisiųsti failo.</string>\n    <string name=\"general_settings\">Bendrieji</string>\n    <string name=\"language\">Rodymo kalba</string>\n    <string name=\"language_settings\">Nustatyti rodymo kalbą</string>\n    <string name=\"dark_theme\">Tamsi tema</string>\n    <string name=\"on\">Įjungta</string>\n    <string name=\"off\">Išjungta</string>\n    <string name=\"cancel\">Atšaukti</string>\n    <string name=\"back\">Atgal</string>\n    <string name=\"version\">Versija</string>\n    <string name=\"downloads_history\">Atsisiuntimai</string>\n    <string name=\"paste_msg\">Įklijuoti URL</string>\n    <string name=\"ytdlp_version\">„Yt-dlp“ versija</string>\n    <string name=\"about\">Apie</string>\n    <string name=\"about_page\">Versija, atsiliepimai, automatinis atnaujinimas</string>\n    <string name=\"release\">Dabartinė laida</string>\n    <string name=\"credits\">Kūrėjai</string>\n    <string name=\"custom_command\">Pasirinktinė komanda</string>\n    <string name=\"display\">Rodinys</string>\n    <string name=\"display_settings\">Tamsi tema, dinaminės spalvos, kalbos</string>\n    <string name=\"edit\">Redaguoti</string>\n    <string name=\"options\">Parinktys</string>\n    <string name=\"additional_settings\">Papildomi nustatymai</string>\n    <string name=\"defaults\">Numatytasis</string>\n    <string name=\"translate_desc\">Padėkite išversti šią programėlę svetainėje „Hosted Weblate“</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d elementas</item>\n        <item quantity=\"few\">%d elementai</item>\n        <item quantity=\"other\">%d elementų</item>\n    </plurals>\n    <string name=\"downloading_indicator_text\">Vykdomas atsisiuntimas…</string>\n    <string name=\"issue_tracker_hint\">Susidūrėte su klaida? Prieš pranešdami apie naują problemą, paieškokite mūsų problemų sekiklyje. Daugelis dažniausiai pasitaikančių problemų jau buvo išspręstos ir aprašytos.</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d garso įrašas</item>\n        <item quantity=\"few\">%d garso įrašai</item>\n        <item quantity=\"other\">%d garso įrašų</item>\n    </plurals>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d vaizdo įrašas</item>\n        <item quantity=\"few\">%d vaizdo įrašai</item>\n        <item quantity=\"other\">%d vaizdo įrašų</item>\n    </plurals>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-lv/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">Saglabāt kā audio</string>\n    <string name=\"create_thumbnail\">saglabāt sīktēlu</string>\n    <string name=\"settings\">Iestatījumi</string>\n    <string name=\"video_directory\">Video mape</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ml/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">വീഡിയോ ഫോൾഡർ</string>\n    <string name=\"create_thumbnail\">ലഘുചിത്രം സംരക്ഷിക്കുക</string>\n    <string name=\"settings\">ക്രമീകരണങ്ങൾ</string>\n    <string name=\"download\">ഡൗൺലോഡ്</string>\n    <string name=\"create_thumbnail_summary\">വീഡിയോ ലഘുചിത്രം ഒരു ഫയലായി സംരക്ഷിക്കുക</string>\n    <string name=\"permission_denied\">അനുമതി നിഷേധിച്ചു</string>\n    <string name=\"dismiss\">റദ്ദാക്കുക</string>\n    <string name=\"ytdlp_version\">Yt-dlp പതിപ്പ്</string>\n    <string name=\"audio\">ഓഡിയോ</string>\n    <string name=\"delete_file\">ഫയൽ ഇല്ലാതാക്കുക</string>\n    <string name=\"about_page\">പതിപ്പ്, ഫീഡ്ബാക്ക്, യാന്ത്രിക അപ്ഡേറ്റ്</string>\n    <string name=\"back\">തിരികെ</string>\n    <string name=\"download_settings_desc\">പൊതുവായ, ഫോർമാറ്റ്, ഇഷ്‌ടാനുസൃത കമാൻഡ്</string>\n    <string name=\"extract_audio\">ഓഡിയോ ആയി സംരക്ഷിക്കുക</string>\n    <string name=\"extract_audio_summary\">വീഡിയോയ്ക്ക് പകരം ഓഡിയോ ഡൗൺലോഡ് ചെയ്ത് സംരക്ഷിക്കുക</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp-യുടെ ഏറ്റവും പുതിയ പതിപ്പ് ഉപയോഗിക്കുന്നു</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"fetch_info_error_msg\">വീഡിയോ വിവരം ലഭ്യമാക്കാനായില്ല</string>\n    <string name=\"yt_dlp_update_fail\">ഏറ്റവും പുതിയ yt-dlp പതിപ്പ് ഇൻസ്റ്റാൾ ചെയ്യാൻ കഴിഞ്ഞില്ല. നിങ്ങൾ ഇന്റർനെറ്റുമായി ബന്ധിപ്പിച്ചിട്ടുണ്ടെന്ന് ദയവായി ഉറപ്പാക്കുക.</string>\n    <string name=\"download_error_msg\">ഫയൽ ഡൗൺലോഡ് ചെയ്യാനായില്ല</string>\n    <string name=\"fetching_info\">വീഡിയോ വിവരം ലഭ്യമാക്കുന്നു…</string>\n    <string name=\"delete_info_msg\">നിങ്ങളുടെ ഡൗൺലോഡ് ചരിത്രത്തിൽ നിന്ന് \\\"%1$s\\\" നീക്കം ചെയ്യണോ\\?</string>\n    <string name=\"download_success_msg\">ഡൗൺലോഡ് പൂർത്തിയായി</string>\n    <string name=\"general_settings\">പൊതുവായ</string>\n    <string name=\"language\">പ്രദർശന ഭാഷ</string>\n    <string name=\"task_running\">നിലവിലുള്ള ഒരു ഡൗൺലോഡ് ടാസ്‌ക് ഇതിനകം പ്രവർത്തിക്കുന്നു</string>\n    <string name=\"paste_msg\">URL ഒട്ടിക്കുക</string>\n    <string name=\"language_settings\">പ്രദർശന ഭാഷ സജ്ജമാക്കുക</string>\n    <string name=\"paste_fail_msg\">ക്ലിപ്പ്ബോർഡിലെ URL-മായി പൊരുത്തപ്പെടാൻ കഴിഞ്ഞില്ല</string>\n    <string name=\"version\">പതിപ്പ്</string>\n    <string name=\"ytdlp_update\">ഏറ്റവും പുതിയ yt-dlp പതിപ്പ് ഇൻസ്റ്റാൾ ചെയ്യാൻ ക്ലിക്ക് ചെയ്യുക</string>\n    <string name=\"delete_info\">നീക്കം ചെയ്യണോ\\?</string>\n    <string name=\"confirm\">സ്ഥിരീകരിക്കുക</string>\n    <string name=\"link_copied\">ലിങ്ക് ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തി</string>\n    <string name=\"downloads_history\">ഡൗൺലോഡുകൾ</string>\n    <string name=\"open_url\">ലിങ്ക് തുറക്കുക</string>\n    <string name=\"about\">ഇതേക്കുറിച്ച്</string>\n    <string name=\"remove\">നീക്കം ചെയ്യുക</string>\n    <string name=\"release_desc\">ചേഞ്ച് ലോഗുകളും പുതിയ പതിപ്പുകളും തിരയുക</string>\n    <string name=\"readme_desc\">ഗിറ്റ്ഹബ് റെപ്പോസിറ്ററിയും README-യും പരിശോധിക്കുക</string>\n    <string name=\"release\">ഏറ്റവും പുതിയ റിലീസ്</string>\n    <string name=\"url_empty\">ലിങ്ക് ശൂന്യമാക്കാൻ കഴിയില്ല</string>\n    <string name=\"video\">വീഡിയോ</string>\n    <string name=\"checked\">പരിശോധിച്ചു</string>\n    <string name=\"custom_command\">കസ്റ്റം കമാൻഡ്</string>\n    <string name=\"advanced_settings\">അഡ്വാൻസ്ഡ്</string>\n    <string name=\"print_details\">വിശദമായ ഔട്ട്പുട്ട്</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp ഉപയോഗ റഫറൻസുകൾ</string>\n    <string name=\"convert_audio_format\">ഓഡിയോ ഫോർമാറ്റ് പരിവർത്തനം ചെയ്യുക</string>\n    <string name=\"convert_to\">%1$s ലേക്ക് പരിവർത്തനം ചെയ്യുക</string>\n    <string name=\"video_quality\">വീഡിയോ ഗുണനിലവാരം</string>\n    <string name=\"video_format\">വീഡിയോ ഫോർമാറ്റ്</string>\n    <string name=\"convert_audio\">പരിവർത്തനം ചെയ്യുക</string>\n    <string name=\"close\">അടയ്ക്കുക</string>\n    <string name=\"close_never_show_again\">വീണ്ടും കാണിക്കരുത്</string>\n    <string name=\"defaults\">സഹജമായ</string>\n    <string name=\"channel_description\">ഡൌൺലോഡ് ചെയ്ത ഫയലുകളും പുരോഗതിയും അറിയിക്കുക</string>\n    <string name=\"video_url\">വീഡിയോ ലിങ്ക്</string>\n    <string name=\"concurrent_download\">മൾട്ടി-ത്രെഡ് ഡൗൺലോഡ്</string>\n    <string name=\"options\">ഓപ്ഷനുകൾ</string>\n    <string name=\"additional_settings\">അധിക ക്രമീകരണങ്ങൾ</string>\n    <string name=\"share_fail_msg\">പങ്കിട്ട ഉള്ളടക്കത്തിൽ നിന്നുള്ള URL-മായി പൊരുത്തപ്പെടുന്നില്ല</string>\n    <string name=\"download_notification_desc\">ഡൗൺലോഡ് ചെയ്ത ഫയലുകളും പുരോഗതിയും അറിയിക്കുക</string>\n    <string name=\"download_range_selection\">പ്ലേലിസ്റ്റ് തിരഞ്ഞെടുക്കൽ</string>\n    <string name=\"cancel\">റദ്ദാക്കുക</string>\n    <string name=\"credits\">ക്രെഡിറ്റുകൾ</string>\n    <string name=\"start_execute\">കമാൻഡ് നടപ്പിലാക്കാൻ തുടങ്ങുക</string>\n    <string name=\"error_copied\">പിശക് റിപ്പോർട്ട് ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തി</string>\n    <string name=\"credits_desc\">ക്രെഡിറ്റുകളും ലിബ്രെ സോഫ്റ്റ് വെയറുകളും</string>\n    <string name=\"custom_command_desc\">ഇഷ്‌ടാനുസൃത ടെംപ്ലേറ്റ് ഉപയോഗിച്ച് yt-dlp കമാൻഡ് പ്രവർത്തിപ്പിക്കുക</string>\n    <string name=\"edit\">എഡിറ്റ് ചെയ്യുക</string>\n    <string name=\"custom_command_template\">കമാൻഡ് ടെംപ്ലേറ്റ്</string>\n    <string name=\"off\">ഓഫ് ചെയ്യുക</string>\n    <string name=\"on\">ഓൺ</string>\n    <string name=\"print_details_desc\">ഡൌൺലോഡ് ചെയ്യുമ്പോൾ വിശദമായ സന്ദേശങ്ങൾ പ്രിന്റ് ചെയ്യുക</string>\n    <string name=\"display\">പ്രദർശിപ്പിക്കുക</string>\n    <string name=\"display_settings\">ഇരുണ്ട തീം, ഡൈനാമിക് നിറം, ഭാഷകൾ</string>\n    <string name=\"dark_theme\">ഇരുണ്ട തീം</string>\n    <string name=\"follow_system\">സിസ്റ്റം</string>\n    <string name=\"settings_before_download_desc\">ഡൌൺലോഡ് ചെയ്യുന്നതിന് മുമ്പ് മുൻഗണനകൾ ക്രമീകരിക്കുക</string>\n    <string name=\"settings_before_download\">ഡൗൺലോഡ് ചെയ്യുന്നതിന് മുമ്പ് ക്രമീകരിയ്ക്കുക</string>\n    <string name=\"thumbnail\">ലഘുചിത്രം</string>\n    <string name=\"settings_before_download_text\">ഈ ഡൗൺലോഡ് ക്രമീകരിക്കുക</string>\n    <string name=\"not_convert\">പരിവർത്തനം ചെയ്യപ്പെടാത്തത്</string>\n    <string name=\"format\">ഫോർമാറ്റ്</string>\n    <string name=\"paste\">പേസ്റ്റ് ചെയ്യുക</string>\n    <string name=\"edit_template_desc\">ഔട്ട്പുട്ട് പാത്തും URL-ഉം ആപ്ലിക്കേഷൻ ചേർക്കും.</string>\n    <string name=\"convert_audio_format_desc\">ഓഡിയോ ഫയലുകൾ വീണ്ടും എൻകോഡ് ചെയ്യുന്നത് ഓഡിയോ നിലവാരം നഷ്‌ടപ്പെടുത്താനും ഫയലിന്റെ വലുപ്പം വർദ്ധിപ്പിക്കാനും ഇടയാക്കും.</string>\n    <string name=\"best_quality\">മികച്ച നിലവാരം</string>\n    <string name=\"download_desc\">അതിന്റെ ക്രമീകരണങ്ങൾ ക്രമീകരിച്ചതിന് ശേഷം \\\"ഡൗൺലോഡ്\\\" ക്ലിക്ക് ചെയ്യുക.</string>\n    <string name=\"not_specified\">വ്യക്തമാക്കിയിട്ടില്ല (സ്വതവേയുള്ളത്)</string>\n    <string name=\"start_download\">ഡൗൺലോഡ്</string>\n    <string name=\"check_download_settings_desc\">ഡൗൺലോഡ് ക്രമീകരണങ്ങൾ പരിശോധിച്ച് അത് ഉപയോഗിക്കുന്നതിന് മുമ്പ് yt-dlp-യുടെ ഏറ്റവും പുതിയ പതിപ്പ് നിങ്ങളുടെ പക്കലുണ്ടെന്ന് ഉറപ്പാക്കുക.</string>\n    <string name=\"download_playlist\">പ്ലേലിസ്റ്റ് ഡൌൺലോഡ് ചെയ്യുക</string>\n    <string name=\"video_quality_desc\">ഒന്നിലധികം ഉള്ളപ്പോൾ വീഡിയോ നിലവാരം പരിമിതപ്പെടുത്തുക</string>\n    <string name=\"video_format_preference\">തിരഞ്ഞെടുത്ത വീഡിയോ ഫോർമാറ്റ്</string>\n    <string name=\"preferred_format_desc\">ഒന്നിലധികം നൽകുമ്പോൾ തിരഞ്ഞെടുത്ത ഫോർമാറ്റ്</string>\n    <string name=\"user_guide\">ഉപയോക്തൃ ഗൈഡ്</string>\n    <string name=\"open_settings\">ക്രമീകരണങ്ങൾ തുറക്കുക</string>\n    <string name=\"paste_desc\">നിങ്ങളുടെ ക്ലിപ്പ്ബോർഡിൽ നിന്ന് വീഡിയോ ലിങ്ക് ലഭിക്കാൻ \\\"ഒട്ടിക്കുക\\\" ക്ലിക്ക് ചെയ്യുക.</string>\n    <string name=\"channel_name\">ഡൗൺലോഡ്</string>\n    <string name=\"download_history_desc\">വീഡിയോകളും ഓഡിയോ ഫയലുകളും ഉൾപ്പെടെ, ഇൻ-ആപ്പ് ഡൗൺലോഡുകൾ പരിശോധിക്കുകയും നിയന്ത്രിക്കുകയും ചെയ്യുക.</string>\n    <string name=\"download_playlist_desc\">ഒരു പ്ലേലിസ്റ്റിൽ നിന്ന് ഒന്നിലധികം വീഡിയോകൾ ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"execute_command_notification\">ഇഷ്ടാനുസൃത കമാൻഡുകൾ പ്രവർത്തിപ്പിക്കുന്നു…</string>\n    <string name=\"download_finish_notification\">ഡൗൺലോഡ് പൂർത്തിയായി. തുറക്കാൻ ക്ലിക്ക് ചെയ്യുക.</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD വീഡിയോകളുടെ കൂടുതൽ ഭാഗങ്ങൾ സമാന്തരമായി ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"concurrent_download_num\">DASH/HLS നേറ്റീവ് വീഡിയോ ഒരേസമയം ഡൗൺലോഡ് ചെയ്യാൻ %d ത്രെഡ്(കൾ) ഉപയോഗിക്കും.</string>\n    <string name=\"show_more_actions\">കൂടുതൽ പ്രവർത്തികൾ കാണിക്കുക</string>\n    <string name=\"download_notification\">ഡൗൺലോഡ് അറിയിപ്പ്</string>\n    <string name=\"share_success_msg\">പങ്കിട്ട ഉള്ളടക്കത്തിൽ നിന്നുള്ള വീഡിയോ ലിങ്ക് വായിക്കുന്നു…</string>\n    <string name=\"fetching_playlist_info\">പ്ലേലിസ്റ്റ് വിവരം ലഭ്യമാക്കുന്നു…</string>\n    <string name=\"battery_settings_desc\">പശ്ചാത്തലത്തിൽ ഡൗൺലോഡ് ചെയ്യുന്നതിനായി ഈ ആപ്പിന്റെ ബാറ്ററി ഉപയോഗം സിസ്റ്റം ക്രമീകരണങ്ങളിൽ \\\"അനിയന്ത്രിതമായത്\\\" എന്ന് സജ്ജീകരിക്കുക.</string>\n    <string name=\"download_range_desc\">പ്ലേലിസ്റ്റിൽ നിന്ന് ഡൗൺലോഡ് ചെയ്യുന്നതിനുള്ള വീഡിയോകളുടെ ശ്രേണി വ്യക്തമാക്കുക \\\"%3$s\\\" (%1$d മുതൽ %2$d) വരെ).</string>\n    <string name=\"from\">ആരംഭിക്കുക</string>\n    <string name=\"to\">അവസാനിക്കുന്നു</string>\n    <string name=\"invalid_index_range\">അസാധുവായ സൂചിക ശ്രേണി</string>\n    <string name=\"audio_directory\">ശബ്ദ ഫോൾഡർ</string>\n    <string name=\"download_directory_desc\">വീഡിയോകളും ഓഡിയോ ഫയലുകളും എവിടെ സൂക്ഷിക്കണമെന്ന് തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"subdirectory\">ഉപഡയറക്‌ടറിയിൽ സംരക്ഷിക്കുക</string>\n    <string name=\"permission_issue\">സംഭരണ അനുമതി പ്രശ്നം</string>\n    <string name=\"permission_issue_desc\">ഡൗൺലോഡ്/, ഡോക്യുമെന്റുകൾ/ എന്നിവയ്ക്ക് പുറത്തുള്ള ഡയറക്ടറികൾ പിന്തുണയ്ക്കുന്നില്ല</string>\n    <string name=\"battery_configuration\">ബാറ്ററി കോൺഫിഗറേഷൻ</string>\n    <string name=\"service_title\">സീൽ ഡൗൺലോഡ് ചെയ്യുന്നു…</string>\n    <string name=\"unknown_error\">അപരിചിതമായ പിശക്</string>\n    <string name=\"embed_subtitles\">സബ്ടൈറ്റിലുകൾ ഉൾച്ചേർക്കുക</string>\n    <string name=\"template_label\">ലേബൽ</string>\n    <string name=\"template_selection\">ടെംപ്ലേറ്റ് തിരഞ്ഞെടുക്കൽ</string>\n    <string name=\"custom_command_template_desc\">കമാൻഡ് ടെംപ്ലേറ്റുകൾ എഡിറ്റ് ചെയ്യുകയും നിയന്ത്രിക്കുകയും ചെയ്യുക</string>\n    <string name=\"task_canceled\">ഡൗൺലോഡ് ടാസ്‌ക് റദ്ദാക്കി</string>\n    <string name=\"github_issue\">ഗിറ്റ്ഹബ് പ്രശ്നം</string>\n    <string name=\"info_copied\">ലിങ്ക് ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തി</string>\n    <string name=\"status_downloading\">ഡൌൺലോഡ് ചെയ്യുന്നു</string>\n    <string name=\"status_canceled\">റദ്ദാക്കി</string>\n    <string name=\"open_file\">ഫയൽ തുറക്കുക</string>\n    <string name=\"status_error\">പിശക്</string>\n    <string name=\"copy_error_report\">റിപ്പോർട്ട് പകർത്തുക</string>\n    <string name=\"import_from_clipboard\">ക്ലിപ്ബോർഡിൽ നിന്ന് ഇംപോർട്ട് ചെയ്യുക</string>\n    <string name=\"download_task_count\">%1$d ജോലികൾ ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"recently_added\">അടുത്തിടെ ചേർത്തത്</string>\n    <string name=\"delete_multiple_items_msg\">നിങ്ങളുടെ ഡൗൺലോഡ് ചരിത്രത്തിൽ നിന്ന് %1$d ഇനം(കൾ) നീക്കം ചെയ്യണോ\\?</string>\n    <string name=\"sponsorblock_categories\">സ്പോൺസർബ്ലോക്ക് വിഭാഗങ്ങൾ</string>\n    <string name=\"check_for_updates\">അപ് ഡേറ്റുകൾ ഉണ്ടോ എന്ന് പരിശോധിക്കുക</string>\n    <string name=\"app_up_to_date\">നിലവിലെ പതിപ്പ് അപ് ടു ഡേറ്റ് ആണ്</string>\n    <string name=\"app_update_failed\">ഏറ്റവും പുതിയ പതിപ്പിലേക്ക് അപ്ഡേറ്റ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു</string>\n    <string name=\"update\">അപ്ഡേറ്റ് ചെയ്യുക</string>\n    <string name=\"clear_temp_files\">താൽക്കാലിക ഫയലുകൾ മായ്ച്ചുകളയുക</string>\n    <string name=\"private_mode\">സ്വകാര്യ</string>\n    <string name=\"dynamic_color\">ഡൈനാമിക് നിറം</string>\n    <string name=\"download_with_cellular\">സെല്ലുലാർ ഉപയോഗിച്ച് ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"file_unavailable\">ഈ ഫയൽ ഇനി ലഭ്യമല്ല</string>\n    <string name=\"network\">നെറ്റ് വർക്ക്</string>\n    <string name=\"rate_limit\">നിരക്ക് പരിധി</string>\n    <string name=\"rate_limit_desc\">പരമാവധി ഡൗൺലോഡ് വേഗത പരിമിതപ്പെടുത്തുക</string>\n    <string name=\"max_rate\">പരമാവധി നിരക്ക്</string>\n    <string name=\"lowest_quality\">ഏറ്റവും കുറഞ്ഞ നിലവാരം</string>\n    <string name=\"dynamic_color_desc\">വാൾപേപ്പറുകളിൽ നിന്ന് ആപ്പ് തീമിലേക്ക് നിറങ്ങൾ പ്രയോഗിക്കുക</string>\n    <string name=\"battery_configuration_desc\">പശ്ചാത്തലത്തിൽ ഡൗൺലോഡ് ചെയ്യാൻ ഈ ആപ്പിനായി ബാറ്ററി ഒപ്റ്റിമൈസേഷൻ അവഗണിക്കുക</string>\n    <string name=\"remove_template_desc\">കമാൻഡ് ടെംപ്ലേറ്റുകളിൽ നിന്ന് \\\"%1$s\\\" നീക്കം ചെയ്യണോ\\?</string>\n    <string name=\"video_file_size\">വീഡിയോ ഫയലിന്റെ വലിപ്പം</string>\n    <string name=\"translate\">വിവർത്തനം ചെയ്യുക</string>\n    <string name=\"new_template\">പുതിയ ടെംപ്ലേറ്റ്</string>\n    <string name=\"remove_template\">നീക്കം ചെയ്യണോ\\?</string>\n    <string name=\"status_fetching_video_info\">വിവരങ്ങൾ ശേഖരിക്കുന്നു</string>\n    <string name=\"translate_desc\">ഹോസ്റ്റുചെയ്ത വെബ്ലേറ്റിൽ ഈ ആപ്പ് പരിഭാഷപ്പെടുത്താൻ സഹായിക്കുക</string>\n    <string name=\"github_issue_desc\">ബഗ് റിപ്പോർട്ടിനോ ഫീച്ചർ അഭ്യർത്ഥനയ്‌ക്കോ ഒരു പ്രശ്നം സമർപ്പിക്കുക</string>\n    <string name=\"playlist_indicator_text\">പ്ലേലിസ്റ്റ് ഡൗൺലോഡ് ചെയ്യുന്നു (%1$d/%2$d)…</string>\n    <string name=\"download_directory\">ഡയറക്ടറി ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"subdirectory_desc\">ഫയലുകൾ ബന്ധപ്പെട്ട ഫീൽഡുകളായി പേരുള്ള ഫോൾഡറുകളിൽ സംരക്ഷിക്കുക</string>\n    <string name=\"prefix\">പാത്ത് ടെംപ്ലേറ്റ്</string>\n    <string name=\"downloading_indicator_text\">ഡൗൺലോഡ് പുരോഗമിക്കുന്നു…</string>\n    <string name=\"embed_subtitles_desc\">ലഭ്യമെങ്കിൽ വീഡിയോകളിൽ നൽകിയിരിക്കുന്ന സബ്‌ടൈറ്റിലുകൾ ഉൾച്ചേർക്കുക</string>\n    <string name=\"status_enqueued\">വരിവരിയായി</string>\n    <string name=\"status_completed\">തീർന്നു</string>\n    <string name=\"restart\">പുനരാരംഭിക്കുക</string>\n    <string name=\"copy_link\">ലിങ്ക് പകർത്തുക</string>\n    <string name=\"export_to_clipboard\">ക്ലിപ്പ്ബോർഡിലേക്ക് കയറ്റുമതി ചെയ്യുക</string>\n    <string name=\"template_imported\">കയറ്റുമതി ചെയ്‌ത %1$d ടെംപ്ലേറ്റ്(കൾ)</string>\n    <string name=\"video_resolution\">വീഡിയോ റെസല്യൂഷൻ</string>\n    <string name=\"template_exported\">കയറ്റുമതി ചെയ്‌ത %1$d ടെംപ്ലേറ്റ്(കൾ)</string>\n    <string name=\"multiselect_item_count\">%1$d വീഡിയോ(കൾ), %2$d ഓഡിയോ ഫയൽ(കൾ)</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API ഉപയോഗിച്ച് വീഡിയോകളിൽ നിന്ന് സെഗ്‌മെന്റുകൾ നീക്കം ചെയ്യുക</string>\n    <string name=\"aria2_desc\">ബാഹ്യ ഡൗൺലോഡറായി aria2c ഉപയോഗിക്കുക</string>\n    <string name=\"multiselect_mode\">മൾട്ടിസെലക്ട് മോഡ്</string>\n    <string name=\"clear_temp_files_desc\">ഡൌൺലോഡ് ഡയറക്ടറിയിൽ നിന്ന് എല്ലാ താൽക്കാലിക ഫയലുകളും ഇല്ലാതാക്കുക</string>\n    <string name=\"private_mode_desc\">ഡൗൺലോഡ് ചരിത്രം പ്രവർത്തനരഹിതമാക്കുക</string>\n    <string name=\"download_with_cellular_desc\">മീറ്റർ നെറ്റ്‌വർക്കുകളിലേക്ക് കണക്‌റ്റ് ചെയ്യുമ്പോൾ മീഡിയ ഡൗൺലോഡ് ചെയ്യാൻ അനുവദിക്കുക</string>\n    <string name=\"sponsorblock_categories_desc\">വീഡിയോ ഫയലിൽ നിന്ന് നീക്കം ചെയ്യേണ്ട SponsorBlock വിഭാഗങ്ങൾ വ്യക്തമാക്കുക</string>\n    <string name=\"check_for_updates_desc\">GitHub-ലെ ഏറ്റവും പുതിയ പതിപ്പിനായി തിരയുക</string>\n    <string name=\"cookies_desc\">ഡൗൺലോഡുകൾക്കായി Netscape ഫോർമാറ്റ് ചെയ്ത കുക്കികൾ ഉപയോഗിക്കുക</string>\n    <string name=\"clear_temp_files_count\">ഇല്ലാതാക്കി %1$d താൽക്കാലിക ഫയൽ(കൾ)</string>\n    <string name=\"clear_temp_files_info\">റദ്ദാക്കിയ ഡൗൺലോഡുകൾ പുനരാരംഭിക്കാൻ താൽക്കാലിക ഫയലുകൾ ഉപയോഗിക്കാം. ഈ ഫയലുകളെല്ലാം ഇല്ലാതാക്കുമെന്ന് തീർച്ചയാണോ?\n\\n\n\\nനിങ്ങൾക്ക് ഈ ഫയലുകൾ %1$s-ൽ ഉപയോഗിക്കാം</string>\n    <string name=\"download_disabled_with_cellular\">സെല്ലുലാർ നെറ്റ്‌വർക്ക് ഉപയോഗിച്ച് ഡൗൺലോഡ് ചെയ്യുന്നത് നിങ്ങളുടെ ക്രമീകരണം അനുസരിച്ച് പ്രവർത്തനരഹിതമാക്കി</string>\n    <string name=\"high_contrast\">ഹൈ കോൺട്രാസ്റ്റ് ഡാർക്ക് തീം</string>\n    <string name=\"invalid_input\">അസാധുവായ ഇൻപുട്ട്</string>\n    <string name=\"private_directory\">സ്വകാര്യ ഡയറക്ടറി</string>\n    <string name=\"cookies\">കുക്കികൾ</string>\n    <string name=\"select_all\">എല്ലാം തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"general_settings_desc\">Yt-dlp പതിപ്പ്, അറിയിപ്പ്, പ്ലേലിസ്റ്റ്</string>\n    <string name=\"network_settings_desc\">നിരക്ക് പരിധി, ഡൗൺലോഡർ, കുക്കികൾ</string>\n    <string name=\"crop_artwork\">ക്രോപ്പ് ആർട്ട് വർക്ക്</string>\n    <string name=\"privacy\">സ്വകാര്യത</string>\n    <string name=\"disable_preview\">പ്രിവ്യൂ പ്രവർത്തനരഹിതമാക്കുക</string>\n    <string name=\"disable_preview_desc\">ഡൗൺലോഡ് സമയത്ത് ലഘുചിത്രങ്ങൾ പ്രദർശിപ്പിക്കുന്നത് ഒഴിവാക്കുക</string>\n    <string name=\"use_custom_command\">ഇഷ്ടാനുസൃത കമാൻഡ് ഉപയോഗിക്കുക</string>\n    <string name=\"private_directory_desc\">ഒരു മറഞ്ഞിരിക്കുന്ന ഡയറക്ടറിയിൽ ഡൗൺലോഡുകൾ സംഭരിക്കുക</string>\n    <string name=\"download_selection_desc\">പ്ലേലിസ്റ്റിൽ നിന്ന് ഡൗൺലോഡ് ചെയ്യാൻ വീഡിയോകൾ തിരഞ്ഞെടുക്കുക \\\"%1$s\\\"</string>\n    <string name=\"crop_artwork_desc\">ഉൾച്ചേർത്ത ചിത്രം ചതുരത്തിലേക്ക് ക്രോപ്പ് ചെയ്യുക</string>\n    <string name=\"unavailable\">ലഭ്യമല്ല</string>\n    <string name=\"format_settings_desc\">ഫയൽ ഫോർമാറ്റ്, വീഡിയോ നിലവാരം, സബ്ടൈറ്റിലുകൾ</string>\n    <string name=\"selected_item_count\">%1$d തിരഞ്ഞെടുത്തു</string>\n    <string name=\"video_only\">വീഡിയോ (ഓഡിയോ ഇല്ല)</string>\n    <string name=\"suggested\">ശുപാർശ ചെയ്ത</string>\n    <string name=\"format_selection\">ഫോർമാറ്റ് തിരഞ്ഞെടുക്കൽ</string>\n    <string name=\"format_selection_desc\">ഡൗൺലോഡ് ആരംഭിക്കുന്നതിന് മുമ്പ് ഡൗൺലോഡ് ചെയ്യേണ്ട ഫോർമാറ്റ് തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"subtitle_sponsorblock\">സ്പോൺസർബ്ലോക്ക് സെഗ്‌മെന്റുകൾ നീക്കം ചെയ്യുമ്പോൾ സബ്‌ടൈറ്റിലുകൾ തെറ്റായി വന്നേക്കാം.</string>\n    <string name=\"use_cookies\">കുക്കികൾ ഉപയോഗിക്കുക</string>\n    <string name=\"remove_cookie_profile_desc\">\\\"%1$s\\\" എന്നതിനായുള്ള ഈ എൻട്രി നീക്കം ചെയ്യണോ? ഈ സൈറ്റിനായി സംഭരിച്ചിരിക്കുന്ന കുക്കികൾ മായ്‌ക്കില്ല എന്നത് ശ്രദ്ധിക്കുക.</string>\n    <string name=\"how_does_it_work\">അതെങ്ങനെയാണ് പ്രവര്ത്തിക്കുന്നത്\\?</string>\n    <string name=\"abs_hint\">മിക്ക വീഡിയോ സ്ട്രീമിംഗ് പ്ലാറ്റ്‌ഫോമുകളും ഓഡിയോയും വീഡിയോയും വെവ്വേറെ ഡെലിവർ ചെയ്യുന്നു, നിങ്ങൾക്ക് ഒരു ഓഡിയോ മാത്രമുള്ള ഫോർമാറ്റ് തിരഞ്ഞെടുത്ത് ഒരു വീഡിയോ മാത്രമുള്ള ഫോർമാറ്റിൽ ഒരു വീഡിയോയിലേക്ക് ലയിപ്പിക്കാം.</string>\n    <string name=\"custom_command_enabled_hint\">കസ്റ്റം കമാൻഡ് ഉപയോഗിക്കുമ്പോൾ ചില ഓപ്ഷനുകൾ ലഭ്യമല്ല</string>\n    <string name=\"cookies_usage_msg\">ചില സൈറ്റുകളിൽ നിന്ന് ഡൗൺലോഡ് ചെയ്യുന്നതിന് അക്കൗണ്ട് പ്രാമാണീകരണ വിവരങ്ങൾ ആവശ്യമാണ്. \\\"പുതിയ കുക്കികൾ സൃഷ്ടിക്കുക\\\" എന്നതിൽ ക്ലിക്ക് ചെയ്യുക, വെബ്‌സൈറ്റിന്റെ URL നൽകുക, തുടർന്ന് ബ്രൗസർ പേജിൽ നിങ്ങളുടെ അക്കൗണ്ട് ഉപയോഗിച്ച് ലോഗിൻ ചെയ്യുക, ആപ്പ് നിങ്ങൾക്കായി അത് ജനറേറ്റ് ചെയ്യും.</string>\n    <string name=\"telegram_channel\">ടെലിഗ്രാം ചാനൽ</string>\n    <string name=\"matrix_space\">മാട്രിക്സ് സ്പേസ്</string>\n    <string name=\"download_subtitles\">സബ്ടൈറ്റിലുകൾ ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"video_title_sample_text\">വീഡിയോ ശീർഷകം മാതൃകാ വാചകം</string>\n    <string name=\"video_creator_sample_text\">വീഡിയോ ക്രിയേറ്റർ മാതൃകാ വാചകം</string>\n    <string name=\"edit_shortcuts\">കുറുക്കുവഴികൾ എഡിറ്റ് ചെയ്യുക</string>\n    <string name=\"subtitle_desc\">ഭാഷകൾ, ഉൾച്ചേർത്ത ഉപശീർഷകങ്ങൾ, സ്വയമേവയുള്ള അടിക്കുറിപ്പുകൾ</string>\n    <string name=\"copy_log\">ലോഗ് പകർത്തുക</string>\n    <string name=\"clear\">മായ്‌ക്കുക</string>\n    <string name=\"running_tasks\">പ്രവർത്തിക്കുന്ന ജോലികൾ</string>\n    <string name=\"show_logs\">വിവരണപതിക കാണിക്കുക</string>\n    <string name=\"logs\">വിവരണപതിക</string>\n    <string name=\"generate_new_cookies\">പുതിയ കുക്കികൾ സൃഷ്ടിക്കുക</string>\n    <string name=\"sdcard_directory\">എസ്.ഡി കാർഡ് ഫോൾഡർ</string>\n    <string name=\"auto_subtitle\">സ്വയമേവയുള്ള അടിക്കുറിപ്പുകൾ</string>\n    <string name=\"auto_subtitle_desc\">സ്വയമേവ സൃഷ്‌ടിച്ച അടിക്കുറിപ്പുകൾ ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"title_activity_share\">പെട്ടെന്ന് ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"subtitle\">ഉപശീർഷകം</string>\n    <string name=\"subtitle_language\">ഉപശീർഷക ഭാഷകൾ</string>\n    <string name=\"add\">ചേർക്കുക</string>\n    <string name=\"shortcuts\">കുറുക്കുവഴികൾ</string>\n    <string name=\"edit_shortcuts_desc\">കമാൻഡ് ടെംപ്ലേറ്റുകൾ രചിക്കാൻ ഉപയോഗിക്കാവുന്ന ഇഷ്‌ടാനുസൃത കുറുക്കുവഴികൾ എഡിറ്റ് ചെയ്യുക.</string>\n    <string name=\"embed_subtitles_mkv_msg\">സോഫ്റ്റ് സബ്‌ടൈറ്റിലുകൾ ഉൾച്ചേർക്കാൻ, വീഡിയോകൾ mkv കണ്ടെയ്‌നറിലേക്ക് റീമക്‌സ് ചെയ്യും. സോഫ്റ്റ് സബ്‌ടൈറ്റിലുകളുള്ള വീഡിയോകൾ കാണാൻ നിങ്ങൾക്ക് VLC മീഡിയ പ്ലെയറോ മറ്റ് അനുയോജ്യമായ ആപ്പുകളോ ഉപയോഗിക്കാം.</string>\n    <string name=\"ytdlp_update_action\">yt-dlp അപ്ഡേറ്റ് ചെയ്യുക</string>\n    <string name=\"second\">സെക്കന്റ്</string>\n    <string name=\"title\">തലക്കെട്ട്</string>\n    <string name=\"import_from_preferences\">ലോഡ് ചെയ്യുക</string>\n    <string name=\"rename\">പേരുമാറ്റുക</string>\n    <string name=\"minute\">മിനിറ്റ്</string>\n    <string name=\"no_downloaded_media\">ഡൗൺലോഡ് ചെയ്ത മീഡിയ ഇല്ല</string>\n    <string name=\"beta_features\">ബീറ്റ</string>\n    <string name=\"remove_multiple_templates_msg\">കമാൻഡ് ടെംപ്ലേറ്റുകളിൽ നിന്ന് %1$s നീക്കം ചെയ്യണോ?</string>\n    <string name=\"edit_file\">ഫയൽ എഡിറ്റ് ചെയ്യുക</string>\n    <string name=\"save\">രക്ഷിക്കും</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d ഇനം</item>\n        <item quantity=\"other\">%d ഇനങ്ങൾ</item>\n    </plurals>\n    <string name=\"embed_metadata\">മെറ്റാഡാറ്റ ഉൾച്ചേർക്കുക</string>\n    <string name=\"audio_format_preference\">മുൻഗണന നൽകേണ്ട ഓഡിയോ ഫോർമാറ്റ്</string>\n    <string name=\"proxy\">പ്രോക്സി</string>\n    <string name=\"custom_command_directory\">ഇഷ്‌ടാനുസൃത കമാൻഡ് ഡയറക്‌ടറി</string>\n    <string name=\"disabled\">പ്രവർത്തനരഹിതമാക്കി</string>\n    <string name=\"allow_once\">ഒരിക്കൽ അനുവദിക്കുക</string>\n    <string name=\"export_to\">ഇതിലേക്ക് കയറ്റുമതി ചെയ്യുക</string>\n    <string name=\"import_download_history\">ഡൗൺലോഡ് ചരിത്രം ഇമ്പോർട്ടുചെയ്യണോ?</string>\n    <string name=\"export_download_history\">ഡൗൺലോഡ് ചരിത്രം കയറ്റുമതി ചെയ്യണോ?</string>\n    <string name=\"import_download_history_msg\">ഡൗൺലോഡ് ചെയ്ത ഫയലുകൾ ഇറക്കുമതി ചെയ്യില്ല. നിങ്ങൾ അവ സ്വമേധയാ തിരികെ ഡൗൺലോഡ് ചെയ്യേണ്ടതുണ്ട്</string>\n    <string name=\"export_download_history_msg\">ഡൗൺലോഡ് ചരിത്രത്തിൽ നിന്ന് %1$s കയറ്റുമതി ചെയ്യുന്നു. ഡൗൺലോഡ് ചെയ്‌ത ഫയലുകളും മുൻഗണനകളും ബാക്കപ്പ് ചെയ്യില്ല.</string>\n    <string name=\"cookies_in_database\">ആകെ %2$d വെബ്‌സൈറ്റുകളിൽ നിന്ന് %1$d കുക്കികൾ</string>\n    <string name=\"every_day\">എല്ലാ ദിവസവും</string>\n    <string name=\"every_week\">എല്ലാ ആഴ്ചയും</string>\n    <string name=\"auto_translated_subtitles\">യാന്ത്രികമായി വിവർത്തനം ചെയ്‌ത സബ്‌ടൈറ്റിലുകൾ</string>\n    <string name=\"auto_translated_subtitles_msg\">യാന്ത്രികമായി വിവർത്തനം ചെയ്‌ത സബ്‌ടൈറ്റിലുകൾ എല്ലാ ഭാഷകൾക്കും ഡൗൺലോഡുകളിൽ ലഭ്യമാകും. ഈ സബ്‌ടൈറ്റിലുകൾ കൃത്യമല്ലാത്തതും മനസ്സിലാക്കാൻ ബുദ്ധിമുട്ടുള്ളതുമാകാം.</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp വീഡിയോകൾ ഡൗൺലോഡ് ചെയ്യുന്നതിനുള്ള ശക്തമായ ഒരു കമാൻഡ്-ലൈൻ ഉപകരണമാണ്. ഒരു അവബോധജന്യമായ GUI, പൊതുവായ കമാൻഡുകൾക്കുള്ള പ്രീസെറ്റുകൾ, മറ്റ് അധിക സവിശേഷതകൾ എന്നിവ നൽകിക്കൊണ്ട് yt-dlp ഉപയോഗിക്കുന്നത് സീൽ എളുപ്പമാക്കുന്നു.\n\\n\n\\nyt-dlp-യുടെ വിപുലമായ ഉപയോഗത്തിനായി, ഒരു ടെർമിനലിൽ പോലെ നേരിട്ട് ഇഷ്‌ടാനുസൃത കമാൻഡ് ടെംപ്ലേറ്റുകൾ സൃഷ്‌ടിക്കാനും സംരക്ഷിക്കാനും നടപ്പിലാക്കാനും സീൽ നിങ്ങളെ അനുവദിക്കുന്നു.\n\\n\n\\nഇഷ്‌ടാനുസൃത കമാൻഡുകൾ ഉപയോഗിക്കുമ്പോൾ, മിക്ക GUI ഓപ്ഷനുകളും സവിശേഷതകളും പ്രവർത്തനരഹിതമാകും.</string>\n    <string name=\"update_channel_desc\">പുതിയ ഫീച്ചറുകളും മാറ്റങ്ങളും പ്രിവ്യൂ ചെയ്യുന്നതിന് പ്രീ-റിലീസ് ബിൽഡുകൾ ഇൻസ്റ്റാൾ ചെയ്യുക.\n\\n\n\\nഈ പതിപ്പുകളിൽ ചില അസ്ഥിരതകൾ ഉണ്ടാകും, അതിനാൽ ഭാവിയിൽ ആപ്പ് മെച്ചപ്പെടുത്താൻ ഞങ്ങളെ സഹായിക്കുന്നതിന് എന്തെങ്കിലും പ്രശ്‌നങ്ങൾ നേരിടുകയാണെങ്കിൽ ഞങ്ങൾക്ക് ഫീഡ്‌ബാക്ക് നൽകാൻ മടിക്കരുത്.</string>\n    <string name=\"sponsor\">സ്പോൺസർ</string>\n    <string name=\"sponsor_desc\">GitHub-ൽ സ്പോൺസർ ചെയ്തുകൊണ്ട് ഈ ആപ്പിനെ പിന്തുണയ്ക്കുക</string>\n    <string name=\"auto_update_disabled_msg\">%1$s ബിൽഡുകൾക്ക് സ്വയമേവയുള്ള അപ്ഡേറ്റ് ലഭ്യമല്ല. നിങ്ങളുടെ ഉപകരണത്തിൽ %1$s ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ലെങ്കിലോ സീലിൽ വരാനിരിക്കുന്ന പുതിയ ഫീച്ചറുകൾ പ്രിവ്യൂ ചെയ്യാൻ ആഗ്രഹിക്കുന്നുവെങ്കിലോ, ദയവായി %2$s പരിഗണിക്കുക.</string>\n    <string name=\"feature_unavailable\">ഫീച്ചർ ലഭ്യമല്ല</string>\n    <string name=\"no_custom_command_tasks\">ഇഷ്‌ടാനുസൃത കമാൻഡ് ടാസ്‌ക്കുകളൊന്നുമില്ല</string>\n    <string name=\"convert_subtitle\">സബ്ടൈറ്റിലുകൾ പരിവർത്തനം ചെയ്യുക</string>\n    <string name=\"convert_subtitle_desc\">സബ്ടൈറ്റിലുകൾ മറ്റൊരു ഫോർമാറ്റിലേക്ക് പരിവർത്തനം ചെയ്യുക</string>\n    <string name=\"proxy_desc\">ഇൻ്റർനെറ്റ് കണക്ഷനുകൾക്ക് പ്രോക്സി ഉപയോഗിക്കുക</string>\n    <string name=\"legacy\">പഴയത്</string>\n    <string name=\"quality\">ഗുണമേന്മ</string>\n    <string name=\"enable_notifications\">അറിയിപ്പുകൾ പ്രവർത്തനക്ഷമമാക്കണോ?</string>\n    <string name=\"enable_notifications_desc\">ഡൗൺലോഡ് നിലയെയും പുരോഗതിയെയും കുറിച്ചുള്ള അറിയിപ്പുകൾ പോസ്റ്റുചെയ്യാൻ ആപ്പിന് നിങ്ങളുടെ അനുമതി ആവശ്യമാണ്.</string>\n    <string name=\"prefer_compatibility_desc\">മറ്റ് ആപ്പുകളിലേക്ക് പങ്കിടുന്നതിന് MP4(H.264) ഫോർമാറ്റുകൾ തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"prefer_quality_desc\">അനുയോജ്യമായ ആപ്പുകളിൽ കാണുന്നതിന് AV1, VP9 അല്ലെങ്കിൽ H.265 ഫോർമാറ്റുകൾ തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"unknown\">അജ്ഞാതം</string>\n    <string name=\"refresh_cookies_desc\">പുതിയ കുക്കികൾ സൃഷ്‌ടിക്കാൻ വെബ്‌പേജ് തുറക്കാൻ ടാപ്പ് ചെയ്യുക:</string>\n    <string name=\"presets\">പ്രീസെറ്റുകൾ</string>\n    <string name=\"download_archive_desc\">ഡ്യൂപ്ലിക്കേറ്റ് ഡൗൺലോഡുകൾ ഒഴിവാക്കാൻ ഡൗൺലോഡ് ചെയ്ത വീഡിയോ ഐഡികൾ ഒരു ആർക്കൈവിൽ റെക്കോർഡ് ചെയ്യുക</string>\n    <string name=\"clear_download_archive_desc\">ആർക്കൈവ് ഫയലിൽ നിന്ന് %1$s നീക്കം ചെയ്യണോ?</string>\n    <string name=\"clear_download_archive\">ഡൗൺലോഡ് ആർക്കൈവ് മായ്‌ക്കണോ?</string>\n    <string name=\"use_format_sorting\">ഫോർമാറ്റ് സോർട്ടിംഗ് ഉപയോഗിക്കുക</string>\n    <string name=\"restrict_filenames_desc\">അനുയോജ്യത ഉറപ്പാക്കാൻ ഫയൽ നാമങ്ങൾ നിർദ്ദിഷ്ട പ്രതീകങ്ങളിലേക്ക് പരിമിതപ്പെടുത്തുക</string>\n    <string name=\"merge_audiostream\">ഒന്നിലധികം ഓഡിയോ സ്ട്രീം ലയിപ്പിക്കുക</string>\n    <string name=\"merge_audiostream_desc\">ഒന്നിലധികം ഓഡിയോ സ്ട്രീമുകൾ ഒരൊറ്റ ഫയലിലേക്ക് ലയിപ്പിക്കാൻ അനുവദിക്കുക</string>\n    <string name=\"search_in_downloads\">ഡൗൺലോഡുകളിൽ തിരയുക</string>\n    <string name=\"search\">തിരയുക</string>\n    <string name=\"subtitle_language_desc\">കോമകളാൽ വേർതിരിച്ച, സ്വയമേവയുള്ള ഫോർമാറ്റ് തിരഞ്ഞെടുപ്പിൽ ഡൗൺലോഡ് ചെയ്യാനുള്ള സബ്‌ടൈറ്റിലുകളുടെ ഭാഷ.</string>\n    <string name=\"remember_for_next_download\">അടുത്ത ഡൗൺലോഡിനായി ഓർക്കുക</string>\n    <string name=\"update_language_msg\">ഭാവിയിലെ ഡൗൺലോഡുകൾക്കായി ഇനിപ്പറയുന്ന ഭാഷകൾ നിങ്ങളുടെ മുൻഗണനയിലേക്ക് ചേർക്കും:</string>\n    <string name=\"update_subtitle_languages\">സബ്‌ടൈറ്റിൽ ഭാഷകൾ അപ്‌ഡേറ്റ് ചെയ്യണോ?</string>\n    <string name=\"import_backup\">ഇറക്കുമതി ചെയ്യുക</string>\n    <string name=\"allow_always\">എല്ലായ്പ്പോഴും അനുവദിക്കുക</string>\n    <string name=\"dont_allow\">അനുവദിക്കരുത്</string>\n    <string name=\"download_with_cellular_request\">സെല്ലുലാർ ഉപയോഗിച്ച് ഡൗൺലോഡ് ചെയ്യാൻ അനുവദിക്കണോ?</string>\n    <string name=\"got_it\">മനസ്സിലായി</string>\n    <string name=\"subdirectory_hint\">നിങ്ങളുടെ ഡൗൺലോഡുകൾ ഇങ്ങനെ സംരക്ഷിക്കപ്പെടും:</string>\n    <string name=\"enable_experimental_feature\">പരീക്ഷണാത്മക ഫീച്ചർ പ്രവർത്തനക്ഷമമാക്കണോ?</string>\n    <string name=\"sponsor_msg\">സീൽ എല്ലായ്‌പ്പോഴും സൗജന്യവും ഓപ്പൺ സോഴ്‌സും ആയിരിക്കും. നിങ്ങൾക്കത് ഇഷ്‌ടമാണെങ്കിൽ, GitHub-ൽ എന്നെ സ്‌പോൺസർ ചെയ്യുന്നത് പരിഗണിക്കൂ!</string>\n    <string name=\"feedback\">പ്രതികരണം</string>\n    <string name=\"sponsors\">സ്പോൺസർമാർ</string>\n    <string name=\"split_video\">വീഡിയോ വിഭജിക്കുക</string>\n    <string name=\"split_video_msg\">വീഡിയോ %1$d അധ്യായങ്ങളായി വിഭജിക്കും</string>\n    <string name=\"ua_header\">User-Agent തലക്കെട്ട്</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"share\">പങ്കിടുക</string>\n    <string name=\"stable_channel\">സ്ഥിരതയുള്ള</string>\n    <string name=\"update_channel\">ചാനൽ അപ്ഡേറ്റ് ചെയ്യുക</string>\n    <string name=\"auto_update\">അപ്ഡേറ്റ് തന്നത്താനെ ചെയ്യുക</string>\n    <string name=\"enable_auto_update\">യാന്ത്രിക അപ്‌ഡേറ്റ് പ്രവർത്തനക്ഷമമാക്കുക</string>\n    <string name=\"unlimited\">അൺലിമിറ്റഡ്</string>\n    <string name=\"lowest_bitrate\">ഏറ്റവും കുറഞ്ഞ ബിറ്റ്റേറ്റ്</string>\n    <string name=\"audio_quality\">ഓഡിയോ നിലവാരം</string>\n    <string name=\"audio_quality_desc\">ഒന്നിലധികം ഗുണങ്ങൾ ഉള്ളപ്പോൾ ഓഡിയോ ബിറ്റ്റേറ്റ് പരിമിതപ്പെടുത്തുക</string>\n    <string name=\"format_sorting\">ഫോർമാറ്റ് സോർട്ടിംഗ്</string>\n    <string name=\"format_sorting_desc\">yt-dlp-ൻ്റെ -S ഓപ്ഷൻ ഉപയോഗിച്ച് ഫോർമാറ്റുകൾ അടുക്കുന്നു</string>\n    <string name=\"clear_all_cookies\">എല്ലാ കുക്കികളും മായ്‌ക്കുക</string>\n    <string name=\"temporary_directory_desc\">ആന്തരിക ഡയറക്ടറിയിൽ താൽക്കാലിക ഫയലുകൾ സംഭരിക്കുക</string>\n    <string name=\"clip_video_dialog_msg\">വീഡിയോയുടെ തിരഞ്ഞെടുത്ത വിഭാഗങ്ങൾ ഡൗൺലോഡ് ചെയ്യുന്നതിനായി ഈ ഫീച്ചർ ഉപയോഗിക്കുന്ന ഡൗൺലോഡുകൾ FFmpeg-ലേക്ക് ഡെലിഗേറ്റ് ചെയ്യപ്പെടും, ഈ ഫീച്ചർ ഇപ്പോഴും പരീക്ഷണാത്മകമാണ്, കട്ടിംഗ് പൂർണ്ണമായും കൃത്യമല്ല, എല്ലാ ഫോർമാറ്റുകളും ഈ ഫീച്ചറിനെ പിന്തുണയ്ക്കുന്നില്ല, നിങ്ങൾക്ക് വേഗത കുറഞ്ഞ ഡൗൺലോഡ് വേഗത അനുഭവപ്പെടാം.</string>\n    <string name=\"download_video_desc\">URL-ൽ നിന്ന് വീഡിയോകൾ ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"copy_and_exit\">പകർത്തി പുറത്തുകടക്കുക</string>\n    <string name=\"expand\">വികസിപ്പിക്കുക</string>\n    <string name=\"new_task\">പുതിയ ഡൗൺലോഡ് ടാസ്ക്</string>\n    <string name=\"start\">ആരംഭിക്കുക</string>\n    <string name=\"edit_template\">\\\"%1$s\\\" എഡിറ്റ് ചെയ്യുക</string>\n    <string name=\"apply\">പ്രയോഗിക്കുക</string>\n    <string name=\"discard\">നിരസിക്കുക</string>\n    <string name=\"clip_video\">വീഡിയോ ക്ലിപ്പ് ചെയ്യുക</string>\n    <string name=\"keep_subtitle_files\">സബ്ടൈറ്റിൽ ഫയലുകൾ സൂക്ഷിക്കുക</string>\n    <string name=\"pre_release_channel\">പ്രിവ്യൂ</string>\n    <string name=\"clear_all_cookies_desc\">ആപ്പിൽ സംഭരിച്ചിരിക്കുന്ന എല്ലാ കുക്കികളും ഇല്ലാതാക്കണോ?</string>\n    <string name=\"folder_picker\">ഫോൾഡർ പിക്കർ</string>\n    <string name=\"auto\">യാന്ത്രികമായി തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"custom\">ഇഷ്ടാനുസരണം</string>\n    <string name=\"learn_more\">കൂടുതലറിയുക</string>\n    <string name=\"remux_container_mkv\">Remux വീഡിയോ കണ്ടെയ്നർ</string>\n    <string name=\"remux_container_mkv_desc\">മികച്ച അനുയോജ്യതയ്ക്കായി എംകെവി കണ്ടെയ്‌നറിലേക്ക് വീഡിയോകൾ റീമുക്സ് ചെയ്യുക</string>\n    <string name=\"embed_metadata_desc\">ഓഡിയോ ഫയലിൽ മെറ്റാഡാറ്റയും വീഡിയോ ലഘുചിത്രവും ഉൾപ്പെടുത്തുക</string>\n    <string name=\"required\">ആവശ്യമാണ്</string>\n    <string name=\"download_archive_error\">വീഡിയോ ഡൗൺലോഡ് ചെയ്തു. ഇത് പ്രതീക്ഷിച്ച സ്വഭാവമല്ലെങ്കിൽ, നിങ്ങളുടെ ഡൗൺലോഡ് ആർക്കൈവ് പരിശോധിക്കുക.</string>\n    <string name=\"show_all_items\">എല്ലാ %1$d ഇനങ്ങളും കാണിക്കുക</string>\n    <string name=\"import_from\">നിന്ന് ഇറക്കുമതി ചെയ്യുക</string>\n    <string name=\"export_to_file\">ഫയലിലേക്ക് കയറ്റുമതി ചെയ്യുക</string>\n    <string name=\"restrict_filenames\">ഫയലുകളുടെ പേരുകൾ നിയന്ത്രിക്കുക</string>\n    <string name=\"website\">വെബ്സൈറ്റ്</string>\n    <string name=\"playlist_title\">പ്ലേലിസ്റ്റ് ശീർഷകം</string>\n    <string name=\"audio_format\">ഓഡിയോ ഫോർമാറ്റ്</string>\n    <string name=\"clip_start\">ആരംഭിക്കുക</string>\n    <string name=\"clip_end\">അവസാനിക്കുന്നു</string>\n    <string name=\"clip_video_desc\">ഫോർമാറ്റ് തിരഞ്ഞെടുക്കൽ പേജിൽ വീഡിയോ ക്ലിപ്പുകൾ ഉണ്ടാക്കുക</string>\n    <string name=\"switch_to_github_builds\">GitHub ബിൽഡുകളിലേക്ക് മാറുന്നു</string>\n    <string name=\"okay\">ശരി</string>\n    <string name=\"msg_from_developer\">ഡെവലപ്പറിൽ നിന്നുള്ള സന്ദേശം</string>\n    <string name=\"sponsor_msg2\">വളരെ നന്ദി!</string>\n    <string name=\"unknown_error_title\">ശ്ശോ! എന്തോ കുഴപ്പം സംഭവിച്ചു</string>\n    <string name=\"disable\">പ്രവർത്തനരഹിതമാക്കുക</string>\n    <string name=\"set_directory_desc\">ഡയറക്ടറി സജ്ജീകരിക്കാൻ ടാപ്പ് ചെയ്യുക</string>\n    <string name=\"custom_command_directory_desc\">ഇഷ്ടാനുസൃത കമാൻഡുകൾ ഉപയോഗിക്കുമ്പോൾ ഔട്ട്പുട്ട് ഡയറക്ടറി വ്യക്തമാക്കുക</string>\n    <string name=\"download_type\">ഡൗൺലോഡ് തരം</string>\n    <string name=\"commands\">കമാൻഡുകൾ</string>\n    <string name=\"format_preference\">ഫോർമാറ്റ് മുൻഗണന</string>\n    <string name=\"output_template\">ഔട്ട്പുട്ട് ടെംപ്ലേറ്റ്</string>\n    <string name=\"output_template_desc\">ഔട്ട്പുട്ട് ഫയൽ പേരുകൾക്കായുള്ള ടെംപ്ലേറ്റ് വ്യക്തമാക്കുക</string>\n    <string name=\"system_settings\">സിസ്റ്റം ക്രമീകരണങ്ങൾ</string>\n    <string name=\"look_and_feel\">കാണുക &amp; അനുഭവിക്കുക</string>\n    <string name=\"interface_and_interaction\">ഇൻ്റർഫേസും ഇടപെടലും</string>\n    <string name=\"use_previous_selection\">മുമ്പത്തെ തിരഞ്ഞെടുപ്പ് ഉപയോഗിക്കുക</string>\n    <string name=\"none\">ഒന്നുമില്ല</string>\n    <string name=\"reset\">പുനഃസജ്ജമാക്കുക</string>\n    <string name=\"search_in_subtitles\">സബ്‌ടൈറ്റിലുകളിൽ തിരയുക</string>\n    <string name=\"no_thanks\">വേണ്ട, നന്ദി</string>\n    <string name=\"export_backup\">കയറ്റുമതി ചെയ്യുക</string>\n    <string name=\"full_backup\">പൂർണ്ണ ബാക്കപ്പ്</string>\n    <string name=\"backup_type\">ബാക്കപ്പ് തരം</string>\n    <string name=\"file\">ഫയൽ</string>\n    <string name=\"clipboard\">ക്ലിപ്പ്ബോർഡ്</string>\n    <string name=\"download_history\">ഡൗൺലോഡ് ചരിത്രം</string>\n    <string name=\"download_archive\">ആർക്കൈവ് ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"force_ipv4\">IPv4 നിർബന്ധിക്കുക</string>\n    <string name=\"force_ipv4_desc\">IPv4 വഴി എല്ലാ കണക്ഷനുകളും ഉണ്ടാക്കുക</string>\n    <string name=\"every_month\">എല്ലാ മാസവും</string>\n    <string name=\"download_history_imported\">ചരിത്രം ഡൗൺലോഡ് ചെയ്യാൻ %1$s ഇറക്കുമതി ചെയ്തു</string>\n    <string name=\"redownload\">വീണ്ടും ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"edit_preset\">പ്രീസെറ്റ് എഡിറ്റ് ചെയ്യുക</string>\n    <string name=\"task_added\">ക്യൂവിൽ ടാസ്ക് ചേർത്തു</string>\n    <string name=\"you_ll_find_your_downloads_here\">നിങ്ങളുടെ ഡൗൺലോഡുകൾ ഇവിടെ കാണാം</string>\n    <string name=\"download_hint\">ഡൗൺലോഡ് ആരംഭിക്കാൻ ഡൗൺലോഡ് ബട്ടണിൽ ടാപ്പ് ചെയ്യുക അല്ലെങ്കിൽ ഈ ആപ്പിലേക്ക് ഒരു വീഡിയോ ലിങ്ക് പങ്കിടുക</string>\n    <string name=\"status_downloaded\">ഡൗൺലോഡ് ചെയ്തു</string>\n    <string name=\"playlist\">പ്ലേലിസ്റ്റ്</string>\n    <string name=\"proceed\">തുടരുക</string>\n    <string name=\"preset\">പ്രീസെറ്റ്</string>\n    <string name=\"prefer_placeholder\">%1$s തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"custom_format_selection_desc\">ഫോർമാറ്റുകൾ, സബ്‌ടൈറ്റിലുകൾ എന്നിവയിൽ നിന്ന് തിരഞ്ഞെടുത്ത് കൂടുതൽ ഇഷ്ടാനുസൃതമാക്കുക</string>\n    <string name=\"best_quality_desc\">ലഭ്യമായ ഏറ്റവും മികച്ച ഫോർമാറ്റ് ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"all\">എല്ലാം</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d വീഡിയോ</item>\n        <item quantity=\"other\">%d വീഡിയോകൾ</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d ഓഡിയോ</item>\n        <item quantity=\"other\">%d ഓഡിയോകൾ</item>\n    </plurals>\n    <string name=\"select_multiple_link\">%1$d ലിങ്കുകളിൽ നിന്ന് തിരഞ്ഞെടുക്കുക</string>\n    <string name=\"download_queue\">ഡൗൺലോഡ് ക്യൂ</string>\n    <string name=\"all_languages\">എല്ലാ ഭാഷകളും</string>\n    <string name=\"preset_format_selection_desc\">നിങ്ങളുടെ ഫോർമാറ്റ് മുൻഗണനകൾ ഉപയോഗിച്ച് സ്വയമേവ ഡൗൺലോഡ് ചെയ്യുക</string>\n    <string name=\"show_navigation_drawer\">നാവിഗേഷൻ ഡ്രോയർ കാണിക്കുക</string>\n    <string name=\"resume\">പുനരാരംഭിക്കുക</string>\n    <string name=\"delete\">ഇല്ലാതാക്കുക</string>\n    <string name=\"media_info\">മീഡിയയുടെ വിവരം</string>\n    <string name=\"issue_tracker_hint\">നിങ്ങൾ ഒരു പിശക് നേരിട്ടോ? അത് അറിയിപ്പിക്കുന്നതിനു മുമ്പ് ഞങ്ങളുടെ പ്രശ്‌ന ട്രാക്കർ തിരയുക. പൊതുവായ പല പ്രശ്നങ്ങളും ഇതിനകം തന്നെ അവിടെ അഭിസംബോധന ചെയ്യുകയും രേഖപ്പെടുത്തുകയും ചെയ്തിട്ടുണ്ട്.</string>\n    <string name=\"trouble_shooting_desc\">പൊതുവായ പിശകുകൾ പരിഹരിക്കുക, അറിയപ്പെടുന്ന പ്രശ്നങ്ങൾ കാണുക</string>\n    <string name=\"trouble_shooting\">പ്രശ്നനിർണയവും പരിഹാരവും</string>\n    <string name=\"issue_tracker\">പ്രശ്ന ട്രാക്കർ</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-mn/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Видео хавтас</string>\n    <string name=\"status_enqueued\">Дараалсан</string>\n    <string name=\"status_completed\">Дууслаа</string>\n    <string name=\"start\">Эхлэх</string>\n    <string name=\"download_type\">Татаж авах төрөл</string>\n    <string name=\"allow_always\">Үргэлж зөвшөөрөх</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d видео</item>\n        <item quantity=\"other\">%d видео</item>\n    </plurals>\n    <string name=\"extract_audio\">Аудио болгон хадгалах</string>\n    <string name=\"create_thumbnail\">Өнгөц зургийг хадгалах</string>\n    <string name=\"settings\">Тохиргоо</string>\n    <string name=\"download_settings_desc\">Ерөнхий, формат, захиалгат тушаал</string>\n    <string name=\"download\">Татаж авах</string>\n    <string name=\"url_empty\">Холбоос хоосон байж болохгүй</string>\n    <string name=\"extract_audio_summary\">Видеоны оронд аудиог татаж аваад хадгалаарай</string>\n    <string name=\"create_thumbnail_summary\">Видеоны өнгөц зургийг файл болгон хадгалах</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp-ийн хамгийн сүүлийн хувилбарыг ашиглаж байна</string>\n    <string name=\"yt_dlp_update_fail\">Хамгийн сүүлийн үеийн yt-dlp хувилбарыг суулгаж чадсангүй. Та интернетэд холбогдсон эсэхээ шалгана уу.</string>\n    <string name=\"fetching_info\">Видеоны мэдээллийг дуудаж байна…</string>\n    <string name=\"permission_denied\">Зөвшөөрөл татгалзсан</string>\n    <string name=\"download_success_msg\">Татаж дууссан</string>\n    <string name=\"download_error_msg\">Файлыг татаж чадсангүй</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" татаж авах</string>\n    <string name=\"fetch_info_error_msg\">Видеоны мэдээллийг татаж авч чадсангүй</string>\n    <string name=\"general_settings\">Генерал</string>\n    <string name=\"language\">Дэлгэцийн хэл</string>\n    <string name=\"language_settings\">Дэлгэцийн хэлийг тохируулах</string>\n    <string name=\"task_running\">Одоо байгаа татаж авах ажил аль хэдийн ажиллаж байна</string>\n    <string name=\"paste_msg\">URL буулгах</string>\n    <string name=\"paste_fail_msg\">Түр санах ойн URL-тай таарч чадсангүй</string>\n    <string name=\"ytdlp_version\">Yt-dlp хувилбар</string>\n    <string name=\"ytdlp_update\">Хамгийн сүүлийн үеийн yt-dlp хувилбарыг суулгахын тулд товшино уу</string>\n    <string name=\"ytdlp_update_action\">yt-dlp-г шинэчлэх</string>\n    <string name=\"delete_info\">Устгах уу?</string>\n    <string name=\"delete_info_msg\">\\\"%1$s\\\"-г татаж авах түүхээсээ бүрмөсөн устгах уу?</string>\n    <string name=\"confirm\">Баталгаажуулах</string>\n    <string name=\"dismiss\">Цуцлах</string>\n    <string name=\"downloads_history\">Татаж авсан зүйлс</string>\n    <string name=\"audio\">Аудио</string>\n    <string name=\"link_copied\">Холбоосыг санах ой руу хуулсан</string>\n    <string name=\"open_url\">Холбоосыг нээх</string>\n    <string name=\"remove\">Устгах</string>\n    <string name=\"delete_file\">Файл устгах</string>\n    <string name=\"about\">тухай</string>\n    <string name=\"about_page\">Хувилбар, санал хүсэлт, автомат шинэчлэлт</string>\n    <string name=\"back\">Буцах</string>\n    <string name=\"version\">Хувилбар</string>\n    <string name=\"release_desc\">Өөрчлөлтийн бүртгэл болон шинэ хувилбаруудыг хайж олоорой</string>\n    <string name=\"release\">Хамгийн сүүлийн хувилбар</string>\n    <string name=\"readme_desc\">GitHub репозитор болон README-г шалгана уу</string>\n    <string name=\"video\">Видео</string>\n    <string name=\"checked\">Шалгасан</string>\n    <string name=\"credits\">Зээл</string>\n    <string name=\"credits_desc\">Кредит болон үнэгүй програм хангамж</string>\n    <string name=\"custom_command\">Тусгай тушаал</string>\n    <string name=\"custom_command_desc\">yt-dlp командыг тусгай загвараар ажиллуулна уу</string>\n    <string name=\"custom_command_template\">Тушаалын загвар</string>\n    <string name=\"edit\">Засварлах</string>\n    <string name=\"start_execute\">Командыг гүйцэтгэж эхэлнэ</string>\n    <string name=\"advanced_settings\">Дэвшилтэт</string>\n    <string name=\"print_details\">Нарийвчилсан гаралт</string>\n    <string name=\"print_details_desc\">Татаж авахдаа дэлгэрэнгүй мессежийг хэвлэх</string>\n    <string name=\"display\">Дэлгэц</string>\n    <string name=\"display_settings\">Харанхуй сэдэв, динамик өнгө, хэл</string>\n    <string name=\"dark_theme\">Харанхуй сэдэв</string>\n    <string name=\"follow_system\">Систем</string>\n    <string name=\"on\">Асаалттай</string>\n    <string name=\"off\">Унтраах</string>\n    <string name=\"cancel\">Цуцлах</string>\n    <string name=\"settings_before_download\">Татаж авахаасаа өмнө тохируулна уу</string>\n    <string name=\"settings_before_download_desc\">Татаж авахаасаа өмнө тохиргоогоо тохируулна уу</string>\n    <string name=\"settings_before_download_text\">Энэ татан авалтыг тохируулна уу</string>\n    <string name=\"error_copied\">Алдааны тайланг санах ой руу хуулсан</string>\n    <string name=\"thumbnail\">Өнгөц зураг</string>\n    <string name=\"paste\">Буулгах</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp хэрэглээний лавлагаа</string>\n    <string name=\"edit_template_desc\">Гаралтын зам болон URL-г апп нэмнэ.</string>\n    <string name=\"convert_audio_format\">Аудио форматыг хөрвүүлэх</string>\n    <string name=\"not_convert\">Хөрвүүлээгүй</string>\n    <string name=\"convert_to\">%1$s руу хөрвүүлэх</string>\n    <string name=\"format\">Формат</string>\n    <string name=\"convert_audio_format_desc\">Аудио файлуудыг дахин кодчилсноор дууны чанар муудаж, файлын хэмжээ нэмэгдэх болно.</string>\n    <string name=\"video_quality\">Видеоны чанар</string>\n    <string name=\"best_quality\">Хамгийн сайн чанар</string>\n    <string name=\"video_quality_desc\">Олон хүн байгаа үед видеоны чанарыг хязгаарлаарай</string>\n    <string name=\"not_specified\">Тодорхойгүй (өгөгдмөл)</string>\n    <string name=\"video_format_preference\">Сонгодог видео формат</string>\n    <string name=\"preferred_format_desc\">Олон өгөгдсөн тохиолдолд илүүд үздэг формат</string>\n    <string name=\"video_format\">Видео формат</string>\n    <string name=\"convert_audio\">Хөрвүүлэх</string>\n    <string name=\"start_download\">Татаж авах</string>\n    <string name=\"close\">Хаах</string>\n    <string name=\"close_never_show_again\">Дахиж битгий хараарай</string>\n    <string name=\"user_guide\">Хэрэглэгчийн гарын авлага</string>\n    <string name=\"open_settings\">Тохиргоог нээх</string>\n    <string name=\"paste_desc\">Өөрийн санах ойноос видео линкийг авахын тулд \\\"Буулгах\\\" дээр дарна уу.</string>\n    <string name=\"download_desc\">Дараа нь тохиргоог нь тохируулсны дараа \\\"Татаж авах\\\" дээр дарна уу.</string>\n    <string name=\"download_history_desc\">Видео болон аудио файл зэрэг апп доторх татан авалтыг шалгаж, удирдах.</string>\n    <string name=\"check_download_settings_desc\">Татаж авах тохиргоог харж, шалгана уу Та үүнийг ашиглахаасаа өмнө yt-dlp-ийн хамгийн сүүлийн хувилбартай байна.</string>\n    <string name=\"download_playlist\">Тоглуулах жагсаалтыг татаж авах</string>\n    <string name=\"download_playlist_desc\">Тоглуулах жагсаалтаас олон видео татаж авах</string>\n    <string name=\"defaults\">Өгөгдмөл</string>\n    <string name=\"channel_name\">Татаж авах</string>\n    <string name=\"channel_description\">Татаж авсан файлууд болон явцын талаар мэдэгдэх</string>\n    <string name=\"video_url\">Видео холбоос</string>\n    <string name=\"download_finish_notification\">Татаж дууссан. Нээх бол товшино уу.</string>\n    <string name=\"execute_command_notification\">Тусгай тушаалуудыг ажиллуулж байна…</string>\n    <string name=\"battery_settings_desc\">Ард татаж авахын тулд энэ програмын батарейны хэрэглээг системийн тохиргооноос \\\"Хязгааргүй\\\" болгож тохируулна уу.</string>\n    <string name=\"concurrent_download\">Олон урсгалтай татаж авах</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD видеоны бусад хэсгийг зэрэгцүүлэн татаж аваарай</string>\n    <string name=\"concurrent_download_num\">%d урсгалыг DASH/HLS үндсэн видеог зэрэг татахад ашиглах болно.</string>\n    <string name=\"options\">Сонголтууд</string>\n    <string name=\"additional_settings\">Нэмэлт тохиргоо</string>\n    <string name=\"share_fail_msg\">Хуваалцсан контентын URL-г тааруулах боломжгүй</string>\n    <string name=\"share_success_msg\">Хуваалцсан контентоос видео холбоосыг уншиж байна…</string>\n    <string name=\"show_more_actions\">Илүү олон үйлдлийг харуулах</string>\n    <string name=\"download_notification\">Мэдэгдэл татаж авах</string>\n    <string name=\"download_notification_desc\">Татаж авсан файлууд болон явцын талаар мэдэгдэх</string>\n    <string name=\"fetching_playlist_info\">Тоглуулах жагсаалтын мэдээллийг дуудаж байна…</string>\n    <string name=\"download_range_selection\">Тоглуулах жагсаалтын сонголт</string>\n    <string name=\"download_range_desc\">\\\"%3$s\\\" (%1$d-аас %2$d хүртэл) тоглуулах жагсаалтаас татаж авах видеоны хүрээг зааж өгнө үү.</string>\n    <string name=\"from\">Эхлэх</string>\n    <string name=\"to\">Төгсгөл</string>\n    <string name=\"invalid_index_range\">Индексийн хүрээ буруу байна</string>\n    <string name=\"playlist_indicator_text\">Тоглуулах жагсаалтыг татаж байна (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Аудио хавтас</string>\n    <string name=\"download_directory\">Татаж авах лавлах</string>\n    <string name=\"download_directory_desc\">Видео болон аудио файлуудыг хаана хадгалахаа сонгоно уу</string>\n    <string name=\"subdirectory\">Дэд директорт хадгалах</string>\n    <string name=\"subdirectory_desc\">Файлуудыг холбогдох талбарт нэрлэсэн хавтсанд хадгална уу</string>\n    <string name=\"permission_issue\">Хадгалах зөвшөөрлийн асуудал</string>\n    <string name=\"permission_issue_desc\">Татаж авах/ болон Баримт бичиг/ гаднах лавлахуудыг дэмждэггүй</string>\n    <string name=\"battery_configuration\">Зайны тохиргоо</string>\n    <string name=\"battery_configuration_desc\">Энэ програмыг далд татаж авахын тулд батерейны оновчлолыг үл тоомсорло</string>\n    <string name=\"service_title\">Seal татаж авч байна…</string>\n    <string name=\"unknown_error\">Үл мэдэгдэх алдаа</string>\n    <string name=\"translate\">Орчуулах</string>\n    <string name=\"translate_desc\">Энэ програмыг Hosted Weblate дээр орчуулахад тусална уу</string>\n    <string name=\"prefix\">Угтвар</string>\n    <string name=\"embed_subtitles\">Хадмал орчуулга оруулах</string>\n    <string name=\"embed_subtitles_desc\">Боломжтой бол видеонуудад зөөлөн дэд файлуудыг оруулаарай</string>\n    <string name=\"new_template\">Шинэ загвар</string>\n    <string name=\"template_label\">Шошго</string>\n    <string name=\"remove_template\">Устгах уу?</string>\n    <string name=\"remove_template_desc\">\\\"%1$s\\\"-г тушаалын загвараас бүрмөсөн устгах уу?</string>\n    <string name=\"template_selection\">Загвар сонгох</string>\n    <string name=\"custom_command_template_desc\">Командын загваруудыг засах, удирдах</string>\n    <string name=\"downloading_indicator_text\">Татаж авч байна…</string>\n    <string name=\"task_canceled\">Татаж авах ажлыг цуцалсан</string>\n    <string name=\"github_issue\">GitHub асуудал</string>\n    <string name=\"github_issue_desc\">Алдааны тайлан эсвэл функцийн хүсэлтийн талаар асуудал илгээнэ үү</string>\n    <string name=\"info_copied\">Мэдээллийг санах ой руу хуулсан</string>\n    <string name=\"status_downloading\">Татаж байна</string>\n    <string name=\"status_canceled\">Цуцлагдсан</string>\n    <string name=\"status_fetching_video_info\">Мэдээлэл авч байна</string>\n    <string name=\"open_file\">Файлыг нээх</string>\n    <string name=\"restart\">Дахин эхлүүлэх</string>\n    <string name=\"status_error\">Алдаа</string>\n    <string name=\"copy_link\">Холбоосыг хуулах</string>\n    <string name=\"copy_error_report\">Тайлан хуулах</string>\n    <string name=\"video_resolution\">Видеоны нягтрал</string>\n    <string name=\"video_file_size\">Видео файлын хэмжээ</string>\n    <string name=\"export_to_clipboard\">Түр санах ой руу экспортлох</string>\n    <string name=\"import_from_clipboard\">Түр санах ойноос импорт хийх</string>\n    <string name=\"template_exported\">Экспортолсон %1$d загвар(ууд)</string>\n    <string name=\"template_imported\">Импортолсон %1$d загвар(ууд)</string>\n    <string name=\"download_task_count\">%1$d Даалгавруудыг татаж авах</string>\n    <string name=\"recently_added\">Саяхан нэмэгдсэн</string>\n    <string name=\"multiselect_item_count\">%1$d видео(s), %2$d аудио файл(ууд)</string>\n    <string name=\"delete_multiple_items_msg\">Татаж авсан түүхээсээ %1$d зүйлийг бүрмөсөн устгах уу?</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API ашиглан видеонуудын сегментүүдийг устгах эсвэл тэмдэглэх</string>\n    <string name=\"sponsorblock_categories_desc\">Видео файлаас хасах эсвэл тэмдэглэхийн тулд SponsorBlock ангиллыг зааж өгнө үү</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock ангилал</string>\n    <string name=\"check_for_updates\">Шинэчлэлт байгаа эсэхийг шалгана уу</string>\n    <string name=\"check_for_updates_desc\">GitHub дээрх хамгийн сүүлийн хувилбарыг автоматаар шалгана уу</string>\n    <string name=\"app_up_to_date\">Одоогийн хувилбар нь шинэчлэгдсэн</string>\n    <string name=\"app_update_failed\">Хамгийн сүүлийн хувилбар руу шинэчилж чадсангүй</string>\n    <string name=\"update\">Шинэчлэх</string>\n    <string name=\"aria2_desc\">aria2c-г гадаад татагч болгон ашигла</string>\n    <string name=\"cookies\">Күүки</string>\n    <string name=\"cookies_desc\">Татаж авахдаа Netscape форматтай күүки ашиглана уу</string>\n    <string name=\"clear_temp_files\">Түр зуурын файлуудыг арилгах</string>\n    <string name=\"clear_temp_files_desc\">Түр зуурын лавлахаас түр зуурын бүх файлыг устгана уу</string>\n    <string name=\"clear_temp_files_count\">%1$d түр файлыг устгасан</string>\n    <string name=\"clear_temp_files_info\">Цуцлагдсан татан авалтыг үргэлжлүүлэхэд түр зуурын файлуудыг ашиглаж болно. Та эдгээр бүх файлыг устгахдаа итгэлтэй байна уу?\n\\n\n\\nТа эдгээр файлд %1$s-д хандах боломжтой</string>\n    <string name=\"multiselect_mode\">Олон сонголттой горим</string>\n    <string name=\"private_mode\">Нууцлалтай</string>\n    <string name=\"private_mode_desc\">Татаж авсан түүхийг идэвхгүй болгох</string>\n    <string name=\"dynamic_color\">Динамик өнгө</string>\n    <string name=\"dynamic_color_desc\">Апп-ын сэдэвт ханын цааснаас өнгө хэрэглээрэй</string>\n    <string name=\"download_with_cellular\">Үүрэн холбоо ашиглан татаж авах</string>\n    <string name=\"download_with_cellular_desc\">Хэмжээтэй сүлжээнд холбогдсон үед медиа татаж авахыг зөвшөөрнө үү</string>\n    <string name=\"download_disabled_with_cellular\">Таны тохиргооны дагуу үүрэн сүлжээгээр татаж авахыг идэвхгүй болгосон</string>\n    <string name=\"file_unavailable\">Энэ файлыг ашиглах боломжгүй болсон</string>\n    <string name=\"network\">Сүлжээ</string>\n    <string name=\"rate_limit\">Үнийн хязгаарлалт</string>\n    <string name=\"rate_limit_desc\">Татаж авах хамгийн дээд хурдыг хязгаарлах</string>\n    <string name=\"max_rate\">Хамгийн их хувь хэмжээ</string>\n    <string name=\"high_contrast\">Өндөр тодосгогчтой бараан загвар</string>\n    <string name=\"invalid_input\">Буруу оролт</string>\n    <string name=\"lowest_quality\">Хамгийн бага чанар</string>\n    <string name=\"unavailable\">Боломжгүй</string>\n    <string name=\"format_settings_desc\">Файлын формат, видеоны чанар, хадмал орчуулга</string>\n    <string name=\"general_settings_desc\">Yt-dlp хувилбар, мэдэгдэл, тоглуулах жагсаалт</string>\n    <string name=\"network_settings_desc\">Үнийн хязгаарлалт, татагч, күүки</string>\n    <string name=\"disable_preview\">Урьдчилан үзэхийг идэвхгүй болгох</string>\n    <string name=\"disable_preview_desc\">Татаж авах явцад өнгөц зургийг харуулахгүй</string>\n    <string name=\"privacy\">Нууцлал</string>\n    <string name=\"use_custom_command\">Тусгай тушаалыг ашиглана уу</string>\n    <string name=\"private_directory\">Хувийн лавлах</string>\n    <string name=\"private_directory_desc\">Татаж авсан файлуудыг далд санд хадгалах</string>\n    <string name=\"crop_artwork\">Урлагийн тайралт</string>\n    <string name=\"crop_artwork_desc\">Суулгасан зургийг дөрвөлжин болгож тайрах</string>\n    <string name=\"download_selection_desc\">\\\"%1$s\\\" тоглуулах жагсаалтаас татаж авах видеонуудыг сонгоно уу.</string>\n    <string name=\"select_all\">Бүгдийг сонгоно уу</string>\n    <string name=\"selected_item_count\">%1$d сонгосон</string>\n    <string name=\"video_only\">Видео (аудио байхгүй)</string>\n    <string name=\"suggested\">Санал болгосон</string>\n    <string name=\"format_selection\">Формат сонгох</string>\n    <string name=\"format_selection_desc\">Татаж эхлэхээсээ өмнө татаж авах форматаа сонгоно уу</string>\n    <string name=\"generate_new_cookies\">Шинэ күүки үүсгэх</string>\n    <string name=\"use_cookies\">Күүки ашиглах</string>\n    <string name=\"remove_cookie_profile_desc\">\\\"%1$s\\\"-н энэ оруулгыг устгах уу? Энэ сайтад хадгалагдсан күүки устгагдахгүй гэдгийг анхаарна уу.</string>\n    <string name=\"custom_command_enabled_hint\">Захиалгат тушаалыг ашиглах үед зарим сонголтууд боломжгүй байдаг</string>\n    <string name=\"how_does_it_work\">Энэ нь хэрхэн ажилладаг вэ?</string>\n    <string name=\"cookies_usage_msg\">Зарим сайтаас татаж авахад акаунтын баталгаажуулалтын мэдээлэл шаардлагатай. \\\"Шинэ күүки үүсгэх\\\" дээр дарж, вэб сайтын URL хаягийг оруулаад хөтчийн хуудсанд өөрийн бүртгэлээр нэвтэрч, апп үүнийг танд үүсгэх болно.</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp бол видео татаж авах командын шугамын хүчирхэг хэрэгсэл юм. Seal нь ойлгомжтой GUI, нийтлэг командуудад зориулсан урьдчилан тохируулгууд болон бусад нэмэлт функцээр хангаснаар yt-dlp-г ашиглахад хялбар болгодог.\n\\n\n\\nYt-dlp-г илүү сайн ашиглахын тулд Seal нь танд захиалгат командын загваруудыг шууд үүсгэх, хадгалах, гүйцэтгэх боломжийг олгодог. яг терминал дээрх шиг.\n\\n\n\\nЗахиалгат тушаалуудыг ашиглах үед ихэнх GUI сонголтууд болон функцууд идэвхгүй болно.</string>\n    <string name=\"telegram_channel\">Telegram суваг</string>\n    <string name=\"matrix_space\">Матрицын орон зай</string>\n    <string name=\"sdcard_directory\">SD картны хавтас</string>\n    <string name=\"auto_subtitle\">Автомат тайлбар</string>\n    <string name=\"auto_subtitle_desc\">Автоматаар үүсгэсэн тайлбарыг татаж авах</string>\n    <string name=\"title_activity_share\">Түргэн татаж авах</string>\n    <string name=\"abs_hint\">Ихэнх видео стриминг платформууд аудио болон видеог тусад нь хүргэдэг тул та зөвхөн видео форматтай зөвхөн аудио форматыг сонгож, нэг видео болгон нэгтгэж болно.</string>\n    <string name=\"video_title_sample_text\">Видеоны гарчгийн жишээ текст</string>\n    <string name=\"video_creator_sample_text\">Видео бүтээгчийн жишээ текст</string>\n    <string name=\"subtitle\">Хадмал орчуулга</string>\n    <string name=\"download_subtitles\">Хадмал орчуулгыг татаж авах</string>\n    <string name=\"subtitle_language\">Хадмал орчуулгын хэлүүд</string>\n    <string name=\"subtitle_desc\">Хэл, хадмал оруулах, автомат тайлбар</string>\n    <string name=\"copy_log\">Бүртгэлийг хуулах</string>\n    <string name=\"clear\">Тодорхой</string>\n    <string name=\"edit_shortcuts\">Товчлолыг засах</string>\n    <string name=\"add\">Нэмэх</string>\n    <string name=\"shortcuts\">Товчлолууд</string>\n    <string name=\"edit_shortcuts_desc\">Командын загвар зохиоход ашиглаж болох захиалгат товчлолуудыг засварлана уу.</string>\n    <string name=\"running_tasks\">Ажиллаж байгаа ажлууд</string>\n    <string name=\"show_logs\">Бүртгэлийг харуулах</string>\n    <string name=\"logs\">Бүртгэл</string>\n    <string name=\"subtitle_sponsorblock\">SponsorBlock сегментүүдийг хасах үед хадмал орчуулгын цаг буруу байж болзошгүй.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Зөөлөн хадмал оруулахын тулд видеонуудыг mkv контейнерт дахин оруулах болно. Та зөөлөн хадмалтай видео үзэхийн тулд VLC Media Player эсвэл бусад нийцтэй програмуудыг ашиглаж болно.</string>\n    <string name=\"filesize_mb\">%.2f МБ</string>\n    <string name=\"filesize_gb\">%.2f ГБ</string>\n    <string name=\"share\">Хуваалцах</string>\n    <string name=\"stable_channel\">Тогтвортой</string>\n    <string name=\"pre_release_channel\">Урьдчилан үзэх</string>\n    <string name=\"update_channel_desc\">Шинэ боломжууд болон өөрчлөлтүүдийг урьдчилан харахын тулд хувилбарын өмнөх хувилбаруудыг суулгана уу.\n\\n\n\\nЭдгээр хувилбаруудад тогтворгүй байдал гарах тул ирээдүйд апп-г сайжруулахад туслах ямар нэгэн асуудал гарвал бидэнд санал хүсэлтээ өгөхөөс бүү эргэлз.</string>\n    <string name=\"update_channel\">Сувгийг шинэчлэх</string>\n    <string name=\"auto_update\">Автоматаар шинэчлэх</string>\n    <string name=\"enable_auto_update\">Автомат шинэчлэлтийг идэвхжүүлэх</string>\n    <string name=\"discard\">Хая</string>\n    <string name=\"apply\">Өргөдөл гаргах</string>\n    <string name=\"clip_video\">Клип видео</string>\n    <string name=\"clip_start\">Эхлэх</string>\n    <string name=\"clip_end\">Төгсгөл</string>\n    <string name=\"audio_format_preference\">Сонгосон аудио формат</string>\n    <string name=\"unlimited\">Хязгааргүй</string>\n    <string name=\"lowest_bitrate\">Хамгийн бага бит хурд</string>\n    <string name=\"audio_quality\">Аудио чанар</string>\n    <string name=\"audio_quality_desc\">Олон чанар байгаа үед аудио битийн хурдыг хязгаарлах</string>\n    <string name=\"format_sorting\">Формат эрэмбэлэх</string>\n    <string name=\"format_sorting_desc\">yt-dlp-ийн -S сонголтоор форматуудыг эрэмбэлэх</string>\n    <string name=\"import_from_preferences\">Импорт</string>\n    <string name=\"title\">Гарчиг</string>\n    <string name=\"rename\">Нэрээ өөрчлөх</string>\n    <string name=\"second\">хоёрдугаарт</string>\n    <string name=\"minute\">минут</string>\n    <string name=\"clear_all_cookies\">Бүх күүкийг устгана уу</string>\n    <string name=\"clear_all_cookies_desc\">Апп-д хадгалагдсан бүх күүкиг бүрмөсөн устгах уу?</string>\n    <string name=\"temporary_directory_desc\">Түр зуурын файлуудыг дотоод директорт хадгалах</string>\n    <string name=\"sponsor\">Ивээн тэтгэгч</string>\n    <string name=\"sponsor_desc\">GitHub дээр ивээн тэтгэж энэ програмыг дэмжээрэй</string>\n    <string name=\"sponsor_msg\">Seal нь үргэлж үнэ төлбөргүй, хүн бүрт нээлттэй эх сурвалж байх болно. Хэрэв танд таалагдаж байвал GitHub дээр намайг ивээн тэтгэх талаар бодож үзээрэй!</string>\n    <string name=\"feedback\">Санал хүсэлт</string>\n    <string name=\"sponsors\">Ивээн тэтгэгчид</string>\n    <string name=\"audio_format\">Аудио формат</string>\n    <string name=\"no_downloaded_media\">Татаж авсан медиа байхгүй</string>\n    <string name=\"beta_features\">Бета</string>\n    <string name=\"enable_experimental_feature\">Туршилтын онцлогийг идэвхжүүлэх үү?</string>\n    <string name=\"clip_video_dialog_msg\">Энэ функцийг ашигласан татан авалтыг FFmpeg-д шилжүүлж, видеоны сонгосон хэсгүүдийг татаж авах болно, энэ функц нь туршилтын хэвээр байгаа бөгөөд огтлолт нь бүрэн нарийвчлалтай биш, бүх формат энэ функцийг дэмждэггүй бөгөөд та татаж авах хурд нь удааширч магадгүй юм.</string>\n    <string name=\"clip_video_desc\">Формат сонгох хуудсанд видео клип хийх</string>\n    <string name=\"auto_update_disabled_msg\">%1$s-д автоматаар шинэчлэх боломжгүй. Хэрэв таны төхөөрөмж дээр %1$s суулгаагүй эсвэл Seal-д удахгүй гарах шинэ боломжуудыг үзэхийг хүсвэл %2$s-г анхаарч үзээрэй.</string>\n    <string name=\"switch_to_github_builds\">GitHub бүтэц рүү шилжих</string>\n    <string name=\"okay\">За</string>\n    <string name=\"got_it\">Ойлголоо</string>\n    <string name=\"feature_unavailable\">Онцлог боломжгүй</string>\n    <string name=\"no_custom_command_tasks\">Тусгай тушаалын даалгавар байхгүй</string>\n    <string name=\"msg_from_developer\">Хөгжүүлэгчээс ирсэн мессеж</string>\n    <string name=\"sponsor_msg2\">Маш их баярлалаа!</string>\n    <string name=\"download_video_desc\">URL-аас видео татаж авах</string>\n    <string name=\"convert_subtitle\">Хадмал орчуулгыг хөрвүүлэх</string>\n    <string name=\"convert_subtitle_desc\">Хадмал орчуулгыг өөр формат руу хөрвүүлэх</string>\n    <string name=\"split_video\">Видеог хуваах</string>\n    <string name=\"split_video_msg\">Видеог %1$d бүлэгт хуваах болно</string>\n    <string name=\"unknown_error_title\">Өө! Ямар нэг алдаа гарлаа</string>\n    <string name=\"copy_and_exit\">Хуулах, гарах</string>\n    <string name=\"expand\">Өргөтгөх</string>\n    <string name=\"new_task\">Шинэ татаж авах даалгавар</string>\n    <string name=\"edit_template\">\\\"%1$s\\\"-г засах</string>\n    <string name=\"proxy\">Прокси</string>\n    <string name=\"proxy_desc\">Интернэт холболтын хувьд прокси ашиглана уу</string>\n    <string name=\"legacy\">Өв залгамжлал</string>\n    <string name=\"quality\">Чанартай</string>\n    <string name=\"enable_notifications\">Мэдэгдлийг идэвхжүүлэх үү?</string>\n    <string name=\"enable_notifications_desc\">Татаж авах байдал болон явцын талаар мэдэгдэл нийтлэхийн тулд апп нь таны зөвшөөрөл шаардлагатай.</string>\n    <string name=\"disable\">Идэвхгүй болгох</string>\n    <string name=\"set_directory_desc\">Лавлахыг тохируулахын тулд товшино уу</string>\n    <string name=\"custom_command_directory\">Тусгай тушаалын лавлах</string>\n    <string name=\"disabled\">Идэвхгүй</string>\n    <string name=\"folder_picker\">Хавтас сонгогч</string>\n    <string name=\"custom_command_directory_desc\">Захиалгат тушаалуудыг ашиглахдаа гаралтын лавлахыг зааж өгнө үү</string>\n    <string name=\"prefer_compatibility_desc\">Бусад программтай хуваалцахын тулд MP4(H.264) форматыг илүүд үзээрэй</string>\n    <string name=\"prefer_quality_desc\">Тохиромжтой программ дээр үзэхийн тулд AV1, VP9 эсвэл H.265 форматыг сонго</string>\n    <string name=\"custom\">Захиалгат</string>\n    <string name=\"auto\">Автомат</string>\n    <string name=\"commands\">Тушаалууд</string>\n    <string name=\"format_preference\">Форматын сонголт</string>\n    <string name=\"learn_more\">Илүү ихийг мэдэж аваарай</string>\n    <string name=\"unknown\">Тодорхойгүй</string>\n    <string name=\"refresh_cookies_desc\">Шинэ күүки үүсгэх вэб хуудсыг нээхийн тулд товшино уу:</string>\n    <string name=\"remove_multiple_templates_msg\">%1$s-г тушаалын загвараас бүрмөсөн устгах уу?</string>\n    <string name=\"ua_header\">Хэрэглэгч-Агент толгой</string>\n    <string name=\"export_to_file\">Файл руу экспортлох</string>\n    <string name=\"output_template\">Гаралтын загвар</string>\n    <string name=\"presets\">Урьдчилсан тохируулгууд</string>\n    <string name=\"output_template_desc\">Гаралтын файлын нэрийн загварыг зааж өгнө үү</string>\n    <string name=\"download_archive\">Архив татаж авах</string>\n    <string name=\"download_archive_desc\">Давхардсан таталтаас зайлсхийхийн тулд татаж авсан видеоны ID-г архивт тэмдэглэнэ үү</string>\n    <string name=\"clear_download_archive\">Татаж авах архивыг арилгах уу?</string>\n    <string name=\"clear_download_archive_desc\">Архив файлаас %1$s-г бүрмөсөн устгах уу?</string>\n    <string name=\"embed_metadata\">Мета өгөгдлийг оруулах</string>\n    <string name=\"embed_metadata_desc\">Аудио файлд мета өгөгдөл болон видеоны өнгөц зургийг оруулах</string>\n    <string name=\"required\">Шаардлагатай</string>\n    <string name=\"show_all_items\">Бүх %1$d зүйлийг харуулах</string>\n    <string name=\"edit_file\">Файлыг засах</string>\n    <string name=\"save\">Хадгалах</string>\n    <string name=\"use_format_sorting\">Формат эрэмбэлэх</string>\n    <string name=\"restrict_filenames\">Файлын нэрийг хязгаарлах</string>\n    <string name=\"restrict_filenames_desc\">Тохиромжтой байдлыг хангахын тулд файлын нэрийг тодорхой тэмдэгтээр хязгаарлаарай</string>\n    <string name=\"website\">Вэб сайт</string>\n    <string name=\"playlist_title\">Тоглуулах жагсаалтын гарчиг</string>\n    <string name=\"subdirectory_hint\">Таны татсан зүйлс дараах байдлаар хадгалагдах болно:</string>\n    <string name=\"system_settings\">Системийн тохиргоо</string>\n    <string name=\"force_ipv4\">IPv4-г хүчлэх</string>\n    <string name=\"force_ipv4_desc\">Бүх холболтыг IPv4-ээр хийнэ үү</string>\n    <string name=\"keep_subtitle_files\">Хадмал файлуудыг хадгалах</string>\n    <string name=\"allow_once\">Нэг удаа зөвшөөрөх</string>\n    <string name=\"dont_allow\">Бүү зөвшөөр</string>\n    <string name=\"download_with_cellular_request\">Үүрэн утсаар татаж авахыг зөвшөөрөх үү?</string>\n    <string name=\"merge_audiostream\">Олон аудио урсгалыг нэгтгэх</string>\n    <string name=\"merge_audiostream_desc\">Олон аудио урсгалыг нэг файлд нэгтгэхийг зөвшөөрөх</string>\n    <string name=\"search_in_downloads\">Татаж авсан файлуудаас хайх</string>\n    <string name=\"search\">Хайх</string>\n    <string name=\"auto_translated_subtitles\">Автоматаар орчуулсан хадмал орчуулга</string>\n    <string name=\"auto_translated_subtitles_msg\">Бүх хэл дээр автоматаар орчуулагдсан хадмал орчуулга татаж авах боломжтой. Эдгээр хадмал орчуулга нь буруу, ойлгоход хэцүү байж магадгүй.</string>\n    <string name=\"subtitle_language_desc\">Автомат форматаар татаж авах хадмал орчуулгын хэлийг таслалаар тусгаарлана.</string>\n    <string name=\"remember_for_next_download\">Дараагийн татаж авахдаа санаарай</string>\n    <string name=\"look_and_feel\">Харж, мэдэр</string>\n    <string name=\"interface_and_interaction\">Интерфейс ба харилцан үйлчлэл</string>\n    <string name=\"use_previous_selection\">Өмнөх сонголтыг ашиглана уу</string>\n    <string name=\"none\">Байхгүй</string>\n    <string name=\"reset\">Дахин тохируулах</string>\n    <string name=\"search_in_subtitles\">Хадмал орчуулгаас хайх</string>\n    <string name=\"no_thanks\">Үгүй баярлалаа</string>\n    <string name=\"update_language_msg\">Дараах хэлүүд нь таны дараагийн татан авалтын сонголтод нэмэгдэх болно:</string>\n    <string name=\"update_subtitle_languages\">Хадмал орчуулгын хэлийг шинэчлэх үү?</string>\n    <string name=\"export_backup\">Экспорт</string>\n    <string name=\"import_backup\">Импорт</string>\n    <string name=\"full_backup\">Бүрэн нөөцлөлт</string>\n    <string name=\"backup_type\">Нөөцлөх төрөл</string>\n    <string name=\"export_to\">руу экспортлох</string>\n    <string name=\"file\">Файл</string>\n    <string name=\"clipboard\">Түр санах ой</string>\n    <string name=\"import_from\">-аас импортлох</string>\n    <string name=\"export_download_history\">Татаж авсан түүхийг экспортлох уу?</string>\n    <string name=\"import_download_history\">Татаж авсан түүхийг импортлох уу?</string>\n    <string name=\"import_download_history_msg\">Татаж авсан файлуудыг импортлохгүй. Та тэдгээрийг гараар буцааж татах шаардлагатай болно</string>\n    <string name=\"export_download_history_msg\">Татаж авсан түүхээс %1$s-г экспорт хийж байна. Татаж авсан файлууд болон тохиргоог нөөцлөхгүй.</string>\n    <string name=\"download_history\">Татаж авах түүх</string>\n    <string name=\"download_history_imported\">Түүхийг татахын тулд %1$s-г импортолсон</string>\n    <string name=\"redownload\">Дахин татаж авах</string>\n    <string name=\"download_archive_error\">Видеог татаж авлаа. Хэрэв энэ нь хүлээгдэж буй үйлдэл биш бол татаж авах архиваа шалгана уу.</string>\n    <string name=\"remux_container_mkv\">Remux видео сав</string>\n    <string name=\"remux_container_mkv_desc\">Илүү сайн нийцтэй байхын тулд Remux видеог MKV саванд хийнэ</string>\n    <string name=\"cookies_in_database\">Нийт %2$d вэбсайтаас %1$d күүки</string>\n    <string name=\"every_day\">Өдөр бүр</string>\n    <string name=\"every_week\">Долоо хоног бүр</string>\n    <string name=\"every_month\">Сар бүр</string>\n    <string name=\"all_languages\">Бүх хэл</string>\n    <string name=\"playlist\">Тоглуулах жагсаалт</string>\n    <string name=\"proceed\">Үргэлжлүүлэх</string>\n    <string name=\"preset\">Урьдчилан тохируулсан</string>\n    <string name=\"prefer_placeholder\">%1$s-г илүүд үзнэ үү</string>\n    <string name=\"custom_format_selection_desc\">Формат, хадмал орчуулгаас сонгоод цааш нь тохируулаарай</string>\n    <string name=\"preset_format_selection_desc\">Өөрийн форматын тохиргоог ашиглан автоматаар татаж аваарай</string>\n    <string name=\"edit_preset\">Урьдчилсан тохиргоог засах</string>\n    <string name=\"best_quality_desc\">Боломжтой хамгийн сайн форматыг татаж аваарай</string>\n    <string name=\"task_added\">Даалгаврыг дараалалд нэмсэн</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d зүйл</item>\n        <item quantity=\"other\">%d зүйл</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d аудио</item>\n        <item quantity=\"other\">%d аудио</item>\n    </plurals>\n    <string name=\"download_queue\">Татах дараалал</string>\n    <string name=\"you_ll_find_your_downloads_here\">Та эндээс татан авалтуудаа олох болно</string>\n    <string name=\"download_hint\">Татаж авах товчийг дарах эсвэл энэ програмын видео холбоосыг хуваалцаж, татаж авч эхэлнэ үү</string>\n    <string name=\"status_downloaded\">Татаж авсан</string>\n    <string name=\"select_multiple_link\">%1$d холбоосоос сонгоно уу</string>\n    <string name=\"trouble_shooting\">Алдааг олж засварлах</string>\n    <string name=\"issue_tracker\">Асуудал хянагч</string>\n    <string name=\"trouble_shooting_desc\">Нийтлэг алдааг засч, мэдэгдэж буй асуудлуудыг шалгана уу</string>\n    <string name=\"issue_tracker_hint\">Алдаа гарсан уу? Шинэ асуудлыг мэдээлэхийн өмнө манай асуудал хянагчаас хайна уу. Тэнд олон нийтлэг асуудлыг аль хэдийн шийдэж, баримтжуулсан.</string>\n    <string name=\"show_navigation_drawer\">Навигацийн цэсийг харуулах</string>\n    <string name=\"resume\">Үргэлжлүүлэх</string>\n    <string name=\"delete\">Устгах</string>\n    <string name=\"all\">Бүгд</string>\n    <string name=\"media_info\">Медиа мэдээлэл</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-mr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">ऑडिओ म्हणून सेव्ह करा</string>\n    <string name=\"follow_system\">सिस्टम</string>\n    <string name=\"settings\">सेटिंग्ज</string>\n    <string name=\"video_directory\">व्हिडिओ फोल्डर</string>\n    <string name=\"create_thumbnail\">थंबनेल सेव्ह करा</string>\n    <string name=\"extract_audio_summary\">व्हिडिओ ऐवजी ऑडिओ डाउनलोड आणि सेव्ह करा</string>\n    <string name=\"task_running\">विद्यमान डाउनलोड कार्य आधीच चालू आहे</string>\n    <string name=\"download_settings_desc\">सामान्य, स्वरूप, सानुकूल कमांड</string>\n    <string name=\"download\">डाउनलोड</string>\n    <string name=\"yt_dlp_update_fail\">नवीनतम yt-dlp आवृत्ती स्थापित करू शकलो नाही. कृपया तुम्ही इंटरनेटशी कनेक्ट असल्याची खात्री करा.</string>\n    <string name=\"fetching_info\">व्हिडिओ माहिती मिळवत आहे…</string>\n    <string name=\"download_error_msg\">फाईल डाऊनलोड करता आली नाही</string>\n    <string name=\"fetch_info_error_msg\">व्हिडिओ माहिती मिळवता आली नाही</string>\n    <string name=\"language\">भाषा प्रदर्शित करा</string>\n    <string name=\"url_empty\">लिंक रिकामी असू शकत नाही</string>\n    <string name=\"create_thumbnail_summary\">व्हिडिओ थंबनेल फाईल म्हणून सेव्ह करा</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp ची नवीनतम आवृत्ती वापरत आहे</string>\n    <string name=\"permission_denied\">परवानगी नाकारली</string>\n    <string name=\"download_success_msg\">डाउनलोड पूर्ण झाले</string>\n    <string name=\"delete_info_msg\">तुमच्या डाउनलोड इतिहासातून \\\"%1$s\\\" काढून टाकायचे\\?</string>\n    <string name=\"dismiss\">रद्द करा</string>\n    <string name=\"downloads_history\">डाउनलोड</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" डाउनलोड करा</string>\n    <string name=\"general_settings\">सामान्य</string>\n    <string name=\"paste_msg\">क्लिपबोर्डवरून URL पेस्ट करा</string>\n    <string name=\"delete_info\">काढायचे\\?</string>\n    <string name=\"language_settings\">प्रदर्शन भाषा सेट करा</string>\n    <string name=\"paste_fail_msg\">क्लिपबोर्डमधील URL जुळू शकलो नाही</string>\n    <string name=\"ytdlp_version\">Yt-dlp आवृत्ती</string>\n    <string name=\"ytdlp_update\">नवीनतम yt-dlp आवृत्ती स्थापित करण्यासाठी क्लिक करा</string>\n    <string name=\"credits_desc\">क्रेडिट्स आणि लिब्रे सॉफ्टवेअर</string>\n    <string name=\"confirm\">पुष्टी करा</string>\n    <string name=\"error_copied\">त्रुटी अहवाल क्लिपबोर्डवर कॉपी केला</string>\n    <string name=\"audio\">ऑडिओ</string>\n    <string name=\"open_url\">लिंक ओपन करा</string>\n    <string name=\"delete_file\">डिलीट करा</string>\n    <string name=\"back\">मागे</string>\n    <string name=\"checked\">तपासले</string>\n    <string name=\"settings_before_download\">डाउनलोड करण्यापूर्वी कॉन्फिगर करा</string>\n    <string name=\"link_copied\">लिंक क्लिपबोर्डवर कॉपी केली</string>\n    <string name=\"remove\">काढा</string>\n    <string name=\"version\">आवृत्ती</string>\n    <string name=\"custom_command\">सानुकूल कमांड</string>\n    <string name=\"about\">आमच्याबद्दल</string>\n    <string name=\"credits\">क्रेडिट्स</string>\n    <string name=\"about_page\">आवृत्ती, फीडबॅक, ऑटो अपडेट</string>\n    <string name=\"release_desc\">चेंजलॉग आणि नवीन आवृत्त्या पहा</string>\n    <string name=\"readme_desc\">GitHub रेपॉजिटरी आणि README तपासा</string>\n    <string name=\"custom_command_desc\">सानुकूल टेम्पलेटसह yt-dlp कमांड चालवा</string>\n    <string name=\"custom_command_template\">कमांड टेम्पलेट</string>\n    <string name=\"print_details\">तपशीलवार आउटपुट</string>\n    <string name=\"settings_before_download_text\">हे डाउनलोड समायोजित करा</string>\n    <string name=\"release\">नवीनतम रिलीज</string>\n    <string name=\"video\">व्हिडिओ</string>\n    <string name=\"cancel\">रद्द करा</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp वापर संदर्भ</string>\n    <string name=\"start_execute\">कमांड कार्यान्वित करण्यास प्रारंभ करा</string>\n    <string name=\"advanced_settings\">अडवांस</string>\n    <string name=\"print_details_desc\">डाउनलोड करताना तपशीलवार संदेश प्रिंट करा</string>\n    <string name=\"display\">डिस्प्ले</string>\n    <string name=\"on\">चालू</string>\n    <string name=\"paste\">पेस्ट करा</string>\n    <string name=\"not_convert\">अपरिवर्तित</string>\n    <string name=\"edit\">संपादित करा</string>\n    <string name=\"display_settings\">गडद थीम, डायनॅमिक रंग, भाषा</string>\n    <string name=\"off\">बंद</string>\n    <string name=\"dark_theme\">गडद थीम</string>\n    <string name=\"settings_before_download_desc\">डाउनलोड करण्यापूर्वी प्राधान्ये कॉन्फिगर करा</string>\n    <string name=\"thumbnail\">थंबनेल</string>\n    <string name=\"format\">स्वरूप</string>\n    <string name=\"best_quality\">सर्वोत्तम गुणवत्ता (डीफॉल्ट)</string>\n    <string name=\"edit_template_desc\">आउटपुट मार्ग आणि URL ॲपद्वारे जोडले जातील.</string>\n    <string name=\"convert_audio_format\">ऑडिओ स्वरूप रूपांतरित करा</string>\n    <string name=\"convert_to\">%1$s मध्ये रूपांतरित करा</string>\n    <string name=\"video_quality_desc\">एकाधिक उपस्थित असताना व्हिडिओ गुणवत्ता मर्यादित करा</string>\n    <string name=\"video_quality\">व्हिडिओ गुणवत्ता</string>\n    <string name=\"convert_audio_format_desc\">ऑडिओ फाइल्स पुन्हा एन्कोडिंग केल्याने ऑडिओ गुणवत्तेत नुकसान होईल आणि फाइलचा आकार वाढेल.</string>\n    <string name=\"ytdlp_update_action\">अपडेट yt-dlp</string>\n    <string name=\"video_format\">व्हिडिओ चा स्वरूप</string>\n    <string name=\"close\">बंद</string>\n    <string name=\"close_never_show_again\">पून्हा दाखवू नका</string>\n    <string name=\"user_guide\">यूजर गाईड</string>\n    <string name=\"open_settings\">सेटिंग्ज उघडा</string>\n    <string name=\"paste_desc\">क्लिप-बोर्डवरून व्हिडिओ लिंक मिळविण्यासाठी \\\"पेस्ट\\\" वर क्लिक करा</string>\n    <string name=\"preferred_format_desc\">अधिक व्हिडिओ साठी तुमचा आवडीचा स्वरूप कोणता</string>\n    <string name=\"convert_audio\">रूपांतर</string>\n    <string name=\"start_download\">डाऊनलोड</string>\n    <string name=\"not_specified\">निर्दिष्ट नाही</string>\n    <string name=\"video_format_preference\">आवडीचा व्हिडिओ स्वरूप</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ms/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Folder video</string>\n    <string name=\"create_thumbnail\">Simpan lakaran kenit</string>\n    <string name=\"settings\">Tetapan</string>\n    <string name=\"download_settings_desc\">Umum, format, arahan tersuai</string>\n    <string name=\"extract_audio_summary\">Muat turun dan simpan audio, bukannya video</string>\n    <string name=\"create_thumbnail_summary\">Simpan lakaran kenit video sebagai fail</string>\n    <string name=\"yt_dlp_update_fail\">Tidak dapat memasang versi yt-dlp terkini. Sila pastikan bahawa anda disambungkan ke Internet.</string>\n    <string name=\"fetching_info\">Mengumpul maklumat video…</string>\n    <string name=\"download_success_msg\">Muat turun selesai</string>\n    <string name=\"download_error_msg\">Tidak dapat memuat turun fail</string>\n    <string name=\"download_start_msg\">Muat turun \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Tidak dapat mengumpul maklumat video</string>\n    <string name=\"general_settings\">Umum</string>\n    <string name=\"task_running\">Tugas muat turun sedia ada sedang berjalan</string>\n    <string name=\"paste_fail_msg\">Tidak dapat memadankan URL dalam papan keratan</string>\n    <string name=\"ytdlp_update\">Tekan untuk memasang versi yt-dlp terkini</string>\n    <string name=\"delete_info\">Buang\\?</string>\n    <string name=\"delete_file\">Padam</string>\n    <string name=\"about\">Perihal</string>\n    <string name=\"about_page\">Versi,maklum balas,kemas kini automatik</string>\n    <string name=\"back\">Kembali</string>\n    <string name=\"readme_desc\">Periksa repositori GitHub dan README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Ditanda</string>\n    <string name=\"credits\">Penghargaan</string>\n    <string name=\"credits_desc\">Penghargaan dan perisian bebas</string>\n    <string name=\"custom_command\">Arahan tersuai</string>\n    <string name=\"custom_command_template\">Templat arahan</string>\n    <string name=\"start_execute\">Mulakan arahan tersuai</string>\n    <string name=\"advanced_settings\">Lanjutan</string>\n    <string name=\"on\">Hidupkan</string>\n    <string name=\"off\">Matikan</string>\n    <string name=\"settings_before_download\">Pelarasan sebelum muat turun</string>\n    <string name=\"settings_before_download_desc\">Pelarasan pilihan sebelum memuat turun</string>\n    <string name=\"settings_before_download_text\">Laraskan muat turun ini</string>\n    <string name=\"thumbnail\">Muka paparan</string>\n    <string name=\"paste\">Tampal</string>\n    <string name=\"extract_audio\">Simpan sebagai audio</string>\n    <string name=\"url_empty\">Pautan tidak boleh dibiarkan kosong</string>\n    <string name=\"download\">Muat turun</string>\n    <string name=\"yt_dlp_up_to_date\">Menggunakan versi yt-dlp terkini</string>\n    <string name=\"permission_denied\">Kebenaran dinafikan</string>\n    <string name=\"language_settings\">Tetapkan bahasa paparan</string>\n    <string name=\"language\">Bahasa paparan</string>\n    <string name=\"ytdlp_version\">Versi yt-dlp</string>\n    <string name=\"paste_msg\">Tampal URL daripada papan keratan</string>\n    <string name=\"delete_info_msg\">Buang \\\"%1$s\\\" daripada sejarah muat turun anda selama-lamanya\\?</string>\n    <string name=\"confirm\">Sahkan</string>\n    <string name=\"dismiss\">Batalkan</string>\n    <string name=\"downloads_history\">Muat turun</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Pautan disalin ke papan keratan</string>\n    <string name=\"open_url\">Buka pautan</string>\n    <string name=\"version\">Versi</string>\n    <string name=\"remove\">Buang</string>\n    <string name=\"release_desc\">Cari log perubahan dan versi baharu</string>\n    <string name=\"release\">Keluaran terkini</string>\n    <string name=\"print_details_desc\">Tunjukkan mesej terperinci ketika memuat turun</string>\n    <string name=\"display\">Paparan</string>\n    <string name=\"edit\">Sunting</string>\n    <string name=\"custom_command_desc\">Jalankan yt-dlp dengan templat tersuai</string>\n    <string name=\"print_details\">Output terperinci</string>\n    <string name=\"edit_template_desc\">Laluan output dan URL akan ditambah oleh aplikasi.</string>\n    <string name=\"display_settings\">Tema gelap, warna dinamik, bahasa</string>\n    <string name=\"dark_theme\">Tema gelap</string>\n    <string name=\"follow_system\">Sistem</string>\n    <string name=\"cancel\">Batal</string>\n    <string name=\"yt_dlp_docs\">Rujukan penggunaan yt-dlp</string>\n    <string name=\"error_copied\">Laporan ralat disalin ke papan keratan</string>\n    <string name=\"convert_audio_format\">Ubah format audio</string>\n    <string name=\"not_convert\">Tidak boleh diubah</string>\n    <string name=\"convert_to\">Ubah ke %1$s</string>\n    <string name=\"format\">Format</string>\n    <string name=\"best_quality\">Qualiti terbaik (tetapan asal)</string>\n    <string name=\"video_quality_desc\">Hadkan kualiti video apabila terdapat banyak</string>\n    <string name=\"not_specified\">Tidak dinyatakan (tetapan asal)</string>\n    <string name=\"video_format_preference\">Format video yang digemari</string>\n    <string name=\"preferred_format_desc\">Format yang dipilih apabila terdapat pelbagai pilihan</string>\n    <string name=\"start_download\">Muat turun</string>\n    <string name=\"close\">Tutup</string>\n    <string name=\"close_never_show_again\">Jangan tunjuk untuk selama-lamanya</string>\n    <string name=\"user_guide\">Panduan pengguna</string>\n    <string name=\"open_settings\">Buka tetapan</string>\n    <string name=\"paste_desc\">Tekan \\\"Tampal\\\" untuk dapatkan pautan video daripada papan keratan.</string>\n    <string name=\"download_history_desc\">Periksa dan uruskan muat turun, termasuk video and audio.</string>\n    <string name=\"check_download_settings_desc\">Periksa versi yt-dlp dalam tetapan adalah terbaharu sebelum menggunakannya.</string>\n    <string name=\"defaults\">Tetapan asal</string>\n    <string name=\"channel_name\">Muat turun</string>\n    <string name=\"channel_description\">Maklumkan tentang perkembangan dan fail yang telah dimuat turun</string>\n    <string name=\"video_url\">Pautan video</string>\n    <string name=\"download_finish_notification\">Muat turun selesai. Tekan untuk buka.</string>\n    <string name=\"execute_command_notification\">Memulakan arahan tersuai…</string>\n    <string name=\"concurrent_download\">Muat turun secara pelbagai benang</string>\n    <string name=\"concurrent_download_desc\">Muat turun bahagian-bahagian video bagi M3U8/MPD secara serentak</string>\n    <string name=\"concurrent_download_num\">%d proses akan digunakan untuk memuat turun video bagi DASH/HLS secara serentak.</string>\n    <string name=\"options\">Pilihan</string>\n    <string name=\"share_fail_msg\">Tidak dapat memadankan URL daripada isi perkongsian</string>\n    <string name=\"share_success_msg\">Membaca pautan video daripada isi perkongsian…</string>\n    <string name=\"show_more_actions\">Tunjukkan lebih lagi aksi</string>\n    <string name=\"download_notification\">Pemberitahuan muat turun</string>\n    <string name=\"download_notification_desc\">Maklumkan perkembangan dan fail yang telan dimuat turun</string>\n    <string name=\"fetching_playlist_info\">Mengumpul maklumat senarai-main…</string>\n    <string name=\"download_range_selection\">Pilihan senarai-main</string>\n    <string name=\"download_range_desc\">Nyatakan julat bagi video untuk dimuat turun daripada senarai-main \\\" %3$s\\\" (dari %1$d ke %2$d).</string>\n    <string name=\"from\">Mula</string>\n    <string name=\"to\">Selesai</string>\n    <string name=\"invalid_index_range\">Julat index tidak sah</string>\n    <string name=\"playlist_indicator_text\">Memuat turun senarai main (%1$d/%2$d), tekan untuk berhenti.</string>\n    <string name=\"audio_directory\">Folder audio</string>\n    <string name=\"download_directory\">Folder muat turun</string>\n    <string name=\"subdirectory\">Simpan ke dalam anak folder</string>\n    <string name=\"subdirectory_desc\">Simpan fail ke dalam folder yang bernama berasaskan laman sesawang</string>\n    <string name=\"permission_issue\">Masalah keizinan bagi peti simpanan</string>\n    <string name=\"permission_issue_desc\">Folder selain Download and Document tidak disokong</string>\n    <string name=\"battery_configuration\">Konfigurasi bateri</string>\n    <string name=\"battery_configuration_desc\">Abaikan pengoptimuman bateri bagi aplikasi ini untuk membolehkannya berjalan di latar belakang</string>\n    <string name=\"service_title\">Seal sedang memuat turun…</string>\n    <string name=\"translate\">Terjemah</string>\n    <string name=\"translate_desc\">Bantu terjemah aplikasi ini on Hosted Weblate</string>\n    <string name=\"prefix\">Templat laluan</string>\n    <string name=\"embed_subtitles\">Benamkan seri kata</string>\n    <string name=\"template_label\">Label</string>\n    <string name=\"remove_template\">Buang\\?</string>\n    <string name=\"remove_template_desc\">Buang \\\"%1$s\\\" daripada templat arahan untuk selama-lamanya\\?</string>\n    <string name=\"template_selection\">Pilihan templat</string>\n    <string name=\"task_canceled\">Tugas muat turun dibatalkan</string>\n    <string name=\"github_issue\">Isu Github</string>\n    <string name=\"github_issue_desc\">Laporkan isu bermasalah atau minta ciri-ciri tertentu</string>\n    <string name=\"open_file\">Buka fail</string>\n    <string name=\"status_completed\">Selesai</string>\n    <string name=\"restart\">Mula semula</string>\n    <string name=\"export_to_clipboard\">Eksport ke papan keratan</string>\n    <string name=\"import_from_clipboard\">Import daripada papan keratan</string>\n    <string name=\"template_exported\">Eksport %1$d templat</string>\n    <string name=\"video_format\">Format video</string>\n    <string name=\"download_desc\">Kemudian tekan \\\"Muat turun\\\" selepas melaras tetapannya.</string>\n    <string name=\"convert_audio_format_desc\">Pengekodan semula fail audio akan menyebabkan kehilangan kualiti audio dan peningkatan saiz fail.</string>\n    <string name=\"video_quality\">Qualiti video</string>\n    <string name=\"download_directory_desc\">Pilih tempat untuk menyimpan fail video dan audio</string>\n    <string name=\"embed_subtitles_desc\">Jika boleh, benamkan seri kata ke dalam video</string>\n    <string name=\"convert_audio\">Ubah</string>\n    <string name=\"download_playlist_desc\">Muat turun beberapa video ke senarai-main</string>\n    <string name=\"download_playlist\">Senarai-main muat turun</string>\n    <string name=\"battery_settings_desc\">Sila laras penggunaan bateri kepada \\\"Tidak terhad\\\" untuk aplikasi ini dalam tetapan sistem bagi membolehkannya berjalan dibelakang.</string>\n    <string name=\"unknown_error\">Masalah tidak diketahui</string>\n    <string name=\"downloading_indicator_text\">Muat turun sedang berjalan, tekan untuk batal.</string>\n    <string name=\"additional_settings\">Tetapan tambahan</string>\n    <string name=\"status_enqueued\">Aturan</string>\n    <string name=\"new_template\">Templat baharu</string>\n    <string name=\"custom_command_template_desc\">Edit dan uruskan templat arahan</string>\n    <string name=\"info_copied\">Maklumat disalin ke papan keratan</string>\n    <string name=\"status_downloading\">Memuat turun</string>\n    <string name=\"status_canceled\">Dibatalkan</string>\n    <string name=\"status_fetching_video_info\">Mungumpul maklumat</string>\n    <string name=\"status_error\">Ralat</string>\n    <string name=\"copy_link\">Salin pautan</string>\n    <string name=\"copy_error_report\">Lapor ralat/masalah</string>\n    <string name=\"video_resolution\">Resolusi video</string>\n    <string name=\"video_file_size\">Saiz fail video</string>\n    <string name=\"template_imported\">Import %1$d templat</string>\n    <string name=\"delete_multiple_items_msg\">Buang %1$d benda daripada sejarah muat turun untuk selama-lamanya\\?</string>\n    <string name=\"sponsorblock_desc\">Buang segmen daripada video dengan API SpnsorBlock</string>\n    <string name=\"sponsorblock_categories\">Kategori SponsorBlock</string>\n    <string name=\"download_task_count\">%1$d Tugas muat turun</string>\n    <string name=\"sponsorblock_categories_desc\">Nyatakan kategori SponsorBlock untuk dibuang daripada video</string>\n    <string name=\"recently_added\">Ditambah Baru-baru Ini</string>\n    <string name=\"multiselect_item_count\">%1$d video, %2$d audio</string>\n    <string name=\"select_all\">Pilih semua</string>\n    <string name=\"selected_item_count\">%1$d dipilih</string>\n    <string name=\"check_for_updates_desc\">Semak versi terkini di GitHub secara automatik</string>\n    <string name=\"high_contrast\">Tema gelap berkontras tinggi</string>\n    <string name=\"invalid_input\">Input tidak sah</string>\n    <string name=\"lowest_quality\">Kualiti terendah</string>\n    <string name=\"format_settings_desc\">Format file, kualiti video, sari kata</string>\n    <string name=\"network_settings_desc\">Kadar had, pemuat turun, kuki</string>\n    <string name=\"disable_preview\">Lumpuhkan pratonton</string>\n    <string name=\"disable_preview_desc\">Lumpuhkan pratonton untuk semua muat turun</string>\n    <string name=\"privacy\">Privasi</string>\n    <string name=\"use_custom_command\">Gunakan perintah tersuai</string>\n    <string name=\"private_directory\">Direktori peribadi</string>\n    <string name=\"private_directory_desc\">Simpan muat turun dalam direktori tersembunyi</string>\n    <string name=\"crop_artwork\">potong karya seni</string>\n    <string name=\"crop_artwork_desc\">Potong imej terbenam dalam segi empat</string>\n    <string name=\"check_for_updates\">Semak kemas kini</string>\n    <string name=\"app_up_to_date\">Versi ini adalah paling terkini</string>\n    <string name=\"aria2_desc\">Gunakan aria2c sebagai pemuat turun luaran</string>\n    <string name=\"clear_temp_files_count\">Berjaya memadam %1$d fail sementara</string>\n    <string name=\"multiselect_mode\">Mod berbilang pilih</string>\n    <string name=\"private_mode\">Mod peribadi</string>\n    <string name=\"private_mode_desc\">Lumpuhkan sejarah muat turun</string>\n    <string name=\"cookies_desc\">Gunakan kuki berformat Netscape untuk muat turun</string>\n    <string name=\"clear_temp_files\">Kosongkan fail sementara</string>\n    <string name=\"clear_temp_files_desc\">Kosongkan semua fail sementara daripada direktori dalaman</string>\n    <string name=\"clear_temp_files_info\">Fail-fail sementara boleh digunakan untuk meneruskan muat turun yang telah dibatalkan. Adakah anda pasti untuk membuang semua\\?</string>\n    <string name=\"dynamic_color\">Warna dinamik</string>\n    <string name=\"dynamic_color_desc\">Guna warna-warna dari kertas dinding sebagai tema aplikasi</string>\n    <string name=\"network\">Rangkaian</string>\n    <string name=\"rate_limit\">Had kadar</string>\n    <string name=\"rate_limit_desc\">Kurangkan kadar maksimum untuk muat turun</string>\n    <string name=\"max_rate\">Kadar maksimum</string>\n    <string name=\"app_update_failed\">Gagal mengemas kini ke versi terkini</string>\n    <string name=\"update\">Kemas kini</string>\n    <string name=\"download_disabled_with_cellular\">Memuat turun menggunakan rangkaian selular telah dilumpuhkan mengikut tetapan anda</string>\n    <string name=\"download_with_cellular\">Muat turun menggunakan selular</string>\n    <string name=\"download_with_cellular_desc\">Benarkan muat turun berlaku ketika bersambung dengan rangkaian terhad</string>\n    <string name=\"unavailable\">Tidak tersedia</string>\n    <string name=\"general_settings_desc\">Versi Yt-dlp, notifikasi, senarai main</string>\n    <string name=\"file_unavailable\">Fail ini tidak lagi wujud</string>\n    <string name=\"download_selection_desc\">Pilih video-video untuk dimuat turun dalam senarai main \\\"%1$s\\\"</string>\n    <string name=\"video_only\">Video (tiada audio)</string>\n    <string name=\"suggested\">Yang dicadang</string>\n    <string name=\"format_selection\">Pemilihan format</string>\n    <string name=\"format_selection_desc\">Pilih format untuk dimuat turun sebelum memulakan muat turun</string>\n    <string name=\"use_cookies\">Guna Kuki</string>\n    <string name=\"auto_subtitle_desc\">Muat turun kapsyen yang dijana secara automatik</string>\n    <string name=\"abs_hint\">Kebanyakan platform penstriman video menyampaikan audio dan video secara berasingan, anda boleh pilih dan gabung format audio sahaja dengan format video sahaja kepada satu video.</string>\n    <string name=\"edit_shortcuts_desc\">Edit jalan pintas tersuai yang boleh digunakan untuk mengarang templat arahan.</string>\n    <string name=\"cookies\">Kuki</string>\n    <string name=\"generate_new_cookies\">Menjana kuki baharu</string>\n    <string name=\"telegram_channel\">Saluran Telegram</string>\n    <string name=\"remove_cookie_profile_desc\">Buang kuki untuk \\\"%1$s\\\"?</string>\n    <string name=\"custom_command_enabled_hint\">Sebahagian pilihan tidak ada apabila menggunakan arahan tersuai</string>\n    <string name=\"how_does_it_work\">Bagaimana ia berfungsi\\?</string>\n    <string name=\"matrix_space\">Ruang Matrix</string>\n    <string name=\"cookies_usage_msg\">Memuat turun daripada sebahagian laman memerlukan maklumat pengesahan akaun. Tekan \\\"Menjana kuki baharu\\\",masukkan URL laman sesawang tersebut dan kemudian log masuk dengan akaun anda dalam muka surat pelayar, aplikasi tersebut akan menjananya untuk anda.</string>\n    <string name=\"sdcard_directory\">Folder kad SD</string>\n    <string name=\"auto_subtitle\">Kapsyen automatik</string>\n    <string name=\"title_activity_share\">Muat turun pantas</string>\n    <string name=\"video_title_sample_text\">Teks sampel tajuk video</string>\n    <string name=\"video_creator_sample_text\">Teks sampel pencipta video</string>\n    <string name=\"subtitle\">Sari kata</string>\n    <string name=\"download_subtitles\">Muat turun sari kata</string>\n    <string name=\"subtitle_language\">Bahasa-bahasa sari kata</string>\n    <string name=\"subtitle_desc\">Bahasa-bahasa, benam sari kata, kapsyen automatik</string>\n    <string name=\"copy_log\">Tiru log</string>\n    <string name=\"clear\">Bersihkan</string>\n    <string name=\"edit_shortcuts\">Edit jalan pintas</string>\n    <string name=\"add\">Tambah</string>\n    <string name=\"shortcuts\">Jalan pintas</string>\n    <string name=\"running_tasks\">Menjalankan tugas</string>\n    <string name=\"subtitle_sponsorblock\">Sari kata mungkin tersalah masa apabila membuang segmen SekatPenaja.</string>\n    <string name=\"show_logs\">Tunjuk log</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"filesize_mb\">%.2f M</string>\n    <string name=\"discard\">Buang</string>\n    <string name=\"embed_subtitles_mkv_msg\">Untuk membenam sari kata, video akan diremux ke dalam bekas MKV.</string>\n    <string name=\"filesize_gb\">%.2f G</string>\n    <string name=\"share\">Kongsi</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"pre_release_channel\">Pratonton</string>\n    <string name=\"update_channel_desc\">Pasang binaan prakeluaran untuk pratonton ciri dan perubahan baharu.\n\\n\n\\nAkan terdapat sebahagian ketidakstabilan dalam versi-versi ini, jadi sila jangan teragak-agak untuk memberi kami maklum balas jika anda mengalami sebarang masalah untuk membantu kami menambah baik aplikasi untuk masa hadapan.</string>\n    <string name=\"update_channel\">Saluran kemas kini</string>\n    <string name=\"auto_update\">Kemas kini automatik</string>\n    <string name=\"enable_auto_update\">Membenarkan kemas kini automatik</string>\n    <string name=\"apply\">Guna</string>\n    <string name=\"lowest_bitrate\">Kadar bit terendah</string>\n    <string name=\"audio_format_preference\">Format audio pilihan</string>\n    <string name=\"format_sorting\">Penyusunan format</string>\n    <string name=\"import_from_preferences\">Import</string>\n    <string name=\"title\">Tajuk</string>\n    <string name=\"format_sorting_desc\">Format penyusunan dengan pilihan -S yt-dlp</string>\n    <string name=\"minute\">minit</string>\n    <string name=\"rename\">Menama semula</string>\n    <string name=\"second\">kedua</string>\n    <string name=\"clear_all_cookies\">Bersihkan semua kuki</string>\n    <string name=\"clear_all_cookies_desc\">Buang semua kuki yang disimpan dalam aplikasi selama-lamanya\\?</string>\n    <string name=\"audio_format\">Format audio</string>\n    <string name=\"no_downloaded_media\">Tiada media dimuat turun</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Membenarkan ciri percubaan\\?</string>\n    <string name=\"clip_video_desc\">Buat klip video dalam muka surat pilihan format</string>\n    <string name=\"auto_update_disabled_msg\">Kemas kini automatik tidak ada untuk binaan %1$s. Jika anda tiada %1$s dipasang pada peranti anda, atau anda ingin pratonton ciri baharu yang akan datang dalam Seal, sila pertimbangkan %2$s.</string>\n    <string name=\"switch_to_github_builds\">bertukar kepada binaan GitHub</string>\n    <string name=\"okay\">Baik</string>\n    <string name=\"got_it\">Faham</string>\n    <string name=\"feature_unavailable\">Ciri tidak ada</string>\n    <string name=\"clip_start\">Mula</string>\n    <string name=\"clip_end\">Tamat</string>\n    <string name=\"unlimited\">Tidak terhad</string>\n    <string name=\"audio_quality\">Kualiti audio</string>\n    <string name=\"audio_quality_desc\">Hadkan kadar bit audio apabila terdapat pelbagai kualiti</string>\n    <string name=\"sponsor_desc\">Sokong aplikasi ini dengan menaja di Github</string>\n    <string name=\"clip_video_dialog_msg\">Muat turun mengguna ciri ini akan diwakilkan kepada FFmpeg untuk memuat turun bahagian video yang dipilih, ciri ini masih dalam percubaan dan pemotongan tidak akan menjadi tepat sepenuhnya, tidak semua formag sokong ciri ini dan anda mungkin akan mengalami kelajuan muat turun yang lebih perlahan.</string>\n    <string name=\"clip_video\">Video klip</string>\n    <string name=\"temporary_directory_desc\">Simpan fail sementara dalam direktori dalaman</string>\n    <string name=\"sponsor\">Taja</string>\n    <string name=\"feedback\">Maklum balas</string>\n    <string name=\"sponsors\">Penaja</string>\n    <string name=\"sponsor_msg\">Seal akan sentiasa menjadi percuma dan sumber terbuka untuk semua orang. Jika anda suka, sila pertimbangkan untuk menaja saya di GitHub!</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-nb/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"confirm\">Bekreft</string>\n    <string name=\"delete_info_msg\">Fjern «%1$s» fra nedlastningshistorikken for godt\\?</string>\n    <string name=\"not_convert\">Ukonvertert</string>\n    <string name=\"video_url\">Videolenke</string>\n    <string name=\"download_range_desc\">Angi område av videoer å laste ned fra %3$s-spillelisten (fra %1$d til %2$d)).</string>\n    <string name=\"from\">Start</string>\n    <string name=\"to\">Slutt</string>\n    <string name=\"audio_directory\">Lydmappe</string>\n    <string name=\"download_directory\">Nedlastningsmappe</string>\n    <string name=\"download_directory_desc\">Velg hvor video- og lydfiler skal lagres</string>\n    <string name=\"paste_msg\">Lim inn nettadresse</string>\n    <string name=\"ytdlp_version\">Yt-dlp -versjon</string>\n    <string name=\"delete_info\">Fjern\\?</string>\n    <string name=\"dismiss\">Avbryt</string>\n    <string name=\"downloads_history\">Nedlastninger</string>\n    <string name=\"link_copied\">Lenke kopiert til utklippstavlen</string>\n    <string name=\"open_url\">Åpne lenke</string>\n    <string name=\"start_execute\">Begynn kjøring av kommando</string>\n    <string name=\"dark_theme\">Mørk drakt</string>\n    <string name=\"cancel\">Avbryt</string>\n    <string name=\"thumbnail\">miniatyrbilde</string>\n    <string name=\"paste\">Lim inn</string>\n    <string name=\"convert_audio_format\">Konverter lydformat</string>\n    <string name=\"video_quality\">Videokvalitet</string>\n    <string name=\"video_format\">Videoformat</string>\n    <string name=\"close\">Lukk</string>\n    <string name=\"open_settings\">Åpne innstillingene</string>\n    <string name=\"download_playlist\">Last ned spilleliste</string>\n    <string name=\"defaults\">Forvalg</string>\n    <string name=\"task_running\">Laster allerede ned noe …</string>\n    <string name=\"custom_command_desc\">Kjør yt-dlp -kommando med egendefinert mal</string>\n    <string name=\"display\">Visning</string>\n    <string name=\"unknown_error\">Ukjent feil</string>\n    <string name=\"print_details_desc\">Skriv ut detaljerte meldinger ved nedlasting</string>\n    <string name=\"download_range_selection\">Valg av spilleliste</string>\n    <string name=\"invalid_index_range\">Ugyldig indeksområde</string>\n    <string name=\"subdirectory\">Lagre i undermappe</string>\n    <string name=\"yt_dlp_docs\">Bruksreferanse for yt-dlp</string>\n    <string name=\"permission_issue\">Problem med lagringstilgang</string>\n    <string name=\"subdirectory_desc\">Lagre filer i mapper med respektive nettsidenavn</string>\n    <string name=\"download_desc\">Klikk på «Last ned»-etter å ha justert innstillingene dens.</string>\n    <string name=\"download_notification_desc\">Merknad om framdrift og nedlastede filer</string>\n    <string name=\"create_thumbnail\">Lagre minatyrbilde</string>\n    <string name=\"download\">Last ned</string>\n    <string name=\"create_thumbnail_summary\">Lagre videominiatyrbilde som en fil</string>\n    <string name=\"fetching_info\">Henter videoinfo …</string>\n    <string name=\"download_success_msg\">Nedlastet</string>\n    <string name=\"fetch_info_error_msg\">Kunne ikke hente videoinfo</string>\n    <string name=\"language\">Visningsspråk</string>\n    <string name=\"language_settings\">Sett visningsspråk</string>\n    <string name=\"remove\">Fjern</string>\n    <string name=\"delete_file\">Slett</string>\n    <string name=\"about_page\">Versjon, utgivelser, bidragsytere</string>\n    <string name=\"version\">Versjon</string>\n    <string name=\"video\">Video</string>\n    <string name=\"credits\">Bidragsytere</string>\n    <string name=\"advanced_settings\">Avansert</string>\n    <string name=\"follow_system\">System</string>\n    <string name=\"not_specified\">Ikke angitt (forvalt)</string>\n    <string name=\"download_notification\">Nedlastingsmerknad</string>\n    <string name=\"yt_dlp_up_to_date\">Bruker nyeste versjon av yt-dlp</string>\n    <string name=\"release_desc\">Se etter endringslogger og nye versjoner</string>\n    <string name=\"display_settings\">Mørk drakt, dynamisk farge, språk</string>\n    <string name=\"service_title\">Seal laster ned …</string>\n    <string name=\"video_format_preference\">Foretrukket videoformat</string>\n    <string name=\"preferred_format_desc\">Valgt format når flere tilbys</string>\n    <string name=\"paste_desc\">Klikk «Lim inn» for å hente videolenken fra utklippstavlen din.</string>\n    <string name=\"download_history_desc\">Sjekk og håndter nedlastninger i programmet, inkludert video- og lydfiler.</string>\n    <string name=\"channel_description\">Merknad om nedlastingsframdrift og fullføring</string>\n    <string name=\"settings_before_download_desc\">Sett opp innstillinger før nedlastning</string>\n    <string name=\"settings_before_download_text\">Juster denne nedlastingen</string>\n    <string name=\"error_copied\">Feilrapport kopiert til utklippstavlen</string>\n    <string name=\"convert_audio_format_desc\">Lyd i MP3 eller M4A-format fungerer på de fleste enheter</string>\n    <string name=\"battery_configuration_desc\">Ignorer batterioptimaliseringer for bakgrunnsnedlastinger i dette programmet</string>\n    <string name=\"permission_issue_desc\">Mapper utenfor Download/ og Documents/ støttes ikke</string>\n    <string name=\"options\">Alternativer</string>\n    <string name=\"additional_settings\">Ytterligere innstillinger</string>\n    <string name=\"concurrent_download\">Last ned flere deler</string>\n    <string name=\"concurrent_download_desc\">Last ned flere deler av M3U8/MPD-videoer samtidig</string>\n    <string name=\"settings\">Innstillinger</string>\n    <string name=\"url_empty\">Lenken kan ikke være tom</string>\n    <string name=\"download_error_msg\">Kunne ikke laste ned fil</string>\n    <string name=\"about\">Om</string>\n    <string name=\"back\">Tilbake</string>\n    <string name=\"custom_command\">Egendefinert kommando</string>\n    <string name=\"edit\">Rediger</string>\n    <string name=\"print_details\">Detaljert utdata</string>\n    <string name=\"on\">På</string>\n    <string name=\"off\">Av</string>\n    <string name=\"best_quality\">Beste kvalitet (forvalg)</string>\n    <string name=\"user_guide\">Brukerveiledning</string>\n    <string name=\"download_playlist_desc\">Last ned flere videoer fra en spilleliste</string>\n    <string name=\"show_more_actions\">Vis flere handlinger</string>\n    <string name=\"checked\">Sjekket</string>\n    <string name=\"credits_desc\">Bidragsytere og fri programvare</string>\n    <string name=\"settings_before_download\">Sett opp før nedlasting</string>\n    <string name=\"battery_configuration\">Batterioppsett</string>\n    <string name=\"close_never_show_again\">Ikke vis igjen</string>\n    <string name=\"execute_command_notification\">Kjører egendefinerte kommandoer …</string>\n    <string name=\"video_quality_desc\">Begrens formatkvaliteten til dette nivået</string>\n    <string name=\"battery_settings_desc\">Sett batteribruk for dette programmet til «Ubegrenset» i systeminnstillingene for nedlasting i bakgrunnen.</string>\n    <string name=\"translate\">Oversett</string>\n    <string name=\"translate_desc\">Bistå oversettelsen på Hosted Weblate</string>\n    <string name=\"video_directory\">Videomappe</string>\n    <string name=\"extract_audio\">Lagre som lyd</string>\n    <string name=\"download_settings_desc\">Generelt, format, egendefinert kommando</string>\n    <string name=\"extract_audio_summary\">Last ned og lagre lyd istedenfor video</string>\n    <string name=\"download_start_msg\">Last ned «%1$s»</string>\n    <string name=\"ytdlp_update\">Klikk for å installere den nyeste yt-dlp-versjonen</string>\n    <string name=\"general_settings\">Generelt</string>\n    <string name=\"audio\">Lyd</string>\n    <string name=\"custom_command_template\">Kommandomal</string>\n    <string name=\"format\">Format</string>\n    <string name=\"convert_to\">Konverter til %1$s</string>\n    <string name=\"channel_name\">Last ned</string>\n    <string name=\"fetching_playlist_info\">Henter spillelisteinfo …</string>\n    <string name=\"yt_dlp_update_fail\">Klarte ikke å installere den nyeste yt-dlp-versjonen. Sørg for at du er tilkoblet til Internett.</string>\n    <string name=\"release\">Nyeste utgave</string>\n    <string name=\"permission_denied\">Tilgang nektet</string>\n    <string name=\"readme_desc\">Sjekk GitHub-kodelageret og LESMEG-filen</string>\n    <string name=\"paste_fail_msg\">Kunne ikke jamføre med nettadressen i utklippstavlen</string>\n    <string name=\"start_download\">Last ned</string>\n    <string name=\"convert_audio\">Konverter</string>\n    <string name=\"check_download_settings_desc\">Ta en titt på nedlastningsinnstillingene og ha nyeste utgave av yt-dlp før bruk.</string>\n    <string name=\"download_finish_notification\">Nedlastning fullført. Klikk for å åpne.</string>\n    <string name=\"playlist_indicator_text\">Laster ned spilleliste (%1$d/%2$d). Klikk for å stoppe.</string>\n    <string name=\"edit_template_desc\">Utdatasti og nettadresse blir lagt til av programmet.</string>\n    <string name=\"share_fail_msg\">Kunne ikke jamføre nettadresse fra delt innhold</string>\n    <string name=\"share_success_msg\">Leser videolenke fra delt innhold …</string>\n    <string name=\"concurrent_download_num\">%d tråd(er) kan bli brukt til å laste ned DASH/HLS native-video samtidig.</string>\n    <string name=\"prefix\">Stimal</string>\n    <string name=\"embed_subtitles\">Legg inn undertekster</string>\n    <string name=\"embed_subtitles_desc\">Legg til undertekster hvis de finnes</string>\n    <string name=\"remove_template\">Fjern\\?</string>\n    <string name=\"remove_template_desc\">Fjern «%1$s» fra kommandomalene for godt\\?</string>\n    <string name=\"new_template\">Ny mal</string>\n    <string name=\"template_label\">Etikett</string>\n    <string name=\"template_selection\">Malvalg</string>\n    <string name=\"custom_command_template_desc\">Rediger og håndter kommandomaler</string>\n    <string name=\"task_canceled\">Nedlastingsoppgave avbrutt</string>\n    <string name=\"downloading_indicator_text\">Laster ned … Klikk for å avbryte.</string>\n    <string name=\"github_issue\">GitHub-feilrapport</string>\n    <string name=\"github_issue_desc\">Send inn en feilrapport om problemer eller ønskede funksjoner</string>\n    <string name=\"info_copied\">Info kopiert til utklippstavle</string>\n    <string name=\"check_for_updates\">Se etter nye versjoner</string>\n    <string name=\"aria2_desc\">Bruk aria2c som ekstern nedlaster</string>\n    <string name=\"app_update_failed\">Klarte ikke å installere den nyeste versjonen</string>\n    <string name=\"update\">Installer</string>\n    <string name=\"template_exported\">Eksporterte %1$d mal(er)</string>\n    <string name=\"copy_link\">Kopier lenke</string>\n    <string name=\"video_file_size\">Videofilstørrelse</string>\n    <string name=\"export_to_clipboard\">Eksporter til utklippstavlen</string>\n    <string name=\"template_imported\">Importerte %1$d mal(er)</string>\n    <string name=\"multiselect_item_count\">%1$d video(er), %2$d lydfil(er)</string>\n    <string name=\"sponsorblock_desc\">Fjern segmenter fra videoer med SponsorBlock-API-et</string>\n    <string name=\"import_from_clipboard\">Importer fra utklippstavlen</string>\n    <string name=\"download_task_count\">%1$d nedlastede gjøremål</string>\n    <string name=\"app_up_to_date\">Du kjører nyeste versjon</string>\n    <string name=\"check_for_updates_desc\">Installer nyeste versjon fra GitHub</string>\n    <string name=\"clear_temp_files_count\">Slettet %1$d midlertidig(e) fil(er)</string>\n    <string name=\"clear_temp_files_info\">Midlertidige filer kan brukes til å gjenoppta avbrutte nedlastinger. Vil du fjerne alle disse filene\\?</string>\n    <string name=\"open_file\">Åpne fil</string>\n    <string name=\"restart\">Start på ny</string>\n    <string name=\"clear_temp_files\">Tøm midlertidige filer</string>\n    <string name=\"clear_temp_files_desc\">Slett alle midlertidige filer fra nedlastingsmappen</string>\n    <string name=\"cookies_desc\">Bruk Netscape-formaterte kaker for nedlastinger</string>\n    <string name=\"status_enqueued\">Kølagt</string>\n    <string name=\"status_completed\">Fullført</string>\n    <string name=\"status_downloading\">Laster ned</string>\n    <string name=\"status_canceled\">Avbrutt</string>\n    <string name=\"status_fetching_video_info\">Henter info …</string>\n    <string name=\"status_error\">Feil</string>\n    <string name=\"copy_error_report\">Feilrapport</string>\n    <string name=\"video_resolution\">Videooppløsning</string>\n    <string name=\"recently_added\">Nylig tillagt</string>\n    <string name=\"delete_multiple_items_msg\">Fjern %1$d element(er) fra nedlastingshistorikken din for godt\\?</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock-kategorier</string>\n    <string name=\"sponsorblock_categories_desc\">Angi SponsorBlock-kategorier å fjerne fra videofilen</string>\n    <string name=\"private_mode\">Privat modus</string>\n    <string name=\"dynamic_color\">Dynamisk farge</string>\n    <string name=\"private_mode_desc\">Skru av miniatyrbilde- og nedlastingshistorikk</string>\n    <string name=\"multiselect_mode\">Multivalgsmodus</string>\n    <string name=\"dynamic_color_desc\">Bruk farger fra bakgrunnsbilder i programdrakt</string>\n    <string name=\"high_contrast\">Mørk høykontrastdrakt</string>\n    <string name=\"network\">Nettverk</string>\n    <string name=\"download_disabled_with_cellular\">Nedlasting ved bruk av mobildata er avskrudd i programinnstillingene</string>\n    <string name=\"rate_limit_desc\">Begrens maksimal hastighet for nedlastinger</string>\n    <string name=\"rate_limit\">Øvre tak for overføringen</string>\n    <string name=\"max_rate\">Maksimal hastighet</string>\n    <string name=\"download_with_cellular_desc\">Tillat nedlasting av media når tilkoblet kvotebaserte nettverk</string>\n    <string name=\"file_unavailable\">Filen er ikke lenger tilgjengelig</string>\n    <string name=\"download_with_cellular\">Last ned med mobildata</string>\n    <string name=\"lowest_quality\">Laveste kvalitet</string>\n    <string name=\"invalid_input\">Ugyldig inndata</string>\n    <string name=\"unavailable\">Utilgjengelig</string>\n    <string name=\"format_settings_desc\">Filformat, videokvalitet, undertekster</string>\n    <string name=\"disable_preview\">Skru av forhåndsvisning</string>\n    <string name=\"private_directory\">Privat mappe</string>\n    <string name=\"privacy\">Personvern</string>\n    <string name=\"use_custom_command\">Bruk egendefinert kommando</string>\n    <string name=\"general_settings_desc\">Yt-dlp-versjon, merknad, spilleliste</string>\n    <string name=\"disable_preview_desc\">Skru av forhåndsvisning for nedlastinger</string>\n    <string name=\"private_directory_desc\">Lagre nedlastninger i en skjult mappe</string>\n    <string name=\"crop_artwork\">Beskjær illustrasjon</string>\n    <string name=\"crop_artwork_desc\">Beskjær innebygd bilde til kvadrat</string>\n    <string name=\"network_settings_desc\">Overføringsterskler, nedlaster, kaker</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-nl/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"convert_audio_format_desc\">Geluidsbestanden in MP3 of M4A werkt op de meeste apparaten</string>\n    <string name=\"video_quality\">Videokwaliteit</string>\n    <string name=\"best_quality\">Beste kwaliteit</string>\n    <string name=\"extract_audio\">Sla op als geluidsbestand</string>\n    <string name=\"create_thumbnail\">Sla voorvertoning op</string>\n    <string name=\"download_settings_desc\">Algemeen, bestandstype, aangepaste command</string>\n    <string name=\"download\">Download</string>\n    <string name=\"yt_dlp_update_fail\">Kon de nieuwste versie van yt-dlp niet installeren. Check of uw internetverbinding werkt.</string>\n    <string name=\"fetching_info\">Video info ophalen…</string>\n    <string name=\"permission_denied\">Toestemming geweigerd</string>\n    <string name=\"download_success_msg\">Download is klaar</string>\n    <string name=\"download_error_msg\">Downloaden van bestand is mislukt</string>\n    <string name=\"fetch_info_error_msg\">Ophalen video info is mislukt</string>\n    <string name=\"language\">Taal</string>\n    <string name=\"language_settings\">Stel een taal in</string>\n    <string name=\"task_running\">Een andere download is al bezig</string>\n    <string name=\"paste_msg\">Plak URL vanuit klembord</string>\n    <string name=\"paste_fail_msg\">Plakken URL vanuit klembord mislukt</string>\n    <string name=\"ytdlp_update\">Klik om de nieuwste versie van yt-dlp te installeren</string>\n    <string name=\"delete_info\">Verwijderen\\?</string>\n    <string name=\"delete_info_msg\">‘%1$s’ definitief uit uw downloadgeschiedenis verwijderen\\?</string>\n    <string name=\"confirm\">Bevestigen</string>\n    <string name=\"audio\">Geluidsbestand</string>\n    <string name=\"link_copied\">Link gekopieerd naar klembord</string>\n    <string name=\"remove\">Verwijderen</string>\n    <string name=\"delete_file\">Bestand wissen</string>\n    <string name=\"about\">Over</string>\n    <string name=\"release_desc\">Zoek naar wijzigingslogs en nieuwe versies</string>\n    <string name=\"release\">Nieuwste versie</string>\n    <string name=\"readme_desc\">Check de GitHub repository en de README</string>\n    <string name=\"video\">Video</string>\n    <string name=\"credits\">Credits</string>\n    <string name=\"credits_desc\">Credits en libre software</string>\n    <string name=\"custom_command_desc\">Voer yt-dlp command uit met een aangepaste sjabloon</string>\n    <string name=\"display\">Uiterlijk</string>\n    <string name=\"display_settings\">Donker thema, dynamische kleuren, talen</string>\n    <string name=\"dark_theme\">Donker thema</string>\n    <string name=\"print_details_desc\">Laat gedetailleerde berichten zien tijdens het downloaden</string>\n    <string name=\"cancel\">Annuleren</string>\n    <string name=\"settings_before_download\">Configureer vóór het downloaden</string>\n    <string name=\"settings_before_download_desc\">Configureer voorkeuren vóór het downloaden</string>\n    <string name=\"settings_before_download_text\">Pas deze download aan</string>\n    <string name=\"error_copied\">Foutrapport gekopieerd naar klembord</string>\n    <string name=\"paste\">Plakken</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp gebruiksreferenties</string>\n    <string name=\"edit_template_desc\">Uitvoerpad en URL zullen door de app worden toegevoegd.</string>\n    <string name=\"convert_audio_format\">Geluidsbestand converteren</string>\n    <string name=\"not_convert\">Niet converteren</string>\n    <string name=\"convert_to\">Converteren naar %1$s</string>\n    <string name=\"format\">Bestandstype</string>\n    <string name=\"video_quality_desc\">Beperk de videokwaliteit wanneer meerdere opties aanwezig zijn</string>\n    <string name=\"not_specified\">Niet gespecificeerd (standaard)</string>\n    <string name=\"video_format_preference\">Voorkeur type videobestand</string>\n    <string name=\"preferred_format_desc\">Voorkeur bestandstype bij meerdere opties</string>\n    <string name=\"video_format\">Type videobestand</string>\n    <string name=\"convert_audio\">Converteren</string>\n    <string name=\"start_download\">Downloaden</string>\n    <string name=\"open_settings\">Instellingen openen</string>\n    <string name=\"download_desc\">Klik daarna op ‘Downloaden’ na het aanpassen van de instellingen.</string>\n    <string name=\"download_history_desc\">Controleer en beheer in-app downloads, inclusief video\\'s en geluidsbestanden.</string>\n    <string name=\"download_playlist\">Afspeellijst downloaden</string>\n    <string name=\"channel_name\">Downloaden</string>\n    <string name=\"video_url\">Videolink</string>\n    <string name=\"battery_settings_desc\">Stel het batterijgebruik van deze app in op ‘Onbeperkt’ in de systeeminstellingen om op de achtergrond te kunnen downloaden.</string>\n    <string name=\"concurrent_download\">Meerdradige download</string>\n    <string name=\"options\">Opties</string>\n    <string name=\"additional_settings\">Extra instellingen</string>\n    <string name=\"share_fail_msg\">Delen van URL mislukt</string>\n    <string name=\"show_more_actions\">Meer acties weergeven</string>\n    <string name=\"fetching_playlist_info\">Afspeellijstinfo ophalen…</string>\n    <string name=\"download_range_selection\">Selectie afspeellijst</string>\n    <string name=\"from\">Begin</string>\n    <string name=\"invalid_index_range\">Ongeldige indexreeks</string>\n    <string name=\"audio_directory\">Audio map</string>\n    <string name=\"download_directory\">Map downloaden</string>\n    <string name=\"subdirectory\">Opslaan in subdirectory</string>\n    <string name=\"subdirectory_desc\">Sla bestanden op in mappen met de naam van de velden</string>\n    <string name=\"permission_issue\">Probleem met opslagmachtiging</string>\n    <string name=\"battery_configuration\">Batterijconfiguratie</string>\n    <string name=\"service_title\">Seal is bezig met downloaden…</string>\n    <string name=\"video_directory\">Video map</string>\n    <string name=\"settings\">Instellingen</string>\n    <string name=\"checked\">Gecheckt</string>\n    <string name=\"url_empty\">Dit vak moet ingevuld worden</string>\n    <string name=\"extract_audio_summary\">Download en sla geluidsbestand op, in plaats van videobestand</string>\n    <string name=\"download_start_msg\">Download ‘%1$s’</string>\n    <string name=\"create_thumbnail_summary\">Sla voorvertoning van video op als een bestand</string>\n    <string name=\"general_settings\">Algemeen</string>\n    <string name=\"dismiss\">Annuleren</string>\n    <string name=\"yt_dlp_up_to_date\">U gebruikt de nieuwste versie van yt-dlp</string>\n    <string name=\"downloads_history\">Downloads</string>\n    <string name=\"ytdlp_version\">Versie yt-dlp</string>\n    <string name=\"open_url\">Link openen</string>\n    <string name=\"back\">Terug</string>\n    <string name=\"about_page\">Versie, feedback, automatische updates</string>\n    <string name=\"version\">Versie</string>\n    <string name=\"custom_command\">Aangepaste command</string>\n    <string name=\"follow_system\">Systeem</string>\n    <string name=\"edit\">Bewerken</string>\n    <string name=\"off\">Uit</string>\n    <string name=\"custom_command_template\">Command sjabloon</string>\n    <string name=\"start_execute\">Start command uit te voeren</string>\n    <string name=\"print_details\">Gedetailleerde output</string>\n    <string name=\"on\">Aan</string>\n    <string name=\"advanced_settings\">Geavanceerd</string>\n    <string name=\"thumbnail\">Voorvertoning</string>\n    <string name=\"close_never_show_again\">Niet meer laten zien</string>\n    <string name=\"channel_description\">Gedownloade bestanden en voortgang melden</string>\n    <string name=\"download_finish_notification\">Download voltooid. Klik om te openen.</string>\n    <string name=\"concurrent_download_desc\">Meerdere delen van M3U8/MPD video\\'s tegelijk downloaden</string>\n    <string name=\"download_notification_desc\">Gedownloade bestanden en voortgang melden</string>\n    <string name=\"user_guide\">Gebruikershandleiding</string>\n    <string name=\"close\">Sluiten</string>\n    <string name=\"paste_desc\">Klik op ‘Plakken’ om de videolink uit uw klembord te halen.</string>\n    <string name=\"check_download_settings_desc\">Bekijk de downloadinstellingen en zorg ervoor dat u de nieuwste versie van yt-dlp hebt voordat u deze app gebruikt.</string>\n    <string name=\"download_playlist_desc\">Download meerdere video\\'s van een afspeellijst</string>\n    <string name=\"defaults\">Standaard</string>\n    <string name=\"execute_command_notification\">Aangepaste commands aan het uitvoeren…</string>\n    <string name=\"concurrent_download_num\">%d thread(s) worden gebruikt om DASH/HLS native video gelijktijdig te downloaden.</string>\n    <string name=\"share_success_msg\">Videolink aan het lezen vanuit gedeelde inhoud…</string>\n    <string name=\"download_notification\">Downloadnotificatie</string>\n    <string name=\"playlist_indicator_text\">Afspeellijst (%1$d/%2$d) aan het downloaden, klik om te stoppen.</string>\n    <string name=\"permission_issue_desc\">Mappen buiten Download/ en Documents/ worden niet ondersteund</string>\n    <string name=\"to\">Einde</string>\n    <string name=\"download_range_desc\">Geef de reeks video\\'s op die u wilt downloaden van de afspeellijst ‘%3$s’ (van %1$d tot %2$d).</string>\n    <string name=\"download_directory_desc\">Selecteer waar u video\\'s en geluidsbestanden wilt opslaan</string>\n    <string name=\"battery_configuration_desc\">Negeer batterijoptimalisatie voor deze app om op de achtergrond te kunnen downloaden</string>\n    <string name=\"unknown_error\">Onbekende fout</string>\n    <string name=\"translate\">Vertalen</string>\n    <string name=\"translate_desc\">Help deze app te vertalen op Hosted Weblate</string>\n    <string name=\"prefix\">Path template</string>\n    <string name=\"app_up_to_date\">De huidige versie is up-to-date</string>\n    <string name=\"template_selection\">Sjabloon selectie</string>\n    <string name=\"sponsorblock_desc\">Verwijder of markeer segmenten van videos met SponserBlock API</string>\n    <string name=\"update\">Update</string>\n    <string name=\"clear_temp_files\">Haal tijdelijke bestanden weg</string>\n    <string name=\"copy_error_report\">Foutrapport</string>\n    <string name=\"export_to_clipboard\">Exporteer naar klembord</string>\n    <string name=\"import_from_clipboard\">Importeer van klembord</string>\n    <string name=\"template_exported\">%1$d sjabloon(s) geëxporteerd</string>\n    <string name=\"template_imported\">%1$d sjabloon(s) geïmporteerd</string>\n    <string name=\"delete_multiple_items_msg\">Haal %1$d item(s) weg van uw downloadgeschiedenis voor altijd\\?</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock categorieën</string>\n    <string name=\"app_update_failed\">De update naar de laatste versie is gefaald</string>\n    <string name=\"aria2_desc\">Gebruik aria2c als de externe downloader</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"copy_link\">Kopieer link</string>\n    <string name=\"video_resolution\">Videoresolutie</string>\n    <string name=\"video_file_size\">Videobestand groote</string>\n    <string name=\"dynamic_color\">Dynamische kleur</string>\n    <string name=\"private_mode\">Incognito modus</string>\n    <string name=\"check_for_updates\">Controleer op updates</string>\n    <string name=\"download_task_count\">%1$d download taken</string>\n    <string name=\"recently_added\">Onlangs Toegevoegd</string>\n    <string name=\"multiselect_mode\">Multi-select modus</string>\n    <string name=\"clear_temp_files_info\">Tijdelijke bestanden kunnen gebruikt worden om geannuleerde downloads opnieuw laten te beginnen. Weet je zeker dat je all deze bestanden wilt verwijderen\\?</string>\n    <string name=\"private_mode_desc\">Zet downloadgeschiedenis uit</string>\n    <string name=\"new_template\">Nieuwe sjabloon</string>\n    <string name=\"template_label\">Label</string>\n    <string name=\"file_unavailable\">Dit bestand is niet meer beschikbaar</string>\n    <string name=\"multiselect_item_count\">%1$d video(s), %2$d audiobestand(en)</string>\n    <string name=\"remove_template\">Weghalen\\?</string>\n    <string name=\"status_error\">Fout</string>\n    <string name=\"custom_command_template_desc\">Wijzig en beheer de commando sjablonen</string>\n    <string name=\"downloading_indicator_text\">Download in werking…</string>\n    <string name=\"network\">Netwerk</string>\n    <string name=\"rate_limit\">Begrenzing</string>\n    <string name=\"embed_subtitles\">Sluit ondertitels in</string>\n    <string name=\"embed_subtitles_desc\">Verwerk voorziene ondertitels in video\\'s indien beschikbaar</string>\n    <string name=\"remove_template_desc\">Haal \\\"%1$s\\\" weg uit commando sjablonen voor altijd\\?</string>\n    <string name=\"sponsorblock_categories_desc\">Specificeer SponserBlock categorie om te verwijder of markeren van het videobestand</string>\n    <string name=\"download_with_cellular\">Download met mobiele data</string>\n    <string name=\"status_completed\">Voltooid</string>\n    <string name=\"restart\">Begin opnieuw</string>\n    <string name=\"status_enqueued\">In de wachtrij geplaatst</string>\n    <string name=\"cookies_desc\">Gebruik Netscape geformatteerde cookies voor downloads</string>\n    <string name=\"check_for_updates_desc\">Controleer voor de laatste versie up GitHub automatisch</string>\n    <string name=\"clear_temp_files_desc\">Verwijder alle tijdelijke bestanden van het interne map</string>\n    <string name=\"clear_temp_files_count\">%1$d tijdelijke bestand(en) verwijderd</string>\n    <string name=\"info_copied\">Info gekopieerd naar klembord</string>\n    <string name=\"task_canceled\">Download taak beïndigt</string>\n    <string name=\"github_issue_desc\">Dien een probleem in voor bug report of functie verzoek</string>\n    <string name=\"github_issue\">GitHub probleem</string>\n    <string name=\"ytdlp_update_action\">Update yt-dlp</string>\n    <string name=\"status_canceled\">Onderbroken</string>\n    <string name=\"status_fetching_video_info\">Informatie aan het ophalen</string>\n    <string name=\"open_file\">Bestand openen</string>\n    <string name=\"status_downloading\">Aan het downloaden</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-nn/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Videomappe</string>\n    <string name=\"extract_audio\">Gøym som ljod</string>\n    <string name=\"settings\">Innstillingar</string>\n    <string name=\"download_settings_desc\">Vanleg, format, eigne påbod</string>\n    <string name=\"download\">Hent</string>\n    <string name=\"url_empty\">Lenka kan ikkje vera tom</string>\n    <string name=\"permission_denied\">Løyve ikkje gjeve</string>\n    <string name=\"download_success_msg\">Henta</string>\n    <string name=\"download_error_msg\">Kunne ikkje hente fila</string>\n    <string name=\"general_settings\">Vanleg</string>\n    <string name=\"language\">Visingsmål</string>\n    <string name=\"language_settings\">Vel visingsmål</string>\n    <string name=\"paste_msg\">Limde inn ei lenke ifrå utklippstavla</string>\n    <string name=\"delete_info\">Tak bort\\?</string>\n    <string name=\"confirm\">Stadfest</string>\n    <string name=\"audio\">Ljod</string>\n    <string name=\"link_copied\">Lenka kopiert til utklippstavla</string>\n    <string name=\"open_url\">Opne lenka</string>\n    <string name=\"remove\">Tak bort</string>\n    <string name=\"delete_file\">Slett</string>\n    <string name=\"custom_command_desc\">Køyr yt-dlp påbod med eigne malar</string>\n    <string name=\"custom_command_template\">Påbodmal</string>\n    <string name=\"edit\">Brigde</string>\n    <string name=\"advanced_settings\">Avansert</string>\n    <string name=\"display\">Vising</string>\n    <string name=\"off\">Av</string>\n    <string name=\"error_copied\">Mistakrapport kopiert til utklippstavla</string>\n    <string name=\"thumbnail\">småbilete</string>\n    <string name=\"paste\">Lim inn</string>\n    <string name=\"yt_dlp_docs\">Tilråding for bruk av yt-dlp</string>\n    <string name=\"format\">Format</string>\n    <string name=\"convert_audio_format_desc\">Omlaging av ljodfiler fører til tap av ljodkvalitet og auking av filstorleik.</string>\n    <string name=\"video_quality\">Oppløysing</string>\n    <string name=\"best_quality\">Høgst mogleg (forval)</string>\n    <string name=\"video_quality_desc\">Avgrens oppløysinga til videoar</string>\n    <string name=\"not_specified\">Ikkje oppgjeve (forval)</string>\n    <string name=\"video_format_preference\">Ynskt videoformat</string>\n    <string name=\"preferred_format_desc\">Valt format når fleire vert tilbodne</string>\n    <string name=\"extract_audio_summary\">Hent og gøym ljod i staden for video</string>\n    <string name=\"fetching_info\">Hentar videoopplysingar…</string>\n    <string name=\"download_start_msg\">Hent «%1$s»</string>\n    <string name=\"fetch_info_error_msg\">Kunne ikkje hente videoopplysingar</string>\n    <string name=\"task_running\">Ei henteføreloge finst og køyrar alt</string>\n    <string name=\"dismiss\">Avbryt</string>\n    <string name=\"delete_info_msg\">Tak bort «%1$s» ifrå hentingshistorikken din for godt\\?</string>\n    <string name=\"downloads_history\">Hentingar</string>\n    <string name=\"custom_command\">Eigne påbod</string>\n    <string name=\"about\">Om</string>\n    <string name=\"back\">Attende</string>\n    <string name=\"video\">Video</string>\n    <string name=\"start_execute\">Utfør påbodet</string>\n    <string name=\"cancel\">Avbryt</string>\n    <string name=\"follow_system\">System</string>\n    <string name=\"on\">På</string>\n    <string name=\"edit_template_desc\">Utdatasti og nettadresse vert lagt til av appen.</string>\n    <string name=\"video_format\">Videoformat</string>\n    <string name=\"start_download\">Hent</string>\n    <string name=\"convert_audio\">Lag om</string>\n    <string name=\"close\">Lat att</string>\n    <string name=\"close_never_show_again\">Ikkje vis att</string>\n    <string name=\"open_settings\">Opne innstillingane</string>\n    <string name=\"create_thumbnail\">Gøym småbilete</string>\n    <string name=\"create_thumbnail_summary\">Gøym videosmåbilete som ei fil</string>\n    <string name=\"yt_dlp_update_fail\">Kunne ikkje leggja inn den nyaste yt-dlp-utgåva. Syrg for at du har samanbinding til Internet.</string>\n    <string name=\"additional_settings\">Fleire innstillingar</string>\n    <string name=\"share_success_msg\">Les videolenka ifrå delt innhald…</string>\n    <string name=\"show_more_actions\">Vis fleire gjerder</string>\n    <string name=\"download_notification\">Hentingsmerknad</string>\n    <string name=\"download_range_selection\">Spelelisteutval</string>\n    <string name=\"download_range_desc\">Oppgje området av videoar som skal verta henta ifrå «%3$s»-spelelista (ifrå %1$d til %2$d).</string>\n    <string name=\"to\">End</string>\n    <string name=\"audio_directory\">Ljodmappe</string>\n    <string name=\"download_directory_desc\">Vel kvar du vil gøyma video- og ljodfiler</string>\n    <string name=\"subdirectory\">Gøym i undermappe</string>\n    <string name=\"subdirectory_desc\">Gøym filer i mapper kalla opp etter nettstadane filene kjem ifrå</string>\n    <string name=\"permission_issue\">Problem med gøymetilgjenget</string>\n    <string name=\"battery_configuration\">Batteri-innstilling</string>\n    <string name=\"battery_configuration_desc\">Hopp over batteriforlenging for denne appen, slik at han kan hente ting i bakgrunnen</string>\n    <string name=\"service_title\">Seal hentar…</string>\n    <string name=\"unknown_error\">Ukjent mistak</string>\n    <string name=\"translate\">Omsett</string>\n    <string name=\"translate_desc\">Hjelp til med å omsetja denne appen hos Hosted Weblate</string>\n    <string name=\"prefix\">Stigmal</string>\n    <string name=\"embed_subtitles\">Bygg inn teksting</string>\n    <string name=\"embed_subtitles_desc\">Om tilgjengelege, bygg gjevne undertekster inn i videoar</string>\n    <string name=\"template_label\">Malnamn</string>\n    <string name=\"remove_template\">Tak bort\\?</string>\n    <string name=\"template_selection\">Malval</string>\n    <string name=\"custom_command_template_desc\">Brigd og handsam påbodmalar</string>\n    <string name=\"task_canceled\">Hentingsføreloga avbroten</string>\n    <string name=\"github_issue\">Github-mistakrapport</string>\n    <string name=\"info_copied\">Opplysingar kopiert til utklippstavla</string>\n    <string name=\"status_enqueued\">Lagt til i venterekkja</string>\n    <string name=\"status_completed\">Utført</string>\n    <string name=\"status_downloading\">Hentar</string>\n    <string name=\"status_canceled\">Avbroten</string>\n    <string name=\"status_fetching_video_info\">Hentar opplysingar</string>\n    <string name=\"video_resolution\">Videooppløysing</string>\n    <string name=\"template_imported\">Innførte %1$d mal(ar)</string>\n    <string name=\"download_task_count\">%1$d henta føreloger</string>\n    <string name=\"multiselect_item_count\">%1$d video(ar), %2$d ljodfil(er)</string>\n    <string name=\"delete_multiple_items_msg\">Tak bort %1$d ting ifrå hentingshistorikken din for godt\\?</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock-slag</string>\n    <string name=\"cookies_desc\">Bruk informasjonskapslar i Netscape-formatet for hentingar</string>\n    <string name=\"clear_temp_files\">Tøm mellombels filer</string>\n    <string name=\"clear_temp_files_count\">Sletta %1$d mellombels fil(er)</string>\n    <string name=\"multiselect_mode\">Fleirvalmodus</string>\n    <string name=\"private_mode\">Privat modus</string>\n    <string name=\"permission_issue_desc\">Mapper utanfor Download/ og Documents/ er ikkje stødde</string>\n    <string name=\"download_notification_desc\">Gje merknad om henta filer og framdrift</string>\n    <string name=\"fetching_playlist_info\">Hentar spelelisteopplysingar…</string>\n    <string name=\"from\">Byrja</string>\n    <string name=\"playlist_indicator_text\">Hentar spelelista (%1$d/%2$d), trykk for å stogga.</string>\n    <string name=\"download_directory\">Hentingsmappe</string>\n    <string name=\"new_template\">Ny mal</string>\n    <string name=\"remove_template_desc\">Tak bort «%1$s» ifrå påbodmalane for godt\\?</string>\n    <string name=\"downloading_indicator_text\">Hentar, trykk for å avbryta.</string>\n    <string name=\"status_error\">Mistak</string>\n    <string name=\"restart\">Byrja om att</string>\n    <string name=\"open_file\">Opne fila</string>\n    <string name=\"copy_link\">Kopier lenka</string>\n    <string name=\"copy_error_report\">Mistakrapport</string>\n    <string name=\"video_file_size\">Videofilstorleik</string>\n    <string name=\"export_to_clipboard\">Utfør til utklippstavla</string>\n    <string name=\"import_from_clipboard\">Innfør ifrå utklippstavla</string>\n    <string name=\"template_exported\">Utførte %1$d mal(ar)</string>\n    <string name=\"recently_added\">Nyleg lagt til</string>\n    <string name=\"sponsorblock_categories_desc\">Oppgjev kva slags SponsorBlock-slag som skal verte tekne bort ifrå videofila</string>\n    <string name=\"aria2_desc\">Bruk aria2c som den ytre hentaren</string>\n    <string name=\"clear_temp_files_desc\">Slett alle mellombels filer ifrå hentingsmappa</string>\n    <string name=\"clear_temp_files_info\">Mellombels filer kan verta nytta til å halde fram med avbrotne hentingar. Er du trygg på at du vil slette alle desse filene\\?</string>\n    <string name=\"private_mode_desc\">Slå av hentingshistorikk</string>\n    <string name=\"download_with_cellular\">Hent med mobildata</string>\n    <string name=\"file_unavailable\">Fila er ikkje lenger tilgjengeleg</string>\n    <string name=\"network\">Nettverk</string>\n    <string name=\"unavailable\">Ikkje tilgjengeleg</string>\n    <string name=\"disable_preview\">Slå av førehandsvising</string>\n    <string name=\"privacy\">Personvern</string>\n    <string name=\"download_disabled_with_cellular\">Henting på mobildata er slått av ifylgje dine innstillingar</string>\n    <string name=\"lowest_quality\">Lægst mogleg</string>\n    <string name=\"disable_preview_desc\">Slå av førehandsvising på hentingar</string>\n    <string name=\"format_settings_desc\">Filformat, videokvalitet, teksting</string>\n    <string name=\"display_settings\">Mørk vising, skiftande létar, mål</string>\n    <string name=\"dark_theme\">Mørk vising</string>\n    <string name=\"private_directory\">Privat mappe</string>\n    <string name=\"private_directory_desc\">Gøym hentingar i ein skjult mappe</string>\n    <string name=\"crop_artwork\">Kutt kunstverk</string>\n    <string name=\"crop_artwork_desc\">Skjer innbygt bilete til eit kvadrat</string>\n    <string name=\"download_selection_desc\">Vel videoar som skal verta henta ifrå spelelista «%1$s»</string>\n    <string name=\"select_all\">Vel alle/alt</string>\n    <string name=\"selected_item_count\">%1$d vald(e)</string>\n    <string name=\"use_custom_command\">Bruk eigne påbod</string>\n    <string name=\"yt_dlp_up_to_date\">Nyttar nyaste utgåve av yt-dlp</string>\n    <string name=\"paste_fail_msg\">Kunne ikkje jamføra med nettadressa i utklippstavla</string>\n    <string name=\"ytdlp_version\">Yt-dlp-utgåve</string>\n    <string name=\"ytdlp_update\">Trykk for å leggja inn den nyaste utgåva av yt-dlp</string>\n    <string name=\"version\">Utgåve</string>\n    <string name=\"release\">Nyaste utgåve</string>\n    <string name=\"readme_desc\">Gransk GitHub-kodegøymet og LESMEG-fila</string>\n    <string name=\"checked\">Granska</string>\n    <string name=\"settings_before_download\">Sett opp før henting</string>\n    <string name=\"settings_before_download_desc\">Sett opp innstillingar før henting</string>\n    <string name=\"convert_audio_format\">Lag om ljodformatet</string>\n    <string name=\"not_convert\">Ikkje omlaga</string>\n    <string name=\"convert_to\">Lag om til %1$s</string>\n    <string name=\"user_guide\">Brukarrettleiing</string>\n    <string name=\"paste_desc\">Trykk på «Lim inn» for å hente videolenka ifrå utklippstavla di.</string>\n    <string name=\"check_download_settings_desc\">Tak og so sjå på hentingsinnstillingane og syrg for at du har den nyaste utgåva av yt-dlp før du nyttar han.</string>\n    <string name=\"download_playlist\">Hent speleliste</string>\n    <string name=\"download_playlist_desc\">Hent fleire videoar ifrå ei speleliste</string>\n    <string name=\"defaults\">Føreval</string>\n    <string name=\"channel_name\">Hent</string>\n    <string name=\"channel_description\">Varsle om henta filer og framdrift</string>\n    <string name=\"video_url\">Videolenke</string>\n    <string name=\"about_page\">Utgåve, tilbakemelding, sjølvoppdater</string>\n    <string name=\"release_desc\">Sjå etter brigdelister og nye utgåver</string>\n    <string name=\"download_history_desc\">Gransk og handsam hentingar i appen, gjeld au videoar og ljodfiler.</string>\n    <string name=\"download_finish_notification\">Henta. Trykk for å opne.</string>\n    <string name=\"execute_command_notification\">Køyrer eigne påbod…</string>\n    <string name=\"check_for_updates_desc\">Lat appen sjå etter den nyaste utgåva på GitHub av seg sjølv</string>\n    <string name=\"app_up_to_date\">Denne utgåva er nyast</string>\n    <string name=\"update\">Legg inn den nyaste utgåva</string>\n    <string name=\"dynamic_color\">Skiftande letar</string>\n    <string name=\"dynamic_color_desc\">Nytta letar ifrå bakgrunnsbilete i appvisinga</string>\n    <string name=\"app_update_failed\">Kunne ikkje leggja inn den nyaste utgåva</string>\n    <string name=\"credits\">Takk til</string>\n    <string name=\"credits_desc\">Hjelpeytarar og fri programvare</string>\n    <string name=\"concurrent_download\">Trådar i bruk ved henting</string>\n    <string name=\"concurrent_download_num\">%d tråd(ar) vil verte nytta til å hente DASH/HLS-innebygd video samstundes.</string>\n    <string name=\"options\">Val</string>\n    <string name=\"github_issue_desc\">Send inn ein mistakrapport om problem eller ynskte funksjonar</string>\n    <string name=\"general_settings_desc\">Yt-dlp-utgåve, merknad, speleliste</string>\n    <string name=\"concurrent_download_desc\">Hent fleire delar av M3U8/MPD-videoar samstundes</string>\n    <string name=\"invalid_index_range\">Ugildt indeksområde</string>\n    <string name=\"video_only\">Video (ingen ljod)</string>\n    <string name=\"suggested\">Tilrådd</string>\n    <string name=\"format_selection_desc\">Vis formatval før ei henting byrjar</string>\n    <string name=\"format_selection\">Formatval</string>\n    <string name=\"print_details\">Detaljert utdata</string>\n    <string name=\"print_details_desc\">Skriv ut detaljerte opplysingar ved henting</string>\n    <string name=\"battery_settings_desc\">Om du vil hente i bakgrunnen, sett denne appens batteribruk til «uavgrensa» i systeminnstillingane.</string>\n    <string name=\"sponsorblock_desc\">Tak bort stødde delar ifrå videoar med SponsorBlocks API</string>\n    <string name=\"check_for_updates\">Sjå etter oppdateringar</string>\n    <string name=\"high_contrast\">Svart vising</string>\n    <string name=\"use_cookies\">Bruk infokapslar</string>\n    <string name=\"remove_cookie_profile_desc\">Tak bort infokapslar for «%1$s»?</string>\n    <string name=\"custom_command_enabled_hint\">Nokre val er utilgjengelege når « bruk eigne påbod» er slegen på</string>\n    <string name=\"how_does_it_work\">Korleis verkar det\\?</string>\n    <string name=\"cookies_usage_msg\">Henting ifrå somme nettstadar krev kontostadfestingsopplysingar. Trykk på «lag nye infokapslar», skriv inn nettadressa til nettstaden, og logg deg so inn i nettlesersida som appen fører deg til.</string>\n    <string name=\"telegram_channel\">Telegram-sambandsline</string>\n    <string name=\"generate_new_cookies\">Lag nye informasjonskapslar</string>\n    <string name=\"download_with_cellular_desc\">Gje løyve til henting av media når sambunden til forbruksmålte nettverk</string>\n    <string name=\"settings_before_download_text\">Still inn denne hentinga</string>\n    <string name=\"download_desc\">Trykk so på «hent» etter å ha stilt inn innstillingane.</string>\n    <string name=\"share_fail_msg\">Kunne ikkje samsvare nettadresse ifrå delt innhald</string>\n    <string name=\"cookies\">Informasjonskapslar</string>\n    <string name=\"invalid_input\">Ugild innmating</string>\n    <string name=\"rate_limit_desc\">Set ei grense for kvar kjapt hentingar kan gå</string>\n    <string name=\"matrix_space\">Matriserom</string>\n    <string name=\"rate_limit\">Rateavgrensing</string>\n    <string name=\"max_rate\">Øvre rategrense</string>\n    <string name=\"network_settings_desc\">Rategrense, hentar, infokapslar</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"subtitle_sponsorblock\">Ved borttaking av SponsorBlock-delar vert kan henda tekstingar ikkje tidfeste rett.</string>\n    <string name=\"share\">Del</string>\n    <string name=\"stable_channel\">Stødug</string>\n    <string name=\"pre_release_channel\">Førehandsvising</string>\n    <string name=\"logs\">Logg</string>\n    <string name=\"subtitle_language\">Tekstingsmål</string>\n    <string name=\"subtitle_desc\">Mål, bygg inn teksting, direkteteksting</string>\n    <string name=\"copy_log\">Kopier loggen</string>\n    <string name=\"title_activity_share\">Kvik henting</string>\n    <string name=\"clear\">Tøm</string>\n    <string name=\"add\">Legg til</string>\n    <string name=\"sdcard_directory\">Mappa til ytre gøyme</string>\n    <string name=\"video_title_sample_text\">Videonamn</string>\n    <string name=\"video_creator_sample_text\">Videoskapar</string>\n    <string name=\"subtitle\">Teksting</string>\n    <string name=\"download_subtitles\">Hent tekstingar</string>\n    <string name=\"running_tasks\">Køyrande føreloger</string>\n    <string name=\"show_logs\">Vis loggen</string>\n    <string name=\"embed_subtitles_mkv_msg\">Videoar vert satt inn i mkv-kar når tekstingar vert bygde inn.</string>\n    <string name=\"clip_start\">Byrjing</string>\n    <string name=\"clip_end\">Ende</string>\n    <string name=\"clip_video\">Klipp video</string>\n    <string name=\"abs_hint\">Dei fleste videostraumingsplattformer sender åtskilde ljodar og videoar. Vel eit ljodformat og eit videoformat utan ljod for å slå dei saman til ei videofil.</string>\n    <string name=\"edit_shortcuts\">Brigd snarpåbod</string>\n    <string name=\"shortcuts\">Snarpåbod</string>\n    <string name=\"edit_shortcuts_desc\">Brigd snare påbod. Desse kan du nytte når du ritar påbodmalar.</string>\n    <string name=\"unlimited\">Uavgrensa</string>\n    <string name=\"lowest_bitrate\">Lægst bitrate</string>\n    <string name=\"audio_quality\">Ljodkvalitet</string>\n    <string name=\"audio_quality_desc\">Avgrens ljodkvaliteten</string>\n    <string name=\"title\">Namn</string>\n    <string name=\"rename\">Byt namn</string>\n    <string name=\"import_from_preferences\">Før inn</string>\n    <string name=\"second\">Sekund</string>\n    <string name=\"audio_format\">Ljodformat</string>\n    <string name=\"no_downloaded_media\">Det som har vorte henta vert vist her</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Slå på røynd funksjon\\?</string>\n    <string name=\"msg_from_developer\">Melding ifrå utviklaren</string>\n    <string name=\"sponsor_msg2\">Mange takk!</string>\n    <string name=\"auto_update_disabled_msg\">Sjølvoppdatering er ikkje tilgjengeleg for %1$s-utgåver. Om du ikkje har %1$s lagt inn på eininga di, eller vil røyna komande funksjonar, tak ein titt på %2$s.</string>\n    <string name=\"switch_to_github_builds\">bytt til GitHub-utgåver</string>\n    <string name=\"okay\">Greitt</string>\n    <string name=\"got_it\">Skjønar</string>\n    <string name=\"feature_unavailable\">Funksjonen er ikkje tilgjengeleg</string>\n    <string name=\"sponsor_msg\">Seal vil for alltid vera kostnadsfri og ha ein open kjeldekode. Om du vil kan du stø meg på GitHub.</string>\n    <string name=\"auto_update\">Sjølvoppdater</string>\n    <string name=\"enable_auto_update\">Slå på sjølvoppdatering</string>\n    <string name=\"audio_format_preference\">Ynkst ljodformat</string>\n    <string name=\"minute\">Minutt</string>\n    <string name=\"clear_all_cookies\">Tøm alle infokapslar</string>\n    <string name=\"clear_all_cookies_desc\">Slett alle infokapslane gøymde i appen\\?</string>\n    <string name=\"sponsor\">Stø</string>\n    <string name=\"sponsor_desc\">Stø appen ved å gje pengar gjennom GitHub</string>\n    <string name=\"feedback\">Tilbakemelding</string>\n    <string name=\"sponsors\">Støarar</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-or/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"version\">ସଂସ୍କରଣ</string>\n    <string name=\"credits\">ଶ୍ରେୟ</string>\n    <string name=\"follow_system\">ସିଷ୍ଟମ୍</string>\n    <string name=\"on\">ଚାଲୁ</string>\n    <string name=\"defaults\">ଡିଫଲ୍ଟ</string>\n    <string name=\"settings\">ସେଟିଂ</string>\n    <string name=\"audio\">ଅଡ଼ିଓ</string>\n    <string name=\"about\">ସମ୍ବନ୍ଧରେ</string>\n    <string name=\"general_settings\">ସାଧାରଣ</string>\n    <string name=\"advanced_settings\">ଵିକଶିତ</string>\n    <string name=\"video\">ଵିଡ଼ିଓ</string>\n    <string name=\"edit\">ସମ୍ପାଦନା</string>\n    <string name=\"display\">ପ୍ରଦର୍ଶନ</string>\n    <string name=\"off\">ବନ୍ଦ</string>\n    <string name=\"options\">ଵିକଳ୍ପ</string>\n    <string name=\"translate\">ଅନୁଵାଦ କରନ୍ତୁ</string>\n    <string name=\"status_error\">ତ୍ରୁଟି</string>\n    <string name=\"private_mode\">ଅପରିଚିତ ମୋଡ୍</string>\n    <string name=\"download_error_msg\">ଫାଇଲ୍ ଡାଉନଲୋଡ୍ କରିହେଲା ନାହିଁ</string>\n    <string name=\"extract_audio\">ଅଡିଓ ଭାବରେ ସେଭ୍ କରନ୍ତୁ</string>\n    <string name=\"download\">ଡାଉନଲୋଡ୍</string>\n    <string name=\"url_empty\">ଲିଙ୍କ ଖାଲି ରହିପାରିବ ନାହିଁ</string>\n    <string name=\"extract_audio_summary\">ଭିଡିଓର ଅପେକ୍ଷା ଧ୍ୱନିକୁ ଡାଉନଲୋଡ୍ ଓ ସଞ୍ଚୟ କରନ୍ତୁ</string>\n    <string name=\"create_thumbnail_summary\">ଭିଡିଓର ଥମ୍ନେଲ୍‌କୁ ଏକ ଫାଇଲ୍ ଭାବରେ ସଞ୍ଚୟ କରନ୍ତୁ</string>\n    <string name=\"yt_dlp_up_to_date\">ନୂତନ ସଂସ୍କରଣର yt-dlp ବ୍ୟବହାର କରନ୍ତୁ</string>\n    <string name=\"fetching_info\">ଭିଡିଓ ସୂଚନା ଆହରଣ କରାଯାଉଛି…</string>\n    <string name=\"fetch_info_error_msg\">ଭିଡିଓ ସୂଚନା ଆହରଣ କରିପାରିଲା ନାହିଁ</string>\n    <string name=\"language\">ଭାଷା ଦେଖାନ୍ତୁ</string>\n    <string name=\"permission_denied\">ଅନୁମତି ଅସ୍ବୀକୃତ</string>\n    <string name=\"download_success_msg\">ଡାଉନଲୋଡ୍ ସମ୍ପୂର୍ଣ୍ଣ ହେଲା</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-pa/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">ਵੀਡੀਓ ਫੋਲਡਰ</string>\n    <string name=\"extract_audio\">ਆਡੀਓ ਦੇ ਰੂਪ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕਰੋ</string>\n    <string name=\"create_thumbnail\">ਥੰਮਨੇਲ ਸੁਰੱਖਿਅਤ ਕਰੋ</string>\n    <string name=\"settings\">ਸੈਟਿੰਗਾਂ</string>\n    <string name=\"download\">ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"convert_audio_format_desc\">ਆਡੀਓ ਫਾਈਲਾਂ ਨੂੰ ਮੁੜ-ਇਨਕੋਡਿੰਗ ਕਰਨ ਨਾਲ ਆਡੀਓ ਗੁਣਵੱਤਾ ਵਿੱਚ ਕਮੀ ਆਵੇਗੀ ਅਤੇ ਫਾਈਲ ਦੇ ਆਕਾਰ ਵਿੱਚ ਵਾਧਾ ਹੋਵੇਗਾ।</string>\n    <string name=\"custom_command_desc\">ਕਸਟਮ ਟੈਮਪਲੇਟ ਨਾਲ yt-dlp ਕਮਾਂਡ ਚਲਾਓ</string>\n    <string name=\"print_details\">ਵਿਸਤ੍ਰਿਤ ਆਉਟਪੁੱਟ</string>\n    <string name=\"print_details_desc\">ਡਾਊਨਲੋਡ ਕਰਨ ਵੇਲੇ ਵਿਸਤ੍ਰਿਤ ਸੁਨੇਹੇ ਪ੍ਰਿੰਟ ਕਰੋ</string>\n    <string name=\"settings_before_download\">ਡਾਊਨਲੋਡ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਸੰਰਚਨਾ ਕਰੋ</string>\n    <string name=\"settings_before_download_text\">ਇਸ ਡਾਊਨਲੋਡ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ</string>\n    <string name=\"video_quality\">ਵੀਡੀਓ ਗੁਣਵੱਤਾ</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp ਵਰਤੋਂ ਦੇ ਹਵਾਲੇ</string>\n    <string name=\"download_settings_desc\">ਜਨਰਲ, ਫਾਰਮੈਟ, ਕਸਟਮ ਕਮਾਂਡ</string>\n    <string name=\"url_empty\">ਲਿੰਕ ਖਾਲੀ ਨਹੀਂ ਹੋ ਸਕਦਾ</string>\n    <string name=\"extract_audio_summary\">ਵੀਡੀਓ ਦੀ ਬਜਾਏ ਆਡੀਓ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰੋ \\'ਤੇ ਸਹੇਜੋ</string>\n    <string name=\"create_thumbnail_summary\">ਵੀਡੀਓ ਥੰਮਨੇਲ ਨੂੰ ਇੱਕ ਫਾਈਲ ਵਜੋਂ ਸਹੇਜੋ</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp ਦੇ ਨਵੀਨਤਮ ਸੰਸਕਰਣ ਦੀ ਵਰਤੋਂ ਕਰ ਰਿਹਾ</string>\n    <string name=\"yt_dlp_update_fail\">ਨਵੀਨਤਮ yt-dlp ਵਰਜਨ ਨੂੰ ਸਥਾਪਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਸੀਂ ਇੰਟਰਨੈੱਟ ਨਾਲ ਕਨੈਕਟ ਹੋ।</string>\n    <string name=\"fetching_info\">ਵੀਡੀਓ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…</string>\n    <string name=\"permission_denied\">ਆਗਿਆ ਤੋਂ ਇਨਕਾਰ</string>\n    <string name=\"download_success_msg\">ਡਾਊਨਲੋਡ ਪੂਰਾ ਹੋਇਆ</string>\n    <string name=\"download_error_msg\">ਫ਼ਾਈਲ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" ਨੂੰ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"fetch_info_error_msg\">ਵੀਡੀਓ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ</string>\n    <string name=\"general_settings\">ਜਨਰਲ</string>\n    <string name=\"language\">ਡਿਸਪਲੇ ਭਾਸ਼ਾ</string>\n    <string name=\"language_settings\">ਡਿਸਪਲੇ ਭਾਸ਼ਾ ਸੈੱਟ ਕਰੋ</string>\n    <string name=\"task_running\">ਇੱਕ ਮੌਜੂਦਾ ਡਾਊਨਲੋਡ ਕਾਰਜ ਪਹਿਲਾਂ ਹੀ ਚੱਲ ਰਿਹਾ ਹੈ</string>\n    <string name=\"paste_msg\">URL ਪੇਸਟ ਕਰੋ</string>\n    <string name=\"paste_fail_msg\">ਕਲਿੱਪਬੋਰਡ ਵਿੱਚ URL ਨਾਲ ਮੇਲ ਨਹੀਂ ਹੋ ਸਕਿਆ</string>\n    <string name=\"ytdlp_version\">Yt-dlp ਵਰਜਨ</string>\n    <string name=\"ytdlp_update\">ਨਵੀਨਤਮ yt-dlp ਵਰਜਨ ਨੂੰ ਸਥਾਪਤ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ</string>\n    <string name=\"delete_info\">ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"delete_info_msg\">ਕੀ ਤੁਹਾਡੇ ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਵਿੱਚੋਂ \\\"%1$s\\\" ਨੂੰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"confirm\">ਪੁਸ਼ਟੀ ਕਰੋ</string>\n    <string name=\"dismiss\">ਰੱਦ ਕਰੋ</string>\n    <string name=\"downloads_history\">ਡਾਊਨਲੋਡਸ</string>\n    <string name=\"audio\">ਆਡੀਓ</string>\n    <string name=\"link_copied\">ਲਿੰਕ ਕਲਿੱਪਬੋਰਡ \\'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ</string>\n    <string name=\"open_url\">ਲਿੰਕ ਖੋਲ੍ਹੋ</string>\n    <string name=\"remove\">ਹਟਾਓ</string>\n    <string name=\"delete_file\">ਫ਼ਾਈਲ ਮਿਟਾਓ</string>\n    <string name=\"about\">ਦੇ ਬਾਰੇ</string>\n    <string name=\"about_page\">ਸੰਸਕਰਣ, ਸੁਝਾਅ, ਆਟੋ-ਅੱਪਡੇਟ</string>\n    <string name=\"back\">ਵਾਪਸ</string>\n    <string name=\"version\">ਸੰਸਕਰਣ</string>\n    <string name=\"release_desc\">ਚੇਂਜਲੌਗ ਅਤੇ ਨਵੇਂ ਸੰਸਕਰਣਾਂ ਦੀ ਭਾਲ ਕਰੋ</string>\n    <string name=\"release\">ਤਾਜ਼ਾ ਰਿਲੀਜ਼</string>\n    <string name=\"readme_desc\">ਗਿਟਹੱਬ ਰਿਪੋਜ਼ਟਰੀ ਅਤੇ ਮੈਨੂੰ ਪੜ੍ਹੋ ਚੈੱਕ ਕਰੋ</string>\n    <string name=\"video\">ਵੀਡੀਓ</string>\n    <string name=\"checked\">ਚੈੱਕ ਕੀਤੀ</string>\n    <string name=\"credits\">ਕ੍ਰੈਡਿਟ</string>\n    <string name=\"credits_desc\">ਕ੍ਰੈਡਿਟ ਅਤੇ ਮੁਫ਼ਤ ਸੌਫਟਵੇਅਰ</string>\n    <string name=\"custom_command\">ਕਸਟਮ ਕਮਾਂਡ</string>\n    <string name=\"custom_command_template\">ਕਮਾਂਡ ਟੈਮਪਲੇਟ</string>\n    <string name=\"edit\">ਸੰਪਾਦਿਤ ਕਰੋ</string>\n    <string name=\"start_execute\">ਕਮਾਂਡ ਚਲਾਉਣੀ ਸ਼ੁਰੂ ਕਰੋ</string>\n    <string name=\"advanced_settings\">ਐਡਵਾਂਸਡ</string>\n    <string name=\"display\">ਡਿਸਪਲੇ</string>\n    <string name=\"display_settings\">ਗੂੜ੍ਹਾ ਥੀਮ, ਗਤੀਸ਼ੀਲ ਰੰਗ, ਭਾਸ਼ਾਵਾਂ</string>\n    <string name=\"dark_theme\">ਗੂੜ੍ਹਾ ਥੀਮ</string>\n    <string name=\"follow_system\">ਸਿਸਟਮ</string>\n    <string name=\"off\">ਬੰਦ</string>\n    <string name=\"on\">ਚਾਲੂ</string>\n    <string name=\"cancel\">ਰੱਦ</string>\n    <string name=\"settings_before_download_desc\">ਡਾਊਨਲੋਡ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਤਰਜੀਹਾਂ ਦੀ ਸੰਰਚਨਾ ਕਰੋ</string>\n    <string name=\"error_copied\">ਤਰੁੱਟੀ ਰਿਪੋਰਟ ਕਲਿੱਪਬੋਰਡ \\'ਤੇ ਕਾਪੀ ਕੀਤੀ ਗਈ</string>\n    <string name=\"thumbnail\">ਥੰਮਨੇਲ</string>\n    <string name=\"edit_template_desc\">ਆਉਟਪੁੱਟ ਮਾਰਗ ਅਤੇ URL ਐਪ ਦੁਆਰਾ ਜੋੜਿਆ ਜਾਵੇਗਾ।</string>\n    <string name=\"convert_audio_format\">ਆਡੀਓ ਫਾਰਮੈਟ ਵਿੱਚ ਬਦਲੋ</string>\n    <string name=\"not_convert\">ਅਣਬਦਲਿਆ</string>\n    <string name=\"convert_to\">%1$s ਵਿੱਚ ਬਦਲੋ</string>\n    <string name=\"format\">ਫਾਰਮੈਟ</string>\n    <string name=\"paste\">ਪੇਸਟ ਕਰੋ</string>\n    <string name=\"best_quality\">ਉੱਤਮ ਕੁਆਲਿਟੀ</string>\n    <string name=\"video_quality_desc\">ਕਈ ਕੁਆਲਿਟੀਆਂ ਮੌਜੂਦ ਹੋਣ \\'ਤੇ ਵੀਡੀਓ ਕੁਆਲਿਟੀ ਨੂੰ ਸੀਮਤ ਕਰੋ</string>\n    <string name=\"not_specified\">ਅਣਨਿਰਦੇਸ਼ਤ (ਡਿਫ਼ਾਲਟ)</string>\n    <string name=\"video_format_preference\">ਪਸੰਦੀਦਾ ਵੀਡੀਓ ਫਾਰਮੈਟ</string>\n    <string name=\"preferred_format_desc\">ਤਰਜੀਹੀ ਫਾਰਮੈਟ ਜਦੋਂ ਇੱਕ ਤੋਂ ਵਧੇਰੇ ਪ੍ਰਦਾਨ ਕੀਤੇ ਜਾਂਦੇ ਹਨ</string>\n    <string name=\"video_format\">ਵੀਡੀਓ ਫਾਰਮੈਟ</string>\n    <string name=\"convert_audio\">ਬਦਲੋ</string>\n    <string name=\"start_download\">ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"close\">ਬੰਦ ਕਰੋ</string>\n    <string name=\"close_never_show_again\">ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ</string>\n    <string name=\"user_guide\">ਉਪਭੋਗਤਾ ਗਾਈਡ</string>\n    <string name=\"open_settings\">ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ</string>\n    <string name=\"paste_desc\">ਆਪਣੇ ਕਲਿੱਪਬੋਰਡ ਤੋਂ ਵੀਡੀਓ ਲਿੰਕ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ \\\"ਪੇਸਟ ਕਰੋ\\\" \\'ਤੇ ਕਲਿੱਕ ਕਰੋ।</string>\n    <string name=\"download_desc\">ਇਸ ਦੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਐਡਜਸਟ ਕਰਨ ਤੋਂ ਬਾਅਦ ਫੇਰ \\\"ਡਾਊਨਲੋਡ\\\" \\'ਤੇ ਕਲਿੱਕ ਕਰੋ।</string>\n    <string name=\"download_history_desc\">ਵੀਡੀਓ ਅਤੇ ਆਡੀਓ ਫਾਈਲਾਂ ਸਮੇਤ ਐਪ-ਵਿੱਚ ਡਾਊਨਲੋਡਾਂ ਦੀ ਜਾਂਚ ਅਤੇ ਪ੍ਰਬੰਧਨ ਕਰੋ।</string>\n    <string name=\"check_download_settings_desc\">ਡਾਊਨਲੋਡ ਸੈਟਿੰਗਾਂ \\'ਤੇ ਇੱਕ ਨਜ਼ਰ ਮਾਰੋ ਅਤੇ ਇਸਦੀ ਵਰਤੋਂ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ yt-dlp ਦਾ ਨਵੀਨਤਮ ਸੰਸਕਰਣ ਹੈ।</string>\n    <string name=\"download_playlist\">ਪਲੇਲਿਸਟ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"download_playlist_desc\">ਇੱਕ ਪਲੇਲਿਸਟ ਤੋਂ ਕਈ ਵੀਡੀਓ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"defaults\">ਡਿਫਾਲਟ</string>\n    <string name=\"channel_name\">ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"channel_description\">ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ ਅਤੇ ਪ੍ਰਗਤੀ ਬਾਰੇ ਸੂਚਿਤ ਕਰੋ</string>\n    <string name=\"video_url\">ਵੀਡੀਓ ਲਿੰਕ</string>\n    <string name=\"download_finish_notification\">ਡਾਊਨਲੋਡ ਪੂਰਾ ਹੋਇਆ, ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ।</string>\n    <string name=\"execute_command_notification\">ਕਸਟਮ ਕਮਾਂਡਾਂ ਚੱਲ ਰਹੀਆਂ ਹਨ…</string>\n    <string name=\"battery_settings_desc\">ਕਿਰਪਾ ਕਰਕੇ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਸ ਐਪ ਦੀ ਬੈਟਰੀ ਵਰਤੋਂ ਨੂੰ \\\"ਅਪ੍ਰਬੰਧਿਤ\\\" \\'ਤੇ ਸੈੱਟ ਕਰੋ।</string>\n    <string name=\"concurrent_download\">ਮਲਟੀ-ਥਰੈੱਡਡ ਡਾਊਨਲੋਡ</string>\n    <string name=\"concurrent_download_desc\">ਸਮਾਨਾਂਤਰ ਵਿੱਚ M3U8/MPD ਵੀਡੀਓ ਦੇ ਹੋਰ ਭਾਗਾਂ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"concurrent_download_num\">%d ਥ੍ਰੈੱਡ(s) ਨੂੰ ਇੱਕੋ ਸਮੇਂ DASH/HLS ਮੂਲ ਵੀਡੀਓ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾਵੇਗਾ।</string>\n    <string name=\"options\">ਵਿਕਲਪ</string>\n    <string name=\"additional_settings\">ਵਾਧੂ ਸੈਟਿੰਗਾਂ</string>\n    <string name=\"download_directory_desc\">ਚੁਣੋ ਕਿ ਵੀਡੀਓ ਅਤੇ ਆਡੀਓ ਫਾਈਲਾਂ ਕਿੱਥੇ ਸਟੋਰ ਕਰਨੀਆਂ ਹਨ</string>\n    <string name=\"translate_desc\">ਹੋਸਟਡ ਵੈਬਲੇਟ \\'ਤੇ ਇਸ ਐਪ ਦਾ ਅਨੁਵਾਦ ਕਰਨ ਵਿੱਚ ਮਦਦ ਕਰੋ</string>\n    <string name=\"prefix\">ਮਾਰਗ ਟੈਮਪਲੇਟ</string>\n    <string name=\"embed_subtitles\">ਉਪਸਿਰਲੇਖ ਸ਼ਾਮਲ ਕਰੋ</string>\n    <string name=\"new_template\">ਨਵਾਂ ਟੈਮਪਲੇਟ</string>\n    <string name=\"template_label\">ਲੇਬਲ</string>\n    <string name=\"remove_template\">ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"template_selection\">ਟੈਮਪਲੇਟ ਚੋਣ</string>\n    <string name=\"downloading_indicator_text\">ਡਾਊਨਲੋਡ ਜਾਰੀ ਹੈ…</string>\n    <string name=\"task_canceled\">ਡਾਊਨਲੋਡ ਕਾਰਜ ਰੱਦ ਕੀਤਾ ਗਿਆ</string>\n    <string name=\"info_copied\">ਜਾਣਕਾਰੀ ਕਲਿੱਪਬੋਰਡ \\'ਤੇ ਕਾਪੀ ਕੀਤੀ ਗਈ</string>\n    <string name=\"status_enqueued\">ਕਤਾਰਬੱਧ</string>\n    <string name=\"status_completed\">ਪੂਰਾ ਹੋਇਆ</string>\n    <string name=\"open_file\">ਫਾਇਲ ਖੋਲੋ</string>\n    <string name=\"restart\">ਰੀਸਟਾਰਟ ਕਰੋ</string>\n    <string name=\"status_error\">ਤਰੁੱਟੀ</string>\n    <string name=\"copy_link\">ਲਿੰਕ ਕਾਪੀ ਕਰੋ</string>\n    <string name=\"copy_error_report\">ਰਿਪੋਰਟ ਕਾਪੀ ਕਰੋ</string>\n    <string name=\"video_resolution\">ਵੀਡੀਓ ਰੈਜ਼ੋਲਿਊਸ਼ਨ</string>\n    <string name=\"export_to_clipboard\">ਕਲਿੱਪਬੋਰਡ ਵਿੱਚ ਨਿਰਯਾਤ ਕਰੋ</string>\n    <string name=\"template_exported\">ਨਿਰਯਾਤ ਕੀਤਾ %1$d ਟੈਮਪਲੇਟ</string>\n    <string name=\"template_imported\">ਆਯਾਤ ਕੀਤਾ %1$d ਟੈਮਪਲੇਟ</string>\n    <string name=\"download_task_count\">%1$d ਡਾਊਨਲੋਡ ਕਾਰਜ</string>\n    <string name=\"recently_added\">ਹਾਲ ਹੀ ਸ਼ਾਮਿਲ ਕੀਤਾ</string>\n    <string name=\"multiselect_item_count\">%1$d ਵੀਡੀਓ, %2$d ਆਡੀਓ ਫ਼ਾਈਲ(ਆਂ)</string>\n    <string name=\"delete_multiple_items_msg\">ਕੀ ਤੁਹਾਡੇ ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਵਿੱਚੋਂ %1$d ਆਈਟਮਾਂ ਨੂੰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"sponsorblock_desc\">ਸਪਾਂਸਰਬਲਾਕ API ਨਾਲ ਵੀਡੀਓ ਵਿੱਚ ਭਾਗਾਂ ਨੂੰ ਹਟਾਓ ਜਾਂ ਨਿਸ਼ਾਨ ਲਗਾਓ</string>\n    <string name=\"sponsorblock_categories\">ਸਪਾਂਸਰਬਲਾਕ ਸ਼੍ਰੇਣੀਆਂ</string>\n    <string name=\"check_for_updates\">ਅੱਪਡੇਟ ਲਈ ਚੈੱਕ ਕਰੋ</string>\n    <string name=\"check_for_updates_desc\">GitHub \\'ਤੇ ਆਪਣੇ ਆਪ ਹੀ ਨਵੀਨਤਮ ਸੰਸਕਰਣ ਦੀ ਜਾਂਚ ਕਰੋ</string>\n    <string name=\"app_up_to_date\">ਮੌਜੂਦਾ ਸੰਸਕਰਣ ਅੱਪ ਟੂ ਡੇਟ ਹੈ</string>\n    <string name=\"app_update_failed\">ਨਵੀਨਤਮ ਸੰਸਕਰਣ \\'ਤੇ ਅੱਪਡੇਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲ</string>\n    <string name=\"update\">ਅੱਪਡੇਟ</string>\n    <string name=\"aria2_desc\">aria2c ਨੂੰ ਬਾਹਰੀ ਡਾਊਨਲੋਡਰ ਵਜੋਂ ਵਰਤੋ</string>\n    <string name=\"cookies_desc\">ਡਾਉਨਲੋਡਸ ਲਈ ਨੈੱਟਸਕੇਪ ਫਾਰਮੈਟਡ ਕੂਕੀਜ਼ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>\n    <string name=\"clear_temp_files\">ਅਸਥਾਈ ਫਾਈਲਾਂ ਨੂੰ ਸਾਫ਼ ਕਰੋ</string>\n    <string name=\"clear_temp_files_desc\">ਅਸਥਾਈ ਡਾਇਰੈਕਟਰੀ ਤੋਂ ਸਾਰੀਆਂ ਅਸਥਾਈ ਫਾਈਲਾਂ ਨੂੰ ਮਿਟਾਓ</string>\n    <string name=\"clear_temp_files_count\">%1$d ਅਸਥਾਈ ਫ਼ਾਈਲ(ਫ਼ਾਈਲਾਂ) ਮਿਟਾਈਆਂ ਗਈਆਂ</string>\n    <string name=\"clear_temp_files_info\">ਅਸਥਾਈ ਫਾਈਲਾਂ ਨੂੰ ਰੱਦ ਕੀਤੇ ਡਾਊਨਲੋਡਾਂ ਨੂੰ ਮੁੜ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ। ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ \\'ਤੇ ਇਹਨਾਂ ਸਾਰੀਆਂ ਫਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ\\?\n\\n\n\\nਤੁਸੀਂ %1$s ਵਿੱਚ ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੇ ਹੋ</string>\n    <string name=\"multiselect_mode\">ਬਹੁ-ਚੋਣ ਮੋਡ</string>\n    <string name=\"private_mode\">ਗੁੰਮਨਾਮ</string>\n    <string name=\"private_mode_desc\">ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ</string>\n    <string name=\"dynamic_color\">ਗਤੀਸ਼ੀਲ ਰੰਗ</string>\n    <string name=\"dynamic_color_desc\">ਵਾਲਪੇਪਰਾਂ ਤੋਂ ਐਪ ਥੀਮ \\'ਤੇ ਰੰਗ ਲਾਗੂ ਕਰੋ</string>\n    <string name=\"download_with_cellular_desc\">ਮੀਟਰ ਕੀਤੇ ਨੈੱਟਵਰਕਾਂ ਨਾਲ ਕਨੈਕਟ ਹੋਣ \\'ਤੇ ਮੀਡੀਆ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ</string>\n    <string name=\"file_unavailable\">ਇਹ ਫ਼ਾਈਲ ਹੁਣ ਉਪਲਬਧ ਨਹੀਂ ਹੈ</string>\n    <string name=\"network\">ਨੈੱਟਵਰਕ</string>\n    <string name=\"rate_limit\">ਦਰ ਸੀਮਾ</string>\n    <string name=\"rate_limit_desc\">ਅਧਿਕਤਮ ਡਾਊਨਲੋਡ ਸਪੀਡ ਨੂੰ ਸੀਮਤ ਕਰੋ</string>\n    <string name=\"generate_new_cookies\">ਨਵੀਆਂ ਕੁਕੀਜ਼ ਤਿਆਰ ਕਰੋ</string>\n    <string name=\"video_only\">ਵੀਡੀਓ (ਕੋਈ ਆਡੀਓ ਨਹੀਂ)</string>\n    <string name=\"suggested\">ਸੁਝਾਏ ਗਏ</string>\n    <string name=\"format_selection\">ਫਾਰਮੈਟ ਚੋਣ</string>\n    <string name=\"format_selection_desc\">ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਫਾਰਮੈਟ ਚੁਣੋ</string>\n    <string name=\"subdirectory\">ਸਬ-ਡਾਇਰੈਕਟਰੀ ਵਿੱਚ ਸਹੇਜੋ</string>\n    <string name=\"embed_subtitles_desc\">ਜਦ ਉਪਲਬਧ ਹੋਣ ਤਾਂ ਸਾਫਟ ਸਬਟਾਈਟਲਾਂ ਨੂੰ ਵੀਡੀਓਜ਼ ਵਿੱਚ ਏਮਬੇਡ ਕਰੋ</string>\n    <string name=\"remove_template_desc\">ਕੀ ਚੰਗੇ ਲਈ ਕਮਾਂਡ ਟੈਮਪਲੇਟਸ ਤੋਂ \\\"%1$s\\\" ਨੂੰ ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"custom_command_template_desc\">ਕਮਾਂਡ ਟੈਂਪਲੇਟਸ ਨੂੰ ਸੰਪਾਦਿਤ ਕਰੋ ਅਤੇ ਪ੍ਰਬੰਧਿਤ ਕਰੋ</string>\n    <string name=\"github_issue\">ਗਿਟਹੱਬ ਮੁੱਦਾ</string>\n    <string name=\"github_issue_desc\">ਬੱਗ ਰਿਪੋਰਟ ਜਾਂ ਵਿਸ਼ੇਸ਼ਤਾ ਬੇਨਤੀ ਲਈ ਇੱਕ ਮੁੱਦਾ ਦਰਜ ਕਰੋ</string>\n    <string name=\"video_file_size\">ਵੀਡੀਓ ਫਾਈਲ ਦਾ ਆਕਾਰ</string>\n    <string name=\"import_from_clipboard\">ਕਲਿੱਪਬੋਰਡ ਤੋਂ ਆਯਾਤ ਕਰੋ</string>\n    <string name=\"sponsorblock_categories_desc\">ਵੀਡੀਓ ਫਾਇਲ ਵਿੱਚ ਹਟਾਉਣ ਜਾਂ ਨਿਸ਼ਾਨ ਲਗਾਉਣ ਲਈ ਸਪਾਂਸਰਬਲਾਕ ਸ਼੍ਰੇਣੀਆਂ ਨਿਰਧਾਰਤ ਕਰੋ</string>\n    <string name=\"download_with_cellular\">ਸੈਲੂਲਰ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"download_disabled_with_cellular\">ਸੈਲੂਲਰ ਨੈੱਟਵਰਕ ਨਾਲ ਡਾਊਨਲੋਡ ਕਰਨਾ ਤੁਹਾਡੀਆਂ ਸੈਟਿੰਗਾਂ ਮੁਤਾਬਕ ਅਸਮਰੱਥ ਹੈ</string>\n    <string name=\"share_success_msg\">ਸਾਂਝੀ ਕੀਤੀ ਸਮੱਗਰੀ ਤੋਂ ਵੀਡੀਓ ਲਿੰਕ ਪੜ੍ਹ ਰਿਹਾ ਹੈ…</string>\n    <string name=\"show_more_actions\">ਹੋਰ ਕਾਰਵਾਈਆਂ ਦਿਖਾਓ</string>\n    <string name=\"download_notification\">ਡਾਊਨਲੋਡ ਅਧਿਸੂਚਨਾ</string>\n    <string name=\"audio_directory\">ਆਡੀਓ ਫੋਲਡਰ</string>\n    <string name=\"download_directory\">ਡਾਉਨਲੋਡ ਡਾਇਰੈਕਟਰੀ</string>\n    <string name=\"share_fail_msg\">ਸਾਂਝੀ ਕੀਤੀ ਸਮੱਗਰੀ ਤੋਂ URL ਨਾਲ ਮੇਲ ਕਰਨ ਵਿੱਚ ਅਸਮਰੱਥ</string>\n    <string name=\"download_notification_desc\">ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ ਅਤੇ ਪ੍ਰਗਤੀ ਬਾਰੇ ਸੂਚਿਤ ਕਰੋ</string>\n    <string name=\"fetching_playlist_info\">ਪਲੇਲਿਸਟ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…</string>\n    <string name=\"download_range_selection\">ਪਲੇਲਿਸਟ ਚੋਣ</string>\n    <string name=\"download_range_desc\">ਪਲੇਲਿਸਟ \\\"%3$s\\\" (%1$d ਤੋਂ %2$d ਤੱਕ) ਤੋਂ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਵਿਡੀਓਜ਼ ਦੀ ਰੇਂਜ ਨਿਰਧਾਰਤ ਕਰੋ।</string>\n    <string name=\"to\">ਅੰਤ</string>\n    <string name=\"from\">ਸ਼ੁਰੂ</string>\n    <string name=\"invalid_index_range\">ਅਵੈਧ ਇੰਡੈਕਸ ਰੇਂਜ</string>\n    <string name=\"playlist_indicator_text\">ਪਲੇਲਿਸਟ (%1$d/%2$d) ਨੂੰ ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…</string>\n    <string name=\"subdirectory_desc\">ਫਾਈਲਾਂ ਨੂੰ ਸੰਬੰਧਿਤ ਖੇਤਰਾਂ ਦੇ ਨਾਮ ਵਾਲੇ ਫੋਲਡਰਾਂ ਵਿੱਚ ਸੇਵ ਕਰੋ</string>\n    <string name=\"permission_issue\">ਸਟੋਰੇਜ਼ ਇਜਾਜ਼ਤ ਸਮੱਸਿਆ</string>\n    <string name=\"permission_issue_desc\">ਡਾਉਨਲੋਡ/ ਅਤੇ ਦਸਤਾਵੇਜ਼/ ਤੋਂ ਬਾਹਰ ਦੀਆਂ ਡਾਇਰੈਕਟਰੀਆਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹਨ</string>\n    <string name=\"battery_configuration\">ਬੈਟਰੀ ਸੰਰਚਨਾ</string>\n    <string name=\"battery_configuration_desc\">ਇਸ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਊਨਲੋਡ ਕਰਨ ਦੇਣ ਲਈ ਬੈਟਰੀ ਔਪਟੀਮਾਈਜੇਸ਼ਨ ਨੂੰ ਅਣਡਿੱਠ ਕਰੋ</string>\n    <string name=\"service_title\">ਸੀਲ ਡਾਊਨਲੋਡ ਕਰ ਰਹੀ ਹੈ…</string>\n    <string name=\"unknown_error\">ਅਣਜਾਣ ਤਰੁੱਟੀ</string>\n    <string name=\"translate\">ਅਨੁਵਾਦ ਕਰੋ</string>\n    <string name=\"status_downloading\">ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</string>\n    <string name=\"status_canceled\">ਰੱਦ ਕਰ ਦਿੱਤਾ</string>\n    <string name=\"status_fetching_video_info\">ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ</string>\n    <string name=\"max_rate\">ਅਧਿਕਤਮ ਦਰ</string>\n    <string name=\"high_contrast\">ਉੱਚ ਕੰਟ੍ਰਾਸਟ ਗੂੜ੍ਹਾ ਥੀਮ</string>\n    <string name=\"invalid_input\">ਅਵੈਧ ਇਨਪੁਟ</string>\n    <string name=\"lowest_quality\">ਸਭ ਤੋਂ ਘੱਟ ਗੁਣਵੱਤਾ</string>\n    <string name=\"unavailable\">ਅਣਉਪਲਬਧ</string>\n    <string name=\"format_settings_desc\">ਫਾਈਲ ਫਾਰਮੈਟ, ਵੀਡੀਓ ਗੁਣਵੱਤਾ, ਉਪਸਿਰਲੇਖ</string>\n    <string name=\"general_settings_desc\">Yt-dlp ਸੰਸਕਰਣ, ਸੂਚਨਾ, ਪਲੇਲਿਸਟ</string>\n    <string name=\"network_settings_desc\">ਦਰ ਸੀਮਾ, ਡਾਊਨਲੋਡਰ, ਕੁਕੀਜ਼</string>\n    <string name=\"disable_preview\">ਝਲਕ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ</string>\n    <string name=\"disable_preview_desc\">ਡਾਊਨਲੋਡ \\'ਤੇ ਥੰਮਨੇਲ ਨਾਂ ਵਿਖਾਓ</string>\n    <string name=\"privacy\">ਗੋਪਨੀਯਤਾ</string>\n    <string name=\"use_custom_command\">ਕਸਟਮ ਕਮਾਂਡ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>\n    <string name=\"download_selection_desc\">ਪਲੇਲਿਸਟ \\\"%1$s\\\" ਤੋਂ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਵੀਡੀਓ ਚੁਣੋ</string>\n    <string name=\"select_all\">ਸਾਰੇ ਚੁਣੋ</string>\n    <string name=\"selected_item_count\">%1$d ਚੁਣਿਆ ਗਿਆ</string>\n    <string name=\"private_directory\">ਪ੍ਰਾਈਵੇਟ ਡਾਇਰੈਕਟਰੀ</string>\n    <string name=\"private_directory_desc\">ਇੱਕ ਲੁਕੀ ਹੋਈ ਡਾਇਰੈਕਟਰੀ ਵਿੱਚ ਡਾਊਨਲੋਡ ਸਟੋਰ ਕਰੋ</string>\n    <string name=\"crop_artwork\">ਕ੍ਰੌਪ ਆਰਟਵਰਕ</string>\n    <string name=\"crop_artwork_desc\">ਏਮਬੇਡ ਚਿੱਤਰ ਨੂੰ ਵਰਗ ਵਿੱਚ ਕੱਟੋ</string>\n    <string name=\"use_cookies\">ਕੂਕੀਜ਼ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>\n    <string name=\"remove_cookie_profile_desc\">ਕੀ \\\"%1$s\\\" ਲਈ ਇਸ ਐਂਟਰੀ ਨੂੰ ਹਟਾਉਣਾ ਹੈ? ਕਿਰਪਾ ਕਰਕੇ ਧਿਆਨ ਦਿਓ ਕਿ ਇਸ ਸਾਈਟ ਲਈ ਸਟੋਰ ਕੀਤੀਆਂ ਕੁੱਕੀਜ਼ ਨੂੰ ਸਾਫ਼ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</string>\n    <string name=\"how_does_it_work\">ਇਹ ਕਿਵੇਂ ਚਲਦਾ ਹੈ\\?</string>\n    <string name=\"telegram_channel\">ਟੈਲੀਗ੍ਰਾਮ ਚੈਨਲ</string>\n    <string name=\"custom_command_enabled_hint\">ਕਸਟਮ ਕਮਾਂਡ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਕੁਝ ਵਿਕਲਪ ਉਪਲਬਧ ਨਹੀਂ ਹਨ</string>\n    <string name=\"cookies_usage_msg\">ਕੁਝ ਸਾਈਟਾਂ ਤੋਂ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਖਾਤਾ ਪ੍ਰਮਾਣੀਕਰਨ ਜਾਣਕਾਰੀ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। \\\"ਨਵੀਆਂ ਕੂਕੀਜ਼ ਤਿਆਰ ਕਰੋ\\\" \\'ਤੇ ਕਲਿੱਕ ਕਰੋ, ਵੈੱਬਸਾਈਟ ਦਾ URL ਦਾਖਲ ਕਰੋ ਅਤੇ ਫਿਰ ਬ੍ਰਾਊਜ਼ਰ ਪੰਨੇ \\'ਤੇ ਆਪਣੇ ਖਾਤੇ ਨਾਲ ਲਾਗ-ਇਨ ਕਰੋ, ਐਪ ਤੁਹਾਡੇ ਲਈ ਇਸਨੂੰ ਤਿਆਰ ਕਰੇਗੀ।</string>\n    <string name=\"cookies\">ਕੁਕੀਜ਼</string>\n    <string name=\"matrix_space\">ਮੈਟ੍ਰਿਕਸ ਸਪੇਸ</string>\n    <string name=\"sdcard_directory\">ਐਸ ਡੀ ਕਾਰਡ ਫੋਲਡਰ</string>\n    <string name=\"auto_subtitle\">ਆਟੋਮੈਟਿਕ ਸੁਰਖੀਆਂ</string>\n    <string name=\"subtitle\">ਸਬ- ਟਾਈਟਲ</string>\n    <string name=\"abs_hint\">ਜ਼ਿਆਦਾਤਰ ਵੀਡੀਓ ਸਟ੍ਰੀਮਿੰਗ ਪਲੇਟਫਾਰਮ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਨੂੰ ਵੱਖਰੇ ਤੌਰ \\'ਤੇ ਪ੍ਰਦਾਨ ਕਰਦੇ ਹਨ, ਤੁਸੀਂ ਇੱਕ ਆਡੀਓ-ਓਨਲੀ ਫਾਰਮੈਟ ਨੂੰ ਚੁਣ ਸਕਦੇ ਹੋ ਅਤੇ ਇੱਕ ਵੀਡੀਓ ਵਿੱਚ ਕੇਵਲ-ਵੀਡੀਓ ਫਾਰਮੈਟ ਨੂੰ ਇੱਕ ਵੀਡੀਓ ਵਿੱਚ ਮਿਲਾ ਸਕਦੇ ਹੋ।</string>\n    <string name=\"download_subtitles\">ਸਬ- ਟਾਈਟਲ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"subtitle_language\">ਸਬ- ਟਾਈਟਲ ਭਾਸ਼ਾਵਾਂ</string>\n    <string name=\"subtitle_desc\">ਭਾਸ਼ਾਵਾਂ, ਇੰਬੈੱਡ ਕੀਤੇ ਸਬ- ਟਾਈਟਲ, ਆਟੋ ਸੁਰਖੀਆਂ</string>\n    <string name=\"copy_log\">ਲੌਗ ਕਾਪੀ ਕਰੋ</string>\n    <string name=\"add\">ਸ਼ਾਮਿਲ ਕਰੋ</string>\n    <string name=\"shortcuts\">ਸ਼ਾਰਟਕੱਟ</string>\n    <string name=\"edit_shortcuts_desc\">ਕਸਟਮ ਸ਼ਾਰਟਕੱਟ ਸੋਧੋ, ਜੋ ਕਿ ਕਮਾਂਡ ਟੈਂਪਲੇਟ ਲਿਖਣ ਲਈ ਵਰਤੇ ਜਾ ਸਕਦੇ ਹਨ।</string>\n    <string name=\"running_tasks\">ਚੱਲ ਰਹੇ ਟਾਸਕ</string>\n    <string name=\"logs\">ਲੌਗ</string>\n    <string name=\"show_logs\">ਲੌਗ ਵਿਖਾਓ</string>\n    <string name=\"auto_subtitle_desc\">ਆਟੋ- ਤਿਆਰ ਕੀਤੀਆਂ ਸੁਰਖੀਆਂ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"title_activity_share\">ਤੁਰੰਤ ਡਾਊਨਲੋਡ</string>\n    <string name=\"video_title_sample_text\">ਵੀਡੀਓ ਟਾਈਟਲ ਨਮੂਨੇ ਦੀ ਲਿਖਤ</string>\n    <string name=\"video_creator_sample_text\">ਵੀਡੀਓ ਨਿਰਮਾਤਾ ਦੀ ਨਮੂਨਾ ਲਿਖਤ</string>\n    <string name=\"clear\">ਸਾਫ ਕਰੋ</string>\n    <string name=\"edit_shortcuts\">ਸ਼ਾਰਟਕੱਟ ਸੋਧ</string>\n    <string name=\"subtitle_sponsorblock\">ਸਪਾਂਸਰ-ਬਲਾਕ ਖੰਡਾਂ ਨੂੰ ਹਟਾਉਂਦੇ ਸਮੇਂ ਸਬ-ਟਾਈਟਲ ਗਲਤ ਸਮੇਂ ਤੇ ਹੋ ਸਕਦੇ ਹਨ।</string>\n    <string name=\"embed_subtitles_mkv_msg\">ਸਾਫ਼ਟ ਸਬਟਾਈਟਲਾਂ ਨੂੰ ਏਮਬੈਡ ਕਰਨ ਲਈ, ਵੀਡੀਓ ਨੂੰ mkv ਕੰਟੇਨਰ ਵਿੱਚ ਫਿਰ ਤੋਂ ਜੋੜਿਆ ਜਾਵੇਗਾ। ਤੁਸੀਂ VLC ਮੀਡੀਆ ਪਲੇਅਰ ਜਾਂ ਹੋਰ ਅਨੁਕੂਲ ਐਪਾਂ ਦੀ ਵਰਤੋਂ ਸਾਫ਼ਟ ਸਬਟਾਈਟਲਾਂ ਵਾਲੇ ਵੀਡੀਓ ਵੇਖਣ ਲਈ ਕਰ ਸਕਦੇ ਹੋ।</string>\n    <string name=\"audio_format_preference\">ਤਰਜੀਹੀ ਆਡੀਓ ਫਾਰਮੈਟ</string>\n    <string name=\"unlimited\">ਅਸੀਮਤ</string>\n    <string name=\"lowest_bitrate\">ਸਭ ਤੋਂ ਘੱਟ ਬਿਟਰੇਟ</string>\n    <string name=\"audio_quality\">ਆਡੀਓ ਕੁਆਲਿਟੀ</string>\n    <string name=\"audio_quality_desc\">ਕਈ ਕੁਆਲਿਟੀਆਂ ਮੌਜੂਦ ਹੋਣ \\'ਤੇ ਆਡੀਓ ਬਿੱਟਰੇਟ ਨੂੰ ਸੀਮਤ ਕਰੋ</string>\n    <string name=\"format_sorting\">ਫਾਰਮੈਟ ਛਾਂਟੀ</string>\n    <string name=\"format_sorting_desc\">yt-dlp ਦੇ -S ਵਿਕਲਪ ਨਾਲ ਫਾਰਮੈਟਾਂ ਨੂੰ ਛਾਂਟਣਾ</string>\n    <string name=\"import_from_preferences\">ਆਯਾਤ ਕਰੋ</string>\n    <string name=\"title\">ਸਿਰਲੇਖ</string>\n    <string name=\"rename\">ਨਾਮ ਬਦਲੋ</string>\n    <string name=\"second\">ਸਕਿੰਟ</string>\n    <string name=\"minute\">ਮਿੰਟ</string>\n    <string name=\"share\">ਸਾਂਝਾ ਕਰੋ</string>\n    <string name=\"stable_channel\">ਸਥਿਰ</string>\n    <string name=\"pre_release_channel\">ਪੂਰਵ-ਝਲਕ</string>\n    <string name=\"update_channel\">ਅੱਪਡੇਟ ਚੈਨਲ</string>\n    <string name=\"auto_update\">ਆਟੋ ਅੱਪਡੇਟ</string>\n    <string name=\"enable_auto_update\">ਆਟੋ ਅੱਪਡੇਟ ਚਾਲੂ ਕਰੋ</string>\n    <string name=\"discard\">ਰੱਦ ਕਰੋ</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"update_channel_desc\">ਨਵੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਤਬਦੀਲੀਆਂ ਦੀ ਪੂਰਵ-ਝਲਕ ਦੇਖਣ ਲਈ ਪ੍ਰੀ-ਰਿਲੀਜ਼ ਬਿਲਡ ਇੰਸਟਾਲ ਕਰੋ।\n\\n\n\\n ਇਹਨਾਂ ਸੰਸਕਰਣਾਂ ਵਿੱਚ ਕੁਝ ਅਸਥਿਰਤਾ ਹੋਵੇਗੀ, ਇਸ ਲਈ ਜੇਕਰ ਤੁਹਾਨੂੰ ਕੋਈ ਸਮੱਸਿਆ ਆਉਂਦੀ ਹੈ ਅਤੇ ਭਵਿੱਖ ਲਈ ਐਪ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਵਿੱਚ ਸਾਡੀ ਮਦਦ ਲਈ ਕਿਰਪਾ ਕਰਕੇ ਸਾਨੂੰ ਫੀਡਬੈਕ ਦੇਣ ਵਿੱਚ ਸੰਕੋਚ ਨਾ ਕਰੋ ।</string>\n    <string name=\"apply\">ਲਾਗੂ ਕਰੋ</string>\n    <string name=\"clear_all_cookies\">ਸਾਰੇ ਕੂਕੀਜ਼ ਨੂੰ ਸਾਫ਼ ਕਰੋ</string>\n    <string name=\"clip_video\">ਕਲਿੱਪ ਵੀਡੀਓ</string>\n    <string name=\"clip_start\">ਸ਼ੁਰੂਆਤ</string>\n    <string name=\"clip_end\">ਅੰਤ</string>\n    <string name=\"clear_all_cookies_desc\">ਕੀ ਐਪ ਵਿੱਚ ਸਟੋਰ ਕੀਤੇ ਸਾਰੀਆਂ ਕੂਕੀਜ਼ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"temporary_directory_desc\">ਅਸਥਾਈ ਫਾਈਲਾਂ ਨੂੰ ਅੰਦਰੂਨੀ ਡਾਇਰੈਕਟਰੀ ਵਿੱਚ ਸਟੋਰ ਕਰੋ</string>\n    <string name=\"audio_format\">ਆਡੀਓ ਫਾਰਮੈਟ</string>\n    <string name=\"no_downloaded_media\">ਕੋਈ ਡਾਊਨਲੋਡ ਕੀਤਾ ਮੀਡੀਆ ਨਹੀਂ ਹੈ</string>\n    <string name=\"beta_features\">ਬੀਟਾ</string>\n    <string name=\"enable_experimental_feature\">ਕੀ ਪ੍ਰਯੋਗਾਤਮਕ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"clip_video_desc\">ਫਾਰਮੈਟ ਚੋਣ ਪੰਨੇ ਵਿੱਚ ਵੀਡੀਓ ਕਲਿੱਪ ਬਣਾਓ</string>\n    <string name=\"sponsor_msg\">ਸੀਲ ਹਮੇਸ਼ਾ ਹਰ ਕਿਸੇ ਲਈ ਮੁਫ਼ਤ ਅਤੇ ਓਪਨ ਸੋਰਸ ਹੋਵੇਗੀ। ਜੇ ਤੁਹਾਨੂੰ ਇਹ ਪਸੰਦ ਹੈ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ ਮੈਨੂੰ GitHub \\'ਤੇ ਸਪਾਂਸਰ ਕਰਨ ਬਾਰੇ ਵਿਚਾਰ ਕਰੋ!</string>\n    <string name=\"msg_from_developer\">ਡਿਵੈਲਪਰ ਤੋਂ ਸੁਨੇਹਾ</string>\n    <string name=\"okay\">ਠੀਕ ਹੈ</string>\n    <string name=\"switch_to_github_builds\">GitHub ਬਿਲਡਸ \\'ਤੇ ਸਵਿੱਚ ਕਰਨਾ</string>\n    <string name=\"got_it\">ਸਮਝ ਗਿਆ</string>\n    <string name=\"sponsor_desc\">GitHub \\'ਤੇ ਸਪਾਂਸਰ ਕਰਕੇ ਇਸ ਐਪ ਦਾ ਸਮਰਥਨ ਕਰੋ</string>\n    <string name=\"clip_video_dialog_msg\">ਵੀਡੀਓ ਦੇ ਚੁਣੇ ਹੋਏ ਭਾਗਾਂ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ ਡਾਊਨਲੋਡਾਂ ਨੂੰ FFmpeg ਨੂੰ ਸੌਂਪਿਆ ਜਾਵੇਗਾ, ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਅਜੇ ਵੀ ਪ੍ਰਯੋਗਾਤਮਕ ਹੈ ਅਤੇ ਕੱਟਣਾ ਪੂਰੀ ਤਰ੍ਹਾਂ ਸਹੀ ਨਹੀਂ ਹੋਵੇਗਾ, ਸਾਰੇ ਫਾਰਮੈਟ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੇ ਹਨ ਅਤੇ ਤੁਸੀਂ ਹੌਲੀ ਡਾਊਨਲੋਡ ਸਪੀਡ ਦਾ ਅਨੁਭਵ ਕਰ ਸਕਦੇ ਹੋ।</string>\n    <string name=\"auto_update_disabled_msg\">%1$s ਬਿਲਡਾਂ ਲਈ ਸਵੈ-ਅੱਪਡੇਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਜੇਕਰ ਤੁਸੀਂ ਆਪਣੀ ਡਿਵਾਈਸ \\'ਤੇ %1$s ਨੂੰ ਸਥਾਪਿਤ ਨਹੀਂ ਕੀਤਾ ਹੈ, ਜਾਂ ਤੁਸੀਂ ਸੀਲ ਵਿੱਚ ਆਉਣ ਵਾਲੀਆਂ ਨਵੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਪੂਰਵਦਰਸ਼ਨ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ %2$s \\'ਤੇ ਵਿਚਾਰ ਕਰੋ।</string>\n    <string name=\"feature_unavailable\">ਵਿਸ਼ੇਸ਼ਤਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ</string>\n    <string name=\"sponsor_msg2\">ਤੁਹਾਡਾ ਬਹੁਤ ਧੰਨਵਾਦ!</string>\n    <string name=\"no_custom_command_tasks\">ਕੋਈ ਕਸਟਮ ਕਮਾਂਡ ਕਾਰਜ ਨਹੀਂ</string>\n    <string name=\"sponsors\">ਪ੍ਰਾਯੋਜਕ</string>\n    <string name=\"feedback\">ਸੁਝਾਅ</string>\n    <string name=\"sponsor\">ਪ੍ਰਾਯੋਜਿਤ ਕਰੋ</string>\n    <string name=\"convert_subtitle\">ਸਬ- ਟਾਈਟਲ ਬਦਲੋ</string>\n    <string name=\"convert_subtitle_desc\">ਸਬ- ਟਾਈਟਲਾਂ ਨੂੰ ਹੋਰ ਫਾਰਮੈਟ ਵਿੱਚ ਬਦਲੋ</string>\n    <string name=\"split_video_msg\">ਵੀਡੀਓ ਨੂੰ %1$d ਚੈਪਟਰਾਂ ਵਿੱਚ ਵੰਡਿਆ ਜਾਵੇਗਾ</string>\n    <string name=\"split_video\">ਵੀਡੀਓ ਵੰਡੋ</string>\n    <string name=\"unknown_error_title\">ਓਹੋ! ਕੁਝ ਗਲਤ ਹੋ ਗਿਆ ਹੈ</string>\n    <string name=\"copy_and_exit\">ਕਾਪੀ ਕਰੋ ਅਤੇ ਬੰਦ ਕਰੋ</string>\n    <string name=\"download_video_desc\">URL ਤੋਂ ਵੀਡੀਓ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"start\">ਸ਼ੁਰੂ ਕਰੋ</string>\n    <string name=\"expand\">ਵਿਸਥਾਰ ਕਰੋ</string>\n    <string name=\"new_task\">ਨਵਾਂ ਡਾਊਨਲੋਡ ਕਾਰਜ</string>\n    <string name=\"edit_template\">ਸੰਪਾਦਨ \\\"%1$s\\\"</string>\n    <string name=\"ytdlp_update_action\">yt-dlp ਅੱਪਡੇਟ ਕਰੋ</string>\n    <string name=\"proxy\">ਪ੍ਰੌਕਸੀ</string>\n    <string name=\"legacy\">ਲੀਗੇਸੀ</string>\n    <string name=\"quality\">ਕੁਆਲਿਟੀ</string>\n    <string name=\"enable_notifications\">ਸੂਚਨਾਵਾਂ ਨੂੰ ਸਮਰੱਥ ਕਰੋ\\?</string>\n    <string name=\"enable_notifications_desc\">ਐਪ ਨੂੰ ਡਾਊਨਲੋਡ ਸਥਿਤੀ ਅਤੇ ਪ੍ਰਗਤੀ ਬਾਰੇ ਸੂਚਨਾਵਾਂ ਪੋਸਟ ਕਰਨ ਲਈ ਤੁਹਾਡੀ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ।</string>\n    <string name=\"disable\">ਅਸਮਰੱਥ ਕਰੋ</string>\n    <string name=\"set_directory_desc\">ਡਾਇਰੈਕਟਰੀ ਸੈੱਟ ਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ</string>\n    <string name=\"custom_command_directory\">ਕਸਟਮ ਕਮਾਂਡ ਡਾਇਰੈਕਟਰੀ</string>\n    <string name=\"disabled\">ਅਸਮਰੱਥ ਕੀਤੀਆਂ</string>\n    <string name=\"folder_picker\">ਫ਼ੋਲਡਰ ਪਿਕਰ</string>\n    <string name=\"prefer_compatibility_desc\">ਹੋਰ ਐਪਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰਨ ਲਈ MP4 (H.264) ਫਾਰਮੈਟਾਂ ਨੂੰ ਤਰਜੀਹ ਦਿਓ</string>\n    <string name=\"prefer_quality_desc\">ਅਨੁਕੂਲ ਐਪਾਂ ਵਿੱਚ ਦੇਖਣ ਲਈ AV1, VP9 ਜਾਂ H.265 ਫਾਰਮੈਟਾਂ ਨੂੰ ਤਰਜੀਹ ਦਿਓ</string>\n    <string name=\"proxy_desc\">ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨਾਂ ਲਈ ਪ੍ਰੌਕਸੀ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>\n    <string name=\"custom_command_directory_desc\">ਕਸਟਮ ਕਮਾਂਡਾਂ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਆਉਟਪੁੱਟ ਡਾਇਰੈਕਟਰੀ ਨਿਰਧਾਰਤ ਕਰੋ</string>\n    <string name=\"download_type\">ਡਾਊਨਲੋਡ ਦੀ ਕਿਸਮ</string>\n    <string name=\"custom\">ਕਸਟਮ</string>\n    <string name=\"auto\">ਆਟੋ</string>\n    <string name=\"commands\">ਕਮਾਂਡਾਂ</string>\n    <string name=\"format_preference\">ਫਾਰਮੈਟ ਦੀ ਤਰਜੀਹ</string>\n    <string name=\"learn_more\">ਜਿਆਦਾ ਜਾਣੋ</string>\n    <string name=\"unknown\">ਅਗਿਆਤ</string>\n    <string name=\"remove_multiple_templates_msg\">ਕਮਾਂਡ ਟੈਮਪਲੇਟਸ ਤੋਂ %1$s ਨੂੰ ਬਿਹਤਰੀ ਲਈ ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"refresh_cookies_desc\">ਨਵੀਆਂ ਕੂਕੀਜ਼ ਬਣਾਉਣ ਵਾਸਤੇ ਵੈੱਬਪੇਜ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ:</string>\n    <string name=\"ua_header\">ਯੂਜ਼ਰ-ਏਜੰਟ ਸਿਰਲੇਖ</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d ਆਈਟਮ</item>\n        <item quantity=\"other\">%d ਆਈਟਮਾਂ</item>\n    </plurals>\n    <string name=\"export_to_file\">ਫਾਈਲ ਵਿੱਚ ਐਕਸਪੋਰਟ ਕਰੋ</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp ਵੀਡੀਓ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਇੱਕ ਸ਼ਕਤੀਸ਼ਾਲੀ ਕਮਾਂਡ-ਲਾਈਨ ਟੂਲ ਹੈ। ਸੀਲ ਇੱਕ ਅਨੁਭਵੀ GUI, ਆਮ ਕਮਾਂਡਾਂ ਲਈ ਪ੍ਰੀਸੈਟਸ, ਅਤੇ ਹੋਰ ਵਾਧੂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਪ੍ਰਦਾਨ ਕਰਕੇ yt-dlp ਦੀ ਵਰਤੋਂ ਕਰਨਾ ਆਸਾਨ ਬਣਾਉਂਦਾ ਹੈ।\n\\n\n\\nyt-dlp ਦੀ ਉੱਨਤ ਵਰਤੋਂ ਲਈ, ਸੀਲ ਤੁਹਾਨੂੰ ਕਸਟਮ ਕਮਾਂਡ ਟੈਂਪਲੇਟਾਂ ਨੂੰ ਸਿੱਧਾ ਬਣਾਉਣ, ਸੁਰੱਖਿਅਤ ਕਰਨ ਅਤੇ ਚਲਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜਿਵੇਂ ਕਿ ਟਰਮੀਨਲ ਵਿੱਚ।\n\\n\n\\nਕਸਟਮ ਕਮਾਂਡਾਂ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ, ਜ਼ਿਆਦਾਤਰ GUI ਵਿਕਲਪ ਅਤੇ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਯੋਗ ਹੋ ਜਾਣਗੀਆਂ।</string>\n    <string name=\"clear_download_archive\">ਡਾਊਨਲੋਡ ਆਰਕਾਇਵ ਨੂੰ ਸਾਫ਼ ਕਰੋ\\?</string>\n    <string name=\"clear_download_archive_desc\">ਕੀ ਆਰਕਾਇਵ ਫਾਈਲ ਵਿੱਚੋਂ %1$s ਨੂੰ ਚੰਗੇ ਲਈ ਹਟਾਉਣਾ ਹੈ\\?</string>\n    <string name=\"presets\">ਪ੍ਰੀਸੈਟਸ</string>\n    <string name=\"output_template\">ਆਉਟਪੁੱਟ ਟੈਮਪਲੇਟ</string>\n    <string name=\"output_template_desc\">ਆਉਟਪੁੱਟ ਫ਼ਾਈਲ ਨਾਮ ਲਈ ਟੈਪਲੇਟ ਨਿਰਧਾਰਿਤ ਕਰੋ</string>\n    <string name=\"download_archive_desc\">ਡੁਪਲੀਕੇਟ ਡਾਉਨਲੋਡਸ ਤੋਂ ਬਚਣ ਲਈ ਇੱਕ ਆਰਕਾਇਵ ਵਿੱਚ ਡਾਊਨਲੋਡ ਕੀਤੇ ਵੀਡੀਓ ਆਈ.ਡੀ. ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ</string>\n    <string name=\"download_archive\">ਡਾਊਨਲੋਡ ਆਰਕਾਇਵ</string>\n    <string name=\"embed_metadata\">ਮੈਟਾਡੇਟਾ ਨੂੰ ਸ਼ਾਮਿਲ ਕਰੋ</string>\n    <string name=\"required\">ਲੋੜੀਂਦਾ ਹੈ</string>\n    <string name=\"embed_metadata_desc\">ਆਡੀਓ ਫਾਈਲ ਵਿੱਚ ਮੈਟਾਡੇਟਾ ਅਤੇ ਵੀਡੀਓ ਥੰਮਨੇਲ ਨੂੰ ਸ਼ਾਮਿਲ ਕਰੋ</string>\n    <string name=\"show_all_items\">ਸਾਰੀਆਂ %1$d ਆਈਟਮਾਂ ਵਿਖਾਓ</string>\n    <string name=\"save\">ਸਾਂਭੋ</string>\n    <string name=\"use_format_sorting\">ਫਾਰਮੈਟ ਛਾਂਟੀ ਵਰਤੋ</string>\n    <string name=\"edit_file\">ਫ਼ਾਈਲ ਸੰਪਾਦਿਤ ਕਰੋ</string>\n    <string name=\"restrict_filenames_desc\">ਅਨੁਕੂਲਤਾ ਨੂੰ ਯਕੀਨੀ ਬਣਾਉਣ ਲਈ ਫਾਈਲ ਨਾਮਾਂ ਨੂੰ ਖਾਸ ਅੱਖਰਾਂ ਤੱਕ ਸੀਮਤ ਕਰੋ</string>\n    <string name=\"restrict_filenames\">ਫਾਈਲਨਾਮਾਂ ਨੂੰ ਪ੍ਰਤਿਬੰਧਿਤ ਕਰੋ</string>\n    <string name=\"website\">ਵੈਬਸਾਈਟ</string>\n    <string name=\"playlist_title\">ਪਲੇਲਿਸਟ ਟਾਈਟਲ</string>\n    <string name=\"subdirectory_hint\">ਤੁਹਾਡੇ ਡਾਊਨਲੋਡ ਇਸ ਰੂਪ ਵਿੱਚ ਸਾਂਭੇ ਜਾਣਗੇ:</string>\n    <string name=\"system_settings\">ਸਿਸਟਮ ਸੈਟਿੰਗਜ਼</string>\n    <string name=\"force_ipv4\">IPv4 ਨੂੰ ਫੋਰਸ ਕਰੋ</string>\n    <string name=\"force_ipv4_desc\">ਸਾਰੇ ਕੁਨੈਕਸ਼ਨ IPv4 ਰਾਹੀਂ ਬਣਾਓ</string>\n    <string name=\"keep_subtitle_files\">ਸਬਟਾਈਟਲ ਫਾਈਲਾਂ ਨੂੰ ਰੱਖੋ</string>\n    <string name=\"dont_allow\">ਇਜਾਜ਼ਤ ਨਾ ਦਿਓ</string>\n    <string name=\"merge_audiostream\">ਮਲਟੀਪਲ ਆਡੀਓ ਸਟ੍ਰੀਮ ਨੂੰ ਮਿਲਾਓ</string>\n    <string name=\"allow_once\">ਇੱਕ ਵਾਰ ਆਗਿਆ ਦਿਓ</string>\n    <string name=\"allow_always\">ਹਮੇਸ਼ਾ ਇਜਾਜ਼ਤ ਦਿਓ</string>\n    <string name=\"download_with_cellular_request\">ਕੀ ਮੋਬਾਈਲ ਡਾਟਾ ਨਾਲ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣੀ ਹੈ?</string>\n    <string name=\"merge_audiostream_desc\">ਮਲਟੀਪਲ ਆਡੀਓ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਇੱਕ ਸਿੰਗਲ ਫਾਈਲ ਵਿੱਚ ਵਿਲੀਨ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ</string>\n    <string name=\"search\">ਖੋਜ ਕਰੋ</string>\n    <string name=\"search_in_downloads\">ਡਾਊਨਲੋਡਸ ਵਿੱਚ ਖੋਜ ਕਰੋ</string>\n    <string name=\"auto_translated_subtitles\">ਸਵੈ-ਅਨੁਵਾਦਿਤ ਉਪਸਿਰਲੇਖ</string>\n    <string name=\"auto_translated_subtitles_msg\">ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ ਲਈ ਸਵੈ-ਅਨੁਵਾਦਿਤ ਉਪਸਿਰਲੇਖ ਡਾਊਨਲੋਡਾਂ ਵਿੱਚ ਉਪਲਬਧ ਹੋਣਗੇ। ਇਹ ਉਪਸਿਰਲੇਖ ਗਲਤ ਅਤੇ ਸਮਝਣ ਵਿੱਚ ਮੁਸ਼ਕਲ ਹੋ ਸਕਦੇ ਹਨ।</string>\n    <string name=\"subtitle_language_desc\">ਆਟੋ ਫਾਰਮੈਟ ਚੋਣ ਵਿੱਚ ਡਾਉਨਲੋਡ ਕਰਨ ਲਈ ਉਪਸਿਰਲੇਖਾਂ ਦੀ ਭਾਸ਼ਾ, ਕਾਮਿਆਂ ਦੁਆਰਾ ਵੱਖ ਕੀਤੀ ਗਈ।</string>\n    <string name=\"remember_for_next_download\">ਅਗਲੇ ਡਾਊਨਲੋਡ ਲਈ ਯਾਦ ਰੱਖੋ</string>\n    <string name=\"look_and_feel\"><![CDATA[ਦਿੱਖ ਅਤੇ ਅਹਿਸਾਸ]]></string>\n    <string name=\"use_previous_selection\">ਪਿਛਲੀ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>\n    <string name=\"none\">ਕੋਈ ਵੀ ਨਹੀਂ</string>\n    <string name=\"reset\">ਰੀਸੈੱਟ ਕਰੋ</string>\n    <string name=\"search_in_subtitles\">ਉਪਸਿਰਲੇਖਾਂ ਵਿੱਚ ਖੋਜ ਕਰੋ</string>\n    <string name=\"no_thanks\">ਨਹੀਂ ਧੰਨਵਾਦ</string>\n    <string name=\"update_subtitle_languages\">ਉਪਸਿਰਲੇਖ ਭਾਸ਼ਾਵਾਂ ਅੱਪਡੇਟ ਕਰੀਏ?</string>\n    <string name=\"update_language_msg\">ਭਵਿੱਖ ਦੇ ਡਾਊਨਲੋਡਾਂ ਲਈ ਤੁਹਾਡੀ ਤਰਜੀਹ ਵਿੱਚ ਅੱਗੇ ਦਿੱਤੀਆਂ ਭਾਸ਼ਾਵਾਂ ਸ਼ਾਮਲ ਕੀਤੀਆਂ ਜਾਣਗੀਆਂ:</string>\n    <string name=\"export_backup\">ਐਕਸਪੋਰਟ ਕਰੋ</string>\n    <string name=\"file\">ਫ਼ਾਈਲ</string>\n    <string name=\"interface_and_interaction\"><![CDATA[ਇੰਟਰਫੇਸ ਅਤੇ ਪਰਸਪਰ ਪ੍ਰਭਾਵ]]></string>\n    <string name=\"import_backup\">ਇੰਪੋਰਟ ਕਰੋ</string>\n    <string name=\"full_backup\">ਪੂਰਾ ਬੈਕਅੱਪ</string>\n    <string name=\"backup_type\">ਬੈਕਅੱਪ ਕਿਸਮ</string>\n    <string name=\"export_to\">ਇਸ ਥਾਂ ਤੇ ਐਕਸਪੋਰਟ ਕਰੋ</string>\n    <string name=\"import_download_history\">ਕੀ ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਇੰਪੋਰਟ ਕਰਨਾ ਹੈ?</string>\n    <string name=\"download_history\">ਡਾਊਨਲੋਡ ਦਾ ਇਤਿਹਾਸ</string>\n    <string name=\"download_history_imported\">ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਲਈ %1$s ਨੂੰ ਇੰਪੋਰਟ ਕੀਤਾ</string>\n    <string name=\"redownload\">ਮੁੜ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"clipboard\">ਕਲਿੱਪਬੋਰਡ</string>\n    <string name=\"import_from\">ਤੋਂ ਇੰਪੋਰਟ ਕਰੋ</string>\n    <string name=\"export_download_history\">ਕੀ ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਐਕਸਪੋਰਟ ਕਰਨਾ ਹੈ?</string>\n    <string name=\"export_download_history_msg\">ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਤੋਂ %1$s ਨੂੰ ਐਕਸਪੋਰਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ। ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ ਅਤੇ ਤਰਜੀਹਾਂ ਦਾ ਬੈਕਅੱਪ ਨਹੀਂ ਲਿਆ ਜਾਵੇਗਾ।</string>\n    <string name=\"import_download_history_msg\">ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਇੰਪੋਰਟ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ। ਤੁਹਾਨੂੰ ਉਹਨਾਂ ਨੂੰ ਹੱਥੀਂ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਲੋੜ ਪਵੇਗੀ</string>\n    <string name=\"download_archive_error\">ਵੀਡੀਓ ਡਾਊਨਲੋਡ ਕਰ ਲਿਆ ਗਿਆ ਹੈ। ਜੇਕਰ ਅਜਿਹੇ ਵਿਵਹਾਰ ਉਮੀਦ ਮੁਤਾਬਿਕ ਨਹੀਂ ਹੈ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਡਾਊਨਲੋਡ ਆਰਕਾਈਵ ਵਿੱਚ ਜਾਂਚ ਕਰੋ।</string>\n    <string name=\"remux_container_mkv\">Remux ਵੀਡੀਓ ਕੰਟੇਨਰ</string>\n    <string name=\"remux_container_mkv_desc\">ਬਿਹਤਰ ਅਨੁਕੂਲਤਾ ਲਈ MKV ਕੰਟੇਨਰ ਵਿੱਚ ਵੀਡੀਓਜ਼ ਨੂੰ ਰੀਮਕਸ ਕਰੋ</string>\n    <string name=\"cookies_in_database\">ਕੁੱਲ ਮਿਲਾ ਕੇ %2$d ਵੈੱਬਸਾਈਟਾਂ ਤੋਂ %1$d ਕੂਕੀਜ਼</string>\n    <string name=\"every_day\">ਹਰ ਰੋਜ਼</string>\n    <string name=\"every_week\">ਹਰ ਹਫ਼ਤੇ</string>\n    <string name=\"every_month\">ਹਰ ਮਹੀਨੇ</string>\n    <string name=\"all_languages\">ਸਭ ਭਾਸ਼ਾਵਾਂ</string>\n    <string name=\"proceed\">ਜਾਰੀ ਰੱਖੋ</string>\n    <string name=\"preset\">ਪ੍ਰੀਸੈੱਟ</string>\n    <string name=\"prefer_placeholder\">%1$s ਨੂੰ ਤਰਜੀਹ ਦਿਓ</string>\n    <string name=\"edit_preset\">ਪ੍ਰੀਸੈਟ ਨੂੰ ਸੰਪਾਦਿਤ ਕਰੋ</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d ਵੀਡੀਓ</item>\n        <item quantity=\"other\">%d ਵੀਡੀਓ</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d ਆਡੀਓ</item>\n        <item quantity=\"other\">%d ਆਡੀਓ</item>\n    </plurals>\n    <string name=\"task_added\">ਕਾਰਜ ਨੂੰ ਕਤਾਰ ਵਿੱਚ ਸ਼ਾਮਿਲ ਕੀਤਾ ਗਿਆ</string>\n    <string name=\"playlist\">ਪਲੇਲਿਸਟ</string>\n    <string name=\"preset_format_selection_desc\">ਆਪਣੀ ਫਾਰਮੈਟ ਤਰਜੀਹਾਂ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਸਵੈਚਲਿਤ ਤੌਰ \\'ਤੇ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"custom_format_selection_desc\">ਫਾਰਮੈਟਾਂ, ਉਪਸਿਰਲੇਖਾਂ ਵਿੱਚੋਂ ਚੁਣੋ, ਅਤੇ ਹੋਰ ਅਨੁਕੂਲਿਤ ਕਰੋ</string>\n    <string name=\"best_quality_desc\">ਸਭ ਤੋਂ ਵਧੀਆ ਉਪਲਬਧ ਫਾਰਮੈਟ ਡਾਊਨਲੋਡ ਕਰੋ</string>\n    <string name=\"download_hint\">ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਡਾਊਨਲੋਡ ਬਟਨ \\'ਤੇ ਟੈਪ ਕਰੋ ਜਾਂ ਇਸ ਐਪ ਨੂੰ ਵੀਡੀਓ ਲਿੰਕ ਸ਼ੇਅਰ ਕਰੋ</string>\n    <string name=\"you_ll_find_your_downloads_here\">ਤੁਹਾਨੂੰ ਆਪਣੇ ਡਾਊਨਲੋਡ ਇੱਥੇ ਮਿਲਣਗੇ</string>\n    <string name=\"status_downloaded\">ਡਾਊਨਲੋਡ ਕੀਤਾ ਗਿਆ</string>\n    <string name=\"all\">ਸਭ</string>\n    <string name=\"select_multiple_link\">%1$d ਲਿੰਕਾਂ ਵਿੱਚੋਂ ਚੁਣੋ</string>\n    <string name=\"download_queue\">ਡਾਊਨਲੋਡ ਕਤਾਰ</string>\n    <string name=\"show_navigation_drawer\">ਨੈਵੀਗੇਸ਼ਨ ਡਰਾਅਰ ਵਿਖਾਓ</string>\n    <string name=\"delete\">ਮਿਟਾਓ</string>\n    <string name=\"media_info\">ਮੀਡੀਆ ਜਾਣਕਾਰੀ</string>\n    <string name=\"resume\">ਮੁੜ ਸ਼ੁਰੂ ਕਰੋ</string>\n    <string name=\"trouble_shooting\">ਸਮੱਸਿਆ ਦਾ ਨਿਪਟਾਰਾ</string>\n    <string name=\"issue_tracker\">ਮੁੱਦਾ ਟਰੈਕਰ</string>\n    <string name=\"trouble_shooting_desc\">ਆਮ ਤਰੁੱਟੀਆਂ ਨੂੰ ਠੀਕ ਕਰੋ ਅਤੇ ਜਾਣੀਆਂ-ਪਛਾਣੀਆਂ ਸਮੱਸਿਆਵਾਂ ਦੀ ਜਾਂਚ ਕਰੋ</string>\n    <string name=\"issue_tracker_hint\">ਇੱਕ ਤਰੁੱਟੀ ਦਾ ਸਾਹਮਣਾ ਕੀਤਾ? ਕਿਸੇ ਨਵੇਂ ਮੁੱਦੇ ਦੀ ਰਿਪੋਰਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ, ਕਿਰਪਾ ਕਰਕੇ ਸਾਡੇ ਮੁੱਦੇ ਟਰੈਕਰ ਨੂੰ ਖੋਜੋ। ਬਹੁਤ ਸਾਰੀਆਂ ਆਮ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਪਹਿਲਾਂ ਹੀ ਸੰਬੋਧਿਤ ਕੀਤਾ ਗਿਆ ਹੈ ਅਤੇ ਉੱਥੇ ਦਸਤਾਵੇਜ਼ੀ ਤੌਰ \\'ਤੇ ਪੇਸ਼ ਕੀਤਾ ਗਿਆ ਹੈ।</string>\n    <string name=\"saved_urls\">ਸੇਵ ਕੀਤੇ ਲਿੰਕ</string>\n    <string name=\"add_new_url\">ਨਵਾਂ ਲਿੰਕ ਸ਼ਾਮਿਲ ਕਰੋ</string>\n    <string name=\"add_to\">%1$s ਵਿੱਚ ਸ਼ਾਮਿਲ ਕਰੋ</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-pl/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"create_thumbnail\">Zapisz miniaturkę</string>\n    <string name=\"extract_audio\">Zapisz tylko audio</string>\n    <string name=\"settings\">Ustawienia</string>\n    <string name=\"download_settings_desc\">Ogólne, format, niestandardowe polecenie</string>\n    <string name=\"download\">Pobieranie</string>\n    <string name=\"url_empty\">Pole nie może być puste</string>\n    <string name=\"extract_audio_summary\">Pobierz i zapisz audio zamiast wideo</string>\n    <string name=\"yt_dlp_up_to_date\">Używasz najnowszej wersji yt-dlp</string>\n    <string name=\"permission_denied\">Nie przyznano uprawnień</string>\n    <string name=\"download_start_msg\">Pobieranie „%1$s”</string>\n    <string name=\"fetch_info_error_msg\">Nie można zebrać informacji o filmie</string>\n    <string name=\"download_error_msg\">Nie można pobrać pliku</string>\n    <string name=\"general_settings\">Ogólne</string>\n    <string name=\"language_settings\">Ustaw język</string>\n    <string name=\"delete_info\">Usunąć\\?</string>\n    <string name=\"downloads_history\">Pobrane</string>\n    <string name=\"open_url\">Otwórz link</string>\n    <string name=\"version\">Wersja</string>\n    <string name=\"video\">Wideo</string>\n    <string name=\"release_desc\">Sprawdź informacje o zmianach i nowych wersjach</string>\n    <string name=\"advanced_settings\">Zaawansowane</string>\n    <string name=\"display\">Wyświetlacz</string>\n    <string name=\"display_settings\">Ciemny motyw, kolor dynamiczny, język</string>\n    <string name=\"on\">Włączono</string>\n    <string name=\"cancel\">Anuluj</string>\n    <string name=\"convert_audio_format_desc\">Ponowne kodowanie plików audio spowoduje utratę jakości dźwięku i zwiększenie rozmiaru pliku.</string>\n    <string name=\"video_quality\">Jakość wideo</string>\n    <string name=\"not_specified\">Nie sprecyzowano (domyślne)</string>\n    <string name=\"video_format_preference\">Preferowany format wideo</string>\n    <string name=\"video_format\">Format wideo</string>\n    <string name=\"convert_audio\">Konwertuj</string>\n    <string name=\"user_guide\">Instrukcja obsługi</string>\n    <string name=\"download_playlist_desc\">Pobierz wiele filmów z playlisty</string>\n    <string name=\"channel_name\">Pobieranie</string>\n    <string name=\"download_finish_notification\">Pobieranie zakończone. Naciśnij, aby otworzyć.</string>\n    <string name=\"video_url\">Adres URL filmu</string>\n    <string name=\"fetching_playlist_info\">Zbieranie informacji o playliście…</string>\n    <string name=\"audio_directory\">Folder audio</string>\n    <string name=\"download_directory_desc\">Wybierz miejsce przechowywania plików wideo i audio</string>\n    <string name=\"from\">Od</string>\n    <string name=\"to\">Do</string>\n    <string name=\"playlist_indicator_text\">Pobieranie playlisty (%1$d,%2$d)…</string>\n    <string name=\"video_directory\">Folder wideo</string>\n    <string name=\"dismiss\">Anuluj</string>\n    <string name=\"download_success_msg\">Pobieranie zakończone</string>\n    <string name=\"language\">Język</string>\n    <string name=\"create_thumbnail_summary\">Zapisz miniaturkę jako osobny plik</string>\n    <string name=\"yt_dlp_update_fail\">Nie można zainstalować najnowszej wersji yt-dlp. Upewnij się, że masz połączenie z Internetem.</string>\n    <string name=\"fetching_info\">Zbieranie informacji o filmie…</string>\n    <string name=\"about\">O nas</string>\n    <string name=\"paste_msg\">Wklej adres URL ze schowka</string>\n    <string name=\"ytdlp_version\">Wersja yt-dlp</string>\n    <string name=\"ytdlp_update\">Naciśnij, aby zainstalować najnowszą wersję yt-dlp</string>\n    <string name=\"confirm\">Potwierdź</string>\n    <string name=\"additional_settings\">Dodatkowe ustawienia</string>\n    <string name=\"remove\">Usuń</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Link skopiowany do schowka</string>\n    <string name=\"delete_file\">Usuń plik</string>\n    <string name=\"readme_desc\">Sprawdź repozytorium Github i README</string>\n    <string name=\"release\">Najnowsze wydanie</string>\n    <string name=\"about_page\">Wersja, informacja zwrotna, automatyczna aktualizacja</string>\n    <string name=\"credits_desc\">Podziękowania i wolne oprogramowanie</string>\n    <string name=\"custom_command\">Niestandardowe polecenie</string>\n    <string name=\"back\">Wstecz</string>\n    <string name=\"credits\">Podziękowania</string>\n    <string name=\"custom_command_template\">Szablon polecenia</string>\n    <string name=\"custom_command_desc\">Uruchom polecenie yt-dlp z niestandardowym szablonem</string>\n    <string name=\"print_details_desc\">Wyświetlaj szczegółowe informacje podczas pobierania</string>\n    <string name=\"thumbnail\">Miniaturka</string>\n    <string name=\"edit\">Edytuj</string>\n    <string name=\"off\">Wyłączono</string>\n    <string name=\"print_details\">Szczegółowe informacje</string>\n    <string name=\"dark_theme\">Ciemny motyw</string>\n    <string name=\"follow_system\">Domyślny systemu</string>\n    <string name=\"settings_before_download\">Skonfiguruj przed pobieraniem</string>\n    <string name=\"paste\">Wklej</string>\n    <string name=\"settings_before_download_text\">Dostosuj to pobieranie</string>\n    <string name=\"convert_audio_format\">Konwertuj format audio</string>\n    <string name=\"settings_before_download_desc\">Dostosuj preferencje przed pobieraniem</string>\n    <string name=\"yt_dlp_docs\">Dokumentacja yt-dlp</string>\n    <string name=\"convert_to\">Konwertuj na %1$s</string>\n    <string name=\"format\">Format</string>\n    <string name=\"best_quality\">Najwyższa jakość</string>\n    <string name=\"close\">Zamknij</string>\n    <string name=\"start_download\">Pobierz</string>\n    <string name=\"close_never_show_again\">Nie pokazuj ponownie</string>\n    <string name=\"open_settings\">Otwórz ustawienia</string>\n    <string name=\"download_playlist\">Pobierz playlistę</string>\n    <string name=\"defaults\">Domyślne</string>\n    <string name=\"channel_description\">Powiadamiaj o pobranych plikach i postępie</string>\n    <string name=\"download_notification_desc\">Powiadamiaj o pobranych plikach i postępie</string>\n    <string name=\"execute_command_notification\">Uruchamianie niestandardowego polecenia…</string>\n    <string name=\"translate\">Przetłumacz</string>\n    <string name=\"translate_desc\">Pomóż tłumaczyć tę aplikację na Hosted Weblate</string>\n    <string name=\"unknown_error\">Nieznany błąd</string>\n    <string name=\"invalid_index_range\">Nieprawidłowy zakres</string>\n    <string name=\"download_desc\">Następnie, po dostosowaniu opcji pobierania, naciśnij „Pobierz”.</string>\n    <string name=\"paste_desc\">Naciśnij „Wklej”, aby dodać link do filmu ze schowka.</string>\n    <string name=\"download_history_desc\">Sprawdź i zarządzaj pobraniami w aplikacji, w tym plikami wideo i audio.</string>\n    <string name=\"check_download_settings_desc\">Przed użyciem upewnij się, że korzystasz z najnowszej wersji yt-dlp sprawdzając ustawienia aplikacji.</string>\n    <string name=\"checked\">Sprawdzono</string>\n    <string name=\"error_copied\">Raport o błędach został skopiowany do schowka</string>\n    <string name=\"concurrent_download\">Wielowątkowe pobieranie</string>\n    <string name=\"concurrent_download_desc\">Pobierz więcej części wideo M3U8/MPD równocześnie</string>\n    <string name=\"options\">Opcje</string>\n    <string name=\"task_running\">Pobieranie zostało już rozpoczęte</string>\n    <string name=\"paste_fail_msg\">Schowek nie zawiera poprawnego adresu URL</string>\n    <string name=\"start_execute\">Rozpocznij wykonywanie polecenia</string>\n    <string name=\"edit_template_desc\">Folder wyjściowy i URL zostaną dodane przez aplikację.</string>\n    <string name=\"not_convert\">Niekonwertowany</string>\n    <string name=\"video_quality_desc\">Ogranicz jakość wideo gdy występuje wiele</string>\n    <string name=\"preferred_format_desc\">Preferowany format, gdy dostępne jest wiele</string>\n    <string name=\"concurrent_download_num\">%d wątek (wątki) będzie używany do jednoczesnego pobierania natywnego wideo DASH/HLS.</string>\n    <string name=\"share_fail_msg\">Nie można odczytać udostępnionego adresu URL</string>\n    <string name=\"share_success_msg\">Odczytywanie udostępnionego linku do filmu…</string>\n    <string name=\"download_range_selection\">Zakres playlisty</string>\n    <string name=\"download_directory\">Folder pobierania</string>\n    <string name=\"delete_info_msg\">Czy chcesz na zawsze usunąć „%1$s” z historii pobierania\\?</string>\n    <string name=\"battery_settings_desc\">W ustawieniach systemowych dla tej aplikacji ustaw „Wykorzystanie baterii” na „Bez ograniczeń”, aby pobierać w tle.</string>\n    <string name=\"show_more_actions\">Pokaż więcej akcji</string>\n    <string name=\"download_notification\">Powiadomienie o pobieraniu</string>\n    <string name=\"subdirectory\">Zapisz w podfolderze</string>\n    <string name=\"subdirectory_desc\">Zapisz pliki w folderach o nazwach odpowiadających poszczególnym polom</string>\n    <string name=\"permission_issue\">Problem z uprawnieniami</string>\n    <string name=\"permission_issue_desc\">Foldery poza Download/ i Documents/ nie są wspierane</string>\n    <string name=\"battery_configuration\">Ustawienia baterii</string>\n    <string name=\"battery_configuration_desc\">Ignoruj optymalizację baterii dla tej aplikacji, aby pobierać w tle</string>\n    <string name=\"service_title\">Seal pobiera…</string>\n    <string name=\"download_range_desc\">Określ zakres filmów z playlisty „%3$s”, które chcesz pobrać (od %1$d do %2$d).</string>\n    <string name=\"prefix\">Szablon folderu wyjściowego</string>\n    <string name=\"audio_format_preference\">Preferowany format audio</string>\n    <string name=\"unlimited\">Nieograniczony</string>\n    <string name=\"format_sorting_desc\">Sortowanie formatów z opcją -S dla yt-dlp</string>\n    <string name=\"import_from_preferences\">Importuj</string>\n    <string name=\"minute\">minuta</string>\n    <string name=\"clear_all_cookies_desc\">Usuń wszystkie ciasteczka zapisane w aplikacji na zawsze\\?</string>\n    <string name=\"clear_all_cookies\">Wyczyść wszystkie ciasteczka</string>\n    <string name=\"audio_format\">Format audio</string>\n    <string name=\"no_downloaded_media\">Brak pobranych multimediów</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"clip_video_desc\">Twórz klipy wideo na stronie wyboru formatu</string>\n    <string name=\"app_up_to_date\">Obecna wersja jest aktualna</string>\n    <string name=\"embed_subtitles\">Osadź napisy</string>\n    <string name=\"template_label\">Etykieta</string>\n    <string name=\"remove_template\">Usunąć\\?</string>\n    <string name=\"template_selection\">Wybór szablonu</string>\n    <string name=\"template_exported\">Wyeksportowano %1$d szablon(y)</string>\n    <string name=\"import_from_clipboard\">Importuj ze schowka</string>\n    <string name=\"recently_added\">Niedawno dodane</string>\n    <string name=\"template_imported\">Zaimportowano %1$d szablo(y)</string>\n    <string name=\"sponsorblock_categories\">Kategorie SponsorBlock</string>\n    <string name=\"check_for_updates_desc\">Automatycznie sprawdź czy dostępna jest aktualizacja na GitHub</string>\n    <string name=\"app_update_failed\">Nie udało się zaktualizować do najnowszej wersji</string>\n    <string name=\"multiselect_item_count\">%1$d pliki wideo, %2$d plik audio</string>\n    <string name=\"check_for_updates\">Sprawdź aktualizacje</string>\n    <string name=\"private_mode_desc\">Wyłącz historię pobierania</string>\n    <string name=\"clear_temp_files\">Usuń pliki tymczasowe</string>\n    <string name=\"invalid_input\">Nieprawidłowe dane wejściowe</string>\n    <string name=\"privacy\">Prywatność</string>\n    <string name=\"use_custom_command\">Użyj polecenia niestandardowego</string>\n    <string name=\"lowest_quality\">Najniższa jakość</string>\n    <string name=\"select_all\">Zaznacz wszystko</string>\n    <string name=\"private_directory\">Katalog prywatny</string>\n    <string name=\"crop_artwork_desc\">Przytnij osadzony obraz do kwadratu</string>\n    <string name=\"video_only\">Wideo (bez audio)</string>\n    <string name=\"suggested\">Sugerowany</string>\n    <string name=\"crop_artwork\">Przytnij grafikę</string>\n    <string name=\"share\">Udostępnij</string>\n    <string name=\"stable_channel\">Stabilna</string>\n    <string name=\"pre_release_channel\">Podgląd</string>\n    <string name=\"status_enqueued\">W kolejce</string>\n    <string name=\"status_completed\">Zakończony</string>\n    <string name=\"status_fetching_video_info\">Pobieranie informacji</string>\n    <string name=\"status_downloading\">Pobieranie</string>\n    <string name=\"open_file\">Otwórz plik</string>\n    <string name=\"copy_error_report\">Kopia raportu</string>\n    <string name=\"sponsorblock_categories_desc\">Określ kategorie SponsorBlock do usunięcia lub zaznaczenia w pliku wideo</string>\n    <string name=\"multiselect_mode\">Tryb wielokrotnego wyboru</string>\n    <string name=\"private_mode\">Tryb prywatny</string>\n    <string name=\"matrix_space\">Kanał Matrix</string>\n    <string name=\"abs_hint\">Większość platform do strumieniowego przesyłania wideo dostarcza osobno audio i wideo, możesz wybrać i połączyć format audio z formatem wideo w jeden film.</string>\n    <string name=\"msg_from_developer\">Wiadomość od twórcy</string>\n    <string name=\"sponsor_msg2\">Dziękuję bardzo!</string>\n    <string name=\"status_error\">Błąd</string>\n    <string name=\"switch_to_github_builds\">przejście na kompilacje z GitHub</string>\n    <string name=\"okay\">Ok</string>\n    <string name=\"got_it\">Zrozumiano</string>\n    <string name=\"download_with_cellular_desc\">Zezwalaj na pobieranie multimediów po podłączeniu do sieci taryfowych</string>\n    <string name=\"download_disabled_with_cellular\">Pobieranie przy pomocy sieci komórkowej jest wyłączone zgodnie z twoimi ustawieniami</string>\n    <string name=\"file_unavailable\">Ten plik nie jest już dostępny</string>\n    <string name=\"apply\">Zastosuj</string>\n    <string name=\"discard\">Odrzuć</string>\n    <string name=\"clip_end\">Koniec</string>\n    <string name=\"clip_start\">Początek</string>\n    <string name=\"custom_command_template_desc\">Edytuj szablony poleceń i zarządzaj nimi</string>\n    <string name=\"clear_temp_files_count\">Usunięto %1$d plików tymczasowych</string>\n    <string name=\"cookies\">Ciasteczka</string>\n    <string name=\"format_selection_desc\">Wybierz format do pobrania przed rozpoczęciem pobierania</string>\n    <string name=\"format_settings_desc\">Format pliku, jakość wideo, napisy</string>\n    <string name=\"github_issue\">Problemy z GitHub</string>\n    <string name=\"high_contrast\">Tryb ciemny o wysokim kontraście</string>\n    <string name=\"new_template\">Nowy szablon</string>\n    <string name=\"format_selection\">Wybór formatu</string>\n    <string name=\"aria2_desc\">Użyj aria2c jako zewnętrzny program do pobierania</string>\n    <string name=\"embed_subtitles_desc\">Dołącz napisy do filmów, jeśli są dostępne</string>\n    <string name=\"status_canceled\">Przerwane</string>\n    <string name=\"disable_preview_desc\">Brak wyświetlania miniatur podczas pobierania</string>\n    <string name=\"unavailable\">Niedostępne</string>\n    <string name=\"selected_item_count\">%1$d wybrane</string>\n    <string name=\"telegram_channel\">Kanał Telegram</string>\n    <string name=\"restart\">Uruchom ponownie</string>\n    <string name=\"info_copied\">Informacja skopiowana do schowka</string>\n    <string name=\"network_settings_desc\">Limit szybkości, program do pobierania, ciasteczka</string>\n    <string name=\"use_cookies\">Użyj ciasteczek</string>\n    <string name=\"remove_cookie_profile_desc\">Usunąć ten wpis dla \\\"%1$s\\\"? Należy pamiętać, że pliki cookie zapisane dla tej witryny nie zostaną usunięte.</string>\n    <string name=\"generate_new_cookies\">Wygeneruj nowe ciasteczka</string>\n    <string name=\"disable_preview\">Wyłącz podgląd</string>\n    <string name=\"private_directory_desc\">Przechowuj pobrane pliki w ukrytym katalogu</string>\n    <string name=\"github_issue_desc\">Prześlij zgłoszenie błędu lub zaproponuj nową funkcję</string>\n    <string name=\"dynamic_color\">Dynamiczny kolor</string>\n    <string name=\"clear_temp_files_info\">Pliki tymczasowe mogą być użyte do wznowienia przerwanych pobrań. Czy na pewno chcesz usunąć wszystkie te pliki?\n\\n\n\\nDostęp do tych plików można uzyskać w %1$s</string>\n    <string name=\"cookies_usage_msg\">Pobieranie z niektórych witryn wymaga informacji uwierzytelniających konto. Kliknij „Wygeneruj nowe ciasteczka”, wprowadź adres URL witryny, a następnie zaloguj się swoim kontem na stronie przeglądarki, aplikacja wygeneruje je za Ciebie.</string>\n    <string name=\"general_settings_desc\">Wersja Yt-dlp, powiadomienia, playlista</string>\n    <string name=\"how_does_it_work\">Jak to działa\\?</string>\n    <string name=\"downloading_indicator_text\">Pobieranie w trakcie…</string>\n    <string name=\"task_canceled\">Pobierania zostało anulowane</string>\n    <string name=\"remove_template_desc\">Usuń \\\"%1$s\\\" z szablonów poleceń na dobre\\?</string>\n    <string name=\"video_file_size\">Rozmiar wideo</string>\n    <string name=\"copy_link\">Skopiuj link</string>\n    <string name=\"video_resolution\">Rozdzielczość wideo</string>\n    <string name=\"download_task_count\">%1$d Zadania pobierania</string>\n    <string name=\"delete_multiple_items_msg\">Usunąć elementy %1$d z historii pobierania na stałe\\?</string>\n    <string name=\"cookies_desc\">Użyj ciastek formatowanych jako Netscape dla pobierania</string>\n    <string name=\"clear_temp_files_desc\">Usuń wszystkie pliki tymczasowe z katalogu tymczasowego</string>\n    <string name=\"download_selection_desc\">Wybierz pliki do pobrania z playlisty \\\"%1$s\\\"</string>\n    <string name=\"clip_video\">Klip wideo</string>\n    <string name=\"enable_experimental_feature\">Włączyć funkcje eksperymentalne\\?</string>\n    <string name=\"feature_unavailable\">Funkcja niedostępna</string>\n    <string name=\"clip_video_dialog_msg\">Pobieranie przy użyciu tej funkcji będzie delegowane do FFmpeg w celu pobrania wybranych fragmentów wideo, ta funkcja jest nadal w fazie eksperymentalnej, a przycinanie nie będzie całkowicie dokładne, nie wszystkie formaty obsługują tę funkcję i możesz doświadczać wolniejszych prędkości pobierania.</string>\n    <string name=\"auto_update_disabled_msg\">Automatyczna aktualizacja nie jest dostępna dla %1$s kompilacji. Jeżeli nie masz %1$s zainstalowanej na telefonie lub chciałbyś zobaczyć nadchodzące nowe funkcje w Seal, rozważ %2$s.</string>\n    <string name=\"no_custom_command_tasks\">Brak niestandardowych rozkazów poleceń</string>\n    <string name=\"export_to_clipboard\">Eksportuj do schowka</string>\n    <string name=\"update\">Aktualizacja</string>\n    <string name=\"sponsorblock_desc\">Usuń lub oznacz segmenty filmów za pomocą API SponsorBlock</string>\n    <string name=\"dynamic_color_desc\">Zastosuj kolory z tapety do motywu aplikacji</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">Wesprzyj aplikację poprzez wsparcie na GitHub</string>\n    <string name=\"download_with_cellular\">Pobierz przy pomocy sieci komórkowej</string>\n    <string name=\"network\">Sieć</string>\n    <string name=\"rate_limit\">Ograniczenie prędkości</string>\n    <string name=\"sdcard_directory\">Folder karty SD</string>\n    <string name=\"custom_command_enabled_hint\">Niektóre opcje są niedostępna podczas korzystania z polecenia niestandardowego</string>\n    <string name=\"rate_limit_desc\">Ogranicz maksymalną szybkość pobierania</string>\n    <string name=\"max_rate\">Maksymalna prędkość</string>\n    <string name=\"title_activity_share\">Szybkie pobieranie</string>\n    <string name=\"auto_subtitle\">Automatyczne napisy</string>\n    <string name=\"auto_subtitle_desc\">Pobierz automatycznie wygenerowane napisy</string>\n    <string name=\"subtitle\">Podtytuł</string>\n    <string name=\"download_subtitles\">Pobierz napisy</string>\n    <string name=\"subtitle_language\">Języki napisów</string>\n    <string name=\"video_title_sample_text\">Przykładowy tekst tytułu wideo</string>\n    <string name=\"video_creator_sample_text\">Przykładowy tekst twórcy wideo</string>\n    <string name=\"clear\">Wyczyść</string>\n    <string name=\"edit_shortcuts\">Edytuj skróty</string>\n    <string name=\"copy_log\">Skopiuj log</string>\n    <string name=\"subtitle_desc\">Języki, osadzanie napisów, napisy automatyczne</string>\n    <string name=\"add\">Dodaj</string>\n    <string name=\"shortcuts\">Skróty</string>\n    <string name=\"edit_shortcuts_desc\">Edytuj niestandardowe skróty, które można używać do tworzenia szablonów poleceń.</string>\n    <string name=\"audio_quality\">Jakość audio</string>\n    <string name=\"title\">Tytuł</string>\n    <string name=\"rename\">Zmień nazwę</string>\n    <string name=\"second\">sekunda</string>\n    <string name=\"lowest_bitrate\">Najniższy bitrate</string>\n    <string name=\"temporary_directory_desc\">Przechowuj pliki tymczasowe w katalogu wewnętrznym</string>\n    <string name=\"running_tasks\">Uruchomione zadania</string>\n    <string name=\"show_logs\">Pokaż logi</string>\n    <string name=\"sponsors\">Sponsorzy</string>\n    <string name=\"sponsor_msg\">Seal zawsze będzie darmowy i z otwartym kodem źródłowym. Jeśli Ci się spodoba, rozważ wsparcie mnie na GitHub!</string>\n    <string name=\"feedback\">Informacja zwrotna</string>\n    <string name=\"subtitle_sponsorblock\">Podczas usuwania segmentów SponsorBlock napisy mogą wyświetlać się w niewłaściwym czasie.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"auto_update\">Automatyczna aktualizacja</string>\n    <string name=\"enable_auto_update\">Włącz automatyczną aktualizację</string>\n    <string name=\"audio_quality_desc\">Ogranicz bitrate dźwięku, gdy występuje wiele jakości</string>\n    <string name=\"format_sorting\">Sortowanie formatu</string>\n    <string name=\"update_channel_desc\">Zainstaluj wersje przedpremierowe, aby skorzystać z nowych funkcji i zmian.\n\\n\n\\nW tych wersjach wystąpią pewne niestabilności, więc nie wahaj się przekazać nam opinii, jeśli napotkasz jakiekolwiek problemy, które pomogą nam ulepszyć aplikację na przyszłość.</string>\n    <string name=\"logs\">Dziennik</string>\n    <string name=\"embed_subtitles_mkv_msg\">Aby osadzić miękkie napisy, wideo będzie zremiksowane do kontenera MKV. Możesz użyć VLC Media Player lub inną zgodną aplikację do oglądania wideo z miękkimi napisami.</string>\n    <string name=\"update_channel\">Zaktualizuj kanał</string>\n    <string name=\"folder_picker\">Wybieranie folderu</string>\n    <string name=\"split_video\">Podziel wideo</string>\n    <string name=\"commands\">Polecenia</string>\n    <string name=\"edit_template\">Edytuj \\\"%1$s\\\"</string>\n    <string name=\"unknown\">Nieznane</string>\n    <string name=\"learn_more\">Dowiedz się więcej</string>\n    <string name=\"convert_subtitle\">Konwertuj napisy</string>\n    <string name=\"download_type\">Typ pobierania</string>\n    <string name=\"legacy\">Przestarzałe</string>\n    <string name=\"embed_metadata\">Osadzone metadane</string>\n    <string name=\"presets\">Szablony</string>\n    <string name=\"start\">Rozpocznij</string>\n    <string name=\"new_task\">Nowe zadanie pobierania</string>\n    <string name=\"copy_and_exit\">Kopiuj i wyjdź</string>\n    <string name=\"required\">Wymagane</string>\n    <string name=\"format_preference\">Preferencje formatu</string>\n    <string name=\"disabled\">Wyłączone</string>\n    <string name=\"disable\">Wyłącz</string>\n    <string name=\"auto\">Automatyczne</string>\n    <string name=\"expand\">Rozwiń</string>\n    <string name=\"quality\">Jakość</string>\n    <string name=\"custom\">Niestandardowe</string>\n    <string name=\"ytdlp_update_action\">Aktualizuj yt-dlp</string>\n    <string name=\"download_archive\">Pobierz archiwum</string>\n    <string name=\"enable_notifications\">Włączyć powiadomienia\\?</string>\n    <string name=\"proxy\">Serwer proxy</string>\n    <string name=\"clear_download_archive\">Wyczyścić archiwum pobierania?</string>\n    <string name=\"save\">Zapisz</string>\n    <string name=\"use_format_sorting\">Użyj sortowania według formatu</string>\n    <string name=\"output_template\">Szablon wyjściowy</string>\n    <string name=\"output_template_desc\">Określ szablon dla nazw plików wyjściowych</string>\n    <string name=\"edit_file\">Edytuj plik</string>\n    <string name=\"playlist_title\">Tytuł listy odtwarzania</string>\n    <string name=\"subdirectory_hint\">Pobrane pliki zostaną zapisane jako:</string>\n    <string name=\"prefer_compatibility_desc\">Preferuj formaty MP4(H.264) do udostępniania innym aplikacjom</string>\n    <string name=\"clear_download_archive_desc\">Usunąć na stałe %1$s z pliku archiwum?</string>\n    <string name=\"website\">Strona internetowa</string>\n    <string name=\"prefer_quality_desc\">Preferuj formaty AV1, VP9 lub H.265 do oglądania w kompatybilnych aplikacjach</string>\n    <string name=\"restrict_filenames_desc\">Ogranicz nazwy plików do określonych znaków w celu zapewnienia kompatybilności</string>\n    <string name=\"restrict_filenames\">Ogranicz nazwy plików</string>\n    <string name=\"download_archive_desc\">Zapisz identyfikatory pobranych filmów w archiwum w celu uniknięcia duplikatów pobrań</string>\n    <string name=\"embed_metadata_desc\">Nanieś metadane i miniatury wideo w pliku audio</string>\n    <string name=\"remove_multiple_templates_msg\">Usunąć %1$s z szablonów poleceń na dobre?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d element</item>\n        <item quantity=\"few\">%d elementy</item>\n        <item quantity=\"many\">%d elementów</item>\n        <item quantity=\"other\">%d elementów</item>\n    </plurals>\n    <string name=\"refresh_cookies_desc\">Kliknij, aby otworzyć stronę do generowania nowych plików cookie:</string>\n    <string name=\"split_video_msg\">Wideo będzie podzielone na %1$d rozdziałów</string>\n    <string name=\"allow_once\">Pozwól raz</string>\n    <string name=\"allow_always\">Pozwalaj zawsze</string>\n    <string name=\"download_with_cellular_request\">Pozwolić na pobieranie przez sieć komórkową?</string>\n    <string name=\"dont_allow\">Nie pozwalaj</string>\n    <string name=\"merge_audiostream\">Scal wiele strumieni audio</string>\n    <string name=\"merge_audiostream_desc\">Umożliwia łączenie wielu strumieni audio w jeden plik</string>\n    <string name=\"convert_subtitle_desc\">Konwertuj napisy na inny format</string>\n    <string name=\"unknown_error_title\">Ups! Coś poszło nie tak</string>\n    <string name=\"ua_header\">Nagłówek User-Agent</string>\n    <string name=\"download_video_desc\">Pobierz wideo z adresu URL</string>\n    <string name=\"keep_subtitle_files\">Zachowaj pliki z napisami</string>\n    <string name=\"proxy_desc\">Użyj serwer proxy do połączenia z internetem</string>\n    <string name=\"enable_notifications_desc\">Aplikacja potrzebuje Twojej zgody, by wyświetlać powiadomienia o statusie i postępie pobierania.</string>\n    <string name=\"show_all_items\">Pokaż wszystkie %1$d elementów</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp to potężne narzędzie wiersza poleceń do pobierania plików wideo. Seal ułatwia korzystanie z yt-dlp, zapewniając intuicyjny graficzny interfejs użytkownika, gotowe presety dla często używanych poleceń i inne dodatkowe funkcje.\n\\n\n\\nW celu zaawansowanego korzystania z yt-dlp Seal umożliwia tworzenie, zapisywanie i wykonywanie niestandardowych szablonów poleceń tak jak w terminalu.\n\\n\n\\nPodczas korzystania z niestandardowych poleceń większość opcji i funkcji GUI będzie wyłączona.</string>\n    <string name=\"set_directory_desc\">Kliknij, aby wybrać katalog</string>\n    <string name=\"custom_command_directory_desc\">Określ katalogu wyjściowy podczas korzystania z poleceń niestandardowych</string>\n    <string name=\"export_to_file\">Eksportuj do pliku</string>\n    <string name=\"custom_command_directory\">Niestandardowy katalog poleceń</string>\n    <string name=\"system_settings\">Ustawienia systemowe</string>\n    <string name=\"force_ipv4\">Wymuś IPv4</string>\n    <string name=\"force_ipv4_desc\">Nawiązuj wszystkie połączenia przez IPv4</string>\n    <string name=\"remux_container_mkv\">Remuksowanie kontenera wideo</string>\n    <string name=\"remux_container_mkv_desc\">Remuksuj wideo do kontenera MKV dla lepszej kompatybilności</string>\n    <string name=\"download_archive_error\">Wideo zostało pobrane. Jeśli nie jest to oczekiwane zachowanie, sprawdź archiwum pobrań.</string>\n    <string name=\"import_from\">Importuj z</string>\n    <string name=\"export_download_history\">Eksportować historię pobrań?</string>\n    <string name=\"cookies_in_database\">Łącznie %1$d plików cookie z %2$d witryn internetowych</string>\n    <string name=\"auto_translated_subtitles\">Automatycznie przetłumaczone napisy</string>\n    <string name=\"subtitle_language_desc\">Języki napisów do pobrania w automatycznym wyborze formatu, oddzielone przecinkami.</string>\n    <string name=\"remember_for_next_download\">Pamiętaj do następnego pobrania</string>\n    <string name=\"use_previous_selection\">Użyj poprzedniego wyboru</string>\n    <string name=\"none\">Żaden</string>\n    <string name=\"search_in_subtitles\">Szukaj w napisach</string>\n    <string name=\"no_thanks\">Nie, dziękuję</string>\n    <string name=\"update_subtitle_languages\">Zaktualizować języki napisów?</string>\n    <string name=\"export_backup\">Eksportuj</string>\n    <string name=\"import_backup\">Importuj</string>\n    <string name=\"full_backup\">Pełna kopia zapasowa</string>\n    <string name=\"backup_type\">Typ kopii zapasowej</string>\n    <string name=\"export_to\">Eksportuj do</string>\n    <string name=\"file\">Plik</string>\n    <string name=\"clipboard\">Schowek</string>\n    <string name=\"import_download_history\">Importować historię pobrań?</string>\n    <string name=\"download_history\">Historia pobrań</string>\n    <string name=\"look_and_feel\">Wygląd i styl</string>\n    <string name=\"auto_translated_subtitles_msg\">Automatycznie przetłumaczone napisy dla wszystkich języków będą dostępne w pobranych. Napisy te mogą być niedokładne i trudne do zrozumienia.</string>\n    <string name=\"interface_and_interaction\">Interfejs i interakcja</string>\n    <string name=\"update_language_msg\">Następujące języki zostaną dodane do preferowanych w przyszłych pobraniach:</string>\n    <string name=\"import_download_history_msg\">Pobrane pliki nie zostaną zaimportowane. Będziesz musiał pobrać je z powrotem ręcznie</string>\n    <string name=\"export_download_history_msg\">Eksportowanie %1$s z historii pobrań. Kopia zapasowa pobranych plików i preferencji nie zostanie utworzona.</string>\n    <string name=\"download_history_imported\">Zaimportowano %1$s do historii pobrań</string>\n    <string name=\"every_day\">Codziennie</string>\n    <string name=\"every_week\">Co tydzień</string>\n    <string name=\"every_month\">Co miesiąc</string>\n    <string name=\"redownload\">Pobierz ponownie</string>\n    <string name=\"search_in_downloads\">Szukaj w pobranych</string>\n    <string name=\"search\">Szukaj</string>\n    <string name=\"all_languages\">Wszystkie języki</string>\n    <string name=\"playlist\">Playlista</string>\n    <string name=\"proceed\">Kontynuuj</string>\n    <string name=\"preset\">Ustawienie wstępne</string>\n    <string name=\"prefer_placeholder\">Preferuj %1$s</string>\n    <string name=\"preset_format_selection_desc\">Pobierz automatyczne przy użyciu twoich preferencji</string>\n    <string name=\"edit_preset\">Edytuj ustawienie wstępne</string>\n    <string name=\"best_quality_desc\">Pobierz używając najlepszy dostępny format</string>\n    <string name=\"task_added\">Zadanie dodane do kolejki</string>\n    <string name=\"reset\">Reset</string>\n    <string name=\"custom_format_selection_desc\">Wybieraj spośród formatów, napisów i dostosowuj dalej</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-pt/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"release_desc\">Procurar registos de alterações e novas versões</string>\n    <string name=\"release\">Versão mais recente</string>\n    <string name=\"readme_desc\">Verifique o repositório GitHub e o README</string>\n    <string name=\"video\">Vídeo</string>\n    <string name=\"checked\">Verificado</string>\n    <string name=\"credits\">Créditos</string>\n    <string name=\"video_directory\">Pasta de vídeo</string>\n    <string name=\"extract_audio\">Guardar como áudio</string>\n    <string name=\"create_thumbnail\">Guardar a miniatura</string>\n    <string name=\"settings\">Definições</string>\n    <string name=\"download_settings_desc\">Geral, formato, comando personalizado</string>\n    <string name=\"download\">Descarregar</string>\n    <string name=\"url_empty\">A ligação não pode estar vazia</string>\n    <string name=\"extract_audio_summary\">Descarregar e guardar áudio, em vez de vídeo</string>\n    <string name=\"create_thumbnail_summary\">Guardar a miniatura do vídeo como um ficheiro</string>\n    <string name=\"yt_dlp_up_to_date\">Usando a versão mais recente do yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Não foi possível instalar a versão mais recente do yt-dlp. Certifique-se de que está ligado à Internet.</string>\n    <string name=\"fetching_info\">Obtenção de informações sobre o vídeo…</string>\n    <string name=\"permission_denied\">Permissão negada</string>\n    <string name=\"download_success_msg\">Descarga concluída</string>\n    <string name=\"download_error_msg\">Não foi possível descarregar o ficheiro</string>\n    <string name=\"download_start_msg\">Descarregar \\\"%1$s\\\"</string>\n    <string name=\"task_running\">Uma tarefa de descarga existente já está em execução</string>\n    <string name=\"fetch_info_error_msg\">Não foi possível obter informações sobre o vídeo</string>\n    <string name=\"general_settings\">Geral</string>\n    <string name=\"language\">Língua de visualização</string>\n    <string name=\"language_settings\">Definir a língua do ecrã</string>\n    <string name=\"paste_msg\">Colar URL</string>\n    <string name=\"paste_fail_msg\">Não foi possível fazer corresponder o URL na área de transferência</string>\n    <string name=\"ytdlp_version\">Versão Yt-dlp</string>\n    <string name=\"ytdlp_update\">Clique para instalar a versão mais recente do yt-dlp</string>\n    <string name=\"ytdlp_update_action\">Atualizar yt-dlp</string>\n    <string name=\"delete_info\">Remover\\?</string>\n    <string name=\"delete_info_msg\">Remover \\\"%1$s\\\" do seu histórico de descargas para sempre?</string>\n    <string name=\"confirm\">Confirmar</string>\n    <string name=\"open_url\">Abrir ligação</string>\n    <string name=\"delete_file\">Eliminar ficheiro</string>\n    <string name=\"about_page\">Versão, feedback, atualização automática</string>\n    <string name=\"dismiss\">Cancelar</string>\n    <string name=\"downloads_history\">Descargas</string>\n    <string name=\"remove\">Remover</string>\n    <string name=\"about\">Acerca</string>\n    <string name=\"audio\">Áudio</string>\n    <string name=\"link_copied\">Ligação copiada para a área de transferência</string>\n    <string name=\"back\">Atrás</string>\n    <string name=\"version\">Versão</string>\n    <string name=\"credits_desc\">Créditos e software livre</string>\n    <string name=\"custom_command_desc\">Executar o comando yt-dlp com modelo personalizado</string>\n    <string name=\"custom_command\">Comando personalizado</string>\n    <string name=\"custom_command_template\">Modelo de comando</string>\n    <string name=\"edit\">Editar</string>\n    <string name=\"start_execute\">Iniciar a execução do comando</string>\n    <string name=\"advanced_settings\">Avançado</string>\n    <string name=\"print_details\">Saída detalhada</string>\n    <string name=\"print_details_desc\">Imprimir mensagens detalhadas durante a descarga</string>\n    <string name=\"settings_before_download_text\">Ajustar esta descarga</string>\n    <string name=\"display\">Ecrã</string>\n    <string name=\"display_settings\">Tema escuro, cor dinâmica, línguas</string>\n    <string name=\"dark_theme\">Tema escuro</string>\n    <string name=\"off\">Desligado</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"on\">Ligado</string>\n    <string name=\"cancel\">Cancelar</string>\n    <string name=\"settings_before_download\">Configurar antes de descarregar</string>\n    <string name=\"settings_before_download_desc\">Configurar as preferências antes de descarregar</string>\n    <string name=\"error_copied\">Relatório de erro copiado para a área de transferência</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"paste\">Colar</string>\n    <string name=\"yt_dlp_docs\">Referências de utilização do Yt-dlp</string>\n    <string name=\"edit_template_desc\">O caminho de saída e o URL serão adicionados pela aplicação.</string>\n    <string name=\"convert_audio_format\">Converter formato de áudio</string>\n    <string name=\"not_convert\">Não convertido</string>\n    <string name=\"format\">Formato</string>\n    <string name=\"best_quality\">A melhor qualidade</string>\n    <string name=\"convert_to\">Converter para %1$s</string>\n    <string name=\"convert_audio_format_desc\">A recodificação de ficheiros de áudio causará perda de qualidade de áudio e aumento do tamanho do ficheiro.</string>\n    <string name=\"video_quality\">Qualidade do vídeo</string>\n    <string name=\"video_quality_desc\">Limite a qualidade do vídeo quando vários estiverem presentes</string>\n    <string name=\"not_specified\">Não especificado (predefinição)</string>\n    <string name=\"video_format_preference\">Formato de vídeo preferido</string>\n    <string name=\"preferred_format_desc\">Formato preferido quando são fornecidos vários</string>\n    <string name=\"video_format\">Formato de vídeo</string>\n    <string name=\"start_download\">Descarregar</string>\n    <string name=\"close\">Fechar</string>\n    <string name=\"close_never_show_again\">Não voltar a aparecer</string>\n    <string name=\"user_guide\">Guia do utilizador</string>\n    <string name=\"open_settings\">Abrir definições</string>\n    <string name=\"paste_desc\">Clique em \\\"Colar\\\" para obter a ligação do vídeo da sua área de transferência.</string>\n    <string name=\"download_desc\">Em seguida, clique em \\\"Descarregar\\\" depois de ajustar as definições.</string>\n    <string name=\"download_history_desc\">Verificar e gerir as descargas na aplicação, incluindo vídeos e ficheiros de áudio.</string>\n    <string name=\"check_download_settings_desc\">Consulte as definições de descarga e certifique-se de que tem a versão mais recente do yt-dlp antes de o utilizar.</string>\n    <string name=\"download_playlist\">Descarregar lista de reprodução</string>\n    <string name=\"download_playlist_desc\">Descarregar vários vídeos de uma lista de reprodução</string>\n    <string name=\"defaults\">Predefinição</string>\n    <string name=\"channel_name\">Descarregar</string>\n    <string name=\"convert_audio\">Converter</string>\n    <string name=\"channel_description\">Notificação dos ficheiros descarregados e do seu progresso</string>\n    <string name=\"video_url\">Ligação vídeo</string>\n    <string name=\"download_finish_notification\">Descarga concluída. Toque para abrir.</string>\n    <string name=\"execute_command_notification\">Executar comandos personalizados…</string>\n    <string name=\"battery_settings_desc\">Defina a utilização da bateria desta aplicação como \\\"Sem restrições\\\" nas definições do sistema para descarregar em segundo plano.</string>\n    <string name=\"concurrent_download\">Descarga multi-tarefa</string>\n    <string name=\"concurrent_download_desc\">Descarregar mais partes de vídeos M3U8/MPD em paralelo</string>\n    <string name=\"concurrent_download_num\">%d thread(s) seria(m) utilizado(s) para descarregar vídeo nativo DASH/HLS em simultâneo.</string>\n    <string name=\"options\">Opções</string>\n    <string name=\"additional_settings\">Definições adicionais</string>\n    <string name=\"use_custom_command\">Utilizar comando personalizado</string>\n    <string name=\"select_all\">Selecionar tudo</string>\n    <string name=\"selected_item_count\">%1$d selecionado(s)</string>\n    <string name=\"video_only\">Vídeo (sem áudio)</string>\n    <string name=\"video_creator_sample_text\">Texto de exemplo do criador de vídeo</string>\n    <string name=\"subtitle\">Legenda</string>\n    <string name=\"clear\">Limpar</string>\n    <string name=\"clip_video\">Cortar vídeo</string>\n    <string name=\"clip_end\">Fim</string>\n    <string name=\"clip_start\">Início</string>\n    <string name=\"audio_format_preference\">Formato áudio preferido</string>\n    <string name=\"no_custom_command_tasks\">Nenhuma tarefa de comando personalizada</string>\n    <string name=\"msg_from_developer\">Mensagem do programador</string>\n    <string name=\"sponsor_msg2\">Muito obrigado!</string>\n    <string name=\"download_video_desc\">Descarregar vídeos a partir do URL</string>\n    <string name=\"convert_subtitle\">Converter legendas</string>\n    <string name=\"convert_subtitle_desc\">Converter as legendas para outro formato</string>\n    <string name=\"unknown_error_title\">Ops! Algo correu mal</string>\n    <string name=\"share_fail_msg\">Não é possível fazer corresponder o URL de um conteúdo partilhado</string>\n    <string name=\"share_success_msg\">Ler a ligação de vídeo de um conteúdo partilhado…</string>\n    <string name=\"show_more_actions\">Mostrar mais acções</string>\n    <string name=\"download_notification\">Notificação de descarga</string>\n    <string name=\"download_notification_desc\">Notificação dos ficheiros descarregados e do seu progresso</string>\n    <string name=\"fetching_playlist_info\">Obter informações sobre a lista de reprodução…</string>\n    <string name=\"download_range_selection\">Seleção da lista de reprodução</string>\n    <string name=\"download_range_desc\">Especifique o intervalo de vídeos a descarregar da lista de reprodução \\\"%3$s\\\" (de %1$d a %2$d).</string>\n    <string name=\"to\">Terminar</string>\n    <string name=\"invalid_index_range\">Intervalo de índices inválido</string>\n    <string name=\"playlist_indicator_text\">A descarregar lista de reprodução (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Pasta áudio</string>\n    <string name=\"download_directory\">Diretório de descarga</string>\n    <string name=\"download_directory_desc\">Selecionar onde guardar vídeos e ficheiros de áudio</string>\n    <string name=\"subdirectory\">Guardar no subdiretório</string>\n    <string name=\"subdirectory_desc\">Guardar ficheiros em pastas com o nome dos respectivos campos</string>\n    <string name=\"permission_issue\">Problema de permissão de armazenamento</string>\n    <string name=\"permission_issue_desc\">Os directórios fora de Download/ e Documents/ não são suportados</string>\n    <string name=\"battery_configuration\">Configuração da bateria</string>\n    <string name=\"from\">Iniciar</string>\n    <string name=\"battery_configuration_desc\">Ignorar a otimização da bateria para que esta aplicação faça descarga em segundo plano</string>\n    <string name=\"service_title\">O Seal está a descarregar…</string>\n    <string name=\"unknown_error\">Erro desconhecido</string>\n    <string name=\"translate\">Traduzir</string>\n    <string name=\"prefix\">Prefixo</string>\n    <string name=\"embed_subtitles\">Incorporar legendas</string>\n    <string name=\"embed_subtitles_desc\">Incorporar legendas fornecidas nos vídeos, se disponíveis</string>\n    <string name=\"new_template\">Novo modelo</string>\n    <string name=\"template_label\">Rótulos</string>\n    <string name=\"remove_template_desc\">Remover \\\"%1$s\\\" dos modelos de comando para sempre\\?</string>\n    <string name=\"template_selection\">Seleção do modelo</string>\n    <string name=\"custom_command_template_desc\">Editar e gerir modelos de comandos</string>\n    <string name=\"downloading_indicator_text\">Descarga em curso…</string>\n    <string name=\"task_canceled\">Tarefa de descarga cancelada</string>\n    <string name=\"export_to_clipboard\">Exportar para a área de transferência</string>\n    <string name=\"translate_desc\">Ajuda para traduzir esta aplicação no Hosted Weblate</string>\n    <string name=\"remove_template\">Remover\\?</string>\n    <string name=\"video_file_size\">Tamanho do ficheiro de vídeo</string>\n    <string name=\"import_from_clipboard\">Importar da área de transferência</string>\n    <string name=\"github_issue_desc\">Apresentar um problema para um relatório de erros ou um pedido de funcionalidades</string>\n    <string name=\"template_imported\">Modelo(s) importado(s) %1$d</string>\n    <string name=\"github_issue\">GitHub issue</string>\n    <string name=\"info_copied\">Informação copiada para a área de transferência</string>\n    <string name=\"template_exported\">Modelo(s) exportado(s) %1$d</string>\n    <string name=\"download_task_count\">%1$d tarefas de descarga</string>\n    <string name=\"status_enqueued\">Enfileirado</string>\n    <string name=\"recently_added\">Recentemente adicionados</string>\n    <string name=\"cookies_desc\">Utilizar cookies formatados pelo Netscape para descargas</string>\n    <string name=\"clear_temp_files\">Limpar ficheiros temporários</string>\n    <string name=\"clear_temp_files_desc\">Eliminar todos os ficheiros temporários do diretório temporário</string>\n    <string name=\"clear_temp_files_info\">Os ficheiros temporários podem ser utilizados para retomar as descargas canceladas. Tem a certeza de que eliminou todos estes ficheiros?\n\\n\n\\nPode aceder a estes ficheiros em %1$s</string>\n    <string name=\"private_mode\">Incógnito</string>\n    <string name=\"invalid_input\">Entrada inválida</string>\n    <string name=\"status_completed\">Terminado</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"multiselect_mode\">Modo de seleção múltipla</string>\n    <string name=\"private_mode_desc\">Desativar o histórico de descargas</string>\n    <string name=\"lowest_quality\">Qualidade mais baixa</string>\n    <string name=\"clear_temp_files_count\">Eliminado %1$d ficheiro(s) temporário(s)</string>\n    <string name=\"dynamic_color\">Cor dinâmica</string>\n    <string name=\"general_settings_desc\">Versão yt-dlp, notificação, lista de reprodução</string>\n    <string name=\"network_settings_desc\">Limite de velocidade, descarregador, cookies</string>\n    <string name=\"disable_preview\">Desativar a pré-visualização</string>\n    <string name=\"private_directory_desc\">Armazenar descargas num diretório oculto</string>\n    <string name=\"status_downloading\">A descarregar</string>\n    <string name=\"multiselect_item_count\">%1$d vídeo(s), %2$d ficheiro(s) áudio</string>\n    <string name=\"delete_multiple_items_msg\">Remover %1$d item(ns) do seu histórico de descargas para sempre?</string>\n    <string name=\"disable_preview_desc\">Não exibir miniaturas durante a descarga</string>\n    <string name=\"status_canceled\">Cancelado</string>\n    <string name=\"dynamic_color_desc\">Aplicar cores dos papéis de parede ao tema da aplicação</string>\n    <string name=\"unavailable\">Não disponível</string>\n    <string name=\"format_settings_desc\">Formato do ficheiro, qualidade do vídeo, legendas</string>\n    <string name=\"privacy\">Privacidade</string>\n    <string name=\"status_fetching_video_info\">Obtenção de informações</string>\n    <string name=\"download_with_cellular\">Descarregar utilizando o telemóvel</string>\n    <string name=\"open_file\">Abrir ficheiro</string>\n    <string name=\"download_with_cellular_desc\">Permitir descarga de multimédia quando ligado a redes com contador</string>\n    <string name=\"private_directory\">Diretório privado</string>\n    <string name=\"crop_artwork\">Cortar arte</string>\n    <string name=\"download_disabled_with_cellular\">Descarregar com a rede celular está desativado de acordo com as suas definições</string>\n    <string name=\"sponsorblock_desc\">Remover ou marcar segmentos em vídeos com a API SponsorBlock</string>\n    <string name=\"crop_artwork_desc\">Cortar imagem incorporada num quadrado</string>\n    <string name=\"restart\">Reiniciar</string>\n    <string name=\"file_unavailable\">Este ficheiro já não está disponível</string>\n    <string name=\"status_error\">Erro</string>\n    <string name=\"copy_link\">Copiar ligação</string>\n    <string name=\"sponsorblock_categories_desc\">Especificar as categorias SponsorBlock a remover ou marcar no ficheiro de vídeo</string>\n    <string name=\"network\">Rede</string>\n    <string name=\"download_selection_desc\">Selecionar vídeos a descarregar da lista de reprodução \\\"%1$s\\\"</string>\n    <string name=\"rate_limit\">Limite de taxa</string>\n    <string name=\"sponsorblock_categories\">Categorias de SponsorBlock</string>\n    <string name=\"rate_limit_desc\">Limitar velocidade máxima de descarga</string>\n    <string name=\"copy_error_report\">Copiar relatório</string>\n    <string name=\"video_resolution\">Resolução de vídeo</string>\n    <string name=\"check_for_updates\">Verificar se há actualizações</string>\n    <string name=\"max_rate\">Taxa máxima</string>\n    <string name=\"high_contrast\">Tema escuro de alto contraste</string>\n    <string name=\"check_for_updates_desc\">Verificar automaticamente a versão mais recente no GitHub</string>\n    <string name=\"suggested\">Sugerido</string>\n    <string name=\"format_selection\">Seleção do formato</string>\n    <string name=\"app_up_to_date\">A versão atual está actualizada</string>\n    <string name=\"format_selection_desc\">Seleccione o formato antes de iniciar a descarga</string>\n    <string name=\"app_update_failed\">Falha na atualização para a versão mais recente</string>\n    <string name=\"generate_new_cookies\">Gerar novos cookies</string>\n    <string name=\"use_cookies\">Utilizar cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Remover esta entrada para \\\"%1$s\\\"? Observe que os cookies armazenados neste site não serão apagados.</string>\n    <string name=\"custom_command_enabled_hint\">Algumas opções não estão disponíveis quando se utiliza o comando personalizado</string>\n    <string name=\"how_does_it_work\">Como funciona\\?</string>\n    <string name=\"telegram_channel\">Canal do Telegram</string>\n    <string name=\"update\">Atualização</string>\n    <string name=\"cookies_usage_msg\">A descarga de alguns sites requer informações de autenticação da conta. Clique em \\\"Gerar novos cookies\\\", introduza o URL do sítio Web e, em seguida, inicie sessão com a sua conta na página do browser; a aplicação irá gerá-los para si.</string>\n    <string name=\"matrix_space\">Espaço no Matrix</string>\n    <string name=\"aria2_desc\">Utilizar aria2c como descarregador externo</string>\n    <string name=\"sdcard_directory\">Pasta do cartão SD</string>\n    <string name=\"title_activity_share\">Descarga rápida</string>\n    <string name=\"auto_subtitle\">Legendas automáticas</string>\n    <string name=\"auto_subtitle_desc\">Descarregar legendas geradas automaticamente</string>\n    <string name=\"abs_hint\">A maioria das plataformas de transmissão de vídeo fornece áudio e vídeo separadamente, mas pode selecionar e fundir um formato só de áudio com um formato só de vídeo num único vídeo.</string>\n    <string name=\"video_title_sample_text\">Título do vídeo texto de amostra</string>\n    <string name=\"download_subtitles\">Descarregar legendas</string>\n    <string name=\"subtitle_language\">Línguas das legendas</string>\n    <string name=\"subtitle_desc\">Línguas, legendas incorporadas, legendas automáticas</string>\n    <string name=\"copy_log\">Copiar registo</string>\n    <string name=\"edit_shortcuts\">Editar atalhos</string>\n    <string name=\"add\">Adicionar</string>\n    <string name=\"shortcuts\">Atalhos</string>\n    <string name=\"edit_shortcuts_desc\">Editar os atalhos personalizados que podem ser utilizados para compor modelos de comandos.</string>\n    <string name=\"running_tasks\">Tarefas em curso</string>\n    <string name=\"show_logs\">Mostrar registo</string>\n    <string name=\"logs\">Registo</string>\n    <string name=\"subtitle_sponsorblock\">As legendas podem ser desfasadas no tempo ao remover segmentos SponsorBlock.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Para incorporar legendas, os vídeos serão remuxados para um contentor mkv. Pode utilizar o VLC Media Player ou outras aplicações compatíveis para ver vídeos com legendas incorporadas.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"pre_release_channel\">Pré-lançamento</string>\n    <string name=\"enable_auto_update\">Ativar a atualização automática</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"update_channel_desc\">Instale versões de pré-lançamento para pré-visualizar novas funcionalidades e alterações.\n\\n\n\\nEstas versões apresentam alguma instabilidade, pelo que não hesite em dar-nos a sua opinião se tiver algum problema para nos ajudar a melhorar a aplicação no futuro.</string>\n    <string name=\"discard\">Descartar</string>\n    <string name=\"share\">Partilhar</string>\n    <string name=\"update_channel\">Canal de atualização</string>\n    <string name=\"apply\">Aplicar</string>\n    <string name=\"unlimited\">Ilimitado</string>\n    <string name=\"sponsor_msg\">O Seal será sempre gratuito e de código aberto para todos. Se gostar, por favor considere patrocinar-me no GitHub!</string>\n    <string name=\"lowest_bitrate\">Taxa de bits mais baixa</string>\n    <string name=\"audio_quality\">Qualidade do áudio</string>\n    <string name=\"audio_quality_desc\">Limitar a taxa de bits de áudio quando estão presentes várias qualidades</string>\n    <string name=\"feedback\">Feedback</string>\n    <string name=\"stable_channel\">Estável</string>\n    <string name=\"auto_update\">Atualização automática</string>\n    <string name=\"sponsors\">Patrocinadores</string>\n    <string name=\"format_sorting\">Ordenação de formatos</string>\n    <string name=\"audio_format\">Formato de áudio</string>\n    <string name=\"format_sorting_desc\">Ordenar formatos com a opção -S do yt-dlp</string>\n    <string name=\"import_from_preferences\">Importar</string>\n    <string name=\"no_downloaded_media\">Nenhuma media descarregada</string>\n    <string name=\"title\">Título</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Ativar a funcionalidade experimental\\?</string>\n    <string name=\"clip_video_dialog_msg\">Descargas que utilizem esta funcionalidade serão delegadas ao FFmpeg para descarregar secções seleccionadas do vídeo. Esta funcionalidade ainda é experimental e o corte não será totalmente exato, nem todos os formatos suportam esta funcionalidade e poderá ter velocidades de descarga mais lentas.</string>\n    <string name=\"clip_video_desc\">Criar cortes de vídeo na página de seleção de formato</string>\n    <string name=\"okay\">Está bem</string>\n    <string name=\"feature_unavailable\">Funcionalidade não disponível</string>\n    <string name=\"rename\">Renomear</string>\n    <string name=\"minute\">minuto</string>\n    <string name=\"auto_update_disabled_msg\">A atualização automática não está disponível para %1$s compilações. Se não tiver %1$s instalado no seu dispositivo, ou se pretender pré-visualizar as novas funcionalidades do Seal, considere %2$s.</string>\n    <string name=\"second\">segundo</string>\n    <string name=\"got_it\">Entendi</string>\n    <string name=\"clear_all_cookies\">Limpar todos os cookies</string>\n    <string name=\"switch_to_github_builds\">mudar para compilações do GitHub</string>\n    <string name=\"clear_all_cookies_desc\">Eliminar definitivamente todos os cookies armazenados na aplicação\\?</string>\n    <string name=\"temporary_directory_desc\">Armazenar ficheiros temporários no diretório interno</string>\n    <string name=\"split_video\">Dividir o vídeo</string>\n    <string name=\"sponsor\">Patrocinador</string>\n    <string name=\"sponsor_desc\">Apoie esta aplicação patrocinando-a no GitHub</string>\n    <string name=\"split_video_msg\">O vídeo será dividido em %1$d capítulos</string>\n    <string name=\"copy_and_exit\">Copiar e sair</string>\n    <string name=\"expand\">Expandir</string>\n    <string name=\"new_task\">Nova tarefa de descarga</string>\n    <string name=\"start\">Iniciar</string>\n    <string name=\"edit_template\">Editar \\\"%1$s\\\"</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"proxy_desc\">Utilizar proxy para ligações à Internet</string>\n    <string name=\"legacy\">Legado</string>\n    <string name=\"quality\">Qualidade</string>\n    <string name=\"enable_notifications\">Ativar as notificações\\?</string>\n    <string name=\"enable_notifications_desc\">A aplicação necessita da sua permissão para exibir notificações sobre o estado e o progresso da descarga.</string>\n    <string name=\"set_directory_desc\">Toque para definir o diretório</string>\n    <string name=\"disabled\">Desativado</string>\n    <string name=\"custom_command_directory\">Diretório de comandos personalizado</string>\n    <string name=\"disable\">Desativar</string>\n    <string name=\"folder_picker\">Seleção de pastas</string>\n    <string name=\"custom_command_directory_desc\">Especificar o diretório de saída quando se utilizam comandos personalizados</string>\n    <string name=\"prefer_compatibility_desc\">Prefira os formatos MP4 (H.264) para partilhar com outras aplicações</string>\n    <string name=\"prefer_quality_desc\">Prefira os formatos AV1, VP9 ou H.265 para ver em aplicações compatíveis</string>\n    <string name=\"download_type\">Tipo de descarga</string>\n    <string name=\"custom\">Personalizado</string>\n    <string name=\"auto\">Automático</string>\n    <string name=\"commands\">Comandos</string>\n    <string name=\"format_preference\">Preferência de formato</string>\n    <string name=\"learn_more\">Saiba mais</string>\n    <string name=\"unknown\">Desconhecido</string>\n    <string name=\"refresh_cookies_desc\">Toque para abrir a página Web para gerar novos cookies:</string>\n    <string name=\"remove_multiple_templates_msg\">Remover %1$s dos modelos de comando para sempre\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d item</item>\n        <item quantity=\"many\">%d itens</item>\n        <item quantity=\"other\">%d item(s)</item>\n    </plurals>\n    <string name=\"ua_header\">Cabeçalho de requisição User-Agent</string>\n    <string name=\"export_to_file\">Exportar para ficheiro</string>\n    <string name=\"custom_command_usage_msg\">O yt-dlp é uma poderosa ferramenta de linha de comando para descarregar vídeos. O Seal facilita o uso do yt-dlp fornecendo uma GUI intuitiva, predefinições para comandos comuns e outros recursos adicionais.\n\\n\n\\nPara uma utilização avançada do yt-dlp, o Seal permite-lhe criar, guardar e executar modelos de comandos personalizados diretamente, tal como num terminal.\n\\n\n\\nAo usar comandos personalizados, a maioria das opções e recursos da GUI serão desativados.</string>\n    <string name=\"presets\">Predefinições</string>\n    <string name=\"output_template\">Modelo de saída</string>\n    <string name=\"output_template_desc\">Especificar o modelo para os nomes dos ficheiros de saída</string>\n    <string name=\"clear_download_archive\">Limpar arquivo de descarga?</string>\n    <string name=\"clear_download_archive_desc\">Remover %1$s do arquivo de descarga?</string>\n    <string name=\"download_archive_desc\">Registar IDs de vídeos descarregados em um arquivo para evitar descargas duplicadas</string>\n    <string name=\"download_archive\">Arquivo de descarga</string>\n    <string name=\"embed_metadata\">Incorporar metadados</string>\n    <string name=\"embed_metadata_desc\">Incorporar metadados e miniatura de vídeo no ficheiro de áudio</string>\n    <string name=\"required\">Obrigatório</string>\n    <string name=\"show_all_items\">Mostrar todos os %1$d itens</string>\n    <string name=\"save\">Guardar</string>\n    <string name=\"use_format_sorting\">Utilizar a ordenação de formatos</string>\n    <string name=\"edit_file\">Editar ficheiro</string>\n    <string name=\"restrict_filenames_desc\">Limitar os nomes de ficheiros a caracteres específicos para garantir a compatibilidade</string>\n    <string name=\"restrict_filenames\">Restringir nomes de ficheiros</string>\n    <string name=\"website\">Sítio</string>\n    <string name=\"playlist_title\">Título da lista de reprodução</string>\n    <string name=\"subdirectory_hint\">As suas descargas serão guardadas como:</string>\n    <string name=\"system_settings\">Definições do sistema</string>\n    <string name=\"force_ipv4\">Forçar IPv4</string>\n    <string name=\"force_ipv4_desc\">Efetuar todas as ligações através de IPv4</string>\n    <string name=\"keep_subtitle_files\">Manter ficheiros de legendas</string>\n    <string name=\"allow_once\">Permitir uma vez</string>\n    <string name=\"allow_always\">Permitir sempre</string>\n    <string name=\"dont_allow\">Não permitir</string>\n    <string name=\"download_with_cellular_request\">Permitir a descarga com telemóvel?</string>\n    <string name=\"merge_audiostream\">Unir vários fluxos de áudio</string>\n    <string name=\"merge_audiostream_desc\">Permitir a fusão de vários fluxos de áudio num único ficheiro</string>\n    <string name=\"search\">Pesquisar</string>\n    <string name=\"search_in_downloads\">Pesquisar em descargas</string>\n    <string name=\"auto_translated_subtitles\">Legendas traduzidas automaticamente</string>\n    <string name=\"remember_for_next_download\">Lembrar para a próxima descarga</string>\n    <string name=\"look_and_feel\"><![CDATA[Look & feel]]></string>\n    <string name=\"use_previous_selection\">Utilizar a seleção anterior</string>\n    <string name=\"none\">Nenhum</string>\n    <string name=\"subtitle_language_desc\">Idioma das legendas a descarregar na seleção de formato automático, separado por vírgulas.</string>\n    <string name=\"auto_translated_subtitles_msg\">As legendas com tradução automática para todos os idiomas estarão disponíveis nas descargas. Estas legendas podem ser inexactas e difíceis de compreender.</string>\n    <string name=\"reset\">Repor</string>\n    <string name=\"search_in_subtitles\">Pesquisar em legendas</string>\n    <string name=\"no_thanks\">Não obrigado</string>\n    <string name=\"update_language_msg\">Os seguintes idiomas serão adicionados às suas preferências para futuras descargas:</string>\n    <string name=\"update_subtitle_languages\">Atualizar idiomas das legendas?</string>\n    <string name=\"import_download_history\">Importar o histórico de descargas?</string>\n    <string name=\"export_backup\">Exportar</string>\n    <string name=\"import_backup\">Importar</string>\n    <string name=\"full_backup\">Backup completo</string>\n    <string name=\"backup_type\">Tipo de Backup</string>\n    <string name=\"file\">Ficheiro</string>\n    <string name=\"clipboard\">Área de transferência</string>\n    <string name=\"import_from\">Importar de</string>\n    <string name=\"import_download_history_msg\">Os ficheiros descarregados não serão importados. Terá de os voltar a descarregar manualmente</string>\n    <string name=\"download_history\">Histórico de descargas</string>\n    <string name=\"interface_and_interaction\"><![CDATA[Interface & interaction]]></string>\n    <string name=\"export_to\">Exportar para</string>\n    <string name=\"export_download_history\">Exportar o histórico de descargas?</string>\n    <string name=\"export_download_history_msg\">A exportar %1$s do histórico de descargas. Os ficheiros descarregados e as preferências não serão guardados.</string>\n    <string name=\"download_history_imported\">Importou %1$s para o histórico de descargas</string>\n    <string name=\"redownload\">Descarregar novamente</string>\n    <string name=\"download_archive_error\">O vídeo foi descarregado. Se este não for o comportamento esperado, verifique o seu arquivo de descarga.</string>\n    <string name=\"remux_container_mkv\">Recipiente de vídeo Remux</string>\n    <string name=\"remux_container_mkv_desc\">Remuxar vídeos para um recipiente MKV para uma melhor compatibilidade</string>\n    <string name=\"cookies_in_database\">%1$d cookies de %2$d sites no total</string>\n    <string name=\"every_day\">Diariamente</string>\n    <string name=\"every_week\">Semanalmente</string>\n    <string name=\"every_month\">Mensalmente</string>\n    <string name=\"all_languages\">Todos os idiomas</string>\n    <string name=\"preset\">Predefinição</string>\n    <string name=\"custom_format_selection_desc\">Escolha entre formatos, legendas e personalize ainda mais</string>\n    <string name=\"preset_format_selection_desc\">Descarregar automaticamente utilizando as suas preferências de formato</string>\n    <string name=\"best_quality_desc\">Descarregar o melhor formato disponível</string>\n    <string name=\"edit_preset\">Editar predefinição</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d vídeo</item>\n        <item quantity=\"many\">%d vídeos</item>\n        <item quantity=\"other\">%d vídeos</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d áudio</item>\n        <item quantity=\"many\">%d áudios</item>\n        <item quantity=\"other\">%d áudios</item>\n    </plurals>\n    <string name=\"playlist\">Lista de reprodução</string>\n    <string name=\"proceed\">Continuar</string>\n    <string name=\"prefer_placeholder\">Preferir %1$s</string>\n    <string name=\"task_added\">Tarefa adicionada à fila</string>\n    <string name=\"you_ll_find_your_downloads_here\">Encontrará as suas descargas aqui</string>\n    <string name=\"download_hint\">Toque no botão de descarga ou partilhe uma ligação de vídeo para esta aplicação para iniciar uma descarga</string>\n    <string name=\"status_downloaded\">Descarregado</string>\n    <string name=\"all\">Tudo</string>\n    <string name=\"select_multiple_link\">Selecionar a partir de %1$d ligações</string>\n    <string name=\"download_queue\">Fila de descargas</string>\n    <string name=\"show_navigation_drawer\">Mostrar gaveta de navegação</string>\n    <string name=\"resume\">Retomar</string>\n    <string name=\"delete\">Eliminar</string>\n    <string name=\"media_info\">Informações da mídia</string>\n    <string name=\"issue_tracker_hint\">Encontrou um erro? Antes de comunicar um novo problema, procure no nosso registo de problemas. Muitos problemas comuns já foram resolvidos e documentados lá.</string>\n    <string name=\"trouble_shooting\">Solução de problemas</string>\n    <string name=\"issue_tracker\">Rastreador de problemas</string>\n    <string name=\"trouble_shooting_desc\">Correção de erros comuns e verificação de problemas conhecidos</string>\n    <string name=\"saved_urls\">Links salvos</string>\n    <string name=\"add_new_url\">Adicionar novo link</string>\n    <string name=\"add_to\">Adicionar a %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-pt-rBR/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Pasta de Vídeo</string>\n    <string name=\"create_thumbnail\">Salvar miniatura</string>\n    <string name=\"download_settings_desc\">Geral, formato, comando personalizado</string>\n    <string name=\"download\">Download</string>\n    <string name=\"url_empty\">O link não pode estar vazio</string>\n    <string name=\"extract_audio_summary\">Baixar e salvar o áudio ao invés do vídeo</string>\n    <string name=\"create_thumbnail_summary\">Salvar miniatura do vídeo como um arquivo</string>\n    <string name=\"yt_dlp_up_to_date\">Usando a versão mais recente do yt-dlp</string>\n    <string name=\"fetching_info\">Buscando informações do vídeo…</string>\n    <string name=\"permission_denied\">Permissão negada</string>\n    <string name=\"download_error_msg\">O arquivo não pôde ser baixado</string>\n    <string name=\"download_start_msg\">Baixar “%1$s”</string>\n    <string name=\"fetch_info_error_msg\">As informações do vídeo não foram encontradas</string>\n    <string name=\"general_settings\">Geral</string>\n    <string name=\"extract_audio\">Salvar como áudio</string>\n    <string name=\"settings\">Configurações</string>\n    <string name=\"yt_dlp_update_fail\">A última versão do yt-dlp não pôde ser instalada. Por favor verifique sua conexão com a internet.</string>\n    <string name=\"download_success_msg\">Download concluído</string>\n    <string name=\"paste_msg\">Colar URL</string>\n    <string name=\"ytdlp_version\">Versão do Yt-dlp</string>\n    <string name=\"delete_info\">Remover\\?</string>\n    <string name=\"delete_info_msg\">Remover “%1$s” do seu histórico de downloads definitivamente\\?</string>\n    <string name=\"confirm\">Confirmar</string>\n    <string name=\"downloads_history\">Downloads</string>\n    <string name=\"audio\">Áudio</string>\n    <string name=\"link_copied\">Link copiado para a área de transferência</string>\n    <string name=\"open_url\">Abrir link</string>\n    <string name=\"remove\">Remover</string>\n    <string name=\"delete_file\">Excluir arquivo</string>\n    <string name=\"about\">Sobre</string>\n    <string name=\"version\">Versão</string>\n    <string name=\"release\">Versão mais recente</string>\n    <string name=\"readme_desc\">Verifique o repositório no GitHub e o README</string>\n    <string name=\"video\">Vídeo</string>\n    <string name=\"credits\">Créditos</string>\n    <string name=\"credits_desc\">Créditos e software livre</string>\n    <string name=\"custom_command\">Comando Personalizado</string>\n    <string name=\"print_details_desc\">Mostrar mensagens detalhadas ao fazer download</string>\n    <string name=\"display_settings\">Tema, cores, idiomas</string>\n    <string name=\"dark_theme\">Tema escuro</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"settings_before_download_text\">Ajustar este download</string>\n    <string name=\"error_copied\">Relatório de erros copiado para a área de transferência</string>\n    <string name=\"paste\">Colar</string>\n    <string name=\"yt_dlp_docs\">Referências de uso do yt-dlp</string>\n    <string name=\"convert_audio_format\">Converter formato de áudio</string>\n    <string name=\"not_convert\">Não convertido</string>\n    <string name=\"convert_to\">Converter para %1$s</string>\n    <string name=\"format\">Formato</string>\n    <string name=\"best_quality\">Melhor qualidade</string>\n    <string name=\"video_quality_desc\">Limitar a qualidade do vídeo quando outras qualidades estiverem presentes</string>\n    <string name=\"not_specified\">Não especificado (padrão)</string>\n    <string name=\"video_format_preference\">Formato de vídeo preferido</string>\n    <string name=\"start_download\">Download</string>\n    <string name=\"settings_before_download\">Configurar antes de fazer o download</string>\n    <string name=\"ytdlp_update\">Clique para instalar a versão mais recente do yt-dlp</string>\n    <string name=\"about_page\">Versão, feedback, atualização</string>\n    <string name=\"settings_before_download_desc\">Configurar preferências antes de fazer o download</string>\n    <string name=\"convert_audio\">Converter</string>\n    <string name=\"paste_fail_msg\">Não foi possível corresponder ao URL na área de transferência</string>\n    <string name=\"task_running\">Uma tarefa de download existente já está em execução</string>\n    <string name=\"dismiss\">Cancelar</string>\n    <string name=\"video_format\">Formato de vídeo</string>\n    <string name=\"release_desc\">Procurar registros de alterações e novas versões</string>\n    <string name=\"edit_template_desc\">O caminho de saída e a URL serão adicionados pelo aplicativo.</string>\n    <string name=\"convert_audio_format_desc\">A recodificação de arquivos de áudio causará perda na qualidade do áudio e aumento no tamanho do arquivo.</string>\n    <string name=\"video_quality\">Qualidade do vídeo</string>\n    <string name=\"preferred_format_desc\">Formato preferido quando outros formatos estiverem presentes</string>\n    <string name=\"language\">Idioma de exibição</string>\n    <string name=\"language_settings\">Definir idioma de exibição</string>\n    <string name=\"close_never_show_again\">Não mostrar novamente</string>\n    <string name=\"user_guide\">Guia do usuário</string>\n    <string name=\"open_settings\">Abrir configurações</string>\n    <string name=\"paste_desc\">Clique em “Colar” para obter o link do vídeo da sua área de transferência.</string>\n    <string name=\"download_playlist\">Baixar playlist</string>\n    <string name=\"download_playlist_desc\">Baixe vários vídeos de uma playlist</string>\n    <string name=\"defaults\">Padrão</string>\n    <string name=\"channel_name\">Download</string>\n    <string name=\"channel_description\">Notificar sobre o download e arquivos baixados</string>\n    <string name=\"video_url\">Link do vídeo</string>\n    <string name=\"download_finish_notification\">Download concluído. Toque para abrir.</string>\n    <string name=\"execute_command_notification\">Executando comandos personalizados…</string>\n    <string name=\"concurrent_download\">Fragmentos Simultâneos</string>\n    <string name=\"options\">Opções</string>\n    <string name=\"share_success_msg\">Lendo o link do vídeo do conteúdo compartilhado…</string>\n    <string name=\"show_more_actions\">Mostrar mais ações</string>\n    <string name=\"download_notification_desc\">Notificar sobre o download e arquivos baixados</string>\n    <string name=\"fetching_playlist_info\">Buscando informações da playlist…</string>\n    <string name=\"download_range_desc\">Especifique o intervalo de vídeos para download da playlist “%3$s” (de %1$d a %2$d).</string>\n    <string name=\"from\">Início</string>\n    <string name=\"to\">Fim</string>\n    <string name=\"invalid_index_range\">Intervalo de índice inválido</string>\n    <string name=\"playlist_indicator_text\">Fazendo o download da playlist (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Pasta de Áudio</string>\n    <string name=\"download_directory\">Pasta de Download</string>\n    <string name=\"download_directory_desc\">Selecione onde armazenar vídeos e arquivos de áudio</string>\n    <string name=\"subdirectory\">Salvar no subdiretório</string>\n    <string name=\"subdirectory_desc\">Salve arquivos em pastas nomeadas como respectivos campos</string>\n    <string name=\"battery_configuration\">Configuração da bateria</string>\n    <string name=\"download_history_desc\">Verifique e gerencie downloads no aplicativo, incluindo vídeos e arquivos de áudio.</string>\n    <string name=\"download_desc\">Em seguida, clique em “Download” depois de ajustar suas configurações.</string>\n    <string name=\"check_download_settings_desc\">Dê uma olhada nas configurações de download e verifique se você tem a versão mais recente do yt-dlp antes de usá-lo.</string>\n    <string name=\"concurrent_download_desc\">Número de fragmentos de um vídeo nativo em M3U8/MPD para baixar paralelamente</string>\n    <string name=\"permission_issue_desc\">Diretórios fora de Download/ e Documents/ não são suportados</string>\n    <string name=\"battery_settings_desc\">Por favor, defina o uso da bateria deste aplicativo para “Irrestrito” nas configurações do sistema para fazer download em segundo plano.</string>\n    <string name=\"additional_settings\">Configurações adicionais</string>\n    <string name=\"share_fail_msg\">Não foi possível corresponder o URL do conteúdo compartilhado</string>\n    <string name=\"concurrent_download_num\">%d fragmento(s) seriam usados para baixar vídeo nativo DASH/HLS simultaneamente.</string>\n    <string name=\"permission_issue\">Problema de permissão de armazenamento</string>\n    <string name=\"translate\">Traduzir</string>\n    <string name=\"battery_configuration_desc\">Ignorar \\\"Otimização da Bateria\\\" para este aplicativo fazer download em segundo plano</string>\n    <string name=\"unknown_error\">Erro desconhecido</string>\n    <string name=\"translate_desc\">Ajude a traduzir este aplicativo em seu idioma usando Weblate</string>\n    <string name=\"back\">Voltar</string>\n    <string name=\"checked\">Verificado</string>\n    <string name=\"custom_command_desc\">Executar o comando yt-dlp com um modelo personalizado</string>\n    <string name=\"custom_command_template\">Modelo de comando</string>\n    <string name=\"edit\">Editar</string>\n    <string name=\"start_execute\">Iniciar a execução do comando</string>\n    <string name=\"advanced_settings\">Avançado</string>\n    <string name=\"print_details\">Saída detalhada</string>\n    <string name=\"display\">Exibição</string>\n    <string name=\"on\">Ativado</string>\n    <string name=\"off\">Desativado</string>\n    <string name=\"cancel\">Cancelar</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"close\">Fechar</string>\n    <string name=\"download_notification\">Notificação de download</string>\n    <string name=\"download_range_selection\">Seleção de playlist</string>\n    <string name=\"service_title\">Seal está fazendo o download…</string>\n    <string name=\"prefix\">Prefixo</string>\n    <string name=\"open_file\">Abrir arquivo</string>\n    <string name=\"restart\">Reiniciar</string>\n    <string name=\"status_downloading\">Fazendo o download</string>\n    <string name=\"status_error\">Erro</string>\n    <string name=\"copy_link\">Copiar link</string>\n    <string name=\"copy_error_report\">Copiar informação</string>\n    <string name=\"status_fetching_video_info\">Buscando informações</string>\n    <string name=\"status_enqueued\">Enfileirado</string>\n    <string name=\"status_canceled\">Cancelado</string>\n    <string name=\"status_completed\">Concluído</string>\n    <string name=\"embed_subtitles\">Adicionar legendas</string>\n    <string name=\"embed_subtitles_desc\">Adicionar legendas em vídeos, se disponíveis</string>\n    <string name=\"new_template\">Novo modelo</string>\n    <string name=\"template_label\">Título</string>\n    <string name=\"remove_template\">Remover\\?</string>\n    <string name=\"remove_template_desc\">Remover %1$s dos modelos de comandos?</string>\n    <string name=\"template_selection\">Seleção de modelos</string>\n    <string name=\"custom_command_template_desc\">Editar e gerenciar modelos de comandos</string>\n    <string name=\"downloading_indicator_text\">Download em andamento…</string>\n    <string name=\"task_canceled\">Tarefa de download cancelada</string>\n    <string name=\"github_issue\">Relatórios do GitHub</string>\n    <string name=\"github_issue_desc\">Envie um problema para relatório de bug ou solicitação de recursos</string>\n    <string name=\"info_copied\">Informação copiada para a área de transferência</string>\n    <string name=\"video_resolution\">Resolução do vídeo</string>\n    <string name=\"video_file_size\">Tamanho do arquivo de vídeo</string>\n    <string name=\"import_from_clipboard\">Importar da área de transferência</string>\n    <string name=\"template_imported\">%1$d modelo(s) importado(s)</string>\n    <string name=\"download_task_count\">%1$d tarefa(s) de download(s)</string>\n    <string name=\"recently_added\">Adicionado recentemente</string>\n    <string name=\"multiselect_item_count\">%1$d vídeo(s), %2$d arquivo(s) de áudio</string>\n    <string name=\"delete_multiple_items_msg\">Remover %1$d item(s) do seu histórico de downloads\\?</string>\n    <string name=\"template_exported\">Exportado %1$d modelo(s)</string>\n    <string name=\"export_to_clipboard\">Exportar para a área de transferência</string>\n    <string name=\"check_for_updates\">Buscar atualizações</string>\n    <string name=\"check_for_updates_desc\">Verificar automaticamente a versão mais recente no GitHub</string>\n    <string name=\"app_up_to_date\">Você já possui a atualização mais recente</string>\n    <string name=\"app_update_failed\">Falha ao atualizar para a versão mais recente</string>\n    <string name=\"update\">Atualizar</string>\n    <string name=\"aria2_desc\">Usar aria2c como provedor de download padrão</string>\n    <string name=\"cookies_desc\">Usar cookies formatados do Netscape para download</string>\n    <string name=\"clear_temp_files\">Remover arquivos temporários</string>\n    <string name=\"clear_temp_files_desc\">Excluir todos os arquivos temporários do diretório temporário</string>\n    <string name=\"clear_temp_files_count\">%1$d arquivo(s) temporário(s) removido(s)</string>\n    <string name=\"multiselect_mode\">Modo multi-seleção</string>\n    <string name=\"clear_temp_files_info\">Arquivos temporários podem ser usados para retomar downloads cancelados. Tem certeza de que deseja excluir todos esses arquivos\\?\n\\n\n\\nVocê pode acessar esses arquivos em %1$s</string>\n    <string name=\"sponsorblock_categories_desc\">Especifique as categorias SponsorBlock para remover ou marcar no arquivo de vídeo</string>\n    <string name=\"sponsorblock_categories\">Categorias do SponsorBlock</string>\n    <string name=\"sponsorblock_desc\">Remover ou marcar segmentos em vídeos com a API SponsorBlock</string>\n    <string name=\"high_contrast\">Tema escuro de alto contraste</string>\n    <string name=\"invalid_input\">Entrada inválida</string>\n    <string name=\"lowest_quality\">Menor qualidade</string>\n    <string name=\"private_mode\">Anônimo</string>\n    <string name=\"private_mode_desc\">Faça o download sem adicionar no histórico</string>\n    <string name=\"dynamic_color\">Cor dinâmica</string>\n    <string name=\"dynamic_color_desc\">Aplicar cores do papel de parede ao tema do aplicativo</string>\n    <string name=\"file_unavailable\">Esse arquivo não está mais disponível</string>\n    <string name=\"network\">Rede</string>\n    <string name=\"rate_limit\">Limite de conexão</string>\n    <string name=\"rate_limit_desc\">Limitar velocidade máxima de download</string>\n    <string name=\"max_rate\">Taxa máxima</string>\n    <string name=\"unavailable\">Indisponível</string>\n    <string name=\"format_settings_desc\">Formato, qualidade, legendas</string>\n    <string name=\"general_settings_desc\">Versão do yt-dlp, notificação, playlist</string>\n    <string name=\"disable_preview\">Desativar pré-visualização</string>\n    <string name=\"disable_preview_desc\">Desativar pré-visualização em downloads</string>\n    <string name=\"privacy\">Privacidade</string>\n    <string name=\"network_settings_desc\">Limite de conexão, provedor de download, cookies</string>\n    <string name=\"private_directory\">Diretório privado</string>\n    <string name=\"private_directory_desc\">Armazenar downloads em um diretório oculto</string>\n    <string name=\"crop_artwork_desc\">Recortar miniatura em um quadrado</string>\n    <string name=\"crop_artwork\">Cortar miniatura</string>\n    <string name=\"download_with_cellular_desc\">Permite fazer o download quando conectado na rede móvel</string>\n    <string name=\"download_disabled_with_cellular\">O download com a rede móvel está desabilitado de acordo com suas configurações</string>\n    <string name=\"use_custom_command\">Usar comando personalizado</string>\n    <string name=\"download_with_cellular\">Fazer download usando a rede móvel</string>\n    <string name=\"select_all\">Selecionar tudo</string>\n    <string name=\"download_selection_desc\">Selecionar vídeos para fazer o download da playlist “%1$s”</string>\n    <string name=\"selected_item_count\">%1$d selecionado(s)</string>\n    <string name=\"unlimited\">Ilimitado</string>\n    <string name=\"lowest_bitrate\">Taxa de bits mais baixa</string>\n    <string name=\"format_sorting_desc\">Classificando formatos com a opção -S de yt-dlp</string>\n    <string name=\"import_from_preferences\">Importar</string>\n    <string name=\"title\">Título</string>\n    <string name=\"rename\">Renomear</string>\n    <string name=\"second\">segundo</string>\n    <string name=\"minute\">minuto</string>\n    <string name=\"clear_all_cookies\">Remover todos os cookies</string>\n    <string name=\"clear_all_cookies_desc\">Excluir todos os cookies armazenados no aplicativo\\?</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"format_selection\">Seleção de formato</string>\n    <string name=\"generate_new_cookies\">Gerar novos cookies</string>\n    <string name=\"video_only\">Vídeo (sem áudio)</string>\n    <string name=\"format_selection_desc\">Selecione o formato a ser baixado antes de iniciar o download</string>\n    <string name=\"subtitle_sponsorblock\">As legendas podem ser mal cronometradas ao remover segmentos do SponsorBlock.</string>\n    <string name=\"share\">Compartilhar</string>\n    <string name=\"stable_channel\">Estável</string>\n    <string name=\"pre_release_channel\">Pré-lançamento</string>\n    <string name=\"update_channel_desc\">Instale compilações de pré-lançamento para visualizar novos recursos e alterações.\n\\n\n\\nHaverá alguma instabilidade nessas versões, portanto, não hesite em nos enviar feedback se tiver algum problema para nos ajudar a melhorar o aplicativo para o futuro.</string>\n    <string name=\"update_channel\">Canal de atualização</string>\n    <string name=\"auto_update\">Atualização automática</string>\n    <string name=\"enable_auto_update\">Ativar atualização automática</string>\n    <string name=\"logs\">Log</string>\n    <string name=\"matrix_space\">Espaço no Matrix</string>\n    <string name=\"abs_hint\">A maioria das plataformas de streaming de vídeo oferece áudio e vídeo separadamente, você pode selecionar e mesclar um formato somente de áudio com um formato somente de vídeo em um único vídeo.</string>\n    <string name=\"discard\">Descartar</string>\n    <string name=\"apply\">Aplicar</string>\n    <string name=\"clip_video\">Cortar vídeo</string>\n    <string name=\"clip_start\">Início</string>\n    <string name=\"clip_end\">Fim</string>\n    <string name=\"suggested\">Sugerido</string>\n    <string name=\"how_does_it_work\">Como funciona\\?</string>\n    <string name=\"use_cookies\">Usar cookies</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Remover esta entrada para \\\"%1$s\\\"? Observe que os cookies armazenados neste site não serão apagados.</string>\n    <string name=\"custom_command_enabled_hint\">Algumas opções não estão disponíveis ao usar o comando personalizado</string>\n    <string name=\"telegram_channel\">Canal do Telegram</string>\n    <string name=\"sdcard_directory\">Pasta do cartão SD</string>\n    <string name=\"auto_subtitle\">Legendas automáticas</string>\n    <string name=\"auto_subtitle_desc\">Baixar legendas geradas automaticamente</string>\n    <string name=\"title_activity_share\">Download rápido</string>\n    <string name=\"video_title_sample_text\">Texto de amostra do título do vídeo</string>\n    <string name=\"video_creator_sample_text\">Texto de amostra do criador de vídeo</string>\n    <string name=\"subtitle\">Legenda</string>\n    <string name=\"download_subtitles\">Baixar legenda</string>\n    <string name=\"subtitle_language\">Idiomas das legendas</string>\n    <string name=\"copy_log\">Copiar log</string>\n    <string name=\"clear\">Limpar</string>\n    <string name=\"add\">Adicionar</string>\n    <string name=\"shortcuts\">Atalhos</string>\n    <string name=\"running_tasks\">Tarefas em execução</string>\n    <string name=\"show_logs\">Mostrar log</string>\n    <string name=\"embed_subtitles_mkv_msg\">Para incorporar legendas, os vídeos serão remixados no contêiner mkv. Você pode usar o VLC Media Player ou outros aplicativos compatíveis para assistir a vídeos com legendas incorporadas.</string>\n    <string name=\"cookies_usage_msg\">O download de alguns sites requer informações de autenticação de conta. Clique em \\\"Gerar novos cookies\\\", digite o URL do site e faça login com sua conta na página do navegador, o aplicativo irá gerá-lo para você.</string>\n    <string name=\"subtitle_desc\">Idiomas, legendas incorporadas, legendas automáticas</string>\n    <string name=\"edit_shortcuts\">Editar atalhos</string>\n    <string name=\"edit_shortcuts_desc\">Edite os atalhos personalizados que podem ser usados para compor modelos de comando.</string>\n    <string name=\"audio_quality_desc\">Limite a taxa de bits de áudio quando várias qualidades estiverem presentes</string>\n    <string name=\"audio_format_preference\">Formato de áudio preferido</string>\n    <string name=\"audio_quality\">Qualidade do áudio</string>\n    <string name=\"format_sorting\">Classificação de formatos</string>\n    <string name=\"sponsors\">Patrocinadores</string>\n    <string name=\"sponsor_desc\">Apoie este aplicativo patrocinando no GitHub</string>\n    <string name=\"sponsor\">Patrocinar</string>\n    <string name=\"temporary_directory_desc\">Armazenar arquivos temporários no diretório interno</string>\n    <string name=\"feedback\">Feedback</string>\n    <string name=\"sponsor_msg\">Seal sempre será livre e de código aberto para todos. Se você gostou, por favor, considere me patrocinar no GitHub!</string>\n    <string name=\"audio_format\">Formato de áudio</string>\n    <string name=\"no_downloaded_media\">Nenhuma mídia baixada</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Ativar recurso experimental\\?</string>\n    <string name=\"clip_video_desc\">Faça cortes nos vídeos na página de seleção de formato</string>\n    <string name=\"clip_video_dialog_msg\">Downloads usando este recurso serão delegados ao FFmpeg para baixar seções selecionadas do vídeo, este recurso ainda é experimental e o corte não será totalmente preciso, nem todos os formatos.</string>\n    <string name=\"switch_to_github_builds\">Mudando para versões no GitHub</string>\n    <string name=\"okay\">Certo</string>\n    <string name=\"got_it\">Entendi</string>\n    <string name=\"feature_unavailable\">Recurso não disponível</string>\n    <string name=\"auto_update_disabled_msg\">A atualização automática não está disponível para as versões do %1$s. Se você não tem o %1$s instalado em seu dispositivo, ou gostaria de visualizar novos recursos em desenvolvimento no aplicativo Seal, por favor, considere %2$s.</string>\n    <string name=\"sponsor_msg2\">Muito obrigado!</string>\n    <string name=\"msg_from_developer\">Mensagem do desenvolvedor</string>\n    <string name=\"convert_subtitle\">Converter legendas</string>\n    <string name=\"convert_subtitle_desc\">Converter legendas para outro formato</string>\n    <string name=\"split_video\">Dividir vídeo</string>\n    <string name=\"split_video_msg\">O vídeo será dividido em %1$d capítulos</string>\n    <string name=\"unknown_error_title\">Oops! Algo deu errado</string>\n    <string name=\"copy_and_exit\">Copiar e sair</string>\n    <string name=\"no_custom_command_tasks\">Nenhuma tarefa de comando personalizada</string>\n    <string name=\"download_video_desc\">Fazer download dos vídeos do URL</string>\n    <string name=\"new_task\">Nova tarefa de download</string>\n    <string name=\"edit_template\">Editar \\\"%1$s\\\"</string>\n    <string name=\"expand\">Expandir</string>\n    <string name=\"start\">Iniciar</string>\n    <string name=\"ytdlp_update_action\">Atualizar yt-dlp</string>\n    <string name=\"proxy_desc\">Usar proxy para conexões de internet</string>\n    <string name=\"disable\">Desativar</string>\n    <string name=\"set_directory_desc\">Toque para configurar o diretório</string>\n    <string name=\"custom_command_directory\">Pasta de comando personalizado</string>\n    <string name=\"disabled\">Desabilitado</string>\n    <string name=\"folder_picker\">Selecionar pasta</string>\n    <string name=\"custom_command_directory_desc\">Especifique o diretório de saída ao usar comandos personalizados</string>\n    <string name=\"prefer_quality_desc\">Preferir formatos AV1, VP9 ou H.265 para assistir em aplicativos compatíveis</string>\n    <string name=\"legacy\">Legado</string>\n    <string name=\"quality\">Melhor formato</string>\n    <string name=\"enable_notifications\">Ativar notificações\\?</string>\n    <string name=\"enable_notifications_desc\">O aplicativo precisa da sua permissão para postar notificações sobre o status e o progresso do download.</string>\n    <string name=\"prefer_compatibility_desc\">Preferir formatos MP4(H.264) para compartilhar com outros aplicativos</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"download_type\">Tipo de download</string>\n    <string name=\"custom\">Personalizado</string>\n    <string name=\"commands\">Comando</string>\n    <string name=\"format_preference\">Preferência de formato</string>\n    <string name=\"learn_more\">Saber mais</string>\n    <string name=\"unknown\">Desconhecido</string>\n    <string name=\"auto\">Automático</string>\n    <string name=\"refresh_cookies_desc\">Toque para abrir a página da web para gerar novos cookies:</string>\n    <string name=\"remove_multiple_templates_msg\">Remover %1$s dos modelos de comando\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d item</item>\n        <item quantity=\"many\">%d itens</item>\n        <item quantity=\"other\">%d itens</item>\n    </plurals>\n    <string name=\"ua_header\">Cabeçalho de requisição User-Agent</string>\n    <string name=\"export_to_file\">Exportar como arquivo</string>\n    <string name=\"custom_command_usage_msg\">O yt-dlp é uma poderosa ferramenta de linha de comando para fazer download de vídeos. Seal facilita o uso do yt-dlp, fornecendo uma GUI intuitiva, predefinições para comandos comuns e outros recursos adicionais.\n\\n\n\\nPara uso avançado do yt-dlp, o Seal permite criar, salvar e executar modelos de comandos personalizados diretamente, como em um terminal.\n\\n\n\\nAo usar comandos personalizados, a maioria das opções e recursos da GUI seriam desabilitados.</string>\n    <string name=\"presets\">Predefinições</string>\n    <string name=\"output_template\">Modelo de saída</string>\n    <string name=\"output_template_desc\">Especificar o modelo para nomes de arquivos de saída</string>\n    <string name=\"clear_download_archive\">Limpar arquivamento de download?</string>\n    <string name=\"clear_download_archive_desc\">Remover %1$s do arquivamento de download?</string>\n    <string name=\"download_archive_desc\">Salvar IDs dos vídeos baixados para evitar downloads duplicados</string>\n    <string name=\"download_archive\">Arquivar downloads</string>\n    <string name=\"embed_metadata\">Incorporar metadados</string>\n    <string name=\"embed_metadata_desc\">Incorporar metadados e miniaturas de vídeo no arquivo de áudio</string>\n    <string name=\"required\">Obrigatório</string>\n    <string name=\"show_all_items\">Mostrar todos os %1$d itens</string>\n    <string name=\"save\">Salvar</string>\n    <string name=\"use_format_sorting\">Usar classificação de formato</string>\n    <string name=\"edit_file\">Editar arquivo</string>\n    <string name=\"restrict_filenames_desc\">Limite os nomes dos arquivos a caracteres específicos para garantir a compatibilidade</string>\n    <string name=\"restrict_filenames\">Restringir nomes de arquivos</string>\n    <string name=\"website\">Site</string>\n    <string name=\"playlist_title\">Título da playlist</string>\n    <string name=\"subdirectory_hint\">Seus downloads serão salvos como:</string>\n    <string name=\"system_settings\">Configurações do sistema</string>\n    <string name=\"force_ipv4\">Forçar IPv4</string>\n    <string name=\"force_ipv4_desc\">Efetuar todas as conexões com IPv4</string>\n    <string name=\"keep_subtitle_files\">Manter arquivos de legenda</string>\n    <string name=\"allow_once\">Permitir uma vez</string>\n    <string name=\"merge_audiostream\">Mesclar vários fluxos de áudio</string>\n    <string name=\"allow_always\">Sempre permitir</string>\n    <string name=\"dont_allow\">Não permitir</string>\n    <string name=\"download_with_cellular_request\">Permitir download através da rede móvel?</string>\n    <string name=\"merge_audiostream_desc\">Permitir que vários fluxos de áudio sejam mesclados em um único arquivo</string>\n    <string name=\"search_in_downloads\">Pesquisar em downloads</string>\n    <string name=\"search\">Pesquisar</string>\n    <string name=\"remember_for_next_download\">Lembrar próximo download</string>\n    <string name=\"use_previous_selection\">Usar seleção anterior</string>\n    <string name=\"none\">Nenhum</string>\n    <string name=\"look_and_feel\">Veja &amp; Sinta</string>\n    <string name=\"auto_translated_subtitles_msg\">Legendas traduzidas automaticamente para todos os idiomas estarão disponíveis para download. Essas legendas podem ser imprecisas e difíceis de entender.</string>\n    <string name=\"subtitle_language_desc\">Idioma das legendas para download em seleção automática de formato, separadas por vírgulas.</string>\n    <string name=\"auto_translated_subtitles\">Legendas traduzidas automaticamente</string>\n    <string name=\"reset\">Reiniciar</string>\n    <string name=\"search_in_subtitles\">Pesquisar nas legendas</string>\n    <string name=\"no_thanks\">Não, obrigado</string>\n    <string name=\"update_subtitle_languages\">Atualizar idiomas das legendas?</string>\n    <string name=\"update_language_msg\">Os seguintes idiomas serão adicionados à sua preferência para downloads futuros:</string>\n    <string name=\"export_to\">Exportar para</string>\n    <string name=\"backup_type\">Tipo de Backup</string>\n    <string name=\"interface_and_interaction\">Interface &amp; Interação</string>\n    <string name=\"export_backup\">Exportar</string>\n    <string name=\"import_backup\">Importar</string>\n    <string name=\"full_backup\">Backup completo</string>\n    <string name=\"file\">Arquivo</string>\n    <string name=\"clipboard\">Área de transferência</string>\n    <string name=\"import_from\">Importar de</string>\n    <string name=\"export_download_history\">Exportar histórico de downloads?</string>\n    <string name=\"import_download_history_msg\">Os arquivos baixados não serão importados. Você precisará baixá-los de volta manualmente</string>\n    <string name=\"download_history\">Histórico de downloads</string>\n    <string name=\"import_download_history\">Importar histórico de downloads?</string>\n    <string name=\"export_download_history_msg\">Exportando %1$s do histórico de downloads. Os arquivos baixados e as preferências não serão exportados.</string>\n    <string name=\"redownload\">Baixar novamente</string>\n    <string name=\"download_history_imported\">Importou %1$s para o histórico de downloads</string>\n    <string name=\"download_archive_error\">O vídeo foi baixado. Se este não for o comportamento esperado, verifique o arquivamento de download.</string>\n    <string name=\"remux_container_mkv\">Contêiner de vídeo Remux</string>\n    <string name=\"remux_container_mkv_desc\">Remuxar vídeos em contêiner MKV para melhor compatibilidade</string>\n    <string name=\"cookies_in_database\">%1$d cookies de %2$d sites no total</string>\n    <string name=\"every_week\">Semanalmente</string>\n    <string name=\"every_month\">Mensalmente</string>\n    <string name=\"every_day\">Diariamente</string>\n    <string name=\"all_languages\">Todos os idiomas</string>\n    <string name=\"proceed\">Continuar</string>\n    <string name=\"playlist\">Playlist</string>\n    <string name=\"edit_preset\">Editar predefinição</string>\n    <string name=\"best_quality_desc\">Faça o download do melhor formato disponível</string>\n    <string name=\"preset\">Predefinição</string>\n    <string name=\"prefer_placeholder\">Preferir %1$s</string>\n    <string name=\"custom_format_selection_desc\">Escolha entre formatos, legendas e personalize ainda mais</string>\n    <string name=\"preset_format_selection_desc\">Faça o download automaticamente usando suas preferências de formato</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d vídeo</item>\n        <item quantity=\"many\">%d vídeos</item>\n        <item quantity=\"other\">%d vídeos</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d áudio</item>\n        <item quantity=\"many\">%d áudios</item>\n        <item quantity=\"other\">%d áudios</item>\n    </plurals>\n    <string name=\"task_added\">Tarefa adicionada à fila</string>\n    <string name=\"you_ll_find_your_downloads_here\">Você encontrará seus downloads aqui</string>\n    <string name=\"download_hint\">Toque no botão de download ou compartilhe um link de vídeo com este aplicativo para iniciar o download</string>\n    <string name=\"status_downloaded\">Download concluído</string>\n    <string name=\"all\">Todos</string>\n    <string name=\"download_queue\">Fila de downloads</string>\n    <string name=\"select_multiple_link\">Selecionar entre %1$d links</string>\n    <string name=\"show_navigation_drawer\">Mostrar menu de navegação</string>\n    <string name=\"delete\">Excluir</string>\n    <string name=\"resume\">Continuar</string>\n    <string name=\"media_info\">Informações da mídia</string>\n    <string name=\"trouble_shooting\">Solução de problemas</string>\n    <string name=\"trouble_shooting_desc\">Corrigir erros comuns e verificar se há problemas conhecidos</string>\n    <string name=\"issue_tracker_hint\">Encontrou um erro? Antes de informar um novo problema, pesquise em nosso rastreador de problemas. Muitos problemas comuns já foram resolvidos e documentados lá.</string>\n    <string name=\"issue_tracker\">Rastreador de problemas</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-pt-rPT/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"delete_file\">Eliminar ficheiro</string>\n    <string name=\"template_imported\">Modelo(s) importado(s) %1$d</string>\n    <string name=\"video_resolution\">Resolução de vídeo</string>\n    <string name=\"switch_to_github_builds\">mudar para compilações do GitHub</string>\n    <string name=\"download_directory_desc\">Selecionar onde guardar vídeos e ficheiros de áudio</string>\n    <string name=\"subdirectory\">Guardar no subdiretório</string>\n    <string name=\"dismiss\">Cancelar</string>\n    <string name=\"download_directory\">Diretório de transferência</string>\n    <string name=\"custom_command_usage_msg\">O yt-dlp é uma poderosa ferramenta de linha de comando para descarregar vídeos. O Seal facilita o uso do yt-dlp fornecendo uma GUI intuitiva, predefinições para comandos comuns e outros recursos adicionais.\n\\n\n\\nPara uma utilização avançada do yt-dlp, o Seal permite-lhe criar, guardar e executar modelos de comandos personalizados diretamente, tal como num terminal.\n\\n\n\\nAo usar comandos personalizados, a maioria das opções e recursos da GUI serão desativados.</string>\n    <string name=\"status_enqueued\">Enfileirado</string>\n    <string name=\"advanced_settings\">Avançado</string>\n    <string name=\"clear_download_archive\">Limpar o arquivo de download?</string>\n    <string name=\"clip_start\">Início</string>\n    <string name=\"max_rate\">Taxa máxima</string>\n    <string name=\"embed_subtitles_desc\">Incorporar legendas fornecidas nos vídeos, se disponíveis</string>\n    <string name=\"close\">Fechar</string>\n    <string name=\"dynamic_color_desc\">Aplicar cores dos papéis de parede ao tema da aplicação</string>\n    <string name=\"rate_limit_desc\">Limitar velocidade máxima de descarga</string>\n    <string name=\"save\">Guardar</string>\n    <string name=\"print_details\">Saída detalhada</string>\n    <string name=\"user_guide\">Guia do utilizador</string>\n    <string name=\"logs\">Registo</string>\n    <string name=\"split_video_msg\">O vídeo será dividido em %1$d capítulos</string>\n    <string name=\"remove_cookie_profile_desc\">Remover esta entrada para \\\"%1$s\\\"? Observe que os cookies armazenados neste site não serão apagados.</string>\n    <string name=\"audio_quality\">Qualidade do áudio</string>\n    <string name=\"invalid_input\">Entrada inválida</string>\n    <string name=\"audio_format\">Formato de áudio</string>\n    <string name=\"delete_multiple_items_msg\">Remover %1$d item(ns) do seu histórico de transferências para sempre?</string>\n    <string name=\"title\">Título</string>\n    <string name=\"video_format_preference\">Formato de vídeo preferido</string>\n    <string name=\"use_cookies\">Utilizar cookies</string>\n    <string name=\"export_to_file\">Exportar para ficheiro</string>\n    <string name=\"stable_channel\">Estável</string>\n    <string name=\"enable_notifications_desc\">A aplicação necessita da sua permissão para publicar notificações sobre o estado e o progresso da transferência.</string>\n    <string name=\"folder_picker\">Seleção de pastas</string>\n    <string name=\"no_downloaded_media\">Nenhuma media descarregada</string>\n    <string name=\"multiselect_mode\">Modo de seleção múltipla</string>\n    <string name=\"link_copied\">Ligação copiada para a área de transferência</string>\n    <string name=\"update_channel_desc\">Instale versões de pré-lançamento para pré-visualizar novas funcionalidades e alterações.\n\\n\n\\nEstas versões apresentam alguma instabilidade, pelo que não hesite em dar-nos a sua opinião se tiver algum problema para nos ajudar a melhorar a aplicação no futuro.</string>\n    <string name=\"subdirectory_hint\">As suas transferências serão guardadas como:</string>\n    <string name=\"edit_shortcuts_desc\">Editar os atalhos personalizados que podem ser utilizados para compor modelos de comandos.</string>\n    <string name=\"video_only\">Vídeo (sem áudio)</string>\n    <string name=\"split_video\">Dividir o vídeo</string>\n    <string name=\"credits_desc\">Créditos e software livre</string>\n    <string name=\"prefer_compatibility_desc\">Prefira os formatos MP4 (H.264) para partilhar com outras aplicações</string>\n    <string name=\"download_video_desc\">Descarregar vídeos a partir do URL</string>\n    <string name=\"commands\">Comandos</string>\n    <string name=\"readme_desc\">Verifique o repositório GitHub e o README</string>\n    <string name=\"video_file_size\">Tamanho do ficheiro de vídeo</string>\n    <string name=\"disable_preview\">Desativar a pré-visualização</string>\n    <string name=\"from\">Iniciar</string>\n    <string name=\"clip_video_dialog_msg\">Os downloads que utilizem esta funcionalidade serão delegados ao FFmpeg para descarregar secções seleccionadas do vídeo. Esta funcionalidade ainda é experimental e o corte não será totalmente exato, nem todos os formatos suportam esta funcionalidade e poderá ter velocidades de download mais lentas.</string>\n    <string name=\"remove_template_desc\">Remover \\\"%1$s\\\" dos modelos de comando para sempre?</string>\n    <string name=\"custom_command_enabled_hint\">Algumas opções não estão disponíveis quando se utiliza o comando personalizado</string>\n    <string name=\"clear_download_archive_desc\">Remover %1$s do arquivo de download?</string>\n    <string name=\"new_template\">Novo modelo</string>\n    <string name=\"remove\">Remover</string>\n    <string name=\"download_disabled_with_cellular\">O descarregamento com a rede celular está desativado de acordo com as suas definições</string>\n    <string name=\"embed_subtitles\">Incorporar legendas</string>\n    <string name=\"disable_preview_desc\">Não apresentação de miniaturas durante a transferência</string>\n    <string name=\"format_selection_desc\">Seleccione o formato a transferir antes de iniciar a transferência</string>\n    <string name=\"clip_end\">Fim</string>\n    <string name=\"edit_template\">Editar \\\"%1$s\\\"</string>\n    <string name=\"remove_template\">Remover?</string>\n    <string name=\"website\">Sítio</string>\n    <string name=\"auto_subtitle_desc\">Descarregar legendas geradas automaticamente</string>\n    <string name=\"selected_item_count\">%1$d selecionado(s)</string>\n    <string name=\"custom_command_desc\">Executar o comando yt-dlp com modelo personalizado</string>\n    <string name=\"unavailable\">Não disponível</string>\n    <string name=\"ytdlp_update\">Clique para instalar a versão mais recente do yt-dlp</string>\n    <string name=\"suggested\">Sugerido</string>\n    <string name=\"high_contrast\">Tema escuro de alto contraste</string>\n    <string name=\"template_selection\">Seleção do modelo</string>\n    <string name=\"fetching_playlist_info\">Obter informações sobre a lista de reprodução…</string>\n    <string name=\"check_download_settings_desc\">Consulte as definições de transferência e certifique-se de que tem a versão mais recente do yt-dlp antes de o utilizar.</string>\n    <string name=\"translate\">Traduzir</string>\n    <string name=\"extract_audio_summary\">Descarregar e guardar áudio, em vez de vídeo</string>\n    <string name=\"subdirectory_desc\">Guardar ficheiros em pastas com o nome dos respectivos campos</string>\n    <string name=\"cookies_desc\">Utilizar cookies formatados pelo Netscape para transferências</string>\n    <string name=\"copy_error_report\">Copiar relatório</string>\n    <string name=\"clear\">Limpar</string>\n    <string name=\"unknown\">Desconhecido</string>\n    <string name=\"paste_fail_msg\">Não foi possível fazer corresponder o URL na área de transferência</string>\n    <string name=\"download_subtitles\">Descarregar legendas</string>\n    <string name=\"lowest_quality\">Qualidade mais baixa</string>\n    <string name=\"learn_more\">Saiba mais</string>\n    <string name=\"preferred_format_desc\">Formato preferido quando são fornecidos vários</string>\n    <string name=\"download_playlist\">Descarregar lista de reprodução</string>\n    <string name=\"paste_desc\">Clique em \\\"Colar\\\" para obter a ligação do vídeo da sua área de transferência.</string>\n    <string name=\"general_settings_desc\">Versão yt-dlp, notificação, lista de reprodução</string>\n    <string name=\"rename\">Renomear</string>\n    <string name=\"convert_subtitle\">Converter legendas</string>\n    <string name=\"aria2_desc\">Utilizar aria2c como descarregador externo</string>\n    <string name=\"prefer_quality_desc\">Prefira os formatos AV1, VP9 ou H.265 para ver em aplicações compatíveis</string>\n    <string name=\"download_with_cellular\">Descarregar utilizando o telemóvel</string>\n    <string name=\"copy_log\">Copiar registo</string>\n    <string name=\"on\">Ligado</string>\n    <string name=\"download_settings_desc\">Geral, formato, comando personalizado</string>\n    <string name=\"yt_dlp_docs\">Referências de utilização do Yt-dlp</string>\n    <string name=\"edit\">Editar</string>\n    <string name=\"download_type\">Tipo de transferência</string>\n    <string name=\"paste_msg\">Colar URL</string>\n    <string name=\"apply\">Aplicar</string>\n    <string name=\"legacy\">Legado</string>\n    <string name=\"clip_video_desc\">Criar cortes de vídeo na página de seleção de formato</string>\n    <string name=\"convert_audio\">Converter</string>\n    <string name=\"unknown_error_title\">Ops! Algo correu mal</string>\n    <string name=\"update\">Atualização</string>\n    <string name=\"video_quality\">Qualidade do vídeo</string>\n    <string name=\"unlimited\">Ilimitado</string>\n    <string name=\"video_url\">Ligação vídeo</string>\n    <string name=\"edit_shortcuts\">Editar atalhos</string>\n    <string name=\"display_settings\">Tema escuro, cor dinâmica, línguas</string>\n    <string name=\"settings_before_download_desc\">Configurar as preferências antes de descarregar</string>\n    <string name=\"release_desc\">Procurar registos de alterações e novas versões</string>\n    <string name=\"how_does_it_work\">Como funciona?</string>\n    <string name=\"got_it\">Entendi</string>\n    <string name=\"permission_issue_desc\">Os directórios fora de Download/ e Documents/ não são suportados</string>\n    <string name=\"channel_description\">Notificação dos ficheiros descarregados e do seu progresso</string>\n    <string name=\"embed_metadata\">Incorporar metadados</string>\n    <string name=\"downloading_indicator_text\">Descarregamento em curso…</string>\n    <string name=\"custom_command_directory\">Diretório de comandos personalizado</string>\n    <string name=\"ytdlp_version\">Versão Yt-dlp</string>\n    <string name=\"format_selection\">Seleção do formato</string>\n    <string name=\"display\">Ecrã</string>\n    <string name=\"custom_command_directory_desc\">Especificar o diretório de saída quando se utilizam comandos personalizados</string>\n    <string name=\"use_format_sorting\">Utilizar a ordenação de formatos</string>\n    <string name=\"feedback\">Feedback</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"permission_issue\">Problema de permissão de armazenamento</string>\n    <string name=\"off\">Desligado</string>\n    <string name=\"network_settings_desc\">Limite de velocidade, descarregador, cookies</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"download_notification\">Notificação de descarregamento</string>\n    <string name=\"prefix\">Prefixo</string>\n    <string name=\"clear_all_cookies\">Limpar todos os cookies</string>\n    <string name=\"start_download\">Descarregar</string>\n    <string name=\"presets\">Predefinições</string>\n    <string name=\"second\">segundo</string>\n    <string name=\"error_copied\">Relatório de erro copiado para a área de transferência</string>\n    <string name=\"set_directory_desc\">Toque para definir o diretório</string>\n    <string name=\"update_channel\">Canal de atualização</string>\n    <string name=\"back\">Atrás</string>\n    <string name=\"downloads_history\">Transferências</string>\n    <string name=\"release\">Versão mais recente</string>\n    <string name=\"download_desc\">Em seguida, clique em \\\"Descarregar\\\" depois de ajustar as definições.</string>\n    <string name=\"audio_directory\">Pasta áudio</string>\n    <string name=\"sponsor_msg\">O Seal será sempre gratuito e de código aberto para todos. Se gostar, por favor considere patrocinar-me no GitHub!</string>\n    <string name=\"crop_artwork\">Cortar arte</string>\n    <string name=\"subtitle_sponsorblock\">As legendas podem ser desfasadas no tempo ao remover segmentos SponsorBlock.</string>\n    <string name=\"start\">Iniciar</string>\n    <string name=\"to\">Terminar</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"sponsor_msg2\">Muito obrigado!</string>\n    <string name=\"task_canceled\">Descarregar tarefa cancelada</string>\n    <string name=\"sponsor_desc\">Apoie esta aplicação patrocinando-a no GitHub</string>\n    <string name=\"version\">Versão</string>\n    <string name=\"yt_dlp_update_fail\">Não foi possível instalar a versão mais recente do yt-dlp. Certifique-se de que está ligado à Internet.</string>\n    <string name=\"enable_experimental_feature\">Ativar a funcionalidade experimental?</string>\n    <string name=\"running_tasks\">Tarefas em curso</string>\n    <string name=\"general_settings\">Geral</string>\n    <string name=\"service_title\">O Seal está a descarregar…</string>\n    <string name=\"ua_header\">Cabeçalho de requisição User-Agent</string>\n    <string name=\"show_logs\">Mostrar registo</string>\n    <string name=\"print_details_desc\">Imprimir mensagens detalhadas durante o descarregamento</string>\n    <string name=\"restrict_filenames_desc\">Limitar os nomes de ficheiros a caracteres específicos para garantir a compatibilidade</string>\n    <string name=\"download_with_cellular_desc\">Permitir o descarregamento de multimédia quando ligado a redes com contador</string>\n    <string name=\"discard\">Descartar</string>\n    <string name=\"sdcard_directory\">Pasta do cartão SD</string>\n    <string name=\"open_settings\">Abrir definições</string>\n    <string name=\"download_history_desc\">Verificar e gerir as transferências na aplicação, incluindo vídeos e ficheiros de áudio.</string>\n    <string name=\"download_success_msg\">Descarga concluída</string>\n    <string name=\"audio_format_preference\">Formato áudio preferido</string>\n    <string name=\"new_task\">Nova tarefa de transferência</string>\n    <string name=\"copy_and_exit\">Copiar e sair</string>\n    <string name=\"clear_temp_files_info\">Os ficheiros temporários podem ser utilizados para retomar as transferências canceladas. Tem a certeza de que eliminou todos estes ficheiros?\n\\n\n\\nPode aceder a estes ficheiros em %1$s</string>\n    <string name=\"video_format\">Formato de vídeo</string>\n    <string name=\"private_directory_desc\">Armazenar transferências num diretório oculto</string>\n    <string name=\"convert_audio_format\">Converter formato de áudio</string>\n    <string name=\"additional_settings\">Definições adicionais</string>\n    <string name=\"custom_command_template_desc\">Editar e gerir modelos de comandos</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"video_directory\">Pasta de vídeo</string>\n    <string name=\"select_all\">Selecionar tudo</string>\n    <string name=\"url_empty\">A ligação não pode estar vazia</string>\n    <string name=\"video_quality_desc\">Limite a qualidade do vídeo quando vários estiverem presentes</string>\n    <string name=\"paste\">Colar</string>\n    <string name=\"template_label\">Rótulos</string>\n    <string name=\"delete_info_msg\">Remover \\\"%1$s\\\" do seu histórico de transferências para sempre?</string>\n    <string name=\"download\">Descarregar</string>\n    <string name=\"download_playlist_desc\">Transferir vários vídeos de uma lista de reprodução</string>\n    <string name=\"create_thumbnail_summary\">Guardar a miniatura do vídeo como um ficheiro</string>\n    <string name=\"unknown_error\">Erro desconhecido</string>\n    <string name=\"network\">Rede</string>\n    <string name=\"format_sorting_desc\">Ordenar formatos com a opção -S do yt-dlp</string>\n    <string name=\"auto_update\">Atualização automática</string>\n    <string name=\"info_copied\">Informação copiada para a área de transferência</string>\n    <string name=\"sponsorblock_categories_desc\">Especificar as categorias SponsorBlock a remover ou marcar no ficheiro de vídeo</string>\n    <string name=\"start_execute\">Iniciar a execução do comando</string>\n    <string name=\"checked\">Verificado</string>\n    <string name=\"about\">Acerca</string>\n    <string name=\"open_url\">Abrir ligação</string>\n    <string name=\"restart\">Reiniciar</string>\n    <string name=\"options\">Opções</string>\n    <string name=\"sponsor\">Patrocinador</string>\n    <string name=\"convert_audio_format_desc\">A recodificação de ficheiros de áudio causará perda de qualidade de áudio e aumento do tamanho do ficheiro.</string>\n    <string name=\"not_convert\">Não convertido</string>\n    <string name=\"auto_subtitle\">Legendas automáticas</string>\n    <string name=\"required\">Obrigatório</string>\n    <string name=\"dynamic_color\">Cor dinâmica</string>\n    <string name=\"embed_subtitles_mkv_msg\">Para incorporar legendas, os vídeos serão remuxados para um contentor mkv. Pode utilizar o VLC Media Player ou outras aplicações compatíveis para ver vídeos com legendas incorporadas.</string>\n    <string name=\"abs_hint\">A maioria das plataformas de transmissão de vídeo fornece áudio e vídeo separadamente, mas pode selecionar e fundir um formato só de áudio com um formato só de vídeo num único vídeo.</string>\n    <string name=\"no_custom_command_tasks\">Nenhuma tarefa de comando personalizada</string>\n    <string name=\"share_fail_msg\">Não é possível fazer corresponder o URL de um conteúdo partilhado</string>\n    <string name=\"enable_auto_update\">Ativar a atualização automática</string>\n    <string name=\"about_page\">Versão, feedback, atualização automática</string>\n    <string name=\"status_fetching_video_info\">Obtenção de informações</string>\n    <string name=\"lowest_bitrate\">Taxa de bits mais baixa</string>\n    <string name=\"thumbnail\">Miniatura</string>\n    <string name=\"concurrent_download\">Descarregamento multi-tarefa</string>\n    <string name=\"download_error_msg\">Não foi possível descarregar o ficheiro</string>\n    <string name=\"custom_command_template\">Modelo de comando</string>\n    <string name=\"concurrent_download_desc\">Descarregar mais partes de vídeos M3U8/MPD em paralelo</string>\n    <string name=\"download_start_msg\">Descarregar \\\"%1$s\\\"</string>\n    <string name=\"format_preference\">Preferência de formato</string>\n    <string name=\"pre_release_channel\">Pré-lançamento</string>\n    <string name=\"clear_temp_files\">Limpar ficheiros temporários</string>\n    <string name=\"sponsorblock_desc\">Remover ou marcar segmentos em vídeos com a API SponsorBlock</string>\n    <string name=\"github_issue_desc\">Apresentar um problema para um relatório de erros ou um pedido de funcionalidades</string>\n    <string name=\"dark_theme\">Tema escuro</string>\n    <string name=\"cancel\">Cancelar</string>\n    <string name=\"clear_temp_files_count\">Eliminado %1$d ficheiro(s) temporário(s)</string>\n    <string name=\"convert_subtitle_desc\">Converter as legendas para outro formato</string>\n    <string name=\"check_for_updates\">Verificar se há actualizações</string>\n    <string name=\"show_more_actions\">Mostrar mais acções</string>\n    <string name=\"show_all_items\">Mostrar todos os %1$d itens</string>\n    <string name=\"app_update_failed\">Falha na atualização para a versão mais recente</string>\n    <string name=\"clear_temp_files_desc\">Eliminar todos os ficheiros temporários do diretório temporário</string>\n    <string name=\"video_title_sample_text\">Título do vídeo texto de amostra</string>\n    <string name=\"use_custom_command\">Utilizar comando personalizado</string>\n    <string name=\"close_never_show_again\">Não voltar a aparecer</string>\n    <string name=\"settings_before_download\">Configurar antes de descarregar</string>\n    <string name=\"check_for_updates_desc\">Verificar automaticamente a versão mais recente no GitHub</string>\n    <string name=\"file_unavailable\">Este ficheiro já não está disponível</string>\n    <string name=\"output_template\">Modelo de saída</string>\n    <string name=\"output_template_desc\">Especificar o modelo para os nomes dos ficheiros de saída</string>\n    <string name=\"subtitle_language\">Línguas das legendas</string>\n    <string name=\"template_exported\">Modelo(s) exportado(s) %1$d</string>\n    <string name=\"private_mode_desc\">Desativar o histórico de transferências</string>\n    <string name=\"confirm\">Confirmar</string>\n    <string name=\"permission_denied\">Permissão negada</string>\n    <string name=\"language_settings\">Definir a língua do ecrã</string>\n    <string name=\"audio_quality_desc\">Limitar a taxa de bits de áudio quando estão presentes várias qualidades</string>\n    <string name=\"follow_system\">Sistema</string>\n    <string name=\"disabled\">Desativado</string>\n    <string name=\"private_directory\">Diretório privado</string>\n    <string name=\"disable\">Desativar</string>\n    <string name=\"delete_info\">Remover?</string>\n    <string name=\"language\">Língua de visualização</string>\n    <string name=\"okay\">Está bem</string>\n    <string name=\"download_range_selection\">Seleção da lista de reprodução</string>\n    <string name=\"download_finish_notification\">Transferência concluída. Toque em para abrir.</string>\n    <string name=\"auto\">Automático</string>\n    <string name=\"shortcuts\">Atalhos</string>\n    <string name=\"download_selection_desc\">Selecionar vídeos a transferir da lista de reprodução \\\"%1$s\\\"</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d item</item>\n        <item quantity=\"many\">%d itens</item>\n        <item quantity=\"other\">%d item(s)</item>\n    </plurals>\n    <string name=\"status_completed\">Terminado</string>\n    <string name=\"custom_command\">Comando personalizado</string>\n    <string name=\"task_running\">Já está a decorrer uma tarefa de descarregamento existente</string>\n    <string name=\"settings_before_download_text\">Ajustar esta transferência</string>\n    <string name=\"video\">Vídeo</string>\n    <string name=\"open_file\">Abrir ficheiro</string>\n    <string name=\"video_creator_sample_text\">Texto de exemplo do criador de vídeo</string>\n    <string name=\"translate_desc\">Ajuda para traduzir esta aplicação no Hosted Weblate</string>\n    <string name=\"expand\">Expandir</string>\n    <string name=\"fetch_info_error_msg\">Não foi possível obter informações sobre o vídeo</string>\n    <string name=\"recently_added\">Recentemente adicionados</string>\n    <string name=\"telegram_channel\">Canal do Telegram</string>\n    <string name=\"invalid_index_range\">Intervalo de índices inválido</string>\n    <string name=\"channel_name\">Descarregar</string>\n    <string name=\"feature_unavailable\">Funcionalidade não disponível</string>\n    <string name=\"temporary_directory_desc\">Armazenar ficheiros temporários no diretório interno</string>\n    <string name=\"system_settings\">Definições do sistema</string>\n    <string name=\"auto_update_disabled_msg\">A atualização automática não está disponível para %1$s compilações. Se não tiver %1$s instalado no seu dispositivo, ou se pretender pré-visualizar as novas funcionalidades do Seal, considere %2$s.</string>\n    <string name=\"cookies_usage_msg\">O descarregamento de alguns sites requer informações de autenticação da conta. Clique em \\\"Gerar novos cookies\\\", introduza o URL do sítio Web e, em seguida, inicie sessão com a sua conta na página do browser; a aplicação irá gerá-los para si.</string>\n    <string name=\"proxy_desc\">Utilizar proxy para ligações à Internet</string>\n    <string name=\"generate_new_cookies\">Gerar novos cookies</string>\n    <string name=\"quality\">Qualidade</string>\n    <string name=\"battery_settings_desc\">Defina a utilização da bateria desta aplicação como \\\"Sem restrições\\\" nas definições do sistema para descarregar em segundo plano.</string>\n    <string name=\"refresh_cookies_desc\">Toque para abrir a página Web para gerar novos cookies:</string>\n    <string name=\"not_specified\">Não especificado (predefinição)</string>\n    <string name=\"status_downloading\">A descarregar</string>\n    <string name=\"settings\">Definições</string>\n    <string name=\"yt_dlp_up_to_date\">Usando a versão mais recente do yt-dlp</string>\n    <string name=\"status_error\">Erro</string>\n    <string name=\"app_up_to_date\">A versão atual está actualizada</string>\n    <string name=\"matrix_space\">Espaço no Matrix</string>\n    <string name=\"extract_audio\">Guardar como áudio</string>\n    <string name=\"sponsorblock_categories\">Categorias de SponsorBlock</string>\n    <string name=\"subtitle\">Legenda</string>\n    <string name=\"download_task_count\">%1$d Tarefas de transferência</string>\n    <string name=\"github_issue\">GitHub issue</string>\n    <string name=\"msg_from_developer\">Mensagem do programador</string>\n    <string name=\"export_to_clipboard\">Exportar para a área de transferência</string>\n    <string name=\"create_thumbnail\">Guardar a miniatura</string>\n    <string name=\"import_from_preferences\">Importar</string>\n    <string name=\"clip_video\">Cortar vídeo</string>\n    <string name=\"download_range_desc\">Especifique o intervalo de vídeos a descarregar da lista de reprodução \\\"%3$s\\\" (de %1$d a %2$d).</string>\n    <string name=\"download_notification_desc\">Notificação dos ficheiros descarregados e do seu progresso</string>\n    <string name=\"restrict_filenames\">Restringir nomes de ficheiros</string>\n    <string name=\"share\">Partilhar</string>\n    <string name=\"concurrent_download_num\">%d thread(s) seria(m) utilizado(s) para descarregar vídeo nativo DASH/HLS em simultâneo.</string>\n    <string name=\"import_from_clipboard\">Importar da área de transferência</string>\n    <string name=\"add\">Adicionar</string>\n    <string name=\"battery_configuration_desc\">Ignorar a otimização da bateria para que esta aplicação seja transferida em segundo plano</string>\n    <string name=\"execute_command_notification\">Executar comandos personalizados…</string>\n    <string name=\"convert_to\">Converter para %1$s</string>\n    <string name=\"privacy\">Privacidade</string>\n    <string name=\"defaults\">Predefinição</string>\n    <string name=\"edit_file\">Editar ficheiro</string>\n    <string name=\"download_archive_desc\">Registar IDs de vídeos descarregados num arquivo para evitar descargas duplicadas</string>\n    <string name=\"format\">Formato</string>\n    <string name=\"custom\">Personalizado</string>\n    <string name=\"ytdlp_update_action\">Atualizar yt-dlp</string>\n    <string name=\"title_activity_share\">Transferência rápida</string>\n    <string name=\"private_mode\">Incógnito</string>\n    <string name=\"embed_metadata_desc\">Incorporar metadados e miniatura de vídeo no ficheiro de áudio</string>\n    <string name=\"crop_artwork_desc\">Cortar imagem incorporada num quadrado</string>\n    <string name=\"playlist_title\">Título da lista de reprodução</string>\n    <string name=\"audio\">Áudio</string>\n    <string name=\"download_archive\">Arquivo de download</string>\n    <string name=\"edit_template_desc\">O caminho de saída e o URL serão adicionados pela aplicação.</string>\n    <string name=\"subtitle_desc\">Línguas, legendas incorporadas, legendas automáticas</string>\n    <string name=\"status_canceled\">Cancelado</string>\n    <string name=\"battery_configuration\">Configuração da bateria</string>\n    <string name=\"share_success_msg\">Ler a ligação de vídeo de um conteúdo partilhado…</string>\n    <string name=\"remove_multiple_templates_msg\">Remover %1$s dos modelos de comando para sempre?</string>\n    <string name=\"enable_notifications\">Ativar as notificações?</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"multiselect_item_count\">%1$d vídeo(s), %2$d ficheiro(s) áudio</string>\n    <string name=\"format_settings_desc\">Formato do ficheiro, qualidade do vídeo, legendas</string>\n    <string name=\"sponsors\">Patrocinadores</string>\n    <string name=\"credits\">Créditos</string>\n    <string name=\"copy_link\">Copiar ligação</string>\n    <string name=\"fetching_info\">Obtenção de informações sobre o vídeo…</string>\n    <string name=\"clear_all_cookies_desc\">Eliminar definitivamente todos os cookies armazenados na aplicação?</string>\n    <string name=\"best_quality\">A melhor qualidade</string>\n    <string name=\"minute\">minuto</string>\n    <string name=\"playlist_indicator_text\">A descarregar lista de reprodução (%1$d/%2$d)…</string>\n    <string name=\"format_sorting\">Ordenação de formatos</string>\n    <string name=\"rate_limit\">Limite de taxa</string>\n    <string name=\"force_ipv4\">Forçar IPv4</string>\n    <string name=\"force_ipv4_desc\">Efetuar todas as ligações através de IPv4</string>\n    <string name=\"keep_subtitle_files\">Manter ficheiros de legendas</string>\n    <string name=\"allow_once\">Permitir uma vez</string>\n    <string name=\"allow_always\">Permitir sempre</string>\n    <string name=\"download_with_cellular_request\">Permitir a descarga com telemóvel?</string>\n    <string name=\"merge_audiostream\">Unir vários fluxos de áudio</string>\n    <string name=\"dont_allow\">Não permitir</string>\n    <string name=\"merge_audiostream_desc\">Permitir a fusão de vários fluxos de áudio num único ficheiro</string>\n    <string name=\"search_in_downloads\">Pesquisar em descargas</string>\n    <string name=\"search\">Pesquisar</string>\n    <string name=\"auto_translated_subtitles\">Legendas traduzidas automaticamente</string>\n    <string name=\"auto_translated_subtitles_msg\">As legendas com tradução automática para todos os idiomas estarão disponíveis nas descargas. Estas legendas podem ser inexactas e difíceis de compreender.</string>\n    <string name=\"subtitle_language_desc\">Idioma das legendas a descarregar na seleção de formato automático, separado por vírgulas.</string>\n    <string name=\"look_and_feel\">Aspeto &amp; Sentimento</string>\n    <string name=\"use_previous_selection\">Utilizar a seleção anterior</string>\n    <string name=\"none\">Nenhum</string>\n    <string name=\"remember_for_next_download\">Lembrar para a próxima descarga</string>\n    <string name=\"reset\">Repor</string>\n    <string name=\"no_thanks\">Não obrigado</string>\n    <string name=\"search_in_subtitles\">Pesquisar em legendas</string>\n    <string name=\"update_language_msg\">Os seguintes idiomas serão adicionados às suas preferências para futuras descargas:</string>\n    <string name=\"update_subtitle_languages\">Atualizar idiomas das legendas?</string>\n    <string name=\"clipboard\">Área de transferência</string>\n    <string name=\"import_from\">Importar de</string>\n    <string name=\"import_download_history_msg\">Os ficheiros descarregados não serão importados. Terá de os voltar a descarregar manualmente</string>\n    <string name=\"interface_and_interaction\">Interface &amp; Interação</string>\n    <string name=\"backup_type\">Tipo de Backup</string>\n    <string name=\"export_to\">Exportar para</string>\n    <string name=\"file\">Ficheiro</string>\n    <string name=\"export_download_history\">Exportar o histórico de descargas?</string>\n    <string name=\"import_download_history\">Importar o histórico de descargas?</string>\n    <string name=\"export_download_history_msg\">A exportar %1$s do histórico de descargas. Os ficheiros descarregados e as preferências não serão guardados.</string>\n    <string name=\"download_history\">Histórico de descargas</string>\n    <string name=\"export_backup\">Exportar</string>\n    <string name=\"import_backup\">Importar</string>\n    <string name=\"full_backup\">Backup completo</string>\n    <string name=\"download_history_imported\">Importou %1$s para o histórico de descargas</string>\n    <string name=\"redownload\">Descarregar novamente</string>\n    <string name=\"download_archive_error\">O vídeo foi descarregado. Se este não for o comportamento esperado, verifique o seu arquivo de descarga.</string>\n    <string name=\"remux_container_mkv\">Recipiente de vídeo Remux</string>\n    <string name=\"remux_container_mkv_desc\">Remuxar vídeos para um recipiente MKV para uma melhor compatibilidade</string>\n    <string name=\"cookies_in_database\">%1$d cookies de %2$d sites no total</string>\n    <string name=\"every_month\">Mensalmente</string>\n    <string name=\"every_day\">Diariamente</string>\n    <string name=\"every_week\">Semanalmente</string>\n    <string name=\"playlist\">Lista de reprodução</string>\n    <string name=\"preset\">Predefinição</string>\n    <string name=\"custom_format_selection_desc\">Escolha entre formatos, legendas e personalize ainda mais</string>\n    <string name=\"edit_preset\">Editar predefinição</string>\n    <string name=\"best_quality_desc\">Descarregar o melhor formato disponível</string>\n    <string name=\"prefer_placeholder\">Preferir %1$s</string>\n    <string name=\"all_languages\">Todos os idiomas</string>\n    <string name=\"proceed\">Continuar</string>\n    <string name=\"preset_format_selection_desc\">Descarregar automaticamente utilizando as suas preferências de formato</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d vídeo</item>\n        <item quantity=\"many\">%d vídeos</item>\n        <item quantity=\"other\">%d vídeos</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d áudio</item>\n        <item quantity=\"many\">%d áudios</item>\n        <item quantity=\"other\">%d áudios</item>\n    </plurals>\n    <string name=\"task_added\">Tarefa adicionada à fila</string>\n    <string name=\"you_ll_find_your_downloads_here\">Encontrará as suas descargas aqui</string>\n    <string name=\"download_hint\">Toque no botão de descarga ou partilhe uma ligação de vídeo para esta aplicação para iniciar uma descarga</string>\n    <string name=\"status_downloaded\">Descarregado</string>\n    <string name=\"all\">Tudo</string>\n    <string name=\"select_multiple_link\">Selecionar a partir de %1$d ligações</string>\n    <string name=\"download_queue\">Fila de descargas</string>\n    <string name=\"show_navigation_drawer\">Mostrar gaveta de navegação</string>\n    <string name=\"resume\">Retomar</string>\n    <string name=\"delete\">Eliminar</string>\n    <string name=\"media_info\">Informações da mídia</string>\n    <string name=\"trouble_shooting\">Solução de problemas</string>\n    <string name=\"issue_tracker\">Rastreador de problemas</string>\n    <string name=\"trouble_shooting_desc\">Correção de erros comuns e verificação de problemas conhecidos</string>\n    <string name=\"issue_tracker_hint\">Encontrou um erro? Antes de comunicar um novo problema, procure no nosso registo de problemas. Muitos problemas comuns já foram resolvidos e documentados lá.</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ro/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">Salvează ca audio</string>\n    <string name=\"create_thumbnail\">Salvează miniatura</string>\n    <string name=\"settings\">Setări</string>\n    <string name=\"download_settings_desc\">General, format, comandă personalizată</string>\n    <string name=\"download\">Descarcă</string>\n    <string name=\"yt_dlp_up_to_date\">Folosind cea mai recentă versiune de yt-dlp</string>\n    <string name=\"fetching_info\">Preluand informatiile video-ului …</string>\n    <string name=\"permission_denied\">Permisiunea refuzată</string>\n    <string name=\"download_start_msg\">Descarcă \\\"%1$s\\\"</string>\n    <string name=\"ytdlp_version\">Versiunea YT-dlp</string>\n    <string name=\"ytdlp_update\">Faceți clic pentru a instala cea mai recentă versiune yt-dlp</string>\n    <string name=\"confirm\">Confirma</string>\n    <string name=\"dismiss\">Anulează</string>\n    <string name=\"delete_info\">Elimină\\?</string>\n    <string name=\"open_url\">Deschide link-ul</string>\n    <string name=\"remove\">Elimina</string>\n    <string name=\"delete_file\">Șterge fișierul</string>\n    <string name=\"back\">Înainte</string>\n    <string name=\"release\">Cea mai recentă versiune</string>\n    <string name=\"video\">Video</string>\n    <string name=\"credits\">Credite</string>\n    <string name=\"edit\">Editați</string>\n    <string name=\"dark_theme\">Temă întunecată</string>\n    <string name=\"follow_system\">Sistem</string>\n    <string name=\"off\">Oprire</string>\n    <string name=\"cancel\">Anulează</string>\n    <string name=\"settings_before_download\">Configurați înainte de a descărca</string>\n    <string name=\"error_copied\">Raport de eroare copiat în clipboard</string>\n    <string name=\"thumbnail\">Miniatură</string>\n    <string name=\"paste\">Lipește</string>\n    <string name=\"url_empty\">Linkul nu poate fi gol</string>\n    <string name=\"extract_audio_summary\">Descarcă și salvează audio, în loc de video</string>\n    <string name=\"create_thumbnail_summary\">Salvează miniatura video ca fișier</string>\n    <string name=\"yt_dlp_update_fail\">Nu s-a putut instala cea mai recentă versiune yt-dlp. Vă rugăm să vă asigurați că sunteți conectat la internet.</string>\n    <string name=\"download_success_msg\">Descărcarea s-a terminat</string>\n    <string name=\"paste_msg\">Lipiți URL-ul din clipboard</string>\n    <string name=\"download_error_msg\">Nu s-a putut descărca fișierul</string>\n    <string name=\"fetch_info_error_msg\">Nu s-a putut prelua informații video</string>\n    <string name=\"general_settings\">General</string>\n    <string name=\"paste_fail_msg\">Nu s-a putut potrivi URL-ul din clipboard</string>\n    <string name=\"downloads_history\">Descărcări</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Link copiat în clipboard</string>\n    <string name=\"about\">Despre</string>\n    <string name=\"about_page\">Versiune, feedback, actualizare automată</string>\n    <string name=\"release_desc\">Căutați changelog-uri și versiuni noi</string>\n    <string name=\"version\">Versiune</string>\n    <string name=\"display\">Afişa</string>\n    <string name=\"checked\">Verificat</string>\n    <string name=\"credits_desc\">Credite și software libre</string>\n    <string name=\"advanced_settings\">Avansat</string>\n    <string name=\"display_settings\">Temă întunecată, culoare dinamică, limbi</string>\n    <string name=\"yt_dlp_docs\">Referințe de utilizare YT-dlp</string>\n    <string name=\"print_details\">Ieșire detaliată</string>\n    <string name=\"custom_command_desc\">Rulați comanda yt-dlp cu template personalizat</string>\n    <string name=\"video_directory\">Dosar video</string>\n    <string name=\"select_all\">Selectează tot</string>\n    <string name=\"template_selection\">Selectarea șablonului</string>\n    <string name=\"template_label\">Etichetă</string>\n    <string name=\"remove_template\">Elimină\\?</string>\n    <string name=\"downloading_indicator_text\">Descărcare în curs…</string>\n    <string name=\"task_canceled\">Descărcați sarcina anulată</string>\n    <string name=\"status_canceled\">Anulat</string>\n    <string name=\"open_file\">Deschide fișierul</string>\n    <string name=\"restart\">Reîncepe</string>\n    <string name=\"copy_error_report\">Raport de eroare</string>\n    <string name=\"sponsorblock_categories_desc\">Specificați categoriile SponsorBlock pentru a elimina sau marca în fișierul video</string>\n    <string name=\"check_for_updates\">Căutați actualizări</string>\n    <string name=\"cookies\">Cookie-uri</string>\n    <string name=\"check_for_updates_desc\">Verificați automat cea mai recentă versiune pe GitHub</string>\n    <string name=\"dynamic_color\">Culoare dinamică</string>\n    <string name=\"dynamic_color_desc\">Aplicați culori din imagini de fundal la tema aplicației</string>\n    <string name=\"download_with_cellular\">Descărcați folosind telefonul mobil</string>\n    <string name=\"download_with_cellular_desc\">Permite descărcarea media atunci când este conectat la rețele măsurate</string>\n    <string name=\"invalid_input\">Intrare invalidă</string>\n    <string name=\"high_contrast\">Temă întunecată cu contrast ridicat</string>\n    <string name=\"lowest_quality\">Cea mai scăzută calitate</string>\n    <string name=\"network_settings_desc\">Limită de rată, descărcare, cookie-uri</string>\n    <string name=\"disable_preview\">Dezactivați previzualizarea</string>\n    <string name=\"disable_preview_desc\">Fără afișarea miniaturilor în timpul descărcării</string>\n    <string name=\"privacy\">Confidențialitate</string>\n    <string name=\"use_custom_command\">Utilizați comanda personalizată</string>\n    <string name=\"private_directory\">Director privat</string>\n    <string name=\"private_directory_desc\">Stocați descărcările într-un director ascuns</string>\n    <string name=\"crop_artwork_desc\">Crop imagine încorporată în pătrat</string>\n    <string name=\"format_selection\">Selectarea formatului</string>\n    <string name=\"status_enqueued\">În așteptare</string>\n    <string name=\"max_rate\">Rata maximă</string>\n    <string name=\"translate\">Traduceți</string>\n    <string name=\"video_resolution\">Rezoluție video</string>\n    <string name=\"general_settings_desc\">Versiunea YT-dlp, notificare, playlist</string>\n    <string name=\"clear_temp_files_info\">Fișierele temporare pot fi utilizate pentru a relua descărcările anulate. Ești sigur că vrei să ștergi toate aceste fișiere?\n\\n\n\\nPoți accesa aceste fișiere în %1$s</string>\n    <string name=\"embed_subtitles_desc\">Încorporează subtitrări furnizate în videoclipuri, dacă sunt disponibile</string>\n    <string name=\"format_settings_desc\">Format de fișier, calitate video, subtitrări</string>\n    <string name=\"selected_item_count\">%1$d selectat</string>\n    <string name=\"translate_desc\">Ajută la traducerea acestei aplicații pe Hosted Weblate</string>\n    <string name=\"import_from_clipboard\">Import din clipboard</string>\n    <string name=\"network\">Rețea</string>\n    <string name=\"rate_limit_desc\">Limitați rata maximă pentru viteza de descărcare</string>\n    <string name=\"copy_link\">Copiază link-ul</string>\n    <string name=\"aria2_desc\">Utilizați aria2c ca descărcător extern</string>\n    <string name=\"unavailable\">Indisponibil</string>\n    <string name=\"app_up_to_date\">Versiunea curentă este actualizată</string>\n    <string name=\"update\">Actualizare</string>\n    <string name=\"video_file_size\">Dimensiunea fișierului video</string>\n    <string name=\"multiselect_item_count\">%1$d video(uri), %2$d fișier(e) audio</string>\n    <string name=\"remove_cookie_profile_desc\">Elimină cookie-urile pentru \\\"%1$s\\\"?</string>\n    <string name=\"new_template\">Șablon nou</string>\n    <string name=\"status_fetching_video_info\">Preluare informații</string>\n    <string name=\"private_mode_desc\">Dezactivează istoricul descărcărilor</string>\n    <string name=\"sponsorblock_categories\">Categoriile SponsorBlock</string>\n    <string name=\"video_only\">Video (fără audio)</string>\n    <string name=\"unknown_error\">Eroare necunoscută</string>\n    <string name=\"download_task_count\">%1$d Descărcați sarcini</string>\n    <string name=\"recently_added\">Adăugat recent</string>\n    <string name=\"generate_new_cookies\">Generați cookie-uri noi</string>\n    <string name=\"file_unavailable\">Acest fișier nu mai este disponibil</string>\n    <string name=\"embed_subtitles\">Încorporează subtitrări</string>\n    <string name=\"custom_command_template_desc\">Editați și gestionați șabloanele de comandă</string>\n    <string name=\"info_copied\">Informații copiate în clipboard</string>\n    <string name=\"prefix\">Prefix</string>\n    <string name=\"use_cookies\">Utilizați cookie-uri</string>\n    <string name=\"app_update_failed\">Nu a reușit să actualizeze la cea mai recentă versiune</string>\n    <string name=\"status_error\">Eroare</string>\n    <string name=\"status_completed\">Efectuat</string>\n    <string name=\"export_to_clipboard\">Exportați în clipboard</string>\n    <string name=\"clear_temp_files_desc\">Ștergeți toate fișierele temporare din directorul temporar</string>\n    <string name=\"private_mode\">Incognito</string>\n    <string name=\"download_disabled_with_cellular\">Descărcarea cu rețeaua celulară este dezactivată conform setărilor dvs</string>\n    <string name=\"format_selection_desc\">Selectați formatul de descărcat înainte de a începe descărcarea</string>\n    <string name=\"github_issue_desc\">Trimiteți o problemă pentru raportul de eroare sau cererea de funcții</string>\n    <string name=\"remove_template_desc\">Eliminați definitiv \\\"%1$s\\\" din șabloanele de comandă\\?</string>\n    <string name=\"sponsorblock_desc\">Eliminați sau marcați segmente în videoclipuri cu SponsorBlock API</string>\n    <string name=\"delete_multiple_items_msg\">Eliminați definitiv articolele %1$d din istoricul de descărcare\\?</string>\n    <string name=\"cookies_desc\">Utilizați cookie-uri formatate Netscape pentru descărcări</string>\n    <string name=\"clear_temp_files\">Ștergeți fișierele temporare</string>\n    <string name=\"clear_temp_files_count\">Fișier(e) temporar(e) șters(e) %1$d</string>\n    <string name=\"rate_limit\">Limită de rată</string>\n    <string name=\"download_selection_desc\">Selectați videoclipuri de descărcat din playlist-ul \\\"%1$s”</string>\n    <string name=\"suggested\">Sugestii</string>\n    <string name=\"fetching_playlist_info\">Se preiau informații despre playlist…</string>\n    <string name=\"download_range_selection\">Selecția playlistului</string>\n    <string name=\"to\">Sfârşit</string>\n    <string name=\"invalid_index_range\">Interval de indexare invalid</string>\n    <string name=\"playlist_indicator_text\">Descărcarea listei de redare (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Dosar audio</string>\n    <string name=\"not_specified\">Nespecificat (implicit)</string>\n    <string name=\"video_format_preference\">Format video preferat</string>\n    <string name=\"video_format\">Format video</string>\n    <string name=\"start_download\">Descarcă</string>\n    <string name=\"user_guide\">Ghid de utilizare</string>\n    <string name=\"open_settings\">Deschide setările</string>\n    <string name=\"concurrent_download\">Descărcare multi-threaded</string>\n    <string name=\"download_directory\">Director de descărcare</string>\n    <string name=\"show_more_actions\">Mai multe acțiuni</string>\n    <string name=\"download_finish_notification\">Descărcare terminat. Atingeți pentru a deschide.</string>\n    <string name=\"battery_settings_desc\">Vă rugăm să setați utilizarea bateriei acestei aplicații la \\\"Nerestricționat” în setările sistemului pentru a o descărca în fundal.</string>\n    <string name=\"share_fail_msg\">Nu se poate potrivi adresa URL din conținutul partajat</string>\n    <string name=\"close_never_show_again\">Să nu mai apari din nou</string>\n    <string name=\"download_desc\">Apoi faceți clic pe \\\"Descarcă” după ajustarea setărilor.</string>\n    <string name=\"download_notification_desc\">Notifică fișierele descărcate și progresul</string>\n    <string name=\"close\">Închide</string>\n    <string name=\"additional_settings\">Setari aditionale</string>\n    <string name=\"channel_description\">Notifică fișierele descărcate și progresul</string>\n    <string name=\"video_url\">Link video</string>\n    <string name=\"execute_command_notification\">Se rulează comenzi personalizate…</string>\n    <string name=\"concurrent_download_desc\">Descărcați mai multe părți ale videoclipurilor M3U8/MPD în paralel</string>\n    <string name=\"download_notification\">Notificare de descărcare</string>\n    <string name=\"paste_desc\">Faceți clic pe \\\"Lipește\\\" pentru a obține link-ul video din clipboard.</string>\n    <string name=\"channel_name\">Descarcă</string>\n    <string name=\"options\">Opțiuni</string>\n    <string name=\"preferred_format_desc\">Formatul preferat atunci când sunt furnizate mai multe</string>\n    <string name=\"download_history_desc\">Verificați și gestionați descărcările în aplicație, inclusiv videoclipuri și fișiere audio.</string>\n    <string name=\"defaults\">Implicit</string>\n    <string name=\"filesize_gb\">%.2f G</string>\n    <string name=\"apply\">Aplică</string>\n    <string name=\"unlimited\">Nelimitat</string>\n    <string name=\"sponsor_msg\">Seal va fi întotdeauna gratuit și open source pentru toată lumea. Dacă îți place, te rog să mă sponsorizezi pe GitHub!</string>\n    <string name=\"convert_audio_format_desc\">Recodificarea fișierelor audio va duce la pierderea calității audio și la creșterea dimensiunii fișierului.</string>\n    <string name=\"clip_video\">Clipează video</string>\n    <string name=\"convert_audio_format\">Convertiți formatul audio</string>\n    <string name=\"audio_format\">Format audio</string>\n    <string name=\"no_downloaded_media\">Nu există medii descărcate</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Activează funcția experimentală\\?</string>\n    <string name=\"clip_video_dialog_msg\">Descărcările care utilizează această caracteristică vor fi delegate FFmpeg pentru a descărca secțiunile selectate ale videoclipului, această funcție este încă experimentală și tăierea nu va fi complet precisă, nu toate formatele acceptă această funcție și este posibil să aveți viteze de descărcare mai lente.</string>\n    <string name=\"clip_video_desc\">Realizați videoclipuri în pagina de selecție a formatului</string>\n    <string name=\"filesize_mb\">%.2f M</string>\n    <string name=\"convert_to\">Convertiți în %1$s</string>\n    <string name=\"video_quality_desc\">Limitați calitatea video atunci când sunt prezenți mai multe</string>\n    <string name=\"from\">Pornire</string>\n    <string name=\"status_downloading\">Descărcarea</string>\n    <string name=\"subtitle_sponsorblock\">Subtitrarile pot fi greșite atunci când eliminați segmente SponsorBlock.</string>\n    <string name=\"share\">Trimite</string>\n    <string name=\"show_logs\">Arată jurnal</string>\n    <string name=\"logs\">Jurnal</string>\n    <string name=\"abs_hint\">Majoritatea platformelor de streaming video oferă audio și video separat, puteți selecta și îmbina un format numai audio cu un format numai video într-un singur videoclip.</string>\n    <string name=\"auto_update_disabled_msg\">Actualizarea automată nu este disponibilă pentru versiunile %1$s. Dacă nu aveți %1$s instalat pe dispozitiv sau doriți să previzualizați funcțiile noi viitoare în Seal, vă rugăm să luați în considerare %2$s.</string>\n    <string name=\"switch_to_github_builds\">trecerea la versiunile GitHub</string>\n    <string name=\"okay\">Ok</string>\n    <string name=\"got_it\">Am înţeles</string>\n    <string name=\"feature_unavailable\">Funcție indisponibilă</string>\n    <string name=\"discard\">Aruncă</string>\n    <string name=\"clip_start\">Pornire</string>\n    <string name=\"on\">Pe</string>\n    <string name=\"video_quality\">Calitatea video</string>\n    <string name=\"best_quality\">Cea mai bună calitate</string>\n    <string name=\"template_imported\">Șablon(uri) %1$d importat(e)</string>\n    <string name=\"settings_before_download_desc\">Configurați preferințele înainte de descărcare</string>\n    <string name=\"check_download_settings_desc\">Aruncă o privire la setările de descărcare și asigură-te că ai cea mai recentă versiune de yt-dlp înainte de a o folosi.</string>\n    <string name=\"template_exported\">Șablon(uri) exportat(e) %1$d</string>\n    <string name=\"settings_before_download_text\">Ajustați această descărcare</string>\n    <string name=\"task_running\">Se execută deja o sarcină de descărcare existentă</string>\n    <string name=\"custom_command_enabled_hint\">Unele opțiuni nu sunt disponibile atunci când se utilizează comanda personalizată</string>\n    <string name=\"custom_command_template\">Șablon de comandă</string>\n    <string name=\"cookies_usage_msg\">Descărcarea de pe unele site-uri necesită informații de autentificare a contului. Faceți clic pe „Generează cookie-uri noi”, introduceți adresa URL a site-ului web și apoi conectați-vă cu contul dvs. în pagina browserului, aplicația o va genera pentru dvs.</string>\n    <string name=\"language\">Limba de afișare</string>\n    <string name=\"download_playlist_desc\">Descărcați mai multe videoclipuri dintr-un playlist</string>\n    <string name=\"download_playlist\">Descărcați playlist-ul</string>\n    <string name=\"permission_issue\">Problemă cu permisiunea de stocare</string>\n    <string name=\"edit_template_desc\">Calea de ieșire și URL-ul vor fi adăugate de aplicație.</string>\n    <string name=\"battery_configuration_desc\">Ignorați optimizarea bateriei pentru ca această aplicație să fie descărcată în fundal</string>\n    <string name=\"matrix_space\">Spațiu Matrix</string>\n    <string name=\"github_issue\">Problemă GitHub</string>\n    <string name=\"not_convert\">Neconvertit</string>\n    <string name=\"convert_audio\">Converti</string>\n    <string name=\"subdirectory\">Salvare în subdirector</string>\n    <string name=\"subdirectory_desc\">Salvați fișierele în folderele numite ca și câmpurile respective</string>\n    <string name=\"multiselect_mode\">Modul Multiselect</string>\n    <string name=\"print_details_desc\">Imprimă mesaje detaliate la descărcare</string>\n    <string name=\"service_title\">Seal se descarcă…</string>\n    <string name=\"language_settings\">Setați limba de afișare</string>\n    <string name=\"delete_info_msg\">Eliminați definitiv \\\"%1$s” din istoricul descărcărilor\\?</string>\n    <string name=\"readme_desc\">Verificați depozitul GitHub și README</string>\n    <string name=\"custom_command\">Comandă personalizată</string>\n    <string name=\"start_execute\">Începeți să executați comanda</string>\n    <string name=\"share_success_msg\">Se citește linkul video din conținutul partajat…</string>\n    <string name=\"download_directory_desc\">Selectați unde să stocați fișierele video și audio</string>\n    <string name=\"battery_configuration\">Configurarea bateriei</string>\n    <string name=\"how_does_it_work\">Cum funcționează\\?</string>\n    <string name=\"telegram_channel\">Canalul Telegram</string>\n    <string name=\"no_custom_command_tasks\">Fără sarcini de comandă personalizate</string>\n    <string name=\"embed_subtitles_mkv_msg\">Pentru încorporarea subtitrărilor, videoclipurile vor fi remuxate în containerul mkv.</string>\n    <string name=\"sdcard_directory\">Dosarul cardului SD</string>\n    <string name=\"auto_subtitle\">Subtitrări automate</string>\n    <string name=\"auto_subtitle_desc\">Descărcați subtitrări generate automat</string>\n    <string name=\"title_activity_share\">Descărcare rapidă</string>\n    <string name=\"subtitle\">Subtitlu</string>\n    <string name=\"download_subtitles\">Descărcați subtitrări</string>\n    <string name=\"subtitle_language\">Limbi de subtitrare</string>\n    <string name=\"subtitle_desc\">Limbi, subtitrări încorporate, subtitrări automate</string>\n    <string name=\"copy_log\">Copiază jurnalul</string>\n    <string name=\"add\">Adaugă</string>\n    <string name=\"shortcuts\">Comenzi rapide</string>\n    <string name=\"edit_shortcuts_desc\">Editați comenzile rapide personalizate care pot fi utilizate pentru a compune șabloane de comandă.</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"pre_release_channel\">Preview-ul</string>\n    <string name=\"update_channel_desc\">Instalați versiuni de pre-lansare pentru a previzualiza noile funcții și modificări.\n\\n\n\\nVa exista o anumită instabilitate în aceste versiuni, așa că vă rugăm să nu ezitați să ne oferiți feedback dacă întâmpinați probleme pentru a ne ajuta să îmbunătățim aplicația pentru viitor.</string>\n    <string name=\"update_channel\">Actualizați canalul</string>\n    <string name=\"auto_update\">Actualizare automată</string>\n    <string name=\"enable_auto_update\">Activează actualizarea automată</string>\n    <string name=\"clip_end\">Sfârşit</string>\n    <string name=\"audio_format_preference\">Formatul audio preferat</string>\n    <string name=\"lowest_bitrate\">Cel mai mic bitrate</string>\n    <string name=\"audio_quality\">Calitate audio</string>\n    <string name=\"audio_quality_desc\">Limitați rata de biți audio atunci când sunt prezente mai multe calități</string>\n    <string name=\"format_sorting\">Sortare format</string>\n    <string name=\"format_sorting_desc\">Sortarea formatelor cu opțiunea -S din yt-dlp</string>\n    <string name=\"import_from_preferences\">Importă</string>\n    <string name=\"title\">Titlu</string>\n    <string name=\"rename\">Redenumire</string>\n    <string name=\"second\">secundă</string>\n    <string name=\"minute\">minut</string>\n    <string name=\"clear_all_cookies\">Ștergeți toate cookie-urile</string>\n    <string name=\"clear_all_cookies_desc\">Ștergeți definitiv toate cookie-urile stocate în aplicație\\?</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">Sprijină această aplicație prin sponsorizare pe GitHub</string>\n    <string name=\"feedback\">Părere</string>\n    <string name=\"sponsors\">Sponsori</string>\n    <string name=\"temporary_directory_desc\">Stocați fișierele temporare în directorul intern</string>\n    <string name=\"format\">Format</string>\n    <string name=\"download_range_desc\">Specifica intervalul de videoclipuri pentru a descarca din playlist-ul \\\"%3$s\\\" (de la %1$d pana la %2$d).</string>\n    <string name=\"msg_from_developer\">Mesaj de la dezvoltator</string>\n    <string name=\"sponsor_msg2\">Mulțumesc foarte mult!</string>\n    <string name=\"concurrent_download_num\">%d din thread-uri v-or fi folosit pentru a descărca video nativ DASH/HLS concurent.</string>\n    <string name=\"crop_artwork\">Decupeaza arta</string>\n    <string name=\"permission_issue_desc\">Locatiile din afara Download/ si Documents/ nu sunt suportate</string>\n    <string name=\"clear\">Sterge</string>\n    <string name=\"video_creator_sample_text\">Exemplu text creator video</string>\n    <string name=\"video_title_sample_text\">Exemplu text titlu video</string>\n    <string name=\"edit_shortcuts\">Editează scurtături</string>\n    <string name=\"running_tasks\">Rularea activităților</string>\n    <string name=\"download_video_desc\">Descărcați videoclipuri de la URL</string>\n    <string name=\"convert_subtitle\">Convertiți subtitrări</string>\n    <string name=\"convert_subtitle_desc\">Convertiți subtitrările într-un alt format</string>\n    <string name=\"split_video\">Împărțiți videoclipul</string>\n    <string name=\"split_video_msg\">Videoclipul va fi împărțit în %1$d capitole</string>\n    <string name=\"unknown_error_title\">Hopa! Ceva n-a mers bine</string>\n    <string name=\"copy_and_exit\">Copiați și ieșiți</string>\n    <string name=\"expand\">Extinde</string>\n    <string name=\"new_task\">Sarcină nouă de descărcare</string>\n    <string name=\"edit_template\">Editați \\\"%1$s\\\"</string>\n    <string name=\"start\">Pornire</string>\n    <string name=\"ytdlp_update_action\">Actualizează yt-dlp</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ru/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"download_settings_desc\">Основные настройки, формат, своя команда</string>\n    <string name=\"settings\">Настройки</string>\n    <string name=\"video_directory\">Папка с видео</string>\n    <string name=\"extract_audio\">Сохранить как аудио</string>\n    <string name=\"create_thumbnail\">Сохранить миниатюру</string>\n    <string name=\"extract_audio_summary\">Скачать и сохранить аудио вместо видео</string>\n    <string name=\"yt_dlp_up_to_date\">Используется новейшая версия yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Не удалось установить новейшую версию yt-dlp. Пожалуйста, удостоверьтесь, что Вы подключены к интернету.</string>\n    <string name=\"fetching_info\">Извлечение информации о видео…</string>\n    <string name=\"create_thumbnail_summary\">Сохранить миниатюру к видео как файл</string>\n    <string name=\"fetch_info_error_msg\">Не получается получить информацию о видео</string>\n    <string name=\"language_settings\">Установить язык</string>\n    <string name=\"task_running\">Существующая загрузка уже запущена</string>\n    <string name=\"paste_msg\">Вставлен URL-адрес</string>\n    <string name=\"delete_info_msg\">Удалить \\\"%1$s\\\" из Вашей истории загрузок навсегда?</string>\n    <string name=\"confirm\">Подтвердить</string>\n    <string name=\"open_url\">Открыть ссылку</string>\n    <string name=\"remove\">Удалить</string>\n    <string name=\"delete_file\">Удалить файл</string>\n    <string name=\"back\">Назад</string>\n    <string name=\"about_page\">Версия, обратная связь, автообновление</string>\n    <string name=\"release\">Новейшая версия</string>\n    <string name=\"checked\">Проверен</string>\n    <string name=\"custom_command\">Своя команда</string>\n    <string name=\"print_details\">Подробный отчёт</string>\n    <string name=\"dark_theme\">Тёмная тема</string>\n    <string name=\"cancel\">Отменить</string>\n    <string name=\"settings_before_download\">Параметры перед загрузкой</string>\n    <string name=\"settings_before_download_desc\">Настройте параметры перед загрузкой</string>\n    <string name=\"edit_template_desc\">Выходной путь и URL-адрес будут добавлены приложением.</string>\n    <string name=\"video_quality\">Качество видео</string>\n    <string name=\"not_specified\">Не указано (по умолчанию)</string>\n    <string name=\"video_format_preference\">Предпочитаемый формат видео</string>\n    <string name=\"start_download\">Начать загрузку</string>\n    <string name=\"user_guide\">Руководство пользователя</string>\n    <string name=\"open_settings\">Открыть настройки</string>\n    <string name=\"video_quality_desc\">Ограничить качество видео, если доступны несколько</string>\n    <string name=\"preferred_format_desc\">Предпочитаемый формат, если доступны несколько</string>\n    <string name=\"check_download_settings_desc\">Ознакомьтесь с настройками загрузки и убедитесь, что у Вас установлена новейшая версия yt-dlp, прежде чем использовать их.</string>\n    <string name=\"download_playlist_desc\">Загружайте сразу несколько видео из плейлиста</string>\n    <string name=\"channel_description\">Уведомлять о загруженных файлах и прогрессе</string>\n    <string name=\"battery_settings_desc\">Пожалуйста, установите в настройках контроля фоновой активности приложения значение \\\"Без ограничений\\\" для загрузки в фоновом режиме.</string>\n    <string name=\"concurrent_download\">Многопоточная загрузка</string>\n    <string name=\"share_fail_msg\">Невозможно сопоставить URL-адрес из общего содержимого</string>\n    <string name=\"share_success_msg\">Чтение ссылки на видео из общего контента…</string>\n    <string name=\"download_notification_desc\">Уведомлять о загруженных файлах и процессе</string>\n    <string name=\"fetching_playlist_info\">Получение информации о плейлисте…</string>\n    <string name=\"download_range_desc\">Укажите диапазон видео для загрузки из плейлиста \\\"%3$s\\\" (от %1$d до %2$d).</string>\n    <string name=\"from\">Начать</string>\n    <string name=\"to\">Закончить</string>\n    <string name=\"invalid_index_range\">Недопустимый диапазон номеров</string>\n    <string name=\"download_directory_desc\">Выберите место для хранения видео- и аудио-файлов</string>\n    <string name=\"permission_issue\">Запрет доступа к хранилищу</string>\n    <string name=\"battery_configuration\">Настройки энергопотребления</string>\n    <string name=\"service_title\">Seal скачивает…</string>\n    <string name=\"unknown_error\">Неизвестная ошибка</string>\n    <string name=\"translate\">Перевод</string>\n    <string name=\"translate_desc\">Помогите с переводом на Hosted Weblate</string>\n    <string name=\"download\">Загрузить</string>\n    <string name=\"url_empty\">Ссылка не может быть пустой</string>\n    <string name=\"permission_denied\">Доступ запрещён</string>\n    <string name=\"download_success_msg\">Загрузка завершена</string>\n    <string name=\"download_start_msg\">Загружаю \\\"%1$s\\\"</string>\n    <string name=\"general_settings\">Основные</string>\n    <string name=\"download_error_msg\">Не удалось загрузить файл</string>\n    <string name=\"ytdlp_version\">Версия yt-dlp</string>\n    <string name=\"ytdlp_update\">Нажмите для установки новейшей версии yt-dlp</string>\n    <string name=\"delete_info\">Удалить\\?</string>\n    <string name=\"audio\">Аудио</string>\n    <string name=\"downloads_history\">Загрузки</string>\n    <string name=\"about\">О приложении</string>\n    <string name=\"link_copied\">Ссылка скопирована в буфер обмена</string>\n    <string name=\"dismiss\">Отменить</string>\n    <string name=\"version\">Версия</string>\n    <string name=\"display_settings\">Тёмная тема, динамические цвета, языки</string>\n    <string name=\"advanced_settings\">Продвинутые настройки</string>\n    <string name=\"credits_desc\">Благодарности и свободное ПО</string>\n    <string name=\"release_desc\">Ознакомьтесь со списком изменений и новых версий</string>\n    <string name=\"readme_desc\">Загляните в репозиторий GitHub и README</string>\n    <string name=\"video\">Видео</string>\n    <string name=\"credits\">Благодарности</string>\n    <string name=\"print_details_desc\">Выводить подробный отчёт во время загрузки</string>\n    <string name=\"custom_command_desc\">Запустить yt-dlp со своими настройками</string>\n    <string name=\"display\">Внешний вид</string>\n    <string name=\"edit\">Править</string>\n    <string name=\"error_copied\">Сообщение об ошибке скопировано в буфер обмена</string>\n    <string name=\"yt_dlp_docs\">Рекомендации по использованию yt-dlp</string>\n    <string name=\"custom_command_template\">Шаблон настроек</string>\n    <string name=\"start_execute\">Выполнить команду</string>\n    <string name=\"thumbnail\">Миниатюра</string>\n    <string name=\"paste\">Вставить</string>\n    <string name=\"follow_system\">Как в системе</string>\n    <string name=\"convert_to\">Преобразовать в %1$s</string>\n    <string name=\"convert_audio_format\">Преобразование аудиоформата</string>\n    <string name=\"not_convert\">Не преобразовывать</string>\n    <string name=\"on\">Включена</string>\n    <string name=\"off\">Отключена</string>\n    <string name=\"convert_audio_format_desc\">Перекодирование аудиофайлов создаст потерю качества и увеличит размер файла.</string>\n    <string name=\"video_format\">Формат видео</string>\n    <string name=\"best_quality\">Наилучшее качество</string>\n    <string name=\"convert_audio\">Преобразовать</string>\n    <string name=\"close\">Закрыть</string>\n    <string name=\"close_never_show_again\">Не показывать снова</string>\n    <string name=\"download_desc\">Затем нажмите \\\"Загрузить\\\" после настройки параметров загрузки.</string>\n    <string name=\"format\">Формат</string>\n    <string name=\"video_url\">Ссылка на видео</string>\n    <string name=\"download_finish_notification\">Загрузка завершена. Нажмите для открытия.</string>\n    <string name=\"execute_command_notification\">Выполнение пользовательской команды…</string>\n    <string name=\"concurrent_download_desc\">Параллельно загружайте другие части видео M3U8/MPD</string>\n    <string name=\"download_range_selection\">Выбор в плейлисте</string>\n    <string name=\"concurrent_download_num\">%d Поток(ов) будут использоваться для одновременной загрузки видео DASH/HLS.</string>\n    <string name=\"additional_settings\">Дополнительные параметры</string>\n    <string name=\"options\">Параметры</string>\n    <string name=\"show_more_actions\">Показать больше действий</string>\n    <string name=\"download_notification\">Уведомление о загрузке</string>\n    <string name=\"playlist_indicator_text\">Загрузка плейлиста (%1$d/%2$d)…</string>\n    <string name=\"download_directory\">Каталог загрузки</string>\n    <string name=\"audio_directory\">Папка с аудио</string>\n    <string name=\"subdirectory\">Сохранить в подкаталог</string>\n    <string name=\"subdirectory_desc\">Сохраняйте файлы в папках, названных местами, откуда был скачан материал</string>\n    <string name=\"permission_issue_desc\">Каталоги за пределами Download/ и Documents/ не поддерживаются</string>\n    <string name=\"battery_configuration_desc\">Игнорируйте оптимизацию батареи, чтобы приложение загружало также и в фоне</string>\n    <string name=\"paste_desc\">Нажмите \\\"Вставить\\\", чтобы вставить ссылку на видео из буфера обмена.</string>\n    <string name=\"download_history_desc\">Проверяйте и управляйте загрузками в приложении, включая видео- и аудио-файлы.</string>\n    <string name=\"download_playlist\">Загрузка плейлиста</string>\n    <string name=\"defaults\">По умолчанию</string>\n    <string name=\"channel_name\">Загрузить</string>\n    <string name=\"language\">Язык приложения</string>\n    <string name=\"paste_fail_msg\">Не удалось найти подходящий URL-адрес в буфере обмена</string>\n    <string name=\"settings_before_download_text\">Настройте эту загрузку</string>\n    <string name=\"prefix\">Шаблон пути</string>\n    <string name=\"embed_subtitles\">Встраивание субтитров</string>\n    <string name=\"embed_subtitles_desc\">Встраивать в видеофайл пререндерные субтитры, если они доступны</string>\n    <string name=\"new_template\">Новый шаблон</string>\n    <string name=\"template_label\">Заголовок</string>\n    <string name=\"remove_template\">Удалить\\?</string>\n    <string name=\"remove_template_desc\">Удалить \\\"%1$s\\\" из шаблонов команд навсегда?</string>\n    <string name=\"template_selection\">Выбор шаблона</string>\n    <string name=\"custom_command_template_desc\">Редактирование шаблонов команд и управление ими</string>\n    <string name=\"downloading_indicator_text\">Загрузка в процессе…</string>\n    <string name=\"task_canceled\">Эта загрузка отменена</string>\n    <string name=\"github_issue_desc\">Отправьте сообщение о проблеме для сообщения об ошибке или запроса функции</string>\n    <string name=\"info_copied\">Информация, скопированная в буфер обмена</string>\n    <string name=\"github_issue\">Сообщить о проблеме (GitHub)</string>\n    <string name=\"open_file\">Открыть файл</string>\n    <string name=\"restart\">Перезапустить</string>\n    <string name=\"status_fetching_video_info\">Получение информации</string>\n    <string name=\"status_completed\">Завершено</string>\n    <string name=\"status_downloading\">Загрузка</string>\n    <string name=\"status_enqueued\">В очереди</string>\n    <string name=\"status_canceled\">Отменено</string>\n    <string name=\"copy_error_report\">Копировать отчет</string>\n    <string name=\"status_error\">Ошибка</string>\n    <string name=\"copy_link\">Скопировать ссылку</string>\n    <string name=\"video_resolution\">Разрешение видео</string>\n    <string name=\"video_file_size\">Размер файла</string>\n    <string name=\"import_from_clipboard\">Импорт из буфера обмена</string>\n    <string name=\"template_exported\">Экспортировано %1$d шаблон(а/ов)</string>\n    <string name=\"template_imported\">Импортировано %1$d шаблон(а/ов)</string>\n    <string name=\"download_task_count\">%1$d Загрузочная задача</string>\n    <string name=\"recently_added\">Недавно добавленные</string>\n    <string name=\"multiselect_item_count\">%1$d видеофайл(а/ов), %2$d аудиофайл(а/ов)</string>\n    <string name=\"delete_multiple_items_msg\">Удалить %1$d элемент(а/ов) из Вашей истории загрузок навсегда\\?</string>\n    <string name=\"export_to_clipboard\">Экспортировать в буфер обмена</string>\n    <string name=\"sponsorblock_categories\">Категории SponsorBlock</string>\n    <string name=\"sponsorblock_desc\">Удаление или пометка сегментов в видео с помощью SponsorBlock API</string>\n    <string name=\"sponsorblock_categories_desc\">Укажите категории SponsorBlock для удаления или отметки в видеофайле</string>\n    <string name=\"check_for_updates\">Проверить обновления</string>\n    <string name=\"check_for_updates_desc\">Автоматически проверять наличие новейшей версии с GitHub\\'а</string>\n    <string name=\"app_up_to_date\">Уже установлена новейшая версия</string>\n    <string name=\"app_update_failed\">Не удалось обновиться до новейшей версии</string>\n    <string name=\"update\">Обновление</string>\n    <string name=\"aria2_desc\">Используйте aria2c как внешний загрузчик</string>\n    <string name=\"cookies_desc\">Используйте файлы cookie в формате Netscape для загрузки</string>\n    <string name=\"clear_temp_files\">Очистить временные файлы</string>\n    <string name=\"clear_temp_files_desc\">Удалить все временные файлы из временного каталога</string>\n    <string name=\"clear_temp_files_count\">Удален(о) %1$d временный(х) файл(а/ов)</string>\n    <string name=\"clear_temp_files_info\">Временные файлы можно использовать для возобновления отменённых загрузок. Вы уверены, что удалили все эти файлы?\n\\n\n\\nВы можете найти эти файлы в %1$s</string>\n    <string name=\"multiselect_mode\">Режим мультивыделения</string>\n    <string name=\"private_mode\">Инкогнито</string>\n    <string name=\"private_mode_desc\">Отключить историю загрузок</string>\n    <string name=\"dynamic_color\">Динамические цвета</string>\n    <string name=\"dynamic_color_desc\">Примените цвета из обоев к теме приложения</string>\n    <string name=\"file_unavailable\">Этот файл больше недоступен</string>\n    <string name=\"download_with_cellular\">Загружать при подключенной мобильной сети</string>\n    <string name=\"download_with_cellular_desc\">Разрешать загрузку медиа, когда подключена мобильная сеть с лимитным трафиком</string>\n    <string name=\"download_disabled_with_cellular\">Согласно Вашим настройкам, загрузка через мобильную сеть отключена</string>\n    <string name=\"network\">Сеть</string>\n    <string name=\"rate_limit_desc\">Ограничить максимальную скорость загрузки</string>\n    <string name=\"high_contrast\">Высококонтрастная тёмная тема</string>\n    <string name=\"invalid_input\">Недопустимый ввод</string>\n    <string name=\"lowest_quality\">Наименьшее качество</string>\n    <string name=\"unavailable\">Недоступно</string>\n    <string name=\"format_settings_desc\">Формат файла, качество видео, субтитры</string>\n    <string name=\"general_settings_desc\">Версия Yt-dlp, уведомление, плейлист</string>\n    <string name=\"network_settings_desc\">Ограничить скорость, загрузчик, файлы cookie</string>\n    <string name=\"disable_preview\">Отключить миниатюру</string>\n    <string name=\"disable_preview_desc\">Не отображать миниатюры во время загрузки</string>\n    <string name=\"use_custom_command\">Использовать свою команду</string>\n    <string name=\"privacy\">Конфиденциальность</string>\n    <string name=\"crop_artwork\">Обрезать изображение</string>\n    <string name=\"crop_artwork_desc\">Обрезать вставленное изображение в квадрат</string>\n    <string name=\"private_directory\">Приватный каталог</string>\n    <string name=\"private_directory_desc\">Сохранять загрузки в скрытый каталог</string>\n    <string name=\"max_rate\">Максимальная скорость</string>\n    <string name=\"rate_limit\">Скоростной лимит</string>\n    <string name=\"selected_item_count\">Выбрано %1$d видео</string>\n    <string name=\"download_selection_desc\">Выберите видео для загрузки из плейлиста \\\"%1$s\\\"</string>\n    <string name=\"select_all\">Выбрать все</string>\n    <string name=\"format_selection_desc\">Выбор формата для загрузки перед её началом</string>\n    <string name=\"generate_new_cookies\">Сгенерировать новые файлы cookie</string>\n    <string name=\"video_only\">Видео (без аудио)</string>\n    <string name=\"format_selection\">Выбор формата</string>\n    <string name=\"suggested\">Предложенный</string>\n    <string name=\"use_cookies\">Использовать файлы cookie</string>\n    <string name=\"how_does_it_work\">Как это работает\\?</string>\n    <string name=\"remove_cookie_profile_desc\">Удалить эту запись для \\\"%1$s\\\"? Обратите внимание, что файлы cookie, сохранённые на этом сайте, не будут удалены.</string>\n    <string name=\"telegram_channel\">Telegram канал</string>\n    <string name=\"custom_command_enabled_hint\">Некоторые настройки недоступны, когда используется своя команда</string>\n    <string name=\"cookies_usage_msg\">Загрузка с некоторых сайтов требует информацию для авторизации аккаунта. Нажмите \\\"Сгенерировать новые файлы cookie\\\", введите URL-адрес сайта и затем войдите в ваш аккаунт на странице браузера, приложение создаст это для Вас.</string>\n    <string name=\"matrix_space\">Матричное пространство</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"auto_subtitle\">Автоматические субтитры</string>\n    <string name=\"copy_log\">Скопировать лог</string>\n    <string name=\"clear\">Очистить</string>\n    <string name=\"add\">Добавить</string>\n    <string name=\"running_tasks\">Запущенные задачи</string>\n    <string name=\"show_logs\">Показать лог</string>\n    <string name=\"logs\">Лог</string>\n    <string name=\"sdcard_directory\">Папка SD карты</string>\n    <string name=\"auto_subtitle_desc\">Загружать автоматически сгенерированные субтитры</string>\n    <string name=\"shortcuts\">Ярлыки</string>\n    <string name=\"edit_shortcuts\">Редактировать ярлыки</string>\n    <string name=\"subtitle_language\">Языки субтитров</string>\n    <string name=\"download_subtitles\">Загружать субтитры</string>\n    <string name=\"title_activity_share\">Быстрая загрузка</string>\n    <string name=\"subtitle\">Субтитры</string>\n    <string name=\"subtitle_desc\">Языки, встроенные субтитры, автоматические субтитры</string>\n    <string name=\"subtitle_sponsorblock\">Тайминги субтитров могут быть нарушены при удалении сегментов SponsorBlock.</string>\n    <string name=\"edit_shortcuts_desc\">Изменяйте ярлыки, которые могут быть использованы для составления своих команд.</string>\n    <string name=\"video_title_sample_text\">Пример названия видео</string>\n    <string name=\"video_creator_sample_text\">Пример автора видео</string>\n    <string name=\"embed_subtitles_mkv_msg\">Чтобы встроить пререндерные субтитры, контейнер видео будет изменен на mkv. Вы можете использовать Проигрыватель VLC или другие совместимые приложения для просмотра видео с пререндерными субтитрами.</string>\n    <string name=\"filesize_mb\">%.2f МБ</string>\n    <string name=\"filesize_gb\">%.2f ГБ</string>\n    <string name=\"share\">Поделиться</string>\n    <string name=\"update_channel\">Канал обновлений</string>\n    <string name=\"pre_release_channel\">Предварительный</string>\n    <string name=\"stable_channel\">Стабильный</string>\n    <string name=\"update_channel_desc\">Устанавливайте предварительные версии, чтобы ознакомиться с новыми функциями и изменениями.\n\\n\n\\nЭти версии могут быть немного нестабильными поэтому, пожалуйста, не стесняйтесь сообщать нам, если у вас возникнут какие-то проблемы, это поможет нам улучшить приложение в будущем.</string>\n    <string name=\"auto_update\">Автообновление</string>\n    <string name=\"enable_auto_update\">Включить автообновление</string>\n    <string name=\"abs_hint\">Большинство стриминговых сервисов поставляют аудио и видео раздельно. Вы можете выбрать и объединить форматы только аудио с только видео в одно видео.</string>\n    <string name=\"clip_end\">Конец</string>\n    <string name=\"clip_video\">Обрезать видео</string>\n    <string name=\"discard\">Отменить</string>\n    <string name=\"apply\">Применить</string>\n    <string name=\"clip_start\">Начало</string>\n    <string name=\"audio_quality\">Качество аудио</string>\n    <string name=\"unlimited\">Без ограничений</string>\n    <string name=\"audio_format_preference\">Предпочитаемый формат аудио</string>\n    <string name=\"rename\">Переименовать</string>\n    <string name=\"import_from_preferences\">Импортировать</string>\n    <string name=\"title\">Название</string>\n    <string name=\"format_sorting\">Сортировка форматов</string>\n    <string name=\"format_sorting_desc\">Сортировка форматов с помощью параметра -S в yt-dlp</string>\n    <string name=\"clear_all_cookies\">Очистить все файлы cookies</string>\n    <string name=\"lowest_bitrate\">Самый низкий битрейт</string>\n    <string name=\"clear_all_cookies_desc\">Удалить все файлы cookies, хранящиеся в приложении, навсегда\\?</string>\n    <string name=\"audio_quality_desc\">Ограничить битрейт, когда несколько качеств доступны</string>\n    <string name=\"second\">секунда</string>\n    <string name=\"minute\">минута</string>\n    <string name=\"temporary_directory_desc\">Хранить временные файлы во внутреннем каталоге</string>\n    <string name=\"sponsor\">Спонсировать</string>\n    <string name=\"sponsor_desc\">Поддержать приложение путём спонсирования на GitHub</string>\n    <string name=\"feedback\">Обратная связь</string>\n    <string name=\"sponsors\">Спонсоры</string>\n    <string name=\"sponsor_msg\">Seal всегда будет бесплатным и с открытым исходным кодом для всех. Если вам нравится это приложение, пожалуйста, подумайте о спонсорстве на GitHub!</string>\n    <string name=\"audio_format\">Формат аудио</string>\n    <string name=\"beta_features\">Бета</string>\n    <string name=\"enable_experimental_feature\">Включить экспериментальную функцию\\?</string>\n    <string name=\"feature_unavailable\">Функция недоступна</string>\n    <string name=\"no_downloaded_media\">Нет скачанных медиафайлов</string>\n    <string name=\"clip_video_desc\">Создание видеороликов на странице выбора формата</string>\n    <string name=\"switch_to_github_builds\">переход на сборки с GitHub</string>\n    <string name=\"okay\">Ок</string>\n    <string name=\"got_it\">Понятно</string>\n    <string name=\"clip_video_dialog_msg\">Загрузки с использованием этой функции будут делегированы FFmpeg для загрузки выбранных фрагментов видео, эта функция все ещё является экспериментальной, и нарезка будет не совсем точной, не все форматы поддерживают эту функцию, и вы можете столкнуться с более низкой скоростью загрузки.</string>\n    <string name=\"auto_update_disabled_msg\">Автообновление недоступно для сборок %1$s. Если на вашем устройстве не установлено приложение %1$s или вы хотите предварительно ознакомиться с новыми функциями Seal, рассмотрите вариант %2$s.</string>\n    <string name=\"no_custom_command_tasks\">Нет пользовательских командных задач</string>\n    <string name=\"sponsor_msg2\">Большое спасибо!</string>\n    <string name=\"msg_from_developer\">Сообщение от разработчика</string>\n    <string name=\"download_video_desc\">Скачать видео с URL-адреса</string>\n    <string name=\"convert_subtitle\">Конвертировать субтитры</string>\n    <string name=\"convert_subtitle_desc\">Конвертировать субтитры в другой формат</string>\n    <string name=\"split_video\">Разделить видео</string>\n    <string name=\"split_video_msg\">Видео будет разделено на %1$d глав</string>\n    <string name=\"unknown_error_title\">Ой! Что-то пошло не так</string>\n    <string name=\"copy_and_exit\">Скопировать и выйти</string>\n    <string name=\"expand\">Развернуть</string>\n    <string name=\"new_task\">Новая задача на загрузку</string>\n    <string name=\"start\">Начать</string>\n    <string name=\"edit_template\">Редактировать \\\"%1$s\\\"</string>\n    <string name=\"ytdlp_update_action\">Обновить yt-dlp</string>\n    <string name=\"proxy\">Прокси</string>\n    <string name=\"set_directory_desc\">Нажмите чтобы задать путь</string>\n    <string name=\"custom_command_directory\">Кастомный путь команды</string>\n    <string name=\"folder_picker\">Выбор папки</string>\n    <string name=\"proxy_desc\">Используйте прокси для соединения с интернетом</string>\n    <string name=\"legacy\">Классический</string>\n    <string name=\"quality\">Высокое разрешение</string>\n    <string name=\"enable_notifications\">Включить уведомления\\?</string>\n    <string name=\"enable_notifications_desc\">Приложение требует ваше разрешение на отправку уведомлений для отображения стадии процесса загрузки.</string>\n    <string name=\"disable\">Отключить</string>\n    <string name=\"disabled\">Отключено</string>\n    <string name=\"prefer_compatibility_desc\">Используется MP4(H.264) формат для взаимодействия с другими приложениями</string>\n    <string name=\"prefer_quality_desc\">Используется AV1, VP9 или H.265 формат для просмотра в совместимых приложениях</string>\n    <string name=\"custom_command_directory_desc\">Укажите путь вывода при использовании кастомных команд</string>\n    <string name=\"auto\">Автоматический</string>\n    <string name=\"custom\">Пользовательский</string>\n    <string name=\"download_type\">Тип загрузки</string>\n    <string name=\"format_preference\">Предпочитаемый формат</string>\n    <string name=\"learn_more\">Узнать больше</string>\n    <string name=\"commands\">Команды</string>\n    <string name=\"unknown\">Неизвестный</string>\n    <string name=\"refresh_cookies_desc\">Нажмите, чтобы открыть веб-страницу для создания новых файлов cookie:</string>\n    <string name=\"remove_multiple_templates_msg\">Удалить %1$s из сохранённых команд\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d предмет</item>\n        <item quantity=\"few\">%d предметы</item>\n        <item quantity=\"many\">%d предметы</item>\n        <item quantity=\"other\">%d предметы</item>\n    </plurals>\n    <string name=\"ua_header\">Заголовок User-Agent</string>\n    <string name=\"export_to_file\">Экспорт в файл</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp — мощный инструмент командной строки для загрузки видео. Seal упрощает использование yt-dlp, предоставляя интуитивно понятный графический интерфейс, предустановки для общих команд и другие дополнительные функции.\n\\n\n\\nДля расширенного использования yt-dlp Seal позволяет создавать, сохранять и выполнять собственные шаблоны команд напрямую, как в терминале.\n\\n\n\\nПри использовании пользовательских команд большинство параметров и функций графического интерфейса будут отключены.</string>\n    <string name=\"presets\">Пресеты</string>\n    <string name=\"output_template\">Вывод шаблона</string>\n    <string name=\"output_template_desc\">Укажите шаблон для имён выходных файлов</string>\n    <string name=\"clear_download_archive\">Очистить архив загрузок\\?</string>\n    <string name=\"clear_download_archive_desc\">Удалить %1$s из файла архива навсегда\\?</string>\n    <string name=\"download_archive_desc\">Записывать ID загруженных видео в архив во избежание дубликатов</string>\n    <string name=\"download_archive\">Архив загрузок</string>\n    <string name=\"embed_metadata\">Встроить метаданные</string>\n    <string name=\"required\">Необходимый</string>\n    <string name=\"embed_metadata_desc\">Встроить метаданные и миниатюру видео в аудиофайл</string>\n    <string name=\"show_all_items\">Показать все элементы (%1$d)</string>\n    <string name=\"save\">Сохранить</string>\n    <string name=\"use_format_sorting\">Использовать сортировку по формату</string>\n    <string name=\"edit_file\">Редактировать файл</string>\n    <string name=\"restrict_filenames_desc\">Ограничьте имена файлов определенными символами, чтобы обеспечить совместимость</string>\n    <string name=\"restrict_filenames\">Ограничить имена файлов</string>\n    <string name=\"website\">Веб-сайт</string>\n    <string name=\"playlist_title\">Название плейлиста</string>\n    <string name=\"subdirectory_hint\">Ваши загрузки будут сохранены как:</string>\n    <string name=\"system_settings\">Настройки системы</string>\n    <string name=\"force_ipv4\">Принудительно использовать IPv4</string>\n    <string name=\"force_ipv4_desc\">Выполнять все подключения через IPv4</string>\n    <string name=\"keep_subtitle_files\">Оставить файлы субтитров</string>\n    <string name=\"allow_once\">Только сейчас</string>\n    <string name=\"download_with_cellular_request\">Разрешать загрузку через мобильную сеть?</string>\n    <string name=\"allow_always\">Всегда разрешать</string>\n    <string name=\"dont_allow\">Не разрешать</string>\n    <string name=\"merge_audiostream\">Объединение нескольких аудио</string>\n    <string name=\"merge_audiostream_desc\">Разрешить объединение нескольких аудиопотоков в один файл</string>\n    <string name=\"search\">Поиск</string>\n    <string name=\"search_in_downloads\">Поиск в загрузках</string>\n    <string name=\"auto_translated_subtitles\">Субтитры с автопереводом</string>\n    <string name=\"auto_translated_subtitles_msg\">В загрузках можно будет выбрать субтитры, созданные автоматически для каждого языка. Они могут быть неточными и трудными для понимания.</string>\n    <string name=\"remember_for_next_download\">Запомнить для будущей загрузки</string>\n    <string name=\"look_and_feel\">Оформление</string>\n    <string name=\"use_previous_selection\">Использовать прошлый выбор</string>\n    <string name=\"subtitle_language_desc\">Язык субтитров для загрузки в автоматическом выборе формата, через запятую.</string>\n    <string name=\"reset\">Перезагрузить</string>\n    <string name=\"search_in_subtitles\">Поиск в субтитрах</string>\n    <string name=\"no_thanks\">Нет, спасибо</string>\n    <string name=\"update_language_msg\">Следующие языки будут добавлены в список ваших предпочтений для будущих загрузок:</string>\n    <string name=\"update_subtitle_languages\">Обновить языки субтитров?</string>\n    <string name=\"backup_type\">Тип резервной копии</string>\n    <string name=\"file\">Файл</string>\n    <string name=\"clipboard\">Буфер обмена</string>\n    <string name=\"export_download_history\">Экспортировать историю загрузок?</string>\n    <string name=\"export_backup\">Экспорт</string>\n    <string name=\"export_to\">Экспортировать в</string>\n    <string name=\"import_from\">Импортировать из</string>\n    <string name=\"import_download_history\">Импортировать историю загрузок?</string>\n    <string name=\"import_backup\">Импорт</string>\n    <string name=\"full_backup\">Полное резервное копирование</string>\n    <string name=\"import_download_history_msg\">Загруженные файлы не будут импортированы. Вам придётся загрузить их обратно вручную</string>\n    <string name=\"export_download_history_msg\">Экспорт %1$s из истории загрузок. Загруженные файлы и настройки не будут скопированы.</string>\n    <string name=\"interface_and_interaction\">Интерфейс и взаимодействие</string>\n    <string name=\"download_history\">История загрузок</string>\n    <string name=\"download_history_imported\">Импортирован %1$s в историю загрузок</string>\n    <string name=\"redownload\">Скачать заново</string>\n    <string name=\"download_archive_error\">Видео было загружено. Если это не ожидаемое поведение, пожалуйста, проверьте архив загрузки.</string>\n    <string name=\"none\">Нет</string>\n    <string name=\"remux_container_mkv\">Remux видео контейнер</string>\n    <string name=\"cookies_in_database\">Кол-во файлов куки: %1$d, кол-во их источников: %2$d</string>\n    <string name=\"remux_container_mkv_desc\">Конвертировать видеофайлы в MKV контейнеры для улучшения совместимости</string>\n    <string name=\"every_day\">Каждый день</string>\n    <string name=\"every_week\">Каждую неделю</string>\n    <string name=\"every_month\">Каждый месяц</string>\n    <string name=\"playlist\">Плейлист</string>\n    <string name=\"preset\">Пресет</string>\n    <string name=\"prefer_placeholder\">Предпочитать %1$s</string>\n    <string name=\"custom_format_selection_desc\">Выберите из форматов, субтитров и настройте дальше</string>\n    <string name=\"all_languages\">Все языки</string>\n    <string name=\"proceed\">Продолжить</string>\n    <string name=\"task_added\">Задача добавлена в очередь</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d видео</item>\n        <item quantity=\"few\">%d видео</item>\n        <item quantity=\"many\">%d видео</item>\n        <item quantity=\"other\">%d видео</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d аудио</item>\n        <item quantity=\"few\">%d аудио</item>\n        <item quantity=\"many\">%d аудио</item>\n        <item quantity=\"other\">%d аудио</item>\n    </plurals>\n    <string name=\"preset_format_selection_desc\">Скачать автоматически с помощью предпочтений формата</string>\n    <string name=\"edit_preset\">Изменить предустановку</string>\n    <string name=\"best_quality_desc\">Скачать лучший доступный формат</string>\n    <string name=\"you_ll_find_your_downloads_here\">Вы найдете свои загрузки здесь</string>\n    <string name=\"download_hint\">Нажмите на кнопку загрузки или поделитесь ссылкой на видео с этим приложением, чтобы начать загрузку</string>\n    <string name=\"status_downloaded\">Загружено</string>\n    <string name=\"all\">Все</string>\n    <string name=\"select_multiple_link\">Выберите из %1$d ссылок</string>\n    <string name=\"show_navigation_drawer\">Показать навигационную панель</string>\n    <string name=\"resume\">Резюме</string>\n    <string name=\"delete\">Удалить</string>\n    <string name=\"media_info\">Информация о медиа</string>\n    <string name=\"download_queue\">Очередь загрузки</string>\n    <string name=\"trouble_shooting\">Устранение неисправностей</string>\n    <string name=\"issue_tracker\">Отслеживание проблем</string>\n    <string name=\"trouble_shooting_desc\">Устранение распространённых ошибок и проверка на наличие известных ошибок</string>\n    <string name=\"issue_tracker_hint\">Возникла ошибка? Прежде чем сообщать о новой проблеме, воспользуйтесь нашим отслеживанием проблем. Многие распространённые проблемы уже решены и задокументированы там.</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-si/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"download_settings_desc\">සාමාන්‍ය, ආකෘතිය, අභිරුචි විධාන</string>\n    <string name=\"download\">බාගත කරන්න</string>\n    <string name=\"fetching_info\">වීඩියෝ තොරතුරු ලබා ගනිමින්…</string>\n    <string name=\"download_success_msg\">බාගත කිරීම අවසන්</string>\n    <string name=\"download_start_msg\">බාගැනීම \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">වීඩියෝ තොරතුරු ලබා ගැනීමට නොහැකි විය</string>\n    <string name=\"general_settings\">සාමාන්‍ය සැකසුම්</string>\n    <string name=\"language_settings\">සංදර්ශක භාෂාව සකසන්න</string>\n    <string name=\"paste_fail_msg\">ක්ලිප්බෝඩයේ ඇති URL ය සමඟ ගැළපීමට නොහැකි විය</string>\n    <string name=\"ytdlp_version\">Yt-dlp අනුවාදය</string>\n    <string name=\"delete_info\">ඉවත් කරන්න\\?</string>\n    <string name=\"delete_info_msg\">ඔබේ බාගැනීම් ඉතිහාසයෙන් \\\"%1$s\\\" ඉවත් කරන්නද\\?</string>\n    <string name=\"confirm\">තහවුරුයි</string>\n    <string name=\"dismiss\">අවලංගු කරන්න</string>\n    <string name=\"downloads_history\">බාගැනීම්</string>\n    <string name=\"audio\">ඕඩියෝ</string>\n    <string name=\"link_copied\">සබැඳිය ක්ලිප්බෝඩයට පිටපත් කරන ලදී</string>\n    <string name=\"open_url\">සබැඳිය විවෘත කරන්න</string>\n    <string name=\"remove\">ඉවත් කරන්න</string>\n    <string name=\"delete_file\">මකන්න</string>\n    <string name=\"about\">විස්තර</string>\n    <string name=\"about_page\">අනුවාදය, නිකුත් කිරීම්, ස්තූතීන්</string>\n    <string name=\"back\">ආපසු</string>\n    <string name=\"readme_desc\">GitHub ගබඩාව සහ README පරීක්ෂා කරන්න</string>\n    <string name=\"start_execute\">විධානය ක්‍රියාත්මක කරන්න</string>\n    <string name=\"print_details\">විස්තරාත්මක ප්‍රතිදාන</string>\n    <string name=\"print_details_desc\">බාගත කිරීමේදී විස්තරාත්මක පණිවිඩ පෙන්වන්න</string>\n    <string name=\"display\">සංදර්ශක සැකසුම්</string>\n    <string name=\"on\">සක්‍රීයයි</string>\n    <string name=\"settings_before_download_desc\">බාගත කිරීමට පෙර වින්‍යාස කරන්න</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp භාවිතයන්</string>\n    <string name=\"best_quality\">උසස් ගුණාත්මකතාව (default)</string>\n    <string name=\"video_quality_desc\">ආකෘතියේ ගුණාත්මකභාවය සහ විශාලත්වය සීමා කිරීම</string>\n    <string name=\"preferred_format_desc\">බහු බාගැනීම් වලදී තෝරාගත් ආකෘතිය</string>\n    <string name=\"close\">වසන්න</string>\n    <string name=\"close_never_show_again\">නැවත නොපෙන්වන්න</string>\n    <string name=\"user_guide\">පරිශීලක මාර්ගෝපදේශ</string>\n    <string name=\"open_settings\">සැකසුම් පෙන්වන්න</string>\n    <string name=\"download_playlist\">Playlist බාගන්න</string>\n    <string name=\"channel_description\">බාගැනීම් සහ ප්‍රගතිය දන්වන්න</string>\n    <string name=\"video_url\">වීඩියො සබැඳිය</string>\n    <string name=\"share_fail_msg\">බෙදාගත් අන්තර්ගතයෙන් URL ගැලපීමට නොහැක</string>\n    <string name=\"share_success_msg\">බෙදාගත් අන්තර්ගතයෙන් වීඩියෝ සබැඳිය කියවමින් පවතී…</string>\n    <string name=\"service_title\">Seal බාගත කරගනිමින් පවතී…</string>\n    <string name=\"unknown_error\">නොදන්නා දෝෂයක්</string>\n    <string name=\"translate\">පරිවර්තනය</string>\n    <string name=\"translate_desc\">යෙදුම Hosted Weblate මත පරිවර්තනය කිරීමට සහාය වන්න</string>\n    <string name=\"remove_template\">ඉවත් කරන්න\\?</string>\n    <string name=\"task_canceled\">බාගැනීම අවලංගු කරන ලදී</string>\n    <string name=\"info_copied\">තොරතුරු ක්ලිප්බෝඩයට පිටපත් විය</string>\n    <string name=\"status_downloading\">බාගනිමින්</string>\n    <string name=\"status_canceled\">අවලංගුයි</string>\n    <string name=\"status_fetching_video_info\">තොරතුරු ගනිමින් පවතී</string>\n    <string name=\"copy_error_report\">දෝෂ වාර්තාව</string>\n    <string name=\"video_resolution\">වීඩියෝ විභේදනය</string>\n    <string name=\"recently_added\">මෑතකදී එකතු කිරීම්</string>\n    <string name=\"delete_multiple_items_msg\">ඔබගේ බාගැනීම් ඉතිහාසයෙන් %1$d ඉවත් කරන්නද\\?</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API මගින් වීඩියෝ වල කොටස් ඉවත් කරන්න</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock ප්‍රවර්ගයන්</string>\n    <string name=\"app_up_to_date\">නව අනුවාදයක් නොමැත</string>\n    <string name=\"update\">යාවත්කාලීන කරන්න</string>\n    <string name=\"aria2_desc\">බාහිර බාගැනීම් සදහා aria2c භාවිතා කරන්න</string>\n    <string name=\"cookies_desc\">බාගැනීම් සඳහා Netscape ආකෘතිගත Cookies භාවිතා කරන්න</string>\n    <string name=\"clear_temp_files_info\">අවලංගු කළ බාගැනීම් නැවත ආරම්භ කිරීමට තාවකාලික ගොනු භාවිතා කළ හැක. මෙම ගොනු සියල්ල මකන්නද\\?</string>\n    <string name=\"multiselect_mode\">බහුවරණ තේරීම්</string>\n    <string name=\"private_mode_desc\">බාගැනීම් ඉතිහාසය අක්‍රිය කරන්න</string>\n    <string name=\"dynamic_color\">ගතික වර්ණ</string>\n    <string name=\"dynamic_color_desc\">යෙදුම් තේමාවට බිතුපත්වල වර්ණ යොදන්න</string>\n    <string name=\"download_with_cellular\">සෙලියුලර් ඩේටා භාවිතයෙන් බාගන්න</string>\n    <string name=\"download_with_cellular_desc\">සීමාගත ජාල තුළ බාගැනීමට අවසර ලබාදෙන්න</string>\n    <string name=\"file_unavailable\">මෙම ගොනුව තවදුරටත් නොමැත</string>\n    <string name=\"rate_limit\">වේග සීමාව</string>\n    <string name=\"max_rate\">උපරිම සීමාව</string>\n    <string name=\"high_contrast\">තද අදුරු තේමාව</string>\n    <string name=\"invalid_input\">වලංගු නොවන ආදානයකි</string>\n    <string name=\"unavailable\">නොපවතී</string>\n    <string name=\"format_settings_desc\">ගොනු ආකෘතිය, වීඩියෝ ගුණාත්මකභාවය, උපසිරැසි</string>\n    <string name=\"disable_preview\">පෙරදසුන අක්‍රිය කරන්න</string>\n    <string name=\"disable_preview_desc\">බාගැනීම්වල පෙරදසුන අබල කරන්න</string>\n    <string name=\"privacy\">පෞද්ගලිකත්වය</string>\n    <string name=\"use_custom_command\">අභිරුචි විධාන භාවිතා කරන්න</string>\n    <string name=\"private_directory\">පුද්ගලික ඩිරෙක්ටරිය</string>\n    <string name=\"private_directory_desc\">සැඟවූ ඩිරෙක්ටරියක බාගත කිරීම් ගබඩා කරන්න</string>\n    <string name=\"extract_audio_summary\">වීඩියෝ වෙනුවට ශ්‍රව්‍ය බාගත කර සුරකින්න</string>\n    <string name=\"video_directory\">වීඩියෝ ගොනුව</string>\n    <string name=\"extract_audio\">ශබ්දය ලෙස සුරකින්න</string>\n    <string name=\"settings\">සැකසුම්</string>\n    <string name=\"url_empty\">සබැඳිය හිස් නොවිය යුතුයි</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp නවතම අනුවාදය භාවිත කරයි</string>\n    <string name=\"permission_denied\">අවසර නොලැබුණි</string>\n    <string name=\"yt_dlp_update_fail\">නවතම yt-dlp අනුවාදය ස්ථාපනය කිරීමට නොහැකි විය. කරුණාකර ඔබ අන්තර්ජාලයට සම්බන්ධ වී ඇති බව සහතික කර ගන්න.</string>\n    <string name=\"download_error_msg\">ගොනුව බාගැනීමට නොහැකි විය</string>\n    <string name=\"paste_msg\">ක්ලිප්බෝඩයෙන් URL පේස්ට් කරන්න</string>\n    <string name=\"ytdlp_update\">නවතම yt-dlp අනුවාදය ස්ථාපනය කිරීමට ක්ලික් කරන්න</string>\n    <string name=\"language\">සංදර්ශක භාෂාව</string>\n    <string name=\"task_running\">පවතින බාගැනීම් කාර්යයක් දැනටමත් ක්‍රියාත්මක වේ</string>\n    <string name=\"version\">අනුවාදය</string>\n    <string name=\"release_desc\">වෙනස් කිරීම් සහ නව අනුවාද</string>\n    <string name=\"release\">නවතම අනුවාදය</string>\n    <string name=\"video\">වීඩියෝ</string>\n    <string name=\"custom_command\">අභිරුචි විධානයන්</string>\n    <string name=\"custom_command_desc\">අභිරුචි ටෙම්ප්ලේට සමඟ yt-dlp විධානය ක්‍රියාත්මක කරන්න</string>\n    <string name=\"custom_command_template\">විධාන ටෙම්ප්ලේට</string>\n    <string name=\"edit\">සංස්කරණය</string>\n    <string name=\"display_settings\">අඳුරු තේමාව, ගතික වර්ණය, භාෂා</string>\n    <string name=\"dark_theme\">අඳුරු තේමාව</string>\n    <string name=\"follow_system\">පද්ධතිය</string>\n    <string name=\"off\">අක්‍රීයයි</string>\n    <string name=\"cancel\">අවලංගු කරන්න</string>\n    <string name=\"settings_before_download\">බාගැනීමට පෙර සකසන්න</string>\n    <string name=\"convert_audio_format\">ඕඩියෝ ආකෘතිය පරිවර්තනය කරන්න</string>\n    <string name=\"settings_before_download_text\">මෙම බාගැනීම සකසන්න</string>\n    <string name=\"error_copied\">දෝෂ වාර්තාව ක්ලිප්බෝඩයට පිටපත් විය</string>\n    <string name=\"paste\">පේස්ට්</string>\n    <string name=\"edit_template_desc\">ප්‍රතිදාන ස්ථානය සහ URL යෙදුම මගින් එක් කරනු ඇත.</string>\n    <string name=\"convert_to\">%1$s ලෙස පරිවර්තනය කරන්න</string>\n    <string name=\"format\">ආකෘතිය</string>\n    <string name=\"convert_audio_format_desc\">MP3 හෝ M4A ආකෘති බොහෝ උපාංගවල ක්‍රියා කරයි</string>\n    <string name=\"video_quality\">වීඩියෝ ගුණාත්මකතාවය</string>\n    <string name=\"not_specified\">නිශ්චිතව දක්වා නැත (default)</string>\n    <string name=\"video_format_preference\">වීඩියෝ ආකෘතිය</string>\n    <string name=\"video_format\">වීඩියෝ ආකෘතිය</string>\n    <string name=\"convert_audio\">පරිවර්තනය කරන්න</string>\n    <string name=\"start_download\">බාගත කරන්න</string>\n    <string name=\"paste_desc\">ක්ලිප්බෝඩයෙන් වීඩියෝ සබැඳිය ලබා ගැනීමට \\\"පේස්ට්\\\" ක්ලික් කරන්න.</string>\n    <string name=\"download_desc\">සැකසුම් සකස් කිරීමෙන් පසු \\\"බාගත කරන්න\\\" ක්ලික් කරන්න.</string>\n    <string name=\"execute_command_notification\">අභිරුචි විධානයන් ක්‍රියාත්මක වෙමින්…</string>\n    <string name=\"check_download_settings_desc\">බාගැනීම් සැකසුම් බලන්න සහ නවතම yt-dlp අනුවාදයෙහි සිටීදැයි තහවුරු කරගන්න.</string>\n    <string name=\"download_playlist_desc\">වීඩියෝ රැසක් එකවර playlist මගින් බාගන්න</string>\n    <string name=\"channel_name\">බාගන්න</string>\n    <string name=\"concurrent_download\">කොටස් ගණනාවකින් බාගන්න</string>\n    <string name=\"download_finish_notification\">බාගැනීම අවසන්. විවෘත කිරීමට ක්ලික් කරන්න.</string>\n    <string name=\"battery_settings_desc\">කරුණාකර පසුබිම් බාගැනීම් සිදුකිරීමට යෙදුමේ බැටරි භාවිතය පද්ධති සැකසීම් තුළ \\\"Unrestricted\\\" ලෙස සකසන්න.</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD වීඩියෝවල කොටස් සමාන්තරව බාගත කරන්න</string>\n    <string name=\"fetching_playlist_info\">Playlist තොරතුරු ලබා ගනිමින්…</string>\n    <string name=\"options\">විකල්ප</string>\n    <string name=\"additional_settings\">අමතර සැකසුම්</string>\n    <string name=\"app_update_failed\">නවතම අනුවාදයට යාවත්කාලීන කිරීමට අසමත් විය</string>\n    <string name=\"clear_temp_files\">තාවකාලික ගොනු ඉවත් කරන්න</string>\n    <string name=\"clear_temp_files_desc\">බාගැනීම් නාමාවලියෙන් සියලුම තාවකාලික ගොනු මකන්න</string>\n    <string name=\"show_more_actions\">තවත් විකල්ප පෙන්වන්න</string>\n    <string name=\"download_notification\">බාගත කිරීම් දැන්වීම්</string>\n    <string name=\"clear_temp_files_count\">තාවකාලික ගොනු %1$dක් මකා දමන ලදී</string>\n    <string name=\"download_notification_desc\">බාගත කළ ගොනු සහ ප්‍රගතිය දැනුම් දෙන්න</string>\n    <string name=\"download_range_selection\">Playlist තේරීම</string>\n    <string name=\"download_range_desc\">\\\"%3$s\\\" ධාවන ලැයිස්තුවෙන් බාගත කිරීමට වීඩියෝ පරාසය සඳහන් කරන්න (%1$d සිට %2$d දක්වා).</string>\n    <string name=\"from\">පටන්ගන්න</string>\n    <string name=\"audio_directory\">ඕඩියෝ ගොනුව</string>\n    <string name=\"download_directory_desc\">වීඩියෝ සහ ශ්‍රව්‍ය ගොනු ගබඩා කළ යුතු ස්ථානය තෝරන්න</string>\n    <string name=\"to\">අවසන් කරන්න</string>\n    <string name=\"invalid_index_range\">වලංගු නොවන දර්ශක පරාසයකි</string>\n    <string name=\"embed_subtitles_desc\">පවතී නම් වීඩියෝවලට උපසිරැසි ඇතුළත් කෙරේ</string>\n    <string name=\"playlist_indicator_text\">ධාවන ලැයිස්තුව බාගනිමින් පවතී (%1$d/%2$d), නතර කිරීමට නවත්වන්න ක්ලික් කරන්න.</string>\n    <string name=\"download_directory\">බාගැනීම් ඩිරෙක්ටරිය</string>\n    <string name=\"download_disabled_with_cellular\">ඔබගේ සැකසීම් අනුව සෙලියුලර් ජාලයන් මගින් බාගැනීම අක්‍රිය කර ඇත</string>\n    <string name=\"subdirectory_desc\">අදාළ වෙබ් අඩවිය ලෙස නම් කර ඇති ෆෝල්ඩරවල ගොනු සුරකින්න</string>\n    <string name=\"permission_issue_desc\">Download/ සහ Documents/ ඩිරෙක්ටරිවලින් පිටත සහාය නොදක්වයි</string>\n    <string name=\"battery_configuration\">බැටරි කළමනාකරණය</string>\n    <string name=\"subdirectory\">උප ඩිරෙක්ටරිය තුළ සුරකින්න</string>\n    <string name=\"battery_configuration_desc\">පසුබිම් බාගැනීම් සදහා බැටරි ප්‍රශස්තකරණය නොසලකා හරින්න</string>\n    <string name=\"network\">ජාලය</string>\n    <string name=\"rate_limit_desc\">බාගැනීම් සඳහා උපරිම වේගය සීමා කරන්න</string>\n    <string name=\"permission_issue\">ආචයන අවසර ගැටලුවකි</string>\n    <string name=\"network_settings_desc\">අනුපාත සීමාව, බාගත කරන්නා, cookies</string>\n    <string name=\"general_settings_desc\">Yt-dlp අනුවාදය, දැනුම්දීම්, playlist</string>\n    <string name=\"crop_artwork_desc\">අන්තර්ගත රූපය චතුරස්‍රාකාර ලෙස කපන්න</string>\n    <string name=\"embed_subtitles\">උපසිරැසි ඇතුළත් කරන්න</string>\n    <string name=\"template_label\">ලේබල්</string>\n    <string name=\"downloading_indicator_text\">බාගනිමින් පවතී, අවලංගු කිරීමට ක්ලික් කරන්න.</string>\n    <string name=\"github_issue\">GitHub වාර්තා කිරීම්</string>\n    <string name=\"restart\">යළි අරඹන්න</string>\n    <string name=\"github_issue_desc\">ගැටලු හෝ විශේෂාංග දැනුම්දීමට Issue ලෙස වාර්තා කරන්න</string>\n    <string name=\"status_completed\">සම්පූර්ණයි</string>\n    <string name=\"import_from_clipboard\">ක්ලිප්බෝඩයෙන් ලබාගන්න</string>\n    <string name=\"check_for_updates\">යාවත්කාලීනයන් පරීක්ෂා කරන්න</string>\n    <string name=\"lowest_quality\">අඩුම ගුණාත්මකතාව</string>\n    <string name=\"open_file\">ගොනුව විවෘත කරන්න</string>\n    <string name=\"status_error\">ගැටලුවක්</string>\n    <string name=\"copy_link\">සබැඳිය පිටපත් කරන්න</string>\n    <string name=\"video_file_size\">වීඩියෝ ගොනු විශාලත්වය</string>\n    <string name=\"export_to_clipboard\">ක්ලිප්බෝඩයට යවන්න</string>\n    <string name=\"download_task_count\">බාගැනීම් කාර්ය %1$d</string>\n    <string name=\"multiselect_item_count\">%1$d වීඩියෝ, %2$d ශ්‍රව්‍ය ගොනු</string>\n    <string name=\"sponsorblock_categories_desc\">වීඩියෝ ගොනුවෙන් ඉවත් කළ යුතු SponsorBlock ප්‍රවර්ග සඳහන් කරන්න</string>\n    <string name=\"check_for_updates_desc\">GitHub හි නවතම අනුවාද ස්වයංක්‍රීයව පරීක්ෂා කරන්න</string>\n    <string name=\"create_thumbnail\">සංක්ෂිප්ත රූපය සුරකින්න</string>\n    <string name=\"create_thumbnail_summary\">වීඩියෝ සංක්ෂිප්ත රූපය ගොනුක් ලෙස සුරකින්න</string>\n    <string name=\"checked\">පරීක්ෂා කළා</string>\n    <string name=\"credits_desc\">ස්තූතීන් සහ libre මෘදුකාංග</string>\n    <string name=\"advanced_settings\">උසස් සැකසුම්</string>\n    <string name=\"thumbnail\">සංක්ෂිප්ත රූපය</string>\n    <string name=\"not_convert\">පරිවර්තනය නොවේ</string>\n    <string name=\"download_history_desc\">යෙදුමේ බාගැනීම් හසුරුවන්න, වීඩියෝ සහ ශ්‍රව්‍ය ගොනු ඇතුලුව.</string>\n    <string name=\"defaults\">පෙරනිමිය</string>\n    <string name=\"concurrent_download_num\">DASH/HLS වීඩියෝ සමගාමීව බාගැනීමට ත්‍රෙඩ් %d ක් භාවිතා කරනු ඇත.</string>\n    <string name=\"prefix\">ආචයන ටෙම්ප්ලේට ස්ථානය</string>\n    <string name=\"new_template\">නව ටෙම්ප්ලේටයක්</string>\n    <string name=\"remove_template_desc\">විධාන ටෙම්ප්ලේට වලින් \\\"%1$s\\\" ඉවත් කරන්නද\\?</string>\n    <string name=\"template_selection\">ටෙම්ප්ලේට තෝරා ගැනීම්</string>\n    <string name=\"custom_command_template_desc\">විධාන ටෙම්ප්ලේට සංස්කරණය සහ කළමනාකරණය</string>\n    <string name=\"status_enqueued\">පේළිගතයි</string>\n    <string name=\"private_mode\">පුද්ගලික පැතිකඩ</string>\n    <string name=\"crop_artwork\">රූපය ක්‍රෝප් කරන්න</string>\n    <string name=\"credits\">ස්තූතීන්</string>\n    <string name=\"template_imported\">ටෙම්ප්ලේට %1$d ක් ආයාත කරන ලදී</string>\n    <string name=\"template_exported\">ටෙම්ප්ලේට %1$d ක් නිර්යාත කරන ලදී</string>\n    <string name=\"select_all\">සියල්ල තෝරන්න</string>\n    <string name=\"selected_item_count\">%1$d තෝරාගන්නා ලදී</string>\n    <string name=\"download_selection_desc\">\\\"%1$s\\\" ධාවන ලැයිස්තුවෙන් වීඩියෝ බාගැනීම සදහා තෝරන්න</string>\n    <string name=\"sdcard_directory\">SD card ගොනුව</string>\n    <string name=\"title_activity_share\">ඉක්මන් බාගත කිරීම්</string>\n    <string name=\"video_only\">වීඩියෝව (ශ්‍රව්‍ය නැත)</string>\n    <string name=\"cookies\">කුකීස්</string>\n    <string name=\"suggested\">යෝජිත</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-sk/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"settings\">Nastavenia</string>\n    <string name=\"create_thumbnail\">Uložiť miniaturu</string>\n    <string name=\"download_settings_desc\">Všeobecné, formát, vlastný príkaz</string>\n    <string name=\"download\">Sťahovanie</string>\n    <string name=\"extract_audio_summary\">Stiahnuť a uložiť zvuk namiesto videa</string>\n    <string name=\"create_thumbnail_summary\">Uložiť miniatúru videa ako súbor</string>\n    <string name=\"yt_dlp_up_to_date\">Používate najnovšiu verziu yt-dlp</string>\n    <string name=\"fetching_info\">Získavanie informácií o videu…</string>\n    <string name=\"download_start_msg\">Sťahovanie „%1$s“</string>\n    <string name=\"general_settings\">Obecné</string>\n    <string name=\"language\">Jazyk</string>\n    <string name=\"language_settings\">Nastaviť jazyk</string>\n    <string name=\"paste_msg\">Vložená adresa zo schránky</string>\n    <string name=\"ytdlp_version\">Yt-dlp verzia</string>\n    <string name=\"ytdlp_update_action\">Aktualizovať yt-dlp</string>\n    <string name=\"delete_info_msg\">Navždy odstrániť „%1$s“ z histórie sťahovania?</string>\n    <string name=\"confirm\">Potvrdiť</string>\n    <string name=\"dismiss\">Zrušiť</string>\n    <string name=\"audio\">Zvuk</string>\n    <string name=\"link_copied\">Odkaz skopírovaný do schránky</string>\n    <string name=\"delete_file\">Odstrániť súbor</string>\n    <string name=\"about\">O aplikácií</string>\n    <string name=\"about_page\">Verzia, spätná väzba, automatické aktualizácie</string>\n    <string name=\"video_directory\">Zložka videí</string>\n    <string name=\"extract_audio\">Uložiť ako zvuk</string>\n    <string name=\"url_empty\">Odkaz nemôže byť prázdny</string>\n    <string name=\"download_success_msg\">Sťahovanie je dokončené</string>\n    <string name=\"yt_dlp_update_fail\">Inštalácia najnovšej verzie yt-dlp zlyhala. Skontrolujte prosím pripojenie k internetu.</string>\n    <string name=\"download_error_msg\">Sťahovanie súboru zlyhalo</string>\n    <string name=\"permission_denied\">Oprávnenie zamietnuté</string>\n    <string name=\"fetch_info_error_msg\">Získavanie informácií o videu zlyhalo</string>\n    <string name=\"paste_fail_msg\">Nepodarilo sa nájsť adresu v schránke</string>\n    <string name=\"task_running\">Už prebieha iná sťahovacia úloha</string>\n    <string name=\"ytdlp_update\">Kliknite pre nainštalovanie najnovšej verzie yt-dlp</string>\n    <string name=\"delete_info\">Odstrániť?</string>\n    <string name=\"downloads_history\">Stiahnuté súbory</string>\n    <string name=\"open_url\">Otvoriť odkaz</string>\n    <string name=\"remove\">Odstrániť</string>\n    <string name=\"back\">Späť</string>\n    <string name=\"version\">Verzia</string>\n    <string name=\"release_desc\">Otvoriť zoznamy zmien a nové verzie</string>\n    <string name=\"release\">Najnovšie vydanie</string>\n    <string name=\"readme_desc\">Najnovšie vydanie</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Skontrolované</string>\n    <string name=\"credits\">Poďakovanie</string>\n    <string name=\"custom_command\">Vlastné príkazy</string>\n    <string name=\"edit\">Upraviť</string>\n    <string name=\"start_execute\">­</string>\n    <string name=\"advanced_settings\">Pokročilé</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-sl/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Video mapa</string>\n    <string name=\"create_thumbnail\">Shrani sličico</string>\n    <string name=\"settings\">Nastavite</string>\n    <string name=\"extract_audio\">Shrani kot avdio</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-sr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"download_desc\">Затим, додирните на „Преузми“ након прилагођавања подешавања.</string>\n    <string name=\"check_download_settings_desc\">Погледајте подешавања преузимања и уверите се да имате најновију верзију yt-dlp пре коришћења.</string>\n    <string name=\"download_playlist\">Преузми плејлисту</string>\n    <string name=\"download_playlist_desc\">Преузмите више видео снимака с плејлисте</string>\n    <string name=\"defaults\">Подразумевано</string>\n    <string name=\"app_update_failed\">Ажурирање на најновију верзију није успело</string>\n    <string name=\"private_mode_desc\">Онемогућите историју преузимања</string>\n    <string name=\"channel_name\">Преузимање</string>\n    <string name=\"channel_description\">Обавештење о преузетим фајловима и напретку</string>\n    <string name=\"download_finish_notification\">Преузимање је завршено. Додирните да бисте отворили.</string>\n    <string name=\"execute_command_notification\">Покретање прилагођених команди…</string>\n    <string name=\"battery_settings_desc\">Подесите потрошњу батерије ове апликације на „Неограничено“ у системским подешавањима да би се преузимање наставило у позадини.</string>\n    <string name=\"options\">Опције</string>\n    <string name=\"additional_settings\">Додатна подешавања</string>\n    <string name=\"download_range_selection\">Избор плејлисте</string>\n    <string name=\"audio_directory\">Фолдер за аудио снимке</string>\n    <string name=\"battery_configuration_desc\">Игноришите оптимизацију батерије за ову апликацију да бисте преузимали у позадини</string>\n    <string name=\"fetching_playlist_info\">Преузимање информација о плејлисти…</string>\n    <string name=\"playlist_indicator_text\">Преузимање плејлисте (%1$d/%2$d)…</string>\n    <string name=\"subdirectory_desc\">Сачувајте фајлове у фолдере који се називају као одговарајућа поља</string>\n    <string name=\"permission_issue_desc\">Фолдери изван Download/ и Documents/ нису подржани</string>\n    <string name=\"unknown_error\">Непозната грешка</string>\n    <string name=\"translate_desc\">Помозите да преведете ову апликацију на Hosted Weblate</string>\n    <string name=\"template_label\">Ознака</string>\n    <string name=\"remove_template_desc\">Заувек уклонити „%1$s“ из командних шаблона\\?</string>\n    <string name=\"aria2_desc\">Користите aria2c као спољни програм за преузимање</string>\n    <string name=\"clear_temp_files_info\">Привремени фајлови се могу користити за наставак отказаних преузимања. Желите ли заиста да избришете све ове фајлове\\?\n\\n\n\\nОвим фајловима можете приступити у %1$s</string>\n    <string name=\"template_selection\">Избор шаблона</string>\n    <string name=\"downloading_indicator_text\">Преузимање је у току…</string>\n    <string name=\"task_canceled\">Задатак преузимања је отказан</string>\n    <string name=\"info_copied\">Информације су копиране у привремену меморију</string>\n    <string name=\"status_enqueued\">Стављено у редослед</string>\n    <string name=\"status_canceled\">Отказано</string>\n    <string name=\"github_issue\">GitHub пријава проблема</string>\n    <string name=\"github_issue_desc\">Пријавите проблем или пошаљите захтев за нову функцију</string>\n    <string name=\"clear_temp_files_desc\">Избришите све привремене фајлове из привременог фолдера</string>\n    <string name=\"dynamic_color\">Динамичка боја</string>\n    <string name=\"general_settings_desc\">Yt-dlp верзија, обавештење, плејлиста</string>\n    <string name=\"rate_limit_desc\">Ограничите максималну брзину преузимања</string>\n    <string name=\"unavailable\">Недоступно</string>\n    <string name=\"video_directory\">Фолдер за видео снимке</string>\n    <string name=\"download\">Преузми</string>\n    <string name=\"url_empty\">Линк не може бити празан</string>\n    <string name=\"fetching_info\">Преузимање информација о видео снимку…</string>\n    <string name=\"permission_denied\">Дозвола је одбијена</string>\n    <string name=\"download_success_msg\">Преузимање је завршено</string>\n    <string name=\"fetch_info_error_msg\">Није могуће прикупити информације о видео снимку</string>\n    <string name=\"language\">Језик</string>\n    <string name=\"paste_fail_msg\">Није могуће пронаћи одговарајућу URL адресу у привременој меморији</string>\n    <string name=\"delete_info_msg\">Заувек уклонити „%1$s“ из историје преузимања\\?</string>\n    <string name=\"delete_info\">Уклонити\\?</string>\n    <string name=\"dismiss\">Откажи</string>\n    <string name=\"downloads_history\">Преузимања</string>\n    <string name=\"open_url\">Отвори линк</string>\n    <string name=\"delete_file\">Избриши фајл</string>\n    <string name=\"about_page\">Верзија, повратне информације, аутоматско ажурирање</string>\n    <string name=\"credits_desc\">Кредити и слободни софтвер</string>\n    <string name=\"custom_command\">Прилагођена команда</string>\n    <string name=\"custom_command_desc\">Покрените команду yt-dlp с прилагођеним шаблоном</string>\n    <string name=\"custom_command_template\">Командни шаблон</string>\n    <string name=\"edit\">Измени</string>\n    <string name=\"start_execute\">Започето је извршавање команде</string>\n    <string name=\"advanced_settings\">Напредно</string>\n    <string name=\"print_details\">Детаљан излаз информација</string>\n    <string name=\"print_details_desc\">Приказивање детаљних порука приликом преузимања</string>\n    <string name=\"display\">Приказ</string>\n    <string name=\"off\">Искључено</string>\n    <string name=\"cancel\">Откажи</string>\n    <string name=\"settings_before_download\">Конфигурација пре преузимања</string>\n    <string name=\"settings_before_download_desc\">Подесите преференце пре преузимања</string>\n    <string name=\"settings_before_download_text\">Прилагодите ово преузимање</string>\n    <string name=\"error_copied\">Извештај о грешци је копиран у привремену меморију</string>\n    <string name=\"thumbnail\">Сличица</string>\n    <string name=\"convert_audio_format_desc\">Поновно кодирање фајлова аудио снимака узроковаће губитак квалитета звука и повећање величине фајла.</string>\n    <string name=\"video_quality\">Квалитет видео снимка</string>\n    <string name=\"video_quality_desc\">Ограничите квалитет видео снимка, када их је доступно више</string>\n    <string name=\"convert_audio\">Претвори</string>\n    <string name=\"user_guide\">Упутство за употребу</string>\n    <string name=\"open_settings\">Отвори подешавања</string>\n    <string name=\"paste_desc\">Додирните на „Налепи“ да бисте добили линк видео снимка из привремене меморије.</string>\n    <string name=\"download_history_desc\">Проверите и управљајте преузимањима у апликацији, укључујући фајлове видео и аудио снимака.</string>\n    <string name=\"video_url\">Линк видео снимка</string>\n    <string name=\"concurrent_download\">Вишенитно преузимање</string>\n    <string name=\"concurrent_download_desc\">Преузмите више делова M3U8/MPD видео снимака паралелно</string>\n    <string name=\"concurrent_download_num\">%d нит(и) би се користило за истовремено преузимање DASH/HLS изворних видео снимака.</string>\n    <string name=\"share_fail_msg\">Није могуће подударање URL адресе из дељеног садржаја</string>\n    <string name=\"share_success_msg\">Читање линка видео снимка из дељеног садржаја…</string>\n    <string name=\"show_more_actions\">Прикажи још радњи</string>\n    <string name=\"download_notification\">Обавештење о преузимању</string>\n    <string name=\"download_notification_desc\">Обавештење о преузетим фајловима и напретку</string>\n    <string name=\"download_range_desc\">Одредите опсег видео снимака за преузимање с плејлисте „%3$s“ (од %1$d до %2$d).</string>\n    <string name=\"from\">Почетак</string>\n    <string name=\"to\">Крај</string>\n    <string name=\"invalid_index_range\">Неважећи опсег индекса</string>\n    <string name=\"download_directory\">Фолдер за преузимања</string>\n    <string name=\"download_directory_desc\">Изаберите где ће се чувати фајлови видео и аудио снимака</string>\n    <string name=\"subdirectory\">Сачувај у потфолдер</string>\n    <string name=\"permission_issue\">Проблем с дозволом за приступ меморији</string>\n    <string name=\"battery_configuration\">Конфигурација батерије</string>\n    <string name=\"service_title\">Seal преузима…</string>\n    <string name=\"translate\">Преведи</string>\n    <string name=\"prefix\">Шаблон путање</string>\n    <string name=\"embed_subtitles\">Угради титлове</string>\n    <string name=\"embed_subtitles_desc\">Уградите обезбеђене титлове у видео снимке, ако су доступни</string>\n    <string name=\"new_template\">Нови шаблон</string>\n    <string name=\"remove_template\">Уклонити\\?</string>\n    <string name=\"custom_command_template_desc\">Измењујте и управљајте командним шаблонима</string>\n    <string name=\"status_completed\">Завршено</string>\n    <string name=\"status_downloading\">Преузимање</string>\n    <string name=\"open_file\">Отвори фајл</string>\n    <string name=\"restart\">Поново покрени</string>\n    <string name=\"video_file_size\">Величина фајла видео снимка</string>\n    <string name=\"template_exported\">Извезен(о) %1$d шаблон(а)</string>\n    <string name=\"download_task_count\">Задаци преузимања: %1$d</string>\n    <string name=\"recently_added\">Недавно додато</string>\n    <string name=\"multiselect_item_count\">%1$d видео фајл(а/ова), %2$d аудио фајл(а/ова)</string>\n    <string name=\"sponsorblock_desc\">Уклоните или означите сегменте из видео снимака помоћу SponsorBlock API</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock категорије</string>\n    <string name=\"check_for_updates\">Провера ажурирања</string>\n    <string name=\"check_for_updates_desc\">Аутоматска провера најновије верзије на GitHub-у</string>\n    <string name=\"app_up_to_date\">Тренутна верзија је ажурна</string>\n    <string name=\"update\">Ажурирај</string>\n    <string name=\"clear_temp_files\">Брисање привремених фајлова</string>\n    <string name=\"clear_temp_files_count\">Избрисан(о) је %1$d привремени(х) фајл(а/ова)</string>\n    <string name=\"multiselect_mode\">Режим вишеструког избора</string>\n    <string name=\"private_mode\">Инкогнито</string>\n    <string name=\"dynamic_color_desc\">Примените боје с позадина на тему апликације</string>\n    <string name=\"download_with_cellular\">Преузимање помоћу мобилних података</string>\n    <string name=\"download_disabled_with_cellular\">Преузимање путем мобилних података је онемогућено у складу с вашим подешавањима</string>\n    <string name=\"file_unavailable\">Овај фајл више није доступан</string>\n    <string name=\"rate_limit\">Ограничење брзине</string>\n    <string name=\"max_rate\">Максимална брзина</string>\n    <string name=\"high_contrast\">Тамна тема високог контраста</string>\n    <string name=\"invalid_input\">Неважећи унос</string>\n    <string name=\"format_settings_desc\">Формат фајла, квалитет видео снимка, титлови</string>\n    <string name=\"disable_preview\">Онемогући преглед</string>\n    <string name=\"privacy\">Приватност</string>\n    <string name=\"use_custom_command\">Користи прилагођену команду</string>\n    <string name=\"private_directory\">Приватни фолдер</string>\n    <string name=\"crop_artwork_desc\">Исеците уграђену слику у квадрат</string>\n    <string name=\"crop_artwork\">Исеци слику</string>\n    <string name=\"download_selection_desc\">Изаберите видео снимке за преузимање с плејлисте „%1$s“</string>\n    <string name=\"select_all\">Изабери све</string>\n    <string name=\"selected_item_count\">Изабрано: %1$d</string>\n    <string name=\"extract_audio\">Сачувај као аудио снимак</string>\n    <string name=\"create_thumbnail\">Сачувај сличицу</string>\n    <string name=\"settings\">Подешавања</string>\n    <string name=\"download_settings_desc\">Општа, команда формат, прилагођена команда</string>\n    <string name=\"create_thumbnail_summary\">Сачувајте сличицу видео снимка као фајл</string>\n    <string name=\"yt_dlp_up_to_date\">Коришћење најновије верзије yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Није могуће инсталирати најновију верзију yt-dlp. Проверите да ли сте повезани на интернет.</string>\n    <string name=\"download_start_msg\">Преузимање „%1$s“</string>\n    <string name=\"download_error_msg\">Није могуће преузети фајл</string>\n    <string name=\"general_settings\">Опште</string>\n    <string name=\"language_settings\">Подеси језик</string>\n    <string name=\"paste_msg\">Налепљена URL адреса</string>\n    <string name=\"task_running\">Постојећи задатак преузимања је већ покренут</string>\n    <string name=\"extract_audio_summary\">Преузмите и сачувајте аудио снимак, уместо видео снимка</string>\n    <string name=\"ytdlp_version\">Yt-dlp верзија</string>\n    <string name=\"ytdlp_update\">Кликните да бисте инсталирали најновију yt-dlp верзију</string>\n    <string name=\"readme_desc\">Проверите GitHub репозиторијум и README</string>\n    <string name=\"video\">Видео снимци</string>\n    <string name=\"not_specified\">Није наведено (подразумевано)</string>\n    <string name=\"confirm\">Потврди</string>\n    <string name=\"audio\">Аудио снимци</string>\n    <string name=\"version\">Верзија</string>\n    <string name=\"link_copied\">Линк је копиран у привремену меморију</string>\n    <string name=\"remove\">Уклони</string>\n    <string name=\"about\">О апликацији</string>\n    <string name=\"back\">Назад</string>\n    <string name=\"release_desc\">Потражите евиденције промена и нове верзије</string>\n    <string name=\"release\">Најновије издање</string>\n    <string name=\"format\">Формат</string>\n    <string name=\"checked\">Проверено</string>\n    <string name=\"credits\">Кредити</string>\n    <string name=\"status_fetching_video_info\">Прикупљање информација</string>\n    <string name=\"status_error\">Грешка</string>\n    <string name=\"template_imported\">Увезен(о) %1$d шаблон(а)</string>\n    <string name=\"copy_link\">Копирај линк</string>\n    <string name=\"copy_error_report\">Копирај извештај</string>\n    <string name=\"network\">Мрежа</string>\n    <string name=\"lowest_quality\">Најнижи квалитет</string>\n    <string name=\"video_resolution\">Резолуција видео снимка</string>\n    <string name=\"display_settings\">Тамна тема, динамичка боја, језици</string>\n    <string name=\"paste\">Налепи</string>\n    <string name=\"dark_theme\">Тамна тема</string>\n    <string name=\"follow_system\">Системски</string>\n    <string name=\"on\">Укључено</string>\n    <string name=\"convert_audio_format\">Претвори формат звучног снимка</string>\n    <string name=\"yt_dlp_docs\">Референце о употреби yt-dlp</string>\n    <string name=\"edit_template_desc\">Апликација ће додати излазну путању и URL адресу.</string>\n    <string name=\"convert_to\">Претвори у %1$s</string>\n    <string name=\"video_format_preference\">Преферирани формат видео снимка</string>\n    <string name=\"not_convert\">Непретворено</string>\n    <string name=\"video_format\">Формат видео снимка</string>\n    <string name=\"best_quality\">Најбољи квалитет</string>\n    <string name=\"export_to_clipboard\">Извези у привремену меморију</string>\n    <string name=\"import_from_clipboard\">Увези из привремене меморије</string>\n    <string name=\"preferred_format_desc\">Преферирани формат, када их је доступно више</string>\n    <string name=\"close\">Затвори</string>\n    <string name=\"close_never_show_again\">Не приказуј поново</string>\n    <string name=\"start_download\">Преузми</string>\n    <string name=\"cookies_desc\">Користите Netscape форматиране колачиће за преузимања</string>\n    <string name=\"delete_multiple_items_msg\">Заувек уклонити %1$d предмет(а) из историје преузимања\\?</string>\n    <string name=\"sponsorblock_categories_desc\">Наведите SponsorBlock категорије које ће бити уклоњене или означене у фајлу видео снимка</string>\n    <string name=\"download_with_cellular_desc\">Дозволите преузимање медија када сте повезани на мреже с ограничењем</string>\n    <string name=\"network_settings_desc\">Ограничење брзине, програм за преузимање, колачићи</string>\n    <string name=\"disable_preview_desc\">Нема приказа сличица током преузимања</string>\n    <string name=\"private_directory_desc\">Чувајте преузимања у скривеном фолдеру</string>\n    <string name=\"suggested\">Предложено</string>\n    <string name=\"format_selection_desc\">Изаберите формат за преузимање пре него што започнете преузимање</string>\n    <string name=\"video_only\">Видео снимци (без звука)</string>\n    <string name=\"format_selection\">Избор формата</string>\n    <string name=\"generate_new_cookies\">Генериши нове колачиће</string>\n    <string name=\"use_cookies\">Користи колачиће</string>\n    <string name=\"custom_command_enabled_hint\">Неке опције су недоступне када користите прилагођену команду</string>\n    <string name=\"how_does_it_work\">Како то функционише\\?</string>\n    <string name=\"telegram_channel\">Telegram канал</string>\n    <string name=\"remove_cookie_profile_desc\">Желите ли да уклоните овај унос за „%1$s“? Имајте на уму да колачићи сачувани за ову страницу неће бити обрисани.</string>\n    <string name=\"cookies_usage_msg\">Преузимање с неких сајтова захтева информације о аутентификацији налога. Кликните на „Генериши нове колачиће“, унесите URL адресу веб-сајта, а затим се пријавите са својим налогом на страници у прегледачу и апликација ће их генерисати за вас.</string>\n    <string name=\"cookies\">Колачићи</string>\n    <string name=\"matrix_space\">Matrix простор</string>\n    <string name=\"abs_hint\">Већина платформи за стримовање видео снимака одвојено испоручује аудио и видео снимке, можете изабрати и спојити формат само за аудио снимак с форматом само за видео снимак, у један видео снимак.</string>\n    <string name=\"sdcard_directory\">Фолдер SD (меморијске) картице</string>\n    <string name=\"auto_subtitle\">Аутоматски титлови</string>\n    <string name=\"auto_subtitle_desc\">Преузмите аутоматски генерисане титлове</string>\n    <string name=\"title_activity_share\">Брзо преузимање</string>\n    <string name=\"video_title_sample_text\">Пример текста наслова видео снимка</string>\n    <string name=\"video_creator_sample_text\">Пример текста креатора видео снимка</string>\n    <string name=\"download_subtitles\">Преузми титлове</string>\n    <string name=\"subtitle_language\">Језици титлова</string>\n    <string name=\"subtitle\">Титлови</string>\n    <string name=\"subtitle_desc\">Језици, уграђени титлови, аутоматски титлови</string>\n    <string name=\"copy_log\">Копирај евиденцију</string>\n    <string name=\"clear\">Избриши</string>\n    <string name=\"edit_shortcuts\">Измени пречице</string>\n    <string name=\"add\">Додај</string>\n    <string name=\"shortcuts\">Пречице</string>\n    <string name=\"edit_shortcuts_desc\">Измените прилагођене пречице које се могу користити за састављање командних шаблона.</string>\n    <string name=\"running_tasks\">Покренути задаци</string>\n    <string name=\"show_logs\">Прикажи евиденцију</string>\n    <string name=\"logs\">Евиденција</string>\n    <string name=\"subtitle_sponsorblock\">Приликом уклањања SponsorBlock сегмената, титлови могу бити несинхронизовани.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Да би се уградили обезбеђени титлови, видео снимци ће бити пребачени у mkv контејнер. Можете користити VLC Media Player или друге компатибилне апликације за гледање видео снимака с обезбеђеним титловима.</string>\n    <string name=\"filesize_gb\">%.2f ГБ</string>\n    <string name=\"filesize_mb\">%.2f МБ</string>\n    <string name=\"share\">Дели</string>\n    <string name=\"stable_channel\">Стабилан</string>\n    <string name=\"pre_release_channel\">Бета</string>\n    <string name=\"auto_update\">Аутоматско ажурирање</string>\n    <string name=\"enable_auto_update\">Омогући аутоматско ажурирање</string>\n    <string name=\"update_channel_desc\">Инсталирајте бета издања апликације да бисте прегледали нове функције и промене.\n\\n\n\\nБиће неких нестабилности у овим верзијама, тако да не оклевајте да нам дате повратне информације ако наиђете на било какве проблеме, како бисте нам помогли да побољшамо апликацију у будућности.</string>\n    <string name=\"update_channel\">Канал ажурирања</string>\n    <string name=\"apply\">Примени</string>\n    <string name=\"discard\">Одбаци</string>\n    <string name=\"clip_video\">Исеци видео снимак</string>\n    <string name=\"clip_end\">Крај</string>\n    <string name=\"clip_start\">Почетак</string>\n    <string name=\"audio_format_preference\">Преферирани формат аудио снимка</string>\n    <string name=\"audio_quality\">Квалитет аудио снимка</string>\n    <string name=\"audio_quality_desc\">Ограничите брзину преноса аудио снимка, када је доступно више квалитета</string>\n    <string name=\"unlimited\">Неограничено</string>\n    <string name=\"format_sorting\">Сортирање формата</string>\n    <string name=\"second\">секунда</string>\n    <string name=\"format_sorting_desc\">Сортирање формата с опцијом -S од yt-dlp</string>\n    <string name=\"minute\">минут</string>\n    <string name=\"lowest_bitrate\">Најнижа брзина преноса</string>\n    <string name=\"title\">Наслов</string>\n    <string name=\"import_from_preferences\">Увези</string>\n    <string name=\"clear_all_cookies_desc\">Заувек избришите све колачиће сачуване у апликацији\\?</string>\n    <string name=\"rename\">Преименуј</string>\n    <string name=\"clear_all_cookies\">Избриши све колачиће</string>\n    <string name=\"temporary_directory_desc\">Чувајте привремене фајлове у унутрашњем фолдеру</string>\n    <string name=\"feedback\">Повратне информације</string>\n    <string name=\"sponsors\">Спонзори</string>\n    <string name=\"sponsor_msg\">Seal ће увек бити бесплатан и отвореног кода за све. Ако вам се свиђа, размислите о томе да ме спонзоришете на GitHub-у!</string>\n    <string name=\"sponsor\">Спонзориши</string>\n    <string name=\"sponsor_desc\">Подржите ову апликацију спонзорисањем на GitHub-у</string>\n    <string name=\"audio_format\">Формат аудио снимка</string>\n    <string name=\"beta_features\">Бета</string>\n    <string name=\"clip_video_desc\">Направите исечке видео снимка на страници за избор формата</string>\n    <string name=\"no_downloaded_media\">Нема преузетих медија</string>\n    <string name=\"enable_experimental_feature\">Омогућити експерименталну функцију\\?</string>\n    <string name=\"clip_video_dialog_msg\">Преузимања која користе ову функцију биће послата на FFmpeg да преузму изабране делове видео снимка, ова функција је и даље експериментална и сечење неће бити потпуно тачно, не подржавају сви формати ову функцију и можда ћете имати спорије брзине преузимања.</string>\n    <string name=\"switch_to_github_builds\">прелазак на GitHub издања</string>\n    <string name=\"auto_update_disabled_msg\">Аутоматско ажурирање није доступно за %1$s издања. Ако немате инсталирано %1$s на свом уређају или бисте желели да прегледате предстојеће нове функције у Seal-у, размислите о %2$s.</string>\n    <string name=\"got_it\">Разумем</string>\n    <string name=\"okay\">У реду</string>\n    <string name=\"feature_unavailable\">Функција није доступна</string>\n    <string name=\"no_custom_command_tasks\">Нема прилагођених командних задатака</string>\n    <string name=\"msg_from_developer\">Порука од програмера</string>\n    <string name=\"sponsor_msg2\">Хвала много!</string>\n    <string name=\"download_video_desc\">Преузмите видео снимке с URL адресе</string>\n    <string name=\"split_video\">Подели видео снимак</string>\n    <string name=\"split_video_msg\">Видео снимак ће бити подељен на %1$d поглавља</string>\n    <string name=\"copy_and_exit\">Копирај и напусти</string>\n    <string name=\"convert_subtitle_desc\">Конвертујте титлове у други формат</string>\n    <string name=\"convert_subtitle\">Конвертуј титлове</string>\n    <string name=\"unknown_error_title\">Упс! Нешто није у реду</string>\n    <string name=\"expand\">Прошири</string>\n    <string name=\"new_task\">Нови задатак преузимања</string>\n    <string name=\"edit_template\">Измени „%1$s“</string>\n    <string name=\"start\">Започни</string>\n    <string name=\"legacy\">Застарело</string>\n    <string name=\"enable_notifications\">Омогућити обавештења\\?</string>\n    <string name=\"disable\">Онемогући</string>\n    <string name=\"set_directory_desc\">Додирните да бисте подесили фолдер</string>\n    <string name=\"custom_command_directory\">Фолдер прилагођене команде</string>\n    <string name=\"folder_picker\">Бирач фолдера</string>\n    <string name=\"custom_command_directory_desc\">Одредите излазни фолдер, када користите прилагођене команде</string>\n    <string name=\"prefer_quality_desc\">Преферирање AV1, VP9 или H.265 формата за гледање у компатибилним апликацијама</string>\n    <string name=\"ytdlp_update_action\">Ажурирај yt-dlp</string>\n    <string name=\"proxy\">Прокси</string>\n    <string name=\"proxy_desc\">Користите прокси за интернет везе</string>\n    <string name=\"quality\">Квалитет</string>\n    <string name=\"enable_notifications_desc\">Апликацији је потребна ваша дозвола да би постављала обавештења о статусу и напретку преузимања.</string>\n    <string name=\"disabled\">Онемогућено</string>\n    <string name=\"prefer_compatibility_desc\">Преферирање MP4(H.264) формата за дељење с другим апликацијама</string>\n    <string name=\"download_type\">Тип преузимања</string>\n    <string name=\"format_preference\">Преференција формата</string>\n    <string name=\"auto\">Аутоматски</string>\n    <string name=\"custom\">Прилагођен</string>\n    <string name=\"commands\">Команде</string>\n    <string name=\"learn_more\">Сазнај више</string>\n    <string name=\"unknown\">Непознато</string>\n    <string name=\"refresh_cookies_desc\">Додирните да отворите веб-страницу за генерисање нових колачића:</string>\n    <string name=\"remove_multiple_templates_msg\">Заувек уклонити %1$s из командних шаблона\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d предмет</item>\n        <item quantity=\"few\">%d предмета</item>\n        <item quantity=\"other\">%d предмета</item>\n    </plurals>\n    <string name=\"ua_header\">Заглавље User-Agent</string>\n    <string name=\"export_to_file\">Извези у фајл</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp је моћна алатка командне линије за преузимање видео снимака. Seal олакшава коришћење yt-dlp-а тако што пружа интуитивни GUI, унапред подешене вредности за уобичајене команде и друге додатне функције.\n\\n\n\\nЗа напредну употребу yt-dlp-а, Seal вам омогућава да направите, сачувате и извршите прилагођене командне шаблоне директно, баш као у терминалу.\n\\n\n\\nКада користите прилагођене команде, већина GUI опција и функција би била онемогућена.</string>\n    <string name=\"presets\">Унапред подешено</string>\n    <string name=\"output_template\">Излазни шаблон</string>\n    <string name=\"output_template_desc\">Одредите шаблон за називе излазних фајлова</string>\n    <string name=\"clear_download_archive\">Очистити архиву преузимања\\?</string>\n    <string name=\"clear_download_archive_desc\">Заувек уклонити %1$s из архивског фајла\\?</string>\n    <string name=\"download_archive_desc\">Сачувајте ID-ове преузетих видео снимака у архиву да бисте избегли дуплирана преузимања</string>\n    <string name=\"download_archive\">Архива преузимања</string>\n    <string name=\"embed_metadata\">Угради метаподатке</string>\n    <string name=\"embed_metadata_desc\">Уградите метаподатке и сличицу видео снимка у фајл аудио снимка</string>\n    <string name=\"required\">Обавезно</string>\n    <string name=\"show_all_items\">Прикажи све предмете: %1$d</string>\n    <string name=\"save\">Сачувај</string>\n    <string name=\"use_format_sorting\">Користи сортирање формата</string>\n    <string name=\"edit_file\">Измените фајл</string>\n    <string name=\"restrict_filenames_desc\">Ограничите називе фајлова на одређене знакове да бисте осигурали компатибилност</string>\n    <string name=\"restrict_filenames\">Ограничи називе фајлова</string>\n    <string name=\"website\">Веб-сајт</string>\n    <string name=\"playlist_title\">Наслов плејлисте</string>\n    <string name=\"subdirectory_hint\">Ваша преузимања ће бити сачувана као:</string>\n    <string name=\"force_ipv4\">Присили IPv4</string>\n    <string name=\"system_settings\">Системска подешавања</string>\n    <string name=\"force_ipv4_desc\">Учините све везе преко IPv4</string>\n    <string name=\"keep_subtitle_files\">Чувај фајлове титлова</string>\n    <string name=\"allow_once\">Дозволи једном</string>\n    <string name=\"allow_always\">Дозволи увек</string>\n    <string name=\"dont_allow\">Не дозволи</string>\n    <string name=\"download_with_cellular_request\">Дозволити преузимање путем мобилних података?</string>\n    <string name=\"merge_audiostream\">Споји више аудио стримова</string>\n    <string name=\"merge_audiostream_desc\">Дозволите да се више аудио стримова споји у један фајл</string>\n    <string name=\"search_in_downloads\">Претрага у преузимањима</string>\n    <string name=\"search\">Претрага</string>\n    <string name=\"auto_translated_subtitles\">Аутоматски преведени титлови</string>\n    <string name=\"auto_translated_subtitles_msg\">Аутоматски преведени титлови за све језике биће доступни у преузимањима. Ови титлови могу бити нетачни и тешки за разумевање.</string>\n    <string name=\"remember_for_next_download\">Запамти за следеће преузимање</string>\n    <string name=\"look_and_feel\"><![CDATA[Изглед и осећај]]></string>\n    <string name=\"use_previous_selection\">Користи прецизан избор</string>\n    <string name=\"none\">Ниједно</string>\n    <string name=\"subtitle_language_desc\">Језик титлова за преузимање у аутоматском избору формата, одвојен запетама.</string>\n    <string name=\"reset\">Ресетуј</string>\n    <string name=\"no_thanks\">Не, хвала</string>\n    <string name=\"search_in_subtitles\">Претрага у титловима</string>\n    <string name=\"update_language_msg\">Следећи језици ће бити додати вашим преференцама за будућа преузимања:</string>\n    <string name=\"update_subtitle_languages\">Ажурирати језике титлова?</string>\n    <string name=\"export_backup\">Извоз</string>\n    <string name=\"import_backup\">Увоз</string>\n    <string name=\"import_download_history\">Увести историју преузимања?</string>\n    <string name=\"export_download_history\">Извести историју преузимања?</string>\n    <string name=\"interface_and_interaction\"><![CDATA[Интерфејс и интеракција]]></string>\n    <string name=\"full_backup\">Потпуна резервна копија</string>\n    <string name=\"backup_type\">Тип резервне копије</string>\n    <string name=\"export_to\">Извоз у</string>\n    <string name=\"file\">Фајл</string>\n    <string name=\"clipboard\">Привремену меморију</string>\n    <string name=\"import_from\">Увоз из</string>\n    <string name=\"import_download_history_msg\">Преузети фајлови неће бити увезени. Мораћете да их поново преузмете ручно</string>\n    <string name=\"export_download_history_msg\">Извоз %1$s из историје преузимања. За преузете фајлове и подешавања неће бити направљена резервна копија.</string>\n    <string name=\"download_history\">Историја преузимања</string>\n    <string name=\"download_history_imported\">Увезен %1$s у историју преузимања</string>\n    <string name=\"redownload\">Поново преузми</string>\n    <string name=\"download_archive_error\">Видео снимак је преузет. Ако ово није очекивано понашање, проверите своју архиву преузимања.</string>\n    <string name=\"remux_container_mkv_desc\">Пребаци видео снимке у MKV контејнер ради боље компатибилности</string>\n    <string name=\"remux_container_mkv\">Пребаци контејнер видео снимка</string>\n    <string name=\"cookies_in_database\">Укупно %1$d колачића са %2$d веб-сајтова</string>\n    <string name=\"every_day\">Сваког дана</string>\n    <string name=\"every_week\">Сваке седмице</string>\n    <string name=\"every_month\">Сваког месеца</string>\n    <string name=\"all_languages\">Сви језици</string>\n    <string name=\"playlist\">Плејлиста</string>\n    <string name=\"preset\">Унапред подешено</string>\n    <string name=\"prefer_placeholder\">Преферирај %1$s</string>\n    <string name=\"edit_preset\">Измени унапред подешено</string>\n    <string name=\"preset_format_selection_desc\">Преузмите аутоматски користећи своје преференце формата</string>\n    <string name=\"task_added\">Задатак је додат у редослед</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d видео снимак</item>\n        <item quantity=\"few\">%d видео снимка</item>\n        <item quantity=\"other\">%d видео снимака</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d аудио снимак</item>\n        <item quantity=\"few\">%d аудио снимка</item>\n        <item quantity=\"other\">%d аудио снимака</item>\n    </plurals>\n    <string name=\"custom_format_selection_desc\">Бирајте између формата, титлова и додатно прилагодите</string>\n    <string name=\"proceed\">Настави</string>\n    <string name=\"best_quality_desc\">Преузмите најбољи доступни формат</string>\n    <string name=\"you_ll_find_your_downloads_here\">Овде ћете пронаћи своја преузимања</string>\n    <string name=\"download_hint\">Додирните дугме за преузимање или поделите линк видео снимка до ове апликације да бисте започели преузимање</string>\n    <string name=\"status_downloaded\">Преузето</string>\n    <string name=\"all\">Све</string>\n    <string name=\"select_multiple_link\">Изаберите неки од %1$d линкова</string>\n    <string name=\"download_queue\">Редослед преузимања</string>\n    <string name=\"show_navigation_drawer\">Прикажи фиоку за навигацију</string>\n    <string name=\"delete\">Избриши</string>\n    <string name=\"resume\">Настави</string>\n    <string name=\"media_info\">Информације о медијима</string>\n    <string name=\"issue_tracker\">Пратилац проблема</string>\n    <string name=\"trouble_shooting\">Решавање проблема</string>\n    <string name=\"issue_tracker_hint\">Наишли сте на грешку? Пре него што пријавите нови проблем, претражите наш алат за праћење проблема. Многи уобичајени проблеми су тамо већ обрађени и документовани.</string>\n    <string name=\"trouble_shooting_desc\">Поправите уобичајене грешке и проверите познате проблеме</string>\n    <string name=\"add_to\">Додај у %1$s</string>\n    <string name=\"add_new_url\">Додај нови линк</string>\n    <string name=\"saved_urls\">Сачувани линкови</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-sv/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Videomapp</string>\n    <string name=\"extract_audio\">Spara som ljud</string>\n    <string name=\"settings\">Inställningar</string>\n    <string name=\"download_settings_desc\">Allmänt, format, anpassat kommando</string>\n    <string name=\"download\">Ladda ner</string>\n    <string name=\"url_empty\">Länken får inte vara tomt</string>\n    <string name=\"extract_audio_summary\">Ladda ner och spara ljud, istället för video</string>\n    <string name=\"yt_dlp_up_to_date\">Använder den senaste versionen av yt-dlp</string>\n    <string name=\"fetching_info\">Hämtar in videoinformation…</string>\n    <string name=\"permission_denied\">Tillstånd nekad</string>\n    <string name=\"download_success_msg\">Nerladdning klar</string>\n    <string name=\"download_error_msg\">Kunde inte ladda ner fil</string>\n    <string name=\"download_start_msg\">Ladda ner \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Kunde inte hämta in videoinformation</string>\n    <string name=\"general_settings\">Allmänt</string>\n    <string name=\"language\">Gränssnittsspråk</string>\n    <string name=\"language_settings\">Ange gränssnittets språk</string>\n    <string name=\"task_running\">En befintlig nedladdningsuppgift är redan igång</string>\n    <string name=\"paste_msg\">Klistra in URL</string>\n    <string name=\"paste_fail_msg\">Kunde inte matcha URL:en i Urklipp</string>\n    <string name=\"ytdlp_version\">Yt-dlp version</string>\n    <string name=\"delete_info\">Ta bort\\?</string>\n    <string name=\"delete_info_msg\">Ta bort \\\"%1$s\\\" från din nerladdningshistorik för gott\\?</string>\n    <string name=\"confirm\">Bekräfta</string>\n    <string name=\"dismiss\">Avbryt</string>\n    <string name=\"downloads_history\">Nerladdningar</string>\n    <string name=\"audio\">Ljud</string>\n    <string name=\"link_copied\">Länk kopierad till urklipp</string>\n    <string name=\"open_url\">Öppna länken</string>\n    <string name=\"remove\">Ta bort</string>\n    <string name=\"delete_file\">Radera fil</string>\n    <string name=\"about_page\">Version, feedback, automatisk uppdatering</string>\n    <string name=\"version\">Version</string>\n    <string name=\"release_desc\">Leta efter ändringsloggar och nya versioner</string>\n    <string name=\"release\">Senaste utgåvan</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Kontrollerat</string>\n    <string name=\"credits\">Krediter</string>\n    <string name=\"credits_desc\">Krediter och fri programvara</string>\n    <string name=\"custom_command\">Anpassat kommando</string>\n    <string name=\"custom_command_template\">Mall för kommando</string>\n    <string name=\"edit\">Redigera</string>\n    <string name=\"start_execute\">Börja utföra kommandot</string>\n    <string name=\"advanced_settings\">Avancerad</string>\n    <string name=\"print_details\">Detaljerad utgång</string>\n    <string name=\"print_details_desc\">Skriv ut detaljerade meddelanden vid nedladdning</string>\n    <string name=\"display\">Skärm</string>\n    <string name=\"display_settings\">Mörkt tema, dynamisk färg, språk</string>\n    <string name=\"dark_theme\">Mörkt tema</string>\n    <string name=\"follow_system\">Systemet</string>\n    <string name=\"on\">På</string>\n    <string name=\"off\">Av</string>\n    <string name=\"cancel\">Avbryt</string>\n    <string name=\"settings_before_download_desc\">Konfigurera inställningar före nedladdning</string>\n    <string name=\"settings_before_download_text\">Justera denna nedladdning</string>\n    <string name=\"error_copied\">Felrapport kopierad till urklipp</string>\n    <string name=\"thumbnail\">Miniatyrbild</string>\n    <string name=\"paste\">Klistra in</string>\n    <string name=\"yt_dlp_docs\">Användningsreferenser för Yt-dlp</string>\n    <string name=\"convert_audio_format\">Konvertera ljudformat</string>\n    <string name=\"not_convert\">Okonverterad</string>\n    <string name=\"convert_to\">Konvertera till %1$s</string>\n    <string name=\"format\">Format</string>\n    <string name=\"video_quality\">Videokvalitet</string>\n    <string name=\"best_quality\">Bästa kvalitet (standard)</string>\n    <string name=\"video_quality_desc\">Begränsa videokvaliteten när flera är närvarande</string>\n    <string name=\"not_specified\">Ej specificerad (standard)</string>\n    <string name=\"video_format_preference\">Föredraget videoformat</string>\n    <string name=\"preferred_format_desc\">Valt format när flera tillhandahålls</string>\n    <string name=\"video_format\">Videoformat</string>\n    <string name=\"convert_audio\">Konvertera</string>\n    <string name=\"start_download\">Ladda ner</string>\n    <string name=\"close\">Stäng</string>\n    <string name=\"close_never_show_again\">Visa inte igen</string>\n    <string name=\"user_guide\">Användarguide</string>\n    <string name=\"open_settings\">Öppna inställningar</string>\n    <string name=\"download_desc\">Klicka sedan på \\\"Ladda ner\\\" efter att ha justerat inställningarna.</string>\n    <string name=\"check_download_settings_desc\">Ta en titt på nedladdningsinställningarna och se till att du har den senaste versionen av yt-dlp innan du använder den.</string>\n    <string name=\"download_playlist\">Ladda ner spellista</string>\n    <string name=\"download_playlist_desc\">Ladda ner flera videor från en spellista</string>\n    <string name=\"defaults\">Standard</string>\n    <string name=\"channel_name\">Ladda ner</string>\n    <string name=\"channel_description\">Meddela om nedladdade filer och framsteg</string>\n    <string name=\"video_url\">Videolänk</string>\n    <string name=\"download_finish_notification\">Nedladdningen är klar. Tryck för att öppna.</string>\n    <string name=\"concurrent_download\">Multitrådad nedladdning</string>\n    <string name=\"concurrent_download_desc\">Ladda ner fler delar av M3U8/MPD-videor parallellt</string>\n    <string name=\"concurrent_download_num\">%d trådar skulle användas för att ladda ner DASH/HLS videon samtidigt.</string>\n    <string name=\"options\">Alternativ</string>\n    <string name=\"share_fail_msg\">Kan inte matcha URL från delat innehåll</string>\n    <string name=\"share_success_msg\">Läser videolänk från delat innehåll…</string>\n    <string name=\"show_more_actions\">Visa fler åtgärder</string>\n    <string name=\"download_notification_desc\">Meddela om nedladdade filer och framsteg</string>\n    <string name=\"fetching_playlist_info\">Hämtar information om spellistan…</string>\n    <string name=\"from\">Börja</string>\n    <string name=\"invalid_index_range\">Ogiltigt indexintervall</string>\n    <string name=\"create_thumbnail\">Spara miniatyrbild</string>\n    <string name=\"create_thumbnail_summary\">Spara video miniatyrbild som fil</string>\n    <string name=\"yt_dlp_update_fail\">Kunde inte installera den senaste yt-dlp version. Kontrollera att du är ansluten till Internet.</string>\n    <string name=\"about\">Om</string>\n    <string name=\"ytdlp_update\">Klicka här för att installera den senaste yt-dlp versionen</string>\n    <string name=\"back\">Tillbaka</string>\n    <string name=\"readme_desc\">Kontrollera GitHub-arkivet och README</string>\n    <string name=\"custom_command_desc\">Kör kommandot yt-dlp med anpassad mall</string>\n    <string name=\"settings_before_download\">Konfigurera före nedladdning</string>\n    <string name=\"edit_template_desc\">Utmatningssökväg och URL kommer att läggas till av appen.</string>\n    <string name=\"convert_audio_format_desc\">Omkodning av ljudfiler leder till försämrad ljudkvalitet och ökad filstorlek.</string>\n    <string name=\"paste_desc\">Klicka på \\\"Klistra in\\\" för att hämta videolänk från urklipp.</string>\n    <string name=\"download_history_desc\">Kontrollera och hantera nedladdningar i appen, inklusive videor och ljudfiler.</string>\n    <string name=\"execute_command_notification\">Kör anpassade kommandon…</string>\n    <string name=\"battery_settings_desc\">Ställ in batterianvändningen för denna app på \\\"Obegränsad\\\" i systeminställningarna för att ladda ner i bakgrunden.</string>\n    <string name=\"additional_settings\">Ytterligare inställningar</string>\n    <string name=\"download_notification\">Nedladdningsanmälan</string>\n    <string name=\"download_range_selection\">Urval av spellista</string>\n    <string name=\"playlist_indicator_text\">Hämtar spellista (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Ljudmapp</string>\n    <string name=\"to\">Sluta</string>\n    <string name=\"download_range_desc\">Ange hur många videor som ska hämtas från spellistan \\\"%3$s\\\" (från %1$d till %2$d).</string>\n    <string name=\"download_directory\">Katalog för nedladdningar</string>\n    <string name=\"download_directory_desc\">Välj plats för nedladdade videor och ljudfiler</string>\n    <string name=\"subdirectory\">Spara till underkatalog</string>\n    <string name=\"subdirectory_desc\">Spara filer i kataloger namngivna efter dess respektive webbplatser</string>\n    <string name=\"permission_issue\">Problem med åtkomst till lagringsutrymme</string>\n    <string name=\"permission_issue_desc\">Kataloger annat än Nedladdade filer/ och Dokument/ stödjs inte</string>\n    <string name=\"battery_configuration\">Batterikonfiguration</string>\n    <string name=\"battery_configuration_desc\">Avaktivera appens batterioptimering för att aktivera bakgrundsnedladdning</string>\n    <string name=\"ytdlp_update_action\">Uppdatera yt-dlp</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ta/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"url_empty\">லிங்க் காலியாக இருக்கக்கூடாது</string>\n    <string name=\"extract_audio_summary\">வீடியோவிற்குப் பதிலாக ஆடியோவைப் பதிவிறக்கிச் சேமிக்கவும்</string>\n    <string name=\"task_running\">ஏற்கனவே ஒரு பதிவிறக்கம் செயல்பாட்டில் உள்ளது</string>\n    <string name=\"delete_info_msg\">உங்கள் பதிவிறக்க வரலாற்றிலிருந்து \\\"%1$s\\\" ஐ அகற்றவா\\?</string>\n    <string name=\"paste_fail_msg\">கிளிப்போர்டில் உள்ள URLஐப் பொருத்த முடியவில்லை</string>\n    <string name=\"yt_dlp_update_fail\">சமீபத்திய yt-dlp பதிப்பை நிறுவ முடியவில்லை. நீங்கள் இணையத்துடன் இணைக்கப்பட்டுள்ளீர்களா என்பதை உறுதிப்படுத்தவும்.</string>\n    <string name=\"video_directory\">வீடியோ கோப்பு</string>\n    <string name=\"extract_audio\">ஆடியோவாக சேமிக்கவும்</string>\n    <string name=\"create_thumbnail\">சிறுபடத்தை சேமிக்கவும்</string>\n    <string name=\"settings\">அமைப்புகள்</string>\n    <string name=\"download_settings_desc\">பொது, வடிவம், தனிப்பயன் கட்டளை</string>\n    <string name=\"download\">பதிவிறக்கு</string>\n    <string name=\"create_thumbnail_summary\">வீடியோ சிறுபடத்தை ஃபைலாக சேமிக்கவும்</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp இன் சமீபத்திய பதிப்பைப் பயன்படுத்துகிறது</string>\n    <string name=\"fetching_info\">வீடியோவின் தகவலைப் பெறுகிறது…</string>\n    <string name=\"permission_denied\">அனுமதி மறுக்கப்பட்டது</string>\n    <string name=\"download_success_msg\">பதிவிறக்கம் முடிந்தது</string>\n    <string name=\"download_error_msg\">ஃபைலை பதிவிறக்க முடியவில்லை</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" ஐ பதிவிறக்கு</string>\n    <string name=\"fetch_info_error_msg\">வீடியோ தகவலைப் பெற முடியவில்லை</string>\n    <string name=\"general_settings\">பொது</string>\n    <string name=\"language\">ஆப் மொழி</string>\n    <string name=\"language_settings\">ஆப் மொழியை அமைக்கவும்</string>\n    <string name=\"paste_msg\">கிளிப்போர்டிலிருந்து URL ஐ ஒட்டவும்</string>\n    <string name=\"ytdlp_version\">Yt-dlpன் பதிப்பு</string>\n    <string name=\"ytdlp_update\">சமீபத்திய yt-dlp பதிப்பை நிறுவ கிளிக் செய்யவும்</string>\n    <string name=\"delete_info\">நீக்கவா\\?</string>\n    <string name=\"confirm\">உறுதிப்படுத்தவும்</string>\n    <string name=\"dismiss\">ரத்து செய்</string>\n    <string name=\"downloads_history\">பதிவிறக்கங்கள்</string>\n    <string name=\"audio\">ஆடியோ</string>\n    <string name=\"link_copied\">லிங்க் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது</string>\n    <string name=\"open_url\">லிங்க்கை திற</string>\n    <string name=\"remove\">நீக்கு</string>\n    <string name=\"delete_file\">கோப்புகளை அழி</string>\n    <string name=\"about\">ஆப்பை பற்றி</string>\n    <string name=\"version\">பதிப்பு</string>\n    <string name=\"video\">காணொளி</string>\n    <string name=\"display\">காட்சி</string>\n    <string name=\"follow_system\">அமைப்பமுறை</string>\n    <string name=\"cancel\">ரத்து செய்</string>\n    <string name=\"settings_before_download\">பதிவிறக்குவதற்கு முன் உள்ளமைக்கவும்</string>\n    <string name=\"about_page\">பதிப்பு, வெளியீடுகள், தானாக மேம்படுத்தல்</string>\n    <string name=\"release_desc\">மாற்ற பதிவுகள் மற்றும் புதிய பதிப்புகளைப் பார்க்கவும்</string>\n    <string name=\"on\">இயக்கவும்</string>\n    <string name=\"settings_before_download_desc\">பதிவிறக்குவதற்கு முன் விருப்பங்களை உள்ளமைக்கவும்</string>\n    <string name=\"settings_before_download_text\">இந்த பதிவிறக்கத்தை சரிசெய்யவும்</string>\n    <string name=\"thumbnail\">சிறுபடம்</string>\n    <string name=\"paste\">ஒட்டவும்</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp பயன்பாட்டுக் குறிப்புகள்</string>\n    <string name=\"edit_template_desc\">அவுட்புட் பாதை மற்றும் URL ஆப்ஸால் சேர்க்கப்படும்.</string>\n    <string name=\"convert_audio_format\">ஆடியோ வடிவத்தை மாற்றவும்</string>\n    <string name=\"not_convert\">மாற்றப்படாதது</string>\n    <string name=\"convert_to\">%1$s ஆக மாற்றவும்</string>\n    <string name=\"format\">வடிவம்</string>\n    <string name=\"video_quality\">காணொளி தரம்</string>\n    <string name=\"video_format_preference\">விருப்பமான காணொளி வடிவம்</string>\n    <string name=\"preferred_format_desc\">பல வழங்கப்படும் போது விருப்பமான வடிவம்</string>\n    <string name=\"best_quality\">சிறந்த தரம்</string>\n    <string name=\"video_quality_desc\">பல இருக்கும் போது வீடியோ தரத்தை வரம்பிடவும்</string>\n    <string name=\"not_specified\">குறிப்பிடப்படவில்லை (இயல்புநிலை)</string>\n    <string name=\"close\">மூடு</string>\n    <string name=\"open_settings\">அமைப்புகளைத் திறக்கவும்</string>\n    <string name=\"video_format\">காணொளி வடிவம்</string>\n    <string name=\"convert_audio\">மாற்றவும்</string>\n    <string name=\"user_guide\">பயனர் வழிகாட்டி</string>\n    <string name=\"start_download\">பதிவிறக்கம்</string>\n    <string name=\"close_never_show_again\">மீண்டும் காட்ட வேண்டாம்</string>\n    <string name=\"paste_desc\">உங்கள் கிளிப்போர்டிலிருந்து வீடியோ இணைப்பைப் பெற \\\"Paste\\\" என்பதைக் கிளிக் செய்யவும்.</string>\n    <string name=\"back\">பின்னோக்கி</string>\n    <string name=\"print_details_desc\">பதிவிறக்கும் போது விரிவான செய்திகளை அச்சிடவும்</string>\n    <string name=\"print_details\">விரிவான வெளியீடு</string>\n    <string name=\"off\">அணைக்க</string>\n    <string name=\"credits\">புகழ்</string>\n    <string name=\"display_settings\">கருப்பு தீம், மாறும் நிறம், மொழிகள்</string>\n    <string name=\"dark_theme\">கருப்பு தீம்</string>\n    <string name=\"error_copied\">பிழை அறிக்கை கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது</string>\n    <string name=\"release\">சமீபத்திய வெளியீடு</string>\n    <string name=\"readme_desc\">\"GitHub repository ஐயும் README ஐயும்  பாறுங்கள்\"</string>\n    <string name=\"custom_command_desc\">தனிப்பயன் டெம்ப்ளேட்டுடன் yt-dlp கட்டளையை இயக்கவும்</string>\n    <string name=\"custom_command\">தனிப்பயன் கட்டளை</string>\n    <string name=\"checked\">சரிபார்க்கப்பட்டது</string>\n    <string name=\"credits_desc\">கடன்கள் மற்றும் இலவச மென்பொருள்</string>\n    <string name=\"convert_audio_format_desc\">மின்-குறியாக்க ஆடியோ கோப்புகள் ஆடியோ தரத்தில் இழப்பு மற்றும் கோப்பு அளவு அதிகரிக்கும்.</string>\n    <string name=\"download_desc\">அதன் அமைப்புகளை சரிசெய்த பிறகு \\\"பதிவிறக்கு\\\" என்பதைக் கிளிக் செய்யவும்.</string>\n    <string name=\"download_history_desc\">வீடியோக்கள் மற்றும் ஆடியோ கோப்புகள் உட்பட ஆப்ஸ் பதிவிறக்கங்களைச் சரிபார்த்து நிர்வகிக்கவும்.</string>\n    <string name=\"channel_description\">பதிவிறக்கம் செய்யப்பட்ட கோப்புகள் மற்றும் முன்னேற்றம் குறித்து தெரிவிக்கவும்</string>\n    <string name=\"video_url\">வீடியோ இணைப்பு</string>\n    <string name=\"execute_command_notification\">தனிப்பயன் கட்டளைகளை இயக்குகிறது…</string>\n    <string name=\"ytdlp_update_action\">yt-dlp மேம்படுத்தல்</string>\n    <string name=\"custom_command_template\">கட்டளை விளக்கம்</string>\n    <string name=\"download_playlist_desc\">பிளேலிஸ்ட்டில் இருந்து பல வீடியோக்களைப் பதிவிறக்கவும்</string>\n    <string name=\"check_download_settings_desc\">பதிவிறக்க அமைப்புகளைப் பார்த்து, அதைப் பயன்படுத்துவதற்கு முன், yt-dlp இன் சமீபத்திய பதிப்பு உங்களிடம் உள்ளதா என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்.</string>\n    <string name=\"defaults\">இயல்புநிலை</string>\n    <string name=\"channel_name\">பதிவிறக்கம்</string>\n    <string name=\"download_playlist\">பிளேலிஸ்ட்டைப் பதிவிறக்கவும்</string>\n    <string name=\"advanced_settings\">மேம்பட்டது</string>\n    <string name=\"download_finish_notification\">பதிவிறக்கம் முடிந்தது. திறக்க தட்டவும்.</string>\n    <string name=\"edit\">திருத்த</string>\n    <string name=\"start_execute\">கட்டளையை இயக்கத் தொடங்குங்கள்</string>\n    <string name=\"from\">ஆரம்பி/ஆரம்பம்</string>\n    <string name=\"to\">முடிவு</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-th/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio_summary\">ดาวน์โหลดและบันทึกเป็นไฟล์เสียงแทนการบันทึกเป็นไฟล์วิดีโอ</string>\n    <string name=\"video_directory\">โฟลเดอร์ของวิดีโอ</string>\n    <string name=\"create_thumbnail\">บันทึกภาพขนาดย่อ</string>\n    <string name=\"settings\">การตั้งค่า</string>\n    <string name=\"download\">ดาวน์โหลด</string>\n    <string name=\"url_empty\">ลิงก์ไม่สามารถปล่อยว่างไว้ได้</string>\n    <string name=\"create_thumbnail_summary\">บันทึกภาพขนาดย่อของวิดีโอเป็นไฟล์แยก</string>\n    <string name=\"yt_dlp_up_to_date\">กำลังใช้ yt-dlp เวอร์ชั่นล่าสุด</string>\n    <string name=\"extract_audio\">บันทึกเป็นไฟล์เสียง</string>\n    <string name=\"download_settings_desc\">ทั่วไป รูปแบบ คำสั่งที่กำหนดเอง</string>\n    <string name=\"unlimited\">ไม่จำกัด</string>\n    <string name=\"lowest_bitrate\">บิทเรตต่ำที่สุด</string>\n    <string name=\"audio_quality\">คุณภาพเสียง</string>\n    <string name=\"import_from_preferences\">นำเข้า</string>\n    <string name=\"title\">ไตเติ้ล</string>\n    <string name=\"second\">วินาที</string>\n    <string name=\"minute\">นาที</string>\n    <string name=\"clear_all_cookies\">ล้างคุกกี้ทั้งหมด</string>\n    <string name=\"no_downloaded_media\">ไม่มีสื่อที่ดาวน์โหลด</string>\n    <string name=\"enable_experimental_feature\">เปิดใช้งานฟีเจอร์ทดลอง\\?</string>\n    <string name=\"beta_features\">เบต้า</string>\n    <string name=\"audio_format\">รูปแบบเสียง</string>\n    <string name=\"share\">แชร์</string>\n    <string name=\"stable_channel\">เสถียร</string>\n    <string name=\"update_channel\">อัปเดทช่อง</string>\n    <string name=\"auto_update\">อัปเดทอัตโนมัติ</string>\n    <string name=\"enable_auto_update\">เปิดใช้งานการอัปเดทอัตโนมัติ</string>\n    <string name=\"sponsor_msg2\">ขอบคุณมาก!</string>\n    <string name=\"msg_from_developer\">ข้อความจากผู้พัฒนา</string>\n    <string name=\"okay\">ตกลง</string>\n    <string name=\"apply\">นำไปใช้</string>\n    <string name=\"discard\">ละทิ้ง</string>\n    <string name=\"pre_release_channel\">ดูตัวอย่าง</string>\n    <string name=\"clip_start\">เริ่ม</string>\n    <string name=\"clip_end\">จบ</string>\n    <string name=\"clip_video\">คลิปวีดีโอ</string>\n    <string name=\"feature_unavailable\">ฟีเจอร์นี้ไม่สามารถใช้งานได้</string>\n    <string name=\"sponsor_desc\">สนับสนุนแอปนี้โดยการสนับสนุนบน GitHub</string>\n    <string name=\"format_sorting\">การจัดเรียงรูปแบบ</string>\n    <string name=\"audio_quality_desc\">จำกัดอัตราการส่งถ่ายบิทเรตของเสียงเมื่อมีคุณภาพหลายชนิดอยู่</string>\n    <string name=\"sponsors\">ผู้สนับสนุน</string>\n    <string name=\"feedback\">ความคิดเห็น</string>\n    <string name=\"sponsor\">ผู้สนับสนุน</string>\n    <string name=\"temporary_directory_desc\">เก็บไฟล์ชั่วคราวในไดเรกทอรีภายใน</string>\n    <string name=\"rename\">เปลี่ยนชื่อ</string>\n    <string name=\"audio_format_preference\">รูปแบบเสียงที่ชอบ</string>\n    <string name=\"preferred_format_desc\">รูปแบบที่ต้องการเมื่อมีวีดีโอหลายรายการ</string>\n    <string name=\"convert_audio_format\">แปลงรูปแบบไฟล์เสียง</string>\n    <string name=\"clear_all_cookies_desc\">ลบคุกกี้ทั้งหมดที่เก็บไว้ในแอปอย่างถาวรหรือไม่\\?</string>\n    <string name=\"selected_item_count\">%1$d ถูกเลือก</string>\n    <string name=\"select_all\">เลือกทั้งหมด</string>\n    <string name=\"download_selection_desc\">เลือกวิดีโอที่จะดาวน์โหลดจากเพลย์ลิสต์ \\\"%1$s\\\"</string>\n    <string name=\"clip_video_desc\">ทำคลิปวิดีโอในหน้าเลือกรูปแบบ</string>\n    <string name=\"convert_to\">แปลงเป็น %1$s</string>\n    <string name=\"convert_audio\">แปลง</string>\n    <string name=\"battery_settings_desc\">โปรดตั้งค่าการใช้งานแบตเตอรี่ของแอพฯ นี้เป็น \\\"ไม่จำกัด\\\" ในการตั้งค่าระบบเพื่อดาวน์โหลดในพื้นหลัง</string>\n    <string name=\"channel_description\">แจ้งเตือนไฟล์ที่ดาวน์โหลดแล้วและความคืบหน้าของการดาวน์โหลด</string>\n    <string name=\"download_directory\">ไดเรกทอรีดาวน์โหลด</string>\n    <string name=\"audio_directory\">โฟลเดอร์ไฟล์เสียง</string>\n    <string name=\"battery_configuration\">การกำหนดค่าแบตเตอรี่</string>\n    <string name=\"permission_issue_desc\">ไม่รองรับไดเรกทอรีที่อยู่นอก Download/ และ Documents/</string>\n    <string name=\"permission_issue\">มีปัญหาการเรียกใช้สิทธิ์การเข้าถึงที่เก็บข้อมูล</string>\n    <string name=\"subdirectory_desc\">บันทึกไฟล์ในโฟลเดอร์ที่ตั้งชื่อตามที่มาที่เกี่ยวข้อง</string>\n    <string name=\"subdirectory\">บันทึกไปยังไดเรกทอรีย่อย</string>\n    <string name=\"github_issue\">Issue ใน GitHub</string>\n    <string name=\"task_canceled\">ยกเลิกงานดาวน์โหลดแล้ว</string>\n    <string name=\"unknown_error\">ข้อผิดพลาดที่ไม่รู้จัก</string>\n    <string name=\"service_title\">Seal กำลังดาวน์โหลด…</string>\n    <string name=\"battery_configuration_desc\">ละเว้นการเพิ่มประสิทธิภาพแบตเตอรี่สำหรับแอพฯ นี้เพื่อดาวน์โหลดในพื้นหลัง</string>\n    <string name=\"downloading_indicator_text\">กำลังดาวน์โหลด…</string>\n    <string name=\"info_copied\">­ข้อมูลถูกคัดลอกไปยังคลิปบอร์ดแล้ว</string>\n    <string name=\"status_canceled\">ยกเลิกแล้ว</string>\n    <string name=\"status_downloading\">กำลังดาวน์โหลด</string>\n    <string name=\"status_completed\">เสร็จสมบูรณ์</string>\n    <string name=\"status_enqueued\">อยู่ในคิว</string>\n    <string name=\"copy_error_report\">คัดลอกรายงาน</string>\n    <string name=\"multiselect_item_count\">ไฟล์วีดีโอจำนวน %1$d รายการ ไฟล์เสียงจำนวน %2$d รายการ</string>\n    <string name=\"download_task_count\">จำนวนงานดาวน์โหลด %1$d รายการ</string>\n    <string name=\"video_file_size\">ขนาดไฟล์วิดีโอ</string>\n    <string name=\"video_resolution\">ความละเอียดของวิดีโอ</string>\n    <string name=\"check_for_updates_desc\">ตรวจสอบเวอร์ชันล่าสุดบน GitHub โดยอัตโนมัติ</string>\n    <string name=\"rate_limit\">จำกัดเรท</string>\n    <string name=\"network\">เครือข่าย</string>\n    <string name=\"cookies_desc\">ใช้คุกกี้ที่จัดรูปแบบโดย Netscape สำหรับการดาวน์โหลด</string>\n    <string name=\"app_update_failed\">ไม่สามารถอัพเดทเป็นเวอร์ชันล่าสุดได้</string>\n    <string name=\"app_up_to_date\">เวอร์ชั่นปัจจุบันเป็นเวอร์ชั่นล่าสุดแล้ว</string>\n    <string name=\"lowest_quality\">คุณภาพต่ำสุด</string>\n    <string name=\"subtitle_sponsorblock\">ซับไตเติ้ลอาจจะถูกจัดเวลาผิดเมื่อลบช่วงของ SponsorBlock</string>\n    <string name=\"playlist_indicator_text\">กำลังดาวน์โหลดเพลย์ลิสต์ (%1$d/%2$d) …</string>\n    <string name=\"use_custom_command\">การใช้คำสั่งที่กำหนดเอง</string>\n    <string name=\"audio\">เสียง</string>\n    <string name=\"dismiss\">ยกเลิก</string>\n    <string name=\"delete_info\">ต้องการลบหรอไม่?</string>\n    <string name=\"paste_fail_msg\">ไม่สามารถจับคู่ URL ในคลิปบอร์ดได้</string>\n    <string name=\"language\">ภาษาที่แสดงในแอพพลิเคชั่น</string>\n    <string name=\"fetch_info_error_msg\">ไม่สามารถดึงข้อมูลของวิดีโอได้</string>\n    <string name=\"release\">รุ่นล่าสุด</string>\n    <string name=\"release_desc\">ค้นหาบันทึกการเปลี่ยนแปลงและเวอร์ชันใหม่ ๆ</string>\n    <string name=\"custom_command_template\">เทมเพลตคำสั่ง</string>\n    <string name=\"checked\">เลือกแล้ว</string>\n    <string name=\"custom_command\">คำสั่งที่กำหนดเอง</string>\n    <string name=\"print_details\">เอาต์พุตโดยละเอียด</string>\n    <string name=\"custom_command_desc\">รันคำสั่ง yt-dlp จากเทมเพลตที่กำหนดเอง</string>\n    <string name=\"print_details_desc\">แสดงข้อความแบบละเอียดเมื่อกำลังดาวน์โหลด</string>\n    <string name=\"display\">การแสดงผล</string>\n    <string name=\"off\">ปิด</string>\n    <string name=\"display_settings\">ธีมมืด สีไดนามิก ภาษาที่แสดง</string>\n    <string name=\"dark_theme\">ธีมมืด</string>\n    <string name=\"paste\">วาง</string>\n    <string name=\"yt_dlp_docs\">การอ้างอิงการใช้งานของ Yt-dlp</string>\n    <string name=\"thumbnail\">ภาพขนาดย่อ</string>\n    <string name=\"error_copied\">รายงานข้อผิดพลาดถูกคัดลอกไปยังคลิปบอร์ดแล้ว</string>\n    <string name=\"settings_before_download\">กำหนดค่าก่อนดาวน์โหลด</string>\n    <string name=\"cancel\">ยกเลิก</string>\n    <string name=\"not_convert\">ไม่ได้แปลง</string>\n    <string name=\"video_format\">รูปแบบไฟล์วีดีโอ</string>\n    <string name=\"video_quality\">คุณภาพวีดีโอ</string>\n    <string name=\"not_specified\">ไม่ได้ระบุ (ค่าเริ่มต้น)</string>\n    <string name=\"video_quality_desc\">จำกัดคุณภาพวิดีโอเมื่อมีวีดีโอหลายรายการ</string>\n    <string name=\"best_quality\">คุณภาพดีที่สุด</string>\n    <string name=\"close_never_show_again\">ไม่ต้องแสดงอีก</string>\n    <string name=\"close\">ปิด</string>\n    <string name=\"start_download\">ดาวน์โหลด</string>\n    <string name=\"video_url\">ลิงก์วีดีโอ</string>\n    <string name=\"channel_name\">ดาวน์โหลด</string>\n    <string name=\"defaults\">ค่าเริ่มต้น</string>\n    <string name=\"download_playlist_desc\">ดาวน์โหลดหลายวิดีโอจากเพลย์ลิสต์</string>\n    <string name=\"download_playlist\">ดาวน์โหลดเพลย์ลิสต์</string>\n    <string name=\"concurrent_download\">ดาวน์โหลดแบบมัลติเธรด</string>\n    <string name=\"execute_command_notification\">กำลังรันคำสั่งที่กำหนดเอง…</string>\n    <string name=\"download_finish_notification\">ดาวน์โหลดเสร็จสิ้น แตะเพื่อเปิด</string>\n    <string name=\"share_success_msg\">กำลังอ่านลิงก์วิดีโอจากเนื้อหาที่แชร์…</string>\n    <string name=\"additional_settings\">การตั้งค่าเพิ่มเติม</string>\n    <string name=\"share_fail_msg\">ไม่สามารถจับคู่ URL จากเนื้อหาที่แชร์มาได้</string>\n    <string name=\"from\">เริ่ม</string>\n    <string name=\"download_range_desc\">กำหนดช่วงของวิดีโอที่จะดาวน์โหลดจากเพลย์ลิสต์ \\\"%3$s\\\" (%1$d ถึง %2$d)</string>\n    <string name=\"embed_subtitles\">ฝังซับไตเติ้ล</string>\n    <string name=\"custom_command_template_desc\">แก้ไขและจัดการเทมเพลตคำสั่ง</string>\n    <string name=\"template_selection\">การเลือกแม่แบบ</string>\n    <string name=\"remove_template_desc\">ลบ \\\"%1$s\\\" ออกจากเทมเพลตคำสั่งอย่างถาวรหรือไม่?</string>\n    <string name=\"remove_template\">ต้องการลบ?</string>\n    <string name=\"template_label\">ป้าย</string>\n    <string name=\"status_error\">ข้อผิดพลาด</string>\n    <string name=\"status_fetching_video_info\">กำลังดึงข้อมูล</string>\n    <string name=\"restart\">เริ่มใหม่</string>\n    <string name=\"open_file\">เปิดไฟล์</string>\n    <string name=\"template_exported\">ส่งออกเทมเพลตแล้ว จำนวน %1$d รายการ</string>\n    <string name=\"template_imported\">นำเข้าเทมเพลตแล้ว จำนวน %1$d รายการ</string>\n    <string name=\"import_from_clipboard\">นำเข้าจากคลิปบอร์ด</string>\n    <string name=\"export_to_clipboard\">ส่งออกไปยังคลิปบอร์ด</string>\n    <string name=\"check_for_updates\">ตรวจสอบการอัพเดท</string>\n    <string name=\"sponsorblock_categories_desc\">ระบุหมวดหมู่ของ SponsorBlock ที่จะถูกลบหรือเพิ่มในไฟล์วิดีโอ</string>\n    <string name=\"clear_temp_files\">ล้างไฟล์ชั่วคราว</string>\n    <string name=\"clear_temp_files_info\">ไฟล์ชั่วคราวสามารถใช้ในการดำเนินการดาวน์โหลดต่อหลังจากที่ถูกยกเลิกแล้วได้ คุณแน่ใจหรือว่าต้องการลบไฟล์ทั้งหมดนี้หรือไม่?\\n\\nคุณสามารถดูไฟล์เหล่านี้ใน %1$s</string>\n    <string name=\"clear_temp_files_count\">ลบไฟล์ชั่วคราวทั้งหมด %1$d รายการ</string>\n    <string name=\"clear_temp_files_desc\">ลบไฟล์ชั่วคราวทั้งหมดจากไดเรกทอรีขั่วคราว</string>\n    <string name=\"download_with_cellular\">ดาวน์โหลดโดยใช้เครือข่ายเซลลูลาร์</string>\n    <string name=\"dynamic_color_desc\">ใช้สีจากวอลเปเปอร์ในธีมของแอป</string>\n    <string name=\"private_mode_desc\">ปิดประวัติการดาวน์โหลด</string>\n    <string name=\"private_mode\">ไม่ระบุตัวตน</string>\n    <string name=\"file_unavailable\">ไฟล์นี้ไม่สามารถใช้งานได้อีกต่อไป</string>\n    <string name=\"download_disabled_with_cellular\">การดาวน์โหลดด้วยเครือข่ายเซลลูลาร์ถูกปิดการใช้งานตามการตั้งค่าของคุณ</string>\n    <string name=\"got_it\">เข้าใจแล้ว</string>\n    <string name=\"switch_to_github_builds\">เปลี่ยนไปใช้ GitHub builds</string>\n    <string name=\"to\">จบ</string>\n    <string name=\"on\">เปิด</string>\n    <string name=\"follow_system\">ระบบ</string>\n    <string name=\"credits_desc\">เครดิตและซอฟต์แวร์ที่เกี่ยวข้อง</string>\n    <string name=\"video\">วีดีโอ</string>\n    <string name=\"about\">เกี่ยวกับ</string>\n    <string name=\"remove\">ลบ</string>\n    <string name=\"open_url\">เปิดลิงก์</string>\n    <string name=\"telegram_channel\">ช่อง Telegram</string>\n    <string name=\"readme_desc\">ตรวจสอบ repository บน GitHub และไฟล์ README</string>\n    <string name=\"ytdlp_version\">เวอร์ชั่นของ Yt-dlp</string>\n    <string name=\"delete_multiple_items_msg\">ลบทั้งหมด %1$d รายการออกจากประวัติการดาวน์โหลดของคุณอย่างถาวร?</string>\n    <string name=\"paste_msg\">วาง URL</string>\n    <string name=\"custom_command_enabled_hint\">เมื่อใช้คำสั่งที่กำหนดเอง บางตัวเลือกจะไม่สามารถใช้ได้</string>\n    <string name=\"fetching_playlist_info\">กำลังดึงข้อมูลของเพลย์ลิสต์…</string>\n    <string name=\"cookies\">คุกกี้</string>\n    <string name=\"suggested\">แนะนำ</string>\n    <string name=\"download_desc\">หลังจากที่คุณปรับการตั้งค่าแล้ว ให้คลิกที่ \\\"ดาวน์โหลด\\\"</string>\n    <string name=\"user_guide\">คู่มือผู้ใช้</string>\n    <string name=\"sponsorblock_desc\">ลบหรือบันทึกเซกเมนต์ในวิดีโอด้วย SponsorBlock API</string>\n    <string name=\"format\">รูปแบบ</string>\n    <string name=\"video_only\">วิดีโอ (ไม่มีเสียง)</string>\n    <string name=\"back\">ย้อนกลับ</string>\n    <string name=\"update\">อัพเดท</string>\n    <string name=\"invalid_input\">ข้อมูลที่ป้อนไม่ถูกต้อง</string>\n    <string name=\"download_start_msg\">ดาวน์โหลด \\\"%1$s\\\"</string>\n    <string name=\"credits\">เครดิต</string>\n    <string name=\"downloads_history\">รายการดาวน์โหลด</string>\n    <string name=\"open_settings\">เปิดการตั้งค่า</string>\n    <string name=\"delete_file\">ลบไฟล์</string>\n    <string name=\"translate\">แปลภาษา</string>\n    <string name=\"start_execute\">เริ่มดำเนินงานตามคำสั่ง</string>\n    <string name=\"edit_template_desc\">เส้นทางขาออกและ URL จะถูกเพิ่มโดยแอพพลิเคชั่น</string>\n    <string name=\"format_selection\">การเลือกรูปแบบ</string>\n    <string name=\"options\">ตัวเลือก</string>\n    <string name=\"download_with_cellular_desc\">อนุญาตให้ดาวน์โหลดสื่อเมื่อเชื่อมต่อกับเครือข่ายที่มีการคิดค่าบริการ</string>\n    <string name=\"how_does_it_work\">มันทำงานอย่างไร\\?</string>\n    <string name=\"private_directory_desc\">เก็บดาวน์โหลดในไดเรกทอรีที่ซ่อนอยู่</string>\n    <string name=\"download_error_msg\">ไม่สามารถดาวน์โหลดไฟล์ได้</string>\n    <string name=\"download_success_msg\">การดาวน์โหลดเสร็จสิ้น</string>\n    <string name=\"language_settings\">ตั้งค่าภาษาที่แสดงในแอพพลิเคชั่น</string>\n    <string name=\"settings_before_download_text\">ปรับแต่งการดาวน์โหลดนี้</string>\n    <string name=\"task_running\">การดาวน์โหลดที่มีอยู่แล้วกำลังทำงานอยู่</string>\n    <string name=\"download_notification\">การแจ้งเตือนการดาวน์โหลด</string>\n    <string name=\"check_download_settings_desc\">ลองดูที่การตั้งค่าการดาวน์โหลด ตรวจสอบว่าคุณมี yt-dlp เวอร์ชันล่าสุดของก่อนที่จะใช้งาน</string>\n    <string name=\"download_history_desc\">ตรวจสอบและจัดการการดาวน์โหลดภายในแอพฯ รวมถึงไฟล์วิดีโอและไฟล์เสียง</string>\n    <string name=\"video_format_preference\">รูปแบบวิดีโอที่ต้องการ</string>\n    <string name=\"remove_cookie_profile_desc\">ลบรายการสำหรับ \\\"%1$s\\\" หรือไม่? โดยคุกกี้ที่เก็บไว้สำหรับเว็บไซต์นี้จะไม่ถูกลบไปด้วย</string>\n    <string name=\"use_cookies\">ใช้คุกกี้</string>\n    <string name=\"auto_subtitle_desc\">ดาวน์โหลดคำบรรยายที่สร้างขึ้นอัตโนมัติ</string>\n    <string name=\"generate_new_cookies\">สร้างคุกกี้ใหม่</string>\n    <string name=\"subtitle_desc\">ภาษา, ซับไตเติ้ลฝัง, คำบรรยายอัตโนมัติ</string>\n    <string name=\"cookies_usage_msg\">การดาวน์โหลดจากบางเว็บไซต์จำเป็นต้องระบุข้อมูลการรับรองความถูกต้องของบัญชี คลิก \\\"สร้างคุกกี้ใหม่\\\" แล้วใส่ URL ของเว็บไซต์และล็อกอินด้วยบัญชีของคุณในหน้าเบราว์เซอร์ แอปจะสร้างคุกกี้สำหรับคุณ</string>\n    <string name=\"video_creator_sample_text\">ตัวอย่างข้อความของผู้สร้างวิดีโอ</string>\n    <string name=\"format_selection_desc\">เลือกรูปแบบที่จะดาวน์โหลดก่อนที่จะเริ่มดาวน์โหลด</string>\n    <string name=\"disable_preview_desc\">ไม่แสดงภาพขนาดย่อระหว่างการดาวน์โหลด</string>\n    <string name=\"rate_limit_desc\">จำกัดความเร็วในการดาวน์โหลดสูงสุด</string>\n    <string name=\"format_settings_desc\">รูปแบบไฟล์, คุณภาพวิดีโอ, ซับไตเติ้ล</string>\n    <string name=\"high_contrast\">ธีมที่มีความคมชัดสูงและมืด</string>\n    <string name=\"sponsorblock_categories\">หมวดหมู่ของ SponsorBlock</string>\n    <string name=\"github_issue_desc\">ส่งรายงานข้อบกพร่องหรือร้องขอฟีเจอร์</string>\n    <string name=\"prefix\">คำนำหน้า</string>\n    <string name=\"new_template\">เทมเพลตใหม่</string>\n    <string name=\"embed_subtitles_desc\">ฝังซับไตเติ้ลในไฟล์วิดีโอหากมีมาให้</string>\n    <string name=\"translate_desc\">ช่วยแปลภาษาของแอพฯ นี้บน Hosted Weblate</string>\n    <string name=\"download_directory_desc\">เลือกตำแหน่งที่จะเก็บไฟล์วิดีโอและเสียง</string>\n    <string name=\"invalid_index_range\">ช่วงดัชนีไม่ถูกต้อง</string>\n    <string name=\"download_range_selection\">การเลือกเพลย์ลิสต์</string>\n    <string name=\"download_notification_desc\">แจ้งเตือนไฟล์ที่ดาวน์โหลดแล้วและความคืบหน้าของการดาวน์โหลด</string>\n    <string name=\"show_more_actions\">แสดงการกระทำเพิ่มเติม</string>\n    <string name=\"concurrent_download_num\">%d เธรด จะถูกใช้เพื่อดาวน์โหลดวิดีโอ DASH/HLS แบบพร้อมกัน</string>\n    <string name=\"concurrent_download_desc\">ดาวน์โหลดส่วนอื่น ๆ ของวิดีโอ M3U8/MPD พร้อมกัน</string>\n    <string name=\"paste_desc\">คลิก \\\"วาง\\\" เพื่อวางลิงค์วิดีโอจากคลิปบอร์ดของคุณ</string>\n    <string name=\"convert_audio_format_desc\">การเข้ารหัสไฟล์เสียงอีกครั้งจะทำให้ไฟล์เสียงสูญเสียคุณภาพและขนาดไฟล์จะเพิ่มมากขึ้น</string>\n    <string name=\"advanced_settings\">ขั้นสูง</string>\n    <string name=\"delete_info_msg\">ต้องการลบ \\\"%1$s\\\" ออกจากประวัติการดาวน์โหลดของคุณอย่างถาวร?</string>\n    <string name=\"auto_update_disabled_msg\">ออโต้อัปเดทไม่สามารถใช้ได้สำหรับ %1$s นี้ ถ้าคุณไม่ได้ติดตั้ง %1$s บนอุปกรณ์ของคุณหรือต้องการดูฟีเจอร์ใหม่ที่กำลังจะมาใน Seal โปรดพิจารณา %2$s</string>\n    <string name=\"embed_subtitles_mkv_msg\">สำหรับการฝังซับไทเทิลฝังแยก วิดีโอจะถูกรีมักซ์เข้ากับคอนเทนเนอร์ mkv คุณสามารถใช้ VLC Media Player หรือแอปพลิเคชั่นอื่น ๆ ที่รองรับเพื่อเล่นวีดีโอที่มีซับไทเทิลฝังแยก</string>\n    <string name=\"settings_before_download_desc\">กำหนดตัวเลือกก่อนการดาวน์โหลด</string>\n    <string name=\"version\">เวอร์ชั่น</string>\n    <string name=\"about_page\">เวอร์ชั่น การตอบรับ การอัปเดตอัตโนมัติ</string>\n    <string name=\"ytdlp_update\">คลิกเพื่อติดตั้ง yt-dlp เวอร์ชั่นล่าสุด</string>\n    <string name=\"clip_video_dialog_msg\">การดาวน์โหลดที่ใช้คุณลักษณะนี้จะถูกมอบหมายให้ FFmpeg เพื่อดาวน์โหลดส่วนที่เลือกของวิดีโอ คุณลักษณะนี้ยังเป็นการทดลองและการตัดจะไม่เป็นแน่นอน ไม่ทุกรูปแบบสนับสนุนคุณลักษณะนี้และคุณอาจพบความเร็วดาวน์โหลดที่ช้าลง</string>\n    <string name=\"edit_shortcuts_desc\">แก้ไขทางลัดที่กำหนดเองที่สามารถใช้ในการสร้างแม่แบบคำสั่ง</string>\n    <string name=\"link_copied\">คัดลอกลิงก์ไปยังคลิปบอร์ดแล้ว</string>\n    <string name=\"confirm\">ยืนยัน</string>\n    <string name=\"general_settings\">ทั่วไป</string>\n    <string name=\"edit\">แก้ไข</string>\n    <string name=\"no_custom_command_tasks\">ไม่มีงานคำสั่งที่กำหนดเอง</string>\n    <string name=\"copy_log\">คัดลอกบันทึก</string>\n    <string name=\"permission_denied\">สิทธิ์ของแอพพลิเคชั่นถูกปฏิเสธ</string>\n    <string name=\"fetching_info\">กำลังดึงข้อมูลของวีดีโอ…</string>\n    <string name=\"yt_dlp_update_fail\">ไม่สามารถติดตั้ง yt-dlp เวอร์ชั่นล่าสุดได้ โปรดตรวจสอบให้แน่ใจว่าคุณได้เชื่อมต่ออินเทอร์เน็ตแล้ว</string>\n    <string name=\"title_activity_share\">ดาวน์โหลดด่วน</string>\n    <string name=\"auto_subtitle\">คำบรรยายอัตโนมัติ</string>\n    <string name=\"sdcard_directory\">โฟลเดอร์การ์ด SD</string>\n    <string name=\"private_directory\">ไดเรกทอรีส่วนตัว</string>\n    <string name=\"privacy\">ความเป็นส่วนตัว</string>\n    <string name=\"disable_preview\">ปิดการแสดงตัวอย่าง</string>\n    <string name=\"network_settings_desc\">จำกัดเรท, ตัวดาวน์โหลด, คุกกี้</string>\n    <string name=\"unavailable\">ไม่พร้อมใช้งาน</string>\n    <string name=\"max_rate\">เรทสูงสุด</string>\n    <string name=\"aria2_desc\">ใช้ aria2c เป็นตัวดาวน์โหลดภายนอก</string>\n    <string name=\"recently_added\">เพิ่มเมื่อเร็วๆ นี้</string>\n    <string name=\"copy_link\">คัดลอกลิงค์</string>\n    <string name=\"logs\">บันทึก</string>\n    <string name=\"show_logs\">แสดงบันทึก</string>\n    <string name=\"shortcuts\">ทางลัด</string>\n    <string name=\"add\">เพิ่ม</string>\n    <string name=\"edit_shortcuts\">แก้ไขทางลัด</string>\n    <string name=\"clear\">ล้าง</string>\n    <string name=\"subtitle_language\">ภาษาซับไตเติ้ล</string>\n    <string name=\"download_subtitles\">ดาวน์โหลดซับไตเติ้ล</string>\n    <string name=\"subtitle\">ซับไตเติ้ล</string>\n    <string name=\"video_title_sample_text\">ตัวอย่างข้อความของไตเติ้ล</string>\n    <string name=\"running_tasks\">กำลังรันงาน</string>\n    <string name=\"sponsor_msg\">Seal จะยังคงเป็นซอร์ตฟรีและเปิดกว้างสำหรับทุกคน ถ้าคุณชอบมัน กรุณาพิจารณาสนับสนุนฉันใน GitHub!</string>\n    <string name=\"format_sorting_desc\">จัดเรียงรูปแบบด้วยตัวเลือก -S ของ yt-dlp</string>\n    <string name=\"update_channel_desc\">ติดตั้งรุ่นก่อนวางจำหน่ายเพื่อดูลักษณะใหม่และการเปลี่ยนแปลง\n\\n\n\\nอาจมีความไม่สมดุลในรุ่นนี้ โปรดอย่าลังเลใจกับเราในการรีบรีบทักทายถ้าคุณพบปัญหาใดๆ เพื่อช่วยให้เราปรับปรุงแอปในอนาคต</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"ytdlp_update_action\">อัพเดต yt-dlp</string>\n    <string name=\"matrix_space\">เมทริกซ์สเปซ</string>\n    <string name=\"multiselect_mode\">โหมดเลือกหลายรายการ</string>\n    <string name=\"crop_artwork\">ครอบตัดรูปภาพ</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp คือเครื่องมือ command line ประสิทธิภาพสูงสำหรับดาวน์โหลดวีดีโอ Seal ทำให้การใช้งาน yt-dlp ง่ายขึ้นด้วยอินเทอร์เฟซที่เรียบง่าย, พรีเซ็ตคำสั่งทั่วไป และฟีเจอร์เพิ่มเติมอื่นๆ\n\\n\n\\nสำหรับการใช้งานขั้นสูงของ yt-dlp. Seal ให้คุณสามารถสร้าง, บันทึก และใช้เทมเพลตคำสั่งที่กำเองได้โดยตรง เหมือนเทอมินอลเลย\n\\n\n\\nเมื่อคุณกำลังใช้คำสั่งที่กำหนดเอง ตัวเลือกและฟีเจอร์ที่เกี่ยวข้องกับส่วนติดต่อผู้ใช้งานจะถูกปิดใช้งานด้วย</string>\n    <string name=\"general_settings_desc\">เวอร์ชั่นของ Yt-dlp, การแจ้งเตือน, เพลย์ลิสต์</string>\n    <string name=\"dynamic_color\">สีไดนามิก</string>\n    <string name=\"start\">เริ่มต้น</string>\n    <string name=\"crop_artwork_desc\">ครอบตัดรูปภาพที่ฝังให้เป็นรูปสี่เหลี่ยม</string>\n    <string name=\"remove_multiple_templates_msg\">นำคำสั่ง %1$s ออกจากเทมเพลตคำสั่งอย่างถาวร?</string>\n    <string name=\"refresh_cookies_desc\">แตะเพื่อเปิดเว็ปเพจเพื่อสร้างคุกกี้:</string>\n    <string name=\"edit_file\">แก้ไขไฟล์</string>\n    <string name=\"save\">บันทึก</string>\n    <string name=\"embed_metadata\">ฝังข้อมูลเมต้า</string>\n    <string name=\"embed_metadata_desc\">ฝังข้อมูลเมต้าและภาพขนาดย่อลงในไฟล์เสียง</string>\n    <string name=\"allow_once\">อนุญาตครั้งเดียว</string>\n    <string name=\"use_format_sorting\">ใช้การจัดเรียงรูปแบบ</string>\n    <string name=\"abs_hint\">แพลตฟอร์มสตรีมมิ่งวิดีโอส่วนใหญ่จะส่งเสียงและวิดีโอแยกจากกัน คุณสามารถเลือกและรวมรูปแบบเฉพาะเสียงเข้ากับรูปแบบเฉพาะวิดีโอให้เป็นวิดีโอเดียวได้</string>\n    <string name=\"allow_always\">อนุญาตทุกครั้ง</string>\n    <string name=\"download_with_cellular_request\">ให้สามารถดาวน์โหลดโดยใช้ข้อมูลมือถือ?</string>\n    <string name=\"download_archive_error\">วีดีโอถูกดาวน์โหลดแล้ว หากนี้ไม่ใช่สิ่งที่คาดไว้ โปรดตรวจสอบในรายการจัดเก็บดาวน์โหลด</string>\n    <string name=\"merge_audiostream\">รวมสตรีมเสียง</string>\n    <string name=\"subdirectory_hint\">รายการดาวน์โหลดของคุณจะถูกบันทึกเป็น:</string>\n    <string name=\"ua_header\">ส่วนของของ User-Agent</string>\n    <string name=\"convert_subtitle_desc\">แปลงซับไทเทิ้ลเป็นรูปแบบอื่น</string>\n    <string name=\"split_video\">แยกวีดิโอ</string>\n    <string name=\"copy_and_exit\">คัดลอกและออก</string>\n    <string name=\"edit_template\">แก้ไข “%1$s”</string>\n    <string name=\"expand\">ขยาย</string>\n    <string name=\"new_task\">เพิ่มงานดาวน์โหลด</string>\n    <string name=\"keep_subtitle_files\">เก็บไฟล์ซับไทเทิล</string>\n    <string name=\"proxy_desc\">ใช้พร็อกซีสำหรับการเชื่อมต่ออินเทอร์เน็ต</string>\n    <string name=\"split_video_msg\">วีดีโอจะถูกแยกเป็น %1$d ตอน</string>\n    <string name=\"unknown_error_title\">อุ้ย! มีบางอย่างผิดพลาด</string>\n    <string name=\"legacy\">เข้ากันได้</string>\n    <string name=\"proxy\">พร็อกซี</string>\n    <string name=\"enable_notifications\">รับการแจ้งเตือนหรือไม่?</string>\n    <string name=\"enable_notifications_desc\">แอปพลิเคชั่นต้องการสิทธิ์ในการแจ้งเตือนเพื่อส่งการแจ้งเตือนสถานะและความคืบหน้าของการดาวน์โหลด</string>\n    <string name=\"set_directory_desc\">แตะเพื่อกำหนดไดเรกทอรี</string>\n    <string name=\"disable\">ปิดใช้งาน</string>\n    <string name=\"prefer_quality_desc\">เลือกรูปแบบ AV1, VP9 หรือ H.265 สำหรับการรับชมบนแอปพลิเคชั่นที่รองรับ</string>\n    <string name=\"download_type\">ชนิดของการดาวน์โหลด</string>\n    <string name=\"prefer_compatibility_desc\">เลือกรูปแบบ MP4(H.264) สำหรับการแชร์ไปที่แอปพลิเคชั่นอื่น ๆ</string>\n    <string name=\"remux_container_mkv_desc\">รีมักซ์วีดีโอลงในคอนเทนเนอร์ MKV สำหรับความเข้ากันที่ดีขึ้น</string>\n    <string name=\"remux_container_mkv\">รีมักซ์คอนเทนเนอรวีดีโอ</string>\n    <string name=\"required\">จำเป็น</string>\n    <string name=\"download_video_desc\">ดาวโหลดวีดีโอจาก URL</string>\n    <string name=\"show_all_items\">แสดงรายการทั้งหมด %1$d รายการ</string>\n    <string name=\"full_backup\">สำรองแบบเต็ม</string>\n    <string name=\"export_to\">ส่งออกไปยัง</string>\n    <string name=\"backup_type\">ชนิดของการสำรอง</string>\n    <string name=\"clipboard\">คลิปบอร์ด</string>\n    <string name=\"import_download_history_msg\">ไฟล์ที่ดาวน์โหลดแล้วจะไม่ถูกนำเข้า คุณต้องดาวน์โหลดด้วยตัวเอง</string>\n    <string name=\"export_to_file\">ส่งออกเป็นไฟล์</string>\n    <string name=\"commands\">คำสั่งต่าง ๆ</string>\n    <string name=\"format_preference\">ตัวเลือกของรูปแบบ</string>\n    <string name=\"learn_more\">เรียนรู้เพิ่มเติม</string>\n    <string name=\"custom\">กำหนดเอง</string>\n    <string name=\"auto\">อัตโนมัติ</string>\n    <string name=\"unknown\">ไม่รู้จัก</string>\n    <string name=\"restrict_filenames\">จำกัดชื่อไฟล์</string>\n    <string name=\"restrict_filenames_desc\">จำกัดชื่อไฟล์ให้มีตัวอักษรเฉพาะ สำหรับความเข้ากัน</string>\n    <string name=\"website\">เว็บไซต์</string>\n    <string name=\"playlist_title\">ชื่อเพลย์ลิสต์</string>\n    <string name=\"disabled\">ปิดใช้งานแล้ว</string>\n    <string name=\"folder_picker\">ที่เปิดโฟลเดอร์</string>\n    <string name=\"custom_command_directory_desc\">ระบุไดเรกทอรีขาออกเมื่อใช้คำสั่งที่กำหนดเอง</string>\n    <string name=\"quality\">คุณภาพ</string>\n    <string name=\"custom_command_directory\">ไดเรกทอรีของคำสั่งที่กำหนดเอง</string>\n    <string name=\"convert_subtitle\">แปลงซับไทเทิล</string>\n    <string name=\"output_template\">ขาออกของเทมเพลต</string>\n    <string name=\"presets\">พรีเซ็ต</string>\n    <string name=\"output_template_desc\">ระบุเทมเพลตสำหรับชื่อไฟล์ขาออก</string>\n    <string name=\"cookies_in_database\">%1$d คุกกี้จากเว็บไซต์ทั้งหมด %2$d เว็บไซต์</string>\n    <string name=\"update_language_msg\">ภาษาที่เลือกนี้จะถูกเพิ่มเป็นภาษาที่คุณชอบเพื่อใช้ในการดาวน์โหลดครั้งต่อ ๆ ไปในอนาคต:</string>\n    <string name=\"redownload\">ดาวน์โหลดใหม่</string>\n    <string name=\"export_download_history_msg\">กำลังส่งออก %1$s จากประวัติการดาวน์โหลด ไฟล์ที่ดาวน์โหลดแล้วและการตั้งค่าต่าง ๆ จะไม่ได้รับการสำรองข้อมูล</string>\n    <string name=\"download_history_imported\">นำเข้า %1$s สู่ประวัติการดาวน์โหลดแล้ว</string>\n    <string name=\"download_archive\">จัดเก็บดาวน์โหลด</string>\n    <string name=\"merge_audiostream_desc\">อนุญาตให้รวมสตรีมเสียงเข้าไปในไฟล์เดียว</string>\n    <string name=\"auto_translated_subtitles\">ซับไทเทิลที่แปลอัตโนมัติแล้ว</string>\n    <string name=\"auto_translated_subtitles_msg\">ซับไทเทิลที่แปลอัตโนมัติแล้วสำหรับทุกภาษาจะสามารถค้นพบได้ในรายการดาวน์โหลด ซับไทเทิลเหล่านี้อาจไม่แม่นยำหรือเข้าใจยากจากการแปลอัตโนมัติ</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">%d รายการ</item>\n    </plurals>\n    <string name=\"remember_for_next_download\">จดจำสำหรับหารดาวน์โหลดครั้งหน้า</string>\n    <string name=\"system_settings\">การตั้งค่าระบบ</string>\n    <string name=\"subtitle_language_desc\">ภาษาของซับไทเทิลที่จะดาวน์โหลดในโหมด“เลือกรูปแบบอัตโนมัติ” แยกแต่ละภาษาที่ต้องการด้วยเครื่องหมายจุลภาค</string>\n    <string name=\"interface_and_interaction\">อินเทอร์เฟซและการใช้งาน</string>\n    <string name=\"use_previous_selection\">ใช้การเลือกครั้งก่อนหน้านี้</string>\n    <string name=\"none\">ไม่มี</string>\n    <string name=\"look_and_feel\">รูปลักษณ์และความรู้สึก</string>\n    <string name=\"reset\">รีเซ็ต</string>\n    <string name=\"search_in_subtitles\">ค้นหาในซับไทเทิล</string>\n    <string name=\"no_thanks\">ไม่เป็นไร ขอบคุณ</string>\n    <string name=\"update_subtitle_languages\">อัพเดตภาษาของซับไทเทิล?</string>\n    <string name=\"export_backup\">ส่งออก</string>\n    <string name=\"import_backup\">นำเข้า</string>\n    <string name=\"file\">ไฟล์</string>\n    <string name=\"import_from\">นำเข้าจาก</string>\n    <string name=\"export_download_history\">ส่งออกไปที่ประวัติการดาวน์โหลด?</string>\n    <string name=\"import_download_history\">นำเข้าประวัติการดาวน์โหลด?</string>\n    <string name=\"download_history\">ประวัติการดาวน์โหลด</string>\n    <string name=\"download_archive_desc\">บันทึกไอดีของวีดีโอที่ดาวน์โหลดแล้วลงในส่วยที่จัดเก็บเพื่อเลี่ยงการดาวน์โหลดซ้ำซ้อน</string>\n    <string name=\"clear_download_archive\">ล้างรายการจัดเก็บดาวน์โหลด?</string>\n    <string name=\"clear_download_archive_desc\">ลบ %1$s ในที่จัดเก็บไฟล์ถาวรหรือไม่?</string>\n    <string name=\"force_ipv4\">บังคับใช้ IPv4</string>\n    <string name=\"force_ipv4_desc\">บังคับให้ทุกการเชื่อมต่อให้ใช้ IPv4</string>\n    <string name=\"every_day\">ทุกวัน</string>\n    <string name=\"every_week\">ทุกสัปดาห์</string>\n    <string name=\"every_month\">ทุก ๆ เดือน</string>\n    <string name=\"search_in_downloads\">ค้นหาในรายการดาวน์โหลด</string>\n    <string name=\"search\">ค้นหา</string>\n    <string name=\"dont_allow\">ไม่อนุญาต</string>\n    <string name=\"task_added\">เพิ่มงานเข้าคิวแล้ว</string>\n    <string name=\"all\">ทั้งหมด</string>\n    <string name=\"all_languages\">ภาษาทั้งหมด</string>\n    <string name=\"prefer_placeholder\">%1$s หากเป็นไปได้</string>\n    <string name=\"best_quality_desc\">ดาวน์โหลดรูปแบบไฟล์ที่ดีที่สุดที่มี</string>\n    <string name=\"download_hint\">แตะปุ่มดาวน์โหลดหรือแชร์ลิงก์วิดีโอมายังแอปนี้เพื่อเริ่มการดาวน์โหลด</string>\n    <string name=\"status_downloaded\">ดาวน์โหลดแล้ว</string>\n    <string name=\"select_multiple_link\">เลือก %1$d จากลิงก์</string>\n    <string name=\"proceed\">ทำต่อ</string>\n    <string name=\"download_queue\">คิวดาวน์โหลด</string>\n    <string name=\"preset\">พรีเซ็ต</string>\n    <string name=\"playlist\">เพลย์ลิสต์</string>\n    <string name=\"edit_preset\">แก้ไขพรีเซต</string>\n    <string name=\"custom_format_selection_desc\">เลือกรูปแบบไฟล์ คำบรรยาย และการปรับแต่งเพิ่มเติม</string>\n    <string name=\"preset_format_selection_desc\">ดาวน์โหลดโดยอัตโนมัติโดยเลือกจากรูปแบบไฟล์ที่ตั้งไว้</string>\n    <string name=\"you_ll_find_your_downloads_here\">การดาวน์โหลดของคุณอยู่ที่นี่</string>\n    <string name=\"trouble_shooting\">การแก้ไขปัญหา</string>\n    <string name=\"issue_tracker\">ตัวติดตามปัญหา</string>\n    <string name=\"trouble_shooting_desc\">แก้ไขข้อผิดพลาดทั่วไปและตรวจสอบดูปัญหาที่ทราบ</string>\n    <string name=\"issue_tracker_hint\">พบข้อผิดพลาด? ก่อนที่จะรายงานปัญหาใหม่ โปรดค้นหาบนตัวติดตามปัญหาของเรา ปัญหาทั่วไปหลายประการได้รับการแก้ไขและบันทึกไว้แล้ว</string>\n    <string name=\"show_navigation_drawer\">แสดงการนำทางแบบลิ้นชัก</string>\n    <string name=\"resume\">ทำต่อ</string>\n    <string name=\"delete\">ลบ</string>\n    <string name=\"media_info\">ข้อมูลสื่อ</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">%d ไฟล์วิดีโอ</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">%d ไฟล์เสียง</item>\n    </plurals>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-tr/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"extract_audio\">Ses olarak kaydet</string>\n    <string name=\"permission_denied\">İzin reddedildi</string>\n    <string name=\"fetch_info_error_msg\">Video bilgileri alınamadı</string>\n    <string name=\"on\">Açık</string>\n    <string name=\"url_empty\">Bağlantı boş olamaz</string>\n    <string name=\"extract_audio_summary\">Video yerine ses olarak indirin ve kaydedin</string>\n    <string name=\"create_thumbnail_summary\">Video küçük resmini dosya olarak kaydet</string>\n    <string name=\"download_settings_desc\">Genel, biçim, özel komut</string>\n    <string name=\"yt_dlp_update_fail\">yt-dlp\\'nin son versiyonu yüklenemedi. Lütfen internete bağlandığınızdan emin olun.</string>\n    <string name=\"settings\">Ayarlar</string>\n    <string name=\"download\">İndir</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp\\'nin en son versiyonu kullanılıyor</string>\n    <string name=\"create_thumbnail\">Küçük resmi kaydet</string>\n    <string name=\"fetching_info\">Video bilgileri alınıyor…</string>\n    <string name=\"download_success_msg\">İndirme tamamlandı</string>\n    <string name=\"download_error_msg\">Dosya indirilemedi</string>\n    <string name=\"download_start_msg\">\\\"%1$s\\\" dosyasını indir</string>\n    <string name=\"general_settings\">Genel</string>\n    <string name=\"language\">Arayüz Dili</string>\n    <string name=\"language_settings\">Arayüz dilini ayarlayın</string>\n    <string name=\"task_running\">Mevcut bir indirme görevi zaten çalışıyor</string>\n    <string name=\"paste_msg\">URL\\'yi yapıştır</string>\n    <string name=\"paste_fail_msg\">Panodaki URL eşleştirilemedi</string>\n    <string name=\"ytdlp_version\">Yt-dlp sürümü</string>\n    <string name=\"delete_info\">Kaldırılsın mı\\?</string>\n    <string name=\"open_url\">Bağlantıyı aç</string>\n    <string name=\"back\">Geri</string>\n    <string name=\"release\">Son sürüm</string>\n    <string name=\"checked\">Kontrol edildi</string>\n    <string name=\"custom_command_desc\">yt-dlp komutunu özel şablonla çalıştır</string>\n    <string name=\"print_details_desc\">İndirilirken detaylı mesajlar yazdır</string>\n    <string name=\"display\">Arayüz</string>\n    <string name=\"display_settings\">Koyu tema, dinamik renk, diller</string>\n    <string name=\"dark_theme\">Koyu tema</string>\n    <string name=\"settings_before_download\">İndirmeden önce düzenleyin</string>\n    <string name=\"settings_before_download_desc\">İndirmeden önce ayarlama tercihleri</string>\n    <string name=\"settings_before_download_text\">Bu indirmeyi ayarla</string>\n    <string name=\"error_copied\">Hata raporu panoya kopyalandı</string>\n    <string name=\"thumbnail\">Küçük resim</string>\n    <string name=\"not_convert\">Orijinal</string>\n    <string name=\"format\">Biçim</string>\n    <string name=\"edit_template_desc\">Çıktı yolu ve URL uygulama tarafından eklenecektir.</string>\n    <string name=\"convert_to\">%1$s biçimine dönüştür</string>\n    <string name=\"preferred_format_desc\">Birden fazla sağlandığında tercih edilen biçim</string>\n    <string name=\"convert_audio\">Dönüştür</string>\n    <string name=\"start_download\">İndir</string>\n    <string name=\"user_guide\">Kullanıcı rehberi</string>\n    <string name=\"open_settings\">Ayarları aç</string>\n    <string name=\"paste_desc\">Panonuzdan video bağlantısını almak için \\\"Yapıştır\\\"a tıklayın.</string>\n    <string name=\"download_desc\">Ardından düzenlemeleri yaptıktan sonra \\\"İndir\\\"e tıklayın.</string>\n    <string name=\"download_history_desc\">Videolar ve ses dosyaları dahil uygulama içi indirmeleri kontrol edin ve yönetin.</string>\n    <string name=\"execute_command_notification\">Özel komutlar çalıştırılıyor…</string>\n    <string name=\"battery_settings_desc\">Arka planda indirmek için lütfen bu uygulamanın pil kullanımını sistem ayarlarında \\\"Kısıtlama yok\\\" olarak ayarlayın.</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD videolarının daha fazla bölümünü paralel olarak indirin</string>\n    <string name=\"options\">Seçenekler</string>\n    <string name=\"concurrent_download_num\">%d sanal çekirdek DASH/HLS yerel videosunu aynı anda indirmek için kullanılacaktır.</string>\n    <string name=\"share_fail_msg\">Paylaşılan içerikten URL eşleştirilemiyor</string>\n    <string name=\"share_success_msg\">Paylaşılan içerikten video bağlantısı okunuyor…</string>\n    <string name=\"fetching_playlist_info\">Oynatma listesi bilgisi alınıyor…</string>\n    <string name=\"download_range_selection\">Oynatma listesi seçimi</string>\n    <string name=\"from\">Başlangıç</string>\n    <string name=\"download_directory_desc\">Videoların ve ses dosyalarının nerede saklanacağını seçin</string>\n    <string name=\"permission_issue\">Depolama izni sorunu</string>\n    <string name=\"battery_configuration\">Pil yapılandırması</string>\n    <string name=\"service_title\">Seal indiriyor…</string>\n    <string name=\"unknown_error\">Bilinmeyen hata</string>\n    <string name=\"translate_desc\">Hosted Weblate\\'de bu uygulamanın çevrilmesine yardımcı olun</string>\n    <string name=\"video_directory\">Video klasörü</string>\n    <string name=\"permission_issue_desc\">İndirilenler/ ve Belgeler/ dışındaki dizinler desteklenmez</string>\n    <string name=\"subdirectory\">Alt dizine kaydet</string>\n    <string name=\"off\">Kapalı</string>\n    <string name=\"convert_audio_format_desc\">Ses dosyalarının yeniden kodlanması ses kalitesinde kayba ve dosya boyutunda artışa neden olacaktır.</string>\n    <string name=\"video_quality\">Video kalitesi</string>\n    <string name=\"not_specified\">Belirtilmemiş (varsayılan)</string>\n    <string name=\"dismiss\">İptal et</string>\n    <string name=\"delete_info_msg\">\\\"%1$s\\\" indirme geçmişinizden tamamen kaldırılsın mı?</string>\n    <string name=\"confirm\">Onayla</string>\n    <string name=\"about\">Hakkında</string>\n    <string name=\"about_page\">Sürüm, geri bildirim, otomatik güncelleme</string>\n    <string name=\"version\">Sürüm</string>\n    <string name=\"readme_desc\">GitHub deposunu ve README dosyasını kontrol edin</string>\n    <string name=\"video\">Video</string>\n    <string name=\"downloads_history\">İndirilenler</string>\n    <string name=\"ytdlp_update\">En son yt-dlp sürümünü indirmek için tıklayın</string>\n    <string name=\"audio\">Ses</string>\n    <string name=\"remove\">Kaldır</string>\n    <string name=\"channel_name\">İndir</string>\n    <string name=\"link_copied\">Bağlantı panoya kopyalandı</string>\n    <string name=\"delete_file\">Dosyayı sil</string>\n    <string name=\"credits_desc\">Emeği geçenler ve özgür yazılımlar</string>\n    <string name=\"print_details\">Detaylı çıktı</string>\n    <string name=\"convert_audio_format\">Ses biçimini dönüştür</string>\n    <string name=\"release_desc\">Değişim kaydına ve yeni sürümlere bakın</string>\n    <string name=\"custom_command\">Özel komut</string>\n    <string name=\"edit\">Düzenle</string>\n    <string name=\"advanced_settings\">Gelişmiş</string>\n    <string name=\"follow_system\">Sistem</string>\n    <string name=\"cancel\">İptal et</string>\n    <string name=\"download_playlist\">Oynatma listesini indir</string>\n    <string name=\"credits\">Emeği geçenler</string>\n    <string name=\"custom_command_template\">Komut şablonu</string>\n    <string name=\"start_execute\">Komut çalıştırılıyor</string>\n    <string name=\"paste\">Yapıştır</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp kullanım örnekleri</string>\n    <string name=\"download_finish_notification\">İndirme tamamlandı. Açmak için dokunun.</string>\n    <string name=\"defaults\">Varsayılan</string>\n    <string name=\"download_playlist_desc\">Bir oynatma listesinden birden fazla video indir</string>\n    <string name=\"concurrent_download\">Çoklu indirme</string>\n    <string name=\"additional_settings\">Ek ayarlar</string>\n    <string name=\"download_notification\">İndirme bildirimi</string>\n    <string name=\"download_notification_desc\">İndirilen dosyaları ve ilerlemeyi bildir</string>\n    <string name=\"best_quality\">En iyi kalite</string>\n    <string name=\"video_format_preference\">Tercih edilen video biçimi</string>\n    <string name=\"channel_description\">İndirilen dosyaları ve ilerlemeyi bildir</string>\n    <string name=\"video_url\">Video bağlantısı</string>\n    <string name=\"invalid_index_range\">Geçersiz dizin aralığı</string>\n    <string name=\"show_more_actions\">Daha fazla işlem göster</string>\n    <string name=\"video_quality_desc\">Birden fazla olduğunda video kalitesini sınırlayın</string>\n    <string name=\"video_format\">Video biçimi</string>\n    <string name=\"playlist_indicator_text\">Oynatma listesi indiriliyor (%1$d/%2$d)…</string>\n    <string name=\"close\">Kapat</string>\n    <string name=\"check_download_settings_desc\">İndirme ayarlarına bir göz atın ve kullanmadan önce yt-dlp\\'nin en son sürümüne sahip olduğunuzdan emin olun.</string>\n    <string name=\"to\">Sonuç</string>\n    <string name=\"download_directory\">İndirme dizini</string>\n    <string name=\"subdirectory_desc\">Dosyaları ilgili alanlar olarak adlandırılan klasörlere kaydedin</string>\n    <string name=\"close_never_show_again\">Tekrar gösterme</string>\n    <string name=\"audio_directory\">Ses dosyası</string>\n    <string name=\"battery_configuration_desc\">Bu uygulamanın arka planda indirilmesi için pil optimizasyonunu yoksay</string>\n    <string name=\"download_range_desc\">Oynatma listesinden indirilecek video aralığını belirtin \\\"%3$s\\\" (%1$d ile %2$d arası).</string>\n    <string name=\"translate\">Çeviri</string>\n    <string name=\"prefix\">Önek</string>\n    <string name=\"embed_subtitles\">Alt yazıları göm</string>\n    <string name=\"new_template\">Yeni şablon</string>\n    <string name=\"template_label\">Etiket</string>\n    <string name=\"remove_template\">Kaldırılsın mı\\?</string>\n    <string name=\"remove_template_desc\">\\\"%1$s\\\" komut şablonundan temelli kaldırılsın mı\\?</string>\n    <string name=\"template_selection\">Şablon seçimi</string>\n    <string name=\"custom_command_template_desc\">Komut şablonlarını düzenle ve yönet</string>\n    <string name=\"downloading_indicator_text\">İndirme devam ediyor…</string>\n    <string name=\"open_file\">Dosyayı aç</string>\n    <string name=\"restart\">Yeniden başlat</string>\n    <string name=\"status_enqueued\">Sıraya alındı</string>\n    <string name=\"status_completed\">Tamamlandı</string>\n    <string name=\"status_fetching_video_info\">Bilgi alınıyor</string>\n    <string name=\"status_error\">Hata</string>\n    <string name=\"copy_link\">Bağlantıyı kopyala</string>\n    <string name=\"copy_error_report\">Raporu kopyala</string>\n    <string name=\"status_canceled\">İptal edildi</string>\n    <string name=\"status_downloading\">İndiriliyor</string>\n    <string name=\"task_canceled\">İndirme işlemi iptal edildi</string>\n    <string name=\"github_issue\">GitHub sorunu</string>\n    <string name=\"info_copied\">Bilgi panoya kopyalandı</string>\n    <string name=\"check_for_updates\">Güncellemeleri denetle</string>\n    <string name=\"check_for_updates_desc\">GitHub\\'da en son sürümü otomatik olarak kontrol et</string>\n    <string name=\"app_up_to_date\">Mevcut sürüm günceldir</string>\n    <string name=\"update\">Güncelle</string>\n    <string name=\"aria2_desc\">Harici indirici olarak aria2c kullanın</string>\n    <string name=\"cookies_desc\">İndirmeler için Netscape biçiminde çerezleri kullanın</string>\n    <string name=\"clear_temp_files_count\">Silinen %1$d geçici dosya</string>\n    <string name=\"clear_temp_files_desc\">Tüm geçici dosyaları dahili dizinden silin</string>\n    <string name=\"clear_temp_files\">Geçici dosyaları temizleyin</string>\n    <string name=\"clear_temp_files_info\">İptal edilen indirme işlemlerine devam etmek için geçici dosyalar kullanılabilir. Bu dosyaların tümünü sildiğinizden emin misiniz?\n\\n\n\\n Bu dosyalara %1$s üzerinden erişebilirsiniz</string>\n    <string name=\"video_resolution\">Video çözünürlüğü</string>\n    <string name=\"video_file_size\">Video dosyası boyutu</string>\n    <string name=\"embed_subtitles_desc\">Varsa alt yazıları videolara gömün</string>\n    <string name=\"template_exported\">Dışa aktarılan %1$d şablon(lar)ı</string>\n    <string name=\"template_imported\">İçe aktarılan %1$d şablon(lar)ı</string>\n    <string name=\"download_task_count\">%1$d İndirme görevleri</string>\n    <string name=\"delete_multiple_items_msg\">%1$d öge indirme geçmişinizden tamamen kaldırılsın mı\\?</string>\n    <string name=\"sponsorblock_categories_desc\">Video dosyasında kaldırılacak veya işaretlenecek SponsorBlock kategorilerini belirtin</string>\n    <string name=\"sponsorblock_desc\">SponsorBlock API ile videolardaki bölümleri kaldırın veya işaretleyin</string>\n    <string name=\"github_issue_desc\">Hata raporu veya özellik isteği için bir konu oluşturun</string>\n    <string name=\"export_to_clipboard\">Panoya aktar</string>\n    <string name=\"import_from_clipboard\">Panodan aktar</string>\n    <string name=\"recently_added\">Son Eklenenler</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock kategorileri</string>\n    <string name=\"multiselect_item_count\">%1$d video, %2$d ses dosyası</string>\n    <string name=\"app_update_failed\">En son sürüme güncellenemedi</string>\n    <string name=\"multiselect_mode\">Çoklu seçim modu</string>\n    <string name=\"private_mode\">Gizli</string>\n    <string name=\"dynamic_color\">Dinamik renk</string>\n    <string name=\"dynamic_color_desc\">Uygulama tema rengini duvar kağıtlarından uygula</string>\n    <string name=\"private_mode_desc\">İndirme geçmişini devre dışı bırak</string>\n    <string name=\"download_disabled_with_cellular\">Hücresel ağ ile indirme, ayarlarınıza göre devre dışı bırakıldı</string>\n    <string name=\"private_directory\">Özel dizin</string>\n    <string name=\"high_contrast\">Yüksek kontrastlı koyu tema</string>\n    <string name=\"invalid_input\">Geçersiz giriş</string>\n    <string name=\"lowest_quality\">En düşük kalite</string>\n    <string name=\"unavailable\">Kullanım dışı</string>\n    <string name=\"format_settings_desc\">Dosya biçimi, video kalitesi, alt yazılar</string>\n    <string name=\"general_settings_desc\">Yt-dlp sürümü, bildirim, çalma listesi</string>\n    <string name=\"network_settings_desc\">Hız sınırı, indirici, çerezler</string>\n    <string name=\"disable_preview\">Önizlemeyi devre dışı bırak</string>\n    <string name=\"disable_preview_desc\">İndirme sırasında küçük resimler görüntülenmiyor</string>\n    <string name=\"privacy\">Gizlilik</string>\n    <string name=\"use_custom_command\">Özel komut kullan</string>\n    <string name=\"private_directory_desc\">İndirilenleri gizli dizinde sakla</string>\n    <string name=\"crop_artwork\">Resmi kırp</string>\n    <string name=\"download_with_cellular\">Hücresel kullanarak indir</string>\n    <string name=\"download_with_cellular_desc\">Tarifeli ağlara bağlanıldığında medya indirmelerine izin ver</string>\n    <string name=\"file_unavailable\">Bu dosya artık mevcut değil</string>\n    <string name=\"max_rate\">Maksimum hız</string>\n    <string name=\"network\">Ağ</string>\n    <string name=\"rate_limit_desc\">Azami indirme hızını sınırla</string>\n    <string name=\"rate_limit\">Hız sınırı</string>\n    <string name=\"download_selection_desc\">\\\"%1$s\\\" oynatma listesinden indirilecek videoları seç</string>\n    <string name=\"select_all\">Hepsini seç</string>\n    <string name=\"selected_item_count\">%1$d seçildi</string>\n    <string name=\"crop_artwork_desc\">Gömülü resmi kareye kırp</string>\n    <string name=\"format_selection_desc\">İndirmeye başlamadan önce indirilecek biçimi seçin</string>\n    <string name=\"video_only\">Video (ses yok)</string>\n    <string name=\"suggested\">Önerilen</string>\n    <string name=\"format_selection\">Biçim seçimi</string>\n    <string name=\"generate_new_cookies\">Yeni çerezler oluştur</string>\n    <string name=\"matrix_space\">Matrix alanı</string>\n    <string name=\"cookies\">Çerezler</string>\n    <string name=\"use_cookies\">Çerezleri kullan</string>\n    <string name=\"remove_cookie_profile_desc\">\\\"%1$s\\\" için bu girdi kaldırılsın mı? Bu site için saklanan çerezlerin silinmeyeceğini lütfen unutmayın.</string>\n    <string name=\"custom_command_enabled_hint\">Bazı seçenekler özel komut kullanırken kullanılamaz</string>\n    <string name=\"how_does_it_work\">Nasıl çalışıyor\\?</string>\n    <string name=\"telegram_channel\">Telegram kanalı</string>\n    <string name=\"cookies_usage_msg\">Bazı sitelerden indirmek için hesap doğrulaması gerekir. \\\"Yeni çerezler üret\\\"e tıkla, sitenin URL\\'sini gir ve sonra tarayıcı sayfasından hesabına gir, uygulama senin için bir tane oluşturacak.</string>\n    <string name=\"audio_format_preference\">Tercih edilen ses kalitesi</string>\n    <string name=\"import_from_preferences\">İçe aktar</string>\n    <string name=\"title\">Başlık</string>\n    <string name=\"rename\">Yeniden adlandır</string>\n    <string name=\"second\">saniye</string>\n    <string name=\"no_downloaded_media\">İndirilmiş medya yok</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Deneysel özelliği etkinleştir\\?</string>\n    <string name=\"audio_format\">Ses biçimi</string>\n    <string name=\"clip_video_desc\">Biçim seçim sayfasında video klipler oluşturun</string>\n    <string name=\"share\">Paylaş</string>\n    <string name=\"stable_channel\">Stabil</string>\n    <string name=\"pre_release_channel\">Önizleme</string>\n    <string name=\"logs\">Günlük</string>\n    <string name=\"auto_subtitle_desc\">Otomatik oluşturulmuş alt yazıları indir</string>\n    <string name=\"subtitle_language\">Alt yazı dilleri</string>\n    <string name=\"edit_shortcuts_desc\">Komut şablonları oluşturmak için kullanılabilecek özel kısayolları düzenleyin.</string>\n    <string name=\"subtitle_sponsorblock\">SponsorBlock bölümleri kaldırılırken alt yazılar yanlış olabilir.</string>\n    <string name=\"unlimited\">Limitsiz</string>\n    <string name=\"update_channel_desc\">Yeni özellikleri ve değişiklikleri önizlemek için yayın öncesi yapıları yükleyin.\n\\n\n\\nBu sürümlerde bazı istikrarsızlıklar olacaktır, bu nedenle herhangi bir sorunla karşılaşırsanız, uygulamayı gelecek için iyileştirmemize yardımcı olacak geri bildirimde bulunmaktan çekinmeyin.</string>\n    <string name=\"update_channel\">Güncelleme kanalı</string>\n    <string name=\"auto_update\">Otomatik güncelleme</string>\n    <string name=\"format_sorting_desc\">yt-dlp\\'nin -S seçeneğiyle biçimleri sırala</string>\n    <string name=\"clip_video_dialog_msg\">Bu özelliği kullanan indirmeler, videonun seçilen bölümlerini indirmesi için FFmpeg\\'e yetkilendirilecektir, bu özellik henüz deneyseldir ve kesme tam olarak doğru olmayacaktır, tüm biçimler bu özelliği desteklemez ve daha düşük indirme hızlarıyla karşılaşabilirsiniz.</string>\n    <string name=\"minute\">dakika</string>\n    <string name=\"clear_all_cookies\">Tüm çerezleri temizle</string>\n    <string name=\"abs_hint\">Çoğu video akış platformu, ses ve videoyu ayrı sunar, yalnızca ses biçimini yalnızca video biçimiyle tek bir videoda seçebilir ve birleştirebilirsiniz.</string>\n    <string name=\"apply\">Uygula</string>\n    <string name=\"discard\">At</string>\n    <string name=\"clip_video\">Video kliple</string>\n    <string name=\"clip_start\">Başlat</string>\n    <string name=\"clip_end\">Bitir</string>\n    <string name=\"sdcard_directory\">SD kart dosyası</string>\n    <string name=\"auto_subtitle\">Otomatik alt yazılar</string>\n    <string name=\"title_activity_share\">Hızlı indir</string>\n    <string name=\"video_title_sample_text\">Video başlığı örnek metni</string>\n    <string name=\"video_creator_sample_text\">Video yaratıcı örnek metni</string>\n    <string name=\"subtitle\">Alt başlık</string>\n    <string name=\"download_subtitles\">Alt yazıları indir</string>\n    <string name=\"subtitle_desc\">Diller, gömülü alt yazılar, otomatik alt yazılar</string>\n    <string name=\"copy_log\">Günlüğü kopyala</string>\n    <string name=\"clear\">Temizle</string>\n    <string name=\"edit_shortcuts\">Kısayolları özelleştir</string>\n    <string name=\"add\">Ekle</string>\n    <string name=\"shortcuts\">Kısayollar</string>\n    <string name=\"running_tasks\">Çalışan görevler</string>\n    <string name=\"show_logs\">Günlüğü göster</string>\n    <string name=\"embed_subtitles_mkv_msg\">Alt yazıları gömmek için videolar mkv konteynerine yeniden düzenlenecektir. Alt yazılı videoları izlemek için VLC Media Player\\'ı veya diğer uyumlu uygulamaları kullanabilirsiniz.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"enable_auto_update\">Otomatik güncellemeyi etkinleştir</string>\n    <string name=\"lowest_bitrate\">En az bit hızı</string>\n    <string name=\"audio_quality\">Ses kalitesi</string>\n    <string name=\"audio_quality_desc\">Birden fazla nitelik mevcut olduğunda ses bit hızını sınırlayın</string>\n    <string name=\"format_sorting\">Biçim sıralaması</string>\n    <string name=\"clear_all_cookies_desc\">Uygulamada saklanan tüm çerezler kalıcı olarak silinsin mi\\?</string>\n    <string name=\"temporary_directory_desc\">Geçici dosyaları dahili dizinde saklayın</string>\n    <string name=\"sponsor\">Sponsor</string>\n    <string name=\"sponsor_desc\">GitHub\\'da sponsor olarak bu uygulamayı destekleyin</string>\n    <string name=\"sponsor_msg\">Seal her zaman ücretsiz ve herkes için açık kaynak olacaktır. Beğendiyseniz, lütfen GitHub\\'da bana sponsor olmayı düşünün!</string>\n    <string name=\"feedback\">Geri bildirim</string>\n    <string name=\"sponsors\">Sponsorlar</string>\n    <string name=\"msg_from_developer\">Geliştiriciden Mesaj</string>\n    <string name=\"sponsor_msg2\">Çok teşekkür ederim!</string>\n    <string name=\"okay\">Tamam.</string>\n    <string name=\"auto_update_disabled_msg\">%1$s yapıları için otomatik güncelleme mevcut değildir. Cihazınızda %1$s yüklü değilse veya Seal\\'de gelecek yeni özellikleri önizlemek istiyorsanız, lütfen %2$s\\'i düşünün.</string>\n    <string name=\"switch_to_github_builds\">GitHub derlemelerine geçiş</string>\n    <string name=\"got_it\">Anladım</string>\n    <string name=\"feature_unavailable\">Özellik mevcut değil</string>\n    <string name=\"convert_subtitle\">Alt yazıları dönüştür</string>\n    <string name=\"convert_subtitle_desc\">Alt yazıları başka bir biçime dönüştürün</string>\n    <string name=\"split_video\">Videoyu böl</string>\n    <string name=\"split_video_msg\">Video %1$d bölümlere ayrılacak</string>\n    <string name=\"unknown_error_title\">Oops! Bir şeyler yanlış gitti</string>\n    <string name=\"copy_and_exit\">Kopyala ve çık</string>\n    <string name=\"no_custom_command_tasks\">Özel komut görevi yok</string>\n    <string name=\"download_video_desc\">Videoları URL\\'den indirin</string>\n    <string name=\"expand\">Genişlet</string>\n    <string name=\"new_task\">Yeni indirme görevi</string>\n    <string name=\"start\">Başla</string>\n    <string name=\"edit_template\">\\\"%1$s\\\"i düzenle</string>\n    <string name=\"remove_multiple_templates_msg\">%1$s komut şablonlarından tamamen kaldırılsın mı\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d öge</item>\n        <item quantity=\"other\">%d ögeler</item>\n    </plurals>\n    <string name=\"refresh_cookies_desc\">Yeni çerezler oluşturmak amacıyla web sayfasını açmak için dokunun:</string>\n    <string name=\"ytdlp_update_action\">yt-dlp\\'yi güncelleyin</string>\n    <string name=\"enable_notifications\">Bildirimler etkinleştirilsin mi\\?</string>\n    <string name=\"set_directory_desc\">Dizini ayarlamak için dokunun</string>\n    <string name=\"ua_header\">Kullanıcı Aracısı başlığı</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"proxy_desc\">İnternet bağlantıları için proxy kullanın</string>\n    <string name=\"legacy\">Eski</string>\n    <string name=\"quality\">Kalite</string>\n    <string name=\"enable_notifications_desc\">Uygulamanın, indirme durumu ve ilerleme durumu hakkında bildirim gönderebilmesi için izninize ihtiyacı var.</string>\n    <string name=\"custom_command_directory\">Özel komut dizini</string>\n    <string name=\"disable\">Devre dışı bırak</string>\n    <string name=\"disabled\">Devre dışı bırakıldı</string>\n    <string name=\"folder_picker\">Klasör seçici</string>\n    <string name=\"custom_command_directory_desc\">Özel komutları kullanırken çıktı dizinini belirtin</string>\n    <string name=\"prefer_compatibility_desc\">Diğer uygulamalarla paylaşmak için MP4(H.264) biçimlerini tercih edin</string>\n    <string name=\"prefer_quality_desc\">Uyumlu uygulamalarda izlemek için AV1, VP9 veya H.265 biçimlerini tercih edin</string>\n    <string name=\"download_type\">İndirme türü</string>\n    <string name=\"auto\">Otomatik</string>\n    <string name=\"commands\">Komutlar</string>\n    <string name=\"format_preference\">Biçim tercihi</string>\n    <string name=\"learn_more\">Daha fazla bilgi edin</string>\n    <string name=\"unknown\">Bilinmeyen</string>\n    <string name=\"export_to_file\">Dosyaya aktar</string>\n    <string name=\"custom\">Özel</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp, videoları indirmek için güçlü bir komut satırı aracıdır. Seal, sezgisel bir GUI, ortak komutlar için ön ayarlar ve diğer ek özellikler sağlayarak yt-dlp\\'nin kullanımını kolaylaştırır.\n\\n\n\\n yt-dlp\\'nin gelişmiş kullanımı için Seal, tıpkı bir terminalde olduğu gibi özel komut şablonlarını doğrudan oluşturmanıza, kaydetmenize ve yürütmenize olanak tanır.\n\\n\n\\n Özel komutlar kullanıldığında GUI seçeneklerinin ve özelliklerinin çoğu devre dışı bırakılır.</string>\n    <string name=\"clear_download_archive\">İndirme arşivi temizlensin mi\\?</string>\n    <string name=\"clear_download_archive_desc\">Arşiv dosyasındaki %1$s tamamen kaldırılsın mı\\?</string>\n    <string name=\"presets\">Ön ayarlar</string>\n    <string name=\"output_template\">Çıktı şablonu</string>\n    <string name=\"output_template_desc\">Çıktı dosyası adları için şablonu belirtin</string>\n    <string name=\"download_archive_desc\">Tekrarlanan indirmeleri önlemek için indirilen video kimliklerini bir arşive kaydedin</string>\n    <string name=\"download_archive\">Arşivi indir</string>\n    <string name=\"embed_metadata\">Meta verileri yerleştir</string>\n    <string name=\"embed_metadata_desc\">Meta verileri ve video küçük resmini ses dosyasına gömün</string>\n    <string name=\"required\">Gerekli</string>\n    <string name=\"show_all_items\">%1$d ögenin tümünü göster</string>\n    <string name=\"save\">Kaydet</string>\n    <string name=\"use_format_sorting\">Biçim sıralamasını kullan</string>\n    <string name=\"restrict_filenames_desc\">Uyumluluğu sağlamak için dosya adlarını belirli karakterlerle sınırlandırın</string>\n    <string name=\"restrict_filenames\">Dosya adlarını kısıtla</string>\n    <string name=\"edit_file\">Dosya düzenle</string>\n    <string name=\"subdirectory_hint\">İndirdikleriniz şu şekilde kaydedilecek:</string>\n    <string name=\"keep_subtitle_files\">Alt yazı dosyalarını tut</string>\n    <string name=\"website\">Web sitesi</string>\n    <string name=\"playlist_title\">Oynatma listesi başlığı</string>\n    <string name=\"system_settings\">Sistem ayarları</string>\n    <string name=\"force_ipv4\">IPv4\\'ü zorla</string>\n    <string name=\"force_ipv4_desc\">Tüm bağlantıları IPv4 üzerinden yapın</string>\n    <string name=\"allow_once\">Bir kez izin ver</string>\n    <string name=\"allow_always\">Her zaman izin ver</string>\n    <string name=\"dont_allow\">İzin verme</string>\n    <string name=\"download_with_cellular_request\">Mobil veri üzerinden indirmeye izin verilsin mi?</string>\n    <string name=\"merge_audiostream\">Çoklu ses akışlarını birleştir</string>\n    <string name=\"merge_audiostream_desc\">Çoklu ses akışlarının tek bir dosyada birleştirilmesine izin verin</string>\n    <string name=\"search_in_downloads\">İndirilenlerde ara</string>\n    <string name=\"search\">Ara</string>\n    <string name=\"auto_translated_subtitles\">Otomatik çevrilen alt yazılar</string>\n    <string name=\"auto_translated_subtitles_msg\">Tüm diller için otomatik çevrilen alt yazılar indirmelerde kullanılabilir olacaktır. Bu alt yazılar hatalı ve anlaşılması zor olabilir.</string>\n    <string name=\"remember_for_next_download\">Bir sonraki indirme için hatırla</string>\n    <string name=\"look_and_feel\">Görünüm</string>\n    <string name=\"use_previous_selection\">Önceki seçimi kullan</string>\n    <string name=\"none\">Yok</string>\n    <string name=\"subtitle_language_desc\">Otomatik biçim seçiminde indirilecek alt yazıların dili, virgülle ayrılmış olarak.</string>\n    <string name=\"reset\">Sıfırla</string>\n    <string name=\"no_thanks\">Hayır, teşekkürler</string>\n    <string name=\"search_in_subtitles\">Alt yazılarda ara</string>\n    <string name=\"update_language_msg\">Şu diller gelecekteki indirmeler için tercihlerinize eklenecek:</string>\n    <string name=\"update_subtitle_languages\">Alt yazı dilleri güncellensin mi?</string>\n    <string name=\"import_backup\">İçe aktar</string>\n    <string name=\"full_backup\">Tam yedekleme</string>\n    <string name=\"backup_type\">Yedekleme türü</string>\n    <string name=\"export_to\">Şuraya aktar</string>\n    <string name=\"file\">Dosya</string>\n    <string name=\"export_download_history\">İndirme geçmişi dışa aktarılsın mı?</string>\n    <string name=\"import_download_history\">İndirme geçmişi içe aktarılsın mı?</string>\n    <string name=\"export_download_history_msg\">İndirme geçmişinden %1$s dışa aktarılıyor. İndirilen dosyalar ve tercihler yedeklenmeyecek.</string>\n    <string name=\"import_download_history_msg\">İndirilen dosyalar içe aktarılmayacaktır. Onları elle tekrar indirmeniz gerekecek</string>\n    <string name=\"export_backup\">Dışarı aktar</string>\n    <string name=\"clipboard\">Pano</string>\n    <string name=\"import_from\">Şuradan içe aktar</string>\n    <string name=\"download_history\">İndirme geçmişi</string>\n    <string name=\"interface_and_interaction\">Arayüz</string>\n    <string name=\"download_history_imported\">İndirme geçmişine %1$s aktarıldı</string>\n    <string name=\"redownload\">Yeniden indir</string>\n    <string name=\"download_archive_error\">Video indirildi. Bu beklenen bir davranış değilse, lütfen indirme arşivinizi gözden geçirin.</string>\n    <string name=\"remux_container_mkv\">Yeniden düzenlenen video konteyneri</string>\n    <string name=\"remux_container_mkv_desc\">Daha iyi uyumluluk için videoları MKV konteynerine yeniden düzenleyin</string>\n    <string name=\"cookies_in_database\">%1$d çerez (%2$d web sitesinden)</string>\n    <string name=\"every_day\">Her gün</string>\n    <string name=\"every_week\">Her hafta</string>\n    <string name=\"every_month\">Her ay</string>\n    <string name=\"best_quality_desc\">Kullanılabilir en iyi biçimi indir</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d video</item>\n        <item quantity=\"other\">%d video</item>\n    </plurals>\n    <string name=\"playlist\">Oynatma listesi</string>\n    <string name=\"preset\">Ön ayar</string>\n    <string name=\"prefer_placeholder\">%1$s tercih et</string>\n    <string name=\"preset_format_selection_desc\">Biçim tercihlerinizi kullanarak otomatik olarak indirin</string>\n    <string name=\"edit_preset\">Ön ayarı düzenle</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d ses</item>\n        <item quantity=\"other\">%d ses</item>\n    </plurals>\n    <string name=\"all_languages\">Tüm diller</string>\n    <string name=\"proceed\">Devam et</string>\n    <string name=\"custom_format_selection_desc\">Biçimler, alt yazılar arasından seçim yapın ve daha fazlasını özelleştirin</string>\n    <string name=\"task_added\">Görev kuyruğa eklendi</string>\n    <string name=\"download_hint\">İndirmeyi başlatmak için indirme düğmesine dokunun veya bu uygulamaya bir video bağlantısı paylaşın</string>\n    <string name=\"you_ll_find_your_downloads_here\">İndirmelerinizi burada bulabilirsiniz</string>\n    <string name=\"status_downloaded\">İndirildi</string>\n    <string name=\"all\">Tümü</string>\n    <string name=\"download_queue\">İndirme kuyruğu</string>\n    <string name=\"select_multiple_link\">%1$d bağlantıdan seç</string>\n    <string name=\"show_navigation_drawer\">Gezinme çekmecesini göster</string>\n    <string name=\"resume\">Devam et</string>\n    <string name=\"delete\">Sil</string>\n    <string name=\"media_info\">Medya bilgileri</string>\n    <string name=\"trouble_shooting_desc\">Yaygın hataları düzeltin ve bilinen sorunları arayın</string>\n    <string name=\"trouble_shooting\">Sorun giderme</string>\n    <string name=\"issue_tracker_hint\">Bir hatayla mı karşılaştınız? Yeni bir sorun bildirmeden önce lütfen sorun izleyicimizde arama yapın. Birçok yaygın sorun zaten ele alınmış ve orada belgelenmiştir.</string>\n    <string name=\"issue_tracker\">Sorun izleyici</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-uk/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Тека для вiдео</string>\n    <string name=\"extract_audio\">Зберігати як аудiо</string>\n    <string name=\"create_thumbnail\">Зберігати обкладинку</string>\n    <string name=\"settings\">Налаштування</string>\n    <string name=\"download_settings_desc\">Загальні налаштування, формат, власна команда</string>\n    <string name=\"download\">Завантаження</string>\n    <string name=\"url_empty\">Посилання не може бути порожнім</string>\n    <string name=\"extract_audio_summary\">Завантажувати та зберігати аудiо, а не вiдео</string>\n    <string name=\"create_thumbnail_summary\">Зберігати обкладинку відео як файл</string>\n    <string name=\"yt_dlp_up_to_date\">Використовується остання версія yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Не вдалося встановити останню версію yt-dlp. Переконайтеся, що ви підключені до інтернету.</string>\n    <string name=\"fetching_info\">Отримання інформації про відео…</string>\n    <string name=\"permission_denied\">Недостатньо повноважень</string>\n    <string name=\"download_success_msg\">Завантаження завершено</string>\n    <string name=\"download_error_msg\">Не вдалося завантажити файл</string>\n    <string name=\"download_start_msg\">Завантаження \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Не вдалося отримати інформацію про відео</string>\n    <string name=\"general_settings\">Загальні</string>\n    <string name=\"language\">Мова застосунку</string>\n    <string name=\"language_settings\">Встановіть мову відображення</string>\n    <string name=\"task_running\">Завдання на завантаження вже запущено</string>\n    <string name=\"paste_msg\">Вставити посилання</string>\n    <string name=\"paste_fail_msg\">Не вдалося знайти посилання в буфері обміну</string>\n    <string name=\"ytdlp_version\">Версiя yt-dlp</string>\n    <string name=\"ytdlp_update\">Натисніть, щоб встановити останню версію yt-dlp</string>\n    <string name=\"delete_info\">Вилучити\\?</string>\n    <string name=\"delete_info_msg\">Вилучити \\\"%1$s\\\" з вашої історії завантажень\\?</string>\n    <string name=\"confirm\">Підтвердити</string>\n    <string name=\"dismiss\">Скасувати</string>\n    <string name=\"downloads_history\">Завантаження</string>\n    <string name=\"audio\">Аудiо</string>\n    <string name=\"link_copied\">Посилання скопiйовано до буфера обмiну</string>\n    <string name=\"open_url\">Відкрити посилання</string>\n    <string name=\"remove\">Вилучити</string>\n    <string name=\"delete_file\">Видалити файл</string>\n    <string name=\"about\">Про застосунок</string>\n    <string name=\"about_page\">Версія, зворотний зв\\'язок та оновлення</string>\n    <string name=\"back\">Назад</string>\n    <string name=\"version\">Версiя</string>\n    <string name=\"release_desc\">Перегляньте історію змін та нові версії</string>\n    <string name=\"release\">Остання версія</string>\n    <string name=\"readme_desc\">Перевірте репозиторій на GitHub та README</string>\n    <string name=\"video\">Вiдео</string>\n    <string name=\"checked\">Перевірено</string>\n    <string name=\"credits\">Подяки</string>\n    <string name=\"credits_desc\">Подяки та вільне програмне забезпечення</string>\n    <string name=\"custom_command\">Власна команда</string>\n    <string name=\"custom_command_desc\">Запустіть yt-dlp зі своїм шаблоном</string>\n    <string name=\"custom_command_template\">Шаблон команди</string>\n    <string name=\"edit\">Редагувати</string>\n    <string name=\"start_execute\">Запустити команду</string>\n    <string name=\"advanced_settings\">Розширені</string>\n    <string name=\"print_details\">Детальний вивід</string>\n    <string name=\"print_details_desc\">Виводити докладні повідомлення під час завантаження</string>\n    <string name=\"display\">Зовнішній вигляд</string>\n    <string name=\"display_settings\">Темна тема, динамічні кольори та мови</string>\n    <string name=\"dark_theme\">Темна тема</string>\n    <string name=\"follow_system\">Як у системі</string>\n    <string name=\"on\">Увімкнено</string>\n    <string name=\"off\">Вимкнено</string>\n    <string name=\"cancel\">Скасувати</string>\n    <string name=\"settings_before_download\">Налаштуйте перед завантаженням</string>\n    <string name=\"settings_before_download_desc\">Налаштуйте завантаження перед його початком</string>\n    <string name=\"settings_before_download_text\">Параметри завантаження</string>\n    <string name=\"error_copied\">Звіт про помилку скопійовано до буфера обміну</string>\n    <string name=\"thumbnail\">Обкладинка</string>\n    <string name=\"paste\">Вставити</string>\n    <string name=\"yt_dlp_docs\">Документація yt-dlp</string>\n    <string name=\"edit_template_desc\">Вихідний шлях та посилання будуть додані застосунком.</string>\n    <string name=\"convert_audio_format\">Конвертувати аудіо формат</string>\n    <string name=\"not_convert\">Не конвертувати</string>\n    <string name=\"convert_to\">Конвертувати у %1$s</string>\n    <string name=\"format\">Формат</string>\n    <string name=\"convert_audio_format_desc\">Перекодування аудіо файлів призведе до погіршення якості звуку та збільшення розміру файлу.</string>\n    <string name=\"video_quality\">Якiсть вiдео</string>\n    <string name=\"best_quality\">Найкраща якiсть</string>\n    <string name=\"video_quality_desc\">Обмежте якість відео за наявності кількох</string>\n    <string name=\"not_specified\">Не вказано (типово)</string>\n    <string name=\"video_format_preference\">Бажаний формат відео</string>\n    <string name=\"preferred_format_desc\">Вибирати цей формат по можливості</string>\n    <string name=\"video_format\">Формат вiдео</string>\n    <string name=\"convert_audio\">Конвертувати</string>\n    <string name=\"start_download\">Завантажити</string>\n    <string name=\"close\">Закрити</string>\n    <string name=\"close_never_show_again\">Не показувати знову</string>\n    <string name=\"user_guide\">Інструкція</string>\n    <string name=\"open_settings\">Вiдкрити налаштування</string>\n    <string name=\"paste_desc\">Натисніть \\\"Вставити\\\", щоб отримати посилання на відео з буфера обміну.</string>\n    <string name=\"download_desc\">Після чого натисніть \\\"Завантажити\\\", щоб почати завантаження.</string>\n    <string name=\"download_history_desc\">Перевіряйте та керуйте завантаженнями в застосунку, включаючи відео та аудіо.</string>\n    <string name=\"check_download_settings_desc\">Спочатку ознайомтеся з налаштуваннями завантажень та переконайтеся, що у вас встановлена остання версія yt-dlp.</string>\n    <string name=\"download_playlist\">Завантажувати плейлисти</string>\n    <string name=\"download_playlist_desc\">Завантажувати декілька відео з плейлиста</string>\n    <string name=\"defaults\">Типово</string>\n    <string name=\"channel_name\">Завантаження</string>\n    <string name=\"channel_description\">Повідомляти про прогрес та закінчення завантажень</string>\n    <string name=\"video_url\">Посилання на вiдео</string>\n    <string name=\"download_finish_notification\">Завантаження завершено. Натисніть, щоб відкрити.</string>\n    <string name=\"execute_command_notification\">Виконання користувацьких команд…</string>\n    <string name=\"battery_settings_desc\">Встановіть у налаштуваннях системи режим використання батареї \\\"Необмежений\\\" для цього застосунка, щоб завантажувати ваші відео та аудіо у фоновому режимі.</string>\n    <string name=\"concurrent_download\">Багатопотокове завантаження</string>\n    <string name=\"concurrent_download_desc\">Завантажувати більше частин M3U8/MPD відео паралельно</string>\n    <string name=\"concurrent_download_num\">%d потоків буде використано для завантаження DASH/HLS вiдео.</string>\n    <string name=\"options\">Опції</string>\n    <string name=\"additional_settings\">Додаткові налаштування</string>\n    <string name=\"share_fail_msg\">Неможливо знайти посилання</string>\n    <string name=\"share_success_msg\">Читаю посилання…</string>\n    <string name=\"show_more_actions\">Більше дій</string>\n    <string name=\"download_notification\">Повідомлення про завантаження</string>\n    <string name=\"download_notification_desc\">\"Повідомляти про завантаження\"</string>\n    <string name=\"fetching_playlist_info\">Збираємо інформацію про плейлист…</string>\n    <string name=\"download_range_selection\">Вибір плейлиста</string>\n    <string name=\"download_range_desc\">Позначити початок та кінець списку завантажень із плейлиста \\\"%3$s\\\" (з %1$d по %2$d).</string>\n    <string name=\"from\">Початок</string>\n    <string name=\"to\">Кінець</string>\n    <string name=\"invalid_index_range\">Неіснуючий діапазон індексу</string>\n    <string name=\"playlist_indicator_text\">Завантаження плейлиста (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Тека для аудiо</string>\n    <string name=\"download_directory\">Тека для завантажень</string>\n    <string name=\"download_directory_desc\">Оберіть, де зберігати файли</string>\n    <string name=\"subdirectory\">Зберігати до підтек</string>\n    <string name=\"subdirectory_desc\">Зберігайте файли в теках з відповідними назвами</string>\n    <string name=\"permission_issue\">Непідтримувана директорія</string>\n    <string name=\"permission_issue_desc\">Директорії за межами Documents/ й Download/ не пiдтримуються</string>\n    <string name=\"battery_configuration\">Налаштування батареї</string>\n    <string name=\"battery_configuration_desc\">Ігнорувати оптимізації батареї для фонових завантажень</string>\n    <string name=\"service_title\">Seal завантажує…</string>\n    <string name=\"unknown_error\">Невідома помилка</string>\n    <string name=\"translate\">Перекласти</string>\n    <string name=\"translate_desc\">Допоможіть перекласти Seal на Weblate</string>\n    <string name=\"prefix\">Шаблон шляху</string>\n    <string name=\"embed_subtitles\">Вбудовані субтитри</string>\n    <string name=\"embed_subtitles_desc\">Вставляти м\\'які субтитри у відео, якщо вони доступні</string>\n    <string name=\"new_template\">Новий шаблон</string>\n    <string name=\"template_label\">Назва</string>\n    <string name=\"remove_template\">Видалити\\?</string>\n    <string name=\"remove_template_desc\">Назавжди видалити \\\"%1$s\\\" з шаблонів команд\\?</string>\n    <string name=\"template_selection\">Вибрати шаблони</string>\n    <string name=\"custom_command_template_desc\">Керувати шаблонами команд</string>\n    <string name=\"downloading_indicator_text\">Завантаження в процесі…</string>\n    <string name=\"task_canceled\">Завантаження скасовано</string>\n    <string name=\"github_issue\">Повідомити про проблему (GitHub)</string>\n    <string name=\"github_issue_desc\">Надіслати звіт про помилку або запропонувати нову функцію</string>\n    <string name=\"info_copied\">Інформація скопійована в буфер обміну</string>\n    <string name=\"open_file\">Відкрити файл</string>\n    <string name=\"status_enqueued\">Поставлено в чергу</string>\n    <string name=\"status_completed\">Завершено</string>\n    <string name=\"status_downloading\">Завантаження</string>\n    <string name=\"status_canceled\">Cкасовано</string>\n    <string name=\"status_fetching_video_info\">Отримання інформації</string>\n    <string name=\"restart\">Перезавантажити</string>\n    <string name=\"status_error\">Помилка</string>\n    <string name=\"copy_link\">Скопіювати посилання</string>\n    <string name=\"copy_error_report\">Скопіювати помилку</string>\n    <string name=\"video_file_size\">Розмір відео</string>\n    <string name=\"video_resolution\">Роздільна здатність</string>\n    <string name=\"clear_temp_files_desc\">Видалити усі тимчасові файли з тимчасової теки</string>\n    <string name=\"clear_temp_files_count\">Видалено %1$d тимчасовий(і/их) файл(и/ів)</string>\n    <string name=\"sponsorblock_categories_desc\">Вкажіть категорії SponsorBlock, що будуть видалені або позначені у відеофайлі</string>\n    <string name=\"check_for_updates\">Перевірити наявність оновлень</string>\n    <string name=\"app_up_to_date\">Поточна версія актуальна</string>\n    <string name=\"update\">Оновлення</string>\n    <string name=\"cookies_desc\">Використовувати файли cookies у Netscape форматі для завантажень</string>\n    <string name=\"check_for_updates_desc\">Автоматично перевіряти GitHub на нові версії</string>\n    <string name=\"aria2_desc\">Використовувати aria2c в якості зовнішнього завантажувача</string>\n    <string name=\"clear_temp_files_info\">Тимчасові файли можна використовувати для відновлення скасованих завантажень. Ви впевнені, що хочете видалити всі ці файли\\?\n\\n\n\\nВи можете отримати доступ до цих файлів у %1$s</string>\n    <string name=\"app_update_failed\">Не вдалося оновити до останньої версії</string>\n    <string name=\"clear_temp_files\">Видалити тимчасові файли</string>\n    <string name=\"export_to_clipboard\">Експортувати в буфер обміну</string>\n    <string name=\"import_from_clipboard\">Імпортувати з буфера обміну</string>\n    <string name=\"template_exported\">Експортовано %1$d шаблон(и/ів)</string>\n    <string name=\"template_imported\">Імпортовано %1$d шаблон(и/ів)</string>\n    <string name=\"download_task_count\">%1$d Завдань для завантаження</string>\n    <string name=\"recently_added\">Нещодавно додані</string>\n    <string name=\"multiselect_item_count\">%1$d відеофайл(и/ів), %2$d аудіофайл(и/ів)</string>\n    <string name=\"delete_multiple_items_msg\">Видалити %1$d елемент(и/ів) з історії завантажень назавжди\\?</string>\n    <string name=\"sponsorblock_desc\">Видаляти або позначати сегменти у відео за допомогою SponsorBlock API</string>\n    <string name=\"sponsorblock_categories\">Категорії SponsorBlock</string>\n    <string name=\"high_contrast\">Темна тема з високим контрастом</string>\n    <string name=\"invalid_input\">Неправильні дані</string>\n    <string name=\"lowest_quality\">Найгірша якість</string>\n    <string name=\"multiselect_mode\">Режим множинного вибору</string>\n    <string name=\"private_mode\">Інкогніто</string>\n    <string name=\"private_mode_desc\">Вимкнути історію завантажень</string>\n    <string name=\"dynamic_color\">Динамічний колір</string>\n    <string name=\"dynamic_color_desc\">Застосовувати кольори зі шпалер до теми застосунку</string>\n    <string name=\"file_unavailable\">Файл більше недоступний</string>\n    <string name=\"network\">Мережа</string>\n    <string name=\"rate_limit\">Ліміт швидкості</string>\n    <string name=\"max_rate\">Максимальна швидкість</string>\n    <string name=\"download_with_cellular_desc\">Дозволяти завантаження медіа під час підключення до мобільних мереж</string>\n    <string name=\"download_disabled_with_cellular\">Завантаження через мобільну мережу вимкнено відповідно до ваших налаштувань</string>\n    <string name=\"download_with_cellular\">Завантажувати через мобільну мережу</string>\n    <string name=\"rate_limit_desc\">Обмежте максимальну швидкість завантаження</string>\n    <string name=\"selected_item_count\">%1$d вибрано</string>\n    <string name=\"general_settings_desc\">Yt-dlp версія, сповіщення, список відтворення</string>\n    <string name=\"network_settings_desc\">Обмеження швидкості, завантажувач та cookies</string>\n    <string name=\"disable_preview_desc\">Не відображати обкладинки під час завантаження</string>\n    <string name=\"privacy\">Конфіденційність</string>\n    <string name=\"use_custom_command\">Використовувати ці команди</string>\n    <string name=\"private_directory\">Приватна тека</string>\n    <string name=\"private_directory_desc\">Зберігати завантаження у прихованій теці</string>\n    <string name=\"crop_artwork\">Обрізати зображення</string>\n    <string name=\"crop_artwork_desc\">Обрізати вбудоване зображення у квадрат</string>\n    <string name=\"select_all\">Вибрати все</string>\n    <string name=\"format_selection\">Вибір формату</string>\n    <string name=\"download_selection_desc\">Виберіть відео для завантаження зі списку відтворення \\\"%1$s\\\"</string>\n    <string name=\"generate_new_cookies\">Згенерувати нові cookies</string>\n    <string name=\"suggested\">Запропоноване</string>\n    <string name=\"video_only\">Відео (без аудіо)</string>\n    <string name=\"format_selection_desc\">Виберіть формат перед початком завантаження</string>\n    <string name=\"unavailable\">Недоступно</string>\n    <string name=\"format_settings_desc\">Формат файлу, якість відео та субтитри</string>\n    <string name=\"disable_preview\">Вимкнути попередній перегляд</string>\n    <string name=\"telegram_channel\">Telegram канал</string>\n    <string name=\"how_does_it_work\">Як це працює\\?</string>\n    <string name=\"use_cookies\">Використовувати cookies</string>\n    <string name=\"remove_cookie_profile_desc\">Видалити цей запис для \\\"%1$s\\\"? Зверніть увагу, що файли cookies, збережені для цього сайту, не будуть видалені.</string>\n    <string name=\"custom_command_enabled_hint\">Деякі параметри недоступні при використанні користувацької команди</string>\n    <string name=\"cookies_usage_msg\">Завантаження з деяких сайтів вимагає інформації про автентифікацію облікового запису. Натисніть «Згенерувати нові cookies», введіть URL-адресу вебсайту, а потім увійдіть за допомогою свого облікового запису на сторінці браузера, застосунок згенерує його для вас.</string>\n    <string name=\"matrix_space\">Кімната Matrix</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"abs_hint\">Більшість платформ надають аудіо та відео окремо, але ви можете об\\'єднати формати \\\"лише відео\\\" та \\\"лише аудіо\\\" у єдине відео.</string>\n    <string name=\"video_creator_sample_text\">Приклад автора відео</string>\n    <string name=\"subtitle_language\">Мови субтитрів</string>\n    <string name=\"show_logs\">Показати журнал</string>\n    <string name=\"auto_subtitle\">Автоматичні субтитри</string>\n    <string name=\"sdcard_directory\">Тека SD-карти</string>\n    <string name=\"auto_subtitle_desc\">Завантажувати автоматично створені субтитри</string>\n    <string name=\"copy_log\">Копіювати лог</string>\n    <string name=\"clear\">Очистити</string>\n    <string name=\"title_activity_share\">Швидке завантаження</string>\n    <string name=\"video_title_sample_text\">Приклад назви відео</string>\n    <string name=\"subtitle\">Субтитри</string>\n    <string name=\"download_subtitles\">Завантажувати субтитри</string>\n    <string name=\"subtitle_desc\">Мови, вбудовані субтитри, автоматичні субтитри</string>\n    <string name=\"add\">Додати</string>\n    <string name=\"running_tasks\">Запущені завдання</string>\n    <string name=\"edit_shortcuts\">Редагувати комбінації клавіш</string>\n    <string name=\"shortcuts\">Комбінації клавіш</string>\n    <string name=\"edit_shortcuts_desc\">Відредагуйте власні комбінації клавіш, які можна використовувати для створення шаблонів команд.</string>\n    <string name=\"logs\">Лог</string>\n    <string name=\"subtitle_sponsorblock\">При видаленні сегментів SponsorBlock субтитри можуть з\\'являтися не вчасно.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Для вбудовування м\\'яких субтитрів, відео буде перетворено у контейнер mkv. Ви зможете використати VLC Media Player або інші сумісні застосунки для перегляду.</string>\n    <string name=\"filesize_gb\">%.2f ГБ</string>\n    <string name=\"filesize_mb\">%.2f МБ</string>\n    <string name=\"stable_channel\">Стабільний</string>\n    <string name=\"pre_release_channel\">Предперегляд</string>\n    <string name=\"share\">Поділитися</string>\n    <string name=\"update_channel\">Канал оновлень</string>\n    <string name=\"auto_update\">Оновлювати автоматично</string>\n    <string name=\"update_channel_desc\">Встановіть версію предперегляд, щоб переглянути нові функції та зміни.\n\\n\n\\nУ цих версіях буде спостерігатися деяка нестабільність, тому, будь ласка, не соромтеся повідомляти нам про будь-які проблеми, щоб допомогти нам покращити застосунок у майбутньому.</string>\n    <string name=\"enable_auto_update\">Увімкнути оновлення</string>\n    <string name=\"apply\">Застосувати</string>\n    <string name=\"clip_video\">Відеокліп</string>\n    <string name=\"clip_start\">Початок</string>\n    <string name=\"clip_end\">Кінець</string>\n    <string name=\"discard\">Відхилити</string>\n    <string name=\"audio_format_preference\">Бажаний формат аудіо</string>\n    <string name=\"lowest_bitrate\">Найнижчий бітрейт</string>\n    <string name=\"audio_quality\">Якість аудіо</string>\n    <string name=\"audio_quality_desc\">Обмежувати бітрейт аудіо при наявності кількох якостей</string>\n    <string name=\"format_sorting\">Сортування форматів</string>\n    <string name=\"format_sorting_desc\">Сортування форматів за допомогою опції -S для yt-dlp</string>\n    <string name=\"import_from_preferences\">Імпортувати</string>\n    <string name=\"title\">Назва</string>\n    <string name=\"rename\">Перейменувати</string>\n    <string name=\"second\">секунди</string>\n    <string name=\"minute\">хвилини</string>\n    <string name=\"clear_all_cookies\">Очистити всі файли cookie</string>\n    <string name=\"unlimited\">Без обмежень</string>\n    <string name=\"clear_all_cookies_desc\">Назавжди видалити всі файли cookie, які зберігаються у застосунку\\?</string>\n    <string name=\"temporary_directory_desc\">Зберігати тимчасові файли у внутрішній теці</string>\n    <string name=\"sponsor\">Спонсорувати</string>\n    <string name=\"feedback\">Зворотний зв\\'язок</string>\n    <string name=\"sponsors\">Спонсори</string>\n    <string name=\"sponsor_desc\">Підтримайте цей застосунок, спонсоруючи нас на GitHub</string>\n    <string name=\"sponsor_msg\">Seal завжди буде безплатним і відкритим для всіх. Якщо вам це подобається, подумайте про те, щоб стати моїм спонсором на GitHub!</string>\n    <string name=\"no_downloaded_media\">Немає завантажених медіа</string>\n    <string name=\"beta_features\">Бета</string>\n    <string name=\"clip_video_desc\">Створюйте відеокліпи на сторінці вибору формату</string>\n    <string name=\"audio_format\">Аудіо формат</string>\n    <string name=\"enable_experimental_feature\">Увімкнути експериментальну функцію\\?</string>\n    <string name=\"clip_video_dialog_msg\">Завантаження за допомогою цієї функції буде делеговано FFmpeg для завантаження вибраних фрагментів відео, ця функція все ще експериментальна і розрізання не буде повністю точним, не всі формати підтримують цю функцію, і ви можете відчути повільну швидкість завантаження.</string>\n    <string name=\"auto_update_disabled_msg\">Автоматичне оновлення недоступне для %1$s збірок. Якщо на вашому пристрої не встановлено %1$s або ви хочете переглянути майбутні нові функції в Seal, розгляньте %2$s.</string>\n    <string name=\"switch_to_github_builds\">перехід на збірки GitHub</string>\n    <string name=\"okay\">Ок</string>\n    <string name=\"got_it\">Зрозумів</string>\n    <string name=\"feature_unavailable\">Функція недоступна</string>\n    <string name=\"no_custom_command_tasks\">Немає спеціальних командних завдань</string>\n    <string name=\"msg_from_developer\">Допис від розробника</string>\n    <string name=\"sponsor_msg2\">Велике спасибі!</string>\n    <string name=\"download_video_desc\">Завантажити відео з URL-адреси</string>\n    <string name=\"convert_subtitle\">Конвертувати субтитри</string>\n    <string name=\"convert_subtitle_desc\">Конвертуйте субтитри в інший формат</string>\n    <string name=\"split_video\">Розділити відео</string>\n    <string name=\"copy_and_exit\">Скопіювати та вийти</string>\n    <string name=\"split_video_msg\">Відео буде розділене на %1$d частини</string>\n    <string name=\"unknown_error_title\">Ой! Щось пішло не так</string>\n    <string name=\"expand\">Розгорнути</string>\n    <string name=\"new_task\">Нове завдання на завантаження</string>\n    <string name=\"start\">Почати</string>\n    <string name=\"edit_template\">Редагувати \\\"%1$s\\\"</string>\n    <string name=\"proxy\">Проксі</string>\n    <string name=\"legacy\">Застарілий</string>\n    <string name=\"quality\">Якість</string>\n    <string name=\"enable_notifications\">Увімкнути сповіщення\\?</string>\n    <string name=\"disable\">Вимкнути</string>\n    <string name=\"custom_command_directory\">Тека для власних команд</string>\n    <string name=\"prefer_compatibility_desc\">Вибирати MP4 (H.264) для обміну у інших застосунках</string>\n    <string name=\"prefer_quality_desc\">Вибирати AV1, VP9 або H.265 для перегляду у сумісних застосунках</string>\n    <string name=\"proxy_desc\">Використовувати проксі для підключень до інтернету</string>\n    <string name=\"ytdlp_update_action\">Оновити yt-dlp</string>\n    <string name=\"enable_notifications_desc\">Додатку потрібен ваш дозвіл, щоб надсилати сповіщення про стан завантаження.</string>\n    <string name=\"set_directory_desc\">Натисніть, щоб налаштувати теку</string>\n    <string name=\"disabled\">Вимкнено</string>\n    <string name=\"folder_picker\">Вибір теки</string>\n    <string name=\"custom_command_directory_desc\">Вкажіть вихідну теку для власних команд</string>\n    <string name=\"download_type\">Тип завантаження</string>\n    <string name=\"custom\">Власний</string>\n    <string name=\"format_preference\">Налаштування формату</string>\n    <string name=\"unknown\">Невідомо</string>\n    <string name=\"auto\">Авто</string>\n    <string name=\"learn_more\">Дізнатися більше</string>\n    <string name=\"commands\">Команди</string>\n    <string name=\"refresh_cookies_desc\">Натисніть, щоб відкрити вебсторінку для створення нових файлів cookie:</string>\n    <string name=\"remove_multiple_templates_msg\">Видалити %1$s з шаблонів команд назавжди\\?</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"one\">%d елемент</item>\n        <item quantity=\"few\">%d елементи</item>\n        <item quantity=\"many\">%d елементів</item>\n        <item quantity=\"other\">%d елементів</item>\n    </plurals>\n    <string name=\"ua_header\">Заголовок User-Agent</string>\n    <string name=\"export_to_file\">Експорт у файл</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp – це потужний інструмент командного рядка для завантаження відео. Seal полегшує використання yt-dlp, надаючи інтуїтивно зрозумілий графічний інтерфейс, пресети для поширених команд та інші додаткові можливості.\n\\n\n\\nДля розширеного використання yt-dlp, Seal дозволяє створювати, зберігати й виконувати власні шаблони команд безпосередньо, як у терміналі.\n\\n\n\\nПід час використання власних команд більшість опцій та можливостей графічного інтерфейсу буде вимкнено.</string>\n    <string name=\"presets\">Пресети</string>\n    <string name=\"output_template\">Шаблон виводу</string>\n    <string name=\"output_template_desc\">Вкажіть шаблон для назв вихідних файлів</string>\n    <string name=\"clear_download_archive\">Очистити архів завантажень\\?</string>\n    <string name=\"clear_download_archive_desc\">Видалити %1$s з файлу архіву назавжди\\?</string>\n    <string name=\"download_archive_desc\">Записувати ID завантажених відео в архів, щоб уникнути дублікатів</string>\n    <string name=\"download_archive\">Архів завантажень</string>\n    <string name=\"embed_metadata\">Вставити метадані</string>\n    <string name=\"required\">Обов\\'язковий</string>\n    <string name=\"embed_metadata_desc\">Вставляти метадані та обкладинку відео до аудіофайлу</string>\n    <string name=\"show_all_items\">Показати всі елементи (%1$d)</string>\n    <string name=\"save\">Зберегти</string>\n    <string name=\"use_format_sorting\">Використовуйте сортування за форматом</string>\n    <string name=\"restrict_filenames_desc\">Обмежте назви файлів певними символами, щоб забезпечити сумісність</string>\n    <string name=\"restrict_filenames\">Обмежити імена файлів</string>\n    <string name=\"edit_file\">Редагувати файл</string>\n    <string name=\"subdirectory_hint\">Ваші завантаження будуть збережені як:</string>\n    <string name=\"website\">Вебсайт</string>\n    <string name=\"playlist_title\">Назва списку відтворення</string>\n    <string name=\"system_settings\">Налаштування системи</string>\n    <string name=\"force_ipv4\">Примусово використовувати IPv4</string>\n    <string name=\"force_ipv4_desc\">Здійснювати всі підключення через IPv4</string>\n    <string name=\"keep_subtitle_files\">Зберігати файли субтитрів</string>\n    <string name=\"allow_once\">Дозволити один раз</string>\n    <string name=\"allow_always\">Завжди дозволяти</string>\n    <string name=\"dont_allow\">Не дозволяти</string>\n    <string name=\"download_with_cellular_request\">Дозволити завантаження через мобільні дані?</string>\n    <string name=\"merge_audiostream\">Об\\'єднувати кілька аудіопотоків</string>\n    <string name=\"merge_audiostream_desc\">Дозволяє об\\'єднувати кілька аудіопотоків в один файл</string>\n    <string name=\"search_in_downloads\">Пошук у завантаженнях</string>\n    <string name=\"search\">Пошук</string>\n    <string name=\"auto_translated_subtitles_msg\">У завантаженнях можна буде вибрати субтитри, створені автоматично для кожної мови. Вони можуть бути неточними та важкими для розуміння.</string>\n    <string name=\"auto_translated_subtitles\">Субтитри з автоперекладом</string>\n    <string name=\"remember_for_next_download\">Запам\\'ятати для майбутнього завантаження</string>\n    <string name=\"look_and_feel\"><![CDATA[Вигляд та відчуття]]></string>\n    <string name=\"subtitle_language_desc\">Мова субтитрів для завантаження в автоматичному виборі формату, розділених комами.</string>\n    <string name=\"backup_type\">Тип резервного копіювання</string>\n    <string name=\"export_backup\">Експортувати</string>\n    <string name=\"import_backup\">Імпортувати</string>\n    <string name=\"export_to\">Експортувати до</string>\n    <string name=\"import_download_history_msg\">Завантажені файли не будуть імпортовані. Вам потрібно завантажити їх вручну</string>\n    <string name=\"use_previous_selection\">Використовувати попередньо вибране</string>\n    <string name=\"none\">Нічого</string>\n    <string name=\"interface_and_interaction\"><![CDATA[Інтерфейс та взаємодія]]></string>\n    <string name=\"reset\">Скинути</string>\n    <string name=\"search_in_subtitles\">Пошук в субтитрах</string>\n    <string name=\"no_thanks\">Ні, дякую</string>\n    <string name=\"update_language_msg\">Наступні мови будуть додані до ваших уподобань для майбутніх завантажень:</string>\n    <string name=\"update_subtitle_languages\">Оновити мови субтитрів?</string>\n    <string name=\"file\">Файл</string>\n    <string name=\"clipboard\">Буфер обміну</string>\n    <string name=\"import_from\">Імпортувати з</string>\n    <string name=\"export_download_history\">Експортувати історію завантажень?</string>\n    <string name=\"import_download_history\">Імпортувати історію завантажень?</string>\n    <string name=\"download_history\">Історія завантажень</string>\n    <string name=\"download_history_imported\">Імпортований %1$s до історії завантажень</string>\n    <string name=\"redownload\">Завантажити повторно</string>\n    <string name=\"full_backup\">Повне резервне копіювання</string>\n    <string name=\"export_download_history_msg\">Експортування %1$s з історії завантажень. Завантажені файли і налаштування не будуть повернені.</string>\n    <string name=\"download_archive_error\">Відео було завантажено. Якщо це не очікувана поведінка, будь ласка, перевірте ваш архів завантаження.</string>\n    <string name=\"remux_container_mkv\">Контейнер для відео Remux</string>\n    <string name=\"every_week\">Щотижня</string>\n    <string name=\"every_month\">Щомісяця</string>\n    <string name=\"remux_container_mkv_desc\">Remux відео в контейнер MKV для кращої сумісності</string>\n    <string name=\"cookies_in_database\">Всього %1$d файлів cookie з %2$d вебсайтів</string>\n    <string name=\"every_day\">Щодня</string>\n    <string name=\"all_languages\">Всі мови</string>\n    <string name=\"playlist\">Список відтворення</string>\n    <string name=\"prefer_placeholder\">Надаю перевагу %1$s</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"one\">%d відео</item>\n        <item quantity=\"few\">%d відео</item>\n        <item quantity=\"many\">%d відео</item>\n        <item quantity=\"other\">%d відео</item>\n    </plurals>\n    <plurals name=\"audio_count\">\n        <item quantity=\"one\">%d аудіо</item>\n        <item quantity=\"few\">%d аудіо</item>\n        <item quantity=\"many\">%d аудіо</item>\n        <item quantity=\"other\">%d аудіо</item>\n    </plurals>\n    <string name=\"proceed\">Продовжити</string>\n    <string name=\"preset\">Передустановка</string>\n    <string name=\"custom_format_selection_desc\">Вибирайте формати, субтитри та налаштовуйте далі</string>\n    <string name=\"preset_format_selection_desc\">Завантажуйте автоматично відповідно до ваших налаштувань формату</string>\n    <string name=\"edit_preset\">Редагувати передустановку</string>\n    <string name=\"best_quality_desc\">Завантажте найкращий доступний формат</string>\n    <string name=\"task_added\">Задачу додано до черги</string>\n    <string name=\"you_ll_find_your_downloads_here\">Ви знайдете свої завантаження тут</string>\n    <string name=\"download_hint\">Натисніть на кнопку завантаження або поділіться відео посиланням на цей застосунок, щоби почати завантаження</string>\n    <string name=\"status_downloaded\">Завантажено</string>\n    <string name=\"all\">Все</string>\n    <string name=\"download_queue\">Завантаження у черзі</string>\n    <string name=\"select_multiple_link\">Виберіть з %1$d посилань</string>\n    <string name=\"show_navigation_drawer\">Показати панель навігації</string>\n    <string name=\"resume\">Відновити</string>\n    <string name=\"delete\">Видалити</string>\n    <string name=\"media_info\">Інформація про медіа</string>\n    <string name=\"issue_tracker_hint\">Виникла помилка? Перш ніж повідомляти про нову проблему, будь ласка, скористайтеся нашим відстеженням проблем. Багато поширених проблем вже вирішено і задокументовано там.</string>\n    <string name=\"trouble_shooting_desc\">Усунення поширених помилок і перевірка на наявність відомих помилок</string>\n    <string name=\"trouble_shooting\">Усунення несправностей</string>\n    <string name=\"issue_tracker\">Відстежування проблем</string>\n    <string name=\"saved_urls\">Збережені посилання</string>\n    <string name=\"add_new_url\">Додати нове посилання</string>\n    <string name=\"add_to\">Додати до %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ur/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">ویڈیو فولڈر</string>\n    <string name=\"download_success_msg\">ڈاؤن لوڈ مکمل</string>\n    <string name=\"yt_dlp_update_fail\">تازہ ترین yt-dlp ورژن انسٹال نہیں ہو سکا۔ براہ کرم یقینی بنائیں کہ آپ انٹرنیٹ سے جڑے ہوئے ہیں۔</string>\n    <string name=\"permission_denied\">اجازت نامنظور</string>\n    <string name=\"download_error_msg\">فائل ڈاؤن لوڈ نہیں ہو سکی</string>\n    <string name=\"extract_audio\">آڈیو میں محفوظ کریں</string>\n    <string name=\"create_thumbnail\">تھمبنیل محفوظ کریں</string>\n    <string name=\"settings\">سیٹنگ</string>\n    <string name=\"download_settings_desc\">جرنل، فارمیٹ، کسٹم کمانڈ</string>\n    <string name=\"download\">ڈاؤنلوڈ</string>\n    <string name=\"url_empty\">لنک خالی نہیں ہو سکتا</string>\n    <string name=\"extract_audio_summary\">ویڈیو کے بجائے آڈیو ڈاؤن لوڈ اور محفوظ کریں</string>\n    <string name=\"create_thumbnail_summary\">ویڈیو تھمب نیل کو بطور فائل محفوظ کریں</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp کا تازہ ترین ورژن استعمال کرنا</string>\n    <string name=\"fetching_info\">ویڈیو کی معلومات حاصل کی جا رہی ہے…</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-uz/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"create_thumbnail_summary\">Video eskizini fayl sifatida saqlash</string>\n    <string name=\"fetch_info_error_msg\">Video maʼlumotlarini yuklab boʻlmadi</string>\n    <string name=\"about_page\">Versiya, nashrlar, avtomatik yangilash</string>\n    <string name=\"custom_command_template\">Buyruq shabloni</string>\n    <string name=\"language\">Displey tili</string>\n    <string name=\"language_settings\">Displey tilini o\\'rnatish</string>\n    <string name=\"task_running\">Mavjud yuklash vazifasi allaqachon ishlamoqda</string>\n    <string name=\"paste_msg\">Buferdan URL manzilni joylashtirish</string>\n    <string name=\"paste_fail_msg\">Buferdagi URL manziliga mos kelmadi</string>\n    <string name=\"ytdlp_version\">Yt-dlp versiyasi</string>\n    <string name=\"ytdlp_update\">Eng so\\'nggi yt-dlp versiyasini o\\'rnatish uchun bosing</string>\n    <string name=\"delete_info\">O\\'chirilsinmi\\?</string>\n    <string name=\"delete_info_msg\">“%1$s” yuklangallar tarixidan butunlay olib o\\'chirilsinmi\\?</string>\n    <string name=\"confirm\">Tasdiqlash</string>\n    <string name=\"dismiss\">Bekor qilish</string>\n    <string name=\"downloads_history\">Yuklanganlar</string>\n    <string name=\"audio\">Audio</string>\n    <string name=\"link_copied\">Havola nusxalandi</string>\n    <string name=\"open_url\">Havolani ochish</string>\n    <string name=\"remove\">O\\'chirish</string>\n    <string name=\"delete_file\">Oʻchirish</string>\n    <string name=\"back\">Ortga</string>\n    <string name=\"version\">Versiya</string>\n    <string name=\"release_desc\">O\\'zgartirishlarni va yangi versiyalarni qidirish</string>\n    <string name=\"release\">Oxirgi nashr</string>\n    <string name=\"readme_desc\">GitHub va README-ni tekshirish</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Tekshirildi</string>\n    <string name=\"credits\">Ma\\'lumotlar</string>\n    <string name=\"credits_desc\">Ma\\'lumotlar va bepul dasturlar</string>\n    <string name=\"custom_command\">Maxsus buyruq</string>\n    <string name=\"custom_command_desc\">Maxsus shablon bilan yt-dlp buyrug\\'ini ishga tushirish</string>\n    <string name=\"extract_audio\">Audio sifatida saqlash</string>\n    <string name=\"create_thumbnail\">Eskizni saqlash</string>\n    <string name=\"settings\">Sozlamalar</string>\n    <string name=\"download_settings_desc\">Umumiy, format, maxsus buyruq</string>\n    <string name=\"download\">Yuklash</string>\n    <string name=\"extract_audio_summary\">Video o\\'rniga audioni yuklab olish va saqlash</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlpning so\\'nggi versiyasidan foydalanish</string>\n    <string name=\"yt_dlp_update_fail\">yt-dlpning so\\'ngi versiyasini o\\'rnatib bo\\'lmadi. Internetga ulanganingizga ishonch hosil qiling.</string>\n    <string name=\"fetching_info\">Video haqida maʼlumot yuklanmoqda…</string>\n    <string name=\"permission_denied\">Ruxsat berilmagan</string>\n    <string name=\"download_success_msg\">Yuklash tugallandi</string>\n    <string name=\"download_error_msg\">Faylni yuklab bo‘lmadi</string>\n    <string name=\"download_start_msg\">“%1$s” ni yuklash</string>\n    <string name=\"video_directory\">Video uchun papka</string>\n    <string name=\"general_settings\">Umumiy</string>\n    <string name=\"url_empty\">Havola bo\\'sh bo\\'lishi mumkin emas</string>\n    <string name=\"about\">Ilova haqida</string>\n    <string name=\"convert_audio_format\">Audio formatga aylantirish</string>\n    <string name=\"convert_audio_format_desc\">Audio fayllarni qayta kodlash audio sifatining yo\\'qolishiga va fayl hajmining oshishiga olib keladi.</string>\n    <string name=\"preferred_format_desc\">Bir nechta taqdim etilganda afzal format</string>\n    <string name=\"not_convert\">Aylantirmaslik</string>\n    <string name=\"convert_to\">%1$s ga aylantirish</string>\n    <string name=\"video_quality\">Video sifati</string>\n    <string name=\"best_quality\">Eng yashi sifat</string>\n    <string name=\"video_format_preference\">Tanlangan video formati</string>\n    <string name=\"video_format\">Video formati</string>\n    <string name=\"convert_audio\">Aylantirish</string>\n    <string name=\"start_download\">Yuklash</string>\n    <string name=\"close\">Yopish</string>\n    <string name=\"close_never_show_again\">Boshqa ko\\'rsatmaslik</string>\n    <string name=\"user_guide\">Foydalanuvchi qo\\'llanma</string>\n    <string name=\"open_settings\">Sozlamalarni ochish</string>\n    <string name=\"download_playlist\">Pleylistni yuklash</string>\n    <string name=\"execute_command_notification\">Foydalanuvchi buyruqlar ishga tushirilmoqda…</string>\n    <string name=\"battery_settings_desc\">Iltimos, fonda yuklab olish uchun ushbu ilovaning batareya quvvatini tizim sozlamalarida “Cheklanmagan” qilib belgilang.</string>\n    <string name=\"concurrent_download\">Ko\\'p tarmoqli yuklab olish</string>\n    <string name=\"concurrent_download_num\">%d ta ip bir vaqtda DASH/HLS mahalliy videosini yuklab olish uchun ishlatiladi.</string>\n    <string name=\"options\">Sozlamalar</string>\n    <string name=\"additional_settings\">Qo\\'shimcha sozlamalar</string>\n    <string name=\"download_notification_desc\">Yuklab olingan fayllar va muvaffaqiyat haqida xabar berish</string>\n    <string name=\"fetching_playlist_info\">Pleylist haqida ma\\'lumot olish…</string>\n    <string name=\"download_range_selection\">Pleylistni tanlash</string>\n    <string name=\"download_range_desc\">“%3$s” pleylistidan yuklab olinadigan videolar oralig‘ini belgilang (%1$d dan %2$d gacha).</string>\n    <string name=\"from\">Boshlash</string>\n    <string name=\"to\">Tugallash</string>\n    <string name=\"invalid_index_range\">Indeks oralig‘i noto‘g‘ri</string>\n    <string name=\"audio_directory\">Audio papkasi</string>\n    <string name=\"ytdlp_update_action\">yt-dlp ni yangilash</string>\n    <string name=\"cancel\">Bekor qilish</string>\n    <string name=\"format\">Format</string>\n    <string name=\"video_quality_desc\">Bir nechta video mavjud bo\\'lsa, video sifatini cheklash</string>\n    <string name=\"not_specified\">Belgilanmagan (standart)</string>\n    <string name=\"share_fail_msg\">Umumiy kontentdan URL manziliga mos kelmadi</string>\n    <string name=\"playlist_indicator_text\">Pleylistni yuklash (%1$d/%2$d)…</string>\n    <string name=\"auto_update\">Avto yangilash</string>\n    <string name=\"edit_shortcuts_desc\">Buyruq shablonlarini yaratish uchun ishlatilishi mumkin bo\\'lgan maxsus yorliqlarni tahrirlang.</string>\n    <string name=\"download_finish_notification\">Yuklash yakunlandi. Ochish uchun bosing.</string>\n    <string name=\"subtitle_sponsorblock\">SponsorBlock segmentlarini olib tashlashda subtitrlar noto\\'g\\'ri bo\\'lishi mumkin.</string>\n    <string name=\"embed_subtitles_mkv_msg\">Taglavhalarni joylashtirish uchun videolar mkv konteyneriga qayta ishlanadi. O\\'rnatilgan subtitrlar bilan videolarni tomosha qilish uchun VLC Media Player yoki boshqa mos ilovalardan foydalanishingiz mumkin.</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"update_channel_desc\">Yangi funksiyalar va oʻzgarishlarni koʻrish uchun relizdan oldingi tuzilmalarni oʻrnating.\n\\n\n\\nUshbu versiyalarda biroz beqarorlik boʻladi, shuning uchun kelajakda ilovani yaxshilashga yordam beradigan muammolarga duch kelsangiz, bizga fikr bildirishdan tortinmang.</string>\n    <string name=\"start_execute\">Buyruqni bajarish</string>\n    <string name=\"advanced_settings\">Ilg\\'or sozlamalar</string>\n    <string name=\"print_details\">Batafsil hisobot</string>\n    <string name=\"print_details_desc\">Yuklash vaqtida batafsil hisobotni chiqarish</string>\n    <string name=\"follow_system\">Tizim</string>\n    <string name=\"on\">Yoqilgan</string>\n    <string name=\"settings_before_download\">Yuklash oldingi sozlamalar</string>\n    <string name=\"display\">Tashqi ko\\'rinish</string>\n    <string name=\"dark_theme\">Tungi mavzu</string>\n    <string name=\"settings_before_download_desc\">Yuklab olishdan oldin sozlamalarni sozlang</string>\n    <string name=\"settings_before_download_text\">Ushbu yuklashni sozlang</string>\n    <string name=\"error_copied\">Xatolik hisoboti vaqtinchalik xotiraga nusxalandi</string>\n    <string name=\"thumbnail\">Eskiz</string>\n    <string name=\"paste\">Kiritmoq</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp foydalanish havolalari</string>\n    <string name=\"edit_template_desc\">Chiqish yoʻli va URL ilova tomonidan qoʻshiladi.</string>\n    <string name=\"download_desc\">Keyin sozlamalarni o\\'rnatganingizdan so\\'ng \\\"Yuklab olish\\\" tugmasini bosing.</string>\n    <string name=\"download_history_desc\">Ilova ichidagi yuklamalarni, jumladan, video va audio fayllarni tekshiring va boshqaring.</string>\n    <string name=\"check_download_settings_desc\">Yuklab olish sozlamalari bilan tanishib chiqing va uni ishlatishdan oldin yt-dlp ning eng so\\'nggi versiyasiga ega ekanligingizga ishonch hosil qiling.</string>\n    <string name=\"defaults\">Standard</string>\n    <string name=\"channel_name\">Yuklash</string>\n    <string name=\"channel_description\">Yuklab olingan fayllar va muvaffaqiyat haqida xabar bering</string>\n    <string name=\"share_success_msg\">Umumiy kontentdan video havolasi o‘qilmoqda…</string>\n    <string name=\"show_more_actions\">Koʻproq amallarni koʻrsatish</string>\n    <string name=\"download_notification\">Yuklanma bildirishnomasi</string>\n    <string name=\"add\">Qo\\'shish</string>\n    <string name=\"shortcuts\">Yorliqlar</string>\n    <string name=\"stable_channel\">Barqaror</string>\n    <string name=\"off\">O\\'chirilgan</string>\n    <string name=\"display_settings\">Tungi mavzu, yorqin rang, tillar</string>\n    <string name=\"paste_desc\">Buferdan video havolasini olish uchun \\\"Joylashtirish\\\" tugmasini bosing.</string>\n    <string name=\"download_playlist_desc\">Pleylistdan bir nechta videolarni yuklab oling</string>\n    <string name=\"concurrent_download_desc\">M3U8/MPD videolarining boshqa qismlarini parallel ravishda yuklab oling</string>\n    <string name=\"logs\">Jurnal</string>\n    <string name=\"pre_release_channel\">Oldindan ko\\'rish</string>\n    <string name=\"update_channel\">Yangilanish kanali</string>\n    <string name=\"edit\">Tahrirlash</string>\n    <string name=\"running_tasks\">Ishga tushirilgan vazifalar</string>\n    <string name=\"show_logs\">Jurnalni ko\\'rsatish</string>\n    <string name=\"share\">Ulashish</string>\n    <string name=\"video_url\">Video havolasi</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-vi/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_directory\">Thư mục video</string>\n    <string name=\"extract_audio\">Lưu dưới dạng âm thanh</string>\n    <string name=\"create_thumbnail\">Lưu hình thu nhỏ</string>\n    <string name=\"settings\">Thiết đặt</string>\n    <string name=\"download_settings_desc\">Tổng quan, định dạng, lệnh tùy chỉnh</string>\n    <string name=\"download\">Tải xuống</string>\n    <string name=\"url_empty\">Đường dẫn không được bỏ trống</string>\n    <string name=\"extract_audio_summary\">Tải xuống và lưu âm thanh, thay vì video</string>\n    <string name=\"create_thumbnail_summary\">Lưu hình thu nhỏ dưới dạng tệp</string>\n    <string name=\"yt_dlp_up_to_date\">Đang sử dụng phiên bản mới nhất của yt-dlp</string>\n    <string name=\"yt_dlp_update_fail\">Không thể cài đặt phiên bản mới nhất của yt-dlp. Hãy chắc chắn bạn đã kết nối internet.</string>\n    <string name=\"fetching_info\">Đang nạp thông tin video…</string>\n    <string name=\"permission_denied\">Quyền bị từ chối</string>\n    <string name=\"download_success_msg\">Đã hoàn thành tải xuống</string>\n    <string name=\"download_error_msg\">Không thể tải xuống tệp</string>\n    <string name=\"download_start_msg\">Tải xuống \\\"%1$s\\\"</string>\n    <string name=\"fetch_info_error_msg\">Không thể nạp thông tin video</string>\n    <string name=\"general_settings\">Tổng quan</string>\n    <string name=\"language\">Ngôn ngữ hiển thị</string>\n    <string name=\"language_settings\">Đặt ngôn ngữ hiển thị</string>\n    <string name=\"task_running\">Có sẵn một tác vụ tải xuống đang chạy</string>\n    <string name=\"paste_msg\">Dán URL từ bàn phím</string>\n    <string name=\"paste_fail_msg\">Không thể khớp với URL trong khay nhớ tạm</string>\n    <string name=\"ytdlp_version\">Phiên bản yt-dlp</string>\n    <string name=\"ytdlp_update\">Nhấn để cài đặt phiên bản yt-dlp mới nhất</string>\n    <string name=\"delete_info\">Gỡ bỏ\\?</string>\n    <string name=\"delete_info_msg\">Gỡ \\\"%1$s\\\" khỏi lịch sử tải xuống của bạn\\?</string>\n    <string name=\"confirm\">Xác nhận</string>\n    <string name=\"dismiss\">Hủy bỏ</string>\n    <string name=\"downloads_history\">Tải xuống</string>\n    <string name=\"audio\">Âm thanh</string>\n    <string name=\"link_copied\">Đã sao chép link tới khay nhớ tạm</string>\n    <string name=\"open_url\">Mở link</string>\n    <string name=\"remove\">Gỡ bỏ</string>\n    <string name=\"delete_file\">Xóa tệp</string>\n    <string name=\"about\">Thông tin</string>\n    <string name=\"about_page\">Phiên bản, phản hồi, cập nhật tự động</string>\n    <string name=\"back\">Quay lại</string>\n    <string name=\"version\">Phiên bản</string>\n    <string name=\"release_desc\">Các thay đổi và phiên bản mới</string>\n    <string name=\"release\">Phiên bản mới nhất</string>\n    <string name=\"video\">Video</string>\n    <string name=\"checked\">Đã kiểm tra</string>\n    <string name=\"credits\">Danh đề</string>\n    <string name=\"credits_desc\">Các đóng góp và phần mềm libre</string>\n    <string name=\"custom_command\">Lệnh tùy chỉnh</string>\n    <string name=\"custom_command_desc\">Chạy lệnh yt-dlp với mẫu tùy chỉnh</string>\n    <string name=\"custom_command_template\">Mẫu lệnh</string>\n    <string name=\"print_details\">Đầu ra chi tiết</string>\n    <string name=\"print_details_desc\">In tin nhắn chi tiết khi đang tải xuống</string>\n    <string name=\"display\">Hiển thị</string>\n    <string name=\"display_settings\">Chủ đề tối, màu sắc sống động, ngôn ngữ</string>\n    <string name=\"dark_theme\">Chế độ tối</string>\n    <string name=\"follow_system\">Hệ thống</string>\n    <string name=\"on\">Bật</string>\n    <string name=\"off\">Tắt</string>\n    <string name=\"cancel\">Hủy bỏ</string>\n    <string name=\"settings_before_download\">Cấu hình trước khi tải xuống</string>\n    <string name=\"settings_before_download_desc\">Định thiết lập tùy chọn trước khi tải xuống</string>\n    <string name=\"settings_before_download_text\">Điều chỉnh tải xuống</string>\n    <string name=\"error_copied\">Báo cáo lỗi đã được sao chép vào khay nhớ tạm</string>\n    <string name=\"thumbnail\">Hình thu nhỏ</string>\n    <string name=\"paste\">Dán</string>\n    <string name=\"yt_dlp_docs\">Tham khảo sử dụng yt-dlp</string>\n    <string name=\"edit_template_desc\">Đường dẫn đầu ra và URL sẽ được thêm bởi ứng dụng.</string>\n    <string name=\"convert_audio_format\">Chuyển đổi định dạng âm thanh</string>\n    <string name=\"not_convert\">Không đổi</string>\n    <string name=\"convert_to\">Chuyển đổi sang %1$s</string>\n    <string name=\"format\">Định dạng</string>\n    <string name=\"convert_audio_format_desc\">Mã hóa lại các tệp âm thanh sẽ làm giảm chất lượng âm thanh và tăng kích thước tệp.</string>\n    <string name=\"video_quality\">Chất lượng video</string>\n    <string name=\"best_quality\">Chất lượng tốt nhất</string>\n    <string name=\"video_format_preference\">Định dạng video ưa thích</string>\n    <string name=\"preferred_format_desc\">Định dạng ưa thích khi nhiều định dạng được cung cấp</string>\n    <string name=\"start_download\">Tải xuống</string>\n    <string name=\"close\">Đóng</string>\n    <string name=\"close_never_show_again\">Không hiển thị lại</string>\n    <string name=\"user_guide\">Hướng dẫn người dùng</string>\n    <string name=\"open_settings\">Mở thiết đặt</string>\n    <string name=\"paste_desc\">Nhấp vào \\\"Dán\\\" để lấy link video từ khay nhớ tạm.</string>\n    <string name=\"download_desc\">Kế đến nhấp vào \\\"Tải xuống\\\" sau khi điều chỉnh thiết đặt của nó.</string>\n    <string name=\"download_history_desc\">Kiểm tra và quản lý Tải xuống trong ứng dụng, gồm tệp video và âm thanh.</string>\n    <string name=\"check_download_settings_desc\">Hãy xem thiết đặt tải xuống và đảm bảo bạn có phiên bản yt-dlp mới nhất trước khi sử dụng.</string>\n    <string name=\"download_playlist\">Tải xuống danh sách phát</string>\n    <string name=\"download_playlist_desc\">Tải xuống nhiều video từ một danh sách phát</string>\n    <string name=\"defaults\">Mặc định</string>\n    <string name=\"channel_name\">Tải xuống</string>\n    <string name=\"channel_description\">Thông báo về các tệp đã tải xuống và tiến trình</string>\n    <string name=\"video_url\">Đường dẫn video</string>\n    <string name=\"download_finish_notification\">Đã hoàn thành tải xuống. Nhấn để mở.</string>\n    <string name=\"concurrent_download\">Tải xuống đa luồng</string>\n    <string name=\"concurrent_download_desc\">Tải xuống song song nhiều phần của video M3U8/MPD</string>\n    <string name=\"concurrent_download_num\">%d chuỗi sẽ được sử dụng cùng lúc để tải xuống video gốc DASH/HLS.</string>\n    <string name=\"options\">Tùy chọn</string>\n    <string name=\"share_fail_msg\">Không thể khớp URL từ nội dung được chia sẻ</string>\n    <string name=\"share_success_msg\">Đang đọc dường dẫn video từ nội dung được chia sẻ…</string>\n    <string name=\"show_more_actions\">Hiển thị thêm các hành động</string>\n    <string name=\"download_notification\">Thông báo tải xuống</string>\n    <string name=\"download_notification_desc\">Thông báo các tệp đã tải xuống và tiến trình</string>\n    <string name=\"from\">Bắt đầu</string>\n    <string name=\"readme_desc\">Xem qua Github repo và README</string>\n    <string name=\"edit\">Chỉnh sửa</string>\n    <string name=\"start_execute\">Bắt đầu thực thi lệnh</string>\n    <string name=\"advanced_settings\">Nâng cao</string>\n    <string name=\"convert_audio\">Chuyển đổi</string>\n    <string name=\"video_quality_desc\">Giới hạn chất lượng khi có nhiều video</string>\n    <string name=\"not_specified\">Không xác định (mặc định)</string>\n    <string name=\"video_format\">Định dạng video</string>\n    <string name=\"additional_settings\">Thiết đặt bổ sung</string>\n    <string name=\"invalid_index_range\">Phạm vi chỉ mục không hợp lệ</string>\n    <string name=\"execute_command_notification\">Đang chạy lệnh tùy chỉnh…</string>\n    <string name=\"fetching_playlist_info\">Đang nạp thông tin danh sách phát…</string>\n    <string name=\"download_range_desc\">Chỉ định phạm vi video sẽ tải xuống từ danh sách phát \\\"%3$s\\\" (từ %1$d đến %2$d).</string>\n    <string name=\"battery_settings_desc\">Hãy chuyển mức sử dụng pin của ứng dụng này sang \\\"Không giới hạn\\\" trong thiết đặt hệ thống để tải xuống trong nền.</string>\n    <string name=\"download_range_selection\">Lựa chọn danh sách phát</string>\n    <string name=\"to\">Kết thúc</string>\n    <string name=\"playlist_indicator_text\">Đang tải xuống danh sách phát (%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">Thư mục âm thanh</string>\n    <string name=\"check_for_updates\">Kiểm tra cập nhật</string>\n    <string name=\"check_for_updates_desc\">Tự động kiểm tra phiên bản mới nhất trên Github</string>\n    <string name=\"app_up_to_date\">Phiên bản hiện tại là mới nhất</string>\n    <string name=\"app_update_failed\">Cập nhật phiên bản mới nhất thất bại</string>\n    <string name=\"update\">Cập nhật</string>\n    <string name=\"aria2_desc\">Sử dụng aria2c làm trình tải xuống bên ngoài</string>\n    <string name=\"cookies_desc\">Sử dụng cookie được định dạng Netscape để tải xuống</string>\n    <string name=\"clear_temp_files\">Dọn các tệp tạm thời</string>\n    <string name=\"clear_temp_files_count\">Đã xóa %1$d tập tin tạm thời</string>\n    <string name=\"clear_temp_files_info\">Các tệp tạm có thể được dùng để khôi phục các tải xuống bị hủy. Bạn có chắc xóa tất cả các tệp này\\?\n\\n\n\\nBạn có thể truy cập các tệp này trong %1$s</string>\n    <string name=\"download_directory\">Thư mục tải xuống</string>\n    <string name=\"download_directory_desc\">Chọn nơi lưu trữ tệp video và âm thanh</string>\n    <string name=\"subdirectory\">Lưu vào thư mục con</string>\n    <string name=\"subdirectory_desc\">Lưu tệp vào các thư mục được đặt tên theo trường tương ứng</string>\n    <string name=\"permission_issue\">Vấn đề quyền truy cập bộ nhớ</string>\n    <string name=\"permission_issue_desc\">Các đường dẫn ngoài Download/ và Documents/ không được hỗ trợ</string>\n    <string name=\"battery_configuration\">Cấu hình pin</string>\n    <string name=\"battery_configuration_desc\">Bỏ qua Tối ưu hóa pin để ứng dụng này tải xuống trong nền</string>\n    <string name=\"service_title\">Seal đang tải xuống…</string>\n    <string name=\"unknown_error\">Lỗi không xác định</string>\n    <string name=\"translate\">Dịch</string>\n    <string name=\"translate_desc\">Giúp dịch ứng dụng này trên Hosted Weblate</string>\n    <string name=\"prefix\">Mẫu đường dẫn</string>\n    <string name=\"embed_subtitles\">Nhúng phụ đề</string>\n    <string name=\"embed_subtitles_desc\">Nhúng phụ đề rời vào video nếu có</string>\n    <string name=\"new_template\">Bản mẫu mới</string>\n    <string name=\"template_label\">Nhãn</string>\n    <string name=\"remove_template\">Loại bỏ\\?</string>\n    <string name=\"remove_template_desc\">Loại bỏ \\\"%1$s\\\" khỏi bản mẫu\\?</string>\n    <string name=\"template_selection\">Lựa chọn bản mẫu</string>\n    <string name=\"custom_command_template_desc\">Chỉnh sửa và quản lý lệnh mẫu</string>\n    <string name=\"downloading_indicator_text\">Đang tải xuống…</string>\n    <string name=\"task_canceled\">Đã hủy tác vụ tải xuống</string>\n    <string name=\"github_issue\">Vấn đề Github</string>\n    <string name=\"github_issue_desc\">Nộp một báo cáo lỗi hoặc yêu cầu tính năng</string>\n    <string name=\"info_copied\">Thông tin đã được sao chép vào khay nhớ tạm</string>\n    <string name=\"open_file\">Mở tệp</string>\n    <string name=\"restart\">Khởi động lại</string>\n    <string name=\"status_enqueued\">Đã cho vào hàng</string>\n    <string name=\"status_completed\">Đã hoàn thành</string>\n    <string name=\"status_downloading\">Đang tải</string>\n    <string name=\"status_canceled\">Đã hủy</string>\n    <string name=\"status_fetching_video_info\">Đang nạp thông tin</string>\n    <string name=\"status_error\">Lỗ</string>\n    <string name=\"copy_link\">Sao chép link</string>\n    <string name=\"copy_error_report\">Sao chép báo cáo</string>\n    <string name=\"video_resolution\">Độ phân giải video</string>\n    <string name=\"video_file_size\">Kích thước tệp video</string>\n    <string name=\"clear_temp_files_desc\">Xóa tất cả các tệp tạm thời khỏi thư mục tạm thời</string>\n    <string name=\"export_to_clipboard\">Xuất sang khay nhớ tạm</string>\n    <string name=\"import_from_clipboard\">Nhập từ khay nhớ tạm</string>\n    <string name=\"template_exported\">Đã xuất %1$d mẫu</string>\n    <string name=\"template_imported\">Đã nhập %1$d mẫu</string>\n    <string name=\"download_task_count\">%1$d tiến trình tải xuống</string>\n    <string name=\"recently_added\">Thêm vào gần đây</string>\n    <string name=\"multiselect_item_count\">%1$d video, %2$d tệp âm thanh</string>\n    <string name=\"delete_multiple_items_msg\">Loại bỏ %1$d mục khỏi lịch sử tải xuống\\?</string>\n    <string name=\"sponsorblock_desc\">Loại bỏ hoặc đánh dấu các phân đoạn có trong video bằng SponsorBlock API</string>\n    <string name=\"sponsorblock_categories_desc\">Chỉ định danh mục SponsorBlock sẽ bị xóa hoặc đánh dấu trong tập tin video</string>\n    <string name=\"sponsorblock_categories\">Danh mục SponsorBlock</string>\n    <string name=\"multiselect_mode\">Chế độ đa lựa chọn</string>\n    <string name=\"select_all\">Chọn tất cả</string>\n    <string name=\"private_mode_desc\">Tắt lịch sử tải xuống</string>\n    <string name=\"download_with_cellular\">Tải xuống bằng di động</string>\n    <string name=\"private_mode\">Ẩn danh</string>\n    <string name=\"download_disabled_with_cellular\">Tải xuống bằng mạng di động bị tắt theo thiết đặt của bạn</string>\n    <string name=\"file_unavailable\">Tập tin này không còn khả dụng nữa</string>\n    <string name=\"rate_limit_desc\">Giới hạn tốc độ tải xuống tối đa</string>\n    <string name=\"dynamic_color\">Màu động</string>\n    <string name=\"dynamic_color_desc\">Áp dụng màu từ hình nền cho chủ đề ứng dụng</string>\n    <string name=\"download_with_cellular_desc\">Cho phép tải xuống phương tiện khi được kết nối với mạng có đồng hồ đo</string>\n    <string name=\"network\">Mạng</string>\n    <string name=\"rate_limit\">Tốc độ giới hạn</string>\n    <string name=\"max_rate\">Tốc độ tối đa</string>\n    <string name=\"clip_start\">Bắt đầu</string>\n    <string name=\"clip_end\">Kết thúc</string>\n    <string name=\"unknown_error_title\">Oops! Có cái gì đó không đúng</string>\n    <string name=\"audio_format_preference\">Định dạng âm thanh ưa thích</string>\n    <string name=\"audio_quality\">Chất lượng âm thanh</string>\n    <string name=\"lowest_bitrate\">Tốc độ bit thấp nhất</string>\n    <string name=\"unlimited\">Không giới hạn</string>\n    <string name=\"format_sorting_desc\">Sắp xếp định dạng với tùy chọn -S của yt-dlp</string>\n    <string name=\"format_sorting\">Sắp xếp định dạng</string>\n    <string name=\"second\">giây</string>\n    <string name=\"minute\">phút</string>\n    <string name=\"download_selection_desc\">Lựa chọn video để tải xuống từ danh sách phát \\\"%1$s\\\"</string>\n    <string name=\"no_downloaded_media\">Không có phương tiện đã tải xuống</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">Bật tính năng thử nghiệm\\?</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"high_contrast\">Chủ đề tối tương phản cao</string>\n    <string name=\"crop_artwork_desc\">Cắt vuông các hình ảnh nhúng</string>\n    <string name=\"video_only\">Video (không âm thanh)</string>\n    <string name=\"disable_preview\">Tắt xem trước</string>\n    <string name=\"network_settings_desc\">Tốc độ giới hạn, trình tải xuống, cookie</string>\n    <string name=\"disable_preview_desc\">Không hiển thị hình thu nhỏ trong khi tải xuống</string>\n    <string name=\"share\">Chia sẻ</string>\n    <string name=\"update_channel\">Kênh cập nhật</string>\n    <string name=\"enable_auto_update\">Bật tự động cập nhật</string>\n    <string name=\"auto_update\">Tự động cập nhật</string>\n    <string name=\"matrix_space\">Khu vực Matrix</string>\n    <string name=\"video_title_sample_text\">Văn bản mẫu tiêu đề video</string>\n    <string name=\"abs_hint\">Đa số các nền tảng phát trực tuyến video đều phân phối âm thanh và video riêng biệt, bạn có thể chọn và hợp nhất định dạng chỉ có âm thanh với định dạng chỉ có video thành một video duy nhất.</string>\n    <string name=\"sponsor_msg\">Seal sẽ luôn miễn phí và là mã nguồn mở cho tất cả mọi người. Nếu bạn thích nó, vui lòng xem xét tài trợ cho tôi trên GitHub!</string>\n    <string name=\"title\">Tiêu đề</string>\n    <string name=\"remove_cookie_profile_desc\">Xóa mục này cho \\\"%1$s\\\"? Xin lưu ý rằng các cookie được lưu trữ cho trang web này sẽ không bị xóa.</string>\n    <string name=\"clip_video_dialog_msg\">Các lượt tải xuống sử dụng tính năng này sẽ được ủy quyền cho FFmpeg để tải xuống các phần đã chọn của video, tính năng này vẫn đang thử nghiệm và việc cắt sẽ không hoàn toàn chính xác, không phải tất cả các định dạng đều hỗ trợ tính năng này và bạn có thể gặp phải tốc độ tải xuống chậm hơn.</string>\n    <string name=\"clip_video\">Cắt video</string>\n    <string name=\"invalid_input\">Đầu vào không hợp lệ</string>\n    <string name=\"lowest_quality\">Chất lượng thấp nhất</string>\n    <string name=\"unavailable\">Không khả dụng</string>\n    <string name=\"format_settings_desc\">Định dạng tập tin, chất lượng video, phụ đề</string>\n    <string name=\"general_settings_desc\">Phiên bản Yt-dlp, thông báo, danh sách phát</string>\n    <string name=\"privacy\">Riêng tư</string>\n    <string name=\"private_directory\">Thư mục riêng</string>\n    <string name=\"custom_command_enabled_hint\">Một vài tùy chọn không khả dụng khi sử dụng lệnh tùy chỉnh</string>\n    <string name=\"cookies_usage_msg\">Tải xuống từ một số trang yêu cầu thông tin xác thực tài khoản. Nhấp vào \\\"Tạo cookie mới\\\", nhập URL của trang web rồi đăng nhập bằng tài khoản của bạn trên trang trình duyệt, ứng dụng sẽ tạo nó cho bạn.</string>\n    <string name=\"subtitle_desc\">Ngôn ngữ, phụ đề nhúng, phụ đề tự động</string>\n    <string name=\"copy_log\">Sao chép nhật ký</string>\n    <string name=\"clear\">Xóa</string>\n    <string name=\"apply\">Áp dụng</string>\n    <string name=\"embed_subtitles_mkv_msg\">Để nhúng phụ đề rời, video sẽ được làm lại vào vùng chứa mkv. Bạn có thể sử dụng VLC Media Player hoặc các ứng dụng tương thích khác để xem video có phụ đề rời.</string>\n    <string name=\"pre_release_channel\">Xem trước</string>\n    <string name=\"edit_shortcuts\">Tùy chỉnh lối tắt</string>\n    <string name=\"update_channel_desc\">Cài đặt bản dụng trước khi phát hành để xem trước các tính năng và thay đổi\n\\n\n\\nSẽ có một số sự không ổn định trong các phiên bản này, vì vậy đừng ngại gửi phản hồi cho chúng tôi nếu bạn gặp bất kỳ sự cố nào để giúp chúng tôi cải thiện ứng dụng trong tương lai.</string>\n    <string name=\"subtitle_sponsorblock\">Phụ đề có thể bị lệch thời gian khi loại bỏ phân đoạn SponsorBlock.</string>\n    <string name=\"audio_quality_desc\">Giới hạn tốc độ bit âm thanh khi có nhiều chất lượng</string>\n    <string name=\"clear_all_cookies\">Xóa sạch cookie</string>\n    <string name=\"clear_all_cookies_desc\">Xóa sạch hoàn toàn tất cả các cookie được lưu trữ trong ứng dụng\\?</string>\n    <string name=\"temporary_directory_desc\">Lưu trữ các tập tin tạm thời trong thư mục nội bộ</string>\n    <string name=\"sponsor\">Tài trợ</string>\n    <string name=\"sponsor_desc\">Hỗ trợ ứng dụng này bằng cách tài trợ trên GitHub</string>\n    <string name=\"switch_to_github_builds\">chuyển sang các bản dựng GitHub</string>\n    <string name=\"auto_update_disabled_msg\">Tự động cập nhật không khả dụng cho các bản dựng %1$s. Nếu bạn chưa cài đặt %1$s trên thiết bị của mình hoặc muốn xem trước các tính năng mới sắp tới trong Seal, vui lòng xem xét %2$s.</string>\n    <string name=\"okay\">Đồng ý</string>\n    <string name=\"feature_unavailable\">Tính năng không khả dụng</string>\n    <string name=\"msg_from_developer\">Tin nhắn từ nhà phát triển</string>\n    <string name=\"got_it\">Đã hiểu</string>\n    <string name=\"sponsor_msg2\">Cám ơn bạn rất nhiều!</string>\n    <string name=\"convert_subtitle_desc\">Chuyển đổi phụ đề sang một định dạng khác</string>\n    <string name=\"convert_subtitle\">Chuyển đổi phụ đề</string>\n    <string name=\"split_video_msg\">Video sẽ được tách thành %1$d chương</string>\n    <string name=\"copy_and_exit\">Sao chép và thoát</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"crop_artwork\">Cắt hình ảnh</string>\n    <string name=\"format_selection\">Lựa chọn định dạng</string>\n    <string name=\"generate_new_cookies\">Tạo cookie mới</string>\n    <string name=\"how_does_it_work\">Nó hoạt động như thế nào\\?</string>\n    <string name=\"telegram_channel\">Kênh Telegram</string>\n    <string name=\"running_tasks\">Nhiệm vụ đang chạy</string>\n    <string name=\"show_logs\">Hiển thị nhật ký</string>\n    <string name=\"logs\">Nhật ký</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"shortcuts\">Lối tắt</string>\n    <string name=\"edit_shortcuts_desc\">Chỉnh sửa các lối tắt tùy chỉnh có thể được sử dụng để soạn các mẫu lệnh.</string>\n    <string name=\"stable_channel\">Ổn định</string>\n    <string name=\"discard\">Hủy bỏ</string>\n    <string name=\"import_from_preferences\">Nhập</string>\n    <string name=\"rename\">Đổi tên</string>\n    <string name=\"clip_video_desc\">Tạo video clip trong trang chọn định dạng</string>\n    <string name=\"no_custom_command_tasks\">Không có nhiệm vụ lệnh tùy chỉnh</string>\n    <string name=\"download_video_desc\">Tải video xuống từ URL</string>\n    <string name=\"split_video\">Tách video</string>\n    <string name=\"expand\">Mở rộng</string>\n    <string name=\"new_task\">Nhiệm vụ tải xuống mới</string>\n    <string name=\"start\">Bắt đầu</string>\n    <string name=\"edit_template\">Chỉnh sửa \\\"%1$s\\\"</string>\n    <string name=\"private_directory_desc\">Lưu trữ các tải xuống trong một thư mục ẩn</string>\n    <string name=\"format_selection_desc\">Lựa chọn định dạng để tải xuống trước khi bắt đầu tải xuống</string>\n    <string name=\"use_custom_command\">Sử dụng lệnh tùy chỉnh</string>\n    <string name=\"use_cookies\">Sử dụng cookie</string>\n    <string name=\"selected_item_count\">%1$d đã chọn</string>\n    <string name=\"suggested\">Đề xuất</string>\n    <string name=\"sdcard_directory\">Thư mục thẻ SD</string>\n    <string name=\"auto_subtitle\">Phụ đề tự động</string>\n    <string name=\"auto_subtitle_desc\">Tải xuống phụ đề được tạo tự động</string>\n    <string name=\"title_activity_share\">Tải xuống nhanh</string>\n    <string name=\"video_creator_sample_text\">Văn bản mẫu người sáng tạo video</string>\n    <string name=\"subtitle\">Phụ đề</string>\n    <string name=\"download_subtitles\">Tải xuống phụ đề</string>\n    <string name=\"subtitle_language\">Ngôn ngữ phụ đề</string>\n    <string name=\"add\">Thêm</string>\n    <string name=\"feedback\">Phản hồi</string>\n    <string name=\"sponsors\">Nhà tài trợ</string>\n    <string name=\"audio_format\">Định dạng âm thanh</string>\n    <string name=\"ytdlp_update_action\">Cập nhật yt-dlp</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"set_directory_desc\">Nhấn để thiết lập đường dẫn thư mục</string>\n    <string name=\"prefer_quality_desc\">Ưu tiên định dạng AV1, VP9 hoặc H.265 để xem trong các ứng dụng tương thích</string>\n    <string name=\"proxy_desc\">Sử dụng proxy cho các kết nối Internet</string>\n    <string name=\"legacy\">Truyền thống</string>\n    <string name=\"quality\">Chất lượng</string>\n    <string name=\"enable_notifications\">Bật thông báo\\?</string>\n    <string name=\"enable_notifications_desc\">Ứng dụng cần được cấp quyền để bật thông báo về trạng thái tải xuống và quá trình.</string>\n    <string name=\"disable\">Tắt</string>\n    <string name=\"custom_command_directory\">Đường dẫn thư mục lệnh tùy chỉnh</string>\n    <string name=\"disabled\">Đã tắt</string>\n    <string name=\"custom_command_directory_desc\">Chỉ định thư mục đầu ra khi sử dụng lệnh tùy chỉnh</string>\n    <string name=\"folder_picker\">Trình chọn thư mục</string>\n    <string name=\"prefer_compatibility_desc\">Ưu tiên định dạng MP4(H.264) để chia sẻ với các ứng dụng khác</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp là công cụ dòng lệnh mạnh mẽ để tải xuống băng hình. Seal giúp sử dụng yt-dlp dễ dàng hơn bằng cách cung cấp GUI trực quan, cài đặt trước cho các lệnh phổ biến và các tính năng bổ sung khác.\n\\n\n\\nĐể sử dụng yt-dlp nâng cao, Seal cho phép bạn tạo, lưu và thực thi trực tiếp các mẫu lệnh tùy chỉnh, giống như trong một thiết bị đầu cuối.\n\\n\n\\nKhi sử dụng các lệnh tùy chỉnh, hầu hết các tùy chọn và tính năng GUI sẽ bị tắt.</string>\n    <string name=\"download_type\">Loại tải xuống</string>\n    <string name=\"clear_download_archive\">Xóa kho lưu trữ tải xuống\\?</string>\n    <string name=\"export_to_file\">Xuất thành tệp</string>\n    <string name=\"commands\">Lệnh</string>\n    <string name=\"clear_download_archive_desc\">Loại bỏ vĩnh viễn %1$s trong tệp lưu trữ\\?</string>\n    <string name=\"unknown\">Không xác định</string>\n    <string name=\"learn_more\">Tìm hiểu thêm</string>\n    <string name=\"presets\">Các cài đặt trước</string>\n    <string name=\"ua_header\">Đầu đề tác nhân người dùng</string>\n    <string name=\"format_preference\">Tùy chọn định dạng</string>\n    <string name=\"output_template\">Mẫu đầu ra</string>\n    <string name=\"output_template_desc\">Chỉ định mẫu cho tên tệp đầu ra</string>\n    <string name=\"refresh_cookies_desc\">Nhấn để mở trang web tạo cookie mới:</string>\n    <string name=\"download_archive_desc\">Ghi lại ID video đã tải xuống vào kho lưu trữ để tránh tải xuống trùng lặp</string>\n    <string name=\"download_archive\">Tải xuống kho lưu trữ</string>\n    <string name=\"remove_multiple_templates_msg\">Loại %1$s khỏi mẫu lệnh vĩnh viễn\\?</string>\n    <string name=\"auto\">Tự động</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">%d mục</item>\n    </plurals>\n    <string name=\"custom\">Tùy chỉnh</string>\n    <string name=\"embed_metadata\">Nhúng siêu dữ liệu</string>\n    <string name=\"embed_metadata_desc\">Nhúng siêu dữ liệu và hình thu nhỏ video vào tệp âm thanh</string>\n    <string name=\"required\">Yêu cầu</string>\n    <string name=\"show_all_items\">Hiển thị tất cả %1$d mục</string>\n    <string name=\"save\">Lưu</string>\n    <string name=\"use_format_sorting\">Sử dụng sắp xếp định dạng</string>\n    <string name=\"restrict_filenames_desc\">Giới hạn tên tệp ở các ký tự cụ thể để đảm bảo tính tương thích</string>\n    <string name=\"restrict_filenames\">Hạn chế tên tệp</string>\n    <string name=\"edit_file\">Chỉnh sửa tệp</string>\n    <string name=\"subdirectory_hint\">Bản tải xuống của bạn sẽ được lưu dưới dạng:</string>\n    <string name=\"keep_subtitle_files\">Giữ các tệp phụ đề</string>\n    <string name=\"website\">Trang mạng</string>\n    <string name=\"playlist_title\">Tiêu đề danh sách phát</string>\n    <string name=\"system_settings\">Thiết đặt hệ thống</string>\n    <string name=\"force_ipv4\">Buộc IPv4</string>\n    <string name=\"force_ipv4_desc\">Thực hiện tất cả các kết nối qua IPv4</string>\n    <string name=\"allow_once\">Cho phép một lần</string>\n    <string name=\"allow_always\">Luôn cho phép</string>\n    <string name=\"download_with_cellular_request\">Cho phép tải xuống bằng mạng di động?</string>\n    <string name=\"merge_audiostream\">Hợp nhất nhiều luồng âm thanh</string>\n    <string name=\"merge_audiostream_desc\">Cho phép hợp nhất nhiều luồng âm thanh vào một tệp duy nhất</string>\n    <string name=\"dont_allow\">Không cho phép</string>\n    <string name=\"auto_translated_subtitles_msg\">Phụ đề dịch tự động cho tất cả các ngôn ngữ sẽ có sẵn trong phần tải xuống. Những phụ đề này có thể không chính xác và khó hiểu.</string>\n    <string name=\"auto_translated_subtitles\">Phụ đề được dịch tự động</string>\n    <string name=\"search_in_downloads\">Tìm kiếm trong phần tải xuống</string>\n    <string name=\"search\">Tìm kiếm</string>\n    <string name=\"subtitle_language_desc\">Ngôn ngữ của phụ đề tải về ở định dạng Auto chọn lọc, phân cách bằng dấu phẩy.</string>\n    <string name=\"remember_for_next_download\">Ghi nhớ cho lần tải tiếp theo</string>\n    <string name=\"look_and_feel\">Cái nhìn &amp; cảm nhận</string>\n    <string name=\"use_previous_selection\">Sử dụng lựa chọn trước đó</string>\n    <string name=\"none\">Không có</string>\n    <string name=\"reset\">Đặt lại</string>\n    <string name=\"search_in_subtitles\">Tìm kiếm trong phụ đề</string>\n    <string name=\"no_thanks\">Không, cám ơn</string>\n    <string name=\"update_language_msg\">Các ngôn ngữ sau sẽ được thêm vào tùy chọn của bạn để tải xuống trong tương lai:</string>\n    <string name=\"update_subtitle_languages\">Cập nhật ngôn ngữ phụ đề?</string>\n    <string name=\"export_download_history\">Xuất lịch sử tải xuống?</string>\n    <string name=\"export_download_history_msg\">Đang xuất %1$s từ lịch sử tải xuống. Các tệp và tùy chọn đã tải xuống sẽ không được sao lưu.</string>\n    <string name=\"interface_and_interaction\">Giao diện và tương tác</string>\n    <string name=\"export_backup\">Xuất</string>\n    <string name=\"import_backup\">Nhập</string>\n    <string name=\"full_backup\">Sao lưu đầy đủ</string>\n    <string name=\"backup_type\">Kiểu sao lưu</string>\n    <string name=\"export_to\">Xuất sang</string>\n    <string name=\"file\">Tệp</string>\n    <string name=\"clipboard\">Bảng nhớ tạm</string>\n    <string name=\"import_from\">Nhập từ</string>\n    <string name=\"import_download_history\">Nhập lịch sử tải xuống?</string>\n    <string name=\"import_download_history_msg\">Các tệp đã tải xuống sẽ không được nhập. Bạn sẽ cần phải tải chúng xuống theo cách thủ công</string>\n    <string name=\"download_history\">Lịch sử tải xuống</string>\n    <string name=\"download_history_imported\">Đã nhập %1$s vào lịch sử tải xuống</string>\n    <string name=\"redownload\">Tải xuống lại</string>\n    <string name=\"download_archive_error\">Video đã được tải xuống. Nếu đây không phải là hành vi mong đợi, vui lòng kiểm tra kho lưu trữ tải xuống của bạn.</string>\n    <string name=\"remux_container_mkv\">Thùng chứa video remux</string>\n    <string name=\"remux_container_mkv_desc\">Remux video vào vùng chứa MKV để có khả năng tương thích tốt hơn</string>\n    <string name=\"cookies_in_database\">Tổng cộng %1$d cookie từ %2$d trang web</string>\n    <string name=\"every_day\">Hằng ngày</string>\n    <string name=\"every_week\">Hàng tuần</string>\n    <string name=\"every_month\">Hàng tháng</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">%d video</item>\n    </plurals>\n    <string name=\"all_languages\">Tất cả ngôn ngữ</string>\n    <string name=\"playlist\">Danh sách phát</string>\n    <string name=\"proceed\">Tiếp tục</string>\n    <string name=\"prefer_placeholder\">­Ưu tiên %1$s</string>\n    <string name=\"preset_format_selection_desc\">Tự động tải xuống sử dụng các thiết lập định dạng của bạn</string>\n    <string name=\"preset\">Cài đặt trước</string>\n    <string name=\"edit_preset\">Chỉnh sửa cài đặt trước</string>\n    <string name=\"best_quality_desc\">Tải xuống định dạng có sẵn tốt nhất</string>\n    <string name=\"task_added\">Nhiệm vụ đã thêm vào danh sách chờ</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">%d âm thanh</item>\n    </plurals>\n    <string name=\"custom_format_selection_desc\">Chọn từ các định dạng, phụ đề và tùy chỉnh nhiều hơn</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-zh-rCN/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"video_url\">视频链接</string>\n    <string name=\"video_directory\">视频目录</string>\n    <string name=\"extract_audio\">保存为音频</string>\n    <string name=\"create_thumbnail\">保存视频封面</string>\n    <string name=\"settings\">设置</string>\n    <string name=\"download_settings_desc\">常规设置、下载格式、自定义命令</string>\n    <string name=\"extract_audio_summary\">下载并保存音频，而非视频</string>\n    <string name=\"create_thumbnail_summary\">以文件形式保存视频封面</string>\n    <string name=\"yt_dlp_up_to_date\">yt-dlp 已更新到最新版本</string>\n    <string name=\"yt_dlp_update_fail\">更新 yt-dlp 失败，请检查与GitHub的连接</string>\n    <string name=\"fetching_info\">正在获取视频信息…</string>\n    <string name=\"permission_denied\">未取得相关权限</string>\n    <string name=\"download_error_msg\">下载视频时发生错误</string>\n    <string name=\"download_start_msg\">开始下载 %1$s</string>\n    <string name=\"fetch_info_error_msg\">获取视频信息时发生错误</string>\n    <string name=\"download_success_msg\">下载完成</string>\n    <string name=\"general_settings\">常规</string>\n    <string name=\"language\">界面语言</string>\n    <string name=\"language_settings\">设置界面语言</string>\n    <string name=\"task_running\">已有正在运行中的下载任务</string>\n    <string name=\"paste_msg\">粘贴 URL</string>\n    <string name=\"paste_fail_msg\">未在剪贴板中匹配到视频链接</string>\n    <string name=\"download\">下载</string>\n    <string name=\"url_empty\">视频链接不能为空</string>\n    <string name=\"ytdlp_version\">下载组件版本</string>\n    <string name=\"ytdlp_update\">点此更新yt-dlp</string>\n    <string name=\"ytdlp_update_action\">更新 yt-dlp</string>\n    <string name=\"delete_info\">从下载记录移除</string>\n    <string name=\"delete_info_msg\">从下载记录中永久移除 “%1$s” 吗？</string>\n    <string name=\"confirm\">确认</string>\n    <string name=\"dismiss\">取消</string>\n    <string name=\"downloads_history\">下载记录</string>\n    <string name=\"audio\">音频</string>\n    <string name=\"link_copied\">链接已复制到剪贴板</string>\n    <string name=\"open_url\">打开链接</string>\n    <string name=\"remove\">移除</string>\n    <string name=\"delete_file\">删除文件</string>\n    <string name=\"about\">关于</string>\n    <string name=\"about_page\">版本、意见反馈、自动更新</string>\n    <string name=\"back\">返回</string>\n    <string name=\"version\">当前版本</string>\n    <string name=\"release\">版本发布</string>\n    <string name=\"release_desc\">查看最新版本与更新日记</string>\n    <string name=\"readme_desc\">查看 GitHub 项目地址与应用说明</string>\n    <string name=\"video\">视频</string>\n    <string name=\"checked\">已选中</string>\n    <string name=\"credits\">致谢</string>\n    <string name=\"credits_desc\">资源与开源软件</string>\n    <string name=\"custom_command\">自定义命令</string>\n    <string name=\"custom_command_desc\">使用自定义的命令模板运行 yt-dlp</string>\n    <string name=\"custom_command_template\">命令模板</string>\n    <string name=\"edit\">编辑</string>\n    <string name=\"start_execute\">开始执行命令</string>\n    <string name=\"advanced_settings\">高级</string>\n    <string name=\"print_details\">显示详细信息</string>\n    <string name=\"print_details_desc\">显示详细的界面信息与错误报告</string>\n    <string name=\"display\">显示</string>\n    <string name=\"dark_theme\">深色模式</string>\n    <string name=\"follow_system\">跟随系统</string>\n    <string name=\"on\">开启</string>\n    <string name=\"off\">关闭</string>\n    <string name=\"cancel\">取消</string>\n    <string name=\"settings_before_download\">下载前设置</string>\n    <string name=\"settings_before_download_desc\">在开始下载前确认下载设置</string>\n    <string name=\"error_copied\">错误报告已复制到剪贴板</string>\n    <string name=\"thumbnail\">缩略图</string>\n    <string name=\"paste\">粘贴</string>\n    <string name=\"yt_dlp_docs\">yt-dlp 使用文档</string>\n    <string name=\"edit_template_desc\">应用会自动向命令中添加输出路径与链接</string>\n    <string name=\"convert_audio_format\">音频格式转换</string>\n    <string name=\"not_convert\">不进行格式转换</string>\n    <string name=\"convert_to\">转换为 %1$s 格式</string>\n    <string name=\"format\">格式</string>\n    <string name=\"convert_audio_format_desc\">重编码音频文件将会造成音质损失并增大文件大小。</string>\n    <string name=\"video_quality\">视频画质</string>\n    <string name=\"best_quality\">最高画质</string>\n    <string name=\"video_quality_desc\">下载画质不高于所选分辨率的最清晰视频</string>\n    <string name=\"not_specified\">默认</string>\n    <string name=\"video_format_preference\">视频格式偏好</string>\n    <string name=\"preferred_format_desc\">当多种格式可供下载时的偏好选项</string>\n    <string name=\"video_format\">视频格式</string>\n    <string name=\"convert_audio\">音频转码</string>\n    <string name=\"start_download\">开始下载</string>\n    <string name=\"close\">关闭</string>\n    <string name=\"close_never_show_again\">关闭后不再显示</string>\n    <string name=\"user_guide\">使用指引</string>\n    <string name=\"open_settings\">打开应用设置</string>\n    <string name=\"paste_desc\">点击粘贴按钮，从剪贴板获取复制的视频链接。</string>\n    <string name=\"download_desc\">随后点击下载按钮，在开始下载前，你可以修改用于本次下载的设置。</string>\n    <string name=\"download_history_desc\">在下载记录页，查看与管理包括视频与音频在内的应用内下载。</string>\n    <string name=\"check_download_settings_desc\">在开始使用前，建议先对下载设置进行确认，并且将 yt-dlp 更新到最新版本。</string>\n    <string name=\"download_playlist\">下载播放列表</string>\n    <string name=\"download_playlist_desc\">一次性下载播放列表中的多个视频</string>\n    <string name=\"defaults\">默认</string>\n    <string name=\"display_settings\">深色主题、动态色彩、语言</string>\n    <string name=\"settings_before_download_text\">确认此次下载的下载设置</string>\n    <string name=\"channel_name\">下载</string>\n    <string name=\"channel_description\">显示下载进度与完成信息</string>\n    <string name=\"download_finish_notification\">下载完成，轻按打开。</string>\n    <string name=\"execute_command_notification\">正在执行自定义命令…</string>\n    <string name=\"battery_settings_desc\">为防止后台下载时系统结束进程，请在系统设置的电池管理中将此应用设置为“无限制”。</string>\n    <string name=\"concurrent_download\">多线程下载</string>\n    <string name=\"concurrent_download_desc\">使用多线程下载 HLS/DASH 流视频</string>\n    <string name=\"concurrent_download_num\">将同时使用 %d 个线程下载 HLS/DASH 流视频</string>\n    <string name=\"options\">选项</string>\n    <string name=\"additional_settings\">附加设置</string>\n    <string name=\"share_fail_msg\">未能从分享内容中匹配到视频链接</string>\n    <string name=\"share_success_msg\">从分享内容获取视频链接</string>\n    <string name=\"show_more_actions\">显示更多操作</string>\n    <string name=\"download_notification\">下载通知</string>\n    <string name=\"download_notification_desc\">在系统通知中显示下载进度与完成信息</string>\n    <string name=\"fetching_playlist_info\">正在获取播放列表信息…</string>\n    <string name=\"download_range_selection\">下载范围选择</string>\n    <string name=\"download_range_desc\">指定要从播放列表\\\"%3$s\\\"下载的视频（序号范围：%1$d-%2$d）。</string>\n    <string name=\"from\">起始序号</string>\n    <string name=\"to\">结束序号</string>\n    <string name=\"invalid_index_range\">序号范围非法</string>\n    <string name=\"playlist_indicator_text\">正在下载播放列表(%1$d/%2$d)…</string>\n    <string name=\"audio_directory\">音频目录</string>\n    <string name=\"download_directory\">下载目录</string>\n    <string name=\"download_directory_desc\">设置视频及音频文件的下载目录</string>\n    <string name=\"subdirectory\">下载到子目录</string>\n    <string name=\"subdirectory_desc\">将文件保存到以各自字段命名的文件夹中</string>\n    <string name=\"permission_issue\">存储权限提示</string>\n    <string name=\"permission_issue_desc\">无法下载到除 Download/ 及 Documents/ 以外的目录</string>\n    <string name=\"battery_configuration\">后台下载设置</string>\n    <string name=\"battery_configuration_desc\">允许本应用在后台运行以在后台进行下载</string>\n    <string name=\"service_title\">Seal 正在进行下载…</string>\n    <string name=\"unknown_error\">出现不可预知的错误</string>\n    <string name=\"translate\">翻译</string>\n    <string name=\"translate_desc\">在 Weblate 上帮助我们翻译此应用</string>\n    <string name=\"prefix\">输出路径模板</string>\n    <string name=\"embed_subtitles\">封装字幕</string>\n    <string name=\"embed_subtitles_desc\">如可用将软字幕嵌入到视频中</string>\n    <string name=\"new_template\">新建命令模板</string>\n    <string name=\"template_label\">模板标签</string>\n    <string name=\"remove_template\">移除？</string>\n    <string name=\"remove_template_desc\">从命令行模板中永久移除 \\\"%1$s\\\" 吗？</string>\n    <string name=\"template_selection\">模板选择</string>\n    <string name=\"custom_command_template_desc\">编辑与管理命令模板</string>\n    <string name=\"downloading_indicator_text\">下载进行中，轻按取消…</string>\n    <string name=\"task_canceled\">下载任务被取消</string>\n    <string name=\"github_issue\">GitHub 议题</string>\n    <string name=\"github_issue_desc\">提交错误报告或改进建议</string>\n    <string name=\"info_copied\">信息已复制到剪贴板</string>\n    <string name=\"status_enqueued\">等待开始</string>\n    <string name=\"status_completed\">已完成</string>\n    <string name=\"status_downloading\">下载中</string>\n    <string name=\"status_canceled\">已取消</string>\n    <string name=\"status_fetching_video_info\">正在获取信息</string>\n    <string name=\"open_file\">打开文件</string>\n    <string name=\"restart\">重新开始</string>\n    <string name=\"status_error\">发生错误</string>\n    <string name=\"copy_link\">复制链接</string>\n    <string name=\"copy_error_report\">复制报告</string>\n    <string name=\"video_resolution\">分辨率</string>\n    <string name=\"video_file_size\">视频文件大小</string>\n    <string name=\"export_to_clipboard\">导出到剪贴板</string>\n    <string name=\"import_from_clipboard\">从剪贴板导入</string>\n    <string name=\"template_exported\">共导出了 %1$d 条模板</string>\n    <string name=\"template_imported\">共导入了 %1$d 条模板</string>\n    <string name=\"download_task_count\">%1$d 下载任务</string>\n    <string name=\"recently_added\">最近添加</string>\n    <string name=\"multiselect_item_count\">%1$d 视频，%2$d 音频</string>\n    <string name=\"delete_multiple_items_msg\">从下载记录中永久删除 %1$d 条记录吗？</string>\n    <string name=\"sponsorblock_desc\">使用 SponsorBlock API 移除视频中的片段</string>\n    <string name=\"sponsorblock_categories_desc\">指定要从视频中移除的片段类别</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock 分类标记</string>\n    <string name=\"check_for_updates\">检查更新</string>\n    <string name=\"check_for_updates_desc\">自动检查并更新到 GitHub 上的最新版本</string>\n    <string name=\"app_up_to_date\">当前版本已为最新</string>\n    <string name=\"app_update_failed\">更新过程中出现错误</string>\n    <string name=\"update\">更新</string>\n    <string name=\"aria2_desc\">使用 aria2c 下载器进行下载</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"cookies_desc\">使用 Netscape 规范的 Cookies 文件进行下载</string>\n    <string name=\"clear_temp_files\">清除临时文件</string>\n    <string name=\"clear_temp_files_desc\">删除临时目录下的所有临时文件</string>\n    <string name=\"clear_temp_files_count\">共清除了 %1$d 个临时文件</string>\n    <string name=\"clear_temp_files_info\">临时文件可用于恢复被取消的下载，是否要清除当前下载目录下的所有临时文件？\n\\n\n\\n你可以在 %1$s 访问这些文件</string>\n    <string name=\"multiselect_mode\">多选模式</string>\n    <string name=\"private_mode\">无痕模式</string>\n    <string name=\"private_mode_desc\">停止保存下载记录</string>\n    <string name=\"dynamic_color\">动态色彩</string>\n    <string name=\"dynamic_color_desc\">将壁纸颜色应用于应用主题</string>\n    <string name=\"download_with_cellular\">使用移动数据下载</string>\n    <string name=\"download_with_cellular_desc\">允许使用计费网络进行下载</string>\n    <string name=\"download_disabled_with_cellular\">使用移动数据网络下载已在设置中被禁用</string>\n    <string name=\"file_unavailable\">无法打开此文件，其可能已被移动或删除</string>\n    <string name=\"network\">网络</string>\n    <string name=\"rate_limit\">限速下载</string>\n    <string name=\"rate_limit_desc\">限制最大下载速度</string>\n    <string name=\"max_rate\">最高速率</string>\n    <string name=\"high_contrast\">高对比度深色主题</string>\n    <string name=\"invalid_input\">输入不合法</string>\n    <string name=\"lowest_quality\">最低画质</string>\n    <string name=\"unavailable\">不可用</string>\n    <string name=\"format_settings_desc\">文件格式、视频画质、字幕</string>\n    <string name=\"general_settings_desc\">Yt-dlp 版本、通知、隐私</string>\n    <string name=\"network_settings_desc\">限速下载、下载工具、cookies</string>\n    <string name=\"disable_preview\">禁用预览</string>\n    <string name=\"disable_preview_desc\">在下载时不显示视频预览图</string>\n    <string name=\"privacy\">隐私</string>\n    <string name=\"use_custom_command\">启用自定义命令</string>\n    <string name=\"private_directory\">隐藏目录</string>\n    <string name=\"private_directory_desc\">将文件下载到隐藏目录中</string>\n    <string name=\"crop_artwork\">裁剪封面</string>\n    <string name=\"crop_artwork_desc\">将音频中内嵌的封面图片裁切为正方形</string>\n    <string name=\"download_selection_desc\">选择要从播放列表 “%1$s” 中下载的视频</string>\n    <string name=\"select_all\">全选</string>\n    <string name=\"selected_item_count\">已选中 %1$d 项</string>\n    <string name=\"video_only\">视频（无音轨）</string>\n    <string name=\"suggested\">推荐</string>\n    <string name=\"format_selection\">格式选择</string>\n    <string name=\"format_selection_desc\">在开始下载前选择要下载的格式</string>\n    <string name=\"generate_new_cookies\">生成新的 Cookies</string>\n    <string name=\"use_cookies\">启用 Cookies</string>\n    <string name=\"remove_cookie_profile_desc\">删除 \\\"%1$s\\\" 的此条目？请注意这不会清理此站点的 cookies 文件。</string>\n    <string name=\"custom_command_enabled_hint\">部分选项在自定义命令模式下不可用</string>\n    <string name=\"how_does_it_work\">使用说明</string>\n    <string name=\"cookies_usage_msg\">从某些站点下载需要帐户验证信息。 点击“生成新的 Cookies”，输入网站的 URL，然后在浏览器页面使用你的账户登录，应用将会自动生成并在下载时输入认证信息。</string>\n    <string name=\"telegram_channel\">Telegram 频道</string>\n    <string name=\"matrix_space\">Matrix 空间</string>\n    <string name=\"sdcard_directory\">SD 卡目录</string>\n    <string name=\"auto_subtitle\">自动生成的字幕</string>\n    <string name=\"auto_subtitle_desc\">下载自动生成的字幕</string>\n    <string name=\"title_activity_share\">一键下载</string>\n    <string name=\"abs_hint\">大部分视频平台将音频流与视频流分开传输，你可以同时选取仅音频格式与仅视频格式，将其合并为一个视频。</string>\n    <string name=\"video_title_sample_text\">视频标题</string>\n    <string name=\"video_creator_sample_text\">视频作者</string>\n    <string name=\"subtitle\">字幕</string>\n    <string name=\"download_subtitles\">下载字幕</string>\n    <string name=\"subtitle_language\">字幕语言</string>\n    <string name=\"subtitle_desc\">语言，封装字幕，自动字幕</string>\n    <string name=\"copy_log\">复制日志</string>\n    <string name=\"clear\">清除</string>\n    <string name=\"edit_shortcuts\">编辑快捷命令</string>\n    <string name=\"add\">添加</string>\n    <string name=\"shortcuts\">快捷命令</string>\n    <string name=\"edit_shortcuts_desc\">编辑可用于撰写命令行模板的定制快捷方式。</string>\n    <string name=\"running_tasks\">任务列表</string>\n    <string name=\"show_logs\">显示日志</string>\n    <string name=\"logs\">日志</string>\n    <string name=\"subtitle_sponsorblock\">从视频中移除 SponsorBlock 段落会导致字幕时间轴错位。</string>\n    <string name=\"embed_subtitles_mkv_msg\">为嵌入软字幕，视频将被封装到 MKV 容器中。你可以使用 VLC 播放器或其他兼容的应用播放内嵌软字幕的视频。</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"share\">分享</string>\n    <string name=\"stable_channel\">稳定</string>\n    <string name=\"pre_release_channel\">预览</string>\n    <string name=\"update_channel_desc\">安装预览版本提前体验新功能与变化。\n\\n\n\\n预览版本可能不太稳定，如在使用的过程中遇到任何问题，请毫不犹豫向我们进行反馈，以帮助我们更好地优化应用。</string>\n    <string name=\"update_channel\">更新频道</string>\n    <string name=\"auto_update\">自动更新</string>\n    <string name=\"enable_auto_update\">启用自动更新</string>\n    <string name=\"discard\">撤销</string>\n    <string name=\"apply\">应用</string>\n    <string name=\"clip_video\">剪辑视频</string>\n    <string name=\"clip_start\">开始时间</string>\n    <string name=\"clip_end\">结束时间</string>\n    <string name=\"audio_format_preference\">音频格式偏好</string>\n    <string name=\"lowest_bitrate\">最低质量</string>\n    <string name=\"unlimited\">无限制</string>\n    <string name=\"audio_quality\">音频质量</string>\n    <string name=\"second\">秒</string>\n    <string name=\"format_sorting\">格式排序</string>\n    <string name=\"audio_quality_desc\">当有多种音质可选时所要下载的音频码率</string>\n    <string name=\"title\">标题</string>\n    <string name=\"format_sorting_desc\">使用 yt-dlp 的 -S 命令对格式进行排序</string>\n    <string name=\"import_from_preferences\">从设置导入</string>\n    <string name=\"rename\">重命名</string>\n    <string name=\"minute\">分</string>\n    <string name=\"clear_all_cookies\">清除所有 Cookies</string>\n    <string name=\"clear_all_cookies_desc\">确定要删除储存在应用中的所有 Cookies 吗？</string>\n    <string name=\"temporary_directory_desc\">将临时文件储存在内部目录中</string>\n    <string name=\"sponsor\">赞助</string>\n    <string name=\"sponsor_desc\">在 GitHub 上赞助以支持本应用</string>\n    <string name=\"sponsor_msg\">Seal 将永远保持免费与开源，如果你想要支持它的持续开发与改进，请考虑在 GitHub 上赞助我！</string>\n    <string name=\"feedback\">反馈</string>\n    <string name=\"sponsors\">赞助</string>\n    <string name=\"no_downloaded_media\">下载记录空空如也</string>\n    <string name=\"beta_features\">测试</string>\n    <string name=\"enable_experimental_feature\">启用试验性功能吗？</string>\n    <string name=\"clip_video_desc\">在格式选择页面进行视频剪辑</string>\n    <string name=\"clip_video_dialog_msg\">该功能将使用 FFmpeg 以下载选定部分的视频，该功能仍处于试验阶段，剪辑不会完全准确，且并非所有格式都支持该功能，使用该功能时的下载速度将会显著减慢。</string>\n    <string name=\"audio_format\">音频格式</string>\n    <string name=\"auto_update_disabled_msg\">%1$s 版本无法使用自动更新，如果你的设备并未安装 %1$s，或想要升级到测试版本以提前体验 Seal 中即将加入的新功能，请考虑 %2$s。</string>\n    <string name=\"switch_to_github_builds\">切换至 GitHub 版本</string>\n    <string name=\"okay\">好</string>\n    <string name=\"got_it\">好</string>\n    <string name=\"feature_unavailable\">此功能不可用</string>\n    <string name=\"sponsor_msg2\">感激不尽！</string>\n    <string name=\"convert_subtitle\">转换字幕格式</string>\n    <string name=\"convert_subtitle_desc\">将字幕文件转换为另一格式</string>\n    <string name=\"split_video\">切分视频</string>\n    <string name=\"split_video_msg\">视频会被切分为 %1$d 个片段</string>\n    <string name=\"unknown_error_title\">糟糕！出现了不可预知的错误</string>\n    <string name=\"msg_from_developer\">开发者的话</string>\n    <string name=\"copy_and_exit\">复制并退出</string>\n    <string name=\"no_custom_command_tasks\">没有正在执行中的自定义命令任务</string>\n    <string name=\"download_video_desc\">从链接下载视频文件</string>\n    <string name=\"expand\">展开</string>\n    <string name=\"new_task\">新下载任务</string>\n    <string name=\"start\">开始</string>\n    <string name=\"edit_template\">编辑命令模板 \\\"%1$s\\\"</string>\n    <string name=\"proxy\">代理设置</string>\n    <string name=\"proxy_desc\">使用代理进行网络连接</string>\n    <string name=\"legacy\">兼容优先</string>\n    <string name=\"quality\">质量优先</string>\n    <string name=\"enable_notifications\">启用通知？</string>\n    <string name=\"enable_notifications_desc\">应用需要通知权限以发送有关下载状态与进度的通知。</string>\n    <string name=\"disable\">禁用</string>\n    <string name=\"set_directory_desc\">点此设置下载目录</string>\n    <string name=\"custom_command_directory\">自定义命令目录</string>\n    <string name=\"disabled\">已禁用</string>\n    <string name=\"folder_picker\">目录选择</string>\n    <string name=\"custom_command_directory_desc\">制定自定义命令模式下要使用的下载路径</string>\n    <string name=\"prefer_compatibility_desc\">优先下载 MP4(H.264) 格式的视频以分享到其他应用</string>\n    <string name=\"prefer_quality_desc\">优先下载 AV1、VP9 或 H.265 编码的视频以在兼容的应用中播放</string>\n    <string name=\"download_type\">下载类型</string>\n    <string name=\"custom\">自定义</string>\n    <string name=\"auto\">自动</string>\n    <string name=\"commands\">命令行</string>\n    <string name=\"format_preference\">格式偏好</string>\n    <string name=\"learn_more\">了解更多信息</string>\n    <string name=\"unknown\">未知</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">%d 个项目</item>\n    </plurals>\n    <string name=\"remove_multiple_templates_msg\">要从命令模板中移除 %1$s吗？</string>\n    <string name=\"refresh_cookies_desc\">点击打开网页以刷新 cookies：</string>\n    <string name=\"ua_header\">用户代理</string>\n    <string name=\"export_to_file\">导出到文件</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp 是一款强大的命令行视频下载工具。通过提供直观的图形用户界面（GUI）、 常见命令行的预设以及其他附加功能，Seal 使该工具更易使用。\n\\n\n\\n对于 yt-dlp 的高级用法，Seal 允许你直接创建、保存并执行自定义的命令行模板，就像在命令行终端上操作一样。\n\\n\n\\n使用自定义命令行时，多数 GUI 选项和功能会被禁用。</string>\n    <string name=\"presets\">预设</string>\n    <string name=\"output_template\">输出模板</string>\n    <string name=\"output_template_desc\">指定输出文件名的模板</string>\n    <string name=\"clear_download_archive\">清理下载存档？</string>\n    <string name=\"clear_download_archive_desc\">永久性删除归档文件中的 %1$s？</string>\n    <string name=\"download_archive_desc\">将已下载视频的 ID 记录在一个归档文件中避免重复下载</string>\n    <string name=\"download_archive\">下载存档</string>\n    <string name=\"embed_metadata\">内嵌元数据</string>\n    <string name=\"embed_metadata_desc\">将元数据和视频缩略图内嵌到音频文件</string>\n    <string name=\"required\">必需的</string>\n    <string name=\"show_all_items\">显示全部 %1$d 项</string>\n    <string name=\"save\">保存</string>\n    <string name=\"use_format_sorting\">使用格式排序</string>\n    <string name=\"edit_file\">编辑文件</string>\n    <string name=\"restrict_filenames_desc\">只允许文件名包含特定字符来确保兼容性</string>\n    <string name=\"restrict_filenames\">限制文件名</string>\n    <string name=\"website\">网站</string>\n    <string name=\"playlist_title\">播放列表标题</string>\n    <string name=\"subdirectory_hint\">下载将被另存为：</string>\n    <string name=\"system_settings\">系统设置</string>\n    <string name=\"force_ipv4\">强制使用 IPv4</string>\n    <string name=\"force_ipv4_desc\">使所有连接通过 IPv4 进行</string>\n    <string name=\"keep_subtitle_files\">保留字幕文件</string>\n    <string name=\"allow_once\">允许一次</string>\n    <string name=\"dont_allow\">不允许</string>\n    <string name=\"download_with_cellular_request\">允许用移动网络数据下载吗？</string>\n    <string name=\"allow_always\">始终允许</string>\n    <string name=\"merge_audiostream\">合并多个音频流</string>\n    <string name=\"merge_audiostream_desc\">允许多个音频流被合并到单一文件</string>\n    <string name=\"search_in_downloads\">在下载中搜索</string>\n    <string name=\"search\">搜索</string>\n    <string name=\"auto_translated_subtitles\">自动翻译的字幕</string>\n    <string name=\"auto_translated_subtitles_msg\">所有自动翻译的字幕都将在下载中可用。这些字幕可能不精确且难以理解。</string>\n    <string name=\"remember_for_next_download\">下次下载时仍使用这些设置</string>\n    <string name=\"look_and_feel\"><![CDATA[视觉和样式]]></string>\n    <string name=\"use_previous_selection\">使用先前所选</string>\n    <string name=\"none\">无</string>\n    <string name=\"subtitle_language_desc\">指定在自动格式选择中要下载哪些语言的字幕，语言名称间用英文逗号隔开。</string>\n    <string name=\"reset\">重置</string>\n    <string name=\"no_thanks\">不，谢了</string>\n    <string name=\"update_language_msg\">今后下载文件时将下载下列语言的字幕：</string>\n    <string name=\"update_subtitle_languages\">更新字幕语言？</string>\n    <string name=\"search_in_subtitles\">在字幕中搜索</string>\n    <string name=\"export_backup\">导出</string>\n    <string name=\"import_backup\">导入</string>\n    <string name=\"export_download_history\">导出下载历史记录？</string>\n    <string name=\"export_download_history_msg\">正在从下载历史记录中导出 %1$s。已下载的文件和偏好设置不会被备份。</string>\n    <string name=\"interface_and_interaction\"><![CDATA[界面与交互]]></string>\n    <string name=\"full_backup\">完整备份</string>\n    <string name=\"backup_type\">备份类型</string>\n    <string name=\"file\">文件</string>\n    <string name=\"clipboard\">剪贴板</string>\n    <string name=\"import_from\">导入位置</string>\n    <string name=\"import_download_history\">导入下载历史记录？</string>\n    <string name=\"import_download_history_msg\">已下载的文件不会被导入 您需要手动重新下载它们</string>\n    <string name=\"download_history\">下载历史</string>\n    <string name=\"download_history_imported\">已将 %1$s 导入下载历史记录</string>\n    <string name=\"redownload\">重新下载</string>\n    <string name=\"export_to\">导出到</string>\n    <string name=\"download_archive_error\">此视频已被下载。如果这不是预期的行为，请检查你的下载存档。</string>\n    <string name=\"remux_container_mkv\">视频封装容器</string>\n    <string name=\"remux_container_mkv_desc\">封装视频至 MKV 容器，改进兼容性</string>\n    <string name=\"cookies_in_database\">共 %1$d 个 cookies，来自 %2$d 个站点</string>\n    <string name=\"every_day\">每天</string>\n    <string name=\"every_week\">每周</string>\n    <string name=\"every_month\">每月</string>\n    <string name=\"proceed\">继续</string>\n    <string name=\"best_quality_desc\">下载可用的最佳格式</string>\n    <string name=\"prefer_placeholder\">首选 %1$s</string>\n    <string name=\"preset_format_selection_desc\">使用格式偏好自动下载</string>\n    <string name=\"edit_preset\">编辑预设</string>\n    <string name=\"all_languages\">所有语言</string>\n    <string name=\"preset\">预设</string>\n    <string name=\"playlist\">播放列表</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">%d 个音频</item>\n    </plurals>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">%d 个视频</item>\n    </plurals>\n    <string name=\"custom_format_selection_desc\">选择格式和字幕并进一步定制</string>\n    <string name=\"task_added\">已添加任务到队列</string>\n    <string name=\"you_ll_find_your_downloads_here\">你会在这里找到下载文件</string>\n    <string name=\"download_hint\">轻按下载按钮或分享视频链接到本应用来启动下载</string>\n    <string name=\"status_downloaded\">已下载</string>\n    <string name=\"all\">全部</string>\n    <string name=\"select_multiple_link\">从 %1$d 个链接中选择</string>\n    <string name=\"download_queue\">下载队列</string>\n    <string name=\"show_navigation_drawer\">显示导航抽屉</string>\n    <string name=\"resume\">继续</string>\n    <string name=\"delete\">删除</string>\n    <string name=\"media_info\">媒体信息</string>\n    <string name=\"trouble_shooting\">故障排除</string>\n    <string name=\"issue_tracker\">问题跟踪器</string>\n    <string name=\"trouble_shooting_desc\">修复常见问题并检查已知问题</string>\n    <string name=\"issue_tracker_hint\">遇到问题了？报告新问题前，请搜索我们的问题跟踪器。许多常见问题已在那里被解决并有记录。</string>\n    <string name=\"saved_urls\">保存的链接</string>\n    <string name=\"add_new_url\">添加新链接</string>\n    <string name=\"add_to\">添加到 %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-zh-rTW/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"paste_msg\">貼上 URL</string>\n    <string name=\"extract_audio_summary\">下載並儲存音訊，而非影片</string>\n    <string name=\"yt_dlp_up_to_date\">正在使用最新版本的 yt-dlp</string>\n    <string name=\"url_empty\">連結不可為空</string>\n    <string name=\"settings\">設定</string>\n    <string name=\"download\">下載</string>\n    <string name=\"yt_dlp_update_fail\">無法安裝最新版本的 yt-dlp。請確認您已連線至網際網路。</string>\n    <string name=\"fetch_info_error_msg\">無法擷取影片資訊</string>\n    <string name=\"general_settings\">一般</string>\n    <string name=\"audio\">音訊</string>\n    <string name=\"open_url\">開啟連結</string>\n    <string name=\"remove\">移除</string>\n    <string name=\"delete_file\">刪除檔案</string>\n    <string name=\"about\">關於</string>\n    <string name=\"about_page\">版本、意見反應、自動更新</string>\n    <string name=\"back\">返回</string>\n    <string name=\"version\">版本</string>\n    <string name=\"release_desc\">查看更新日誌和最新版本</string>\n    <string name=\"release\">最新版本</string>\n    <string name=\"download_settings_desc\">一般、格式、自訂命令</string>\n    <string name=\"fetching_info\">正在擷取影片資訊…</string>\n    <string name=\"download_success_msg\">下載完成</string>\n    <string name=\"permission_denied\">存取遭拒</string>\n    <string name=\"download_error_msg\">無法下載檔案</string>\n    <string name=\"confirm\">確認</string>\n    <string name=\"language\">介面語言</string>\n    <string name=\"ytdlp_update\">點擊以下載最新版本的 yt-dlp</string>\n    <string name=\"dismiss\">取消</string>\n    <string name=\"credits\">鳴謝</string>\n    <string name=\"downloads_history\">下載</string>\n    <string name=\"language_settings\">設定介面語言</string>\n    <string name=\"ytdlp_version\">Yt-dlp 版本</string>\n    <string name=\"task_running\">現有的下載任務仍在執行</string>\n    <string name=\"delete_info\">確定移除？</string>\n    <string name=\"video\">影片</string>\n    <string name=\"checked\">已選取</string>\n    <string name=\"custom_command\">自訂命令</string>\n    <string name=\"credits_desc\">來源與自由軟體</string>\n    <string name=\"video_directory\">影片資料夾</string>\n    <string name=\"extract_audio\">儲存為音訊</string>\n    <string name=\"create_thumbnail_summary\">另存影片縮圖</string>\n    <string name=\"download_start_msg\">下載「%1$s」</string>\n    <string name=\"paste_fail_msg\">在剪貼簿中沒有相符的 URL</string>\n    <string name=\"delete_info_msg\">確定要從下載記錄中移除「%1$s」嗎？</string>\n    <string name=\"link_copied\">已複製連結到剪貼簿</string>\n    <string name=\"readme_desc\">查看 GitHub 存放庫和 README</string>\n    <string name=\"custom_command_desc\">使用自訂的範本來執行 yt-dlp 命令</string>\n    <string name=\"custom_command_template\">命令範本</string>\n    <string name=\"edit\">編輯</string>\n    <string name=\"start_execute\">開始執行命令</string>\n    <string name=\"display\">顯示</string>\n    <string name=\"display_settings\">深色主題、動態色彩、語言</string>\n    <string name=\"dark_theme\">深色主題</string>\n    <string name=\"follow_system\">系統預設</string>\n    <string name=\"on\">開啟</string>\n    <string name=\"off\">關閉</string>\n    <string name=\"cancel\">取消</string>\n    <string name=\"print_details\">詳細資訊</string>\n    <string name=\"advanced_settings\">進階</string>\n    <string name=\"print_details_desc\">下載時顯示詳細資訊</string>\n    <string name=\"create_thumbnail\">另存縮圖</string>\n    <string name=\"settings_before_download_desc\">下載前配置偏好設定</string>\n    <string name=\"settings_before_download\">下載前配置</string>\n    <string name=\"settings_before_download_text\">調整本次下載的配置</string>\n    <string name=\"yt_dlp_docs\">Yt-dlp 使用參考</string>\n    <string name=\"edit_template_desc\">應用程式將自動加入輸出路徑和 URL。</string>\n    <string name=\"convert_audio_format\">轉換音訊格式</string>\n    <string name=\"not_convert\">不轉換</string>\n    <string name=\"convert_to\">轉換成 %1$s</string>\n    <string name=\"format\">格式</string>\n    <string name=\"convert_audio_format_desc\">音訊重新編碼將造成品質下降和檔案大小增加。</string>\n    <string name=\"best_quality\">最佳品質</string>\n    <string name=\"video_quality_desc\">當存在多種選項時限縮影片品質</string>\n    <string name=\"not_specified\">不指定 (預設)</string>\n    <string name=\"video_quality\">影片品質</string>\n    <string name=\"video_format\">影片格式</string>\n    <string name=\"preferred_format_desc\">當提供多種選項時的偏好格式</string>\n    <string name=\"open_settings\">開啟設定</string>\n    <string name=\"download_playlist\">下載播放清單</string>\n    <string name=\"defaults\">預設</string>\n    <string name=\"download_history_desc\">檢查並管理應用程式內下載，包含影片檔和音訊檔。</string>\n    <string name=\"check_download_settings_desc\">檢查下載配置並確保在使用前擁有最新版本的 yt-dlp。</string>\n    <string name=\"download_playlist_desc\">從播放清單中下載多項影片</string>\n    <string name=\"channel_name\">下載</string>\n    <string name=\"execute_command_notification\">正在執行自訂命令…</string>\n    <string name=\"concurrent_download\">多執行緒下載</string>\n    <string name=\"video_url\">影片連結</string>\n    <string name=\"battery_settings_desc\">請將此應用程式的系統電池用量設定設為「無限制」以利背景下載。</string>\n    <string name=\"show_more_actions\">顯示更多操作</string>\n    <string name=\"share_success_msg\">正在從分享內容中讀取影片連結…</string>\n    <string name=\"concurrent_download_num\">%d 個執行緒將用於同時下載 DASH/HLS 原生影片。</string>\n    <string name=\"download_notification\">下載通知</string>\n    <string name=\"fetching_playlist_info\">正在擷取播放清單資訊…</string>\n    <string name=\"download_range_selection\">播放清單範圍</string>\n    <string name=\"invalid_index_range\">無效的索引範圍</string>\n    <string name=\"playlist_indicator_text\">正在下載播放清單 (%1$d/%2$d)…</string>\n    <string name=\"download_notification_desc\">通知下載檔案和進度資訊</string>\n    <string name=\"from\">起始編號</string>\n    <string name=\"to\">結束編號</string>\n    <string name=\"audio_directory\">音訊資料夾</string>\n    <string name=\"download_directory\">下載目錄</string>\n    <string name=\"subdirectory_desc\">儲存檔案到以相應欄位命名的資料夾</string>\n    <string name=\"permission_issue_desc\">不支援 Download/ 和 Documents/ 以外的目錄</string>\n    <string name=\"battery_configuration\">電池配置</string>\n    <string name=\"service_title\">Seal 正在下載…</string>\n    <string name=\"unknown_error\">未知錯誤</string>\n    <string name=\"translate\">翻譯</string>\n    <string name=\"translate_desc\">在 Hosted Weblate 上協助翻譯此應用程式</string>\n    <string name=\"prefix\">路徑範本</string>\n    <string name=\"new_template\">新增範本</string>\n    <string name=\"embed_subtitles_desc\">如有提供可用的軟字幕，則將其內嵌至影片中</string>\n    <string name=\"permission_issue\">儲存權限有已知問題</string>\n    <string name=\"battery_configuration_desc\">忽略此應用程式的電池最佳化設定以利背景下載</string>\n    <string name=\"template_label\">標籤</string>\n    <string name=\"remove_template\">確定移除？</string>\n    <string name=\"remove_template_desc\">確定要從命令範例中移除「%1$s」嗎？</string>\n    <string name=\"template_selection\">範本選取</string>\n    <string name=\"github_issue_desc\">提交錯誤報告或功能請求議題</string>\n    <string name=\"info_copied\">已複製資訊到剪貼簿</string>\n    <string name=\"status_enqueued\">等候開始</string>\n    <string name=\"status_completed\">已完成</string>\n    <string name=\"status_downloading\">正在下載</string>\n    <string name=\"status_fetching_video_info\">正在擷取資訊</string>\n    <string name=\"open_file\">開啟檔案</string>\n    <string name=\"restart\">重新啟動</string>\n    <string name=\"status_error\">錯誤</string>\n    <string name=\"video_resolution\">影片解析度</string>\n    <string name=\"video_file_size\">影片檔大小</string>\n    <string name=\"start_download\">下載</string>\n    <string name=\"user_guide\">使用指南</string>\n    <string name=\"paste\">貼上</string>\n    <string name=\"thumbnail\">縮圖</string>\n    <string name=\"error_copied\">已複製錯誤報告到剪貼簿</string>\n    <string name=\"video_format_preference\">影片格式偏好</string>\n    <string name=\"options\">選項</string>\n    <string name=\"close\">關閉</string>\n    <string name=\"close_never_show_again\">不再顯示</string>\n    <string name=\"convert_audio\">轉換</string>\n    <string name=\"paste_desc\">點擊 [貼上] 從您的剪貼簿取得影片連結。</string>\n    <string name=\"download_desc\">然後調整設定後點擊 [下載]。</string>\n    <string name=\"channel_description\">通知下載檔案和進度資訊</string>\n    <string name=\"download_finish_notification\">下載完成。輕觸以開啟。</string>\n    <string name=\"additional_settings\">其他設定</string>\n    <string name=\"share_fail_msg\">無法比對來自分享內容中的 URL</string>\n    <string name=\"download_range_desc\">指定欲從「%3$s」播放清單中下載的影片項目範圍 (編號從 %1$d 到 %2$d)。</string>\n    <string name=\"subdirectory\">儲存到子目錄</string>\n    <string name=\"download_directory_desc\">選取影片檔和音訊檔的儲存位置</string>\n    <string name=\"embed_subtitles\">內嵌字幕</string>\n    <string name=\"github_issue\">GitHub 議題</string>\n    <string name=\"custom_command_template_desc\">編輯和管理命令範本</string>\n    <string name=\"downloading_indicator_text\">正在下載…</string>\n    <string name=\"status_canceled\">已取消</string>\n    <string name=\"task_canceled\">已取消下載任務</string>\n    <string name=\"copy_link\">複製連結</string>\n    <string name=\"copy_error_report\">複製報告</string>\n    <string name=\"concurrent_download_desc\">以更多執行緒下載 M3U8/MPD 影片</string>\n    <string name=\"import_from_clipboard\">從剪貼簿匯入</string>\n    <string name=\"template_exported\">已匯出 %1$d 個範本</string>\n    <string name=\"template_imported\">已匯入 %1$d 個範本</string>\n    <string name=\"download_task_count\">%1$d 項下載任務</string>\n    <string name=\"recently_added\">最近新增</string>\n    <string name=\"multiselect_item_count\">%1$d 個影片，%2$d 個音訊</string>\n    <string name=\"export_to_clipboard\">匯出到剪貼簿</string>\n    <string name=\"delete_multiple_items_msg\">確定要移除 %1$d 項下載記錄嗎？</string>\n    <string name=\"sponsorblock_categories_desc\">指定欲從影片檔中移除或標記的 SponsorBlock 類別</string>\n    <string name=\"sponsorblock_desc\">使用 SponsorBlock API 移除或標記影片中的片段</string>\n    <string name=\"sponsorblock_categories\">SponsorBlock 類別</string>\n    <string name=\"check_for_updates\">檢查更新</string>\n    <string name=\"app_up_to_date\">已是最新版本</string>\n    <string name=\"app_update_failed\">更新到最新版本失敗</string>\n    <string name=\"update\">更新</string>\n    <string name=\"clear_temp_files_desc\">從暫存目錄中刪除全數暫存檔案</string>\n    <string name=\"clear_temp_files_count\">已刪除 %1$d 個暫存檔案</string>\n    <string name=\"aria2_desc\">使用 aria2c 作為外部下載程式</string>\n    <string name=\"cookies_desc\">使用 Netscape 格式的 Cookies 檔案進行下載</string>\n    <string name=\"clear_temp_files\">清除暫存檔案</string>\n    <string name=\"check_for_updates_desc\">自動檢查來自 GitHub 提供的更新</string>\n    <string name=\"clear_temp_files_info\">暫存檔案可用於繼續已取消的下載。確定要刪除全數暫存檔案嗎？\n\\n\n\\n您可以在 %1$s 中存取上述檔案</string>\n    <string name=\"multiselect_mode\">多選模式</string>\n    <string name=\"private_mode_desc\">停用下載記錄</string>\n    <string name=\"private_mode\">無痕模式</string>\n    <string name=\"download_with_cellular_desc\">允許使用計量付費網路進行媒體下載</string>\n    <string name=\"download_disabled_with_cellular\">「以行動數據進行下載」已設為停用</string>\n    <string name=\"dynamic_color\">動態顏色</string>\n    <string name=\"dynamic_color_desc\">將桌布顏色套用至應用程式主題</string>\n    <string name=\"download_with_cellular\">以行動數據進行下載</string>\n    <string name=\"file_unavailable\">無法開啟檔案</string>\n    <string name=\"network\">網際網路</string>\n    <string name=\"max_rate\">最高速率</string>\n    <string name=\"high_contrast\">高對比深色主題</string>\n    <string name=\"rate_limit\">限制速率</string>\n    <string name=\"rate_limit_desc\">限制最大下載速度</string>\n    <string name=\"invalid_input\">輸入無效</string>\n    <string name=\"lowest_quality\">最低畫質</string>\n    <string name=\"unavailable\">不可用</string>\n    <string name=\"network_settings_desc\">速率限制、下載程式、Cookies</string>\n    <string name=\"disable_preview_desc\">下載時不顯示縮圖</string>\n    <string name=\"disable_preview\">停用預覽</string>\n    <string name=\"privacy\">隱私</string>\n    <string name=\"use_custom_command\">使用自訂命令</string>\n    <string name=\"private_directory\">隱藏目錄</string>\n    <string name=\"private_directory_desc\">將檔案儲存到隱藏目錄中</string>\n    <string name=\"crop_artwork_desc\">將內嵌封面裁剪至正方形</string>\n    <string name=\"crop_artwork\">裁剪封面</string>\n    <string name=\"format_settings_desc\">檔案格式、影片畫質、字幕</string>\n    <string name=\"general_settings_desc\">Yt-dlp 版本、通知、播放清單</string>\n    <string name=\"download_selection_desc\">從「%1$s」播放清單中選取影片以進行下載</string>\n    <string name=\"selected_item_count\">已選取 %1$d 項</string>\n    <string name=\"select_all\">全部選取</string>\n    <string name=\"format_selection\">格式選取</string>\n    <string name=\"format_selection_desc\">在開始下載前選取下載格式</string>\n    <string name=\"suggested\">建議</string>\n    <string name=\"video_only\">影片 (無音訊)</string>\n    <string name=\"generate_new_cookies\">產生新 cookies</string>\n    <string name=\"custom_command_enabled_hint\">部分選項在使用自訂命令時不可用</string>\n    <string name=\"how_does_it_work\">如何使用？</string>\n    <string name=\"telegram_channel\">Telegram 頻道</string>\n    <string name=\"remove_cookie_profile_desc\">確定要刪除「%1$s」？請注意，此操作不會清除此網站的 cookies 檔案。</string>\n    <string name=\"use_cookies\">使用 Cookies</string>\n    <string name=\"cookies_usage_msg\">從某些網站下載時會需要帳戶驗證資訊。按一下 [產生新 Cookies]，接著輸入網站 URL 並在瀏覽器中以個人帳戶登入，應用程式將產生下載時所需的必要資訊。</string>\n    <string name=\"matrix_space\">Matrix 空間</string>\n    <string name=\"cookies\">Cookies</string>\n    <string name=\"abs_hint\">大多數影音串流平台皆分別提供純音訊和純影片格式，可選取純音訊和純影片格式，並將其合併為單個影片。</string>\n    <string name=\"clear\">清除</string>\n    <string name=\"sdcard_directory\">SD 卡資料夾</string>\n    <string name=\"auto_subtitle\">自動化字幕</string>\n    <string name=\"auto_subtitle_desc\">下載自動產生的字幕</string>\n    <string name=\"title_activity_share\">快速下載</string>\n    <string name=\"video_title_sample_text\">影片標題範例文字</string>\n    <string name=\"video_creator_sample_text\">影片建立者範例文字</string>\n    <string name=\"subtitle\">字幕</string>\n    <string name=\"download_subtitles\">下載字幕</string>\n    <string name=\"subtitle_language\">字幕語言</string>\n    <string name=\"subtitle_desc\">語言、內嵌字幕、自動化字幕</string>\n    <string name=\"copy_log\">複製記錄檔</string>\n    <string name=\"add\">新增</string>\n    <string name=\"edit_shortcuts\">編輯捷徑</string>\n    <string name=\"shortcuts\">捷徑</string>\n    <string name=\"edit_shortcuts_desc\">編輯可用於撰寫命令範本的自訂捷徑。</string>\n    <string name=\"running_tasks\">正在執行的任務</string>\n    <string name=\"show_logs\">顯示記錄</string>\n    <string name=\"logs\">記錄</string>\n    <string name=\"subtitle_sponsorblock\">當移除 SponsorBlock 區段時，可能導致字幕時間軸錯位。</string>\n    <string name=\"embed_subtitles_mkv_msg\">為嵌入軟字幕，影片將重新混合至 MKV 容器中。請使用 VLC Media Player 或其他相容的應用程式，以觀賞嵌入軟字幕的影片。</string>\n    <string name=\"filesize_gb\">%.2f GB</string>\n    <string name=\"filesize_mb\">%.2f MB</string>\n    <string name=\"share\">分享</string>\n    <string name=\"stable_channel\">穩定</string>\n    <string name=\"pre_release_channel\">預覽</string>\n    <string name=\"update_channel_desc\">安裝預先發行版組建以預覽最新功能和變更。\n\\n\n\\n此版本可能會有不穩定的情況發生，如在使用過程中有任何問題，請不要吝嗇於給予回饋，以協助我們改進應用程式。</string>\n    <string name=\"update_channel\">更新頻道</string>\n    <string name=\"auto_update\">自動更新</string>\n    <string name=\"enable_auto_update\">啟用自動更新</string>\n    <string name=\"apply\">套用</string>\n    <string name=\"clip_video\">剪裁影片</string>\n    <string name=\"clip_start\">開始時間</string>\n    <string name=\"clip_end\">結束時間</string>\n    <string name=\"discard\">捨棄</string>\n    <string name=\"audio_format_preference\">音訊格式偏好</string>\n    <string name=\"unlimited\">無限制</string>\n    <string name=\"lowest_bitrate\">最低位元速率</string>\n    <string name=\"audio_quality\">音訊品質</string>\n    <string name=\"rename\">重新命名</string>\n    <string name=\"second\">秒</string>\n    <string name=\"import_from_preferences\">匯入</string>\n    <string name=\"audio_quality_desc\">當存在多種品質時限縮音訊位元速率</string>\n    <string name=\"minute\">分</string>\n    <string name=\"clear_all_cookies\">清除所有 Cookies</string>\n    <string name=\"clear_all_cookies_desc\">確定要刪除在應用程式中所有 Cookies 嗎？</string>\n    <string name=\"format_sorting\">格式排序</string>\n    <string name=\"format_sorting_desc\">使用 yt-dlp 的 -S 選項對格式進行排序</string>\n    <string name=\"title\">標題</string>\n    <string name=\"temporary_directory_desc\">在內部目錄儲存暫存檔案</string>\n    <string name=\"sponsor\">贊助</string>\n    <string name=\"sponsor_desc\">透過在 GitHub 上贊助以支持此應用程式</string>\n    <string name=\"feedback\">意見反應</string>\n    <string name=\"sponsors\">贊助</string>\n    <string name=\"sponsor_msg\">Seal 永遠提供眾人免費使用並開放原始碼。若您悅納，請考慮在 GitHub 上贊助我！</string>\n    <string name=\"no_downloaded_media\">沒有已下載的媒體</string>\n    <string name=\"beta_features\">Beta</string>\n    <string name=\"enable_experimental_feature\">確定要啟用實驗性功能？</string>\n    <string name=\"clip_video_desc\">在格式選取頁中剪裁影片</string>\n    <string name=\"audio_format\">音訊格式</string>\n    <string name=\"clip_video_dialog_msg\">使用此功能以將下載任務—— 選取的影片區段，委派予 FFmpeg。此功能仍在實驗性階段，剪裁並非完全精確且並非支援全部格式，下載速率可能較慢。</string>\n    <string name=\"auto_update_disabled_msg\">自動更新不適用於 %1$s 組建。如果您的裝置尚未安裝 %1$s，或想要預覽 Seal 即將推出的新功能，請考慮使用 %2$s。</string>\n    <string name=\"switch_to_github_builds\">切換至 GitHub 組建</string>\n    <string name=\"okay\">確定</string>\n    <string name=\"got_it\">瞭解</string>\n    <string name=\"feature_unavailable\">此功能無法使用</string>\n    <string name=\"no_custom_command_tasks\">沒有自訂命令的任務</string>\n    <string name=\"msg_from_developer\">來自開發者的訊息</string>\n    <string name=\"sponsor_msg2\">非常感謝您！</string>\n    <string name=\"download_video_desc\">從 URL 下載影片</string>\n    <string name=\"split_video_msg\">影片將被分割成 %1$d 個章節</string>\n    <string name=\"unknown_error_title\">糟糕！發生錯誤</string>\n    <string name=\"convert_subtitle\">轉換字幕</string>\n    <string name=\"convert_subtitle_desc\">轉換字幕至其他格式</string>\n    <string name=\"split_video\">分割影片</string>\n    <string name=\"copy_and_exit\">複製並離開</string>\n    <string name=\"expand\">展開</string>\n    <string name=\"new_task\">新增下載任務</string>\n    <string name=\"start\">開始</string>\n    <string name=\"edit_template\">編輯「%1$s」</string>\n    <string name=\"legacy\">傳統</string>\n    <string name=\"quality\">品質</string>\n    <string name=\"enable_notifications\">確定要啟用通知？</string>\n    <string name=\"disable\">停用</string>\n    <string name=\"set_directory_desc\">輕觸以設定目錄</string>\n    <string name=\"custom_command_directory\">自訂命令目錄</string>\n    <string name=\"folder_picker\">資料夾選擇器</string>\n    <string name=\"custom_command_directory_desc\">當使用自訂命令時指定輸出目錄</string>\n    <string name=\"prefer_compatibility_desc\">當分享至其他應用程式時偏好 MP4(H.264) 格式</string>\n    <string name=\"proxy_desc\">使用 Proxy 連線至網際網路</string>\n    <string name=\"enable_notifications_desc\">請授予應用程式權限以推播下載狀態和進度的通知。</string>\n    <string name=\"disabled\">停用</string>\n    <string name=\"prefer_quality_desc\">在相容的應用程式裡進行觀賞時偏好 AV1, VP9 或 H.265 格式</string>\n    <string name=\"proxy\">Proxy</string>\n    <string name=\"ytdlp_update_action\">更新 yt-dlp</string>\n    <string name=\"refresh_cookies_desc\">輕觸以開啟產生新 Cookies 的網頁:</string>\n    <string name=\"download_type\">下載類型</string>\n    <string name=\"custom\">自訂</string>\n    <string name=\"auto\">自動</string>\n    <string name=\"commands\">命令</string>\n    <string name=\"format_preference\">偏好格式</string>\n    <string name=\"learn_more\">進一步了解</string>\n    <string name=\"unknown\">未知</string>\n    <string name=\"remove_multiple_templates_msg\">確定要從命令範本中移除「%1$s」嗎？</string>\n    <plurals name=\"item_count\">\n        <item quantity=\"other\">%d 項</item>\n    </plurals>\n    <string name=\"ua_header\">使用者代理程式標頭</string>\n    <string name=\"export_to_file\">匯出成檔案</string>\n    <string name=\"custom_command_usage_msg\">yt-dlp 是功能強大的下載影片命令列工具。Seal 透過提供直觀的 GUI、常見命令的預設值和其他額外功能，讓您更輕鬆地使用 yt-dlp。\n\\n\n\\n如果您需要進階使用 yt-dlp，您可以在 Seal 中直接建立、儲存和執行自訂命令範本，就像在終端機一樣。\n\\n\n\\n當您使用自訂命令時，大部分 GUI 選項和功能將會停用。</string>\n    <string name=\"presets\">預設</string>\n    <string name=\"output_template\">輸出範本</string>\n    <string name=\"output_template_desc\">為輸出檔案名稱指定範本</string>\n    <string name=\"clear_download_archive\">確定要清除下載封存？</string>\n    <string name=\"clear_download_archive_desc\">確定要從下載封存中移除「%1$s」嗎？</string>\n    <string name=\"download_archive_desc\">將已下載的影片識別碼記錄至封存，以避免重複下載</string>\n    <string name=\"download_archive\">下載封存</string>\n    <string name=\"save\">儲存</string>\n    <string name=\"embed_metadata\">內嵌中繼資料</string>\n    <string name=\"use_format_sorting\">使用格式排序</string>\n    <string name=\"required\">必要</string>\n    <string name=\"show_all_items\">顯示所有項目 (%1$d)</string>\n    <string name=\"edit_file\">編輯檔案</string>\n    <string name=\"embed_metadata_desc\">內嵌中繼資料和影片縮圖至音訊檔</string>\n    <string name=\"restrict_filenames_desc\">限制檔案名稱需包含特定字元以確保相容性</string>\n    <string name=\"restrict_filenames\">限制命名</string>\n    <string name=\"website\">網站</string>\n    <string name=\"playlist_title\">播放清單標題</string>\n    <string name=\"subdirectory_hint\">下載將另存於:</string>\n    <string name=\"force_ipv4\">強制使用 IPv4</string>\n    <string name=\"system_settings\">系統設定</string>\n    <string name=\"force_ipv4_desc\">讓所有連線皆透過 IPv4 進行</string>\n    <string name=\"keep_subtitle_files\">保留字幕檔案</string>\n    <string name=\"allow_once\">允許一次</string>\n    <string name=\"allow_always\">永久允許</string>\n    <string name=\"dont_allow\">不允許</string>\n    <string name=\"download_with_cellular_request\">確定要允許以行動數據下載？</string>\n    <string name=\"merge_audiostream\">合併多個音訊串流</string>\n    <string name=\"merge_audiostream_desc\">允許將多個音訊串流合併成單一檔案</string>\n    <string name=\"download_archive_error\">此影片已下載完成。如果這是未預期的行為，請檢查您的下載檔案。</string>\n    <string name=\"import_backup\">匯入</string>\n    <string name=\"export_backup\">匯出</string>\n    <string name=\"export_download_history\">確定要匯出下載記錄？</string>\n    <string name=\"import_from\">匯入於</string>\n    <string name=\"export_download_history_msg\">正在從下載記錄中匯出 %1$s。已下載的檔案和偏好設定不會備份。</string>\n    <string name=\"redownload\">重新下載</string>\n    <string name=\"auto_translated_subtitles\">自動翻譯字幕</string>\n    <string name=\"auto_translated_subtitles_msg\">所有自動翻譯的字幕都將在下載中可用。不過，字幕有可能不準確且難以理解。</string>\n    <string name=\"remember_for_next_download\">記住本次下載設定</string>\n    <string name=\"subtitle_language_desc\">指定在自動格式選取中要下載哪些語言的字幕，語言名稱間以英文逗號分隔。</string>\n    <string name=\"reset\">重設</string>\n    <string name=\"no_thanks\">不，謝謝</string>\n    <string name=\"update_language_msg\">今後預設下載下列語言的字幕:</string>\n    <string name=\"full_backup\">完整備份</string>\n    <string name=\"look_and_feel\"><![CDATA[介面與外觀]]></string>\n    <string name=\"interface_and_interaction\"><![CDATA[介面與互動]]></string>\n    <string name=\"use_previous_selection\">使用先前所選</string>\n    <string name=\"none\">無</string>\n    <string name=\"search_in_subtitles\">在字幕中搜尋</string>\n    <string name=\"backup_type\">備份類型</string>\n    <string name=\"export_to\">匯出至</string>\n    <string name=\"file\">檔案</string>\n    <string name=\"clipboard\">剪貼簿</string>\n    <string name=\"import_download_history\">確定要匯入下載記錄？</string>\n    <string name=\"import_download_history_msg\">不會匯入已下載的檔案，請手動重新下載</string>\n    <string name=\"download_history\">下載歷史記錄</string>\n    <string name=\"update_subtitle_languages\">確定要更新字幕語言嗎？</string>\n    <string name=\"download_history_imported\">已將 %1$s 匯入下載記錄</string>\n    <string name=\"search_in_downloads\">在下載中搜尋</string>\n    <string name=\"search\">搜尋</string>\n    <string name=\"remux_container_mkv\">重新混合影片容器</string>\n    <string name=\"cookies_in_database\">共 %1$d 個 cookies，來自 %2$d 個網站</string>\n    <string name=\"remux_container_mkv_desc\">將影片重新混合至 MKV 容器以提高相容性</string>\n    <string name=\"every_day\">每天</string>\n    <string name=\"every_week\">每週</string>\n    <string name=\"every_month\">每月</string>\n    <string name=\"all_languages\">所有語言</string>\n    <string name=\"prefer_placeholder\">偏好 %1$s</string>\n    <string name=\"preset\">預設</string>\n    <string name=\"best_quality_desc\">下載可用的最佳格式</string>\n    <plurals name=\"video_count\">\n        <item quantity=\"other\">%d 部影片</item>\n    </plurals>\n    <string name=\"task_added\">已將任務加入佇列</string>\n    <plurals name=\"audio_count\">\n        <item quantity=\"other\">%d 段音訊</item>\n    </plurals>\n    <string name=\"playlist\">播放清單</string>\n    <string name=\"proceed\">繼續</string>\n    <string name=\"custom_format_selection_desc\">選擇格式、字幕並進一步自訂</string>\n    <string name=\"preset_format_selection_desc\">使用你的格式偏好自動下載</string>\n    <string name=\"edit_preset\">編輯預設</string>\n    <string name=\"you_ll_find_your_downloads_here\">您可以在這裡找到您的下載內容</string>\n    <string name=\"download_hint\">輕觸 [下載] 按鈕或分享影片連結到此應用程式以開始下載</string>\n    <string name=\"status_downloaded\">已下載</string>\n    <string name=\"all\">全部</string>\n    <string name=\"select_multiple_link\">從 %1$d 個連結中選取</string>\n    <string name=\"download_queue\">下載佇列</string>\n    <string name=\"show_navigation_drawer\">顯示導覽匣</string>\n    <string name=\"resume\">繼續</string>\n    <string name=\"delete\">刪除</string>\n    <string name=\"media_info\">媒體資訊</string>\n    <string name=\"trouble_shooting\">疑難排解</string>\n    <string name=\"issue_tracker\">議題追蹤工具</string>\n    <string name=\"trouble_shooting_desc\">修復常見錯誤並檢查已知問題</string>\n    <string name=\"issue_tracker_hint\">發生錯誤？在回報新問題之前，請先檢查議題追蹤工具。許多常見問題已經解決，並且記錄在案。</string>\n    <string name=\"saved_urls\">已儲存的連結</string>\n    <string name=\"add_new_url\">新增新連結</string>\n    <string name=\"add_to\">新增至 %1$s</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/xml/provider_paths.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n    <external-path\n        name=\"external_files\"\n        path=\".\" />\n    <cache-path\n        name=\"cache\"\n        path=\".\" />\n</paths>"
  },
  {
    "path": "app/src/test/java/com/junkfood/seal/ExampleUnitTest.kt",
    "content": "package com.junkfood.seal\n\nimport com.junkfood.seal.util.connectWithDelimiter\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\nclass ExampleUnitTest {\n    @Test\n    fun addition_isCorrect() {\n        assertEquals(4, 2 + 2)\n    }\n\n    @Test\n    fun testTextJoin() {\n        assertEquals(\n            connectWithDelimiter(\"123\", \"456\", \"789\", delimiter = \",\"),\n            listOf(123, 456, 789).joinToString(separator = \",\") { it.toString() },\n        )\n        assertEquals(connectWithDelimiter(delimiter = \",\"), \"\")\n        assertEquals(emptyList<String>().joinToString(separator = \",\") { it }, \"\")\n    }\n}\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "plugins {\n    alias(libs.plugins.android.application) apply false\n    alias(libs.plugins.android.library) apply false\n    alias(libs.plugins.kotlin.android) apply false\n    alias(libs.plugins.kotlin.serialization) apply false\n    alias(libs.plugins.ksp) apply false\n    alias(libs.plugins.compose.compiler) apply false\n    alias(libs.plugins.room) apply false\n}\n\nbuildscript {\n    repositories {\n        mavenCentral()\n        google()\n    }\n}\n\ntasks.register(\"clean\", Delete::class) {\n    delete(rootProject.layout.buildDirectory)\n}\n\n"
  },
  {
    "path": "buildSrc/.gitignore",
    "content": "/build"
  },
  {
    "path": "buildSrc/build.gradle.kts",
    "content": "plugins { `kotlin-dsl` }\n\nrepositories {\n    mavenCentral()\n    google()\n}\n\ndependencies {\n    implementation(gradleApi())\n    implementation(localGroovy())\n}\n\nkotlin { jvmToolchain(21) }\n"
  },
  {
    "path": "buildSrc/src/main/kotlin/Version.kt",
    "content": "sealed class Version(val major: Int, val minor: Int, val patch: Int, val build: Int = 0) {\n    abstract val name: String\n    abstract val code: Long\n\n    class Alpha(versionMajor: Int, versionMinor: Int, versionPatch: Int, versionBuild: Int) :\n        Version(versionMajor, versionMinor, versionPatch, versionBuild) {\n        override val name: String\n            get() = \"${major}.${minor}.${patch}-alpha.$build\"\n\n        override val code: Long\n            get() = major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + ALPHA\n    }\n\n    class Beta(versionMajor: Int, versionMinor: Int, versionPatch: Int, versionBuild: Int) :\n        Version(versionMajor, versionMinor, versionPatch, versionBuild) {\n        override val name: String\n            get() = \"${major}.${minor}.${patch}-beta.$build\"\n\n        override val code: Long\n            get() = major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + BETA\n    }\n\n    class Stable(versionMajor: Int, versionMinor: Int, versionPatch: Int) :\n        Version(versionMajor, versionMinor, versionPatch) {\n        override val name: String\n            get() = \"${major}.${minor}.${patch}\"\n\n        override val code: Long\n            get() = major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + STABLE\n    }\n\n    class ReleaseCandidate(\n        versionMajor: Int,\n        versionMinor: Int,\n        versionPatch: Int,\n        versionBuild: Int,\n    ) : Version(versionMajor, versionMinor, versionPatch, versionBuild) {\n        override val name: String\n            get() = \"${major}.${minor}.${patch}-rc.$build\"\n\n        override val code: Long\n            get() =\n                major * MAJOR + minor * MINOR + patch * PATCH + build * BUILD + RELEASE_CANDIDATE\n    }\n}\n\n// private const val ABI = 1L\nprivate const val BUILD = 10L\nprivate const val VARIANT = 100L\nprivate const val PATCH = 10_000L\nprivate const val MINOR = 1_000_000L\nprivate const val MAJOR = 100_000_000L\n\nprivate const val STABLE = VARIANT * 4\nprivate const val ALPHA = VARIANT * 1\nprivate const val BETA = VARIANT * 2\nprivate const val RELEASE_CANDIDATE = VARIANT * 3\n\nval currentVersion: Version =\n    Version.Alpha(versionMajor = 2, versionMinor = 0, versionPatch = 0, versionBuild = 5)\n"
  },
  {
    "path": "color/.gitignore",
    "content": "/build"
  },
  {
    "path": "color/build.gradle.kts",
    "content": "plugins {\n    alias(libs.plugins.android.library)\n    alias(libs.plugins.kotlin.android)\n    alias(libs.plugins.compose.compiler)\n}\n\njava {\n    sourceCompatibility = JavaVersion.VERSION_1_8\n    targetCompatibility = JavaVersion.VERSION_1_8\n}\nkotlin {\n    jvmToolchain(21)\n}\nandroid {\n    compileSdk = 34\n    defaultConfig {\n        minSdk = 21\n    }\n    namespace = \"com.junkfood.seal.color\"\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_1_8\n        sourceCompatibility = JavaVersion.VERSION_1_8\n    }\n    buildTypes {\n        release {\n            proguardFiles(\n                getDefaultProguardFile(\"proguard-android-optimize.txt\"), \"proguard-rules.pro\"\n            )\n            isMinifyEnabled = true\n        }\n    }\n}\ndependencies {\n    api(platform(libs.androidx.compose.bom))\n    api(libs.androidx.compose.ui)\n    api(libs.androidx.compose.runtime)\n    api(libs.androidx.core.ktx)\n    api(libs.androidx.compose.foundation)\n    api(libs.androidx.compose.material3)\n}"
  },
  {
    "path": "color/proguard-rules.pro",
    "content": "-keep class com.kyant.monet.** { *; }\n-keep class io.material.hct.** { *; }\n-dontwarn java.lang.invoke.StringConcatFactory"
  },
  {
    "path": "color/src/main/java/com/kyant/monet/ColorSpec.kt",
    "content": "package com.kyant.monet\n\ndata class ColorSpec(\n    val chroma: (Double) -> Double = { it },\n    val hueShift: (Double) -> Double = { 0.0 }\n)\n"
  },
  {
    "path": "color/src/main/java/com/kyant/monet/Monet.kt",
    "content": "package com.kyant.monet\n\nimport androidx.compose.foundation.isSystemInDarkTheme\nimport androidx.compose.material3.ColorScheme\nimport androidx.compose.material3.darkColorScheme\nimport androidx.compose.material3.lightColorScheme\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.staticCompositionLocalOf\nimport androidx.compose.ui.graphics.Color\nimport com.kyant.monet.TonalPalettes.Companion.toTonalPalettes\n\nval LocalTonalPalettes = staticCompositionLocalOf {\n    Color(0xFF007FAC).toTonalPalettes()\n}\n\ninline val Number.a1: Color\n    @Composable\n    get() = LocalTonalPalettes.current accent1 toDouble()\n\ninline val Number.a2: Color\n    @Composable get() = LocalTonalPalettes.current accent2 toDouble()\n\ninline val Number.a3: Color\n    @Composable get() = LocalTonalPalettes.current accent3 toDouble()\n\ninline val Number.n1: Color\n    @Composable get() = LocalTonalPalettes.current neutral1 toDouble()\n\ninline val Number.n2: Color\n    @Composable get() = LocalTonalPalettes.current neutral2 toDouble()\n\n@Composable\nfun dynamicColorScheme(isLight: Boolean = !isSystemInDarkTheme()): ColorScheme {\n    return if (isLight) {\n        lightColorScheme(\n            background = 98.n1,\n            inverseOnSurface = 95.n1,\n            inversePrimary = 80.a1,\n            inverseSurface = 20.n1,\n            onBackground = 10.n1,\n            onPrimary = 100.a1,\n            onPrimaryContainer = 10.a1,\n            onSecondary = 100.a2,\n            onSecondaryContainer = 10.a2,\n            onSurface = 10.n1,\n            onSurfaceVariant = 30.n2,\n            onTertiary = 100.a3,\n            onTertiaryContainer = 10.a3,\n            outline = 50.n2,\n            outlineVariant = 80.n2,\n            primary = 40.a1,\n            primaryContainer = 90.a1,\n//            scrim = 0.n1,\n            secondary = 40.a2,\n            secondaryContainer = 90.a2,\n            surface = 98.n1,\n            surfaceVariant = 90.n2,\n            tertiary = 40.a3,\n            tertiaryContainer = 90.a3,\n            surfaceBright = 98.n1,\n            surfaceDim = 87.n1,\n            surfaceContainerLowest = 100.n1,\n            surfaceContainerLow = 96.n1,\n            surfaceContainer = 94.n1,\n            surfaceContainerHigh = 92.n1,\n            surfaceContainerHighest = 90.n1,\n        )\n    } else {\n        darkColorScheme(\n            background = 6.n1,\n            inverseOnSurface = 20.n1,\n            inversePrimary = 40.a1,\n            inverseSurface = 90.n1,\n            onBackground = 90.n1,\n            onPrimary = 20.a1,\n            onPrimaryContainer = 90.a1,\n            onSecondary = 20.a2,\n            onSecondaryContainer = 90.a2,\n            onSurface = 90.n1,\n            onSurfaceVariant = 80.n2,\n            onTertiary = 20.a3,\n            onTertiaryContainer = 90.a3,\n            outline = 60.n2,\n            outlineVariant = 30.n2,\n            primary = 80.a1,\n            primaryContainer = 30.a1,\n//            scrim = 0.n1,\n            secondary = 80.a2,\n            secondaryContainer = 30.a2,\n            surface = 6.n1,\n            surfaceVariant = 30.n2,\n            tertiary = 80.a3,\n            tertiaryContainer = 30.a3,\n            surfaceBright = 24.n1,\n            surfaceDim = 6.n1,\n            surfaceContainerLowest = 4.n1,\n            surfaceContainerLow = 10.n1,\n            surfaceContainer = 12.n1,\n            surfaceContainerHigh = 17.n1,\n            surfaceContainerHighest = 22.n1,\n        )\n    }\n}\n"
  },
  {
    "path": "color/src/main/java/com/kyant/monet/PaletteStyle.kt",
    "content": "@file:Suppress(\"unused\")\n\npackage com.kyant.monet\n\nclass PaletteStyle(\n    val accent1Spec: ColorSpec,\n    val accent2Spec: ColorSpec,\n    val accent3Spec: ColorSpec,\n    val neutral1Spec: ColorSpec,\n    val neutral2Spec: ColorSpec\n) {\n    companion object {\n        private val VibrantSecondaryHueRotation = arrayOf(\n            0 to 18,\n            41 to 15,\n            61 to 10,\n            101 to 12,\n            131 to 15,\n            181 to 18,\n            251 to 15,\n            301 to 12,\n            360 to 12\n        )\n        private val VibrantTertiaryHueRotation = arrayOf(\n            0 to 35,\n            41 to 30,\n            61 to 20,\n            101 to 25,\n            131 to 30,\n            181 to 35,\n            251 to 30,\n            301 to 25,\n            360 to 25\n        )\n        private val ExpressiveSecondaryHueRotation = arrayOf(\n            0 to 45,\n            21 to 95,\n            51 to 45,\n            121 to 20,\n            151 to 45,\n            191 to 90,\n            271 to 45,\n            321 to 45,\n            360 to 45\n        )\n        private val ExpressiveTertiaryHueRotation = arrayOf(\n            0 to 120,\n            21 to 120,\n            51 to 120,\n            121 to 45,\n            151 to 20,\n            191 to 15,\n            271 to 20,\n            321 to 120,\n            360 to 120\n        )\n        val TonalSpot: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 36.0 }) { 0.0 },\n            accent2Spec = ColorSpec({ 16.0 }) { 0.0 },\n            accent3Spec = ColorSpec({ 24.0 }) { 60.0 },\n            neutral1Spec = ColorSpec({ 6.0 }) { 0.0 },\n            neutral2Spec = ColorSpec({ 8.0 }) { 0.0 }\n        )\n        val Spritz: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 12.0 }) { 0.0 },\n            accent2Spec = ColorSpec({ 8.0 }) { 0.0 },\n            accent3Spec = ColorSpec({ 16.0 }) { 30.0 },\n            neutral1Spec = ColorSpec({ 2.0 }) { 0.0 },\n            neutral2Spec = ColorSpec({ 2.0 }) { 0.0 }\n        )\n        val Vibrant: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 48.0 }) { 0.0 },\n            accent2Spec = ColorSpec({ 24.0 }) { it.hueRotation(VibrantSecondaryHueRotation) },\n            accent3Spec = ColorSpec({ 32.0 }) { it.hueRotation(VibrantTertiaryHueRotation) },\n            neutral1Spec = ColorSpec({ 10.0 }) { 0.0 },\n            neutral2Spec = ColorSpec({ 12.0 }) { 0.0 }\n        )\n        val Expressive: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 40.0 }) { 240.0 },\n            accent2Spec = ColorSpec({ 24.0 }) { it.hueRotation(ExpressiveSecondaryHueRotation) },\n            accent3Spec = ColorSpec({ 32.0 }) { it.hueRotation(ExpressiveTertiaryHueRotation) },\n            neutral1Spec = ColorSpec({ 15.0 }) { 15.0 },\n            neutral2Spec = ColorSpec({ 12.0 }) { 15.0 }\n        )\n        val Rainbow: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 48.0 }) { 0.0 },\n            accent2Spec = ColorSpec({ 16.0 }) { 0.0 },\n            accent3Spec = ColorSpec({ 24.0 }) { -60.0 },\n            neutral1Spec = ColorSpec({ 0.0 }) { 0.0 },\n            neutral2Spec = ColorSpec({ 0.0 }) { 0.0 }\n        )\n        val FruitSalad: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 48.0 }) { -50.0 },\n            accent2Spec = ColorSpec({ 36.0 }) { -30.0 },\n            accent3Spec = ColorSpec({ 36.0 }) { 0.0 },\n            neutral1Spec = ColorSpec({ 10.0 }) { 0.0 },\n            neutral2Spec = ColorSpec({ 16.0 }) { 0.0 }\n        )\n        val Content: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ it * 1 }) { 0.0 },\n            accent2Spec = ColorSpec({ it / 3 }) { 0.0 },\n            accent3Spec = ColorSpec({ it * 2 / 3 }) { 60.0 },\n            neutral1Spec = ColorSpec({ it / 12 }) { 0.0 },\n            neutral2Spec = ColorSpec({ it / 6 }) { 0.0 }\n        )\n        val Monochrome: PaletteStyle = PaletteStyle(\n            accent1Spec = ColorSpec({ 0.0 }) { 0.0 },\n            accent2Spec = ColorSpec({ 0.0 }) { 0.0 },\n            accent3Spec = ColorSpec({ 0.0 }) { 0.0 },\n            neutral1Spec = ColorSpec({ 0.0 }) { 0.0 },\n            neutral2Spec = ColorSpec({ 0.0 }) { 0.0 },\n        )\n\n\n        private fun Double.hueRotation(list: Array<Pair<Int, Int>>): Double {\n            var i = 0\n            val size = list.size - 2\n            if (size >= 0) {\n                while (true) {\n                    val i2 = i + 1\n                    val intValue = (list[i2]).first.toFloat()\n                    when {\n                        list[i].first <= this && this < intValue -> {\n                            return (this + list[i].second.toDouble()).mod(360.0)\n                        }\n\n                        i == size -> break\n                        else -> i = i2\n                    }\n                }\n            }\n            return this\n        }\n    }\n}\n"
  },
  {
    "path": "color/src/main/java/com/kyant/monet/TonalPalettes.kt",
    "content": "package com.kyant.monet\n\nimport androidx.compose.material3.ColorScheme\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.graphics.toArgb\nimport io.material.hct.Hct\n\ntypealias TonalPalette = Map<Double, Color>\n\nclass TonalPalettes(\n    val keyColor: Color,\n    val style: PaletteStyle = PaletteStyle.TonalSpot,\n    private val accent1: TonalPalette,\n    private val accent2: TonalPalette,\n    private val accent3: TonalPalette,\n    private val neutral1: TonalPalette,\n    private val neutral2: TonalPalette\n) {\n    infix fun accent1(tone: Double): Color = accent1.getOrElse(tone) {\n        keyColor.transform(tone, style.accent1Spec)\n    }\n\n    infix fun accent2(tone: Double): Color = accent2.getOrElse(tone) {\n        keyColor.transform(tone, style.accent2Spec)\n    }\n\n    infix fun accent3(tone: Double): Color = accent3.getOrElse(tone) {\n        keyColor.transform(tone, style.accent3Spec)\n    }\n\n    infix fun neutral1(tone: Double): Color = neutral1.getOrElse(tone) {\n        keyColor.transform(tone, style.neutral1Spec)\n    }\n\n    infix fun neutral2(tone: Double): Color = neutral2.getOrElse(tone) {\n        keyColor.transform(tone, style.neutral2Spec)\n    }\n\n    companion object {\n        private val M3TonalValues = doubleArrayOf(\n            0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 85.0, 90.0, 95.0, 99.0, 100.0\n        )\n        private val M3SurfaceTonalValues = doubleArrayOf(\n            0.0,\n            4.0,\n            6.0,\n            10.0,\n            12.0,\n            17.0,\n            20.0,\n            22.0,\n            24.0,\n            30.0,\n            40.0,\n            50.0,\n            60.0,\n            70.0,\n            80.0,\n            85.0,\n            87.0,\n            90.0,\n            92.0,\n            94.0,\n            95.0,\n            96.0,\n            98.0,\n            99.0,\n            100.0\n        )\n\n        fun Color.toTonalPalettes(\n            style: PaletteStyle = PaletteStyle.TonalSpot,\n            tonalValues: DoubleArray = M3TonalValues\n        ): TonalPalettes = TonalPalettes(\n            keyColor = this,\n            style = style,\n            accent1 = tonalValues.associateWith { transform(it, style.accent1Spec) },\n            accent2 = tonalValues.associateWith { transform(it, style.accent2Spec) },\n            accent3 = tonalValues.associateWith { transform(it, style.accent3Spec) },\n            neutral1 = M3SurfaceTonalValues.associateWith { transform(it, style.neutral1Spec) },\n            neutral2 = tonalValues.associateWith { transform(it, style.neutral2Spec) }\n        )\n\n\n        private fun Color.toTonalPalette(\n            tonalValues: DoubleArray = M3TonalValues\n        ): TonalPalette =\n            tonalValues.associateWith { transform(it, ColorSpec()) }\n\n\n        /**\n         * Convert an existing `ColorScheme` to an MD3 `TonalPalettes`\n         *\n         * Notice: This function is `PaletteStyle` independent\n         *\n         * @see ColorScheme\n         * @see TonalPalettes\n         */\n        fun ColorScheme.toTonalPalettes(\n            tonalValues: DoubleArray = M3TonalValues\n        ): TonalPalettes = TonalPalettes(\n            keyColor = primary,\n            accent1 = primary.toTonalPalette(tonalValues),\n            accent2 = secondary.toTonalPalette(tonalValues),\n            accent3 = tertiary.toTonalPalette(tonalValues),\n            neutral1 = surface.toTonalPalette(M3SurfaceTonalValues),\n            neutral2 = surfaceVariant.toTonalPalette(tonalValues),\n        )\n\n        private fun Color.transform(tone: Double, spec: ColorSpec): Color {\n            return Color(Hct.fromInt(this.toArgb()).apply {\n                setTone(tone)\n                setChroma(spec.chroma(this.chroma))\n                setHue(spec.hueShift(this.hue) + this.hue)\n            }.toInt())\n        }\n\n    }\n}\n"
  },
  {
    "path": "color/src/main/java/io/material/hct/Cam16.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage io.material.hct\n\nimport io.material.utils.ColorUtils\nimport kotlin.math.abs\nimport kotlin.math.atan2\nimport kotlin.math.cos\nimport kotlin.math.expm1\nimport kotlin.math.hypot\nimport kotlin.math.ln1p\nimport kotlin.math.max\nimport kotlin.math.pow\nimport kotlin.math.sign\nimport kotlin.math.sin\nimport kotlin.math.sqrt\n\n/**\n * CAM16, a color appearance model. Colors are not just defined by their hex code, but rather, a hex\n * code and viewing conditions.\n *\n *\n * CAM16 instances also have coordinates in the CAM16-UCS space, called J*, a*, b*, or jstar,\n * astar, bstar in code. CAM16-UCS is included in the CAM16 specification, and should be used when\n * measuring distances between colors.\n *\n *\n * In traditional color spaces, a color can be identified solely by the observer's measurement of\n * the color. Color appearance models such as CAM16 also use information about the environment where\n * the color was observed, known as the viewing conditions.\n *\n *\n * For example, white under the traditional assumption of a midday sun white point is accurately\n * measured as a slightly chromatic blue by CAM16. (roughly, hue 203, chroma 3, lightness 100)\n */\nclass Cam16\n/**\n * All of the CAM16 dimensions can be calculated from 3 of the dimensions, in the following\n * combinations: - {j or q} and {c, m, or s} and hue - jstar, astar, bstar Prefer using a static\n * method that constructs from 3 of those dimensions. This constructor is intended for those\n * methods to use to return all possible dimensions.\n *\n * @param hue for example, red, orange, yellow, green, etc.\n * @param chroma informally, colorfulness / color intensity. like saturation in HSL, except\n * perceptually accurate.\n * @param j lightness\n * @param q brightness; ratio of lightness to white point's lightness\n * @param m colorfulness\n * @param s saturation; ratio of chroma to white point's chroma\n * @param jstar CAM16-UCS J coordinate\n * @param astar CAM16-UCS a coordinate\n * @param bstar CAM16-UCS b coordinate\n */ private constructor(\n    /** Hue in CAM16  */\n    // CAM16 color dimensions, see getters for documentation.\n    val hue: Double,\n    /** Chroma in CAM16  */\n    val chroma: Double,\n    /** Lightness in CAM16  */\n    val j: Double,\n    /**\n     * Brightness in CAM16.\n     *\n     *\n     * Prefer lightness, brightness is an absolute quantity. For example, a sheet of white paper is\n     * much brighter viewed in sunlight than in indoor light, but it is the lightest object under any\n     * lighting.\n     */\n    val q: Double,\n    /**\n     * Colorfulness in CAM16.\n     *\n     *\n     * Prefer chroma, colorfulness is an absolute quantity. For example, a yellow toy car is much\n     * more colorful outside than inside, but it has the same chroma in both environments.\n     */\n    val m: Double,\n    /**\n     * Saturation in CAM16.\n     *\n     *\n     * Colorfulness in proportion to brightness. Prefer chroma, saturation measures colorfulness\n     * relative to the color's own brightness, where chroma is colorfulness relative to white.\n     */\n    val s: Double,\n    /** Lightness coordinate in CAM16-UCS  */\n    // Coordinates in UCS space. Used to determine color distance, like delta E equations in L*a*b*.\n    val jstar: Double,\n    /** a* coordinate in CAM16-UCS  */\n    val astar: Double,\n    /** b* coordinate in CAM16-UCS  */\n    val bstar: Double\n) {\n\n\n    // Avoid allocations during conversion by pre-allocating an array.\n    private val tempArray = doubleArrayOf(0.0, 0.0, 0.0)\n\n    /**\n     * CAM16 instances also have coordinates in the CAM16-UCS space, called J*, a*, b*, or jstar,\n     * astar, bstar in code. CAM16-UCS is included in the CAM16 specification, and is used to measure\n     * distances between colors.\n     */\n    fun distance(other: Cam16): Double {\n        val dJ = jstar - other.jstar\n        val dA = astar - other.astar\n        val dB = bstar - other.bstar\n        val dEPrime = sqrt(dJ * dJ + dA * dA + dB * dB)\n        return 1.41 * dEPrime.pow(0.63)\n    }\n\n    /**\n     * ARGB representation of the color. Assumes the color was viewed in default viewing conditions,\n     * which are near-identical to the default viewing conditions for sRGB.\n     */\n    fun toInt(): Int {\n        return viewed(ViewingConditions.Companion.DEFAULT)\n    }\n\n    /**\n     * ARGB representation of the color, in defined viewing conditions.\n     *\n     * @param viewingConditions Information about the environment where the color will be viewed.\n     * @return ARGB representation of color\n     */\n    fun viewed(viewingConditions: ViewingConditions): Int {\n        val xyz = xyzInViewingConditions(viewingConditions, tempArray)\n        return ColorUtils.argbFromXyz(xyz[0], xyz[1], xyz[2])\n    }\n\n    fun xyzInViewingConditions(\n        viewingConditions: ViewingConditions,\n        returnArray: DoubleArray?\n    ): DoubleArray {\n        val alpha = if (chroma == 0.0 || j == 0.0) 0.0 else chroma / sqrt(\n            j / 100.0\n        )\n        val t = (alpha / (1.64 - 0.29.pow(viewingConditions.n)).pow(0.73)).pow(1.0 / 0.9)\n        val hRad = hue.toRadians()\n\n        val eHue = 0.25 * (cos(hRad + 2.0) + 3.8)\n        val ac = (viewingConditions.aw\n                * (j / 100.0).pow(1.0 / viewingConditions.c / viewingConditions.z))\n        val p1 = eHue * (50000.0 / 13.0) * viewingConditions.nc * viewingConditions.ncb\n        val p2 = ac / viewingConditions.nbb\n        val hSin = sin(hRad)\n        val hCos = cos(hRad)\n        val gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11.0 * t * hCos + 108.0 * t * hSin)\n        val a = gamma * hCos\n        val b = gamma * hSin\n        val rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0\n        val gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0\n        val bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0\n        val rCBase = max(0.0, 27.13 * abs(rA) / (400.0 - abs(rA)))\n        val rC = sign(rA) * (100.0 / viewingConditions.fl) * rCBase.pow(1.0 / 0.42)\n        val gCBase = max(0.0, 27.13 * abs(gA) / (400.0 - abs(gA)))\n        val gC = sign(gA) * (100.0 / viewingConditions.fl) * gCBase.pow(1.0 / 0.42)\n        val bCBase = max(0.0, 27.13 * abs(bA) / (400.0 - abs(bA)))\n        val bC = sign(bA) * (100.0 / viewingConditions.fl) * bCBase.pow(1.0 / 0.42)\n        val rF = rC / viewingConditions.rgbD[0]\n        val gF = gC / viewingConditions.rgbD[1]\n        val bF = bC / viewingConditions.rgbD[2]\n        val matrix = CAM16RGB_TO_XYZ\n        val x = rF * matrix[0][0] + gF * matrix[0][1] + bF * matrix[0][2]\n        val y = rF * matrix[1][0] + gF * matrix[1][1] + bF * matrix[1][2]\n        val z = rF * matrix[2][0] + gF * matrix[2][1] + bF * matrix[2][2]\n        return if (returnArray != null) {\n            returnArray[0] = x\n            returnArray[1] = y\n            returnArray[2] = z\n            returnArray\n        } else {\n            doubleArrayOf(x, y, z)\n        }\n    }\n\n    companion object {\n        // Transforms XYZ color space coordinates to 'cone'/'RGB' responses in CAM16.\n        val XYZ_TO_CAM16RGB = arrayOf(\n            doubleArrayOf(0.401288, 0.650173, -0.051461),\n            doubleArrayOf(-0.250268, 1.204414, 0.045854),\n            doubleArrayOf(-0.002079, 0.048952, 0.953127)\n        )\n\n        // Transforms 'cone'/'RGB' responses in CAM16 to XYZ color space coordinates.\n        val CAM16RGB_TO_XYZ = arrayOf(\n            doubleArrayOf(1.8620678, -1.0112547, 0.14918678),\n            doubleArrayOf(0.38752654, 0.62144744, -0.00897398),\n            doubleArrayOf(-0.01584150, -0.03412294, 1.0499644)\n        )\n\n        /**\n         * Create a CAM16 color from a color, assuming the color was viewed in default viewing conditions.\n         *\n         * @param argb ARGB representation of a color.\n         */\n        fun fromInt(argb: Int): Cam16 {\n            return fromIntInViewingConditions(argb, ViewingConditions.Companion.DEFAULT)\n        }\n\n        /**\n         * Create a CAM16 color from a color in defined viewing conditions.\n         *\n         * @param argb ARGB representation of a color.\n         * @param viewingConditions Information about the environment where the color was observed.\n         */\n        // The RGB => XYZ conversion matrix elements are derived scientific constants. While the values\n        // may differ at runtime due to floating point imprecision, keeping the values the same, and\n        // accurate, across implementations takes precedence.\n        fun fromIntInViewingConditions(argb: Int, viewingConditions: ViewingConditions): Cam16 {\n            // Transform ARGB int to XYZ\n            val red = argb and 0x00ff0000 shr 16\n            val green = argb and 0x0000ff00 shr 8\n            val blue = argb and 0x000000ff\n            val redL = ColorUtils.linearized(red)\n            val greenL = ColorUtils.linearized(green)\n            val blueL = ColorUtils.linearized(blue)\n            val x = 0.41233895 * redL + 0.35762064 * greenL + 0.18051042 * blueL\n            val y = 0.2126 * redL + 0.7152 * greenL + 0.0722 * blueL\n            val z = 0.01932141 * redL + 0.11916382 * greenL + 0.95034478 * blueL\n            return fromXyzInViewingConditions(x, y, z, viewingConditions)\n        }\n\n        fun fromXyzInViewingConditions(\n            x: Double, y: Double, z: Double, viewingConditions: ViewingConditions\n        ): Cam16 {\n            // Transform XYZ to 'cone'/'rgb' responses\n            val matrix = XYZ_TO_CAM16RGB\n            val rT = x * matrix[0][0] + y * matrix[0][1] + z * matrix[0][2]\n            val gT = x * matrix[1][0] + y * matrix[1][1] + z * matrix[1][2]\n            val bT = x * matrix[2][0] + y * matrix[2][1] + z * matrix[2][2]\n\n            // Discount illuminant\n            val rD = viewingConditions.rgbD[0] * rT\n            val gD = viewingConditions.rgbD[1] * gT\n            val bD = viewingConditions.rgbD[2] * bT\n\n            // Chromatic adaptation\n            val rAF = (viewingConditions.fl * abs(rD) / 100.0).pow(0.42)\n            val gAF = (viewingConditions.fl * abs(gD) / 100.0).pow(0.42)\n            val bAF = (viewingConditions.fl * abs(bD) / 100.0).pow(0.42)\n            val rA = sign(rD) * 400.0 * rAF / (rAF + 27.13)\n            val gA = sign(gD) * 400.0 * gAF / (gAF + 27.13)\n            val bA = sign(bD) * 400.0 * bAF / (bAF + 27.13)\n\n            // redness-greenness\n            val a = (11.0 * rA + -12.0 * gA + bA) / 11.0\n            // yellowness-blueness\n            val b = (rA + gA - 2.0 * bA) / 9.0\n\n            // auxiliary components\n            val u = (20.0 * rA + 20.0 * gA + 21.0 * bA) / 20.0\n            val p2 = (40.0 * rA + 20.0 * gA + bA) / 20.0\n\n            // hue\n            val atan2 = atan2(b, a)\n            val atanDegrees = atan2.toDegrees()\n            val hue =\n                if (atanDegrees < 0) atanDegrees + 360.0 else if (atanDegrees >= 360) atanDegrees - 360.0 else atanDegrees\n            val hueRadians = hue.toRadians()\n\n            // achromatic response to color\n            val ac = p2 * viewingConditions.nbb\n\n            // CAM16 lightness and brightness\n            val j = (100.0\n                    * (ac / viewingConditions.aw).pow(viewingConditions.c * viewingConditions.z))\n            val q = ((4.0\n                    / viewingConditions.c) * sqrt(j / 100.0)\n                    * (viewingConditions.aw + 4.0)\n                    * viewingConditions.flRoot)\n\n            // CAM16 chroma, colorfulness, and saturation.\n            val huePrime = if (hue < 20.14) hue + 360 else hue\n            val eHue = 0.25 * (cos(huePrime.toRadians() + 2.0) + 3.8)\n            val p1 = 50000.0 / 13.0 * eHue * viewingConditions.nc * viewingConditions.ncb\n            val t = p1 * hypot(a, b) / (u + 0.305)\n            val alpha =\n                (1.64 - 0.29.pow(viewingConditions.n)).pow(0.73) * t.pow(0.9)\n            // CAM16 chroma, colorfulness, saturation\n            val c = alpha * sqrt(j / 100.0)\n            val m = c * viewingConditions.flRoot\n            val s = 50.0 * sqrt(alpha * viewingConditions.c / (viewingConditions.aw + 4.0))\n\n            // CAM16-UCS components\n            val jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j)\n            val mstar = 1.0 / 0.0228 * ln1p(0.0228 * m)\n            val astar = mstar * cos(hueRadians)\n            val bstar = mstar * sin(hueRadians)\n            return Cam16(hue, c, j, q, m, s, jstar, astar, bstar)\n        }\n\n        /**\n         * @param j CAM16 lightness\n         * @param c CAM16 chroma\n         * @param h CAM16 hue\n         */\n        fun fromJch(j: Double, c: Double, h: Double): Cam16 {\n            return fromJchInViewingConditions(j, c, h, ViewingConditions.Companion.DEFAULT)\n        }\n\n        /**\n         * @param j CAM16 lightness\n         * @param c CAM16 chroma\n         * @param h CAM16 hue\n         * @param viewingConditions Information about the environment where the color was observed.\n         */\n        private fun fromJchInViewingConditions(\n            j: Double, c: Double, h: Double, viewingConditions: ViewingConditions\n        ): Cam16 {\n            val q = ((4.0\n                    / viewingConditions.c) * sqrt(j / 100.0)\n                    * (viewingConditions.aw + 4.0)\n                    * viewingConditions.flRoot)\n            val m = c * viewingConditions.flRoot\n            val alpha = c / sqrt(j / 100.0)\n            val s = 50.0 * sqrt(alpha * viewingConditions.c / (viewingConditions.aw + 4.0))\n            val hueRadians = h.toRadians()\n            val jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j)\n            val mstar = 1.0 / 0.0228 * ln1p(0.0228 * m)\n            val astar = mstar * cos(hueRadians)\n            val bstar = mstar * sin(hueRadians)\n            return Cam16(h, c, j, q, m, s, jstar, astar, bstar)\n        }\n\n        /**\n         * Create a CAM16 color from CAM16-UCS coordinates.\n         *\n         * @param jstar CAM16-UCS lightness.\n         * @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian coordinate on the Y\n         * axis.\n         * @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian coordinate on the X\n         * axis.\n         */\n        fun fromUcs(jstar: Double, astar: Double, bstar: Double): Cam16 {\n            return fromUcsInViewingConditions(\n                jstar,\n                astar,\n                bstar,\n                ViewingConditions.Companion.DEFAULT\n            )\n        }\n\n        /**\n         * Create a CAM16 color from CAM16-UCS coordinates in defined viewing conditions.\n         *\n         * @param jstar CAM16-UCS lightness.\n         * @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian coordinate on the Y\n         * axis.\n         * @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian coordinate on the X\n         * axis.\n         * @param viewingConditions Information about the environment where the color was observed.\n         */\n        fun fromUcsInViewingConditions(\n            jstar: Double, astar: Double, bstar: Double, viewingConditions: ViewingConditions\n        ): Cam16 {\n            val m = hypot(astar, bstar)\n            val m2 = expm1(m * 0.0228) / 0.0228\n            val c = m2 / viewingConditions.flRoot\n            var h = atan2(bstar, astar) * (180.0 / kotlin.math.PI)\n            if (h < 0.0) {\n                h += 360.0\n            }\n            val j = jstar / (1.0 - (jstar - 100.0) * 0.007)\n            return fromJchInViewingConditions(j, c, h, viewingConditions)\n        }\n\n        private inline fun Double.toRadians() = this * kotlin.math.PI / 180.0\n\n        private inline fun Double.toDegrees() = this * 180.0 / kotlin.math.PI\n    }\n}"
  },
  {
    "path": "color/src/main/java/io/material/hct/Hct.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage io.material.hct\n\nimport io.material.utils.ColorUtils\n\n/**\n * A color system built using CAM16 hue and chroma, and L* from L*a*b*.\n *\n *\n * Using L* creates a link between the color system, contrast, and thus accessibility. Contrast\n * ratio depends on relative luminance, or Y in the XYZ color space. L*, or perceptual luminance can\n * be calculated from Y.\n *\n *\n * Unlike Y, L* is linear to human perception, allowing trivial creation of accurate color tones.\n *\n *\n * Unlike contrast ratio, measuring contrast in L* is linear, and simple to calculate. A\n * difference of 40 in HCT tone guarantees a contrast ratio >= 3.0, and a difference of 50\n * guarantees a contrast ratio >= 4.5.\n */\n/**\n * HCT, hue, chroma, and tone. A color system that provides a perceptually accurate color\n * measurement system that can also accurately render what colors will appear as in different\n * lighting environments.\n */\nclass Hct private constructor(argb: Int) {\n    var hue = 0.0\n        private set\n    var chroma = 0.0\n        private set\n    var tone = 0.0\n        private set\n    var argb = 0\n\n    init {\n        setInternalState(argb)\n    }\n\n\n    fun toInt(): Int {\n        return argb\n    }\n\n    /**\n     * Set the hue of this color. Chroma may decrease because chroma has a different maximum for any\n     * given hue and tone.\n     *\n     * @param newHue 0 <= newHue < 360; invalid values are corrected.\n     */\n    fun setHue(newHue: Double) {\n        setInternalState(HctSolver.solveToInt(newHue, chroma, tone))\n    }\n\n    /**\n     * Set the chroma of this color. Chroma may decrease because chroma has a different maximum for\n     * any given hue and tone.\n     *\n     * @param newChroma 0 <= newChroma < ?\n     */\n    fun setChroma(newChroma: Double) {\n        setInternalState(HctSolver.solveToInt(hue, newChroma, tone))\n    }\n\n    /**\n     * Set the tone of this color. Chroma may decrease because chroma has a different maximum for any\n     * given hue and tone.\n     *\n     * @param newTone 0 <= newTone <= 100; invalid valids are corrected.\n     */\n    fun setTone(newTone: Double) {\n        setInternalState(HctSolver.solveToInt(hue, chroma, newTone))\n    }\n\n    /**\n     * Translate a color into different ViewingConditions.\n     *\n     *\n     * Colors change appearance. They look different with lights on versus off, the same color, as\n     * in hex code, on white looks different when on black. This is called color relativity, most\n     * famously explicated by Josef Albers in Interaction of Color.\n     *\n     *\n     * In color science, color appearance models can account for this and calculate the appearance\n     * of a color in different settings. HCT is based on CAM16, a color appearance model, and uses it\n     * to make these calculations.\n     *\n     *\n     * See ViewingConditions.make for parameters affecting color appearance.\n     */\n    fun inViewingConditions(vc: ViewingConditions): Hct {\n        // 1. Use CAM16 to find XYZ coordinates of color in specified VC.\n        val cam16: Cam16 = Cam16.Companion.fromInt(toInt())\n        val viewedInVc = cam16.xyzInViewingConditions(vc, null)\n\n        // 2. Create CAM16 of those XYZ coordinates in default VC.\n        val recastInVc: Cam16 = Cam16.Companion.fromXyzInViewingConditions(\n            viewedInVc[0], viewedInVc[1], viewedInVc[2], ViewingConditions.Companion.DEFAULT\n        )\n\n        // 3. Create HCT from:\n        // - CAM16 using default VC with XYZ coordinates in specified VC.\n        // - L* converted from Y in XYZ coordinates in specified VC.\n        return from(\n            recastInVc.hue, recastInVc.chroma, ColorUtils.lstarFromY(\n                viewedInVc[1]\n            )\n        )\n    }\n\n    private fun setInternalState(argb: Int) {\n        this.argb = argb\n        val cam: Cam16 = Cam16.Companion.fromInt(argb)\n        hue = cam.hue\n        chroma = cam.chroma\n        tone = ColorUtils.lstarFromArgb(argb)\n    }\n\n    companion object {\n        /**\n         * Create an HCT color from hue, chroma, and tone.\n         *\n         * @param hue 0 <= hue < 360; invalid values are corrected.\n         * @param chroma 0 <= chroma < ?; Informally, colorfulness. The color returned may be lower than\n         * the requested chroma. Chroma has a different maximum for any given hue and tone.\n         * @param tone 0 <= tone <= 100; invalid values are corrected.\n         * @return HCT representation of a color in default viewing conditions.\n         */\n        fun from(hue: Double, chroma: Double, tone: Double): Hct {\n            val argb = HctSolver.solveToInt(hue, chroma, tone)\n            return Hct(argb)\n        }\n\n        /**\n         * Create an HCT color from a color.\n         *\n         * @param argb ARGB representation of a color.\n         * @return HCT representation of a color in default viewing conditions\n         */\n        fun fromInt(argb: Int): Hct {\n            return Hct(argb)\n        }\n    }\n}"
  },
  {
    "path": "color/src/main/java/io/material/hct/HctSolver.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// This file is automatically generated. Do not modify it.\npackage io.material.hct\n\nimport io.material.utils.ColorUtils\nimport io.material.utils.MathUtils\nimport kotlin.math.abs\nimport kotlin.math.atan2\nimport kotlin.math.ceil\nimport kotlin.math.cos\nimport kotlin.math.floor\nimport kotlin.math.max\nimport kotlin.math.pow\nimport kotlin.math.sin\nimport kotlin.math.sqrt\n\n/** A class that solves the HCT equation.  */\nobject HctSolver {\n    val SCALED_DISCOUNT_FROM_LINRGB = arrayOf(\n        doubleArrayOf(\n            0.001200833568784504, 0.002389694492170889, 0.0002795742885861124\n        ), doubleArrayOf(\n            0.0005891086651375999, 0.0029785502573438758, 0.0003270666104008398\n        ), doubleArrayOf(\n            0.00010146692491640572, 0.0005364214359186694, 0.0032979401770712076\n        )\n    )\n    val LINRGB_FROM_SCALED_DISCOUNT = arrayOf(\n        doubleArrayOf(\n            1373.2198709594231, -1100.4251190754821, -7.278681089101213\n        ), doubleArrayOf(\n            -271.815969077903, 559.6580465940733, -32.46047482791194\n        ), doubleArrayOf(\n            1.9622899599665666, -57.173814538844006, 308.7233197812385\n        )\n    )\n    val Y_FROM_LINRGB = doubleArrayOf(0.2126, 0.7152, 0.0722)\n    val CRITICAL_PLANES = doubleArrayOf(\n        0.015176349177441876,\n        0.045529047532325624,\n        0.07588174588720938,\n        0.10623444424209313,\n        0.13658714259697685,\n        0.16693984095186062,\n        0.19729253930674434,\n        0.2276452376616281,\n        0.2579979360165119,\n        0.28835063437139563,\n        0.3188300904430532,\n        0.350925934958123,\n        0.3848314933096426,\n        0.42057480301049466,\n        0.458183274052838,\n        0.4976837250274023,\n        0.5391024159806381,\n        0.5824650784040898,\n        0.6277969426914107,\n        0.6751227633498623,\n        0.7244668422128921,\n        0.775853049866786,\n        0.829304845476233,\n        0.8848452951698498,\n        0.942497089126609,\n        1.0022825574869039,\n        1.0642236851973577,\n        1.1283421258858297,\n        1.1946592148522128,\n        1.2631959812511864,\n        1.3339731595349034,\n        1.407011200216447,\n        1.4823302800086415,\n        1.5599503113873272,\n        1.6398909516233677,\n        1.7221716113234105,\n        1.8068114625156377,\n        1.8938294463134073,\n        1.9832442801866852,\n        2.075074464868551,\n        2.1693382909216234,\n        2.2660538449872063,\n        2.36523901573795,\n        2.4669114995532007,\n        2.5710888059345764,\n        2.6777882626779785,\n        2.7870270208169257,\n        2.898822059350997,\n        3.0131901897720907,\n        3.1301480604002863,\n        3.2497121605402226,\n        3.3718988244681087,\n        3.4967242352587946,\n        3.624204428461639,\n        3.754355295633311,\n        3.887192587735158,\n        4.022731918402185,\n        4.160988767090289,\n        4.301978482107941,\n        4.445716283538092,\n        4.592217266055746,\n        4.741496401646282,\n        4.893568542229298,\n        5.048448422192488,\n        5.20615066083972,\n        5.3666897647573375,\n        5.5300801301023865,\n        5.696336044816294,\n        5.865471690767354,\n        6.037501145825082,\n        6.212438385869475,\n        6.390297286737924,\n        6.571091626112461,\n        6.7548350853498045,\n        6.941541251256611,\n        7.131223617812143,\n        7.323895587840543,\n        7.5195704746346665,\n        7.7182615035334345,\n        7.919981813454504,\n        8.124744458384042,\n        8.332562408825165,\n        8.543448553206703,\n        8.757415699253682,\n        8.974476575321063,\n        9.194643831691977,\n        9.417930041841839,\n        9.644347703669503,\n        9.873909240696694,\n        10.106627003236781,\n        10.342513269534024,\n        10.58158024687427,\n        10.8238400726681,\n        11.069304815507364,\n        11.317986476196008,\n        11.569896988756009,\n        11.825048221409341,\n        12.083451977536606,\n        12.345119996613247,\n        12.610063955123938,\n        12.878295467455942,\n        13.149826086772048,\n        13.42466730586372,\n        13.702830557985108,\n        13.984327217668513,\n        14.269168601521828,\n        14.55736596900856,\n        14.848930523210871,\n        15.143873411576273,\n        15.44220572664832,\n        15.743938506781891,\n        16.04908273684337,\n        16.35764934889634,\n        16.66964922287304,\n        16.985093187232053,\n        17.30399201960269,\n        17.62635644741625,\n        17.95219714852476,\n        18.281524751807332,\n        18.614349837764564,\n        18.95068293910138,\n        19.290534541298456,\n        19.633915083172692,\n        19.98083495742689,\n        20.331304511189067,\n        20.685334046541502,\n        21.042933821039977,\n        21.404114048223256,\n        21.76888489811322,\n        22.137256497705877,\n        22.50923893145328,\n        22.884842241736916,\n        23.264076429332462,\n        23.6469514538663,\n        24.033477234264016,\n        24.42366364919083,\n        24.817520537484558,\n        25.21505769858089,\n        25.61628489293138,\n        26.021211842414342,\n        26.429848230738664,\n        26.842203703840827,\n        27.258287870275353,\n        27.678110301598522,\n        28.10168053274597,\n        28.529008062403893,\n        28.96010235337422,\n        29.39497283293396,\n        29.83362889318845,\n        30.276079891419332,\n        30.722335150426627,\n        31.172403958865512,\n        31.62629557157785,\n        32.08401920991837,\n        32.54558406207592,\n        33.010999283389665,\n        33.4802739966603,\n        33.953417292456834,\n        34.430438229418264,\n        34.911345834551085,\n        35.39614910352207,\n        35.88485700094671,\n        36.37747846067349,\n        36.87402238606382,\n        37.37449765026789,\n        37.87891309649659,\n        38.38727753828926,\n        38.89959975977785,\n        39.41588851594697,\n        39.93615253289054,\n        40.460400508064545,\n        40.98864111053629,\n        41.520882981230194,\n        42.05713473317016,\n        42.597404951718396,\n        43.141702194811224,\n        43.6900349931913,\n        44.24241185063697,\n        44.798841244188324,\n        45.35933162437017,\n        45.92389141541209,\n        46.49252901546552,\n        47.065252796817916,\n        47.64207110610409,\n        48.22299226451468,\n        48.808024568002054,\n        49.3971762874833,\n        49.9904556690408,\n        50.587870934119984,\n        51.189430279724725,\n        51.79514187861014,\n        52.40501387947288,\n        53.0190544071392,\n        53.637271562750364,\n        54.259673423945976,\n        54.88626804504493,\n        55.517063457223934,\n        56.15206766869424,\n        56.79128866487574,\n        57.43473440856916,\n        58.08241284012621,\n        58.734331877617365,\n        59.39049941699807,\n        60.05092333227251,\n        60.715611475655585,\n        61.38457167773311,\n        62.057811747619894,\n        62.7353394731159,\n        63.417162620860914,\n        64.10328893648692,\n        64.79372614476921,\n        65.48848194977529,\n        66.18756403501224,\n        66.89098006357258,\n        67.59873767827808,\n        68.31084450182222,\n        69.02730813691093,\n        69.74813616640164,\n        70.47333615344107,\n        71.20291564160104,\n        71.93688215501312,\n        72.67524319850172,\n        73.41800625771542,\n        74.16517879925733,\n        74.9167682708136,\n        75.67278210128072,\n        76.43322770089146,\n        77.1981124613393,\n        77.96744375590167,\n        78.74122893956174,\n        79.51947534912904,\n        80.30219030335869,\n        81.08938110306934,\n        81.88105503125999,\n        82.67721935322541,\n        83.4778813166706,\n        84.28304815182372,\n        85.09272707154808,\n        85.90692527145302,\n        86.72564993000343,\n        87.54890820862819,\n        88.3767072518277,\n        89.2090541872801,\n        90.04595612594655,\n        90.88742016217518,\n        91.73345337380438,\n        92.58406282226491,\n        93.43925555268066,\n        94.29903859396902,\n        95.16341895893969,\n        96.03240364439274,\n        96.9059996312159,\n        97.78421388448044,\n        98.6670533535366,\n        99.55452497210776\n    )\n\n    /**\n     * Sanitizes a small enough angle in radians.\n     *\n     * @param angle An angle in radians; must not deviate too much from 0.\n     * @return A coterminal angle between 0 and 2pi.\n     */\n    fun sanitizeRadians(angle: Double): Double {\n        return (angle + kotlin.math.PI * 8) % (kotlin.math.PI * 2)\n    }\n\n    /**\n     * Delinearizes an RGB component, returning a floating-point number.\n     *\n     * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel\n     * @return 0.0 <= output <= 255.0, color channel converted to regular RGB space\n     */\n    fun trueDelinearized(rgbComponent: Double): Double {\n        val normalized = rgbComponent / 100.0\n        var delinearized = 0.0\n        delinearized = if (normalized <= 0.0031308) {\n            normalized * 12.92\n        } else {\n            1.055 * normalized.pow(1.0 / 2.4) - 0.055\n        }\n        return delinearized * 255.0\n    }\n\n    fun chromaticAdaptation(component: Double): Double {\n        val af = abs(component).pow(0.42)\n        return MathUtils.signum(component) * 400.0 * af / (af + 27.13)\n    }\n\n    /**\n     * Returns the hue of a linear RGB color in CAM16.\n     *\n     * @param linrgb The linear RGB coordinates of a color.\n     * @return The hue of the color in CAM16, in radians.\n     */\n    fun hueOf(linrgb: DoubleArray): Double {\n        val scaledDiscount = MathUtils.matrixMultiply(linrgb, SCALED_DISCOUNT_FROM_LINRGB)\n        val rA = chromaticAdaptation(scaledDiscount[0])\n        val gA = chromaticAdaptation(scaledDiscount[1])\n        val bA = chromaticAdaptation(scaledDiscount[2])\n        // redness-greenness\n        val a = (11.0 * rA + -12.0 * gA + bA) / 11.0\n        // yellowness-blueness\n        val b = (rA + gA - 2.0 * bA) / 9.0\n        return atan2(b, a)\n    }\n\n    fun areInCyclicOrder(a: Double, b: Double, c: Double): Boolean {\n        val deltaAB = sanitizeRadians(b - a)\n        val deltaAC = sanitizeRadians(c - a)\n        return deltaAB < deltaAC\n    }\n\n    /**\n     * Solves the lerp equation.\n     *\n     * @param source The starting number.\n     * @param mid The number in the middle.\n     * @param target The ending number.\n     * @return A number t such that lerp(source, target, t) = mid.\n     */\n    fun intercept(source: Double, mid: Double, target: Double): Double {\n        return (mid - source) / (target - source)\n    }\n\n    fun lerpPoint(source: DoubleArray, t: Double, target: DoubleArray): DoubleArray {\n        return doubleArrayOf(\n            source[0] + (target[0] - source[0]) * t,\n            source[1] + (target[1] - source[1]) * t,\n            source[2] + (target[2] - source[2]) * t\n        )\n    }\n\n    /**\n     * Intersects a segment with a plane.\n     *\n     * @param source The coordinates of point A.\n     * @param coordinate The R-, G-, or B-coordinate of the plane.\n     * @param target The coordinates of point B.\n     * @param axis The axis the plane is perpendicular with. (0: R, 1: G, 2: B)\n     * @return The intersection point of the segment AB with the plane R=coordinate, G=coordinate, or\n     * B=coordinate\n     */\n    fun setCoordinate(\n        source: DoubleArray,\n        coordinate: Double,\n        target: DoubleArray,\n        axis: Int\n    ): DoubleArray {\n        val t = intercept(source[axis], coordinate, target[axis])\n        return lerpPoint(source, t, target)\n    }\n\n    fun isBounded(x: Double): Boolean {\n        return x in 0.0..100.0\n    }\n\n    /**\n     * Returns the nth possible vertex of the polygonal intersection.\n     *\n     * @param y The Y value of the plane.\n     * @param n The zero-based index of the point. 0 <= n <= 11.\n     * @return The nth possible vertex of the polygonal intersection of the y plane and the RGB cube,\n     * in linear RGB coordinates, if it exists. If this possible vertex lies outside of the cube,\n     * [-1.0, -1.0, -1.0] is returned.\n     */\n    fun nthVertex(y: Double, n: Int): DoubleArray {\n        val kR = Y_FROM_LINRGB[0]\n        val kG = Y_FROM_LINRGB[1]\n        val kB = Y_FROM_LINRGB[2]\n        val coordA = if (n % 4 <= 1) 0.0 else 100.0\n        val coordB = if (n % 2 == 0) 0.0 else 100.0\n        return if (n < 4) {\n            val r = (y - coordA * kG - coordB * kB) / kR\n            if (isBounded(r)) {\n                doubleArrayOf(r, coordA, coordB)\n            } else {\n                doubleArrayOf(-1.0, -1.0, -1.0)\n            }\n        } else if (n < 8) {\n            val g = (y - coordB * kR - coordA * kB) / kG\n            if (isBounded(g)) {\n                doubleArrayOf(coordB, g, coordA)\n            } else {\n                doubleArrayOf(-1.0, -1.0, -1.0)\n            }\n        } else {\n            val b = (y - coordA * kR - coordB * kG) / kB\n            if (isBounded(b)) {\n                doubleArrayOf(coordA, coordB, b)\n            } else {\n                doubleArrayOf(-1.0, -1.0, -1.0)\n            }\n        }\n    }\n\n    /**\n     * Finds the segment containing the desired color.\n     *\n     * @param y The Y value of the color.\n     * @param targetHue The hue of the color.\n     * @return A list of two sets of linear RGB coordinates, each corresponding to an endpoint of the\n     * segment containing the desired color.\n     */\n    fun bisectToSegment(y: Double, targetHue: Double): Array<DoubleArray> {\n        var left = doubleArrayOf(-1.0, -1.0, -1.0)\n        var right = left\n        var leftHue = 0.0\n        var rightHue = 0.0\n        var initialized = false\n        var uncut = true\n        for (n in 0..11) {\n            val mid = nthVertex(y, n)\n            if (mid[0] < 0) {\n                continue\n            }\n            val midHue = hueOf(mid)\n            if (!initialized) {\n                left = mid\n                right = mid\n                leftHue = midHue\n                rightHue = midHue\n                initialized = true\n                continue\n            }\n            if (uncut || areInCyclicOrder(leftHue, midHue, rightHue)) {\n                uncut = false\n                if (areInCyclicOrder(leftHue, targetHue, midHue)) {\n                    right = mid\n                    rightHue = midHue\n                } else {\n                    left = mid\n                    leftHue = midHue\n                }\n            }\n        }\n        return arrayOf(left, right)\n    }\n\n    fun midpoint(a: DoubleArray, b: DoubleArray): DoubleArray {\n        return doubleArrayOf(\n            (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2\n        )\n    }\n\n    fun criticalPlaneBelow(x: Double): Int {\n        return floor(x - 0.5).toInt()\n    }\n\n    fun criticalPlaneAbove(x: Double): Int {\n        return ceil(x - 0.5).toInt()\n    }\n\n    /**\n     * Finds a color with the given Y and hue on the boundary of the cube.\n     *\n     * @param y The Y value of the color.\n     * @param targetHue The hue of the color.\n     * @return The desired color, in linear RGB coordinates.\n     */\n    fun bisectToLimit(y: Double, targetHue: Double): DoubleArray {\n        val segment = bisectToSegment(y, targetHue)\n        var left = segment[0]\n        var leftHue = hueOf(left)\n        var right = segment[1]\n        for (axis in 0..2) {\n            if (left[axis] != right[axis]) {\n                var lPlane = -1\n                var rPlane = 255\n                if (left[axis] < right[axis]) {\n                    lPlane = criticalPlaneBelow(\n                        trueDelinearized(\n                            left[axis]\n                        )\n                    )\n                    rPlane = criticalPlaneAbove(\n                        trueDelinearized(\n                            right[axis]\n                        )\n                    )\n                } else {\n                    lPlane = criticalPlaneAbove(\n                        trueDelinearized(\n                            left[axis]\n                        )\n                    )\n                    rPlane = criticalPlaneBelow(\n                        trueDelinearized(\n                            right[axis]\n                        )\n                    )\n                }\n                for (i in 0..7) {\n                    if (abs(rPlane - lPlane) <= 1) {\n                        break\n                    } else {\n                        val mPlane = floor((lPlane + rPlane) / 2.0).toInt()\n                        val midPlaneCoordinate = CRITICAL_PLANES[mPlane]\n                        val mid = setCoordinate(left, midPlaneCoordinate, right, axis)\n                        val midHue = hueOf(mid)\n                        if (areInCyclicOrder(leftHue, targetHue, midHue)) {\n                            right = mid\n                            rPlane = mPlane\n                        } else {\n                            left = mid\n                            leftHue = midHue\n                            lPlane = mPlane\n                        }\n                    }\n                }\n            }\n        }\n        return midpoint(left, right)\n    }\n\n    fun inverseChromaticAdaptation(adapted: Double): Double {\n        val adaptedAbs = abs(adapted)\n        val base = max(0.0, 27.13 * adaptedAbs / (400.0 - adaptedAbs))\n        return MathUtils.signum(adapted) * base.pow(1.0 / 0.42)\n    }\n\n    /**\n     * Finds a color with the given hue, chroma, and Y.\n     *\n     * @param hueRadians The desired hue in radians.\n     * @param chroma The desired chroma.\n     * @param y The desired Y.\n     * @return The desired color as a hexadecimal integer, if found; 0 otherwise.\n     */\n    fun findResultByJ(hueRadians: Double, chroma: Double, y: Double): Int {\n        // Initial estimate of j.\n        var j = sqrt(y) * 11.0\n        // ===========================================================\n        // Operations inlined from Cam16 to avoid repeated calculation\n        // ===========================================================\n        val viewingConditions: ViewingConditions = ViewingConditions.Companion.DEFAULT\n        val tInnerCoeff = 1 / (1.64 - 0.29.pow(viewingConditions.n)).pow(0.73)\n        val eHue = 0.25 * (cos(hueRadians + 2.0) + 3.8)\n        val p1 = eHue * (50000.0 / 13.0) * viewingConditions.nc * viewingConditions.ncb\n        val hSin = sin(hueRadians)\n        val hCos = cos(hueRadians)\n        for (iterationRound in 0..4) {\n            // ===========================================================\n            // Operations inlined from Cam16 to avoid repeated calculation\n            // ===========================================================\n            val jNormalized = j / 100.0\n            val alpha = if (chroma == 0.0 || j == 0.0) 0.0 else chroma / sqrt(jNormalized)\n            val t = (alpha * tInnerCoeff).pow(1.0 / 0.9)\n            val ac = (viewingConditions.aw\n                    * jNormalized.pow(1.0 / viewingConditions.c / viewingConditions.z))\n            val p2 = ac / viewingConditions.nbb\n            val gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11 * t * hCos + 108.0 * t * hSin)\n            val a = gamma * hCos\n            val b = gamma * hSin\n            val rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0\n            val gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0\n            val bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0\n            val rCScaled = inverseChromaticAdaptation(rA)\n            val gCScaled = inverseChromaticAdaptation(gA)\n            val bCScaled = inverseChromaticAdaptation(bA)\n            val linrgb = MathUtils.matrixMultiply(\n                doubleArrayOf(rCScaled, gCScaled, bCScaled),\n                LINRGB_FROM_SCALED_DISCOUNT\n            )\n            // ===========================================================\n            // Operations inlined from Cam16 to avoid repeated calculation\n            // ===========================================================\n            if (linrgb[0] < 0 || linrgb[1] < 0 || linrgb[2] < 0) {\n                return 0\n            }\n            val kR = Y_FROM_LINRGB[0]\n            val kG = Y_FROM_LINRGB[1]\n            val kB = Y_FROM_LINRGB[2]\n            val fnj = kR * linrgb[0] + kG * linrgb[1] + kB * linrgb[2]\n            if (fnj <= 0) {\n                return 0\n            }\n            if (iterationRound == 4 || abs(fnj - y) < 0.002) {\n                return if (linrgb[0] > 100.01 || linrgb[1] > 100.01 || linrgb[2] > 100.01) {\n                    0\n                } else ColorUtils.argbFromLinrgb(linrgb)\n            }\n            // Iterates with Newton method,\n            // Using 2 * fn(j) / j as the approximation of fn'(j)\n            j -= (fnj - y) * j / (2 * fnj)\n        }\n        return 0\n    }\n\n    /**\n     * Finds an sRGB color with the given hue, chroma, and L*, if possible.\n     *\n     * @param hueDegrees The desired hue, in degrees.\n     * @param chroma The desired chroma.\n     * @param lstar The desired L*.\n     * @return A hexadecimal representing the sRGB color. The color has sufficiently close hue,\n     * chroma, and L* to the desired values, if possible; otherwise, the hue and L* will be\n     * sufficiently close, and chroma will be maximized.\n     */\n    fun solveToInt(hueDegrees: Double, chroma: Double, lstar: Double): Int {\n        var hueDegrees = hueDegrees\n        if (chroma < 0.0001 || lstar < 0.0001 || lstar > 99.9999) {\n            return ColorUtils.argbFromLstar(lstar)\n        }\n        hueDegrees = MathUtils.sanitizeDegreesDouble(hueDegrees)\n        val hueRadians = hueDegrees / 180 * kotlin.math.PI\n        val y = ColorUtils.yFromLstar(lstar)\n        val exactAnswer = findResultByJ(hueRadians, chroma, y)\n        if (exactAnswer != 0) {\n            return exactAnswer\n        }\n        val linrgb = bisectToLimit(y, hueRadians)\n        return ColorUtils.argbFromLinrgb(linrgb)\n    }\n\n    /**\n     * Finds an sRGB color with the given hue, chroma, and L*, if possible.\n     *\n     * @param hueDegrees The desired hue, in degrees.\n     * @param chroma The desired chroma.\n     * @param lstar The desired L*.\n     * @return An CAM16 object representing the sRGB color. The color has sufficiently close hue,\n     * chroma, and L* to the desired values, if possible; otherwise, the hue and L* will be\n     * sufficiently close, and chroma will be maximized.\n     */\n    fun solveToCam(hueDegrees: Double, chroma: Double, lstar: Double): Cam16 {\n        return Cam16.Companion.fromInt(solveToInt(hueDegrees, chroma, lstar))\n    }\n}"
  },
  {
    "path": "color/src/main/java/io/material/hct/ViewingConditions.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage io.material.hct\n\nimport io.material.utils.ColorUtils\nimport io.material.utils.MathUtils\nimport kotlin.math.exp\nimport kotlin.math.max\nimport kotlin.math.pow\nimport kotlin.math.sqrt\n\n/**\n * In traditional color spaces, a color can be identified solely by the observer's measurement of\n * the color. Color appearance models such as CAM16 also use information about the environment where\n * the color was observed, known as the viewing conditions.\n *\n *\n * For example, white under the traditional assumption of a midday sun white point is accurately\n * measured as a slightly chromatic blue by CAM16. (roughly, hue 203, chroma 3, lightness 100)\n *\n *\n * This class caches intermediate values of the CAM16 conversion process that depend only on\n * viewing conditions, enabling speed ups.\n */\nclass ViewingConditions\n/**\n * Parameters are intermediate values of the CAM16 conversion process. Their names are shorthand\n * for technical color science terminology, this class would not benefit from documenting them\n * individually. A brief overview is available in the CAM16 specification, and a complete overview\n * requires a color science textbook, such as Fairchild's Color Appearance Models.\n */ private constructor(\n    val n: Double,\n    val aw: Double,\n    val nbb: Double,\n    val ncb: Double,\n    val c: Double,\n    val nc: Double,\n    val rgbD: DoubleArray,\n    val fl: Double,\n    val flRoot: Double,\n    val z: Double\n) {\n\n    companion object {\n        /** sRGB-like viewing conditions.  */\n        val DEFAULT = defaultWithBackgroundLstar(50.0)\n\n        /**\n         * Create ViewingConditions from a simple, physically relevant, set of parameters.\n         *\n         * @param whitePoint White point, measured in the XYZ color space. default = D65, or sunny day\n         * afternoon\n         * @param adaptingLuminance The luminance of the adapting field. Informally, how bright it is in\n         * the room where the color is viewed. Can be calculated from lux by multiplying lux by\n         * 0.0586. default = 11.72, or 200 lux.\n         * @param backgroundLstar The lightness of the area surrounding the color. measured by L* in\n         * L*a*b*. default = 50.0\n         * @param surround A general description of the lighting surrounding the color. 0 is pitch dark,\n         * like watching a movie in a theater. 1.0 is a dimly light room, like watching TV at home at\n         * night. 2.0 means there is no difference between the lighting on the color and around it.\n         * default = 2.0\n         * @param discountingIlluminant Whether the eye accounts for the tint of the ambient lighting,\n         * such as knowing an apple is still red in green light. default = false, the eye does not\n         * perform this process on self-luminous objects like displays.\n         */\n        fun make(\n            whitePoint: DoubleArray?,\n            adaptingLuminance: Double,\n            backgroundLstar: Double,\n            surround: Double,\n            discountingIlluminant: Boolean\n        ): ViewingConditions {\n            // A background of pure black is non-physical and leads to infinities that represent the idea\n            // that any color viewed in pure black can't be seen.\n            var backgroundLstar = backgroundLstar\n            backgroundLstar = max(0.1, backgroundLstar)\n            // Transform white point XYZ to 'cone'/'rgb' responses\n            val matrix: Array<DoubleArray> = Cam16.Companion.XYZ_TO_CAM16RGB\n            val rW =\n                whitePoint!![0] * matrix[0][0] + whitePoint[1] * matrix[0][1] + whitePoint[2] * matrix[0][2]\n            val gW =\n                whitePoint[0] * matrix[1][0] + whitePoint[1] * matrix[1][1] + whitePoint[2] * matrix[1][2]\n            val bW =\n                whitePoint[0] * matrix[2][0] + whitePoint[1] * matrix[2][1] + whitePoint[2] * matrix[2][2]\n            val f = 0.8 + surround / 10.0\n            val c = if (f >= 0.9) MathUtils.lerp(\n                0.59,\n                0.69,\n                (f - 0.9) * 10.0\n            ) else MathUtils.lerp(0.525, 0.59, (f - 0.8) * 10.0)\n            var d =\n                if (discountingIlluminant) 1.0 else f * (1.0 - 1.0 / 3.6 * exp((-adaptingLuminance - 42.0) / 92.0))\n            d = MathUtils.clampDouble(0.0, 1.0, d)\n            val rgbD = doubleArrayOf(\n                d * (100.0 / rW) + 1.0 - d, d * (100.0 / gW) + 1.0 - d, d * (100.0 / bW) + 1.0 - d\n            )\n            val k = 1.0 / (5.0 * adaptingLuminance + 1.0)\n            val k4 = k * k * k * k\n            val k4F = 1.0 - k4\n            val fl = k4 * adaptingLuminance + 0.1 * k4F * k4F * kotlin.math.cbrt(5.0 * adaptingLuminance)\n            val n = ColorUtils.yFromLstar(backgroundLstar) / whitePoint[1]\n            val z = 1.48 + sqrt(n)\n            val nbb = 0.725 / n.pow(0.2)\n            val rgbAFactors = doubleArrayOf(\n                (fl * rgbD[0] * rW / 100.0).pow(0.42),\n                (fl * rgbD[1] * gW / 100.0).pow(0.42),\n                (fl * rgbD[2] * bW / 100.0).pow(0.42)\n            )\n            val rgbA = doubleArrayOf(\n                400.0 * rgbAFactors[0] / (rgbAFactors[0] + 27.13),\n                400.0 * rgbAFactors[1] / (rgbAFactors[1] + 27.13),\n                400.0 * rgbAFactors[2] / (rgbAFactors[2] + 27.13)\n            )\n            val aw = (2.0 * rgbA[0] + rgbA[1] + 0.05 * rgbA[2]) * nbb\n            return ViewingConditions(\n                n,\n                aw,\n                nbb,\n                nbb,\n                c,\n                f,\n                rgbD,\n                fl,\n                fl.pow(0.25),\n                z\n            )\n        }\n\n        /**\n         * Create sRGB-like viewing conditions with a custom background lstar.\n         *\n         *\n         * Default viewing conditions have a lstar of 50, midgray.\n         */\n        fun defaultWithBackgroundLstar(lstar: Double): ViewingConditions {\n            return make(\n                ColorUtils.whitePointD65(),\n                200.0 / kotlin.math.PI * ColorUtils.yFromLstar(50.0) / 100f,\n                lstar,\n                2.0,\n                false\n            )\n        }\n    }\n}"
  },
  {
    "path": "color/src/main/java/io/material/utils/ColorUtils.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// This file is automatically generated. Do not modify it.\npackage io.material.utils\n\nimport kotlin.math.pow\nimport kotlin.math.roundToLong\n\n/**\n * Color science utilities.\n *\n *\n * Utility methods for color science constants and color space conversions that aren't HCT or\n * CAM16.\n */\nobject ColorUtils {\n    val SRGB_TO_XYZ = arrayOf(\n        doubleArrayOf(0.41233895, 0.35762064, 0.18051042),\n        doubleArrayOf(0.2126, 0.7152, 0.0722),\n        doubleArrayOf(0.01932141, 0.11916382, 0.95034478)\n    )\n    val XYZ_TO_SRGB = arrayOf(\n        doubleArrayOf(\n            3.2413774792388685, -1.5376652402851851, -0.49885366846268053\n        ), doubleArrayOf(\n            -0.9691452513005321, 1.8758853451067872, 0.04156585616912061\n        ), doubleArrayOf(\n            0.05562093689691305, -0.20395524564742123, 1.0571799111220335\n        )\n    )\n    val WHITE_POINT_D65 = doubleArrayOf(95.047, 100.0, 108.883)\n\n    /** Converts a color from RGB components to ARGB format.  */\n    fun argbFromRgb(red: Int, green: Int, blue: Int): Int {\n        return 255 shl 24 or (red and 255 shl 16) or (green and 255 shl 8) or (blue and 255)\n    }\n\n    /** Converts a color from linear RGB components to ARGB format.  */\n    fun argbFromLinrgb(linrgb: DoubleArray?): Int {\n        val r = delinearized(linrgb!![0])\n        val g = delinearized(linrgb[1])\n        val b = delinearized(linrgb[2])\n        return argbFromRgb(r, g, b)\n    }\n\n    /** Returns the alpha component of a color in ARGB format.  */\n    fun alphaFromArgb(argb: Int): Int {\n        return argb shr 24 and 255\n    }\n\n    /** Returns the red component of a color in ARGB format.  */\n    fun redFromArgb(argb: Int): Int {\n        return argb shr 16 and 255\n    }\n\n    /** Returns the green component of a color in ARGB format.  */\n    fun greenFromArgb(argb: Int): Int {\n        return argb shr 8 and 255\n    }\n\n    /** Returns the blue component of a color in ARGB format.  */\n    fun blueFromArgb(argb: Int): Int {\n        return argb and 255\n    }\n\n    /** Returns whether a color in ARGB format is opaque.  */\n    fun isOpaque(argb: Int): Boolean {\n        return alphaFromArgb(argb) >= 255\n    }\n\n    /** Converts a color from ARGB to XYZ.  */\n    fun argbFromXyz(x: Double, y: Double, z: Double): Int {\n        val matrix = XYZ_TO_SRGB\n        val linearR = matrix[0][0] * x + matrix[0][1] * y + matrix[0][2] * z\n        val linearG = matrix[1][0] * x + matrix[1][1] * y + matrix[1][2] * z\n        val linearB = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2] * z\n        val r = delinearized(linearR)\n        val g = delinearized(linearG)\n        val b = delinearized(linearB)\n        return argbFromRgb(r, g, b)\n    }\n\n    /** Converts a color from XYZ to ARGB.  */\n    fun xyzFromArgb(argb: Int): DoubleArray? {\n        val r = linearized(redFromArgb(argb))\n        val g = linearized(greenFromArgb(argb))\n        val b = linearized(blueFromArgb(argb))\n        return MathUtils.matrixMultiply(doubleArrayOf(r, g, b), SRGB_TO_XYZ)\n    }\n\n    /** Converts a color represented in Lab color space into an ARGB integer.  */\n    fun argbFromLab(l: Double, a: Double, b: Double): Int {\n        val whitePoint = WHITE_POINT_D65\n        val fy = (l + 16.0) / 116.0\n        val fx = a / 500.0 + fy\n        val fz = fy - b / 200.0\n        val xNormalized = labInvf(fx)\n        val yNormalized = labInvf(fy)\n        val zNormalized = labInvf(fz)\n        val x = xNormalized * whitePoint[0]\n        val y = yNormalized * whitePoint[1]\n        val z = zNormalized * whitePoint[2]\n        return argbFromXyz(x, y, z)\n    }\n\n    /**\n     * Converts a color from ARGB representation to L*a*b* representation.\n     *\n     * @param argb the ARGB representation of a color\n     * @return a Lab object representing the color\n     */\n    fun labFromArgb(argb: Int): DoubleArray {\n        val linearR = linearized(redFromArgb(argb))\n        val linearG = linearized(greenFromArgb(argb))\n        val linearB = linearized(blueFromArgb(argb))\n        val matrix = SRGB_TO_XYZ\n        val x = matrix[0][0] * linearR + matrix[0][1] * linearG + matrix[0][2] * linearB\n        val y = matrix[1][0] * linearR + matrix[1][1] * linearG + matrix[1][2] * linearB\n        val z = matrix[2][0] * linearR + matrix[2][1] * linearG + matrix[2][2] * linearB\n        val whitePoint = WHITE_POINT_D65\n        val xNormalized = x / whitePoint[0]\n        val yNormalized = y / whitePoint[1]\n        val zNormalized = z / whitePoint[2]\n        val fx = labF(xNormalized)\n        val fy = labF(yNormalized)\n        val fz = labF(zNormalized)\n        val l = 116.0 * fy - 16\n        val a = 500.0 * (fx - fy)\n        val b = 200.0 * (fy - fz)\n        return doubleArrayOf(l, a, b)\n    }\n\n    /**\n     * Converts an L* value to an ARGB representation.\n     *\n     * @param lstar L* in L*a*b*\n     * @return ARGB representation of grayscale color with lightness matching L*\n     */\n    fun argbFromLstar(lstar: Double): Int {\n        val y = yFromLstar(lstar)\n        val component = delinearized(y)\n        return argbFromRgb(component, component, component)\n    }\n\n    /**\n     * Computes the L* value of a color in ARGB representation.\n     *\n     * @param argb ARGB representation of a color\n     * @return L*, from L*a*b*, coordinate of the color\n     */\n    fun lstarFromArgb(argb: Int): Double {\n        val y = xyzFromArgb(argb)!![1]\n        return 116.0 * labF(y / 100.0) - 16.0\n    }\n\n    /**\n     * Converts an L* value to a Y value.\n     *\n     *\n     * L* in L*a*b* and Y in XYZ measure the same quantity, luminance.\n     *\n     *\n     * L* measures perceptual luminance, a linear scale. Y in XYZ measures relative luminance, a\n     * logarithmic scale.\n     *\n     * @param lstar L* in L*a*b*\n     * @return Y in XYZ\n     */\n    fun yFromLstar(lstar: Double): Double {\n        return 100.0 * labInvf((lstar + 16.0) / 116.0)\n    }\n\n    /**\n     * Converts a Y value to an L* value.\n     *\n     *\n     * L* in L*a*b* and Y in XYZ measure the same quantity, luminance.\n     *\n     *\n     * L* measures perceptual luminance, a linear scale. Y in XYZ measures relative luminance, a\n     * logarithmic scale.\n     *\n     * @param y Y in XYZ\n     * @return L* in L*a*b*\n     */\n    fun lstarFromY(y: Double): Double {\n        return labF(y / 100.0) * 116.0 - 16.0\n    }\n\n    /**\n     * Linearizes an RGB component.\n     *\n     * @param rgbComponent 0 <= rgb_component <= 255, represents R/G/B channel\n     * @return 0.0 <= output <= 100.0, color channel converted to linear RGB space\n     */\n    fun linearized(rgbComponent: Int): Double {\n        val normalized = rgbComponent / 255.0\n        return if (normalized <= 0.040449936) {\n            normalized / 12.92 * 100.0\n        } else {\n            ((normalized + 0.055) / 1.055).pow(2.4) * 100.0\n        }\n    }\n\n    /**\n     * Delinearizes an RGB component.\n     *\n     * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel\n     * @return 0 <= output <= 255, color channel converted to regular RGB space\n     */\n    fun delinearized(rgbComponent: Double): Int {\n        val normalized = rgbComponent / 100.0\n        var delinearized = 0.0\n        delinearized = if (normalized <= 0.0031308) {\n            normalized * 12.92\n        } else {\n            1.055 * normalized.pow(1.0 / 2.4) - 0.055\n        }\n        return MathUtils.clampInt(0, 255, (delinearized * 255.0).roundToLong().toInt())\n    }\n\n    /**\n     * Returns the standard white point; white on a sunny day.\n     *\n     * @return The white point\n     */\n    fun whitePointD65(): DoubleArray {\n        return WHITE_POINT_D65\n    }\n\n    fun labF(t: Double): Double {\n        val e = 216.0 / 24389.0\n        val kappa = 24389.0 / 27.0\n        return if (t > e) {\n            t.pow(1.0 / 3.0)\n        } else {\n            (kappa * t + 16) / 116\n        }\n    }\n\n    fun labInvf(ft: Double): Double {\n        val e = 216.0 / 24389.0\n        val kappa = 24389.0 / 27.0\n        val ft3 = ft * ft * ft\n        return if (ft3 > e) {\n            ft3\n        } else {\n            (116 * ft - 16) / kappa\n        }\n    }\n}"
  },
  {
    "path": "color/src/main/java/io/material/utils/MathUtils.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// This file is automatically generated. Do not modify it.\npackage io.material.utils\n\nimport kotlin.math.abs\n\n/** Utility methods for mathematical operations.  */\nobject MathUtils {\n    /**\n     * The signum function.\n     *\n     * @return 1 if num > 0, -1 if num < 0, and 0 if num = 0\n     */\n    fun signum(num: Double): Int {\n        return if (num < 0) {\n            -1\n        } else if (num == 0.0) {\n            0\n        } else {\n            1\n        }\n    }\n\n    /**\n     * The linear interpolation function.\n     *\n     * @return start if amount = 0 and stop if amount = 1\n     */\n    fun lerp(start: Double, stop: Double, amount: Double): Double {\n        return (1.0 - amount) * start + amount * stop\n    }\n\n    /**\n     * Clamps an integer between two integers.\n     *\n     * @return input when min <= input <= max, and either min or max otherwise.\n     */\n    fun clampInt(min: Int, max: Int, input: Int): Int {\n        if (input < min) {\n            return min\n        } else if (input > max) {\n            return max\n        }\n        return input\n    }\n\n    /**\n     * Clamps an integer between two floating-point numbers.\n     *\n     * @return input when min <= input <= max, and either min or max otherwise.\n     */\n    fun clampDouble(min: Double, max: Double, input: Double): Double {\n        if (input < min) {\n            return min\n        } else if (input > max) {\n            return max\n        }\n        return input\n    }\n\n    /**\n     * Sanitizes a degree measure as an integer.\n     *\n     * @return a degree measure between 0 (inclusive) and 360 (exclusive).\n     */\n    fun sanitizeDegreesInt(degrees: Int): Int {\n        var degrees = degrees\n        degrees %= 360\n        if (degrees < 0) {\n            degrees += 360\n        }\n        return degrees\n    }\n\n    /**\n     * Sanitizes a degree measure as a floating-point number.\n     *\n     * @return a degree measure between 0.0 (inclusive) and 360.0 (exclusive).\n     */\n    fun sanitizeDegreesDouble(degrees: Double): Double {\n        var degrees = degrees\n        degrees %= 360.0\n        if (degrees < 0) {\n            degrees += 360.0\n        }\n        return degrees\n    }\n\n    /**\n     * Sign of direction change needed to travel from one angle to another.\n     *\n     *\n     * For angles that are 180 degrees apart from each other, both directions have the same travel\n     * distance, so either direction is shortest. The value 1.0 is returned in this case.\n     *\n     * @param from The angle travel starts from, in degrees.\n     * @param to The angle travel ends at, in degrees.\n     * @return -1 if decreasing from leads to the shortest travel distance, 1 if increasing from leads\n     * to the shortest travel distance.\n     */\n    fun rotationDirection(from: Double, to: Double): Double {\n        val increasingDifference = sanitizeDegreesDouble(to - from)\n        return if (increasingDifference <= 180.0) 1.0 else -1.0\n    }\n\n    /** Distance of two points on a circle, represented using degrees.  */\n    fun differenceDegrees(a: Double, b: Double): Double {\n        return 180.0 - abs(abs(a - b) - 180.0)\n    }\n\n    /** Multiplies a 1x3 row vector with a 3x3 matrix.  */\n    fun matrixMultiply(row: DoubleArray, matrix: Array<DoubleArray>): DoubleArray {\n        val a = row[0] * matrix[0][0] + row[1] * matrix[0][1] + row[2] * matrix[0][2]\n        val b = row[0] * matrix[1][0] + row[1] * matrix[1][1] + row[2] * matrix[1][2]\n        val c = row[0] * matrix[2][0] + row[1] * matrix[2][1] + row[2] * matrix[2][2]\n        return doubleArrayOf(a, b, c)\n    }\n}"
  },
  {
    "path": "color/src/main/java/io/material/utils/StringUtils.kt",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage io.material.utils\n\n/** Utility methods for string representations of colors.  */\ninternal object StringUtils {\n    /**\n     * Hex string representing color, ex. #ff0000 for red.\n     *\n     * @param argb ARGB representation of a color.\n     */\n    fun hexFromArgb(argb: Int): String {\n        val red = ColorUtils.redFromArgb(argb)\n        val blue = ColorUtils.blueFromArgb(argb)\n        val green = ColorUtils.greenFromArgb(argb)\n        return String.format(\"#%02x%02x%02x\", red, green, blue)\n    }\n}"
  },
  {
    "path": "fastlane/metadata/android/ar-SA/full_description.txt",
    "content": "<b>الميزات</b>\n- تحميل مقاطع الفيديو والملفات الصوتية من منصات الفيديو المدعومة من yt-dlp\n- تضمين البيانات الوصفية وصورة الفيديو المصغرة في ملفات الصوت المستخرجة التي يدعمها mutagen.\n- تنزيل جميع مقاطع الفيديو في قائمة التشغيل بنقرة واحدة.\n- استخدم aria2c المدمج كبرنامج تنزيل خارجي لجميع التنزيلات الخاصة بك\n- دمج ملفات الترجمة في مقاطع الفيديو التي تم تنزيلها.\n- تنفيذ أوامر yt-dlp المخصصة باستخدام القوالب.\n- إدارة التنزيلات داخل التطبيق وقوالب الأوامر المخصصة.\n- سهل الاستخدام.\n- واجهة مستخدم بنمط تصميم Material Design 3 ، مع سمة ألوان ديناميكية Dynamic color.\n"
  },
  {
    "path": "fastlane/metadata/android/ar-SA/short_description.txt",
    "content": "برنامج لتنزيل ملفات الصوت والفيديو مصمم باستخدام Material You\n"
  },
  {
    "path": "fastlane/metadata/android/ar-SA/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/bn/short_description.txt",
    "content": "ম্যাটেরিয়াল ইউয়ের সাথে ডিজাইন করা অডিও/ভিডিও ডাউনলোডার\n"
  },
  {
    "path": "fastlane/metadata/android/bn/title.txt",
    "content": "সিল\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/changelogs/10320.txt",
    "content": "Verbesserungen der Zugänglichkeit:\nEntfernung von redundanter Semantik und Optimierung der Komponenten für TalkBack-Screenreader\n\nFehlerbehebung:\nApp stürzt aufgrund des Statusleistensymbols ab\nMP4-Formatpräferenz funktioniert manchmal nicht wie erwartet\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/changelogs/10330.txt",
    "content": "Funktionsupdate:\nPrivater Modus: Vorschaubild und Downloadverlauf deaktivieren\n\nWeißrussische Übersetzungen hinzugefügt von @Kekich-dev\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/changelogs/10340.txt",
    "content": "Funktionserweiterung:\nDynamische Farbe für Android 12+ aktivierbar\n\nFehlerbehebung:\nDropdown-Menü wird bei der Auswahl der Videoauflösung nicht angezeigt\n\nKroatische Übersetzungen von @ElizabethWega hinzugefügt\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/changelogs/10350.txt",
    "content": "Funktions-Update:\nSofortige Anzeige des Download-Dialogs nach Freigabe der Url\nVerhindern des Herunterladens bei gebührenpflichtigen Netzwerken\n\nFehlerbehebung:\nUnerwartetes Verhalten beim Öffnen gelöschter Dateien\nDrehen des Geräts führt dazu, dass Dialoge wieder angezeigt werden\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/full_description.txt",
    "content": "<b>Funktionen</b>\nHerunterladen von Videos und Audiodateien von Videoplattformen, die von yt-dlp unterstützt werden\nEinbetten von Metadaten und Videovorschaubildern in extrahierte Audiodateien\nDownload aller Videos in der Wiedergabeliste mit einem Klick\nNutzung des eingebetteten Aria2c als externen Downloader für alle Downloads\nUntertitel in heruntergeladene Videos einbetten\nAusführen von benutzerdefinierten yt-dlp-Befehlen mit Vorlagen\nVerwalten von In-App-Downloads und benutzerdefinierte Befehlsvorlagen\nEinfach zu bedienen und benutzerfreundlich\nBenutzeroberfläche im Material Design 3 Stil mit dynamischem Farbdesigns\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/short_description.txt",
    "content": "Video-/Audio-Downloader, gestaltet und designt mit Material You\n"
  },
  {
    "path": "fastlane/metadata/android/de-DE/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10704.txt",
    "content": "Feature Update:\nSelect from the formats of videos to download\nBuilt-in WebView to generate cookies for downloading\nRunning custom commands in parallel\n\nTranslation Update:\nAdd translations for Norwegian Nynorsk, Azerbaijani, and Punjabi\n\nFor full changelogs, please refer to GitHub"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10714.txt",
    "content": "Bug fixes and UI Improvements\n\nFor full changelogs, please refer to GitHub"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10724.txt",
    "content": "Bug Fix:\nPermission denied error when trying to access termux directory by accident\nApp crashes below API 26 (Android 8)"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10734.txt",
    "content": "Bug fixes and UI Improvements\n\nFor full changelogs, please refer to GitHub"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10804.txt",
    "content": "UI Improvements & Feature Updates:\n\nDownload to SD card\nQuick download\nTask dashboard, log page and custom shortcuts for custom commands\n...\n\nFor full changelogs, please refer to GitHub"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10814.txt",
    "content": "Fixed\n- App crashes when downloading in private mode\n- Unexpected ImeActions in TextFields\n- Disable SD card download when the directory is not set\n- Localized strings for file size texts"
  },
  {
    "path": "fastlane/metadata/android/en-US/changelogs/10824.txt",
    "content": "### Fixed\n- Trimmed ASCII characters filename\n- Unexpected error when downloading multiple video to SD card with quick download\n- Error when cropping vertical thumbnails as artwork"
  },
  {
    "path": "fastlane/metadata/android/en-US/full_description.txt",
    "content": "<b>Features</b>\nDownload videos and audio files from video platforms supported by yt-dlp\nEmbed metadata and video thumbnail into extracted audio files\nDownload all videos in the playlist with one click\nUse embedded aria2c as external downloader for all your downloads\nEmbed subtitles into downloaded videos\nExecute custom yt-dlp commands with templates\nManage in-app downloads and custom command templates\nEasy to use and user-friendly\nMaterial Design 3 style UI, with dynamic color theme"
  },
  {
    "path": "fastlane/metadata/android/en-US/short_description.txt",
    "content": "Video/Audio downloader designed and themed with Material You"
  },
  {
    "path": "fastlane/metadata/android/en-US/title.txt",
    "content": "Seal"
  },
  {
    "path": "fastlane/metadata/android/es/changelogs/10320.txt",
    "content": "Mejoras en la accesibilidad:\nEliminación de la semántica redundante y optimización de los componentes para el lector de pantalla TalkBack\n\nCorrección de errores:\nLa aplicación se bloqueaba debido al icono de la barra de estado\nLa preferencia de formato MP4 a veces no funcionaba como se esperaba\n"
  },
  {
    "path": "fastlane/metadata/android/es/changelogs/10330.txt",
    "content": "Actualización de características:\nModo privado: Deasctiva el historial de descargas y el almacenamiento de carátulas/miniaturas\n\nAñadido el idioma Bielorruso por @Kekich-dev\n"
  },
  {
    "path": "fastlane/metadata/android/es/changelogs/10340.txt",
    "content": "Actualización de características:\nHabilitar el color dinámico para Android 12+\n\nCorrección de errores:\nEl menú desplegable no se muestra al seleccionar la resolución de vídeo\n\nAñadir traducciones al croata por @ElizabethWega\n"
  },
  {
    "path": "fastlane/metadata/android/es/full_description.txt",
    "content": "<b>Características</b>\nDescargar vídeos y archivos de audio desde las plataformas soportadas por yt-dlp\nIncruste de metadatos y miniaturas de video en archivos de audio descargados\nDescarga de todos los vídeos de una lista de reproducción con un solo click\nUsar la librería incrustada aria2c como descargador externo \nSubtítulos integrados en los vídeos descargados\nEjecutar comandos personalizados de yt-dlp con plantillas\nManejar las descargas de dentro de la aplicación y las plantillas de comando personalizadas\nFácil de usar y muy intuitiva\nDiseño de interfaz hecho con Material Design 3 y con uso de los colores dinámicos\n"
  },
  {
    "path": "fastlane/metadata/android/es/short_description.txt",
    "content": "Descargador de audio/video diseñado y tematizado con Material You\n"
  },
  {
    "path": "fastlane/metadata/android/es/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/fr-FR/changelogs/10350.txt",
    "content": "Mise à jour de la fonctionnalité :\nAfficher la boîte de dialogue de téléchargement immédiatement après le partage de l'URL\nEmpêcher le téléchargement avec les réseaux à compteur\n\nCorrection de bogue :\nComportement inattendu lors de l'ouverture de fichiers supprimés\nLa rotation de l'appareil fait réapparaître les boîtes de dialogue\n"
  },
  {
    "path": "fastlane/metadata/android/fr-FR/full_description.txt",
    "content": "<b>Caractéristiques</b>\nTéléchargez des vidéos et des fichiers audio à partir de plateformes vidéo prises en charge par yt-dlp\nIncorporation de métadonnées et de vignettes vidéo dans les fichiers audio extraits\nTéléchargez toutes les vidéos de la liste de lecture en un seul clic\nUtilisez l'aria2c intégré comme téléchargeur externe pour tous vos téléchargements.\nIncorporation de sous-titres dans les vidéos téléchargées\nExécutez des commandes yt-dlp personnalisées à l'aide de modèles.\nGérez les téléchargements dans l'application et les modèles de commande personnalisés.\nFacile à utiliser et convivial\nInterface utilisateur de style Material Design 3, avec thème de couleurs dynamique\n"
  },
  {
    "path": "fastlane/metadata/android/fr-FR/short_description.txt",
    "content": "Téléchargeur vidéo/audio conçu et thématisé avec Material You\n"
  },
  {
    "path": "fastlane/metadata/android/fr-FR/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/hi/full_description.txt",
    "content": "<b>विशेषताएं</b>\nyt-dlp . द्वारा समर्थित वीडियो प्लेटफ़ॉर्म से वीडियो और ऑडियो फ़ाइलें डाउनलोड करें\nनिकाली गई ऑडियो फ़ाइलों में मेटाडेटा और वीडियो थंबनेल एम्बेड करें\nप्लेलिस्ट में सभी वीडियो एक क्लिक से डाउनलोड करें\nअपने सभी डाउनलोड के लिए बाहरी डाउनलोडर के रूप में एम्बेडेड aria2c का उपयोग करें\nडाउनलोड किए गए वीडियो में उपशीर्षक एम्बेड करें\nटेम्प्लेट के साथ कस्टम yt-dlp कमांड निष्पादित करें\nइन-ऐप डाउनलोड और कस्टम कमांड टेम्प्लेट प्रबंधित करें\nप्रयोग करने में आसान और उपयोगकर्ता के अनुकूल\nसामग्री डिजाइन 3 शैली यूआई, गतिशील रंग विषय के साथ\n"
  },
  {
    "path": "fastlane/metadata/android/hi/short_description.txt",
    "content": "वीडियो/ऑडियो डाउनलोडर जिसे आप सामग्री के साथ डिजाइन और थीम पर आधारित करते हैं\n"
  },
  {
    "path": "fastlane/metadata/android/hi/title.txt",
    "content": "सील\n"
  },
  {
    "path": "fastlane/metadata/android/hr/changelogs/10330.txt",
    "content": "Nove Značajke:\nPrivatni Način rada: Onemogućite minijature i povijest preuzimanja\n\nAplikacija prevedena na bjeloruski jezik uz pomoć @Kekich-dev\n"
  },
  {
    "path": "fastlane/metadata/android/hr/changelogs/10340.txt",
    "content": "Nove Značajke:\nMogućnost odabira dinamičnih boja za temu na Android 12+ verzijama\n\nPopravljena greška:\nPadajući prikaz se ne pojavljuje prilikom odabiranja razlučivosti videa\n\nPrijevod na hrvatski dodao/la: @ElizabethWega\n"
  },
  {
    "path": "fastlane/metadata/android/hr/full_description.txt",
    "content": "<b>Značajke</b>\nPreuzimajte video datoteke i zvučne zapise sa bilo koje video platforme koju podržava yt-dlp\nUgrađeni meta-podaci i minijatura videa izvedeni u audio datoteke\nSa samo jednim klikom preuzmite sve videe unutar popisa za reprodukciju\nMogućnost korištenja aria2c kako biste preuzeli ono što želite\nMogućnost ugrađivanja podnaslova u preuzete videe\nIzvršite razne yt-dlp naredbe pomoću naredbenih predložaka\nUpravljajte svojim preuzimanjima i prilagođenim naredbenim predlošcima\nLako za korištenje i prilagođeno korisniku\nMaterial Design 3 stil korisničkog sučelja, s dinamičnom promjenom boje tema\n"
  },
  {
    "path": "fastlane/metadata/android/hr/short_description.txt",
    "content": "Preuzima video/audio datoteka, dizajniran pomoću Material You\n"
  },
  {
    "path": "fastlane/metadata/android/hr/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/id/full_description.txt",
    "content": "<b>Fitur</b>\nUnduh video dan file audio dari platform video yang didukung oleh yt-dlp\nSematkan metadata dan gambar mini video ke dalam file audio yang diekstrak\nUnduh semua video di daftar putar dengan satu klik\nGunakan aria2c yang disematkan sebagai pengunduh eksternal untuk semua unduhan Anda\nSematkan subtitle ke dalam video yang diunduh\nJalankan perintah yt-dlp khusus dengan template\nKelola unduhan dalam aplikasi dan templat perintah khusus\nMudah digunakan dan ramah pengguna\nDesain Material 3 gaya UI, dengan tema warna dinamis\n"
  },
  {
    "path": "fastlane/metadata/android/id/short_description.txt",
    "content": "Pengunduh video/audio didesain dan ditema dengan Material You\n"
  },
  {
    "path": "fastlane/metadata/android/id/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/it/full_description.txt",
    "content": "<b>Features</b>\nDownload video e file audio da piattaforme video supportate da yt-dlp\nIncorpora metadati e miniature video nei file audio estratti\nScarica tutti i video nella playlist con un clic\nUsa aria2c incorporato come downloader esterno per tutti i tuoi download\nIncorpora i sottotitoli nei video scaricati\nEsegui comandi yt-dlp personalizzati con templates\nGestisci i download in-app e templates di comando personalizzati\nFacile da usare e user-friendly\nUI in stile Material Design 3, con tema colori dinamico\n"
  },
  {
    "path": "fastlane/metadata/android/it/short_description.txt",
    "content": "Video/Audio downloader progettato a tema con Material You\n"
  },
  {
    "path": "fastlane/metadata/android/it/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/ja/full_description.txt",
    "content": "<b>機能</b>\nyt-dlp がサポートするビデオプラットフォームから動画や音声ファイルをダウンロードすることができます。\n抽出した音声ファイルへのメタデータと動画サムネイルの埋め込み\nワンクリックでプレイリスト内の全動画をダウンロード\n外部ダウンローダーとして埋め込まれたaria2cを使用し、すべてのダウンロードを行うことができます。\nダウンロードしたビデオへの字幕の埋め込み\nテンプレートによるyt-dlpのカスタムコマンドの実行\nアプリ内ダウンロードとカスタムコマンドテンプレートの管理\n使いやすく、ユーザーフレンドリー\nシステムのカラーテーマに対応したMaterial Design 3スタイルのUI\n"
  },
  {
    "path": "fastlane/metadata/android/ja/short_description.txt",
    "content": "Material You デザインの動画・音声ダウンローダー\n"
  },
  {
    "path": "fastlane/metadata/android/ja/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/ml/full_description.txt",
    "content": "<b>സവിശേഷതകൾ</b>\nyt-dlp പിന്തുണയ്ക്കുന്ന വീഡിയോ പ്ലാറ്റ്‌ഫോമുകളിൽ നിന്ന് വീഡിയോകളും ഓഡിയോ ഫയലുകളും ഡൗൺലോഡ് ചെയ്യുക\nഎക്‌സ്‌ട്രാക്‌റ്റുചെയ്‌ത ഓഡിയോ ഫയലുകളിലേക്ക് മെറ്റാഡാറ്റയും വീഡിയോ ലഘുചിത്രവും ഉൾച്ചേർക്കുക\nഒരു ക്ലിക്കിലൂടെ പ്ലേലിസ്റ്റിലെ എല്ലാ വീഡിയോകളും ഡൗൺലോഡ് ചെയ്യുക\nനിങ്ങളുടെ എല്ലാ ഡൗൺലോഡുകൾക്കും ബാഹ്യ ഡൌൺലോഡറായി ഉൾച്ചേർത്ത aria2c ഉപയോഗിക്കുക\nഡൗൺലോഡ് ചെയ്‌ത വീഡിയോകളിൽ സബ്‌ടൈറ്റിലുകൾ ഉൾച്ചേർക്കുക\nടെംപ്ലേറ്റുകൾ ഉപയോഗിച്ച് ഇഷ്‌ടാനുസൃത yt-dlp കമാൻഡുകൾ എക്‌സിക്യൂട്ട് ചെയ്യുക\nഇൻ-ആപ്പ് ഡൗൺലോഡുകളും ഇഷ്‌ടാനുസൃത കമാൻഡ് ടെംപ്ലേറ്റുകളും നിയന്ത്രിക്കുക\nഉപയോഗിക്കാൻ എളുപ്പവും ഉപയോക്തൃ സൗഹൃദവും\nഡൈനാമിക് കളർ തീം ഉള്ള മെറ്റീരിയൽ ഡിസൈൻ 3 ശൈലി UI\n"
  },
  {
    "path": "fastlane/metadata/android/ml/short_description.txt",
    "content": "വീഡിയോ/ഓഡിയോ ഡൗൺലോഡർ രൂപകൽപ്പന ചെയ്‌ത് മെറ്റീരിയൽ യൂ ഉപയോഗിച്ച് തീം ചെയ്യുന്നു\n"
  },
  {
    "path": "fastlane/metadata/android/ml/title.txt",
    "content": "സീൽ\n"
  },
  {
    "path": "fastlane/metadata/android/nb-NO/full_description.txt",
    "content": "<b>Funksjoner</b>\nLast ned video- og lydfiler fra videoplattformer som støttes av yt-dlp\nInnebygg metadata og videominiatyrbilder inn i utledede lydfiler\nLast ned all video i en spilleliste med ett klikk\nBruk innebygd aria2c som ekstern nedlaster for alle nedlastinger\nInnebygg undertekster inn i alle nedlastede videoer\nKjør egendefinerte kommandoer og maler i yt-dlp\nHåndter nedlastinger og egendefinerte kommandomaler i programmet\nEnkelt å bruke og brukervennlig\nMateriell design 3 , med dynamisk fargedrakt\n"
  },
  {
    "path": "fastlane/metadata/android/nb-NO/short_description.txt",
    "content": "Nedlaster for video og lyd i materiell stil\n"
  },
  {
    "path": "fastlane/metadata/android/nb-NO/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/nl-NL/changelogs/10350.txt",
    "content": "Feature Update:\nToon download dialoog direct na het delen van url's\nVoorkomen van downloaden met netwerken met een meter\n\nBug Fix:\nOnverwacht gedrag bij het openen van verwijderde bestanden\nDraaien van apparaat zorgt ervoor dat dialogen weer verschijnen\n"
  },
  {
    "path": "fastlane/metadata/android/nl-NL/full_description.txt",
    "content": "<b>Kenmerken</b>\nDownload video's en audiobestanden van videoplatforms die door yt-dlp worden ondersteund\nEmbed metadata en video thumbnail in uitgepakte audiobestanden\nDownload alle video's in de afspeellijst met één klik\nGebruik embedded aria2c als externe downloader voor al uw downloads\nOndertitels insluiten in gedownloade video's\nVoer aangepaste yt-dlp commando's uit met sjablonen\nBeheer in-app downloads en aangepaste opdrachtsjablonen\nGebruiksvriendelijk en gebruiksvriendelijk\nMaterial Design 3 stijl UI, met dynamisch kleurenthema\n"
  },
  {
    "path": "fastlane/metadata/android/nl-NL/short_description.txt",
    "content": "Video/Audio downloader ontworpen en gethematiseerd met Material You\n"
  },
  {
    "path": "fastlane/metadata/android/nl-NL/title.txt",
    "content": "Zeehond\n"
  },
  {
    "path": "fastlane/metadata/android/pt-BR/short_description.txt",
    "content": "Baixador de Vídeo/Audio projetado e tematizado com Material You\n"
  },
  {
    "path": "fastlane/metadata/android/pt-BR/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/ru/full_description.txt",
    "content": "<b>Особенности</b>\nЗагружайте видео- и аудиофайлы с видеоплатформ, поддерживаемых yt-dlp\nВстраивать метаданные и миниатюры видео в извлеченные аудиофайлы\nЗагружайте все из плейлиста одним нажатием\nИспользуйте встроенный aria2c в качестве внешнего загрузчика для всех Ваших загрузок\nДобавляйте субтитры к загруженным видео\nВыполнение пользовательских команд yt-dlp с помощью шаблонов\nУправление загрузками в приложении и пользовательскими шаблонами команд\nПростой в использовании и удобный для пользователя\nПользовательский интерфейс в стиле Material Design 3 с динамической цветовой темой\n"
  },
  {
    "path": "fastlane/metadata/android/ru/short_description.txt",
    "content": "Видео/аудио загрузчик разработанный и созданный с помощью Material You\n"
  },
  {
    "path": "fastlane/metadata/android/ru/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/th/full_description.txt",
    "content": "<b>ความสามารถ</b>\nดาวน์โหลดไฟล์วิดีโอและเสียงจากแพลตฟอร์มวิดีโอด้วย yt-dlp\nฝังข้อมูลเมตาและภาพขนาดย่อของวิดีโอลงในไฟล์เสียงที่แยกออกมา\nดาวน์โหลดวิดีโอทั้งหมดในเพลย์ลิสต์ได้ในคลิกเดียว\nใช้ aria2c แบบฝังเป็นตัวดาวน์โหลดภายนอกสำหรับการดาวน์โหลดทั้งหมด\nฝังคำบรรยายลงในวิดีโอที่ดาวน์โหลดไว้\nใช้คำสั่ง yt-dlp แบบกำหนดเองด้วยเทมเพลต\nจัดการการดาวน์โหลดภายในแอพและเทมเพลตคำสั่งกำหนดเอง\nใช้งานง่ายและเป็นมิตรกับผู้ใช้\nUI สไตล์ Material Design 3 ด้วยธีมสีไดนามิก\n"
  },
  {
    "path": "fastlane/metadata/android/th/short_description.txt",
    "content": "โปรแกรมดาวน์โหลดวิดีโอ/เสียงที่ออกแบบในธีมbMaterial You\n"
  },
  {
    "path": "fastlane/metadata/android/th/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "fastlane/metadata/android/uk/full_description.txt",
    "content": "<b>Особливості</b>\nЗавантажуйте відео та аудіо файли з відео-платформ, які підтримуються yt-dlp\nВбудовуйте дані і прев'ю у вилучені аудіо файли\nЗавантажуйте усі відео з плейлиста в один клік\nВикористовуйте вбудований aria2c як зовнішній завантажувач для всіх своїх завантажень\nВбудовуйте субтитри у завантажені відео\nВиконуйте власні команди yt-dlp із шаблонами\nКеруйте завантаження у застосунку та спеціальні шаблони команд\nПростий у використанні та зручний\nСтилізований у Material Design 3 інтерфейс з динамічною колірною схемою\n"
  },
  {
    "path": "fastlane/metadata/android/uk/short_description.txt",
    "content": "Завантажувач відео та аудіо розроблений з Material You\n"
  },
  {
    "path": "fastlane/metadata/android/uk/title.txt",
    "content": "Тюлень\n"
  },
  {
    "path": "fastlane/metadata/android/vi/changelogs/10320.txt",
    "content": "Cải tiến khả năng tiếp cận:\nLoại bỏ ngữ nghĩa thừa và tối ưu hóa các thành phần cho trình đọc màn hình TalkBack\n\nVá lỗi:\nỨng dụng bị treo do biểu tượng trên thanh trạng thái\nTùy chọn định dạng MP4 đôi khi không hoạt động như mong đợi\n"
  },
  {
    "path": "fastlane/metadata/android/vi/full_description.txt",
    "content": "<b>Tính năng</b>\nTải video và âm thanh từ các nền tảng được hỗ trợ bởi yt-dlp\nNhúng metadata và thumbnail video vào tệp âm thanh\nTải tất cả video từ danh sách phát chỉ với một nhấn\nSử dụng aria2c làm trình tải về bên ngoài cho tất cả các Tải xuống của bạn\nNhúng chú thích vào video đã tải\nThực thi các lệnh yt-dlp tùy chỉnh theo mẫu\nQuản lý các tải xuống trong ứng dụng và mẫu lệnh tùy chỉnh\nDễ sử dụng và thân thiện với người dùng\nThiết kế Material Design 3, cùng với chủ đề màu động\n"
  },
  {
    "path": "fastlane/metadata/android/vi/short_description.txt",
    "content": "Phần mềm tải video/âm thanh và được thiết kế với Material You\n"
  },
  {
    "path": "fastlane/metadata/android/vi/title.txt",
    "content": "Hải Cẩu\n"
  },
  {
    "path": "fastlane/metadata/android/zh-CN/full_description.txt",
    "content": "<b>功能特色</b>\n从 yt-dlp 支持的视频平台下载视频和音频文件\n将元数据和视频缩略图嵌入到提取的音频文件中\n播放列表下载支持\n使用 aria2c 进行下载\n使用模板执行自定义 yt-dlp 命令\n管理应用内下载与自定义命令模板\n易于使用且用户友好\n遵循 Material Design 3 设计规范，动态色彩应用界面"
  },
  {
    "path": "fastlane/metadata/android/zh-CN/short_description.txt",
    "content": "从数千个网站下载视频与音频，以 Material You 设计风格呈现。"
  },
  {
    "path": "fastlane/metadata/android/zh-CN/title.txt",
    "content": "Seal"
  },
  {
    "path": "fastlane/metadata/android/zh-TW/changelogs/10330.txt",
    "content": "功能更新:\n無痕模式: 停用縮圖和儲存下載記錄\n\n新增白俄羅斯文，由 @Kekich-dev 提供\n"
  },
  {
    "path": "fastlane/metadata/android/zh-TW/full_description.txt",
    "content": "<b>功能特色</b>\n從 yt-dlp 支援的視訊平台下載視訊和音訊檔案\n可嵌入中繼資料和視訊縮圖至擷取的音訊檔案\n一鍵下載播放清單中的全數視訊\n可使用內建之 aria2c 作為外部下載程式\n可嵌入字幕至欲下載的視訊中\n可使用自訂範本以執行自訂 yt-dlp 命令\n輕鬆管理應用程式內下載和自訂範本\n簡單易用、平易近人\n以具有動態顏色主題的 Material Design 3 風格，作為介面 UI\n"
  },
  {
    "path": "fastlane/metadata/android/zh-TW/short_description.txt",
    "content": "以 Material You 設計打造的視訊/音訊下載程式\n"
  },
  {
    "path": "fastlane/metadata/android/zh-TW/title.txt",
    "content": "Seal\n"
  },
  {
    "path": "gradle/libs.versions.toml",
    "content": "[versions]\naccompanist = \"0.34.0\"\nandroidGradlePlugin = \"8.7.2\"\nandroidxComposeBom = \"2025.03.01\"\nandroidxCore = \"1.15.0\"\nandroidMaterial = \"1.12.0\"\nandroidxAppCompat = \"1.7.0\"\nandroidxActivity = \"1.10.1\"\ngraphics = \"1.0.1\"\nconstraintLayout = \"1.1.0\"\n\nandroidxLifecycle = \"2.8.7\"\nandroidxNavigation = \"2.8.9\"\n\nandroidxEspresso = \"3.5.0\"\nandroidxTestExt = \"1.1.4\"\n\n\ncoil = \"2.5.0\"\n\njunit4 = \"4.13.2\"\n\nkotlin = \"2.0.20\"\n\ncoroutines = \"1.9.0\"\ndatetime = \"0.6.1\"\nserialization = \"1.7.2\"\nokhttp = \"5.0.0-alpha.10\"\n\nroom = \"2.6.1\"\nksp = \"2.0.20-1.0.25\"\n\nyoutubedlAndroid = \"0.17.3\"\n\nmmkv = \"1.3.12\"\n# pin to v1.3.x for 32-bit support\n\nkoin = \"4.0.0\"\n\nktfmt = \"0.20.1\"\n\n[libraries]\n\n\nandroidx-core-ktx = { group = \"androidx.core\", name = \"core-ktx\", version.ref = \"androidxCore\" }\nandroid-material = { group = \"com.google.android.material\", name = \"material\", version.ref = \"androidMaterial\" }\nandroidx-appcompat = { group = \"androidx.appcompat\", name = \"appcompat\", version.ref = \"androidxAppCompat\" }\nandroidx-activity-compose = { group = \"androidx.activity\", name = \"activity-compose\", version.ref = \"androidxActivity\" }\n\nandroidx-lifecycle-runtimeCompose = { group = \"androidx.lifecycle\", name = \"lifecycle-runtime-compose\", version.ref = \"androidxLifecycle\" }\n\naccompanist-permissions = { group = \"com.google.accompanist\", name = \"accompanist-permissions\", version.ref = \"accompanist\" }\naccompanist-webview = { group = \"com.google.accompanist\", name = \"accompanist-webview\", version.ref = \"accompanist\" }\naccompanist-pager-indicators = { group = \"com.google.accompanist\", name = \"accompanist-pager-indicators\", version.ref = \"accompanist\" }\n\n#androidx-compose-bom = { group = \"androidx.compose\", name = \"compose-bom\", version.ref = \"androidxComposeBom\" }\nandroidx-compose-bom = { group = \"androidx.compose\", name = \"compose-bom-alpha\", version.ref = \"androidxComposeBom\" }\n\nandroidx-compose-foundation = { group = \"androidx.compose.foundation\", name = \"foundation\" }\nandroidx-compose-material-iconsExtended = { group = \"androidx.compose.material\", name = \"material-icons-extended\" }\nandroidx-compose-animation = { group = \"androidx.compose.animation\", name = \"animation\" }\nandroidx-compose-ui = { group = \"androidx.compose.ui\", name = \"ui\" }\n\nandroidx-compose-material = { group = \"androidx.compose.material\", name = \"material\" }\n\nandroidx-compose-material3 = { group = \"androidx.compose.material3\", name = \"material3\" }\nandroidx-compose-material3-windowSizeClass = { group = \"androidx.compose.material3\", name = \"material3-window-size-class\" }\n\nandroidx-graphics-shapes = { group = \"androidx.graphics\", name = \"graphics-shapes\", version.ref = \"graphics\" }\n\nokhttp = { group = \"com.squareup.okhttp3\", name = \"okhttp\", version.ref = \"okhttp\" }\n\nandroidx-compose-runtime = { group = \"androidx.compose.runtime\", name = \"runtime\" }\nandroidx-compose-ui-test = { group = \"androidx.compose.ui\", name = \"ui-test-junit4\" }\nandroidx-compose-ui-tooling = { group = \"androidx.compose.ui\", name = \"ui-tooling\" }\nandroidx-compose-ui-tooling-preview = { group = \"androidx.compose.ui\", name = \"ui-tooling-preview\" }\n\nandroidx-constraintlayout-compose = { group = \"androidx.constraintlayout\", name = \"constraintlayout-compose\", version.ref = \"constraintLayout\" }\n\nandroidx-navigation-compose = { group = \"androidx.navigation\", name = \"navigation-compose\", version.ref = \"androidxNavigation\" }\n\nandroidx-test-ext = { group = \"androidx.test.ext\", name = \"junit-ktx\", version.ref = \"androidxTestExt\" }\n\nandroidx-test-espresso-core = { group = \"androidx.test.espresso\", name = \"espresso-core\", version.ref = \"androidxEspresso\" }\n\n\ncoil-kt-compose = { group = \"io.coil-kt\", name = \"coil-compose\", version.ref = \"coil\" }\n\njunit4 = { group = \"junit\", name = \"junit\", version.ref = \"junit4\" }\n\nkotlinx-coroutines-android = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-coroutines-android\", version.ref = \"coroutines\" }\nkotlinx-datetime = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-datetime\", version.ref = \"datetime\" }\nkotlinx-serialization-json = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-serialization-json\", version.ref = \"serialization\" }\n\nkoin-android = { group = \"io.insert-koin\", name = \"koin-android\", version.ref = \"koin\" }\nkoin-compose = { group = \"io.insert-koin\", name = \"koin-androidx-compose\", version.ref = \"koin\" }\n\n\nroom-runtime = { group = \"androidx.room\", name = \"room-runtime\", version.ref = \"room\" }\nroom-ktx = { group = \"androidx.room\", name = \"room-ktx\", version.ref = \"room\" }\nroom-compiler = { group = \"androidx.room\", name = \"room-compiler\", version.ref = \"room\" }\n\n#youtubedl-android-library = { group = \"com.github.yausername.youtubedl_android\", name = \"library\", version.ref = \"youtubedlAndroid\" }\n#youtubedl-android-ffmpeg = { group = \"com.github.yausername.youtubedl_android\", name = \"ffmpeg\", version.ref = \"youtubedlAndroid\" }\n#youtubedl-android-aria2c = { group = \"com.github.yausername.youtubedl_android\", name = \"aria2c\", version.ref = \"youtubedlAndroid\" }\n\nyoutubedl-android-library = { group = \"io.github.junkfood02.youtubedl-android\", name = \"library\", version.ref = \"youtubedlAndroid\" }\nyoutubedl-android-ffmpeg = { group = \"io.github.junkfood02.youtubedl-android\", name = \"ffmpeg\", version.ref = \"youtubedlAndroid\" }\nyoutubedl-android-aria2c = { group = \"io.github.junkfood02.youtubedl-android\", name = \"aria2c\", version.ref = \"youtubedlAndroid\" }\n\nmmkv = { group = \"com.tencent\", name = \"mmkv\", version.ref = \"mmkv\" }\n\n[plugins]\nandroid-application = { id = \"com.android.application\", version.ref = \"androidGradlePlugin\" }\nandroid-library = { id = \"com.android.library\", version.ref = \"androidGradlePlugin\" }\nandroid-test = { id = \"com.android.test\", version.ref = \"androidGradlePlugin\" }\nkotlin-serialization = { id = \"org.jetbrains.kotlin.plugin.serialization\", version.ref = \"kotlin\" }\nkotlin-android = { id = \"org.jetbrains.kotlin.android\", version.ref = \"kotlin\" }\nksp = { id = \"com.google.devtools.ksp\", version.ref = \"ksp\" }\ncompose-compiler = { id = \"org.jetbrains.kotlin.plugin.compose\", version.ref = \"kotlin\" }\nroom = { id = \"androidx.room\", version.ref = \"room\" }\nktfmt-gradle = { id = \"com.ncorti.ktfmt.gradle\", version.ref = \"ktfmt\" }\n\n\n[bundles]\naccompanist = [\n    \"accompanist-permissions\",\n    \"accompanist-webview\",\n    \"accompanist-pager-indicators\",\n]\n\nandroidxCompose = [\"androidx-compose-ui\",\n    \"androidx-compose-ui-tooling-preview\",\n    \"androidx-compose-material-iconsExtended\",\n    \"androidx-compose-material3\",\n    \"androidx-compose-material3-windowSizeClass\",\n    \"androidx-compose-foundation\",\n    \"androidx-navigation-compose\",\n    \"androidx-compose-animation\",\n    \"androidx-constraintlayout-compose\"\n]\n\nyoutubedlAndroid = [\"youtubedl-android-library\",\n    \"youtubedl-android-ffmpeg\",\n    \"youtubedl-android-aria2c\"]\n\ncore = [\"androidx-activity-compose\",\n    \"android-material\",\n    \"androidx-appcompat\",\n    \"androidx-core-ktx\"]\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Oct 23 22:26:59 CST 2023\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.10.2-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app\"s APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\n# Enables namespacing of each library's R class so that its R class includes only the\n# resources declared in the library itself and none from the library's dependencies,\n# thereby reducing the size of the R class for that library\nandroid.nonTransitiveRClass=true\nABI_FILTERS=arm64-v8a\nandroid.nonFinalResIds=true\norg.gradle.configuration-cache=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "pluginManagement {\n    repositories {\n        gradlePluginPortal()\n        google()\n        mavenCentral()\n    }\n}\nplugins {\n    id(\"org.gradle.toolchains.foojay-resolver-convention\") version(\"0.4.0\")\n}\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        google()\n        mavenCentral()\n        mavenLocal()\n    }\n}\nrootProject.name = \"Seal\"\ninclude (\":app\")\ninclude(\":color\")"
  },
  {
    "path": "translations/README-ar.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### تطبيق لتحميل ملفات الفيديو والصوت من الإنترنت لنظام تشغيل اندرويد\n\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nالعربية\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n</a>\n\n<div align=\"right\">\n\n## 📱 لقطات شاشة\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n## 📖 الميزات\n\n<div dir=\"rtl\" align=\"rtl\">\n\t<ul dir=rtl>\n\t\t<li>  تحميل مقاطع الفيديو والملفات الصوتية من منصات الفيديو المدعومة من <a href=\"https://github.com/yt-dlp/yt-dlp\">yt-dlp</a> \n\t\t\t<a href=\"https://github.com/ytdl-org/youtube-dl\">سابقا youtube-dl</a>. </li>\n\t\t<li> قم بتضمين البيانات الوصفية وصورة الفيديو المصغرة في ملفات الصوت المستخرجة التي يدعمها <a href=\"https://github.com/quodlibet/mutagen\">mutagen</a>. </li>\n\t\t<li> استخدم <a href=\"https://github.com/aria2/aria2\">aria2c</a> المدمج كبرنامج تنزيل خارجي لجميع التنزيلات الخاصة بك. </li>\n\t\t<li> دمج ملفات الترجمة في مقاطع الفيديو التي تم تنزيلها. </li>\n\t\t<li>  تنفيذ أوامر <a href=\"https://github.com/yt-dlp/yt-dlp#usage-and-options\">yt-dlp</a> المخصصة باستخدام القوالب. </li>\n\t\t<li>  إدارة التنزيلات داخل التطبيق وقوالب الأوامر المخصصة. </li>\n\t\t<li>  سهل الاستخدام. </li>\n\t\t<li>  واجهة مستخدم بنمط تصميم <a href=\"https://m3.material.io/\">Material Design 3</a> ، مع سمة ألوان ديناميكية <a href=\"https://m3.material.io/foundations/customization\">Dynamic color</a>. </li>\n\t\t<li> واجهة المستخدم والمنطق مكتوبة باستخدام لغة Kotlin. نشاط فردي ، بدون أجزاء ، وجهات قابلة للتكوين فقط. </li>\n\n</div>\n\t\t\n## ⬇️ تحميل\n\nبالنسبة لمعظم الأجهزة ، يوصى بتثبيت إصدار **arm64-va** من التطبيق\n\n   قم بتنزيل أحدث <a href=\"https://github.com/JunkFood02/Seal/releases/latest\">إصدار مستقر</a> من إصدارات GitHub\n    \nقم بتثبيت <a href=\"https://github.com/JunkFood02/Seal/releases/\">الإصدارات المسبقة</a> لمساعدتنا في اختبار الميزات والتغييرات الجديدة\n  الإصدارات المستقرة متاحة أيضًا على F-Droid\n\n[<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on-ar.png\"\n    alt=\"Get it on F-Droid\"\n    height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/)\n\n\n## 🤝 المساهمة\n\nالمساهمات مرحب بها !\n\nيمكنك المساعدة في ترجمة Seal على موقع [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\n## 🔤 حالة الترجمة\n<p align=\"right\">\n<a href=\"https://hosted.weblate.org/engage/seal/ar/\">\n<img src=\"https://hosted.weblate.org/widgets/seal/ar/strings/multi-auto.svg\" alt=\"حالة الترجمة\" />\n</a>\n\n\nلإرسال تقارير الأخطاء أو طلب ميزات جديدة أو الأسئلة أو أي أفكار أخرى للتحسين ، يرجى قراءة ملف [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) للحصول على الإرشادات أولاً.\n\n## ⭐️ تاريخ النجوم\n<p align=\"right\">\n<a href=\"https://star-history.com/#JunkFood02/Seal&Timeline\">\n<img src=\"https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline\" alt=\"Star History Chart\" />\n</a>\n\n## 🧱 الاعتمادات\n\nهذا البرنامج عبارة عن واجهة مستخدم بسيطة لـ [yt-dlp](https://github.com/yt-dlp/yt-dlp) ، المبني على [youtubedl-android](https://github.com/yausername/youtubedl-android)\n\nتم استعارة بعض تصميمات وبرمجيات واجهة المستخدم من [Read You](https://github.com/Ashinch/ReadYou) و [Music You](https://github.com/Kyant0/MusicYou)\n<p align=\"right\">\n<a href=\"https://github.com/yausername/dvd\">dvd</a>\n</p>\n<p align=\"right\">\n<a href=https://github.com/material-foundation/material-color-utilities>Material color utilities</a>\n</p>\n<p align=\"right\">\n<a href=https://github.com/Kyant0/Monet>Monet</a>\n</p>\n\n## 📃 الرُخصة\n\n\n<p align=\"right\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/LICENSE\">\n<img src=\"https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge\" alt=\"GitHub\" />\n</a>\n\n​\t\n\n## ⚠️ تحذير\n\n<div dir=\"rtl\" align=\"rtl\">\n\t<ul dir=rtl>\n<p>باستثناء الرمز المصدري المرخص بموجب ترخيص GPLv3، يُحظر على جميع الأطراف الأخرى استخدام اسم Seal كتطبيق تنزيل، وينطبق الشيء نفسه على مشتقات\\نسخ Seal. المشتقات على سبيل المثال ليست حَصْرًا النسخ (Forks) والبنيات غير الرسمية (Unofficial Builds).<i>\n</div>\n\n<div align=\"left\">\n<table><td>\n<a href=\"#start-of-content\">👆 انتقل إلى أعلى</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-az.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Android üçün Video/Səs Yükləyici\n\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nAzərbaycanca\n</p>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub buraxılışı (ən son tarixə görə)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub buraxılışı (ilkin buraxılışlar daxil olmaqla son tarix)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Dəyişikliklər jurnalın saxla](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub bütün buraxılışlar](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Depo ulduzları](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Dəstəklənən Saytlar](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Kanalı](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Məkanı](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n  \n</div>\n\n\n## 📱 Ekran görüntüləri\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 Xüsusiyyətləri\n\n- [yt-dlp](https://github.com/yt-dlp/yt-dlp)(əvvəllər youtube-dl) tərəfindən dəstəklənən video platformalardan video və səs faylları yüklə. \n\n- [mutagen](https://github.com/quodlibet/mutagen) tərəfindən dəstəklənən çıxarılan səs fayllarına üst məlumat və video miniatür yerləşdirin.  \n\n- Pleylistdəki bütün videoları bir kliklə yüklə. \n\n- Bütün yükləmələriniz üçün xarici yükləyici kimi yerləşdirilmiş [aria2c](https://github.com/aria2/aria2) istifadə edin.  \n\n- Yüklənilmiş videolara titrlər yerləşdir. \n\n- Şablonlarla şəxsi yt-dlp əmrlərin icra edin.  \n\n- Tətbiqdaxili yükləmələri və şəxsi əmr şablonların idarə et.  \n\n- İstifadə üçün asan və istifadəçi dostudur.\n\n- [Material Design 3](https://m3.material.io/) stil UI, dinamik rəng temalı.  \n\n- MAD: UI və təmiz Kotlin ilə yazılan məntiq.Tək fəaliyyət, hissələr yoxdur, yalnız tərtib edilə bilən istiqamətlər.\n\n\n\n## ⬇️ Yüklənilmə\n\nƏksər cihazlar üçün apk-lərin **arm64-v8a** versiyasın quraşdırmaq tövsiyə olunur\n\n- Ən son stabil versiyanı [GitHub buraxılışlarından](https://github.com/JunkFood02/Seal/releases/latest) yüklə\n  - Yeni xüsusiyyətləri & dəyişiklikləri sınamağımıza kömək etmək üçün [buraxılışdan əvvəl](https://github.com/JunkFood02/Seal/releases/) versiyaların quraşdır\n    \n- Həmçinin stabil buraxılışlar [F-Droid](https://f-droid.org/packages/com.junkfood.seal/)-də mövcuddur\n \n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"F-Droid-də əldə et\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 Əlaqə\n\nMüzakirə, elanlar və buraxılışlar üçün [Telegram Kanalımıza](https://t.me/seal_app) və ya [Matrix Məkanımıza](https://matrix.to/#/#seal-space:matrix.org) qoşulun!\n\n## 💖 Himayədarlar\n\n<p><!-- sponsors --><a href=\"https://github.com/Marco-9456\"><img src=\"https://github.com/Marco-9456.png\" width=\"60px\" alt=\"mohammed_9456\" /></a><a href=\"https://github.com/Jas0n2k\"><img src=\"https://github.com/Jas0n2k.png\" width=\"60px\" alt=\"Jas0n2k\" /></a><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/gordongw\"><img src=\"https://github.com/gordongw.png\" width=\"60px\" alt=\"Gordon\" /></a><!-- sponsors --></p>\n\n\nSeal həmişə, hər kəs üçün pulsuz və açıq mənbə olacaqdır.Əgər bunu bəyənirsinizsə, xahiş edirəm [mənə himayədarlıq etməyi](https://github.com/sponsors/JunkFood02) fikirləşin!\n\n## 🤝 Töhfə\n\nTöhfələr Xoşdur!\n\nSiz [Hosted Weblate](https://hosted.weblate.org/projects/seal/)-də Seal-ı tərcümə etməyə kömək edə bilərsiniz.\n\n[![Tərcümə vəziyyəti](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>**Qeyd**\n>\n>Səhv hesabatları, xüsusiyyət sorğuları, suallar və ya təkmilləşdirmək üçün hər hansı digər ideyalar təqdim etmək üçün əvvəlcə təlimlər və təlimatlar üçün [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) bölməsin oxuyun.\n\n## ⭐️ Ulduz Tarixçəsi\n\n[![Ulduz Tarixçəsi Sxemi](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 Kreditlər\n\nSeal [youtubedl-android](https://github.com/yausername/youtubedl-android) əsasında [yt-dlp](https://github.com/yt-dlp/yt-dlp) ilə sadə GUI-dir.  \n\nBəzi UI dizaynları və kodları [Read You](https://github.com/Ashinch/ReadYou) və [Music You](https://github.com/Kyant0/MusicYou)-dan götürülmüşdür.\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 Lisenziya\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>**Xəbərdarlıq**\n>\n>GPLv3 lisenziyası əsasında lisenziyalaşdırılmış mənbə kodu istisna olmaqla,\n>bütün digər tərəflərə Seal-ın adından yükləyici tətbiq kimi istifadə etmək qadağandır,\n>və eynisi Seal-ın törəmələri üçün keçərlidir.\n>Törəmələrə çəngəllər və qeyri-rəsmi quruluşlar daxildir, lakin bunlarla məhdudlaşmır.  \n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Yuxarıya sürüşdür</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-bn.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Video/Audio Downloader for Android\n\n\nEnglish\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hans.md\">简体中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hant.md\">繁體中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ar.md\">العربية</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-pt.md\">Portuguese</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ua.md\">Українська</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-th.md\">ภาษาไทย</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-fa.md\">فارسی</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-it.md\">Italiano</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-az.md\">Azərbaycanca</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ru.md\">Русский</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-sr.md\">Српски</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ja.md\">日本語</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-id.md\">Indonesia</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-hi.md\">हिंदी</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-bn.md\">বাংলা</a>\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIC05NjAgOTYwIDk2MCIgd2lkdGg9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0zNTQtMjQ3IDEyNi03NiAxMjYgNzctMzMtMTQ0IDExMS05Ni0xNDYtMTMtNTgtMTM2LTU4IDEzNS0xNDYgMTMgMTExIDk3LTMzIDE0M1pNMjMzLTgwbDY1LTI4MUw4MC01NTBsMjg4LTI1IDExMi0yNjUgMTEyIDI2NSAyODggMjUtMjE4IDE4OSA2NSAyODEtMjQ3LTE0OUwyMzMtODBabTI0Ny0zNTBaIiBzdHlsZT0iZmlsbDogcmdiKDI0NSwgMjI3LCA2Nik7Ii8%2BCjwvc3ZnPg%3D%3D&color=%23f8e444)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported-Sites](https://img.shields.io/badge/Sites-9cf?style=flat&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0cHgiIGZpbGw9IiNGRkZGRkYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTExLjk5IDJDNi40NyAyIDIgNi40OCAyIDEyczQuNDcgMTAgOS45OSAxMEMxNy41MiAyMiAyMiAxNy41MiAyMiAxMlMxNy41MiAyIDExLjk5IDJ6bTYuOTMgNmgtMi45NWMtLjMyLTEuMjUtLjc4LTIuNDUtMS4zOC0zLjU2IDEuODQuNjMgMy4zNyAxLjkxIDQuMzMgMy41NnpNMTIgNC4wNGMuODMgMS4yIDEuNDggMi41MyAxLjkxIDMuOTZoLTMuODJjLjQzLTEuNDMgMS4wOC0yLjc2IDEuOTEtMy45NnpNNC4yNiAxNEM0LjEgMTMuMzYgNCAxMi42OSA0IDEycy4xLTEuMzYuMjYtMmgzLjM4Yy0uMDguNjYtLjE0IDEuMzItLjE0IDJzLjA2IDEuMzQuMTQgMkg0LjI2em0uODIgMmgyLjk1Yy4zMiAxLjI1Ljc4IDIuNDUgMS4zOCAzLjU2LTEuODQtLjYzLTMuMzctMS45LTQuMzMtMy41NnptMi45NS04SDUuMDhjLjk2LTEuNjYgMi40OS0yLjkzIDQuMzMtMy41NkM4LjgxIDUuNTUgOC4zNSA2Ljc1IDguMDMgOHpNMTIgMTkuOTZjLS44My0xLjItMS40OC0yLjUzLTEuOTEtMy45NmgzLjgyYy0uNDMgMS40My0xLjA4IDIuNzYtMS45MSAzLjk2ek0xNC4zNCAxNEg5LjY2Yy0uMDktLjY2LS4xNi0xLjMyLS4xNi0ycy4wNy0xLjM1LjE2LTJoNC42OGMuMDkuNjUuMTYgMS4zMi4xNiAycy0uMDcgMS4zNC0uMTYgMnptLjI1IDUuNTZjLjYtMS4xMSAxLjA2LTIuMzEgMS4zOC0zLjU2aDIuOTVjLS45NiAxLjY1LTIuNDkgMi45My00LjMzIDMuNTZ6TTE2LjM2IDE0Yy4wOC0uNjYuMTQtMS4zMi4xNC0ycy0uMDYtMS4zNC0uMTQtMmgzLjM4Yy4xNi42NC4yNiAxLjMxLjI2IDJzLS4xIDEuMzYtLjI2IDJoLTMuMzh6IiBzdHlsZT0iZmlsbDogcmdiKDE2MiwgMTk4LCAyMzQpOyIvPgo8L3N2Zz4=&label=Supported)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix](https://img.shields.io/matrix/seal-space%3Amatrix.org?server_fqdn=matrix.org&style=flat&logo=element&label=Matrix&color=%230DBD8B)\n](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱  স্ক্রিনশট\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 ফিচারস\n\n- [yt-dlp](https://github.com/yt-dlp/yt-dlp) (পূর্বের youtube-dl) সাপোর্টেড ভিডিও প্ল্যাটফর্ম থেকে ভিডিও এবং অডিও ফাইল ডাউনলোড করুন।\n\n- [mutagen](https://github.com/quodlibet/mutagen) সাপোর্টেড এক্সট্র্যাক্টটেড অডিও ফাইলগুলিতে মেটাডেটা এবং ভিডিও থাম্বনেল এমবেডেড।\n\n- এক ক্লিকে প্লে লিস্টের সব ভিডিও ডাউনলোড করুন।\n\n- সব ডাউনলোডের জন্য ডাউনলোডার হিসাবে এমবেডেড [aria2c](https://github.com/aria2/aria2) .\n\n- ডাউনলোড করা ভিডিওগুলিতে সাবটাইটেল এম্বেড।\n\n- টেমপ্লেট সহ কাস্টম yt-dlp কমান্ড রান করা।\n\n- ইন-অ্যাপ ডাউনলোড এবং কাস্টম কমান্ড টেমপ্লেট এর ব্যাবহার।\n\n- ব্যবহার করা সহজ এবং ইউজার ফ্রেন্ডলি।\n\n- [Material Design 3](https://m3.material.io/) স্টাইলের UI, ডাইনামিক থিম সহ।\n\n- MAD: UI এবং logic pure Kotlin এ কোড করা. একক কার্যকলাপ, কোন টুকরা নেই, শুধুমাত্র কমপোজ যোগ্য গন্তব্য।\n\n\n\n## ⬇️ ডাউনলোড\n\nবেশিরভাগ ডিভাইসের জন্য, apks-এর **arm64-v8a** ইনস্টল করুন।\n\n- [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest) থেকে লেটেস্ট রিলিজ ডাউনলোড করুন।\n  - আমাদের সাহায্য করতে নতুন ফিচার ও পরিবর্তন টেস্ট করতে জন্য [pre-release](https://github.com/JunkFood02/Seal/releases/) ভার্সন ইনস্টল করুন।\n\n- [F-Droid](https://f-droid.org/packages/com.junkfood.seal/) এও লেটেস্ট রিলিজ পাওয়া যাবে।\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 যোগাযোগ\n\nআলোচনা, ঘোষণা এবং রিলিজের জন্য আমাদের  [টেলিগ্রাম চ্যানেল](https://t.me/seal_app) বা [ম্যাট্রিক্স স্পেস](https://matrix.to/#/#seal-space:matrix.org) এ যোগ দিন!\n\n## 💖 স্পনসর\n\n<p><!-- sponsors --><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/gordongw\"><img src=\"https://github.com/gordongw.png\" width=\"60px\" alt=\"Gordon\" /></a><a href=\"https://github.com/zuble\"><img src=\"https://github.com/zuble.png\" width=\"60px\" alt=\"zuble\" /></a><a href=\"https://github.com/Dannyordaniel\"><img src=\"https://github.com/Dannyordaniel.png\" width=\"60px\" alt=\"Daniel \" /></a><a href=\"https://github.com/NRN83\"><img src=\"https://github.com/NRN83.png\" width=\"60px\" alt=\"\" /></a><!-- sponsors --></p>\n\n\nসীল সর্বদা বিনামূল্যে এবং সবার জন্য উন্মুক্ত থাকবে । আপনারা যদি এটা পছন্দ করে থাকেন, আমাকে [স্পনসর করুন!](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 অবদান\n\n সবার অবদানকে স্বাগত জানাই!\n আপনি [Hosted Weblate](https://hosted.weblate.org/projects/seal/) সিল অনুবাদ করতে সাহায্য করতে পারেন।\n\t\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\t\n>[!দ্রষ্টব্য]\n>\n>বাগ রিপোর্ট জমা দেওয়ার জন্য, ফিচার এর অনুরোধ, প্রশ্ন, বা ডেভেলপমেন্টের জন্য অন্য কোন পরামর্শ থাকলে অনুগ্রহ করে প্রথমে নির্দেশাবলী এবং নির্দেশিকাগুলির জন্য  [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) পড়ুন।\n\n## ⭐️ স্টার চার্ট\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 ক্রেডিট\n\n[youtubedl-android](https://github.com/yausername/youtubedl-android) -এর উপর ভিত্তি করে সিল  [yt-dlp](https://github.com/yt-dlp/yt-dlp) -এর একটি সাধারণ GUI, \n\nকিছু UI ডিজাইন এবং কোড [Read You](https://github.com/Ashinch/ReadYou) এবং [Music You](https://github.com/Kyant0/MusicYou) থেকে ধার করা হয়েছে।\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃  লাইসেন্স\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>[!সতর্কতা]\n>\n>GPLv3 লাইসেন্সের অধীনে লাইসেন্সকৃত সোর্স কোড ব্যতীত, অন্যান্য সমস্ত পক্ষকে ডাউনলোডার অ্যাপ \n>হিসাবে সিলের নাম ব্যবহার করা নিষিদ্ধ এবং সিলের ডেরিভেটিভের ক্ষেত্রেও এটি সত্য। ডেরিভেটিভস \n>অন্তর্ভুক্ত কিন্তু ফোর্ক এবং অফিসিয়াল বিল্ডের মধ্যে সীমাবদ্ধ নয়।\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 উপরে স্ক্রোল করুন</a>\n</td></table>\n</div>"
  },
  {
    "path": "translations/README-fa.md",
    "content": "<div align=\"center\">\n<p align=\"center\"> \n\t<img src=\"fastlane/metadata/android/en-US/images/icon.png\" width=160 height=160 >\n</p>\n<h1 align=\"center\">\nSeal\n</h1>\n</div>\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal.svg?logo=F-Droid&color=green&style=flat-square)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![Releases](https://img.shields.io/github/release/JunkFood02/Seal.svg?logo=github&color=171515&label=stable&style=flat-square)](https://github.com/JunkFood02/Seal/releases/latest)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=preview&logo=github)](https://github.com/JunkFood02/Seal/releases)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?style=flat-square)](https://github.com/JunkFood02/Seal/releases)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat-square)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat-square)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat-square&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat-square&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n<p align=\"center\">\n  <a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nفارسی\n</p>\n\n## 📱 اسکرین شات ها\n\n<div align=\"center\">\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n<br>\n\n## 📖 امکانات\n\n<div dir=\"rtl\" align=\"rtl\">\n\t<ul dir=rtl>\n\t\t<li> دانلود ویدیو و صدا های پشتیبانی شده توسط <a href=\"https://github.com/yt-dlp/yt-dlp\">yt-dlp</a> </li>\n\t\t<li>چسباندن فراداده و تصویر بندانگشتی ویدیو را در فایل های صوتی که توسط <a href=\"https://github.com/quodlibet/mutagen\">mutagen</a>. پشتیبانی می شود</li>\n\t\t<li>دانلود تمامی ویدیو های یک لیست پخش فقط با یک کلیک</li>\n\t\t<li>قابلیت استفاده از <a href=\"https://github.com/aria2/aria2\">aria2c</a> برای دانلود</li>\n\t\t<li>چسباندن زیرنویس ها به فیلم های دانلودی</li>\n\t\t<li>اجرای دستورات سفارشی yt-dlp به وسیله الگو ها</li>\n\t\t<li>امکان مدیریت دانلود های درون برنامه ای و الگو های سفارشی دستورات</li>\n\t\t<li>سادگی در استفاده و کاربرپسند</li>\n\t\t<li> طراحی رابط کاربری <a href=\"https://m3.material.io/\">Material Design 3</a> با رنگ پویا</li>\n\t\t<li> ظاهر برنامه و شرط ها با زبان کاتلین نوشته شده است</li>\n\n</div>\n\n## ⬇️ دانلود \n\nبرای اکثر دستگاه ها پیشنهاد می شود نسخه **arm64-v8a** را دانلود کنید.\n\n-دانلود آخرین نسخه برنامه [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest)\n\n-[نسخه آزمایشی](https://github.com/JunkFood02/Seal/releases/) را جهت تست و کمک به ما در توسعه دانلود کنید\n\n- دانلود آخرین نسخه از F-Droid :\n\n[<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/)\n     \n## 💬 تماس با ما\n\nجهت گفتگو و با خبر شدن از آخرین بروزرسانی به کانال ما در تلگرام به [@seal_app](https://t.me/seal_app) و در فضای ماتریکس به آدرس [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) بپیوندید\n\n## 🤝 همکاری\n\nعلاقه مند به کمک به ما هستید ؟ برای کمک در ترجمه برنامه می توانید به [Hosted Weblate](https://hosted.weblate.org/projects/seal/) مراجعه کنید و مارا در ترجمه برنامه یاری کنید\n\n<p align=\"right\">\n<a href=\"https://hosted.weblate.org/engage/seal/fa/\">\n<img src=\"https://hosted.weblate.org/widgets/seal/fa/strings/multi-auto.svg\" alt=\"وضعیت ترجمه\" />\n</a>\n\n>**نکته**\n\nجهت ارسال هرگونه گزارش مشکل, سوالات, ایده ها و کمک در توسعه برنامه ابتدا دستورالعمل را به آدرس [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) مطالعه کنید\n\n## ⭐️تاریخچه امتیاز\n<p align=\"right\">\n<a href=\"https://star-history.com/#JunkFood02/Seal&Timeline\">\n<img src=\"https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline\" alt=\"Star History Chart\" />\n</p>\n\n## 🧱 منابع\n\nبرنامه Seal یک نسخه گرافیکی از [yt-dlp](https://github.com/yt-dlp/yt-dlp) می باشد و بر پایه [youtubedl-android](https://github.com/yausername/youtubedl-android) توسعه داده شده است\n\nبرخی از کد های برنامه از [Read You](https://github.com/Ashinch/ReadYou) و [Music You](https://github.com/Kyant0/MusicYou) قرض گرفته شده است\n<p align=\"right\">\n<a href=\"https://github.com/yausername/dvd\">dvd</a>\n</p>\n<p align=\"right\">\n<a href=\"https://github.com/material-foundation/material-color-utilities\">Material color utilities</a>\n</p>\n<p align=\"right\">\n<a href=\"https://github.com/Kyant0/Monet\">Monet</a>\n</p>\n\n## 📃 لایسنس\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">رفتن به بالا</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-hi.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Android के लिए वीडियो/ऑडियो डाउनलोडर\n\nEnglish\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hans.md\">简体中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hant.md\">繁體中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ar.md\">العربية</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-pt.md\">Portuguese</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ua.md\">Українська</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-th.md\">ภาษาไทย</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-fa.md\">فارسی</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-it.md\">Italiano</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-az.md\">Azərbaycanca</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ru.md\">Русский</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-sr.md\">Српски</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ja.md\">日本語</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-id.md\">Indonesia</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-hi.md\">हिंदी</a>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIC05NjAgOTYwIDk2MCIgd2lkdGg9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0zNTQtMjQ3IDEyNi03NiAxMjYgNzctMzMtMTQ0IDExMS05Ni0xNDYtMTMtNTgtMTM2LTU4IDEzNS0xNDYgMTMgMTExIDk3LTMzIDE0M1pNMjMzLTgwbDY1LTI4MUw4MC01NTBsMjg4LTI1IDExMi0yNjUgMTEyIDI2NSAyODggMjUtMjE4IDE4OSA2NSAyODEtMjQ3LTE0OUwyMzMtODBabTI0Ny0zNTBaIiBzdHlsZT0iZmlsbDogcmdiKDI0NSwgMjI3LCA2Nik7Ii8%2BCjwvc3ZnPg%3D%3D&color=%23f8e444)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported-Sites](https://img.shields.io/badge/Sites-9cf?style=flat&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0cHgiIGZpbGw9IiNGRkZGRkYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTExLjk5IDJDNi40NyAyIDIgNi40OCAyIDEyczQuNDcgMTAgOS45OSAxMEMxNy41MiAyMiAyMiAxNy41MiAyMiAxMlMxNy41MiAyIDExLjk5IDJ6bTYuOTMgNmgtMi45NWMtLjMyLTEuMjUtLjc4LTIuNDUtMS4zOC0zLjU2IDEuODQuNjMgMy4zNyAxLjkxIDQuMzMgMy41NnpNMTIgNC4wNGMuODMgMS4yIDEuNDggMi41MyAxLjkxIDMuOTZoLTMuODJjLjQzLTEuNDMgMS4wOC0yLjc2IDEuOTEtMy45NnpNNC4yNiAxNEM0LjEgMTMuMzYgNCAxMi42OSA0IDEycy4xLTEuMzYuMjYtMmgzLjM4Yy0uMDguNjYtLjE0IDEuMzItLjE0IDJzLjA2IDEuMzQuMTQgMkg0LjI2em0uODIgMmgyLjk1Yy4zMiAxLjI1Ljc4IDIuNDUgMS4zOCAzLjU2LTEuODQtLjYzLTMuMzctMS45LTQuMzMtMy41NnptMi45NS04SDUuMDhjLjk2LTEuNjYgMi40OS0yLjkzIDQuMzMtMy41NkM4LjgxIDUuNTUgOC4zNSA2Ljc1IDguMDMgOHpNMTIgMTkuOTZjLS44My0xLjItMS40OC0yLjUzLTEuOTEtMy45NmgzLjgyYy0uNDMgMS40My0xLjA4IDIuNzYtMS45MSAzLjk2ek0xNC4zNCAxNEg5LjY2Yy0uMDktLjY2LS4xNi0xLjMyLS4xNi0ycy4wNy0xLjM1LjE2LTJoNC42OGMuMDkuNjUuMTYgMS4zMi4xNiAycy0uMDcgMS4zNC0uMTYgMnptLjI1IDUuNTZjLjYtMS4xMSAxLjA2LTIuMzEgMS4zOC0zLjU2aDIuOTVjLS45NiAxLjY1LTIuNDkgMi45My00LjMzIDMuNTZ6TTE2LjM2IDE0Yy4wOC0uNjYuMTQtMS4zMi4xNC0ycy0uMDYtMS4zNC0uMTQtMmgzLjM4Yy4xNi42NC4yNiAxLjMxLjI2IDJzLS4xIDEuMzYtLjI2IDJoLTMuMzh6IiBzdHlsZT0iZmlsbDogcmdiKDE2MiwgMTk4LCAyMzQpOyIvPgo8L3N2Zz4=&label=Supported)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix](https://img.shields.io/matrix/seal-space%3Amatrix.org?server_fqdn=matrix.org&style=flat&logo=element&label=Matrix&color=%230DBD8B)\n](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱 स्क्रीनशॉट\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 विशेषताएँ\n\n- [yt-dlp](https://github.com/yt-dlp/yt-dlp) (पूर्व में youtube-dl) द्वारा समर्थित वीडियो प्लेटफ़ॉर्म से वीडियो और ऑडियो फ़ाइलें डाउनलोड करें।\n\n- [mutagen](https://github.com/quodlibet/mutagen) द्वारा समर्थित ऑडियो फ़ाइलों में मेटाडेटा और वीडियो थंबनेल एम्बेड करें।\n\n- एक क्लिक में प्लेलिस्ट में सभी वीडियो डाउनलोड करें।\n\n- सभी डाउनलोड के लिए बाहरी डाउनलोडर के रूप में एम्बेडेड [aria2c](https://github.com/aria2/aria2) का उपयोग करें।\n\n- डाउनलोड किए गए वीडियो में सबटाइटल एम्बेड करें।\n\n- टेम्प्लेट के साथ कस्टम yt-dlp कमांड चलाएँ।\n\n- इन-ऐप डाउनलोड और कस्टम कमांड टेम्प्लेट प्रबंधित करें।\n\n- उपयोग में आसान और उपयोगकर्ता-मित्रवत।\n\n- [Material Design 3](https://m3.material.io/) शैली UI, डायनेमिक रंग थीम के साथ।\n\n- MAD: UI और लॉजिक को शुद्ध Kotlin में लिखा गया है। एकल गतिविधि, कोई फ़्रैगमेंट नहीं, केवल संयोजनीय गंतव्य।\n\n## ⬇️ डाउनलोड\n\nअधिकांश डिवाइसों के लिए, **arm64-v8a** संस्करण की स्थापना की सिफारिश की जाती है।\n\n- [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest) से नवीनतम स्थिर संस्करण डाउनलोड करें।\n  - नए फीचर्स और परिवर्तनों का परीक्षण करने के लिए [pre-release](https://github.com/JunkFood02/Seal/releases/) संस्करणों को इंस्टॉल करें।\n\n- स्थिर रिलीज़ [F-Droid](https://f-droid.org/packages/com.junkfood.seal/) पर भी उपलब्ध हैं।\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 संपर्क\n\nचर्चा, घोषणाओं और रिलीज़ के लिए हमारे [Telegram Channel](https://t.me/seal_app) या [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) से जुड़ें!\n\n## 💖 प्रायोजक\n\n<p><!-- sponsors --><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/gordongw\"><img src=\"https://github.com/gordongw.png\" width=\"60px\" alt=\"Gordon\" /></a><a href=\"https://github.com/zuble\"><img src=\"https://github.com/zuble.png\" width=\"60px\" alt=\"zuble\" /></a><a href=\"https://github.com/Dannyordaniel\"><img src=\"https://github.com/Dannyordaniel.png\" width=\"60px\" alt=\"Daniel \" /></a><!-- sponsors --></p>\n\nSeal हमेशा के लिए मुफ्त और ओपन-सोर्स रहेगा। अगर आपको पसंद आए, तो कृपया [मुझे प्रायोजित करने](https://github.com/sponsors/JunkFood02) पर विचार करें!\n\n## 🤝 योगदान\n\nयोगदान का स्वागत है!\n\nआप [Hosted Weblate](https://hosted.weblate.org/projects/seal/) पर Seal का अनुवाद करने में मदद कर सकते हैं।\n\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>[!Note]\n>\n>बग रिपोर्ट, फीचर अनुरोध, सवाल, या सुधार के किसी भी विचार को सबमिट करने के लिए, कृपया पहले [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) को पढ़ें।\n\n## ⭐️ स्टार इतिहास\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n## 🧱 क्रेडिट\n\nSeal एक सरल GUI है [yt-dlp](https://github.com/yt-dlp/yt-dlp) का, जो [youtubedl-android](https://github.com/yausername/youtubedl-android) पर आधारित है।\n\nUI डिज़ाइन और कोड में से कुछ [Read You](https://github.com/Ashinch/ReadYou) और [Music You](https://github.com/Kyant0/MusicYou) से उधार लिए गए हैं।\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 लाइसेंस\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>[!Warning]\n>\n>स्रोत कोड के GPLv3 लाइसेंस के तहत लाइसेंस प्राप्त सिवाय,\n>अन्य सभी पक्षों को Seal के नाम का उपयोग डाउनलोडर ऐप के रूप में करने से रोक दिया गया है,\n>और Seal के उपोत्पादों के लिए भी यही सच है।\n>उपोत्पादों में शामिल हैं लेकिन केवल फोर्क्स और अनधिकृत निर्माण तक सीमित नहीं हैं।\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Scroll to top</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-id.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Pengunduh Video/Audio untuk Android\n\n\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;|&nbsp;&nbsp;\nIndonesia\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱 Tangkapan layar\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 Fitur\n\n- Unduh file video dan audio dari platform video yang didukung oleh [yt-dlp](https://github.com/yt-dlp/yt-dlp) (sebelumnya youtube-dl).\n\n- Menyematkan metadata dan gambar mini video ke dalam file audio yang diekstrak yang didukung oleh [mutagen](https://github.com/quodlibet/mutagen).\n\n- Unduh semua video dalam daftar putar dengan satu klik.\n\n- Gunakan [aria2c](https://github.com/aria2/aria2) yang disematkan sebagai pengunduh eksternal untuk semua unduhan Anda.\n\n- Menyematkan subtitle ke dalam video yang diunduh.\n\n- Menjalankan perintah yt-dlp khusus dengan templat.\n\n- Mengelola unduhan dalam aplikasi dan templat perintah khusus.\n\n- Mudah digunakan dan ramah pengguna.\n\n- UI bergaya [Material Design 3](https://m3.material.io/), dengan tema warna yang dinamis.\n\n- MAD: UI dan logika yang ditulis dengan Kotlin murni. Aktivitas tunggal, tidak ada fragmen, hanya komposisi\ntujuan yang dapat dikomposisikan.\n\n\n## ⬇️ Unduh\n\nUntuk sebagian besar perangkat, disarankan untuk menginstal versi **arm64-v8a** dari aplikasi\n\n- Unduh versi stabil terbaru dari [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest)\n  - Instal versi [Pra-rilis](https://github.com/JunkFood02/Seal/releases/) untuk membantu kami menguji fitur & perubahan baru\n\n- Rilis stabil juga tersedia di [F-Droid](https://f-droid.org/packages/com.junkfood.seal/)\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Dapatkan di F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 Kontak\n\nBergabunglah dengan [Telegram Channel](https://t.me/seal_app) atau [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) untuk diskusi, pengumuman, dan rilis!\n\n## 💖 Sponsor\n\n<p><!-- sponsors --><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/gordongw\"><img src=\"https://github.com/gordongw.png\" width=\"60px\" alt=\"Gordon\" /></a><a href=\"https://github.com/t1hta\"><img src=\"https://github.com/t1hta.png\" width=\"60px\" alt=\"t1hta\" /></a><a href=\"https://github.com/nameoneeman\"><img src=\"https://github.com/nameoneeman.png\" width=\"60px\" alt=\"James\" /></a><a href=\"https://github.com/iguanaguy44\"><img src=\"https://github.com/iguanaguy44.png\" width=\"60px\" alt=\"\" /></a><!-- sponsors --></p>\n\n\nSeal akan selalu gratis dan open source untuk semua orang. Jika Anda menyukainya, mohon pertimbangkan untuk [mensponsori saya](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 Berkontribusi\n\nKontribusi dipersilakan!\n\nAnda dapat membantu menerjemahkan Seal di [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\t\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\t\n>**Catatan**\n>\n>Untuk mengirimkan laporan bug, permintaan fitur, pertanyaan, atau ide lain untuk perbaikan, silakan baca [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) untuk petunjuk dan panduan terlebih dahulu.\n\n## ⭐️ Sejarah bintang\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 Kredit\n\nSeal adalah sebuah GUI sederhana dari [yt-dlp](https://github.com/yt-dlp/yt-dlp), berdasarkan [youtubedl-android](https://github.com/yausername/youtubedl-android)\n\nBeberapa desain dan kode UI dipinjam dari [Read You](https://github.com/Ashinch/ReadYou) dan [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Utilitas warna material](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 Lisensi\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>**Peringatan**\n>\n>Kecuali untuk kode sumber yang dilisensikan di bawah lisensi GPLv3,\n>semua pihak lain dilarang menggunakan nama Seal sebagai aplikasi pengunduh,\n>dan hal yang sama juga berlaku untuk turunan Seal.\n>Turunannya termasuk tetapi tidak terbatas pada fork dan build tidak resmi.\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Gulir ke atas</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-it.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Video/Audio Downloader per Android\n\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nItaliano\n</p>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n<div align=\"left\">\n\n## 📱 Screenshots\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 Funzionalità\n\n- Scarica video e audio da tutte le piattaforme supportate da [yt-dlp](https://github.com/yt-dlp/yt-dlp) (conosciuto precedentemente come youtube-dl).\n\n- Integra i metadati e le anteprime degli audio attraverso [mutagen](https://github.com/quodlibet/mutagen).\n\n- Scarica tutti i video in una playlist con un solo click.\n\n- Usa [aria2c](https://github.com/aria2/aria2) integrato per tutti i tuoi download esterni.\n\n- Integra i sottotitoli nel video scaricato.\n\n- Esegui comandi di yt-dlp personalizzati.\n\n- Gestisci i download in-app e i template di comandi personalizzati.\n\n- Facile da usare.\n\n- UI a tema dinamico [Material Design 3](https://m3.material.io/).\n\n- MAD: UI e logica scritti interamente in Kotlin. Attività singola, niente frammentazioni, solo destinazioni componibili.\n\n\n\n## ⬇️ Download\n\nPer la maggior parte dei dispositivi, é consigliato installare la versione **arm64-v8a** dell'apk.\n\n- Scarica l'ultima versione stabile dalle [release di GitHub](https://github.com/JunkFood02/Seal/releases/latest)\n  - Installa la versione [pre-release](https://github.com/JunkFood02/Seal/releases/) per aiutarci a testare nuove funzionalità e trovare bug.\n\n- Le versioni stabili sono disponibili anche su [F-Droid](https://f-droid.org/packages/com.junkfood.seal/)\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 Contatti\n\nEntra nel nostro [Canale Telegram](https://t.me/seal_app) o nel nostro [spazio Matrix](https://matrix.to/#/#seal-space:matrix.org) per discussioni, annunci e molto altro!\n\n## 💖 Sponsor\n\n<p><!-- sponsors --><a href=\"https://github.com/Marco-9456\"><img src=\"https://github.com/Marco-9456.png\" width=\"60px\" alt=\"mohammed_9456\" /></a><a href=\"https://github.com/Jas0n2k\"><img src=\"https://github.com/Jas0n2k.png\" width=\"60px\" alt=\"Jas0n2k\" /></a><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/gordongw\"><img src=\"https://github.com/gordongw.png\" width=\"60px\" alt=\"Gordon\" /></a><!-- sponsors --></p>\n\n\nSeal rimarra sempre gratis e open-source per tutti. Se ti piace, considera [diventare uno sponsor](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 Contribuire\n\nTutte le contribuzioni sono ben accette!\n\nPuoi aiutare a tradurre Seal su [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\t\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\t\n>**Nota Bene**\n>\n>Per inviare report di bug, richieste di feature, domande o qualsiasi altra idea per migliorare, perfavore leggi [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) per istruzioni e linee guida.\n\n## ⭐️ Storia delle Stelle\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 Crediti\n\nSeal é una semplice GUI per [yt-dlp](https://github.com/yt-dlp/yt-dlp), basata su [youtubedl-android](https://github.com/yausername/youtubedl-android)\n\nAlcune parti del design UI sono prese da [Read You](https://github.com/Ashinch/ReadYou) e [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 Licenza\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>**Avvertimento**\n>\n>Eccetto per le parti di codice sotto licenza GPLv3, é proibito da parte di terzi di usare il nome di Seal come il nome per un app di download e lo stesso vale per tutti i lavori derivati di Seal.\n>I derivati includono ma non sono limitati a fork del progetto o build non ufficiali.\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Torna su</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-ja.md",
    "content": "<div align=\"center\">\n<p align=\"center\"> \n\t<img src=\"fastlane/metadata/android/en-US/images/icon.png\" width=160 height=160 >\n</p>\n<h1 align=\"center\">\nSeal\n</h1>\n</div>\n\n<div align=\"center\">\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal.svg?logo=F-Droid&color=green&style=flat-square)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![Releases](https://img.shields.io/github/release/JunkFood02/Seal.svg?logo=github&color=171515&label=stable&style=flat-square)](https://github.com/JunkFood02/Seal/releases/latest)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=preview&logo=github)](https://github.com/JunkFood02/Seal/releases)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?style=flat-square)](https://github.com/JunkFood02/Seal/releases)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat-square)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat-square)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat-square&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat-square&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n<p align=\"center\">\nAndroid用動画・音声ダウンローダー\n</p>\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n日本語\n</p>\n\n</div>\n\n## 📱 スクリーンショット\n\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n<br>\n\n## 📖 特徴\n\n- [yt-dlp](https://github.com/yt-dlp/yt-dlp) (旧 youtube-dl)に対応する動画プラットフォームから動画や音声ファイルをダウンロードします\n\n- [mutagen](https://github.com/quodlibet/mutagen) で抽出した音声ファイルにメタデータとサムネイルを埋め込みます\n\n- 一度クリックするだけで再生リスト内のすべての動画をダウンロードします\n\n-  [aria2c](https://github.com/aria2/aria2) をすべての動画ダウンロードに使用しています\n\n- テンプレートを使って yt-dlp コマンドを指定して実行します\n\n- アプリ内でダウンロードとコマンド指定用のテンプレートを管理します\n\n- 簡単、また使いやすいです\n\n- [Material Design 3](https://m3.material.io/) のUIに [ダイナミックカラー](https://m3.material.io/foundations/customization)のテーマを使用しています\n\n- MAD: UIやロジックはすべてKotlinで書かれています。シングルアクティビティ、フラグメントなし、composable destinationsのみで構成されています\n\n\n## ⬇️ ダウンロード\nほとんどの端末上では、**arm64-v8a**版のapkのインストールをお勧めします。\n\n-  [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest)から最新の安定板をダウンロードしてください\n    - 新機能や変更点をテストをするには[プレリリース版](https://github.com/JunkFood02/Seal/releases/)をインストールしてください\n\n- F-Droid からも安定板をダウンロードできます \n\n[<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\nalt=\"F-droidで入手\"\nheight=\"70\">](https://f-droid.org/packages/com.junkfood.seal/)\n\n## 💬 連絡先\n\n私たちの [Telegram Channel](https://t.me/seal_app) もしくは [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) で議論に参加したり、お知らせなどをご覧ください！\n\n## 💖 スポンサー\n\nSeal は誰にとっても常にフリーでオープンソースです。気に入っていただけたら[スポンサーになることもご検討ください](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 貢献\n\nあらゆる貢献を歓迎します！\n\nSealの翻訳を [Hosted Weblate](https://hosted.weblate.org/projects/seal/) で手伝ってください！\n\n[![翻訳状況](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>**備考**\n>\n>バグ報告、機能要望、質問、その他改善のためのアイデアを投稿する場合は、まず [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) を読んで、手順とガイドラインを確認してください。\n\n## ⭐️星の推移\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n## 🧱 クレジット\n\nSealは [youtubedl-android](https://github.com/yausername/youtubedl-android) をベースにした [yt-dlp](https://github.com/yt-dlp/yt-dlp) のシンプルなGUIです\n\nUIとソースコードの一部は、[Read You](https://github.com/Ashinch/ReadYou) や [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\nなどから借用しています\n\n## 📃ライセンス\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 上に戻る</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-pt.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### Baixador de vídeos/áudio para Android\n\n\n<a href=\"https://github.com/JunkFoos02/Seal/blob/main/README.md\">Inglês</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hans.md\">简体中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-zh_Hant.md\">繁體中文</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ar.md\">العربية</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nPortuguês\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ua.md\">Українська</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-th.md\">ภาษาไทย</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-fa.md\">فارسی</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-it.md\">Italiano</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-az.md\">Azərbaycanca</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ru.md\">Русский</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-sr.md\">Српски</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-ja.md\">日本語</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-id.md\">Indonesia</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/translations/README-hi.md\">हिंदी</a>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIC05NjAgOTYwIDk2MCIgd2lkdGg9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0zNTQtMjQ3IDEyNi03NiAxMjYgNzctMzMtMTQ0IDExMS05Ni0xNDYtMTMtNTgtMTM2LTU4IDEzNS0xNDYgMTMgMTExIDk3LTMzIDE0M1pNMjMzLTgwbDY1LTI4MUw4MC01NTBsMjg4LTI1IDExMi0yNjUgMTEyIDI2NSAyODggMjUtMjE4IDE4OSA2NSAyODEtMjQ3LTE0OUwyMzMtODBabTI0Ny0zNTBaIiBzdHlsZT0iZmlsbDogcmdiKDI0NSwgMjI3LCA2Nik7Ii8%2BCjwvc3ZnPg%3D%3D&color=%23f8e444)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported-Sites](https://img.shields.io/badge/Sites-9cf?style=flat&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0cHgiIGZpbGw9IiNGRkZGRkYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTExLjk5IDJDNi40NyAyIDIgNi40OCAyIDEyczQuNDcgMTAgOS45OSAxMEMxNy41MiAyMiAyMiAxNy41MiAyMiAxMlMxNy41MiAyIDExLjk5IDJ6bTYuOTMgNmgtMi45NWMtLjMyLTEuMjUtLjc4LTIuNDUtMS4zOC0zLjU2IDEuODQuNjMgMy4zNyAxLjkxIDQuMzMgMy41NnpNMTIgNC4wNGMuODMgMS4yIDEuNDggMi41MyAxLjkxIDMuOTZoLTMuODJjLjQzLTEuNDMgMS4wOC0yLjc2IDEuOTEtMy45NnpNNC4yNiAxNEM0LjEgMTMuMzYgNCAxMi42OSA0IDEycy4xLTEuMzYuMjYtMmgzLjM4Yy0uMDguNjYtLjE0IDEuMzItLjE0IDJzLjA2IDEuMzQuMTQgMkg0LjI2em0uODIgMmgyLjk1Yy4zMiAxLjI1Ljc4IDIuNDUgMS4zOCAzLjU2LTEuODQtLjYzLTMuMzctMS45LTQuMzMtMy41NnptMi45NS04SDUuMDhjLjk2LTEuNjYgMi40OS0yLjkzIDQuMzMtMy41NkM4LjgxIDUuNTUgOC4zNSA2Ljc1IDguMDMgOHpNMTIgMTkuOTZjLS44My0xLjItMS40OC0yLjUzLTEuOTEtMy45NmgzLjgyYy0uNDMgMS40My0xLjA4IDIuNzYtMS45MSAzLjk2ek0xNC4zNCAxNEg5LjY2Yy0uMDktLjY2LS4xNi0xLjMyLS4xNi0ycy4wNy0xLjM1LjE2LTJoNC42OGMuMDkuNjUuMTYgMS4zMi4xNiAycy0uMDcgMS4zNC0uMTYgMnptLjI1IDUuNTZjLjYtMS4xMSAxLjA2LTIuMzEgMS4zOC0zLjU2aDIuOTVjLS45NiAxLjY1LTIuNDkgMi45My00LjMzIDMuNTZ6TTE2LjM2IDE0Yy4wOC0uNjYuMTQtMS4zMi4xNC0ycy0uMDYtMS4zNC0uMTQtMmgzLjM4Yy4xNi42NC4yNiAxLjMxLjI2IDJzLS4xIDEuMzYtLjI2IDJoLTMuMzh6IiBzdHlsZT0iZmlsbDogcmdiKDE2MiwgMTk4LCAyMzQpOyIvPgo8L3N2Zz4=&label=Supported)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix](https://img.shields.io/matrix/seal-space%3Amatrix.org?server_fqdn=matrix.org&style=flat&logo=element&label=Matrix&color=%230DBD8B)\n](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱 Capturas de tela\n\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n<br>\n\n## 📖 Funcionalidades\n\n- Baixe arquivos de vídeo e áudio de plataformas suportadas pelo [yt-dlp](https://github.com/yt-dlp/yt-dlp) (antigo youtube-dl)\n\n- Adicione metadados e capa de vídeo suportados pelo [mutagen](https://github.com/quodlibet/mutagen) nos arquivos de áudio extraidos\n\n- Baixe todos vídeos de uma playlist em apenas um clique.\n\n- Use o [aria2c](https://github.com/aria2/aria2) pré-instalado como baixador externo para todos os seus downloads;\n\n- Incorpore legendas nos vídeos baixados.\n\n- Execute comandos do `yt-dlp` customizados, ou a partir de modelos.\n\n- Gerencie downloads e modelos de comando customizados dentro do aplicativo.\n\n- Simples e intuitivo\n\n- Estilo de interface [Material Design 3](https://m3.material.io/), com temas de cores dinâmicas\n\n- MAD: UI e lógica escrita em Kotlin puro. Atividade única, sem fragmentos, apenas destinos combináveis.\n\n\n\n## ⬇️ Download\n\nPara a maioria dos dispositivos, é recomendado usar a versão **arm64-v8a** dos apks\n\n- Baixe a versão estável mais recente do [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest)\n  - Instale versões de \"[pre-release](https://github.com/JunkFood02/Seal/releases/)\" para testar novas funcionalidades e mudanças\n\n- Versões estáveis disponíveis no [F-Droid](https://f-droid.org/packages/com.junkfood.seal/)\n\n## 💬 Contato\n\nEntre no nosso [Canal do Telegram](https://t.me/seal_app) ou [Espaço no Matrix](https://matrix.to/#/#seal-space:matrix.org) para discuções, anúncios e versões novas!\n\n## 💖 Patrocinadores\n\n<p><!-- sponsors --><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/zuble\"><img src=\"https://github.com/zuble.png\" width=\"60px\" alt=\"zuble\" /></a><a href=\"https://github.com/Dannyordaniel\"><img src=\"https://github.com/Dannyordaniel.png\" width=\"60px\" alt=\"Daniel \" /></a><a href=\"https://github.com/NRN83\"><img src=\"https://github.com/NRN83.png\" width=\"60px\" alt=\"\" /></a><!-- sponsors --></p>\n\n\nO seal vai ser sempre grátis e de código aberto pra todo mundo. Se você curte o app, considere [me patrocinar](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 Contribuir\n\nContribuições são bem-vindas!!\n\nVocê pode ajudar a traduzir o Seal no [Weblate Hosteado](https://hosted.weblate.org/projects/seal/).\n\t\n[![Status de tradução](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>[!Nota]\n>\n>Para enviar bug reports, sugestões de funcionalidades, questões, ou ideias para melhorias, por favor leia [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) para instruções e regras primeiro.\n\n## ⭐️ Linha de tempo de Stars\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n## 🧱 Creditos\n\nSeal é uma interface simples do [yt-dlp](https://github.com/yt-dlp/yt-dlp), com o código baseado no [youtubedl-android](https://github.com/yausername/youtubedl-android )\n\nAlguns dos designs e códigos da interface do usuário são emprestados de [Read You](https://github.com/Ashinch/ReadYou) e [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 License\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>[!Warning]\n>\n>Exceto pelo código-fonte que é licensiado em GPLv3,\n>todas as outras fontes estão proibidas de usarem o nome Seal como um aplicativo baixador,\n>e o mesmo se aplica para os aplicativos derivados do seal.\n>Derivações incluem mas não se limitam a forks e builds não oficiais..\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Voltar ao topo</a>\n</td></table>\n</div>"
  },
  {
    "path": "translations/README-ru.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n\n### Загрузчик видео и аудио файлов на Android\n\n\n\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nРусский\n</p>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/ru/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIC05NjAgOTYwIDk2MCIgd2lkdGg9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0zNTQtMjQ3IDEyNi03NiAxMjYgNzctMzMtMTQ0IDExMS05Ni0xNDYtMTMtNTgtMTM2LTU4IDEzNS0xNDYgMTMgMTExIDk3LTMzIDE0M1pNMjMzLTgwbDY1LTI4MUw4MC01NTBsMjg4LTI1IDExMi0yNjUgMTEyIDI2NSAyODggMjUtMjE4IDE4OSA2NSAyODEtMjQ3LTE0OUwyMzMtODBabTI0Ny0zNTBaIiBzdHlsZT0iZmlsbDogcmdiKDI0NSwgMjI3LCA2Nik7Ii8%2BCjwvc3ZnPg%3D%3D&color=%23f8e444)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported-Sites](https://img.shields.io/badge/Sites-9cf?style=flat&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0cHgiIGZpbGw9IiNGRkZGRkYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTExLjk5IDJDNi40NyAyIDIgNi40OCAyIDEyczQuNDcgMTAgOS45OSAxMEMxNy41MiAyMiAyMiAxNy41MiAyMiAxMlMxNy41MiAyIDExLjk5IDJ6bTYuOTMgNmgtMi45NWMtLjMyLTEuMjUtLjc4LTIuNDUtMS4zOC0zLjU2IDEuODQuNjMgMy4zNyAxLjkxIDQuMzMgMy41NnpNMTIgNC4wNGMuODMgMS4yIDEuNDggMi41MyAxLjkxIDMuOTZoLTMuODJjLjQzLTEuNDMgMS4wOC0yLjc2IDEuOTEtMy45NnpNNC4yNiAxNEM0LjEgMTMuMzYgNCAxMi42OSA0IDEycy4xLTEuMzYuMjYtMmgzLjM4Yy0uMDguNjYtLjE0IDEuMzItLjE0IDJzLjA2IDEuMzQuMTQgMkg0LjI2em0uODIgMmgyLjk1Yy4zMiAxLjI1Ljc4IDIuNDUgMS4zOCAzLjU2LTEuODQtLjYzLTMuMzctMS45LTQuMzMtMy41NnptMi45NS04SDUuMDhjLjk2LTEuNjYgMi40OS0yLjkzIDQuMzMtMy41NkM4LjgxIDUuNTUgOC4zNSA2Ljc1IDguMDMgOHpNMTIgMTkuOTZjLS44My0xLjItMS40OC0yLjUzLTEuOTEtMy45NmgzLjgyYy0uNDMgMS40My0xLjA4IDIuNzYtMS45MSAzLjk2ek0xNC4zNCAxNEg5LjY2Yy0uMDktLjY2LS4xNi0xLjMyLS4xNi0ycy4wNy0xLjM1LjE2LTJoNC42OGMuMDkuNjUuMTYgMS4zMi4xNiAycy0uMDcgMS4zNC0uMTYgMnptLjI1IDUuNTZjLjYtMS4xMSAxLjA2LTIuMzEgMS4zOC0zLjU2aDIuOTVjLS45NiAxLjY1LTIuNDkgMi45My00LjMzIDMuNTZ6TTE2LjM2IDE0Yy4wOC0uNjYuMTQtMS4zMi4xNC0ycy0uMDYtMS4zNC0uMTQtMmgzLjM4Yy4xNi42NC4yNiAxLjMxLjI2IDJzLS4xIDEuMzYtLjI2IDJoLTMuMzh6IiBzdHlsZT0iZmlsbDogcmdiKDE2MiwgMTk4LCAyMzQpOyIvPgo8L3N2Zz4=&label=Supported)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix](https://img.shields.io/matrix/seal-space%3Amatrix.org?server_fqdn=matrix.org&style=flat&logo=element&label=Matrix&color=%230DBD8B)\n](https://matrix.to/#/#seal-space:matrix.org)\n\n\n\n</div>\n\n## 📱 Снимки экрана\n\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n<br>\n\n## 📖 Возможности\n- Загрузка видео и аудио файлов с видео платформ, поддерживаемых [yt-dlp](https://github.com/yt-dlp/yt-dlp) (ранее youtube-dl).\n\n- Добавляйте метаданные и превью в загружаемые аудио файлы с помощью [mutagen](https://github.com/quodlibet/mutagen).\n\n- Загрузка всех видео из плейлиста в один клик\n\n- Использует встроенный [aria2c](https://github.com/aria2/aria2) как внешний загрузчик для всех ваших загрузок\n\n- Можно встроить субтитры в загружаемое видео\n\n- Контроль над загрузками в приложении и кастомные шаблоны команд\n\n- Просмотр и управление загрузками в приложении\n\n- Простой в использовании\n\n- Стилизованный под [Material Design 3](https://m3.material.io/), с динамической цветовой схемой\n\n- Интерфейс и его поведение написано на Kotlin. Один активити, без фрагментов, только composable destinations.\n\n\n\n\n## ⬇️ Установка\n\nДля большинства устройств рекомендовано устанавливать версию apk **arm64-v8a**\n\n- Скачать последнюю стабильную версию со [страницы с релизами](https://github.com/JunkFood02/Seal/releases/latest)\n  - Установить [пре-релиз](https://github.com/JunkFood02/Seal/releases/) чтобы помочь протестировать нам новые функции и изменения\n\n- Стабильные релизы также доступны на [F-Droid](https://f-droid.org/packages/com.junkfood.seal/)\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Скачайте его с F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 Связаться\n\nПрисоединяйтесь к нашему [Telegram каналу](https://t.me/seal_app) или [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) для рассуждений, анонсов и релизов!\n\n## 💖 Спонсоры\n\nSeal всегда будет бесплатным проектом с открытым исходным кодом для каждого. Если вам это нравится, пожалуйста рассмотрите возможность [поддержать меня](https://github.com/sponsors/JunkFood02)!\n\n## 🤝 Помочь с переводом\n\nПомощь приветствуется!\n\nВы можете принять участие в переводе Seal на [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>[!Note]\n>\n> Чтобы отсылать нам баги, запросы на добавление новых функций или любые другие идеи, которые помогут проекту, сперва прочитайте [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) для важной информации и инструкций.\n\n## ⭐️ График роста кол-ва звёздочек\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n## 🧱 Особая благодарность\n\nSeal - это простой интерфейс для [yt-dlp](https://github.com/yt-dlp/yt-dlp), созданный на базе [youtubedl-android](https://github.com/yausername/youtubedl-android)\n\nНекоторые элементы дизайна и кода были заимствованны у [Read You](https://github.com/Ashinch/ReadYou) и [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 Лицензия\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>[!Warning]\n>\n>За исключением исходного кода, лицензированного по лицензии GPLv3,\n>всем остальным сторонам запрещено использовать название Seal в качестве загрузчика приложений,\n>то же самое распространяется на производные Seal.\n>Деривативы разрешены, но они не ограничиваются в производных и неофициальных сборках.\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Пролистать наверх</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-sr.md",
    "content": "<div align=\"center\"> \n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal \n\n### Апликација за преузимање видео и аудио снимака за Android\n\n\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nСрпски\n</p>\n\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱 Снимци екрана \n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div> \n\n<br> \n\n## 📖 Карактеристике \n\n- Преузмите видео и аудио снимке с платформи за видео снимке које су подржане од [yt-dlp](https://github.com/yt-dlp/yt-dlp) (раније youtube-dl) платформе. \n\n- Уградите метаподатке и сличицу видео снимка у екстрактоване аудио фајлове који су подржани од [mutagen](https://github.com/quodlibet/mutagen) модула. \n\n- Преузмите све видео снимке с плејлисте једним кликом. \n\n- Користите уграђени [aria2c](https://github.com/aria2/aria2) као спољни програм за преузимање, за сва преузимања. \n\n- Уградите титлове у преузете видео снимке. \n\n- Извршите прилагођене yt-dlp команде са шаблонима. \n\n- Управљајте преузимањима у апликацији и прилагођеним командним шаблонима. \n\n- Једноставно за употребу и прилагођено кориснику. \n\n- [Material Design 3](https://m3.material.io/) стил корисничког интерфејса, са динамичком темом боја. \n\n- MAD: Кориснички интерфејс и логика написана користећи Kotlin. Једна активност, без фрагмената, само састављајућа одредишта.\n\n\n\n## ⬇️ Преузимање \n\nЗа већину уређаја, препоручује се инсталирање **arm64-v8a** верзије APK-ова \n\n- Преузмите најновију стабилну верзију са [GitHub издања](https://github.com/JunkFood02/Seal/releases/latest)\n  - Инсталирајте [бета издања](https://github.com/JunkFood02/Seal/releases/) апликације да бисте нам помогли да тестирамо нове функције и промене \n\n- Стабилна издања су такође доступна у продавници апликација [F-Droid](https://f-droid.org/packages/com.junkfood.seal/) \n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) --> \n\n## 💬 Контакт \n\nПридружите се нашем [Telegram каналу](https://t.me/seal_app) или [Matrix простору](https://matrix.to/#/#seal-space:matrix.org) за дискусију, најаве и издања. \n\n## 💖 Спонзори \n\n<p><!-- sponsors --><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/Velioris\"><img src=\"https://github.com/Velioris.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/Driverator\"><img src=\"https://github.com/Driverator.png\" width=\"60px\" alt=\"\" /></a><!-- sponsors --></p>\n\n\nSeal ће увек бити бесплатан и отвореног кода за све. Ако вам се свиђа, размислите о томе да ме [спонзоришете](https://github.com/sponsors/JunkFood02)! \n\n## 🤝 Допринос \n\nДоприноси су добродошли! \n\nМожете помоћи у превођењу апликације Seal на веб-сајту [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>**Напомена**\n>\n>За слање извештаја о грешкама, захтева за функције, питања или било које друге идеје за побољшање апликације, прво прочитајте [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) за упутства и смернице. \n\n## ⭐️ Графикон раста броја звездица\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 Кредити \n\nSeal је једноставан графички кориснички интерфејс за [yt-dlp](https://github.com/yt-dlp/yt-dlp), заснован на [youtubedl-android](https://github.com/yausername/youtubedl-android) \n\nНеки дизајни корисничког интерфејса и кодови су позајмљени од [Read You](https://github.com/Ashinch/ReadYou) и [Music You](https://github.com/Kyant0/MusicYou) \n\n[dvd](https://github.com/yausername/dvd) \n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities) \n\n[Monet](https://github.com/Kyant0/Monet) \n\n## 📃 Лиценца \n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE) \n\n>**Упозорење**\n>\n>Осим изворног кода, лиценцираног под GPLv3 лиценцом,\n>свим другим странама је забрањено да користе назив апликације Seal као програм за преузимање,\n>а исто важи и за деривате апликације Seal.\n>Деривати укључују, али нису ограничени на форкове кода и незваничне верзије. \n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Иди на врх</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-th.md",
    "content": "<div align=\"center\">\n<p align=\"center\"> \n\t<img src=\"fastlane/metadata/android/en-US/images/icon.png\" width=160 height=160 >\n</p>\n<h1 align=\"center\">\nSeal\n</h1>\n</div>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal.svg?logo=F-Droid&color=green&style=flat-square)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![Releases](https://img.shields.io/github/release/JunkFood02/Seal.svg?logo=github&color=171515&label=stable&style=flat-square)](https://github.com/JunkFood02/Seal/releases/latest)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=preview&logo=github)](https://github.com/JunkFood02/Seal/releases)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?style=flat-square)](https://github.com/JunkFood02/Seal/releases)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?style=flat-square)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat-square)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat-square&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat-square&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n<p align=\"center\">\nแอพดาวน์โหลดวิดิโอสำหรับ Android\n</p>\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nภาษาไทย\n</p>\n\n</div>\n\n## 📱 Screenshots\n\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n\n\n<br>\n\n## 📖 คุณสมบัติ\n\n - ดาวน์โหลดวิดีโอและไฟล์เสียงจากแพลตฟอร์มวิดีโอที่รองรับโดย [yt-dlp](https://github.com/yt-dlp/yt-dlp) (เดิมคือ youtube-dl)\n\n - ฝังข้อมูลเมตาและภาพขนาดย่อของวิดีโอลงในไฟล์เสียงที่แยกออกมาซึ่งรองรับโดย [mutagen](https://github.com/quodlibet/mutagen)\n\n - ดาวน์โหลดวิดีโอทั้งหมดในเพลย์ลิสต์ได้ด้วยคลิกเดียว\n\n - ใช้ [aria2c](https://github.com/aria2/aria2) แบบฝังเป็นตัวดาวน์โหลดภายนอกสำหรับการดาวน์โหลดทั้งหมดของคุณ\n\n - ฝังคำบรรยายลงในวิดีโอที่ดาวน์โหลด\n\n - ดำเนินการคำสั่ง yt-dlp ที่กำหนดเองด้วยเทมเพลต\n\n - จัดการการดาวน์โหลดในแอปและเทมเพลตคำสั่งที่กำหนดเอง\n\n - ใช้งานง่ายและเป็นมิตรกับผู้ใช้\n\n - [Material Design 3](https://m3.material.io/) UI สไตล์พร้อมธีมสีแบบไดนามิก\n\n - MAD: UI และตรรกะที่เขียนด้วย Kotlin ล้วนๆ  กิจกรรมเดียว ไม่มีแฟรกเมนต์ มีเพียงปลายทางที่รวบรวมได้\n\n\n## ⬇️ ดาวน์โหลด\n\n สำหรับอุปกรณ์ส่วนใหญ่ ขอแนะนำให้ติดตั้ง APK เวอร์ชัน **arm64-v8a**\n\n - ดาวน์โหลดเวอร์ชันเสถียรล่าสุดจาก [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest)\n   - ติดตั้งเวอร์ชัน [ก่อนเผยแพร่](https://github.com/JunkFood02/Seal/releases/) เพื่อช่วยเราทดสอบฟีเจอร์และการเปลี่ยนแปลงใหม่ๆ\n\n - เวอร์ชั้นเสถียรก็มีอยู่ใน F-Droid เช่นกัน\n\n [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n      alt=\"ดาวน์โหลดบน F-Droid\"\n      height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/)\n      \n## 💬 ติดต่อ\n\n เข้าร่วม [Telegram Channel](https://t.me/seal_app) หรือ [Matrix Space](https://matrix.to/#/#seal-space:matrix.org) เพื่อพูดคุย, ฟังประกาศ, และเผยแพร่!\n\n ## 🤝 ร่วมสมทบทุน\n\n คุณสามารถสนับสนุน Seal ได้!\n\n คุณสามารถช่วยแปล Seal ได้ที่ [Hosted Weblate](https://hosted.weblate.org/projects/seal/)\n\n [![สถานะการแปล](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n >**หมายเหตุ**\n\n หากต้องการส่งรายงานข้อบกพร่อง คำขอฟีเจอร์ คำถาม หรือแนวคิดอื่นๆ เพื่อปรับปรุง โปรดอ่านคำแนะนำและหลักเกณฑ์ที่ [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md)  .\n\n ## ⭐️ประวัติ Star\n\n [![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n ## 🧱 เครดิต\n\n Seal เป็น GUI อย่างง่ายของ [yt-dlp](https://github.com/yt-dlp/yt-dlp) โดยอ้างอิงจาก [youtubedl-android](https://github.com/yausername/youtubedl-android  )\n\n การออกแบบ UI และโค้ดบางส่วนยืมมาจาก [Read You](https://github.com/Ashinch/ReadYou) และ [Music You](https://github.com/Kyant0/MusicYou)\n\n [ดีวีดี](https://github.com/yausername/dvd)\n\n [ยูทิลิตี้สีวัสดุ](https://github.com/material-foundation/material-color-utilities)\n\n [โมเนต์](https://github.com/Kyant0/Monet)\n\n ## 📃ใบอนุญาติ\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Scroll to top</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-ua.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n\n### Завантажувач відео та аудіо для Android\n\n\n\n\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\nУкраїнська\n</p>\n\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n\n</div>\n\n## 📱 Скріншоти\n\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n<br>\n\n## 📖 Особливості\n\n- Завантажуйте відео та аудіо файли з сайтів, які підтримуються yt-dlp (тобто youtube-dl)\n\n- Додавайте метадані і прев'ю у завантажені аудіо файли завдяки mutagen\n\n- Завантажуйте усі відео з плейлиста в один клік\n\n- Використовуйте вбудований aria2c як завантажувач для всіх своїх завантажень\n\n- Додавайте субтитри у завантажені відео\n\n- Використовуйте власні команди yt-dlp завдяки шаблонам\n\n- Переглядайте та керуйте завантаженнями у застосунку\n\n- Простий та приємний у використанні\n\n- Стилізований під Material Design 3 інтерфейс з динамічною колірною схемою\n\n- Круте: Інтерфейс та логіка написані на Kotlin. Один актівіті, без фрагментів, лише composable destinations.\n\n\n\n\n## ⬇️ Завантажити\n\n[<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Завантажте з F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/)\n\nАбо завантажте останні APK на сторінці [з релізами.](https://github.com/JunkFood02/Seal/releases/)\n\n\n\n## 🤝 Допомога\n\nСпівпраця вітається!\n\nДопоможіть перекласти Seal на [Hosted Weblate](https://hosted.weblate.org/projects/seal/).\n\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n>**Нотатка**  \n> Щоб надіслати звіти про помилки, запити на додавання нових функцій, запитання чи будь-які інші ідеї щодо покращення, спершу прочитайте [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) за інструкціями та вказівками.\n\n## ⭐️ Історія зірочок\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n## 🧱 Подяки\n\nSeal - це простий інтерфейс для [yt-dlp](https://github.com/yt-dlp/yt-dlp), який був створений на базі [youtubedl-android](https://github.com/yausername/youtubedl-android)\n\nДеякий код та елементи інтерфейсу взяті з [Read You](https://github.com/Ashinch/ReadYou) та [Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n## 📃 Ліцензія\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 Прокрутити вгору</a>\n</td></table>\n</div>\n"
  },
  {
    "path": "translations/README-zh_Hans.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n\n\n### 一个简单的 Android 视频/音频下载器，使用 Jetpack Compose 进行开发\n\n<p align=\"center\">\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;|&nbsp;&nbsp;\n简体中文\n</p>\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n</div>\n## 屏幕截图\n\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n\n\n## 功能特色\n\n- 从 [yt-dlp](https://github.com/yt-dlp/yt-dlp) 所支持的数千个视频平台下载视频与音频\n\n- 提取媒体元数据与专辑封面，调用 [mutagen](https://github.com/quodlibet/mutagen) 嵌入到提取的音频文件中\n\n- 播放列表下载支持\n\n- 使用 [aria2c](https://github.com/aria2/aria2) 进行下载\n\n- 内嵌字幕于视频文件中\n\n- 执行自定义的 yt-dlp 命令模板\n\n- 管理应用内下载与自定义命令模板\n\n- 使用简单、用户友好\n\n- 遵循 [Material Design 3](https://m3.material.io/) 设计规范，实现了 [动态色彩](https://m3.material.io/foundations/customization) 主题的应用界面\n  \n- MAD：完全使用 Kotlin 构造界面与编写逻辑，单 Activity + Compose Navigation 应用结构\n\n## 下载\n\n[<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\nalt=\"Get it on F-Droid\"\nheight=\"80\">](https://f-droid.org/packages/com.junkfood.seal/)\n\n你也可以从 [releases](https://github.com/JunkFood02/Seal/releases) 获取最新的 apk\n\n## 贡献\n\n欢迎贡献！\n\n你可以在 [Hosted Weblate](https://hosted.weblate.org/projects/seal/)  参与 Seal 的翻译\n\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\n对于错误报告、功能请求或其他改进的想法，请先在 Issue 和 Discussion 中进行搜索（包括已关闭的 Issue）。如果没有出现重复，欢迎 [发起讨论](https://github.com/JunkFood02/Seal/discussions) 或 [提交问题](https://github.com/JunkFood02/Seal/issues/new)。\n\nSeal 被设计为 yt-dlp 的一个简单的 GUI 封装，所以我们不会接受 yt-dlp 不支持的功能请求。\n\n## 致谢\n\n[youtubedl-android](https://github.com/yausername/youtubedl-android)\n\n[yt-dlp](https://github.com/yt-dlp/yt-dlp)\n\n[Read You](https://github.com/Ashinch/ReadYou)\n\n[Music You](https://github.com/Kyant0/MusicYou)\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n## 许可证\n\n[GNU GPL v3.0](https://github.com/JunkFood02/Seal/blob/main/LICENSE)"
  },
  {
    "path": "translations/README-zh_Hant.md",
    "content": "<div align=\"center\">\n\n<img width=\"\" src=\"fastlane/metadata/android/en-US/images/icon.png\"  width=160 height=160  align=\"center\">\n\n# Seal\n\n### 只為 Android 而生的視訊/音訊下載程式\n\n\n<a href=\"https://github.com/JunkFood02/Seal/blob/main/README.md\">English</a>\n&nbsp;&nbsp;| &nbsp;&nbsp;\n繁體中文\n\n[![F-Droid](https://img.shields.io/f-droid/v/com.junkfood.seal?color=b4eb12&label=F-Droid&logo=fdroid&logoColor=1f78d2)](https://f-droid.org/en/packages/com.junkfood.seal)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/JunkFood02/Seal?color=black&label=Stable&logo=github)](https://github.com/JunkFood02/Seal/releases/latest/)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/JunkFood02/Seal?include_prereleases&label=Preview&logo=Github)](https://github.com/JunkFood02/Seal/releases/)\n[![Keep a Changelog](https://img.shields.io/badge/Changelog-lightgray?style=flat&color=gray&logo=keep-a-changelog)](https://github.com/JunkFood02/Seal/blob/main/CHANGELOG.md)\n[![GitHub all releases](https://img.shields.io/github/downloads/JunkFood02/Seal/total?label=Downloads&logo=github)](https://github.com/JunkFood02/Seal/releases/)\n[![GitHub Repo stars](https://img.shields.io/github/stars/JunkFood02/Seal?color=informational&label=Stars)](https://github.com/JunkFood02/Seal/stargazers)\n[![Supported Sites](https://img.shields.io/badge/Supported-Sites-9cf.svg?style=flat)](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Seal-blue?style=flat&logo=telegram)](https://t.me/seal_app)\n[![Matrix Space](https://img.shields.io/badge/Matrix-Seal-Black?style=flat&color=black&logo=matrix)](https://matrix.to/#/#seal-space:matrix.org)\n\n\n</div>\n\n\n## 📱 螢幕擷圖\n\n<div align=\"center\">\n<div>\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg\" width=\"30%\" />\n<img src=\"/fastlane/metadata/android/en-US/images/phoneScreenshots/9.jpg\" width=\"30%\" />\n</div>\n</div>\n\n<br>\n\n## 📖 特色功能\n\n- 透過 [yt-dlp](https://github.com/yt-dlp/yt-dlp) (youtube-dl) 所支援的平臺下載視訊和音訊。\n\n- 透過 [mutagen](https://github.com/quodlibet/mutagen)，內嵌中繼資料和視訊縮圖至擷取的音訊檔。\n\n- 一鍵下載播放清單中的全數視訊。\n\n- 支援使用內建之 [aria2c](https://github.com/aria2/aria2) 外部下載程式進行下載。\n\n- 支援內嵌字幕至視訊檔案中。\n\n- 支援執行 yt-dlp 自訂命令範本\n\n- 提供應用程式內管理下載和自訂命令範本。\n\n- 刪繁就簡、簡單易用。\n\n- 使用 [Material Design 3](https://m3.material.io/) UI 風格規範，支援動態顏色主題。\n\n- MAD: 全面使用 Kotlin 建構 UI 和編撰邏輯。單 Activity、無 fragments，僅使用 Compose Destinations。\n\n\n\n## ⬇️ 如何下載\n\n我們建議大多數裝置使用 **arm64-v8a** 版本的 APK 檔。\n\n- 從 [GitHub releases](https://github.com/JunkFood02/Seal/releases/latest) 下載最新穩定發行版\n  - 安裝 [預先發行版本](https://github.com/JunkFood02/Seal/releases/)，以幫助我們測試最新功能和變更\n\n- 穩定發行版亦可於 [F-Droid](https://f-droid.org/packages/com.junkfood.seal/) 取得\n\n<!-- [<img src=\"https://fdroid.gitlab.io/artwork/badge/get-it-on.png\"\n     alt=\"Get it on F-Droid\"\n     height=\"70\">](https://f-droid.org/packages/com.junkfood.seal/) -->\n\n## 💬 如何聯繫\n\n誠摯邀請您加入 [Telegram 頻道](https://t.me/seal_app) 或 [Matrix Space](https://matrix.to/#/#seal-space:matrix.org)，與我們一同討論、接收最新消息，以及軟體發行！\n\n## 💖 贊助之友\n\n<p><!-- sponsors --><a href=\"https://github.com/4kaimar\"><img src=\"https://github.com/4kaimar.png\" width=\"60px\" alt=\"\" /></a><a href=\"https://github.com/gordongw\"><img src=\"https://github.com/gordongw.png\" width=\"60px\" alt=\"Gordon\" /></a><a href=\"https://github.com/t1hta\"><img src=\"https://github.com/t1hta.png\" width=\"60px\" alt=\"t1hta\" /></a><a href=\"https://github.com/nameoneeman\"><img src=\"https://github.com/nameoneeman.png\" width=\"60px\" alt=\"James\" /></a><a href=\"https://github.com/iguanaguy44\"><img src=\"https://github.com/iguanaguy44.png\" width=\"60px\" alt=\"\" /></a><!-- sponsors --></p>\n\n\nSeal 永遠提供眾人免費使用並開放原始碼。若您悅納，請考慮[贊助我](https://github.com/sponsors/JunkFood02)！\n\n## 🤝 一同貢獻\n\n永遠歡迎您的貢獻！\n\n您可以在 [Hosted Weblate](https://hosted.weblate.org/projects/seal/)，參與 Seal 的翻譯。\n\t\n[![Translate status](https://hosted.weblate.org/widgets/seal/-/strings/multi-auto.svg)](https://hosted.weblate.org/engage/seal/)\n\t\n>**備註**\n>\n>請在回報錯誤、功能請求、求問，或提供任何改進建言之前，先閱讀 [CONTRIBUTING.md](https://github.com/JunkFood02/Seal/blob/main/CONTRIBUTING.md) 相關指引。\n\n## ⭐️ Star 歷程\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JunkFood02/Seal&type=Timeline)](https://star-history.com/#JunkFood02/Seal&Timeline)\n\n\n## 🧱 致謝\n\nSeal 是基於 [youtubedl-android](https://github.com/yausername/youtubedl-android) 的 [yt-dlp](https://github.com/yt-dlp/yt-dlp) 簡易化 GUI。\n\n部分 UI 設計和程式碼來自 [Read You](https://github.com/Ashinch/ReadYou) 和 [Music You](https://github.com/Kyant0/MusicYou)。\n\n[dvd](https://github.com/yausername/dvd)\n\n[Material color utilities](https://github.com/material-foundation/material-color-utilities)\n\n[Monet](https://github.com/Kyant0/Monet)\n\n## 📃 授權（本節僅供參考，敬請閱讀原文）\n\n[![GitHub](https://img.shields.io/github/license/JunkFood02/Seal?style=for-the-badge)](https://github.com/JunkFood02/Seal/blob/main/LICENSE)\n\n>**警告**\n>\n>除依據 GPLv3 授權之來源代碼外，\n>各方均不得以 Seal 作為下載程式之應用程式命名，\n>Seal 衍生產品亦之。\n>衍生產品包括但不限於分支和非官方組建。\n\n<div align=\"right\">\n<table><td>\n<a href=\"#start-of-content\">👆 回到置頂</a>\n</td></table>\n</div>\n"
  }
]