diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a258e9f..8ec52ab 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,8 @@ on: jobs: release: name: Release + permissions: + contents: write runs-on: ubuntu-latest steps: - name: Checkout @@ -56,7 +58,7 @@ jobs: - name: Release env: - GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} KEYSTORE_ENTRY_ALIAS: ${{ secrets.KEYSTORE_ENTRY_ALIAS }} KEYSTORE_ENTRY_PASSWORD: ${{ secrets.KEYSTORE_ENTRY_PASSWORD }} diff --git a/.gitignore b/.gitignore index 58b769c..390ce08 100644 --- a/.gitignore +++ b/.gitignore @@ -123,4 +123,8 @@ gradle-app.setting node_modules/ # Ignore IDEA files -.idea/ \ No newline at end of file +.idea/ + +.kotlin/ + +local.properties diff --git a/.releaserc b/.releaserc index 1188057..6ad60d9 100644 --- a/.releaserc +++ b/.releaserc @@ -21,10 +21,10 @@ "@semantic-release/git", { "assets": [ - "README.md", "CHANGELOG.md", "gradle.properties", - ] + ], + "message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" } ], [ @@ -32,7 +32,7 @@ { "assets": [ { - "path": "build\outputs\apk\release\*.apk", + "path": "build/outputs/apk/release/*.apk?(.asc)", } ], successComment: false diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..612b75b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# 1.0.0-dev.1 (2025-01-13) + + +### Features + +* Initialize repository ([aa5ce82](https://github.com/ReVanced/revanced-manager-downloader-template/commit/aa5ce824eaedf7b94d5e80eff44954fc7909dd7f)) +* Update to account for API changes ([2aa975a](https://github.com/ReVanced/revanced-manager-downloader-template/commit/2aa975ab5a440cd07056fbf911f67e0d979b1fe5)) diff --git a/README.md b/README.md index c522806..813e9e8 100644 --- a/README.md +++ b/README.md @@ -63,13 +63,11 @@ ![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/ReVanced/revanced-manager-downloader-template/release.yml) ![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg) -Template repository for ReVanced Manager downloader. +Template repository for ReVanced Manager downloader plugins. ## ❓ About -This is a template to create a new ReVanced Manager downloader repository. - -For an example repository, see [TODO](https://github.com/revanced/revanced-manager). +This is a template to create a new ReVanced Manager downloader repository. An example implementation is included. ## 🚀 Get started @@ -79,18 +77,15 @@ To start using this template, follow these steps: 2. Set up the [build.gradle.kts](build.gradle.kts) file (Specifically, the [package nme](build.gradle.kts#L21). 3. Update dependencies in the [libs.versions.toml](gradle/libs.versions.toml) file 4. [Create a pass-phrased GPG master key and subkey](https://mikeross.xyz/create-gpg-key-pair-with-subkeys/) - 1. Add the private key as a secret named [GPG_PRIVATE_KEY](.github/workflows/release.yml#L49) to your repository - 2. Add the passphrase as a secret named [GPG_PASSPHRASE](.github/workflows/release.yml#L50) to your repository - 3. Add the fingerprint of the GPG subkey as a secret named [GPG_FINGERPRINT](.github/workflows/release.yml#L51) + 1. Add the private key as a secret named [GPG_PRIVATE_KEY](.github/workflows/release.yml#L51) to your repository + 2. Add the passphrase as a secret named [GPG_PASSPHRASE](.github/workflows/release.yml#L52) to your repository + 3. Add the fingerprint of the GPG subkey as a variable named [GPG_FINGERPRINT](.github/workflows/release.yml#L53) to your repository 5. [Generate a keystore](https://developer.android.com/studio/publish/app-signing#generate-key) - 1. Add the Base64 encoded key store as a secret named [KEYSTORE](.github/workflows/release.yml#L55) to your repository - 2. Add the keystore password as a secret named [KEYSTORE_PASSWORD](.github/workflows/release.yml#L60) to your repository - 3. Add the keystore entry alias as a secret named [KEYSTORE_ENTRY_ALIAS](.github/workflows/release.yml#L61) to your repository - 4. Add the keystore entry password as a secret named [KEYSTORE_ENTRY_PASSWORD](.github/workflows/release.yml#L62) to your repository -6. [Create a PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) -with [push access](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/ci-configuration.md#authentication) - 1. Add it as a secret named [REPOSITORY_PUSH_ACCESS](.github/workflows/release.yml#L59) to your repository + 1. Add the Base64 encoded key store as a secret named [KEYSTORE](.github/workflows/release.yml#L57) to your repository + 2. Add the keystore password as a secret named [KEYSTORE_PASSWORD](.github/workflows/release.yml#L62) to your repository + 3. Add the keystore entry alias as a secret named [KEYSTORE_ENTRY_ALIAS](.github/workflows/release.yml#L63) to your repository + 4. Add the keystore entry password as a secret named [KEYSTORE_ENTRY_PASSWORD](.github/workflows/release.yml#L64) to your repository 7. Set up the [README.md](README.md) file[^1] (e.g, title, description, license, summary), the [issue templates](.github/ISSUE_TEMPLATE)[^2] and the [contribution guidelines](CONTRIBUTING.md)[^3] @@ -111,7 +106,7 @@ To develop and release ReVanced Manager downloader using this template, some thi - Commits on the `dev` branch and `main` branch are automatically released via the [release.yml](.github/workflows/release.yml) workflow, which is also responsible for generating the changelog and updating the version of ReVanced Manager downloader. It is triggered by pushing to the `dev` or `main` branch. -The workflow uses the `publish` task to publish the release of ReVanced Patches +The workflow uses the `publish` task to publish the release. - The `publish` task depends on the `assembleRelease` task, so it will be run automatically when publishing a release. ## 📚 Everything else @@ -129,6 +124,17 @@ Follow the steps below to build ReVanced Manager downloader template: 1. Run `git clone git@github.com:ReVanced/revanced-manager-downloader-template.git` to clone the repository 2. Run `gradlew assembleRelease` to build the project +> [!NOTE] +> If the build fails due to authentication, you may need to authenticate to GitHub Packages. +> Create a PAT with the scope `read:packages` [here](https://github.com/settings/tokens/new?scopes=read:packages&description=ReVanced) and add your token to ~/.gradle/gradle.properties. +> +> Example `gradle.properties` file: +> +> ```properties +> gpr.user = user +> gpr.key = key +> ``` + ## 📜 Licence ReVanced Manager downloader template is licensed under the GPLv3 licence. diff --git a/build.gradle.kts b/build.gradle.kts index d720cfb..4f47d5d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,57 +1,47 @@ plugins { alias(libs.plugins.android.application) - alias(libs.plugins.compose.compiler) alias(libs.plugins.kotlin.android) - alias(libs.plugins.kotlin.parcelize) publishing signing } dependencies { - implementation(libs.compose.activity) - implementation(platform(libs.compose.bom)) - implementation(libs.compose.material3) - implementation(libs.compose.ui) - implementation(libs.compose.ui.tooling) - - compileOnly(project(":downloader-plugin")) + compileOnly(libs.plugin.api) } android { val packageName = "app.revanced.manager.plugin.downloader.example" namespace = packageName - compileSdk = 34 + compileSdk = 35 defaultConfig { applicationId = packageName minSdk = 26 - targetSdk = 34 + targetSdk = 35 versionName = version.toString() versionCode = versionName!!.filter { it.isDigit() }.toInt() - - buildConfigField("String", "PLUGIN_PACKAGE_NAME", "\"$packageName\"") } buildTypes { release { - if ("CI" in System.getenv()) { - signingConfig = signingConfigs.create("release") { - storeFile = file("keystore.jks") - storePassword = System.getenv("KEYSTORE_PASSWORD") - keyAlias = System.getenv("KEYSTORE_ENTRY_ALIAS") - keyPassword = System.getenv("KEYSTORE_ENTRY_PASSWORD") - } - } - proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" + "proguard-rules.pro", ) - } - debug { - signingConfig = signingConfigs.getByName("debug") + val keystoreFile = file("keystore.jks") + signingConfig = + if (keystoreFile.exists()) { + signingConfigs.create("release") { + storeFile = keystoreFile + storePassword = System.getenv("KEYSTORE_PASSWORD") + keyAlias = System.getenv("KEYSTORE_ENTRY_ALIAS") + keyPassword = System.getenv("KEYSTORE_ENTRY_PASSWORD") + } + } else { + signingConfigs["debug"] + } } } @@ -64,11 +54,6 @@ android { jvmTarget = "17" } - buildFeatures { - compose = true - buildConfig = true - } - applicationVariants.all { outputs.all { this as com.android.build.gradle.internal.api.ApkVariantOutputImpl diff --git a/gradle.properties b/gradle.properties index bab8b10..5e4e3d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,7 @@ -android.useAndroidX=true -android.nonTransitiveRClass=true -android.nonFinalResIds=false +android.useAndroidX = true +android.nonTransitiveRClass = true +android.nonFinalResIds = false kotlin.code.style = official org.gradle.parallel = true org.gradle.caching = true +version = 1.0.0-dev.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index abd6cad..fefb0d6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,20 +1,11 @@ [versions] -android = "8.5.2" -compose-activity = "1.9.1" -compose-bom = "2024.08.00" -kotlin = "2.0.20" -material3 = "1.3.0-rc01" -ui-tooling = "1.6.8" +plugin-api = "1.0.0" +android-gradle-plugin = "8.7.3" +kotlin = "2.1.0" [libraries] -compose-activity = { group = "androidx.activity", name = "activity-compose", version.ref = "compose-activity" } -compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } -compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3"} -compose-ui = { group = "androidx.compose.ui", name = "ui" } -compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "ui-tooling" } +plugin-api = { group = "app.revanced", name = "revanced-manager-downloader-api", version.ref = "plugin-api" } [plugins] -android-application = { id = "com.android.application", version.ref = "android" } -compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/package-lock.json b/package-lock.json index 80fa04e..86564ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,8 @@ "@saithodev/semantic-release-backmerge": "^4.0.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", - "gradle-semantic-release-plugin": "1.9.2", - "semantic-release": "24.1.0" + "gradle-semantic-release-plugin": "^1.10.1", + "semantic-release": "^24.1.2" } }, "node_modules/@babel/code-frame": { @@ -235,13 +235,13 @@ "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz", - "integrity": "sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz", + "integrity": "sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^13.5.0" + "@octokit/types": "^13.6.0" }, "engines": { "node": ">= 18" @@ -251,9 +251,9 @@ } }, "node_modules/@octokit/plugin-retry": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz", - "integrity": "sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.2.tgz", + "integrity": "sha512-XOWnPpH2kJ5VTwozsxGurw+svB2e61aWlmk5EVIYZPwFK5F9h4cyPyj9CIKRyMXMHSwpIsI3mPOdpMmrRhe7UQ==", "dev": true, "license": "MIT", "dependencies": { @@ -302,9 +302,9 @@ } }, "node_modules/@octokit/request-error": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz", - "integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", + "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -315,9 +315,9 @@ } }, "node_modules/@octokit/types": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", - "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.0.tgz", + "integrity": "sha512-CrooV/vKCXqwLa+osmHLIMUb87brpgUqlqkPGc6iE2wCkUvTrHiXFMhAKoDDaAAYJrtKtrFTgSQTg5nObBEaew==", "dev": true, "license": "MIT", "dependencies": { @@ -977,6 +977,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@saithodev/semantic-release-backmerge/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@saithodev/semantic-release-backmerge/node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -1372,9 +1385,9 @@ } }, "node_modules/@semantic-release/github": { - "version": "10.1.7", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.1.7.tgz", - "integrity": "sha512-QnhP4k1eqzYLz6a4kpWrUQeKJYXqHggveMykvUFbSquq07GF85BXvr/QLhpOD7bpDcmEfL8VnphRA7KT5i9lzQ==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.0.tgz", + "integrity": "sha512-Uon6G6gJD8U1JNvPm7X0j46yxNRJ8Ui6SgK4Zw5Ktu8RgjEft3BGn+l/RX1TTzhhO3/uUcKuqM+/9/ETFxWS/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1399,7 +1412,7 @@ "node": ">=20.8.1" }, "peerDependencies": { - "semantic-release": ">=20.1.0" + "semantic-release": ">=24.1.0" } }, "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { @@ -1569,9 +1582,9 @@ } }, "node_modules/@semantic-release/npm/node_modules/execa": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.1.tgz", - "integrity": "sha512-gdhefCCNy/8tpH/2+ajP9IQc14vXchNdd0weyzSJEFURhRMGncQ+zKFxwjAufIewPEJm9BPOaJnvg2UtlH2gPQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz", + "integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==", "dev": true, "license": "MIT", "dependencies": { @@ -1582,7 +1595,7 @@ "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", - "npm-run-path": "^5.2.0", + "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", @@ -1649,16 +1662,17 @@ } }, "node_modules/@semantic-release/npm/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1703,6 +1717,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@semantic-release/npm/node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@semantic-release/release-notes-generator": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.1.tgz", @@ -2273,13 +2300,13 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2358,9 +2385,9 @@ "license": "MIT" }, "node_modules/env-ci": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz", - "integrity": "sha512-apikxMgkipkgTvMdRT9MNqWx5VLOci79F4VBd7Op/7OPjjoanjdAvn6fglMCCEf/1bAh8eOiuEVCUs4V3qP3nQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.0.tgz", + "integrity": "sha512-Z8dnwSDbV1XYM9SBF2J0GcNVvmfmfh3a49qddGIROhBoVro6MZVTji15z/sJbQ2ko2ei8n988EU1wzoLU/tF+g==", "dev": true, "license": "MIT", "dependencies": { @@ -2549,9 +2576,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -2847,9 +2874,9 @@ "license": "ISC" }, "node_modules/gradle-semantic-release-plugin": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.9.2.tgz", - "integrity": "sha512-8qpf4GYFPQ+UMUymYBy/VchOOwLILAWzZMrZX1R0RR3JMgJBMN2R0tJn92R/3rXmxx4OAqwUFH6Np51eFoxr3w==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.10.1.tgz", + "integrity": "sha512-Q4dLAFICjPouUyRRHEKK8cXNB75nraXoioYZDZlVQOg4sYKudnTDZ3ohLmV3k4cPGiiMCh1ckXETkx9JnuyKmA==", "dev": true, "funding": [ { @@ -2925,16 +2952,16 @@ } }, "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.0.tgz", + "integrity": "sha512-4nw3vOVR+vHUOT8+U4giwe2tcGv+R3pwwRidUe67DoMBTjhrfr6rZYJVVwdkBE+Um050SG+X9tf0Jo4fOpn01w==", "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/http-proxy-agent": { @@ -3191,9 +3218,9 @@ } }, "node_modules/is-unicode-supported": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", - "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { @@ -3547,9 +3574,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, @@ -3610,6 +3637,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/normalize-url": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", @@ -3624,9 +3664,9 @@ } }, "node_modules/npm": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.2.tgz", - "integrity": "sha512-x/AIjFIKRllrhcb48dqUNAAZl0ig9+qMuN91RpZo3Cb2+zuibfh+KISl6+kVVyktDz230JKc208UkQwwMqyB+w==", + "version": "10.8.3", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.3.tgz", + "integrity": "sha512-0IQlyAYvVtQ7uOhDFYZCGK8kkut2nh8cpAdA9E6FvRSJaTgtZRZgNjlC5ZCct//L73ygrpY93CxXpRJDtNqPVg==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -3719,13 +3759,13 @@ "@sigstore/tuf": "^2.3.4", "abbrev": "^2.0.0", "archy": "~1.0.0", - "cacache": "^18.0.3", + "cacache": "^18.0.4", "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", - "glob": "^10.4.2", + "glob": "^10.4.5", "graceful-fs": "^4.2.11", "hosted-git-info": "^7.0.2", "ini": "^4.1.3", @@ -3734,7 +3774,7 @@ "json-parse-even-better-errors": "^3.0.2", "libnpmaccess": "^8.0.6", "libnpmdiff": "^6.1.4", - "libnpmexec": "^8.1.3", + "libnpmexec": "^8.1.4", "libnpmfund": "^5.0.12", "libnpmhook": "^10.0.5", "libnpmorg": "^6.0.6", @@ -3748,12 +3788,12 @@ "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^10.1.0", + "node-gyp": "^10.2.0", "nopt": "^7.2.1", "normalize-package-data": "^6.0.2", "npm-audit-report": "^5.0.0", "npm-install-checks": "^6.3.0", - "npm-package-arg": "^11.0.2", + "npm-package-arg": "^11.0.3", "npm-pick-manifest": "^9.1.0", "npm-profile": "^10.0.0", "npm-registry-fetch": "^17.1.0", @@ -3764,7 +3804,7 @@ "proc-log": "^4.2.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", - "semver": "^7.6.2", + "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0", "ssri": "^10.0.6", "supports-color": "^9.4.0", @@ -4335,7 +4375,7 @@ } }, "node_modules/npm/node_modules/cacache": { - "version": "18.0.3", + "version": "18.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -4502,7 +4542,7 @@ } }, "node_modules/npm/node_modules/debug": { - "version": "4.3.5", + "version": "4.3.6", "dev": true, "inBundle": true, "license": "MIT", @@ -4586,7 +4626,7 @@ } }, "node_modules/npm/node_modules/foreground-child": { - "version": "3.2.1", + "version": "3.3.0", "dev": true, "inBundle": true, "license": "ISC", @@ -4614,7 +4654,7 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "10.4.2", + "version": "10.4.5", "dev": true, "inBundle": true, "license": "ISC", @@ -4629,9 +4669,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -4815,16 +4852,13 @@ "license": "ISC" }, "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.0", + "version": "3.4.3", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -4910,7 +4944,7 @@ } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "8.1.3", + "version": "8.1.4", "dev": true, "inBundle": true, "license": "ISC", @@ -5044,13 +5078,10 @@ } }, "node_modules/npm/node_modules/lru-cache": { - "version": "10.2.2", + "version": "10.4.3", "dev": true, "inBundle": true, - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } + "license": "ISC" }, "node_modules/npm/node_modules/make-fetch-happen": { "version": "13.0.1", @@ -5262,7 +5293,7 @@ } }, "node_modules/npm/node_modules/node-gyp": { - "version": "10.1.0", + "version": "10.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -5273,9 +5304,9 @@ "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.1.0", "semver": "^7.3.5", - "tar": "^6.1.2", + "tar": "^6.2.1", "which": "^4.0.0" }, "bin": { @@ -5285,15 +5316,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/npm/node_modules/nopt": { "version": "7.2.1", "dev": true, @@ -5366,7 +5388,7 @@ } }, "node_modules/npm/node_modules/npm-package-arg": { - "version": "11.0.2", + "version": "11.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -5540,7 +5562,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.0", + "version": "6.1.2", "dev": true, "inBundle": true, "license": "MIT", @@ -5678,7 +5700,7 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.6.2", + "version": "7.6.3", "dev": true, "inBundle": true, "license": "ISC", @@ -6437,9 +6459,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -6738,15 +6760,15 @@ "license": "MIT" }, "node_modules/semantic-release": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.0.tgz", - "integrity": "sha512-FwaE2hKDHQn9G6GA7xmqsc9WnsjaFD/ppLM5PUg56Do9oKSCf+vH6cPeb3hEBV/m06n8Sh9vbVqPjHu/1onzQw==", + "version": "24.1.2", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.2.tgz", + "integrity": "sha512-hvEJ7yI97pzJuLsDZCYzJgmRxF8kiEJvNZhf0oiZQcexw+Ycjy4wbdsn/sVMURgNCu8rwbAXJdBRyIxM4pe32g==", "dev": true, "license": "MIT", "dependencies": { "@semantic-release/commit-analyzer": "^13.0.0-beta.1", "@semantic-release/error": "^4.0.0", - "@semantic-release/github": "^10.0.0", + "@semantic-release/github": "^11.0.0", "@semantic-release/npm": "^12.0.0", "@semantic-release/release-notes-generator": "^14.0.0-beta.1", "aggregate-error": "^5.0.0", @@ -6759,7 +6781,7 @@ "get-stream": "^6.0.0", "git-log-parser": "^1.2.0", "hook-std": "^3.0.0", - "hosted-git-info": "^7.0.0", + "hosted-git-info": "^8.0.0", "import-from-esm": "^1.3.1", "lodash-es": "^4.17.21", "marked": "^12.0.0", @@ -6851,9 +6873,9 @@ } }, "node_modules/semantic-release/node_modules/execa": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.1.tgz", - "integrity": "sha512-gdhefCCNy/8tpH/2+ajP9IQc14vXchNdd0weyzSJEFURhRMGncQ+zKFxwjAufIewPEJm9BPOaJnvg2UtlH2gPQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz", + "integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==", "dev": true, "license": "MIT", "dependencies": { @@ -6864,7 +6886,7 @@ "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", - "npm-run-path": "^5.2.0", + "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", @@ -6931,16 +6953,17 @@ } }, "node_modules/semantic-release/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6998,6 +7021,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/semantic-release/node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -7533,9 +7569,9 @@ } }, "node_modules/type-fest": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.25.0.tgz", - "integrity": "sha512-bRkIGlXsnGBRBQRAY56UXBm//9qH4bmJfFvq83gSz41N282df+fjy8ofcEgc1sM8geNt5cl6mC2g9Fht1cs8Aw==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -7546,9 +7582,9 @@ } }, "node_modules/uglify-js": { - "version": "3.19.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", - "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, "license": "BSD-2-Clause", "optional": true, diff --git a/package.json b/package.json index b407c02..105a5ca 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "@saithodev/semantic-release-backmerge": "^4.0.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", - "gradle-semantic-release-plugin": "1.9.2", - "semantic-release": "24.1.0" + "gradle-semantic-release-plugin": "^1.10.1", + "semantic-release": "^24.1.2" } } diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index b89570b..fdee611 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -7,14 +7,12 @@ - - + tools:targetApi="35"> + diff --git a/src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt b/src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt deleted file mode 100644 index 32724f7..0000000 --- a/src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt +++ /dev/null @@ -1,61 +0,0 @@ -@file:Suppress("Unused") - -package app.revanced.manager.plugin.downloader.example - -import android.content.Intent -import android.content.pm.PackageManager -import app.revanced.manager.plugin.downloader.App -import app.revanced.manager.plugin.downloader.example.BuildConfig.PLUGIN_PACKAGE_NAME -import app.revanced.manager.plugin.downloader.DownloaderContext -import app.revanced.manager.plugin.downloader.downloader -import kotlinx.coroutines.delay -import kotlinx.parcelize.Parcelize -import java.nio.file.Files -import java.nio.file.StandardCopyOption -import kotlin.io.path.Path - -// TODO: document API, change dispatcher. - -@Parcelize -class InstalledApp( - override val packageName: String, - override val version: String, - internal val apkPath: String -) : App(packageName, version) - -fun installedAppDownloader(context: DownloaderContext) = downloader { - val pm = context.androidContext.packageManager - - get { packageName, version -> - val packageInfo = try { - pm.getPackageInfo(packageName, 0) - } catch (_: PackageManager.NameNotFoundException) { - return@get null - } - - requestUserInteraction().launch(Intent().apply { - setClassName( - PLUGIN_PACKAGE_NAME, - InteractionActivity::class.java.canonicalName!! - ) - }) - - InstalledApp( - packageName, - packageInfo.versionName, - packageInfo.applicationInfo.sourceDir - ).takeIf { version == null || it.version == version } - } - - download { - // Simulate download progress - for (i in 0..5) { - reportProgress(i.megaBytes, 5.megaBytes) - delay(1000L) - } - - Files.copy(Path(it.apkPath), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING) - } -} - -private val Int.megaBytes get() = times(1_000_000).toLong() \ No newline at end of file diff --git a/src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt b/src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt deleted file mode 100644 index 0390f3b..0000000 --- a/src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt +++ /dev/null @@ -1,65 +0,0 @@ -package app.revanced.manager.plugin.downloader.example - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.ui.Modifier - -class InteractionActivity : ComponentActivity() { - @OptIn(ExperimentalMaterial3Api::class) - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - val isDarkTheme = isSystemInDarkTheme() - - val colorScheme = if (isDarkTheme) darkColorScheme() else lightColorScheme() - - MaterialTheme(colorScheme) { - Scaffold( - topBar = { - TopAppBar( - title = { Text("User interaction example") } - ) - } - ) { paddingValues -> - Column(modifier = Modifier.padding(paddingValues)) { - Text("This is an example interaction.") - Row { - TextButton( - onClick = { - setResult(RESULT_CANCELED) - finish() - } - ) { - Text("Cancel") - } - - TextButton( - onClick = { - setResult(RESULT_OK) - finish() - } - ) { - Text("Continue") - } - } - } - } - } - - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt b/src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt new file mode 100644 index 0000000..e177694 --- /dev/null +++ b/src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt @@ -0,0 +1,42 @@ +@file:Suppress("Unused") + +package app.revanced.manager.plugin.downloader.example + +import android.annotation.SuppressLint +import android.app.Application +import android.content.Intent +import android.content.res.AssetFileDescriptor +import app.revanced.manager.plugin.downloader.* + +// This file contains an example downloader implementation using the system file picker. +// Remember to update the Android manifest if you move the definition file. + +val exampleDownloader = Downloader { + get { packageName, version -> + // Use the requestStartActivity API to open the system file picker and get the resulting content URI. + val uri = requestStartActivity( + Intent(Intent.ACTION_GET_CONTENT) + .addCategory(Intent.CATEGORY_OPENABLE) + .setType("application/vnd.android.package-archive") + )?.data ?: return@get null + + println("Package name: $packageName, version: $version") + + // We assume the user has selected the correct version, but this might not be the case. + // Real plugins should verify the version and package name if possible. + uri to version + } + + // Get an Android context. This is only used for reading the file that the user selected. + // This hack should not be necessary in a real plugin. + @SuppressLint("PrivateApi") + val application = with(Class.forName("android.app.ActivityThread")) { + val activityThread = getMethod("currentActivityThread")(null) + getMethod("getApplication")(activityThread) as Application + } + download { uri -> + // Open the file and return an InputStream to it along with the size. + val fd = application.contentResolver.openAssetFileDescriptor(uri, "r")!! + AssetFileDescriptor.AutoCloseInputStream(fd) to fd.length.takeIf { it > 0L } + } +} \ No newline at end of file