Compare commits

..

No commits in common. "62c1fe79027d0140014633ff14026da65679b7f1" and "7743d6d4c3ff1cc0835fe6462b492da55538d9f5" have entirely different histories.

561 changed files with 3559 additions and 3895 deletions

View File

@ -76,7 +76,7 @@ body:
description: Where did you install Spotube from? description: Where did you install Spotube from?
multiple: true multiple: true
options: options:
- "Website (spotube.org)" - "Website (spotube.cc)"
- "GitHub Releases (Binary)" - "GitHub Releases (Binary)"
- "GitHub Actions (Nightly Binary)" - "GitHub Actions (Nightly Binary)"
- "Play Store (Android)" - "Play Store (Android)"

View File

@ -1,5 +1,5 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Ask a question - name: Ask a question
url: https://github.com/team-spotube/spotube/discussions/new?category=q-a url: https://github.com/KRTirtho/spotube/discussions/new?category=q-a
about: The place for questions, support and feature requests about: The place for questions, support and feature requests

View File

@ -141,16 +141,11 @@ jobs:
EOF EOF
- name: Assemble Release - name: Assemble Release
run: | run: ./gradlew :composeApp:assembleRelease
if [ "${{ inputs.release_type }}" = "nightly" ]; then
./gradlew :composeApp:assembleNightlyRelease -Pnightly=true -PbuildNumber=${{ github.run_number }}
else
./gradlew :composeApp:assembleStableRelease
fi
- name: Rename APK - name: Rename APK
run: | run: |
APK_FILE=$(find composeApp/build/outputs/apk -path "*elease*" -name "*.apk" -type f | head -1) APK_FILE=$(find composeApp/build/outputs/apk/release -name "*.apk" -type f | head -1)
cp "$APK_FILE" Spotube-android-all-arch.apk cp "$APK_FILE" Spotube-android-all-arch.apk
- name: Upload APK - name: Upload APK
@ -199,7 +194,7 @@ jobs:
run: chmod +x gradlew run: chmod +x gradlew
- name: Package Linux - name: Package Linux
run: ./gradlew :composeApp:packageReleaseDeb :composeApp:packageReleaseRpm -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }} run: ./gradlew :composeApp:packageReleaseDeb :composeApp:packageReleaseRpm
- name: Rename Linux artifacts - name: Rename Linux artifacts
run: | run: |
@ -260,7 +255,7 @@ jobs:
run: chmod +x gradlew run: chmod +x gradlew
- name: Package Linux - name: Package Linux
run: ./gradlew :composeApp:packageReleaseDeb :composeApp:packageReleaseRpm -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }} run: ./gradlew :composeApp:packageReleaseDeb :composeApp:packageReleaseRpm
- name: Rename Linux artifacts - name: Rename Linux artifacts
run: | run: |
@ -313,7 +308,7 @@ jobs:
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Package EXE - name: Package EXE
run: ./gradlew :composeApp:packageReleaseExe -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }} run: ./gradlew :composeApp:packageReleaseExe
- name: Rename Windows artifacts - name: Rename Windows artifacts
shell: pwsh shell: pwsh
@ -362,7 +357,7 @@ jobs:
run: chmod +x gradlew run: chmod +x gradlew
- name: Package DMG - name: Package DMG
run: ./gradlew :composeApp:packageReleaseDmg -Pnightly=${{ inputs.release_type == 'nightly' }} -PbuildNumber=${{ github.run_number }} run: ./gradlew :composeApp:packageReleaseDmg
- name: Rename macOS artifact - name: Rename macOS artifact
run: | run: |
@ -394,35 +389,18 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
# The build resolves its plugins from mavenLocal, so Gradle needs the same setup as the build jobs
- name: Download maven local
uses: actions/download-artifact@v4
with:
name: maven-local
path: ~/.m2/repository/
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Set release variables - name: Set release variables
id: vars id: vars
run: | run: |
if [ "${{ inputs.release_type }}" = "stable" ]; then if [ "${{ inputs.release_type }}" = "stable" ]; then
chmod +x gradlew VERSION=$(grep 'versionName' composeApp/build.gradle.kts | head -1 | sed 's/.*"\(.*\)".*/\1/')
VERSION=$(./gradlew -q :composeApp:printVersion)
TAG="v${VERSION}" TAG="v${VERSION}"
echo "is_prerelease=false" >> "$GITHUB_OUTPUT" echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
echo "is_draft=true" >> "$GITHUB_OUTPUT" echo "is_draft=true" >> "$GITHUB_OUTPUT"
echo "release_name=Spotube ${TAG}" >> "$GITHUB_OUTPUT" echo "release_name=Spotube ${TAG}" >> "$GITHUB_OUTPUT"
else else
TAG="nightly" TAG="nightly"
VERSION="$(date +%Y-%m-%d)-${{ github.run_number }}" VERSION="$(date +%Y-%m-%d)"
echo "is_prerelease=true" >> "$GITHUB_OUTPUT" echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
echo "is_draft=false" >> "$GITHUB_OUTPUT" echo "is_draft=false" >> "$GITHUB_OUTPUT"
echo "release_name=Nightly ${VERSION}" >> "$GITHUB_OUTPUT" echo "release_name=Nightly ${VERSION}" >> "$GITHUB_OUTPUT"

View File

@ -5,14 +5,14 @@
- `:composeApp` uses custom KMP source sets (`mobileMain`, `androidJvmMain`) with explicit `dependsOn`; Gradle prints "Default Kotlin Hierarchy Template Not Applied Correctly" warning. Treat as known/expected. - `:composeApp` uses custom KMP source sets (`mobileMain`, `androidJvmMain`) with explicit `dependsOn`; Gradle prints "Default Kotlin Hierarchy Template Not Applied Correctly" warning. Treat as known/expected.
## Real app entrypoints ## Real app entrypoints
- Desktop/JVM: `composeApp/src/jvmMain/kotlin/org/spotube/spotube/main.kt` (`mainClass = org.spotube.spotube.MainKt`). - Desktop/JVM: `composeApp/src/jvmMain/kotlin/dev/krtirtho/spotube/main.kt` (`mainClass = dev.krtirtho.spotube.MainKt`).
- Android: `composeApp/src/androidMain/kotlin/org/spotube/spotube/MainActivity.kt`. - Android: `composeApp/src/androidMain/kotlin/dev/krtirtho/spotube/MainActivity.kt`.
- iOS bridge: `composeApp/src/iosMain/kotlin/org/spotube/spotube/MainViewController.kt` and `iosApp/iosApp/ContentView.swift`. - iOS bridge: `composeApp/src/iosMain/kotlin/dev/krtirtho/spotube/MainViewController.kt` and `iosApp/iosApp/ContentView.swift`.
## High-value commands ## High-value commands
- Use Gradle wrapper (`./gradlew` or `./gradlew.bat`) only. - Use Gradle wrapper (`./gradlew` or `./gradlew.bat`) only.
- Run desktop: `:composeApp:run` - Run desktop: `:composeApp:run`
- Build Android debug: `:composeApp:assembleStableDebug` (or `assembleNightlyDebug`). Android has `stable`/`nightly` product flavors (nightly = beta channel: `.nightly` applicationId suffix, own icons/name in `composeApp/src/nightly/res`). Desktop icons come from `composeApp/icons/{stable,nightly}`, chosen with `-Pnightly=true`. - Build Android debug: `:composeApp:assembleDebug`
- Module checks: `:composeApp:check`, `:plugin_interfaces:check`, `:js_plugin_example:check` - Module checks: `:composeApp:check`, `:plugin_interfaces:check`, `:js_plugin_example:check`
- Focused tests: `:composeApp:jvmTest`, `:composeApp:iosSimulatorArm64Test`, `:plugin_interfaces:jvmTest`, `:plugin_interfaces:jsTest`, `:js_plugin_example:jsTest` - Focused tests: `:composeApp:jvmTest`, `:composeApp:iosSimulatorArm64Test`, `:plugin_interfaces:jvmTest`, `:plugin_interfaces:jsTest`, `:js_plugin_example:jsTest`
- No lint/typecheck/formatter tasks are configured; `:composeApp:check` is the only aggregated check. - No lint/typecheck/formatter tasks are configured; `:composeApp:check` is the only aggregated check.
@ -24,7 +24,7 @@
## Codegen and plugin packaging ## Codegen and plugin packaging
- JS plugin bundles: `:js_plugin_example:packageDevelopmentPlugin` and `:js_plugin_example:packageProductionPlugin`. Output is `.smplug` files in `js_plugin_example/build/distributions/`. - JS plugin bundles: `:js_plugin_example:packageDevelopmentPlugin` and `:js_plugin_example:packageProductionPlugin`. Output is `.smplug` files in `js_plugin_example/build/distributions/`.
- Zipline plugin entrypoint: `mainFunction = "org.spotube.js_plugin_example.main"` in `js_plugin_example/build.gradle.kts`. Plugin metadata from `js_plugin_example/plugin.json`. - Zipline plugin entrypoint: `mainFunction = "dev.krtirtho.js_plugin_example.main"` in `js_plugin_example/build.gradle.kts`. Plugin metadata from `js_plugin_example/plugin.json`.
## Plugin architecture ## Plugin architecture
- `plugin_interfaces` exports `zipline.core` and `semver` as API. `composeApp` depends on it for the plugin system. - `plugin_interfaces` exports `zipline.core` and `semver` as API. `composeApp` depends on it for the plugin system.
@ -70,6 +70,6 @@
- **Adaptive Components:** Use `AdaptiveDropdownBottomSheet` or `AdaptiveDialogBottomSheet` inside `commonMain` for adaptive layouts[cite: 2]. Do NOT create platform-specific `expect/actual` variants unless platform-native APIs (like windowing or native scrollbars) are explicitly required[cite: 2]. - **Adaptive Components:** Use `AdaptiveDropdownBottomSheet` or `AdaptiveDialogBottomSheet` inside `commonMain` for adaptive layouts[cite: 2]. Do NOT create platform-specific `expect/actual` variants unless platform-native APIs (like windowing or native scrollbars) are explicitly required[cite: 2].
### 3. Verification & Diagnostic Loops ### 3. Verification & Diagnostic Loops
- **Post-Edit Verification:** After editing Kotlin code, validate compilation by running `./gradlew :composeApp:check` or `./gradlew :composeApp:assembleStableDebug` via MCP[cite: 2]. - **Post-Edit Verification:** After editing Kotlin code, validate compilation by running `./gradlew :composeApp:check` or `./gradlew :composeApp:assembleDebug` via MCP[cite: 2].
- **Dispatcher Integrity:** Never remove or bypass `SwingMainDispatcherFactory` in `composeApp/src/jvmMain/.../core/coroutines/`[cite: 2]. It is required to prevent `compose-webview` from hijacking `Dispatchers.Main` away from the Swing EDT[cite: 2]. - **Dispatcher Integrity:** Never remove or bypass `SwingMainDispatcherFactory` in `composeApp/src/jvmMain/.../core/coroutines/`[cite: 2]. It is required to prevent `compose-webview` from hijacking `Dispatchers.Main` away from the Swing EDT[cite: 2].
- **Live Preview Iteration:** Use `compose-hot-reload` to evaluate UI layout changes headlessly without forcing full Gradle rebuilds. - **Live Preview Iteration:** Use `compose-hot-reload` to evaluate UI layout changes headlessly without forcing full Gradle rebuilds.

File diff suppressed because it is too large Load Diff

View File

@ -30,19 +30,19 @@ All types of contributions are encouraged and valued. See the [Table of Contents
## Code of Conduct ## Code of Conduct
This project and everyone participating in it is governed by the This project and everyone participating in it is governed by the
[Spotube Code of Conduct](https://github.com/team-spotube/spotube/blob/master/CODE_OF_CONDUCT.md). [Spotube Code of Conduct](https://github.com/KRTirtho/spotube/blob/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable behavior By participating, you are expected to uphold this code. Please report unacceptable behavior
to krtirtho@gmail.com. to krtirtho@gmail.com.
## I Have a Question ## I Have a Question
> If you want to ask a question, we assume that you have read the available [Documentation](https://github.com/team-spotube/spotube#readme). > If you want to ask a question, we assume that you have read the available [Documentation](https://github.com/KRTirtho/spotube#readme).
Before you ask a question, it is best to search for existing [Issues](https://github.com/team-spotube/spotube/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. Before you ask a question, it is best to search for existing [Issues](https://github.com/KRTirtho/spotube/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.
If you then still feel the need to ask a question and need clarification, we recommend the following: If you then still feel the need to ask a question and need clarification, we recommend the following:
- Open an [Discussion](https://github.com/team-spotube/spotube/discussions/new) with the question label. - Open an [Discussion](https://github.com/KRTirtho/spotube/discussions/new) with the question label.
- Provide as much context as you can about what you're running into. - Provide as much context as you can about what you're running into.
- Provide project and platform versions (flutter, dart, pub, linux etc..), depending on what seems relevant. - Provide project and platform versions (flutter, dart, pub, linux etc..), depending on what seems relevant.
@ -61,8 +61,8 @@ We will then take care of the issue as soon as possible.
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
- Make sure that you are using the latest version. - Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://github.com/team-spotube/spotube#readme). If you are looking for support, you might want to check [this section](#i-have-a-question)). - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://github.com/KRTirtho/spotube#readme). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/team-spotube/spotube/issues?q=label%3Abug). - To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/KRTirtho/spotubeissues?q=label%3Abug).
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
- Collect information about the bug: - Collect information about the bug:
- Stack trace (Traceback) - Stack trace (Traceback)
@ -77,7 +77,7 @@ A good bug report shouldn't leave others needing to chase you up for more inform
We use GitHub issues to track bugs and errors. If you run into an issue with the project: We use GitHub issues to track bugs and errors. If you run into an issue with the project:
- Open an [Issue](https://github.com/team-spotube/spotube/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) - Open an [Issue](https://github.com/KRTirtho/spotube/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Explain the behavior you would expect and the actual behavior. - Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. - Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section. - Provide the information you collected in the previous section.
@ -97,15 +97,15 @@ This section guides you through submitting an enhancement suggestion for Spotube
#### Before Submitting an Enhancement #### Before Submitting an Enhancement
- Make sure that you are using the latest version. - Make sure that you are using the latest version.
- Read the [documentation](https://github.com/team-spotube/spotube#readme) carefully and find out if the functionality is already covered, maybe by an individual configuration. - Read the [documentation](https://github.com/KRTirtho/spotube#readme) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/team-spotube/spotube/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. - Perform a [search](https://github.com/KRTirtho/spotube/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset
<!-- omit in toc --> <!-- omit in toc -->
#### How Do I Submit a Good Enhancement Suggestion? #### How Do I Submit a Good Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://github.com/team-spotube/spotube/issues). Enhancement suggestions are tracked as [GitHub issues](https://github.com/KRTirtho/spotube/issues).
- Use a **clear and descriptive title** for the issue to identify the suggestion. - Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible. - Provide a **step-by-step description of the suggested enhancement** in as many details as possible.

View File

@ -4,7 +4,7 @@
A cross-platform extensible open-source music streaming platform.<br> A cross-platform extensible open-source music streaming platform.<br>
Bring your own music metadata/playlist/audio-source with plugins created by community or by yourself. A small step towards the decentralized music streaming era! Bring your own music metadata/playlist/audio-source with plugins created by community or by yourself. A small step towards the decentralized music streaming era!
<a href="https://spotube.org"><img alt="Visit the website" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/website_vector.svg"></a> <a href="https://spotube.cc"><img alt="Visit the website" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/website_vector.svg"></a>
<a href="https://discord.gg/uJ94vxB6vg"><img alt="Discord Server" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/social/discord-plural_vector.svg"></a> <a href="https://discord.gg/uJ94vxB6vg"><img alt="Discord Server" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/social/discord-plural_vector.svg"></a>
<a href="https://patreon.com/krtirtho"><img alt="Support me on Patron" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/donate/patreon-singular_vector.svg"></a> <a href="https://patreon.com/krtirtho"><img alt="Support me on Patron" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/donate/patreon-singular_vector.svg"></a>
@ -37,21 +37,21 @@ Bring your own music metadata/playlist/audio-source with plugins created by comm
### ⬇️ Download ### ⬇️ Download
Download Spotube from the Official Website: https://spotube.org Download Spotube from the Official Website: https://spotube.cc
### 🔄 Nightly Builds ### 🔄 Nightly Builds
Grab the latest nightly builds of Spotube [from the Offical Website](https://spotube.org/downloads/nightly). Grab the latest nightly builds of Spotube [from the Offical Website](https://spotube.cc/downloads/nightly).
## 🕳️ Building from source ## 🕳️ Building from source
<a href="https://github.com/team-spotube/spotube/actions"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/KRTirtho/spotube/spotube-release-binary.yml?+label=Build%20Status"></a> <a href="https://github.com/KRTirtho/spotube/actions"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/KRTirtho/spotube/spotube-release-binary.yml?+label=Build%20Status"></a>
You can compile Spotube's source code by [following these instructions](CONTRIBUTION.md#your-first-code-contribution). You can compile Spotube's source code by [following these instructions](CONTRIBUTION.md#your-first-code-contribution).
## 👥 The Spotube team ## 👥 The Spotube team
- [Kingkor Roy Tirtho](https://github.com/team-spotube) - The Founder, Maintainer and Lead Developer - [Kingkor Roy Tirtho](https://github.com/KRTirtho) - The Founder, Maintainer and Lead Developer
- [Owen Connor](https://github.com/owencz1998) - The Cool Discord Moderator - [Owen Connor](https://github.com/owencz1998) - The Cool Discord Moderator
- [Piotr Rogowski](https://github.com/karniv00l) - The MacOS Developer - [Piotr Rogowski](https://github.com/karniv00l) - The MacOS Developer
- [Rusty Apple](https://github.com/RustyApple) - The Mysterious Unknown Guy - [Rusty Apple](https://github.com/RustyApple) - The Mysterious Unknown Guy

View File

@ -27,7 +27,7 @@ render_always = true
# An array of regex based postprocessors to modify the changelog. # An array of regex based postprocessors to modify the changelog.
postprocessors = [ postprocessors = [
# Replace the placeholder <REPO> with a URL. # Replace the placeholder <REPO> with a URL.
{ pattern = '<REPO>', replace = "https://github.com/team-spotube/spotube" }, { pattern = '<REPO>', replace = "https://github.com/KRTirtho/spotube" },
] ]
# render body even when there are no releases to process # render body even when there are no releases to process
# render_always = true # render_always = true

View File

@ -40,34 +40,22 @@ plugins {
kotlin("plugin.atomicfu") version libs.versions.kotlin kotlin("plugin.atomicfu") version libs.versions.kotlin
} }
val bundleId = "org.spotube.spotube" val bundleId = "dev.krtirtho.spotube"
val version = "6.0.0" val version = "6.0.0"
val buildNumber = 46 val buildNumber = 46
// Desktop icon channel; Android picks its icons via the stable/nightly product flavor. Use -Pnightly=true.
val isNightly = providers.gradleProperty("nightly").map { it.toBoolean() }.getOrElse(false)
val desktopIconDir = if (isNightly) "icons/nightly" else "icons/stable"
// Nightlies are numbered by the CI run (-PbuildNumber=<run>, or GITHUB_RUN_NUMBER) so every build is traceable to its run.
val nightlyBuildNumber = providers.gradleProperty("buildNumber").orNull?.toIntOrNull()
?: System.getenv("GITHUB_RUN_NUMBER")?.toIntOrNull()
?: buildNumber
val targetName = "Spotube" val targetName = "Spotube"
val homePageUrl = "https://spotube.org" val homePageUrl = "https://spotube.cc"
val repositoryUrl = "https://github.com/team-spotube/spotube" val repositoryUrl = "https://github.com/team-spotube/spotube"
val appVersionName = version val appVersionName = version
val appBuildNumber = if (isNightly) nightlyBuildNumber else buildNumber val appBuildNumber = buildNumber
val appRepositoryUrl = repositoryUrl val appRepositoryUrl = repositoryUrl
// CI reads the release version from here instead of scraping this file.
tasks.register("printVersion") {
val appVersion = appVersionName
doLast { println(appVersion) }
}
val githubRepositoryPath = repositoryUrl.removePrefix("https://github.com/") val githubRepositoryPath = repositoryUrl.removePrefix("https://github.com/")
val latestReleaseApiUrl = "https://api.github.com/repos/$githubRepositoryPath/releases/latest" val latestReleaseApiUrl = "https://api.github.com/repos/$githubRepositoryPath/releases/latest"
val generatedAppInfoDir = layout.buildDirectory.dir("generated/appBuildInfo/commonMain/kotlin") val generatedAppInfoDir = layout.buildDirectory.dir("generated/appBuildInfo/commonMain/kotlin")
val generateAppBuildInfo by tasks.registering(Copy::class) { val generateAppBuildInfo by tasks.registering(Copy::class) {
description = "Generate AppBuildInfo.kt" description = "Generate AppBuildInfo.kt"
from(layout.projectDirectory.file("src/commonMain/templates/AppBuildInfo.kt.template")) from(layout.projectDirectory.file("src/commonMain/templates/AppBuildInfo.kt.template"))
into(layout.buildDirectory.dir("generated/appBuildInfo/commonMain/kotlin/org/spotube/spotube")) into(layout.buildDirectory.dir("generated/appBuildInfo/commonMain/kotlin/dev/krtirtho/spotube"))
rename("AppBuildInfo.kt.template", "AppBuildInfo.kt") rename("AppBuildInfo.kt.template", "AppBuildInfo.kt")
expand( expand(
mapOf( mapOf(
@ -299,7 +287,7 @@ kotlin {
} }
android { android {
namespace = "org.spotube.spotube" namespace = "dev.krtirtho.spotube"
compileSdk = libs.versions.android.compileSdk.get().toInt() compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig { defaultConfig {
@ -309,19 +297,6 @@ android {
versionCode = buildNumber versionCode = buildNumber
versionName = version versionName = version
} }
// stable = production channel, nightly = beta channel (own icon, name and installable side by side)
flavorDimensions += "channel"
productFlavors {
create("stable") {
dimension = "channel"
}
create("nightly") {
dimension = "channel"
applicationIdSuffix = ".nightly"
versionCode = nightlyBuildNumber
versionNameSuffix = "-nightly.$nightlyBuildNumber"
}
}
packaging { packaging {
resources { resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}" excludes += "/META-INF/{AL2.0,LGPL2.1}"
@ -375,7 +350,7 @@ dependencies {
} }
nucleus.application { nucleus.application {
mainClass = "org.spotube.spotube.MainKt" mainClass = "dev.krtirtho.spotube.MainKt"
jvmArgs += listOf( jvmArgs += listOf(
"--enable-native-access=ALL-UNNAMED", // need for JNA for compose-webview (wry) to work "--enable-native-access=ALL-UNNAMED", // need for JNA for compose-webview (wry) to work
@ -407,13 +382,11 @@ nucleus.application {
homepage = homePageUrl homepage = homePageUrl
linux { linux {
iconFile.set(project.file("$desktopIconDir/icon.png"))
modules("jdk.security.auth") modules("jdk.security.auth")
debMaintainer = "Team Spotube <team.spotube@proton.me>" debMaintainer = "Team Spotube <team.spotube@proton.me>"
rpmLicenseType = "AGPL-3.0-or-later" rpmLicenseType = "AGPL-3.0-or-later"
} }
windows { windows {
iconFile.set(project.file("$desktopIconDir/icon.ico"))
shortcut = true shortcut = true
menu = true menu = true
dirChooser = true dirChooser = true
@ -421,7 +394,6 @@ nucleus.application {
} }
macOS { macOS {
iconFile.set(project.file("$desktopIconDir/icon.icns"))
notarization { notarization {
} }

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

View File

@ -15,14 +15,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.newpipe package dev.krtirtho.spotube.core.newpipe
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import org.spotube.spotube.core.paths.Paths import dev.krtirtho.spotube.core.paths.Paths
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@ -15,10 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.newpipe package dev.krtirtho.spotube.core.newpipe
import org.spotube.plugin_interfaces.plugin_apis.audio.AudioStream import dev.krtirtho.plugin_interfaces.plugin_apis.audio.AudioStream
import org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol import dev.krtirtho.plugin_interfaces.plugin_apis.audio.StreamProtocol
import io.ktor.http.Url import io.ktor.http.Url
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube package dev.krtirtho.spotube
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
@ -23,10 +23,10 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import org.spotube.spotube.core.deeplink.ExternalUriHandler import dev.krtirtho.spotube.core.deeplink.ExternalUriHandler
import org.spotube.spotube.core.newpipe.NewPipeDownloader import dev.krtirtho.spotube.core.newpipe.NewPipeDownloader
import org.spotube.spotube.core.paths.Paths import dev.krtirtho.spotube.core.paths.Paths
import org.spotube.spotube.media.PlaybackService import dev.krtirtho.spotube.media.PlaybackService
import io.github.vinceglb.filekit.FileKit import io.github.vinceglb.filekit.FileKit
import io.github.vinceglb.filekit.dialogs.init import io.github.vinceglb.filekit.dialogs.init

View File

@ -15,11 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube package dev.krtirtho.spotube
import android.app.Application import android.app.Application
import org.spotube.spotube.core.di.initKoin import dev.krtirtho.spotube.core.di.initKoin
import org.spotube.spotube.core.paths.Paths import dev.krtirtho.spotube.core.paths.Paths
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube package dev.krtirtho.spotube
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.audioplayer package dev.krtirtho.spotube.core.audioplayer
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -27,7 +27,7 @@ import androidx.media3.common.MediaMetadata
import androidx.media3.common.PlaybackException import androidx.media3.common.PlaybackException
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import org.spotube.spotube.media.PlaybackService import dev.krtirtho.spotube.media.PlaybackService
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob

View File

@ -15,17 +15,17 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.di package dev.krtirtho.spotube.core.di
import android.content.Context import android.content.Context
import org.spotube.spotube.core.audioplayer.AudioPlayer import dev.krtirtho.spotube.core.audioplayer.AudioPlayer
import org.spotube.spotube.core.audioplayer.AudioPlayerInterface import dev.krtirtho.spotube.core.audioplayer.AudioPlayerInterface
import org.spotube.spotube.core.paths.Paths import dev.krtirtho.spotube.core.paths.Paths
import org.spotube.spotube.core.share.AndroidShareService import dev.krtirtho.spotube.core.share.AndroidShareService
import org.spotube.spotube.core.share.ShareService import dev.krtirtho.spotube.core.share.ShareService
import org.spotube.spotube.media.MediaBrowseHelper import dev.krtirtho.spotube.media.MediaBrowseHelper
import org.spotube.spotube.modules.library.local_tracks.media.AndroidLocalMediaDiscoveryService import dev.krtirtho.spotube.modules.library.local_tracks.media.AndroidLocalMediaDiscoveryService
import org.spotube.spotube.modules.library.local_tracks.media.LocalMediaDiscoveryService import dev.krtirtho.spotube.modules.library.local_tracks.media.LocalMediaDiscoveryService
import org.koin.dsl.module import org.koin.dsl.module
actual val platformModules = module { actual val platformModules = module {

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.discovery package dev.krtirtho.spotube.core.discovery
import android.Manifest import android.Manifest
import android.content.pm.PackageManager import android.content.pm.PackageManager

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.i18n package dev.krtirtho.spotube.core.i18n
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.paths package dev.krtirtho.spotube.core.paths
import android.content.Context import android.content.Context
import android.os.Environment import android.os.Environment

View File

@ -15,11 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.share package dev.krtirtho.spotube.core.share
import android.content.Context import android.content.Context
import androidx.core.app.ShareCompat import androidx.core.app.ShareCompat
import org.spotube.spotube.core.share.ShareService import dev.krtirtho.spotube.core.share.ShareService
class AndroidShareService(private val context: Context) : ShareService { class AndroidShareService(private val context: Context) : ShareService {
override fun share(url: String, title: String) { override fun share(url: String, title: String) {

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.webview package dev.krtirtho.spotube.core.webview
import android.webkit.CookieManager import android.webkit.CookieManager
import android.webkit.WebStorage import android.webkit.WebStorage

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.zipline package dev.krtirtho.spotube.core.zipline
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executors import java.util.concurrent.Executors

View File

@ -15,31 +15,31 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.media package dev.krtirtho.spotube.media
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata import androidx.media3.common.MediaMetadata
import org.spotube.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum
import org.spotube.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist
import org.spotube.plugin_interfaces.plugin_apis.metadata.browse.MetadataBrowseItem import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.browse.MetadataBrowseItem
import org.spotube.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylist import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylist
import org.spotube.plugin_interfaces.plugin_apis.metadata.search.MetadataSearchResult import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.search.MetadataSearchResult
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.QueueEntry import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import org.spotube.spotube.core.playback.CollectionPlaybackHelper import dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper
import org.spotube.spotube.modules.album.AlbumRepository import dev.krtirtho.spotube.modules.album.AlbumRepository
import org.spotube.spotube.modules.blacklist.BlacklistRepository import dev.krtirtho.spotube.modules.blacklist.BlacklistRepository
import org.spotube.spotube.modules.home.HomeScreenRepository import dev.krtirtho.spotube.modules.home.HomeScreenRepository
import org.spotube.spotube.modules.library.LibraryRepository import dev.krtirtho.spotube.modules.library.LibraryRepository
import org.spotube.spotube.modules.playlist.PlaylistRepository import dev.krtirtho.spotube.modules.playlist.PlaylistRepository
import org.spotube.spotube.modules.plugin.PluginManager import dev.krtirtho.spotube.modules.plugin.PluginManager
import org.spotube.spotube.modules.saved_tracks.SavedTracksRepository import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksRepository
import org.spotube.spotube.modules.search.SearchRepository import dev.krtirtho.spotube.modules.search.SearchRepository
import org.spotube.spotube.modules.settings.SettingsRepository import dev.krtirtho.spotube.modules.settings.SettingsRepository
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import org.jetbrains.compose.resources.getString import org.jetbrains.compose.resources.getString
import spotube.composeapp.generated.resources.Res import spotube.composeapp.generated.resources.Res

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.media package dev.krtirtho.spotube.media
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.NotificationChannel import android.app.NotificationChannel
@ -29,7 +29,6 @@ import androidx.core.app.NotificationCompat
import androidx.media3.common.MediaItem as Media3MediaItem import androidx.media3.common.MediaItem as Media3MediaItem
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.session.DefaultMediaNotificationProvider
import androidx.media3.session.LibraryResult import androidx.media3.session.LibraryResult
import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaLibraryService
import androidx.media3.session.MediaLibraryService.LibraryParams import androidx.media3.session.MediaLibraryService.LibraryParams
@ -41,12 +40,11 @@ import com.google.common.collect.ImmutableList
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import org.spotube.spotube.MainActivity import dev.krtirtho.spotube.MainActivity
import org.spotube.spotube.R import dev.krtirtho.spotube.core.audioplayer.AudioPlayer
import org.spotube.spotube.core.audioplayer.AudioPlayer import dev.krtirtho.spotube.core.audioplayer.AudioPlayerInterface
import org.spotube.spotube.core.audioplayer.AudioPlayerInterface import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import org.spotube.spotube.core.audioplayer.QueueEntry
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
@ -77,16 +75,6 @@ class PlaybackService : MediaLibraryService(), KoinComponent {
createNotificationChannel() createNotificationChannel()
// Media3 posts the real playback notification; point it at our channel,
// ID and monochrome icon so it replaces the placeholder below in place.
setMediaNotificationProvider(
DefaultMediaNotificationProvider.Builder(this)
.setChannelId(CHANNEL_ID)
.setNotificationId(NOTIFICATION_ID)
.build()
.apply { setSmallIcon(R.drawable.ic_stat_spotube) }
)
val sessionActivity = PendingIntent.getActivity( val sessionActivity = PendingIntent.getActivity(
this, this,
0, 0,
@ -99,7 +87,7 @@ class PlaybackService : MediaLibraryService(), KoinComponent {
val notification = NotificationCompat.Builder(this, CHANNEL_ID) val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Spotube") .setContentTitle("Spotube")
.setContentText(runBlocking { getString(Res.string.notification_playback_service_text) }) .setContentText(runBlocking { getString(Res.string.notification_playback_service_text) })
.setSmallIcon(R.drawable.ic_stat_spotube) .setSmallIcon(android.R.drawable.ic_media_play)
.setContentIntent(sessionActivity) .setContentIntent(sessionActivity)
.setOngoing(true) .setOngoing(true)
.build() .build()
@ -383,20 +371,20 @@ class PlaybackService : MediaLibraryService(), KoinComponent {
when { when {
mediaId.startsWith("${MediaBrowseHelper.MEDIA_ID_PLAYLIST}:") -> { mediaId.startsWith("${MediaBrowseHelper.MEDIA_ID_PLAYLIST}:") -> {
val playlistId = mediaId.removePrefix("${MediaBrowseHelper.MEDIA_ID_PLAYLIST}:") val playlistId = mediaId.removePrefix("${MediaBrowseHelper.MEDIA_ID_PLAYLIST}:")
val helper: org.spotube.spotube.core.playback.CollectionPlaybackHelper by inject() val helper: dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper by inject()
helper.playPlaylist(playlistId) helper.playPlaylist(playlistId)
return return
} }
mediaId.startsWith("${MediaBrowseHelper.MEDIA_ID_ALBUM}:") -> { mediaId.startsWith("${MediaBrowseHelper.MEDIA_ID_ALBUM}:") -> {
val albumId = mediaId.removePrefix("${MediaBrowseHelper.MEDIA_ID_ALBUM}:") val albumId = mediaId.removePrefix("${MediaBrowseHelper.MEDIA_ID_ALBUM}:")
val helper: org.spotube.spotube.core.playback.CollectionPlaybackHelper by inject() val helper: dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper by inject()
helper.playAlbum(albumId) helper.playAlbum(albumId)
return return
} }
mediaId == MediaBrowseHelper.MEDIA_ID_SAVED_TRACKS -> { mediaId == MediaBrowseHelper.MEDIA_ID_SAVED_TRACKS -> {
val helper: org.spotube.spotube.core.playback.CollectionPlaybackHelper by inject() val helper: dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper by inject()
helper.playSavedTracks() helper.playSavedTracks()
return return
} }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.modules.library.local_tracks.media package dev.krtirtho.spotube.modules.library.local_tracks.media
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
@ -26,7 +26,7 @@ import android.os.Environment
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.provider.MediaStore import android.provider.MediaStore
import org.spotube.spotube.core.di.injectLogger import dev.krtirtho.spotube.core.di.injectLogger
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import java.io.File import java.io.File
import java.util.Locale import java.util.Locale

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.modules.library.local_tracks.media package dev.krtirtho.spotube.modules.library.local_tracks.media
import android.Manifest import android.Manifest
import android.content.pm.PackageManager import android.content.pm.PackageManager

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

View File

@ -0,0 +1,47 @@
<!--
~ Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU Affero General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU Affero General Public License for more details.
~
~ You should have received a copy of the GNU Affero General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU Affero General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU Affero General Public License for more details.
~
~ You should have received a copy of the GNU Affero General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -17,7 +17,6 @@
--> -->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" /> <background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" /> <foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon> </adaptive-icon>

View File

@ -17,7 +17,6 @@
--> -->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" /> <background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" /> <foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon> </adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU Affero General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU Affero General Public License for more details.
~
~ You should have received a copy of the GNU Affero General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<resources>
<color name="ic_launcher_background">#000000</color>
</resources>

View File

@ -907,7 +907,6 @@
<string name="plugin_discover_badge_verified">Verified</string> <string name="plugin_discover_badge_verified">Verified</string>
<string name="plugin_discover_stars_content_description">GitHub stars</string> <string name="plugin_discover_stars_content_description">GitHub stars</string>
<string name="plugin_discover_repository_content_description">GitHub repository URL</string> <string name="plugin_discover_repository_content_description">GitHub repository URL</string>
<string name="plugin_discover_repository_host">github.com</string>
<!-- Plugin release install dialog --> <!-- Plugin release install dialog -->
<string name="plugin_install_no_releases">No releases found</string> <string name="plugin_install_no_releases">No releases found</string>

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube package dev.krtirtho.spotube
import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.SharedTransitionLayout
@ -33,42 +33,42 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation3.ui.NavDisplay import androidx.navigation3.ui.NavDisplay
import org.spotube.spotube.core.DebugConfig import dev.krtirtho.spotube.core.DebugConfig
import org.spotube.spotube.core.i18n.AppLocaleProvider import dev.krtirtho.spotube.core.i18n.AppLocaleProvider
import org.spotube.spotube.core.navigation.Navigator import dev.krtirtho.spotube.core.navigation.Navigator
import org.spotube.spotube.core.navigation.Routes import dev.krtirtho.spotube.core.navigation.Routes
import org.spotube.spotube.core.navigation.TOP_LEVEL_ROUTES import dev.krtirtho.spotube.core.navigation.TOP_LEVEL_ROUTES
import org.spotube.spotube.core.navigation.navPopTransitionSpec import dev.krtirtho.spotube.core.navigation.navPopTransitionSpec
import org.spotube.spotube.core.navigation.navPredictivePopTransitionSpec import dev.krtirtho.spotube.core.navigation.navPredictivePopTransitionSpec
import org.spotube.spotube.core.navigation.navPushTransitionSpec import dev.krtirtho.spotube.core.navigation.navPushTransitionSpec
import org.spotube.spotube.core.navigation.rememberNavigationState import dev.krtirtho.spotube.core.navigation.rememberNavigationState
import org.spotube.spotube.core.navigation.toEntries import dev.krtirtho.spotube.core.navigation.toEntries
import org.spotube.spotube.core.ui.component.LocalSharedTransitionScope import dev.krtirtho.spotube.core.ui.component.LocalSharedTransitionScope
import org.spotube.spotube.core.ui.theming.SpotubeTheme import dev.krtirtho.spotube.core.ui.theming.SpotubeTheme
import org.spotube.spotube.modules.library.LibraryTab import dev.krtirtho.spotube.modules.library.LibraryTab
import org.spotube.spotube.modules.settings.SettingsRepository import dev.krtirtho.spotube.modules.settings.SettingsRepository
import org.spotube.spotube.modules.settings.UserSettings import dev.krtirtho.spotube.modules.settings.UserSettings
import org.spotube.spotube.modules.shell.AppShell import dev.krtirtho.spotube.modules.shell.AppShell
import org.spotube.spotube.modules.support.LocalSupportPrompt import dev.krtirtho.spotube.modules.support.LocalSupportPrompt
import org.spotube.spotube.modules.support.SupportDialog import dev.krtirtho.spotube.modules.support.SupportDialog
import org.spotube.spotube.modules.support.SupportReminderIntervalMillis import dev.krtirtho.spotube.modules.support.SupportReminderIntervalMillis
import org.spotube.spotube.modules.update.AppUpdateDialog import dev.krtirtho.spotube.modules.update.AppUpdateDialog
import org.spotube.spotube.modules.update.AppUpdateService import dev.krtirtho.spotube.modules.update.AppUpdateService
import org.spotube.spotube.modules.update.PluginUpdateDialog import dev.krtirtho.spotube.modules.update.PluginUpdateDialog
import org.spotube.spotube.modules.update.PluginUpdateService import dev.krtirtho.spotube.modules.update.PluginUpdateService
import org.spotube.spotube.modules.webview.WebViewScreen import dev.krtirtho.spotube.modules.webview.WebViewScreen
import org.spotube.spotube.modules.welcome.WelcomeRepository import dev.krtirtho.spotube.modules.welcome.WelcomeRepository
import org.spotube.spotube.resources.iconsax.Iconsax import dev.krtirtho.spotube.resources.iconsax.Iconsax
import org.spotube.spotube.resources.iconsax.IconsaxCd import dev.krtirtho.spotube.resources.iconsax.IconsaxCd
import org.spotube.spotube.resources.iconsax.IconsaxDirectboxReceive import dev.krtirtho.spotube.resources.iconsax.IconsaxDirectboxReceive
import org.spotube.spotube.resources.iconsax.IconsaxHome import dev.krtirtho.spotube.resources.iconsax.IconsaxHome
import org.spotube.spotube.resources.iconsax.IconsaxMirrorScreenRegular import dev.krtirtho.spotube.resources.iconsax.IconsaxMirrorScreenRegular
import org.spotube.spotube.resources.iconsax.IconsaxMusicDashboard import dev.krtirtho.spotube.resources.iconsax.IconsaxMusicDashboard
import org.spotube.spotube.resources.iconsax.IconsaxMusicLibrary import dev.krtirtho.spotube.resources.iconsax.IconsaxMusicLibrary
import org.spotube.spotube.resources.iconsax.IconsaxSearch import dev.krtirtho.spotube.resources.iconsax.IconsaxSearch
import org.spotube.spotube.resources.iconsax.IconsaxSetting2 import dev.krtirtho.spotube.resources.iconsax.IconsaxSetting2
import org.spotube.spotube.resources.iconsax.IconsaxSoundTwotone import dev.krtirtho.spotube.resources.iconsax.IconsaxSoundTwotone
import org.spotube.spotube.resources.iconsax.User import dev.krtirtho.spotube.resources.iconsax.User
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlin.time.Clock import kotlin.time.Clock
import org.koin.compose.koinInject import org.koin.compose.koinInject
@ -253,7 +253,7 @@ fun App(
onDismiss = appUpdateService::dismissUpdate, onDismiss = appUpdateService::dismissUpdate,
onIgnore = appUpdateService::ignoreUpdate, onIgnore = appUpdateService::ignoreUpdate,
onUpdate = { onUpdate = {
runCatching { openUrlInBrowser("https://spotube.org/downloads/") } runCatching { openUrlInBrowser("https://spotube.cc/downloads/") }
appUpdateService.dismissUpdate() appUpdateService.dismissUpdate()
}) })
} }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube package dev.krtirtho.spotube
enum class PlatformType { enum class PlatformType {
Android, IOS, Windows, Linux, MacOS, Unknown Android, IOS, Windows, Linux, MacOS, Unknown

View File

@ -15,10 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core package dev.krtirtho.spotube.core
/** /**
* Development-only switches. These are intentionally kept out of [org.spotube.spotube.modules.settings.UserSettings] * Development-only switches. These are intentionally kept out of [dev.krtirtho.spotube.modules.settings.UserSettings]
* so they can never leak into user-facing configuration. * so they can never leak into user-facing configuration.
*/ */
object DebugConfig { object DebugConfig {

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.audioplayer package dev.krtirtho.spotube.core.audioplayer
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow

View File

@ -15,10 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.audioplayer package dev.krtirtho.spotube.core.audioplayer
import org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol import dev.krtirtho.plugin_interfaces.plugin_apis.audio.StreamProtocol
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlin.time.Duration import kotlin.time.Duration

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.audioplayer package dev.krtirtho.spotube.core.audioplayer
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow

View File

@ -15,11 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.audioplayer package dev.krtirtho.spotube.core.audioplayer
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import org.spotube.spotube.core.db.Database import dev.krtirtho.spotube.core.db.Database
import org.spotube.spotube.core.db.DatabaseKeys import dev.krtirtho.spotube.core.db.DatabaseKeys
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@ -15,13 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.audioplayer package dev.krtirtho.spotube.core.audioplayer
import org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol import dev.krtirtho.plugin_interfaces.plugin_apis.audio.StreamProtocol
import org.spotube.spotube.core.di.injectLogger import dev.krtirtho.spotube.core.di.injectLogger
import org.spotube.spotube.modules.blacklist.BlacklistRepository import dev.krtirtho.spotube.modules.blacklist.BlacklistRepository
import org.spotube.spotube.modules.plugin.PluginProvider import dev.krtirtho.spotube.modules.plugin.PluginProvider
import org.spotube.spotube.modules.settings.SettingsProvider import dev.krtirtho.spotube.modules.settings.SettingsProvider
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO import kotlinx.coroutines.IO

View File

@ -15,14 +15,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.db package dev.krtirtho.spotube.core.db
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import org.spotube.spotube.core.paths.Paths import dev.krtirtho.spotube.core.paths.Paths
import okio.FileSystem import okio.FileSystem
import okio.Path.Companion.toPath import okio.Path.Companion.toPath
import okio.SYSTEM import okio.SYSTEM
@ -77,12 +77,6 @@ class Database(val paths: Paths) {
) )
} }
val windowStateDataStore: DataStore<Preferences> by lazy {
PreferenceDataStoreFactory.createWithPath(
produceFile = { "${paths.getApplicationDataDirPath()}/spotube_window.preferences_pb".toPath() }
)
}
private companion object { private companion object {
/** Preference files written by previous launches; their presence means an upgrade. */ /** Preference files written by previous launches; their presence means an upgrade. */
val EXISTING_INSTALL_PROBE_FILES = listOf( val EXISTING_INSTALL_PROBE_FILES = listOf(
@ -101,5 +95,4 @@ object DatabaseKeys {
val AUDIO_PLAYER_QUEUE_STATE_KEY = stringPreferencesKey("audio_player_queue_state") val AUDIO_PLAYER_QUEUE_STATE_KEY = stringPreferencesKey("audio_player_queue_state")
val LOCAL_MEDIA_CACHE_STATE_KEY = stringPreferencesKey("local_media_cache_state") val LOCAL_MEDIA_CACHE_STATE_KEY = stringPreferencesKey("local_media_cache_state")
val LOCAL_MEDIA_LAST_SCAN_AT_KEY = longPreferencesKey("local_media_last_scan_at") val LOCAL_MEDIA_LAST_SCAN_AT_KEY = longPreferencesKey("local_media_last_scan_at")
val WINDOW_STATE_KEY = stringPreferencesKey("window_state")
} }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.deeplink package dev.krtirtho.spotube.core.deeplink
/** /**
* Cross-platform receiver for URIs handed to the app by the operating system * Cross-platform receiver for URIs handed to the app by the operating system

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.di package dev.krtirtho.spotube.core.di
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.di package dev.krtirtho.spotube.core.di
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import co.touchlab.kermit.koin.KermitKoinLogger import co.touchlab.kermit.koin.KermitKoinLogger

View File

@ -15,82 +15,82 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.di package dev.krtirtho.spotube.core.di
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.AudioPlayerQueueRepository import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueueRepository
import org.spotube.spotube.core.audioplayer.DeviceAudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.DeviceAudioPlayerQueue
import org.spotube.spotube.core.audioplayer.QueueStateRepository import dev.krtirtho.spotube.core.audioplayer.QueueStateRepository
import org.spotube.spotube.core.db.Database import dev.krtirtho.spotube.core.db.Database
import org.spotube.spotube.core.discovery.DeviceDiscoveryService import dev.krtirtho.spotube.core.discovery.DeviceDiscoveryService
import org.spotube.spotube.core.discord.DiscordRpcService import dev.krtirtho.spotube.core.discord.DiscordRpcService
import org.spotube.spotube.core.jam.JamRoomClient import dev.krtirtho.spotube.core.jam.JamRoomClient
import org.spotube.spotube.core.jam.JamRoomService import dev.krtirtho.spotube.core.jam.JamRoomService
import org.spotube.spotube.core.navigation.navigationModule import dev.krtirtho.spotube.core.navigation.navigationModule
import org.spotube.spotube.core.remote.RemoteControlClient import dev.krtirtho.spotube.core.remote.RemoteControlClient
import org.spotube.spotube.core.remote.RemoteControlHandler import dev.krtirtho.spotube.core.remote.RemoteControlHandler
import org.spotube.spotube.core.remote.RemoteControlService import dev.krtirtho.spotube.core.remote.RemoteControlService
import org.spotube.spotube.core.remote.RemotePlaybackController import dev.krtirtho.spotube.core.remote.RemotePlaybackController
import org.spotube.spotube.core.scrobble.ScrobbleManager import dev.krtirtho.spotube.core.scrobble.ScrobbleManager
import org.spotube.spotube.core.playback.CollectionPlaybackHelper import dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper
import org.spotube.spotube.core.server.AlternativeTracksRepository import dev.krtirtho.spotube.core.server.AlternativeTracksRepository
import org.spotube.spotube.core.server.CacheManager import dev.krtirtho.spotube.core.server.CacheManager
import org.spotube.spotube.core.server.LocalServer import dev.krtirtho.spotube.core.server.LocalServer
import org.spotube.spotube.core.server.MatchedTracksRepository import dev.krtirtho.spotube.core.server.MatchedTracksRepository
import org.spotube.spotube.core.server.TrackSourceRepository import dev.krtirtho.spotube.core.server.TrackSourceRepository
import org.spotube.spotube.core.server.StreamingUrlRepository import dev.krtirtho.spotube.core.server.StreamingUrlRepository
import org.spotube.spotube.core.webview.WebViewController import dev.krtirtho.spotube.core.webview.WebViewController
import org.spotube.spotube.modules.album.AlbumRepository import dev.krtirtho.spotube.modules.album.AlbumRepository
import org.spotube.spotube.modules.album.AlbumViewModel import dev.krtirtho.spotube.modules.album.AlbumViewModel
import org.spotube.spotube.modules.artist.ArtistRepository import dev.krtirtho.spotube.modules.artist.ArtistRepository
import org.spotube.spotube.modules.artist.ArtistViewModel import dev.krtirtho.spotube.modules.artist.ArtistViewModel
import org.spotube.spotube.modules.blacklist.BlacklistRepository import dev.krtirtho.spotube.modules.blacklist.BlacklistRepository
import org.spotube.spotube.modules.blacklist.BlacklistViewModel import dev.krtirtho.spotube.modules.blacklist.BlacklistViewModel
import org.spotube.spotube.modules.devices.DevicesViewModel import dev.krtirtho.spotube.modules.devices.DevicesViewModel
import org.spotube.spotube.modules.devices.RemoteControlViewModel import dev.krtirtho.spotube.modules.devices.RemoteControlViewModel
import org.spotube.spotube.modules.jam.JamViewModel import dev.krtirtho.spotube.modules.jam.JamViewModel
import org.spotube.spotube.modules.downloads.DownloadManager import dev.krtirtho.spotube.modules.downloads.DownloadManager
import org.spotube.spotube.modules.downloads.DownloadsViewModel import dev.krtirtho.spotube.modules.downloads.DownloadsViewModel
import org.spotube.spotube.modules.home.HomeScreenRepository import dev.krtirtho.spotube.modules.home.HomeScreenRepository
import org.spotube.spotube.modules.home.HomeScreenViewModel import dev.krtirtho.spotube.modules.home.HomeScreenViewModel
import org.spotube.spotube.modules.plugin.MetadataAuthViewModel import dev.krtirtho.spotube.modules.plugin.MetadataAuthViewModel
import org.spotube.spotube.modules.library.LibraryRepository import dev.krtirtho.spotube.modules.library.LibraryRepository
import org.spotube.spotube.modules.library.LibraryState import dev.krtirtho.spotube.modules.library.LibraryState
import org.spotube.spotube.modules.library.album.LibraryAlbumsViewModel import dev.krtirtho.spotube.modules.library.album.LibraryAlbumsViewModel
import org.spotube.spotube.modules.library.artist.LibraryArtistsViewModel import dev.krtirtho.spotube.modules.library.artist.LibraryArtistsViewModel
import org.spotube.spotube.modules.library.local_tracks.LibraryLocalTracksViewModel import dev.krtirtho.spotube.modules.library.local_tracks.LibraryLocalTracksViewModel
import org.spotube.spotube.modules.library.local_tracks.media.LocalMediaCacheRepository import dev.krtirtho.spotube.modules.library.local_tracks.media.LocalMediaCacheRepository
import org.spotube.spotube.modules.library.local_tracks.media.LocalMediaFoldersConfig import dev.krtirtho.spotube.modules.library.local_tracks.media.LocalMediaFoldersConfig
import org.spotube.spotube.modules.library.local_tracks.media.LocalMediaLibraryCoordinator import dev.krtirtho.spotube.modules.library.local_tracks.media.LocalMediaLibraryCoordinator
import org.spotube.spotube.modules.library.playlist.LibraryPlaylistsViewModel import dev.krtirtho.spotube.modules.library.playlist.LibraryPlaylistsViewModel
import org.spotube.spotube.modules.lyrics.LyricsViewModel import dev.krtirtho.spotube.modules.lyrics.LyricsViewModel
import org.spotube.spotube.modules.playlist.PlaylistRepository import dev.krtirtho.spotube.modules.playlist.PlaylistRepository
import org.spotube.spotube.modules.playlist.PlaylistViewModel import dev.krtirtho.spotube.modules.playlist.PlaylistViewModel
import org.spotube.spotube.modules.plugin.AudioPluginSource import dev.krtirtho.spotube.modules.plugin.AudioPluginSource
import org.spotube.spotube.modules.plugin.PluginManager import dev.krtirtho.spotube.modules.plugin.PluginManager
import org.spotube.spotube.modules.plugin.PluginProvider import dev.krtirtho.spotube.modules.plugin.PluginProvider
import org.spotube.spotube.modules.plugin.PluginViewModel import dev.krtirtho.spotube.modules.plugin.PluginViewModel
import org.spotube.spotube.modules.plugin.guard.MetadataPluginGuardViewModel import dev.krtirtho.spotube.modules.plugin.guard.MetadataPluginGuardViewModel
import org.spotube.spotube.modules.plugin.ScrobblePluginSource import dev.krtirtho.spotube.modules.plugin.ScrobblePluginSource
import org.spotube.spotube.modules.saved_tracks.SavedTracksRepository import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksRepository
import org.spotube.spotube.modules.saved_tracks.SavedTracksViewModel import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksViewModel
import org.spotube.spotube.modules.search.SearchRepository import dev.krtirtho.spotube.modules.search.SearchRepository
import org.spotube.spotube.modules.search.SearchScreenViewModel import dev.krtirtho.spotube.modules.search.SearchScreenViewModel
import org.spotube.spotube.modules.update.AppUpdateService import dev.krtirtho.spotube.modules.update.AppUpdateService
import org.spotube.spotube.modules.update.PluginUpdateService import dev.krtirtho.spotube.modules.update.PluginUpdateService
import org.spotube.spotube.modules.settings.SettingsProvider import dev.krtirtho.spotube.modules.settings.SettingsProvider
import org.spotube.spotube.modules.settings.SettingsRepository import dev.krtirtho.spotube.modules.settings.SettingsRepository
import org.spotube.spotube.modules.settings.UserSettingsSource import dev.krtirtho.spotube.modules.settings.UserSettingsSource
import org.spotube.spotube.modules.settings.SettingsViewModel import dev.krtirtho.spotube.modules.settings.SettingsViewModel
import org.spotube.spotube.modules.settings.JamSettingsViewModel import dev.krtirtho.spotube.modules.settings.JamSettingsViewModel
import org.spotube.spotube.modules.settings.LocalMediaFoldersViewModel import dev.krtirtho.spotube.modules.settings.LocalMediaFoldersViewModel
import org.spotube.spotube.modules.shell.AppShellViewModel import dev.krtirtho.spotube.modules.shell.AppShellViewModel
import org.spotube.spotube.modules.shell.PlayerOptionsViewModel import dev.krtirtho.spotube.modules.shell.PlayerOptionsViewModel
import org.spotube.spotube.modules.shell.alternative_track.AlternativeTrackContentViewModel import dev.krtirtho.spotube.modules.shell.alternative_track.AlternativeTrackContentViewModel
import org.spotube.spotube.modules.shell.player_queue.PlayerQueueContentViewModel import dev.krtirtho.spotube.modules.shell.player_queue.PlayerQueueContentViewModel
import org.spotube.spotube.modules.welcome.WelcomeRepository import dev.krtirtho.spotube.modules.welcome.WelcomeRepository
import org.spotube.spotube.modules.welcome.WelcomeViewModel import dev.krtirtho.spotube.modules.welcome.WelcomeViewModel
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.core.module.dsl.bind import org.koin.core.module.dsl.bind
import org.koin.core.module.dsl.createdAtStart import org.koin.core.module.dsl.createdAtStart

View File

@ -15,12 +15,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.discord package dev.krtirtho.spotube.core.discord
import org.spotube.spotube.core.audioplayer.AudioPlayerInterface import dev.krtirtho.spotube.core.audioplayer.AudioPlayerInterface
import org.spotube.spotube.core.audioplayer.PlayerState import dev.krtirtho.spotube.core.audioplayer.PlayerState
import org.spotube.spotube.core.di.injectLogger import dev.krtirtho.spotube.core.di.injectLogger
import org.spotube.spotube.modules.settings.SettingsProvider import dev.krtirtho.spotube.modules.settings.SettingsProvider
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO import kotlinx.coroutines.IO
@ -202,7 +202,7 @@ class DiscordRpcService(
private data class DiscordRpcState( private data class DiscordRpcState(
val enabled: Boolean, val enabled: Boolean,
val playerState: PlayerState, val playerState: PlayerState,
val mediaItem: org.spotube.spotube.core.audioplayer.MediaItem?, val mediaItem: dev.krtirtho.spotube.core.audioplayer.MediaItem?,
val position: kotlin.time.Duration, val position: kotlin.time.Duration,
val duration: kotlin.time.Duration) val duration: kotlin.time.Duration)
} }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.discovery package dev.krtirtho.spotube.core.discovery
import com.appstractive.dnssd.DiscoveryEvent import com.appstractive.dnssd.DiscoveryEvent
import com.appstractive.dnssd.NetService import com.appstractive.dnssd.NetService

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.discovery package dev.krtirtho.spotube.core.discovery
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.extras package dev.krtirtho.spotube.core.extras
fun String.kebabToTitleCase(): String { fun String.kebabToTitleCase(): String {
return this.split("-").joinToString(" ") { it.replaceFirstChar { char -> char.uppercase() } } return this.split("-").joinToString(" ") { it.replaceFirstChar { char -> char.uppercase() } }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.i18n package dev.krtirtho.spotube.core.i18n
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
@ -23,7 +23,7 @@ import androidx.compose.runtime.ProvidedValue
import androidx.compose.runtime.key import androidx.compose.runtime.key
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import org.spotube.spotube.modules.settings.SupportedLanguages import dev.krtirtho.spotube.modules.settings.SupportedLanguages
/** /**
* Points the platform locale (which Compose resources resolve strings from) at [languageTag], * Points the platform locale (which Compose resources resolve strings from) at [languageTag],

View File

@ -15,11 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.jam package dev.krtirtho.spotube.core.jam
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import org.spotube.spotube.core.audioplayer.MediaItem import dev.krtirtho.spotube.core.audioplayer.MediaItem
import org.spotube.spotube.core.audioplayer.QueueEntry import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -168,7 +168,7 @@ data class JamMediaItem(
duration = kotlin.time.Duration.parse("${item.durationMs}ms"), duration = kotlin.time.Duration.parse("${item.durationMs}ms"),
coverURL = item.coverUrl, coverURL = item.coverUrl,
url = item.url, url = item.url,
protocol = org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol protocol = dev.krtirtho.plugin_interfaces.plugin_apis.audio.StreamProtocol
.valueOf(item.protocol.ifBlank { "PROGRESSIVE" })) .valueOf(item.protocol.ifBlank { "PROGRESSIVE" }))
} }
} }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.jam package dev.krtirtho.spotube.core.jam
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import com.ditchoom.buffer.Charset import com.ditchoom.buffer.Charset
@ -29,7 +29,7 @@ import com.ditchoom.mqtt.controlpacket.QualityOfService
import com.ditchoom.mqtt.controlpacket.TopicName import com.ditchoom.mqtt.controlpacket.TopicName
import com.ditchoom.mqtt.controlpacket.WillConfig import com.ditchoom.mqtt.controlpacket.WillConfig
import com.ditchoom.mqtt5.controlpacket.ConnectionRequest import com.ditchoom.mqtt5.controlpacket.ConnectionRequest
import org.spotube.spotube.modules.settings.JamBroker import dev.krtirtho.spotube.modules.settings.JamBroker
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.jam package dev.krtirtho.spotube.core.jam
import kotlin.random.Random import kotlin.random.Random

View File

@ -15,18 +15,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.jam package dev.krtirtho.spotube.core.jam
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol import dev.krtirtho.plugin_interfaces.plugin_apis.audio.StreamProtocol
import org.spotube.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist
import org.spotube.plugin_interfaces.plugin_apis.metadata.common.Thumbnail import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.Thumbnail
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import org.spotube.spotube.core.audioplayer.AudioPlayerInterface import dev.krtirtho.spotube.core.audioplayer.AudioPlayerInterface
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.PlayerState import dev.krtirtho.spotube.core.audioplayer.PlayerState
import org.spotube.spotube.core.audioplayer.QueueEntry import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import org.spotube.spotube.modules.settings.SettingsRepository import dev.krtirtho.spotube.modules.settings.SettingsRepository
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -481,7 +481,7 @@ class JamRoomService(
return configured.ifBlank { "$fallbackPrefix-${Random.nextInt(1000, 9999)}" } return configured.ifBlank { "$fallbackPrefix-${Random.nextInt(1000, 9999)}" }
} }
private fun newClientId(broker: org.spotube.spotube.modules.settings.JamBroker): String { private fun newClientId(broker: dev.krtirtho.spotube.modules.settings.JamBroker): String {
val suffix = buildString(6) { val suffix = buildString(6) {
val chars = "0123456789abcdef" val chars = "0123456789abcdef"
repeat(6) { append(chars[Random.nextInt(chars.length)]) } repeat(6) { append(chars[Random.nextInt(chars.length)]) }

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.navigation package dev.krtirtho.spotube.core.navigation
import androidx.compose.animation.AnimatedContentTransitionScope import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.ContentTransform import androidx.compose.animation.ContentTransform

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.navigation package dev.krtirtho.spotube.core.navigation
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow

View File

@ -15,27 +15,27 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.navigation package dev.krtirtho.spotube.core.navigation
import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.NavKey
import org.spotube.spotube.modules.album.AlbumScreen import dev.krtirtho.spotube.modules.album.AlbumScreen
import org.spotube.spotube.modules.artist.ArtistScreen import dev.krtirtho.spotube.modules.artist.ArtistScreen
import org.spotube.spotube.modules.blacklist.BlacklistScreen import dev.krtirtho.spotube.modules.blacklist.BlacklistScreen
import org.spotube.spotube.modules.devices.DevicesScreen import dev.krtirtho.spotube.modules.devices.DevicesScreen
import org.spotube.spotube.modules.devices.RemoteControlScreen import dev.krtirtho.spotube.modules.devices.RemoteControlScreen
import org.spotube.spotube.modules.jam.JamScreen import dev.krtirtho.spotube.modules.jam.JamScreen
import org.spotube.spotube.modules.home.HomeScreen import dev.krtirtho.spotube.modules.home.HomeScreen
import org.spotube.spotube.modules.library.LibraryScreen import dev.krtirtho.spotube.modules.library.LibraryScreen
import org.spotube.spotube.modules.lyrics.LyricsScreen import dev.krtirtho.spotube.modules.lyrics.LyricsScreen
import org.spotube.spotube.modules.playlist.PlaylistScreen import dev.krtirtho.spotube.modules.playlist.PlaylistScreen
import org.spotube.spotube.modules.plugin.PluginScreen import dev.krtirtho.spotube.modules.plugin.PluginScreen
import org.spotube.spotube.modules.plugin.guard.MetadataPluginGuard import dev.krtirtho.spotube.modules.plugin.guard.MetadataPluginGuard
import org.spotube.spotube.modules.saved_tracks.SAVED_TRACKS_COLLECTION_ID import dev.krtirtho.spotube.modules.saved_tracks.SAVED_TRACKS_COLLECTION_ID
import org.spotube.spotube.modules.saved_tracks.SavedTracksScreen import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksScreen
import org.spotube.spotube.modules.search.SearchScreen import dev.krtirtho.spotube.modules.search.SearchScreen
import org.spotube.spotube.modules.settings.SettingsScreen import dev.krtirtho.spotube.modules.settings.SettingsScreen
import org.spotube.spotube.modules.settings.JamSettingsScreen import dev.krtirtho.spotube.modules.settings.JamSettingsScreen
import org.spotube.spotube.modules.welcome.WelcomeScreen import dev.krtirtho.spotube.modules.welcome.WelcomeScreen
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel
import org.koin.core.annotation.KoinExperimentalAPI import org.koin.core.annotation.KoinExperimentalAPI

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.navigation package dev.krtirtho.spotube.core.navigation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
@ -34,7 +34,7 @@ import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.savedstate.compose.serialization.serializers.MutableStateSerializer import androidx.savedstate.compose.serialization.serializers.MutableStateSerializer
import androidx.savedstate.serialization.SavedStateConfiguration import androidx.savedstate.serialization.SavedStateConfiguration
import org.spotube.spotube.core.di.injectLogger import dev.krtirtho.spotube.core.di.injectLogger
import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic import kotlinx.serialization.modules.polymorphic

View File

@ -15,9 +15,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.newpipe package dev.krtirtho.spotube.core.newpipe
import org.spotube.plugin_interfaces.plugin_apis.audio.AudioStream import dev.krtirtho.plugin_interfaces.plugin_apis.audio.AudioStream
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.newpipe package dev.krtirtho.spotube.core.newpipe
enum class SearchKind { enum class SearchKind {
/** YouTube Music "Songs" catalogue. */ /** YouTube Music "Songs" catalogue. */

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.paths package dev.krtirtho.spotube.core.paths
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
expect class Paths() { expect class Paths() {

View File

@ -15,18 +15,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.playback package dev.krtirtho.spotube.core.playback
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.QueueCollectionEntry import dev.krtirtho.spotube.core.audioplayer.QueueCollectionEntry
import org.spotube.spotube.core.audioplayer.QueueEntry import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import org.spotube.spotube.modules.album.AlbumRepository import dev.krtirtho.spotube.modules.album.AlbumRepository
import org.spotube.spotube.modules.artist.ArtistRepository import dev.krtirtho.spotube.modules.artist.ArtistRepository
import org.spotube.spotube.modules.blacklist.BlacklistRepository import dev.krtirtho.spotube.modules.blacklist.BlacklistRepository
import org.spotube.spotube.modules.playlist.PlaylistRepository import dev.krtirtho.spotube.modules.playlist.PlaylistRepository
import org.spotube.spotube.modules.saved_tracks.SavedTracksRepository import dev.krtirtho.spotube.modules.saved_tracks.SavedTracksRepository
import org.spotube.spotube.core.remote.RemoteCollectionType import dev.krtirtho.spotube.core.remote.RemoteCollectionType
class CollectionPlaybackHelper( class CollectionPlaybackHelper(
private val albumRepository: AlbumRepository, private val albumRepository: AlbumRepository,

View File

@ -15,13 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.remote package dev.krtirtho.spotube.core.remote
import org.spotube.millennium.composables.MillenniumAlertDialog import org.spotube.millennium.composables.MillenniumAlertDialog
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import org.spotube.spotube.core.ui.theming.AppTheme import dev.krtirtho.spotube.core.ui.theming.AppTheme
import com.composeunstyled.Text import com.composeunstyled.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.remote package dev.krtirtho.spotube.core.remote
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import io.ktor.client.HttpClient import io.ktor.client.HttpClient

View File

@ -15,16 +15,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.remote package dev.krtirtho.spotube.core.remote
import org.spotube.spotube.core.audioplayer.AudioPlayerInterface import dev.krtirtho.spotube.core.audioplayer.AudioPlayerInterface
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.LoopState import dev.krtirtho.spotube.core.audioplayer.LoopState
import org.spotube.spotube.core.audioplayer.PlayerState as AudioPlayerState import dev.krtirtho.spotube.core.audioplayer.PlayerState as AudioPlayerState
import org.spotube.spotube.core.audioplayer.QueueEntry import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import org.spotube.spotube.core.di.injectLogger import dev.krtirtho.spotube.core.di.injectLogger
import org.spotube.spotube.core.playback.CollectionPlaybackHelper import dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper
import org.spotube.spotube.modules.settings.SettingsRepository import dev.krtirtho.spotube.modules.settings.SettingsRepository
import io.ktor.server.websocket.WebSocketServerSession import io.ktor.server.websocket.WebSocketServerSession
import io.ktor.websocket.CloseReason import io.ktor.websocket.CloseReason
import io.ktor.websocket.Frame import io.ktor.websocket.Frame

View File

@ -15,9 +15,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.remote package dev.krtirtho.spotube.core.remote
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -15,13 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.remote package dev.krtirtho.spotube.core.remote
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import com.appstractive.dnssd.NetService import com.appstractive.dnssd.NetService
import org.spotube.spotube.core.discovery.DeviceDiscoveryService import dev.krtirtho.spotube.core.discovery.DeviceDiscoveryService
import org.spotube.spotube.core.server.LocalServer import dev.krtirtho.spotube.core.server.LocalServer
import org.spotube.spotube.modules.settings.SettingsRepository import dev.krtirtho.spotube.modules.settings.SettingsRepository
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View File

@ -15,16 +15,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package org.spotube.spotube.core.remote package dev.krtirtho.spotube.core.remote
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import org.spotube.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
import org.spotube.spotube.core.audioplayer.AudioPlayerQueue import dev.krtirtho.spotube.core.audioplayer.AudioPlayerQueue
import org.spotube.spotube.core.audioplayer.QueueEntry import dev.krtirtho.spotube.core.audioplayer.QueueEntry
import org.spotube.spotube.core.jam.JamRole import dev.krtirtho.spotube.core.jam.JamRole
import org.spotube.spotube.core.jam.JamRoomService import dev.krtirtho.spotube.core.jam.JamRoomService
import org.spotube.spotube.core.playback.CollectionPlaybackHelper import dev.krtirtho.spotube.core.playback.CollectionPlaybackHelper
import org.spotube.spotube.modules.blacklist.BlacklistRepository import dev.krtirtho.spotube.modules.blacklist.BlacklistRepository
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob

Some files were not shown because too many files have changed in this diff Show More