diff --git a/README.md b/README.md index 6afc33878..5683764e2 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,122 @@ # Straw -A Sulkta fork of [NewPipe](https://github.com/TeamNewPipe/NewPipe). Android YouTube -client, Compose UI, Media3 player, with [SponsorBlock](https://sponsor.ajay.app/) -and [Return YouTube Dislike](https://returnyoutubedislike.com/) baked in. +A privacy-focused Android YouTube client. Compose UI, Media3 player, with +[SponsorBlock](https://sponsor.ajay.app/) auto-skip and +[Return YouTube Dislike](https://returnyoutubedislike.com/) baked in. No login, +no Google Play Services, no tracking — Straw talks to public web endpoints only. -The extractor is `strawcore`, a Rust port of NewPipeExtractor exposed to Kotlin -via UniFFI. No InnerTube/JS deobf code path lives on the JVM anymore. +Straw is a fork of [NewPipe](https://github.com/TeamNewPipe/NewPipe). The +extractor is **strawcore**, a Rust port of NewPipe's extraction logic exposed +to Kotlin via [UniFFI](https://mozilla.github.io/uniffi-rs/) — there's no +InnerTube/JS-deobfuscation code path on the JVM anymore. + +## Features + +- Search, video detail, channel pages, playlists +- Inline player + fullscreen + swipe-down minibar + background audio + PiP +- Media3 ExoPlayer (DASH / HLS / progressive / merged DASH chunks) +- SponsorBlock auto-skip, with per-category toggles +- Return YouTube Dislike on the video detail page +- RSS-based subscription feed (fast — about a second for 50 subscriptions) +- Hide-shorts / hide-paid / hide-age-restricted feed filters +- Resume positions, watch history, search history +- Local playlists; downloads (video + audio) +- Imports NewPipe-format settings (subscriptions + playlists + history) + +### Out of scope (on purpose) + +- Trending / algorithmic feeds — subscriptions only +- iOS / desktop targets — Android only for now +- Anything that needs Google Play Services or an account ## Install -F-Droid repo: - -Add the repo in your F-Droid client of choice, then install Straw. - -The app also self-updates from the same repo when an APK lands there with a -higher `versionCode`. - -## What's in - -- Search, video detail, channel pages, playlists -- Inline player + fullscreen + minibar + background audio + PiP -- Media3 ExoPlayer (DASH / HLS / progressive / merged DASH chunks) -- SponsorBlock auto-skip (categories user-toggleable) -- Return YouTube Dislike on video detail -- RSS-based subscription feed (fast — ~1s for 50 subs) -- Hide-shorts / hide-paid / hide-age-restricted feed filters -- Resume positions + watch history + search history -- Local playlists, downloads (video + audio) -- NewPipe-format settings import (subs + playlists + history) - -## What's out (on purpose) - -- Trending / algorithmic feeds. Subscriptions only. -- iOS / desktop targets. Android-only for now. -- Google Play Services anything. - -## Layout +Pre-built APKs are published to an F-Droid repository: ``` -strawApp/ Sulkta-authored app — Compose UI, Media3 wiring, SB + RYD clients -rust/ strawcore — UniFFI wrapper around the Rust extractor -shared/ KMP scaffold inherited from upstream NewPipe (unused for now) -app/ Upstream NewPipe :app module — kept for reference +https://fdroid.sulkta.com/fdroid/repo ``` +Add that repo to the F-Droid client of your choice and install **Straw**. The +app also self-updates from the same repo when a newer `versionCode` is +published. + +If you'd rather build it yourself, see **Build** below. + ## Build -``` -./gradlew :strawApp:assembleDebug -``` +Straw is a standard Gradle project with a Rust component (`strawcore`) compiled +for Android via `cargo-ndk` and bound to Kotlin with `uniffi-bindgen`. The +Gradle build drives both automatically. -Requires the Rust toolchain plus the four Android targets: +### Prerequisites -``` +- JDK 21 +- Android SDK with platform `android-36`, build-tools `36.0.0`, and NDK `r27` + (`ANDROID_NDK_HOME` must point at it) +- A Rust stable toolchain with the four Android targets, plus `cargo-ndk` and + `uniffi-bindgen`: + +```sh rustup target add aarch64-linux-android armv7-linux-androideabi \ x86_64-linux-android i686-linux-android cargo install cargo-ndk uniffi-bindgen ``` -…and `ANDROID_NDK_HOME` pointing at NDK r27c (or newer). The Gradle build runs -`cargo ndk` + `uniffi-bindgen` automatically. +### Assemble a debug APK + +```sh +./gradlew :strawApp:assembleDebug +``` + +The APK lands in `strawApp/build/outputs/apk/debug/`. + +### Reproducible build image + +`ci/Dockerfile` defines a self-contained image with the exact JDK + Android SDK ++ NDK + Rust toolchain the build expects, if you'd rather not install all of +that on your host: + +```sh +docker build -t straw-build ci/ +docker run --rm -v "$PWD":/src -w /src straw-build ./gradlew :strawApp:assembleDebug +``` + +## Project layout + +``` +strawApp/ The app — Compose UI, Media3 wiring, SponsorBlock + RYD clients +rust/ strawcore — the UniFFI wrapper crate around the Rust extractor +buildSrc/ Shared Gradle build logic and version constants +iosApp/ Empty iOS shell inherited from upstream (not built) +``` + +The actual extraction engine (`strawcore-core`) lives in a sibling repository, +[`strawcore`](https://git.sulkta.com/Sulkta-OSS/strawcore), and is pulled in as +a path/Git dependency by `rust/strawcore`. + +## Contributing + +Issues and pull requests are welcome. A few notes: + +- Keep changes scoped and described; the build runs lint/format checks. +- The app is Kotlin + Jetpack Compose; the extractor is Rust. Touch the layer + the change belongs in. +- By contributing you agree your work is licensed under GPL-3.0-or-later (see + **License**). ## License -GPL-3.0-or-later, inherited from upstream NewPipe. +GPL-3.0-or-later, inherited from upstream NewPipe. See [`LICENSE`](LICENSE). ## Upstream -This repo tracks . Upstream changes -get pulled periodically via the `upstream` remote. +Straw tracks [NewPipe](https://github.com/TeamNewPipe/NewPipe); upstream +improvements are pulled in periodically. The `app/` and `shared/` modules from +NewPipe were removed once Straw became its own app on the strawcore pipeline. ## Disclaimer -Not affiliated with YouTube, Google, NewPipe e.V., the SponsorBlock project, -or Return YouTube Dislike. Trademarks belong to their owners. Straw uses -public web endpoints; nothing here authenticates to any account. +Not affiliated with YouTube, Google, NewPipe e.V., the SponsorBlock project, or +Return YouTube Dislike. All trademarks belong to their respective owners. Straw +uses public web endpoints and does not authenticate to any account. diff --git a/ci/Dockerfile b/ci/Dockerfile new file mode 100644 index 000000000..b6a5773da --- /dev/null +++ b/ci/Dockerfile @@ -0,0 +1,59 @@ +# straw-build — reproducible Android + Rust build image for the Straw APK. +# +# A fully self-contained toolchain so a fresh build needs nothing on the host +# but Docker. Build it, then run the Gradle assemble inside it: +# +# docker build -t straw-build ci/ +# docker run --rm -v "$PWD":/src -w /src straw-build \ +# ./gradlew :strawApp:assembleDebug +# +# Toolchain pinned to what builds successfully: +# JDK 21 · NDK 27.2.12479018 · build-tools 34.0.0 + 36.0.0 · platforms android-36 +# Rust stable + 4 Android targets · cargo-ndk · clang/libclang (rquickjs bindgen) +# AGP (compileSdk 36) requires build-tools 36; we pre-install it so the build +# doesn't sdkmanager-download it on every run. 34.0.0 is kept as a fallback; +# apksigner uses the highest build-tools present (36). +FROM eclipse-temurin:21-jdk-jammy + +ENV DEBIAN_FRONTEND=noninteractive \ + ANDROID_SDK_ROOT=/opt/android-sdk \ + ANDROID_HOME=/opt/android-sdk \ + ANDROID_NDK_HOME=/opt/android-sdk/ndk/27.2.12479018 \ + CARGO_HOME=/opt/cargo \ + RUSTUP_HOME=/opt/rustup \ + PATH=/opt/cargo/bin:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools:/usr/bin:/bin + +# Base OS deps: clang/libclang for rquickjs bindgen, a C toolchain for the +# QuickJS C sources, unzip for the SDK zips, git+ca-certs for checkout. +RUN apt-get update && apt-get install -y --no-install-recommends \ + git curl unzip ca-certificates clang libclang-dev build-essential pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Android cmdline-tools + the SDK packages the build needs. +ARG CMDLINE_TOOLS_ZIP=commandlinetools-linux-11076708_latest.zip +RUN mkdir -p "$ANDROID_SDK_ROOT/cmdline-tools" \ + && curl -fsSL -o /tmp/cmdtools.zip "https://dl.google.com/android/repository/${CMDLINE_TOOLS_ZIP}" \ + && unzip -q /tmp/cmdtools.zip -d "$ANDROID_SDK_ROOT/cmdline-tools" \ + && mv "$ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools" "$ANDROID_SDK_ROOT/cmdline-tools/latest" \ + && rm /tmp/cmdtools.zip \ + && yes | sdkmanager --licenses >/dev/null 2>&1 \ + && sdkmanager --install \ + "platform-tools" \ + "platforms;android-36" \ + "build-tools;34.0.0" \ + "build-tools;36.0.0" \ + "ndk;27.2.12479018" >/dev/null \ + && rm -rf "$ANDROID_SDK_ROOT/.temp" /tmp/* + +# Rust toolchain + the four Android targets + cargo-ndk. +RUN curl -fsSL https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal \ + && rustup target add \ + aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android \ + && cargo install cargo-ndk --locked \ + && rm -rf /opt/cargo/registry/cache /opt/cargo/registry/src + +# Sanity: fail the image build early if anything's missing. +RUN java -version && cargo --version && cargo ndk --version || true \ + && test -d "$ANDROID_NDK_HOME" \ + && test -d "$ANDROID_SDK_ROOT/build-tools/34.0.0" \ + && test -d "$ANDROID_SDK_ROOT/build-tools/36.0.0"