diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..b34abfa11 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# +# SPDX-FileCopyrightText: 2025 NewPipe e.V. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +root = true + +[*.{kt,kts}] +ktlint_code_style = android_studio +# https://pinterest.github.io/ktlint/latest/rules/standard/#function-naming +ktlint_function_naming_ignore_when_annotated_with = Composable + +ktlint_standard_class-signature = disabled +ktlint_standard_function-expression-body = disabled +ktlint_standard_max-line-length = disabled +ktlint_standard_mixed-condition-operators = disabled +ktlint_standard_package-name = disabled +ktlint_standard_property-naming = disabled diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 686ae233a..069f003f4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -3,6 +3,19 @@ NewPipe contribution guidelines =============================== +## AI policy + +* Using generative AI to develop new features or making larger code changes is generally prohibited. Please refrain from contributions which are heavily depending on AI generated source code because they are usually lacking a fundamental understanding of the overall project structure and thus come with poor quality. However, you are allowed to use gen. AI if you + * are aware of the project structure, + * ensure that the generated code follows the project structure, + * fully understand the generated code, and + * review the generated code completely. +* Using AI to find the root cause of bugs and generating small fixes might be acceptable. However, gen. AI often does not fix the underlying problem but is trying to fix the symptoms. If you are using AI to fix bugs, ensure that the root cause is tackled. +* The use of AI to generate documentation is allowed. We ask you to thoroughly check the quality of generated documentation – wrong, misleading or uninformative documentation is useless and wastes the reader's time. Ensure that reasoning is documented. +* Using generative AI to write or fill in PR or issue templates is prohibited. Those texts are often lengthy and miss critical information. +* PRs and issues that do not follow this AI policy can be closed without further explanation. + + ## Crash reporting Report crashes through the **automated crash report system** of NewPipe. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 52897f1ac..60c94ad25 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -26,6 +26,8 @@ body: required: true - label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)." required: true + - label: "I have read and understood the [AI policy](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md#ai-policy). The content of this bug report is not generated by AI." + required: true - type: input id: app-version diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 31ef92c44..97a3e38b5 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -25,6 +25,8 @@ body: required: true - label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)." required: true + - label: "I have read and understood the [AI policy](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md#ai-policy). The content of this request is not generated by AI." + required: true - type: textarea diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 407c00a39..2af1556d4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,7 +2,7 @@ #### What is it? - [ ] Bugfix (user facing) -- [ ] Feature (user facing) +- [ ] Feature (user facing) ⚠️ **Your PR must target the [`refactor`](https://github.com/TeamNewPipe/NewPipe/tree/refactor) branch** - [ ] Codebase improvement (dev facing) - [ ] Meta improvement to the project (dev facing) @@ -32,3 +32,5 @@ The APK can be found by going to the "Checks" tab below the title. On the left p #### Due diligence - [ ] I read the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md). +- [ ] The proposed changes follow the [AI policy](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md#ai-policy). +- [ ] I tested the changes using an emulator or a physical device. diff --git a/.github/workflows/backport-pr.yml b/.github/workflows/backport-pr.yml new file mode 100644 index 000000000..1e3074064 --- /dev/null +++ b/.github/workflows/backport-pr.yml @@ -0,0 +1,48 @@ +name: Backport merged pull request +on: + issue_comment: + types: [created] +permissions: + contents: write # for comment creation on original PR + pull-requests: write +jobs: + backport: + name: Backport pull request + runs-on: ubuntu-latest + + # Only run when the comment starts with the `/backport` command on a PR and + # the commenter has write access to the repository. We do not want to allow + # everybody to trigger backports and create branches in our repository. + if: > + github.event.issue.pull_request && + startsWith(github.event.comment.body, '/backport ') && + ( + github.event.comment.author_association == 'OWNER' || + github.event.comment.author_association == 'COLLABORATOR' || + github.event.comment.author_association == 'MEMBER' + ) + steps: + - uses: actions/checkout@v6 + - name: Get backport metadata + # the target branch is the first argument after `/backport` + env: + COMMENT_BODY: ${{ github.event.comment.body }} + run: | + set -euo pipefail + body="$COMMENT_BODY" + + line=${body%%$'\n'*} # Get the first line + if [[ $line =~ ^/backport[[:space:]]+([^[:space:]]+) ]]; then + echo "BACKPORT_TARGET=${BASH_REMATCH[1]}" >> "$GITHUB_ENV" + else + echo "Usage: /backport " >&2 + exit 1 + fi + + - name: Create backport pull request + uses: korthout/backport-action@v4 + with: + add_labels: 'backport' + copy_labels_pattern: '.*' + label_pattern: '' + target_branches: ${{ env.BACKPORT_TARGET }} \ No newline at end of file diff --git a/.github/workflows/build-release-apk.yml b/.github/workflows/build-release-apk.yml index 0fad8e169..b558d90dd 100644 --- a/.github/workflows/build-release-apk.yml +++ b/.github/workflows/build-release-apk.yml @@ -7,11 +7,11 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: 'master' - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' @@ -32,7 +32,7 @@ jobs: mv app/build/outputs/apk/release/*.apk "app/build/outputs/apk/release/NewPipe_v$VERSION_NAME.apk" - name: "Upload APK" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: app path: app/build/outputs/apk/release/*.apk diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a184dd83d..cb8fbc12a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,8 +37,8 @@ jobs: contents: read steps: - - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v2 + - uses: actions/checkout@v6 + - uses: gradle/actions/wrapper-validation@v5 - name: create and checkout branch # push events already checked out the branch @@ -48,7 +48,7 @@ jobs: run: git checkout -B "$BRANCH" - name: set up JDK - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: 21 distribution: "temurin" @@ -58,7 +58,7 @@ jobs: run: ./gradlew assembleDebug lintDebug testDebugUnitTest --stacktrace -DskipFormatKtlint - name: Upload APK - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: app path: app/build/outputs/apk/debug/*.apk @@ -80,7 +80,7 @@ jobs: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Enable KVM run: | @@ -89,7 +89,7 @@ jobs: sudo udevadm trigger --name-match=kvm - name: set up JDK - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: 21 distribution: "temurin" @@ -104,7 +104,7 @@ jobs: script: ./gradlew connectedCheck --stacktrace - name: Upload test report when tests fail # because the printed out stacktrace (console) is too short, see also #7553 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 if: failure() with: name: android-test-report-api${{ matrix.api-level }} @@ -118,19 +118,19 @@ jobs: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: 21 distribution: "temurin" cache: 'gradle' - name: Cache SonarCloud packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar diff --git a/.github/workflows/image-minimizer.yml b/.github/workflows/image-minimizer.yml index d9241c33b..264a0ac6c 100644 --- a/.github/workflows/image-minimizer.yml +++ b/.github/workflows/image-minimizer.yml @@ -17,9 +17,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 16 @@ -27,7 +27,7 @@ jobs: run: npm i probe-image-size@7.2.3 --ignore-scripts - name: Minimize simple images - uses: actions/github-script@v7 + uses: actions/github-script@v8 timeout-minutes: 3 with: script: | diff --git a/.gitignore b/.gitignore index 1352b6917..49267a9f0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ captures/ *.iml *~ .weblate +.kotlin *.class app/debug/ app/release/ diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 38765476a..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,360 +0,0 @@ -import com.android.tools.profgen.ArtProfileKt -import com.android.tools.profgen.ArtProfileSerializer -import com.android.tools.profgen.DexFile - -plugins { - id "com.android.application" - id "kotlin-android" - id "kotlin-kapt" - id "kotlin-parcelize" - id "checkstyle" - id "org.sonarqube" version "4.0.0.2929" -} - -android { - compileSdk 36 - namespace 'org.schabi.newpipe' - - defaultConfig { - applicationId "org.schabi.newpipe" - resValue "string", "app_name", "NewPipe" - minSdk 21 - targetSdk 35 - if (System.properties.containsKey('versionCodeOverride')) { - versionCode System.getProperty('versionCodeOverride') as Integer - } else { - versionCode 1005 - } - versionName "0.28.0" - if (System.properties.containsKey('versionNameSuffix')) { - versionNameSuffix System.getProperty('versionNameSuffix') - } - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - javaCompileOptions { - annotationProcessorOptions { - arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] - } - } - } - - buildTypes { - debug { - debuggable true - - // suffix the app id and the app name with git branch name - def workingBranch = getGitWorkingBranch() - def normalizedWorkingBranch = workingBranch.replaceFirst("^[^A-Za-z]+", "").replaceAll("[^0-9A-Za-z]+", "") - if (normalizedWorkingBranch.isEmpty() || workingBranch == "master" || workingBranch == "dev") { - // default values when branch name could not be determined or is master or dev - applicationIdSuffix ".debug" - resValue "string", "app_name", "NewPipe Debug" - } else { - applicationIdSuffix ".debug." + normalizedWorkingBranch - resValue "string", "app_name", "NewPipe " + workingBranch - archivesBaseName = 'NewPipe_' + normalizedWorkingBranch - } - } - - release { - if (System.properties.containsKey('packageSuffix')) { - applicationIdSuffix System.getProperty('packageSuffix') - resValue "string", "app_name", "NewPipe " + System.getProperty('packageSuffix') - archivesBaseName = 'NewPipe_' + System.getProperty('packageSuffix') - } - minifyEnabled true - shrinkResources false // disabled to fix F-Droid's reproducible build - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - archivesBaseName = 'app' - } - } - - lint { - checkReleaseBuilds false - // Or, if you prefer, you can continue to check for errors in release builds, - // but continue the build even when errors are found: - abortOnError false - // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version - // 5.0, avoid using them in switch case statements"), which affects only library projects - disable 'NonConstantResourceId' - } - - compileOptions { - // Flag to enable support for the new language APIs - coreLibraryDesugaringEnabled true - - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - encoding 'utf-8' - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17 - } - - sourceSets { - androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) - } - - androidResources { - generateLocaleConfig = true - } - - buildFeatures { - viewBinding true - buildConfig true - } - - packagingOptions { - resources { - // remove two files which belong to jsoup - // no idea how they ended up in the META-INF dir... - excludes += ['META-INF/README.md', 'META-INF/CHANGES', - // 'COPYRIGHT' belongs to RxJava... - 'META-INF/COPYRIGHT'] - } - } -} - -ext { - checkstyleVersion = '10.12.1' - - androidxLifecycleVersion = '2.6.2' - androidxRoomVersion = '2.6.1' - androidxWorkVersion = '2.8.1' - - stateSaverVersion = '1.4.1' - exoPlayerVersion = '2.18.7' - googleAutoServiceVersion = '1.1.1' - groupieVersion = '2.10.1' - markwonVersion = '4.6.2' - - leakCanaryVersion = '2.12' - stethoVersion = '1.6.0' -} - -configurations { - checkstyle - ktlint -} - -checkstyle { - getConfigDirectory().set(rootProject.file("checkstyle")) - ignoreFailures false - showViolations true - toolVersion = checkstyleVersion -} - -tasks.register('runCheckstyle', Checkstyle) { - source 'src' - include '**/*.java' - exclude '**/gen/**' - exclude '**/R.java' - exclude '**/BuildConfig.java' - exclude 'main/java/us/shandian/giga/**' - - classpath = configurations.checkstyle - - showViolations true - - reports { - xml.getRequired().set(true) - html.getRequired().set(true) - } -} - -def outputDir = "${project.buildDir}/reports/ktlint/" -def inputFiles = project.fileTree(dir: "src", include: "**/*.kt") - -tasks.register('runKtlint', JavaExec) { - inputs.files(inputFiles) - outputs.dir(outputDir) - getMainClass().set("com.pinterest.ktlint.Main") - classpath = configurations.ktlint - args "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -tasks.register('formatKtlint', JavaExec) { - inputs.files(inputFiles) - outputs.dir(outputDir) - getMainClass().set("com.pinterest.ktlint.Main") - classpath = configurations.ktlint - args "-F", "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -afterEvaluate { - if (!System.properties.containsKey('skipFormatKtlint')) { - preDebugBuild.dependsOn formatKtlint - } - preDebugBuild.dependsOn runCheckstyle, runKtlint -} - -sonar { - properties { - property "sonar.projectKey", "TeamNewPipe_NewPipe" - property "sonar.organization", "teamnewpipe" - property "sonar.host.url", "https://sonarcloud.io" - } -} - -dependencies { -/** Desugaring **/ - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4' - -/** NewPipe libraries **/ - // You can use a local version by uncommenting a few lines in settings.gradle - // Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub - // name and the commit hash with the commit hash of the (pushed) commit you want to test - // This works thanks to JitPack: https://jitpack.io/ - implementation 'com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996' - // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with - // the corresponding commit hash, since JitPack sometimes deletes artifacts. - // If there’s already a git hash, just add more of it to the end (or remove a letter) - // to cause jitpack to regenerate the artifact. - implementation 'com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3' - implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' - -/** Checkstyle **/ - checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" - ktlint 'com.pinterest:ktlint:0.45.2' - -/** Kotlin **/ - implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" - -/** AndroidX **/ - implementation 'androidx.appcompat:appcompat:1.7.1' - implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.core:core-ktx:1.12.0' - implementation 'androidx.documentfile:documentfile:1.0.1' - implementation 'androidx.fragment:fragment-ktx:1.6.2' - implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}" - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}" - implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' - implementation 'androidx.media:media:1.7.0' - implementation 'androidx.preference:preference:1.2.1' - implementation 'androidx.recyclerview:recyclerview:1.3.2' - implementation "androidx.room:room-runtime:${androidxRoomVersion}" - implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" - kapt "androidx.room:room-compiler:${androidxRoomVersion}" - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - // Newer version specified to prevent accessibility regressions with RecyclerView, see: - // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 - implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02' - implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}" - implementation "androidx.work:work-rxjava3:${androidxWorkVersion}" - implementation 'com.google.android.material:material:1.11.0' - implementation "androidx.webkit:webkit:1.9.0" - -/** Third-party libraries **/ - // Instance state boilerplate elimination - implementation 'com.github.livefront:bridge:v2.0.2' - implementation "com.evernote:android-state:$stateSaverVersion" - kapt "com.evernote:android-state-processor:$stateSaverVersion" - - // HTML parser - implementation "org.jsoup:jsoup:1.17.2" - - // HTTP client - implementation "com.squareup.okhttp3:okhttp:4.12.0" - - // Media player - implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-dash:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-database:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-datasource:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-hls:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-ui:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:extension-mediasession:${exoPlayerVersion}" - - // Metadata generator for service descriptors - compileOnly "com.google.auto.service:auto-service-annotations:${googleAutoServiceVersion}" - kapt "com.google.auto.service:auto-service:${googleAutoServiceVersion}" - - // Manager for complex RecyclerView layouts - implementation "com.github.lisawray.groupie:groupie:${groupieVersion}" - implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}" - - // Image loading - //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! - implementation "com.squareup.picasso:picasso:2.8" - - // Markdown library for Android - implementation "io.noties.markwon:core:${markwonVersion}" - implementation "io.noties.markwon:linkify:${markwonVersion}" - - // Crash reporting - implementation "ch.acra:acra-core:5.11.3" - - // Properly restarting - implementation 'com.jakewharton:process-phoenix:2.1.2' - - // Reactive extensions for Java VM - implementation "io.reactivex.rxjava3:rxjava:3.1.8" - implementation "io.reactivex.rxjava3:rxandroid:3.0.2" - // RxJava binding APIs for Android UI widgets - implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0" - - // Date and time formatting - implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final" - -/** Debugging **/ - // Memory leak detection - debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}" - debugImplementation "com.squareup.leakcanary:plumber-android:${leakCanaryVersion}" - debugImplementation "com.squareup.leakcanary:leakcanary-android-core:${leakCanaryVersion}" - // Debug bridge for Android - debugImplementation "com.facebook.stetho:stetho:${stethoVersion}" - debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoVersion}" - -/** Testing **/ - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.mockito:mockito-core:5.6.0' - - androidTestImplementation "androidx.test.ext:junit:1.1.5" - androidTestImplementation "androidx.test:runner:1.5.2" - androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}" - androidTestImplementation "org.assertj:assertj-core:3.24.2" -} - -static String getGitWorkingBranch() { - try { - def gitProcess = "git rev-parse --abbrev-ref HEAD".execute() - gitProcess.waitFor() - if (gitProcess.exitValue() == 0) { - return gitProcess.text.trim() - } else { - // not a git repository - return "" - } - } catch (IOException ignored) { - // git was not found - return "" - } -} - -// fix reproducible builds -project.afterEvaluate { - tasks.compileReleaseArtProfile.doLast { - outputs.files.each { file -> - if (file.toString().endsWith(".profm")) { - println("Sorting ${file} ...") - def version = ArtProfileSerializer.valueOf("METADATA_0_0_2") - def profile = ArtProfileKt.ArtProfile(file) - def keys = new ArrayList(profile.profileData.keySet()) - def sortedData = new LinkedHashMap() - Collections.sort keys, new DexFile.Companion() - keys.each { key -> sortedData[key] = profile.profileData[key] } - new FileOutputStream(file).with { - write(version.magicBytes$profgen) - write(version.versionBytes$profgen) - version.write$profgen(it, sortedData, "") - } - } - } - } -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..62afd8522 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,313 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.jetbrains.kotlin.kapt) + alias(libs.plugins.google.ksp) + alias(libs.plugins.jetbrains.kotlin.parcelize) + alias(libs.plugins.sonarqube) + checkstyle +} + +val gitWorkingBranch = providers.exec { + commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") +}.standardOutput.asText.map { it.trim() } + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +kotlin { + compilerOptions { + // TODO: Drop annotation default target when it is stable + freeCompilerArgs.addAll( + "-Xannotation-default-target=param-property" + ) + } +} + +android { + compileSdk = 36 + namespace = "org.schabi.newpipe" + + defaultConfig { + applicationId = "org.schabi.newpipe" + resValue("string", "app_name", "NewPipe") + minSdk = 21 + targetSdk = 35 + + versionCode = System.getProperty("versionCodeOverride")?.toInt() ?: 1007 + + versionName = "0.28.2" + System.getProperty("versionNameSuffix")?.let { versionNameSuffix = it } + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + debug { + isDebuggable = true + + // suffix the app id and the app name with git branch name + val defaultBranches = listOf("master", "dev") + val workingBranch = gitWorkingBranch.getOrElse("") + val normalizedWorkingBranch = workingBranch + .replaceFirst("^[^A-Za-z]+".toRegex(), "") + .replace("[^0-9A-Za-z]+".toRegex(), "") + + if (normalizedWorkingBranch.isEmpty() || workingBranch in defaultBranches) { + // default values when branch name could not be determined or is master or dev + applicationIdSuffix = ".debug" + resValue("string", "app_name", "NewPipe Debug") + } else { + applicationIdSuffix = ".debug.$normalizedWorkingBranch" + resValue("string", "app_name", "NewPipe $workingBranch") + } + } + + release { + System.getProperty("packageSuffix")?.let { suffix -> + applicationIdSuffix = suffix + resValue("string", "app_name", "NewPipe $suffix") + } + isMinifyEnabled = true + isShrinkResources = false // disabled to fix F-Droid"s reproducible build + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + } + + lint { + checkReleaseBuilds = false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError = false + // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version + // 5.0, avoid using them in switch case statements"), which affects only library projects + disable += "NonConstantResourceId" + } + + compileOptions { + // Flag to enable support for the new language APIs + isCoreLibraryDesugaringEnabled = true + encoding = "utf-8" + } + + sourceSets { + getByName("androidTest") { + assets.srcDir("$projectDir/schemas") + } + } + + androidResources { + generateLocaleConfig = true + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + packaging { + resources { + // remove two files which belong to jsoup + // no idea how they ended up in the META-INF dir... + excludes += setOf( + "META-INF/README.md", + "META-INF/CHANGES", + "META-INF/COPYRIGHT" // "COPYRIGHT" belongs to RxJava... + ) + } + } +} + +ksp { + arg("room.schemaLocation", "$projectDir/schemas") +} + + +// Custom dependency configuration for ktlint +val ktlint by configurations.creating + +// https://checkstyle.org/#JRE_and_JDK +tasks.withType().configureEach { + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(21) + } +} + +checkstyle { + configDirectory = rootProject.file("checkstyle") + isIgnoreFailures = false + isShowViolations = true + toolVersion = libs.versions.checkstyle.get() +} + +tasks.register("runCheckstyle") { + source("src") + include("**/*.java") + exclude("**/gen/**") + exclude("**/R.java") + exclude("**/BuildConfig.java") + exclude("main/java/us/shandian/giga/**") + + classpath = configurations.getByName("checkstyle") + + isShowViolations = true + + reports { + xml.required = true + html.required = true + } +} + +val outputDir = project.layout.buildDirectory.dir("reports/ktlint/") +val inputFiles = fileTree("src") { include("**/*.kt") } + +tasks.register("runKtlint") { + inputs.files(inputFiles) + outputs.dir(outputDir) + mainClass.set("com.pinterest.ktlint.Main") + classpath = configurations.getByName("ktlint") + args = listOf("--editorconfig=../.editorconfig", "src/**/*.kt") + jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED") +} + +tasks.register("formatKtlint") { + inputs.files(inputFiles) + outputs.dir(outputDir) + mainClass.set("com.pinterest.ktlint.Main") + classpath = configurations.getByName("ktlint") + args = listOf("--editorconfig=../.editorconfig", "-F", "src/**/*.kt") + jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED") +} + +tasks.register("checkDependenciesOrder") { + tomlFile = layout.projectDirectory.file("../gradle/libs.versions.toml") +} + +afterEvaluate { + tasks.named("preDebugBuild").configure { + if (!System.getProperties().containsKey("skipFormatKtlint")) { + dependsOn("formatKtlint") + } + dependsOn("runCheckstyle", "runKtlint", "checkDependenciesOrder") + } +} + +sonar { + properties { + property("sonar.projectKey", "TeamNewPipe_NewPipe") + property("sonar.organization", "teamnewpipe") + property("sonar.host.url", "https://sonarcloud.io") + } +} + +dependencies { + /** Desugaring **/ + coreLibraryDesugaring(libs.android.desugar) + + /** NewPipe libraries **/ + implementation(libs.newpipe.nanojson) + implementation(libs.newpipe.extractor) + implementation(libs.newpipe.filepicker) + + /** Checkstyle **/ + checkstyle(libs.puppycrawl.checkstyle) + ktlint(libs.pinterest.ktlint) + + /** AndroidX **/ + implementation(libs.androidx.appcompat) + implementation(libs.androidx.cardview) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.core) + implementation(libs.androidx.documentfile) + implementation(libs.androidx.fragment) + implementation(libs.androidx.lifecycle.livedata) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.localbroadcastmanager) + implementation(libs.androidx.media) + implementation(libs.androidx.preference) + implementation(libs.androidx.recyclerview) + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.rxjava3) + ksp(libs.androidx.room.compiler) + implementation(libs.androidx.swiperefreshlayout) + implementation(libs.androidx.viewpager2) + implementation(libs.androidx.work.runtime) + implementation(libs.androidx.work.rxjava3) + implementation(libs.google.android.material) + implementation(libs.androidx.webkit) + + /** Third-party libraries **/ + implementation(libs.livefront.bridge) + implementation(libs.evernote.statesaver.core) + kapt(libs.evernote.statesaver.compiler) + + // HTML parser + implementation(libs.jsoup) + + // HTTP client + implementation(libs.squareup.okhttp) + + // Media player + implementation(libs.google.exoplayer.core) + implementation(libs.google.exoplayer.dash) + implementation(libs.google.exoplayer.database) + implementation(libs.google.exoplayer.datasource) + implementation(libs.google.exoplayer.hls) + implementation(libs.google.exoplayer.mediasession) + implementation(libs.google.exoplayer.smoothstreaming) + implementation(libs.google.exoplayer.ui) + + // Manager for complex RecyclerView layouts + implementation(libs.lisawray.groupie.core) + implementation(libs.lisawray.groupie.viewbinding) + + // Image loading + implementation(libs.squareup.picasso) + + // Markdown library for Android + implementation(libs.noties.markwon.core) + implementation(libs.noties.markwon.linkify) + + // Crash reporting + implementation(libs.acra.core) + compileOnly(libs.google.autoservice.annotations) + ksp(libs.zacsweers.autoservice.compiler) + + // Properly restarting + implementation(libs.jakewharton.phoenix) + + // Reactive extensions for Java VM + implementation(libs.reactivex.rxjava) + implementation(libs.reactivex.rxandroid) + // RxJava binding APIs for Android UI widgets + implementation(libs.jakewharton.rxbinding) + + // Date and time formatting + implementation(libs.ocpsoft.prettytime) + + /** Debugging **/ + // Memory leak detection + debugImplementation(libs.squareup.leakcanary.watcher) + debugImplementation(libs.squareup.leakcanary.plumber) + debugImplementation(libs.squareup.leakcanary.core) + // Debug bridge for Android + debugImplementation(libs.facebook.stetho.core) + debugImplementation(libs.facebook.stetho.okhttp3) + + /** Testing **/ + testImplementation(libs.junit) + testImplementation(libs.mockito.core) + + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.runner) + androidTestImplementation(libs.androidx.room.testing) + androidTestImplementation(libs.assertj.core) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 0cdffbe2e..8bcef3fbd 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -16,6 +16,11 @@ -dontwarn javax.script.** -keep class jdk.dynalink.** { *; } -dontwarn jdk.dynalink.** +# Rules for jsoup +# Ignore intended-to-be-optional re2j classes - only needed if using re2j for jsoup regex +# jsoup safely falls back to JDK regex if re2j not on classpath, but has concrete re2j refs +# See https://github.com/jhy/jsoup/issues/2459 - may be resolved in future, then this may be removed +-dontwarn com.google.re2j.** ## Rules for ExoPlayer -keep class com.google.android.exoplayer2.** { *; } diff --git a/app/schemas/org.schabi.newpipe.database.AppDatabase/9.json b/app/schemas/org.schabi.newpipe.database.AppDatabase/9.json index aced06c0a..b9a618638 100644 --- a/app/schemas/org.schabi.newpipe.database.AppDatabase/9.json +++ b/app/schemas/org.schabi.newpipe.database.AppDatabase/9.json @@ -458,7 +458,7 @@ "notNull": true }, { - "fieldPath": "name", + "fieldPath": "orderingName", "columnName": "name", "affinity": "TEXT", "notNull": false diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt index a34cfece6..fd551b7b8 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt @@ -129,7 +129,7 @@ class DatabaseMigrationTest { ) val migratedDatabaseV3 = getMigratedDatabase() - val listFromDB = migratedDatabaseV3.streamDAO().all.blockingFirst() + val listFromDB = migratedDatabaseV3.streamDAO().getAll().blockingFirst() // Only expect 2, the one with the null url will be ignored assertEquals(2, listFromDB.size) @@ -176,28 +176,32 @@ class DatabaseMigrationTest { databaseInV7.run { insert( - "search_history", SQLiteDatabase.CONFLICT_FAIL, + "search_history", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("service_id", serviceId) put("search", defaultSearch1) } ) insert( - "search_history", SQLiteDatabase.CONFLICT_FAIL, + "search_history", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("service_id", serviceId) put("search", defaultSearch2) } ) insert( - "search_history", SQLiteDatabase.CONFLICT_FAIL, + "search_history", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("service_id", otherServiceId) put("search", defaultSearch1) } ) insert( - "search_history", SQLiteDatabase.CONFLICT_FAIL, + "search_history", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("service_id", otherServiceId) put("search", defaultSearch2) @@ -207,17 +211,21 @@ class DatabaseMigrationTest { } testHelper.runMigrationsAndValidate( - AppDatabase.DATABASE_NAME, Migrations.DB_VER_8, - true, Migrations.MIGRATION_7_8 + AppDatabase.DATABASE_NAME, + Migrations.DB_VER_8, + true, + Migrations.MIGRATION_7_8 ) testHelper.runMigrationsAndValidate( - AppDatabase.DATABASE_NAME, Migrations.DB_VER_9, - true, Migrations.MIGRATION_8_9 + AppDatabase.DATABASE_NAME, + Migrations.DB_VER_9, + true, + Migrations.MIGRATION_8_9 ) val migratedDatabaseV8 = getMigratedDatabase() - val listFromDB = migratedDatabaseV8.searchHistoryDAO().all.blockingFirst() + val listFromDB = migratedDatabaseV8.searchHistoryDAO().getAll().blockingFirst() assertEquals(2, listFromDB.size) assertEquals("abc", listFromDB[0].search) @@ -235,7 +243,8 @@ class DatabaseMigrationTest { val remoteUid2: Long databaseInV8.run { localUid1 = insert( - "playlists", SQLiteDatabase.CONFLICT_FAIL, + "playlists", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("name", DEFAULT_NAME + "1") put("is_thumbnail_permanent", false) @@ -243,7 +252,8 @@ class DatabaseMigrationTest { } ) localUid2 = insert( - "playlists", SQLiteDatabase.CONFLICT_FAIL, + "playlists", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("name", DEFAULT_NAME + "2") put("is_thumbnail_permanent", false) @@ -251,25 +261,29 @@ class DatabaseMigrationTest { } ) delete( - "playlists", "uid = ?", + "playlists", + "uid = ?", Array(1) { localUid1 } ) remoteUid1 = insert( - "remote_playlists", SQLiteDatabase.CONFLICT_FAIL, + "remote_playlists", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("service_id", DEFAULT_SERVICE_ID) put("url", DEFAULT_URL) } ) remoteUid2 = insert( - "remote_playlists", SQLiteDatabase.CONFLICT_FAIL, + "remote_playlists", + SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { put("service_id", DEFAULT_SECOND_SERVICE_ID) put("url", DEFAULT_SECOND_URL) } ) delete( - "remote_playlists", "uid = ?", + "remote_playlists", + "uid = ?", Array(1) { remoteUid2 } ) close() @@ -283,8 +297,8 @@ class DatabaseMigrationTest { ) val migratedDatabaseV9 = getMigratedDatabase() - var localListFromDB = migratedDatabaseV9.playlistDAO().all.blockingFirst() - var remoteListFromDB = migratedDatabaseV9.playlistRemoteDAO().all.blockingFirst() + var localListFromDB = migratedDatabaseV9.playlistDAO().getAll().blockingFirst() + var remoteListFromDB = migratedDatabaseV9.playlistRemoteDAO().getAll().blockingFirst() assertEquals(1, localListFromDB.size) assertEquals(localUid2, localListFromDB[0].uid) @@ -294,17 +308,27 @@ class DatabaseMigrationTest { assertEquals(-1, remoteListFromDB[0].displayIndex) val localUid3 = migratedDatabaseV9.playlistDAO().insert( - PlaylistEntity(DEFAULT_NAME + "3", false, -1, -1) + PlaylistEntity( + name = "${DEFAULT_NAME}3", + isThumbnailPermanent = false, + thumbnailStreamId = -1, + displayIndex = -1 + ) ) val remoteUid3 = migratedDatabaseV9.playlistRemoteDAO().insert( PlaylistRemoteEntity( - DEFAULT_THIRD_SERVICE_ID, DEFAULT_NAME, DEFAULT_THIRD_URL, - DEFAULT_THUMBNAIL, DEFAULT_UPLOADER_NAME, -1, 10 + serviceId = DEFAULT_THIRD_SERVICE_ID, + orderingName = DEFAULT_NAME, + url = DEFAULT_THIRD_URL, + thumbnailUrl = DEFAULT_THUMBNAIL, + uploader = DEFAULT_UPLOADER_NAME, + displayIndex = -1, + streamCount = 10 ) ) - localListFromDB = migratedDatabaseV9.playlistDAO().all.blockingFirst() - remoteListFromDB = migratedDatabaseV9.playlistRemoteDAO().all.blockingFirst() + localListFromDB = migratedDatabaseV9.playlistDAO().getAll().blockingFirst() + remoteListFromDB = migratedDatabaseV9.playlistRemoteDAO().getAll().blockingFirst() assertEquals(2, localListFromDB.size) assertEquals(localUid3, localListFromDB[1].uid) assertEquals(-1, localListFromDB[1].displayIndex) diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt index 893ae82b7..a61caad06 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt @@ -4,6 +4,8 @@ import android.content.Context import androidx.room.Room import androidx.test.core.app.ApplicationProvider import io.reactivex.rxjava3.core.Single +import java.io.IOException +import java.time.OffsetDateTime import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull @@ -20,9 +22,6 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity import org.schabi.newpipe.extractor.ServiceList import org.schabi.newpipe.extractor.channel.ChannelInfo import org.schabi.newpipe.extractor.stream.StreamType -import java.io.IOException -import java.time.OffsetDateTime -import kotlin.streams.toList class FeedDAOTest { private lateinit var db: AppDatabase @@ -41,14 +40,21 @@ class FeedDAOTest { private val stream7 = StreamEntity(7, serviceId, "https://youtube.com/watch?v=7", "stream 7", StreamType.VIDEO_STREAM, 1000, "channel-4", "https://youtube.com/channel/4", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-10", OffsetDateTime.parse("2023-08-10T00:00:00Z")) private val allStreams = listOf( - stream1, stream2, stream3, stream4, stream5, stream6, stream7 + stream1, + stream2, + stream3, + stream4, + stream5, + stream6, + stream7 ) @Before fun createDb() { val context = ApplicationProvider.getApplicationContext() db = Room.inMemoryDatabaseBuilder( - context, AppDatabase::class.java + context, + AppDatabase::class.java ).build() feedDAO = db.feedDAO() streamDAO = db.streamDAO() @@ -65,7 +71,10 @@ class FeedDAOTest { fun testUnlinkStreamsOlderThan_KeepOne() { setupUnlinkDelete("2023-08-15T00:00:00Z") val streams = feedDAO.getStreams( - FeedGroupEntity.GROUP_ALL_ID, includePlayed = true, includePartiallyPlayed = true, null + FeedGroupEntity.GROUP_ALL_ID, + includePlayed = true, + includePartiallyPlayed = true, + null ) .blockingGet() val allowedStreams = listOf(stream3, stream5, stream6, stream7) @@ -76,7 +85,10 @@ class FeedDAOTest { fun testUnlinkStreamsOlderThan_KeepMultiple() { setupUnlinkDelete("2023-08-01T00:00:00Z") val streams = feedDAO.getStreams( - FeedGroupEntity.GROUP_ALL_ID, includePlayed = true, includePartiallyPlayed = true, null + FeedGroupEntity.GROUP_ALL_ID, + includePlayed = true, + includePartiallyPlayed = true, + null ) .blockingGet() val allowedStreams = listOf(stream3, stream4, stream5, stream6, stream7) @@ -112,7 +124,7 @@ class FeedDAOTest { SubscriptionEntity.from(ChannelInfo(serviceId, "1", "https://youtube.com/channel/1", "https://youtube.com/channel/1", "channel-1")), SubscriptionEntity.from(ChannelInfo(serviceId, "2", "https://youtube.com/channel/2", "https://youtube.com/channel/2", "channel-2")), SubscriptionEntity.from(ChannelInfo(serviceId, "3", "https://youtube.com/channel/3", "https://youtube.com/channel/3", "channel-3")), - SubscriptionEntity.from(ChannelInfo(serviceId, "4", "https://youtube.com/channel/4", "https://youtube.com/channel/4", "channel-4")), + SubscriptionEntity.from(ChannelInfo(serviceId, "4", "https://youtube.com/channel/4", "https://youtube.com/channel/4", "channel-4")) ) ) feedDAO.insertAll( @@ -123,7 +135,7 @@ class FeedDAOTest { FeedEntity(4, 2), FeedEntity(5, 2), FeedEntity(6, 3), - FeedEntity(7, 4), + FeedEntity(7, 4) ) ) } diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt index 24be0f868..32fb08db0 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/local/history/HistoryRecordManagerTest.kt @@ -1,6 +1,9 @@ package org.schabi.newpipe.local.history import androidx.test.core.app.ApplicationProvider +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.time.ZoneOffset import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Assert.assertEquals @@ -11,9 +14,6 @@ import org.schabi.newpipe.database.AppDatabase import org.schabi.newpipe.database.history.model.SearchHistoryEntry import org.schabi.newpipe.testUtil.TestDatabase import org.schabi.newpipe.testUtil.TrampolineSchedulerRule -import java.time.LocalDateTime -import java.time.OffsetDateTime -import java.time.ZoneOffset class HistoryRecordManagerTest { @@ -41,7 +41,7 @@ class HistoryRecordManagerTest { // For some reason the Flowable returned by getAll() never completes, so we can't assert // that the number of Lists it returns is exactly 1, we can only check if the first List is // correct. Why on earth has a Flowable been used instead of a Single for getAll()?!? - val entities = database.searchHistoryDAO().all.blockingFirst() + val entities = database.searchHistoryDAO().getAll().blockingFirst() assertThat(entities).hasSize(1) assertThat(entities[0].id).isEqualTo(1) assertThat(entities[0].serviceId).isEqualTo(0) @@ -51,54 +51,53 @@ class HistoryRecordManagerTest { @Test fun deleteSearchHistory() { val entries = listOf( - SearchHistoryEntry(time.minusSeconds(1), 0, "A"), - SearchHistoryEntry(time.minusSeconds(2), 2, "A"), - SearchHistoryEntry(time.minusSeconds(3), 1, "B"), - SearchHistoryEntry(time.minusSeconds(4), 0, "B"), + SearchHistoryEntry(creationDate = time.minusSeconds(1), serviceId = 0, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(2), serviceId = 2, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(3), serviceId = 1, search = "B"), + SearchHistoryEntry(creationDate = time.minusSeconds(4), serviceId = 0, search = "B") ) // make sure all 4 were inserted database.searchHistoryDAO().insertAll(entries) - assertThat(database.searchHistoryDAO().all.blockingFirst()).hasSameSizeAs(entries) + assertThat(database.searchHistoryDAO().getAll().blockingFirst()).hasSameSizeAs(entries) // try to delete only "A" entries, "B" entries should be untouched manager.deleteSearchHistory("A").test().await().assertValue(2) - val entities = database.searchHistoryDAO().all.blockingFirst() + val entities = database.searchHistoryDAO().getAll().blockingFirst() assertThat(entities).hasSize(2) assertThat(entities).usingElementComparator { o1, o2 -> if (o1.hasEqualValues(o2)) 0 else 1 } .containsExactly(*entries.subList(2, 4).toTypedArray()) // assert that nothing happens if we delete a search query that does exist in the db manager.deleteSearchHistory("A").test().await().assertValue(0) - val entities2 = database.searchHistoryDAO().all.blockingFirst() + val entities2 = database.searchHistoryDAO().getAll().blockingFirst() assertThat(entities2).hasSize(2) assertThat(entities2).usingElementComparator { o1, o2 -> if (o1.hasEqualValues(o2)) 0 else 1 } .containsExactly(*entries.subList(2, 4).toTypedArray()) // delete all remaining entries manager.deleteSearchHistory("B").test().await().assertValue(2) - assertThat(database.searchHistoryDAO().all.blockingFirst()).isEmpty() + assertThat(database.searchHistoryDAO().getAll().blockingFirst()).isEmpty() } @Test fun deleteCompleteSearchHistory() { val entries = listOf( - SearchHistoryEntry(time.minusSeconds(1), 1, "A"), - SearchHistoryEntry(time.minusSeconds(2), 2, "B"), - SearchHistoryEntry(time.minusSeconds(3), 0, "C"), + SearchHistoryEntry(creationDate = time.minusSeconds(1), serviceId = 1, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(2), serviceId = 2, search = "B"), + SearchHistoryEntry(creationDate = time.minusSeconds(3), serviceId = 0, search = "C") ) // make sure all 3 were inserted database.searchHistoryDAO().insertAll(entries) - assertThat(database.searchHistoryDAO().all.blockingFirst()).hasSameSizeAs(entries) + assertThat(database.searchHistoryDAO().getAll().blockingFirst()).hasSameSizeAs(entries) // should remove everything manager.deleteCompleteSearchHistory().test().await().assertValue(entries.size) - assertThat(database.searchHistoryDAO().all.blockingFirst()).isEmpty() + assertThat(database.searchHistoryDAO().getAll().blockingFirst()).isEmpty() } private fun insertShuffledRelatedSearches(relatedSearches: Collection) { - // shuffle to make sure the order of items returned by queries depends only on // SearchHistoryEntry.creationDate, not on the actual insertion time, so that we can // verify that the `ORDER BY` clause does its job @@ -107,7 +106,7 @@ class HistoryRecordManagerTest { // make sure all entries were inserted assertEquals( relatedSearches.size, - database.searchHistoryDAO().all.blockingFirst().size + database.searchHistoryDAO().getAll().blockingFirst().size ) } @@ -121,25 +120,24 @@ class HistoryRecordManagerTest { RELATED_SEARCHES_ENTRIES[6].search, // A (even if in two places) RELATED_SEARCHES_ENTRIES[4].search, // B RELATED_SEARCHES_ENTRIES[5].search, // AA - RELATED_SEARCHES_ENTRIES[2].search, // BA + RELATED_SEARCHES_ENTRIES[2].search // BA ) } @Test fun getRelatedSearches_emptyQuery_manyDuplicates() { - insertShuffledRelatedSearches( - listOf( - SearchHistoryEntry(time.minusSeconds(9), 3, "A"), - SearchHistoryEntry(time.minusSeconds(8), 3, "AB"), - SearchHistoryEntry(time.minusSeconds(7), 3, "A"), - SearchHistoryEntry(time.minusSeconds(6), 3, "A"), - SearchHistoryEntry(time.minusSeconds(5), 3, "BA"), - SearchHistoryEntry(time.minusSeconds(4), 3, "A"), - SearchHistoryEntry(time.minusSeconds(3), 3, "A"), - SearchHistoryEntry(time.minusSeconds(2), 0, "A"), - SearchHistoryEntry(time.minusSeconds(1), 2, "AA"), - ) + val relatedSearches = listOf( + SearchHistoryEntry(creationDate = time.minusSeconds(9), serviceId = 3, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(8), serviceId = 3, search = "AB"), + SearchHistoryEntry(creationDate = time.minusSeconds(7), serviceId = 3, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(6), serviceId = 3, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(5), serviceId = 3, search = "BA"), + SearchHistoryEntry(creationDate = time.minusSeconds(4), serviceId = 3, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(3), serviceId = 3, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(2), serviceId = 0, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(1), serviceId = 2, search = "AA") ) + insertShuffledRelatedSearches(relatedSearches) val searches = manager.getRelatedSearches("", 9, 3).blockingFirst() assertThat(searches).containsExactly("AA", "A", "BA") @@ -154,7 +152,7 @@ class HistoryRecordManagerTest { assertThat(searches).containsExactly( RELATED_SEARCHES_ENTRIES[6].search, // A (even if in two places) RELATED_SEARCHES_ENTRIES[5].search, // AA - RELATED_SEARCHES_ENTRIES[1].search, // BA + RELATED_SEARCHES_ENTRIES[1].search // BA ) // also make sure that the string comparison is case insensitive @@ -166,13 +164,13 @@ class HistoryRecordManagerTest { private val time = OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 1, 1), ZoneOffset.UTC) private val RELATED_SEARCHES_ENTRIES = listOf( - SearchHistoryEntry(time.minusSeconds(7), 2, "AC"), - SearchHistoryEntry(time.minusSeconds(6), 0, "ABC"), - SearchHistoryEntry(time.minusSeconds(5), 1, "BA"), - SearchHistoryEntry(time.minusSeconds(4), 3, "A"), - SearchHistoryEntry(time.minusSeconds(2), 0, "B"), - SearchHistoryEntry(time.minusSeconds(3), 2, "AA"), - SearchHistoryEntry(time.minusSeconds(1), 1, "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(7), serviceId = 2, search = "AC"), + SearchHistoryEntry(creationDate = time.minusSeconds(6), serviceId = 0, search = "ABC"), + SearchHistoryEntry(creationDate = time.minusSeconds(5), serviceId = 1, search = "BA"), + SearchHistoryEntry(creationDate = time.minusSeconds(4), serviceId = 3, search = "A"), + SearchHistoryEntry(creationDate = time.minusSeconds(2), serviceId = 0, search = "B"), + SearchHistoryEntry(creationDate = time.minusSeconds(3), serviceId = 2, search = "AA"), + SearchHistoryEntry(creationDate = time.minusSeconds(1), serviceId = 1, search = "A") ) } } diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt index c392d8d3d..ac9e84228 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt @@ -33,8 +33,12 @@ class LocalPlaylistManagerTest { fun createPlaylist() { val NEWPIPE_URL = "https://newpipe.net/" val stream = StreamEntity( - serviceId = 1, url = NEWPIPE_URL, title = "title", - streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", + serviceId = 1, + url = NEWPIPE_URL, + title = "title", + streamType = StreamType.VIDEO_STREAM, + duration = 1, + uploader = "uploader", uploaderUrl = NEWPIPE_URL ) @@ -58,20 +62,28 @@ class LocalPlaylistManagerTest { @Test() fun createPlaylist_nonExistentStreamsAreUpserted() { val stream = StreamEntity( - serviceId = 1, url = "https://newpipe.net/", title = "title", - streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", + serviceId = 1, + url = "https://newpipe.net/", + title = "title", + streamType = StreamType.VIDEO_STREAM, + duration = 1, + uploader = "uploader", uploaderUrl = "https://newpipe.net/" ) database.streamDAO().insert(stream) val upserted = StreamEntity( - serviceId = 1, url = "https://newpipe.net/2", title = "title2", - streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", + serviceId = 1, + url = "https://newpipe.net/2", + title = "title2", + streamType = StreamType.VIDEO_STREAM, + duration = 1, + uploader = "uploader", uploaderUrl = "https://newpipe.net/" ) val result = manager.createPlaylist("name", listOf(stream, upserted)) result.test().await().assertComplete() - database.streamDAO().all.test().awaitCount(1).assertValue(listOf(stream, upserted)) + database.streamDAO().getAll().test().awaitCount(1).assertValue(listOf(stream, upserted)) } } diff --git a/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt index 75f5c6195..8b9f6b752 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt @@ -17,21 +17,20 @@ class TrampolineSchedulerRule : TestRule { private val scheduler = Schedulers.trampoline() - override fun apply(base: Statement, description: Description): Statement = - object : Statement() { - override fun evaluate() { - try { - RxJavaPlugins.setComputationSchedulerHandler { scheduler } - RxJavaPlugins.setIoSchedulerHandler { scheduler } - RxJavaPlugins.setNewThreadSchedulerHandler { scheduler } - RxJavaPlugins.setSingleSchedulerHandler { scheduler } - RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler } + override fun apply(base: Statement, description: Description): Statement = object : Statement() { + override fun evaluate() { + try { + RxJavaPlugins.setComputationSchedulerHandler { scheduler } + RxJavaPlugins.setIoSchedulerHandler { scheduler } + RxJavaPlugins.setNewThreadSchedulerHandler { scheduler } + RxJavaPlugins.setSingleSchedulerHandler { scheduler } + RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler } - base.evaluate() - } finally { - RxJavaPlugins.reset() - RxAndroidPlugins.reset() - } + base.evaluate() + } finally { + RxJavaPlugins.reset() + RxAndroidPlugins.reset() } } + } } diff --git a/app/src/androidTest/java/org/schabi/newpipe/util/StreamItemAdapterTest.kt b/app/src/androidTest/java/org/schabi/newpipe/util/StreamItemAdapterTest.kt index 9b8ee211e..22c7887f9 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/util/StreamItemAdapterTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/util/StreamItemAdapterTest.kt @@ -156,41 +156,51 @@ class StreamItemAdapterTest { helper.assertInvalidResponse(getResponse(mapOf(Pair("content-length", "mp3"))), 0) helper.assertInvalidResponse( - getResponse(mapOf(Pair("Content-Disposition", "filename=\"train.png\""))), 1 + getResponse(mapOf(Pair("Content-Disposition", "filename=\"train.png\""))), + 1 ) helper.assertInvalidResponse( - getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"data.csv\""))), 2 + getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"data.csv\""))), + 2 ) helper.assertInvalidResponse( - getResponse(mapOf(Pair("Content-Disposition", "form-data; filename=\"data.csv\""))), 3 + getResponse(mapOf(Pair("Content-Disposition", "form-data; filename=\"data.csv\""))), + 3 ) helper.assertInvalidResponse( - getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"fieldName\"; filename*=\"filename.jpg\""))), 4 + getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"fieldName\"; filename*=\"filename.jpg\""))), + 4 ) helper.assertValidResponse( getResponse(mapOf(Pair("Content-Disposition", "filename=\"train.ogg\""))), - 5, MediaFormat.OGG + 5, + MediaFormat.OGG ) helper.assertValidResponse( getResponse(mapOf(Pair("Content-Disposition", "some-form-data; filename=\"audio.flac\""))), - 6, MediaFormat.FLAC + 6, + MediaFormat.FLAC ) helper.assertValidResponse( getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"audio.aiff\"; filename=\"audio.aiff\""))), - 7, MediaFormat.AIFF + 7, + MediaFormat.AIFF ) helper.assertValidResponse( getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"alien?\"; filename*=UTF-8''%CE%B1%CE%BB%CE%B9%CF%B5%CE%BD.m4a"))), - 8, MediaFormat.M4A + 8, + MediaFormat.M4A ) helper.assertValidResponse( getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"audio.mp3\"; filename=\"audio.opus\"; filename*=UTF-8''alien.opus"))), - 9, MediaFormat.OPUS + 9, + MediaFormat.OPUS ) helper.assertValidResponse( getResponse(mapOf(Pair("Content-Disposition", "form-data; name=\"audio.mp3\"; filename=\"audio.opus\"; filename*=\"UTF-8''alien.opus\""))), - 10, MediaFormat.OPUS + 10, + MediaFormat.OPUS ) } @@ -213,16 +223,24 @@ class StreamItemAdapterTest { helper.assertInvalidResponse(getResponse(mapOf()), 7) helper.assertValidResponse( - getResponse(mapOf(Pair("Content-Type", "audio/flac"))), 8, MediaFormat.FLAC + getResponse(mapOf(Pair("Content-Type", "audio/flac"))), + 8, + MediaFormat.FLAC ) helper.assertValidResponse( - getResponse(mapOf(Pair("Content-Type", "audio/wav"))), 9, MediaFormat.WAV + getResponse(mapOf(Pair("Content-Type", "audio/wav"))), + 9, + MediaFormat.WAV ) helper.assertValidResponse( - getResponse(mapOf(Pair("Content-Type", "audio/opus"))), 10, MediaFormat.OPUS + getResponse(mapOf(Pair("Content-Type", "audio/opus"))), + 10, + MediaFormat.OPUS ) helper.assertValidResponse( - getResponse(mapOf(Pair("Content-Type", "audio/aiff"))), 11, MediaFormat.AIFF + getResponse(mapOf(Pair("Content-Type", "audio/aiff"))), + 11, + MediaFormat.AIFF ) } @@ -230,39 +248,37 @@ class StreamItemAdapterTest { * @return a list of video streams, in which their video only property mirrors the provided * [videoOnly] vararg. */ - private fun getVideoStreams(vararg videoOnly: Boolean) = - StreamItemAdapter.StreamInfoWrapper( - videoOnly.map { - VideoStream.Builder() - .setId(Stream.ID_UNKNOWN) - .setContent("https://example.com", true) - .setMediaFormat(MediaFormat.MPEG_4) - .setResolution("720p") - .setIsVideoOnly(it) - .build() - }, - context - ) + private fun getVideoStreams(vararg videoOnly: Boolean) = StreamInfoWrapper( + videoOnly.map { + VideoStream.Builder() + .setId(Stream.ID_UNKNOWN) + .setContent("https://example.com", true) + .setMediaFormat(MediaFormat.MPEG_4) + .setResolution("720p") + .setIsVideoOnly(it) + .build() + }, + context + ) /** * @return a list of audio streams, containing valid and null elements mirroring the provided * [shouldBeValid] vararg. */ - private fun getAudioStreams(vararg shouldBeValid: Boolean) = - getSecondaryStreamsFromList( - shouldBeValid.map { - if (it) { - AudioStream.Builder() - .setId(Stream.ID_UNKNOWN) - .setContent("https://example.com", true) - .setMediaFormat(MediaFormat.OPUS) - .setAverageBitrate(192) - .build() - } else { - null - } + private fun getAudioStreams(vararg shouldBeValid: Boolean) = getSecondaryStreamsFromList( + shouldBeValid.map { + if (it) { + AudioStream.Builder() + .setId(Stream.ID_UNKNOWN) + .setContent("https://example.com", true) + .setMediaFormat(MediaFormat.OPUS) + .setAverageBitrate(192) + .build() + } else { + null } - ) + } + ) private fun getIncompleteAudioStreams(size: Int): List { val list = ArrayList(size) @@ -292,7 +308,7 @@ class StreamItemAdapterTest { Assert.assertEquals( "normal visibility (pos=[$position]) is not correct", findViewById(R.id.wo_sound_icon).visibility, - normalVisibility, + normalVisibility ) } spinner.adapter.getDropDownView(position, null, spinner).run { @@ -307,18 +323,17 @@ class StreamItemAdapterTest { /** * Helper function that builds a secondary stream list. */ - private fun getSecondaryStreamsFromList(streams: List) = - SparseArrayCompat?>(streams.size).apply { - streams.forEachIndexed { index, stream -> - val secondaryStreamHelper: SecondaryStreamHelper? = stream?.let { - SecondaryStreamHelper( - StreamItemAdapter.StreamInfoWrapper(streams, context), - it - ) - } - put(index, secondaryStreamHelper) + private fun getSecondaryStreamsFromList(streams: List) = SparseArrayCompat?>(streams.size).apply { + streams.forEachIndexed { index, stream -> + val secondaryStreamHelper: SecondaryStreamHelper? = stream?.let { + SecondaryStreamHelper( + StreamItemAdapter.StreamInfoWrapper(streams, context), + it + ) } + put(index, secondaryStreamHelper) } + } private fun getResponse(headers: Map): Response { val listHeaders = HashMap>() @@ -345,7 +360,8 @@ class StreamItemAdapterTest { index: Int ) { assertFalse( - "invalid header returns valid value", retrieveMediaFormat(streams[index], response) + "invalid header returns valid value", + retrieveMediaFormat(streams[index], response) ) assertNull("Media format extracted although stated otherwise", wrapper.getFormat(index)) } @@ -359,7 +375,8 @@ class StreamItemAdapterTest { format: MediaFormat ) { assertTrue( - "header was not recognized", retrieveMediaFormat(streams[index], response) + "header was not recognized", + retrieveMediaFormat(streams[index], response) ) assertEquals("Wrong media format extracted", format, wrapper.getFormat(index)) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8a6b22ab3..20e9a6ca9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -340,6 +340,7 @@ + @@ -384,6 +385,7 @@ + diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 5b8c96d3e..92cb0f2a0 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -65,6 +65,8 @@ public class App extends Application { private static final String TAG = App.class.toString(); private boolean isFirstRun = false; + private boolean notificationsRequested = false; + private static App app; @NonNull @@ -72,6 +74,14 @@ public class App extends Application { return app; } + public boolean getNotificationsRequested() { + return notificationsRequested; + } + + public void setNotificationsRequested() { + notificationsRequested = true; + } + @Override protected void attachBaseContext(final Context base) { super.attachBaseContext(base); diff --git a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java index 23e18d034..4b33c4c30 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java +++ b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java @@ -169,9 +169,7 @@ public final class DownloaderImpl extends Downloader { String responseBodyToReturn = null; try (ResponseBody body = response.body()) { - if (body != null) { - responseBodyToReturn = body.string(); - } + responseBodyToReturn = body.string(); } final String latestUrl = response.request().url().toString(); diff --git a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java deleted file mode 100644 index 21c5354f4..000000000 --- a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.schabi.newpipe; - -import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME; -import static org.schabi.newpipe.database.Migrations.MIGRATION_1_2; -import static org.schabi.newpipe.database.Migrations.MIGRATION_2_3; -import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4; -import static org.schabi.newpipe.database.Migrations.MIGRATION_4_5; -import static org.schabi.newpipe.database.Migrations.MIGRATION_5_6; -import static org.schabi.newpipe.database.Migrations.MIGRATION_6_7; -import static org.schabi.newpipe.database.Migrations.MIGRATION_7_8; -import static org.schabi.newpipe.database.Migrations.MIGRATION_8_9; - -import android.content.Context; -import android.database.Cursor; - -import androidx.annotation.NonNull; -import androidx.room.Room; - -import org.schabi.newpipe.database.AppDatabase; - -public final class NewPipeDatabase { - private static volatile AppDatabase databaseInstance; - - private NewPipeDatabase() { - //no instance - } - - private static AppDatabase getDatabase(final Context context) { - return Room - .databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) - .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, - MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8, MIGRATION_8_9) - .build(); - } - - @NonNull - public static AppDatabase getInstance(@NonNull final Context context) { - AppDatabase result = databaseInstance; - if (result == null) { - synchronized (NewPipeDatabase.class) { - result = databaseInstance; - if (result == null) { - databaseInstance = getDatabase(context); - result = databaseInstance; - } - } - } - - return result; - } - - public static void checkpoint() { - if (databaseInstance == null) { - throw new IllegalStateException("database is not initialized"); - } - final Cursor c = databaseInstance.query("pragma wal_checkpoint(full)", null); - if (c.moveToFirst() && c.getInt(0) == 1) { - throw new RuntimeException("Checkpoint was blocked from completing"); - } - } - - public static void close() { - if (databaseInstance != null) { - synchronized (NewPipeDatabase.class) { - if (databaseInstance != null) { - databaseInstance.close(); - databaseInstance = null; - } - } - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.kt b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.kt new file mode 100644 index 000000000..6527bd2ae --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.kt @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2017-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe + +import android.content.Context +import androidx.room.Room.databaseBuilder +import kotlin.concurrent.Volatile +import org.schabi.newpipe.database.AppDatabase +import org.schabi.newpipe.database.Migrations.MIGRATION_1_2 +import org.schabi.newpipe.database.Migrations.MIGRATION_2_3 +import org.schabi.newpipe.database.Migrations.MIGRATION_3_4 +import org.schabi.newpipe.database.Migrations.MIGRATION_4_5 +import org.schabi.newpipe.database.Migrations.MIGRATION_5_6 +import org.schabi.newpipe.database.Migrations.MIGRATION_6_7 +import org.schabi.newpipe.database.Migrations.MIGRATION_7_8 +import org.schabi.newpipe.database.Migrations.MIGRATION_8_9 + +object NewPipeDatabase { + + @Volatile + private var databaseInstance: AppDatabase? = null + + private fun getDatabase(context: Context): AppDatabase { + return databaseBuilder( + context.applicationContext, + AppDatabase::class.java, + AppDatabase.Companion.DATABASE_NAME + ).addMigrations( + MIGRATION_1_2, + MIGRATION_2_3, + MIGRATION_3_4, + MIGRATION_4_5, + MIGRATION_5_6, + MIGRATION_6_7, + MIGRATION_7_8, + MIGRATION_8_9 + ).build() + } + + @JvmStatic + fun getInstance(context: Context): AppDatabase { + var result = databaseInstance + if (result == null) { + synchronized(NewPipeDatabase::class.java) { + result = databaseInstance + if (result == null) { + databaseInstance = getDatabase(context) + result = databaseInstance + } + } + } + + return result!! + } + + @JvmStatic + fun checkpoint() { + checkNotNull(databaseInstance) { "database is not initialized" } + val c = databaseInstance!!.query("pragma wal_checkpoint(full)", null) + if (c.moveToFirst() && c.getInt(0) == 1) { + throw RuntimeException("Checkpoint was blocked from completing") + } + } + + @JvmStatic + fun close() { + if (databaseInstance != null) { + synchronized(NewPipeDatabase::class.java) { + if (databaseInstance != null) { + databaseInstance!!.close() + databaseInstance = null + } + } + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt index 000b83953..fb48d3f70 100644 --- a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt @@ -18,10 +18,10 @@ import androidx.work.WorkerParameters import androidx.work.workDataOf import com.grack.nanojson.JsonParser import com.grack.nanojson.JsonParserException +import java.io.IOException import org.schabi.newpipe.extractor.downloader.Response import org.schabi.newpipe.extractor.exceptions.ReCaptchaException import org.schabi.newpipe.util.ReleaseVersionUtil -import java.io.IOException class NewVersionWorker( context: Context, @@ -46,7 +46,8 @@ class NewVersionWorker( // Show toast stating that the app is up-to-date if the update check was manual. ContextCompat.getMainExecutor(applicationContext).execute { Toast.makeText( - applicationContext, R.string.app_update_unavailable_toast, + applicationContext, + R.string.app_update_unavailable_toast, Toast.LENGTH_SHORT ).show() } @@ -58,7 +59,11 @@ class NewVersionWorker( val intent = Intent(Intent.ACTION_VIEW, apkLocationUrl?.toUri()) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) val pendingIntent = PendingIntentCompat.getActivity( - applicationContext, 0, intent, 0, false + applicationContext, + 0, + intent, + 0, + false ) val channelId = applicationContext.getString(R.string.app_update_notification_channel_id) val notificationBuilder = NotificationCompat.Builder(applicationContext, channelId) @@ -71,7 +76,8 @@ class NewVersionWorker( ) .setContentText( applicationContext.getString( - R.string.app_update_available_notification_text, versionName + R.string.app_update_available_notification_text, + versionName ) ) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 50639c5ae..d85fdf7de 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -316,7 +316,8 @@ public class RouterActivity extends AppCompatActivity { if (choiceChecker.isAvailableAndSelected( R.string.video_player_key, R.string.background_player_key, - R.string.popup_player_key)) { + R.string.popup_player_key, + R.string.enqueue_key)) { final String selectedChoice = choiceChecker.getSelectedChoiceKey(); @@ -329,6 +330,8 @@ public class RouterActivity extends AppCompatActivity { || selectedChoice.equals(getString(R.string.popup_player_key)); final boolean isAudioPlayerSelected = selectedChoice.equals(getString(R.string.background_player_key)); + final boolean isEnqueueSelected = + selectedChoice.equals(getString(R.string.enqueue_key)); if (currentLinkType != LinkType.STREAM && ((isExtAudioEnabled && isAudioPlayerSelected) @@ -345,7 +348,9 @@ public class RouterActivity extends AppCompatActivity { // Check if the service supports the choice if ((isVideoPlayerSelected && capabilities.contains(VIDEO)) - || (isAudioPlayerSelected && capabilities.contains(AUDIO))) { + || (isAudioPlayerSelected && capabilities.contains(AUDIO)) + || (isEnqueueSelected && (capabilities.contains(VIDEO) + || capabilities.contains(AUDIO)))) { handleChoice(selectedChoice); } else { handleChoice(getString(R.string.show_info_key)); @@ -526,7 +531,7 @@ public class RouterActivity extends AppCompatActivity { final List capabilities = service.getServiceInfo().getMediaCapabilities(); - if (linkType == LinkType.STREAM) { + if (linkType == LinkType.STREAM || linkType == LinkType.PLAYLIST) { if (capabilities.contains(VIDEO)) { returnedItems.add(videoPlayer); returnedItems.add(popupPlayer); @@ -534,17 +539,28 @@ public class RouterActivity extends AppCompatActivity { if (capabilities.contains(AUDIO)) { returnedItems.add(backgroundPlayer); } - // download is redundant for linkType CHANNEL AND PLAYLIST (till playlist downloading is - // not supported ) - returnedItems.add(new AdapterChoiceItem(getString(R.string.download_key), - getString(R.string.download), - R.drawable.ic_file_download)); - // Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can - // not be added to a playlist - returnedItems.add(new AdapterChoiceItem(getString(R.string.add_to_playlist_key), - getString(R.string.add_to_playlist), - R.drawable.ic_add)); + // Enqueue is only shown if the current queue is not empty. + // However, if the playqueue or the player is cleared after this item was chosen and + // while the item is extracted, it will automatically fall back to background player. + if (PlayerHolder.getInstance().getQueueSize() > 0) { + returnedItems.add(new AdapterChoiceItem(getString(R.string.enqueue_key), + getString(R.string.enqueue_stream), R.drawable.ic_add)); + } + + if (linkType == LinkType.STREAM) { + // download is redundant for linkType CHANNEL AND PLAYLIST + // (till playlist downloading is not supported ) + returnedItems.add(new AdapterChoiceItem(getString(R.string.download_key), + getString(R.string.download), + R.drawable.ic_file_download)); + + // Add to playlist is not necessary for CHANNEL and PLAYLIST linkType + // since those can not be added to a playlist + returnedItems.add(new AdapterChoiceItem(getString(R.string.add_to_playlist_key), + getString(R.string.add_to_playlist), + R.drawable.ic_playlist_add)); + } } else { // LinkType.NONE is never present because it's filtered out before // channels and playlist can be played as they contain a list of videos @@ -1016,6 +1032,8 @@ public class RouterActivity extends AppCompatActivity { NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); } else if (choice.playerChoice.equals(popupPlayerKey)) { NavigationHelper.playOnPopupPlayer(this, playQueue, true); + } else if (choice.playerChoice.equals(getString(R.string.enqueue_key))) { + NavigationHelper.enqueueOnPlayer(this, playQueue); } }; } diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt index 826616e59..cfb504200 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt @@ -116,86 +116,145 @@ class AboutActivity : AppCompatActivity() { */ private val SOFTWARE_COMPONENTS = arrayListOf( SoftwareComponent( - "ACRA", "2013", "Kevin Gaudin", - "https://github.com/ACRA/acra", StandardLicenses.APACHE2 + "ACRA", + "2013", + "Kevin Gaudin", + "https://github.com/ACRA/acra", + StandardLicenses.APACHE2 ), SoftwareComponent( - "AndroidX", "2005 - 2011", "The Android Open Source Project", - "https://developer.android.com/jetpack", StandardLicenses.APACHE2 + "AndroidX", + "2005 - 2011", + "The Android Open Source Project", + "https://developer.android.com/jetpack", + StandardLicenses.APACHE2 ), SoftwareComponent( - "ExoPlayer", "2014 - 2020", "Google, Inc.", - "https://github.com/google/ExoPlayer", StandardLicenses.APACHE2 + "ExoPlayer", + "2014 - 2020", + "Google, Inc.", + "https://github.com/google/ExoPlayer", + StandardLicenses.APACHE2 ), SoftwareComponent( - "GigaGet", "2014 - 2015", "Peter Cai", - "https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3 + "GigaGet", + "2014 - 2015", + "Peter Cai", + "https://github.com/PaperAirplane-Dev-Team/GigaGet", + StandardLicenses.GPL3 ), SoftwareComponent( - "Groupie", "2016", "Lisa Wray", - "https://github.com/lisawray/groupie", StandardLicenses.MIT + "Groupie", + "2016", + "Lisa Wray", + "https://github.com/lisawray/groupie", + StandardLicenses.MIT ), SoftwareComponent( - "Android-State", "2018", "Evernote", - "https://github.com/Evernote/android-state", StandardLicenses.EPL1 + "Android-State", + "2018", + "Evernote", + "https://github.com/Evernote/android-state", + StandardLicenses.EPL1 ), SoftwareComponent( - "Bridge", "2021", "Livefront", - "https://github.com/livefront/bridge", StandardLicenses.APACHE2 + "Bridge", + "2021", + "Livefront", + "https://github.com/livefront/bridge", + StandardLicenses.APACHE2 ), SoftwareComponent( - "Jsoup", "2009 - 2020", "Jonathan Hedley", - "https://github.com/jhy/jsoup", StandardLicenses.MIT + "Jsoup", + "2009 - 2020", + "Jonathan Hedley", + "https://github.com/jhy/jsoup", + StandardLicenses.MIT ), SoftwareComponent( - "Markwon", "2019", "Dimitry Ivanov", - "https://github.com/noties/Markwon", StandardLicenses.APACHE2 + "Markwon", + "2019", + "Dimitry Ivanov", + "https://github.com/noties/Markwon", + StandardLicenses.APACHE2 ), SoftwareComponent( - "Material Components for Android", "2016 - 2020", "Google, Inc.", + "Material Components for Android", + "2016 - 2020", + "Google, Inc.", "https://github.com/material-components/material-components-android", StandardLicenses.APACHE2 ), SoftwareComponent( - "NewPipe Extractor", "2017 - 2020", "Christian Schabesberger", - "https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3 + "NewPipe Extractor", + "2017 - 2020", + "Christian Schabesberger", + "https://github.com/TeamNewPipe/NewPipeExtractor", + StandardLicenses.GPL3 ), SoftwareComponent( - "NoNonsense-FilePicker", "2016", "Jonas Kalderstam", - "https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2 + "NoNonsense-FilePicker", + "2016", + "Jonas Kalderstam", + "https://github.com/spacecowboy/NoNonsense-FilePicker", + StandardLicenses.MPL2 ), SoftwareComponent( - "OkHttp", "2019", "Square, Inc.", - "https://square.github.io/okhttp/", StandardLicenses.APACHE2 + "OkHttp", + "2019", + "Square, Inc.", + "https://square.github.io/okhttp/", + StandardLicenses.APACHE2 ), SoftwareComponent( - "Picasso", "2013", "Square, Inc.", - "https://square.github.io/picasso/", StandardLicenses.APACHE2 + "Picasso", + "2013", + "Square, Inc.", + "https://square.github.io/picasso/", + StandardLicenses.APACHE2 ), SoftwareComponent( - "PrettyTime", "2012 - 2020", "Lincoln Baxter, III", - "https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2 + "PrettyTime", + "2012 - 2020", + "Lincoln Baxter, III", + "https://github.com/ocpsoft/prettytime", + StandardLicenses.APACHE2 ), SoftwareComponent( - "ProcessPhoenix", "2015", "Jake Wharton", - "https://github.com/JakeWharton/ProcessPhoenix", StandardLicenses.APACHE2 + "ProcessPhoenix", + "2015", + "Jake Wharton", + "https://github.com/JakeWharton/ProcessPhoenix", + StandardLicenses.APACHE2 ), SoftwareComponent( - "RxAndroid", "2015", "The RxAndroid authors", - "https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2 + "RxAndroid", + "2015", + "The RxAndroid authors", + "https://github.com/ReactiveX/RxAndroid", + StandardLicenses.APACHE2 ), SoftwareComponent( - "RxBinding", "2015", "Jake Wharton", - "https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2 + "RxBinding", + "2015", + "Jake Wharton", + "https://github.com/JakeWharton/RxBinding", + StandardLicenses.APACHE2 ), SoftwareComponent( - "RxJava", "2016 - 2020", "RxJava Contributors", - "https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2 + "RxJava", + "2016 - 2020", + "RxJava Contributors", + "https://github.com/ReactiveX/RxJava", + StandardLicenses.APACHE2 ), SoftwareComponent( - "SearchPreference", "2018", "ByteHamster", - "https://github.com/ByteHamster/SearchPreference", StandardLicenses.MIT - ), + "SearchPreference", + "2018", + "ByteHamster", + "https://github.com/ByteHamster/SearchPreference", + StandardLicenses.MIT + ) ) } } diff --git a/app/src/main/java/org/schabi/newpipe/about/License.kt b/app/src/main/java/org/schabi/newpipe/about/License.kt index 117ff9bf5..fc50c646d 100644 --- a/app/src/main/java/org/schabi/newpipe/about/License.kt +++ b/app/src/main/java/org/schabi/newpipe/about/License.kt @@ -1,8 +1,8 @@ package org.schabi.newpipe.about import android.os.Parcelable -import kotlinx.parcelize.Parcelize import java.io.Serializable +import kotlinx.parcelize.Parcelize /** * Class for storing information about a software license. diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.kt b/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.kt index 189fa148b..bd0632c13 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import android.webkit.WebView import androidx.appcompat.app.AlertDialog +import androidx.core.os.BundleCompat import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers @@ -33,7 +34,9 @@ class LicenseFragment : Fragment() { super.onCreate(savedInstanceState) softwareComponents = arguments?.parcelableArrayList(ARG_COMPONENTS)!! .sortedBy { it.name } // Sort components by name - activeSoftwareComponent = savedInstanceState?.getSerializable(SOFTWARE_COMPONENT_KEY) as? SoftwareComponent + activeSoftwareComponent = savedInstanceState?.let { + BundleCompat.getSerializable(it, SOFTWARE_COMPONENT_KEY, SoftwareComponent::class.java) + } } override fun onDestroy() { @@ -94,7 +97,8 @@ class LicenseFragment : Fragment() { .observeOn(AndroidSchedulers.mainThread()) .subscribe { formattedLicense -> val webViewData = Base64.encodeToString( - formattedLicense.toByteArray(), Base64.NO_PADDING + formattedLicense.toByteArray(), + Base64.NO_PADDING ) val webView = WebView(context) webView.loadData(webViewData, "text/html; charset=UTF-8", "base64") diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.kt b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.kt index 56e21c88a..32e4f812f 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.kt @@ -1,9 +1,9 @@ package org.schabi.newpipe.about import android.content.Context +import java.io.IOException import org.schabi.newpipe.R import org.schabi.newpipe.util.ThemeHelper -import java.io.IOException /** * @param context the context to use @@ -28,13 +28,16 @@ fun getFormattedLicense(context: Context, license: License): String { fun getLicenseStylesheet(context: Context): String { val isLightTheme = ThemeHelper.isLightThemeSelected(context) val licenseBackgroundColor = getHexRGBColor( - context, if (isLightTheme) R.color.light_license_background_color else R.color.dark_license_background_color + context, + if (isLightTheme) R.color.light_license_background_color else R.color.dark_license_background_color ) val licenseTextColor = getHexRGBColor( - context, if (isLightTheme) R.color.light_license_text_color else R.color.dark_license_text_color + context, + if (isLightTheme) R.color.light_license_text_color else R.color.dark_license_text_color ) val youtubePrimaryColor = getHexRGBColor( - context, if (isLightTheme) R.color.light_youtube_primary_color else R.color.dark_youtube_primary_color + context, + if (isLightTheme) R.color.light_youtube_primary_color else R.color.dark_youtube_primary_color ) return "body{padding:12px 15px;margin:0;background:#$licenseBackgroundColor;color:#$licenseTextColor}" + "a[href]{color:#$youtubePrimaryColor}pre{white-space:pre-wrap}" diff --git a/app/src/main/java/org/schabi/newpipe/about/SoftwareComponent.kt b/app/src/main/java/org/schabi/newpipe/about/SoftwareComponent.kt index 262641caa..a43ddfd5e 100644 --- a/app/src/main/java/org/schabi/newpipe/about/SoftwareComponent.kt +++ b/app/src/main/java/org/schabi/newpipe/about/SoftwareComponent.kt @@ -1,8 +1,8 @@ package org.schabi.newpipe.about import android.os.Parcelable -import kotlinx.parcelize.Parcelize import java.io.Serializable +import kotlinx.parcelize.Parcelize @Parcelize class SoftwareComponent diff --git a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java deleted file mode 100644 index 04d93a238..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.schabi.newpipe.database; - -import static org.schabi.newpipe.database.Migrations.DB_VER_9; - -import androidx.room.Database; -import androidx.room.RoomDatabase; -import androidx.room.TypeConverters; - -import org.schabi.newpipe.database.feed.dao.FeedDAO; -import org.schabi.newpipe.database.feed.dao.FeedGroupDAO; -import org.schabi.newpipe.database.feed.model.FeedEntity; -import org.schabi.newpipe.database.feed.model.FeedGroupEntity; -import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity; -import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity; -import org.schabi.newpipe.database.history.dao.SearchHistoryDAO; -import org.schabi.newpipe.database.history.dao.StreamHistoryDAO; -import org.schabi.newpipe.database.history.model.SearchHistoryEntry; -import org.schabi.newpipe.database.history.model.StreamHistoryEntity; -import org.schabi.newpipe.database.playlist.dao.PlaylistDAO; -import org.schabi.newpipe.database.playlist.dao.PlaylistRemoteDAO; -import org.schabi.newpipe.database.playlist.dao.PlaylistStreamDAO; -import org.schabi.newpipe.database.playlist.model.PlaylistEntity; -import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; -import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity; -import org.schabi.newpipe.database.stream.dao.StreamDAO; -import org.schabi.newpipe.database.stream.dao.StreamStateDAO; -import org.schabi.newpipe.database.stream.model.StreamEntity; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; -import org.schabi.newpipe.database.subscription.SubscriptionDAO; -import org.schabi.newpipe.database.subscription.SubscriptionEntity; - -@TypeConverters({Converters.class}) -@Database( - entities = { - SubscriptionEntity.class, SearchHistoryEntry.class, - StreamEntity.class, StreamHistoryEntity.class, StreamStateEntity.class, - PlaylistEntity.class, PlaylistStreamEntity.class, PlaylistRemoteEntity.class, - FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class, - FeedLastUpdatedEntity.class - }, - version = DB_VER_9 -) -public abstract class AppDatabase extends RoomDatabase { - public static final String DATABASE_NAME = "newpipe.db"; - - public abstract SearchHistoryDAO searchHistoryDAO(); - - public abstract StreamDAO streamDAO(); - - public abstract StreamHistoryDAO streamHistoryDAO(); - - public abstract StreamStateDAO streamStateDAO(); - - public abstract PlaylistDAO playlistDAO(); - - public abstract PlaylistStreamDAO playlistStreamDAO(); - - public abstract PlaylistRemoteDAO playlistRemoteDAO(); - - public abstract FeedDAO feedDAO(); - - public abstract FeedGroupDAO feedGroupDAO(); - - public abstract SubscriptionDAO subscriptionDAO(); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.kt b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.kt new file mode 100644 index 000000000..286eddf7b --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.kt @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2017-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database + +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.TypeConverters +import org.schabi.newpipe.database.feed.dao.FeedDAO +import org.schabi.newpipe.database.feed.dao.FeedGroupDAO +import org.schabi.newpipe.database.feed.model.FeedEntity +import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity +import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity +import org.schabi.newpipe.database.history.dao.SearchHistoryDAO +import org.schabi.newpipe.database.history.dao.StreamHistoryDAO +import org.schabi.newpipe.database.history.model.SearchHistoryEntry +import org.schabi.newpipe.database.history.model.StreamHistoryEntity +import org.schabi.newpipe.database.playlist.dao.PlaylistDAO +import org.schabi.newpipe.database.playlist.dao.PlaylistRemoteDAO +import org.schabi.newpipe.database.playlist.dao.PlaylistStreamDAO +import org.schabi.newpipe.database.playlist.model.PlaylistEntity +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity +import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity +import org.schabi.newpipe.database.stream.dao.StreamDAO +import org.schabi.newpipe.database.stream.dao.StreamStateDAO +import org.schabi.newpipe.database.stream.model.StreamEntity +import org.schabi.newpipe.database.stream.model.StreamStateEntity +import org.schabi.newpipe.database.subscription.SubscriptionDAO +import org.schabi.newpipe.database.subscription.SubscriptionEntity + +@TypeConverters(Converters::class) +@Database( + version = Migrations.DB_VER_9, + entities = [ + SubscriptionEntity::class, + SearchHistoryEntry::class, + StreamEntity::class, + StreamHistoryEntity::class, + StreamStateEntity::class, + PlaylistEntity::class, + PlaylistStreamEntity::class, + PlaylistRemoteEntity::class, + FeedEntity::class, + FeedGroupEntity::class, + FeedGroupSubscriptionEntity::class, + FeedLastUpdatedEntity::class + ] +) +abstract class AppDatabase : RoomDatabase() { + abstract fun feedDAO(): FeedDAO + abstract fun feedGroupDAO(): FeedGroupDAO + abstract fun playlistDAO(): PlaylistDAO + abstract fun playlistRemoteDAO(): PlaylistRemoteDAO + abstract fun playlistStreamDAO(): PlaylistStreamDAO + abstract fun searchHistoryDAO(): SearchHistoryDAO + abstract fun streamDAO(): StreamDAO + abstract fun streamHistoryDAO(): StreamHistoryDAO + abstract fun streamStateDAO(): StreamStateDAO + abstract fun subscriptionDAO(): SubscriptionDAO + + companion object { + const val DATABASE_NAME: String = "newpipe.db" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java b/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java deleted file mode 100644 index 255f5ba8d..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.schabi.newpipe.database; - -import androidx.room.Dao; -import androidx.room.Delete; -import androidx.room.Insert; -import androidx.room.Update; - -import java.util.Collection; -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -@Dao -public interface BasicDAO { - /* Inserts */ - @Insert - long insert(Entity entity); - - @Insert - List insertAll(Collection entities); - - /* Searches */ - Flowable> getAll(); - - Flowable> listByService(int serviceId); - - /* Deletes */ - @Delete - void delete(Entity entity); - - int deleteAll(); - - /* Updates */ - @Update - int update(Entity entity); - - @Update - void update(Collection entities); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/BasicDAO.kt b/app/src/main/java/org/schabi/newpipe/database/BasicDAO.kt new file mode 100644 index 000000000..74c7cc87c --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/BasicDAO.kt @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2017-2022 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Update +import io.reactivex.rxjava3.core.Flowable + +@Dao +interface BasicDAO { + + /* Inserts */ + @Insert + fun insert(entity: Entity): Long + + @Insert + fun insertAll(entities: Collection): List + + /* Searches */ + fun getAll(): Flowable> + + fun listByService(serviceId: Int): Flowable> + + /* Deletes */ + @Delete + fun delete(entity: Entity) + + fun deleteAll(): Int + + /* Updates */ + @Update + fun update(entity: Entity): Int + + @Update + fun update(entities: Collection) +} diff --git a/app/src/main/java/org/schabi/newpipe/database/Converters.kt b/app/src/main/java/org/schabi/newpipe/database/Converters.kt index ec097cc1b..f9cbb1de2 100644 --- a/app/src/main/java/org/schabi/newpipe/database/Converters.kt +++ b/app/src/main/java/org/schabi/newpipe/database/Converters.kt @@ -1,11 +1,11 @@ package org.schabi.newpipe.database import androidx.room.TypeConverter -import org.schabi.newpipe.extractor.stream.StreamType -import org.schabi.newpipe.local.subscription.FeedGroupIcon import java.time.Instant import java.time.OffsetDateTime import java.time.ZoneOffset +import org.schabi.newpipe.extractor.stream.StreamType +import org.schabi.newpipe.local.subscription.FeedGroupIcon class Converters { /** diff --git a/app/src/main/java/org/schabi/newpipe/database/LocalItem.java b/app/src/main/java/org/schabi/newpipe/database/LocalItem.java deleted file mode 100644 index 54b856b06..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/LocalItem.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.schabi.newpipe.database; - -public interface LocalItem { - LocalItemType getLocalItemType(); - - enum LocalItemType { - PLAYLIST_LOCAL_ITEM, - PLAYLIST_REMOTE_ITEM, - - PLAYLIST_STREAM_ITEM, - STATISTIC_STREAM_ITEM, - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/LocalItem.kt b/app/src/main/java/org/schabi/newpipe/database/LocalItem.kt new file mode 100644 index 000000000..944b247bf --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/LocalItem.kt @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2018-2020 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database + +interface LocalItem { + val localItemType: LocalItemType + + enum class LocalItemType { + PLAYLIST_LOCAL_ITEM, + PLAYLIST_REMOTE_ITEM, + + PLAYLIST_STREAM_ITEM, + STATISTIC_STREAM_ITEM + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.java b/app/src/main/java/org/schabi/newpipe/database/Migrations.java deleted file mode 100644 index c9f630869..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/Migrations.java +++ /dev/null @@ -1,307 +0,0 @@ -package org.schabi.newpipe.database; - -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.room.migration.Migration; -import androidx.sqlite.db.SupportSQLiteDatabase; - -import org.schabi.newpipe.MainActivity; - -public final class Migrations { - - ///////////////////////////////////////////////////////////////////////////// - // Test new migrations manually by importing a database from daily usage // - // and checking if the migration works (Use the Database Inspector // - // https://developer.android.com/studio/inspect/database). // - // If you add a migration point it out in the pull request, so that // - // others remember to test it themselves. // - ///////////////////////////////////////////////////////////////////////////// - - public static final int DB_VER_1 = 1; - public static final int DB_VER_2 = 2; - public static final int DB_VER_3 = 3; - public static final int DB_VER_4 = 4; - public static final int DB_VER_5 = 5; - public static final int DB_VER_6 = 6; - public static final int DB_VER_7 = 7; - public static final int DB_VER_8 = 8; - public static final int DB_VER_9 = 9; - - private static final String TAG = Migrations.class.getName(); - public static final boolean DEBUG = MainActivity.DEBUG; - - public static final Migration MIGRATION_1_2 = new Migration(DB_VER_1, DB_VER_2) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - if (DEBUG) { - Log.d(TAG, "Start migrating database"); - } - /* - * Unfortunately these queries must be hardcoded due to the possibility of - * schema and names changing at a later date, thus invalidating the older migration - * scripts if they are not hardcoded. - * */ - - // Not much we can do about this, since room doesn't create tables before migration. - // It's either this or blasting the entire database anew. - database.execSQL("CREATE INDEX `index_search_history_search` " - + "ON `search_history` (`search`)"); - database.execSQL("CREATE TABLE IF NOT EXISTS `streams` " - + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "`service_id` INTEGER NOT NULL, `url` TEXT, `title` TEXT, " - + "`stream_type` TEXT, `duration` INTEGER, `uploader` TEXT, " - + "`thumbnail_url` TEXT)"); - database.execSQL("CREATE UNIQUE INDEX `index_streams_service_id_url` " - + "ON `streams` (`service_id`, `url`)"); - database.execSQL("CREATE TABLE IF NOT EXISTS `stream_history` " - + "(`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, " - + "`repeat_count` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), " - + "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " - + "ON UPDATE CASCADE ON DELETE CASCADE )"); - database.execSQL("CREATE INDEX `index_stream_history_stream_id` " - + "ON `stream_history` (`stream_id`)"); - database.execSQL("CREATE TABLE IF NOT EXISTS `stream_state` " - + "(`stream_id` INTEGER NOT NULL, `progress_time` INTEGER NOT NULL, " - + "PRIMARY KEY(`stream_id`), FOREIGN KEY(`stream_id`) " - + "REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )"); - database.execSQL("CREATE TABLE IF NOT EXISTS `playlists` " - + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "`name` TEXT, `thumbnail_url` TEXT)"); - database.execSQL("CREATE INDEX `index_playlists_name` ON `playlists` (`name`)"); - database.execSQL("CREATE TABLE IF NOT EXISTS `playlist_stream_join` " - + "(`playlist_id` INTEGER NOT NULL, `stream_id` INTEGER NOT NULL, " - + "`join_index` INTEGER NOT NULL, PRIMARY KEY(`playlist_id`, `join_index`), " - + "FOREIGN KEY(`playlist_id`) REFERENCES `playlists`(`uid`) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " - + "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"); - database.execSQL("CREATE UNIQUE INDEX " - + "`index_playlist_stream_join_playlist_id_join_index` " - + "ON `playlist_stream_join` (`playlist_id`, `join_index`)"); - database.execSQL("CREATE INDEX `index_playlist_stream_join_stream_id` " - + "ON `playlist_stream_join` (`stream_id`)"); - database.execSQL("CREATE TABLE IF NOT EXISTS `remote_playlists` " - + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " - + "`thumbnail_url` TEXT, `uploader` TEXT, `stream_count` INTEGER)"); - database.execSQL("CREATE INDEX `index_remote_playlists_name` " - + "ON `remote_playlists` (`name`)"); - database.execSQL("CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " - + "ON `remote_playlists` (`service_id`, `url`)"); - - // Populate streams table with existing entries in watch history - // Latest data first, thus ignoring older entries with the same indices - database.execSQL("INSERT OR IGNORE INTO streams (service_id, url, title, " - + "stream_type, duration, uploader, thumbnail_url) " - - + "SELECT service_id, url, title, 'VIDEO_STREAM', duration, " - + "uploader, thumbnail_url " - - + "FROM watch_history " - + "ORDER BY creation_date DESC"); - - // Once the streams have PKs, join them with the normalized history table - // and populate it with the remaining data from watch history - database.execSQL("INSERT INTO stream_history (stream_id, access_date, repeat_count)" - + "SELECT uid, creation_date, 1 " - + "FROM watch_history INNER JOIN streams " - + "ON watch_history.service_id == streams.service_id " - + "AND watch_history.url == streams.url " - + "ORDER BY creation_date DESC"); - - database.execSQL("DROP TABLE IF EXISTS watch_history"); - - if (DEBUG) { - Log.d(TAG, "Stop migrating database"); - } - } - }; - - public static final Migration MIGRATION_2_3 = new Migration(DB_VER_2, DB_VER_3) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - // Add NOT NULLs and new fields - database.execSQL("CREATE TABLE IF NOT EXISTS streams_new " - + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "service_id INTEGER NOT NULL, url TEXT NOT NULL, title TEXT NOT NULL, " - + "stream_type TEXT NOT NULL, duration INTEGER NOT NULL, " - + "uploader TEXT NOT NULL, thumbnail_url TEXT, view_count INTEGER, " - + "textual_upload_date TEXT, upload_date INTEGER, " - + "is_upload_date_approximation INTEGER)"); - - database.execSQL("INSERT INTO streams_new (uid, service_id, url, title, stream_type, " - + "duration, uploader, thumbnail_url, view_count, textual_upload_date, " - + "upload_date, is_upload_date_approximation) " - - + "SELECT uid, service_id, url, ifnull(title, ''), " - + "ifnull(stream_type, 'VIDEO_STREAM'), ifnull(duration, 0), " - + "ifnull(uploader, ''), ifnull(thumbnail_url, ''), NULL, NULL, NULL, NULL " - - + "FROM streams WHERE url IS NOT NULL"); - - database.execSQL("DROP TABLE streams"); - database.execSQL("ALTER TABLE streams_new RENAME TO streams"); - database.execSQL("CREATE UNIQUE INDEX index_streams_service_id_url " - + "ON streams (service_id, url)"); - - // Tables for feed feature - database.execSQL("CREATE TABLE IF NOT EXISTS feed " - + "(stream_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " - + "PRIMARY KEY(stream_id, subscription_id), " - + "FOREIGN KEY(stream_id) REFERENCES streams(uid) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " - + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"); - database.execSQL("CREATE INDEX index_feed_subscription_id ON feed (subscription_id)"); - database.execSQL("CREATE TABLE IF NOT EXISTS feed_group " - + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, " - + "icon_id INTEGER NOT NULL, sort_order INTEGER NOT NULL)"); - database.execSQL("CREATE INDEX index_feed_group_sort_order ON feed_group (sort_order)"); - database.execSQL("CREATE TABLE IF NOT EXISTS feed_group_subscription_join " - + "(group_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " - + "PRIMARY KEY(group_id, subscription_id), " - + "FOREIGN KEY(group_id) REFERENCES feed_group(uid) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " - + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"); - database.execSQL("CREATE INDEX index_feed_group_subscription_join_subscription_id " - + "ON feed_group_subscription_join (subscription_id)"); - database.execSQL("CREATE TABLE IF NOT EXISTS feed_last_updated " - + "(subscription_id INTEGER NOT NULL, last_updated INTEGER, " - + "PRIMARY KEY(subscription_id), " - + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " - + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"); - } - }; - - public static final Migration MIGRATION_3_4 = new Migration(DB_VER_3, DB_VER_4) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - database.execSQL( - "ALTER TABLE streams ADD COLUMN uploader_url TEXT" - ); - } - }; - - public static final Migration MIGRATION_4_5 = new Migration(DB_VER_4, DB_VER_5) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - database.execSQL("ALTER TABLE `subscriptions` ADD COLUMN `notification_mode` " - + "INTEGER NOT NULL DEFAULT 0"); - } - }; - - public static final Migration MIGRATION_5_6 = new Migration(DB_VER_5, DB_VER_6) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - database.execSQL("ALTER TABLE `playlists` ADD COLUMN `is_thumbnail_permanent` " - + "INTEGER NOT NULL DEFAULT 0"); - } - }; - - public static final Migration MIGRATION_6_7 = new Migration(DB_VER_6, DB_VER_7) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - // Create a new column thumbnail_stream_id - database.execSQL("ALTER TABLE `playlists` ADD COLUMN `thumbnail_stream_id` " - + "INTEGER NOT NULL DEFAULT -1"); - - // Migrate the thumbnail_url to the thumbnail_stream_id - database.execSQL("UPDATE playlists SET thumbnail_stream_id = (" - + " SELECT CASE WHEN COUNT(*) != 0 then stream_uid ELSE -1 END" - + " FROM (" - + " SELECT p.uid AS playlist_uid, s.uid AS stream_uid" - + " FROM playlists p" - + " LEFT JOIN playlist_stream_join ps ON p.uid = ps.playlist_id" - + " LEFT JOIN streams s ON s.uid = ps.stream_id" - + " WHERE s.thumbnail_url = p.thumbnail_url) AS temporary_table" - + " WHERE playlist_uid = playlists.uid)"); - - // Remove the thumbnail_url field in the playlist table - database.execSQL("CREATE TABLE IF NOT EXISTS `playlists_new`" - + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "name TEXT, " - + "is_thumbnail_permanent INTEGER NOT NULL, " - + "thumbnail_stream_id INTEGER NOT NULL)"); - - database.execSQL("INSERT INTO playlists_new" - + " SELECT uid, name, is_thumbnail_permanent, thumbnail_stream_id " - + " FROM playlists"); - - - database.execSQL("DROP TABLE playlists"); - database.execSQL("ALTER TABLE playlists_new RENAME TO playlists"); - database.execSQL("CREATE INDEX IF NOT EXISTS " - + "`index_playlists_name` ON `playlists` (`name`)"); - } - }; - - public static final Migration MIGRATION_7_8 = new Migration(DB_VER_7, DB_VER_8) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - database.execSQL("DELETE FROM search_history WHERE id NOT IN (SELECT id FROM (SELECT " - + "MIN(id) as id FROM search_history GROUP BY trim(search), service_id ) tmp)"); - database.execSQL("UPDATE search_history SET search = trim(search)"); - } - }; - - public static final Migration MIGRATION_8_9 = new Migration(DB_VER_8, DB_VER_9) { - @Override - public void migrate(@NonNull final SupportSQLiteDatabase database) { - try { - database.beginTransaction(); - - // Update playlists. - // Create a temp table to initialize display_index. - database.execSQL("CREATE TABLE `playlists_tmp` " - + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "`name` TEXT, `is_thumbnail_permanent` INTEGER NOT NULL, " - + "`thumbnail_stream_id` INTEGER NOT NULL, " - + "`display_index` INTEGER NOT NULL)"); - database.execSQL("INSERT INTO `playlists_tmp` " - + "(`uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " - + "`display_index`) " - + "SELECT `uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " - + "-1 " - + "FROM `playlists`"); - - // Replace the old table, note that this also removes the index on the name which - // we don't need anymore. - database.execSQL("DROP TABLE `playlists`"); - database.execSQL("ALTER TABLE `playlists_tmp` RENAME TO `playlists`"); - - - // Update remote_playlists. - // Create a temp table to initialize display_index. - database.execSQL("CREATE TABLE `remote_playlists_tmp` " - + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " - + "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " - + "`thumbnail_url` TEXT, `uploader` TEXT, " - + "`display_index` INTEGER NOT NULL," - + "`stream_count` INTEGER)"); - database.execSQL("INSERT INTO `remote_playlists_tmp` (`uid`, `service_id`, " - + "`name`, `url`, `thumbnail_url`, `uploader`, `display_index`, " - + "`stream_count`)" - + "SELECT `uid`, `service_id`, `name`, `url`, `thumbnail_url`, `uploader`, " - + "-1, `stream_count` FROM `remote_playlists`"); - - // Replace the old table, note that this also removes the index on the name which - // we don't need anymore. - database.execSQL("DROP TABLE `remote_playlists`"); - database.execSQL("ALTER TABLE `remote_playlists_tmp` RENAME TO `remote_playlists`"); - - // Create index on the new table. - database.execSQL("CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " - + "ON `remote_playlists` (`service_id`, `url`)"); - - database.setTransactionSuccessful(); - } finally { - database.endTransaction(); - } - } - }; - - private Migrations() { - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.kt b/app/src/main/java/org/schabi/newpipe/database/Migrations.kt new file mode 100644 index 000000000..414f74893 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.kt @@ -0,0 +1,351 @@ +/* + * SPDX-FileCopyrightText: 2018-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database + +import android.util.Log +import androidx.room.migration.Migration +import org.schabi.newpipe.MainActivity + +object Migrations { + + // /////////////////////////////////////////////////////////////////////// // + // Test new migrations manually by importing a database from daily usage // + // and checking if the migration works (Use the Database Inspector // + // https://developer.android.com/studio/inspect/database). // + // If you add a migration point it out in the pull request, so that // + // others remember to test it themselves. // + // /////////////////////////////////////////////////////////////////////// // + + const val DB_VER_1 = 1 + const val DB_VER_2 = 2 + const val DB_VER_3 = 3 + const val DB_VER_4 = 4 + const val DB_VER_5 = 5 + const val DB_VER_6 = 6 + const val DB_VER_7 = 7 + const val DB_VER_8 = 8 + const val DB_VER_9 = 9 + + private val TAG = Migrations::class.java.getName() + private val isDebug = MainActivity.DEBUG + + val MIGRATION_1_2 = Migration(DB_VER_1, DB_VER_2) { db -> + if (isDebug) { + Log.d(TAG, "Start migrating database") + } + + /* + * Unfortunately these queries must be hardcoded due to the possibility of + * schema and names changing at a later date, thus invalidating the older migration + * scripts if they are not hardcoded. + * */ + + // Not much we can do about this, since room doesn't create tables before migration. + // It's either this or blasting the entire database anew. + db.execSQL( + "CREATE INDEX `index_search_history_search` " + + "ON `search_history` (`search`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `streams` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`service_id` INTEGER NOT NULL, `url` TEXT, `title` TEXT, " + + "`stream_type` TEXT, `duration` INTEGER, `uploader` TEXT, " + + "`thumbnail_url` TEXT)" + ) + db.execSQL( + "CREATE UNIQUE INDEX `index_streams_service_id_url` " + + "ON `streams` (`service_id`, `url`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `stream_history` " + + "(`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, " + + "`repeat_count` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), " + + "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " + + "ON UPDATE CASCADE ON DELETE CASCADE )" + ) + db.execSQL( + "CREATE INDEX `index_stream_history_stream_id` " + + "ON `stream_history` (`stream_id`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `stream_state` " + + "(`stream_id` INTEGER NOT NULL, `progress_time` INTEGER NOT NULL, " + + "PRIMARY KEY(`stream_id`), FOREIGN KEY(`stream_id`) " + + "REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `playlists` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`name` TEXT, `thumbnail_url` TEXT)" + ) + db.execSQL("CREATE INDEX `index_playlists_name` ON `playlists` (`name`)") + db.execSQL( + "CREATE TABLE IF NOT EXISTS `playlist_stream_join` " + + "(`playlist_id` INTEGER NOT NULL, `stream_id` INTEGER NOT NULL, " + + "`join_index` INTEGER NOT NULL, PRIMARY KEY(`playlist_id`, `join_index`), " + + "FOREIGN KEY(`playlist_id`) REFERENCES `playlists`(`uid`) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + + "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + db.execSQL( + "CREATE UNIQUE INDEX " + + "`index_playlist_stream_join_playlist_id_join_index` " + + "ON `playlist_stream_join` (`playlist_id`, `join_index`)" + ) + db.execSQL( + "CREATE INDEX `index_playlist_stream_join_stream_id` " + + "ON `playlist_stream_join` (`stream_id`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `remote_playlists` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " + + "`thumbnail_url` TEXT, `uploader` TEXT, `stream_count` INTEGER)" + ) + db.execSQL( + "CREATE INDEX `index_remote_playlists_name` " + + "ON `remote_playlists` (`name`)" + ) + db.execSQL( + "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " + + "ON `remote_playlists` (`service_id`, `url`)" + ) + + // Populate streams table with existing entries in watch history + // Latest data first, thus ignoring older entries with the same indices + db.execSQL( + "INSERT OR IGNORE INTO streams (service_id, url, title, " + + "stream_type, duration, uploader, thumbnail_url) " + + + "SELECT service_id, url, title, 'VIDEO_STREAM', duration, " + + "uploader, thumbnail_url " + + + "FROM watch_history " + + "ORDER BY creation_date DESC" + ) + + // Once the streams have PKs, join them with the normalized history table + // and populate it with the remaining data from watch history + db.execSQL( + "INSERT INTO stream_history (stream_id, access_date, repeat_count)" + + "SELECT uid, creation_date, 1 " + + "FROM watch_history INNER JOIN streams " + + "ON watch_history.service_id == streams.service_id " + + "AND watch_history.url == streams.url " + + "ORDER BY creation_date DESC" + ) + + db.execSQL("DROP TABLE IF EXISTS watch_history") + + if (isDebug) { + Log.d(TAG, "Stop migrating database") + } + } + + val MIGRATION_2_3 = Migration(DB_VER_2, DB_VER_3) { db -> + // Add NOT NULLs and new fields + db.execSQL( + "CREATE TABLE IF NOT EXISTS streams_new " + + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "service_id INTEGER NOT NULL, url TEXT NOT NULL, title TEXT NOT NULL, " + + "stream_type TEXT NOT NULL, duration INTEGER NOT NULL, " + + "uploader TEXT NOT NULL, thumbnail_url TEXT, view_count INTEGER, " + + "textual_upload_date TEXT, upload_date INTEGER, " + + "is_upload_date_approximation INTEGER)" + ) + + db.execSQL( + "INSERT INTO streams_new (uid, service_id, url, title, stream_type, " + + "duration, uploader, thumbnail_url, view_count, textual_upload_date, " + + "upload_date, is_upload_date_approximation) " + + + "SELECT uid, service_id, url, ifnull(title, ''), " + + "ifnull(stream_type, 'VIDEO_STREAM'), ifnull(duration, 0), " + + "ifnull(uploader, ''), ifnull(thumbnail_url, ''), NULL, NULL, NULL, NULL " + + + "FROM streams WHERE url IS NOT NULL" + ) + + db.execSQL("DROP TABLE streams") + db.execSQL("ALTER TABLE streams_new RENAME TO streams") + db.execSQL( + "CREATE UNIQUE INDEX index_streams_service_id_url " + + "ON streams (service_id, url)" + ) + + // Tables for feed feature + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed " + + "(stream_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " + + "PRIMARY KEY(stream_id, subscription_id), " + + "FOREIGN KEY(stream_id) REFERENCES streams(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + db.execSQL("CREATE INDEX index_feed_subscription_id ON feed (subscription_id)") + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed_group " + + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, " + + "icon_id INTEGER NOT NULL, sort_order INTEGER NOT NULL)" + ) + db.execSQL("CREATE INDEX index_feed_group_sort_order ON feed_group (sort_order)") + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed_group_subscription_join " + + "(group_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " + + "PRIMARY KEY(group_id, subscription_id), " + + "FOREIGN KEY(group_id) REFERENCES feed_group(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + db.execSQL( + "CREATE INDEX index_feed_group_subscription_join_subscription_id " + + "ON feed_group_subscription_join (subscription_id)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed_last_updated " + + "(subscription_id INTEGER NOT NULL, last_updated INTEGER, " + + "PRIMARY KEY(subscription_id), " + + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + } + + val MIGRATION_3_4 = Migration(DB_VER_3, DB_VER_4) { db -> + db.execSQL("ALTER TABLE streams ADD COLUMN uploader_url TEXT") + } + + val MIGRATION_4_5 = Migration(DB_VER_4, DB_VER_5) { db -> + db.execSQL( + "ALTER TABLE `subscriptions` ADD COLUMN `notification_mode` " + + "INTEGER NOT NULL DEFAULT 0" + ) + } + + val MIGRATION_5_6 = Migration(DB_VER_5, DB_VER_6) { db -> + db.execSQL( + "ALTER TABLE `playlists` ADD COLUMN `is_thumbnail_permanent` " + + "INTEGER NOT NULL DEFAULT 0" + ) + } + + val MIGRATION_6_7 = Migration(DB_VER_6, DB_VER_7) { db -> + // Create a new column thumbnail_stream_id + db.execSQL( + "ALTER TABLE `playlists` ADD COLUMN `thumbnail_stream_id` " + + "INTEGER NOT NULL DEFAULT -1" + ) + + // Migrate the thumbnail_url to the thumbnail_stream_id + db.execSQL( + "UPDATE playlists SET thumbnail_stream_id = (" + + " SELECT CASE WHEN COUNT(*) != 0 then stream_uid ELSE -1 END" + + " FROM (" + + " SELECT p.uid AS playlist_uid, s.uid AS stream_uid" + + " FROM playlists p" + + " LEFT JOIN playlist_stream_join ps ON p.uid = ps.playlist_id" + + " LEFT JOIN streams s ON s.uid = ps.stream_id" + + " WHERE s.thumbnail_url = p.thumbnail_url) AS temporary_table" + + " WHERE playlist_uid = playlists.uid)" + ) + + // Remove the thumbnail_url field in the playlist table + db.execSQL( + "CREATE TABLE IF NOT EXISTS `playlists_new`" + + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "name TEXT, " + + "is_thumbnail_permanent INTEGER NOT NULL, " + + "thumbnail_stream_id INTEGER NOT NULL)" + ) + + db.execSQL( + "INSERT INTO playlists_new" + + " SELECT uid, name, is_thumbnail_permanent, thumbnail_stream_id " + + " FROM playlists" + ) + + db.execSQL("DROP TABLE playlists") + db.execSQL("ALTER TABLE playlists_new RENAME TO playlists") + db.execSQL( + "CREATE INDEX IF NOT EXISTS " + + "`index_playlists_name` ON `playlists` (`name`)" + ) + } + + val MIGRATION_7_8 = Migration(DB_VER_7, DB_VER_8) { db -> + db.execSQL( + "DELETE FROM search_history WHERE id NOT IN (SELECT id FROM (SELECT " + + "MIN(id) as id FROM search_history GROUP BY trim(search), service_id ) tmp)" + ) + db.execSQL("UPDATE search_history SET search = trim(search)") + } + + val MIGRATION_8_9 = Migration(DB_VER_8, DB_VER_9) { db -> + try { + db.beginTransaction() + + // Update playlists. + // Create a temp table to initialize display_index. + db.execSQL( + "CREATE TABLE `playlists_tmp` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`name` TEXT, `is_thumbnail_permanent` INTEGER NOT NULL, " + + "`thumbnail_stream_id` INTEGER NOT NULL, " + + "`display_index` INTEGER NOT NULL)" + ) + db.execSQL( + "INSERT INTO `playlists_tmp` " + + "(`uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " + + "`display_index`) " + + "SELECT `uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " + + "-1 " + + "FROM `playlists`" + ) + + // Replace the old table, note that this also removes the index on the name which + // we don't need anymore. + db.execSQL("DROP TABLE `playlists`") + db.execSQL("ALTER TABLE `playlists_tmp` RENAME TO `playlists`") + + // Update remote_playlists. + // Create a temp table to initialize display_index. + db.execSQL( + "CREATE TABLE `remote_playlists_tmp` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " + + "`thumbnail_url` TEXT, `uploader` TEXT, " + + "`display_index` INTEGER NOT NULL," + + "`stream_count` INTEGER)" + ) + db.execSQL( + "INSERT INTO `remote_playlists_tmp` (`uid`, `service_id`, " + + "`name`, `url`, `thumbnail_url`, `uploader`, `display_index`, " + + "`stream_count`)" + + "SELECT `uid`, `service_id`, `name`, `url`, `thumbnail_url`, `uploader`, " + + "-1, `stream_count` FROM `remote_playlists`" + ) + + // Replace the old table, note that this also removes the index on the name which + // we don't need anymore. + db.execSQL("DROP TABLE `remote_playlists`") + db.execSQL("ALTER TABLE `remote_playlists_tmp` RENAME TO `remote_playlists`") + + // Create index on the new table. + db.execSQL( + "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " + + "ON `remote_playlists` (`service_id`, `url`)" + ) + + db.setTransactionSuccessful() + } finally { + db.endTransaction() + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt index e7ed93497..5861fa767 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt @@ -8,6 +8,7 @@ import androidx.room.Transaction import androidx.room.Update import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Maybe +import java.time.OffsetDateTime import org.schabi.newpipe.database.feed.model.FeedEntity import org.schabi.newpipe.database.feed.model.FeedGroupEntity import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity @@ -15,7 +16,6 @@ import org.schabi.newpipe.database.stream.StreamWithState import org.schabi.newpipe.database.stream.model.StreamStateEntity import org.schabi.newpipe.database.subscription.NotificationMode import org.schabi.newpipe.database.subscription.SubscriptionEntity -import java.time.OffsetDateTime @Dao abstract class FeedDAO { @@ -168,10 +168,10 @@ abstract class FeedDAO { ON fgs.subscription_id = lu.subscription_id AND fgs.group_id = :groupId """ ) - abstract fun oldestSubscriptionUpdate(groupId: Long): Flowable> + abstract fun oldestSubscriptionUpdate(groupId: Long): Flowable> @Query("SELECT MIN(last_updated) FROM feed_last_updated") - abstract fun oldestSubscriptionUpdateFromAll(): Flowable> + abstract fun oldestSubscriptionUpdateFromAll(): Flowable> @Query("SELECT COUNT(*) FROM feed_last_updated WHERE last_updated IS NULL") abstract fun notLoadedCount(): Flowable diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedEntity.kt b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedEntity.kt index beeedc62b..86568bc90 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedEntity.kt @@ -19,13 +19,17 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity entity = StreamEntity::class, parentColumns = [StreamEntity.STREAM_ID], childColumns = [STREAM_ID], - onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE, + deferred = true ), ForeignKey( entity = SubscriptionEntity::class, parentColumns = [SubscriptionEntity.SUBSCRIPTION_UID], childColumns = [SUBSCRIPTION_ID], - onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE, + deferred = true ) ] ) diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupSubscriptionEntity.kt b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupSubscriptionEntity.kt index b114a734c..6dac3c89c 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupSubscriptionEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupSubscriptionEntity.kt @@ -18,14 +18,18 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity entity = FeedGroupEntity::class, parentColumns = [FeedGroupEntity.ID], childColumns = [GROUP_ID], - onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE, + deferred = true ), ForeignKey( entity = SubscriptionEntity::class, parentColumns = [SubscriptionEntity.SUBSCRIPTION_UID], childColumns = [SUBSCRIPTION_ID], - onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE, + deferred = true ) ] ) diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedLastUpdatedEntity.kt b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedLastUpdatedEntity.kt index a19af9c45..fc0ee6742 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedLastUpdatedEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedLastUpdatedEntity.kt @@ -4,10 +4,10 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.PrimaryKey +import java.time.OffsetDateTime import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity.Companion.FEED_LAST_UPDATED_TABLE import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity.Companion.SUBSCRIPTION_ID import org.schabi.newpipe.database.subscription.SubscriptionEntity -import java.time.OffsetDateTime @Entity( tableName = FEED_LAST_UPDATED_TABLE, @@ -16,7 +16,9 @@ import java.time.OffsetDateTime entity = SubscriptionEntity::class, parentColumns = [SubscriptionEntity.SUBSCRIPTION_UID], childColumns = [SUBSCRIPTION_ID], - onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE, + deferred = true ) ] ) diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/HistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/history/dao/HistoryDAO.java deleted file mode 100644 index 1ade08122..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/history/dao/HistoryDAO.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.schabi.newpipe.database.history.dao; - -import org.schabi.newpipe.database.BasicDAO; - -public interface HistoryDAO extends BasicDAO { - T getLatestEntry(); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java deleted file mode 100644 index 8a281bdb4..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.schabi.newpipe.database.history.dao; - -import androidx.annotation.Nullable; -import androidx.room.Dao; -import androidx.room.Query; - -import org.schabi.newpipe.database.history.model.SearchHistoryEntry; - -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -import static org.schabi.newpipe.database.history.model.SearchHistoryEntry.CREATION_DATE; -import static org.schabi.newpipe.database.history.model.SearchHistoryEntry.ID; -import static org.schabi.newpipe.database.history.model.SearchHistoryEntry.SEARCH; -import static org.schabi.newpipe.database.history.model.SearchHistoryEntry.SERVICE_ID; -import static org.schabi.newpipe.database.history.model.SearchHistoryEntry.TABLE_NAME; - -@Dao -public interface SearchHistoryDAO extends HistoryDAO { - String ORDER_BY_CREATION_DATE = " ORDER BY " + CREATION_DATE + " DESC"; - String ORDER_BY_MAX_CREATION_DATE = " ORDER BY MAX(" + CREATION_DATE + ") DESC"; - - @Query("SELECT * FROM " + TABLE_NAME - + " WHERE " + ID + " = (SELECT MAX(" + ID + ") FROM " + TABLE_NAME + ")") - @Nullable - SearchHistoryEntry getLatestEntry(); - - @Query("DELETE FROM " + TABLE_NAME) - @Override - int deleteAll(); - - @Query("DELETE FROM " + TABLE_NAME + " WHERE " + SEARCH + " = :query") - int deleteAllWhereQuery(String query); - - @Query("SELECT * FROM " + TABLE_NAME + ORDER_BY_CREATION_DATE) - @Override - Flowable> getAll(); - - @Query("SELECT " + SEARCH + " FROM " + TABLE_NAME + " GROUP BY " + SEARCH - + ORDER_BY_MAX_CREATION_DATE + " LIMIT :limit") - Flowable> getUniqueEntries(int limit); - - @Query("SELECT * FROM " + TABLE_NAME - + " WHERE " + SERVICE_ID + " = :serviceId" + ORDER_BY_CREATION_DATE) - @Override - Flowable> listByService(int serviceId); - - @Query("SELECT " + SEARCH + " FROM " + TABLE_NAME + " WHERE " + SEARCH + " LIKE :query || '%'" - + " GROUP BY " + SEARCH + ORDER_BY_MAX_CREATION_DATE + " LIMIT :limit") - Flowable> getSimilarEntries(String query, int limit); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.kt b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.kt new file mode 100644 index 000000000..ddcb00489 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.kt @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.history.dao + +import androidx.room.Dao +import androidx.room.Query +import io.reactivex.rxjava3.core.Flowable +import org.schabi.newpipe.database.BasicDAO +import org.schabi.newpipe.database.history.model.SearchHistoryEntry + +@Dao +interface SearchHistoryDAO : BasicDAO { + + @get:Query("SELECT * FROM search_history WHERE id = (SELECT MAX(id) FROM search_history)") + val latestEntry: SearchHistoryEntry? + + @Query("DELETE FROM search_history") + override fun deleteAll(): Int + + @Query("DELETE FROM search_history WHERE search = :query") + fun deleteAllWhereQuery(query: String): Int + + @Query("SELECT * FROM search_history ORDER BY creation_date DESC") + override fun getAll(): Flowable> + + @Query("SELECT search FROM search_history GROUP BY search ORDER BY MAX(creation_date) DESC LIMIT :limit") + fun getUniqueEntries(limit: Int): Flowable> + + @Query("SELECT * FROM search_history WHERE service_id = :serviceId ORDER BY creation_date DESC") + override fun listByService(serviceId: Int): Flowable> + + @Query( + """ + SELECT search FROM search_history WHERE search LIKE :query || + '%' GROUP BY search ORDER BY MAX(creation_date) DESC LIMIT :limit + """ + ) + fun getSimilarEntries(query: String, limit: Int): Flowable> +} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java deleted file mode 100644 index 150d4a8e5..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.schabi.newpipe.database.history.dao; - -import androidx.annotation.Nullable; -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.RewriteQueriesToDropUnusedColumns; - -import org.schabi.newpipe.database.history.model.StreamHistoryEntity; -import org.schabi.newpipe.database.history.model.StreamHistoryEntry; -import org.schabi.newpipe.database.stream.StreamStatisticsEntry; - -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.JOIN_STREAM_ID; -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_ACCESS_DATE; -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_HISTORY_TABLE; -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_REPEAT_COUNT; -import static org.schabi.newpipe.database.stream.StreamStatisticsEntry.STREAM_LATEST_DATE; -import static org.schabi.newpipe.database.stream.StreamStatisticsEntry.STREAM_WATCH_COUNT; -import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_ID; -import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID_ALIAS; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE; - -@Dao -public abstract class StreamHistoryDAO implements HistoryDAO { - @Query("SELECT * FROM " + STREAM_HISTORY_TABLE - + " WHERE " + STREAM_ACCESS_DATE + " = " - + "(SELECT MAX(" + STREAM_ACCESS_DATE + ") FROM " + STREAM_HISTORY_TABLE + ")") - @Override - @Nullable - public abstract StreamHistoryEntity getLatestEntry(); - - @Override - @Query("SELECT * FROM " + STREAM_HISTORY_TABLE) - public abstract Flowable> getAll(); - - @Override - @Query("DELETE FROM " + STREAM_HISTORY_TABLE) - public abstract int deleteAll(); - - @Override - public Flowable> listByService(final int serviceId) { - throw new UnsupportedOperationException(); - } - - @Query("SELECT * FROM " + STREAM_TABLE - + " INNER JOIN " + STREAM_HISTORY_TABLE - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID - + " ORDER BY " + STREAM_ACCESS_DATE + " DESC") - public abstract Flowable> getHistory(); - - - @Query("SELECT * FROM " + STREAM_TABLE - + " INNER JOIN " + STREAM_HISTORY_TABLE - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID - + " ORDER BY " + STREAM_ID + " ASC") - public abstract Flowable> getHistorySortedById(); - - @Query("SELECT * FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID - + " = :streamId ORDER BY " + STREAM_ACCESS_DATE + " DESC LIMIT 1") - @Nullable - public abstract StreamHistoryEntity getLatestEntry(long streamId); - - @Query("DELETE FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId") - public abstract int deleteStreamHistory(long streamId); - - @RewriteQueriesToDropUnusedColumns - @Query("SELECT * FROM " + STREAM_TABLE - - // Select the latest entry and watch count for each stream id on history table - + " INNER JOIN " - + "(SELECT " + JOIN_STREAM_ID + ", " - + " MAX(" + STREAM_ACCESS_DATE + ") AS " + STREAM_LATEST_DATE + ", " - + " SUM(" + STREAM_REPEAT_COUNT + ") AS " + STREAM_WATCH_COUNT - + " FROM " + STREAM_HISTORY_TABLE + " GROUP BY " + JOIN_STREAM_ID + ")" - - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID - - + " LEFT JOIN " - + "(SELECT " + JOIN_STREAM_ID + " AS " + JOIN_STREAM_ID_ALIAS + ", " - + STREAM_PROGRESS_MILLIS - + " FROM " + STREAM_STATE_TABLE + " )" - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID_ALIAS) - public abstract Flowable> getStatistics(); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.kt b/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.kt new file mode 100644 index 000000000..916d4e5ed --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.kt @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2018-2022 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.history.dao + +import androidx.room.Dao +import androidx.room.Query +import androidx.room.RewriteQueriesToDropUnusedColumns +import io.reactivex.rxjava3.core.Flowable +import org.schabi.newpipe.database.BasicDAO +import org.schabi.newpipe.database.history.model.StreamHistoryEntity +import org.schabi.newpipe.database.history.model.StreamHistoryEntry +import org.schabi.newpipe.database.stream.StreamStatisticsEntry + +@Dao +abstract class StreamHistoryDAO : BasicDAO { + + @Query("SELECT * FROM stream_history") + abstract override fun getAll(): Flowable> + + @Query("DELETE FROM stream_history") + abstract override fun deleteAll(): Int + + override fun listByService(serviceId: Int): Flowable> { + throw UnsupportedOperationException() + } + + @get:Query("SELECT * FROM streams INNER JOIN stream_history ON uid = stream_id ORDER BY access_date DESC") + abstract val history: Flowable> + + @get:Query("SELECT * FROM streams INNER JOIN stream_history ON uid = stream_id ORDER BY uid ASC") + abstract val historySortedById: Flowable> + + @Query("SELECT * FROM stream_history WHERE stream_id = :streamId ORDER BY access_date DESC LIMIT 1") + abstract fun getLatestEntry(streamId: Long): StreamHistoryEntity? + + @Query("DELETE FROM stream_history WHERE stream_id = :streamId") + abstract fun deleteStreamHistory(streamId: Long): Int + + // Select the latest entry and watch count for each stream id on history table + @RewriteQueriesToDropUnusedColumns + @Query( + """ + SELECT * FROM streams + + INNER JOIN ( + SELECT stream_id, MAX(access_date) AS latestAccess, SUM(repeat_count) AS watchCount + FROM stream_history + GROUP BY stream_id + ) + ON uid = stream_id + + LEFT JOIN (SELECT stream_id AS stream_id_alias, progress_time FROM stream_state ) + ON uid = stream_id_alias + """ + ) + abstract fun getStatistics(): Flowable> +} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/model/SearchHistoryEntry.kt b/app/src/main/java/org/schabi/newpipe/database/history/model/SearchHistoryEntry.kt index 8cb9a25ca..eee213453 100644 --- a/app/src/main/java/org/schabi/newpipe/database/history/model/SearchHistoryEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/history/model/SearchHistoryEntry.kt @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2022 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + package org.schabi.newpipe.database.history.model import androidx.room.ColumnInfo @@ -11,23 +17,24 @@ import java.time.OffsetDateTime tableName = SearchHistoryEntry.TABLE_NAME, indices = [Index(value = [SearchHistoryEntry.SEARCH])] ) -data class SearchHistoryEntry( - @field:ColumnInfo(name = CREATION_DATE) var creationDate: OffsetDateTime?, - @field:ColumnInfo( - name = SERVICE_ID - ) var serviceId: Int, - @field:ColumnInfo(name = SEARCH) var search: String? -) { +data class SearchHistoryEntry @JvmOverloads constructor( + @ColumnInfo(name = CREATION_DATE) + var creationDate: OffsetDateTime?, + + @ColumnInfo(name = SERVICE_ID) + val serviceId: Int, + + @ColumnInfo(name = SEARCH) + val search: String?, + @ColumnInfo(name = ID) @PrimaryKey(autoGenerate = true) - var id: Long = 0 + val id: Long = 0 +) { @Ignore fun hasEqualValues(otherEntry: SearchHistoryEntry): Boolean { - return ( - serviceId == otherEntry.serviceId && - search == otherEntry.search - ) + return serviceId == otherEntry.serviceId && search == otherEntry.search } companion object { diff --git a/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntity.java b/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntity.java deleted file mode 100644 index a9d69afe8..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntity.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.schabi.newpipe.database.history.model; - -import androidx.annotation.NonNull; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Index; - -import org.schabi.newpipe.database.stream.model.StreamEntity; - -import java.time.OffsetDateTime; - -import static androidx.room.ForeignKey.CASCADE; -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.JOIN_STREAM_ID; -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_ACCESS_DATE; -import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_HISTORY_TABLE; - -@Entity(tableName = STREAM_HISTORY_TABLE, - primaryKeys = {JOIN_STREAM_ID, STREAM_ACCESS_DATE}, - // No need to index for timestamp as they will almost always be unique - indices = {@Index(value = {JOIN_STREAM_ID})}, - foreignKeys = { - @ForeignKey(entity = StreamEntity.class, - parentColumns = StreamEntity.STREAM_ID, - childColumns = JOIN_STREAM_ID, - onDelete = CASCADE, onUpdate = CASCADE) - }) -public class StreamHistoryEntity { - public static final String STREAM_HISTORY_TABLE = "stream_history"; - public static final String JOIN_STREAM_ID = "stream_id"; - public static final String STREAM_ACCESS_DATE = "access_date"; - public static final String STREAM_REPEAT_COUNT = "repeat_count"; - - @ColumnInfo(name = JOIN_STREAM_ID) - private long streamUid; - - @NonNull - @ColumnInfo(name = STREAM_ACCESS_DATE) - private OffsetDateTime accessDate; - - @ColumnInfo(name = STREAM_REPEAT_COUNT) - private long repeatCount; - - /** - * @param streamUid the stream id this history item will refer to - * @param accessDate the last time the stream was accessed - * @param repeatCount the total number of views this stream received - */ - public StreamHistoryEntity(final long streamUid, - @NonNull final OffsetDateTime accessDate, - final long repeatCount) { - this.streamUid = streamUid; - this.accessDate = accessDate; - this.repeatCount = repeatCount; - } - - public long getStreamUid() { - return streamUid; - } - - public void setStreamUid(final long streamUid) { - this.streamUid = streamUid; - } - - @NonNull - public OffsetDateTime getAccessDate() { - return accessDate; - } - - public void setAccessDate(@NonNull final OffsetDateTime accessDate) { - this.accessDate = accessDate; - } - - public long getRepeatCount() { - return repeatCount; - } - - public void setRepeatCount(final long repeatCount) { - this.repeatCount = repeatCount; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntity.kt b/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntity.kt new file mode 100644 index 000000000..deba7dd3a --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntity.kt @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2018-2022 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.history.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.ForeignKey.Companion.CASCADE +import androidx.room.Index +import java.time.OffsetDateTime +import org.schabi.newpipe.database.history.model.StreamHistoryEntity.Companion.JOIN_STREAM_ID +import org.schabi.newpipe.database.history.model.StreamHistoryEntity.Companion.STREAM_ACCESS_DATE +import org.schabi.newpipe.database.history.model.StreamHistoryEntity.Companion.STREAM_HISTORY_TABLE +import org.schabi.newpipe.database.stream.model.StreamEntity +import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID + +/** + * @param streamUid the stream id this history item will refer to + * @param accessDate the last time the stream was accessed + * @param repeatCount the total number of views this stream received + */ +@Entity( + tableName = STREAM_HISTORY_TABLE, + primaryKeys = [JOIN_STREAM_ID, STREAM_ACCESS_DATE], + indices = [Index(value = [JOIN_STREAM_ID])], + foreignKeys = [ + ForeignKey( + entity = StreamEntity::class, + parentColumns = arrayOf(STREAM_ID), + childColumns = arrayOf(JOIN_STREAM_ID), + onDelete = CASCADE, + onUpdate = CASCADE + ) + ] +) +data class StreamHistoryEntity( + @ColumnInfo(name = JOIN_STREAM_ID) + val streamUid: Long, + + @ColumnInfo(name = STREAM_ACCESS_DATE) + var accessDate: OffsetDateTime, + + @ColumnInfo(name = STREAM_REPEAT_COUNT) + var repeatCount: Long +) { + companion object { + const val STREAM_HISTORY_TABLE: String = "stream_history" + const val STREAM_ACCESS_DATE: String = "access_date" + const val JOIN_STREAM_ID: String = "stream_id" + const val STREAM_REPEAT_COUNT: String = "repeat_count" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntry.kt b/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntry.kt index 27fc429f1..816b25c2a 100644 --- a/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntry.kt @@ -2,10 +2,10 @@ package org.schabi.newpipe.database.history.model import androidx.room.ColumnInfo import androidx.room.Embedded +import java.time.OffsetDateTime import org.schabi.newpipe.database.stream.model.StreamEntity import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.util.image.ImageStrategy -import java.time.OffsetDateTime data class StreamHistoryEntry( @Embedded @@ -30,16 +30,15 @@ data class StreamHistoryEntry( accessDate.isEqual(other.accessDate) } - fun toStreamInfoItem(): StreamInfoItem = - StreamInfoItem( - streamEntity.serviceId, - streamEntity.url, - streamEntity.title, - streamEntity.streamType, - ).apply { - duration = streamEntity.duration - uploaderName = streamEntity.uploader - uploaderUrl = streamEntity.uploaderUrl - thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl) - } + fun toStreamInfoItem(): StreamInfoItem = StreamInfoItem( + streamEntity.serviceId, + streamEntity.url, + streamEntity.title, + streamEntity.streamType + ).apply { + duration = streamEntity.duration + uploaderName = streamEntity.uploader + uploaderUrl = streamEntity.uploaderUrl + thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl) + } } diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistDuplicatesEntry.java b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistDuplicatesEntry.java deleted file mode 100644 index 3be85e6e1..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistDuplicatesEntry.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.schabi.newpipe.database.playlist; - -import androidx.room.ColumnInfo; - -/** - * This class adds a field to {@link PlaylistMetadataEntry} that contains an integer representing - * how many times a specific stream is already contained inside a local playlist. Used to be able - * to grey out playlists which already contain the current stream in the playlist append dialog. - * @see org.schabi.newpipe.local.playlist.LocalPlaylistManager#getPlaylistDuplicates(String) - */ -public class PlaylistDuplicatesEntry extends PlaylistMetadataEntry { - public static final String PLAYLIST_TIMES_STREAM_IS_CONTAINED = "timesStreamIsContained"; - @ColumnInfo(name = PLAYLIST_TIMES_STREAM_IS_CONTAINED) - public final long timesStreamIsContained; - - @SuppressWarnings("checkstyle:ParameterNumber") - public PlaylistDuplicatesEntry(final long uid, - final String name, - final String thumbnailUrl, - final boolean isThumbnailPermanent, - final long thumbnailStreamId, - final long displayIndex, - final long streamCount, - final long timesStreamIsContained) { - super(uid, name, thumbnailUrl, isThumbnailPermanent, thumbnailStreamId, displayIndex, - streamCount); - this.timesStreamIsContained = timesStreamIsContained; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistDuplicatesEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistDuplicatesEntry.kt new file mode 100644 index 000000000..84972a89e --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistDuplicatesEntry.kt @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist + +import androidx.room.ColumnInfo +import org.schabi.newpipe.database.playlist.model.PlaylistEntity + +/** + * This class adds a field to [PlaylistMetadataEntry] that contains an integer representing + * how many times a specific stream is already contained inside a local playlist. Used to be able + * to grey out playlists which already contain the current stream in the playlist append dialog. + * @see org.schabi.newpipe.local.playlist.LocalPlaylistManager.getPlaylistDuplicates + */ +data class PlaylistDuplicatesEntry( + @ColumnInfo(name = PlaylistEntity.PLAYLIST_ID) + override val uid: Long, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_THUMBNAIL_URL) + override val thumbnailUrl: String?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_THUMBNAIL_PERMANENT) + override val isThumbnailPermanent: Boolean?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_THUMBNAIL_STREAM_ID) + override val thumbnailStreamId: Long?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_DISPLAY_INDEX) + override var displayIndex: Long?, + + @ColumnInfo(name = PLAYLIST_STREAM_COUNT) + override val streamCount: Long, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_NAME) + override val orderingName: String?, + + @ColumnInfo(name = PLAYLIST_TIMES_STREAM_IS_CONTAINED) + val timesStreamIsContained: Long +) : PlaylistMetadataEntry( + uid = uid, + orderingName = orderingName, + thumbnailUrl = thumbnailUrl, + isThumbnailPermanent = isThumbnailPermanent, + thumbnailStreamId = thumbnailStreamId, + displayIndex = displayIndex, + streamCount = streamCount +) { + companion object { + const val PLAYLIST_TIMES_STREAM_IS_CONTAINED: String = "timesStreamIsContained" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java deleted file mode 100644 index 91f4622e9..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.schabi.newpipe.database.playlist; - -import androidx.annotation.Nullable; - -import org.schabi.newpipe.database.LocalItem; - -public interface PlaylistLocalItem extends LocalItem { - String getOrderingName(); - - long getDisplayIndex(); - - long getUid(); - - void setDisplayIndex(long displayIndex); - - @Nullable - String getThumbnailUrl(); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.kt new file mode 100644 index 000000000..4f2f79aa0 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.kt @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2018-2025 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist + +import org.schabi.newpipe.database.LocalItem + +interface PlaylistLocalItem : LocalItem { + val orderingName: String? + val displayIndex: Long? + val uid: Long + val thumbnailUrl: String? +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java deleted file mode 100644 index 8fbadb020..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.schabi.newpipe.database.playlist; - -import androidx.room.ColumnInfo; - -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_DISPLAY_INDEX; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_PERMANENT; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_STREAM_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_URL; - -import androidx.annotation.Nullable; - -public class PlaylistMetadataEntry implements PlaylistLocalItem { - public static final String PLAYLIST_STREAM_COUNT = "streamCount"; - - @ColumnInfo(name = PLAYLIST_ID) - private final long uid; - @ColumnInfo(name = PLAYLIST_NAME) - public final String name; - @ColumnInfo(name = PLAYLIST_THUMBNAIL_PERMANENT) - private final boolean isThumbnailPermanent; - @ColumnInfo(name = PLAYLIST_THUMBNAIL_STREAM_ID) - private final long thumbnailStreamId; - @ColumnInfo(name = PLAYLIST_THUMBNAIL_URL) - public final String thumbnailUrl; - @ColumnInfo(name = PLAYLIST_DISPLAY_INDEX) - private long displayIndex; - @ColumnInfo(name = PLAYLIST_STREAM_COUNT) - public final long streamCount; - - public PlaylistMetadataEntry(final long uid, final String name, final String thumbnailUrl, - final boolean isThumbnailPermanent, final long thumbnailStreamId, - final long displayIndex, final long streamCount) { - this.uid = uid; - this.name = name; - this.thumbnailUrl = thumbnailUrl; - this.isThumbnailPermanent = isThumbnailPermanent; - this.thumbnailStreamId = thumbnailStreamId; - this.displayIndex = displayIndex; - this.streamCount = streamCount; - } - - @Override - public LocalItemType getLocalItemType() { - return LocalItemType.PLAYLIST_LOCAL_ITEM; - } - - @Override - public String getOrderingName() { - return name; - } - - public boolean isThumbnailPermanent() { - return isThumbnailPermanent; - } - - public long getThumbnailStreamId() { - return thumbnailStreamId; - } - - @Override - public long getDisplayIndex() { - return displayIndex; - } - - @Override - public long getUid() { - return uid; - } - - @Override - public void setDisplayIndex(final long displayIndex) { - this.displayIndex = displayIndex; - } - - @Nullable - @Override - public String getThumbnailUrl() { - return thumbnailUrl; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.kt new file mode 100644 index 000000000..9b62c1380 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.kt @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2018-2025 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist + +import androidx.room.ColumnInfo +import org.schabi.newpipe.database.LocalItem.LocalItemType +import org.schabi.newpipe.database.playlist.model.PlaylistEntity + +open class PlaylistMetadataEntry( + @ColumnInfo(name = PlaylistEntity.PLAYLIST_ID) + override val uid: Long, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_NAME) + override val orderingName: String?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_THUMBNAIL_URL) + override val thumbnailUrl: String?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_DISPLAY_INDEX) + override var displayIndex: Long?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_THUMBNAIL_PERMANENT) + open val isThumbnailPermanent: Boolean?, + + @ColumnInfo(name = PlaylistEntity.PLAYLIST_THUMBNAIL_STREAM_ID) + open val thumbnailStreamId: Long?, + + @ColumnInfo(name = PLAYLIST_STREAM_COUNT) + open val streamCount: Long +) : PlaylistLocalItem { + + override val localItemType: LocalItemType + get() = LocalItemType.PLAYLIST_LOCAL_ITEM + + companion object { + const val PLAYLIST_STREAM_COUNT: String = "streamCount" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt index 1d74c6d31..90fdee2d3 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + package org.schabi.newpipe.database.playlist import androidx.room.ColumnInfo @@ -23,18 +29,21 @@ data class PlaylistStreamEntry( val joinIndex: Int ) : LocalItem { + override val localItemType: LocalItem.LocalItemType + get() = LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM + @Throws(IllegalArgumentException::class) fun toStreamInfoItem(): StreamInfoItem { - val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType) - item.duration = streamEntity.duration - item.uploaderName = streamEntity.uploader - item.uploaderUrl = streamEntity.uploaderUrl - item.thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl) - - return item - } - - override fun getLocalItemType(): LocalItem.LocalItemType { - return LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM + return StreamInfoItem( + streamEntity.serviceId, + streamEntity.url, + streamEntity.title, + streamEntity.streamType + ).apply { + duration = streamEntity.duration + uploaderName = streamEntity.uploader + uploaderUrl = streamEntity.uploaderUrl + thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl) + } } } diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java deleted file mode 100644 index d8071e0af..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.schabi.newpipe.database.playlist.dao; - -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.Transaction; - -import org.schabi.newpipe.database.BasicDAO; -import org.schabi.newpipe.database.playlist.model.PlaylistEntity; - -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE; - -@Dao -public interface PlaylistDAO extends BasicDAO { - @Override - @Query("SELECT * FROM " + PLAYLIST_TABLE) - Flowable> getAll(); - - @Override - @Query("DELETE FROM " + PLAYLIST_TABLE) - int deleteAll(); - - @Override - default Flowable> listByService(final int serviceId) { - throw new UnsupportedOperationException(); - } - - @Query("SELECT * FROM " + PLAYLIST_TABLE + " WHERE " + PLAYLIST_ID + " = :playlistId") - Flowable> getPlaylist(long playlistId); - - @Query("DELETE FROM " + PLAYLIST_TABLE + " WHERE " + PLAYLIST_ID + " = :playlistId") - int deletePlaylist(long playlistId); - - @Query("SELECT COUNT(*) FROM " + PLAYLIST_TABLE) - Flowable getCount(); - - @Transaction - default long upsertPlaylist(final PlaylistEntity playlist) { - final long playlistId = playlist.getUid(); - - if (playlistId == -1) { - // This situation is probably impossible. - return insert(playlist); - } else { - update(playlist); - return playlistId; - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.kt new file mode 100644 index 000000000..9c2dd89a8 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.kt @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2018-2022 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist.dao + +import androidx.room.Dao +import androidx.room.Query +import androidx.room.Transaction +import io.reactivex.rxjava3.core.Flowable +import org.schabi.newpipe.database.BasicDAO +import org.schabi.newpipe.database.playlist.model.PlaylistEntity + +@Dao +interface PlaylistDAO : BasicDAO { + + @Query("SELECT * FROM playlists") + override fun getAll(): Flowable> + + @Query("DELETE FROM playlists") + override fun deleteAll(): Int + + override fun listByService(serviceId: Int): Flowable> { + throw UnsupportedOperationException() + } + + @Query("SELECT * FROM playlists WHERE uid = :playlistId") + fun getPlaylist(playlistId: Long): Flowable> + + @Query("DELETE FROM playlists WHERE uid = :playlistId") + fun deletePlaylist(playlistId: Long): Int + + @get:Query("SELECT COUNT(*) FROM playlists") + val count: Flowable + + @Transaction + fun upsertPlaylist(playlist: PlaylistEntity): Long { + if (playlist.uid == -1L) { + // This situation is probably impossible. + return insert(playlist) + } else { + update(playlist) + return playlist.uid + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.java deleted file mode 100644 index ef77d5ade..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.schabi.newpipe.database.playlist.dao; - -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.Transaction; - -import org.schabi.newpipe.database.BasicDAO; -import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; - -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_DISPLAY_INDEX; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_SERVICE_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_TABLE; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_URL; - -@Dao -public interface PlaylistRemoteDAO extends BasicDAO { - @Override - @Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE) - Flowable> getAll(); - - @Override - @Query("DELETE FROM " + REMOTE_PLAYLIST_TABLE) - int deleteAll(); - - @Override - @Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE - + " WHERE " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId") - Flowable> listByService(int serviceId); - - @Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE " - + REMOTE_PLAYLIST_ID + " = :playlistId") - Flowable getPlaylist(long playlistId); - - @Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE " - + REMOTE_PLAYLIST_URL + " = :url AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId") - Flowable> getPlaylist(long serviceId, String url); - - @Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE - + " ORDER BY " + REMOTE_PLAYLIST_DISPLAY_INDEX) - Flowable> getPlaylists(); - - @Query("SELECT " + REMOTE_PLAYLIST_ID + " FROM " + REMOTE_PLAYLIST_TABLE - + " WHERE " + REMOTE_PLAYLIST_URL + " = :url " - + "AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId") - Long getPlaylistIdInternal(long serviceId, String url); - - @Transaction - default long upsert(final PlaylistRemoteEntity playlist) { - final Long playlistId = getPlaylistIdInternal(playlist.getServiceId(), playlist.getUrl()); - - if (playlistId == null) { - return insert(playlist); - } else { - playlist.setUid(playlistId); - update(playlist); - return playlistId; - } - } - - @Query("DELETE FROM " + REMOTE_PLAYLIST_TABLE - + " WHERE " + REMOTE_PLAYLIST_ID + " = :playlistId") - int deletePlaylist(long playlistId); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.kt new file mode 100644 index 000000000..36a80bc91 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.kt @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2018-2025 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist.dao + +import androidx.room.Dao +import androidx.room.Query +import androidx.room.Transaction +import io.reactivex.rxjava3.core.Flowable +import org.schabi.newpipe.database.BasicDAO +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity + +@Dao +interface PlaylistRemoteDAO : BasicDAO { + + @Query("SELECT * FROM remote_playlists") + override fun getAll(): Flowable> + + @Query("DELETE FROM remote_playlists") + override fun deleteAll(): Int + + @Query("SELECT * FROM remote_playlists WHERE service_id = :serviceId") + override fun listByService(serviceId: Int): Flowable> + + @Query("SELECT * FROM remote_playlists WHERE uid = :playlistId") + fun getPlaylist(playlistId: Long): Flowable + + @Query("SELECT * FROM remote_playlists WHERE url = :url AND service_id = :serviceId") + fun getPlaylist(serviceId: Long, url: String?): Flowable> + + @get:Query("SELECT * FROM remote_playlists ORDER BY display_index") + val playlists: Flowable> + + @Query("SELECT uid FROM remote_playlists WHERE url = :url AND service_id = :serviceId") + fun getPlaylistIdInternal(serviceId: Long, url: String?): Long? + + @Transaction + fun upsert(playlist: PlaylistRemoteEntity): Long { + val playlistId = getPlaylistIdInternal(playlist.serviceId.toLong(), playlist.url) + + if (playlistId == null) { + return insert(playlist) + } else { + playlist.uid = playlistId + update(playlist) + return playlistId + } + } + + @Query("DELETE FROM remote_playlists WHERE uid = :playlistId") + fun deletePlaylist(playlistId: Long): Int +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java deleted file mode 100644 index 6b77166ea..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.schabi.newpipe.database.playlist.dao; - -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.RewriteQueriesToDropUnusedColumns; -import androidx.room.Transaction; - -import org.schabi.newpipe.database.BasicDAO; -import org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry; -import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; -import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; -import org.schabi.newpipe.database.playlist.model.PlaylistEntity; -import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity; - -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -import static org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry.PLAYLIST_TIMES_STREAM_IS_CONTAINED; -import static org.schabi.newpipe.database.playlist.PlaylistMetadataEntry.PLAYLIST_STREAM_COUNT; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_DISPLAY_INDEX; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.DEFAULT_THUMBNAIL; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_PERMANENT; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_STREAM_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_URL; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_INDEX; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_STREAM_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.PLAYLIST_STREAM_JOIN_TABLE; -import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_ID; -import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE; -import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_THUMBNAIL_URL; -import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID_ALIAS; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE; - -@Dao -public interface PlaylistStreamDAO extends BasicDAO { - @Override - @Query("SELECT * FROM " + PLAYLIST_STREAM_JOIN_TABLE) - Flowable> getAll(); - - @Override - @Query("DELETE FROM " + PLAYLIST_STREAM_JOIN_TABLE) - int deleteAll(); - - @Override - default Flowable> listByService(final int serviceId) { - throw new UnsupportedOperationException(); - } - - @Query("DELETE FROM " + PLAYLIST_STREAM_JOIN_TABLE - + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId") - void deleteBatch(long playlistId); - - @Query("SELECT COALESCE(MAX(" + JOIN_INDEX + "), -1)" - + " FROM " + PLAYLIST_STREAM_JOIN_TABLE - + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId") - Flowable getMaximumIndexOf(long playlistId); - - @Query("SELECT CASE WHEN COUNT(*) != 0 then " + STREAM_ID - + " ELSE " + PlaylistEntity.DEFAULT_THUMBNAIL_ID + " END" - + " FROM " + STREAM_TABLE - + " LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID - + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId " - + " LIMIT 1" - ) - Flowable getAutomaticThumbnailStreamId(long playlistId); - - @RewriteQueriesToDropUnusedColumns - @Transaction - @Query("SELECT * FROM " + STREAM_TABLE + " INNER JOIN " - // get ids of streams of the given playlist - + "(SELECT " + JOIN_STREAM_ID + "," + JOIN_INDEX - + " FROM " + PLAYLIST_STREAM_JOIN_TABLE - + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId)" - - // then merge with the stream metadata - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID - - + " LEFT JOIN " - + "(SELECT " + JOIN_STREAM_ID + " AS " + JOIN_STREAM_ID_ALIAS + ", " - + STREAM_PROGRESS_MILLIS - + " FROM " + STREAM_STATE_TABLE + " )" - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID_ALIAS - - + " ORDER BY " + JOIN_INDEX + " ASC") - Flowable> getOrderedStreamsOf(long playlistId); - - @Transaction - @Query("SELECT " + PLAYLIST_ID + ", " + PLAYLIST_NAME + ", " - + PLAYLIST_THUMBNAIL_PERMANENT + ", " + PLAYLIST_THUMBNAIL_STREAM_ID + ", " - + PLAYLIST_DISPLAY_INDEX + ", " - - + " CASE WHEN " + PLAYLIST_THUMBNAIL_STREAM_ID + " = " - + PlaylistEntity.DEFAULT_THUMBNAIL_ID + " THEN " + "'" + DEFAULT_THUMBNAIL + "'" - + " ELSE (SELECT " + STREAM_THUMBNAIL_URL - + " FROM " + STREAM_TABLE - + " WHERE " + STREAM_TABLE + "." + STREAM_ID + " = " + PLAYLIST_THUMBNAIL_STREAM_ID - + " ) END AS " + PLAYLIST_THUMBNAIL_URL + ", " - - + "COALESCE(COUNT(" + JOIN_PLAYLIST_ID + "), 0) AS " + PLAYLIST_STREAM_COUNT - + " FROM " + PLAYLIST_TABLE - + " LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE - + " ON " + PLAYLIST_TABLE + "." + PLAYLIST_ID + " = " + JOIN_PLAYLIST_ID - + " GROUP BY " + PLAYLIST_ID - + " ORDER BY " + PLAYLIST_DISPLAY_INDEX) - Flowable> getPlaylistMetadata(); - - @RewriteQueriesToDropUnusedColumns - @Transaction - @Query("SELECT *, MIN(" + JOIN_INDEX + ")" - + " FROM " + STREAM_TABLE + " INNER JOIN" - + " (SELECT " + JOIN_STREAM_ID + "," + JOIN_INDEX - + " FROM " + PLAYLIST_STREAM_JOIN_TABLE - + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId)" - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID - + " LEFT JOIN " - + "(SELECT " + JOIN_STREAM_ID + " AS " + JOIN_STREAM_ID_ALIAS + ", " - + STREAM_PROGRESS_MILLIS - + " FROM " + STREAM_STATE_TABLE + " )" - + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID_ALIAS - + " GROUP BY " + STREAM_ID - + " ORDER BY MIN(" + JOIN_INDEX + ") ASC") - Flowable> getStreamsWithoutDuplicates(long playlistId); - - @Transaction - @Query("SELECT " + PLAYLIST_TABLE + "." + PLAYLIST_ID + ", " + PLAYLIST_NAME + ", " - + PLAYLIST_THUMBNAIL_PERMANENT + ", " + PLAYLIST_THUMBNAIL_STREAM_ID + ", " - + PLAYLIST_DISPLAY_INDEX + ", " - - + " CASE WHEN " + PLAYLIST_THUMBNAIL_STREAM_ID + " = " - + PlaylistEntity.DEFAULT_THUMBNAIL_ID + " THEN " + "'" + DEFAULT_THUMBNAIL + "'" - + " ELSE (SELECT " + STREAM_THUMBNAIL_URL - + " FROM " + STREAM_TABLE - + " WHERE " + STREAM_TABLE + "." + STREAM_ID + " = " + PLAYLIST_THUMBNAIL_STREAM_ID - + " ) END AS " + PLAYLIST_THUMBNAIL_URL + ", " - - + "COALESCE(COUNT(" + JOIN_PLAYLIST_ID + "), 0) AS " + PLAYLIST_STREAM_COUNT + ", " - + "COALESCE(SUM(" + STREAM_URL + " = :streamUrl), 0) AS " - + PLAYLIST_TIMES_STREAM_IS_CONTAINED - - + " FROM " + PLAYLIST_TABLE - + " LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE - + " ON " + PLAYLIST_TABLE + "." + PLAYLIST_ID + " = " + JOIN_PLAYLIST_ID - - + " LEFT JOIN " + STREAM_TABLE - + " ON " + STREAM_TABLE + "." + STREAM_ID + " = " + JOIN_STREAM_ID - + " AND :streamUrl = :streamUrl" - - + " GROUP BY " + JOIN_PLAYLIST_ID - + " ORDER BY " + PLAYLIST_DISPLAY_INDEX + ", " + PLAYLIST_NAME) - Flowable> getPlaylistDuplicatesMetadata(String streamUrl); -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.kt new file mode 100644 index 000000000..c6b6e37a4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.kt @@ -0,0 +1,136 @@ +/* + * SPDX-FileCopyrightText: 2018-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist.dao + +import androidx.room.Dao +import androidx.room.Query +import androidx.room.RewriteQueriesToDropUnusedColumns +import androidx.room.Transaction +import io.reactivex.rxjava3.core.Flowable +import org.schabi.newpipe.database.BasicDAO +import org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry +import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry +import org.schabi.newpipe.database.playlist.PlaylistStreamEntry +import org.schabi.newpipe.database.playlist.model.PlaylistEntity.Companion.DEFAULT_THUMBNAIL_ID +import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity + +@Dao +interface PlaylistStreamDAO : BasicDAO { + + @Query("SELECT * FROM playlist_stream_join") + override fun getAll(): Flowable> + + @Query("DELETE FROM playlist_stream_join") + override fun deleteAll(): Int + + override fun listByService(serviceId: Int): Flowable> { + throw UnsupportedOperationException() + } + + @Query("DELETE FROM playlist_stream_join WHERE playlist_id = :playlistId") + fun deleteBatch(playlistId: Long) + + @Query("SELECT COALESCE(MAX(join_index), -1) FROM playlist_stream_join WHERE playlist_id = :playlistId") + fun getMaximumIndexOf(playlistId: Long): Flowable + + @Query( + """ + SELECT CASE WHEN COUNT(*) != 0 then stream_id ELSE $DEFAULT_THUMBNAIL_ID END + FROM streams + + LEFT JOIN playlist_stream_join + ON uid = stream_id + + WHERE playlist_id = :playlistId LIMIT 1 + """ + ) + fun getAutomaticThumbnailStreamId(playlistId: Long): Flowable + + // get ids of streams of the given playlist then merge with the stream metadata + @RewriteQueriesToDropUnusedColumns + @Transaction + @Query( + """ + SELECT * FROM streams + + INNER JOIN (SELECT stream_id, join_index FROM playlist_stream_join WHERE playlist_id = :playlistId) + ON uid = stream_id + + LEFT JOIN (SELECT stream_id AS stream_id_alias, progress_time FROM stream_state ) + ON uid = stream_id_alias + + ORDER BY join_index ASC + """ + ) + fun getOrderedStreamsOf(playlistId: Long): Flowable> + + // If a playlist has no streams, there won’t be any rows in the **playlist_stream_join** table + // that have a foreign key to that playlist. Thus, the **playlist_id** will not have a + // corresponding value in any rows of the join table. So, if you group by the **playlist_id**, + // only playlists that contain videos are grouped and displayed. Look at #9642 #13055 + + @Transaction + @Query( + """ + SELECT uid, name, is_thumbnail_permanent, thumbnail_stream_id, display_index, + (SELECT thumbnail_url FROM streams WHERE streams.uid = thumbnail_stream_id) AS thumbnail_url, + + COALESCE(COUNT(playlist_id), 0) AS streamCount FROM playlists + + LEFT JOIN playlist_stream_join + ON playlists.uid = playlist_id + + GROUP BY uid + ORDER BY display_index + """ + ) + fun getPlaylistMetadata(): Flowable> + + @RewriteQueriesToDropUnusedColumns + @Transaction + @Query( + """ + SELECT *, MIN(join_index) FROM streams + + INNER JOIN (SELECT stream_id, join_index FROM playlist_stream_join WHERE playlist_id = :playlistId) + ON uid = stream_id + + LEFT JOIN (SELECT stream_id AS stream_id_alias, progress_time FROM stream_state ) + ON uid = stream_id_alias + + GROUP BY uid + ORDER BY MIN(join_index) ASC + """ + ) + fun getStreamsWithoutDuplicates(playlistId: Long): Flowable> + + // If a playlist has no streams, there won’t be any rows in the **playlist_stream_join** table + // that have a foreign key to that playlist. Thus, the **playlist_id** will not have a + // corresponding value in any rows of the join table. So, if you group by the **playlist_id**, + // only playlists that contain videos are grouped and displayed. Look at #9642 #13055 + + @Transaction + @Query( + """ + SELECT playlists.uid, name, is_thumbnail_permanent, thumbnail_stream_id, display_index, + (SELECT thumbnail_url FROM streams WHERE streams.uid = thumbnail_stream_id) AS thumbnail_url, + + COALESCE(COUNT(playlist_id), 0) AS streamCount, + COALESCE(SUM(url = :streamUrl), 0) AS timesStreamIsContained FROM playlists + + LEFT JOIN playlist_stream_join + ON playlists.uid = playlist_id + + LEFT JOIN streams + ON streams.uid = stream_id AND :streamUrl = :streamUrl + + GROUP BY playlists.uid + ORDER BY display_index, name + """ + ) + fun getPlaylistDuplicatesMetadata(streamUrl: String): Flowable> +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java deleted file mode 100644 index e0c1a06b7..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.schabi.newpipe.database.playlist.model; - -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; - -@Entity(tableName = PLAYLIST_TABLE) -public class PlaylistEntity { - - public static final String DEFAULT_THUMBNAIL = "drawable://" - + R.drawable.placeholder_thumbnail_playlist; - public static final long DEFAULT_THUMBNAIL_ID = -1; - - public static final String PLAYLIST_TABLE = "playlists"; - public static final String PLAYLIST_ID = "uid"; - public static final String PLAYLIST_NAME = "name"; - public static final String PLAYLIST_THUMBNAIL_URL = "thumbnail_url"; - public static final String PLAYLIST_DISPLAY_INDEX = "display_index"; - public static final String PLAYLIST_THUMBNAIL_PERMANENT = "is_thumbnail_permanent"; - public static final String PLAYLIST_THUMBNAIL_STREAM_ID = "thumbnail_stream_id"; - - @PrimaryKey(autoGenerate = true) - @ColumnInfo(name = PLAYLIST_ID) - private long uid = 0; - - @ColumnInfo(name = PLAYLIST_NAME) - private String name; - - @ColumnInfo(name = PLAYLIST_THUMBNAIL_PERMANENT) - private boolean isThumbnailPermanent; - - @ColumnInfo(name = PLAYLIST_THUMBNAIL_STREAM_ID) - private long thumbnailStreamId; - - @ColumnInfo(name = PLAYLIST_DISPLAY_INDEX) - private long displayIndex; - - public PlaylistEntity(final String name, final boolean isThumbnailPermanent, - final long thumbnailStreamId, final long displayIndex) { - this.name = name; - this.isThumbnailPermanent = isThumbnailPermanent; - this.thumbnailStreamId = thumbnailStreamId; - this.displayIndex = displayIndex; - } - - @Ignore - public PlaylistEntity(final PlaylistMetadataEntry item) { - this.uid = item.getUid(); - this.name = item.name; - this.isThumbnailPermanent = item.isThumbnailPermanent(); - this.thumbnailStreamId = item.getThumbnailStreamId(); - this.displayIndex = item.getDisplayIndex(); - } - - public long getUid() { - return uid; - } - - public void setUid(final long uid) { - this.uid = uid; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public long getThumbnailStreamId() { - return thumbnailStreamId; - } - - public void setThumbnailStreamId(final long thumbnailStreamId) { - this.thumbnailStreamId = thumbnailStreamId; - } - - public boolean getIsThumbnailPermanent() { - return isThumbnailPermanent; - } - - public void setIsThumbnailPermanent(final boolean isThumbnailSet) { - this.isThumbnailPermanent = isThumbnailSet; - } - - public long getDisplayIndex() { - return displayIndex; - } - - public void setDisplayIndex(final long displayIndex) { - this.displayIndex = displayIndex; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.kt new file mode 100644 index 000000000..1f1862f4f --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.kt @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2018-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Ignore +import androidx.room.PrimaryKey +import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry + +@Entity(tableName = PlaylistEntity.Companion.PLAYLIST_TABLE) +data class PlaylistEntity @JvmOverloads constructor( + @PrimaryKey(autoGenerate = true) + @ColumnInfo(name = PLAYLIST_ID) + var uid: Long = 0, + + @ColumnInfo(name = PLAYLIST_NAME) + var name: String?, + + @ColumnInfo(name = PLAYLIST_THUMBNAIL_PERMANENT) + var isThumbnailPermanent: Boolean, + + @ColumnInfo(name = PLAYLIST_THUMBNAIL_STREAM_ID) + var thumbnailStreamId: Long, + + @ColumnInfo(name = PLAYLIST_DISPLAY_INDEX) + var displayIndex: Long +) { + + @Ignore + constructor(item: PlaylistMetadataEntry) : this( + uid = item.uid, + name = item.orderingName, + isThumbnailPermanent = item.isThumbnailPermanent!!, + thumbnailStreamId = item.thumbnailStreamId!!, + displayIndex = item.displayIndex!! + ) + + companion object { + const val DEFAULT_THUMBNAIL_ID = -1L + + const val PLAYLIST_TABLE = "playlists" + const val PLAYLIST_ID = "uid" + const val PLAYLIST_NAME = "name" + const val PLAYLIST_THUMBNAIL_URL = "thumbnail_url" + const val PLAYLIST_DISPLAY_INDEX = "display_index" + const val PLAYLIST_THUMBNAIL_PERMANENT = "is_thumbnail_permanent" + const val PLAYLIST_THUMBNAIL_STREAM_ID = "thumbnail_stream_id" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java deleted file mode 100644 index 0b0e3605e..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.schabi.newpipe.database.playlist.model; - -import android.text.TextUtils; - -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.Index; -import androidx.room.PrimaryKey; - -import org.schabi.newpipe.database.playlist.PlaylistLocalItem; -import org.schabi.newpipe.extractor.playlist.PlaylistInfo; -import org.schabi.newpipe.util.Constants; -import org.schabi.newpipe.util.image.ImageStrategy; - -import static org.schabi.newpipe.database.LocalItem.LocalItemType.PLAYLIST_REMOTE_ITEM; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_NAME; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_SERVICE_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_TABLE; -import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_URL; - -@Entity(tableName = REMOTE_PLAYLIST_TABLE, - indices = { - @Index(value = {REMOTE_PLAYLIST_SERVICE_ID, REMOTE_PLAYLIST_URL}, unique = true) - }) -public class PlaylistRemoteEntity implements PlaylistLocalItem { - public static final String REMOTE_PLAYLIST_TABLE = "remote_playlists"; - public static final String REMOTE_PLAYLIST_ID = "uid"; - public static final String REMOTE_PLAYLIST_SERVICE_ID = "service_id"; - public static final String REMOTE_PLAYLIST_NAME = "name"; - public static final String REMOTE_PLAYLIST_URL = "url"; - public static final String REMOTE_PLAYLIST_THUMBNAIL_URL = "thumbnail_url"; - public static final String REMOTE_PLAYLIST_UPLOADER_NAME = "uploader"; - public static final String REMOTE_PLAYLIST_DISPLAY_INDEX = "display_index"; - public static final String REMOTE_PLAYLIST_STREAM_COUNT = "stream_count"; - - @PrimaryKey(autoGenerate = true) - @ColumnInfo(name = REMOTE_PLAYLIST_ID) - private long uid = 0; - - @ColumnInfo(name = REMOTE_PLAYLIST_SERVICE_ID) - private int serviceId = Constants.NO_SERVICE_ID; - - @ColumnInfo(name = REMOTE_PLAYLIST_NAME) - private String name; - - @ColumnInfo(name = REMOTE_PLAYLIST_URL) - private String url; - - @ColumnInfo(name = REMOTE_PLAYLIST_THUMBNAIL_URL) - private String thumbnailUrl; - - @ColumnInfo(name = REMOTE_PLAYLIST_UPLOADER_NAME) - private String uploader; - - @ColumnInfo(name = REMOTE_PLAYLIST_DISPLAY_INDEX) - private long displayIndex = -1; // Make sure the new item is on the top - - @ColumnInfo(name = REMOTE_PLAYLIST_STREAM_COUNT) - private Long streamCount; - - public PlaylistRemoteEntity(final int serviceId, final String name, final String url, - final String thumbnailUrl, final String uploader, - final Long streamCount) { - this.serviceId = serviceId; - this.name = name; - this.url = url; - this.thumbnailUrl = thumbnailUrl; - this.uploader = uploader; - this.streamCount = streamCount; - } - - @Ignore - public PlaylistRemoteEntity(final int serviceId, final String name, final String url, - final String thumbnailUrl, final String uploader, - final long displayIndex, final Long streamCount) { - this.serviceId = serviceId; - this.name = name; - this.url = url; - this.thumbnailUrl = thumbnailUrl; - this.uploader = uploader; - this.displayIndex = displayIndex; - this.streamCount = streamCount; - } - - @Ignore - public PlaylistRemoteEntity(final PlaylistInfo info) { - this(info.getServiceId(), info.getName(), info.getUrl(), - // use uploader avatar when no thumbnail is available - ImageStrategy.imageListToDbUrl(info.getThumbnails().isEmpty() - ? info.getUploaderAvatars() : info.getThumbnails()), - info.getUploaderName(), info.getStreamCount()); - } - - @Ignore - public boolean isIdenticalTo(final PlaylistInfo info) { - /* - * Returns boolean comparing the online playlist and the local copy. - * (False if info changed such as playlist name or track count) - */ - return getServiceId() == info.getServiceId() - && getStreamCount() == info.getStreamCount() - && TextUtils.equals(getName(), info.getName()) - && TextUtils.equals(getUrl(), info.getUrl()) - // we want to update the local playlist data even when either the remote thumbnail - // URL changes, or the preferred image quality setting is changed by the user - && TextUtils.equals(getThumbnailUrl(), - ImageStrategy.imageListToDbUrl(info.getThumbnails())) - && TextUtils.equals(getUploader(), info.getUploaderName()); - } - - @Override - public long getUid() { - return uid; - } - - public void setUid(final long uid) { - this.uid = uid; - } - - public int getServiceId() { - return serviceId; - } - - public void setServiceId(final int serviceId) { - this.serviceId = serviceId; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - @Nullable - @Override - public String getThumbnailUrl() { - return thumbnailUrl; - } - - public void setThumbnailUrl(final String thumbnailUrl) { - this.thumbnailUrl = thumbnailUrl; - } - - public String getUrl() { - return url; - } - - public void setUrl(final String url) { - this.url = url; - } - - public String getUploader() { - return uploader; - } - - public void setUploader(final String uploader) { - this.uploader = uploader; - } - - @Override - public long getDisplayIndex() { - return displayIndex; - } - - @Override - public void setDisplayIndex(final long displayIndex) { - this.displayIndex = displayIndex; - } - - public Long getStreamCount() { - return streamCount; - } - - public void setStreamCount(final Long streamCount) { - this.streamCount = streamCount; - } - - @Override - public LocalItemType getLocalItemType() { - return PLAYLIST_REMOTE_ITEM; - } - - @Override - public String getOrderingName() { - return name; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt new file mode 100644 index 000000000..82162e1e4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.kt @@ -0,0 +1,104 @@ +/* + * SPDX-FileCopyrightText: 2018-2025 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist.model + +import android.text.TextUtils +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Ignore +import androidx.room.Index +import androidx.room.PrimaryKey +import org.schabi.newpipe.database.LocalItem.LocalItemType +import org.schabi.newpipe.database.playlist.PlaylistLocalItem +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.Companion.REMOTE_PLAYLIST_SERVICE_ID +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.Companion.REMOTE_PLAYLIST_TABLE +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.Companion.REMOTE_PLAYLIST_URL +import org.schabi.newpipe.extractor.playlist.PlaylistInfo +import org.schabi.newpipe.util.NO_SERVICE_ID +import org.schabi.newpipe.util.image.ImageStrategy + +@Entity( + tableName = REMOTE_PLAYLIST_TABLE, + indices = [ + Index( + value = [REMOTE_PLAYLIST_SERVICE_ID, REMOTE_PLAYLIST_URL], + unique = true + ) + ] +) +data class PlaylistRemoteEntity( + @PrimaryKey(autoGenerate = true) + @ColumnInfo(name = REMOTE_PLAYLIST_ID) + override var uid: Long = 0, + + @ColumnInfo(name = REMOTE_PLAYLIST_SERVICE_ID) + val serviceId: Int = NO_SERVICE_ID, + + @ColumnInfo(name = REMOTE_PLAYLIST_NAME) + override val orderingName: String?, + + @ColumnInfo(name = REMOTE_PLAYLIST_URL) + val url: String?, + + @ColumnInfo(name = REMOTE_PLAYLIST_THUMBNAIL_URL) + override val thumbnailUrl: String?, + + @ColumnInfo(name = REMOTE_PLAYLIST_UPLOADER_NAME) + val uploader: String?, + + @ColumnInfo(name = REMOTE_PLAYLIST_DISPLAY_INDEX) + override var displayIndex: Long = -1, // Make sure the new item is on the top + + @ColumnInfo(name = REMOTE_PLAYLIST_STREAM_COUNT) + val streamCount: Long? +) : PlaylistLocalItem { + + constructor(playlistInfo: PlaylistInfo) : this( + serviceId = playlistInfo.serviceId, + orderingName = playlistInfo.name, + url = playlistInfo.url, + thumbnailUrl = ImageStrategy.imageListToDbUrl( + if (playlistInfo.thumbnails.isEmpty()) { + playlistInfo.uploaderAvatars + } else { + playlistInfo.thumbnails + } + ), + uploader = playlistInfo.uploaderName, + streamCount = playlistInfo.streamCount + ) + + override val localItemType: LocalItemType + get() = LocalItemType.PLAYLIST_REMOTE_ITEM + + /** + * Returns boolean comparing the online playlist and the local copy. + * (False if info changed such as playlist name or track count) + */ + @Ignore + fun isIdenticalTo(info: PlaylistInfo): Boolean { + return this.serviceId == info.serviceId && this.streamCount == info.streamCount && + TextUtils.equals(this.orderingName, info.name) && + TextUtils.equals(this.url, info.url) && + // we want to update the local playlist data even when either the remote thumbnail + // URL changes, or the preferred image quality setting is changed by the user + TextUtils.equals(thumbnailUrl, ImageStrategy.imageListToDbUrl(info.thumbnails)) && + TextUtils.equals(this.uploader, info.uploaderName) + } + + companion object { + const val REMOTE_PLAYLIST_TABLE = "remote_playlists" + const val REMOTE_PLAYLIST_ID = "uid" + const val REMOTE_PLAYLIST_SERVICE_ID = "service_id" + const val REMOTE_PLAYLIST_NAME = "name" + const val REMOTE_PLAYLIST_URL = "url" + const val REMOTE_PLAYLIST_THUMBNAIL_URL = "thumbnail_url" + const val REMOTE_PLAYLIST_UPLOADER_NAME = "uploader" + const val REMOTE_PLAYLIST_DISPLAY_INDEX = "display_index" + const val REMOTE_PLAYLIST_STREAM_COUNT = "stream_count" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistStreamEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistStreamEntity.java deleted file mode 100644 index f3208b6d5..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistStreamEntity.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.schabi.newpipe.database.playlist.model; - -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Index; - -import org.schabi.newpipe.database.stream.model.StreamEntity; - -import static androidx.room.ForeignKey.CASCADE; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_INDEX; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_STREAM_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.PLAYLIST_STREAM_JOIN_TABLE; - -@Entity(tableName = PLAYLIST_STREAM_JOIN_TABLE, - primaryKeys = {JOIN_PLAYLIST_ID, JOIN_INDEX}, - indices = { - @Index(value = {JOIN_PLAYLIST_ID, JOIN_INDEX}, unique = true), - @Index(value = {JOIN_STREAM_ID}) - }, - foreignKeys = { - @ForeignKey(entity = PlaylistEntity.class, - parentColumns = PlaylistEntity.PLAYLIST_ID, - childColumns = JOIN_PLAYLIST_ID, - onDelete = CASCADE, onUpdate = CASCADE, deferred = true), - @ForeignKey(entity = StreamEntity.class, - parentColumns = StreamEntity.STREAM_ID, - childColumns = JOIN_STREAM_ID, - onDelete = CASCADE, onUpdate = CASCADE, deferred = true) - }) -public class PlaylistStreamEntity { - public static final String PLAYLIST_STREAM_JOIN_TABLE = "playlist_stream_join"; - public static final String JOIN_PLAYLIST_ID = "playlist_id"; - public static final String JOIN_STREAM_ID = "stream_id"; - public static final String JOIN_INDEX = "join_index"; - - @ColumnInfo(name = JOIN_PLAYLIST_ID) - private long playlistUid; - - @ColumnInfo(name = JOIN_STREAM_ID) - private long streamUid; - - @ColumnInfo(name = JOIN_INDEX) - private int index; - - public PlaylistStreamEntity(final long playlistUid, final long streamUid, final int index) { - this.playlistUid = playlistUid; - this.streamUid = streamUid; - this.index = index; - } - - public long getPlaylistUid() { - return playlistUid; - } - - public void setPlaylistUid(final long playlistUid) { - this.playlistUid = playlistUid; - } - - public long getStreamUid() { - return streamUid; - } - - public void setStreamUid(final long streamUid) { - this.streamUid = streamUid; - } - - public int getIndex() { - return index; - } - - public void setIndex(final int index) { - this.index = index; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistStreamEntity.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistStreamEntity.kt new file mode 100644 index 000000000..6ab1b6ac4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistStreamEntity.kt @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2018-2020 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.ForeignKey.Companion.CASCADE +import androidx.room.Index +import org.schabi.newpipe.database.LocalItem +import org.schabi.newpipe.database.playlist.model.PlaylistEntity.Companion.PLAYLIST_ID +import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.Companion.JOIN_INDEX +import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.Companion.JOIN_PLAYLIST_ID +import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.Companion.JOIN_STREAM_ID +import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.Companion.PLAYLIST_STREAM_JOIN_TABLE +import org.schabi.newpipe.database.stream.model.StreamEntity + +@Entity( + tableName = PLAYLIST_STREAM_JOIN_TABLE, + primaryKeys = [JOIN_PLAYLIST_ID, JOIN_INDEX], + indices = [ + Index(value = [JOIN_PLAYLIST_ID, JOIN_INDEX], unique = true), + Index(value = [JOIN_STREAM_ID]) + ], + foreignKeys = [ + ForeignKey( + entity = PlaylistEntity::class, + parentColumns = arrayOf(PLAYLIST_ID), + childColumns = arrayOf(JOIN_PLAYLIST_ID), + onDelete = CASCADE, + onUpdate = CASCADE, + deferred = true + ), + ForeignKey( + entity = StreamEntity::class, + parentColumns = arrayOf(StreamEntity.STREAM_ID), + childColumns = arrayOf(JOIN_STREAM_ID), + onDelete = CASCADE, + onUpdate = CASCADE, + deferred = true + ) + ] +) +data class PlaylistStreamEntity( + @ColumnInfo(name = JOIN_PLAYLIST_ID) + val playlistUid: Long, + + @ColumnInfo(name = JOIN_STREAM_ID) + val streamUid: Long, + + @ColumnInfo(name = JOIN_INDEX) + val index: Int +) : LocalItem { + + override val localItemType: LocalItem.LocalItemType + get() = LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM + + companion object { + const val PLAYLIST_STREAM_JOIN_TABLE = "playlist_stream_join" + const val JOIN_PLAYLIST_ID = "playlist_id" + const val JOIN_STREAM_ID = "stream_id" + const val JOIN_INDEX = "join_index" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt b/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt index 1f3654e7a..ce74678ca 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt @@ -1,16 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + package org.schabi.newpipe.database.stream import androidx.room.ColumnInfo import androidx.room.Embedded +import androidx.room.Ignore +import java.time.OffsetDateTime import org.schabi.newpipe.database.LocalItem import org.schabi.newpipe.database.history.model.StreamHistoryEntity import org.schabi.newpipe.database.stream.model.StreamEntity -import org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS +import org.schabi.newpipe.database.stream.model.StreamStateEntity.Companion.STREAM_PROGRESS_MILLIS import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.util.image.ImageStrategy -import java.time.OffsetDateTime -class StreamStatisticsEntry( +data class StreamStatisticsEntry( @Embedded val streamEntity: StreamEntity, @@ -26,18 +33,23 @@ class StreamStatisticsEntry( @ColumnInfo(name = STREAM_WATCH_COUNT) val watchCount: Long ) : LocalItem { + + override val localItemType: LocalItem.LocalItemType + get() = LocalItem.LocalItemType.STATISTIC_STREAM_ITEM + + @Ignore fun toStreamInfoItem(): StreamInfoItem { - val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType) - item.duration = streamEntity.duration - item.uploaderName = streamEntity.uploader - item.uploaderUrl = streamEntity.uploaderUrl - item.thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl) - - return item - } - - override fun getLocalItemType(): LocalItem.LocalItemType { - return LocalItem.LocalItemType.STATISTIC_STREAM_ITEM + return StreamInfoItem( + streamEntity.serviceId, + streamEntity.url, + streamEntity.title, + streamEntity.streamType + ).apply { + duration = streamEntity.duration + uploaderName = streamEntity.uploader + uploaderUrl = streamEntity.uploaderUrl + thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl) + } } companion object { diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt index d8c19c1e9..a6ab2c6cc 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt @@ -8,12 +8,12 @@ import androidx.room.Query import androidx.room.Transaction import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable +import java.time.OffsetDateTime import org.schabi.newpipe.database.BasicDAO import org.schabi.newpipe.database.stream.model.StreamEntity import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID import org.schabi.newpipe.extractor.stream.StreamType import org.schabi.newpipe.util.StreamTypeUtil -import java.time.OffsetDateTime @Dao abstract class StreamDAO : BasicDAO { @@ -91,7 +91,6 @@ abstract class StreamDAO : BasicDAO { newerStream.uid = existentMinimalStream.uid if (!StreamTypeUtil.isLiveStream(newerStream.streamType)) { - // Use the existent upload date if the newer stream does not have a better precision // (i.e. is an approximation). This is done to prevent unnecessary changes. val hasBetterPrecision = diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.java b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.java deleted file mode 100644 index 06371248d..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.schabi.newpipe.database.stream.dao; - -import androidx.room.Dao; -import androidx.room.Insert; -import androidx.room.OnConflictStrategy; -import androidx.room.Query; -import androidx.room.Transaction; - -import org.schabi.newpipe.database.BasicDAO; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; - -import java.util.List; - -import io.reactivex.rxjava3.core.Flowable; - -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE; - -@Dao -public interface StreamStateDAO extends BasicDAO { - @Override - @Query("SELECT * FROM " + STREAM_STATE_TABLE) - Flowable> getAll(); - - @Override - @Query("DELETE FROM " + STREAM_STATE_TABLE) - int deleteAll(); - - @Override - default Flowable> listByService(final int serviceId) { - throw new UnsupportedOperationException(); - } - - @Query("SELECT * FROM " + STREAM_STATE_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId") - Flowable> getState(long streamId); - - @Query("DELETE FROM " + STREAM_STATE_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId") - int deleteState(long streamId); - - @Insert(onConflict = OnConflictStrategy.IGNORE) - void silentInsertInternal(StreamStateEntity streamState); - - @Transaction - default long upsert(final StreamStateEntity stream) { - silentInsertInternal(stream); - return update(stream); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.kt b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.kt new file mode 100644 index 000000000..f3c44f1f2 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.kt @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2018-2021 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.stream.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Transaction +import io.reactivex.rxjava3.core.Flowable +import org.schabi.newpipe.database.BasicDAO +import org.schabi.newpipe.database.stream.model.StreamStateEntity + +@Dao +interface StreamStateDAO : BasicDAO { + + @Query("SELECT * FROM " + StreamStateEntity.STREAM_STATE_TABLE) + override fun getAll(): Flowable> + + @Query("DELETE FROM " + StreamStateEntity.STREAM_STATE_TABLE) + override fun deleteAll(): Int + + override fun listByService(serviceId: Int): Flowable> { + throw UnsupportedOperationException() + } + + @Query("SELECT * FROM " + StreamStateEntity.STREAM_STATE_TABLE + " WHERE " + StreamStateEntity.JOIN_STREAM_ID + " = :streamId") + fun getState(streamId: Long): Flowable> + + @Query("DELETE FROM " + StreamStateEntity.STREAM_STATE_TABLE + " WHERE " + StreamStateEntity.JOIN_STREAM_ID + " = :streamId") + fun deleteState(streamId: Long): Int + + @Insert(onConflict = OnConflictStrategy.Companion.IGNORE) + fun silentInsertInternal(streamState: StreamStateEntity) + + @Transaction + fun upsert(stream: StreamStateEntity): Long { + silentInsertInternal(stream) + return update(stream).toLong() + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt index d9c160b89..067f666b6 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt @@ -5,6 +5,8 @@ import androidx.room.Entity import androidx.room.Ignore import androidx.room.Index import androidx.room.PrimaryKey +import java.io.Serializable +import java.time.OffsetDateTime import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_SERVICE_ID import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_TABLE import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_URL @@ -14,8 +16,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.extractor.stream.StreamType import org.schabi.newpipe.player.playqueue.PlayQueueItem import org.schabi.newpipe.util.image.ImageStrategy -import java.io.Serializable -import java.time.OffsetDateTime @Entity( tableName = STREAM_TABLE, @@ -86,8 +86,12 @@ data class StreamEntity( @Ignore constructor(item: PlayQueueItem) : this( - serviceId = item.serviceId, url = item.url, title = item.title, - streamType = item.streamType, duration = item.duration, uploader = item.uploader, + serviceId = item.serviceId, + url = item.url, + title = item.title, + streamType = item.streamType, + duration = item.duration, + uploader = item.uploader, uploaderUrl = item.uploaderUrl, thumbnailUrl = ImageStrategy.imageListToDbUrl(item.thumbnails) ) diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.java b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.java deleted file mode 100644 index 627acea45..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.schabi.newpipe.database.stream.model; - -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; - -import java.util.Objects; - -import static androidx.room.ForeignKey.CASCADE; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE; - -@Entity(tableName = STREAM_STATE_TABLE, - primaryKeys = {JOIN_STREAM_ID}, - foreignKeys = { - @ForeignKey(entity = StreamEntity.class, - parentColumns = StreamEntity.STREAM_ID, - childColumns = JOIN_STREAM_ID, - onDelete = CASCADE, onUpdate = CASCADE) - }) -public class StreamStateEntity { - public static final String STREAM_STATE_TABLE = "stream_state"; - public static final String JOIN_STREAM_ID = "stream_id"; - // This additional field is required for the SQL query because 'stream_id' is used - // for some other joins already - public static final String JOIN_STREAM_ID_ALIAS = "stream_id_alias"; - public static final String STREAM_PROGRESS_MILLIS = "progress_time"; - - /** - * Playback state will not be saved, if playback time is less than this threshold (5000ms = 5s). - */ - public static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000; - - /** - * Stream will be considered finished if the playback time left exceeds this threshold - * (60000ms = 60s). - * @see #isFinished(long) - * @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams() - * @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreamsForGroup(long) - */ - public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000; - - @ColumnInfo(name = JOIN_STREAM_ID) - private long streamUid; - - @ColumnInfo(name = STREAM_PROGRESS_MILLIS) - private long progressMillis; - - public StreamStateEntity(final long streamUid, final long progressMillis) { - this.streamUid = streamUid; - this.progressMillis = progressMillis; - } - - public long getStreamUid() { - return streamUid; - } - - public void setStreamUid(final long streamUid) { - this.streamUid = streamUid; - } - - public long getProgressMillis() { - return progressMillis; - } - - public void setProgressMillis(final long progressMillis) { - this.progressMillis = progressMillis; - } - - /** - * The state will be considered valid, and thus be saved, if the progress is more than {@link - * #PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS} or at least 1/4 of the video length. - * @param durationInSeconds the duration of the stream connected with this state, in seconds - * @return whether this stream state entity should be saved or not - */ - public boolean isValid(final long durationInSeconds) { - return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS - || progressMillis > durationInSeconds * 1000 / 4; - } - - /** - * The video will be considered as finished, if the time left is less than {@link - * #PLAYBACK_FINISHED_END_MILLISECONDS} and the progress is at least 3/4 of the video length. - * The state will be saved anyway, so that it can be shown under stream info items, but the - * player will not resume if a state is considered as finished. Finished streams are also the - * ones that can be filtered out in the feed fragment. - * @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams() - * @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreamsForGroup(long) - * @param durationInSeconds the duration of the stream connected with this state, in seconds - * @return whether the stream is finished or not - */ - public boolean isFinished(final long durationInSeconds) { - return progressMillis >= durationInSeconds * 1000 - PLAYBACK_FINISHED_END_MILLISECONDS - && progressMillis >= durationInSeconds * 1000 * 3 / 4; - } - - @Override - public boolean equals(@Nullable final Object obj) { - if (obj instanceof StreamStateEntity) { - return ((StreamStateEntity) obj).streamUid == streamUid - && ((StreamStateEntity) obj).progressMillis == progressMillis; - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hash(streamUid, progressMillis); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.kt b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.kt new file mode 100644 index 000000000..759a2dcec --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamStateEntity.kt @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2018-2023 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.stream.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.ForeignKey.Companion.CASCADE +import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID +import org.schabi.newpipe.database.stream.model.StreamStateEntity.Companion.JOIN_STREAM_ID +import org.schabi.newpipe.database.stream.model.StreamStateEntity.Companion.PLAYBACK_FINISHED_END_MILLISECONDS +import org.schabi.newpipe.database.stream.model.StreamStateEntity.Companion.STREAM_STATE_TABLE + +@Entity( + tableName = STREAM_STATE_TABLE, + primaryKeys = [JOIN_STREAM_ID], + foreignKeys = [ + ForeignKey( + entity = StreamEntity::class, + parentColumns = arrayOf(STREAM_ID), + childColumns = arrayOf(JOIN_STREAM_ID), + onDelete = CASCADE, + onUpdate = CASCADE + ) + ] +) +data class StreamStateEntity( + @ColumnInfo(name = JOIN_STREAM_ID) + val streamUid: Long, + + @ColumnInfo(name = STREAM_PROGRESS_MILLIS) + val progressMillis: Long +) { + /** + * The state will be considered valid, and thus be saved, if the progress is more than + * [PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS] or at least 1/4 of the video length. + * @param durationInSeconds the duration of the stream connected with this state, in seconds + * @return whether this stream state entity should be saved or not + */ + fun isValid(durationInSeconds: Long): Boolean { + return progressMillis > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS || + progressMillis > durationInSeconds * 1000 / 4 + } + + /** + * The video will be considered as finished, if the time left is less than + * [PLAYBACK_FINISHED_END_MILLISECONDS] and the progress is at least 3/4 of the video length. + * The state will be saved anyway, so that it can be shown under stream info items, but the + * player will not resume if a state is considered as finished. Finished streams are also the + * ones that can be filtered out in the feed fragment. + * @param durationInSeconds the duration of the stream connected with this state, in seconds + * @return whether the stream is finished or not + */ + fun isFinished(durationInSeconds: Long): Boolean { + return progressMillis >= durationInSeconds * 1000 - PLAYBACK_FINISHED_END_MILLISECONDS && + progressMillis >= durationInSeconds * 1000 * 3 / 4 + } + + companion object { + const val STREAM_STATE_TABLE = "stream_state" + const val JOIN_STREAM_ID = "stream_id" + + // This additional field is required for the SQL query because 'stream_id' is used + // for some other joins already + const val JOIN_STREAM_ID_ALIAS = "stream_id_alias" + const val STREAM_PROGRESS_MILLIS = "progress_time" + + /** + * Playback state will not be saved, if playback time is less than this threshold + * (5000ms = 5s). + */ + const val PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000L + + /** + * Stream will be considered finished if the playback time left exceeds this threshold + * (60000ms = 60s). + * @see org.schabi.newpipe.database.stream.model.StreamStateEntity.isFinished + */ + const val PLAYBACK_FINISHED_END_MILLISECONDS = 60000L + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/NotificationMode.java b/app/src/main/java/org/schabi/newpipe/database/subscription/NotificationMode.java deleted file mode 100644 index 07e0eb7d3..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/subscription/NotificationMode.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.schabi.newpipe.database.subscription; - -import androidx.annotation.IntDef; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@IntDef({NotificationMode.DISABLED, NotificationMode.ENABLED}) -@Retention(RetentionPolicy.SOURCE) -public @interface NotificationMode { - - int DISABLED = 0; - int ENABLED = 1; - //other values reserved for the future -} diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/NotificationMode.kt b/app/src/main/java/org/schabi/newpipe/database/subscription/NotificationMode.kt new file mode 100644 index 000000000..f9bb18c0c --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/subscription/NotificationMode.kt @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2021 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.subscription + +import androidx.annotation.IntDef + +@IntDef(NotificationMode.Companion.DISABLED, NotificationMode.Companion.ENABLED) +@Retention(AnnotationRetention.SOURCE) +annotation class NotificationMode { + companion object { + const val DISABLED = 0 + const val ENABLED = 1 // other values reserved for the future + } +} diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt index 47b6f4dd9..e6fdcbf70 100644 --- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.kt @@ -99,7 +99,7 @@ abstract class SubscriptionDAO : BasicDAO { if (uidFromInsert != -1L) { entity.uid = uidFromInsert } else { - val subscriptionIdFromDb = getSubscriptionIdInternal(entity.serviceId, entity.url) + val subscriptionIdFromDb = getSubscriptionIdInternal(entity.serviceId, entity.url!!) ?: throw IllegalStateException("Subscription cannot be null just after insertion.") entity.uid = subscriptionIdFromDb diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java deleted file mode 100644 index df5a3067a..000000000 --- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java +++ /dev/null @@ -1,200 +0,0 @@ -package org.schabi.newpipe.database.subscription; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.Index; -import androidx.room.PrimaryKey; - -import org.schabi.newpipe.extractor.channel.ChannelInfo; -import org.schabi.newpipe.extractor.channel.ChannelInfoItem; -import org.schabi.newpipe.util.Constants; -import org.schabi.newpipe.util.image.ImageStrategy; - -import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_SERVICE_ID; -import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_TABLE; -import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_URL; - -@Entity(tableName = SUBSCRIPTION_TABLE, - indices = {@Index(value = {SUBSCRIPTION_SERVICE_ID, SUBSCRIPTION_URL}, unique = true)}) -public class SubscriptionEntity { - public static final String SUBSCRIPTION_UID = "uid"; - public static final String SUBSCRIPTION_TABLE = "subscriptions"; - public static final String SUBSCRIPTION_SERVICE_ID = "service_id"; - public static final String SUBSCRIPTION_URL = "url"; - public static final String SUBSCRIPTION_NAME = "name"; - public static final String SUBSCRIPTION_AVATAR_URL = "avatar_url"; - public static final String SUBSCRIPTION_SUBSCRIBER_COUNT = "subscriber_count"; - public static final String SUBSCRIPTION_DESCRIPTION = "description"; - public static final String SUBSCRIPTION_NOTIFICATION_MODE = "notification_mode"; - - @PrimaryKey(autoGenerate = true) - private long uid = 0; - - @ColumnInfo(name = SUBSCRIPTION_SERVICE_ID) - private int serviceId = Constants.NO_SERVICE_ID; - - @ColumnInfo(name = SUBSCRIPTION_URL) - private String url; - - @ColumnInfo(name = SUBSCRIPTION_NAME) - private String name; - - @ColumnInfo(name = SUBSCRIPTION_AVATAR_URL) - private String avatarUrl; - - @ColumnInfo(name = SUBSCRIPTION_SUBSCRIBER_COUNT) - private Long subscriberCount; - - @ColumnInfo(name = SUBSCRIPTION_DESCRIPTION) - private String description; - - @ColumnInfo(name = SUBSCRIPTION_NOTIFICATION_MODE) - private int notificationMode; - - @Ignore - public static SubscriptionEntity from(@NonNull final ChannelInfo info) { - final SubscriptionEntity result = new SubscriptionEntity(); - result.setServiceId(info.getServiceId()); - result.setUrl(info.getUrl()); - result.setData(info.getName(), ImageStrategy.imageListToDbUrl(info.getAvatars()), - info.getDescription(), info.getSubscriberCount()); - return result; - } - - public long getUid() { - return uid; - } - - public void setUid(final long uid) { - this.uid = uid; - } - - public int getServiceId() { - return serviceId; - } - - public void setServiceId(final int serviceId) { - this.serviceId = serviceId; - } - - public String getUrl() { - return url; - } - - public void setUrl(final String url) { - this.url = url; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - @Nullable - public String getAvatarUrl() { - return avatarUrl; - } - - public void setAvatarUrl(@Nullable final String avatarUrl) { - this.avatarUrl = avatarUrl; - } - - public Long getSubscriberCount() { - return subscriberCount; - } - - public void setSubscriberCount(final Long subscriberCount) { - this.subscriberCount = subscriberCount; - } - - public String getDescription() { - return description; - } - - public void setDescription(final String description) { - this.description = description; - } - - @NotificationMode - public int getNotificationMode() { - return notificationMode; - } - - public void setNotificationMode(@NotificationMode final int notificationMode) { - this.notificationMode = notificationMode; - } - - @Ignore - public void setData(final String n, final String au, final String d, final Long sc) { - this.setName(n); - this.setAvatarUrl(au); - this.setDescription(d); - this.setSubscriberCount(sc); - } - - @Ignore - public ChannelInfoItem toChannelInfoItem() { - final ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName()); - item.setThumbnails(ImageStrategy.dbUrlToImageList(getAvatarUrl())); - item.setSubscriberCount(getSubscriberCount()); - item.setDescription(getDescription()); - return item; - } - - - // TODO: Remove these generated methods by migrating this class to a data class from Kotlin. - @Override - @SuppressWarnings("EqualsReplaceableByObjectsCall") - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - final SubscriptionEntity that = (SubscriptionEntity) o; - - if (uid != that.uid) { - return false; - } - if (serviceId != that.serviceId) { - return false; - } - if (!url.equals(that.url)) { - return false; - } - if (name != null ? !name.equals(that.name) : that.name != null) { - return false; - } - if (avatarUrl != null ? !avatarUrl.equals(that.avatarUrl) : that.avatarUrl != null) { - return false; - } - if (subscriberCount != null - ? !subscriberCount.equals(that.subscriberCount) - : that.subscriberCount != null) { - return false; - } - return description != null - ? description.equals(that.description) - : that.description == null; - } - - @Override - public int hashCode() { - int result = (int) (uid ^ (uid >>> 32)); - result = 31 * result + serviceId; - result = 31 * result + url.hashCode(); - result = 31 * result + (name != null ? name.hashCode() : 0); - result = 31 * result + (avatarUrl != null ? avatarUrl.hashCode() : 0); - result = 31 * result + (subscriberCount != null ? subscriberCount.hashCode() : 0); - result = 31 * result + (description != null ? description.hashCode() : 0); - return result; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.kt b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.kt new file mode 100644 index 000000000..7df9830e4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.kt @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2017-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.subscription + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Ignore +import androidx.room.Index +import androidx.room.PrimaryKey +import org.schabi.newpipe.extractor.channel.ChannelInfo +import org.schabi.newpipe.extractor.channel.ChannelInfoItem +import org.schabi.newpipe.util.NO_SERVICE_ID +import org.schabi.newpipe.util.image.ImageStrategy + +@Entity( + tableName = SubscriptionEntity.Companion.SUBSCRIPTION_TABLE, + indices = [ + Index( + value = [SubscriptionEntity.Companion.SUBSCRIPTION_SERVICE_ID, SubscriptionEntity.Companion.SUBSCRIPTION_URL], + unique = true + ) + ] +) +data class SubscriptionEntity( + @PrimaryKey(autoGenerate = true) + var uid: Long = 0, + + @ColumnInfo(name = SUBSCRIPTION_SERVICE_ID) + var serviceId: Int = NO_SERVICE_ID, + + @ColumnInfo(name = SUBSCRIPTION_URL) + var url: String? = null, + + @ColumnInfo(name = SUBSCRIPTION_NAME) + var name: String? = null, + + @ColumnInfo(name = SUBSCRIPTION_AVATAR_URL) + var avatarUrl: String? = null, + + @ColumnInfo(name = SUBSCRIPTION_SUBSCRIBER_COUNT) + var subscriberCount: Long? = null, + + @ColumnInfo(name = SUBSCRIPTION_DESCRIPTION) + var description: String? = null, + + @get:NotificationMode + @ColumnInfo(name = SUBSCRIPTION_NOTIFICATION_MODE) + var notificationMode: Int = 0 +) { + @Ignore + fun toChannelInfoItem(): ChannelInfoItem { + return ChannelInfoItem(this.serviceId, this.url, this.name).apply { + thumbnails = ImageStrategy.dbUrlToImageList(this@SubscriptionEntity.avatarUrl) + subscriberCount = this@SubscriptionEntity.subscriberCount ?: -1 + description = this@SubscriptionEntity.description + } + } + + companion object { + const val SUBSCRIPTION_UID: String = "uid" + const val SUBSCRIPTION_TABLE: String = "subscriptions" + const val SUBSCRIPTION_SERVICE_ID: String = "service_id" + const val SUBSCRIPTION_URL: String = "url" + const val SUBSCRIPTION_NAME: String = "name" + const val SUBSCRIPTION_AVATAR_URL: String = "avatar_url" + const val SUBSCRIPTION_SUBSCRIBER_COUNT: String = "subscriber_count" + const val SUBSCRIPTION_DESCRIPTION: String = "description" + const val SUBSCRIPTION_NOTIFICATION_MODE: String = "notification_mode" + + @JvmStatic + @Ignore + fun from(info: ChannelInfo): SubscriptionEntity { + return SubscriptionEntity( + serviceId = info.serviceId, + url = info.url, + name = info.name, + avatarUrl = ImageStrategy.imageListToDbUrl(info.avatars), + description = info.description, + subscriberCount = info.subscriberCount + ) + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 0857fa339..741bda246 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -1133,7 +1133,7 @@ public class DownloadDialog extends DialogFragment } DownloadManagerService.startMission(context, urls, storage, kind, threads, - currentInfo.getUrl(), psName, psArgs, nearLength, new ArrayList<>(recoveryInfo)); + currentInfo, psName, psArgs, nearLength, new ArrayList<>(recoveryInfo)); Toast.makeText(context, getString(R.string.download_has_started), Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index 609fbb336..cd48fb298 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -7,6 +7,7 @@ import androidx.core.content.ContextCompat import com.google.android.exoplayer2.ExoPlaybackException import com.google.android.exoplayer2.upstream.HttpDataSource import com.google.android.exoplayer2.upstream.Loader +import java.net.UnknownHostException import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R import org.schabi.newpipe.extractor.Info @@ -28,7 +29,6 @@ import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentExcepti import org.schabi.newpipe.ktx.isNetworkRelated import org.schabi.newpipe.player.mediasource.FailedMediaSource import org.schabi.newpipe.player.resolver.PlaybackResolver -import java.net.UnknownHostException /** * An error has occurred in the app. This class contains plain old parcelable data that can be used @@ -59,7 +59,7 @@ class ErrorInfo private constructor( * If present, this resource can alternatively be opened in browser (useful if NewPipe is * badly broken). */ - val openInBrowserUrl: String?, + val openInBrowserUrl: String? ) : Parcelable { @JvmOverloads @@ -68,7 +68,7 @@ class ErrorInfo private constructor( userAction: UserAction, request: String, serviceId: Int? = null, - openInBrowserUrl: String? = null, + openInBrowserUrl: String? = null ) : this( throwableToStringList(throwable), userAction, @@ -78,7 +78,7 @@ class ErrorInfo private constructor( isReportable(throwable), isRetryable(throwable), (throwable as? ReCaptchaException)?.url, - openInBrowserUrl, + openInBrowserUrl ) @JvmOverloads @@ -87,7 +87,7 @@ class ErrorInfo private constructor( userAction: UserAction, request: String, serviceId: Int? = null, - openInBrowserUrl: String? = null, + openInBrowserUrl: String? = null ) : this( throwableListToStringList(throwables), userAction, @@ -97,7 +97,7 @@ class ErrorInfo private constructor( throwables.any(::isReportable), throwables.isEmpty() || throwables.any(::isRetryable), throwables.firstNotNullOfOrNull { it as? ReCaptchaException }?.url, - openInBrowserUrl, + openInBrowserUrl ) // constructor to manually build ErrorInfo when no throwable is available @@ -118,7 +118,7 @@ class ErrorInfo private constructor( throwable: Throwable, userAction: UserAction, request: String, - info: Info?, + info: Info? ) : this(throwable, userAction, request, info?.serviceId, info?.url) @@ -127,7 +127,7 @@ class ErrorInfo private constructor( throwables: List, userAction: UserAction, request: String, - info: Info?, + info: Info? ) : this(throwables, userAction, request, info?.serviceId, info?.url) @@ -144,7 +144,7 @@ class ErrorInfo private constructor( class ErrorMessage( @StringRes private val stringRes: Int, - private vararg val formatArgs: String, + private vararg val formatArgs: String ) : Parcelable { fun getString(context: Context): String { return if (formatArgs.isEmpty()) { @@ -160,21 +160,19 @@ class ErrorInfo private constructor( const val SERVICE_NONE = "" - private fun getServiceName(serviceId: Int?) = - // not using getNameOfServiceById since we want to accept a nullable serviceId and we + private fun getServiceName(serviceId: Int?) = // not using getNameOfServiceById since we want to accept a nullable serviceId and we // want to default to SERVICE_NONE - ServiceList.all()?.firstOrNull { it.serviceId == serviceId }?.serviceInfo?.name + ServiceList.all().firstOrNull { it.serviceId == serviceId }?.serviceInfo?.name ?: SERVICE_NONE fun throwableToStringList(throwable: Throwable) = arrayOf(throwable.stackTraceToString()) - fun throwableListToStringList(throwableList: List) = - throwableList.map { it.stackTraceToString() }.toTypedArray() + fun throwableListToStringList(throwableList: List) = throwableList.map { it.stackTraceToString() }.toTypedArray() fun getMessage( throwable: Throwable?, action: UserAction?, - serviceId: Int?, + serviceId: Int? ): ErrorMessage { return when { // player exceptions @@ -193,18 +191,24 @@ class ErrorInfo private constructor( ErrorMessage(R.string.player_http_invalid_status, cause.responseCode.toString()) } } + cause is Loader.UnexpectedLoaderException && cause.cause is ExtractionException -> getMessage(throwable, action, serviceId) + throwable.type == ExoPlaybackException.TYPE_SOURCE -> ErrorMessage(R.string.player_stream_failure) + throwable.type == ExoPlaybackException.TYPE_UNEXPECTED -> ErrorMessage(R.string.player_recoverable_failure) + else -> ErrorMessage(R.string.player_unrecoverable_failure) } } + throwable is FailedMediaSource.FailedMediaSourceException -> getMessage(throwable.cause, action, serviceId) + throwable is PlaybackResolver.ResolverException -> ErrorMessage(R.string.player_stream_failure) @@ -220,34 +224,46 @@ class ErrorInfo private constructor( ) } ?: ErrorMessage(R.string.account_terminated) + throwable is AgeRestrictedContentException -> ErrorMessage(R.string.restricted_video_no_stream) + throwable is GeographicRestrictionException -> ErrorMessage(R.string.georestricted_content) + throwable is PaidContentException -> ErrorMessage(R.string.paid_content) + throwable is PrivateContentException -> ErrorMessage(R.string.private_content) + throwable is SoundCloudGoPlusContentException -> ErrorMessage(R.string.soundcloud_go_plus_content) + throwable is UnsupportedContentInCountryException -> ErrorMessage(R.string.unsupported_content_in_country) + throwable is YoutubeMusicPremiumContentException -> ErrorMessage(R.string.youtube_music_premium_content) + throwable is SignInConfirmNotBotException -> ErrorMessage(R.string.sign_in_confirm_not_bot_error, getServiceName(serviceId)) + throwable is ContentNotAvailableException -> ErrorMessage(R.string.content_not_available) // other extractor exceptions throwable is ContentNotSupportedException -> ErrorMessage(R.string.content_not_supported) + // ReCaptchas will be handled in a special way anyway throwable is ReCaptchaException -> ErrorMessage(R.string.recaptcha_request_toast) + // test this at the end as many exceptions could be a subclass of IOException throwable != null && throwable.isNetworkRelated -> ErrorMessage(R.string.network_error) + // an extraction exception unrelated to the network // is likely an issue with parsing the website throwable is ExtractionException -> @@ -256,16 +272,22 @@ class ErrorInfo private constructor( // user actions (in case the exception is null or unrecognizable) action == UserAction.UI_ERROR -> ErrorMessage(R.string.app_ui_crash) + action == UserAction.REQUESTED_COMMENTS -> ErrorMessage(R.string.error_unable_to_load_comments) + action == UserAction.SUBSCRIPTION_CHANGE -> ErrorMessage(R.string.subscription_change_failed) + action == UserAction.SUBSCRIPTION_UPDATE -> ErrorMessage(R.string.subscription_update_failed) + action == UserAction.LOAD_IMAGE -> ErrorMessage(R.string.could_not_load_thumbnails) + action == UserAction.DOWNLOAD_OPEN_DIALOG -> ErrorMessage(R.string.could_not_setup_download_menu) + else -> ErrorMessage(R.string.error_snackbar_message) } @@ -276,15 +298,19 @@ class ErrorInfo private constructor( // we don't have an exception, so this is a manually built error, which likely // indicates that it's important and is thus reportable null -> true - // the service explicitly said that content is not available (e.g. age restrictions, - // video deleted, etc.), there is no use in letting users report it - is ContentNotAvailableException -> false + + // if the service explicitly said that content is not available (e.g. age + // restrictions, video deleted, etc.), there is no use in letting users report it + is ContentNotAvailableException -> !isContentSurelyNotAvailable(throwable) + // we know the content is not supported, no need to let the user report it is ContentNotSupportedException -> false + // happens often when there is no internet connection; we don't use // `throwable.isNetworkRelated` since any `IOException` would make that function // return true, but not all `IOException`s are network related is UnknownHostException -> false + // by default, this is an unexpected exception, which the user could report else -> true } @@ -292,14 +318,39 @@ class ErrorInfo private constructor( fun isRetryable(throwable: Throwable?): Boolean { return when (throwable) { - // we know the content is not available, retrying won't help - is ContentNotAvailableException -> false + // if we know the content is surely not available, retrying won't help + is ContentNotAvailableException -> !isContentSurelyNotAvailable(throwable) + // we know the content is not supported, retrying won't help is ContentNotSupportedException -> false + // by default (including if throwable is null), enable retrying (though the retry // button will be shown only if a way to perform the retry is implemented) else -> true } } + + /** + * Unfortunately sometimes [ContentNotAvailableException] may not indicate that the content + * is blocked/deleted/paid, but may just indicate that we could not extract it. This is an + * inconsistency in the exceptions thrown by the extractor, but until it is fixed, this + * function will distinguish between the two types. + * @return `true` if the content is not available because of a limitation imposed by the + * service or the owner, `false` if the extractor could not extract info about it + */ + fun isContentSurelyNotAvailable(e: ContentNotAvailableException): Boolean { + return when (e) { + is AccountTerminatedException, + is AgeRestrictedContentException, + is GeographicRestrictionException, + is PaidContentException, + is PrivateContentException, + is SoundCloudGoPlusContentException, + is UnsupportedContentInCountryException, + is YoutubeMusicPremiumContentException -> true + + else -> false + } + } } } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt index 4ec5f58c3..023d13e9d 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt @@ -11,16 +11,16 @@ import androidx.fragment.app.Fragment import com.jakewharton.rxbinding4.view.clicks import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.disposables.Disposable +import java.util.concurrent.TimeUnit import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.ktx.animate import org.schabi.newpipe.util.external_communication.ShareUtils -import java.util.concurrent.TimeUnit class ErrorPanelHelper( private val fragment: Fragment, rootView: View, - onRetry: Runnable?, + onRetry: Runnable? ) { private val context: Context = rootView.context!! diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index b358a5fd2..7facb5d85 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -46,7 +46,7 @@ class ErrorUtil { @JvmStatic fun openActivity(context: Context, errorInfo: ErrorInfo) { if (PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(MainActivity.KEY_IS_IN_BACKGROUND, true) + .getBoolean(MainActivity.KEY_IS_IN_BACKGROUND, true) ) { createNotification(context, errorInfo) } else { diff --git a/app/src/main/java/org/schabi/newpipe/error/UserAction.java b/app/src/main/java/org/schabi/newpipe/error/UserAction.kt similarity index 83% rename from app/src/main/java/org/schabi/newpipe/error/UserAction.java rename to app/src/main/java/org/schabi/newpipe/error/UserAction.kt index d3af9d32e..b3f14e2da 100644 --- a/app/src/main/java/org/schabi/newpipe/error/UserAction.java +++ b/app/src/main/java/org/schabi/newpipe/error/UserAction.kt @@ -1,9 +1,14 @@ -package org.schabi.newpipe.error; +/* + * SPDX-FileCopyrightText: 2017-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.error /** * The user actions that can cause an error. */ -public enum UserAction { +enum class UserAction(val message: String) { USER_REPORT("user report"), UI_ERROR("ui error"), DATABASE_IMPORT_EXPORT("database import or export"), @@ -35,15 +40,5 @@ public enum UserAction { OPEN_INFO_ITEM_DIALOG("open info item dialog"), GETTING_MAIN_SCREEN_TAB("getting main screen tab"), PLAY_ON_POPUP("play on popup"), - SUBSCRIPTIONS("loading subscriptions"); - - private final String message; - - UserAction(final String message) { - this.message = message; - } - - public String getMessage() { - return message; - } + SUBSCRIPTIONS("loading subscriptions") } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 7b8705565..ef9fa1137 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -1230,7 +1230,13 @@ public final class VideoDetailFragment disposables.add(recordManager.onViewed(info).onErrorComplete() .subscribe( ignored -> { /* successful */ }, - error -> Log.e(TAG, "Register view failure: ", error) + error -> showSnackBarError( + new ErrorInfo( + error, + UserAction.PLAY_STREAM, + "Got an error when modifying history on viewed" + ) + ) )); } @@ -1416,8 +1422,10 @@ public final class VideoDetailFragment bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } // Rebound to the service if it was closed via notification or mini player - playerHolder.setListener(VideoDetailFragment.this); - playerHolder.tryBindIfNeeded(context); + if (!playerHolder.isBound()) { + playerHolder.startService( + false, VideoDetailFragment.this); + } break; } } @@ -1900,12 +1908,13 @@ public final class VideoDetailFragment @Override public void onScreenRotationButtonClicked() { + // On Android TV screen rotation is not supported // In tablet user experience will be better if screen will not be rotated // from landscape to portrait every time. // Just turn on fullscreen mode in landscape orientation // or portrait & unlocked global orientation final boolean isLandscape = DeviceUtils.isLandscape(requireContext()); - if (DeviceUtils.isTablet(activity) + if (DeviceUtils.isTv(activity) || DeviceUtils.isTablet(activity) && (!globalScreenOrientationLocked(activity) || isLandscape)) { player.UIs().get(MainPlayerUi.class).ifPresent(MainPlayerUi::toggleFullscreen); return; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index d36fc5fc9..d75d14b4a 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -361,10 +361,10 @@ public class ChannelFragment extends BaseStateFragment final SubscriptionEntity channel = new SubscriptionEntity(); channel.setServiceId(info.getServiceId()); channel.setUrl(info.getUrl()); - channel.setData(info.getName(), - ImageStrategy.imageListToDbUrl(info.getAvatars()), - info.getDescription(), - info.getSubscriberCount()); + channel.setName(info.getName()); + channel.setAvatarUrl(ImageStrategy.imageListToDbUrl(info.getAvatars())); + channel.setDescription(info.getDescription()); + channel.setSubscriberCount(info.getSubscriberCount()); channelSubscription = null; updateNotifyButton(null); subscribeButtonMonitor = monitorSubscribeButton(mapOnSubscribe(channel)); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionItem.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionItem.java deleted file mode 100644 index 83f68dbb5..000000000 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.schabi.newpipe.fragments.list.search; - -import androidx.annotation.NonNull; - -public class SuggestionItem { - final boolean fromHistory; - public final String query; - - public SuggestionItem(final boolean fromHistory, final String query) { - this.fromHistory = fromHistory; - this.query = query; - } - - @Override - public boolean equals(final Object o) { - if (o instanceof SuggestionItem) { - return query.equals(((SuggestionItem) o).query); - } - return false; - } - - @Override - public int hashCode() { - return query.hashCode(); - } - - @NonNull - @Override - public String toString() { - return "[" + fromHistory + "→" + query + "]"; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionItem.kt b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionItem.kt new file mode 100644 index 000000000..1317f9acb --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionItem.kt @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2017-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.fragments.list.search + +class SuggestionItem(@JvmField val fromHistory: Boolean, @JvmField val query: String) { + override fun equals(other: Any?): Boolean { + if (other is SuggestionItem) { + return query == other.query + } + return false + } + + override fun hashCode() = query.hashCode() + + override fun toString() = "[$fromHistory→$query]" +} diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.java deleted file mode 100644 index 856ba22f1..000000000 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.schabi.newpipe.fragments.list.search; - -import android.view.LayoutInflater; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.ListAdapter; -import androidx.recyclerview.widget.RecyclerView; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.databinding.ItemSearchSuggestionBinding; - -public class SuggestionListAdapter - extends ListAdapter { - private OnSuggestionItemSelected listener; - - public SuggestionListAdapter() { - super(new SuggestionItemCallback()); - } - - public void setListener(final OnSuggestionItemSelected listener) { - this.listener = listener; - } - - @NonNull - @Override - public SuggestionItemHolder onCreateViewHolder(@NonNull final ViewGroup parent, - final int viewType) { - return new SuggestionItemHolder(ItemSearchSuggestionBinding - .inflate(LayoutInflater.from(parent.getContext()), parent, false)); - } - - @Override - public void onBindViewHolder(final SuggestionItemHolder holder, final int position) { - final SuggestionItem currentItem = getItem(position); - holder.updateFrom(currentItem); - holder.itemBinding.suggestionSearch.setOnClickListener(v -> { - if (listener != null) { - listener.onSuggestionItemSelected(currentItem); - } - }); - holder.itemBinding.suggestionSearch.setOnLongClickListener(v -> { - if (listener != null) { - listener.onSuggestionItemLongClick(currentItem); - } - return true; - }); - holder.itemBinding.suggestionInsert.setOnClickListener(v -> { - if (listener != null) { - listener.onSuggestionItemInserted(currentItem); - } - }); - } - - public interface OnSuggestionItemSelected { - void onSuggestionItemSelected(SuggestionItem item); - - void onSuggestionItemInserted(SuggestionItem item); - - void onSuggestionItemLongClick(SuggestionItem item); - } - - public static final class SuggestionItemHolder extends RecyclerView.ViewHolder { - private final ItemSearchSuggestionBinding itemBinding; - - private SuggestionItemHolder(final ItemSearchSuggestionBinding binding) { - super(binding.getRoot()); - this.itemBinding = binding; - } - - private void updateFrom(final SuggestionItem item) { - itemBinding.itemSuggestionIcon.setImageResource(item.fromHistory ? R.drawable.ic_history - : R.drawable.ic_search); - itemBinding.itemSuggestionQuery.setText(item.query); - } - } - - private static class SuggestionItemCallback extends DiffUtil.ItemCallback { - @Override - public boolean areItemsTheSame(@NonNull final SuggestionItem oldItem, - @NonNull final SuggestionItem newItem) { - return oldItem.fromHistory == newItem.fromHistory - && oldItem.query.equals(newItem.query); - } - - @Override - public boolean areContentsTheSame(@NonNull final SuggestionItem oldItem, - @NonNull final SuggestionItem newItem) { - return true; // items' contents never change; the list of items themselves does - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.kt b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.kt new file mode 100644 index 000000000..4eb4c1574 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.kt @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2017-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.fragments.list.search + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.ItemSearchSuggestionBinding +import org.schabi.newpipe.fragments.list.search.SuggestionListAdapter.SuggestionItemHolder + +class SuggestionListAdapter : + ListAdapter(SuggestionItemCallback()) { + + var listener: OnSuggestionItemSelected? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SuggestionItemHolder { + return SuggestionItemHolder( + ItemSearchSuggestionBinding.inflate(LayoutInflater.from(parent.context), parent, false) + ) + } + + override fun onBindViewHolder(holder: SuggestionItemHolder, position: Int) { + val currentItem = getItem(position) + holder.updateFrom(currentItem) + holder.binding.suggestionSearch.setOnClickListener { + listener?.onSuggestionItemSelected(currentItem) + } + holder.binding.suggestionSearch.setOnLongClickListener { + listener?.onSuggestionItemLongClick(currentItem) + true + } + holder.binding.suggestionInsert.setOnClickListener { + listener?.onSuggestionItemInserted(currentItem) + } + } + + interface OnSuggestionItemSelected { + fun onSuggestionItemSelected(item: SuggestionItem) + + fun onSuggestionItemInserted(item: SuggestionItem) + + fun onSuggestionItemLongClick(item: SuggestionItem) + } + + class SuggestionItemHolder(val binding: ItemSearchSuggestionBinding) : + RecyclerView.ViewHolder(binding.getRoot()) { + fun updateFrom(item: SuggestionItem) { + binding.itemSuggestionIcon.setImageResource( + if (item.fromHistory) { + R.drawable.ic_history + } else { + R.drawable.ic_search + } + ) + binding.itemSuggestionQuery.text = item.query + } + } + + private class SuggestionItemCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: SuggestionItem, newItem: SuggestionItem): Boolean { + return oldItem.fromHistory == newItem.fromHistory && oldItem.query == newItem.query + } + + override fun areContentsTheSame(oldItem: SuggestionItem, newItem: SuggestionItem): Boolean { + return true // items' contents never change; the list of items themselves does + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/info_list/ItemViewMode.java b/app/src/main/java/org/schabi/newpipe/info_list/ItemViewMode.kt similarity index 65% rename from app/src/main/java/org/schabi/newpipe/info_list/ItemViewMode.java rename to app/src/main/java/org/schabi/newpipe/info_list/ItemViewMode.kt index 447c540a0..899223afa 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/ItemViewMode.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/ItemViewMode.kt @@ -1,21 +1,29 @@ -package org.schabi.newpipe.info_list; +/* + * SPDX-FileCopyrightText: 2023-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.info_list /** * Item view mode for streams & playlist listing screens. */ -public enum ItemViewMode { +enum class ItemViewMode { /** * Default mode. */ AUTO, + /** * Full width list item with thumb on the left and two line title & uploader in right. */ LIST, + /** * Grid mode places two cards per row. */ GRID, + /** * A full width card in phone - portrait. */ diff --git a/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt b/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt index 869bf6f48..9b6005f65 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt +++ b/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt @@ -2,8 +2,8 @@ package org.schabi.newpipe.info_list import android.util.Log import com.xwray.groupie.GroupieAdapter -import org.schabi.newpipe.extractor.stream.StreamInfo import kotlin.math.max +import org.schabi.newpipe.extractor.stream.StreamInfo /** * Custom RecyclerView.Adapter/GroupieAdapter for [StreamSegmentItem] for handling selection state. diff --git a/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentItem.kt b/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentItem.kt index 1e52d3168..a7ca3bd68 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentItem.kt +++ b/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentItem.kt @@ -41,7 +41,10 @@ class StreamSegmentItem( viewHolder.root.findViewById(R.id.textViewStartSeconds).text = Localization.getDurationString(item.startTimeSeconds.toLong()) viewHolder.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) } - viewHolder.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds); true } + viewHolder.root.setOnLongClickListener { + onClick.onItemLongClick(this, item.startTimeSeconds) + true + } viewHolder.root.isSelected = isSelected } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java index c7ac9556f..a2bf4a1ff 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java @@ -13,6 +13,9 @@ import androidx.annotation.StringRes; import org.schabi.newpipe.R; import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.download.DownloadDialog; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; @@ -132,6 +135,16 @@ public enum StreamDialogDefaultEntry { MARK_AS_WATCHED(R.string.mark_as_watched, (fragment, item) -> new HistoryRecordManager(fragment.getContext()) .markAsWatched(item) + .doOnError(error -> { + ErrorUtil.showSnackbar( + fragment.requireContext(), + new ErrorInfo( + error, + UserAction.OPEN_INFO_ITEM_DIALOG, + "Got an error when trying to mark as watched" + ) + ); + }) .onErrorComplete() .observeOn(AndroidSchedulers.mainThread()) .subscribe() diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt index b781335e1..432b974cb 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt @@ -41,14 +41,16 @@ fun View.animate( execOnEnd: Runnable? = null ) { if (DEBUG) { - val id = try { - resources.getResourceEntryName(id) - } catch (e: Exception) { - id.toString() - } + val id = runCatching { resources.getResourceEntryName(id) }.getOrDefault(id.toString()) val msg = String.format( - "%8s → [%s:%s] [%s %s:%s] execOnEnd=%s", enterOrExit, - javaClass.simpleName, id, animationType, duration, delay, execOnEnd + "%8s → [%s:%s] [%s %s:%s] execOnEnd=%s", + enterOrExit, + javaClass.simpleName, + id, + animationType, + duration, + delay, + execOnEnd ) Log.d(TAG, "animate(): $msg") } @@ -291,5 +293,9 @@ private class HideAndExecOnEndListener(private val view: View, execOnEnd: Runnab } enum class AnimationType { - ALPHA, SCALE_AND_ALPHA, LIGHT_SCALE_AND_ALPHA, SLIDE_AND_ALPHA, LIGHT_SLIDE_AND_ALPHA + ALPHA, + SCALE_AND_ALPHA, + LIGHT_SCALE_AND_ALPHA, + SLIDE_AND_ALPHA, + LIGHT_SLIDE_AND_ALPHA } diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java index 90ef8c352..d690a2607 100644 --- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java @@ -28,6 +28,8 @@ import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling; import static org.schabi.newpipe.util.ThemeHelper.getItemViewMode; +import java.util.function.Supplier; + /** * This fragment is design to be used with persistent data such as * {@link org.schabi.newpipe.database.LocalItem}, and does not cache the data contained @@ -100,7 +102,7 @@ public abstract class BaseLocalListFragment extends BaseStateFragment //////////////////////////////////////////////////////////////////////////*/ @Nullable - protected ViewBinding getListHeader() { + protected Supplier getListHeaderSupplier() { return null; } @@ -131,9 +133,9 @@ public abstract class BaseLocalListFragment extends BaseStateFragment itemsList = rootView.findViewById(R.id.items_list); refreshItemViewMode(); - headerRootBinding = getListHeader(); - if (headerRootBinding != null) { - itemListAdapter.setHeader(headerRootBinding.getRoot()); + final Supplier listHeaderSupplier = getListHeaderSupplier(); + if (listHeaderSupplier != null) { + itemListAdapter.setHeaderSupplier(listHeaderSupplier); } footerRootBinding = getListFooter(); itemListAdapter.setFooter(footerRootBinding.getRoot()); @@ -210,6 +212,8 @@ public abstract class BaseLocalListFragment extends BaseStateFragment showListFooter(false); } + @Deprecated(since = "Calling this method with `true` may cause crashes, see " + + "https://github.com/TeamNewPipe/NewPipe/pull/12996#pullrequestreview-3713317115") @Override public void showListFooter(final boolean show) { if (itemsList == null) { diff --git a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java index b33619dea..6bbe536e3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java @@ -37,6 +37,7 @@ import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; /* * Created by Christian Schabesberger on 01.08.16. @@ -88,7 +89,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter headerSupplier = null; private View footer = null; private ItemViewMode itemViewMode = ItemViewMode.LIST; private boolean useItemHandle = false; @@ -97,6 +98,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter(); + dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) .withLocale(Localization.getPreferredLocale(context)); } @@ -124,7 +126,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter offsetStart = " + offsetStart + ", " + "localItems.size() = " + localItems.size() + ", " - + "header = " + header + ", footer = " + footer + ", " + + "header = " + hasHeader() + ", footer = " + footer + ", " + "showFooter = " + showFooter); } notifyItemRangeInserted(offsetStart, data.size()); @@ -144,7 +146,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter headerSupplier) { + final boolean changed = headerSupplier != this.headerSupplier; + this.headerSupplier = headerSupplier; if (changed) { notifyDataSetChanged(); } @@ -201,6 +203,12 @@ public class LocalItemListAdapter extends RecyclerView.Adapter getItemsList() { @@ -232,7 +242,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter playlists) { return playlists.stream() - .anyMatch(playlist -> playlist.timesStreamIsContained > 0); + .anyMatch(playlist -> playlist.getTimesStreamIsContained() > 0); } private void onPlaylistSelected(@NonNull final LocalPlaylistManager manager, @@ -146,9 +147,9 @@ public final class PlaylistAppendDialog extends PlaylistDialog { @NonNull final List streams) { final String toastText; - if (playlist.timesStreamIsContained > 0) { + if (playlist.getTimesStreamIsContained() > 0) { toastText = getString(R.string.playlist_add_stream_success_duplicate, - playlist.timesStreamIsContained); + playlist.getTimesStreamIsContained()); } else { toastText = getString(R.string.playlist_add_stream_success); } @@ -160,8 +161,9 @@ public final class PlaylistAppendDialog extends PlaylistDialog { .subscribe(ignored -> { successToast.show(); - if (playlist.thumbnailUrl != null - && playlist.thumbnailUrl.equals(PlaylistEntity.DEFAULT_THUMBNAIL)) { + if (playlist.getThumbnailStreamId() != null + && playlist.getThumbnailStreamId() == DEFAULT_THUMBNAIL_ID + ) { playlistDisposables.add(manager .changePlaylistThumbnail(playlist.getUid(), streams.get(0).getUid(), false) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt index ed65d4048..3e3a47f57 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedDatabaseManager.kt @@ -7,6 +7,9 @@ import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.schedulers.Schedulers +import java.time.LocalDate +import java.time.OffsetDateTime +import java.time.ZoneOffset import org.schabi.newpipe.MainActivity.DEBUG import org.schabi.newpipe.NewPipeDatabase import org.schabi.newpipe.database.feed.model.FeedEntity @@ -18,9 +21,6 @@ import org.schabi.newpipe.database.subscription.NotificationMode import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.extractor.stream.StreamType import org.schabi.newpipe.local.subscription.FeedGroupIcon -import java.time.LocalDate -import java.time.OffsetDateTime -import java.time.ZoneOffset class FeedDatabaseManager(context: Context) { private val database = NewPipeDatabase.getInstance(context) @@ -85,14 +85,13 @@ class FeedDatabaseManager(context: Context) { items: List, oldestAllowedDate: OffsetDateTime = FEED_OLDEST_ALLOWED_DATE ) { - val itemsToInsert = ArrayList() - loop@ for (streamItem in items) { - val uploadDate = streamItem.uploadDate + val itemsToInsert = items.mapNotNull { stream -> + val uploadDate = stream.uploadDate - itemsToInsert += when { - uploadDate == null && streamItem.streamType == StreamType.LIVE_STREAM -> streamItem - uploadDate != null && uploadDate.offsetDateTime() >= oldestAllowedDate -> streamItem - else -> continue@loop + when { + uploadDate == null && stream.streamType == StreamType.LIVE_STREAM -> stream + uploadDate != null && uploadDate.offsetDateTime() >= oldestAllowedDate -> stream + else -> null } } @@ -177,7 +176,7 @@ class FeedDatabaseManager(context: Context) { .observeOn(AndroidSchedulers.mainThread()) } - fun oldestSubscriptionUpdate(groupId: Long): Flowable> { + fun oldestSubscriptionUpdate(groupId: Long): Flowable> { return when (groupId) { FeedGroupEntity.GROUP_ALL_ID -> feedTable.oldestSubscriptionUpdateFromAll() else -> feedTable.oldestSubscriptionUpdate(groupId) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 91f98f5d2..ac076f1b8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -53,6 +53,8 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.schedulers.Schedulers +import java.time.OffsetDateTime +import java.util.function.Consumer import org.schabi.newpipe.NewPipeDatabase import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity @@ -81,8 +83,6 @@ import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountStreams import org.schabi.newpipe.util.ThemeHelper.getItemViewMode import org.schabi.newpipe.util.ThemeHelper.resolveDrawable import org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout -import java.time.OffsetDateTime -import java.util.function.Consumer class FeedFragment : BaseStateFragment() { private var _feedBinding: FragmentFeedBinding? = null @@ -91,7 +91,10 @@ class FeedFragment : BaseStateFragment() { private val disposables = CompositeDisposable() private lateinit var viewModel: FeedViewModel - @State @JvmField var listState: Parcelable? = null + + @State + @JvmField + var listState: Parcelable? = null private var groupId = FeedGroupEntity.GROUP_ALL_ID private var groupName = "" @@ -149,7 +152,6 @@ class FeedFragment : BaseStateFragment() { if (newState == RecyclerView.SCROLL_STATE_IDLE && !recyclerView.canScrollVertically(-1) ) { - if (tryGetNewItemsLoadedButton()?.isVisible == true) { hideNewItemsLoaded(true) } @@ -387,8 +389,13 @@ class FeedFragment : BaseStateFragment() { if (item is StreamItem && !isRefreshing) { val stream = item.streamWithState.stream NavigationHelper.openVideoDetailFragment( - requireContext(), fm, - stream.serviceId, stream.url, stream.title, null, false + requireContext(), + fm, + stream.serviceId, + stream.url, + stream.title, + null, + false ) } } @@ -500,14 +507,15 @@ class FeedFragment : BaseStateFragment() { ) { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) val isFastFeedModeEnabled = sharedPreferences.getBoolean( - getString(R.string.feed_use_dedicated_fetch_method_key), false + getString(R.string.feed_use_dedicated_fetch_method_key), + false ) val builder = AlertDialog.Builder(requireContext()) .setTitle(R.string.feed_load_error) .setPositiveButton(R.string.unsubscribe) { _, _ -> SubscriptionManager(requireContext()) - .deleteSubscription(subscriptionEntity.serviceId, subscriptionEntity.url) + .deleteSubscription(subscriptionEntity.serviceId, subscriptionEntity.url!!) .subscribe() handleItemsErrors(nextItemsErrors) } @@ -535,7 +543,8 @@ class FeedFragment : BaseStateFragment() { private fun updateRelativeTimeViews() { updateRefreshViewState() groupAdapter.notifyItemRangeChanged( - 0, groupAdapter.itemCount, + 0, + groupAdapter.itemCount, StreamItem.UPDATE_RELATIVE_TIME ) } diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedState.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedState.kt index 665ebbe43..6d6bc9007 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedState.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedState.kt @@ -1,8 +1,8 @@ package org.schabi.newpipe.local.feed import androidx.annotation.StringRes -import org.schabi.newpipe.local.feed.item.StreamItem import java.time.OffsetDateTime +import org.schabi.newpipe.local.feed.item.StreamItem sealed class FeedState { data class ProgressState( diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt index 728570b17..7e781b30f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedViewModel.kt @@ -14,6 +14,8 @@ import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.functions.Function6 import io.reactivex.rxjava3.processors.BehaviorProcessor import io.reactivex.rxjava3.schedulers.Schedulers +import java.time.OffsetDateTime +import java.util.concurrent.TimeUnit import org.schabi.newpipe.App import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity @@ -25,8 +27,6 @@ import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ProgressEvent import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.SuccessResultEvent import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT -import java.time.OffsetDateTime -import java.util.concurrent.TimeUnit class FeedViewModel( private val application: Application, @@ -64,8 +64,14 @@ class FeedViewModel( feedDatabaseManager.notLoadedCount(groupId), feedDatabaseManager.oldestSubscriptionUpdate(groupId), - Function6 { t1: FeedEventManager.Event, t2: Boolean, t3: Boolean, t4: Boolean, - t5: Long, t6: List -> + Function6 { + t1: FeedEventManager.Event, + t2: Boolean, + t3: Boolean, + t4: Boolean, + t5: Long, + t6: List + -> return@Function6 CombineResultEventHolder(t1, t2, t3, t4, t5, t6.firstOrNull()) } ) @@ -73,12 +79,13 @@ class FeedViewModel( .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) .map { (event, showPlayedItems, showPartiallyPlayedItems, showFutureItems, notLoadedCount, oldestUpdate) -> - val streamItems = if (event is SuccessResultEvent || event is IdleEvent) + val streamItems = if (event is SuccessResultEvent || event is IdleEvent) { feedDatabaseManager .getStreams(groupId, showPlayedItems, showPartiallyPlayedItems, showFutureItems) .blockingGet(arrayListOf()) - else + } else { arrayListOf() + } CombineResultDataHolder(event, streamItems, notLoadedCount, oldestUpdate) } @@ -150,17 +157,14 @@ class FeedViewModel( fun getShowFutureItemsFromPreferences() = getShowFutureItemsFromPreferences(application) companion object { - private fun getShowPlayedItemsFromPreferences(context: Context) = - PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(context.getString(R.string.feed_show_watched_items_key), true) + private fun getShowPlayedItemsFromPreferences(context: Context) = PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.feed_show_watched_items_key), true) - private fun getShowPartiallyPlayedItemsFromPreferences(context: Context) = - PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(context.getString(R.string.feed_show_partially_watched_items_key), true) + private fun getShowPartiallyPlayedItemsFromPreferences(context: Context) = PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.feed_show_partially_watched_items_key), true) - private fun getShowFutureItemsFromPreferences(context: Context) = - PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(context.getString(R.string.feed_show_future_items_key), true) + private fun getShowFutureItemsFromPreferences(context: Context) = PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.feed_show_future_items_key), true) fun getFactory(context: Context, groupId: Long) = viewModelFactory { initializer { diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt index 4a071d6df..e367961f1 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt @@ -6,6 +6,8 @@ import android.view.View import androidx.core.content.ContextCompat import androidx.preference.PreferenceManager import com.xwray.groupie.viewbinding.BindableItem +import java.util.concurrent.TimeUnit +import java.util.function.Consumer import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.database.stream.StreamWithState @@ -20,8 +22,6 @@ import org.schabi.newpipe.extractor.stream.StreamType.VIDEO_STREAM import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.StreamTypeUtil import org.schabi.newpipe.util.image.PicassoHelper -import java.util.concurrent.TimeUnit -import java.util.function.Consumer data class StreamItem( val streamWithState: StreamWithState, @@ -132,6 +132,7 @@ data class StreamItem( viewsAndDate.isEmpty() -> uploadDate!! else -> Localization.concatenateStrings(viewsAndDate, uploadDate) } + else -> viewsAndDate } } diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt index 646596884..d2d16a755 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt @@ -15,6 +15,7 @@ import androidx.core.app.NotificationManagerCompat import androidx.core.app.PendingIntentCompat import androidx.core.content.ContextCompat import androidx.core.content.getSystemService +import androidx.core.net.toUri import androidx.preference.PreferenceManager import com.squareup.picasso.Picasso import com.squareup.picasso.Target @@ -41,7 +42,9 @@ class NotificationHelper(val context: Context) { fun displayNewStreamsNotifications(data: FeedUpdateInfo) { val newStreams = data.newStreams val summary = context.resources.getQuantityString( - R.plurals.new_streams, newStreams.size, newStreams.size + R.plurals.new_streams, + newStreams.size, + newStreams.size ) val summaryBuilder = NotificationCompat.Builder( context, @@ -181,8 +184,7 @@ class NotificationHelper(val context: Context) { val manager = context.getSystemService()!! val enabled = manager.areNotificationsEnabled() val channel = manager.getNotificationChannel(channelId) - val importance = channel?.importance - enabled && channel != null && importance != NotificationManager.IMPORTANCE_NONE + enabled && channel?.importance != NotificationManager.IMPORTANCE_NONE } else { NotificationManagerCompat.from(context).areNotificationsEnabled() } @@ -212,7 +214,7 @@ class NotificationHelper(val context: Context) { context.startActivity(intent) } else { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - intent.data = Uri.parse("package:" + context.packageName) + intent.data = "package:${context.packageName}".toUri() context.startActivity(intent) } } diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt index 6fe311fb0..d1fd29945 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt @@ -16,6 +16,7 @@ import androidx.work.WorkerParameters import androidx.work.rxjava3.RxWorker import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Single +import java.util.concurrent.TimeUnit import org.schabi.newpipe.App import org.schabi.newpipe.R import org.schabi.newpipe.error.ErrorInfo @@ -23,7 +24,6 @@ import org.schabi.newpipe.error.ErrorUtil import org.schabi.newpipe.error.UserAction import org.schabi.newpipe.local.feed.service.FeedLoadManager import org.schabi.newpipe.local.feed.service.FeedLoadService -import java.util.concurrent.TimeUnit /* * Worker which checks for new streams of subscribed channels @@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit */ class NotificationWorker( appContext: Context, - workerParams: WorkerParameters, + workerParams: WorkerParameters ) : RxWorker(appContext, workerParams) { private val notificationHelper by lazy { @@ -95,9 +95,8 @@ class NotificationWorker( private val TAG = NotificationWorker::class.java.simpleName private const val WORK_TAG = App.PACKAGE_NAME + "_streams_notifications" - private fun areNotificationsEnabled(context: Context) = - NotificationHelper.areNewStreamsNotificationsEnabled(context) && - NotificationHelper.areNotificationsEnabledOnDevice(context) + private fun areNotificationsEnabled(context: Context) = NotificationHelper.areNewStreamsNotificationsEnabled(context) && + NotificationHelper.areNotificationsEnabledOnDevice(context) /** * Schedules a task for the [NotificationWorker] diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/ScheduleOptions.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/ScheduleOptions.kt index 37e8fc39e..6d5f12b2b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/ScheduleOptions.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/ScheduleOptions.kt @@ -2,8 +2,9 @@ package org.schabi.newpipe.local.feed.notifications import android.content.Context import androidx.preference.PreferenceManager -import org.schabi.newpipe.R import java.util.concurrent.TimeUnit +import org.schabi.newpipe.R +import org.schabi.newpipe.ktx.getStringSafe /** * Information for the Scheduler which checks for new streams. @@ -20,11 +21,9 @@ data class ScheduleOptions( val preferences = PreferenceManager.getDefaultSharedPreferences(context) return ScheduleOptions( interval = TimeUnit.SECONDS.toMillis( - preferences.getString( + preferences.getStringSafe( context.getString(R.string.streams_notifications_interval_key), - null - )?.toLongOrNull() ?: context.getString( - R.string.streams_notifications_interval_default + context.getString(R.string.streams_notifications_interval_default) ).toLong() ), isRequireNonMeteredNetwork = preferences.getString( diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedEventManager.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedEventManager.kt index 1c2826e7a..952a59b9a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedEventManager.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedEventManager.kt @@ -3,8 +3,8 @@ package org.schabi.newpipe.local.feed.service import androidx.annotation.StringRes import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.processors.BehaviorProcessor -import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent import java.util.concurrent.atomic.AtomicBoolean +import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent object FeedEventManager { private var processor: BehaviorProcessor = BehaviorProcessor.create() diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadManager.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadManager.kt index 9b0f177d5..3090a92d4 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadManager.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadManager.kt @@ -11,6 +11,10 @@ import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.functions.Consumer import io.reactivex.rxjava3.processors.PublishProcessor import io.reactivex.rxjava3.schedulers.Schedulers +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity import org.schabi.newpipe.database.subscription.NotificationMode @@ -27,10 +31,6 @@ import org.schabi.newpipe.util.ChannelTabHelper import org.schabi.newpipe.util.ExtractorHelper.getChannelInfo import org.schabi.newpipe.util.ExtractorHelper.getChannelTab import org.schabi.newpipe.util.ExtractorHelper.getMoreChannelTabItems -import java.time.OffsetDateTime -import java.time.ZoneOffset -import java.util.concurrent.atomic.AtomicBoolean -import java.util.concurrent.atomic.AtomicInteger class FeedLoadManager(private val context: Context) { @@ -60,7 +60,7 @@ class FeedLoadManager(private val context: Context) { */ fun startLoading( groupId: Long = FeedGroupEntity.GROUP_ALL_ID, - ignoreOutdatedThreshold: Boolean = false, + ignoreOutdatedThreshold: Boolean = false ): Single>> { val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) val useFeedExtractor = defaultSharedPreferences.getBoolean( @@ -85,9 +85,12 @@ class FeedLoadManager(private val context: Context) { FeedGroupEntity.GROUP_ALL_ID -> feedDatabaseManager.outdatedSubscriptions( outdatedThreshold ) + GROUP_NOTIFICATION_ENABLED -> feedDatabaseManager.outdatedSubscriptionsWithNotificationMode( - outdatedThreshold, NotificationMode.ENABLED + outdatedThreshold, + NotificationMode.ENABLED ) + else -> feedDatabaseManager.outdatedSubscriptionsForGroup(groupId, outdatedThreshold) } @@ -186,7 +189,8 @@ class FeedLoadManager(private val context: Context) { val channelInfo = getChannelInfo( subscriptionEntity.serviceId, - subscriptionEntity.url, true + subscriptionEntity.url, + true ) .onErrorReturn(storeOriginalErrorAndRethrow) .blockingGet() @@ -216,7 +220,8 @@ class FeedLoadManager(private val context: Context) { ) { val infoItemsPage = getMoreChannelTabItems( subscriptionEntity.serviceId, - linkHandler, channelTabInfo.nextPage + linkHandler, + channelTabInfo.nextPage ) .blockingGet() @@ -234,7 +239,7 @@ class FeedLoadManager(private val context: Context) { subscriptionEntity, originalInfo!!, streams!!, - errors, + errors ) ) } catch (e: Throwable) { @@ -305,6 +310,7 @@ class FeedLoadManager(private val context: Context) { feedDatabaseManager.markAsOutdated(info.uid) } } + notification.isOnError -> { val error = notification.error feedResultsHolder.addError(error!!) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt index 4aa825ca8..48ad5df94 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt @@ -36,13 +36,13 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.functions.Function +import java.util.concurrent.TimeUnit import org.schabi.newpipe.App import org.schabi.newpipe.MainActivity.DEBUG import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent import org.schabi.newpipe.local.feed.service.FeedEventManager.postEvent -import java.util.concurrent.TimeUnit class FeedLoadService : Service() { companion object { @@ -94,7 +94,8 @@ class FeedLoadService : Service() { .doOnSubscribe { startForeground(NOTIFICATION_ID, notificationBuilder.build()) } - .subscribe { _, error: Throwable? -> // explicitly mark error as nullable + .subscribe { _, error: Throwable? -> + // explicitly mark error as nullable if (error != null) { Log.e(TAG, "Error while storing result", error) handleError(error) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadState.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadState.kt index 703f593ad..2aedf0925 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadState.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadState.kt @@ -3,5 +3,5 @@ package org.schabi.newpipe.local.feed.service data class FeedLoadState( val updateDescription: String, val maxProgress: Int, - val currentProgress: Int, + val currentProgress: Int ) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedUpdateInfo.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedUpdateInfo.kt index b44eec353..fb4a27913 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedUpdateInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedUpdateInfo.kt @@ -25,13 +25,13 @@ data class FeedUpdateInfo( val description: String?, val subscriberCount: Long?, val streams: List, - val errors: List, + val errors: List ) { constructor( subscription: SubscriptionEntity, info: Info, streams: List, - errors: List, + errors: List ) : this( uid = subscription.uid, notificationMode = subscription.notificationMode, @@ -46,7 +46,7 @@ data class FeedUpdateInfo( description = (info as? ChannelInfo)?.description, subscriberCount = (info as? ChannelInfo)?.subscriberCount, streams = streams, - errors = errors, + errors = errors ) /** diff --git a/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java b/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java deleted file mode 100644 index 709a16b68..000000000 --- a/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.schabi.newpipe.local.history; - -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.RecyclerView; - -import org.schabi.newpipe.util.Localization; - -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; - - -/** - * This is an adapter for history entries. - * - * @param the type of the entries - * @param the type of the view holder - */ -public abstract class HistoryEntryAdapter - extends RecyclerView.Adapter { - private final ArrayList mEntries; - private final DateFormat mDateFormat; - private final Context mContext; - private OnHistoryItemClickListener onHistoryItemClickListener = null; - - public HistoryEntryAdapter(final Context context) { - super(); - mContext = context; - mEntries = new ArrayList<>(); - mDateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, - Localization.getPreferredLocale(context)); - } - - public void setEntries(@NonNull final Collection historyEntries) { - mEntries.clear(); - mEntries.addAll(historyEntries); - notifyDataSetChanged(); - } - - public Collection getItems() { - return mEntries; - } - - public void clear() { - mEntries.clear(); - notifyDataSetChanged(); - } - - protected String getFormattedDate(final Date date) { - return mDateFormat.format(date); - } - - protected String getFormattedViewString(final long viewCount) { - return Localization.shortViewCount(mContext, viewCount); - } - - @Override - public int getItemCount() { - return mEntries.size(); - } - - @Override - public void onBindViewHolder(final VH holder, final int position) { - final E entry = mEntries.get(position); - holder.itemView.setOnClickListener(v -> { - if (onHistoryItemClickListener != null) { - onHistoryItemClickListener.onHistoryItemClick(entry); - } - }); - - holder.itemView.setOnLongClickListener(view -> { - if (onHistoryItemClickListener != null) { - onHistoryItemClickListener.onHistoryItemLongClick(entry); - return true; - } - return false; - }); - - onBindViewHolder(holder, entry, position); - } - - @Override - public void onViewRecycled(@NonNull final VH holder) { - super.onViewRecycled(holder); - holder.itemView.setOnClickListener(null); - } - - abstract void onBindViewHolder(VH holder, E entry, int position); - - public void setOnHistoryItemClickListener( - @Nullable final OnHistoryItemClickListener onHistoryItemClickListener) { - this.onHistoryItemClickListener = onHistoryItemClickListener; - } - - public boolean isEmpty() { - return mEntries.isEmpty(); - } - - public interface OnHistoryItemClickListener { - void onHistoryItemClick(E item); - - void onHistoryItemLongClick(E item); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 3302e387e..43b7f1c0d 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -13,7 +13,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.viewbinding.ViewBinding; import com.evernote.android.state.State; import com.google.android.material.snackbar.Snackbar; @@ -45,6 +44,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.function.Supplier; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -126,12 +126,12 @@ public class StatisticsPlaylistFragment } @Override - protected ViewBinding getListHeader() { + protected Supplier getListHeaderSupplier() { headerBinding = StatisticPlaylistControlBinding.inflate(activity.getLayoutInflater(), itemsList, false); playlistControlBinding = headerBinding.playlistControl; - return headerBinding; + return headerBinding::getRoot; } @Override diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java index 336f5cfe3..528275d75 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java @@ -35,15 +35,15 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { } final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem; - itemTitleView.setText(item.name); + itemTitleView.setText(item.getOrderingName()); itemStreamCountView.setText(Localization.localizeStreamCountMini( - itemStreamCountView.getContext(), item.streamCount)); + itemStreamCountView.getContext(), item.getStreamCount())); itemUploaderView.setVisibility(View.INVISIBLE); - PicassoHelper.loadPlaylistThumbnail(item.thumbnailUrl).into(itemThumbnailView); + PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView); if (item instanceof PlaylistDuplicatesEntry - && ((PlaylistDuplicatesEntry) item).timesStreamIsContained > 0) { + && ((PlaylistDuplicatesEntry) item).getTimesStreamIsContained() > 0) { itemView.setAlpha(GRAYED_OUT_ALPHA); } else { itemView.setAlpha(1.0f); diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java index 765732063..3a339aec8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java @@ -34,7 +34,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { } final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem; - itemTitleView.setText(item.getName()); + itemTitleView.setText(item.getOrderingName()); itemStreamCountView.setText(Localization.localizeStreamCountMini( itemStreamCountView.getContext(), item.getStreamCount())); // Here is where the uploader name is set in the bookmarked playlists library diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/ExportPlaylist.kt b/app/src/main/java/org/schabi/newpipe/local/playlist/ExportPlaylist.kt index 0d4dcbfd0..a6c3561ec 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/ExportPlaylist.kt +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/ExportPlaylist.kt @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + package org.schabi.newpipe.local.playlist import android.content.Context @@ -21,11 +26,7 @@ fun export( } } -fun exportWithTitles( - playlist: List, - context: Context -): String { - +private fun exportWithTitles(playlist: List, context: Context): String { return playlist.asSequence() .map { it.streamEntity } .map { entity -> @@ -38,18 +39,13 @@ fun exportWithTitles( .joinToString(separator = "\n") } -fun exportJustUrls(playlist: List): String { - - return playlist.asSequence() - .map { it.streamEntity.url } - .joinToString(separator = "\n") +private fun exportJustUrls(playlist: List): String { + return playlist.joinToString(separator = "\n") { it.streamEntity.url } } -fun exportAsYoutubeTempPlaylist(playlist: List): String { - +private fun exportAsYoutubeTempPlaylist(playlist: List): String { val videoIDs = playlist.asReversed().asSequence() - .map { it.streamEntity.url } - .mapNotNull(::getYouTubeId) + .mapNotNull { getYouTubeId(it.streamEntity.url) } .take(50) // YouTube limitation: temp playlists can't have more than 50 items .toList() .asReversed() @@ -58,7 +54,7 @@ fun exportAsYoutubeTempPlaylist(playlist: List): String { return "https://www.youtube.com/watch_videos?video_ids=$videoIDs" } -val linkHandler: YoutubeStreamLinkHandlerFactory = YoutubeStreamLinkHandlerFactory.getInstance() +private val linkHandler: YoutubeStreamLinkHandlerFactory = YoutubeStreamLinkHandlerFactory.getInstance() /** * Gets the video id from a YouTube URL. @@ -66,7 +62,6 @@ val linkHandler: YoutubeStreamLinkHandlerFactory = YoutubeStreamLinkHandlerFacto * @param url YouTube URL * @return the video id */ -fun getYouTubeId(url: String): String? { - - return try { linkHandler.getId(url) } catch (e: ParsingException) { null } +private fun getYouTubeId(url: String): String? { + return runCatching { linkHandler.getId(url) }.getOrNull() } diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index f5562549c..cb38d9bae 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -1,5 +1,7 @@ package org.schabi.newpipe.local.playlist; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static org.schabi.newpipe.error.ErrorUtil.showUiErrorSnackbar; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.local.playlist.ExportPlaylistKt.export; @@ -22,6 +24,8 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; import android.widget.Toast; import androidx.annotation.NonNull; @@ -29,7 +33,6 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; -import androidx.viewbinding.ViewBinding; import com.evernote.android.state.State; import org.reactivestreams.Subscriber; @@ -55,6 +58,7 @@ import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; +import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; @@ -67,6 +71,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; import java.util.stream.Collectors; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; @@ -111,7 +116,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment getListHeaderSupplier() { headerBinding = LocalPlaylistHeaderBinding.inflate(activity.getLayoutInflater(), itemsList, - false); + false); playlistControlBinding = headerBinding.playlistControl; headerBinding.playlistTitleView.setSelected(true); - return headerBinding; + return headerBinding::getRoot; } @Override @@ -180,9 +185,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment() { @Override public void selected(final LocalItem selectedItem) { - if (selectedItem instanceof PlaylistStreamEntry) { - final StreamEntity item = - ((PlaylistStreamEntry) selectedItem).getStreamEntity(); + if (selectedItem instanceof PlaylistStreamEntry entry) { + final StreamEntity item = entry.getStreamEntity(); NavigationHelper.openVideoDetailFragment(requireContext(), getFM(), item.getServiceId(), item.getUrl(), item.getTitle(), null, false); } @@ -366,17 +370,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment - removeWatchedStreams(false)) - .setNeutralButton( - R.string.remove_watched_popup_yes_and_partially_watched_videos, - (d, id) -> removeWatchedStreams(true)) - .setNegativeButton(R.string.cancel, - (d, id) -> d.cancel()) - .show(); + openRemoveWatchedConfirmationDialog(); } } else if (item.getItemId() == R.id.menu_item_remove_duplicates) { if (!isRewritingPlaylist) { @@ -448,39 +442,28 @@ public class LocalPlaylistFragment extends BaseLocalListFragment items = itemListAdapter.getItemsList(); final List streamIds = new ArrayList<>(items.size()); for (final LocalItem item : items) { - if (item instanceof PlaylistStreamEntry) { - streamIds.add(((PlaylistStreamEntry) item).getStreamId()); + if (item instanceof PlaylistStreamEntry entry) { + streamIds.add(entry.getStreamId()); } } @@ -771,6 +756,13 @@ public class LocalPlaylistFragment extends BaseLocalListFragment + removeWatchedStreams(removePartiallyWatchedCheckbox.isChecked())) + .setNegativeButton(R.string.cancel, (d, id) -> d.cancel()) + .show(); + } + public void setTabsPagerAdapter( @Nullable final MainFragment.SelectedTabsPagerAdapter tabsPagerAdapter) { this.tabsPagerAdapter = tabsPagerAdapter; diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java index dd9307675..1480735fb 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java @@ -148,7 +148,7 @@ public class LocalPlaylistManager { public boolean getIsPlaylistThumbnailPermanent(final long playlistId) { return playlistTable.getPlaylist(playlistId).blockingFirst().get(0) - .getIsThumbnailPermanent(); + .isThumbnailPermanent(); } public long getAutomaticPlaylistThumbnailStreamId(final long playlistId) { @@ -174,7 +174,7 @@ public class LocalPlaylistManager { } if (thumbnailStreamId != THUMBNAIL_ID_LEAVE_UNCHANGED) { playlist.setThumbnailStreamId(thumbnailStreamId); - playlist.setIsThumbnailPermanent(isPermanent); + playlist.setThumbnailPermanent(isPermanent); } return playlistTable.update(playlist); }).subscribeOn(Schedulers.io()); diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/PlayListShareMode.java b/app/src/main/java/org/schabi/newpipe/local/playlist/PlayListShareMode.java deleted file mode 100644 index f0433aba8..000000000 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/PlayListShareMode.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.schabi.newpipe.local.playlist; - -public enum PlayListShareMode { - - JUST_URLS, - WITH_TITLES, - YOUTUBE_TEMP_PLAYLIST -} diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/PlayListShareMode.kt b/app/src/main/java/org/schabi/newpipe/local/playlist/PlayListShareMode.kt new file mode 100644 index 000000000..5595ce7fa --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/PlayListShareMode.kt @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.local.playlist + +enum class PlayListShareMode { + JUST_URLS, + WITH_TITLES, + YOUTUBE_TEMP_PLAYLIST +} diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.java b/app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.java deleted file mode 100644 index 08b203a7e..000000000 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.schabi.newpipe.local.playlist; - -import org.schabi.newpipe.database.AppDatabase; -import org.schabi.newpipe.database.playlist.dao.PlaylistRemoteDAO; -import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; -import org.schabi.newpipe.extractor.playlist.PlaylistInfo; - -import java.util.List; - -import io.reactivex.rxjava3.core.Completable; -import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.core.Single; -import io.reactivex.rxjava3.schedulers.Schedulers; - -public class RemotePlaylistManager { - - private final AppDatabase database; - private final PlaylistRemoteDAO playlistRemoteTable; - - public RemotePlaylistManager(final AppDatabase db) { - database = db; - playlistRemoteTable = db.playlistRemoteDAO(); - } - - public Flowable> getPlaylists() { - return playlistRemoteTable.getPlaylists().subscribeOn(Schedulers.io()); - } - - public Flowable getPlaylist(final long playlistId) { - return playlistRemoteTable.getPlaylist(playlistId).subscribeOn(Schedulers.io()); - } - - public Flowable> getPlaylist(final PlaylistInfo info) { - return playlistRemoteTable.getPlaylist(info.getServiceId(), info.getUrl()) - .subscribeOn(Schedulers.io()); - } - - public Single deletePlaylist(final long playlistId) { - return Single.fromCallable(() -> playlistRemoteTable.deletePlaylist(playlistId)) - .subscribeOn(Schedulers.io()); - } - - public Completable updatePlaylists(final List updateItems, - final List deletedItems) { - return Completable.fromRunnable(() -> database.runInTransaction(() -> { - for (final Long uid: deletedItems) { - playlistRemoteTable.deletePlaylist(uid); - } - for (final PlaylistRemoteEntity item: updateItems) { - playlistRemoteTable.upsert(item); - } - })).subscribeOn(Schedulers.io()); - } - - public Single onBookmark(final PlaylistInfo playlistInfo) { - return Single.fromCallable(() -> { - final PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo); - return playlistRemoteTable.upsert(playlist); - }).subscribeOn(Schedulers.io()); - } - - public Single onUpdate(final long playlistId, final PlaylistInfo playlistInfo) { - return Single.fromCallable(() -> { - final PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo); - playlist.setUid(playlistId); - return playlistRemoteTable.update(playlist); - }).subscribeOn(Schedulers.io()); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.kt b/app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.kt new file mode 100644 index 000000000..6961b6bb4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.kt @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2018-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.local.playlist + +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.core.Single +import io.reactivex.rxjava3.schedulers.Schedulers +import org.schabi.newpipe.database.AppDatabase +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity +import org.schabi.newpipe.extractor.playlist.PlaylistInfo + +class RemotePlaylistManager(private val database: AppDatabase) { + private val playlistRemoteTable = database.playlistRemoteDAO() + + val playlists: Flowable> + get() = playlistRemoteTable.playlists.subscribeOn(Schedulers.io()) + + fun getPlaylist(playlistId: Long): Flowable { + return playlistRemoteTable.getPlaylist(playlistId).subscribeOn(Schedulers.io()) + } + + fun getPlaylist(info: PlaylistInfo): Flowable> { + return playlistRemoteTable.getPlaylist(info.serviceId.toLong(), info.url) + .subscribeOn(Schedulers.io()) + } + + fun deletePlaylist(playlistId: Long): Single { + return Single.fromCallable { playlistRemoteTable.deletePlaylist(playlistId) } + .subscribeOn(Schedulers.io()) + } + + fun updatePlaylists( + updateItems: List, + deletedItems: List + ): Completable { + return Completable.fromRunnable { + database.runInTransaction { + deletedItems.forEach { playlistRemoteTable.deletePlaylist(it) } + updateItems.forEach { playlistRemoteTable.upsert(it) } + } + }.subscribeOn(Schedulers.io()) + } + + fun onBookmark(playlistInfo: PlaylistInfo): Single { + return Single.fromCallable { + val playlist = PlaylistRemoteEntity(playlistInfo) + playlistRemoteTable.upsert(playlist) + }.subscribeOn(Schedulers.io()) + } + + fun onUpdate(playlistId: Long, playlistInfo: PlaylistInfo): Single { + return Single.fromCallable { + val playlist = PlaylistRemoteEntity(playlistInfo).apply { uid = playlistId } + playlistRemoteTable.update(playlist) + }.subscribeOn(Schedulers.io()) + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java b/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java index 03dd4a1cd..0067e1154 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java @@ -10,26 +10,23 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; -import com.evernote.android.state.State; import com.livefront.bridge.Bridge; import org.schabi.newpipe.R; public class ImportConfirmationDialog extends DialogFragment { - @State protected Intent resultServiceIntent; + private static final String EXTRA_RESULT_SERVICE_INTENT = "extra_result_service_intent"; public static void show(@NonNull final Fragment fragment, @NonNull final Intent resultServiceIntent) { final ImportConfirmationDialog confirmationDialog = new ImportConfirmationDialog(); - confirmationDialog.setResultServiceIntent(resultServiceIntent); + final Bundle args = new Bundle(); + args.putParcelable(EXTRA_RESULT_SERVICE_INTENT, resultServiceIntent); + confirmationDialog.setArguments(args); confirmationDialog.show(fragment.getParentFragmentManager(), null); } - public void setResultServiceIntent(final Intent resultServiceIntent) { - this.resultServiceIntent = resultServiceIntent; - } - @NonNull @Override public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { @@ -38,9 +35,7 @@ public class ImportConfirmationDialog extends DialogFragment { .setCancelable(true) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.ok, (dialogInterface, i) -> { - if (resultServiceIntent != null && getContext() != null) { - getContext().startService(resultServiceIntent); - } + requireContext().startService(resultServiceIntent); dismiss(); }) .create(); @@ -50,11 +45,7 @@ public class ImportConfirmationDialog extends DialogFragment { public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (resultServiceIntent == null) { - throw new IllegalStateException("Result intent is null"); - } - - Bridge.restoreInstanceState(this, savedInstanceState); + resultServiceIntent = requireArguments().getParcelable(EXTRA_RESULT_SERVICE_INTENT); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 8e758adef..28abe4cf9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -27,6 +27,9 @@ import com.xwray.groupie.GroupAdapter import com.xwray.groupie.Section import com.xwray.groupie.viewbinding.GroupieViewHolder import io.reactivex.rxjava3.disposables.CompositeDisposable +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity.Companion.GROUP_ALL_ID import org.schabi.newpipe.databinding.DialogTitleBinding @@ -62,9 +65,6 @@ import org.schabi.newpipe.util.OnClickGesture import org.schabi.newpipe.util.ServiceHelper import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountChannels import org.schabi.newpipe.util.external_communication.ShareUtils -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale class SubscriptionFragment : BaseStateFragment() { private var _binding: FragmentSubscriptionBinding? = null @@ -276,10 +276,13 @@ class SubscriptionFragment : BaseStateFragment() { when (item) { is FeedGroupCardItem -> NavigationHelper.openFeedFragment(fm, item.groupId, item.name) + is FeedGroupCardGridItem -> NavigationHelper.openFeedFragment(fm, item.groupId, item.name) + is FeedGroupAddNewItem -> FeedGroupDialog.newInstance().show(fm, null) + is FeedGroupAddNewGridItem -> FeedGroupDialog.newInstance().show(fm, null) } @@ -294,6 +297,7 @@ class SubscriptionFragment : BaseStateFragment() { when (item) { is FeedGroupCardItem -> FeedGroupDialog.newInstance(item.groupId).show(fm, null) + is FeedGroupCardGridItem -> FeedGroupDialog.newInstance(item.groupId).show(fm, null) } @@ -309,7 +313,7 @@ class SubscriptionFragment : BaseStateFragment() { title = getString(R.string.feed_groups_header_title), onSortClicked = ::openReorderDialog, onToggleListViewModeClicked = ::toggleListViewMode, - listViewMode = viewModel.getListViewMode(), + listViewMode = viewModel.getListViewMode() ) add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) @@ -342,9 +346,14 @@ class SubscriptionFragment : BaseStateFragment() { val actions = DialogInterface.OnClickListener { _, i -> when (i) { 0 -> ShareUtils.shareText( - requireContext(), selectedItem.name, selectedItem.url, selectedItem.thumbnails + requireContext(), + selectedItem.name, + selectedItem.url, + selectedItem.thumbnails ) + 1 -> ShareUtils.openUrlInBrowser(requireContext(), selectedItem.url) + 2 -> deleteChannel(selectedItem) } } @@ -374,7 +383,9 @@ class SubscriptionFragment : BaseStateFragment() { private val listenerChannelItem = object : OnClickGesture { override fun selected(selectedItem: ChannelInfoItem) = NavigationHelper.openChannelFragment( fm, - selectedItem.serviceId, selectedItem.url, selectedItem.name + selectedItem.serviceId, + selectedItem.url, + selectedItem.name ) override fun held(selectedItem: ChannelInfoItem) = showLongTapDialog(selectedItem) @@ -404,6 +415,7 @@ class SubscriptionFragment : BaseStateFragment() { itemsListState = null } } + is SubscriptionState.ErrorState -> { result.error?.let { showError(ErrorInfo(result.error, UserAction.SOMETHING_ELSE, "Subscriptions")) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt index 474add4f4..2918ad5fb 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt @@ -26,7 +26,7 @@ class SubscriptionManager(context: Context) { private val feedDatabaseManager = FeedDatabaseManager(context) fun subscriptionTable(): SubscriptionDAO = subscriptionTable - fun subscriptions() = subscriptionTable.all + fun subscriptions() = subscriptionTable.getAll() fun getSubscriptions( currentGroupId: Long = FeedGroupEntity.GROUP_ALL_ID, @@ -37,14 +37,17 @@ class SubscriptionManager(context: Context) { filterQuery.isNotEmpty() -> { return if (showOnlyUngrouped) { subscriptionTable.getSubscriptionsOnlyUngroupedFiltered( - currentGroupId, filterQuery + currentGroupId, + filterQuery ) } else { subscriptionTable.getSubscriptionsFiltered(filterQuery) } } + showOnlyUngrouped -> subscriptionTable.getSubscriptionsOnlyUngrouped(currentGroupId) - else -> subscriptionTable.all + + else -> subscriptionTable.getAll() } } @@ -67,19 +70,18 @@ class SubscriptionManager(context: Context) { return listEntities } - fun updateChannelInfo(info: ChannelInfo): Completable = - subscriptionTable.getSubscription(info.serviceId, info.url) - .flatMapCompletable { - Completable.fromRunnable { - it.setData( - info.name, - ImageStrategy.imageListToDbUrl(info.avatars), - info.description, - info.subscriberCount - ) - subscriptionTable.update(it) + fun updateChannelInfo(info: ChannelInfo): Completable = subscriptionTable.getSubscription(info.serviceId, info.url) + .flatMapCompletable { + Completable.fromRunnable { + it.apply { + name = info.name + avatarUrl = ImageStrategy.imageListToDbUrl(info.avatars) + description = info.description + subscriberCount = info.subscriberCount } + subscriptionTable.update(it) } + } fun updateNotificationMode(serviceId: Int, url: String, @NotificationMode mode: Int): Completable { return subscriptionTable().getSubscription(serviceId, url) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt index dfad60c3f..fc28f8e59 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt @@ -9,6 +9,7 @@ import com.xwray.groupie.Group import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.processors.BehaviorProcessor import io.reactivex.rxjava3.schedulers.Schedulers +import java.util.concurrent.TimeUnit import org.schabi.newpipe.info_list.ItemViewMode import org.schabi.newpipe.local.feed.FeedDatabaseManager import org.schabi.newpipe.local.subscription.item.ChannelItem @@ -16,7 +17,6 @@ import org.schabi.newpipe.local.subscription.item.FeedGroupCardGridItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT import org.schabi.newpipe.util.ThemeHelper.getItemViewMode -import java.util.concurrent.TimeUnit class SubscriptionViewModel(application: Application) : AndroidViewModel(application) { private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(application) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt index 71c90e3c1..ab856278f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt @@ -23,6 +23,7 @@ import com.livefront.bridge.Bridge import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.OnItemClickListener import com.xwray.groupie.Section +import java.io.Serializable import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity import org.schabi.newpipe.databinding.DialogFeedGroupCreateBinding @@ -40,7 +41,6 @@ import org.schabi.newpipe.local.subscription.item.PickerIconItem import org.schabi.newpipe.local.subscription.item.PickerSubscriptionItem import org.schabi.newpipe.util.DeviceUtils import org.schabi.newpipe.util.ThemeHelper -import java.io.Serializable class FeedGroupDialog : DialogFragment(), BackPressable { private var _feedGroupCreateBinding: DialogFeedGroupCreateBinding? = null @@ -61,16 +61,41 @@ class FeedGroupDialog : DialogFragment(), BackPressable { data object DeleteScreen : ScreenState() } - @State @JvmField var selectedIcon: FeedGroupIcon? = null - @State @JvmField var selectedSubscriptions: HashSet = HashSet() - @State @JvmField var wasSubscriptionSelectionChanged: Boolean = false - @State @JvmField var currentScreen: ScreenState = InitialScreen + @State + @JvmField + var selectedIcon: FeedGroupIcon? = null - @State @JvmField var subscriptionsListState: Parcelable? = null - @State @JvmField var iconsListState: Parcelable? = null - @State @JvmField var wasSearchSubscriptionsVisible = false - @State @JvmField var subscriptionsCurrentSearchQuery = "" - @State @JvmField var subscriptionsShowOnlyUngrouped = false + @State + @JvmField + var selectedSubscriptions: HashSet = HashSet() + + @State + @JvmField + var wasSubscriptionSelectionChanged: Boolean = false + + @State + @JvmField + var currentScreen: ScreenState = InitialScreen + + @State + @JvmField + var subscriptionsListState: Parcelable? = null + + @State + @JvmField + var iconsListState: Parcelable? = null + + @State + @JvmField + var wasSearchSubscriptionsVisible = false + + @State + @JvmField + var subscriptionsCurrentSearchQuery = "" + + @State + @JvmField + var subscriptionsShowOnlyUngrouped = false private val subscriptionMainSection = Section() private val subscriptionEmptyFooter = Section() @@ -153,8 +178,10 @@ class FeedGroupDialog : DialogFragment(), BackPressable { itemAnimator = null adapter = subscriptionGroupAdapter layoutManager = GridLayoutManager( - requireContext(), subscriptionGroupAdapter.spanCount, - RecyclerView.VERTICAL, false + requireContext(), + subscriptionGroupAdapter.spanCount, + RecyclerView.VERTICAL, + false ).apply { spanSizeLookup = subscriptionGroupAdapter.spanSizeLookup } @@ -362,7 +389,8 @@ class FeedGroupDialog : DialogFragment(), BackPressable { val selectedCount = this.selectedSubscriptions.size val selectedCountText = resources.getQuantityString( R.plurals.feed_group_dialog_selection_count, - selectedCount, selectedCount + selectedCount, + selectedCount ) feedGroupCreateBinding.selectedSubscriptionCountView.text = selectedCountText feedGroupCreateBinding.subscriptionsHeaderInfo.text = selectedCountText diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialogViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialogViewModel.kt index 292bda394..d8eac2492 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialogViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialogViewModel.kt @@ -55,7 +55,8 @@ class FeedGroupDialogViewModel( private var subscriptionsDisposable = Flowable .combineLatest( - subscriptionsFlowable, feedDatabaseManager.subscriptionIdsForGroup(groupId) + subscriptionsFlowable, + feedDatabaseManager.subscriptionIdsForGroup(groupId) ) { t1: List, t2: List -> t1 to t2.toSet() } .subscribeOn(Schedulers.io()) .subscribe(mutableSubscriptionsLiveData::postValue) @@ -125,7 +126,10 @@ class FeedGroupDialogViewModel( ) = viewModelFactory { initializer { FeedGroupDialogViewModel( - context.applicationContext, groupId, initialQuery, initialShowOnlyUngrouped + context.applicationContext, + groupId, + initialQuery, + initialShowOnlyUngrouped ) } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt index c087da464..11f034ba0 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt @@ -15,6 +15,7 @@ import com.evernote.android.state.State import com.livefront.bridge.Bridge import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.TouchCallback +import java.util.Collections import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity import org.schabi.newpipe.databinding.DialogFeedGroupReorderBinding @@ -22,7 +23,6 @@ import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewMo import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.SuccessEvent import org.schabi.newpipe.local.subscription.item.FeedGroupReorderItem import org.schabi.newpipe.util.ThemeHelper -import java.util.Collections class FeedGroupReorderDialog : DialogFragment() { private var _binding: DialogFeedGroupReorderBinding? = null diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt index bc39dafe6..7946de693 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt @@ -43,7 +43,10 @@ class ChannelItem( gesturesListener?.run { viewHolder.root.setOnClickListener { selected(infoItem) } - viewHolder.root.setOnLongClickListener { held(infoItem); true } + viewHolder.root.setOnLongClickListener { + held(infoItem) + true + } } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt index 5a9d6887b..c78801c03 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt @@ -10,7 +10,7 @@ import org.schabi.newpipe.local.subscription.FeedGroupIcon data class FeedGroupCardGridItem( val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, val name: String, - val icon: FeedGroupIcon, + val icon: FeedGroupIcon ) : BindableItem() { constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 39f941693..e18ead899 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -114,6 +114,7 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.player.resolver.AudioPlaybackResolver; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver.SourceType; +import org.schabi.newpipe.player.ui.BackgroundPlayerUi; import org.schabi.newpipe.player.ui.MainPlayerUi; import org.schabi.newpipe.player.ui.PlayerUi; import org.schabi.newpipe.player.ui.PlayerUiList; @@ -271,6 +272,7 @@ public final class Player implements PlaybackListener, Listener { @NonNull private final HistoryRecordManager recordManager; + private boolean screenOn = true; /*////////////////////////////////////////////////////////////////////////// // Constructor @@ -395,7 +397,7 @@ public final class Player implements PlaybackListener, Listener { return; } final PlayQueueItem newItem = newQueue.getStreams().get(0); - newQueue.enqueueNext(newItem, false); + playQueue.enqueueNext(newItem, false); return; } @@ -574,6 +576,7 @@ public final class Player implements PlaybackListener, Listener { private void initUIsForCurrentPlayerType() { if ((UIs.get(MainPlayerUi.class).isPresent() && playerType == PlayerType.MAIN) + || (UIs.get(BackgroundPlayerUi.class).isPresent() && playerType == PlayerType.AUDIO) || (UIs.get(PopupPlayerUi.class).isPresent() && playerType == PlayerType.POPUP)) { // correct UI already in place return; @@ -592,14 +595,17 @@ public final class Player implements PlaybackListener, Listener { switch (playerType) { case MAIN: UIs.destroyAll(PopupPlayerUi.class); + UIs.destroyAll(BackgroundPlayerUi.class); UIs.addAndPrepare(new MainPlayerUi(this, binding)); break; case POPUP: UIs.destroyAll(MainPlayerUi.class); + UIs.destroyAll(BackgroundPlayerUi.class); UIs.addAndPrepare(new PopupPlayerUi(this, binding)); break; case AUDIO: - UIs.destroyAll(VideoPlayerUi.class); + UIs.destroyAll(VideoPlayerUi.class); // destroys both MainPlayerUi and PopupPlayerUi + UIs.addAndPrepare(new BackgroundPlayerUi(this)); break; } } @@ -842,6 +848,12 @@ public final class Player implements PlaybackListener, Listener { case ACTION_SHUFFLE: toggleShuffleModeEnabled(); break; + case Intent.ACTION_SCREEN_OFF: + screenOn = false; + break; + case Intent.ACTION_SCREEN_ON: + screenOn = true; + break; case Intent.ACTION_CONFIGURATION_CHANGED: if (DEBUG) { Log.d(TAG, "ACTION_CONFIGURATION_CHANGED received"); @@ -2195,12 +2207,12 @@ public final class Player implements PlaybackListener, Listener { } } - public void useVideoSource(final boolean videoEnabled) { - if (playQueue == null || audioPlayerSelected()) { + public void useVideoAndSubtitles(final boolean videoAndSubtitlesEnabled) { + if (playQueue == null) { return; } - isAudioOnly = !videoEnabled; + isAudioOnly = !videoAndSubtitlesEnabled; getCurrentStreamInfo().ifPresentOrElse(info -> { // In case we don't know the source type, fall back to either video-with-audio, or @@ -2208,27 +2220,28 @@ public final class Player implements PlaybackListener, Listener { final SourceType sourceType = videoResolver.getStreamSourceType() .orElse(SourceType.VIDEO_WITH_AUDIO_OR_AUDIO_ONLY); + setRecovery(); // making sure to save playback position before reloadPlayQueueManager() + if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) { reloadPlayQueueManager(); } - - setRecovery(); - - // Disable or enable video and subtitles renderers depending of the videoEnabled value - trackSelector.setParameters(trackSelector.buildUponParameters() - .setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled) - .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled)); }, () -> { /* The current metadata may be null sometimes (for e.g. when using an unstable connection - in livestreams) so we will be not able to execute the block below + in livestreams) so we will be not able to execute the block above Reload the play queue manager in this case, which is the behavior when we don't know the index of the video renderer or playQueueManagerReloadingNeeded returns true */ + setRecovery(); // making sure to save playback position before reloadPlayQueueManager() reloadPlayQueueManager(); - setRecovery(); }); + + // Disable or enable video and subtitles renderers depending of the + // videoAndSubtitlesEnabled value + trackSelector.setParameters(trackSelector.buildUponParameters() + .setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoAndSubtitlesEnabled) + .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoAndSubtitlesEnabled)); } /** @@ -2461,4 +2474,11 @@ public final class Player implements PlaybackListener, Listener { .orElse(RENDERER_UNAVAILABLE); } //endregion + + /** + * @return whether the device screen is turned on. + */ + public boolean isScreenOn() { + return screenOn; + } } diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerType.java b/app/src/main/java/org/schabi/newpipe/player/PlayerType.java deleted file mode 100644 index f74389d79..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/PlayerType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.schabi.newpipe.player; - -public enum PlayerType { - MAIN, - AUDIO, - POPUP; -} diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerType.kt b/app/src/main/java/org/schabi/newpipe/player/PlayerType.kt new file mode 100644 index 000000000..42b2e1131 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/PlayerType.kt @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2022-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.player + +enum class PlayerType { + MAIN, + AUDIO, + POPUP +} diff --git a/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java b/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java index be8941103..ed32450ba 100644 --- a/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/datasource/YoutubeHttpDataSource.java @@ -14,10 +14,8 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Util.castNonNull; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getAndroidUserAgent; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getIosUserAgent; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTvHtml5UserAgent; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isAndroidStreamingUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isIosStreamingUrl; -import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isTvHtml5StreamingUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebEmbeddedPlayerStreamingUrl; import static java.lang.Math.min; @@ -670,10 +668,7 @@ public final class YoutubeHttpDataSource extends BaseDataSource implements HttpD } } - final boolean isTvHtml5StreamingUrl = isTvHtml5StreamingUrl(requestUrl); - if (isWebStreamingUrl(requestUrl) - || isTvHtml5StreamingUrl || isWebEmbeddedPlayerStreamingUrl(requestUrl)) { httpURLConnection.setRequestProperty(HttpHeaders.ORIGIN, YOUTUBE_BASE_URL); httpURLConnection.setRequestProperty(HttpHeaders.REFERER, YOUTUBE_BASE_URL); @@ -694,9 +689,6 @@ public final class YoutubeHttpDataSource extends BaseDataSource implements HttpD } else if (isIosStreamingUrl) { httpURLConnection.setRequestProperty(HttpHeaders.USER_AGENT, getIosUserAgent(null)); - } else if (isTvHtml5StreamingUrl) { - httpURLConnection.setRequestProperty(HttpHeaders.USER_AGENT, - getTvHtml5UserAgent()); } else { // non-mobile user agent httpURLConnection.setRequestProperty(HttpHeaders.USER_AGENT, DownloaderImpl.USER_AGENT); diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt index 0453f297a..8682adc43 100644 --- a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt @@ -18,7 +18,7 @@ import org.schabi.newpipe.player.ui.VideoPlayerUi * and provides some abstract methods to make it easier separating the logic from the UI. */ abstract class BasePlayerGestureListener( - private val playerUi: VideoPlayerUi, + private val playerUi: VideoPlayerUi ) : GestureDetector.SimpleOnGestureListener(), View.OnTouchListener { protected val player: Player = playerUi.player @@ -86,8 +86,9 @@ abstract class BasePlayerGestureListener( // /////////////////////////////////////////////////////////////////// override fun onDown(e: MotionEvent): Boolean { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "onDown called with e = [$e]") + } if (isDoubleTapping && isDoubleTapEnabled) { doubleTapControls?.onDoubleTapProgressDown(getDisplayPortion(e)) @@ -108,8 +109,9 @@ abstract class BasePlayerGestureListener( } override fun onDoubleTap(e: MotionEvent): Boolean { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "onDoubleTap called with e = [$e]") + } onDoubleTap(e, getDisplayPortion(e)) return true @@ -136,8 +138,9 @@ abstract class BasePlayerGestureListener( private fun startMultiDoubleTap(e: MotionEvent) { if (!isDoubleTapping) { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "startMultiDoubleTap called with e = [$e]") + } keepInDoubleTapMode() doubleTapControls?.onDoubleTapStarted(getDisplayPortion(e)) @@ -145,8 +148,9 @@ abstract class BasePlayerGestureListener( } fun keepInDoubleTapMode() { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "keepInDoubleTapMode called") + } isDoubleTapping = true doubleTapHandler.removeCallbacksAndMessages(DOUBLE_TAP) @@ -161,8 +165,9 @@ abstract class BasePlayerGestureListener( } fun endMultiDoubleTap() { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "endMultiDoubleTap called") + } isDoubleTapping = false doubleTapHandler.removeCallbacksAndMessages(DOUBLE_TAP) diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/DisplayPortion.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/DisplayPortion.kt index 684f6d326..c5d483628 100644 --- a/app/src/main/java/org/schabi/newpipe/player/gesture/DisplayPortion.kt +++ b/app/src/main/java/org/schabi/newpipe/player/gesture/DisplayPortion.kt @@ -1,5 +1,9 @@ package org.schabi.newpipe.player.gesture enum class DisplayPortion { - LEFT, MIDDLE, RIGHT, LEFT_HALF, RIGHT_HALF + LEFT, + MIDDLE, + RIGHT, + LEFT_HALF, + RIGHT_HALF } diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt index ff0bb269d..7cc9ba224 100644 --- a/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt @@ -8,6 +8,7 @@ import android.widget.ProgressBar import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources import androidx.core.view.isVisible +import kotlin.math.abs import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.ktx.AnimationType @@ -17,7 +18,6 @@ import org.schabi.newpipe.player.helper.AudioReactor import org.schabi.newpipe.player.helper.PlayerHelper import org.schabi.newpipe.player.ui.MainPlayerUi import org.schabi.newpipe.util.ThemeHelper.getAndroidDimenPx -import kotlin.math.abs /** * GestureListener for the player @@ -42,24 +42,29 @@ class MainPlayerGestureListener( v.parent?.requestDisallowInterceptTouchEvent(playerUi.isFullscreen) true } + MotionEvent.ACTION_UP -> { v.parent?.requestDisallowInterceptTouchEvent(false) false } + else -> true } } override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "onSingleTapConfirmed() called with: e = [$e]") + } - if (isDoubleTapping) + if (isDoubleTapping) { return true + } super.onSingleTapConfirmed(e) - if (player.currentState != Player.STATE_BLOCKED) + if (player.currentState != Player.STATE_BLOCKED) { onSingleTap() + } return true } @@ -195,6 +200,7 @@ class MainPlayerGestureListener( when (PlayerHelper.getActionForRightGestureSide(player.context)) { player.context.getString(R.string.volume_control_key) -> onScrollVolume(distanceY) + player.context.getString(R.string.brightness_control_key) -> onScrollBrightness(distanceY) } @@ -202,6 +208,7 @@ class MainPlayerGestureListener( when (PlayerHelper.getActionForLeftGestureSide(player.context)) { player.context.getString(R.string.volume_control_key) -> onScrollVolume(distanceY) + player.context.getString(R.string.brightness_control_key) -> onScrollBrightness(distanceY) } diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt index 0b94bf364..60752652e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt @@ -5,17 +5,17 @@ import android.view.MotionEvent import android.view.View import android.view.ViewConfiguration import androidx.core.view.isVisible -import org.schabi.newpipe.MainActivity -import org.schabi.newpipe.ktx.AnimationType -import org.schabi.newpipe.ktx.animate -import org.schabi.newpipe.player.ui.PopupPlayerUi import kotlin.math.abs import kotlin.math.hypot import kotlin.math.max import kotlin.math.min +import org.schabi.newpipe.MainActivity +import org.schabi.newpipe.ktx.AnimationType +import org.schabi.newpipe.ktx.animate +import org.schabi.newpipe.player.ui.PopupPlayerUi class PopupPlayerGestureListener( - private val playerUi: PopupPlayerUi, + private val playerUi: PopupPlayerUi ) : BasePlayerGestureListener(playerUi) { private var isMoving = false @@ -205,13 +205,16 @@ class PopupPlayerGestureListener( } override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "onSingleTapConfirmed() called with: e = [$e]") + } - if (isDoubleTapping) + if (isDoubleTapping) { return true - if (player.exoPlayerIsNull()) + } + if (player.exoPlayerIsNull()) { return false + } onSingleTap() return true diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 6b4f470e8..2bae110ed 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -129,6 +129,13 @@ public class PlayerDataSource { getDefaultDashChunkSourceFactory(cachelessDataSourceFactory), cachelessDataSourceFactory); } + + public DashMediaSource.Factory getLiveYoutubeDashMediaSourceFactory() { + return new DashMediaSource.Factory( + getDefaultDashChunkSourceFactory(cachelessDataSourceFactory), + cachelessDataSourceFactory) + .setManifestParser(new YoutubeDashLiveManifestParser()); + } //endregion diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index c335e9b7c..0f9579352 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -141,11 +141,11 @@ public final class PlayerHelper { @ResizeMode final int resizeMode) { switch (resizeMode) { case AspectRatioFrameLayout.RESIZE_MODE_FIT: - return context.getResources().getString(R.string.resize_fit); + return context.getString(R.string.resize_fit); case AspectRatioFrameLayout.RESIZE_MODE_FILL: - return context.getResources().getString(R.string.resize_fill); + return context.getString(R.string.resize_fill); case AspectRatioFrameLayout.RESIZE_MODE_ZOOM: - return context.getResources().getString(R.string.resize_zoom); + return context.getString(R.string.resize_zoom); case AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT: case AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH: default: diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/YoutubeDashLiveManifestParser.java b/app/src/main/java/org/schabi/newpipe/player/helper/YoutubeDashLiveManifestParser.java new file mode 100644 index 000000000..00f5de071 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/helper/YoutubeDashLiveManifestParser.java @@ -0,0 +1,68 @@ +package org.schabi.newpipe.player.helper; + +import android.net.Uri; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.exoplayer2.source.dash.manifest.DashManifest; +import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser; +import com.google.android.exoplayer2.source.dash.manifest.Period; +import com.google.android.exoplayer2.source.dash.manifest.ProgramInformation; +import com.google.android.exoplayer2.source.dash.manifest.ServiceDescriptionElement; +import com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement; + +import java.util.List; + +/** + * A {@link DashManifestParser} fixing YouTube DASH manifests to allow starting playback from the + * newest period available instead of the earliest one in some cases. + * + *

+ * It changes the {@code availabilityStartTime} passed to a custom value doing the workaround. + * A better approach to fix the issue should be investigated and used in the future. + *

+ */ +public class YoutubeDashLiveManifestParser extends DashManifestParser { + + // Result of Util.parseXsDateTime("1970-01-01T00:00:00Z") + private static final long AVAILABILITY_START_TIME_TO_USE = 0; + + // There is no computation made with the availabilityStartTime value in the + // parseMediaPresentationDescription method itself, so we can just override methods called in + // this method using the workaround value + // Overriding parsePeriod does not seem to be needed + + @SuppressWarnings("checkstyle:ParameterNumber") + @NonNull + @Override + protected DashManifest buildMediaPresentationDescription( + final long availabilityStartTime, + final long durationMs, + final long minBufferTimeMs, + final boolean dynamic, + final long minUpdateTimeMs, + final long timeShiftBufferDepthMs, + final long suggestedPresentationDelayMs, + final long publishTimeMs, + @Nullable final ProgramInformation programInformation, + @Nullable final UtcTimingElement utcTiming, + @Nullable final ServiceDescriptionElement serviceDescription, + @Nullable final Uri location, + @NonNull final List periods) { + return super.buildMediaPresentationDescription( + AVAILABILITY_START_TIME_TO_USE, + durationMs, + minBufferTimeMs, + dynamic, + minUpdateTimeMs, + timeShiftBufferDepthMs, + suggestedPresentationDelayMs, + publishTimeMs, + programInformation, + utcTiming, + serviceDescription, + location, + periods); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserImpl.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserImpl.kt index b7d57657d..6b59f683a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserImpl.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserImpl.kt @@ -17,6 +17,7 @@ import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.schedulers.Schedulers +import java.util.function.Consumer import org.schabi.newpipe.MainActivity.DEBUG import org.schabi.newpipe.NewPipeDatabase import org.schabi.newpipe.R @@ -37,7 +38,6 @@ import org.schabi.newpipe.local.playlist.RemotePlaylistManager import org.schabi.newpipe.util.ExtractorHelper import org.schabi.newpipe.util.ServiceHelper import org.schabi.newpipe.util.image.ImageStrategy -import java.util.function.Consumer /** * This class is used to cleanly separate the Service implementation (in @@ -47,7 +47,8 @@ import java.util.function.Consumer */ class MediaBrowserImpl( private val context: Context, - notifyChildrenChanged: Consumer, // parentId + // parentId + notifyChildrenChanged: Consumer ) { private val packageValidator = PackageValidator(context) private val database = NewPipeDatabase.getInstance(context) @@ -89,7 +90,8 @@ class MediaBrowserImpl( val extras = Bundle() extras.putBoolean( - MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true + MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, + true ) return MediaBrowserServiceCompat.BrowserRoot(ID_ROOT, extras) } @@ -137,7 +139,7 @@ class MediaBrowserImpl( ) } - when (/*val uriType = */path.removeAt(0)) { + when (path.removeAt(0)) { ID_BOOKMARKS -> { if (path.isEmpty()) { return populateBookmarks() @@ -204,12 +206,12 @@ class MediaBrowserImpl( val extras = Bundle() extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, - context.resources.getString(R.string.tab_bookmarks), + context.resources.getString(R.string.tab_bookmarks) ) builder.setExtras(extras) return MediaBrowserCompat.MediaItem( builder.build(), - MediaBrowserCompat.MediaItem.FLAG_BROWSABLE, + MediaBrowserCompat.MediaItem.FLAG_BROWSABLE ) } @@ -266,7 +268,7 @@ class MediaBrowserImpl( private fun createLocalPlaylistStreamMediaItem( playlistId: Long, item: PlaylistStreamEntry, - index: Int, + index: Int ): MediaBrowserCompat.MediaItem { val builder = MediaDescriptionCompat.Builder() builder.setMediaId(createMediaIdForPlaylistIndex(false, playlistId, index)) @@ -283,7 +285,7 @@ class MediaBrowserImpl( private fun createRemotePlaylistStreamMediaItem( playlistId: Long, item: StreamInfoItem, - index: Int, + index: Int ): MediaBrowserCompat.MediaItem { val builder = MediaDescriptionCompat.Builder() builder.setMediaId(createMediaIdForPlaylistIndex(true, playlistId, index)) @@ -303,7 +305,7 @@ class MediaBrowserImpl( private fun createMediaIdForPlaylistIndex( isRemote: Boolean, playlistId: Long, - index: Int, + index: Int ): String { return buildLocalPlaylistItemMediaId(isRemote, playlistId) .appendPath(index.toString()) @@ -315,7 +317,7 @@ class MediaBrowserImpl( } private fun populateHistory(): Single> { - val history = database.streamHistoryDAO().getHistory().firstOrError() + val history = database.streamHistoryDAO().history.firstOrError() return history.map { items -> items.map { this.createHistoryMediaItem(it) } } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt index 4815965a3..890c83cfa 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt @@ -14,6 +14,8 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.schedulers.Schedulers +import java.util.function.BiConsumer +import java.util.function.Consumer import org.schabi.newpipe.MainActivity import org.schabi.newpipe.NewPipeDatabase import org.schabi.newpipe.R @@ -30,8 +32,6 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue import org.schabi.newpipe.util.ChannelTabHelper import org.schabi.newpipe.util.ExtractorHelper import org.schabi.newpipe.util.NavigationHelper -import java.util.function.BiConsumer -import java.util.function.Consumer /** * This class is used to cleanly separate the Service implementation (in @@ -51,7 +51,7 @@ class MediaBrowserPlaybackPreparer( private val context: Context, private val setMediaSessionError: BiConsumer, // error string, error code private val clearMediaSessionError: Runnable, - private val onPrepare: Consumer, + private val onPrepare: Consumer ) : PlaybackPreparer { private val database = NewPipeDatabase.getInstance(context) private var disposable: Disposable? = null @@ -146,7 +146,7 @@ class MediaBrowserPlaybackPreparer( throw parseError(mediaId) } - return when (/*val uriType = */path.removeAt(0)) { + return when (path.removeAt(0)) { ID_BOOKMARKS -> extractPlayQueueFromPlaylistMediaId( mediaId, path, @@ -172,7 +172,7 @@ class MediaBrowserPlaybackPreparer( private fun extractPlayQueueFromPlaylistMediaId( mediaId: String, path: MutableList, - url: String?, + url: String? ): Single { if (path.isEmpty()) { throw parseError(mediaId) @@ -185,10 +185,11 @@ class MediaBrowserPlaybackPreparer( } val playlistId = path[0].toLong() val index = path[1].toInt() - return if (playlistType == ID_LOCAL) + return if (playlistType == ID_LOCAL) { extractLocalPlayQueue(playlistId, index) - else + } else { extractRemotePlayQueue(playlistId, index) + } } ID_URL -> { @@ -208,14 +209,14 @@ class MediaBrowserPlaybackPreparer( @Throws(ContentNotAvailableException::class) private fun extractPlayQueueFromHistoryMediaId( mediaId: String, - path: List, + path: List ): Single { if (path.size != 1) { throw parseError(mediaId) } val streamId = path[0].toLong() - return database.streamHistoryDAO().getHistory() + return database.streamHistoryDAO().history .firstOrError() .map { items -> val infoItems = items @@ -229,14 +230,14 @@ class MediaBrowserPlaybackPreparer( private fun extractPlayQueueFromInfoItemMediaId( mediaId: String, path: List, - url: String, + url: String ): Single { if (path.size != 2) { throw parseError(mediaId) } val serviceId = path[1].toInt() - return when (/*val infoItemType = */infoItemTypeFromString(path[0])) { + return when (infoItemTypeFromString(path[0])) { InfoType.STREAM -> ExtractorHelper.getStreamInfo(serviceId, url, false) .map { SinglePlayQueue(it) } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt index 05719b6d4..05c94e990 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt @@ -30,9 +30,9 @@ import android.support.v4.media.session.MediaSessionCompat import android.util.Log import androidx.core.app.NotificationManagerCompat import androidx.media.MediaBrowserServiceCompat -import org.schabi.newpipe.BuildConfig import java.security.MessageDigest import java.security.NoSuchAlgorithmException +import org.schabi.newpipe.BuildConfig /** * Validates that the calling package is authorized to browse a [MediaBrowserServiceCompat]. @@ -94,18 +94,22 @@ internal class PackageValidator(context: Context) { val isCallerKnown = when { // If it's our own app making the call, allow it. callingUid == Process.myUid() -> true + // If the system is making the call, allow it. callingUid == Process.SYSTEM_UID -> true + // If the app was signed by the same certificate as the platform itself, also allow it. callerSignature == platformSignature -> true - /** + + /* * [MEDIA_CONTENT_CONTROL] permission is only available to system applications, and * while it isn't required to allow these apps to connect to a * [MediaBrowserServiceCompat], allowing this ensures optimal compatability with apps * such as Android TV and the Google Assistant. */ callerPackageInfo.permissions.contains(MEDIA_CONTENT_CONTROL) -> true - /** + + /* * If the calling app has a notification listener it is able to retrieve notifications * and can connect to an active [MediaSessionCompat]. * @@ -169,11 +173,10 @@ internal class PackageValidator(context: Context) { */ @Suppress("deprecation") @SuppressLint("PackageManagerGetSignatures") - private fun getPackageInfo(callingPackage: String): PackageInfo? = - packageManager.getPackageInfo( - callingPackage, - PackageManager.GET_SIGNATURES or PackageManager.GET_PERMISSIONS - ) + private fun getPackageInfo(callingPackage: String): PackageInfo? = packageManager.getPackageInfo( + callingPackage, + PackageManager.GET_SIGNATURES or PackageManager.GET_PERMISSIONS + ) /** * Gets the signature of a given package's [PackageInfo]. @@ -185,23 +188,21 @@ internal class PackageValidator(context: Context) { * returns `null` as the signature. */ @Suppress("deprecation") - private fun getSignature(packageInfo: PackageInfo): String? = - if (packageInfo.signatures == null || packageInfo.signatures!!.size != 1) { - // Security best practices dictate that an app should be signed with exactly one (1) - // signature. Because of this, if there are multiple signatures, reject it. - null - } else { - val certificate = packageInfo.signatures!![0].toByteArray() - getSignatureSha256(certificate) - } + private fun getSignature(packageInfo: PackageInfo): String? = if (packageInfo.signatures == null || packageInfo.signatures!!.size != 1) { + // Security best practices dictate that an app should be signed with exactly one (1) + // signature. Because of this, if there are multiple signatures, reject it. + null + } else { + val certificate = packageInfo.signatures!![0].toByteArray() + getSignatureSha256(certificate) + } /** * Finds the Android platform signing key signature. This key is never null. */ - private fun getSystemSignature(): String = - getPackageInfo(ANDROID_PLATFORM)?.let { platformInfo -> - getSignature(platformInfo) - } ?: throw IllegalStateException("Platform signature not found") + private fun getSystemSignature(): String = getPackageInfo(ANDROID_PLATFORM)?.let { platformInfo -> + getSignature(platformInfo) + } ?: throw IllegalStateException("Platform signature not found") /** * Creates a SHA-256 signature given a certificate byte array. diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index 88d7145bc..5cffc7f62 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -17,10 +17,10 @@ import org.schabi.newpipe.player.mediasource.ManagedMediaSource; import org.schabi.newpipe.player.mediasource.ManagedMediaSourcePlaylist; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueueItem; -import org.schabi.newpipe.player.playqueue.events.MoveEvent; -import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent; -import org.schabi.newpipe.player.playqueue.events.RemoveEvent; -import org.schabi.newpipe.player.playqueue.events.ReorderEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.MoveEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.RemoveEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.ReorderEvent; import java.util.Collection; import java.util.Collections; diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java index 97196805d..8a66dc2ff 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java @@ -4,15 +4,14 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.schabi.newpipe.MainActivity; -import org.schabi.newpipe.player.playqueue.events.AppendEvent; -import org.schabi.newpipe.player.playqueue.events.ErrorEvent; -import org.schabi.newpipe.player.playqueue.events.InitEvent; -import org.schabi.newpipe.player.playqueue.events.MoveEvent; -import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent; -import org.schabi.newpipe.player.playqueue.events.RecoveryEvent; -import org.schabi.newpipe.player.playqueue.events.RemoveEvent; -import org.schabi.newpipe.player.playqueue.events.ReorderEvent; -import org.schabi.newpipe.player.playqueue.events.SelectEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.AppendEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.ErrorEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.InitEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.MoveEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.RecoveryEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.RemoveEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.ReorderEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.SelectEvent; import java.io.Serializable; import java.util.ArrayList; @@ -23,7 +22,7 @@ import java.util.concurrent.atomic.AtomicInteger; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.BackpressureStrategy; import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.subjects.BehaviorSubject; +import io.reactivex.rxjava3.subjects.PublishSubject; /** * PlayQueue is responsible for keeping track of a list of streams and the index of @@ -46,7 +45,7 @@ public abstract class PlayQueue implements Serializable { private List backup; private List streams; - private transient BehaviorSubject eventBroadcast; + private transient PublishSubject eventBroadcast; private transient Flowable broadcastReceiver; private transient boolean disposed = false; @@ -71,7 +70,7 @@ public abstract class PlayQueue implements Serializable { *

*/ public void init() { - eventBroadcast = BehaviorSubject.create(); + eventBroadcast = PublishSubject.create(); broadcastReceiver = eventBroadcast.toFlowable(BackpressureStrategy.BUFFER) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java index dd95fb4d5..2e19672e5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java @@ -10,12 +10,11 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import org.schabi.newpipe.R; -import org.schabi.newpipe.player.playqueue.events.AppendEvent; -import org.schabi.newpipe.player.playqueue.events.ErrorEvent; -import org.schabi.newpipe.player.playqueue.events.MoveEvent; -import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent; -import org.schabi.newpipe.player.playqueue.events.RemoveEvent; -import org.schabi.newpipe.player.playqueue.events.SelectEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.AppendEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.ErrorEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.MoveEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.RemoveEvent; +import org.schabi.newpipe.player.playqueue.PlayQueueEvent.SelectEvent; import org.schabi.newpipe.util.FallbackViewHolder; import java.util.List; diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueEvent.kt b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueEvent.kt new file mode 100644 index 000000000..f1952ef95 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueEvent.kt @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2017-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.player.playqueue + +import java.io.Serializable + +sealed interface PlayQueueEvent : Serializable { + fun type(): Type + + class InitEvent : PlayQueueEvent { + override fun type() = Type.INIT + } + + // sent when the index is changed + class SelectEvent(val oldIndex: Int, val newIndex: Int) : PlayQueueEvent { + override fun type() = Type.SELECT + } + + // sent when more streams are added to the play queue + class AppendEvent(val amount: Int) : PlayQueueEvent { + override fun type() = Type.APPEND + } + + // sent when a pending stream is removed from the play queue + class RemoveEvent(val removeIndex: Int, val queueIndex: Int) : PlayQueueEvent { + override fun type() = Type.REMOVE + } + + // sent when two streams swap place in the play queue + class MoveEvent(val fromIndex: Int, val toIndex: Int) : PlayQueueEvent { + override fun type() = Type.MOVE + } + + // sent when queue is shuffled + class ReorderEvent(val fromSelectedIndex: Int, val toSelectedIndex: Int) : PlayQueueEvent { + override fun type() = Type.REORDER + } + + // sent when recovery record is set on a stream + class RecoveryEvent(val index: Int, val position: Long) : PlayQueueEvent { + override fun type() = Type.RECOVERY + } + + // sent when the item at index has caused an exception + class ErrorEvent(val errorIndex: Int, val queueIndex: Int) : PlayQueueEvent { + override fun type() = Type.ERROR + } + + // It is necessary only for use in java code. Remove it and use kotlin pattern + // matching when all users of this enum are converted to kotlin + enum class Type { INIT, SELECT, APPEND, REMOVE, MOVE, REORDER, RECOVERY, ERROR } +} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/AppendEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/AppendEvent.java deleted file mode 100644 index cc922dbb1..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/AppendEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class AppendEvent implements PlayQueueEvent { - private final int amount; - - public AppendEvent(final int amount) { - this.amount = amount; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.APPEND; - } - - public int getAmount() { - return amount; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/ErrorEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/ErrorEvent.java deleted file mode 100644 index 7b7e39212..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/ErrorEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class ErrorEvent implements PlayQueueEvent { - private final int errorIndex; - private final int queueIndex; - - public ErrorEvent(final int errorIndex, final int queueIndex) { - this.errorIndex = errorIndex; - this.queueIndex = queueIndex; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.ERROR; - } - - public int getErrorIndex() { - return errorIndex; - } - - public int getQueueIndex() { - return queueIndex; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/InitEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/InitEvent.java deleted file mode 100644 index 559975b35..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/InitEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class InitEvent implements PlayQueueEvent { - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.INIT; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/MoveEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/MoveEvent.java deleted file mode 100644 index 55d198923..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/MoveEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class MoveEvent implements PlayQueueEvent { - private final int fromIndex; - private final int toIndex; - - public MoveEvent(final int oldIndex, final int newIndex) { - this.fromIndex = oldIndex; - this.toIndex = newIndex; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.MOVE; - } - - public int getFromIndex() { - return fromIndex; - } - - public int getToIndex() { - return toIndex; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/PlayQueueEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/PlayQueueEvent.java deleted file mode 100644 index 431053e7b..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/PlayQueueEvent.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -import java.io.Serializable; - -public interface PlayQueueEvent extends Serializable { - PlayQueueEventType type(); -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/PlayQueueEventType.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/PlayQueueEventType.java deleted file mode 100644 index 1cc710c7b..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/PlayQueueEventType.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public enum PlayQueueEventType { - INIT, - - // sent when the index is changed - SELECT, - - // sent when more streams are added to the play queue - APPEND, - - // sent when a pending stream is removed from the play queue - REMOVE, - - // sent when two streams swap place in the play queue - MOVE, - - // sent when queue is shuffled - REORDER, - - // sent when recovery record is set on a stream - RECOVERY, - - // sent when the item at index has caused an exception - ERROR -} - diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/RecoveryEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/RecoveryEvent.java deleted file mode 100644 index 6f21b36cd..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/RecoveryEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class RecoveryEvent implements PlayQueueEvent { - private final int index; - private final long position; - - public RecoveryEvent(final int index, final long position) { - this.index = index; - this.position = position; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.RECOVERY; - } - - public int getIndex() { - return index; - } - - public long getPosition() { - return position; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/RemoveEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/RemoveEvent.java deleted file mode 100644 index a5872906d..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/RemoveEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class RemoveEvent implements PlayQueueEvent { - private final int removeIndex; - private final int queueIndex; - - public RemoveEvent(final int removeIndex, final int queueIndex) { - this.removeIndex = removeIndex; - this.queueIndex = queueIndex; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.REMOVE; - } - - public int getQueueIndex() { - return queueIndex; - } - - public int getRemoveIndex() { - return removeIndex; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/ReorderEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/ReorderEvent.java deleted file mode 100644 index 4f4f14756..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/ReorderEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class ReorderEvent implements PlayQueueEvent { - private final int fromSelectedIndex; - private final int toSelectedIndex; - - public ReorderEvent(final int fromSelectedIndex, final int toSelectedIndex) { - this.fromSelectedIndex = fromSelectedIndex; - this.toSelectedIndex = toSelectedIndex; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.REORDER; - } - - public int getFromSelectedIndex() { - return fromSelectedIndex; - } - - public int getToSelectedIndex() { - return toSelectedIndex; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/SelectEvent.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/events/SelectEvent.java deleted file mode 100644 index 95e344211..000000000 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/events/SelectEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.player.playqueue.events; - -public class SelectEvent implements PlayQueueEvent { - private final int oldIndex; - private final int newIndex; - - public SelectEvent(final int oldIndex, final int newIndex) { - this.oldIndex = oldIndex; - this.newIndex = newIndex; - } - - @Override - public PlayQueueEventType type() { - return PlayQueueEventType.SELECT; - } - - public int getOldIndex() { - return oldIndex; - } - - public int getNewIndex() { - return newIndex; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java index e204b8372..7dc80a958 100644 --- a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java +++ b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java @@ -201,12 +201,15 @@ public interface PlaybackResolver extends Resolver { try { final StreamInfoTag tag = StreamInfoTag.of(info); - if (!info.getHlsUrl().isEmpty()) { - return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.CONTENT_TYPE_HLS, tag); - } else if (!info.getDashMpdUrl().isEmpty()) { + // Prefer DASH over HLS because of an exoPlayer bug that causes the background player to + // also fetch the video stream even if it is supposed to just fetch the audio stream. + if (!info.getDashMpdUrl().isEmpty()) { return buildLiveMediaSource( dataSource, info.getDashMpdUrl(), C.CONTENT_TYPE_DASH, tag); } + if (!info.getHlsUrl().isEmpty()) { + return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.CONTENT_TYPE_HLS, tag); + } } catch (final Exception e) { Log.w(TAG, "Error when generating live media source, falling back to standard sources", e); @@ -225,7 +228,11 @@ public interface PlaybackResolver extends Resolver { factory = dataSource.getLiveSsMediaSourceFactory(); break; case C.CONTENT_TYPE_DASH: - factory = dataSource.getLiveDashMediaSourceFactory(); + if (metadata.getServiceId() == ServiceList.YouTube.getServiceId()) { + factory = dataSource.getLiveYoutubeDashMediaSourceFactory(); + } else { + factory = dataSource.getLiveDashMediaSourceFactory(); + } break; case C.CONTENT_TYPE_HLS: factory = dataSource.getLiveHlsMediaSourceFactory(); diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/BackgroundPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/BackgroundPlayerUi.java new file mode 100644 index 000000000..4172df35e --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/ui/BackgroundPlayerUi.java @@ -0,0 +1,29 @@ +package org.schabi.newpipe.player.ui; + +import androidx.annotation.NonNull; + +import org.schabi.newpipe.player.Player; + +/** + * This is not a "graphical" UI for the background player, but it is used to disable fetching video + * and text tracks with it. + * + *

+ * This allows reducing data usage for manifest sources with demuxed audio and video, + * such as livestreams. + *

+ */ +public class BackgroundPlayerUi extends PlayerUi { + + public BackgroundPlayerUi(@NonNull final Player player) { + super(player); + } + + @Override + public void initPlayback() { + super.initPlayback(); + + // Make sure to disable video and subtitles track types + player.useVideoAndSubtitles(false); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java index d8efb30df..868881782 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java @@ -216,6 +216,10 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh playQueueAdapter = new PlayQueueAdapter(context, Objects.requireNonNull(player.getPlayQueue())); segmentAdapter = new StreamSegmentAdapter(getStreamSegmentListener()); + + // Make sure video and text tracks are enabled if the user is in the app, in the case user + // switched from background player to main player + player.useVideoAndSubtitles(fragmentIsVisible); } @Override @@ -289,8 +293,10 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh binding.topControls.setClickable(true); binding.topControls.setFocusable(true); - binding.titleTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); - binding.channelTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); + binding.metadataView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); + + // Reset workaround changes from popup player + binding.audioTrackTextView.setMaxWidth(Integer.MAX_VALUE); } @Override @@ -329,7 +335,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } else if (VideoDetailFragment.ACTION_VIDEO_FRAGMENT_RESUMED.equals(intent.getAction())) { // Restore video source when user returns to the fragment fragmentIsVisible = true; - player.useVideoSource(true); + player.useVideoAndSubtitles(true); // When a user returns from background, the system UI will always be shown even if // controls are invisible: hide it in that case @@ -368,7 +374,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh if (player.isPlaying() || player.isLoading()) { switch (getMinimizeOnExitAction(context)) { case MINIMIZE_ON_EXIT_MODE_BACKGROUND: - player.useVideoSource(false); + player.useVideoAndSubtitles(false); break; case MINIMIZE_ON_EXIT_MODE_POPUP: getParentActivity().ifPresent(activity -> { @@ -934,8 +940,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } fragmentListener.onFullscreenStateChanged(isFullscreen); - binding.titleTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); - binding.channelTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); + binding.metadataView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); binding.playerCloseButton.setVisibility(isFullscreen ? View.GONE : View.VISIBLE); setupScreenRotationButton(); } diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java index 6c98ab0fa..b9c29c008 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java @@ -40,6 +40,7 @@ import org.schabi.newpipe.player.Player; import org.schabi.newpipe.player.gesture.BasePlayerGestureListener; import org.schabi.newpipe.player.gesture.PopupPlayerGestureListener; import org.schabi.newpipe.player.helper.PlayerHelper; +import org.schabi.newpipe.util.DeviceUtils; public final class PopupPlayerUi extends VideoPlayerUi { private static final String TAG = PopupPlayerUi.class.getSimpleName(); @@ -151,6 +152,14 @@ public final class PopupPlayerUi extends VideoPlayerUi { windowManager.addView(closeOverlayBinding.getRoot(), closeOverlayLayoutParams); } + @Override + public void initPlayback() { + super.initPlayback(); + // Make sure video and text tracks are enabled if the screen is turned on (which should + // always be the case), in the case user switched from background player to popup player + player.useVideoAndSubtitles(player.isScreenOn()); + } + @Override protected void setupElementsVisibility() { binding.fullScreenButton.setVisibility(View.VISIBLE); @@ -174,6 +183,8 @@ public final class PopupPlayerUi extends VideoPlayerUi { binding.topControls.setClickable(false); binding.topControls.setFocusable(false); binding.bottomControls.bringToFront(); + // Workaround that UI elements are pushed off screen + binding.audioTrackTextView.setMaxWidth(DeviceUtils.dpToPx(48, context)); super.setupElementsVisibility(); } @@ -216,10 +227,10 @@ public final class PopupPlayerUi extends VideoPlayerUi { } else if (player.isPlaying() || player.isLoading()) { if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { // Use only audio source when screen turns off while popup player is playing - player.useVideoSource(false); + player.useVideoAndSubtitles(false); } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { // Restore video source when screen turns on and user was watching video in popup - player.useVideoSource(true); + player.useVideoAndSubtitles(true); } } } diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java index 7157d6af2..b68d3d94d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java @@ -1554,6 +1554,11 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa @Override public void onVideoSizeChanged(@NonNull final VideoSize videoSize) { super.onVideoSizeChanged(videoSize); + // Starting with ExoPlayer 2.19.0, the VideoSize will report a width and height of 0 + // if the renderer is disabled. In that case, we skip updating the aspect ratio. + if (videoSize.width == 0 || videoSize.height == 0) { + return; + } binding.surfaceView.setAspectRatio(((float) videoSize.width) / videoSize.height); } //endregion diff --git a/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java index 321ad65da..baaa93e44 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java @@ -40,6 +40,8 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class BackupRestoreSettingsFragment extends BasePreferenceFragment { @@ -96,10 +98,9 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment { return true; }); - final Preference resetSettings = findPreference(getString(R.string.reset_settings)); + final Preference resetSettings = requirePreference(R.string.reset_settings); // Resets all settings by deleting shared preference and restarting the app // A dialogue will pop up to confirm if user intends to reset all settings - assert resetSettings != null; resetSettings.setOnPreferenceClickListener(preference -> { // Show Alert Dialogue final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); @@ -155,9 +156,9 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment { } private void exportDatabase(final StoredFileHelper file, final Uri exportDataUri) { - try { + try (ExecutorService executor = Executors.newSingleThreadExecutor()) { //checkpoint before export - NewPipeDatabase.checkpoint(); + executor.submit(NewPipeDatabase::checkpoint).get(); final SharedPreferences preferences = PreferenceManager .getDefaultSharedPreferences(requireContext()); diff --git a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java index 619579f3a..21cba3daa 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java @@ -48,8 +48,8 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat { } @NonNull - public final Preference requirePreference(@StringRes final int resId) { - final Preference preference = findPreference(getString(resId)); + public final T requirePreference(@StringRes final int resId) { + final T preference = findPreference(getString(resId)); Objects.requireNonNull(preference); return preference; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java index d78ade49d..82f2f5bb6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DebugSettingsFragment.java @@ -22,27 +22,20 @@ public class DebugSettingsFragment extends BasePreferenceFragment { addPreferencesFromResourceRegistry(); final Preference allowHeapDumpingPreference = - findPreference(getString(R.string.allow_heap_dumping_key)); + requirePreference(R.string.allow_heap_dumping_key); final Preference showMemoryLeaksPreference = - findPreference(getString(R.string.show_memory_leaks_key)); + requirePreference(R.string.show_memory_leaks_key); final Preference showImageIndicatorsPreference = - findPreference(getString(R.string.show_image_indicators_key)); + requirePreference(R.string.show_image_indicators_key); final Preference checkNewStreamsPreference = - findPreference(getString(R.string.check_new_streams_key)); + requirePreference(R.string.check_new_streams_key); final Preference crashTheAppPreference = - findPreference(getString(R.string.crash_the_app_key)); + requirePreference(R.string.crash_the_app_key); final Preference showErrorSnackbarPreference = - findPreference(getString(R.string.show_error_snackbar_key)); + requirePreference(R.string.show_error_snackbar_key); final Preference createErrorNotificationPreference = - findPreference(getString(R.string.create_error_notification_key)); + requirePreference(R.string.create_error_notification_key); - assert allowHeapDumpingPreference != null; - assert showMemoryLeaksPreference != null; - assert showImageIndicatorsPreference != null; - assert checkNewStreamsPreference != null; - assert crashTheAppPreference != null; - assert showErrorSnackbarPreference != null; - assert createErrorNotificationPreference != null; final Optional optBVLeakCanary = getBVDLeakCanary(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 32e33d55b..cb3de39a0 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -25,7 +25,7 @@ public class MainSettingsFragment extends BasePreferenceFragment { // Check if the app is updatable if (!ReleaseVersionUtil.INSTANCE.isReleaseApk()) { getPreferenceScreen().removePreference( - findPreference(getString(R.string.update_pref_screen_key))); + requirePreference(R.string.update_pref_screen_key)); defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply(); } @@ -33,7 +33,7 @@ public class MainSettingsFragment extends BasePreferenceFragment { // Hide debug preferences in RELEASE build variant if (!DEBUG) { getPreferenceScreen().removePreference( - findPreference(getString(R.string.debug_pref_screen_key))); + requirePreference(R.string.debug_pref_screen_key)); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/NotificationsSettingsFragment.kt b/app/src/main/java/org/schabi/newpipe/settings/NotificationsSettingsFragment.kt index 2d3344c09..d6b0a84da 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NotificationsSettingsFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/NotificationsSettingsFragment.kt @@ -29,8 +29,7 @@ class NotificationsSettingsFragment : BasePreferenceFragment(), OnSharedPreferen override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.notifications_settings) - streamsNotificationsPreference = - findPreference(getString(R.string.enable_streams_notifications)) + streamsNotificationsPreference = requirePreference(R.string.enable_streams_notifications) // main check is done in onResume, but also do it here to prevent flickering updateEnabledState(NotificationHelper.areNotificationsEnabledOnDevice(requireContext())) @@ -125,8 +124,8 @@ class NotificationsSettingsFragment : BasePreferenceFragment(), OnSharedPreferen private fun updateSubscriptions(subscriptions: List) { val notified = subscriptions.count { it.notificationMode != NotificationMode.DISABLED } - val preference = findPreference(getString(R.string.streams_notifications_channels_key)) - preference?.apply { summary = "$notified/${subscriptions.size}" } + val preference = requirePreference(R.string.streams_notifications_channels_key) + preference.summary = "$notified/${subscriptions.size}" } private fun onError(e: Throwable) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java b/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java index 1158b3d83..81fddbcfb 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java @@ -396,7 +396,8 @@ public class PeertubeInstanceListFragment extends Fragment { } } - private static class PeertubeInstanceCallback extends DiffUtil.ItemCallback { + private static final class PeertubeInstanceCallback + extends DiffUtil.ItemCallback { @Override public boolean areItemsTheSame(@NonNull final PeertubeInstance oldItem, @NonNull final PeertubeInstance newItem) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java index 37335421d..18e0816bb 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java @@ -174,7 +174,7 @@ public class SelectChannelFragment extends DialogFragment { void onCancel(); } - private class SelectChannelAdapter + private final class SelectChannelAdapter extends RecyclerView.Adapter { @NonNull @Override diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectFeedGroupFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectFeedGroupFragment.java index 662379369..c106f5998 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectFeedGroupFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectFeedGroupFragment.java @@ -175,7 +175,7 @@ public class SelectFeedGroupFragment extends DialogFragment { void onCancel(); } - private class SelectFeedGroupAdapter + private final class SelectFeedGroupAdapter extends RecyclerView.Adapter { @NonNull @Override diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java index 36abef9e5..880cbb282 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java @@ -118,12 +118,12 @@ public class SelectPlaylistFragment extends DialogFragment { if (selectedItem instanceof PlaylistMetadataEntry) { final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem); - onSelectedListener.onLocalPlaylistSelected(entry.getUid(), entry.name); + onSelectedListener.onLocalPlaylistSelected(entry.getUid(), entry.getOrderingName()); } else if (selectedItem instanceof PlaylistRemoteEntity) { final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem); onSelectedListener.onRemotePlaylistSelected( - entry.getServiceId(), entry.getUrl(), entry.getName()); + entry.getServiceId(), entry.getUrl(), entry.getOrderingName()); } } dismiss(); @@ -138,7 +138,7 @@ public class SelectPlaylistFragment extends DialogFragment { void onRemotePlaylistSelected(int serviceId, String url, String name); } - private class SelectPlaylistAdapter + private final class SelectPlaylistAdapter extends RecyclerView.Adapter { @NonNull @Override @@ -157,14 +157,15 @@ public class SelectPlaylistFragment extends DialogFragment { if (selectedItem instanceof PlaylistMetadataEntry) { final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem); - holder.titleView.setText(entry.name); + holder.titleView.setText(entry.getOrderingName()); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadPlaylistThumbnail(entry.thumbnailUrl).into(holder.thumbnailView); + PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl()) + .into(holder.thumbnailView); } else if (selectedItem instanceof PlaylistRemoteEntity) { final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem); - holder.titleView.setText(entry.getName()); + holder.titleView.setText(entry.getOrderingName()); holder.view.setOnClickListener(view -> clickedItem(position)); PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl()) .into(holder.thumbnailView); diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index b8d0aa556..8923972b0 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -34,9 +34,9 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { addPreferencesFromResourceRegistry(); - findPreference(getString(R.string.update_app_key)) + requirePreference(R.string.update_app_key) .setOnPreferenceChangeListener(updatePreferenceChange); - findPreference(getString(R.string.manual_update_key)) + requirePreference(R.string.manual_update_key) .setOnPreferenceClickListener(manualUpdateClick); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java index a1f563724..c5c4c480c 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java @@ -90,12 +90,12 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment { showHigherResolutions); // get resolution preferences - final ListPreference defaultResolution = findPreference( - getString(R.string.default_resolution_key)); - final ListPreference defaultPopupResolution = findPreference( - getString(R.string.default_popup_resolution_key)); - final ListPreference mobileDataResolution = findPreference( - getString(R.string.limit_mobile_data_usage_key)); + final ListPreference defaultResolution = requirePreference( + R.string.default_resolution_key); + final ListPreference defaultPopupResolution = requirePreference( + R.string.default_popup_resolution_key); + final ListPreference mobileDataResolution = requirePreference( + R.string.limit_mobile_data_usage_key); // update resolution preferences with new resolutions, entries & values for each defaultResolution.setEntries(resolutionListDescriptions.toArray(new String[0])); @@ -161,8 +161,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment { } } - final ListPreference durations = findPreference( - getString(R.string.seek_duration_key)); + final ListPreference durations = requirePreference(R.string.seek_duration_key); durations.setEntryValues(displayedDurationValues.toArray(new CharSequence[0])); durations.setEntries(displayedDescriptionValues.toArray(new CharSequence[0])); final int selectedDuration = Integer.parseInt(durations.getValue()); diff --git a/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt b/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt index c864e4a0d..f44d4f3e2 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt @@ -8,6 +8,7 @@ import java.io.File class BackupFileLocator(private val homeDir: File) { companion object { const val FILE_NAME_DB = "newpipe.db" + @Deprecated( "Serializing preferences with Java's ObjectOutputStream is vulnerable to injections", replaceWith = ReplaceWith("FILE_NAME_JSON_PREFS") diff --git a/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt b/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt index 36e0b9ce1..83cca2e0b 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt @@ -5,13 +5,13 @@ import com.grack.nanojson.JsonArray import com.grack.nanojson.JsonParser import com.grack.nanojson.JsonParserException import com.grack.nanojson.JsonWriter -import org.schabi.newpipe.streams.io.SharpOutputStream -import org.schabi.newpipe.streams.io.StoredFileHelper -import org.schabi.newpipe.util.ZipHelper import java.io.FileNotFoundException import java.io.IOException import java.io.ObjectOutputStream import java.util.zip.ZipOutputStream +import org.schabi.newpipe.streams.io.SharpOutputStream +import org.schabi.newpipe.streams.io.StoredFileHelper +import org.schabi.newpipe.util.ZipHelper class ImportExportManager(private val fileLocator: BackupFileLocator) { companion object { @@ -31,7 +31,7 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) { ZipHelper.addFileToZip( outZip, BackupFileLocator.FILE_NAME_DB, - fileLocator.db.path, + fileLocator.db.path ) // add the legacy vulnerable serialized preferences (will be removed in the future) @@ -78,7 +78,7 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) { val success = ZipHelper.extractFileFromZip( file, BackupFileLocator.FILE_NAME_DB, - fileLocator.db.path, + fileLocator.db.path ) if (success) { @@ -122,10 +122,15 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) { for ((key, value) in entries) { when (value) { is Boolean -> editor.putBoolean(key, value) + is Float -> editor.putFloat(key, value) + is Int -> editor.putInt(key, value) + is Long -> editor.putLong(key, value) + is String -> editor.putString(key, value) + is Set<*> -> { // There are currently only Sets with type String possible @Suppress("UNCHECKED_CAST") @@ -159,10 +164,15 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) { for ((key, value) in jsonObject) { when (value) { is Boolean -> editor.putBoolean(key, value) + is Float -> editor.putFloat(key, value) + is Int -> editor.putInt(key, value) + is Long -> editor.putLong(key, value) + is String -> editor.putString(key, value) + is JsonArray -> { editor.putStringSet(key, value.mapNotNull { e -> e as? String }.toSet()) } diff --git a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt index f61aa72ab..fd8abfa16 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt @@ -31,7 +31,7 @@ class NotificationModeConfigAdapter( fun update(newData: List) { val items = newData.map { - SubscriptionItem(it.uid, it.name, it.notificationMode, it.serviceId, it.url) + SubscriptionItem(it.uid, it.name!!, it.notificationMode, it.serviceId, it.url!!) } submitList(items) } diff --git a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt index 581768c30..9dbfa826a 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt @@ -45,7 +45,7 @@ class NotificationModeConfigFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?, + savedInstanceState: Bundle? ): View { _binding = FragmentChannelsNotificationsBinding.inflate(inflater, container, false) return binding.root @@ -88,6 +88,7 @@ class NotificationModeConfigFragment : Fragment() { toggleAll() true } + else -> super.onOptionsItemSelected(item) } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java index d6e2021a1..dd59ba86e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchAdapter.java @@ -69,7 +69,8 @@ class PreferenceSearchAdapter } } - private static class PreferenceCallback extends DiffUtil.ItemCallback { + private static final class PreferenceCallback + extends DiffUtil.ItemCallback { @Override public boolean areItemsTheSame(@NonNull final PreferenceSearchItem oldItem, @NonNull final PreferenceSearchItem newItem) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java deleted file mode 100644 index 33856326c..000000000 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.schabi.newpipe.settings.preferencesearch; - -import androidx.annotation.NonNull; -import androidx.annotation.XmlRes; - -import java.util.List; -import java.util.Objects; - -/** - * Represents a preference-item inside the search. - */ -public class PreferenceSearchItem { - /** - * Key of the setting/preference. E.g. used inside {@link android.content.SharedPreferences}. - */ - @NonNull - private final String key; - /** - * Title of the setting, e.g. 'Default resolution' or 'Show higher resolutions'. - */ - @NonNull - private final String title; - /** - * Summary of the setting, e.g. '480p' or 'Only some devices can play 2k/4k'. - */ - @NonNull - private final String summary; - /** - * Possible entries of the setting, e.g. 480p,720p,... - */ - @NonNull - private final String entries; - /** - * Breadcrumbs - a hint where the setting is located e.g. 'Video and Audio > Player' - */ - @NonNull - private final String breadcrumbs; - /** - * The xml-resource where this item was found/built from. - */ - @XmlRes - private final int searchIndexItemResId; - - public PreferenceSearchItem( - @NonNull final String key, - @NonNull final String title, - @NonNull final String summary, - @NonNull final String entries, - @NonNull final String breadcrumbs, - @XmlRes final int searchIndexItemResId - ) { - this.key = Objects.requireNonNull(key); - this.title = Objects.requireNonNull(title); - this.summary = Objects.requireNonNull(summary); - this.entries = Objects.requireNonNull(entries); - this.breadcrumbs = Objects.requireNonNull(breadcrumbs); - this.searchIndexItemResId = searchIndexItemResId; - } - - @NonNull - public String getKey() { - return key; - } - - @NonNull - public String getTitle() { - return title; - } - - @NonNull - public String getSummary() { - return summary; - } - - @NonNull - public String getEntries() { - return entries; - } - - @NonNull - public String getBreadcrumbs() { - return breadcrumbs; - } - - public int getSearchIndexItemResId() { - return searchIndexItemResId; - } - - boolean hasData() { - return !key.isEmpty() && !title.isEmpty(); - } - - public List getAllRelevantSearchFields() { - return List.of(getTitle(), getSummary(), getEntries(), getBreadcrumbs()); - } - - @NonNull - @Override - public String toString() { - return "PreferenceItem: " + title + " " + summary + " " + key; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt new file mode 100644 index 000000000..750e40eae --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchItem.kt @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.settings.preferencesearch + +import androidx.annotation.XmlRes + +/** + * Represents a preference-item inside the search. + * + * @param key Key of the setting/preference. E.g. used inside [android.content.SharedPreferences]. + * @param title Title of the setting, e.g. 'Default resolution' or 'Show higher resolutions'. + * @param summary Summary of the setting, e.g. '480p' or 'Only some devices can play 2k/4k'. + * @param entries Possible entries of the setting, e.g. 480p,720p,... + * @param breadcrumbs Breadcrumbs - a hint where the setting is located e.g. 'Video and Audio > Player' + * @param searchIndexItemResId The xml-resource where this item was found/built from. + */ + +data class PreferenceSearchItem( + val key: String, + val title: String, + val summary: String, + val entries: String, + val breadcrumbs: String, + @XmlRes val searchIndexItemResId: Int +) { + fun hasData(): Boolean { + return !key.isEmpty() && !title.isEmpty() + } + + fun getAllRelevantSearchFields(): MutableList { + return mutableListOf(title, summary, entries, breadcrumbs) + } + + override fun toString(): String { + return "PreferenceItem: $title $summary $key" + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java deleted file mode 100644 index 1f0636454..000000000 --- a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.schabi.newpipe.settings.preferencesearch; - -import androidx.annotation.NonNull; - -public interface PreferenceSearchResultListener { - void onSearchResultClicked(@NonNull PreferenceSearchItem result); -} diff --git a/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.kt b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.kt new file mode 100644 index 000000000..7b7b7884a --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/preferencesearch/PreferenceSearchResultListener.kt @@ -0,0 +1,10 @@ +/* + * SPDX-FileCopyrightText: 2022-2026 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.settings.preferencesearch + +interface PreferenceSearchResultListener { + fun onSearchResultClicked(result: PreferenceSearchItem) +} diff --git a/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java b/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java index 266cec24a..7cdc84e22 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java +++ b/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java @@ -1,8 +1,14 @@ package org.schabi.newpipe.streams; +import static org.schabi.newpipe.MainActivity.DEBUG; + +import android.util.Log; +import android.util.Pair; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.streams.WebMReader.Cluster; import org.schabi.newpipe.streams.WebMReader.Segment; import org.schabi.newpipe.streams.WebMReader.SimpleBlock; @@ -13,6 +19,10 @@ import java.io.Closeable; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; /** * @author kapodamy @@ -52,8 +62,10 @@ public class OggFromWebMWriter implements Closeable { private long segmentTableNextTimestamp = TIME_SCALE_NS; private final int[] crc32Table = new int[256]; + private final StreamInfo streamInfo; - public OggFromWebMWriter(@NonNull final SharpStream source, @NonNull final SharpStream target) { + public OggFromWebMWriter(@NonNull final SharpStream source, @NonNull final SharpStream target, + @Nullable final StreamInfo streamInfo) { if (!source.canRead() || !source.canRewind()) { throw new IllegalArgumentException("source stream must be readable and allows seeking"); } @@ -63,6 +75,7 @@ public class OggFromWebMWriter implements Closeable { this.source = source; this.output = target; + this.streamInfo = streamInfo; this.streamId = (int) System.currentTimeMillis(); @@ -271,12 +284,31 @@ public class OggFromWebMWriter implements Closeable { @Nullable private byte[] makeMetadata() { + if (DEBUG) { + Log.d("OggFromWebMWriter", "Downloading media with codec ID " + webmTrack.codecId); + } + if ("A_OPUS".equals(webmTrack.codecId)) { - return new byte[]{ - 0x4F, 0x70, 0x75, 0x73, 0x54, 0x61, 0x67, 0x73, // "OpusTags" binary string - 0x00, 0x00, 0x00, 0x00, // writing application string size (not present) - 0x00, 0x00, 0x00, 0x00 // additional tags count (zero means no tags) - }; + final var metadata = new ArrayList>(); + if (streamInfo != null) { + metadata.add(Pair.create("COMMENT", streamInfo.getUrl())); + metadata.add(Pair.create("GENRE", streamInfo.getCategory())); + metadata.add(Pair.create("ARTIST", streamInfo.getUploaderName())); + metadata.add(Pair.create("TITLE", streamInfo.getName())); + metadata.add(Pair.create("DATE", streamInfo + .getUploadDate() + .getLocalDateTime() + .format(DateTimeFormatter.ISO_DATE))); + } + + if (DEBUG) { + Log.d("OggFromWebMWriter", "Creating metadata header with this data:"); + metadata.forEach(p -> { + Log.d("OggFromWebMWriter", p.first + "=" + p.second); + }); + } + + return makeOpusTagsHeader(metadata); } else if ("A_VORBIS".equals(webmTrack.codecId)) { return new byte[]{ 0x03, // ¿¿¿??? @@ -290,6 +322,59 @@ public class OggFromWebMWriter implements Closeable { return null; } + /** + * This creates a single metadata tag for use in opus metadata headers. It contains the four + * byte string length field and includes the string as-is. This cannot be used independently, + * but must follow a proper "OpusTags" header. + * + * @param pair A key-value pair in the format "KEY=some value" + * @return The binary data of the encoded metadata tag + */ + private static byte[] makeOpusMetadataTag(final Pair pair) { + final var keyValue = pair.first.toUpperCase() + "=" + pair.second.trim(); + + final var bytes = keyValue.getBytes(); + final var buf = ByteBuffer.allocate(4 + bytes.length); + buf.order(ByteOrder.LITTLE_ENDIAN); + buf.putInt(bytes.length); + buf.put(bytes); + return buf.array(); + } + + /** + * This returns a complete "OpusTags" header, created from the provided metadata tags. + *

+ * You probably want to use makeOpusMetadata(), which uses this function to create + * a header with sensible metadata filled in. + * + * @param keyValueLines A list of pairs of the tags. This can also be though of as a mapping + * from one key to multiple values. + * @return The binary header + */ + private static byte[] makeOpusTagsHeader(final List> keyValueLines) { + final var tags = keyValueLines + .stream() + .filter(p -> !p.second.isBlank()) + .map(OggFromWebMWriter::makeOpusMetadataTag) + .collect(Collectors.toUnmodifiableList()); + + final var tagsBytes = tags.stream().collect(Collectors.summingInt(arr -> arr.length)); + + // Fixed header fields + dynamic fields + final var byteCount = 16 + tagsBytes; + + final var head = ByteBuffer.allocate(byteCount); + head.order(ByteOrder.LITTLE_ENDIAN); + head.put(new byte[]{ + 0x4F, 0x70, 0x75, 0x73, 0x54, 0x61, 0x67, 0x73, // "OpusTags" binary string + 0x00, 0x00, 0x00, 0x00, // vendor (aka. Encoder) string of length 0 + }); + head.putInt(tags.size()); // 4 bytes for tag count + tags.forEach(head::put); // dynamic amount of tag bytes + + return head.array(); + } + private void write(final ByteBuffer buffer) throws IOException { output.write(buffer.array(), 0, buffer.position()); buffer.position(0); diff --git a/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java b/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java index 1ec78ba21..8c8dc175b 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java +++ b/app/src/main/java/org/schabi/newpipe/streams/SrtFromTtmlWriter.java @@ -15,7 +15,11 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; /** - * @author kapodamy + * Converts TTML subtitles to SRT format. + * + * References: + * - TTML 2.0 (W3C): https://www.w3.org/TR/ttml2/ + * - SRT format: https://en.wikipedia.org/wiki/SubRip */ public class SrtFromTtmlWriter { private static final String NEW_LINE = "\r\n"; @@ -59,6 +63,226 @@ public class SrtFromTtmlWriter { out.write(text.getBytes(charset)); } + /** + * Decode XML or HTML entities into their actual (literal) characters. + * + * TTML is XML-based, so text nodes may contain escaped entities + * instead of direct characters. For example: + * + * "&" → "&" + * "<" → "<" + * ">" → ">" + * " " → "\t" (TAB) + * " " ( ) → "\n" (LINE FEED) + * + * XML files cannot contain characters like "<", ">", "&" directly, + * so they must be represented using their entity-encoded forms. + * + * Jsoup sometimes leaves nested or encoded entities unresolved + * (e.g. inside

text nodes in TTML files), so this function + * acts as a final “safety net” to ensure all entities are decoded + * before further normalization. + * + * Character representation layers for reference: + * - Literal characters: <, >, & + * → appear in runtime/output text (e.g. final SRT output) + * - Escaped entities: <, >, & + * → appear in XML/HTML/TTML source files + * - Numeric entities:  , , + * → appear mainly in XML/TTML files (also valid in HTML) + * for non-printable or special characters + * - Unicode escapes: \u00A0 (Java/Unicode internal form) + * → appear only in Java source code (NOT valid in XML) + * + * XML entities include both named (&, <) and numeric + * ( ,  ) forms. + * + * @param encodedEntities The raw text fragment possibly containing + * encoded XML entities. + * @return A decoded string where all entities are replaced by their + * actual (literal) characters. + */ + private String decodeXmlEntities(final String encodedEntities) { + return Parser.unescapeEntities(encodedEntities, true); + } + + /** + * Handle rare XML entity characters like LF: (`\n`), + * CR: (`\r`) and CRLF: (`\r\n`). + * + * These are technically valid in TTML (XML allows them) + * but unusual in practice, since most TTML line breaks + * are represented as
tags instead. + * As a defensive approach, we normalize them: + * + * - Windows (\r\n), macOS (\r), and Unix (\n) → unified SRT NEW_LINE (\r\n) + * + * Although well-formed TTML normally encodes line breaks + * as
tags, some auto-generated or malformed TTML files + * may embed literal newline entities ( , ). This + * normalization ensures these cases render properly in SRT + * players instead of breaking the subtitle structure. + * + * @param text To be normalized text with actual characters. + * @return Unified SRT NEW_LINE converted from all kinds of line breaks. + */ + private String normalizeLineBreakForSrt(final String text) { + String cleaned = text; + + // NOTE: + // The order of newline replacements must NOT change, + // or duplicated line breaks (e.g. \r\n → \n\n) will occur. + cleaned = cleaned.replace("\r\n", "\n") + .replace("\r", "\n"); + + cleaned = cleaned.replace("\n", NEW_LINE); + + return cleaned; + } + + private String normalizeForSrt(final String actualText) { + String cleaned = actualText; + + // Replace NBSP "non-breaking space" (\u00A0) with regular space ' '(\u0020). + // + // Why: + // - Some viewers render NBSP(\u00A0) incorrectly: + // * MPlayer 1.5: shown as “??” + // * Linux command `cat -A`: displayed as control-like markers + // (M-BM-) + // * Acode (Android editor): displayed as visible replacement + // glyphs (red dots) + // - Other viewers show it as a normal space (e.g., VS Code 1.104.0, + // vlc 3.0.20, mpv 0.37.0, Totem 43.0) + // → Mixed rendering creates inconsistency and may confuse users. + // + // Details: + // - YouTube TTML subtitles use both regular spaces (\u0020) + // and non-breaking spaces (\u00A0). + // - SRT subtitles only support regular spaces (\u0020), + // so \u00A0 may cause display issues. + // - \u00A0 and \u0020 are visually identical (i.e., they both + // appear as spaces ' '), but they differ in Unicode encoding, + // and NBSP (\u00A0) renders differently in different viewers. + // - SRT is a plain-text format and does not interpret + // "non-breaking" behavior. + // + // Conclusion: + // - Ensure uniform behavior, so replace it to a regular space + // without "non-breaking" behavior. + // + // References: + // - Unicode U+00A0 NBSP (Latin-1 Supplement): + // https://unicode.org/charts/PDF/U0080.pdf + cleaned = cleaned.replace('\u00A0', ' ') // Non-breaking space + .replace('\u202F', ' ') // Narrow no-break space + .replace('\u205F', ' ') // Medium mathematical space + .replace('\u3000', ' ') // Ideographic space + // \u2000 ~ \u200A are whitespace characters (e.g., + // en space, em space), replaced with regular space (\u0020). + .replaceAll("[\\u2000-\\u200A]", " "); // Whitespace characters + + // \u200B ~ \u200F are a range of non-spacing characters + // (e.g., zero-width space, zero-width non-joiner, etc.), + // which have no effect in *.SRT files and may cause + // display issues. + // These characters are invisible to the human eye, and + // they still exist in the encoding, so they need to be + // removed. + // After removal, the actual content becomes completely + // empty "", meaning there are no characters left, just + // an empty space, which helps avoid formatting issues + // in subtitles. + cleaned = cleaned.replaceAll("[\\u200B-\\u200F]", ""); // Non-spacing characters + + // Remove control characters (\u0000 ~ \u001F, except + // \n, \r, \t). + // - These are ASCII C0 control codes (e.g. \u0001 SOH, + // \u0008 BS, \u001F US), invisible and irrelevant in + // subtitles, may cause square boxes (?) in players. + // - Reference: + // Unicode Basic Latin (https://unicode.org/charts/PDF/U0000.pdf) + // ASCII Control (https://en.wikipedia.org/wiki/ASCII#Control_characters) + cleaned = cleaned.replaceAll("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F]", ""); + + // Reasoning: + // - subtitle files generally don't require tabs for alignment. + // - Tabs can be displayed with varying widths across different + // editors or platforms, which may cause display issues. + // - Replace it with a single space for consistent display + // across different editors or platforms. + cleaned = cleaned.replace('\t', ' '); + + cleaned = normalizeLineBreakForSrt(cleaned); + + return cleaned; + } + + private String sanitizeFragment(final String raw) { + if (null == raw) { + return ""; + } + + final String actualCharacters = decodeXmlEntities(raw); + + final String srtSafeText = normalizeForSrt(actualCharacters); + + return srtSafeText; + } + + // Recursively process all child nodes to ensure text inside + // nested tags (e.g., ) is also extracted. + private void traverseChildNodesForNestedTags(final Node parent, + final StringBuilder text) { + for (final Node child : parent.childNodes()) { + extractText(child, text); + } + } + + // CHECKSTYLE:OFF checkstyle:JavadocStyle + // checkstyle does not understand that span tags are inside a code block + /** + *

Recursive method to extract text from all nodes.

+ *

+ * This method processes {@link TextNode}s and {@code
} tags, + * recursively extracting text from nested tags + * (e.g. extracting text from nested {@code } tags). + * Newlines are added for {@code
} tags. + *

+ * @param node the current node to process + * @param text the {@link StringBuilder} to append the extracted text to + */ + // -------------------------------------------------------------------- + // [INTERNAL NOTE] TTML text layer explanation + // + // TTML parsing involves multiple text "layers": + // 1. Raw XML entities (e.g., <,  ) are decoded by Jsoup. + // 2. extractText() works on DOM TextNodes (already parsed strings). + // 3. sanitizeFragment() decodes remaining entities and fixes + // Unicode quirks. + // 4. normalizeForSrt() ensures literal text is safe for SRT output. + // + // In short: + // Jsoup handles XML-level syntax, + // our code handles text-level normalization for subtitles. + // -------------------------------------------------------------------- + private void extractText(final Node node, final StringBuilder text) { + if (node instanceof TextNode textNode) { + String rawTtmlFragment = textNode.getWholeText(); + String srtContent = sanitizeFragment(rawTtmlFragment); + text.append(srtContent); + } else if (node instanceof Element element) { + //
is a self-closing HTML tag used to insert a line break. + if (element.tagName().equalsIgnoreCase("br")) { + // Add a newline for
tags + text.append(NEW_LINE); + } + } + + traverseChildNodesForNestedTags(node, text); + } + // CHECKSTYLE:ON + public void build(final SharpStream ttml) throws IOException { /* * TTML parser with BASIC support @@ -79,21 +303,15 @@ public class SrtFromTtmlWriter { final Elements paragraphList = doc.select("body > div > p"); // check if has frames - if (paragraphList.size() < 1) { + if (paragraphList.isEmpty()) { return; } for (final Element paragraph : paragraphList) { text.setLength(0); - for (final Node children : paragraph.childNodes()) { - if (children instanceof TextNode) { - text.append(((TextNode) children).text()); - } else if (children instanceof Element - && ((Element) children).tagName().equalsIgnoreCase("br")) { - text.append(NEW_LINE); - } - } + // Recursively extract text from all child nodes + extractText(paragraph, text); if (ignoreEmptyFrames && text.length() < 1) { continue; diff --git a/app/src/main/java/org/schabi/newpipe/util/FilenameUtils.java b/app/src/main/java/org/schabi/newpipe/util/FilenameUtils.java deleted file mode 100644 index bc15f3f02..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/FilenameUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.preference.PreferenceManager; - -import org.schabi.newpipe.R; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class FilenameUtils { - private static final String CHARSET_MOST_SPECIAL = "[\\n\\r|?*<\":\\\\>/']+"; - private static final String CHARSET_ONLY_LETTERS_AND_DIGITS = "[^\\w\\d]+"; - - private FilenameUtils() { } - - /** - * #143 #44 #42 #22: make sure that the filename does not contain illegal chars. - * - * @param context the context to retrieve strings and preferences from - * @param title the title to create a filename from - * @return the filename - */ - public static String createFilename(final Context context, final String title) { - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - - final String charsetLd = context.getString(R.string.charset_letters_and_digits_value); - final String charsetMs = context.getString(R.string.charset_most_special_value); - final String defaultCharset = context.getString(R.string.default_file_charset_value); - - final String replacementChar = sharedPreferences.getString( - context.getString(R.string.settings_file_replacement_character_key), "_"); - String selectedCharset = sharedPreferences.getString( - context.getString(R.string.settings_file_charset_key), null); - - final String charset; - - if (selectedCharset == null || selectedCharset.isEmpty()) { - selectedCharset = defaultCharset; - } - - if (selectedCharset.equals(charsetLd)) { - charset = CHARSET_ONLY_LETTERS_AND_DIGITS; - } else if (selectedCharset.equals(charsetMs)) { - charset = CHARSET_MOST_SPECIAL; - } else { - charset = selectedCharset; // Is the user using a custom charset? - } - - final Pattern pattern = Pattern.compile(charset); - - return createFilename(title, pattern, Matcher.quoteReplacement(replacementChar)); - } - - /** - * Create a valid filename. - * - * @param title the title to create a filename from - * @param invalidCharacters patter matching invalid characters - * @param replacementChar the replacement - * @return the filename - */ - private static String createFilename(final String title, final Pattern invalidCharacters, - final String replacementChar) { - return title.replaceAll(invalidCharacters.pattern(), replacementChar); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/FilenameUtils.kt b/app/src/main/java/org/schabi/newpipe/util/FilenameUtils.kt new file mode 100644 index 000000000..1237a984b --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/FilenameUtils.kt @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2017-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.content.Context +import androidx.preference.PreferenceManager +import java.util.regex.Matcher +import org.schabi.newpipe.R +import org.schabi.newpipe.ktx.getStringSafe + +object FilenameUtils { + private const val CHARSET_MOST_SPECIAL = "[\\n\\r|?*<\":\\\\>/']+" + private const val CHARSET_ONLY_LETTERS_AND_DIGITS = "[^\\w\\d]+" + + /** + * #143 #44 #42 #22: make sure that the filename does not contain illegal chars. + * + * @param context the context to retrieve strings and preferences from + * @param title the title to create a filename from + * @return the filename + */ + @JvmStatic + fun createFilename(context: Context, title: String): String { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + + val charsetLd = context.getString(R.string.charset_letters_and_digits_value) + val charsetMs = context.getString(R.string.charset_most_special_value) + val defaultCharset = context.getString(R.string.default_file_charset_value) + + val replacementChar = sharedPreferences.getStringSafe( + context.getString(R.string.settings_file_replacement_character_key), + "_" + ) + val selectedCharset = sharedPreferences.getStringSafe( + context.getString(R.string.settings_file_charset_key), + "" + ).ifEmpty { defaultCharset } + + val charset = when (selectedCharset) { + charsetLd -> CHARSET_ONLY_LETTERS_AND_DIGITS + charsetMs -> CHARSET_MOST_SPECIAL + else -> selectedCharset // Is the user using a custom charset? + } + + return createFilename(title, charset, Matcher.quoteReplacement(replacementChar)) + } + + /** + * Create a valid filename. + * + * @param title the title to create a filename from + * @param invalidCharacters patter matching invalid characters + * @param replacementChar the replacement + * @return the filename + */ + private fun createFilename( + title: String, + invalidCharacters: String, + replacementChar: String + ): String { + return title.replace(invalidCharacters.toRegex(), replacementChar) + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java deleted file mode 100644 index 5aa332159..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.Context; - -import org.schabi.newpipe.R; - -/** - * Created by Christian Schabesberger on 28.09.17. - * KioskTranslator.java is part of NewPipe. - *

- * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - *

- *

- * NewPipe 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 General Public License for more details. - *

- *

- * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - *

- */ - -public final class KioskTranslator { - private KioskTranslator() { } - - public static String getTranslatedKioskName(final String kioskId, final Context c) { - switch (kioskId) { - case "Trending": - return c.getString(R.string.trending); - case "Top 50": - return c.getString(R.string.top_50); - case "New & hot": - return c.getString(R.string.new_and_hot); - case "Local": - return c.getString(R.string.local); - case "Recently added": - return c.getString(R.string.recently_added); - case "Most liked": - return c.getString(R.string.most_liked); - case "conferences": - return c.getString(R.string.conferences); - case "recent": - return c.getString(R.string.recent); - case "live": - return c.getString(R.string.duration_live); - case "Featured": - return c.getString(R.string.featured); - case "Radio": - return c.getString(R.string.radio); - case "trending_gaming": - return c.getString(R.string.trending_gaming); - case "trending_music": - return c.getString(R.string.trending_music); - case "trending_movies_and_shows": - return c.getString(R.string.trending_movies); - case "trending_podcasts_episodes": - return c.getString(R.string.trending_podcasts); - default: - return kioskId; - } - } - - public static int getKioskIcon(final String kioskId) { - switch (kioskId) { - case "Trending": - case "Top 50": - case "New & hot": - case "conferences": - return R.drawable.ic_whatshot; - case "Local": - return R.drawable.ic_home; - case "Recently added": - case "recent": - return R.drawable.ic_add_circle_outline; - case "Most liked": - return R.drawable.ic_thumb_up; - case "live": - return R.drawable.ic_live_tv; - case "Featured": - return R.drawable.ic_stars; - case "Radio": - return R.drawable.ic_radio; - case "trending_gaming": - return R.drawable.ic_videogame_asset; - case "trending_music": - return R.drawable.ic_music_note; - case "trending_movies_and_shows": - return R.drawable.ic_movie; - case "trending_podcasts_episodes": - return R.drawable.ic_podcasts; - default: - return 0; - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.kt b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.kt new file mode 100644 index 000000000..1f86f5db7 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.kt @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2017-2025 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util + +import android.content.Context +import org.schabi.newpipe.R + +object KioskTranslator { + @JvmStatic + fun getTranslatedKioskName(kioskId: String, context: Context): String { + return when (kioskId) { + "Trending" -> context.getString(R.string.trending) + "Top 50" -> context.getString(R.string.top_50) + "New & hot" -> context.getString(R.string.new_and_hot) + "Local" -> context.getString(R.string.local) + "Recently added" -> context.getString(R.string.recently_added) + "Most liked" -> context.getString(R.string.most_liked) + "conferences" -> context.getString(R.string.conferences) + "recent" -> context.getString(R.string.recent) + "live" -> context.getString(R.string.duration_live) + "Featured" -> context.getString(R.string.featured) + "Radio" -> context.getString(R.string.radio) + "trending_gaming" -> context.getString(R.string.trending_gaming) + "trending_music" -> context.getString(R.string.trending_music) + "trending_movies_and_shows" -> context.getString(R.string.trending_movies) + "trending_podcasts_episodes" -> context.getString(R.string.trending_podcasts) + else -> kioskId + } + } + + @JvmStatic + fun getKioskIcon(kioskId: String): Int { + return when (kioskId) { + "Trending", "Top 50", "New & hot", "conferences" -> R.drawable.ic_whatshot + "Local" -> R.drawable.ic_home + "Recently added", "recent" -> R.drawable.ic_add_circle_outline + "Most liked" -> R.drawable.ic_thumb_up + "live" -> R.drawable.ic_live_tv + "Featured" -> R.drawable.ic_stars + "Radio" -> R.drawable.ic_radio + "trending_gaming" -> R.drawable.ic_videogame_asset + "trending_music" -> R.drawable.ic_music_note + "trending_movies_and_shows" -> R.drawable.ic_movie + "trending_podcasts_episodes" -> R.drawable.ic_podcasts + else -> 0 + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java index ea41f3e81..409fcb30c 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java @@ -806,7 +806,7 @@ public final class ListHelper { final Locale preferredLanguage = Localization.getPreferredLocale(context); final boolean preferOriginalAudio = preferences.getBoolean(context.getString(R.string.prefer_original_audio_key), - false); + true); final boolean preferDescriptiveAudio = preferences.getBoolean(context.getString(R.string.prefer_descriptive_audio_key), false); diff --git a/app/src/main/java/org/schabi/newpipe/util/Localization.java b/app/src/main/java/org/schabi/newpipe/util/Localization.java index b8cc26b41..49e27d108 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -153,9 +153,9 @@ public final class Localization { case (int) ListExtractor.ITEM_COUNT_UNKNOWN: return ""; case (int) ListExtractor.ITEM_COUNT_INFINITE: - return context.getResources().getString(R.string.infinite_videos); + return context.getString(R.string.infinite_videos); case (int) ListExtractor.ITEM_COUNT_MORE_THAN_100: - return context.getResources().getString(R.string.more_than_100_videos); + return context.getString(R.string.more_than_100_videos); default: return getQuantity(context, R.plurals.videos, R.string.no_videos, streamCount, localizeNumber(streamCount)); @@ -168,9 +168,9 @@ public final class Localization { case (int) ListExtractor.ITEM_COUNT_UNKNOWN: return ""; case (int) ListExtractor.ITEM_COUNT_INFINITE: - return context.getResources().getString(R.string.infinite_videos_mini); + return context.getString(R.string.infinite_videos_mini); case (int) ListExtractor.ITEM_COUNT_MORE_THAN_100: - return context.getResources().getString(R.string.more_than_100_videos_mini); + return context.getString(R.string.more_than_100_videos_mini); default: return String.valueOf(streamCount); } diff --git a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java index 2785afab0..969d787d7 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java @@ -17,6 +17,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import org.schabi.newpipe.App; import org.schabi.newpipe.R; import org.schabi.newpipe.settings.NewPipeSettings; @@ -89,9 +90,12 @@ public final class PermissionHelper { && ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(activity, - new String[] {Manifest.permission.POST_NOTIFICATIONS}, requestCode); - return false; + if (!App.getApp().getNotificationsRequested()) { + ActivityCompat.requestPermissions(activity, + new String[]{Manifest.permission.POST_NOTIFICATIONS}, requestCode); + App.getApp().setNotificationsRequested(); + return false; + } } return true; } diff --git a/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java b/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java index 9727c8083..655ea7092 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PlayButtonHelper.java @@ -50,6 +50,10 @@ public final class PlayButtonHelper { }); // long click listener + playlistControlBinding.playlistCtrlPlayAllButton.setOnLongClickListener(view -> { + NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.MAIN); + return true; + }); playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> { NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.POPUP); return true; diff --git a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt index 3ea19fa4f..bc3849384 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt @@ -2,13 +2,13 @@ package org.schabi.newpipe.util import android.content.pm.PackageManager import androidx.core.content.pm.PackageInfoCompat +import java.time.Instant +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter import org.schabi.newpipe.App import org.schabi.newpipe.error.ErrorInfo import org.schabi.newpipe.error.ErrorUtil.Companion.createNotification import org.schabi.newpipe.error.UserAction -import java.time.Instant -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter object ReleaseVersionUtil { // Public key of the certificate that is used in NewPipe release versions @@ -26,7 +26,8 @@ object ReleaseVersionUtil { PackageInfoCompat.hasSignatures(app.packageManager, app.packageName, certificates, false) } catch (e: PackageManager.NameNotFoundException) { createNotification( - app, ErrorInfo(e, UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info") + app, + ErrorInfo(e, UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info") ) false } diff --git a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java index ab74e0305..24a0f457f 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java @@ -263,7 +263,7 @@ public final class ThemeHelper { private static String getSelectedThemeKey(final Context context) { final String themeKey = context.getString(R.string.theme_key); - final String defaultTheme = context.getResources().getString(R.string.default_theme_value); + final String defaultTheme = context.getString(R.string.default_theme_value); return PreferenceManager.getDefaultSharedPreferences(context) .getString(themeKey, defaultTheme); } diff --git a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java deleted file mode 100644 index da97179b6..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java +++ /dev/null @@ -1,195 +0,0 @@ -package org.schabi.newpipe.util.image; - -import static org.schabi.newpipe.extractor.Image.HEIGHT_UNKNOWN; -import static org.schabi.newpipe.extractor.Image.WIDTH_UNKNOWN; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.schabi.newpipe.extractor.Image; - -import java.util.Comparator; -import java.util.List; - -public final class ImageStrategy { - - // when preferredImageQuality is LOW or MEDIUM, images are sorted by how close their preferred - // image quality is to these values (H stands for "Height") - private static final int BEST_LOW_H = 75; - private static final int BEST_MEDIUM_H = 250; - - private static PreferredImageQuality preferredImageQuality = PreferredImageQuality.MEDIUM; - - private ImageStrategy() { - } - - public static void setPreferredImageQuality(final PreferredImageQuality preferredImageQuality) { - ImageStrategy.preferredImageQuality = preferredImageQuality; - } - - public static boolean shouldLoadImages() { - return preferredImageQuality != PreferredImageQuality.NONE; - } - - - static double estimatePixelCount(final Image image, final double widthOverHeight) { - if (image.getHeight() == HEIGHT_UNKNOWN) { - if (image.getWidth() == WIDTH_UNKNOWN) { - // images whose size is completely unknown will be in their own subgroups, so - // any one of them will do, hence returning the same value for all of them - return 0; - } else { - return image.getWidth() * image.getWidth() / widthOverHeight; - } - } else if (image.getWidth() == WIDTH_UNKNOWN) { - return image.getHeight() * image.getHeight() * widthOverHeight; - } else { - return image.getHeight() * image.getWidth(); - } - } - - /** - * {@link #choosePreferredImage(List)} contains the description for this function's logic. - * - * @param images the images from which to choose - * @param nonNoneQuality the preferred quality (must NOT be {@link PreferredImageQuality#NONE}) - * @return the chosen preferred image, or {@link null} if the list is empty - * @see #choosePreferredImage(List) - */ - @Nullable - static String choosePreferredImage(@NonNull final List images, - final PreferredImageQuality nonNoneQuality) { - // this will be used to estimate the pixel count for images where only one of height or - // width are known - final double widthOverHeight = images.stream() - .filter(image -> image.getHeight() != HEIGHT_UNKNOWN - && image.getWidth() != WIDTH_UNKNOWN) - .mapToDouble(image -> ((double) image.getWidth()) / image.getHeight()) - .findFirst() - .orElse(1.0); - - final Image.ResolutionLevel preferredLevel = nonNoneQuality.toResolutionLevel(); - final Comparator initialComparator = Comparator - // the first step splits the images into groups of resolution levels - .comparingInt(i -> { - if (i.getEstimatedResolutionLevel() == Image.ResolutionLevel.UNKNOWN) { - return 3; // avoid unknowns as much as possible - } else if (i.getEstimatedResolutionLevel() == preferredLevel) { - return 0; // prefer a matching resolution level - } else if (i.getEstimatedResolutionLevel() == Image.ResolutionLevel.MEDIUM) { - return 1; // the preferredLevel is only 1 "step" away (either HIGH or LOW) - } else { - return 2; // the preferredLevel is the furthest away possible (2 "steps") - } - }) - // then each level's group is further split into two subgroups, one with known image - // size (which is also the preferred subgroup) and the other without - .thenComparing(image -> - image.getHeight() == HEIGHT_UNKNOWN && image.getWidth() == WIDTH_UNKNOWN); - - // The third step chooses, within each subgroup with known image size, the best image based - // on how close its size is to BEST_LOW_H or BEST_MEDIUM_H (with proper units). Subgroups - // without known image size will be left untouched since estimatePixelCount always returns - // the same number for those. - final Comparator finalComparator = switch (nonNoneQuality) { - case NONE -> initialComparator; // unreachable - case LOW -> initialComparator.thenComparingDouble(image -> { - final double pixelCount = estimatePixelCount(image, widthOverHeight); - return Math.abs(pixelCount - BEST_LOW_H * BEST_LOW_H * widthOverHeight); - }); - case MEDIUM -> initialComparator.thenComparingDouble(image -> { - final double pixelCount = estimatePixelCount(image, widthOverHeight); - return Math.abs(pixelCount - BEST_MEDIUM_H * BEST_MEDIUM_H * widthOverHeight); - }); - case HIGH -> initialComparator.thenComparingDouble( - // this is reversed with a - so that the highest resolution is chosen - i -> -estimatePixelCount(i, widthOverHeight)); - }; - - return images.stream() - // using "min" basically means "take the first group, then take the first subgroup, - // then choose the best image, while ignoring all other groups and subgroups" - .min(finalComparator) - .map(Image::getUrl) - .orElse(null); - } - - /** - * Chooses an image amongst the provided list based on the user preference previously set with - * {@link #setPreferredImageQuality(PreferredImageQuality)}. {@code null} will be returned in - * case the list is empty or the user preference is to not show images. - *
- * These properties will be preferred, from most to least important: - *
    - *
  1. The image's {@link Image#getEstimatedResolutionLevel()} is not unknown and is close - * to {@link #preferredImageQuality}
  2. - *
  3. At least one of the image's width or height are known
  4. - *
  5. The highest resolution image is finally chosen if the user's preference is {@link - * PreferredImageQuality#HIGH}, otherwise the chosen image is the one that has the height - * closest to {@link #BEST_LOW_H} or {@link #BEST_MEDIUM_H}
  6. - *
- *
- * Use {@link #imageListToDbUrl(List)} if the URL is going to be saved to the database, to avoid - * saving nothing in case at the moment of saving the user preference is to not show images. - * - * @param images the images from which to choose - * @return the chosen preferred image, or {@link null} if the list is empty or the user disabled - * images - * @see #imageListToDbUrl(List) - */ - @Nullable - public static String choosePreferredImage(@NonNull final List images) { - if (preferredImageQuality == PreferredImageQuality.NONE) { - return null; // do not load images - } - - return choosePreferredImage(images, preferredImageQuality); - } - - /** - * Like {@link #choosePreferredImage(List)}, except that if {@link #preferredImageQuality} is - * {@link PreferredImageQuality#NONE} an image will be chosen anyway (with preferred quality - * {@link PreferredImageQuality#MEDIUM}. - *
- * To go back to a list of images (obviously with just the one chosen image) from a URL saved in - * the database use {@link #dbUrlToImageList(String)}. - * - * @param images the images from which to choose - * @return the chosen preferred image, or {@link null} if the list is empty - * @see #choosePreferredImage(List) - * @see #dbUrlToImageList(String) - */ - @Nullable - public static String imageListToDbUrl(@NonNull final List images) { - final PreferredImageQuality quality; - if (preferredImageQuality == PreferredImageQuality.NONE) { - quality = PreferredImageQuality.MEDIUM; - } else { - quality = preferredImageQuality; - } - - return choosePreferredImage(images, quality); - } - - /** - * Wraps the URL (coming from the database) in a {@code List} so that it is usable - * seamlessly in all of the places where the extractor would return a list of images, including - * allowing to build info objects based on database objects. - *
- * To obtain a url to save to the database from a list of images use {@link - * #imageListToDbUrl(List)}. - * - * @param url the URL to wrap coming from the database, or {@code null} to get an empty list - * @return a list containing just one {@link Image} wrapping the provided URL, with unknown - * image size fields, or an empty list if the URL is {@code null} - * @see #imageListToDbUrl(List) - */ - @NonNull - public static List dbUrlToImageList(@Nullable final String url) { - if (url == null) { - return List.of(); - } else { - return List.of(new Image(url, -1, -1, Image.ResolutionLevel.UNKNOWN)); - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.kt b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.kt new file mode 100644 index 000000000..c7e94c7f8 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.kt @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util.image + +import kotlin.math.abs +import org.schabi.newpipe.extractor.Image +import org.schabi.newpipe.extractor.Image.ResolutionLevel + +object ImageStrategy { + // when preferredImageQuality is LOW or MEDIUM, images are sorted by how close their preferred + // image quality is to these values (H stands for "Height") + private const val BEST_LOW_H = 75 + private const val BEST_MEDIUM_H = 250 + + private var preferredImageQuality = PreferredImageQuality.MEDIUM + + @JvmStatic + fun setPreferredImageQuality(preferredImageQuality: PreferredImageQuality) { + ImageStrategy.preferredImageQuality = preferredImageQuality + } + + @JvmStatic + fun shouldLoadImages(): Boolean { + return preferredImageQuality != PreferredImageQuality.NONE + } + + @JvmStatic + fun estimatePixelCount(image: Image, widthOverHeight: Double): Double { + if (image.height == Image.HEIGHT_UNKNOWN) { + if (image.width == Image.WIDTH_UNKNOWN) { + // images whose size is completely unknown will be in their own subgroups, so + // any one of them will do, hence returning the same value for all of them + return 0.0 + } else { + return image.width * image.width / widthOverHeight + } + } else if (image.width == Image.WIDTH_UNKNOWN) { + return image.height * image.height * widthOverHeight + } else { + return (image.height * image.width).toDouble() + } + } + + /** + * [choosePreferredImage] contains the description for this function's logic. + * + * @param images the images from which to choose + * @param nonNoneQuality the preferred quality (must NOT be [PreferredImageQuality.NONE]) + * @return the chosen preferred image, or `null` if the list is empty + * @see [choosePreferredImage] + */ + @JvmStatic + fun choosePreferredImage(images: List, nonNoneQuality: PreferredImageQuality): String? { + // this will be used to estimate the pixel count for images where only one of height or + // width are known + val widthOverHeight = images + .filter { image -> + image.height != Image.HEIGHT_UNKNOWN && image.width != Image.WIDTH_UNKNOWN + } + .map { image -> (image.width.toDouble()) / image.height } + .elementAtOrNull(0) ?: 1.0 + + val preferredLevel = nonNoneQuality.toResolutionLevel() + // TODO: rewrite using kotlin collections API `groupBy` will be handy + val initialComparator = + Comparator // the first step splits the images into groups of resolution levels + .comparingInt { i: Image -> + return@comparingInt when (i.estimatedResolutionLevel) { + // avoid unknowns as much as possible + ResolutionLevel.UNKNOWN -> 3 + + // prefer a matching resolution level + preferredLevel -> 0 + + // the preferredLevel is only 1 "step" away (either HIGH or LOW) + ResolutionLevel.MEDIUM -> 1 + + // the preferredLevel is the furthest away possible (2 "steps") + else -> 2 + } + } + // then each level's group is further split into two subgroups, one with known image + // size (which is also the preferred subgroup) and the other without + .thenComparing { image -> image.height == Image.HEIGHT_UNKNOWN && image.width == Image.WIDTH_UNKNOWN } + + // The third step chooses, within each subgroup with known image size, the best image based + // on how close its size is to BEST_LOW_H or BEST_MEDIUM_H (with proper units). Subgroups + // without known image size will be left untouched since estimatePixelCount always returns + // the same number for those. + val finalComparator = when (nonNoneQuality) { + PreferredImageQuality.NONE -> initialComparator + + PreferredImageQuality.LOW -> initialComparator.thenComparingDouble { image -> + val pixelCount = estimatePixelCount(image, widthOverHeight) + abs(pixelCount - BEST_LOW_H * BEST_LOW_H * widthOverHeight) + } + + PreferredImageQuality.MEDIUM -> initialComparator.thenComparingDouble { image -> + val pixelCount = estimatePixelCount(image, widthOverHeight) + abs(pixelCount - BEST_MEDIUM_H * BEST_MEDIUM_H * widthOverHeight) + } + + PreferredImageQuality.HIGH -> initialComparator.thenComparingDouble { image -> + // this is reversed with a - so that the highest resolution is chosen + -estimatePixelCount(image, widthOverHeight) + } + } + + return images.stream() // using "min" basically means "take the first group, then take the first subgroup, + // then choose the best image, while ignoring all other groups and subgroups" + .min(finalComparator) + .map(Image::getUrl) + .orElse(null) + } + + /** + * Chooses an image amongst the provided list based on the user preference previously set with + * [setPreferredImageQuality]. `null` will be returned in + * case the list is empty or the user preference is to not show images. + *
+ * These properties will be preferred, from most to least important: + * + * 1. The image's [Image.estimatedResolutionLevel] is not unknown and is close to [preferredImageQuality] + * 2. At least one of the image's width or height are known + * 3. The highest resolution image is finally chosen if the user's preference is + * [PreferredImageQuality.HIGH], otherwise the chosen image is the one that has the height + * closest to [BEST_LOW_H] or [BEST_MEDIUM_H] + * + *
+ * Use [imageListToDbUrl] if the URL is going to be saved to the database, to avoid + * saving nothing in case at the moment of saving the user preference is to not show images. + * + * @param images the images from which to choose + * @return the chosen preferred image, or `null` if the list is empty or the user disabled + * images + * @see [imageListToDbUrl] + */ + @JvmStatic + fun choosePreferredImage(images: List): String? { + if (preferredImageQuality == PreferredImageQuality.NONE) { + return null // do not load images + } + + return choosePreferredImage(images, preferredImageQuality) + } + + /** + * Like [choosePreferredImage], except that if [preferredImageQuality] is + * [PreferredImageQuality.NONE] an image will be chosen anyway (with preferred quality + * [PreferredImageQuality.MEDIUM]. + *

+ * To go back to a list of images (obviously with just the one chosen image) from a URL saved in + * the database use [dbUrlToImageList]. + * + * @param images the images from which to choose + * @return the chosen preferred image, or `null` if the list is empty + * @see [choosePreferredImage] + * @see [dbUrlToImageList] + */ + @JvmStatic + fun imageListToDbUrl(images: List): String? { + val quality = when (preferredImageQuality) { + PreferredImageQuality.NONE -> PreferredImageQuality.MEDIUM + else -> preferredImageQuality + } + + return choosePreferredImage(images, quality) + } + + /** + * Wraps the URL (coming from the database) in a `List` so that it is usable + * seamlessly in all of the places where the extractor would return a list of images, including + * allowing to build info objects based on database objects. + *

+ * To obtain a url to save to the database from a list of images use [imageListToDbUrl]. + * + * @param url the URL to wrap coming from the database, or `null` to get an empty list + * @return a list containing just one [Image] wrapping the provided URL, with unknown + * image size fields, or an empty list if the URL is `null` + * @see [imageListToDbUrl] + */ + @JvmStatic + fun dbUrlToImageList(url: String?): List { + return when (url) { + null -> listOf() + else -> listOf(Image(url, -1, -1, ResolutionLevel.UNKNOWN)) + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java deleted file mode 100644 index 7106359b3..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.schabi.newpipe.util.image; - -import android.content.Context; - -import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.Image; - -public enum PreferredImageQuality { - NONE, - LOW, - MEDIUM, - HIGH; - - public static PreferredImageQuality fromPreferenceKey(final Context context, final String key) { - if (context.getString(R.string.image_quality_none_key).equals(key)) { - return NONE; - } else if (context.getString(R.string.image_quality_low_key).equals(key)) { - return LOW; - } else if (context.getString(R.string.image_quality_high_key).equals(key)) { - return HIGH; - } else { - return MEDIUM; // default to medium - } - } - - public Image.ResolutionLevel toResolutionLevel() { - switch (this) { - case LOW: - return Image.ResolutionLevel.LOW; - case MEDIUM: - return Image.ResolutionLevel.MEDIUM; - case HIGH: - return Image.ResolutionLevel.HIGH; - default: - case NONE: - return Image.ResolutionLevel.UNKNOWN; - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.kt b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.kt new file mode 100644 index 000000000..b90ba87aa --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.kt @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util.image + +import android.content.Context +import org.schabi.newpipe.R +import org.schabi.newpipe.extractor.Image.ResolutionLevel + +enum class PreferredImageQuality { + NONE, + LOW, + MEDIUM, + HIGH; + + fun toResolutionLevel(): ResolutionLevel { + return when (this) { + LOW -> ResolutionLevel.LOW + MEDIUM -> ResolutionLevel.MEDIUM + HIGH -> ResolutionLevel.HIGH + NONE -> ResolutionLevel.UNKNOWN + } + } + + companion object { + @JvmStatic + fun fromPreferenceKey(context: Context, key: String?): PreferredImageQuality { + return when (key) { + context.getString(R.string.image_quality_none_key) -> NONE + context.getString(R.string.image_quality_low_key) -> LOW + context.getString(R.string.image_quality_high_key) -> HIGH + else -> MEDIUM // default to medium + } + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenException.kt b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenException.kt index 879f8f3e6..683fd48b2 100644 --- a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenException.kt +++ b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenException.kt @@ -6,8 +6,9 @@ class PoTokenException(message: String) : Exception(message) class BadWebViewException(message: String) : Exception(message) fun buildExceptionForJsError(error: String): Exception { - return if (error.contains("SyntaxError")) + return if (error.contains("SyntaxError")) { BadWebViewException(error) - else + } else { PoTokenException(error) + } } diff --git a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt index 5383a613a..12fadb68d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt +++ b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenProviderImpl.kt @@ -37,7 +37,9 @@ object PoTokenProviderImpl : PoTokenProvider { webViewBadImpl = true return null } + null -> throw e + else -> throw cause // includes PoTokenException } } @@ -58,7 +60,6 @@ object PoTokenProviderImpl : PoTokenProvider { webPoTokenGenerator!!.isExpired() if (shouldRecreate) { - val innertubeClientRequestInfo = InnertubeClientRequestInfo.ofWebClient() innertubeClientRequestInfo.clientInfo.clientVersion = YoutubeParsingHelper.getClientVersion() diff --git a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenWebView.kt b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenWebView.kt index 9b4b500f0..deeef613a 100644 --- a/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenWebView.kt +++ b/app/src/main/java/org/schabi/newpipe/util/potoken/PoTokenWebView.kt @@ -16,14 +16,14 @@ import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.SingleEmitter import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.schedulers.Schedulers +import java.time.Instant import org.schabi.newpipe.BuildConfig import org.schabi.newpipe.DownloaderImpl -import java.time.Instant class PoTokenWebView private constructor( context: Context, // to be used exactly once only during initialization! - private val generatorEmitter: SingleEmitter, + private val generatorEmitter: SingleEmitter ) : PoTokenGenerator { private val webView = WebView(context) private val disposables = CompositeDisposable() // used only during initialization @@ -93,7 +93,7 @@ class PoTokenWebView private constructor( ), "text/html", "utf-8", - null, + null ) }, this::onInitializationErrorCloseAndCancel @@ -113,7 +113,7 @@ class PoTokenWebView private constructor( makeBotguardServiceRequest( "https://www.youtube.com/api/jnn/v1/Create", - "[ \"$REQUEST_KEY\" ]", + "[ \"$REQUEST_KEY\" ]" ) { responseBody -> val parsedChallengeData = parseChallengeData(responseBody) webView.evaluateJavascript( @@ -156,7 +156,7 @@ class PoTokenWebView private constructor( } makeBotguardServiceRequest( "https://www.youtube.com/api/jnn/v1/GenerateIT", - "[ \"$REQUEST_KEY\", \"$botguardResponse\" ]", + "[ \"$REQUEST_KEY\", \"$botguardResponse\" ]" ) { responseBody -> if (BuildConfig.DEBUG) { Log.d(TAG, "GenerateIT response: $responseBody") @@ -179,16 +179,15 @@ class PoTokenWebView private constructor( //endregion //region Obtaining poTokens - override fun generatePoToken(identifier: String): Single = - Single.create { emitter -> - if (BuildConfig.DEBUG) { - Log.d(TAG, "generatePoToken() called with identifier $identifier") - } - runOnMainThread(emitter) { - addPoTokenEmitter(identifier, emitter) - val u8Identifier = stringToU8(identifier) - webView.evaluateJavascript( - """try { + override fun generatePoToken(identifier: String): Single = Single.create { emitter -> + if (BuildConfig.DEBUG) { + Log.d(TAG, "generatePoToken() called with identifier $identifier") + } + runOnMainThread(emitter) { + addPoTokenEmitter(identifier, emitter) + val u8Identifier = stringToU8(identifier) + webView.evaluateJavascript( + """try { identifier = "$identifier" u8Identifier = $u8Identifier poTokenU8 = obtainPoToken(webPoSignalOutput, integrityToken, u8Identifier) @@ -200,10 +199,10 @@ class PoTokenWebView private constructor( $JS_INTERFACE.onObtainPoTokenResult(identifier, poTokenU8String) } catch (error) { $JS_INTERFACE.onObtainPoTokenError(identifier, error + "\n" + error.stack) - }""", - ) {} - } + }""" + ) {} } + } /** * Called by the JavaScript snippet from [generatePoToken] when an error occurs in calling the @@ -245,6 +244,7 @@ class PoTokenWebView private constructor( //endregion //region Handling multiple emitters + /** * Adds the ([identifier], [emitter]) pair to the [poTokenEmitters] list. This makes it so that * multiple poToken requests can be generated invparallel, and the results will be notified to @@ -283,6 +283,7 @@ class PoTokenWebView private constructor( //endregion //region Utils + /** * Makes a POST request to [url] with the given [data] by setting the correct headers. Calls * [onInitializationErrorCloseAndCancel] in case of any network errors and also if the response @@ -294,7 +295,7 @@ class PoTokenWebView private constructor( private fun makeBotguardServiceRequest( url: String, data: String, - handleResponseBody: (String) -> Unit, + handleResponseBody: (String) -> Unit ) { disposables.add( Single.fromCallable { @@ -306,7 +307,7 @@ class PoTokenWebView private constructor( "Accept" to listOf("application/json"), "Content-Type" to listOf("application/json+protobuf"), "x-goog-api-key" to listOf(GOOGLE_API_KEY), - "x-user-agent" to listOf("grpc-web-javascript/0.1"), + "x-user-agent" to listOf("grpc-web-javascript/0.1") ), data.toByteArray() ) @@ -363,6 +364,7 @@ class PoTokenWebView private constructor( companion object : PoTokenGenerator.Factory { private val TAG = PoTokenWebView::class.simpleName + // Public API key used by BotGuard, which has been got by looking at BotGuard requests private const val GOOGLE_API_KEY = "AIzaSyDyT5W0Jh49F30Pqqtyfdf7pDLFKLJoAnw" // NOSONAR private const val REQUEST_KEY = "O43z0dpjhgX20SCx4KAo" @@ -370,14 +372,13 @@ class PoTokenWebView private constructor( "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.3" private const val JS_INTERFACE = "PoTokenWebView" - override fun newPoTokenGenerator(context: Context): Single = - Single.create { emitter -> - runOnMainThread(emitter) { - val potWv = PoTokenWebView(context, emitter) - potWv.loadHtmlAndObtainBotguard(context) - emitter.setDisposable(potWv.disposables) - } + override fun newPoTokenGenerator(context: Context): Single = Single.create { emitter -> + runOnMainThread(emitter) { + val potWv = PoTokenWebView(context, emitter) + potWv.loadHtmlAndObtainBotguard(context) + emitter.setDisposable(potWv.disposables) } + } /** * Runs [runnable] on the main thread using `Handler(Looper.getMainLooper()).post()`, and @@ -385,7 +386,7 @@ class PoTokenWebView private constructor( */ private fun runOnMainThread( emitterIfPostFails: SingleEmitter, - runnable: Runnable, + runnable: Runnable ) { if (!Handler(Looper.getMainLooper()).post(runnable)) { emitterIfPostFails.onError(PoTokenException("Could not run on main thread")) diff --git a/app/src/main/java/org/schabi/newpipe/util/text/TimestampExtractor.java b/app/src/main/java/org/schabi/newpipe/util/text/TimestampExtractor.java index be603f41a..b1357b943 100644 --- a/app/src/main/java/org/schabi/newpipe/util/text/TimestampExtractor.java +++ b/app/src/main/java/org/schabi/newpipe/util/text/TimestampExtractor.java @@ -54,30 +54,6 @@ public final class TimestampExtractor { return new TimestampMatchDTO(timestampStart, timestampEnd, seconds); } - public static class TimestampMatchDTO { - private final int timestampStart; - private final int timestampEnd; - private final int seconds; - - public TimestampMatchDTO( - final int timestampStart, - final int timestampEnd, - final int seconds) { - this.timestampStart = timestampStart; - this.timestampEnd = timestampEnd; - this.seconds = seconds; - } - - public int timestampStart() { - return timestampStart; - } - - public int timestampEnd() { - return timestampEnd; - } - - public int seconds() { - return seconds; - } + public record TimestampMatchDTO(int timestampStart, int timestampEnd, int seconds) { } } diff --git a/app/src/main/java/org/schabi/newpipe/util/text/TimestampLongPressClickableSpan.java b/app/src/main/java/org/schabi/newpipe/util/text/TimestampLongPressClickableSpan.java deleted file mode 100644 index 35a9fd996..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/text/TimestampLongPressClickableSpan.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.schabi.newpipe.util.text; - -import static org.schabi.newpipe.util.text.InternalUrlsHandler.playOnPopup; - -import android.content.Context; -import android.view.View; - -import androidx.annotation.NonNull; - -import org.schabi.newpipe.extractor.ServiceList; -import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.util.external_communication.ShareUtils; - -import io.reactivex.rxjava3.disposables.CompositeDisposable; - -final class TimestampLongPressClickableSpan extends LongPressClickableSpan { - - @NonNull - private final Context context; - @NonNull - private final String descriptionText; - @NonNull - private final CompositeDisposable disposables; - @NonNull - private final StreamingService relatedInfoService; - @NonNull - private final String relatedStreamUrl; - @NonNull - private final TimestampExtractor.TimestampMatchDTO timestampMatchDTO; - - TimestampLongPressClickableSpan( - @NonNull final Context context, - @NonNull final String descriptionText, - @NonNull final CompositeDisposable disposables, - @NonNull final StreamingService relatedInfoService, - @NonNull final String relatedStreamUrl, - @NonNull final TimestampExtractor.TimestampMatchDTO timestampMatchDTO) { - this.context = context; - this.descriptionText = descriptionText; - this.disposables = disposables; - this.relatedInfoService = relatedInfoService; - this.relatedStreamUrl = relatedStreamUrl; - this.timestampMatchDTO = timestampMatchDTO; - } - - @Override - public void onClick(@NonNull final View view) { - playOnPopup(context, relatedStreamUrl, relatedInfoService, - timestampMatchDTO.seconds()); - } - - @Override - public void onLongClick(@NonNull final View view) { - ShareUtils.copyToClipboard(context, getTimestampTextToCopy( - relatedInfoService, relatedStreamUrl, descriptionText, timestampMatchDTO)); - } - - @NonNull - private static String getTimestampTextToCopy( - @NonNull final StreamingService relatedInfoService, - @NonNull final String relatedStreamUrl, - @NonNull final String descriptionText, - @NonNull final TimestampExtractor.TimestampMatchDTO timestampMatchDTO) { - // TODO: use extractor methods to get timestamps when this feature will be implemented in it - if (relatedInfoService == ServiceList.YouTube) { - return relatedStreamUrl + "&t=" + timestampMatchDTO.seconds(); - } else if (relatedInfoService == ServiceList.SoundCloud - || relatedInfoService == ServiceList.MediaCCC) { - return relatedStreamUrl + "#t=" + timestampMatchDTO.seconds(); - } else if (relatedInfoService == ServiceList.PeerTube) { - return relatedStreamUrl + "?start=" + timestampMatchDTO.seconds(); - } - - // Return timestamp text for other services - return descriptionText.subSequence(timestampMatchDTO.timestampStart(), - timestampMatchDTO.timestampEnd()).toString(); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/text/TimestampLongPressClickableSpan.kt b/app/src/main/java/org/schabi/newpipe/util/text/TimestampLongPressClickableSpan.kt new file mode 100644 index 000000000..c99e2f639 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/text/TimestampLongPressClickableSpan.kt @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.util.text + +import android.content.Context +import android.view.View +import io.reactivex.rxjava3.disposables.CompositeDisposable +import org.schabi.newpipe.extractor.ServiceList +import org.schabi.newpipe.extractor.StreamingService +import org.schabi.newpipe.util.external_communication.ShareUtils +import org.schabi.newpipe.util.text.TimestampExtractor.TimestampMatchDTO + +class TimestampLongPressClickableSpan( + private val context: Context, + private val descriptionText: String, + private val disposables: CompositeDisposable, + private val relatedInfoService: StreamingService, + private val relatedStreamUrl: String, + private val timestampMatchDTO: TimestampMatchDTO +) : LongPressClickableSpan() { + override fun onClick(view: View) { + InternalUrlsHandler.playOnPopup( + context, + relatedStreamUrl, + relatedInfoService, + timestampMatchDTO.seconds() + ) + } + + override fun onLongClick(view: View) { + ShareUtils.copyToClipboard( + context, + getTimestampTextToCopy( + relatedInfoService, + relatedStreamUrl, + descriptionText, + timestampMatchDTO + ) + ) + } + + companion object { + private fun getTimestampTextToCopy( + relatedInfoService: StreamingService, + relatedStreamUrl: String, + descriptionText: String, + timestampMatchDTO: TimestampMatchDTO + ): String { + // TODO: use extractor methods to get timestamps when this feature will be implemented in it + when (relatedInfoService) { + ServiceList.YouTube -> + return relatedStreamUrl + "&t=" + timestampMatchDTO.seconds() + + ServiceList.SoundCloud, ServiceList.MediaCCC -> + return relatedStreamUrl + "#t=" + timestampMatchDTO.seconds() + + ServiceList.PeerTube -> + return relatedStreamUrl + "?start=" + timestampMatchDTO.seconds() + } + + // Return timestamp text for other services + return descriptionText.substring( + timestampMatchDTO.timestampStart(), + timestampMatchDTO.timestampEnd() + ) + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java b/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java deleted file mode 100644 index 91b5ebd07..000000000 --- a/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2018 Mauricio Colli - * CollapsibleView.java is part of NewPipe - * - * License: GPL-3.0+ - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.schabi.newpipe.views; - -import static org.schabi.newpipe.MainActivity.DEBUG; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.animation.ValueAnimator; -import android.content.Context; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.Log; -import android.widget.LinearLayout; - -import androidx.annotation.IntDef; -import androidx.annotation.Nullable; - -import com.evernote.android.state.State; -import com.livefront.bridge.Bridge; - -import org.schabi.newpipe.ktx.ViewUtils; - -import java.lang.annotation.Retention; -import java.util.ArrayList; -import java.util.List; - -/** - * A view that can be fully collapsed and expanded. - */ -public class CollapsibleView extends LinearLayout { - private static final String TAG = CollapsibleView.class.getSimpleName(); - - private static final int ANIMATION_DURATION = 420; - - public static final int COLLAPSED = 0; - public static final int EXPANDED = 1; - - @State - @ViewMode - int currentState = COLLAPSED; - private boolean readyToChangeState; - - private int targetHeight = -1; - private ValueAnimator currentAnimator; - private final List listeners = new ArrayList<>(); - - public CollapsibleView(final Context context) { - super(context); - } - - public CollapsibleView(final Context context, @Nullable final AttributeSet attrs) { - super(context, attrs); - } - - public CollapsibleView(final Context context, @Nullable final AttributeSet attrs, - final int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public CollapsibleView(final Context context, final AttributeSet attrs, final int defStyleAttr, - final int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - /*////////////////////////////////////////////////////////////////////////// - // Collapse/expand logic - //////////////////////////////////////////////////////////////////////////*/ - - /** - * This method recalculates the height of this view so it must be called when - * some child changes (e.g. add new views, change text). - */ - public void ready() { - if (DEBUG) { - Log.d(TAG, getDebugLogString("ready() called")); - } - - measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), - MeasureSpec.UNSPECIFIED); - targetHeight = getMeasuredHeight(); - - getLayoutParams().height = currentState == COLLAPSED ? 0 : targetHeight; - requestLayout(); - broadcastState(); - - readyToChangeState = true; - - if (DEBUG) { - Log.d(TAG, getDebugLogString("ready() *after* measuring")); - } - } - - public void collapse() { - if (DEBUG) { - Log.d(TAG, getDebugLogString("collapse() called")); - } - - if (!readyToChangeState) { - return; - } - - final int height = getHeight(); - if (height == 0) { - setCurrentState(COLLAPSED); - return; - } - - if (currentAnimator != null && currentAnimator.isRunning()) { - currentAnimator.cancel(); - } - currentAnimator = ViewUtils.animateHeight(this, ANIMATION_DURATION, 0); - - setCurrentState(COLLAPSED); - } - - public void expand() { - if (DEBUG) { - Log.d(TAG, getDebugLogString("expand() called")); - } - - if (!readyToChangeState) { - return; - } - - final int height = getHeight(); - if (height == this.targetHeight) { - setCurrentState(EXPANDED); - return; - } - - if (currentAnimator != null && currentAnimator.isRunning()) { - currentAnimator.cancel(); - } - currentAnimator = ViewUtils.animateHeight(this, ANIMATION_DURATION, this.targetHeight); - setCurrentState(EXPANDED); - } - - public void switchState() { - if (!readyToChangeState) { - return; - } - - if (currentState == COLLAPSED) { - expand(); - } else { - collapse(); - } - } - - @ViewMode - public int getCurrentState() { - return currentState; - } - - public void setCurrentState(@ViewMode final int currentState) { - this.currentState = currentState; - broadcastState(); - } - - public void broadcastState() { - for (final StateListener listener : listeners) { - listener.onStateChanged(currentState); - } - } - - /** - * Add a listener which will be listening for changes in this view (i.e. collapsed or expanded). - * @param listener {@link StateListener} to be added - */ - public void addListener(final StateListener listener) { - if (listeners.contains(listener)) { - throw new IllegalStateException("Trying to add the same listener multiple times"); - } - - listeners.add(listener); - } - - /** - * Remove a listener so it doesn't receive more state changes. - * @param listener {@link StateListener} to be removed - */ - public void removeListener(final StateListener listener) { - listeners.remove(listener); - } - - /*////////////////////////////////////////////////////////////////////////// - // State Saving - //////////////////////////////////////////////////////////////////////////*/ - - @Nullable - @Override - public Parcelable onSaveInstanceState() { - return Bridge.saveInstanceState(this, super.onSaveInstanceState()); - } - - @Override - public void onRestoreInstanceState(final Parcelable state) { - super.onRestoreInstanceState(Bridge.restoreInstanceState(this, state)); - - ready(); - } - - /*////////////////////////////////////////////////////////////////////////// - // Internal - //////////////////////////////////////////////////////////////////////////*/ - - public String getDebugLogString(final String description) { - return String.format("%-100s → %s", - description, "readyToChangeState = [" + readyToChangeState + "], " - + "currentState = [" + currentState + "], " - + "targetHeight = [" + targetHeight + "], " - + "mW x mH = [" + getMeasuredWidth() + "x" + getMeasuredHeight() + "], " - + "W x H = [" + getWidth() + "x" + getHeight() + "]"); - } - - @Retention(SOURCE) - @IntDef({COLLAPSED, EXPANDED}) - public @interface ViewMode { } - - /** - * Simple interface used for listening state changes of the {@link CollapsibleView}. - */ - public interface StateListener { - /** - * Called when the state changes. - * - * @param newState the state that the {@link CollapsibleView} transitioned to,
- * it's an integer being either {@link #COLLAPSED} or {@link #EXPANDED} - */ - void onStateChanged(@ViewMode int newState); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/views/ExpandableSurfaceView.java b/app/src/main/java/org/schabi/newpipe/views/ExpandableSurfaceView.java index 175c81e46..7452fff09 100644 --- a/app/src/main/java/org/schabi/newpipe/views/ExpandableSurfaceView.java +++ b/app/src/main/java/org/schabi/newpipe/views/ExpandableSurfaceView.java @@ -35,12 +35,12 @@ public class ExpandableSurfaceView extends SurfaceView { && resizeMode != RESIZE_MODE_FIT && verticalVideo ? maxHeight : baseHeight; - if (height == 0) { + if (width == 0 || height == 0) { return; } final float viewAspectRatio = width / ((float) height); - final float aspectDeformation = videoAspectRatio / viewAspectRatio - 1; + final float aspectDeformation = (videoAspectRatio / viewAspectRatio) - 1; scaleX = 1.0f; scaleY = 1.0f; @@ -100,7 +100,7 @@ public class ExpandableSurfaceView extends SurfaceView { } public void setAspectRatio(final float aspectRatio) { - if (videoAspectRatio == aspectRatio) { + if (videoAspectRatio == aspectRatio || aspectRatio == 0 || !Float.isFinite(aspectRatio)) { return; } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt index 877070a91..08b7df6af 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/PlayerFastSeekOverlay.kt @@ -52,8 +52,9 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : private var initTap: Boolean = false override fun onDoubleTapStarted(portion: DisplayPortion) { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "onDoubleTapStarted called with portion = [$portion]") + } initTap = false @@ -64,7 +65,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : val shouldForward: Boolean = performListener?.getFastSeekDirection(portion)?.directionAsBoolean ?: return - if (DEBUG) + if (DEBUG) { Log.d( TAG, "onDoubleTapProgressDown called with " + @@ -72,6 +73,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : "wasForwarding = [$wasForwarding], " + "initTap = [$initTap], " ) + } /* * Check if a initial tap occurred or if direction was switched @@ -97,8 +99,9 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : } override fun onDoubleTapFinished() { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "onDoubleTapFinished called with initTap = [$initTap]") + } if (initTap) performListener?.onDoubleTapEnd() initTap = false @@ -112,8 +115,10 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : clone(rootConstraintLayout) clear(secondsView.id, if (forward) START else END) connect( - secondsView.id, if (forward) END else START, - PARENT_ID, if (forward) END else START + secondsView.id, + if (forward) END else START, + PARENT_ID, + if (forward) END else START ) secondsView.startAnimation() applyTo(rootConstraintLayout) @@ -123,6 +128,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : interface PerformListener { fun onDoubleTap() fun onDoubleTapEnd() + /** * Determines if the playback should forward/rewind or do nothing. */ @@ -132,7 +138,7 @@ class PlayerFastSeekOverlay(context: Context, attrs: AttributeSet?) : enum class FastSeekDirection(val directionAsBoolean: Boolean?) { NONE(null), FORWARD(true), - BACKWARD(false); + BACKWARD(false) } } diff --git a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt index 8472653fb..5e4885129 100644 --- a/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt +++ b/app/src/main/java/org/schabi/newpipe/views/player/SecondsView.kt @@ -29,7 +29,9 @@ class SecondsView(context: Context, attrs: AttributeSet?) : LinearLayout(context var seconds: Int = 0 set(value) { binding.tvSeconds.text = context.resources.getQuantityString( - R.plurals.seconds, value, value + R.plurals.seconds, + value, + value ) field = value } diff --git a/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java b/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java index eed5db463..1d2483e79 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadRunnableFallback.java @@ -85,6 +85,7 @@ public class DownloadRunnableFallback extends Thread { if (mMission.unknownLength || mConn.getResponseCode() == 200) { // restart amount of bytes downloaded mMission.done = mMission.offsets[mMission.current] - mMission.offsets[0]; + start = 0; // reset position to avoid writing at wrong offset } mF = mMission.storage.getStream(); diff --git a/app/src/main/java/us/shandian/giga/get/MissionRecoveryInfo.kt b/app/src/main/java/us/shandian/giga/get/MissionRecoveryInfo.kt index c2f9dc9b2..c145b8506 100644 --- a/app/src/main/java/us/shandian/giga/get/MissionRecoveryInfo.kt +++ b/app/src/main/java/us/shandian/giga/get/MissionRecoveryInfo.kt @@ -1,13 +1,13 @@ package us.shandian.giga.get import android.os.Parcelable +import java.io.Serializable import kotlinx.parcelize.Parcelize import org.schabi.newpipe.extractor.MediaFormat import org.schabi.newpipe.extractor.stream.AudioStream import org.schabi.newpipe.extractor.stream.Stream import org.schabi.newpipe.extractor.stream.SubtitlesStream import org.schabi.newpipe.extractor.stream.VideoStream -import java.io.Serializable @Parcelize class MissionRecoveryInfo( @@ -25,16 +25,19 @@ class MissionRecoveryInfo( isDesired2 = false kind = 'a' } + is VideoStream -> { desired = stream.getResolution() isDesired2 = stream.isVideoOnly() kind = 'v' } + is SubtitlesStream -> { desired = stream.languageTag isDesired2 = stream.isAutoGenerated kind = 's' } + else -> throw RuntimeException("Unknown stream kind") } } @@ -48,14 +51,17 @@ class MissionRecoveryInfo( str.append("audio") info = "bitrate=$desiredBitrate" } + 'v' -> { str.append("video") info = "quality=$desired videoOnly=$isDesired2" } + 's' -> { str.append("subtitles") info = "language=$desired autoGenerated=$isDesired2" } + else -> { info = "" str.append("other") diff --git a/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java b/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java index dc46ced5d..badb5f7ed 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java @@ -34,7 +34,7 @@ class OggFromWebmDemuxer extends Postprocessing { @Override int process(SharpStream out, @NonNull SharpStream... sources) throws IOException { - OggFromWebMWriter demuxer = new OggFromWebMWriter(sources[0], out); + OggFromWebMWriter demuxer = new OggFromWebMWriter(sources[0], out, streamInfo); demuxer.parseSource(); demuxer.selectTrack(0); demuxer.build(); diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java index 7f5c85d27..1c9143252 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java @@ -4,6 +4,7 @@ import android.util.Log; import androidx.annotation.NonNull; +import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.streams.io.SharpStream; import java.io.File; @@ -30,7 +31,8 @@ public abstract class Postprocessing implements Serializable { public transient static final String ALGORITHM_M4A_NO_DASH = "mp4D-m4a"; public transient static final String ALGORITHM_OGG_FROM_WEBM_DEMUXER = "webm-ogg-d"; - public static Postprocessing getAlgorithm(@NonNull String algorithmName, String[] args) { + public static Postprocessing getAlgorithm(@NonNull String algorithmName, String[] args, + StreamInfo streamInfo) { Postprocessing instance; switch (algorithmName) { @@ -56,6 +58,7 @@ public abstract class Postprocessing implements Serializable { } instance.args = args; + instance.streamInfo = streamInfo; return instance; } @@ -75,8 +78,8 @@ public abstract class Postprocessing implements Serializable { */ private final String name; - private String[] args; + protected StreamInfo streamInfo; private transient DownloadMission mission; diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index 45211211f..76da18b2d 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -40,6 +40,7 @@ import androidx.preference.PreferenceManager; import org.schabi.newpipe.R; import org.schabi.newpipe.download.DownloadActivity; +import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.player.helper.LockManager; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; @@ -74,12 +75,12 @@ public class DownloadManagerService extends Service { private static final String EXTRA_THREADS = "DownloadManagerService.extra.threads"; private static final String EXTRA_POSTPROCESSING_NAME = "DownloadManagerService.extra.postprocessingName"; private static final String EXTRA_POSTPROCESSING_ARGS = "DownloadManagerService.extra.postprocessingArgs"; - private static final String EXTRA_SOURCE = "DownloadManagerService.extra.source"; private static final String EXTRA_NEAR_LENGTH = "DownloadManagerService.extra.nearLength"; private static final String EXTRA_PATH = "DownloadManagerService.extra.storagePath"; private static final String EXTRA_PARENT_PATH = "DownloadManagerService.extra.storageParentPath"; private static final String EXTRA_STORAGE_TAG = "DownloadManagerService.extra.storageTag"; private static final String EXTRA_RECOVERY_INFO = "DownloadManagerService.extra.recoveryInfo"; + private static final String EXTRA_STREAM_INFO = "DownloadManagerService.extra.streamInfo"; private static final String ACTION_RESET_DOWNLOAD_FINISHED = APPLICATION_ID + ".reset_download_finished"; private static final String ACTION_OPEN_DOWNLOADS_FINISHED = APPLICATION_ID + ".open_downloads_finished"; @@ -353,13 +354,13 @@ public class DownloadManagerService extends Service { * @param kind type of file (a: audio v: video s: subtitle ?: file-extension defined) * @param threads the number of threads maximal used to download chunks of the file. * @param psName the name of the required post-processing algorithm, or {@code null} to ignore. - * @param source source url of the resource + * @param streamInfo stream metadata that may be written into the downloaded file. * @param psArgs the arguments for the post-processing algorithm. * @param nearLength the approximated final length of the file * @param recoveryInfo array of MissionRecoveryInfo, in case is required recover the download */ public static void startMission(Context context, String[] urls, StoredFileHelper storage, - char kind, int threads, String source, String psName, + char kind, int threads, StreamInfo streamInfo, String psName, String[] psArgs, long nearLength, ArrayList recoveryInfo) { final Intent intent = new Intent(context, DownloadManagerService.class) @@ -367,14 +368,14 @@ public class DownloadManagerService extends Service { .putExtra(EXTRA_URLS, urls) .putExtra(EXTRA_KIND, kind) .putExtra(EXTRA_THREADS, threads) - .putExtra(EXTRA_SOURCE, source) .putExtra(EXTRA_POSTPROCESSING_NAME, psName) .putExtra(EXTRA_POSTPROCESSING_ARGS, psArgs) .putExtra(EXTRA_NEAR_LENGTH, nearLength) .putExtra(EXTRA_RECOVERY_INFO, recoveryInfo) .putExtra(EXTRA_PARENT_PATH, storage.getParentUri()) .putExtra(EXTRA_PATH, storage.getUri()) - .putExtra(EXTRA_STORAGE_TAG, storage.getTag()); + .putExtra(EXTRA_STORAGE_TAG, storage.getTag()) + .putExtra(EXTRA_STREAM_INFO, streamInfo); context.startService(intent); } @@ -387,9 +388,9 @@ public class DownloadManagerService extends Service { char kind = intent.getCharExtra(EXTRA_KIND, '?'); String psName = intent.getStringExtra(EXTRA_POSTPROCESSING_NAME); String[] psArgs = intent.getStringArrayExtra(EXTRA_POSTPROCESSING_ARGS); - String source = intent.getStringExtra(EXTRA_SOURCE); long nearLength = intent.getLongExtra(EXTRA_NEAR_LENGTH, 0); String tag = intent.getStringExtra(EXTRA_STORAGE_TAG); + StreamInfo streamInfo = (StreamInfo)intent.getSerializableExtra(EXTRA_STREAM_INFO); final var recovery = IntentCompat.getParcelableArrayListExtra(intent, EXTRA_RECOVERY_INFO, MissionRecoveryInfo.class); Objects.requireNonNull(recovery); @@ -405,11 +406,11 @@ public class DownloadManagerService extends Service { if (psName == null) ps = null; else - ps = Postprocessing.getAlgorithm(psName, psArgs); + ps = Postprocessing.getAlgorithm(psName, psArgs, streamInfo); final DownloadMission mission = new DownloadMission(urls, storage, kind, ps); mission.threadCount = threads; - mission.source = source; + mission.source = streamInfo.getUrl(); mission.nearLength = nearLength; mission.recoveryInfo = recovery.toArray(new MissionRecoveryInfo[0]); diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index f245b3dd9..54ae2cfa4 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -2,6 +2,7 @@ package us.shandian.giga.ui.adapter; import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; +import static android.content.Intent.createChooser; import static us.shandian.giga.get.DownloadMission.ERROR_CONNECT_HOST; import static us.shandian.giga.get.DownloadMission.ERROR_FILE_CREATION; import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_NO_CONTENT; @@ -349,11 +350,15 @@ public class MissionAdapter extends Adapter implements Handler.Callb if (BuildConfig.DEBUG) Log.v(TAG, "Mime: " + mimeType + " package: " + BuildConfig.APPLICATION_ID + ".provider"); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(resolveShareableUri(mission), mimeType); - intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION); - intent.addFlags(FLAG_GRANT_PREFIX_URI_PERMISSION); - ShareUtils.openIntentInApp(mContext, intent); + Intent viewIntent = new Intent(Intent.ACTION_VIEW); + viewIntent.setDataAndType(resolveShareableUri(mission), mimeType); + viewIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION); + viewIntent.addFlags(FLAG_GRANT_PREFIX_URI_PERMISSION); + + Intent chooserIntent = createChooser(viewIntent, null); + chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | FLAG_GRANT_READ_URI_PERMISSION); + + ShareUtils.openIntentInApp(mContext, chooserIntent); } private void shareFile(Mission mission) { @@ -364,8 +369,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb shareIntent.putExtra(Intent.EXTRA_STREAM, resolveShareableUri(mission)); shareIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION); - final Intent intent = new Intent(Intent.ACTION_CHOOSER); - intent.putExtra(Intent.EXTRA_INTENT, shareIntent); + final Intent intent = createChooser(shareIntent, null); // unneeded to set a title to the chooser on Android P and higher because the system // ignores this title on these versions if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) { diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/player.xml index 99b514bb0..a6a0884c7 100644 --- a/app/src/main/res/layout/player.xml +++ b/app/src/main/res/layout/player.xml @@ -109,71 +109,89 @@ android:layout_marginEnd="8dp" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" + android:contentDescription="@string/close" android:focusable="true" android:padding="@dimen/player_main_buttons_padding" android:scaleType="fitXY" android:src="@drawable/ic_close" android:visibility="gone" app:tint="@color/white" - android:contentDescription="@string/close" tools:ignore="RtlHardcoded" /> + android:orientation="horizontal"> - + android:layout_marginTop="6dp" + android:layout_marginEnd="8dp" + android:layout_weight="1" + android:gravity="top" + android:orientation="vertical" + tools:ignore="NestedWeights,RtlHardcoded"> - + + + + + + + android:layout_weight="1"> + + + + - - @@ -368,11 +386,11 @@ android:layout_height="40dp" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" + android:contentDescription="@string/toggle_fullscreen" android:focusable="true" android:padding="@dimen/player_main_buttons_padding" android:scaleType="fitCenter" android:src="@drawable/ic_fullscreen" - android:contentDescription="@string/toggle_fullscreen" android:visibility="gone" app:tint="@color/white" tools:ignore="RtlHardcoded" @@ -492,13 +510,13 @@ android:layout_marginStart="4dp" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" + android:contentDescription="@string/toggle_screen_orientation" android:focusable="true" android:nextFocusUp="@id/playbackSeekBar" android:padding="@dimen/player_main_buttons_padding" android:scaleType="fitCenter" android:src="@drawable/ic_fullscreen" android:visibility="gone" - android:contentDescription="@string/toggle_screen_orientation" app:tint="@color/white" tools:ignore="RtlHardcoded" tools:visibility="visible" /> @@ -520,10 +538,10 @@ android:layout_weight="1" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" + android:contentDescription="@string/previous_stream" android:focusable="true" android:scaleType="fitCenter" android:src="@drawable/ic_previous" - android:contentDescription="@string/previous_stream" app:tint="@color/white" /> @@ -533,9 +551,9 @@ android:layout_height="60dp" android:layout_weight="1" android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/pause" android:scaleType="fitCenter" android:src="@drawable/ic_pause" - android:contentDescription="@string/pause" app:tint="@color/white" /> @@ -596,12 +614,12 @@ android:layout_marginLeft="40dp" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" + android:contentDescription="@string/notification_action_repeat" android:focusable="true" android:padding="10dp" android:scaleType="fitXY" android:src="@drawable/exo_controls_repeat_off" android:tint="?attr/colorAccent" - android:contentDescription="@string/notification_action_repeat" tools:ignore="RtlHardcoded" /> %s مُشاهِد عرض تلميح عند الضغط على زر استخدام المشغل الخلفي أو النافذة المنبثقة في صفحة تفاصيل الفديو - نعم، ومقاطع الفيديو التي تمت مشاهدتها جزئيًا + نعم، ومقاطع الفيديو التي تمت مشاهدتها جزئيًا انتهى وقت الاتصال غير معروف تشغيل تلقائي @@ -428,8 +428,7 @@ هذا الإذن مطلوب \nللفتح في وضع النافذة المنبثقة الموجز - ستتم إزالة مقاطع الفيديو التي تمت مشاهدتها قبل وبعد إضافتها إلى قائمة التشغيل. -\nهل أنت واثق؟ لا يمكن التراجع عن هذا! + ستتم إزالة مقاطع الفيديو التي تمت مشاهدتها قبل وبعد إضافتها إلى قائمة التشغيل. \nهل أنت واثق؟ لا يمكن التراجع عن هذا! عدم الإعجاب مشاهدة على الموقع هذا الخيار متاح فقط إذا تم تحديد %s للسمة diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index f5c8efb0d..51a1e47cb 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -547,9 +547,8 @@ هذا الفيديو مقيد بالفئة العمرية. \n \nقم بتشغيل \"%1$s\" في الإعدادات إذا كنت تريد رؤيته. - نعم، ومقاطع الفيديو التي تمت مشاهدتها جزئيًا - ستتم إزالة مقاطع الفيديو التي تمت مشاهدتها قبل وبعد إضافتها إلى قائمة التشغيل. -\nهل أنت واثق؟ لا يمكن التراجع عن هذا! + نعم، ومقاطع الفيديو التي تمت مشاهدتها جزئيًا + ستتم إزالة مقاطع الفيديو التي تمت مشاهدتها قبل وبعد إضافتها إلى قائمة التشغيل. \nهل أنت واثق؟ لا يمكن التراجع عن هذا! إزالة مقاطع الفيديو التي تمت مشاهدتها؟ إزالة ما تمت مشاهدته ستكون النصوص الأصلية من الخدمات مرئية في عناصر البث @@ -886,4 +885,24 @@ البحث %1$s (%2$s) تمت إزالة صفحة أفضل 50 من SoundCloud أوقفت SoundCloud صفحة أفضل 50 الأصلية. تمت إزالة علامة التبويب المقابلة من صفحتك الرئيسية. + تمت إزالة تريندات YouTube المجمعة + أوقف YouTube صفحة الترند المدمجة اعتبارًا من 21 يوليو 2025. استبدلت NewPipe صفحة الموضوعات المتداولة الافتراضية بصفحة الموضوعات المتداولة الشائعة مع البث المباشر المتداول.\n\nيمكنك أيضًا تحديد صفحات رائجة مختلفة في \"الإعدادات > المحتوى > محتوى الصفحة الرئيسية\". + توجهات الألعاب + توجهات البث الصوتي + الأفلام والعروض الأكثر رواجاً + الموسيقى الرائجة + %s الف + %s مليون + %sمليار + لاستخدام المشغل المنبثق، يرجى تحديد %1$s في قائمة إعدادات اندرويد التالية وتمكين %2$s. + “السماح بالعرض فوق التطبيقات الاخرى” + حذف ملف + حذف المدخلات + تم إنهاء الحساب\n\n%1$s يقدم هذا السبب: %2$s + تم حذف المدخلات + تم تلقي خطأ HTTP 403 من الخادم أثناء التشغيل، ويرجح أن يكون السبب هو انتهاء صلاحية عنوان URL للبث أو حظر عنوان IP + حدث خطأ HTTP %1$s من الخادم أثناء التشغيل + تم تلقي خطأ HTTP 403 من الخادم أثناء التشغيل، ويرجح أن يكون السبب هو حظر عنوان IP أو مشكلات في إزالة التعتيم عن عنوان URL للبث + رفض %1$s تقديم البيانات، وطلب تسجيل الدخول للتأكد من أن الطالب ليس روبوتًا.\n\nربما تم حظر عنوان IP الخاص بك مؤقتًا من قبل %1$s، يمكنك الانتظار بعض الوقت أو التبديل إلى عنوان IP مختلف (على سبيل المثال عن طريق تشغيل/إيقاف تشغيل VPN، أو التبديل من WiFi إلى بيانات الهاتف المحمول). + هذا المحتوى غير متاح للبلد المحدد حاليًا.\n\nقم بتغيير اختيارك من ”الإعدادات > المحتوى > البلد الافتراضي للمحتوى“. diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 0e0135c71..d1d2c8bd9 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -192,10 +192,10 @@ Sil Hələ ki, kanal abunəliyi yoxdur Kanal seç - Kanal Səhifəsi + Kanal səhifəsi Standart Bölmə - Kənar Səhifə - Boş Səhifə + Kənar səhifə + Boş səhifə Əsas səhifədə hansı tablar göstərilir Əsas səhifə məzmunu Yeni versiya mövcud olduqda tətbiq yeniləməsini xatırlatmaq üçün bildiriş göstər @@ -295,7 +295,7 @@ Nə baş verdi: Yükləyənin avatar miniatürü Bəyən - Bəyənmə + Bəyənməmə Yenidən sıralamaq üçün sürüklə Xidməti dəyiş, hazırda seçilmiş: Abunəçi yoxdur @@ -397,8 +397,7 @@ Server çox iş parçalı endirmələri qəbul etmir, @string/msg_threads = 1 ilə yenidən cəhd edin Bütün endirilmiş fayllar diskdən silinsin\? Maksimum təkrar cəhdlər - Pleylistə əlavə olunandan əvvəl və sonrakı baxılmış videolar silinəcək. -\nSiz əminsiniz? Bu geri qaytarıla bilməz! + Pleylistə əlavə olunandan əvvəl və sonrakı baxılmış videolar silinəcək. \nSiz əminsiniz? Bu geri qaytarıla bilməz! Kanal qrupları Yeni axın elementləri Abunəlik köhnəlmiş hesab edilənə qədərki son yeniləmədən sonrakı vaxt — %s @@ -529,7 +528,7 @@ ExoPlayer standartı Mövcud olduqda xüsusi axından al - Baxılmış videolar silinsin\? + Baxılmış videolar silinsin? İzləniləni sil Sistem qovluğu seçicisini (SAF) istifadə et Bağlantı fasiləsi @@ -585,7 +584,7 @@ Serveri təsdiqləmək mümkün olmadı %s-də bəyəndiyiniz serverləri tapın Video \"Təfsilatlar\" səhifəsində fon və ya ani görüntü düyməsin basarkən ipucu göstər - Oynadıcı titr mətn miqyasını və arxa fon üslublarını dəyişdir. Effektiv olması üçün tətbiqi yenidən başlatmaq tələb olunur + Oynadıcı titr mətn miqyasını və arxa plan üslublarını dəyişdir. Effektiv olması üçün tətbiqi yenidən başlatmaq tələb olunur Xəta baş verdi: %1$s Fayl mövcud deyil, yaxud oxumaq və ya yazmaq icazəsi yoxdur Veb saytı təhlil etmək alınmadı @@ -652,7 +651,7 @@ Oynatma Sürəti Nizamlamaları Ayır (pozuntuya səbəb ola bilər) Xətanı göstər - Bəli və qismən baxılmış videolar + Bəli və qismən baxılmış videolar %1$s endirməsi silindi %1$s endirmə silindi @@ -803,4 +802,29 @@ Axın qrupu seçin Hələ heç bir axın qrupu yaradılmayıb Kanal qrupu səhifəsi + %1$s axtar + %1$s (%2$s) axtar + Bəyənmə + SoundCloud Top 50 səhifəsi silindi + SoundCloud ilk Ən yaxşı 50 siyahısın ləğv etdi. Uyğun səhifə əsas səhifənizdən silindi. + %sMin + %sMln + %sMlrd + YouTube birləşmiş trend silindi + YouTube 21 iyul 2025-ci il tarixindən birləşmiş trend səhifəsini ləğv etdi. NewPipe ilkin trend səhifəsini trend olan canlı yayımlarla əvəz etdi. \n\nHəmçinin \"Tənzimləmələr > Məzmun > Əsas səhifə məzmunu\" bölməsində müxtəlif trendli səhifələri seçə bilərsiniz. + Trenddə olan Oyun + Trenddə olan podkastlar + Trend film və tamaşalar + Trenddə olan musiqilər + Ani oynadıcı istifadə etmək üçün lütfən, aşağıdakı Android tənzimləmələr menyusunda %1$s seçin və %2$s-ı aktivləşdirin. + \"Digər tətbiqlər üzərində göstərməyə icazə verin\" + Faylı sil + Girişi silin + Giriş silindi + Hesab ləğv edilib\n\n %1$s bu səbəbi təmin edir: %2$s + Oynadarkən serverdən alınan HTTP xətası 403, çox güman ki, yayım URL-si müddətinin bitməsi və ya IP qadağası ilə bağlıdır + HTTP xətası %1$s oynadarkən serverdən alındı + HTTP xətası 403 oynadarkən serverdən alındı, ehtimal ki, IP qadağası və ya yayım URL-nin deobfuscation problemləri ilə bağlıdır + %1$s sorğuçunun bot olmadığını təsdiqləmək üçün giriş tələb edərək data təmin etməkdən imtina etdi.\n\nIP-niz %1$s tərəfindən müvəqqəti şəkildə qadağan oluna bilər, bir müddət gözləyə və ya başqa IP-yə keçə bilərsiniz (məsələn, VPN-i açıb/qapatmaqla və ya WiFi-dan mobil dataya keçməklə). + Bu məzmun hazırda seçilən məzmun ölkəsi üçün əlçatan deyil. \n\nSeçiminizi \"Tənzimləmələr > Məzmun > İlkin məzmun ölkəsi\"- dən dəyişin. diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index 81b212f80..c64972eb3 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -312,10 +312,9 @@ Últimu anovamientu del feed: %s Grupos de canales Pola mor de les torgues d\'ExoPlayer la duración afitóse en %d segundos - Sí, y tamién los vistos parcialmente - Van desaniciase los vídeos que se vieren enantes y dempués d\'amestase a la llista de reproducción. -\n¿De xuru\? ¡Esto nun pue desfacese! - ¿Desaniciar los vídeos vistos\? + Sí, y tamién los vistos parcialmente + Van desaniciase los vídeos que se vieren enantes y dempués d\'amestase a la llista de reproducción. \n¿De xuru? ¡Esto nun pue desfacese! + ¿Desaniciar los vídeos vistos? Desaniciar lo visto Escoyeta d\'una instancia El «Storage Access Framework» permite les descargues nuna tarxeta SD esterna. diff --git a/app/src/main/res/values-b+uz+Latn/strings.xml b/app/src/main/res/values-b+uz+Latn/strings.xml index 2be37ea7c..cc82ec69c 100644 --- a/app/src/main/res/values-b+uz+Latn/strings.xml +++ b/app/src/main/res/values-b+uz+Latn/strings.xml @@ -384,10 +384,9 @@ %d sekondlar ExoPlayer cheklovlari tufayli qidiruv davomiyligi %d soniya qilib belgilandi - Ha, va qisman videolarni tomosha qildim - Pleylistga qo\'shilishdan oldin va keyin ko\'rilgan videolar o\'chiriladi. -\nIshonchingiz komilmi\? Buni qaytarib bo\'lmaydi! - Ko\'rilgan videolar olib tashlansinmi\? + Ha, va qisman videolarni tomosha qildim + Pleylistga qo\'shilishdan oldin va keyin ko\'rilgan videolar o\'chiriladi. \nIshonchingiz komilmi? Buni qaytarib bo\'lmaydi! + Ko\'rilgan videolar olib tashlansinmi? Ko\'rilganlarni olib tashlash Tizimning standart qiymati Ilova tili diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 72b08414e..e44d2ea5c 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -85,7 +85,7 @@ Прайграванне ў фонавым рэжыме Прайграванне ва ўсплывальным акне Кантэнт - Паказваць кантэнт 18+ + Кантэнт з ўзроставым абмежаваннем Ужывую Спампоўкі Спампоўкі @@ -106,8 +106,8 @@ Апавяшчэнне NewPipe Апавяшчэнні для прайгравальніка NewPipe [Невядома] - Перайсці ў фон - Перайсці ў акно + Перайсці ў фонавы рэжым + Перайсці ў аконны рэжым Перайсці ў галоўнае акно Імпартаваць даныя Экспартаваць даныя @@ -427,7 +427,7 @@ Уключыць гук Адключыць гук Дадаць у чаргу - Даданае ў чаргу + Дададзена у чаргу Чарга прайгравання Найбольш папулярнае Лакальнае @@ -576,7 +576,7 @@ Шукайце серверы, якія вам даспадобы, на %s Паказваць метаданыя Ігнараваць падзеі апаратных медыякнопак - Паказваць змесціва, магчыма непрыдатнае для дзяцей, таму што яно мае ўзроставыя абмежаванні (напрыклад, 18+) + Паказваць змесціва, якое можа быць непрыдатным для дзяцей, бо мае ўзроставыя абмежаванні (напрыклад, 18+) Праверце, ці не існуе заяўкі з абмеркаваннем вашай праблемы. Дублікаты марнуюць наш час і праз гэта адцягваецца вырашэнне сапраўдных задач. Адбылася памылка, глядзіце апавяшчэнне Збой плэера @@ -597,8 +597,8 @@ %s новых трансляцый Каментарыі - У чаргу далей - У чарзе наступны + Дадаць у чаргу наступным + Дададзена у чаргу (наступным) Загрузка звестак аб стрыме… Ідзе апрацоўка… Крыху пачакайце Дублікат дададзены %d раз(ы) @@ -616,8 +616,8 @@ Апрацоўка стужкі… Пры кожным спампоўванні вам будзе прапанавана выбраць месца захавання Загрузка канала… - Выдаліць прагледжаныя відэа\? - Так, часткова прагледжаныя відэа таксама + Выдаліць прагледжаныя відэа? + Так, часткова прагледжаныя відэа таксама Працэнт Відэа, якія прагледжаны перад дадаваннем і пасля дадавання ў спіс прайгравання, будуць выдалены. \nВы ўпэўнены? Гэта дзеянне немагчыма скасаваць! Паказвае варыянт збою пры выкарыстанні плэера @@ -692,22 +692,20 @@ Радыё Паказваць наступныя патокі Паказаць/схаваць трансляцыі - Гэты кантэнт яшчэ не падтрымліваецца NewPipe. -\n -\nСпадзяюся, ён будзе падтрымлівацца ў наступных версіях. + Гэты кантэнт яшчэ не падтрымліваецца NewPipe.\n\nСпадзяёмся, што падтрымка з\'явіцца ў наступных версіях. Старонка плэй-ліста Паказваць мініяцюру Выкарыстоўваць мініяцюру як фон для экрана блакіроўкі і апавяшчэнняў Для гэтага дзеяння не знойдзены прыдатны файлавы менеджар. \nУсталюйце файлавы менеджар або паспрабуйце адключыць «%s» у наладах спампоўвання Гэты кантэнт недаступны ў вашай краіне. - Гэта трэк SoundCloud Go+, прынамсі ў вашай краіне, таму NewPipe не можа трансляваць ці спампоўваць яго. - Гэта змесціва з\'яўляецца прыватным, таму NewPipe не можа яго трансляваць або спампоўваць. - Гэта відэа даступна толькі для падпісчыкаў YouTube Music Premium, таму NewPipe не можа яго трансляваць або спампоўваць. + Гэта трэк SoundCloud Go+ (прынамсі ў вашай краіне), таму NewPipe не можа яго прайграць або спампаваць. + Гэты кантэнт прыватны, таму NewPipe не можа яго прайграць або спампаваць. + Гэта відэа даступна толькі для падпісчыкаў YouTube Music Premium, таму NewPipe не можа яго прайграць або спампаваць. Уліковы запіс спынены Вартае ўвагі Унутраная Прагледжаныя цалкам - Гэты кантэнт даступны толькі для аплачаных карыстальнікаў, таму NewPipe не можа яго трансляваць або спампоўваць. + Гэты кантэнт даступны карыстальнікам толькі за плату, таму NewPipe не можа яго прайграць або спампаваць. Даступна для некаторых сэрвісаў, звычайна значна хутчэй, але можа перадаваць абмежаваную колькасць элементаў і не ўсю інфармацыю (можа адсутнічаць працягласць, тып элемента, паказчык трансляцыі) Узроставае абмежаванне Для гэтага дзеяння не знойдзены прыдатны файлавы менеджар. \nУсталюйце файлавы менеджар, сумяшчальны з Storage Access Framework @@ -729,7 +727,7 @@ Аддаваць перавагу арыгінальнаму гуку Аддаваць перавагу апісальнаму гуку Выбіраць гукавую дарожку з апісаннем для людзей са слабым зрокам, калі яна ёсць - Аўдыя: %s + Аўдыядарожка: %s Гукавая дарожка Выберыце гукавую дарожку для знешніх прайгравальнікаў Невядомая @@ -819,4 +817,19 @@ Пошук %1$s Пошук %1$s (%2$s) Спадабалася + «Дазволіць паказ па-над астатнімі праграмамі» + %s тыс. + %s млн + %s млрд + Выдаліць файл + Выдаліць запіс + Старонка SoundCloud Top 50 выдалена + Трэнды – музыка + Запіс выдалены + Трэнды – гульні + Трэнды – падкасты + Трэнды – фільмы і перадачы + Гэты кантэнт недаступны для цяперашняй краіны кантэнту.\n\nЯе можна змяніць праз «Налады > Кантэнт > Прадвызначаная краіна кантэнту». + 21 ліпеня 2025 года YouTube спыніў падтрымку аб\'яднанай старонкі трэндаў. NewPipe замяніў старонку трэндаў на трэнды трансляцый.\n\nТаксама можна выбраць іншыя старонкі трэндаў праз «Налады > Кантэнт > Змесціва галоўнай старонкі». + Аб\'яднаныя трэнды YouTube выдалены diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 870b6be79..a038ac07b 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -163,8 +163,8 @@ Само веднъж Файл Мини във фонов режим - Мини към нов прозорец - Мини в основен режим + Мини в нов прозорец + Мини към основен режим Внасяне на база данни Изнасяне на база данни Замества текущата ви история, абонаменти, списъци за възпроизвеждане и (по избор) настройки @@ -258,7 +258,7 @@ Нов Плейлист Преименувай Име - Добави Към Плейлист + Добави към плейлист Задай като миниатюра на плейлиста Миниатюрата на плейлиста е сменена Премахни отметката @@ -277,7 +277,7 @@ Докладвай за извънредни грешки Внасяне Внасяне от - Изнеси в + Изнасяне във Внасяне… Изнасяне… Файл с данни за внасяне @@ -464,8 +464,7 @@ \nЕвентуално може да бъде поддържано в бъдещи версии.
Обработка… Ще отнеме момент Поради ограничения в ExoPlayer, стъпката за превъртане е зададена на %d секунди - Видата, които са били изгледани преди и след добавянето към плейлиста ще бъдат премахнати. -\nСигурни ли сте\? Това не може да бъде отменено! + Видата, които са били изгледани преди и след добавянето към плейлиста ще бъдат премахнати. \nСигурни ли сте? Това не може да бъде отменено! „Storage Access Framework“ позволява изтегляния във външна SD-карта Започни изтеглянията Затвори @@ -501,8 +500,8 @@ Създаден от %s Съдържанието е достъпно само за хора, които са си платили, затова не може да бъде гледано или изтеглено с NewPipe. Това видео е достъпно за абонати на YouTube Music Premium, затова не може да бъде гледано или изтеглено с NewPipe. - Премахни изгледаните видеа\? - Да, както и само частично изгледаните видеа + Премахни изгледаните видеа? + Да, както и само частично изгледаните видеа Брой на абонати не е наличен Инстанцията вече съществува Файлът е преместен или изтрит @@ -660,7 +659,7 @@ Въведете URL адреса на инстанцията Аудио: %s Покажи информация за канала - Автоматично генерирани (не е намерен ъплоудер) + Авто-генерирани (не е намерен ъплоудер) Създай известие за грешка NewPipe може автоматично да проверява за нови версии от време на време и да ви известява при наличие. \nИскате ли да го включите? @@ -815,4 +814,24 @@ Харесвания Страница SoundCloud Top 50 е премахната SoundCloud преустанови оригиналните класации Топ 50. Съответният раздел е премахнат от главната ви страница. + YouTube преустанови комбинираната страница с популярни от 21 юли 2025 г. NewPipe замени стандартната страница с популярни с популярни предавания на живо.\n\nМожете също да изберете различни популярни страници в „Настройки > Съдържание > Съдържание на главната страница“. + YouTube комбинирани популярни са премахнати + Популярни игри + Популярни подкасти + Популярни филми и сериали + Популярна музика + %s хил. + %s млн. + %s млрд. + За да използвате изскачащия плейър, моля, изберете %1$s в следното меню с настройки на Android и активирайте %2$s. + “Разреши показване върху други приложения” + Изтриване на файл + Изтриване на запис + Записът е изтрит + Профилът е прекратен\n\n%1$s предоставя тази причина: %2$s + HTTP грешка 403, получена от сървъра по време на възпроизвеждане, вероятно причинена от изтичане на URL адреса за стрийминг или забрана на IP адреса + HTTP грешка %1$s получена от сървъра по време на възпроизвеждане + HTTP грешка 403, получена от сървъра по време на възпроизвеждане, вероятно причинена от забрана на IP адреса или проблеми с деобфускацията на URL адреси за стрийминг + %1$s отказа да предостави данни, като поиска вход, за да потвърди, че заявителят не е бот.\n\nВашият IP адрес може да е временно забранен от %1$s. Можете да изчакате известно време или да превключите към друг IP адрес (например като включите/изключите VPN или като превключите от WiFi към мобилни данни). + Това съдържание не е налично за текущо избраната държава на съдържанието.\n\nПроменете избора си от \"Настройки > Съдържание > Държава на съдържанието по подразбиране\". diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index e6269b5b9..a79319ee3 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -307,4 +307,8 @@ বিজ্ঞপ্তিতে প্রদর্শিত ভিডিও থাম্বনেল 16:9 থেকে 1:1 অনুপাতের করুন (বিকৃতি দেখা যেতে পারে) অদলবদল কিছু না + হ্যাঁ + না + সার্চ + খুঁজুন diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 682b59fe3..7a4c8b3b0 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -296,7 +296,7 @@ এক প্লেয়ার থেকে অন্য প্লেয়ারে পরিবর্তন করলে তোমার সারি প্রতিস্থাপিত হতে পারে কিউ মোছার আগে নিশ্চিত করো কমপ্যাক্ট বিজ্ঞপ্তিতে প্রদর্শন করতে তুমি সর্বাধিক তিনটি ক্রিয়া নির্বাচন করতে পারো! - নিচের প্রতিটি প্রজ্ঞাপন ক্রিয়া সম্পাদনা করো। ডান দিকের চেকবাক্স ব্যবহার করে কম্প্যাক্ট নোটিফিকেশনে দেখানোর জন্য তিনটি পর্যন্ত নির্বাচন করো + নিচের প্রতিটি প্রজ্ঞাপন ক্রিয়া সম্পাদনা করুন । ডান দিকের চেকবাক্স ব্যবহার করে কম্প্যাক্ট নোটিফিকেশনে দেখানোর জন্য তিনটি পর্যন্ত নির্বাচন করুন । প্রদর্শিত ভিডিও থাম্বনেইল ১৬:৯ থেকে ১:১অনুপাতে পরিবর্তন করো ফিড ওভাররাইট @@ -337,7 +337,7 @@ অপুনরুদ্ধারযোগ্য প্লেয়ার ত্রুটি ঘটেছে ইন্সট্যান্সটি যাচাই করা যায়নি রিক্যাপচা কুকিগুলো পরিষ্কার করা হয়েছে - হ্যাঁ, এবং আংশিকভাবে দেখা ভিডিও + হ্যাঁ, এবং আংশিকভাবে দেখা ভিডিও ব্যবস্থা দ্বারা ক্রিয়া অস্বীকার করা হয়েছে স্বয়ংক্রিয়ভাবে প্লেব্যাক শুরু করো %s — তে একটি পপ-আপে প্লে শুরু করো @@ -434,7 +434,7 @@ খালি গ্রুপ নাম কোনো সদস্যতা নির্বাচিত হয়নি %d: লোড হয়নি - দেখা ভিডিওগুলো সরাও\? + দেখা ভিডিওগুলো সরাও? একটি ইন্সট্যান্স নাও ডাউনলোড সারি সীমিত করো অনন্য নাম বানাও @@ -628,4 +628,8 @@ ভুক্তি মুছতে ডানে-বামে সরাও সম্প্রচার বিষয়ক তথ্য প্রক্রিয়ারত… প্লেব্যাক লোড বিরতির আকার + হ্যা + না + প্লেলিস্ট + উদাহরণস্বরূপ, যদি আপনি ভাঙা ফিজিক্যাল বোতাম সহ একটি হেডসেট ব্যবহার করেন তবে এটি কার্যকর diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index a0a7744f6..dfff3c2cc 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -117,5 +117,4 @@ Lenn ar video, pad: Titouroù: Video - diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index 4921a6aa8..ee4fc3317 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -28,7 +28,7 @@ Otkazana pratnja kanala Nije moguće promijeniti pratnju Nije moguće ažurirati pratnju - Instalirajte nedostajeću Kode aplikaciju\? + Instalirati nedostajuću Kore aplikaciju? Obilježeni Popisi Iskačni prozor Izaberite Podprozor @@ -43,9 +43,9 @@ Zadani režim za iskačući prozor Prekinite pokretač Prikažite postavku da biste video preko KODI medijskog centra video pokrenuli - Skalirajte sličicu na 1:1 omjer + Izrežite sličicu na omjer slike 1:1 Prvo radno dugme - Skalirajte video sličicu prikazanu u obavijesti sa 16:9 na 1:1 omjer (može uvesti poremećaje) + Izrežite sličicu videa prikazanu u obavještenju sa omjera stranica 16:9 na 1:1 Drugo radno dugme Treće radno dugme Četvrto radno dugme @@ -53,7 +53,7 @@ Možete najviše tri radnje odabrati za prikaz u kompaktnom obavještaju! Ponovi Pomiješajte - Uredite svaku radnju obavještenja ispod pri dodiru na nju. Odaberite bar tri od njih za prikaz u kompaktnom obavještenju koristeći potvrdne okvire s desne strane + Uredite svaku radnju obavještenja ispod dodirom na nju. Odaberite do tri od njih koje će biti prikazane u kompaktnom obavještenju pomoću potvrdnih okvira s desne strane. Ništa Obojite obavještenje Učitavanje @@ -62,7 +62,7 @@ Zvuk Zadani video format Tema - Noćna Tema + Noćna tema Svijetla Tamna Zapamtite podešavanja za iskočne prozore @@ -114,4 +114,709 @@ Pokrenite s KODI-jem Vrijeme premotavanja naprijed/nazad Aktivni pokretni red će biti zamijenjen - \ No newline at end of file + Da + Ne + Pretraži %1$s + Pretraži %1$s (%2$s) + Plejliste + Uredite svaku radnju obavještenja ispod dodirom na nju. Prve tri radnje (reprodukcija/pauza, prethodno i sljedeće) postavlja sistem i ne mogu se prilagođavati. + Veličina intervala učitavanja reprodukcije + Promijenite veličinu intervala učitavanja progresivnog sadržaja (trenutno %s). Niža vrijednost može ubrzati njihovo početno učitavanje + Zanemari događaje hardverskih medijskih tipki + Korisno, na primjer, ako koristite slušalice s pokvarenim fizičkim tipkama + Preferiraj originalni audio + Odaberite originalni audio zapis bez obzira na jezik + Preferiraj opisni audio + Odaberite audio zapis s opisima za osobe s oštećenim vidom ako su dostupni + Odaberite gestu za lijevu polovinu ekrana igrača + Radnja lijevog pokreta + Odaberite gestu za desnu polovinu ekrana igrača + Radnja desnog gesta + Svjetlina + Volumen + Nema + Prikaži savjet \"Drži za dodavanje u red\" + Prikaži savjet prilikom pritiska na pozadinu ili iskačuće dugme u videu \"Detalji:\" + Nepodržani URL + URL nije prepoznat. Otvoriti s drugom aplikacijom? + Zadana zemlja sadržaja + Zadani jezik sadržaja + PeerTube instance + Odaberite svoje omiljene PeerTube instance + Pronađite instance koje vam se sviđaju na %s + Dodaj instancu + Unesite URL instance + Nije moguće validirati instancu + Podržani su samo HTTPS URL-ovi + Instanca već postoji + Pokretač + Ponašanje + Video i audio + Historija i keš memorija + Izgled + Debug + Nadogradnje + Obavještenje za igrača + Konfigurišite obavještenja o trenutno reprodukovanom toku + Sigurnosna kopija i vraćanje + Reprodukcija u pozadini + Reprodukcija u skočnom modu + Sadržaj + Prikaži sadržaj s ograničenjem za uzrast + Prikaži sadržaj koji je možda neprikladan za djecu jer ima starosno ograničenje (npr. 18+) + Uključite \"Ograničeni način rada\" na YouTubeu + YouTube nudi \"Ograničeni način rada\" koji skriva potencijalno sadržaj za odrasle + Ovaj video ima dobno ograničenje.\n\nUključite \"%1$s\" u postavkama ako ga želite pogledati. + Ovaj video ima dobno ograničenje. \nZbog novih YouTube pravila o videozapisima s dobnim ograničenjem, NewPipe ne može pristupiti nijednom od svojih video tokova i stoga ga ne može reproducirati. + Uživo + Preuzimanja + Preuzimanja + Učitavanje metapodataka… + Izvještaj o grešci + Sve + Kanali + Plejliste + Videozapisi + Snimke + Korisnici + Događanja + Pjesme + Albuma + Umjetnici + Onemogućeno + Rasčisti + Najbolja rezolucija + Poništi + Datoteka je izbrisana + Reproduciraj sve + Uvijek + Samo jednom + Datoteka + Obavijesti + Obavještenje o novoj cijevi + Obavještenja za NewPipeovog igrača + Obavještenje o ažuriranju aplikacije + Obavještenja za nove verzije NewPipe-a + Obavještenje o hešu videa + Obavještenja o napretku heširanja videa + Novi tokovi + Obavještenja o novim tokovima za pretplatnike + Obavještenje o grešci + Obavještenja za prijavu grešaka + [Nepoznato] + Prebaci na pozadinu + Prebaci na skočni prozor + Prebaci na glavni + Uvoz baze podataka + Izvoz baze podataka + Obriši reCAPTCHA kolačiće + reCAPTCHA kolačići su obrisani + Zaobilazi vašu trenutnu historiju, pretplate, liste pjesama i (opcionalno) postavke + Izvoz historije, pretplata, plejlista i postavki + Obrišite kolačiće koje NewPipe pohranjuje kada riješite reCAPTCHA + Obriši historiju gledanja + Briše historiju reprodukovanih tokova i pozicije reprodukcije + Izbrisati cijelu historiju gledanja? + Historija gledanja je izbrisana + Brisanje pozicija reprodukcije + Briše sve pozicije reprodukcije + Izbrisati sve pozicije reprodukcije? + Pozicije reprodukcije su izbrisane + Obriši historiju pretraživanja + Briše historiju ključnih riječi pretrage + Izbrisati cijelu historiju pretraživanja? + Historija pretrage je izbrisana + Brzi način rada + Pomakni glavni birač kartica na dno + Položaj glavnih kartica + Greška + Vanjska pohrana nije dostupna + Preuzimanje na eksternu SD karticu nije moguće. Poništiti lokaciju mape za preuzimanje? + Greška mreže + Nije moguće učitati sve sličice + Nije moguće analizirati web stranicu + Sadržaj nije dostupan + Nije moguće postaviti meni za preuzimanje + Aplikacija/korisnički interfejs se srušio/la + Nije moguće reproducirati ovaj tok + Došlo je do nepopravljive greške igrača + Oporavak od greške igrača + Vanjski playeri ne podržavaju ove vrste linkova + Nisu pronađeni video tokovi + Nisu pronađeni audio tokovi + Datoteka je premještena ili izbrisana + Fascikla sa popisima + Nema takve datoteke/izvora sadržaja + Datoteka ne postoji ili nedostaje dozvola za čitanje ili pisanje u nju + Naziv datoteke ne može biti prazan + Došlo je do greške: %1$s + Nema dostupnih tokova za preuzimanje + Nije moguće pročitati sačuvane kartice, pa se koriste zadane + Vrati zadane postavke + Želite li vratiti zadane postavke? + Dozvoli prikaz preko drugih aplikacija + Da biste koristili Popup Player, odaberite %1$s u sljedećem meniju postavki Androida i omogućite %2$s. + \"Dozvoli prikaz preko drugih aplikacija\" + NewPipe je naišao na grešku, dodirnite za prijavu + Došlo je do greške, pogledajte obavještenje + Žao mi je, to se nije trebalo desiti. + Prijavi putem e-pošte + Kopiraj formatirani izvještaj + Izvještaj na GitHubu + Molimo Vas da provjerite da li već postoji problem koji se odnosi na Vaš pad sistema. Prilikom kreiranja duplikata tiketa, oduzimate nam vrijeme koje bismo mogli posvetiti ispravljanju samog problema. + Izvinite, ali nešto je pošlo po zlu. + Prijavi + Info: + Šta se dogodilo: + Šta:\\nZahtjev:\\nJezik sadržaja:\\nZemlja sadržaja:\\nJezik aplikacije:\\nUsluga:\\nVremenska oznaka:\\nPaket:\\nVerzija:\\nVerzija OS-a: + Vaš komentar (na engleskom): + Detalji: + Reproduciraj video, trajanje: + Sličica avatara osobe koja je postavila sliku + Sviđanja + Nesviđa mi se + Komentari + Povezane stavke + Opis + Bez rezultata + Ovdje nema ničega osim cvrčaka + Uvoz ili izvoz pretplata iz menija s tri tačke + Prevucite da promijenite redoslijed + Video + Audio + Pokušaj ponovo + %sK + %sM + %sB + Uključi/isključi uslugu, trenutno odabrana: + Nema pretplatnika + Broj pretplatnika nije dostupan + Nema pregleda + Niko ne gleda + Niko ne sluša + Nema videozapisa + 100+ videa + ∞ videozapisi + Nema komentara + Komentari su onemogućeni + Nema tokova + Nema prijenosa uživo + Početak + Pauziraj + Napravi + Izbriši + Izbriši datoteku + Izbriši unos + Kontrolni zbir + Raspusti + Preimenuj + Naziv datoteke + Teme + Greška + Preuzimanje NewPipe-a + Dodirnite za detalje + Izračunavanje heša + Molimo pričekajte… + Kopirano u međuspremnik + Kopiranje u međuspremnik nije uspjelo + Molimo vas da kasnije u postavkama definišete folder za preuzimanje + Još nije postavljen folder za preuzimanje, odaberite zadani folder za preuzimanje sada + Ova dozvola je potrebna za \notvaranje u skočnom prozoru + 1 stavka je izbrisana. + reCAPTCHA izazov + Pritisnite \"Gotovo\" kada riješite problem + Zatražen je reCAPTCHA izazov + Riješi + Gotovo + Preuzimanje + Dozvoljeni znakovi u nazivima datoteka + Nevažeći znakovi se zamjenjuju ovom vrijednošću + Zamjenski lik + Slova i brojevi + Većina specijalnih znakova + O NewPipe-u + Licence trećih strana + © %1$s od %2$s pod %3$s + Dozvole + Besplatno lagano tokanje na Androidu. + Doprinesite + Bez obzira da li imate ideje za: prevod, promjene dizajna, čišćenje koda ili zaista velike promjene koda - pomoć je uvijek dobrodošla. Što se više uradi, to bolje postaje! + Pogledajte na GitHubu + Donirajte + NewPipe je razvijen od strane volontera koji svoje slobodno vrijeme provode pružajući vam najbolje korisničko iskustvo. Doprinesite programerima kako biste ih učinili još boljim dok uživaju u šoljici kafe. + Vratite + Web stranica + Posjetite web stranicu NewPipe za više informacija i novosti. + Politika privatnosti kompanije NewPipe + Projekat NewPipe veoma ozbiljno shvata vašu privatnost. Stoga aplikacija ne prikuplja nikakve podatke bez vašeg pristanka.\nPolitika privatnosti NewPipe-a detaljno objašnjava koji se podaci šalju i pohranjuju kada pošaljete izvještaj o padu sistema. + Pročitajte politiku privatnosti + NewPipe-ova licenca + NewPipe je copyleft libre softver: Možete ga koristiti, proučavati, dijeliti i poboljšavati po volji. Konkretno, možete ga redistribuirati i/ili mijenjati pod uvjetima GNU Opće javne licence koju je objavila Fondacija za slobodni softver, bilo verzije 3 Licence ili (po vašem izboru) bilo koje kasnije verzije. + Pročitaj licencu + Često postavljana pitanja + Ako imate problema s korištenjem aplikacije, obavezno pogledajte ove odgovore na česta pitanja! + Pogledajte na web stranici + Historija + Historija + Želite li izbrisati ovu stavku iz historije pretrage? + Posljednje igrano + Najigranije + Sadržaj glavne stranice + Koje kartice se prikazuju na glavnoj stranici + Prevucite stavke da biste ih uklonili + Prazna stranica + Stranica kioska + Zadani kiosk + Stranica kanala + Odaberite kanal + Još nema pretplata na kanale + Odaberite listu za reprodukciju + Još nema oznaka za plejlistu + Odaberite kiosk + Izvezeno + Uvezeno + Nema važeće ZIP datoteke + Upozorenje: Nije moguće uvesti sve datoteke. + Ovo će poništiti vašu trenutnu postavku. + Želite li uvesti i postavke? + Nije moguće učitati komentare + Odaberite grupu feedova + Još nije kreirana nijedna grupa feedova + U trendu + Top 50 + Novo i popularno + Lokalno + Nedavno dodano + Najpopularnije + Konferencije + Red za reprodukciju + Ukloni + Detalji + Postavke zvuka + Audio: %s + Zvučni zapis + Držite za dodavanje u red + Prikaži detalje kanala + Stavi u red + Stavljeno u red čekanja + Stavi sljedeće u red + Sljedeće u redu čekanja + Počni reprodukciju u pozadini + Počnite igrati u iskačućem prozoru + Učitavanje detalja toka… + Otvori ladicu + Zatvori ladicu + Preferirana akcija \'otvaranja\' + Zadana radnja pri otvaranju sadržaja — %s + Video plejer + Pozadinski plejer + Iskačući plejer + Uvijek pitajte + Dobijanje informacija… + Učitavanje traženog sadržaja + Nova plejlista + Liste za reprodukciju koje su sive već sadrže ovu stavku. + Preimenuj + Ime + Dodaj na listu pjesama + Obrada… Može potrajati trenutak + Isključi zvuk + Uključi zvuk + Postavi kao sličicu za reprodukciju + Poništi trajnu sličicu + Označi plejlistu + Ukloni oznaku + Izbrisati ovaj popis? + Plejlista je kreirana + Plejlista + Duplikat dodan %d puta + Sličica plejliste je promijenjena. + Automatski generirano (nije pronađen korisnik koji je otpremio) + Nema titlova + Prilagođeno + Popuni + Uvećanje + Automatski generirano + Titlovi + Izmijenite veličinu teksta titlova i stilove pozadine za player. Za primjenu je potrebno ponovno pokretanje aplikacije + LeakCanary nije dostupan + Praćenje curenja memorije može uzrokovati da aplikacija prestane reagirati prilikom ispisa heap memorije + Prikaži curenje memorije + Prijavi greške izvan životnog ciklusa + Prisilno prijavljivanje izuzetaka neisporučenih Rx zahtjeva izvan životnog ciklusa fragmenta ili aktivnosti nakon odlaganja + Prikaži originalno vrijeme prije stavki + Originalni tekstovi iz usluga bit će vidljivi u stavkama toka + Onemogući tuneliranje medija + Onemogućite tuneliranje medija ako se pojavi crni ekran ili se prilikom reprodukcije videa pojavi prekid. + Tuneliranje medija je onemogućeno prema zadanim postavkama na vašem uređaju jer je poznato da vaš model uređaja to ne podržava. + Prikaži indikatore slike + Prikažite Picasso obojene trake preko slika koje označavaju njihov izvor: crvena za mrežu, plava za disk i zelena za memoriju + Prikaži \"Sruši plejer\" + Prikazuje opciju pada sistema prilikom korištenja plejera + Pokreni provjeru za nove tokove + Sruši aplikaciju + Prikaži traku s upozorenjem o grešci + Kreiraj obavještenje o grešci + Uvoz + Uvoz iz + Izvoz u + Uvoz… + Izvoz… + Uvoz datoteke + Prethodni izvoz + Nije moguće uvesti pretplate + Nije moguće izvesti pretplate + Uvoz YouTube pretplata iz Google arhive:\n\n1. Idite na ovaj URL: %1$s\n2. Prijavite se kada se to od vas zatraži\n3. Kliknite na \"Svi podaci uključeni\", zatim na \"Poništi odabir svih\", a zatim odaberite samo \"pretplate\" i kliknite na \"U redu\"\n4. Kliknite na \"Sljedeći korak\", a zatim na \"Kreiraj izvoz\"\n5. Kliknite na dugme \"Preuzmi\" nakon što se pojavi\n6. Kliknite na UVOZ DATOTEKE ispod i odaberite preuzetu .zip datoteku\n7. [Ako uvoz .zip datoteke ne uspije] Izvucite .csv datoteku (obično pod \"YouTube i YouTube Music/pretplate/pretplate.csv\"), kliknite na UVOZ DATOTEKE ispod i odaberite izvučenu csv datoteku + Uvezite SoundCloud profil unosom URL-a ili vašeg ID-a:\n\n1. Omogućite \"desktop mode\" u web pregledniku (stranica nije dostupna za mobilne uređaje)\n2. Idite na ovaj URL: %1$s\n3. Prijavite se kada se to od vas zatraži\n4. Kopirajte URL profila na koji ste preusmjereni. + tvoj ID, soundcloud.com/tvojID + Imajte na umu da ova operacija može biti skupa za mrežu.\n\nŽelite li nastaviti? + Kontrole brzine reprodukcije + Brzina + Točka glasa + Otkačite (može uzrokovati distorziju) + Premotavanje unaprijed tokom tišine + Korak + Resetuj + Postotak + Poluton + Kako bismo se pridržavali Opće uredbe o zaštiti podataka (GDPR), ovim putem skrećemo vašu pažnju na politiku privatnosti kompanije NewPipe. Molimo vas da je pažljivo pročitate.\nMorate je prihvatiti da biste nam poslali izvještaj o grešci. + Prihvati + Odbij + Bez ograničenja + Ograničenje rezolucije prilikom korištenja mobilnih podataka + Obavještenja o novim tokovima + Obavijesti me o novim tokovima s pretplata + Učestalost provjere + Potrebna mrežna veza + Bilo koja mreža + Nadogradnje + Prikaži obavještenje za podsticanje ažuriranja aplikacije kada je dostupna nova verzija + Provjeri ažuriranja + NewPipe može automatski provjeravati nove verzije s vremena na vrijeme i obavijestiti vas kada budu dostupne.\nŽelite li ovo omogućiti? + Ručno provjerite nove verzije + Minimiziraj pri prebacivanju aplikacija + Radnja prilikom prelaska na drugu aplikaciju iz glavnog video plejera — %s + Nema + Minimiziraj na pozadinski plejer + Minimiziraj da bi se player pojavio u skočnom prozoru + Automatski pokreni reprodukciju — %s + Samo na Wi-Fi mreži + Nikad + Način prikaza liste + Spisak + Rešetka + Kartica + Automatski + Pregled sličice trake za pretraživanje + Visok kvalitet (veći) + Nizak kvalitet (manji) + Ne prikazuj + Koristite najnoviju verziju NewPipe-a + Ažuriranje NewPipe-a je dostupno! + Dodirnite za preuzimanje %s + Završeno + Na čekanju + pauzirano + u redu čekanja + naknadna obrada + oporavlja se + Stavi u red + Sistem je odbio akciju + Provjera ažuriranja… + Preuzimanje nije uspjelo + Resetiraj postavke + Resetujte sve postavke na njihove zadane vrijednosti + Resetovanjem svih postavki poništit ćete sve svoje željene postavke i ponovo pokrenuti aplikaciju.\n\nJeste li sigurni da želite nastaviti? + Generiraj jedinstveno ime + Prebriši + Datoteka s ovim imenom već postoji + Preuzeta datoteka s ovim nazivom već postoji + ne može prepisati datoteku + U toku je preuzimanje s ovim imenom + Postoji preuzimanje s ovim nazivom na čekanju + Prikaži grešku + Datoteka ne može biti kreirana + Nije moguće kreirati odredišnu mapu + Nije moguće uspostaviti sigurnu vezu + Nije moguće pronaći server + Ne mogu se povezati sa serverom + Server ne šalje podatke + Server ne prihvata višenitna preuzimanja, pokušajte ponovo sa @string/msg_threads = 1 + Nije pronađeno + Naknadna obrada nije uspjela + NewPipe je zatvoren tokom rada na datoteci + Nema dovoljno slobodnog prostora na uređaju + Nema više prostora na uređaju + Napredak je izgubljen jer je datoteka izbrisana + Vremensko ograničenje veze + Nije moguće oporaviti ovo preuzimanje + Obriši historiju preuzimanja + Želite li obrisati historiju preuzimanja ili izbrisati sve preuzete datoteke? + Izbriši preuzete datoteke + Izbrisati sve preuzete datoteke s diska? + Zaustavi + Maksimalan broj ponovnih pokušaja + Maksimalan broj pokušaja prije otkazivanja preuzimanja + Prekid na mrežama s ograničenim pristupom + Korisno prilikom prelaska na mobilne podatke, iako se neka preuzimanja ne mogu obustaviti + Zatvori + Ograniči red čekanja za preuzimanje + Jedno preuzimanje će se pokrenuti istovremeno + Započni preuzimanja + Pauziraj preuzimanja + Pitaj gdje preuzeti + Bit ćete upitani gdje želite sačuvati svako preuzimanje.\nOmogućite birač sistemskih foldera (SAF) ako želite preuzeti na eksternu SD karticu + Bit ćete upitani gdje sačuvati svako preuzimanje + Koristi birač sistemskih foldera (SAF) + \'Okvir za pristup pohrani\' omogućava preuzimanje na eksternu SD karticu + Počevši od Androida 10, podržan je samo \'Storage Access Framework\' + Odaberite instancu + Jezik aplikacije + Zadano sistemsko + Ukloni gledano + Ukloniti gledane videozapise? + Ukloni duplikate + Ukloniti duplikate? + Želite li ukloniti sve duplikatne tokove na ovoj listi za reprodukciju? + Videozapisi koji su pregledani prije i poslije dodavanja na listu za reprodukciju bit će uklonjeni.\nJeste li sigurni? Ovo se ne može poništiti! + Da, i djelimično odgledani videozapisi + Zbog ograničenja ExoPlayera, trajanje pretraživanja je postavljeno na %d sekundi + Šta je novo + Stranica grupe kanala + Grupe kanala + Sažetak zadnji put ažuriran: %s + Nije učitano: %d + Učitavanje feeda… + Obrada feeda… + Nove stavke feeda + Odaberite pretplate + Nije odabrana pretplata + Prazan naziv grupe + Želite li izbrisati ovu grupu? + Novo + Prikaži samo negrupirane pretplate + Sažetak + Prag ažuriranja feeda + Vrijeme nakon posljednjeg ažuriranja prije nego što se pretplata smatra zastarjelom — %s + Uvijek ažuriraj + Greška pri učitavanju feeda + Nije moguće učitati feed za \'%s\'. + Autorov račun je ukinut. \nNewPipe ubuduće neće moći učitavati ovaj sažetak. \nŽeliš li ukinuti pretplatu za ovaj kanal? + Režim brzog hranjenja ne pruža više informacija o ovome. + Preuzmi iz namjenskog feeda kada je dostupan + Dostupno u nekim servisima, obično je mnogo brže, ali može vratiti ograničen broj artikala i često nepotpune informacije (npr. bez trajanja, vrste artikla, bez aktivnog statusa) + Omogući brzi način rada + Onemogući brzi način rada + Mislite li da je učitavanje feeda previše sporo? Ako je tako, pokušajte omogućiti brzo učitavanje (možete ga promijeniti u postavkama ili pritiskom na dugme ispod).\n\nNewPipe nudi dvije strategije učitavanja feeda:\n• Preuzimanje cijelog pretplatničkog kanala, što je sporo, ali potpuno.\n• Korištenje namjenske krajnje tačke usluge, što je brzo, ali obično nije potpuno.\n\nRazlika između ove dvije je u tome što brza obično nema neke informacije, poput trajanja ili vrste stavke (ne može razlikovati videozapise uživo od normalnih) i može vratiti manje stavki.\n\nYouTube je primjer usluge koja nudi ovu brzu metodu sa svojim RSS feedom.\n\nDakle, izbor se svodi na to šta preferirate: brzinu ili precizne informacije. + Prikaži sljedeće tokove + Prikaži/Sakrij tokove + Dohvati kartice kanala + Kartice koje treba preuzeti prilikom ažuriranja feeda. Ova opcija nema efekta ako se kanal ažurira pomoću brzog načina rada. + Ovaj sadržaj još uvijek nije podržan od strane NewPipe-a.\n\nNadamo se da će biti podržan u budućoj verziji. + Sličica avatara kanala + Kreirao/la %s + Napisao %s + Stranica s popisom za reprodukciju + Prikaži sličicu + Koristite sličicu i za pozadinu zaključanog ekrana i za obavještenja + Nedavno + Poglavlja + Nijedna aplikacija na vašem uređaju ne može ovo otvoriti + Nije pronađen odgovarajući upravitelj datoteka za ovu radnju.\nMolimo instalirajte upravitelj datoteka ili pokušajte onemogućiti \'%s\' u postavkama preuzimanja + Nije pronađen odgovarajući upravitelj datoteka za ovu radnju.\nMolimo instalirajte upravitelj datoteka kompatibilan sa Storage Access Frameworkom + Ovaj sadržaj nije dostupan u vašoj zemlji. + Ovo je pjesma na SoundCloud Go+ platformi, barem u vašoj zemlji, tako da je NewPipe ne može strimovati ili preuzeti. + Ovaj sadržaj je privatan, tako da ga NewPipe ne može strimovati ili preuzimati. + Ovaj video je dostupan samo članovima YouTube Music Premium-a, tako da ga NewPipe ne može strimovati ili preuzeti. + Račun ukinut + Račun ukinut\n\n%1$s navodi ovaj razlog: %2$s + Ovaj sadržaj je dostupan samo korisnicima koji su platili, tako da ga NewPipe ne može strimovati ili preuzimati. + Istaknuto + Radio + Automatski (tema uređaja) + Odaberite svoju omiljenu noćnu temu — %s + Možete odabrati svoju omiljenu noćnu temu ispod + Ova opcija je dostupna samo ako je za temu odabrana %s + Preuzimanje je počelo + Sada možete odabrati tekst unutar opisa. Imajte na umu da stranica može treperiti i da linkovi možda neće biti dostupni za klikanje dok ste u načinu odabira. + Omogući odabir teksta u opisu + Onemogući odabir teksta u opisu + Kategorija + Oznake + Dozvola + Privatnost + Starosna granica + Jezik + Podrška + Domaćin + Sličice + Avatari koji su postavili profil + Avatari podkanala + Avatari + Baneri + Javno + Nije navedeno + Privatno + Unutrašnje + Pretplatnici + Zakačen komentar + Srce od strane kreatora + Otvori web stranicu + Tabletni način rada + Upaljeno + Ugašeno + Zadano za ExoPlayer + Obavještenja su onemogućena + Primajte obavještenja + Sada ste pretplaćeni na ovaj kanal + , + Prikaži/Uključi sve + Strimovi koje program za preuzimanje još ne podržava nisu prikazani + Zvučni zapis bi već trebao biti prisutan u ovom toku + Odabrani tok nije podržan od strane eksternih plejera + Nema dostupnih audio tokova za vanjske uređaje za reprodukciju + Nema video tokova dostupnih za vanjske uređaje za reprodukciju + Odaberite kvalitet za vanjske uređaje za reprodukciju + Odaberite audio zapis za vanjske uređaje za reprodukciju + Nepoznati format + Nepoznat kvalitet + Nepoznato + Potpuno odgledano + Djelomično gledano + Nadolazeći + Sortiraj + Postavke ExoPlayera + Upravljajte nekim postavkama ExoPlayera. Ove promjene zahtijevaju ponovno pokretanje plejera da bi stupile na snagu + Koristite ExoPlayer-ovu rezervnu funkciju dekodera + Omogućite ovu opciju ako imate problema s inicijalizacijom dekodera, koja se vraća na dekodere nižeg prioriteta ako inicijalizacija primarnih dekodera ne uspije. Ovo može rezultirati lošijim performansama reprodukcije nego kada se koriste primarni dekoderi + Uvijek koristite ExoPlayer-ovo rješenje za podešavanje površine video izlaza + Ovo zaobilazno rješenje oslobađa i ponovo instancira video kodeke kada dođe do promjene površine, umjesto direktnog postavljanja površine na kodek. Već korištena od strane ExoPlayera na nekim uređajima s ovim problemom, ova postavka ima učinak samo na Androidu 6 i novijim verzijama.\n\nOmogućavanje ove opcije može spriječiti greške u reprodukciji prilikom prebacivanja trenutnog video playera ili prelaska na cijeli ekran + %1$s %2$s + original + sinhronizovano + opisni + sekundarni + Videozapisi + Snimke + Kratke hlače + Uživo + Kanali + Plejliste + Albuma + Sviđanja + O tome + Kartice kanala + Koje kartice se prikazuju na stranicama kanala + Otvori red za reprodukciju + Prikaz preko cijelog ekrana + Uključi/isključi orijentaciju ekrana + Prethodni tok + Sljedeći tok + Pokrenuti + Ponovna reprodukcija + Više opcija + Trajanje + Premotavanje unazad + Naprijed + Kvalitet slike + Odaberite kvalitet slika i da li će se slike uopće učitavati kako biste smanjili potrošnju podataka i memorije. Promjene brišu keš memoriju slika i u memoriji i na disku — %s + Ne učitavaj slike + Niska kvaliteta + Srednji kvalitet + Visoka kvaliteta + \? + Dijeli plejlistu + Podijeli s naslovima + Podijeli listu URL-ova + Podijeli kao privremenu YouTube plejlistu + - %1$s: %2$s + %1$s\n%2$s + Prikaži više + Prikaži manje + Postavke u izvozu koji se uvozi koriste ranjivi format koji je zastario od verzije NewPipe 0.27.0. Provjerite da izvoz koji se uvozi dolazi iz pouzdanog izvora i u budućnosti preferirajte korištenje samo izvoza dobivenih iz NewPipe 0.27.0 ili novije verzije. Podrška za uvoz postavki u ovom ranjivom formatu uskoro će biti potpuno uklonjena, a zatim stare verzije NewPipe-a više neće moći uvoziti postavke izvoza iz novih verzija. + Stranica SoundCloud Top 50 uklonjena + SoundCloud je ukinuo originalne Top 50 liste. Odgovarajuća kartica je uklonjena sa vaše glavne stranice. + Uklonjen je kombinovani prikaz trendova na YouTubeu + Trendovi u igrama + Trendovi podcasti + Popularni filmovi i serije + Popularna muzika + Unos izbrisan + HTTP greška 403 primljena od servera tokom reprodukcije, vjerovatno uzrokovana istekom URL-a za tokove ili zabranom IP adrese + HTTP greška %1$s primljena od servera tokom reprodukcije + HTTP greška 403 primljena od servera tokom reprodukcije, vjerovatno uzrokovana zabranom IP adrese ili problemima s deobfuskacijom URL-a za tokove + %1$s je odbio dati podatke, tražeći prijavu kako bi potvrdio da podnosilac zahtjeva nije bot.\n\nVašu IP adresu je možda privremeno zabranio %1$s, možete pričekati neko vrijeme ili preći na drugu IP adresu (na primjer uključivanjem/isključivanjem VPN-a ili prelaskom s WiFi-ja na mobilne podatke). + + %s pretplatnik + %s pretplatnika + %s pretplatnika + + + %s pregled + %s pregleda + %s pregleda + + + %s gledatelj + %s gledatelja + %s gledatelja + + + %s slušatelj + %s slušatelja + %s slušatelja + + + %s video + %s videozapisa + %s videozapisa + + + %s novi tok + %s nova toka + %s novih tokova + + O aplikaciji i pitanja + + %s preuzimanje je gotovo + %s preuzimanja su gotova + %s preuzimanja je gotovo + + + Izbrisano %1$s preuzimanje + Izbrisana %1$s preuzimanja + Izbrisano %1$s preuzimanja + + + %d sekunda + %d sekunde + %d sekundi + + + %d minut + %d minute + %d minuta + + + %d sat + %d sata + %d sati + + + %d dan + %d dana + %d dana + + + %d odabrana + %d odabrane + %d odabranih + + + %s odgovor + %s odgovora + %s odgovora + + YouTube je ukinuo kombinovanu stranicu s trendovima od 21. jula 2025. NewPipe je zamijenio zadanu stranicu s trendovima s trendovima uživo prijenosa.\n\nTakođer možete odabrati različite stranice s trendovima u \"Postavke > Sadržaj > Sadržaj glavne stranice\". + Ovaj sadržaj nije dostupan za trenutno odabranu zemlju sadržaja.\n\nPromijenite svoj odabir u \"Postavke > Sadržaj > Zadana zemlja sadržaja\". + diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index dadac3c3f..ff12819f5 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -215,7 +215,7 @@ Controls de la velocitat de reproducció Tempo To - Toca \"Cerca\" per començar. + Toqueu la lupa per començar. Elimina l\'àudio en algunes resolucions Reproductor d\'àudio extern Emmagatzema les cerques localment @@ -508,10 +508,9 @@ %d segons A causa de les limitacions d\'ExoPlayer, la durada de cerca és de %d segons - Sí, i també els vídeos vistos parcialment - Els vídeos que ja heu vist tant abans com després d\'haver estat afegits a la llista de reproducció seran suprimits. -\nN\'esteu segurs\? Aquesta acció no pot desfer-se! - Esborrar els vídeos ja vistos\? + Sí, i també els vídeos vistos parcialment + Els vídeos que ja heu vist tant abans com després d\'haver estat afegits a la llista de reproducció seran suprimits. \nN\'esteu segurs? Aquesta acció no pot desfer-se! + Esborrar els vídeos ja vistos? Esborra els ja vistos Valors per defecte Llengua de l\'aplicació diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index f0ddfb6e9..d448c1118 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -191,8 +191,7 @@ باشترین ٥٠ تەنها بەستەرەکانی https پشتگیریکراون پەیوەستبوونی پارێزراو هه‌ره‌سی هێنا - ئەو ڤیدیۆیانەی پێشتر سەیرت کردوون و دواتر زیادت کردوون بۆ خشتەلێدان لادەدرێن. -\nئایا دڵنیایت؟ ئەمە ناگەڕێنرێتەوە! + ئەو ڤیدیۆیانەی پێشتر سەیرت کردوون و دواتر زیادت کردوون بۆ خشتەلێدان لادەدرێن. \nئایا دڵنیایت؟ ئەمە ناگەڕێنرێتەوە! وێنۆچکەی سه‌روێنه‌ی کەناڵ دەتەوێت ڕێکخستنەکانیش هاوردە بكرینه‌وه‌؟ هیچ لێدەرێکی ڤیدیۆیی نه‌دۆزرایه‌وه‌. ده‌ته‌وێت VLC دابمەزرێنیت؟ @@ -350,7 +349,7 @@ په‌نجه‌ڕاگرتن له‌سه‌ری بۆ نۆبه‌ت نه‌بوون زۆرترین ژمارەی هەوڵدان پێش پاشگەزبوونەوە لە دابەزاندنەکە هەڵه‌ - بەڵێ، لەگەڵ ڤیدیۆ سەیر کراوەکانەوە + بەڵێ، لەگەڵ ڤیدیۆ سەیر کراوەکانەوە دەستپێکردنی لێدان لە پەنجەرەوه‌ نابەدڵه‌كان مێژوو diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 756cf17cf..ce64e46db 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -486,7 +486,7 @@ Prázdné jméno skupiny Přejete si odstranit tuto skupinu? - Nová + Nový Novinky Limit aktualizace novinek Doba po poslední aktualizaci, po níž je odběr považován za zastaralý — %s @@ -517,11 +517,10 @@ Toto video má věkové omezení. \n \nPokud jej chcete vidět, povolte „%1$s“ v nastavení. - Ano, i zčásti zhlédnutá videa + Ano, i zčásti zhlédnutá videa Odstranit zhlédnutá videa? Odstranit zhlédnutá - Videa, která jste zhlédli před a po jejich přidání do playlistu, budou odstraněna. -\nJste se jisti? Tato akce je nevratná! + Videa, která jste zhlédli před a po jejich přidání do playlistu, budou odstraněna. \nJste se jisti? Tato akce je nevratná! Původní texty služeb budou viditelné u položek streamů U položek zobrazit původní čas Zapnout „Omezený režim“ YouTube @@ -719,7 +718,7 @@ Klepnutím stáhnete %s Rychlý režim Používáte nejnovější verzi NewPipe - Import nebo export odběrů z 3-tečkové nabídky + Importujte nebo exportujte odběry z 3tečkové nabídky Tato možnost je dostupná pouze při vybraném motivu %s Zrušení nastavení trvalého náhledu Karta @@ -844,4 +843,24 @@ Líbí se Stránka SoundCloud Top 50 odstraněna SoundCloud zrušil původní žebříčky Top 50. Příslušná karta byla odstraněna z vaší hlavní stránky. + YouTube kombinované trendy odstraněny + YouTube ukončil provoz kombinované stránky s trendy k 21. červenci 2025. NewPipe nahradil výchozí stránku s trendy stránkou s trendy živými přenosy.\n\nMůžete také vybrat různé stránky s trendy v části „Nastavení > Obsah > Obsah úvodní stránky“. + Populární hry + Populární podcasty + Populární filmy a seriály + Populární hudba + %s tis. + %s mil. + %s mld. + Pro používání Popup Playeru vyberte v následující nabídce nastavení Androidu možnost %1$s a povolte %2$s. + \"Povolit zobrazení přes jiné aplikace\" + Vymazat soubor + Vymazat položku + Položka vymazána + Ukončení účtu\n\n%1$s uvádí tento důvod: %2$s + Během přehrávání byla ze serveru přijata chyba HTTP 403, pravděpodobně způsobená vypršením platnosti streamingové adresy URL nebo zákazem IP adresy + Chyba HTTP %1$s obdržená ze serveru během přehrávání + Chyba HTTP 403 obdržená od serveru během přehrávání, pravděpodobně způsobená zákazem IP adresy nebo problémy s deobfuskací streamovací adresy URL + %1$s odmítl poskytnout data, žádá o přihlášení k potvrzení, že žadatel není bot.\n\nVaše IP adresa mohla být dočasně zakázána %1$s, můžete nějakou dobu počkat nebo přepnout na jinou IP adresu (například zapnutím/vypnutím VPN nebo přepnutím z WiFi na mobilní data). + Tento obsah není pro aktuálně vybranou zemi obsahu dostupný.\n\nZměňte výběr v nabídce \"Nastavení > Obsah > Výchozí země obsahu\". diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 5354bb7ad..f3a25e3b7 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -232,7 +232,7 @@ Mest Afspillet Indhold af hovedside Hvilke faner vises på hovedsiden - Tom Side + Tom side Kioskside Kanalside Vælg en kanal @@ -523,7 +523,7 @@ gendanner \"Hurtig feed\"-tilstand oplyser ikke mere info om dette. Tjek efter opdateringer - Fjern sete videoer\? + Fjern sete videoer? Deaktivér medietunneling, hvis du oplever en sort skærm eller hakken ved videoafspilning. Tjek venligst, om der allerede findes et problem, der diskuterer dit nedbrud. Når du opretter flere tickets, tager du tid fra os, som vi kunne bruge på at løse den faktiske fejl. Tjek efter nye streams @@ -541,8 +541,7 @@ Vælg abonnementer Dette indhold er ikke tilgængeligt i dit land. Af %s - Videoer, der er blevet set før og efter tilføjelse til playlisten, vil blive fjernet. -\nEr du sikker? Dette kan ikke fortrydes! + Videoer, der er blevet set før og efter tilføjelse til playlisten, vil blive fjernet. \nEr du sikker? Dette kan ikke fortrydes! Vis miniaturebillede Tags Aldersbegrænsning @@ -630,7 +629,7 @@ Ingen app på din enhed kan åbne dette Ingen ledig plads på enheden App-sprog - Ja, og delvist sete videoer + Ja, og delvist sete videoer Fejl ved indlæsning af feed Kunne ikke indlæse feed for \'%s\'. Vis \"Crash afspilleren\" @@ -825,4 +824,20 @@ Kanalgruppeside Vælg en feed-gruppe Ingen feed-gruppe oprettet endnu + Søg %1$s + Søg %1$s (%2$s) + For at kunne bruge pop op-afspilleren skal du vælge %1$s i følgende Android-indstillingsmenu og aktivere %2$s. + “Tillad visning over andre apps” + %sK + %sM + %sB + Slet fil + Kontoen er blevet lukket\n\n%1$s angiver følgende årsag: %2$s + Likes + SoundCloud Top 50-siden fjernet + SoundCloud har udfaset de oprindelige Top 50-hitlister. Den tilhørende fane er blevet fjernet fra din hovedside. + YouTube kombineret trending fjernet + YouTube har udfaset den kombinerede trending-side pr. 21. juli 2025. NewPipe har erstattet standardsiden for trending med trending livestreams.\n\nDu kan også vælge andre trending-sider under \"Indstillinger > Indhold > Indhold på hovedsiden\". + Gaming-trends + Trending podcasts diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b99209f0f..b07151585 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -516,11 +516,10 @@ Dieses Video ist altersbeschränkt. \n \nAktiviere in den Einstellungen „%1$s“, falls du diese sehen möchtest. - Videos, die vor und nach dem Hinzufügen zur Wiedergabeliste angeschaut wurden, werden entfernt. -\nBist du sicher\? Dies kann nicht rückgängig gemacht werden! - Ja, und teilweise gesehene Videos + Videos, die vor und nach dem Hinzufügen zur Wiedergabeliste angeschaut wurden, werden entfernt. \nBist du sicher? Dies kann nicht rückgängig gemacht werden! + Ja, und teilweise gesehene Videos Gesehene entfernen - Gesehene Videos entfernen\? + Gesehene Videos entfernen? Originalzeit vor Elementen anzeigen Originaltexte von Diensten werden in Stream-Elementen sichtbar sein YouTubes „Eingeschränkten Modus“ aktivieren @@ -830,4 +829,24 @@ Gefällt mir SoundCloud-Top-50-Seite entfernt SoundCloud hat die ursprünglichen Top-50-Charts abgeschafft. Der entsprechende Tab wurde von deiner Hauptseite entfernt. + %sMio. + %sMrd. + %sTsd. + Gaming-Trends + Beliebte Filme und Shows + Beliebte Musik + Beliebte Podcasts + YouTube hat die kombinierten „beliebten Seiten“ entfernt + YouTube hat die kombinierte Trending-Seite ab dem 21. Juli 2025 eingestellt. NewPipe hat die Standard-Trending-Seite durch die Trending-Livestreams ersetzt.\n\nDu kannst auch verschiedene Trendseiten unter „Einstellungen > Inhalt > Inhalt der Hauptseite“ auswählen. + Um den Pop-up-Player zu verwenden, bitte in den folgenden Android-Einstellungen %1$s auswählen und %2$s aktivieren. + „Über anderen Apps einblenden“ + Datei löschen + Eintrag löschen + Eintrag gelöscht + Konto geschlossen\n\n%1$s gibt folgenden Grund an: %2$s + HTTP-Fehler 403 vom Server während der Wiedergabe erhalten, wahrscheinlich verursacht durch Ablauf der Streaming-URL oder eine IP-Sperre + HTTP-Fehler %1$s vom Server während der Wiedergabe erhalten + HTTP-Fehler 403 vom Server während der Wiedergabe erhalten, wahrscheinlich verursacht durch eine IP-Sperre oder Probleme beim Entschlüsseln der Streaming-URL + %1$s hat die Datenbereitstellung verweigert und verlangt eine Anmeldung, um zu bestätigen, dass es sich bei dem Anfragenden nicht um einen Bot handelt.\n\nDeine IP-Adresse wurde möglicherweise vorübergehend von %1$s gesperrt. Du kannst einige Zeit warten oder zu einer anderen IP-Adresse wechseln (z. B. durch Ein- und Ausschalten eines VPNs oder durch Wechseln von WLAN zu mobilen Daten). + Dieser Inhalt ist für das aktuell ausgewählte Land des Inhalts nicht verfügbar.\n\nÄndere die Auswahl unter „Einstellungen > Inhalt > Bevorzugtes Land des Inhalts“. diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 5cb645bfa..7c23666d5 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -524,9 +524,8 @@ %d δευτερόλεπτα Λόγω περιορισμών του ExoPlayer, η διάρκεια αναζήτησης ορίστηκε στα %d δευτερόλεπτα - Ναι. Και τα μερικώς θεαθέντα βίντεο - Τα βίντεο που εθεάθησαν πριν και αφού προστέθηκαν στη λίστα αναπαραγωγής θα απομακρυνθούν -\nΕίστε σίγουρος; Δεν μπορεί να αναιρεθεί! + Ναι. Και τα μερικώς θεαθέντα βίντεο + Τα βίντεο που εθεάθησαν πριν και αφού προστέθηκαν στη λίστα αναπαραγωγής θα απομακρυνθούν \nΕίστε σίγουρος; Δεν μπορεί να αναιρεθεί! Απομάκρυνση θεαθέντων βίντεο; Απομάκρυνση όσων θεάθησαν Γλώσσα εφαρμογής @@ -827,7 +826,27 @@ Σελίδα καναλιού ομάδας Αναζήτηση %1$s Αναζήτηση %1$s (%2$s) - Likes + Μου αρέσει Η σελίδα των SoundCloud Top 50 αφαιρέθηκε Το SoundCloud έχει καταργήσει τα αρχικά charts με τα Top 50. Η αντίστοιχη καρτέλα έχει αφαιρεθεί από την κύρια σελίδα σας. + Οι συνδυασμένες τάσεις στο YouTube καταργήθηκαν + Το YouTube έχει καταργήσει τη συνδυασμένη σελίδα με τάσεις από την 21 Ιουλίου 2025. Το NewPipe αντικατέστησε την προεπιλεγμένη σελίδα τάσεων με τις ζωντανές ροές τάσεων.\n\nΜπορείτε επίσης να επιλέξετε διαφορετικές σελίδες με τάσεις στις \"Ρυθμίσεις > Περιεχόμενο > Περιεχόμενο κύριας σελίδας\". + Τάσεις παιχνιδιών + Τάσεις podcasts + Τάσεις ταινιών και εκπομπών + Μουσικές τάσεις + %sK + %sM + %sB + Για να χρησιμοποιήσετε το Αναδυόμενο Πρόγραμμα Αναπαραγωγής, επιλέξτε %1$s στο ακόλουθο μενού ρυθμίσεων Android και ενεργοποιήστε το %2$s. + «Να επιτρέπεται η εμφάνιση πάνω από άλλες εφαρμογές» + Διαγραφή αρχείου + Διαγραφή καταχώρησης + Η καταχώρηση διαγράφηκε + Ο λογαριασμός έκλεισε\n\n%1$s παρέχει αυτήν την αιτία: %2$s + Σφάλμα HTTP 403 που ελήφθη από τον διακομιστή κατά την αναπαραγωγή, πιθανώς λόγω λήξης διεύθυνσης URL ροής ή αποκλεισμού IP + Σφάλμα HTTP %1$s ελήφθη από τον διακομιστή κατά την αναπαραγωγή + Σφάλμα HTTP 403 ελήφθη από τον διακομιστή κατά την αναπαραγωγή, πιθανώς λόγω αποκλεισμού IP ή προβλημάτων απεμπλοκής URL ροής + Ο %1$s αρνήθηκε να παράσχει δεδομένα, ζητώντας σύνδεση για να επιβεβαιώσει ότι ο αιτών δεν είναι bot.\n\nΗ IP σας ενδέχεται να έχει αποκλειστεί προσωρινά από τον %1$s. Μπορείτε να περιμένετε λίγο ή να αλλάξετε IP (για παράδειγμα, ενεργοποιώντας/απενεργοποιώντας ένα VPN ή αλλάζοντας από WiFi σε δεδομένα κινητής τηλεφωνίας). + Αυτό το περιεχόμενο δεν είναι διαθέσιμο για την τρέχουσα επιλεγμένη χώρα περιεχομένου.\n\nΑλλάξτε την επιλογή σας από \"Ρυθμίσεις > Περιεχόμενο > Προεπιλεγμένη χώρα περιεχομένου\". diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 8b022bcff..1a80eefd9 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -84,4 +84,14 @@ Okay Open in browser No stream player found (you can install VLC to play it). + Yes + No + Mark as watched + Open in popup mode + Open with + Share + Download + Download stream file + Search + Settings diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 3dde69618..cc42c0426 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -612,5 +612,5 @@ Filmetoj Filmetoj kiuj spektiĝis antaŭ aŭ post sia aldoniĝo al la ludlisto foriĝus.. \nĈu vi certas? Ĉi tio nemalfareblus! Restarigi implicitajn agordojn - Jes, kaj ankaŭ parte spektitajn filmetojn + Jes, kaj ankaŭ parte spektitajn filmetojn diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c88da0a2f..a2ab5ca52 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -512,10 +512,9 @@ Álbumes Canciones Este vídeo tiene restricción de edad. \n \nHabilitar \"%1$s\" en los ajustes si quieres verlo. - Sí, y también vídeos vistos parcialmente - Los vídeos que ya se hayan visto luego de añadidos a la lista de reproducción, serán quitados. -\n¿Estás seguro\? ¡Esta acción no se puede deshacer! - ¿Quitar vídeos ya vistos\? + Sí, y también vídeos vistos parcialmente + Los vídeos que ya se hayan visto luego de añadidos a la lista de reproducción, serán quitados. \n¿Estás seguro? ¡Esta acción no se puede deshacer! + ¿Quitar vídeos ya vistos? Quitar vídeos ya vistos Por %s Creado por %s @@ -829,4 +828,29 @@ Selecciona un grupo de feed Aún no se ha creado ningún grupo de feed Página de grupo de canales + Buscar %1$s + Buscar %1$s (%2$s) + Me gusta + Página Top 50 de SoundCloud eliminada + SoundCloud ha descontinuado las listas originales del Top 50. La pestaña correspondiente se ha eliminado de la página principal. + YouTube tendencias combinadas eliminado + YouTube ha descontinuado la página de tendencias combinadas a partir del 21 de julio de 2025. NewPipe reemplazó la página de tendencias predeterminada con tendencias en directo.\n\nTambién puedes seleccionar diferentes páginas de tendencias en \"Ajustes > Contenido > Contenido de la página principal\". + Tendencias videojuegos + Tendencias pódcasts + Tendencias películas y programas + Tendencias música + “Permitir mostrar sobre otras aplicaciones” + Eliminar archivo + %sM + %sM + Eliminar entrada + Cuenta cancelada\n\n%1$s proporciona esta razón: %2$s + Entrada eliminada + Error HTTP 403 recibido del servidor durante la reproducción, probablemente causado por la expiración de la URL de transmisión o una prohibición de IP + Error HTTP %1$s recibido del servidor durante la reproducción + Error HTTP 403 recibido del servidor durante la reproducción, probablemente causado por una prohibición de IP o problemas de desofuscación de la URL de transmisión + %1$s se negó a proporcionar datos y solicitó un inicio de sesión para confirmar que el solicitante no es un bot.\n\nEs posible que tu IP haya sido bloqueada temporalmente por %1$s. Puedes esperar un tiempo o cambiar a una IP diferente (por ejemplo, habilitando o deshabilitando una VPN, o cambiando de WiFi a datos móviles). + %sMM + Este contenido no está disponible para el país seleccionado actualmente.\n\nCambia tu selección en «Ajustes > Contenido > País predefinido del contenido». + Para usar el reproductor emergente, seleccione %1$s en el siguiente menú de la configuración de Android y habilite %2$s. diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index dc9643678..0ede00587 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -530,10 +530,9 @@ %d sekund %d sekundit - Sellega eemaldame vaadatud videod ja esitusloendisse lisatud videod. -\nKas sa oled kindel\? Seda tegevust ei saa hiljem tagasi pöörata! - Jah, sealhulgas videod, mille vaatmine jäi pooleli - Kas eemaldame vaadatud videod\? + Sellega eemaldame vaadatud videod ja esitusloendisse lisatud videod. \nKas sa oled kindel? Seda tegevust ei saa hiljem tagasi pöörata! + Jah, sealhulgas videod, mille vaatmine jäi pooleli + Kas eemaldame vaadatud videod? Eemalda vaadatud videod Kasuta süsteemi keelt Rakenduse keel @@ -603,7 +602,7 @@ Hangi võimalusel spetsiaalsest voost Kiirvoo režiim ei paku selle kohta täiendavat teavet. Autori konto on suletud. \nTulevikus ei saa NewPipe seda meediavoogu laadida. \nKas soovid tühistada selle kanali tellimuse? - Voo \'%s\' laadimine nurjus. + Voo \'%s\' laadimine ei õnnestnud. Via voo laadimisel Värskenda alati Aeg pärast viimast värskendust, mille möödudes loetakse tellimus aegunuks — %s @@ -815,4 +814,24 @@ Meeldimisi SoundCloudi „Top 50“ leht on eemaldatud SoundCloud on lõpetanud oma algse „Top 50“ edetabeli pidamise. Seega on ka vastav vahekaart meie rakenduse põhivaatest eemaldatud. + YouTube\'i kombineeritud populaarsust koguvad videovoog on eemaldatud + YouTube on alates 21.07.25 lõpetanud ühendatud populaarsust koguvate videote lehe kasutamise. Mistõttu ka NewPipe on asendanud vaikimisi populaarsust koguvate videote lehe sarnase otse-eetri lehega.\n\n„Seadistused -> Sisu -> Avalehe sisu“ alt saad ka muid sarnaseid lehti seadistada. + Populaarsust koguvad taskuhäälingud + Populaarsust koguvad filmid ja telesarjad + Populaarsust koguv muusika + Populaarsust koguvad mängud + %s tuh + %s mln + %s mld + Kasutamaks meediaesitajat hüpikaknas palun vali järgnevast Androidi seadistuste valikust „%1$s“ ja lülita sisse „%2$s“. + Luba kuvamine teiste rakenduste peal + Kustuta fail + Kustuta kirje + Kirje on kustutatud + Kasutajakonto on suletud\n\n%1$s on märkinud põhjuseks: %2$s + Esitamise ajal lisas server andmevoogu HTTP oleku 403 ning tavaliselt tähendab see, et voogedastuse võrguaadress on aegunud või sinu seadme IP-aadress on keelatud + Esitamise ajal lisas server andmevoogu HTTP oleku %1$s + Esitamise ajal lisas server andmevoogu HTTP oleku 403 ning tavaliselt tähendab see, et sinu seadme IP-aadress on keelatud või voogedastuse võrguaadressi hägustamisvastastes meetmetes on viga + See sisu pole saadaval hetkel kehtvas riigis.\n\nRiiki saad muuta: Seadistused > Sisu > Sisu vaikimisi riik. + %1$s keeldus andmete edastamisest ning eeldab sisselogimist tuvastamaks, et tegemist pole robotiga.\n\nLisaks võib olla juhtunud, et %1$s on lisanud sinu seadme ip-aadressi ajutisse keelunimekirja. Sa võid oodata natuke aega või vahetada võrguühendus viisi (näiteks lülitades VPN sisse/välja või kasutades WiFi asemel mobiilset internetiühendust). diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 5c963d6b7..dc2fefa21 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -10,32 +10,32 @@ Ezarpenak Partekatu honekin Bideoak deskargatzeko karpeta - Deskargatutako bideoak hemen gordeko dira - Aukeratu bideoak deskargatzeko karpeta + Deskargatutako bideoak hemen gordetzen dira + Aukeratu bideo-fitxategien deskarga karpeta Lehenetsitako bereizmena - Jo Kodirekin + Erreproduzitu Kodi-rekin Falta den Kore aplikazioa instalatu nahi duzu? - Erakutsi \"Jo Kodirekin\" aukera - Erakutsi bideoa Kodi multimedia zentroarekin erreproduzitzeko aukera + Erakutsi «Erreproduzitu Kodi-rekin» aukera + Erakutsi bideoa Kodi multimedia zentroarekin erreproduzitzeko aukera bat Audioa Audio formatu lehenetsia Deskargatu Erakutsi \'hurrengo\' eta \'antzeko\' bideoak - URLak ez du euskarririk - Edukiaren hizkuntz lehenetsia + Ez da URLa onartzen + Edukiaren hizkuntza lehenetsia Bideoa eta audioa Erreproduzitu bideoa, iraupena: - Igotzailearen abatarraren iruditxoa - Ez dute gustoko - Gustoko dute + Igotzailearen abatarraren miniatura + Desatseginak + Atseginak Ez da igorpen-erreproduzigailurik aurkitu. VLC instalatu? \"%1$s\" esan nahi al zenuen\? - Erabili kanpo bideo-erreproduzigailua - Erabili kanpo audio-erreproduzigailua + Erabili kanpo bideo-erreproduzitzailea + Erabili kanpo audio-erreproduzitzailea Atzeko planoan erreproduzitzen Sakatu lupan hasteko. Audioa deskargatzeko karpeta - Aukeratu audio fitxategiak deskargatzeko karpeta + Aukeratu audio-fitxategien deskarga karpeta Deskargatutako audio fitxategiak hemen gordetzen dira Iluna Argia @@ -45,15 +45,15 @@ Bigarren planoa Laster-leihoa Laster-leihoaren lehenetsitako bereizmena - Erakutsi bereizmen altuagoak - Bakarrik gailu batzuk onartzen dituzte 2K/4K bideoak erreproduzitzea - Hobetsitako bideo-formatua + Erakutsi bereizmen handiagoak + Gailu batzuek soilik erreproduzitu ditzakete 2K/4K bideoak + Lehenetsitako bideo-formatua Gaia Beltza - Gogoratu laster-leihoaren tamaina eta posizioa + Gogoratu laster-leihoaren propietateak Gogoratu laster-leihoaren azken tamaina eta posizioa Bilaketa-iradokizunak - Bilatzean erakutsi beharreko iradokizunak aukeratu + Aukeratu bilaketak egitean erakutsiko diren iradokizunak Laster-leiho moduan erreproduzitzen Edukia Adinez mugatutako edukia erakutsi @@ -67,18 +67,18 @@ Bereizmen onena Errorea Sare-errorea - Ezin izan dira iruditxo guztiak deskargatu + Ezin izan dira miniatura guztiak kargatu Ezin izan da webgunea analizatu Edukia ez dago eskuragarri Ezin izan da deskargen menua ezarri - Aplikazioa/interfazea kraskatu da + Aplikazioa/EIa kraskatu da Hori ez litzateke gertatu behar. Eman honen berri e-posta bidez Barkatu, zerbait gaizki atera da. Salatu Informazioa: Zer gertatu da: - Zer:\\nEskaria:\\nEdukiaren hizkuntza:\\nEdukiaren herrialdea:\\nAplikazioaren hizkuntza:\\nZerbitzua:\\nGMT Ordua:\\nPaketea:\\nBertsioa:\\nSE bertsioa: + Zer:\\nEskaria:\\nEdukiaren hizkuntza:\\nEdukiaren herrialdea:\\nAplikazioaren hizkuntza:\\nZerbitzua:\\nDenbora-zigilua:\\nPaketea:\\nBertsioa:\\nSE bertsioa: Zure iruzkina (Ingelesez): Xehetasunak: Bideoa @@ -93,7 +93,7 @@ Hariak Errorea NewPipe deskargatzen - Ukitu xehetasunetarako + Sakatu xehetasunetarako Itxaron mesedez… Arbelera kopiatuta Ezarri deskargetarako karpeta bat ezarpenetan geroago @@ -101,17 +101,17 @@ \nlaster-leiho moduan irekitzeko
reCAPTCHA erronka reCAPTCHA erronka eskatu da - NewPipe aplikazioari buruz - Hirugarrengoen lizentziak - © %1$s %2$s. %3$s + NewPipe-i buruz + Hirugarrenen lizentziak + © %1$s %2$s-(r)engatik, %3$s lizentziapean Honi buruz eta ohiko galderak Lizentziak Igorpen libre eta arinak Android-en. - Ikusi GitHub zerbitzarian - NewPipe Lizentzia - Ideiak, itzulpenak, diseinu aldaketak, kode garbiketak, kode aldaketa sakonak badituzu, laguntza beti da ongi etorria. Eginaz hobetzen da! + Ikusi GitHub-en + NewPipe-en lizentzia + Itzulpen, diseinu aldaketa, kode garbiketa edo kode aldaketa sakonak bezalako ideiak badituzu, laguntza beti da ongi etorria. Zenbat eta gehiago egin, orduan eta hobeto! Irakurri lizentzia - Hartu parte + Lagundu Harpidetu Harpidetuta Kanaletik harpidetza kenduta @@ -119,8 +119,8 @@ Ezin izan da harpidetza eguneratu Harpidetzak Zer dago berri - Jarraitu erreprodukzioa - Jarraitu etenaldiak eta gero (adib. telefono deiak) + Berrekin erreprodukzioa + Jarraitu erreproduzitzen etenaldien ostean (adib. telefono deiak) Deskargak Fitxategi-izenetan baimendutako karaktereak Karaktere baliogabeak balio honekin ordezkatzen dira @@ -128,15 +128,15 @@ Hizkiak eta zenbakiak Karaktere berezi gehienak Bilaketa historiala - Gorde bilaketak lokalki + Gorde bilaketa-kontsultak tokian Ikustaldien historiala Gorde ikusitako bideoen historiala NewPipe jakinarazpena - Erreproduzigailua + Erreproduzitzailea Portaera Historia eta cache-a Desegin - NewPipe erreproduzigailuaren jakinarazpenak + NewPipe erreproduzitzailearen jakinarazpenak Emaitzarik ez Kilkerrak besterik ez daude hemen Harpidedunik ez @@ -144,10 +144,10 @@ Harpidedun %s %s harpidedun - Ikustaldirik ez + Erreprodukziorik ez - ikustaldi %s - %s ikustaldi + Erreprodukzio %s + %s erreprodukzio Bideorik ez @@ -156,52 +156,52 @@ Historiala Historiala - Erakutsi \"mantendu eransteko\" aholkua - Erakutsi aholkua bigarren planoko eta popup botoia sakatzean bideoaren \"Xehetasunak:\" atalean + Erakutsi «Mantendu ilaran jartzeko » aholkua + Erakutsi aholkua bigarren planoko eta laster-leiho botoia sakatzean bideoaren «Xehetasunak: » atalean Lehenetsitako edukiaren herrialdea - Jo denak + Erreproduzitu denak [Ezezaguna] Aldatu bigarren planora Aldatu laster-leihora Aldatu nagusira Ezin izan da igorpen hau erreproduzitu - Erreproduzigailuaren errore berreskuraezina gertatu da - Erreproduzigailuaren erroretik berreskuratzen - Dohaintza - NewPipe zuri erabiltzaile esperientziarik onena ekartzeko haien denbora librea ematen duten boluntarioek garatzen dute. Emaiezu zerbait garatzaileei NewPipe kafe bat hartzen duten bitartean hobetu ahal izan dezaten. + Erreproduzitzailearen errore berreskuraezina gertatu da + Erreproduzitzailearen erroretik berreskuratzen + Egin dohaintza + NewPipe boluntarioek garatu dute, haien denbora librea erabiltzaile esperientzia onena eskaintzen emanez. Eman dohaintza garatzaileei NewPipe are hobea izan dadin kafe bat hartzen duten bitartean. Egin dohaintza Webgunea Bisitatu NewPipe webgunea informazio gehiagorako eta berriak irakurtzeko. - Elementu hau bilaketen historialetik ezabatu nahi duzu? + Elementu hau bilaketa-historiatik ezabatu nahi duzu? Orri nagusiko edukia Orri hutsa Kioskoaren orria - Kanal-orria + Kanalaren orria Hautatu kanal bat - Ez zara inolako kanalera harpidetu oraindik + Ez dago kanal harpidetzarik oraindik Hautatu kiosko bat Joerak - Lehen 50ak + 50 onenak Berria eta arrakastatsua Kendu Xehetasunak Audio ezarpenak Mantendu ilaran jartzeko Hasi erreproduzitzen bigarren planoan - Laster-leihoan erreproduzitzen hasi + Hasi erreproduzitzen laster-leihoan Ireki tiradera Itxi tiradera Ez da igorpen-erreproduzigailurik aurkitu (VLC instalatu dezakezu erreproduzitzeko). Beti Behin besterik ez - Kanpo erreproduzigailuek ez dituzte mota honetako estekak onartzen + Kanpo erreproduzitzaileek ez dituzte mota honetako estekak onartzen Ez da bideo-igorpenik aurkitu Ez da audio-igorpenik aurkitu - Bideo erreproduzigailua - Bigarren planoko erreproduzigailua - Laster-leiho erreproduzigailua + Bideo erreproduzitzailea + Atzeko planoko erreproduzitzailea + Laster-leiho erreproduzitzailea Informazioa eskuratzen… - Kargatzen eskatutako edukia + Eskatutako edukia kargatzen Deskargatu igorpen-fitxategia Erakutsi informazioa Gogoko erreprodukzio-zerrendak @@ -211,54 +211,54 @@ Ezabatu cacheko metadatuak Kendu cachetik webguneen datu guztiak Metadatuen cachea ezabatuta - Gehitu automatikoki hurrengo igorpena ilarara - Gehitu ilararen amaieran lotutako igorpen bat errepikatu gabe + Jarri ilaran hurrengo igorpena automatikoki + Jarraitu erreprodukzioa errepikatu gabe, erlazionatutako igorpen bat gehituz Arazketa Fitxategia Inportatu datu-basea Esportatu datu-basea Zure uneko historiala, harpidetzak eta (aukeran) ezarpenak gainidazten ditu Esportatu historiala, harpidetzak, erreprodukzio-zerrendak eta ezarpenak - Garbitu ikusitakoaren historiala + Garbitu erreprodukzio-historia Erreproduzitutako igorpen-historia eta erreprodukzio-kokapenak ezabatzen ditu - Ezabatu ikusitakoaren historia osoa\? - Ikusitakoaren historiala ezabatuta - Garbitu bilaketa historiala - Ezabatu bilaketa gakoen historiala - Ezabatu bilaketen historia osoa\? - Bilaketen historiala ezabatuta - Karpeta baliogabea - Fitxategi edo edukiaren iturri baliogabea + Ezabatu erreprodukzio-historia osoa? + Erreprodukzio-historia ezabatuta + Garbitu bilaketa-historia + Bilaketa-gakoen historia ezabatzen du + Ezabatu bilaketa-historia osoa? + Bilaketa-historia ezabatuta + Karpeta ez da existitzen + Fitxategi/edukiaren iturria ez da existitzen Fitxategia ez dago edo ez dago baimenik irakurri edo idazteko - Fitxategi izena ezin da hutsik egon + Fitxategi-izena ezin da hutsik egon Errore bat gertatu da: %1$s Ez dago igorpenik eskuragarri deskargatzeko Arrastatu ordena aldatzeko Sortu Baztertu - Aldatu izena + Berrizendatu Elementu 1 ezabatuta. - Jotako azkena - Ikusiena + Erreproduzitutako azkena + Gehien erreproduzitutakoa Esportatuta Inportatuta Ez da baliozko ZIP fitxategia - Ebisua: Ezin izan dira fitxategi guztiak inportatu. - Honek oraingo ezarpenak gainidatziko ditu. - \'Ireki\' ekintza hobetsia + Abisua: Ezin izan dira fitxategi guztiak inportatu. + Honek zure uneko konfigurazioa gainidatziko du. + «Ireki» ekintza hobetsia Lehenetsitako ekintza edukia irekitzean — %s Galdetu beti Erreprodukzio-zerrenda berria - Aldatu izena + Berrizendatu Izena Gehitu erreprodukzio-zerrendara - Ezarri erreprodukzio-zerrendaren iruditxo gisa - Gogoko erreprodukzio-zerrenda - Kendu gogokoa - Erreprodukzio zerrenda hau ezabatu\? + Ezarri erreprodukzio-zerrendaren miniatura gisa + Laster-markatu erreprodukzio-zerrenda + Kendu laster-marka + Erreprodukzio-zerrenda hau ezabatu? Erreprodukzio-zerrenda sortuta Zerrendara gehitua - Erreprodukzio zerrendaren iruditxoa aldatuta. + Erreprodukzio zerrendaren miniatura aldatuta. Azpititulurik ez Doitu Bete @@ -277,21 +277,8 @@ Aurreko esportazioa Ezin izan dira harpidetzak inportatu Ezin izan dira harpidetzak esportatu - Inportatu YouTube harpidetzak Google takeoutetik: -\n -\n1. Joan URL honetara: %1$s -\n2. Hasi saioa eskatzen zaizunean -\n3. Hautatu \"Datu guztiak barne\", gero \"Kendu hautapen guztiak\", eta hautatu \"harpidetzak\" soilik eta egin klik \"Ados\" botoian -\n4. Egin klik \"Hurrengo pausua\"-n eta \"Sortu esportazioa\" -\n5. Egin klik \"Deskargatu\" botoian agertzen denean -\n6. Egin klik INPORTATU FITXATEGIA botoian eta hautatu deskargatutako zip fitxategia -\n7. [.zip inportazioak huts egiten badu] Erauzi .csv fitxategia deskargatutako takeout zip-etik (normalean \"Youtube eta Youtube Music/harpidetzak/harpidetzak.csv\"), egin klik INPORTATU FITXATEGIA botoian eta hautatu erauzitako csv fitxategia - Inportatu SoundCloud profila URL-a edo zure ID-a idatziz: -\n -\n1. Gaitu \"mahaigain modua\" web nabigatzailean (gunea ez dabil mugikorretan) -\n2. Joan URL honetara: %1$s -\n3. Hasi saioa eskatzen zaizunean -\n4. Kopiatu profilaren URL-a eraman zaizun orritik. + Inportatu YouTube harpidetzak Google takeout-etik: \n \n1. Joan URL honetara: %1$s \n2. Hasi saioa eskatzen zaizunean \n3. Hautatu «Datu guztiak barne», gero «Kendu hautapen guztiak», eta hautatu «harpidetzak» soilik eta egin klik «Ados» botoian \n4. Egin klik «Hurrengo pausua» eta «Sortu esportazioa» botoietan \n5. Egin klik «Deskargatu» botoian agertzen denean \n6. Egin klik INPORTATU FITXATEGIA botoian eta hautatu deskargatutako .zip fitxategia \n7. [.zip inportazioak huts egiten badu] Erauzi .csv fitxategia deskargatutako takeout zip-etik (normalean «Youtube eta Youtube Music/harpidetzak/harpidetzak.csv»), egin klik INPORTATU FITXATEGIA botoian eta hautatu erauzitako csv fitxategia + Inportatu SoundCloud profila URL-a edo zure ID-a idatziz: \n \n1. Gaitu «mahaigain modua» web nabigatzailean (gunea ez dabil mugikorretan) \n2. Joan URL honetara: %1$s \n3. Hasi saioa eskatzen zaizunean \n4. Kopiatu profilaren URL-a eraman zaizun orritik. zureID,soundcloud.com/zureid Eragiketa honek sarearen erabilera handia egin lezake. \n @@ -299,17 +286,15 @@ Erreprodukzio-abiaduraren kontrolak Tempoa Tonua - Desaktibatu (distortsioa sor lezake) + Desgaitu (distortsioa sor lezake) Ezarpenak ere inportatu nahi dituzu? - Bilaketa ez zehatzak posizioak azkarrago baina prezisio gutxiagoz bilatzea ahalbidetzen du. 5, 15 edo 25 segundo bilatzea ez du honekin funtzionatzen - NewPipe Software Librea eta Copyleft da: Erabili, ikertu, partekatu eta hobetu dezakezu. Zehazki, elkarbanatzea eta aldatzea Free Software Foundation-ek argitaratutako GNU General Public License-ren 3. bertsioa edo berriagoren baten terminoen arabera egiteko baimena duzu. + Bilaketa ez zehatzak erreproduzitzaileari posizioak azkarrago baina zehaztasun txikiagoarekin bilatzea ahalbidetzen dio. 5, 15 edo 25 segundoz bilatzea ez du honekin funtzionatzen + NewPipe copyleft software librea da: nahi duzunean erabili, aztertu, partekatu eta hobetu dezakezu. Zehazki, GNU Lizentzia Publiko Orokorraren baldintzen arabera birbanatu eta/edo aldatu dezakezu, Free Software Foundation-ek argitaratutako moduan, Lizentziaren 3. bertsioan edo (zure aukeran) ondorengo edozein bertsiotan. Behartu aktibitatearen bizitza ziklotik kanpo baztertu eta gero entregatu ezin diren Rx salbuespenen inguruko txostena - NewPipe pribatutasun politika - NewPipe proiektuak aintzat hartzen du zure pribatutasuna. Aplikazioak ez du zure baimenik gabe daturik jasotzen. -\nNewPipe pribatutasun politikak azaltzen du zehazki bidali eta gordetako informazioa zein den kraskatze txosten bat bidaltzen duzunean. + NewPipe-en pribatutasun politika + NewPipe proiektuak aintzat hartzen du zure pribatutasuna. Aplikazioak ez du zure baimenik gabe daturik jasotzen. \nNewPipe-en pribatutasun politikak zehazki azaltzen du zer datu bidali eta gordetzen den kraskatze txosten bat bidaltzen duzunean. Irakurri pribatutasun politika - Datuak Babesteko Araudi Orokorra (GDPR) betetzeko, NewPipe-en pribatutasun politika kontuan hartzera gonbidatzen zaitugu. Mesedez, irakurri kontu handiz. -\nAkats txosten bat bidali ahal izateko onartu behar duzu. + Europako Datuak Babesteko Erregelamendu Orokorra (GDPR) betetzeko, NewPipe-ren pribatutasun-politikaren berri ematen dizugu. Mesedez, irakurri arretaz. \nAkatsen txostena bidaltzeko onartu behar duzu. Onartu Ukatu Mugagabea @@ -318,31 +303,31 @@ Urratsa Leheneratu Minimizatu app-a aldatzean - Ekintza bideo erreproduzigailu nagusitik beste app batera aldatzean — %s + Ekintza bideo-erreproduzitzaile nagusitik beste aplikazio batera aldatzean — %s Bat ere ez - Minimizatu bigarren planoko erreproduzigailura - Minimizatu laster-leiho erreproduzigailura + Minimizatu bigarren planoko erreproduzitzailera + Minimizatu laster-leiho erreproduzitzailera Kanalak Erreprodukzio-zerrendak Pistak Erabiltzaileak Kendu harpidetza - Hautatu fitxa + Aukeratu fitxa Eguneraketak Gertaerak - Fitxategia ezabatu da + Fitxategia ezabatuta Aplikazioaren eguneraketen jakinarazpena NewPipe aplikazioaren bertsio berrien jakinarazpena - Kanpo biltegiratzea ez dago eskuragarri + Kanpoko biltegiratzea ez dago eskuragarri Ezin da SD txartel batera deskargatu. Deskargen karpeta berrezarri nahi duzu\? - Ezin izan dira gordetako fitxak irakurri, lehenetsitako fitxak erabiltzen + Ezin izan dira gordetako fitxak irakurri, lehenetsitakoak erabiltzen Berrezarri lehenetsitakoak - Lehenetsiak berrezarri nahi dituzu\? + Lehenetsitako balioak berrezarri nahi dituzu? Harpidedun kopurua ez dago eskuragarri Orri nagusian ikusiko diren fitxak Konferentziak Eguneraketak - Erakutsi jakinarazpena aplikazioa eguneratzea eskatuz bertsio berria eskuragarri dagoenean + Erakutsi jakinarazpena bertsio berri bat eskuragarri dagoenean aplikazioaren eguneratzea eskatzeko Zerrenda ikuspegi modua Zerrenda Sareta @@ -352,11 +337,11 @@ Zain pausatuta ilaran - post-prozesua - Enkargatu - Ekintza sistemak ukatu du + post-prozesamendua + Ilaran jarri + Sistemak ekintza ukatu du Deskargak huts egin du - Sortu izen bakana + Sortu izen bakarra Gainidatzi Badago izen bera duen deskargatutako fitxategi bat Badago izen bera duen deskarga bat abian @@ -365,17 +350,17 @@ Ezin da helburu karpeta sortu Ezin izan da konexio seguru bat ezarri Ezin izan da zerbitzaria aurkitu - Ezin da zerbitzariarekin konektatu + Ezin da zerbitzariara konektatu Zerbitzariak ez du daturik bidaltzen Zerbitzariak ez ditu hainbat hariko deskargak onartzen, saiatu @string/msg_threads = 1 erabilita - Ez aurkitua - Post-prozesuak huts egin du + Ez da aurkitu + Post-prozesamenduak huts egin du Gelditu Gehienezko saiakerak - Deskarga ezeztatu aurretik saiatu beharreko aldi kopurua + Deskarga utzi aurretik saiatu beharreko aldi kopurua Eten sare neurtuetan Erabilgarria datu mugikorretara aldatzean, hala ere deskarga batzuk ezin dira pausatu - Konexioaren denbora muga + Konexioaren denbora-muga Erakutsi iruzkinak Desgaitu iruzkinak ezkutatzeko Erreprodukzio automatikoa @@ -387,17 +372,17 @@ Posizioak zerrendetan Erakutsi erreprodukzio-posizioen adierazleak zerrendetan Garbitu datuak - Erreprodukzio-posizioak ezabatuta + Erreprodukzio-kokapenak ezabatuta Fitxategia lekuz aldatu edo ezabatu da Badago izen bereko fitxategi bat - Ezin da fitxategia gainidatzi - Badago izen bereko deskarga bat burutzeke + ezin da fitxategia gainidatzi + Badago izen bereko deskarga bat zain NewPipe itxi egin da fitxategian lanean zegoela Ez dago lekurik gailuan - Progresioa galdu da, fitxategia ezabatu delako - Zure deskargen historiala garbitu nahi duzu ala deskargatutako fitxategi guztiak ezabatu\? + Aurrerapena galdu da, fitxategia ezabatu delako + Zure deskargen historia garbitu nahi duzu ala deskargatutako fitxategi guztiak ezabatu? Mugatu deskargen ilara - Deskarga bakarra aldi berean + Deskarga bakarra soilik onartuko da aldi berean Hasi deskargak Pausatu deskargak Galdetu non deskargatu @@ -405,21 +390,21 @@ \nGaitu sistemaren karpeta hautatzailea (SAF) kanpoko SD txartel batera deskargatu nahi baduzu Ez dago inor ikusten - ikusle %s + Ikusle %s %s ikusle Ez dago inor entzuten - entzule %s + Entzule %s %s entzule Erabili sistemaren karpeta hautatzailea (SAF) \'Biltegiaren Sarrera Framework\'ak kanpoko SD txartel betera deskargatzea ahalbidetzen du - Ezabatu erreprodukziorako kokapenak - Erreprodukziorako kokapen guztiak ezabatzen ditu - Ezabatu erreprodukziorako kokapen guztiak\? + Ezabatu erreprodukzio-kokapenak + Erreprodukzio-kokapen guztiak ezabatzen ditu + Ezabatu erreprodukzio-kokapen guztiak? Aktibatu zerbitzua, orain hautatua: - Kiosko Lehenetsia + Kiosko lehenetsia Aurreratze/atzeratze bilaketaren iraupena PeerTube instantziak Hautatu zure gogoko PeerTube instantziak @@ -427,26 +412,26 @@ Gehitu instantzia Sartu instantziaren URLa Ezin izan da instantzia balioztatu - HTTPS URLak onartzen dira soilik + HTTPS URLak soilik onartzen dira Instantzia badago aurretik - Lokala + Tokikoa Berriki gehitua Gogokoenak Automatikoki sortua (igotzailea ez da aurkitu) berreskuratzen Ezin da deskarga hau berreskuratu - Aukeratu instantzia - Garbitu deskargen historiala + Aukeratu instantzia bat + Garbitu deskargen historia Ezabatu deskargatutako fitxategiak Baimena eman beste aplikazioen gainetik erakusteko Aplikazioaren hizkuntza Sistemaren lehenetsia - Sakatu \"Egina\" konponduta dagoenean - Egina + Sakatu «Eginda» konponduta dagoenean + Eginda Bideoak - segundu %d - %d segundu + segundo %d + %d segundo ExoPlayer-en mugak direla eta bilaketaren iraupena %d segundotan ezarri da Jarioaren karga motelegia dela uste duzu\? Hala bada, saiatu karga azkarra gaitzen (ezarpenetan edo beheko botoia sakatzen aldatu dezakezu). @@ -462,7 +447,7 @@ \nBeraz aukerak zure nahietara murrizten dira: abiadura edo informazio zehatza. Desgaitu modu azkarra Gaitu modu azkarra - Zenbait zerbitzuetan eskuragarri, normalean askoz azkarragoa da, baina elementu kopuru mugatua eta osatu gabeko informazioa itzuli dezake (adib. iraupenik ez, elementu mota, zuzeneko egoera) + Zerbitzu batzuetan eskuragarri, normalean askoz azkarragoa da, baina elementu kopuru mugatu eta osatu gabeko informazioa itzuli dezake (adib. iraupenik ez, elementu mota, zuzeneko egoerarik ez) Eskuratu jario dedikatutik eskuragarri dagoenean Eguneratu beti Pasatzen den denbora harpidetza bat zaharkituta dagoela kontuan hartzen den arte — %s @@ -473,15 +458,15 @@ Talde izena hutsik %d hautatuta - %d hautatutak + %d hautatuta - Ez da harpidetzarik aukeratu + Ez da harpidetzarik hautatu Hautatu harpidetzak Jarioa prozesatzen… Jarioa kargatzen… Kargatu gabe: %d - Jarioa azkenik eguneratuta: %s - Kanal taldeak + Jarioaren azken eguneraketa: %s + Kanal-taldeak egun %d %d egun @@ -494,68 +479,63 @@ minutu %d %d minutu - Aktibatu audioa + Gaitu audioa Isilarazi - Eduki hau ez dago oraindik NewPipengatik onatuta. -\n -\nEtorkizuneko bertsio batean onartua izatea espero da. + Eduki hau ez dago oraindik NewPiperengatik onartuta. \n \nEtorkizuneko bertsio batean onartua izatea espero da. ∞ bideo 100 bideo baino gehiago Artistak Albumak Abestiak - Bideo hau adinez mugatua dago. -\n -\nIkusi nahi baduzu, piztu ezazu \"%1$s\" ezarpenetan. + Bideo hau adinez mugatua dago. \n \nIkusi nahi baduzu, gaitu ezazu \"%1$s\" ezarpenetan. Egilea: %s - Erreprodukzio zerrendaren orria - %s-k sortua - Kanalaren avatar-earen miniatura - Erakutsi agrupatuta ez dauden harpidetzak bakarrik - Bai, partzialki ikusitako bideoak ere bai - Jada ikusi eta gero erreprodukzio zerrendara gehitu diren bideoak ezabatuak izango dira. -\nJarraitu nahi duzu\? Ekintza hau ezin da desegin! - Ikusitako bideoak ezabatu\? - Ikusitako bideoak ezabatu + Erreprodukzio-zerrendaren orria + %s-(e)k sortuta + Kanalaren avatarraren miniatura + Erakutsi taldekatuta ez dauden harpidetzak soilik + Bai, partzialki ikusitako bideoak ere bai + Dagoeneko ikusi eta gero erreprodukzio-zerrendara gehitu diren bideoak kendu egingo dira. \nJarraitu nahi duzu? Ekintza hau ezin da desegin! + Ikusitako bideoak kendu? + Kendu ikusitako bideoak Inoiz ez - Bakarrik WiFi-arekin + WiFi-arekin soilik Erreprodukzioa automatikoki hasi — %s Erakutsi memoria galerak - Ilara erreproduzitu + Erreproduzitu ilara Oraindik ez dago erreprodukzio-zerrenda laster-markarik - Playlist bat aukeratu - Mesedez, egiaztatu jada zure arazoarekin diskusiorik sortuta badagoen. Sarrera duplikatuak daudenean, arazoa ebazteko erabili dezakegun denbora galtzen ari gara. - Formatodun erreportea kopiatu - GitHub-en erreportatu - reCAPTCHA bat egiten duzunean NewPipe-k gordetzen dituen kookiak ezabatu + Hautatu erreprodukzio-zerrenda bat + Mesedez, egiaztatu dagoeneko zure arazoarekin eztabaidarik sortuta badagoen. Sarrera duplikatuak daudenean, arazoa ebazteko erabili dezakegun denbora galtzen ari gara. + Formatodun txostena kopiatu + Eman berri GitHub-en + Garbitu NewPipe-k gordetzen dituen cookieak reCAPTCHA bat ebazten duzunean reCAPTCHA kookiak garbitu dira Ezabatu reCAPTCHA-ren kookiak Adinez mugatuta dagoen eta haurrentzako desegokia izan daitezkeen edukia erakutsi (+18 adibidez) - YouTube-ren \"Modu Murriztua\" helduentzako edukia izan daitekeen edukia ezkutatzen du - Piztu YouTube-ren \"Modu Murriztua\" + YouTube-ren «Modu mugatua» helduentzako edukia izan daitekeen edukia ezkutatzen du + Gaitu YouTube-ren «Modu mugatua» Ezin izan da URL-a ezagutu. Beste aplikazio batekin ireki\? - Auto-ilara - Erreprodukzio ilara aktiboa ordezkatuko da + Auto-ilaratzea + Erreprodukzio-ilara aktiboa ordezkatuko da Erreproduzitzaile batetik beste batera aldatzeak ilara ordezkatu dezake - Konfirmazioa eskatu ilaratik ezabatu baino lehenago + Eskatu berrespena ilara bat garbitu baino lehenago Ezer ez Buferreratzen - Aleatorio - Gehienez hiru ekintza aukera ditzakezu jakinarazpenean erakusteko! + Nahastu + Gehienez hiru ekintza aukera ditzakezu jakinarazpen trinkoan erakusteko! Errepikatu Bostgarren ekintzaren botoia Laugarren ekintzaren botoia Hirugarren ekintzaren botoia Bigarren ekintzaren botoia Lehenego ekintzaren botoia - Ebaki jakinarazpenetan erakusten den bideo miniaturaren formatu-ratioa 16:9tik 1:1era - Miniatura 1:1 formatu-ratiora ebaki + Ebaki jakinarazpenetan erakusten den bideo miniaturaren itxura-erlazioa 16:9tik 1:1era + Miniatura 1:1 itxura-erlaziora ebaki %s bilaketaren erantzunak erakusten Ilaran jarri da Jarri ilaran Zerbitzuen jatorrizko testuak igorpenaren elementuetan ikusgai egongo dira Erakutsi «orain dela» jatorrizko denbora elementuetan - Editatu beheko jakinarazpen ekintza bakoitza gainean sakatuz. Hautatu horietako hiru gehienez jakinarazpen trinkoan erakusteko eskuineko kontrol laukiak erabiliz. + Editatu beheko jakinarazpen-ekintza bakoitza sakatuz. Hautatu horietako hiru gehienez jakinarazpen trinkoan erakusteko, eskuineko kontrol-laukiak erabiliz. Androidek miniaturako kolore nagusiaren arabera jakinarazpenaren kolorea pertsonalizatzea baimendu (kontuan izan ez dagoela gailu guztietan erabilgarri) Koloreztatu jakinarazpena Erabili miniatura blokeo pantaila eta jakinarazpenentzako @@ -564,20 +544,20 @@ Bideo hash jakinarazpena Hash-a kalkulatzen Azkenak - Desgaitu igorpen-sortzailearen informazio gehigarria, igorpenaren edukia edo bilaketa-eskaera duten metadatuen informazio-koadroak ezkutatzeko + Desgaitu igorpenaren sortzaileari, eduki edo bilaketa-eskaera bati buruzko meta informazio-koadroak ezkutatzeko Erakutsi meta informazioa Ez dago zure gailuan hau ireki dezakeen aplikaziorik Kapituluak Deskribapena - Erlazionatutako jarioak + Erlazionatutako elementuak Iruzkinak - Desaktibatu bideoaren deskribapena eta informazio gehigarria ezkutatzeko + Desgaitu bideoaren deskribapen eta informazio gehigarria ezkutatzeko Erakutsi deskribapena Ireki honekin Irratia Nabarmenduak - Eduki hau ordaindu duten erabiltzaileentzat soilik dago erabilgarri, eta NewPipe-k ezin du igorri edo deskargatu. - Bideo hau YouTube Music Premium kideentzako soilik erabilgarri dago, eta NewPipe-k ezin du igorri edo deskargatu. + Eduki hau ordaindu duten erabiltzaileentzat soilik dago eskuragarri, eta NewPipe-k ezin du igorri edo deskargatu. + Bideo hau YouTube Music Premium kideentzako soilik dago eskuragarri, eta NewPipe-k ezin du igorri edo deskargatu. Eduki hau pribatua da, eta NewPipe-k ezin du igorri edo deskargatu. Hau SoundCloud Go+ zerbitzuko pista bat da, zure herrialdean behintzat, eta NewPipe-k ezin du igorri edo deskargatu. Eduki hau ez dago eskuragarri zure herrialdean. @@ -586,26 +566,26 @@ Bideo hau adinez mugatua dago. \nAdinez mugatutako bideoekiko YouTube-ren politika berriengatik, NewPipe-k ezin ditu bideoen igorpen hauek atzitu eta erreproduzitu. Deskarga hasi da - Behean gaueko gai gogokoena hauta dezakezu + Behean gaueko gai gogokoena hautatu dezakezu Hautatu zure gaueko gai gogokoena — %s Automatikoa (gailuaren gaia) - Gauaren gaia - kanalaren xehetasunak erakutsi - Desgaitu edukien tunela bideo-erreprodukzioan pantaila beltza badago edo bideoa totelka ari bada. - Hedabideen tunela desaktibatu + Gaueko gaia + Erakutsi kanalaren xehetasunak + Desgaitu multimedia-tunelatzea pantaila beltza edo bideoa erreproduzitzean eten egiten bada. + Multimedia-tunela desgaitu Itzalita Piztuta Tablet modua - Web-orrialdea ireki + Ireki webgunea Pribatua Publikoa Hizkuntza Lizentzia - Tag-ak + Etiketak Kategoria - Desgaitu bideo deskripzioaren testua hautatzea - Bideo deskripzioaren testua hautatzea gaitu - Orain, testua aukeratu dezakezu deskribapenaren barruan. Kontuan izan orriak begiak kliskatu ditzakeela eta estekak ez direla klikagarriak izango hautaketa moduan dagoen bitartean. + Desgaitu deskribapenaren testu-hautaketa + Deskribapenaren testu-hautaketa gaitu + Orain deskribapenaren barruko testua hauta dezakezu. Kontuan izan orrialdea keinuka hasi dezakela eta estekak ezin direla klikatu hautaketa moduan zauden bitartean. Egilearen kontua itxi da. \nNewPipe-k ezingo du etorkizunean jario hau kargatu. \nKanal honetatik harpidetza kendu nahi duzu\? @@ -615,7 +595,7 @@ Non gorde galdetuko zaizu deskarga bakoitzean Ez da deskargatzeko karpetarik ezarri oraindik, aukeratu lehenetsitako deskargatzeko karpeta orain Pribatutasuna - Kontua ezabatu da + Kontua itxi da Jario azkarrak ez du honi buruz informazio gehiagorik ematen. Adin muga Barnekoa @@ -625,30 +605,30 @@ Ez da agertzen Kalitate txikia (txikiagoa) Kalitate handia (handiagoa) - Seekbarren miniaturen aurrebista - Iruzkinak desaktibatuta daude + Bilaketa-barraren miniaturen aurrebista + Iruzkinak desgaituta daude Sortzaileak baloratua Deskarga %1$s ezabatuta - %1$s deskarga ezabatuak + %1$s deskarga ezabatuta Deskarga amaituta - %s Deskarga amaituta + %s deskarga amaituta Irudien gainean Picasso koloretako zintak erakutsi, jatorria adieraziz: gorria sarerako, urdina diskorako eta berdea memoriarako Erakutsi irudi-adierazleak - Urruneko bilaketaren iradokizunak + Urruneko bilaketa-iradokizunak Tokiko bilaketa-iradokizunak - Ikusi gisa markatu - Lerratu elementuak aldetara ezabatzeko + Ikusitako gisa markatu + Irristatu elementuak kentzeko Ez hasi bideoak mini erreproduzitzailean eta hasi bideoak pantaila osoan zuzenean, auto biraketa blokeatuta badago. Mini erreproduzitzailea erabili dezakezu pantaila osotik irtetzean Hasi erreproduzitzaile nagusia pantaila osoan - Isatsari bideo hau erantsita + Jarraian jarrita Gehitu jarraian - Erakutsi \"Itxi erreproduzigailua\" + Erakutsi «Erreproduzitzailea kraskatu» Prozesatzen... Itxoin mesedez - Erroreen txostenen jakinarazpena + Errore-txostenen jakinarazpena Jakinarazpenak erroreen berri emateko NewPipe-k errore bat aurkitu du, sakatu berri emateko Errore bat gertatu da, ikusi jakinarazpena @@ -658,16 +638,16 @@ Ez da fitxategi kudeatzaile bat aurkitu ekintza honetarako. \nMesedez, instalatu Storage Access Framework-ekin bateragarria den fitxategi kudeatzaile bat Ainguratutako iruzkina - Itxi erreproduzigailua + Erreproduzitzailea kraskatu Eguneraketak bilatzen… Ez da fitxategi kudeatzaile bat aurkitu ekintza honetarako. \nMesedez, instalatu fitxategi kudeatzaile bat edo saiatu \'%s\' desgaitzen deskarga ezarpenetan - Erreproduzigailua erabiltzean ustekabean ixteko aukera ematen du + Erreproduzitzailea erabiltzean kraskadura aukera erakusten du Erakutsi errore barra bat Sortu errore jakinarazpen bat - Konfiguratu unean erreproduzitzen ari den igorpenaren jakinarazpena + Konfiguratu uneko erreprodukzio-igorpenaren jakinarazpena Jakinarazpenak - Erreproduzigailuaren jakinarazpenak + Erreproduzitzailearen jakinarazpenak Igorpen berriak Bilatu igorpen berriak Igorpen berrien jakinarazpenak @@ -681,27 +661,27 @@ Harpidetzen igorpen berrien jakinarazpenak Igorpenaren xehetasunak kargatzen… - igorpen berri %s + Igorpen berri %s %s igorpen berri LeakCanary ez dago eskuragarri - Egiaztapen maiztasuna - Jakinarazi + Egiaztatze maiztasuna + Jaso jakinarazpenak ExoPlayer lehenetsia Beharrezko sareko konexioa Portzentaia Semitonoa Erreprodukzioaren kargatze-tartearen tamaina Deskargatzaileak onartzen ez dituen igorpenak ez dira erakusten - Hautatutako igorpena ez dute kanpoko erreproduzitzaileek onartzen - Ez dato erabilgarri audio-igorpenik kanpoko erreproduzitzaileentzat - Ez dago erabilgarri bideo-igorpenik kanpoko erreproduzitzaileentzat + Kanpoko erreproduzitzaileek ez dute hautatutako igorpena onartzen + Ez dago audio-igorpenik eskuragarri kanpoko erreproduzitzaileentzat + Ez dago bideo-igorpenik eskuragarri kanpoko erreproduzitzaileentzat Formatu ezezaguna Kalitate ezezaguna - Hautatu kanpoko erreproduzigailuen kalitatea + Hautatu kanpoko erreproduzitzaileen kalitatea Grisez idatzitako erreprodukzio-zerrendek jada badute elementu hau. Webgunean ikusi - Akatsa arbelera kopiatzean + Akatsa arbelera kopiatzeak huts egin du Arazoren bat baduzu aplikazioa erabiltzerakoan, irakur itzazu ohiko galdera hauen erantzunak! Betiko miniatura kendu NewPipe-en azken bertsioa erabiltzen ari zara @@ -712,8 +692,8 @@ Ordenatu Modu azkarra Hiru-puntutako menutik harpidetzak inportatu edo esportatu - Maiz galdetutako galderak - Ezikusi hardware multimedia botoien gertaerak + Maiz egindako galderak + Ezikusi hardware multimedia-botoien gertaerak Erabilgarria, adibidez, botoi fisiko hautsiak dituen entzungailua erabiltzen ari bazara Kendu bikoiztuak Kendu bikoiztuak\? @@ -737,9 +717,9 @@ Eskuineko keinuaren ekintza Erabili beti ExoPlayer-en bideo-irteeraren interfazeko ezarpenaren konponbidea Hurrengo igorpena - Edukien tunela desgaitu da lehenespenez gailuan, gailuaren modeloak ez du onartzen eta. + Multimedia-tunela desgaitu da lehenespenez gailuan, gailuaren modeloak ez du onartzen eta. Azpikanalen abatarrak - Audio-pista bat egon behar da igorpen honetan jada + Audio-pista bat egon beharko litzateke igorpen honetan dagoeneko Hautatu jatorrizko audioaren pista hizkuntza zein den kontuan hartu gabe Hautatu kanpoko erreproduzitzailearen audio-pista Lortuko diren fitxak jarioa eguneratzean. Aukera honek ez du eraginik kanal bat modu azkarra erabiliz eguneratzen bada. @@ -747,7 +727,7 @@ Ezkerreko keinuaren ekintza Hobetsi audio deskribatzailea Igotako abatarrak - Aldatu eduki progresiboen kargatze-tartearen tamaina (oraingoa: %s). Balio baxu batek hasierako kargatzea bizkortu dezake + Aldatu eduki progresiboen kargatze-tartearen tamaina (oraingoa: %s). Balio baxu batek hasierako karga bizkortu dezake Hobetsi jatorrizko audioa Audioa: %s Bannerrak @@ -766,7 +746,7 @@ %1$s %2$s Honi buruz Ez - Editatu beheko jakinarazpen ekintza bakoitza gainean sakatuz. Lehen hiru ekintzak (erreproduzitu/pausatu, aurrekoa eta hurrengoa) sistemarengatik ezarrita daude eta ezin dira pertsonalizatu. + Editatu beheko jakinarazpen-ekintza bakoitza sakatuz. Lehen hiru ekintzak (erreproduzitu/pausatu, aurrekoa eta hurrengoa) sistemarengatik ezarrita daude eta ezin dira pertsonalizatu. Atzera egin Irudiaren kalitatea Aukera gehiago @@ -787,7 +767,7 @@ Ezarpenak berrezartzeak zure ezarpen gogokoenak baztertzen ditu eta aplikazioa berrabiarazten du. \n \nAurrera egin nahi duzu? - Ez dago nahikoa lekurik gailuan + Ez dago leku libre nahikorik gailuan Konponbide honek azal aldaketa bat gertatzean bideo kodekak askatu eta berrezartzen ditu, azalaren kodeka zuzenean ezarri ordez. ExoPlayer-ek dagoeneko erabiltzen du arazoak dituzten gailu batzuetan. Ezarpen honek Android 6 eta berriagotan funtzionatzen du soilik \n \nAukera hau gaitzeak erreprodukzio erroreak saihestu ditzake bideo-erreproduktorea aldatzean edo pantaila osoan jartzean @@ -820,4 +800,34 @@ Erakutsi gutxiago bigarren mailako + Bilatu %1$s + Bilatu %1$s (%2$s) + Erreprodukzio-zerrendak + Laster-leiho erreproduzitzailea erabiltzeko, hautatu %1$s Android-en ezarpenen menu hauan, eta gaitu %2$s. + «Baimendu beste aplikazio batzuen gainean bistaratzea» + %sK + %sM + %sMM + Ezabatu fitxategia + Ezabatu sarrera + Hatutatu jario talde bat + Ez da jario talderik sortu oraindik + Kanal-taldeen orria + Kontua itxi da\n\n%1$s-ek arrazoi hau ematen du: %2$s + Gustoko + Partekatu YouTubeko aldi baterako erreprodukzio-zerrenda gisa + SoundCloud-eko 50 onenen orrialdea kendu da + SoundCloud-ek jatorrizko Top 50 zerrendetan eten egin du. Dagokion fitxa kendu da zure orrialde nagusitik. + YouTubeko joera konbinatuak kendu dira + YouTube-k joera-orrialde konbinatua eten du 2025eko uztailaren 21etik aurrera. NewPipe-k joera-orrialde lehenetsia zuzeneko emankizunekin ordezkatu du.\n\nJoera desberdineko orrialdeak ere hauta ditzakezu \"Ezarpenak > Edukia > Orrialde nagusiaren edukia\" atalean. + Bideojoko joerak + Podcast joerak + Film eta telesail joerak + Musika joerak + Sarrera ezabatua + 403 HTTP errorea jaso da zerbitzaritik erreproduzitzen ari zenean, ziurrenik streaming URLaren iraungipenak edo IP debeku batek eraginda + %1$s HTTP errorea jaso da zerbitzaritik erreproduzitzen ari zela + 403 HTTP errorea jaso da zerbitzaritik erreproduzitzen ari zenean, ziurrenik IP debeku batek edo streaming URLaren desofuskazio arazoek eraginda + %1$s-ek datuak emateari uko egin dio, eskatzailea bot bat ez dela baieztatzeko saioa hasteko eskatuz.\n\nBaliteke zure IP helbidea %1$s-ek aldi baterako debekatu izana, denbora pixka bat itxaron dezakezu edo beste IP batera aldatu (adibidez, VPN bat aktibatu/itzaliz, edo WiFitik datu mugikorretara aldatuz). + Eduki hau ez dago eskuragarri hautatutako edukiaren herrialderako.\n\nAldatu zure hautaketa \"Ezarpenak > Edukia > Edukiaren herrialde lehenetsia\" ataletik. diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 403fb4c11..cd2d1ec32 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -449,7 +449,7 @@ %d ثانیه %d ثانیه - بله، و ویدیوهای ناقص دیده شده + بله، و ویدیوهای ناقص دیده شده برداشتن ویدیوهای دیده شده؟ پاک کردن دیده شده‌ها پیش‌فرض دستگاه @@ -500,8 +500,7 @@ نمایش اشتراک های دسته بندی نشده آواتار بندانگشتی کانال صفحه فهرست پخش - ویدیوهایی که پیش و‌ پس از افزوده شدن به سیاههٔ پخش دیده شده‌اند حذف خواهند شد. -\nمطمئنید؟ این کار قابل بازگشت نیست! + ویدیوهایی که پیش و‌ پس از افزوده شدن به سیاههٔ پخش دیده شده‌اند حذف خواهند شد. \nمطمئنید؟ این کار قابل بازگشت نیست! گزارش اجباری خطاهای Rx غیرقابل تحویل خارج از چرخه حیات فعالیت یا بخش پس از اتمام فکر می‌کنید دریافت خوراک بیش از حد آهسته است؟ اگر چنین است، بارگیری سریع را فعالی کنید (می‌توانید آن را در تنظیمات یا با فشردن دکمه زیر تغییر دهید) \n diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 22c1fab12..3f66a85eb 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -392,10 +392,9 @@ Näytä toistokohtien osoittimet listoissa Kohdat listoissa Palauta edellinen toistokohta - Aiemmin katsotut ja soittolistaan lisätyt videot poistetaan. -\nOletko varma\? Tätä ei voi peruuttaa! - Poistetaanko katsotut videot\? - Kyllä ja osittain katsotut videot + Aiemmin katsotut ja soittolistaan lisätyt videot poistetaan. \nOletko varma? Tätä ei voi peruuttaa! + Poistetaanko katsotut videot? + Kyllä ja osittain katsotut videot Pysäytä Tyhjennä lataushistoria Sulje diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 5dfcbd2ce..abb13644a 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -249,7 +249,7 @@ Mga track Mga gumagamit Hangganan ng Edad - Oo, pati na rin ang mga napanood nang video + Oo, pati na rin ang mga napanood nang video Kusa (tema ng device) Tanggalin ang kabuuan ng watch history? Walang mga stream na maaaring i-download diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ffb78e19f..2977d982e 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -229,9 +229,9 @@ Nom Ajouter à la liste de lecture Définir comme miniature de la liste de lecture - Enregister la liste de lecture + Enregistrer la liste de lecture Supprimer le signet - Voulez-vous supprimer cette liste de lecture \? + Voulez-vous supprimer cette liste de lecture ? Liste de lecture créée Ajouté à la liste de lecture Miniature de la liste de lecture changée. @@ -386,7 +386,7 @@ Aucun commentaire Impossible de charger les commentaires Fermer - Reprendre la liste de lecture + Reprendre la lecture Effacer les données Fichier déplacé ou supprimé impossible d’écraser le fichier @@ -521,10 +521,9 @@ \n \nActivez « %1$s » dans les paramètres si vous voulez la voir. Supprimer les vidéos visionnées - Oui ainsi que les vidéos partiellement visionnées - Les vidéos qui ont été visionnées avant et après avoir été ajoutées à la liste de lecture seront supprimées. -\nÊtes-vous certain(e)  \? Cette action est irréversible ! - Supprimer les vidéos visionnées \? + Oui ainsi que les vidéos partiellement visionnées + Les vidéos qui ont été visionnées avant et après avoir été ajoutées à la playlist seront supprimées. \nÊtes-vous certain(e) ? Cette action est irréversible ! + Supprimer les vidéos visionnées ? Miniature de l\'avatar de la chaine De %s Créé par %s @@ -532,7 +531,7 @@ Afficher la date originelle sur les items Activer le « Mode restreint » de YouTube Afficher uniquement les abonnements non groupés - Page des listes de lecture + Page des playlists Aucune liste de lecture encore enregistrée Sélectionner une liste de lecture Veuillez vérifier si un ticket concernant votre problème existe déjà. Lorsque vous créez des tickets dupliqués, cela nous prend du temps que nous pourrions passer à résoudre effectivement le problème. @@ -839,11 +838,31 @@ Partager comme liste de lecture YouTube temporaire Listes de lecture Sélectionnez un groupe de flux - Aucun groupe de flux n\'a encore été créé + Encore aucun groupe de flux créé Page du groupe de chaînes Rechercher %1$s Rechercher %1$s (%2$s) - Likes + J’aime Page SoundCloud Top 50 supprimée SoundCloud a abandonné le classement original du Top 50. L\'onglet correspondant a été supprimé de votre page d\'accueil. + Suppression des tendances combinées sur YouTube + YouTube a supprimé la page des tendances combinées depuis le 21 juillet 2025. NewPipe a remplacé la page des tendances par défaut par les diffusions en direct les plus populaires.\n\nVous pouvez également sélectionner différentes pages de tendances dans « Paramètres > Contenu > Contenu de la page principale ». + Tendances jeu vidéo + Tendances podcasts + Tendances films et séries + Tendances musique + %sK + %sM + %sB + Pour utiliser le lecteur contextuel, veuillez sélectionner %1$s dans le menu des paramètres Android suivant et activer %2$s. + « Autoriser l\'affichage sur d\'autres applications » + Supprimer le fichier + Supprimer l\'entrée + Entrée supprimée + Compte fermé\n\n%1$s fournit la raison suivante : %2$s + Erreur HTTP 403 reçue du serveur pendant la lecture, probablement causée par l\'expiration de l\'URL de streaming ou une interdiction d\'IP + Erreur HTTP %1$s reçue du serveur pendant la lecture + Erreur HTTP 403 reçue du serveur pendant la lecture, probablement causée par un bannissement d\'IP ou des problèmes de désobfuscation de l\'URL de streaming + %1$s a refusé de fournir des données et a demandé un identifiant pour confirmer que le demandeur n\'est pas un robot.\n\nVotre adresse IP a peut-être été temporairement bannie par %1$s. Vous pouvez patienter un peu ou changer d\'adresse IP (par exemple en activant/désactivant un VPN, ou en passant du Wi-Fi aux données mobiles). + Ce contenu n\'est pas disponible pour le pays actuellement sélectionné.\n\nModifiez votre sélection dans « Paramètres > Contenu > Pays par défaut ». diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index aacaf9288..6c7fa3e3c 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -387,10 +387,9 @@ %d segundos Debido ás restricións de ExoPlayer, a duración da busca estableceuse en %d segundos - Si, e visualizou parcialmente estes vídeos - Eliminaranse os vídeos vistos antes e despois de seren engadidos á lista de reprodución. -\nEstás seguro\? Isto non se pode desfacer.! - Borrar todos os vídeos vistos\? + Si, e visualizou parcialmente estes vídeos + Eliminaranse os vídeos vistos antes e despois de seren engadidos á lista de reprodución. \nEstás seguro? Isto non se pode desfacer.! + Borrar todos os vídeos vistos? Eliminar o visto Sistema predeterminado Lingua do aplicativo diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 2131dc9c0..c979ab229 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -527,11 +527,10 @@ סרטון זה מוגבל לצפייה מגיל מסוים. \n \nיש להפעיל את „%1$s” בהגדרות כדי לצפות בו. - כן, לרבות סרטונים שהפסקתי באמצע - סרטונים שלאחר שצפית בהם מופיע לרשימת הנגינה יוסרו. -\nלהמשיך\? זאת פעולה בלתי הפיכה! + כן, לרבות סרטונים שהפסקתי באמצע + סרטונים שלאחר שצפית בהם מופיע לרשימת הנגינה יוסרו. \nלהמשיך? זאת פעולה בלתי הפיכה! הסרת נצפו - להסיר סרטונים שנצפו\? + להסיר סרטונים שנצפו? הטקסט המקורי משירותים יופיע בפריטי התזרים הצגת לפני כמה זמן מקורי על פריטים הפעלת „מצב מוגבל” של YouTube @@ -595,7 +594,7 @@ פתיחה באמצעות אין יישומון על המכשיר שלך שיכול לפתוח את זה להקריס את היישומון - תוכן זה זמין רק למשתמשים ששילמו, לכן לא ניתן להזרים או להוריד אותו עם NewPipe. + התוכן הזה זמין רק למשתמשים ששילמו, לכן לא ניתן להזרים או להוריד אותו עם NewPipe. סרטון זה זמין רק למנויי YouTube Music Premium, לכן לא ניתן להזרים או להוריד אותו עם NewPipe. זה תוכן פרטי, לכן לא ניתן להזרים או להוריד אותו עם NewPipe. רצועה זו של SoundCloud Go+‎ מוגבלת, לפחות במדינה שלך, לכן לא ניתן להזרים או להוריד אותה עם NewPipe. @@ -855,4 +854,26 @@ חיפוש ב־%1$s חיפוש ב־%1$s‏ (%2$s) לייקים + חשבון הושמד\n\n%1$s מספק את הסיבה הבאה: %2$s + כדי להשתמש בנגן צף, נא לבחור ב־%1$s בתפריט ההגדרות הבא של Android ולהפעיל את %2$s. + „תמיד להציג מעל יישומונים אחרים” + %s אלף + %s מיליון + %s מיליארד + המובילים המשולבים של YouTube הוסרו + מחיקת קובץ + מחיקת רשומה + עמוד 50 המובילים ב־SoundCloud הוסר + מגמות במשחקים + פודקאסטים מובילים + סרטים וסדרות מובילים + מוזיקה מובילה + הרשומה נמחקה + SoundCloud הפסיקו את מצעדי 50 הלהיטים המקוריים. הלשונית התואמת הוסרה מהעמוד הראשי שלך. + ב־YouTube הושבת עמוד המובילים המשולב החל מ־21 ביולי 2025. NewPipe החליפה את עמוד המובילים המוגדר כברירת מחדל בשידורים חיים מובילים.\n\nניתן גם לבחור עמודי מובילים שונים תחת „הגדרות > תוכן > תוכן הדף הראשי”. + שגיאת HTTP 403 שהתקבלה מהשרת בזמן השמעה, ככל הנראה נגרמת עקב פקיעת כתובת URL של סטרימינג או חסימת IP + שגיאת HTTP %1$s התקבלה מהשרת בזמן הניגון + שגיאת HTTP‏ 403 שהתקבלה מהשרת בזמן הניגון, ככל הנראה נגרמה עקב חסימת IP או בעיות בהסרת ערפול כתובת תזרים + %1$s סירב לספק נתונים, וביקש התחברות כדי לאשר שהמבקש אינו בוט.\n\nכנראה שה־IP שלך נחסם זמנית על ידי %1$s, ניתן להמתין זמן מה או לעבור ל־IP אחר (לדוגמה על ידי הפעלה/כיבוי של VPN, או על ידי מעבר מרשת אלחוטית לתקשורת נתונים סלולרית). + תוכן זה אינו זמין עבור מדינת התוכן שנבחרה כעת.\n\nניתן לשנות את בחירתך דרך „הגדרות > תוכן > מדינת תוכן ברירת מחדל”. diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index dd23cfc08..5c7be01b4 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -74,7 +74,7 @@ देखे गए वीडियोज़ की सूची रखें प्लेबैक फिर से शुरू करें रुकावटें (जैसे कि फ़ोन कॉल) खत्म होने के बाद वीडियो प्ले जारी रखें - \'अगले\' और \'सबंधित\' वीडियो दिखाएं + \'अगला\' और \'संबंधित\' वीडियो दिखाएं \"कतार में जोड़ने के लिए स्पर्श बनाये रखें\" दिखाएं जब बैकग्राउंड और पॉपअप बटन वीडियो के विवरण पन्ने में दबाई जाए तो सलाह दिखाएं असमर्थित URL @@ -93,7 +93,7 @@ बंद किया साफ करें उत्तम रिजॉल्युशन - वापिस + अन-डू करें सभी प्ले करें न्यूपाइप की नोटीफिकेशन न्यूपाइप के प्लेयर के लिए नोटीफिकेशन @@ -104,7 +104,7 @@ वैबसाइट parse नहीं हो सकी विषय वस्तु उपलब्ध नहीं है डाउनलोड मेनू स्थापित नहीं किया जा सका - APP/UI करैश हो गई + ऐप/UI करैश हो गई इस वीडियो को चलाने में असफल हुए अनचाही वीडियो प्लेयर त्रुटी आयी है वीडियो प्लेयर त्रुटी से ठीक हो रहा है @@ -391,7 +391,7 @@ प्लेबैक स्थानों को मिटाएं सारे प्लेबैक स्थानों को मिटाता है सारे प्लेबैक स्थानों को मिटाएं\? - निपटान के बाद खंड या गतिविधि जीवन चक्र के बाहर अविभाज्य आरएक्स अपवादों की रिपोर्टिंग को बलपूर्वक लागू करें + हैंडलिंग के बाद फ्रैगमेंट या एक्टिविटी लूप के बाहर अनहैंडल्ड Rx एक्सेप्शन की रिपोर्टिंग को बलपूर्वक लागू करें साउंडक्लाउड प्रोफाइल निर्यात करने के लिए आईडी या युआरएल दीजिये: \n \n1. अपने वेब ब्राउज़र में \"डेस्कटॉप मोड\" चालू करें (वेबसाइट मोबाइल उपकरणों के लिए उपलब्ध नहीं है) @@ -406,7 +406,7 @@ ग्रिड ऑटो त्रुटि दिखाएं - सर्वर मल्टी थ्रेडेड डाउनलोड स्वीकार नहीं करता, पुनः कोशिश करे @string/msg_threads = 1 के साथ + सर्वर मल्टी थ्रेडेड डाउनलोड स्वीकार नहीं करता, @string/msg_threads = 1 के साथ पुनः कोशिश करें \'स्टोरेज एक्सेस फ्रेमवर्क\' आपको बाहरी एसडी कार्ड पर डाउनलोड करने देता है सेवा चुनें, वर्तमान चुनाव : डिफ़ॉल्ट कियोस्क @@ -483,7 +483,7 @@ %d सेकेंड %d सेकंड्स - देखे गए वीडियो हटायें\? + देखे गए वीडियो हटायें? देखे गए को हटा दें सिस्टम डिफ़ॉल्ट ऐप की भाषा @@ -502,7 +502,7 @@ अनगिनत विडीओज़ 100+ विडीओज़ विवरण - संबंधित स्ट्रीमस + संबंधित आइटम्स टिप्पणियाँ कृपया जांचें लें कि क्या आपके क्रैश पर चर्चा करने वाला मुद्दा पहले से मौजूद है। डुप्लिकेट टिकट बनाते समय, आप हमसे समय लेते हैं जो हम वास्तविक बग को ठीक करने के लिए खर्च कर सकते हैं। गिटहब पर रिपोर्ट करें @@ -584,7 +584,7 @@ डिस्क से सभी डाउनलोड की गई फ़ाइलें मिटाएं\? एंड्रॉइड 10 से शुरू होकर केवल \'स्टोरेज एक्सेस फ्रेमवर्क\' समर्थित है एक इंस्टेंस चुनें - हां, और आंशिक रूप से देखे गए वीडियो भी + हां, और आंशिक रूप से देखे गए वीडियो भी फ़ीड लोड हो रही है… फ़ीड अपडेट चरणसीमा फ़ीड लोड करने में त्रुटि हूई @@ -671,8 +671,7 @@ चैनल विवरण दिखाएं आइटम्स का असल अपलोड समय दिखाएं सेवाओं से मूल पाठ स्ट्रीम आइटम में दिखाई देंगे - प्लेलिस्ट में शामिल, पहले और बाद में देखे जा चुके वीडियो हटा दिए जाएंगे। -\nक्या यक़ीनन आप ऐसा चाह्ते हैं\? इसे असंपादित नहीं किया जा सकेगा! + प्लेलिस्ट में शामिल, पहले और बाद में देखे जा चुके वीडियो हटा दिए जाएंगे। \nक्या यक़ीनन आप ऐसा चाह्ते हैं? इसे असंपादित नहीं किया जा सकेगा! %d मिनट %d मिनट्स @@ -828,4 +827,26 @@ चैनल समूह पेज पसंद यूट्यूब अस्थायी प्लेलिस्ट के रूप में साझा करें + एंटरी मिटा दी गई + फाईल डिलीट करें + एंटरी मिटाऐं + %sहज़ार + पॉपअप प्लेयर इस्तेमाल करने के लिए, कृपया नीचे दिए गए Android सेटिंग्स मेनू में %1$s चुनें और %2$s चालू करें। + “अन्य ऐप्स पर डिस्प्ले की अनुमति दें” + %sमिलीअन + %sअरब + अकाउंट बंद कर दिया गया\n\n%1$s यह कारण बताता है: %2$s + साउंडक्लाउड टॉप 50 पेज हटा दिया गया + साउंडक्लाउड ने ओरिजिनल टॉप 50 चार्ट बंद कर दिए हैं। इससे जुड़ा टैब आपके मेन पेज से हटा दिया गया है। + YouTube कंबाइंड ट्रेंडिंग हटा दी गई + YouTube ने 21 जुलाई 2025 से कंबाइंड ट्रेंडिंग पेज बंद कर दिया है। NewPipe ने डिफ़ॉल्ट ट्रेंडिंग पेज को ट्रेंडिंग लाइवस्ट्रीम से बदल दिया है।\n\nआप \"सेटिंग्स > कंटेंट > मेन पेज कंटेंट\" में अलग-अलग ट्रेंडिंग पेज भी चुन सकते हैं। + गेमिंग ट्रेंडस + ट्रेंडिंग पॉडकास्ट + ट्रेंडिंग फिल्में और शो + ट्रेंडिंग संगीत + पले करते समय सर्वर से HTTP error 403 मिला, शायद स्ट्रीमिंग URL एक्सपायर होने या IP बैन की वजह से हुआ + पले करते समय सर्वर से HTTP error %1$s मिला + पले करते समय सर्वर से HTTP error 403 मिला, जो शायद IP बैन या स्ट्रीमिंग URL डीओबफस्केशन की दिक्कतों की वजह से हुआ है + %1$s ने डेटा देने से मना कर दिया, और यह कन्फर्म करने के लिए लॉगिन मांगा कि रिक्वेस्ट करने वाला बोट नहीं है।\n\nहो सकता है कि %1$s ने आपके IP को कुछ समय के लिए बैन कर दिया हो, आप कुछ समय इंतज़ार कर सकते हैं या किसी दूसरे IP पर स्विच कर सकते हैं (जैसे VPN ऑन/ऑफ करके, या WiFi से मोबाइल डेटा पर स्विच करके)। + यह कंटेंट अभी चुने गए देश के कंटेंट के लिए उपलब्ध नहीं है।\n\n\"सेटिंग्स > कंटेंट > डिफ़ॉल्ट कंटेंट देश\" से अपना चुनाव बदलें। diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 77a256ba4..85a2fa367 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -2,7 +2,7 @@ Počni dodirom na povećalo. Objavljeno %1$s - Nije pronađen nijedan player streamova. Želiš li instalirati VLC\? + Nije pronađen nijedan player tokova. Želiš li instalirati VLC? Instaliraj Odustani Otvori u pregledniku @@ -125,7 +125,7 @@ © %1$s od %2$s pod %3$s O aplikaciji i ČPP Licence - Slobodan i mali streaming na Android uređaju. + Slobodan i mali tok na Android uređaju. Pogledaj na GitHubu NewPipe licenca Ako imate ideja za prijevod, promjene u dizajnu, čišćenje koda ili neke veće promjene u kodu, pomoć je uvijek dobro došla. Što više radimo, to bolji postajemo! @@ -160,7 +160,7 @@ %s videa Reproduciraj sve - Nije bilo moguće reproducirati ovaj stream + Nije bilo moguće reproducirati ovaj tok Dogodila se neoporavljiva greška playera Oporavljanje od greške playera Prikaži savjet za držanje @@ -231,7 +231,7 @@ Poništava tvoju trenutačnu povijest, pretplate, playliste i (opcionalno) postavke Izvezi povijest, pretplate, playliste i postavke Izbriši povijest gledanja - Briše povijest reproduciranih streamova i pozicije reprodukcije + Briše povijest reproduciranih tokova i pozicije reprodukcije Izbrisati cijelu povijest gledanja\? Povijest gledanja je izbrisana Izbriši povijest pretraživanja @@ -288,8 +288,8 @@ Bez ograničenja Ograniči rezoluciju tijekom korištenja mobilnih podataka Nijedan - Nije pronađen nijedan player streamova (možeš instalirati VLC za reprodukciju). - Preuzmi datoteku streama + Nije pronađen nijedan player tokova (možeš instalirati VLC za reprodukciju). + Preuzmi datoteku toka Koristi brzo netočno premotavanje Netočno premotavanje omogućuje playeru brže premotavanje uz manju točnost. Premotavanje od 5, 15 ili 25 sekundi s ovime ne radi Otkaži pretplatu @@ -309,8 +309,8 @@ Prikaži pogrešku Izbriši sve podatke web-stranica iz predmemorije Metapodaci su izbrisani - Automatski dodaj sljedeći stream u popisa izvođenja - Nastavi završavati (ne ponavljajući) popis reprodukcija dodavanjem povezanog streama + Automatski dodaj sljedeći tok u popisa izvođenja + Nastavi završavati (ne ponavljajući) popis reprodukcija dodavanjem povezanog toka Zadana zemlja sadržaja Otkrivanje grešaka Obavijest o novoj verziji aplikacije @@ -437,7 +437,7 @@ Ograniči popis preuzimanja Koristi sustavksi birač mapa (SAF) Ukloni pregledano - Ukloni pogledana videa\? + Ukloni pogledana videa? %d sekunda %d sekunde @@ -502,7 +502,7 @@ Obrada feeda u tijeku … Zadnje aktualiziranje feeda: %s Grupe kanala - Da, i djelomično pogledana videa + Da, i djelomično pogledana videa Odaberi jednu instancu Aplikacija će te pitati kamo spremati preuzimanja. \nUključi sustavksi birač mapa (SAF) ako želiš preuzeti na eksternu SD karticu @@ -510,8 +510,7 @@ Napredak je izgubljen, jer je datoteka izbrisana NewPipe se zatvorio tijekom rada s datotekom Stranica playliste - Videa koji su gledani prije i nakon dodavanja u playlistu će se ukloniti. -\nStvarno ih želiš ukloniti\? Ovo je nepovratna radnja! + Videa koji su gledani prije i nakon dodavanja u playlistu će se ukloniti. \nStvarno ih želiš ukloniti? Ovo je nepovratna radnja! Još nema zabilježenih playlista Odaberi playlistu obnavljanje @@ -574,7 +573,7 @@ Obavijest šifriranja videa Obavijesti o napretku šifriranja videa Nedavni - Isključi za skrivanje polja metapodataka s dodatnim podacima o autoru streama, sadržaju streama ili zahtjevu za pretraživanje + Isključi za skrivanje polja metapodataka s dodatnim podacima o autoru toka, sadržaju toka ili zahtjevu za pretraživanje Prikaži metapodatke Povezane stavke Nijedna aplikacija na tvom uređaju ovo ne može otvoriti @@ -643,9 +642,9 @@ Za ukljanjanje stavki povuci ih Prikaži indikatore slike - Preuzimanje je gotovo + %s preuzimanje je gotovo %s preuzimanja su gotova - %s preuzimanja su gotova + %s preuzimanja je gotovo Pokreni glavni player u cjeloekranskom prikazu Dodaj u popis kao sljedeći @@ -670,23 +669,23 @@ Došlo je do greške, pogledaj obavijest Prekini rad playera Obavijest playera - Konfiguriraj obavijest trenutačno reproduciranog streama + Konfiguriraj obavijest trenutačno reproduciranog toka Obavijesti Novi videozapisi - Obavijesti novih streamova od pretplaćenih kanala + Obavijesti novih tokova od pretplaćenih kanala Želiš li izbrisati sve preuzete datoteke\? Obavijesti su isljučene Pretplatio/la si se na ovaj kanal , Uključi/isključi sve Bilo kakva mreža - Obavijesti novih streamova pretplaćenih kanala + Obavijesti novih tokova pretplaćenih kanala Prikaži kratku poruku greške - Učitavanje pojedinosti streama … - Pokreni traženje novih streamova + Učitavanje pojedinosti toka … + Pokreni traženje novih tokova Prvjeravanje učestalosti Biblioteka „LeakCanary” nije dostupna - Obavijesti o novim streamovima + Obavijesti o novim tokovima Potrebna mrežna veza Primaj obavijesti Za ovu radnju nije pronađen odgovarajući upravljač datoteka. @@ -698,12 +697,12 @@ Posto Poluton Streamovi koje aplikacija za preuzimanje još ne podržava se ne prikazuju - Eksterni playeri ne podržavaju odabrani stream + Eksterni playeri ne podržavaju odabrani tok Promijenite veličinu intervala učitavanja progresivnog sadržaja (trenutno %s). Niža vrijednost može ubrzati učitavanje - %s novi stream - %s nova streama - %s novih streamova + %s novi tok + %s nova toka + %s novih tokova Veličina intervala učitavanja reprodukcije Nepoznat format @@ -830,4 +829,36 @@ Uvijek koristi ExoPlayer postavku zaobilaženja videa za izlaznu površinu Kartice za dohvaćanje prilikom aktualiziranja feeda. Ova opcija nema učinka ako se kanal aktualizira pomoću brzog modusa. sekundarno + Pretraži %1$s + Pretraži %1$s (%2$s) + Popisi izvođenja + Da biste koristili Popup Player, odaberite %1$s u sljedećem izborniku postavki Androida i omogućite %2$s. + \"Dopusti prikaz preko drugih aplikacija\" + %sK + %sM + %sB + Izbriši datoteku + Obriši unos + Odaberite grupu feedova + Još nije stvorena nijedna grupa feedova + Stranica grupe kanala + Račun ukinut\n\n%1$s navodi ovaj razlog: %2$s + Ovo zaobilazno rješenje oslobađa i ponovno instancira video kodeke kada dođe do promjene površine, umjesto da se površina izravno postavlja na kodek. Već se koristi od strane ExoPlayera na nekim uređajima s ovim problemom, ova postavka ima učinak samo na Androidu 6 i novijim verzijama.\n\nOmogućavanje ove opcije može spriječiti pogreške reprodukcije prilikom prebacivanja trenutnog video playera ili prebacivanja na cijeli zaslon + Lajkovi + Podijeli kao privremenu playlistu na YouTubeu + Postavke u izvozu koji se uvozi koriste ranjivi format koji je zastario od verzije NewPipe 0.27.0. Provjerite je li izvoz koji se uvozi iz pouzdanog izvora i u budućnosti radije koristite samo izvoze dobivene iz NewPipe 0.27.0 ili novije verzije. Podrška za uvoz postavki u ovom ranjivom formatu uskoro će biti potpuno uklonjena, a zatim stare verzije NewPipea više neće moći uvoziti postavke izvoza iz novih verzija. + Stranica SoundCloud Top 50 uklonjena + SoundCloud je ukinuo originalne Top 50 ljestvice. Odgovarajuća kartica je uklonjena s vaše glavne stranice. + Uklonjeni kombinirani trendovi na YouTubeu + YouTube je ukinuo kombiniranu stranicu s trendovima od 21. srpnja 2025. NewPipe je zamijenio zadanu stranicu s trendovima s trendovima prijenosa uživo.\n\nTakođer možete odabrati različite stranice s trendovima u \"Postavke > Sadržaj > Sadržaj glavne stranice\". + Trendovi u igrama + Trendovi podcasti + Trendovi u filmovima i serijama + Glazba u trendu + Unos izbrisan + HTTP greška 403 primljena od poslužitelja tijekom reprodukcije, vjerojatno uzrokovana istekom URL-a za streaming ili zabranom IP adrese + HTTP greška %1$s primljena od poslužitelja tijekom reprodukcije + HTTP greška 403 primljena od poslužitelja tijekom reprodukcije, vjerojatno uzrokovana zabranom IP adrese ili problemima s deobfuskacijom URL-a za streaming + %1$s je odbio dati podatke, tražeći prijavu kako bi potvrdio da podnositelj zahtjeva nije bot.\n\nVašu IP adresu je možda privremeno zabranio %1$s, možete pričekati neko vrijeme ili se prebaciti na drugu IP adresu (na primjer uključivanjem/isključivanjem VPN-a ili prebacivanjem s WiFi-ja na mobilne podatke). + Ovaj sadržaj nije dostupan za trenutno odabranu zemlju sadržaja.\n\nPromijenite odabir u \"Postavke > Sadržaj > Zadana zemlja sadržaja\". diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index cf0e9da04..ad5ac913d 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -49,7 +49,7 @@ Jelentés Információ: Ez történt: - Saját hozzászólás (angolul): + Saját megjegyzés (angolul): Részletek: Elnézést, valami balul sült el. Elnézést, ennek nem kellett volna megtörténnie. @@ -90,7 +90,7 @@ Néhány felbontásnál eltávolítja a hangot Feliratkozás Feliratkozva - További infó + További információ Felugró ablak alapértelmezett felbontása Magasabb felbontások megjelenítése Csak bizonyos eszközök tudnak 2K/4K-s videókat lejátszani @@ -219,11 +219,11 @@ Legtöbbet lejátszott Főoldal tartalma Üres oldal - Kioszk oldal + Témagyűjtemények Csatornaoldal Válasszon egy csatornát Még nincs csatornafeliratkozás - Válasszon egy kioszkot + Válasszon egy témagyűjteményt Exportálva Importálva Nem érvényes ZIP-fájl @@ -529,13 +529,13 @@ Fiók megnyitása Csatorna részleteinek megjelenítése Tartsa a sorba állításhoz - Alapértelmezett kioszk + Alapértelmezett témagyűjtemény A NewPipe egy copyleft szabad szoftver: tetszése szerint felhasználhatja, tanulmányozhatja, megoszthatja és fejlesztheti. Egész pontosan a Free Software Foundation által kiadott GNU General Public License 3-as, vagy (választható módon) újabb verziójának feltételei szerint módosíthatja vagy adhatja tovább. Megoldás Nyomja meg a „Kész” gombot, ha megoldotta Ujjlenyomat számítása Kapcsolódó elemek - Ellenőrizze, hogy létezik-e már olyan jegy, amely az összeomlásával foglalkozik. Ha duplikált jegyet ad fel, akkor olyan időt vesz el tőlünk, amelyet a hiba javítására tudnánk fordítani. + Ellenőrizze, hogy létezik-e már hibajegy a leírt összeomlással kapcsolatban. Az ismétlődő hibajegyek létrehozása feleslegesen elvonja az erőforrásokat a hiba tényleges javításától. Minimalizálás alkalmazásváltáskor Helyi keresési javaslatok Távoli keresési javaslatok @@ -620,9 +620,8 @@ Címkék Adatvédelem Gyors mód letiltása - Igen, és távolítsa el a részben megnézett videókat is - A videók, melyeket már megnézett miután a lejátszási listához adta őket, el lesznek távolítva. -\nBiztos benne\? Ez nem vonható vissza! + Igen, és távolítsa el a részben megnézett videókat is + A videók, melyeket már megnézett miután a lejátszási listához adta őket, el lesznek távolítva. \nBiztos benne? Ez nem vonható vissza! A szolgáltatásokból származó eredeti szövegek láthatók lesznek a közvetítési elemeken Lejátszó összeomlasztása Képjelölők megjelenítése @@ -632,7 +631,7 @@ Frissítések keresése Ne jelenítse meg Megnézettek eltávolítása - Eltávolítja a megnézett videókat\? + Eltávolítja a megnézett videókat? %1$s letöltés törölve %1$s letöltés törölve @@ -724,7 +723,7 @@ Eltávolítja az összes ismétlődő közvetítést ebből a lejátszólistáról\? eredeti Kezdőlap pozíciója - A médiacsatornázás alapértelmezés szerint le van tiltva a saját eszközén, mivel a saját eszközmodellje nem támogatja azt. + A médiacsatornázás alapértelmezetten le van tiltva az eszközén, mivel a saját eszközmodellje nem támogatja azt. Kezdőlapválasztó alulra helyezése Nincs élő közvetítés Nincs adatfolyam @@ -801,4 +800,24 @@ Kedvelések SoundCloud Top 50 oldal eltávolítva A SoundCloud megszüntette az eredeti Top 50-es listákat. A megfelelő lap el lett távolítva a főoldalról. + YouTube „felkapott lapok” eltávolítva + A YouTube 2025. július 21-től megszüntette a „felkapott” oldalt. A NewPipe a korábbi alapértelmezett „felkapott” oldalt felkapott élő közvetítésekkel helyettesítette.\n\nA „Beállítások > Tartalom > Főoldal tartalma” menüpontban különböző felkapott lapokat is kiválaszthat. + Felkapott játékok + Felkapott podcastok + Felkapott filmek és sorozatok + Felkapott zenék + %se + %sm + %sM + A felugró ablakos lejátszó használatához válassza ki a(z) %1$s elemet a következő Android beállítások menüben, és engedélyezze a(z) %2$s elemet. + „Megjelenítés a többi alkalmazás fölött” engedélyezése + Fájl törlése + Bejegyzés törlése + Bejegyzés törölve + Fiók megszüntetve\n\n%1$s az alábbi ok miatt: %2$s + A lejátszás közben a kiszolgáló 403-as HTTP-hibát adott vissza, valószínűleg a közvetítési hivatkozás érvényessége lejárt vagy a IP-tiltás miatt + HTTP-hiba (%1$s) érkezett a kiszolgálótól a lejátszás során + HTTP 403-as hiba érkezett a kiszolgálótól a lejátszás közben, valószínűleg IP-tiltás vagy a közvetítési hivatkozás feloldási problémák miatt + %1$s visszautasította az adatok szolgáltatását, és bejelentkezést kér annak megerősítésére, hogy a kérés nem robot által érkezik.\n\nElőfordulhat, hogy az IP-címét ideiglenesen letiltotta %1$s, várhat egy keveset, vagy váltson egy másik IP-címre (például VPN be-/kikapcsolásával, vagy Wi-Fi-ről mobiladat-forgalomra váltva). + Ez a tartalom a jelenleg kiválasztott tartalom országában nem elérhető.\n\nVáltoztassa meg a „Beállítások > Tartalom >Tartalom alapértelmezett országa” menüpontban. diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index d0bc29057..3b00674a5 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -163,10 +163,9 @@ Chronologia de recerca delite Exportar le chronologia, subscriptiones, listas de reproduction e configurationes Reimplaciar tu chronologia, subscriptiones e (optionalmente) configurationes currente - Le videos jam observate ante e post de esser addite al lista de reproduction essera removite. -\nSecur que tu vole\? Isto non pote disfacer se! - Si, e le videos partialmente observate - Deler le videos observate\? + Le videos jam observate ante e post de esser addite al lista de reproduction essera removite. \nSecur que tu vole? Isto non pote disfacer se! + Si, e le videos partialmente observate + Deler le videos observate? Deler le videos observate %s visualisation diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 3c3f03192..003994de2 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -478,7 +478,7 @@ Album Lagu Ambil dari langganan aslinya jika tersedia - Buang video yang sudah ditonton\? + Buang video yang sudah ditonton? Buang ditonton Video ini dibatasi usia. \n @@ -486,9 +486,8 @@ Konten ini belum didukung oleh NewPipe. \n \nSemoga akan didukung pada versi berikutnya. - Iya, dan video yang ditonton sebagian - Video yang sudah ditonton sebelum dan sesudah ditambahkan ke daftar putar akan dibuang. -\nApakah Anda yakin\? Ini tidak bisa diurungkan! + Iya, dan video yang ditonton sebagian + Video yang sudah ditonton sebelum dan sesudah ditambahkan ke daftar putar akan dibuang. \nApakah Anda yakin? Ini tidak bisa diurungkan! Batal bisukan Bisukan Apakah Anda merasa pemuatan langganan sangat lambat\? Jika iya, coba nyalakan pemuatan cepat (Anda bisa mengubahnya di dalam pengaturan atau dengan menekan tombol di bawah) @@ -816,4 +815,24 @@ Suka Halaman Top 50 SoundCloud dihapus SoundCloud telah menghentikan dukungan tangga lagu Top 50. Tab terkait telah dihapus dari halaman utama Anda. + Untuk menggunakan Pemutar Sembul, silakan pilih %1$s dalam menu pengaturan Android berikut dan aktifkan %2$s. + \"Izinkan menampilkan di atas aplikasi\" + Hapus berkas + Hapus entri + Akun dihapus\n\n%1$s menyediakan alasan ini: %2$s + Tren terpadu YouTube dihilangkan + YouTube telah mengakhiri halaman tren terpadu pada 21 Juli 2025. NewPipe mengganti halaman tren bawaan dengan tren siaran langsung.\n\nAnda juga dapat memilih halaman tren berbeda dalam \"Pengaturan > Konten > Konten di halaman utama\". + Tren permainan + Tren siniar + Tren film dan acara + Tren musik + Entri dihapus + Kesalahan HTTP 403 diterima dari server saat memutar, dapat disebabkan oleh URL streaming kedaluwarsa atau pemblokiran IP + Kesalahan HTTP %1$s diterima dari server saat memutar + Kesalahan HTTP 403 diterima dari server saat memutar, dapat disebabkan oleh pemblokiran IP atau masalah deobfuskasi URL streaming + %1$s menolak memberikan data, meminta login untuk memastikan peminta bukan bot.\n\nAlamat IP Anda mungkin telah diblokir sementara oleh %1$s, Anda dapat menunggu beberapa saat atau beralih ke alamat IP yang berbeda (misalnya dengan mengaktifkan/menonaktifkan VPN, atau beralih dari WiFi ke data seluler). + Konten ini tidak tersedia untuk negara konten yang saat ini dipilih.\n\nUbah pilihan Anda dari “Pengaturan > Konten > Negara konten bawaan”. + %sK + %sM + %sB diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 9daa67dbf..9473f5f92 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -673,9 +673,8 @@ %1$s sóttum skrám eytt Fjöldi tilrauna áður en hætt er við niðurhal - Myndskeiðum sem skoðuð voru áður eða eftir að þeim var bætt við spilunarlistann verður eytt. -\nErtu viss? Það er ekki hægt að afturkalla þetta! - Já og skoðuð að hluta + Myndskeiðum sem skoðuð voru áður eða eftir að þeim var bætt við spilunarlistann verður eytt. \nErtu viss? Það er ekki hægt að afturkalla þetta! + Já og skoðuð að hluta Nota RSS ef tiltækt Hjartað af höfunda Slökkt er á tilkynningum @@ -809,4 +808,16 @@ Líkar við Topp 50 síða SoundCloud fjarlægð SoundCloud er hætt með Topp 50 vinsældalistann. Viðkomandi flipi hefur verið fjarlægður af aðalsíðunni þinni. + %sK + %sM + %sB + Vinsælir leikir + Vinsæl hlaðvörp + Vinsælar kvikmyndir og þættir + Vinsæl tónlist + \"Leyfa birtingu ofan á öðrum forritum\" + Eyða skrá + Eyða færslu + Aðgangi lokað\n\n%1$s gefur þessa ástæðu: %2$s + Færslu eytt diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 459bab3d3..10a3c976f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -517,10 +517,9 @@ Questo video ha restrizioni di età. \n \nAttivare «%1$s» nelle Impostazioni per poterlo vedere. - Sì, anche quelli visualizzati parzialmente - I video che sono stati visti prima e dopo essere stati aggiunti alla playlist verranno rimossi. -\nProcedere\? L\'azione è irreversibile! - Rimuovere i video già visti\? + Sì, anche quelli visualizzati parzialmente + I video che sono stati visti prima e dopo essere stati aggiunti alla playlist verranno rimossi. \nProcedere? L\'azione è irreversibile! + Rimuovere i video già visti? Rimuovi elementi visti Attiva la \"Modalità con restrizioni\" di YouTube I testi originali dei servizi saranno visibili negli elementi video @@ -844,4 +843,24 @@ Mi piace Pagina Top 50 di SoundCloud rimossa SoundCloud ha dismesso i grafici Top 50 originali. La scheda relativa è stata rimossa dalla pagina principale. + %sK + %sMilio. + %sMilia. + Rimosse tendenze combinate YouTube + YouTube ha interrotto la pagina di tendenza combinata il 21 luglio 2025. NewPipe ha sostituito la pagina di tendenza predefinita con le dirette in tendenza.\n\nPuoi anche selezionare diverse pagine di tendenza in \"Impostazioni > Contenuto > Contenuto della pagina principale\". + Giochi in tendenza + Podcast in tendenza + Film e spettacoli in tendenza + Musica in tendenza + Per usare il riproduttore popup, seleziona %1$s nel seguente menu delle impostazioni Android e attiva %2$s. + “Consenti la visualizzazione sopra altre app” + Elimina file + Elimina voce + Account eliminato\n\n%1$s fornisce questa motivazione: %2$s + Voce eliminata + Errore HTTP 403 ricevuto dal server durante la riproduzione, probabilmente causato dalla scadenza dell\'URL in streaming o da un divieto dell\'IP + Errore HTTP %1$s ricevuto dal server durante la riproduzione + Errore HTTP 403 ricevuto dal server durante la riproduzione, probabilmente causato da un divieto dell\'IP o problemi di de-offuscamento dell\'URL in streaming + %1$s ha rifiutato di fornire i dati, chiedendo un accesso per confermare che il richiedente non sia un bot.\n\nIl tuo IP potrebbe essere stato temporaneamente vietato da %1$s, puoi aspettare un po\' di tempo o passare ad un IP diverso (ad esempio accendendo/spegnendo una VPN, o passando dal WiFi ai dati mobili). + Questo contenuto non è disponibile per il Paese dei contenuti attualmente selezionato.\n\nModifica la selezione da \"Impostazioni > Contenuti > Paese dei contenuti predefinito\". diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 3274062b5..d78a06547 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -497,9 +497,8 @@ この動画には年齢制限があります。 \n \n閲覧したい場合、設定から \"%1$s\" を有効化してください。 - プレイリストに追加される前も追加された後も視聴した動画はプレイリストから削除されます。 -\nよろしいですか?この操作は元に戻せません! - はい、部分的に視聴した動画も削除します + プレイリストに追加される前も追加された後も視聴した動画はプレイリストから削除されます。 \nよろしいですか?この操作は元に戻せません! + はい、部分的に視聴した動画も削除します 視聴済みの動画を削除しますか? 視聴済みを削除 サービスのオリジナルのテキストが生放送に表示されます diff --git a/app/src/main/res/values-ji/strings.xml b/app/src/main/res/values-ji/strings.xml new file mode 100644 index 000000000..55344e519 --- /dev/null +++ b/app/src/main/res/values-ji/strings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index b27443344..61b3ee523 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -482,8 +482,8 @@ აპლიკაციის ენა სისტემის ნაგულისხმევი ნანახის ამოღება - წაშალოთ ნანახი ვიდეოები\? - დიახ, და ნაწილობრივ ნანახი ვიდეოები + წაშალოთ ნანახი ვიდეოები? + დიახ, და ნაწილობრივ ნანახი ვიდეოები ExoPlayer-ის შეზღუდვების გამო ძიების ხანგრძლივობა დაყენდა %d წამზე %d წამი @@ -655,8 +655,7 @@ იკითხეთ, სად უნდა ჩამოტვირთოთ თქვენ მოგეთხოვებათ სად შეინახოთ თითოეული ჩამოტვირთვა. \n ჩართეთ სისტემის საქაღალდის ამომრჩევი (SAF), თუ გსურთ ჩამოტვირთოთ გარე SD ბარათზე - ვიდეოები, რომლებიც უყურეთ დასაკრავ სიაში დამატებამდე და მის შემდეგ, წაიშლება. -\n დარწმუნებული ხართ\? ამის გაუქმება შეუძლებელია! + ვიდეოები, რომლებიც უყურეთ დასაკრავ სიაში დამატებამდე და მის შემდეგ, წაიშლება. \n დარწმუნებული ხართ? ამის გაუქმება შეუძლებელია! NewPipe არის copyleft უფასო პროგრამული უზრუნველყოფა: თქვენ შეგიძლიათ გამოიყენოთ, შეისწავლოთ, გააზიაროთ და გააუმჯობესოთ იგი სურვილისამებრ. კონკრეტულად თქვენ შეგიძლიათ გადაანაწილოთ და/ან შეცვალოთ იგი GNU-ს ზოგადი საჯარო ლიცენზიის პირობებით, როგორც ეს გამოქვეყნებულია თავისუფალი პროგრამული უზრუნველყოფის ფონდის მიერ, ლიცენზიის მე-3 ვერსიით, ან (თქვენი სურვილისამებრ) ნებისმიერი შემდგომი ვერსიით. ავტო ცარიელი გვერდი @@ -737,4 +736,60 @@ არჩიე თავდაპირველი ხმის ჩანაწერი ხმა: %s ხმის ჩანაწერი + დიახ + არა + %1$s-ის ძიება + მოძებნეთ %1$s %2$s + დასაკრავი სიები + ქვემოთ მოცემული თითოეული შეტყობინების მოქმედების რედაქტირებისთვის მასზე შეხებით აირჩიეთ. პირველი სამი მოქმედება (დაკვრა/პაუზა, წინა და შემდეგი) სისტემის მიერ არის დაყენებული და მათი მორგება შეუძლებელია. + აღწერილობითი აუდიოს უპირატესობა + სარეზერვო ასლის შექმნა და აღდგენა + მთავარი ჩანართის ამომრჩევის ქვემოთ გადატანა + მთავარი ჩანართების პოზიცია + ამომხტარი ფანჯრის გამოსაყენებლად, გთხოვთ, აირჩიოთ %1$s შემდეგ Android პარამეტრების მენიუში და ჩართოთ %2$s. + “სხვა აპლიკაციებზე ჩვენების დაშვება“ + %sათასი + %sმლნ + %sმლრდ + ნაკადები არ არის + პირდაპირი ტრანსლაციები არ არის + ფაილის წაშლა + ჩანაწერის წაშლა + აირჩიეთ არხის ჯგუფი + არხის ჯგუფი ჯერ არ შექმნილა + მედიის გვირაბირება თქვენს მოწყობილობაზე ნაგულისხმევად გამორთულია, რადგან თქვენი მოწყობილობის მოდელი, როგორც ცნობილია, მას არ უჭერს მხარს. + NewPipe-ს შეუძლია დროდადრო ავტომატურად შეამოწმოს ახალი ვერსიები და შეგატყობინოთ, როგორც კი ისინი ხელმისაწვდომი გახდება.\nგსურთ ამის ჩართვა? + პარამეტრების გადაყენება + ყველა პარამეტრის ნაგულისხმევ მნიშვნელობებზე დაბრუნება + ყველა პარამეტრის გადატვირთვა გააუქმებს თქვენს მიერ არჩეულ ყველა პარამეტრს და გადატვირთავს აპლიკაციას.\n\nდარწმუნებული ხართ, რომ გსურთ გაგრძელება? + მოწყობილობაზე საკმარისი თავისუფალი ადგილი არ არის + არხის ჯგუფის გვერდი + არხის ჩანართების მოძიება + არხის განახლებისას გამოსატანი ჩანართები. ამ პარამეტრს არანაირი ეფექტი არ აქვს, თუ არხი სწრაფი რეჟიმის გამოყენებით განახლდება. + ანგარიში შეწყვეტილია\n\n%1$s ამ მიზეზს იძლევა: %2$s + მინიატურები + ამტვირთავის ავატარები + ქვეარხის ავატარები + ავატარები + ბანერები + გამომწერები + ამ ნაკადში აუდიო ჩანაწერი უკვე უნდა იყოს წარმოდგენილი + გარე პლეერებისთვის აუდიო ჩანაწერის არჩევა + უცნობი + ExoPlayer-ის პარამეტრები + ExoPlayer-ის ზოგიერთი პარამეტრის მართვა. ამ ცვლილებების ძალაში შესასვლელად მოთამაშის გადატვირთვაა საჭირო. + გამოიყენეთ ExoPlayer-ის დეკოდერის სარეზერვო ფუნქცია + ჩართეთ ეს პარამეტრი, თუ დეკოდერის ინიციალიზაციის პრობლემები გაქვთ, რაც, თუ პირველადი დეკოდერების ინიციალიზაცია ვერ მოხერხდა, დაბალი პრიორიტეტის მქონე დეკოდერებს ეხება. ამან შეიძლება გამოიწვიოს დაკვრის დაბალი შესრულება, ვიდრე პირველადი დეკოდერების გამოყენებისას. + ყოველთვის გამოიყენეთ ExoPlayer-ის ვიდეო გამომავალი ზედაპირის პარამეტრების ალტერნატიული გადაწყვეტა + ეს გამოსავალი ათავისუფლებს და ხელახლა ააქტიურებს ვიდეო კოდეკებს ზედაპირის ცვლილებისას, ზედაპირის პირდაპირ კოდეკზე დაყენების ნაცვლად. ეს პარამეტრი უკვე გამოიყენება ExoPlayer-ის მიერ ზოგიერთ მოწყობილობაზე, რომელსაც ეს პრობლემა აქვს, და მოქმედებს მხოლოდ Android 6-ზე და უფრო მაღალ ვერსიებზე.\n\nამ პარამეტრის ჩართვამ შეიძლება თავიდან აიცილოს დაკვრის შეცდომები მიმდინარე ვიდეო პლეერის გადართვისას ან სრულ ეკრანზე გადართვისას. + თამაშების ტრენდები + ტრენდული პოდკასტები + ტრენდული ფილმები და შოუები + ტრენდული მუსიკა + ჩანაწერი წაშლილია + დაკვრის დროს სერვერიდან მიღებული HTTP შეცდომა 403, სავარაუდოდ, გამოწვეული სტრიმინგის URL-ის ვადის გასვლით ან IP აკრძალვით. + დაკვრის დროს სერვერიდან მიღებული HTTP შეცდომა %1$s + დაკვრის დროს სერვერიდან მიღებული HTTP შეცდომა 403, სავარაუდოდ, გამოწვეულია IP აკრძალვით ან სტრიმინგის URL-ის დებფუსკაციის პრობლემებით. + %1$s-მა უარი თქვა მონაცემების მიწოდებაზე და ითხოვა შესვლა იმის დასადასტურებლად, რომ მომთხოვნი რობოტი არ არის.\n\nშესაძლოა, თქვენი IP მისამართი დროებით აიკრძალა %1$s-ის მიერ, შეგიძლიათ დაელოდოთ ცოტა ხანს ან გადახვიდეთ სხვა IP მისამართზე (მაგალითად, VPN-ის ჩართვით/გამორთვით, ან WiFi-დან მობილურ მონაცემებზე გადართვით). + ეს კონტენტი ამჟამად არჩეული კონტენტის ქვეყნისთვის მიუწვდომელია.\n\nშეცვალეთ თქვენი არჩევანი „პარამეტრები > კონტენტი > ნაგულისხმევი კონტენტის ქვეყანა“-დან. diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index 0ded7974c..29db74172 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -7,9 +7,9 @@ Sbedd asnas n Kore yexxuṣen\? Sbedd Asider - Isidar - Isidar - Iɣewwaṛen + Isadaren + Isadaren + Iɣewwaren Akter… Tulya n telɣut… Awurman diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml index 24bc5574e..f8da8d1a7 100644 --- a/app/src/main/res/values-kmr/strings.xml +++ b/app/src/main/res/values-kmr/strings.xml @@ -355,10 +355,9 @@ %d çirkeyan Ji ber astengiyên ExoPlayer dema lêgerînê li %d çirkeyan hate saz kirin - Erê, û bi qismî vîdyoyan temaşe kir - Vîdyoyên ku berî û piştî ku li lîsteya lîsteyê hatine zêdekirin hatine temaşekirin, dê werin rakirin. -\nPiştrastin\? Ev nayê betal kirin! - Vîdyoyên temaşekirî rakin\? + Erê, û bi qismî vîdyoyan temaşe kir + Vîdyoyên ku berî û piştî ku li lîsteya lîsteyê hatine zêdekirin hatine temaşekirin, dê werin rakirin. \nPiştrastin? Ev nayê betal kirin! + Vîdyoyên temaşekirî rakin? Jê temaşe rakin Pergala wekî ku heyî Zimanê appê diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 6a7e463a1..39a985a96 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -24,7 +24,7 @@ 다운로드 다음/유사한 비디오 표시 지원하지 않는 URL입니다 - 기본 컨텐츠 언어 + 기본 콘텐츠 언어 비디오 및 오디오 비디오 재생, 구간: 업로더 썸네일 @@ -42,13 +42,13 @@ 백그라운드에서 재생 중 네트워크 오류 돋보기를 탭하여 시작합니다. - 컨텐츠 - 연령 제한 컨텐츠 보여주기 + 콘텐츠 + 연령 제한 콘텐츠 보여주기 라이브 오류 모든 썸네일을 불러올 수 없습니다 웹사이트를 가져올 수 없습니다 - 컨텐츠를 사용할 수 없습니다 + 콘텐츠를 사용할 수 없습니다 다운로드 메뉴를 설정할 수 없습니다 죄송합니다. 오류가 발생했습니다. 이메일을 통해 보고 @@ -284,7 +284,7 @@ 영상과 소리 분리 (왜곡이 발생할 수 있음) 다운로드 가능한 스트림이 없습니다 선호하는 열기 동작 - 컨텐츠를 열 때 사용할 기본 동작 — %s + 콘텐츠를 열 때 사용할 기본 동작 — %s 자막 플레이어 자막 글자 크기와 배경 스타일을 수정합니다. 적용하려면 앱을 다시 시작해야 합니다 채널 @@ -480,7 +480,7 @@ %d초 - 시청 기록을 지우겠습니까\? + 시청 기록을 지우겠습니까? 시청 기록 지우기 재생목록 실행 URL을 인식할 수 없습니다. 다른 앱으로 여시겠습니까\? @@ -589,7 +589,7 @@ %s 다운로드 완료 앱 언어 - 예, 부분적으로 본 비디오 + 예, 부분적으로 본 비디오 카테고리 %s에 의해 아래에서 선호하는 어두운 테마를 선택할 수 있습니다 @@ -659,8 +659,7 @@ 구독 선택 일부 서비스에서 사용할 수 있으며 일반적으로 훨씬 빠르지만 제한된 양의 항목과 종종 불완전한 정보를 반환할 수 있습니다 (예: 기간 없음, 항목 유형, 라이브 상태 없음) 안드로이드 10부터 \'저장영역 접속 프레임워크\'만 지원됩니다 - 재생 목록에 추가되기 전과 후에 시청한 동영상은 제거됩니다. -\n확실합니까\? 이것은 취소 할 수 없습니다! + 재생 목록에 추가되기 전과 후에 시청한 동영상은 제거됩니다. \n확실합니까? 이것은 취소 할 수 없습니다! 화면 자동 회전이 잠겨 있는 경우 미니 플레이어에서 동영상을 시작하지 말고 바로 전체 화면 모드로 재생하세요. 전체 화면을 종료해서 미니 플레이어를 이용할 수도 있습니다 공식 라디오 @@ -805,4 +804,25 @@ 설정 초기화 모든 설정을 기본값으로 초기화 + YouTube 임시 재생목록으로 공유 + SoundCloud Top 50 페이지가 삭제되었습니다 + SoundCloud에서 더 이상 기존 Top 50 차트를 제공하지 않습니다. 해당하는 탭이 메인 페이지에서 제거되었습니다. + %s천 + %s백만 + %s십억 + 파일 삭제 + 피드 그룹 선택 + 피드 그룹을 생성하지 않았습니다 + 채널 그룹 페이지 + 계정 정지됨\n\n%1$s에서 제공한 이유: %2$s + 재생목록 + %1$s 검색 + %1$s 검색 (%2$s) + \"다른 앱 위에 표시 허용\" + YouTube 통합 인기 급상승 동영상이 삭제되었습니다 + YouTube에서 2025년 7월 21일부로 더 이상 통합 인기 급상승 동영상을 제공하지 않습니다. NewPipe에서는 기본 인기 급상승 페이지를 인기 급상승 실시간 페이지로 교체했습니다.\n\n\"설정 > 콘텐츠 > 메인 화면의 내용\"에서 다른 인기 급상승 페이지를 선택할 수 있습니다. + 인기 급상승 게임 + 인기 급상승 팟캐스트 + 인기 급상승 영화 및 쇼 + 인기 급상승 음악 diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index 3dc51fcc8..e556fcf26 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -499,9 +499,8 @@ هونەرمەندەکان ئەلبوومەکان گۆرانییەکان - بەڵێ، لەگەڵ ڤیدیۆ تەماشاکراوەکانەوە - ئەو ڤیدیۆیانەی پێشتر سەیرت کردوون و دواتر زیادت کردوون بۆ لیستەلێدان دەسڕێنەوە. -\nئایا دڵنیایت؟ ئەمە ناگەڕێنرێتەوە! + بەڵێ، لەگەڵ ڤیدیۆ تەماشاکراوەکانەوە + ئەو ڤیدیۆیانەی پێشتر سەیرت کردوون و دواتر زیادت کردوون بۆ لیستەلێدان دەسڕێنەوە. \nئایا دڵنیایت؟ ئەمە ناگەڕێنرێتەوە! ڤیدیۆ تەماشاکراوەکان بسڕێنەوە؟ سڕینەوەی تەماشاکراوەکان دەقە بنچینەییەکان لە خزمەتگوزارییەکانەوە لە بابەتی پەخشەکاندا دیار دەبن diff --git a/app/src/main/res/values-lmo/strings.xml b/app/src/main/res/values-lmo/strings.xml new file mode 100644 index 000000000..1f18b248a --- /dev/null +++ b/app/src/main/res/values-lmo/strings.xml @@ -0,0 +1,40 @@ + + + Pigia la lente per inziaa. + Canai + Mandad fœra el %1$s + Installa + Scassa + Va ben + + No + Derva ind el browser + Marca tant\'mè vardad + Derva a fenestra + Derva con + Spantega + Descarga + Cerca + Cerca %1$s + Cerca %1$s (%2$s) + Impostazione + Vœlevet dir \"%1$s\"? + Adree a far vider i resultads per: %s + Spantega con + Al tira via el son ind una quai resoluzion + Inscrivess + Inscrivud + Tira via inscrizion + Tœvuda via l\'inscrizion + L\'è stait minga possibil de mudar l\'inscrizion + L\'è stait minga possibil d\'atualizar l\'inscrizion + Fà vider informazione + Inscrizione + Cerniss sqeda + Fond + Fenestra + Jonta a + Cartella dei video descargads + I video descargads inn rejistrads qì + Cerniss una cartella per i fail video + diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 91c8005ce..70700bb5d 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -409,7 +409,7 @@ Užmegzti saugaus ryšio nepavyko Riboti raišką naudojant mobilius duomenis Automatiškai atkurti — %s - Taip ir iš dalies žiūrėtus vaizdo įrašus + Taip ir iš dalies žiūrėtus vaizdo įrašus Atstatyti parsiuntimo nepavyko Pertraukti matuojamuose tinkluose Sumažinti iki iššokančio lango grotuvo @@ -519,8 +519,7 @@ Siekdami laikytis Europos bendrojo duomenų apsaugos reglamento (GDPR), atkreipiame jūsų dėmesį į NewPipe privatumo politiką. Prašome atidžiai ją perskaityti. \nNorėdami išsiųsti mums pranešimą apie klaidą, turite su ja sutikti. Prieinama kai kuriose tarnybose, paprastai yra daug greitesnė, tačiau gali grąžinti ribotą kiekį elementų ir dažnai neišsamią informaciją (pvz., nėra trukmės, elemento tipo, nėra tiesioginės būsenos) - Vaizdo įrašai, kurie buvo peržiūrėti prieš juos įtraukiant į grojaraštį ir po to, kai jie buvo įtraukti į grojaraštį, bus pašalinti. -\nAr tikrai\? To negalima atšaukti! + Vaizdo įrašai, kurie buvo peržiūrėti prieš juos įtraukiant į grojaraštį ir po to, kai jie buvo įtraukti į grojaraštį, bus pašalinti. \nAr tikrai? To negalima atšaukti! Tai \"SoundCloud Go+\" kūrinys, bent jau jūsų šalyje, todėl jo negalima transliuoti ar atsisiųsti per \"NewPipe\". Šio turinio \"NewPipe\" dar nepalaiko. \n @@ -564,7 +563,7 @@ Automatinis (įrenginio tema) Programa nulūžo Sukūrė %s - Pašalinti žiūrėtus video\? + Pašalinti žiūrėtus video? Įjungti greitą režimą Kanalo atnaujinimo slenkstis Tuščias grupės pavadinimas @@ -836,4 +835,26 @@ Grojaraščiai Antrinis Dalintis kaip laikinuoju youtube grojaraščiu + Ieškoti %1$s + Ieškoti %1$s (%2$s) + Norėdami įjungti \"Popup Grotuvą\" pasirinkite Android nustatymų meniu pasirinkite %1$s ir įjunkite %2$s. + \"Leisti piešti virš kitų langų\" + %sK + %sM + %sB + Pašalinti failą + Ištrinti įrašą + Pasirinkite kanalo grupę + Dar nėra kanalo grupės + Kanalo grupės puslapis + Paskyra pašalinta\n\n%1$s dėl šios priežasties: %2$s + Mėgsta + SoundCloud Top 50 puslapis pašalintas + SoundCloud nebeteikia Top 50. Šis puslapis pašalintas iš jūsų pagrindinio puslapio. + YouTube sujungti rekomenduojami pašalinti + Žaidimų pasiūlymai + Mėgstami podcasts + Mėgstami filmai ir laidos + Mėgstama muzika + Įrašas pašalintas diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index c769392cf..f36c2aff6 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -39,13 +39,13 @@ Nav atskaņošanas sarakstu pagaidām Izvēlaties atskaņošanas sarakstu Nav kanālu abonamentu pagaidām - Izvēlaties kanālu - Kanālu lapa + Atlasiet kanālu + Kanāls Noklusējuma Kiosks - Kioska Lapa - Tukša Lapa - Kuras cilnes rāda galvenajā lapā - Galvenās lapas saturs + Kioska lapa + Tukša lapa + Kādas cilnes rādīt galvenajā lapā + Galvenā lapa Visvairāk Atskaņotais Pēdējais Atskaņotais Vai jūs vēlaties izdzēst šo lietu no meklēšanas vēstures\? @@ -95,7 +95,7 @@ Faila nosaukums Labi Pārsaukt - Atcelt + Noraidīt Kontrolsumma Izdzēst Radīt @@ -338,10 +338,9 @@ %d sekundes ExoPlayer ierobežojumu dēļ meklēšanas ilgums tika iestatīts uz %d sekundēm - Jā, un daļēji skatītos videoklipus - Videoklipi, kas ir skatīti pirms un pēc pievienošanas atskaņošanas sarakstam, tiks noņemti. -\nVai tu esi pārliecināts\? To nevar atsaukt! - Vai noņemt skatītos videoklipus\? + Jā, un daļēji skatītos video + Video, kas skatīti pirms un pēc pievienošanas atskaņošanas sarakstam, tiks noņemti. \nVai tiešām turpināt? Šo darbību nevarēs atsaukt! + Vai tiešām noņemt skatītos video? Noņemt skatīto System default Lietotnes valoda @@ -479,7 +478,7 @@ Lejupielādēt Turpināt atskaņošanu pēc pārtraukumiem (piemēram, telefona zvana) Turpināt atskaņošanu - Saglabājiet skatītos videoklipus + Uzglabāt skatīto video vēsturi Dzēst datus Rādīt atskaņošanas pozīcijas indikatoru sarakstos Atskaņošanas pozīcija sarakstos @@ -494,7 +493,7 @@ Turpināt atskaņot videoklipus, automātiski pievienojot līdzīgus videoklipus Automātiski atskaņot nākošo videoklipu Kešatmiņas metadati notīrīti - Izdzēst visus kešatmiņā glabātos mājaslapu datus + Izdzēš visus kešatmiņā glabātos vietnes datus Notīrīt kešatmiņas metadatus Attēlu kešatmiņa notīrīta Izslēdziet, lai paslēptu papildus informācijas laukus par video autoru, video saturu vai meklēšanas vaicājuma rezultātu @@ -527,7 +526,7 @@ Netika atrasts video atskaņotājs. Uzstādīt VLC? Publicēts %1$s Nospiediet uz meklēšanas ikonas, lai sāktu. - Iekrāsot paziņojumu + Pielāgot paziņojumu krāsu Nekas Ielādējas Sajaukt @@ -552,7 +551,7 @@ Lejupielādētie audio faili tiek glabāti šeit Audio lejupielādes mape Izvēlaties lejupielādes mapi priekš video failiem - Lejupielādētie video faili tiek glabāti šeit + Lejupielādētās video datnes tiek glabātas šeit Video lejupielādes mape Pievienot Fonā @@ -616,7 +615,7 @@ Rādīt krāsainas lentes virs attēliem, norādot to avotu: sarkana - tīkls, zila - disks, zaļa - atmiņa Ieslēgt teksta atlasīšanu video aprakstā Lejupielādes mape vēl nav iestatīta, izvēlieties noklusējuma lejupielādes mapi - Pārvelciet objektus, lai tos noņemtu + Pavelciet atlasīto elementu pa kreisi vai labi, lai to aizvāktu Lokālie meklēšanas ieteikumi Rādīt attēlu indikatorus Augstas kvalitātes (lielāks) @@ -627,9 +626,7 @@ Sākot ar Android 10, tikai“Krātuves Piekļuves Sistēma” ir atbalstīta Nevarēja ielādēt straumi priekš \'%s\'. Kļūda lādējot plūsmu - Autora konts tika slēgts. -\nNewPipe turpmāk nevarēs ielādēt šo plūsmu. -\nVai vēlaties atteikties no šī kanāla abonēšanas\? + Autora konts tika slēgts.\nNewPipe turpmāk vairs nevarēs ielādēt šī kanāla plūsmas saturu.\nVai tiešām atteikties no šī kanāla abonēšanas? Ātrās straumes režīms nesniedz vairāk informācijas par šo. Izslēgt teksta atlasīšanu video aprakstā Iekšeji @@ -641,7 +638,7 @@ Sarakstā neiekļauts Uzņēmums Servera meklēšanas ieteikumi - Atzīmēt kā skatītu + Atzīmēt kā noskatītu Apstrādā... Var aizņemt kādu laiku Izdzēsa %1$s lejupielāžu @@ -725,7 +722,7 @@ Metadatu ielādēšana… Galvenās cilnes pozīcija Nepazīstams formāts - Daļēji noskatīti + Daļēji skatīti Nav tiešraides Nav pietiekami daudz brīvās vietas uz ierīces Par @@ -826,4 +823,14 @@ Atskaņošanas saraksti Kopīgot kā pagaidu YouTube atskaņošanas sarakstu sekundārais + %s tūkst. + %s milj. + %s mljrd. + Patīk + Pašlaik populāra mūzika + Pašlaik populāras filmas un TV raidījumi + Pašlaik populāri raidieraksti + Pašlaik populārs spēļu nozarē + YouTube pārtrauca piedāvāt apvienoto pašlaik populārs lapu kopš 2025. gada 21. jūlija. NewPipe aizstāja noklusējuma pašlaik populārs lapu ar pašlaik populāras tiešraides.\n\nJūs variet atlasīt arī citas pašlaik populārs lapas zem \"Iestatījumi > Saturs > Galvenā lapa\". + Dzēst datni diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 3a8fa2f07..5ce379216 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -406,7 +406,7 @@ Премести ги основниот селектор на јазичиња најдолу Позиција на основните јазичиња Прикажи информации за каналот - Да, како и делумно изгледаните видеа + Да, како и делумно изгледаните видеа Аудио снимка треба да е веќе присутна во овој стрим %s слушател diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 5a449025e..2fce034d2 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -461,10 +461,9 @@ %d സെക്കൻഡുകൾ എക്സോപ്ലെയർ പരിമിതികൾ കാരണം തിരയൽ ദൈർഘ്യം %d സെക്കൻഡിലേക്ക് സജ്ജമാക്കി - അതെ, അതിന്റെകൂടെ ഭാഗികമായി കണ്ട വീഡിയോകളും - പ്ലേലിസ്റ്റിലേക്ക് ചേർക്കുന്നതിന് മുമ്പും ശേഷവും കണ്ട വീഡിയോകൾ നീക്കംചെയ്യും. -\nനിങ്ങൾക്ക് ഉറപ്പാണോ\? ഇത് പഴയപടിയാക്കാൻ കഴിയില്ല! - കണ്ട വീഡിയോകൾ നീക്കംചെയ്യണോ\? + അതെ, അതിന്റെകൂടെ ഭാഗികമായി കണ്ട വീഡിയോകളും + പ്ലേലിസ്റ്റിലേക്ക് ചേർക്കുന്നതിന് മുമ്പും ശേഷവും കണ്ട വീഡിയോകൾ നീക്കംചെയ്യും. \nനിങ്ങൾക്ക് ഉറപ്പാണോ? ഇത് പഴയപടിയാക്കാൻ കഴിയില്ല! + കണ്ട വീഡിയോകൾ നീക്കംചെയ്യണോ? കണ്ടത് നീക്കംചെയ്യുക സിസ്റ്റം ഡിഫോൾട്ട് അപ്ലിക്കേഷൻ ഭാഷ diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index d5edc2060..404851e6d 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -488,8 +488,8 @@ Artister Album Sanger - Ja, og delvist sette videoer - Fjern sette videoer\? + Ja, og delvist sette videoer + Fjern sette videoer? Fjern sette Opprettet av %s Av %s @@ -526,8 +526,7 @@ Hent fra dedikert strøm når tilgjengelig Tid siden siste oppdatering før et abonnement vurderes utdatert — %s Som følge av begrensninger i ExoPlayer er blafringsdistansen kun %d sekunder - Videoer som har blitt sett før og etter at de er lagt til spillelisten, vil bli fjernet. -\nEr du sikker\? Dette kan ikke angres! + Videoer som har blitt sett før og etter at de er lagt til spillelisten, vil bli fjernet. \nEr du sikker? Dette kan ikke angres! Start avspilling automatisk — %s Kunne ikke gjenkjenne angitt nettadresse. Åpne den med et annet program\? Innholdet støttes ikke enda av NewPipe. diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index b40145aa6..75e113d4e 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -493,10 +493,8 @@ %d मिनेट च्यानल अवतार थम्बनेल - भिडियोहरू जुन प्लेलिस्टमा थपिनु अघि र पछि हेरिएको थियो हटाइनेछ। -\n… -\n के तपाईँ निश्चित हुनुहुन्छ\? यो उल्ट्याउन सकिदैन! - हेरिएका भिडियोहरू हटाउने हो\? + भिडियोहरू जुन प्लेलिस्टमा थपिनु अघि र पछि हेरिएको थियो हटाइनेछ। \n… \n के तपाईँ निश्चित हुनुहुन्छ? यो उल्ट्याउन सकिदैन! + हेरिएका भिडियोहरू हटाउने हो? हेरिसकेको हटाउनुहोस सेवाहरूबाट मूल पाठहरू स्ट्रिम वस्तुहरूमा देखिने छन् आईटमहरूमा मूल समय पहिले देखाउनुहोस् @@ -514,7 +512,7 @@ यो सामग्री अझै NewPipeमा समर्थित छैन। \n… \nआशा छ कि भविष्यको संस्करणमा समर्थित हुनेछ। - हो र आंशिक रूपमा हेरिएको भिडियोहरू + हो र आंशिक रूपमा हेरिएको भिडियोहरू सूचना पाटी रंगिन बनाउनु केहि छैन Buffering हुँदै diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index 3b3277307..148468dd2 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -440,10 +440,9 @@ %d seconden Door beperkingen van ExoPlayer is de zoekduur ingesteld op %d seconden - Ja, en deels bekeken video\'s - Video\'s die zijn bekeken voor, en na, ze werden toegevoegd aan de afspeellijst worden verwijderd. -\nBent u zeker\? Dit kan niet ongedaan gemaakt worden! - Verwijder bekeken video\'s\? + Ja, en deels bekeken video\'s + Video\'s die zijn bekeken voor, en na, ze werden toegevoegd aan de afspeellijst worden verwijderd. \nBent u zeker? Dit kan niet ongedaan gemaakt worden! + Verwijder bekeken video\'s? Verwijder bekeken Systeem standaard App taal @@ -635,4 +634,6 @@ Verkies beschrijvende audio Verkies originele audio Selecteer het oorspronkelijke audiospoor, ongeacht de taal + Zoeken%1$s + Zoeken%1$s(%2$s) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 9f99e3a70..c7aab3577 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -502,10 +502,9 @@ Deze inhoud wordt nog niet ondersteund door NewPipe. \n \nHopelijk zal dit bij een toekomstige versie ondersteund worden. - Ja, en deels bekeken video\'s - Video\'s die zijn bekeken voor, en na ze werden toegevoegd aan de afspeellijst worden verwijderd. -\nWeet u dit zeker\? Deze actie kan niet ongedaan gemaakt worden! - Bekeken video\'s verwijderen\? + Ja, en deels bekeken video\'s + Video\'s die zijn bekeken voor, en na ze werden toegevoegd aan de afspeellijst worden verwijderd. \nWeet u dit zeker? Deze actie kan niet ongedaan gemaakt worden! + Bekeken video\'s verwijderen? ∞ video\'s 100+ video\'s Deze video heeft een leeftijdsbeperking. @@ -825,4 +824,29 @@ Selecteer een feedgroep Kanaalgroep­pagina Nog geen feedgroep geselecteerd + Zoeken met %1$s + Zoeken met %1$s (%2$s) + Vind-ik-leuks + Trending podcasts + Trending games + Trending films en series + Trending muziek + ‘SoundCloud Top 50’-pagina verwijderd + SoundCloud heeft de originele Top 50-hitlijsten stopgezet. Het bijbehorende tabblad is van uw hoofdpagina verwijderd. + YouTube gecombineerde trending verwijderd + YouTube heeft de gecombineerde trending­pagina per 21 juli 2025 stopgezet. NewPipe heeft de standaard­trendingpagina vervangen door de trending livestreams.\n\nU kunt ook andere trending­pagina\'s selecteren via \'Instellingen > Inhoud > Inhoud van de hoofdpagina\'. + %s dznd. + %s mln. + %s mld. + Bestand verwijderen + Item verwijderen + Item verwijderd + Om de Pop-up-speler te gebruiken, selecteert u %1$s in het volgende Android-instellingenmenu en schakelt u %2$s in. + ‘Weergeven vóór andere apps toestaan’ + Account beëindigd\n\n%1$s geeft de volgende reden: %2$s + HTTP-fout 403 ontvangen van de server tijdens het afspelen, waarschijnlijk veroorzaakt door het verlopen van de streaming-url of een ip-blokkade + HTTP-fout %1$s ontvangen van de server tijdens het afspelen + HTTP-fout 403 ontvangen van de server tijdens het afspelen, waarschijnlijk veroorzaakt door een ip-blokkade of problemen met de deobfuscatie van de streaming-url + %1$s weigerde gegevens te verstrekken en vroeg om een login om te bevestigen dat de aanvrager geen bot is.\n\nUw ip-adres is mogelijk tijdelijk geblokkeerd door %1$s. U kunt even wachten of overschakelen naar een ander ip-adres (bijvoorbeeld door een vpn in of uit te schakelen, of door over te schakelen van wifi naar mobiele data). + Deze inhoud is niet beschikbaar voor het momenteel geselecteerde inhouds­land.\n\nWijzig uw selectie via ‘Instellingen > Inhoud > Standaard­land voor inhoud’. diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index caf8509e3..fb6950046 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -592,9 +592,8 @@ ߞߊ߲ߞߋ ߟߊ߫ ߖߏߣߡߊ ߞߊ߬ ߖߌ߬ߦߊ߬ߖߟߎ߬ ߦߋߣߍ߲ ߠߎ߫ ߖߏ߬ߛߌ߫ ؟ ߞߊ߬ ߖߌ߬ߦߊ߬ߖߟߎ߬ ߦߋߣߍ߲ ߠߎ߫ ߖߏ߬ߛߌ߫ - ߦߋߡߍ߲ߕߊ ߟߎ߫ ߖߏ߬ߛߌ߬ߕߐ߫ ߟߋ߬߸ ߡߍ߲ ߠߎ߬ ߡߊߝߍߣߍ߲ߣߍ߲߫ ߊ߬ߟߎ߫ ߝߊ߬ߙߊ ߢߍ߫ ߥߊߟߴߊ߬ߟߎ߫ ߝߊ߬ߙߊ ߞߐ߫ ߕߏߟߏ߲߫ ߛߙߍߘߍ ߟߊ߫. -\nߌ ߟߊߣߍ߲߫ ߊ߬ ߟߊ߫ ؟ ߊ߬ ߕߍߣߊ߬ ߛߋ߫ ߟߊ߫ ߟߊߛߊ߬ߦߌ߬ ߟߊ߫߹ - ߐ߬ߤߐ߲߫߸ ߊ߬ߣߌ߫ ߘߏ߫ ߡߊߝߍߣߍ߲ߣߍ߲߫ ߖߌ߬ߦߊ߬ߖߟߎ ߡߍ߲ ߠߎ߬ ߘߐ߫ + ߦߋߡߍ߲ߕߊ ߟߎ߫ ߖߏ߬ߛߌ߬ߕߐ߫ ߟߋ߬߸ ߡߍ߲ ߠߎ߬ ߡߊߝߍߣߍ߲ߣߍ߲߫ ߊ߬ߟߎ߫ ߝߊ߬ߙߊ ߢߍ߫ ߥߊߟߴߊ߬ߟߎ߫ ߝߊ߬ߙߊ ߞߐ߫ ߕߏߟߏ߲߫ ߛߙߍߘߍ ߟߊ߫. \nߌ ߟߊߣߍ߲߫ ߊ߬ ߟߊ߫ ؟ ߊ߬ ߕߍߣߊ߬ ߛߋ߫ ߟߊ߫ ߟߊߛߊ߬ߦߌ߬ ߟߊ߫߹ + ߐ߬ߤߐ߲߫߸ ߊ߬ߣߌ߫ ߘߏ߫ ߡߊߝߍߣߍ߲ߣߍ߲߫ ߖߌ߬ߦߊ߬ߖߟߎ ߡߍ߲ ߠߎ߬ ߘߐ߫ ߞߵߊ߬ ߓߍ߲߬ ExoPlayer ߟߊ߫ ߛߙߊߕߌ߫ ߛߌ߰ߣߍ߲ ߠߎ߫ ߡߊ߬߸ ߓߐߒߣߐ߬ߘߐ ߛߋ߲߬ߕߊ ߓߘߊ߬ ߞߍ߫ ߝߌ߬ߟߊ߲߬ %d ߘߌ߫ ߡߌ߬ߛߍ߲߬ %d diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index 81184d526..d15afa4fe 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -190,8 +190,7 @@ କିଛି ରେଜୋଲୁସନରେ ଅଡିଓ ଅପସାରଣ କରେ ଉଚ୍ଚ ରେଜୋଲୁସନ ଦେଖାନ୍ତୁ \"କୋଡି ସହିତ ଖୋଲନ୍ତୁ\" ବିକଳ୍ପ ଦେଖାନ୍ତୁ - ପ୍ଲେ ଲିଷ୍ଟରେ ଯୋଡାଯିବା ପୂର୍ବରୁ ଏବଂ ପରେ ଦେଖାଯାଇଥିବା ଭିଡିଓଗୁଡିକ ଅପସାରିତ ହେବ । -\nତମେ ନିଶ୍ଚିତ କି\? ଏହାକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ! + ପ୍ଲେ ଲିଷ୍ଟରେ ଯୋଡାଯିବା ପୂର୍ବରୁ ଏବଂ ପରେ ଦେଖାଯାଇଥିବା ଭିଡିଓଗୁଡିକ ଅପସାରିତ ହେବ । \nତମେ ନିଶ୍ଚିତ କି? ଏହାକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ! ପ୍ଲେୟାରକୁ କ୍ରାସ୍ କରନ୍ତୁ ଡିଫଲ୍ଟ ଅଡିଓ ଫର୍ମାଟ୍ ଅକ୍ଷୟ ସନ୍ଧାନ ପ୍ଲେୟାରକୁ ହ୍ରାସ ହୋଇଥିବା ସଠିକତା ସହିତ ଶୀଘ୍ର ପଦବୀ ଖୋଜିବାକୁ ଅନୁମତି ଦିଏ । 5, 15 କିମ୍ବା 25 ସେକେଣ୍ଡ ଖୋଜିବା ଏହା ସହିତ କାମ କରେ ନାହିଁ @@ -412,7 +411,7 @@ ଅଦ୍ୟତନ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ ନୂତନ ସଂସ୍କରଣଗୁଡ଼ିକ ପାଇଁ ମାନୁଆଲ ଯାଞ୍ଚ କରନ୍ତୁ ବିଚାରାଧୀନ ଅଛି - ଦେଖାଯାଇଥିବା ଭିଡିଓଗୁଡିକ ଅପସାରଣ କରିବେ କି\? + ଦେଖାଯାଇଥିବା ଭିଡିଓଗୁଡିକ ଅପସାରଣ କରିବେ କି? ବର୍ଣ୍ଣନାରେ ପାଠ ବାଛିବା ଅକ୍ଷମ କରନ୍ତୁ ଏକ ସୁରକ୍ଷିତ ସଂଯୋଗ ସ୍ଥାପନ କରିପାରିଲା ନାହିଁ ଟୋଗଲ୍ ସେବା, ବର୍ତ୍ତମାନ ମନୋନୀତ: @@ -595,7 +594,7 @@ ଏହି ନାମ ସହିତ ଏକ ଡାଉନଲୋଡ୍ ଫାଇଲ୍ ପୂର୍ବରୁ ବିଦ୍ୟମାନ ଅଛି ଡାଉନଲୋଡ୍ ହୋଇଥିବା ଫାଇଲଗୁଡିକ ଡିଲିଟ୍ କରନ୍ତୁ ସିଷ୍ଟମ୍ ଫୋଲ୍ଡର୍ ପିକର୍ (SAF) ବ୍ୟବହାର କରନ୍ତୁ - ହଁ, ଏବଂ ଆଂଶିକ ଦେଖାଯାଇଥିବା ଭିଡିଓଗୁଡିକ + ହଁ, ଏବଂ ଆଂଶିକ ଦେଖାଯାଇଥିବା ଭିଡିଓଗୁଡିକ ଗୋଷ୍ଠୀ ନାମ ଖାଲି ଅଛି ଉପଲବ୍ଧ ଥିବାବେଳେ ଉତ୍ସର୍ଗୀକୃତ ଫିଡରୁ ଆଣ ତାଲିକା diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 8b5969c0c..2c6158355 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -29,7 +29,7 @@ ਨਵਾਂ ਕੀ ਹੈ ਬੈਕਗ੍ਰਾਊਂਡ ਪੌਪ-ਅਪ - ਵਿੱਚ ਸ਼ਾਮਿਲ ਕਰੋ + ਦੇ ਵਿੱਚ ਜੋੜ੍ਹੋ ਵੀਡੀਓ ਲਈ ਡਾਊਨਲੋਡ ਫ਼ੋਲਡਰ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਵੀਡੀਓ ਫ਼ਾਈਲਾਂ ਇੱਥੇ ਜਮ੍ਹਾਂ ਹੁੰਦੀਆਂ ਹਨ ਵੀਡੀਓ ਫ਼ਾਈਲਾਂ ਲਈ ਡਾਊਨਲੋਡ ਫ਼ੋਲਡਰ ਚੁਣੋ @@ -93,7 +93,7 @@ ਬੰਦ ਕੀਤਾ ਸਾਫ ਕਰੋ ਵਧੀਆ ਰੈਜ਼ੋਲਿਊਸ਼ਨ - ਵਾਪਿਸ + ਅਣ-ਕੀਤਾ ਕਰੋ ਸਾਰੇ ਚਲਾਓ ਹਮੇਸ਼ਾਂ ਸਿਰਫ਼ ਇਸ ਬਾਰ @@ -184,8 +184,7 @@ ਕ੍ਰਿਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ… ਕਲਿਪ-ਬੋਰਡ ਵਿੱਚ ਕਾਪੀ ਹੋ ਗਿਆ ਹੈ ਬਾਅਦ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਵਿਚੋਂ ਇੱਕ ਡਾਊਨਲੋਡ ਫੋਲਡਰ ਨੂੰ ਚੁਣੋ - ਪੌਪ-ਅਪ ਮੋਡ ਵਿੱਚ ਖੋਲ੍ਹਣ ਵਾਸਤੇ -\nਇਸ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ + ਪੌਪ-ਅਪ ਮੋਡ ਵਿੱਚ ਖੋਲ੍ਹਣ ਵਾਸਤੇ\nਇਸ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ 1 ਆਈਟਮ ਮਿਟਾਈ ਗਈ। ReCaptcha ਚੁਣੌਤੀ ReCaptcha ਚੁਣੌਤੀ ਲਈ ਬੇਨਤੀ @@ -278,36 +277,19 @@ ਪਿੱਛਲਾ ਐਕਸਪੋਰਟ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਨਹੀਂ ਹੋ ਸਕੀਆਂ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਐਕਸਪੋਰਟ ਨਹੀਂ ਹੋ ਸਕੀਆਂ - ਗੂਗਲ ਟੇਕਅਊਟ ਤੋਂ ਯੂਟਿਊਬ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਐਕਸਪੋਰਟ ਫਾਈਲ ਡਾਊਨਲੋਡ ਕਰੋ: -\n -\n1. ਇਸ URL ਤੇ ਜਾਓ: %1$s -\n2. ਮੰਗਣ ਤੇ ਆਪਣੇ ਖਾਤੇ \'ਚ ਲਾਗ-ਇਨ ਕਰੋ -\n3. ਕਲਿੱਕ ਕਰੋ \" All data incuded\" ਤੇ, ਫੇਰ \"Deselect all\" ਤੇ ਫੇਰ ਸਿਰਫ \"subscriprion\" ਚੁਣੋ ਅਤੇ \"OK\" ਕਰੋ -\n4. \"Next step\" ਤੇ ਕਲਿੱਕ ਕਰੋ ਤੇ ਫੇਰ \"create export\" ਤੇ -\n5. ਡਾਊਨਲੋਡ ਬਟਨ ਦਿਖਾਈ ਦੇਣ ਤੇ ਇਸ ਤੇ ਕਲਿੱਕ ਕਰੋ।ਇੱਕ ਡਾਉਨਲੋਡ ਸ਼ੁਰੂ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ (ਇਹੀ ਐਕਸਪੋਰਟ ਫਾਈਲ ਹੈ) -\n6. ਥੱਲੇ ਇੰਪੋਰਟ ਫਾਈਲ ਤੇ ਕਲਿੱਕ ਕਰੋ ਤੇ ਡਾਊਨਲੋਡ ਕੀਤੀ .zip ਫਾਈਲ ਚੁਣੋ -\n7. [ਜੇ .zip ਤੋਂ ਐਕਸਪੋਰਟ ਫੇਲ ਹੋ ਜਾਂਦੀ ਹੈ] ਤਾਂ .csv ਫਾਈਲ ਐਕਸਟਰੈਕਟ ਕਰੋ (ਆਮ ਤੌਰ ਤੇ \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), ਥੱਲੇ ਦਿੱਤੇ ਇੰਪੋਰਟ ਫਾਈਲ ਤੇ ਕਲਿੱਕ ਕਰਕੇ ਐਕਸਟਰੈਕਟ ਕੀਤੀ csv ਫਾਈਲ ਚੁਣੋ - URL ਜਾਂ ਆਪਣੀ ID ਟਾਈਪ ਕਰਕੇ ਸਾਉੰਡ ਕਲਾਉਡ ਪ੍ਰੋਫਾਈਲ ਇੰਪੋਰਟ ਕਰੋ: -\n -\n1. ਇੱਕ ਵੈਬ-ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ \"ਡੈਸਕਟਾਪ ਮੋਡ\" ਨੂੰ ਚਾਲੂ ਕਰੋ (ਸਾਈਟ ਮੋਬਾਈਲ ਉਪਕਰਣਾਂ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ) -\n2. ਇਸ URL ਤੇ ਜਾਓ: %1$s -\n3. ਆਪਣੇ ਖਾਤੇ ਚ ਲੌਗ-ਇਨ ਕਰੋ -\n4. ਨਿਰਦੇਸ਼ਤ ਕੀਤੇ ਗਏ ਪ੍ਰੋਫਾਈਲ URL ਨੂੰ ਕਾਪੀ ਕਰੋ. + ਗੂਗਲ ਟੇਕਆਊਟ ਤੋਂ ਯੂਟਿਊਬ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਐਕਸਪੋਰਟ ਫਾਈਲ ਡਾਊਨਲੋਡ ਕਰੋ:\n\n1. ਇਸ URL ਤੇ ਜਾਓ: %1$s\n2. ਮੰਗਣ ਤੇ ਆਪਣੇ ਖਾਤੇ \'ਚ ਲਾਗ-ਇਨ ਕਰੋ\n3. ਕਲਿੱਕ ਕਰੋ \" All data incuded\" ਤੇ, ਫੇਰ \"Deselect all\" ਤੇ ਫੇਰ ਸਿਰਫ \"subscriprion\" ਚੁਣੋ ਅਤੇ \"OK\" ਕਰੋ\n4. \"Next step\" ਤੇ ਕਲਿੱਕ ਕਰੋ ਅਤੇ ਫੇਰ \"create export\" ਤੇ\n5. ਡਾਊਨਲੋਡ ਬਟਨ ਦਿਖਾਈ ਦੇਣ ਤੇ ਇਸ ਤੇ ਕਲਿੱਕ ਕਰੋ। ਇੱਕ ਡਾਉਨਲੋਡ ਸ਼ੁਰੂ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ (ਇਹੀ ਐਕਸਪੋਰਟ ਫਾਈਲ ਹੈ)\n6. ਥੱਲੇ ਇੰਪੋਰਟ ਫਾਈਲ ਤੇ ਕਲਿੱਕ ਕਰੋ ਤੇ ਡਾਊਨਲੋਡ ਕੀਤੀ .zip ਫਾਈਲ ਚੁਣੋ\n7. [ਜੇ .zip ਤੋਂ ਐਕਸਪੋਰਟ ਫੇਲ ਹੋ ਜਾਂਦੀ ਹੈ] ਤਾਂ .csv ਫਾਈਲ ਐਕਸਟਰੈਕਟ ਕਰੋ (ਆਮ ਤੌਰ ਤੇ \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), ਥੱਲੇ ਦਿੱਤੇ ਇੰਪੋਰਟ ਫਾਈਲ ਤੇ ਕਲਿੱਕ ਕਰਕੇ ਐਕਸਟਰੈਕਟ ਕੀਤੀ csv ਫਾਈਲ ਚੁਣੋ + URL ਜਾਂ ਆਪਣੀ ID ਟਾਈਪ ਕਰਕੇ ਸਾਉੰਡ ਕਲਾਉਡ ਪ੍ਰੋਫਾਈਲ ਇੰਪੋਰਟ ਕਰੋ: \n \n1. ਇੱਕ ਵੈਬ-ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ \"ਡੈਸਕਟਾਪ ਮੋਡ\" ਨੂੰ ਚਾਲੂ ਕਰੋ (ਸਾਈਟ ਮੋਬਾਈਲ ਉਪਕਰਣਾਂ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ) \n2. ਇਸ URL ਤੇ ਜਾਓ: %1$s \n3. ਆਪਣੇ ਖਾਤੇ ਚ ਲੌਗ-ਇਨ ਕਰੋ \n4. ਨਿਰਦੇਸ਼ਤ ਕੀਤੇ ਗਏ ਪ੍ਰੋਫਾਈਲ URL ਨੂੰ ਕਾਪੀ ਕਰੋ। ਤੁਹਾਡੀ ਆਈਡੀ, soundcloud.com/ਤੁਹਾਡੀ ਆਈਡੀ - ਯਾਦ ਰੱਖੋ ਕਿ ਇਸ ਕਾਰਜ ਨਾਲ ਡਾਟਾ ਖਪਤ ਹੋ ਸਕਦਾ ਹੈ। -\n -\nਕੀ ਤੁਸੀਂ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ\? + ਯਾਦ ਰੱਖੋ ਕਿ ਇਸ ਕਾਰਜ ਨਾਲ ਡਾਟਾ ਖਪਤ ਹੋ ਸਕਦਾ ਹੈ।\n\nਕੀ ਤੁਸੀਂ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਪਲੇਅਬੈਕ ਸਪੀਡ ਕੰਟਰੋਲ ਤਾਲ ਪਿੱਚ ਅਲਹਿਦਾ ਕਰੋ (ਵਿਗਾੜ ਪੈ ਸਕਦਾ ਹੈ) ਕੀ ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵੀ ਇੰਪੋਰਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ\? ਨਿਊਪਾਈਪ ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ - ਨਿਊਪਾਈਪ ਪ੍ਰੋਜੈਕਟ ਤੁਹਾਡੀ ਗੋਪਨੀਯਤਾ ਨੂੰ ਬਹੁਤ ਗੰਭੀਰਤਾ ਨਾਲ ਲੈਂਦਾ ਹੈ। ਇਸ ਲਈ ਐਪ ਤੁਹਾਡੀ ਸਹਿਮਤੀ ਤੋਂ ਬਿਨਾਂ ਕੋਈ ਵੀ ਡਾਟਾ ਇੱਕਠਾ ਨਹੀਂ ਕਰਦਾ। -\nਨਿਊਪਾਈਪ ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਵਿਸਥਾਰ ਵਿੱਚ ਦੱਸਦੀ ਹੈ ਕਿ ਜਦੋਂ ਤੁਸੀਂ ਕਰੈਸ਼ ਰਿਪੋਰਟ ਭੇਜਦੇ ਹੋ ਤਾਂ ਕਿਹੜਾ ਡਾਟਾ ਭੇਜਿਆ ਜਾਂ ਸਟੋਰ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। + ਨਿਊਪਾਈਪ ਪ੍ਰੋਜੈਕਟ ਤੁਹਾਡੀ ਗੋਪਨੀਯਤਾ ਨੂੰ ਬਹੁਤ ਗੰਭੀਰਤਾ ਨਾਲ ਲੈਂਦਾ ਹੈ। ਇਸ ਲਈ ਐਪ ਤੁਹਾਡੀ ਸਹਿਮਤੀ ਤੋਂ ਬਿਨਾਂ ਕੋਈ ਵੀ ਡਾਟਾ ਇੱਕਠਾ ਨਹੀਂ ਕਰਦਾ।\nਨਿਊਪਾਈਪ ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਵਿਸਥਾਰ ਵਿੱਚ ਦੱਸਦੀ ਹੈ ਕਿ ਜਦੋਂ ਤੁਸੀਂ ਕਰੈਸ਼ ਰਿਪੋਰਟ ਭੇਜਦੇ ਹੋ ਤਾਂ ਕਿਹੜਾ ਡਾਟਾ ਭੇਜਿਆ ਜਾਂ ਸਟੋਰ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਪੜ੍ਹੋ - ਯੂਰਪੀਅਨ ਜਨਰਲ ਡੇਟਾ ਪ੍ਰੋਟੈਕਸ਼ਨ ਰੈਗੂਲੇਸ਼ਨ (ਜੀਡੀਪੀਆਰ) ਦੀ ਪਾਲਣਾ ਕਰਨ ਲਈ, ਅਸੀਂ ਤੁਹਾਡਾ ਧਿਆਨ ਨਿਊਪਾਈਪ ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਵੱਲ ਖਿੱਚਦੇ ਹਾਂ। ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਧਿਆਨ ਨਾਲ ਪੜ੍ਹੋ। -\nਸਾਨੂੰ ਨੁਕਸ ਰਿਪੋਰਟ ਭੇਜਣ ਲਈ ਤੁਹਾਨੂੰ ਇਸ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨਾ ਹੋਵੇਗਾ। + ਯੂਰਪੀਅਨ ਜਨਰਲ ਡੇਟਾ ਪ੍ਰੋਟੈਕਸ਼ਨ ਰੈਗੂਲੇਸ਼ਨ (ਜੀਡੀਪੀਆਰ) ਦੀ ਪਾਲਣਾ ਕਰਨ ਲਈ, ਅਸੀਂ ਤੁਹਾਡਾ ਧਿਆਨ ਨਿਊਪਾਈਪ ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਵੱਲ ਖਿੱਚਦੇ ਹਾਂ। ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਧਿਆਨ ਨਾਲ ਪੜ੍ਹੋ।\nਸਾਨੂੰ ਨੁਕਸ ਰਿਪੋਰਟ ਭੇਜਣ ਲਈ ਤੁਹਾਨੂੰ ਇਸ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨਾ ਹੋਵੇਗਾ। ਸਵੀਕਾਰ ਕਰੋ ਅਸਵੀਕਾਰ ਕੋਈ ਸੀਮਾ ਨਹੀਂ @@ -511,10 +493,9 @@ %d ਸਕਿੰਟ %d ਸਕਿੰਟ - ਹਾਂ, ਅਤੇ ਅੱਧ-ਪਚੱਧੀਆਂ ਵੇਖੀਆਂ ਹੋਈਆਂ ਵੀ - ਪਲੇਲਿਸਟ ਵਿੱਚ ਸ਼ਾਮਿਲ, ਪਹਿਲਾਂ ਚਾਹੇ ਬਾਅਦ ਵਿੱਚ ਵੇਖੇ ਜਾ ਚੁੱਕੇ ਵੀਡੀਓ ਹਟਾ ਦਿੱਤੇ ਜਾਣਗੇ। -\nਕੀ ਵਾਕਿਆ ਹੀ ਤੁਸੀਂ ਇਹਨਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਵਾਪਸ ਨਹੀਂ ਮੋੜਿਆ ਜਾ ਸਕਣਾ! - ਵੇਖੇ ਹੋਏ ਵੀਡੀਓ ਹਟਾ ਦੇਈਏ\? + ਹਾਂ, ਅਤੇ ਅੱਧ-ਪਚੱਧੀਆਂ ਵੇਖੀਆਂ ਹੋਈਆਂ ਵੀ + ਪਲੇਲਿਸਟ ਵਿੱਚ ਸ਼ਾਮਿਲ ਪਹਿਲਾਂ ਤੇ ਬਾਅਦ ਵਿੱਚ ਵੇਖੇ ਜਾ ਚੁੱਕੇ ਵੀਡੀਓ ਹਟਾ ਦਿੱਤੇ ਜਾਣਗੇ। \nਕੀ ਵਾਕਿਆ ਹੀ ਤੁਸੀਂ ਇਹਨਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਵਾਪਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਣਾ! + ਵੇਖੇ ਹੋਏ ਵੀਡੀਓ ਹਟਾ ਦੇਈਏ? ਵੇਖੇ ਹੋਏ ਨੂੰ ਹਟਾਓ ਸਿਸਟਮ ਡਿਫ਼ਾਲਟ ਐਪ ਦੀ ਭਾਸ਼ਾ @@ -554,7 +535,7 @@ ਕੋਈ ਸਰੋਤਾ ਨਹੀਂ ਸੁਣ ਰਿਹਾ ਕੋਈ ਦਰਸ਼ਕ ਨਹੀਂ ਵੇਖ ਰਿਹਾ ਵੇਰਵਾ - ਸਬੰਧਤ ਨਗ + ਸਬੰਧਤ ਆਈਟਮਾਂ ਟਿੱਪਣੀਆਂ ਗਿਟਹੱਬ \'ਤੇ ਜਾ ਕੇ ਇਤਲਾਹ ਦਿਓ ਦੂਜੀਆਂ ਐਪਾਂ ਦੇ ਉੱਤੇ ਵਿਖਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ @@ -822,10 +803,32 @@ ਸੈਕੰਡਰੀ ਅਸਥਾਈ ਯੂਟਿਊਬ ਪਲੇਲਿਸਟ ਵਜੋਂ ਸਾਂਝਾ ਕਰੋ ਪਲੇਲਿਸਟਾਂ - %1$s ਦੀ ਖੋਜ ਕਰੋ - %1$s (%2$s) ٪1$s ਦੀ ਖੋਜ ਕਰੋ + %1$s ਖੋਜੋ + %1$s (%2$s) ਖੋਜੋ ਫੀਡ ਗਰੁੱਪ ਚੁਣੋ ਅਜੇ ਤੱਕ ਕੋਈ ਫੀਡ ਗਰੁੱਪ ਨਹੀਂ ਬਣਾਇਆ ਗਿਆ ਚੈਨਲ ਗਰੁੱਪ ਪੰਨਾ ਪਸੰਦ + ਫ਼ਾਈਲ ਮਿਟਾਓ + ਐਂਟਰੀ ਮਿਟਾਓ + ਖ਼ਾਤਾ ਬੰਦ ਕੀਤਾ ਗਿਆ\n\n%1$s ਇਹ ਕਾਰਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ: %2$s + ਐਂਟਰੀ ਮਿਟਾ ਦਿੱਤੀ ਗਈ + ਪੌਪਅੱਪ ਪਲੇਅਰ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਦਿੱਤੇ Android ਸੈਟਿੰਗ ਮੀਨੂ ਵਿੱਚ %1$s ਚੁਣੋ ਅਤੇ %2$s ਨੂੰ ਇਨੇਬਲ ਕਰੋ। + \"ਹੋਰ ਐਪਾਂ ਉੱਤੇ ਡਿਸਪਲੇ ਦੀ ਆਗਿਆ ਦਿਓ\" + %sਹਜ਼ਾਰ + %sਮਿਲੀਅਨ + %sਅਰਬ + SoundCloud ਟੌਪ 50 ਪੰਨਾ ਹਟਾ ਦਿੱਤਾ ਗਿਆ + SoundCloud ਨੇ ਮੂਲ ਟੌਪ 50 ਚਾਰਟਾਂ ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਹੈ। ਸੰਬੰਧਿਤ ਟੈਬ ਨੂੰ ਤੁਹਾਡੇ ਮੁੱਖ ਪੰਨੇ ਤੋਂ ਹਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ। + YouTube ਸੰਯੁਕਤ ਰੁਝਾਨ ਹਟਾਇਆ ਗਿਆ + YouTube ਨੇ 21 ਜੁਲਾਈ 2025 ਤੋਂ ਸੰਯੁਕਤ \"ਰੁਝਾਨ ਵਿੱਚ\" ਪੰਨੇ ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਹੈ। NewPipe ਨੇ ਡਿਫ਼ਾਲਟ \"ਰੁਝਾਨ ਵਿੱਚ\" ਪੰਨੇ ਨੂੰ ਟ੍ਰੈਂਡਿੰਗ ਲਾਈਵਸਟ੍ਰੀਮਾਂ ਨਾਲ ਬਦਲ ਦਿੱਤਾ ਹੈ।\n\nਤੁਸੀਂ \"ਸੈਟਿੰਗਾਂ > ਸਮੱਗਰੀ > ਮੁੱਖ ਪੰਨੇ ਦੀ ਸਮੱਗਰੀ\" ਵਿੱਚ ਵੱਖ-ਵੱਖ ਟ੍ਰੈਂਡਿੰਗ ਪੰਨਿਆਂ ਨੂੰ ਵੀ ਚੁਣ ਸਕਦੇ ਹੋ। + ਗੇਮਿੰਗ ਟ੍ਰੈਂਡਸ + ਟ੍ਰੈਂਡਿੰਗ ਪੌਡਕਾਸਟ + ਟਰੈਂਡਿੰਗ ਫ਼ਿਲਮਾਂ ਅਤੇ ਸ਼ੋਅ + ਟਰੈਂਡਿੰਗ ਸੰਗੀਤ + ਪਲੇਅ ਕਰਦੇ ਸਮੇਂ ਸਰਵਰ ਤੋਂ HTTP error 403 ਪ੍ਰਾਪਤ ਹੋਇਆ, ਜੋ ਸ਼ਾਇਦ ਸਟ੍ਰੀਮਿੰਗ URL ਦੀ ਮਿਆਦ ਪੁੱਗਣ ਜਾਂ IP ਦੀ ਪਾਬੰਦੀ ਕਾਰਨ ਹੋਈ ਹੈ + ਚਲਾਉਣ ਦੌਰਾਨ ਸਰਵਰ ਤੋਂ HTTP error %1$s ਪ੍ਰਾਪਤ ਹੋਇਆ + ਪਲੇਅ ਕਰਦੇ ਸਮੇਂ ਸਰਵਰ ਤੋਂ HTTP error 403 ਪ੍ਰਾਪਤ ਹੋਇਆ, ਜੋ ਸ਼ਾਇਦ IP ਬੈਨ ਜਾਂ ਸਟ੍ਰੀਮਿੰਗ URL ਡੀਔਬਫਸਕੇਸ਼ਨ ਸਮੱਸਿਆਵਾਂ ਕਾਰਨ ਹੋਈ ਹੈ + %1$s ਨੇ ਡੇਟਾ ਪ੍ਰਦਾਨ ਕਰਨ ਤੋਂ ਇਨਕਾਰ ਕਰ ਦਿੱਤਾ, ਅਤੇ ਇਹ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਲੌਗਇਨ ਕਰਨ ਲਈ ਕਿਹਾ ਕਿ ਬੇਨਤੀਕਰਤਾ ਬੋਟ ਨਹੀਂ ਹੈ।\n\nਹੋ ਸਕਦਾ ਹੈ ਕਿ %1$s ਨੇ ਤੁਹਾਡੇ IP ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਪਾਬੰਦੀ ਲਗਾਈ ਹੋਵੇ, ਤੁਸੀਂ ਕੁਝ ਸਮਾਂ ਉਡੀਕ ਕਰ ਸਕਦੇ ਹੋ ਜਾਂ ਕਿਸੇ ਵੱਖਰੇ IP \'ਤੇ ਸਵਿੱਚ ਕਰ ਸਕਦੇ ਹੋ (ਉਦਾਹਰਣ ਵਜੋਂ VPN ਨੂੰ ਚਾਲੂ/ਬੰਦ ਕਰਕੇ, ਜਾਂ WiFi ਤੋਂ ਮੋਬਾਈਲ ਡੇਟਾ \'ਤੇ ਸਵਿੱਚ ਕਰਕੇ)। + ਇਹ ਸਮੱਗਰੀ ਵਰਤਮਾਨ ਵਿੱਚ ਚੁਣੇ ਗਏ ਦੇਸ਼ ਦੀ ਸਮੱਗਰੀ ਲਈ ਉਪਲੱਬਧ ਨਹੀਂ ਹੈ।\n\n\"ਸੈਟਿੰਗਾਂ > ਸਮੱਗਰੀ > ਡਿਫ਼ਾਲਟ ਸਮੱਗਰੀ ਦੇਸ਼\" ਤੋਂ ਆਪਣੀ ਚੋਣ ਬਦਲੋ। diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 0a95609cd..5580ea24a 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -522,10 +522,9 @@ To wideo jest objęte ograniczeniem wiekowym. \n \nWłącz „%1$s” w ustawieniach, jeśli chcesz je zobaczyć. - Tak, i częściowo obejrzane wideo - Wideo, które zostały obejrzane przed i po dodaniu do playlisty, zostaną usunięte. -\nCzy na pewno\? Tego nie da się cofnąć! - Czy usunąć obejrzane wideo\? + Tak, i częściowo obejrzane wideo + Wideo, które zostały obejrzane przed i po dodaniu do playlisty, zostaną usunięte. \nCzy na pewno? Tego nie da się cofnąć! + Czy usunąć obejrzane wideo? Usuń obejrzane Oryginalne teksty z usług będą widoczne w strumieniowanych pozycjach Pokazuj oryginalny czas na pozycjach @@ -592,8 +591,8 @@ Zepsuj aplikację Ta treść dostępna jest tylko dla użytkowników, którzy za nią zapłacili. Nie może być strumieniowana ani pobierana przez NewPipe. To wideo dostępne jest tylko dla subskrybentów usługi YouTube Music Premium. Nie może być strumieniowane ani pobierane przez NewPipe. - Ta treść jest prywatna, więc nie może być strumieniowana ani pobierana przez NewPipe - Ta treść nie jest dostępna w Twoim kraju + Ta treść jest prywatna, więc nie może być strumieniowana ani pobierana przez NewPipe. + Ta treść nie jest dostępna w Twoim kraju. To wideo jest objęte ograniczeniem wiekowym. \nZe względu na nowe zasady YouTube dotyczące wideo z ograniczeniami wiekowymi NewPipe nie może uzyskać dostępu do żadnego z jego strumieni wideo i dlatego nie jest w stanie go odtworzyć. To jest utwór SoundCloud Go+ (przynajmniej w Twoim kraju). Nie może być strumieniowany ani pobierany przez NewPipe. @@ -623,7 +622,7 @@ Kategoria Otwórz stronę Teraz możesz zaznaczyć tekst wewnątrz opisu. Pamiętaj, że w trybie zaznaczania strona może migotać i linki nie będą klikalne. - Konto zamknięte + Konto zamknięte. Tryb szybki dla ładowania kanału nie dostarcza więcej informacji na ten temat. Konto autora zostało zawieszone. \nNewPipe nie będzie w stanie załadować tego kanału w przyszłości. @@ -853,4 +852,24 @@ Polubienia Usunięto stronę SoundCloud 50 najlepszych SoundCloud wycofał oryginalną listę 50 najlepszych. Odpowiadająca karta została usunięta ze strony głównej. + Usunięto połączone Na czasie YouTube + Od 21 lipca 2025 r. YouTube zaprzestał korzystania z połączonego Na czasie. NewPipe zastąpił domyślną stronę Na czasie popularnymi transmisjami na żywo.\n\nMożesz także wybrać różne strony Na czasie w „Ustawienia > Zawartość > Zawartość strony głównej”. + Gry na czasie + Podcasty na czasie + Filmy i programy na czasie + Muzyka na czasie + %stys. + %smln + %smld + Usuń plik + Usuń wpis + Usunięto wpis + Aby korzystać z odtwarzacza w trybie okienkowym, wybierz %1$s w następującym menu ustawień Androida i włącz %2$s. + „Zezwól na wyświetlanie nad innymi aplikacjami” + Konto zamknięte.\n\n%1$s podaje następujący powód: %2$s + Podczas odtwarzania otrzymano od serwera błąd HTTP 403, prawdopodobnie spowodowany wygaśnięciem adresu URL strumienia lub blokadą adresu IP. + Podczas odtwarzania otrzymano od serwera błąd HTTP %1$s. + Podczas odtwarzania otrzymano od serwera błąd HTTP 403, prawdopodobnie spowodowany blokadą adresu IP lub problemami z odszyfrowaniem adresu URL strumienia. + %1$s odmówił dostarczenia danych, prosząc o zalogowanie się w celu potwierdzenia, że nie jest się botem.\n\nTwoje IP mogło zostać tymczasowo zablokowane przez %1$s. Możesz chwilę poczekać lub zmienić adres IP (na przykład włączając/wyłączając VPN lub przełączając się z sieci Wi-Fi na dane komórkowe). + Ta treść nie jest dostępna dla aktualnie wybranego kraju treści.\n\nZmień swój wybór w „Ustawienia > Zawartość > Domyślny kraj treści”. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 30fc565c6..7488e69c7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -517,9 +517,8 @@ Este vídeo tem restrição de idade. \n \nAtive \"%1$s\" nas configurações se quiser vê-lo. - Sim, e vídeos parcialmente assistidos - Os vídeos que foram assistidos antes e depois de terem sidos adicionados à playlist serão removidos. -\nTem certeza? Esta ação não pode ser desfeita! + Sim, e vídeos parcialmente assistidos + Os vídeos que foram assistidos antes e depois de terem sidos adicionados à playlist serão removidos. \nTem certeza? Esta ação não pode ser desfeita! Remover vídeos assistidos? Remover assistidos Textos originais dos serviços serão visíveis nos itens de transmissão @@ -839,9 +838,29 @@ Selecione um grupo de feeds Nenhum grupo de feeds criado ainda Página do grupo do canal - Pesquisar %1$s - Pesquisar %1$s (%2$s) + Buscar %1$s + Buscar %1$s (%2$s) Curtidas Página Top 50 do SoundCloud removida O SoundCloud descontinuou as paradas originais do Top 50. A aba correspondente foi removida da sua página principal. + Para usar o Popup Player, selecione %1$s no seguinte menu de configurações do Android e ative %2$s. + “Permitir exibição sobre outros aplicativos” + %sK + %sM + %sB + Excluir arquivo + Excluir entrada + Tendências combinadas do YouTube removidas + O YouTube descontinuou a página de tendências combinadas em 21 de julho de 2025. O NewPipe substituiu a página de tendências padrão pelas transmissões ao vivo em alta.\n\nVocê também pode selecionar páginas de tendências diferentes em \"Configurações > Conteúdo > Conteúdo da página principal\". + Jogos em alta + Podcasts em alta + Filmes e programas em alta + Músicas em alta + Entrada excluída + Conta encerrada\n\n%1$s informa este motivo: %2$s + Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por URL de streaming expirado ou IP banido + Erro HTTP %1$s recebido do servidor durante reprodução + Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por um banimento de IP ou problemas de desofuscação de URL de streaming + %1$s se recusou a fornecer dados, solicitando um login para confirmar que o solicitante não é um bot.\n\nSeu IP pode ter sido temporariamente banido por %1$s. Você pode esperar um pouco ou mudar para um IP diferente (por exemplo, ativando/desativando uma VPN ou alternando de Wi-Fi para dados móveis). + Este conteúdo não está disponível para o país selecionado atualmente.\n\nAltere sua seleção acessando “Configurações > Conteúdo > País padrão do conteúdo”. diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 6783327ec..4e9a85522 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -144,8 +144,7 @@ Eliminar ficheiros descarregados Idioma da aplicação Utilizadores - Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. -\nTem a certeza\? Esta ação não pode ser revertida! + Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. \nTem a certeza? Esta ação não pode ser revertida! %s a ver %s a ver @@ -228,7 +227,7 @@ Limite de atualização da fonte OK Não foi possível atualizar a subscrição - Sim e também os vídeos parcialmente vistos + Sim e também os vídeos parcialmente vistos Ainda não há listas de reprodução favoritas %s ouvinte @@ -281,7 +280,7 @@ Notificações para novas versões do NewPipe Histórico Lista - Remover vídeos visualizados\? + Remover vídeos visualizados? %d minuto %d minutos @@ -841,4 +840,27 @@ Página do grupo do canal Pesquisar %1$s Pesquisar %1$s (%2$s) + Gostos + Página Top 50 do SoundCloud removida + O SoundCloud descontinuou os gráficos originais do Top 50. A guia correspondente foi removida da sua página principal. + Tendência combinada do YouTube removida + O YouTube descontinuou a página de tendência combinada a partir de 21 de julho de 2025. O NewPipe substituiu a página de tendência predefinida com as streams ao vivo de tendência.\n\nTambém pode escolher páginas de tendência diferentes em \"Definições > Conteúdo > Conteúdo da página principal\". + Tendências de jogos + Tendências de podcasts + Tendências de filmes e shows + Tendências de música + %sK + %sM + %sB + Para usar o reprodutor pop-up, escolhe %1$s no menu seguinte de configurações do Android e ative %2$s. + “Permitir exibição sobre outras apps” + Apagar ficheiro + Apagar entrada + Entrada apagada + Conta terminada\n\n%1$s fornece esta razão: %2$s + Erro HTTP %1$s recebido do servidor ao reproduzir + %1$s recusou fornecer dados, pedindo por um login para confirmar que o solicitante não é um bot.\n\nO seu IP pode ter sido temporariamente banido por %1$s, pode esperar algum tempo ou mudar para um IP diferente (por exemplo, a ligar / desligar uma VPN, ou a alternar de Wi-Fi para dados móveis). + Este conteúdo não está disponível para o país de conteúdo atualmente selecionado.\n\nAltere a sua seleção de \"Configurações > Conteúdo > País predefinido de conteúdo\". + Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado pela URL de streaming expirado ou IP banido + Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por um bloqueio de IP ou problemas de desofuscação da URL de streaming diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index d4b35fa55..e18984dc2 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -517,10 +517,9 @@ Este vídeo está restringido a adultos. \n \nPara o poder ver, tem que ativar \"%1$s\" nas definições. - Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. -\nTem a certeza\? Esta ação não pode ser revertida! - Sim e também os vídeos parcialmente vistos - Remover vídeos visualizados\? + Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. \nTem a certeza? Esta ação não pode ser revertida! + Sim e também os vídeos parcialmente vistos + Remover vídeos visualizados? Remover visualizados Os textos originais dos serviços serão visíveis nos itens do vídeo Mostrar antiguidade nos itens @@ -841,4 +840,27 @@ Página do grupo do canal Pesquisar %1$s Pesquisar %1$s (%2$s) + Gostos + Página Top 50 do SoundCloud removida + O SoundCloud descontinuou os gráficos originais do Top 50. A guia correspondente foi removida da sua página principal. + Tendência combinada do YouTube removida + O YouTube descontinuou a página de tendência combinada a partir de 21 de julho de 2025. O NewPipe substituiu a página de tendência predefinida com as streams ao vivo de tendência.\n\nTambém pode escolher páginas de tendência diferentes em \"Definições > Conteúdo > Conteúdo da página principal\". + Tendências de jogos + Tendências de podcasts + Tendências de filmes e shows + Tendências de música + %sK + %sM + %sB + Para usar o reprodutor pop-up, escolhe %1$s no menu seguinte de configurações do Android e ative %2$s. + “Permitir exibição sobre outras apps” + Apagar ficheiro + Apagar entrada + Entrada apagada + Conta terminada\n\n%1$s fornece esta razão: %2$s + Erro HTTP %1$s recebido do servidor ao reproduzir + %1$s recusou fornecer dados, pedindo por um login para confirmar que o solicitante não é um bot.\n\nO seu IP pode ter sido temporariamente banido por %1$s, pode esperar algum tempo ou mudar para um IP diferente (por exemplo, a ligar / desligar uma VPN, ou a alternar de Wi-Fi para dados móveis). + Este conteúdo não está disponível para o país de conteúdo atualmente selecionado.\n\nAltere a sua seleção de \"Configurações > Conteúdo > País predefinido de conteúdo\". + Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado pela URL de streaming expirado ou IP banido + Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por um bloqueio de IP ou problemas de desofuscação da URL de streaming diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 17106ed45..ccd1483a1 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -432,10 +432,9 @@ %d de secunde Datorită constrângerilor ExoPlayer, durata de căutare a fost setată la %d secunde - Da, și videoclipuri vizionate parțial - Videoclipurile care au fost vizionate înainte și după ce au fost adăugate la lista de redare vor fi eliminate. -\nSunteți sigur\? Acest lucru nu poate fi anulat! - Eliminați videoclipurile vizionate\? + Da, și videoclipuri vizionate parțial + Videoclipurile care au fost vizionate înainte și după ce au fost adăugate la lista de redare vor fi eliminate. \nSunteți sigur? Acest lucru nu poate fi anulat! + Eliminați videoclipurile vizionate? Eliminare cele urmărite Prestabilită de sistem Limba aplicației @@ -844,4 +843,8 @@ Aprecieri Pagina SoundCloud Top 50 a fost eliminată SoundCloud a eliminat Top 50. Fila corespunzătoare a fost eliminată din pagina principală. + „Permite afișarea deasupra altor aplicații” + %s mii + %s mil. + %s mld. diff --git a/app/src/main/res/values-rom/strings.xml b/app/src/main/res/values-rom/strings.xml new file mode 100644 index 000000000..55344e519 --- /dev/null +++ b/app/src/main/res/values-rom/strings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 4e7428b3c..b96667f93 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -525,10 +525,9 @@ Исполнители Альбомы Удалить просмотренные - Да, и частично просмотренные - Видео, просмотренные до или после добавления в плейлист, будут удалены. -\nПродолжить\? Не может быть отменено! - Удалить просмотренные видео\? + Да, и частично просмотренные + Видео, просмотренные до или после добавления в плейлист, будут удалены. \nПродолжить? Не может быть отменено! + Удалить просмотренные видео? Отображать сообщённое сервисом время с момента публикации Исходное время публикации Включить \"Ограниченный режим\" YouTube @@ -849,4 +848,24 @@ Лайки Страница SoundCloud Top 50 удалена SoundCloud прекратил поддерживать оригинальные чарты Top 50. Соответствующая вкладка была удалена с вашей главной страницы. + %sК + %sмлн + %sмлрд + Игровые тренды + Удалены объединённые тренды YouTube + YouTube прекратил поддержку объединённой страницы трендов 21 июля 2025 года. NewPipe заменил страницу трендов по умолчанию на тренды в прямых трансляциях.\n\nВы также можете выбрать другие страницы трендов в \"Настройки > Контент > Главная страница\". + Тренды в подкастах + Тренды в фильмах и шоу + Тренды в музыке + Чтобы использовать Popup Player, выберите %1$s в следующем меню настроек Android и включите %2$s. + «Разрешить отображение поверх других приложений» + Удалить файл + Удалить запись + Учётная запись закрыта\n\n%1$s указал причину: %2$s + Запись удалена + Во время воспроизведения получена ошибка HTTP 403 от сервера, вероятно, вызванная истечением срока действия URL-адреса потоковой передачи или блокировкой IP-адреса + Ошибка HTTP %1$s получена от сервера во время воспроизведения + Во время воспроизведения получена ошибка HTTP 403 от сервера, вероятно, вызванная блокировкой IP-адреса или проблемами деобфускации URL-адреса потоковой передачи + %1$s отказался предоставить данные, запросив логин для подтверждения, что запросчик не бот.\n\nВозможно, ваш IP-адрес временно заблокирован %1$s. Вы можете подождать некоторое время или переключиться на другой IP-адрес (например, включив/выключив VPN или переключившись с Wi-Fi на мобильный интернет). + Этот контент недоступен для выбранной страны контента.\n\nИзмените свой выбор в разделе «Настройки > Контент > Страна контента по умолчанию». diff --git a/app/src/main/res/values-ryu/strings.xml b/app/src/main/res/values-ryu/strings.xml index e9baa11da..6b70c0c8e 100644 --- a/app/src/main/res/values-ryu/strings.xml +++ b/app/src/main/res/values-ryu/strings.xml @@ -507,9 +507,8 @@ くぬちゃーがんかいはにーるれいうぅいゆいぎんぬあいびーん。 \n \nいちらんさるいばあい、しっていから \"%1$s\" ゆーいるこうかしみそーれー。 - プレイリストんかいちいからさりーるめーんちいからさったるあとぅんしちょうさんちゃーしがはプレイリストからさくじょさりやびーん。 -\nゆたさいびーが?くぬあしっさーむとぅんかいむどぅしやびらん! - はい、ぶぶんてぃちーがしちょうさんちゃーしがんさちゅるじょさびーん + プレイリストんかいちいからさりーるめーんちいからさったるあとぅんしちょうさんちゃーしがはプレイリストからさくじょさりやびーん。 \nゆたさいびーが?くぬあしっさーむとぅんかいむどぅしやびらん! + はい、ぶぶんてぃちーがしちょうさんちゃーしがんさちゅるじょさびーん しちょうじみぬちゃーしがさちゅるじょさびーが? しちょうじみさちゅるじょ サービスぬオリジナルぬテキストぬやーまほうあぬんかいひょうじさりやびーん diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index 717283e83..88e9cfca1 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -313,7 +313,7 @@ ᱧᱮᱞᱚᱜ ᱟᱠᱟᱱ ᱥᱟᱯᱲᱟᱣ ᱢᱮ ᱧᱮᱞ ᱟᱠᱟᱱ ᱵᱷᱤᱰᱤᱭᱳ ᱠᱚ ᱪᱷᱩᱴᱟᱹᱣ? ᱫᱩᱯᱞᱟᱹᱲ ᱠᱚ ᱦᱮᱡ ᱢᱮ - ᱭ, ᱟᱨ ᱵᱷᱤᱰᱤᱭᱳ ᱠᱚ ᱡᱟᱦᱟᱸ ᱞᱮᱠᱟ ᱧᱮᱞᱚᱜᱼᱟ + ᱭ, ᱟᱨ ᱵᱷᱤᱰᱤᱭᱳ ᱠᱚ ᱡᱟᱦᱟᱸ ᱞᱮᱠᱟ ᱧᱮᱞᱚᱜᱼᱟ ᱪᱟᱱᱮᱞ ᱜᱨᱩᱯ ᱯᱷᱤᱰ ᱢᱩᱪᱟᱹᱫ ᱵᱚᱫᱚᱞᱟᱠᱟᱱ: %s ᱵᱟᱝ ᱞᱚᱰ ᱟᱠᱟᱱᱟ: %d diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index ac694bba9..dcaf7290e 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -284,10 +284,9 @@ %d segundu Pro more de sos lìmites de ExoPlayer sa longària de s\'iscostiamentu lestru est istada impostada a %d segundos - Eja, e fintzas sos vìdeos pompiados in parte - Sos vìdeos pompiados in antis e a pustis de los àere annànghidos a s\'iscalita ant a èssere bogados. -\n Seguru ses\? Custu no est reversìbile! - Bogare sos elementos pompiados\? + Eja, e fintzas sos vìdeos pompiados in parte + Sos vìdeos pompiados in antis e a pustis de los àere annànghidos a s\'iscalita ant a èssere bogados. \n Seguru ses? Custu no est reversìbile! + Bogare sos elementos pompiados? Boga sos elementos pompiados Predefinida de su sistema Limba de s\'aplicatzione @@ -822,4 +821,18 @@ Iscalitas Cumpartzi comente un\'iscalita temporànea de YouTube segundàriu + Chirca in %1$s + Chirca %1$s (%2$s) + Seletziona unu grupu de flussos + Galu perunu grupu de flussos creadu + Pàgina de grupu de canales + Agradessimentos + Pàgina Top 50 de SoundCloud bogada + SoundCloud at abbandonadu sos gràficos Top 50 originales. S\'ischeda currispondente est istada bogada dae sa pàgina printzipale tua. + Tendèntzias cumbinadas de YouTube bogadas + YouTube at abbandonadu sa pàgina de sas tendèntzias cumbinadas in su 21 de trìulas de su 2025. NewPipe at sostituidu sa pàgina de sas tendèntzias printzipales cun sas diretas de tendèntzia.\n\nPodes fintzas seletzionare pàginas de sas tendèntzias diferentes in \"Impostatziones > Cuntenutos > Cuntenutu de sa pàgina printzipale\". + Giogos de tendèntzia + Podcasts de tendèntzia + Films e programmas de tendèntzia + Mùsica de tendèntzia diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index f725965e2..9f79f2331 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -45,7 +45,7 @@ Náhľad avataru uploadera Lajky Dislajky - Začnite klepnutím na lupu. + Začnite ťuknutím na lupu. Obsah Zobraziť vekovo obmedzený obsah Naživo @@ -74,7 +74,7 @@ Čakajte prosím… Skopírované do schránky Priečinok na sťahovanie zadefinujte prosím neskôr v nastaveniach - Sťahované súbory + Stiahnuté súbory Stiahnuté Hlásenie o chybe Aplikácia/UP zlyhalo @@ -208,7 +208,7 @@ Neplatný ZIP súbor Upozornenie: Nemožno importovať všetky súbory. Toto prepíše vaše aktuálne nastavenie. - Trendy + Populárne Top 50 Nové a horúce Odstrániť @@ -473,7 +473,7 @@ %d dní Skupiny kanálov - Zdroj naposledy aktualizovaný: %s + Zdroj aktualizovaný: %s Nenačítané: %d Načítavanie zdroja… Spracovávanie zdroja… @@ -486,7 +486,7 @@ Bez názvu skupiny Chcete zmazať vybranú skupinu\? - Nová + Nový Zdroj Interval obnovy zdroja Čas od poslednej aktualizácie, kedy sa odber považuje za neaktuálny - %s @@ -509,9 +509,9 @@ Tento obsah ešte nie je podporovaný v NwPipe. \n \nMožno v budúcnosti sa to zmení. - Áno aj čiastočne pozreté videá + Áno aj čiastočne pozreté videá Pozreté videá, ktoré ste pozreli pred a po ich pridaní do playlistu, budú odstránené. \nSte si istí ich odstránením z playlistu? Táto operácia je nezvratná! - Odstrániť pozreté videá\? + Odstrániť pozreté videá? Odstrániť pozreté Pôvodné texty zo služieb budú viditeľné v položkách streamu Zobrazovať pôvodný čas @@ -724,7 +724,7 @@ Používate najnovšiu verziu NewPipe Táto možnosť je dostupná len pre motív %s Rýchly režim - Import alebo export odberov z 3-bodkovej ponuky + Importujte alebo exportujte odbery v menu s 3-mi bodkami Akcia gesta vľavo Vyberte gesto pre pravú polovicu obrazovky prehrávača Akcia gesta vpravo @@ -843,4 +843,24 @@ Páči sa SoundCloud Top 50 stránka odstránená SoundCloud prestal používať pôvodnú Top 50. Daná stránka bola odstránená z hlavnej stránky. + Odstránené kombinované trendy na YouTube + YouTube ukončil prevádzku kombinovanej stránky s trendmi k 21. júlu 2025. NewPipe nahradil predvolenú stránku s trendmi stránkou s trendovými živými prenosmi.\n\nV nastaveniach „Nastavenia > Obsah > Obsah hlavnej stránky“ môžete vybrať aj iné stránky s trendmi. + Populárne hry + Populárne podcasty + Populárne filmy a seriály + Populárna hudba + %stis. + %smil. + %smld. + Položka vymazaná + Vymazať položku + \"Povoliť zobrazenie cez iné aplikácie\" + Vymazať súbor + Ak chcete používať Popup Player, vyberte %1$s v nasledujúcej ponuke nastavení Androidu a povoľte %2$s. + Účet bol zrušený\n\n%1$s uvádza tento dôvod: %2$s + Počas prehrávania bola zo servera prijatá chyba HTTP 403, pravdepodobne spôsobená vypršaním platnosti streamingovej adresy URL alebo zákazom IP adresy + Chyba HTTP %1$s prijatá zo servera počas prehrávania + Chyba HTTP 403 prijatá zo servera počas prehrávania, pravdepodobne spôsobená zákazom IP adresy alebo problémami s deobfuskáciou streamingovej URL adresy + %1$s odmietol poskytnúť údaje, žiada o prihlásenie na potvrdenie, že žiadateľ nie je bot.\n\nVaša IP adresa mohla byť dočasne zakázaná %1$s, môžete nejaký čas počkať alebo prejsť na inú IP adresu (napríklad zapnutím/vypnutím VPN alebo prepnutím z WiFi na mobilné dáta). + Tento obsah nie je dostupný pre aktuálne zvolenú krajinu obsahu.\n\nZmeňte výber v ponuke \"Nastavenia > Obsah > Predvolená krajina obsahu\". diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 474be8127..8b4ba8f7b 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -261,7 +261,7 @@ NewPipe-ovi pravilnik zasebnosti Obiščite spletno mesto od NewPipe za več informacij in novic. Končano - Ni komantarjev + Ni komentarjev Nobeden ne posluša Nobeden ne gleda Zgodila se je napaka: %1$s diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 860a607f5..f40df57f1 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -490,10 +490,9 @@ %d ilbiriqsi Ayadooy ugu wacantahay xayiraad xaga ExoPlayer-ka ah xadka dhaaf-dhaafinta waa %d ilbiriqsi - Haa, sidoo kale ku dar muuqaalada qayb laga daawaday - Muuqaalada la daawaday kahor iyo kadib markii xulka lagu daray waa la saari doonaa. -\nMa hubtaa\? Arrinkan dib looma soocelin karo! - Saar muuqaalada la daawaday\? + Haa, sidoo kale ku dar muuqaalada qayb laga daawaday + Muuqaalada la daawaday kahor iyo kadib markii xulka lagu daray waa la saari doonaa. \nMa hubtaa? Arrinkan dib looma soocelin karo! + Saar muuqaalada la daawaday? Saar kuwa la daawaday Aaladu saytahay Luuqada Appka diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 4b9c2ac36..5a33ad77f 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -506,10 +506,9 @@ Zgjidhni dosjen e shkarkimit për skedarët video Skedarët video të shkarkuara ruhen këtu Nuk u gjend lexues për stream (ju mund të instaloni VLC për ta lexuar). - Po, dhe videot e shikuara pjesërisht - Videot që janë shikuar më parë dhe pasi janë shtuar në listën e luajtjes do të hiqen. -\nA jeni të sigurt\? Kjo nuk mund të zhbëhet! - Dëshironi t\'i hiqni videot e para\? + Po, dhe videot e shikuara pjesërisht + Videot që janë shikuar më parë dhe pasi janë shtuar në listën e luajtjes do të hiqen. \nA jeni të sigurt? Kjo nuk mund të zhbëhet! + Dëshironi t\'i hiqni videot e para? Hiq të parat Tekstet origjinale nga shërbimet do shihen në produktet e luajtshme Shfaq titullin origjinal \"kohë më parë\" në objekte diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 722ce6855..847b60f2f 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -78,7 +78,7 @@ Преузимања Извештај о грешци Програм је отказао - Шта:\\nЗахтев:\\nЈезик садржаја:\\nЗемља садржаја:\\nЈезик апликације:\\nУслуга:\\nGMT време:\\nПакет:\\nВерзија:\\nВерзија ОС-а: + Шта:\\nЗахтев:\\nЈезик садржаја:\\nДржава садржаја:\\nЈезик апликације:\\nУслуга:\\nGMT време:\\nПакет:\\nВерзија:\\nВерзија ОС-а: „reCAPTCHA“ задатак Решите „reCAPTCHA“ задатак Црна @@ -114,7 +114,7 @@ О NewPipe О нама и ЧПП Лиценце - Слободно и лагано стримовање на Android-у. + Слободно и лагано токовање на Android-у. Погледај на GitHub-у Прочитај лиценцу Допринос @@ -161,7 +161,7 @@ Без обзира имате ли идеје; превод, промене дизајна, чишћење кода или праве, озбиљне, промене кода—помоћ је увек добродошла. Што се више уради, то је боље! Прикажите савет када притиснете позадину или искачуће дугме у видео снимку „Детаљи:“ Пусти све - Није могуће пустити овај стрим + Није могуће пустити овај ток Дошло је до непоправљиве грешке плејера Опорављање од грешке плејера Желите ли да избришете ову ставку из историје претраге\? @@ -179,11 +179,11 @@ Детаљи Подешавања аудио снимка Није пронађен ниједан извођач довода (можете уградити ВЛЦ ради извођења садржаја). - Преузимање фајла стрима + Преузимање фајла тока Прикажи информације Обележене плејлисте Додај на - Подразумевана држава за садржај + Подразумевана држава садржаја Исправљање грешака Увек Само једном @@ -205,10 +205,9 @@ Приказ коментара Искључите да бисте сакрили коментаре Због ограничења ExoPlayer-а, премотавање је постављено на %d секунди - Да, и делимично одгледани видео снимци - Видео снимци који су одгледани пре и после додавања на плејлисту биће уклоњени. -\nЈесте ли сигурни\? Ово се не може поништити! - Уклонити одгледане видео снимке\? + Да, и делимично одгледани видео снимци + Видео снимци који су одгледани пре и после додавања на плејлисту биће уклоњени. \nЈесте ли сигурни? Ово се не може поништити! + Уклонити одгледане видео снимке? Уклони одгледано Системски подразумевано Језик апликације @@ -319,7 +318,7 @@ Увоз из Увоз Срушите апликацију - Изворни текстови са услуга биће видљиви у ставкама стрима + Изворни текстови са услуга биће видљиви у ставкама тока Прикажи изворно време ставки Присилно извештавање о „Rx“ изузецима који се не могу испоручити ван фрагмента или животног циклуса активности након одлагања Пријави грешке ван животног циклуса @@ -418,15 +417,15 @@ Врати подразумеване вредности Желите ли да вратите подразумеване вредности\? Није могуће прочитати сачуване картице, тако да се користе подразумеване - Нема стримова доступних за преузимање + Нема токова доступних за преузимање Дошло је до грешке: %1$s Фајл не постоји или нема дозволе за читање или писање Назив фајла не може бити празан Нема таквог фајла/извора садржаја Нема таквог фолдера Фајл је премештен или избрисан - Нису пронађени видео стримови - Нису пронађени аудио стримови + Нису пронађени видео токови + Нису пронађени аудио токови Спољни плејери не подржавају ове врсте линкова Преузимање на спољну, SD (меморијску), картицу није могуће. Ресетовати локацију фолдера за преузимање\? Спољна меморија није доступна @@ -440,7 +439,7 @@ Избриши позиције репродукције Историја гледања је избрисана Избрисати целу историју гледања\? - Брише историју пуштаних стримова и позиције репродукције + Брише историју пуштаних токова и позиције репродукције Очисти историју гледања Чисти колачиће које NewPipe чува када решите „reCAPTCHA“ Извоз историје, праћења, плејлисти и подешавања @@ -492,10 +491,10 @@ Вратите последњу позицију репродукције Настави репродукцију Аутоматско стављање у редослед - Наставите да завршавате (непонављајући) редослед репродукције додавањем сродног стрима - Аутоматски стави у редослед следећи стрим + Наставите да завршавате (непонављајући) редослед репродукције додавањем сродног тока + Аутоматски стави у редослед следећи ток Кеш метаподатака обрисан - Искључите да бисте сакрили поља за метаподатке са додатним информацијама о креатору стрима, садржају стрима или захтеву за претрагу + Искључите да бисте сакрили поља за метаподатке са додатним информацијама о креатору тока, садржају тока или захтеву за претрагу Прикажи метаподатке Искључите да бисте сакрили опис видео снимка и додатне информације Прикажи опис @@ -527,10 +526,10 @@ Аутоматски (тема уређаја) Радио Истакнуто - Овај садржај је доступан само корисницима који су платили, тако да га NewPipe не може стримовати или преузимати. - Овај видео снимак је доступан само премијум YouTube Music члановима, тако да га NewPipe не може стримовати или преузимати. - Овај садржај је приватан, тако да га NewPipe не може стримовати или преузимати. - Ово је SoundCloud Go+ нумера, барем у вашој земљи, тако да је NewPipe не може стримовати или преузимати. + Овај садржај је доступан само корисницима који су платили, тако да га NewPipe не може токовати или преузимати. + Овај видео снимак је доступан само премијум YouTube Music члановима, тако да га NewPipe не може токовати или преузимати. + Овај садржај је приватан, тако да га NewPipe не може токовати или преузимати. + Ово је SoundCloud Go+ нумера, барем у вашој земљи, тако да је NewPipe не може токовати или преузимати. Овај садржај није доступан у вашој земљи. Ниједна апликација на вашем уређају не може да отвори ово Поглавља @@ -649,7 +648,7 @@ %s преузимања је завршено %1$s %2$s - Обавештења о новим стримовима + Обавештења о новим токовима Обавештења Погледај на веб-сајту Ако имате проблема са коришћењем апликације, обавезно погледајте ове одговоре на честа питања! @@ -662,7 +661,7 @@ Поништи трајну сличицу Било која мрежа Ручно проверите постоје ли нове верзије - Спољни плејери не подржавају изабрани стрим + Спољни плејери не подржавају изабрани ток Померите главни бирач картице на дно Положај главних картица Дошло је до грешке, погледајте обавештење @@ -671,34 +670,34 @@ Учесталост провере Картица Уклонити дупликате\? - Желите ли да уклоните све дупликате стримова на овој плејлисти\? + Желите ли да уклоните све дупликате токова на овој плејлисти? Предстојеће Подешавања ExoPlayer-а Увек користи заобилазно решење ExoPlayer-а за подешавање површине излаза видео снимка Изабери квалитет за спољне плејере - Нема стримова - Нема стримова уживо + Нема токова + Нема токова уживо - %s нови стрим - %s нова стрима - %s нових стримова + %s нови ток + %s нова тока + %s нових токова - Учитавање детаља стрима… + Учитавање детаља тока… Прикажи „Сруши плејер“ - Покрени проверу нових стримова + Покрени проверу нових токова Тунеловање медија је подразумевано онемогућено на вашем уређају, јер је познато да ваш уређај то не подржава. Полутон - Обавештавање о новим стримовима из праћења + Обавештавање о новим токовима из праћења Провера ажурирања… Избрисати све преузете фајлове са диска\? Уклони дупликате Прикачен коментар ExoPlayer подразумевано Изабери све - Не приказују се стримови које програм за преузимање још увек не подржава - Аудио снимак би већ требало да буде присутан у овом стриму - Нема доступних аудио стримова за спољне плејере - Нема доступних видео стримова за спољне плејере + Не приказују се токови које програм за преузимање још увек не подржава + Аудио снимак би већ требало да буде присутан у овом току + Нема доступних аудио токова за спољне плејере + Нема доступних видео токова за спољне плејере Непознати формат Непознати квалитет Непознато @@ -712,8 +711,8 @@ Додирните да бисте преузели %s Провера ажурирања Преглед сличице траке за претрагу - Приказ следећих стримова - Прикажи/сакриј стримове + Приказ следећих токова + Прикажи/сакриј токове Користи резервну функцију декодера ExoPlayer-а оригинални Промените величину интервала учитавања на прогресивним садржајима (тренутно %s). Нижа вредност може убрзати њихово почетно учитавање @@ -722,8 +721,8 @@ Радња покретом улево Изаберите покрет за десну половину екрана плејера Обавештење плејера - Обавештења о новим стримовима за праћења - Конфигуришите обавештење о тренутно репродукованом стриму + Обавештења о новим токовима за праћења + Конфигуришите обавештење о тренутно репродукованом току Изаберите оригинални аудио снимак, без обзира на језик Изаберите аудио снимак са описима за особе са оштећеним видом, ако је доступан Преферирај описни аудио снимак @@ -731,7 +730,7 @@ Осветљеност Јачина звука Ниједно - Нови стримови + Нови токови Обавештења за пријаву грешака Увезите или извезите праћења из менија са 3 тачке Аудио снимак @@ -790,7 +789,7 @@ Низак квалитет Укључи цео екран Аватари - Следећи стрим + Следећи ток Аватари потканала Отвори редослед пуштања Не учитавај слике @@ -806,7 +805,7 @@ Више опција Сличице Трајање - Претходни стрим + Претходни ток Дели листу URL адреса Дели са насловима %1$s @@ -840,4 +839,28 @@ Изаберите групу фидова Страница групе канала Ликовања + Претрага %1$s + Претрага %1$s (%2$s) + Да бисте користили искачући плејер, изаберите %1$s у следећем менију подешавања Android-а и омогућите %2$s. + „Дозволи приказ преко других апликација“ + %sк + %sмлн. + %sмлрд. + Избриши фајл + Избриши унос + Налог је укинут\n\n%1$s наводи овај разлог: %2$s + Страница SoundCloud Top 50 је уклоњена + SoundCloud је укинуо оригиналне топ 50 листе. Одговарајућа картица је уклоњена са ваше главне странице. + Уклоњен је комбиновану страницу у тренду на YouTube-у + YouTube је укинуо комбиновану страницу у тренду од 21. јула 2025. NewPipe је заменио подразумевану страницу у тренду са страницом уживо у тренду.\n\nТакође можете одабрати различите странице у тренду у „Подешавања > Садржај > Садржај главне странице“. + Игре у тренду + Подкасти у тренду + Филмови и серије у тренду + Музика у тренду + Унос избрисан + HTTP грешка 403 примљена са сервера током репродукције, вероватно узрокована истеком URL-а за токовање или забраном IP адресе + HTTP грешка %1$s примљена са сервера током репродукције + HTTP грешка 403 примљена са сервера током репродукције, вероватно узрокована забраном IP адресе или проблемима са деобфускацијом URL-а за токовање + %1$s је одбио да пружи податке, тражећи пријаву како би се потврдило да подносилац захтева није бот.\n\nВаша IP адреса је можда привремено забрањена од стране %1$s, можете сачекати неко време или прећи на другу IP адресу (на пример, укључивањем/искључивањем VPN-а или преласком са WiFi-ја на мобилне податке). + Овај садржај није доступан за тренутно изабрану земљу садржаја.\n\nПромените свој избор у „Подешавања > Садржај > Подразумевана држава садржаја“. diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index f3703ea87..fb23c9201 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -144,7 +144,7 @@ \nöppna i popup-läge reCAPTCHA utmaning reCAPTCHA utmaning begärd - Hämta + Hämtning Tillåtna tecken i filnamn Ogiltiga tecken ersätts med detta värde Ersättningstecken @@ -166,8 +166,8 @@ Vill du ta bort det här objektet från sökhistoriken? Huvudsidans innehåll Tom sida - Kiosk sida - Kanal-sida + Kiosksida + Kanalsida Välj en kanal Inga kanal prenumerationer ännu Välj en kiosk @@ -473,10 +473,9 @@ %d sekunder På grund av ExoPlayer-begränsningar sattes söktiden till %d sekunder - Ja, och delvis tittade videor - Videor som har spelats före och efter att de har lagts till i spellistan kommer att tas bort. -\nÄr du säker\? Detta kan inte ångras! - Ta bort tittade videor\? + Ja, och delvis tittade videor + Videor som har spelats före och efter att de har lagts till i spellistan kommer att tas bort. \nÄr du säker? Detta kan inte ångras! + Ta bort tittade videor? Ta bort tittade Systemstandard Appspråk @@ -825,4 +824,29 @@ Välj en flödesgrupp Ingen flödesgrupp har skapats ännu Kanalgruppsida + Sök %1$s + Sök %1$s (%2$s) + %sK + %sM + %sB + Gillar + SoundCloud Topp 50-sida borttagen + SoundCloud har lagt ner de ursprungliga topp 50-listorna. Motsvarande flik har tagits bort från din startsida. + YouTubes kombinerade trender har tagits bort + YouTube har upphört med den kombinerade trendsidan från och med den 21 juli 2025. NewPipe ersatte standardtrendsidan med trendiga livestreams.\n\nDu kan också välja olika trendsidor i \"Inställningar > Innehåll > Innehåll på huvudsidan\". + Speltrender + Trendiga poddar + Trendiga filmer och serier + Trendig musik + För att använda Popup Player, välj %1$s i följande Android-inställningsmeny och aktivera %2$s. + \"Tillåt visning över andra appar\" + Ta bort fil + Ta bort post + Konto avslutat\n\n%1$s anger denna anledning: %2$s + Posten borttagen + HTTP-fel 403 mottogs från servern under uppspelning, troligen orsakat av att streaming-URL:en har löpt ut eller att en IP-adress har blockerats + HTTP-fel %1$s mottogs från servern under spelning + HTTP-fel 403 mottogs från servern under spelning, troligen orsakat av en IP-avstängning eller problem med deobfuskering av streaming-URL:er + %1$s vägrade att tillhandahålla data och bad om en inloggning för att bekräfta att den som begärde detta inte är en bot.\n\nDin IP-adress kan ha blivit tillfälligt avstängd av %1$s. Du kan vänta en stund eller byta till en annan IP-adress (till exempel genom att slå på/av ett VPN eller genom att byta från WiFi till mobildata). + Detta innehåll är inte tillgängligt för det valda innehållslandet.\n\nÄndra ditt val från \"Inställningar > Innehåll > Standardinnehållsland\". diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index f1d388393..b7534ccc0 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -509,7 +509,7 @@ ச்ட்ரீம்களைக் காட்டு/மறைக்க இந்த உள்ளடக்கம் உங்கள் நாட்டில் கிடைக்கவில்லை. திருப்பித் தரவும் - ஆம், மற்றும் ஓரளவு பார்த்த வீடியோக்கள் + ஆம், மற்றும் ஓரளவு பார்த்த வீடியோக்கள் கடைசியாக புதுப்பிக்கப்பட்டது: %s %s கேட்பவர் diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index c2cb4669e..e309b7fc7 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -409,4 +409,24 @@ ไม่มี ไม่ ใช่/ตกลง + วิดีโอ + ปิดเสียง + เลิกปิดเสียง + ใหม่ + ฟีด + เพลง + อัลบั้ม + ไม่ต้อง + ล่าสุด + ความคิดเห็น + คำอธิบาย + แนะนำ + หมวดหมู่ + แท็ก + ลิขสิทธิ์ + ภาษา + จัดเรียง + การ์ด + กำลังจะมา + ค้นหา %1$s diff --git a/app/src/main/res/values-ti/strings.xml b/app/src/main/res/values-ti/strings.xml index f25b86cc1..ccce73524 100644 --- a/app/src/main/res/values-ti/strings.xml +++ b/app/src/main/res/values-ti/strings.xml @@ -52,7 +52,7 @@ ቀዳማይ ወሰን ተጠዋቃ ደገመ ድምጺ ምውራድ ማህደር - ቦኦክማርከድ ዝርዝር-ጸወታ + ዝርዝር-ጸወታት ናይ ድምጺ ፋይል ኣራግፍ ምረጽ ዝጎደለ ኮረ ኣፕፕ ኣውራድ፧ ነባሪ ቅርጺ ድምጺ @@ -94,4 +94,95 @@ ደርፍታት ኣልበማት ስነ-ጥበባውያን + %1$s ድለ + ድለ %1$sን %2$s + ዝርዝር-ጸወታት + ራብዓይ ስጉምቲ መጠወቒ + ሕንፍሽፍሽ + ታሪኽ + ዞባዊ + ኣኼባ + ኣወግድ + ዝርዝር ሓበሬታ + መስርዕ + ተሰሪዑ + ስም ቀያር + ስም + ዓባስ + ኣብ ዝርዝር-ጸወታ ኮነ + ግጡም + ሙሉእ + ስጉሚ + ተቐበል + ንጸግ + ዋላ-ሓደ + ብፍጹም + ዝርዝር + ብዘይ መግለጺ ጽሑፍ + + %s ተራእዩ + %s ተራእዩ + + + %s ተኸታሊ + %s ተኸታተልቲ + + ሓድሽ ዝርዝር ጸወታ + ፍጠር + + %d ሰዓት + %d ሰዓታት + + + %d መዓልቲ + %d መዓልታት + + + %d ካልኢት + %d ካልኢት + + + %d ደቒቕ + %d ደቓይቕ + + እንታይ ሓድሽ ኣሎ + ሓድሽ + ጉጅለታት መስመር + ኩሉ ተጻወቶ + ኣብ ዝመጺእ + ብኸፊል ዝተራእየ + ብምሉእ ዝተራእየ + እዞም ዝስዕቡ ውሕጅታት ኣርእዩ + ዝተሓደሰ ዕለት: %s + ቅልጡፍ ኣገባብ ኣንቅሕ + ዝርዝራት: + ፈተውቲ + ጸላእቲ + ርእይቶታት + መብርሂ + ብድምጺ + እንደገና ፈትን + %sሽ + %sሚ + %sቢ + ጀምር + ደምስስ + ሰሩዞ + ስም ቀያር + ስሕተት + መፍለዪ + ህዝባዊ + ብሕትነት + ፍቓድታት + ፍቓድ ኣንብብ + ምድብ + ፍቓድ + እዋናዊታት + ኣቫታራት + ባነራት + ዘይተዘርዘረ + ብሕታዊ + ውሽጣዊ + ተኸታተልቲ + መርበብ-ቦታ ክፈት diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index c1d364226..083225ff9 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -506,10 +506,9 @@ Bu video yaş kısıtlıdır. \n \nGörmek istiyorsanız ayarlarda \"%1$s\" seçeneğini açın. - Oynatma listesine eklendikten önce ve sonra izlenen videolar kaldırılacak. -\nEmin misiniz\? Bu geri döndürülemez! - Evet ve kısmen izlenmiş videolar - İzlenen videoları kaldır\? + Oynatma listesine eklendikten önce ve sonra izlenen videolar kaldırılacak. \nEmin misiniz? Bu geri döndürülemez! + Evet ve kısmen izlenmiş videolar + İzlenen videoları kaldır? İzleneni kaldır Akış ögelerinde hizmetlerden alınan özgün metinler görünecektir Ögelerde özgün \'… önce\'yi göster @@ -830,4 +829,24 @@ %1$s İle Ara (%2$s) SoundCloud Top 50 sayfası kaldırıldı SoundCloud, özgün Top 50 listesini artık yayınlamıyor. İlgili sekme ana sayfanızdan kaldırıldı. + %sK + %sM + %sB + YouTube birleşik trendler kaldırıldı + YouTube, 21 Temmuz 2025\'ten sonra birleşik trendler sayfasını kaldırdı. NewPipe, öntanımlı trendler sayfasını trend canlı akışlarla değiştirdi.\n\n\"Ayarlar > İçerik > Ana sayfanın içeriği\"nden başka trend sayfalar seçebilirsiniz. + Oyun trendleri + Trend podcastler + Trend film ve gösteriler + Trend müzik + Açılır Oynatıcıyı kullanmak için Android ayarlar menüsünden %1$s seçilmeli ve %2$s etkinleştirilmeli. + “Diğer uygulamaların üstünde göstermeye izin ver” + Dosyayı sil + Girdiyi sil + Girdi silindi + Hesap sonlandırıldı\n\n%1$s şu nedeni sağladı: %2$s + Oynatırken sunucudan HTTP 403 hatası alındı, akış URL’si bitmiş ya da IP engellenmiş olabilir + Oynatırken sunucudan HTTP %1$s hatası alındı + Oynatırken sunucudan HTTP 403 hatası alındı, IP engeli ya da akış URL’si çözme sorunları olabilir + %1$s veri sağlamayı geri çevirdi, istekçinin robot olmadığını doğrulaması için oturum açmasını istiyor.\n\n%1$s, IP adresinizi geçici olarak engellemiş olabilir, bir süre bekleyebilir ya da başka IP\'ye geçebilirsiniz (örneğin VPN\'i açıp/kapatarak ya da WiFi\'den mobil veriye geçerek). + Bu içerik şu anda seçili içerik ülkesinde kullanılamıyor.\n\nSeçiminizi \"Ayarlar > İçerik > Öntanımlı içerik ülkesi\"nden değiştirin. diff --git a/app/src/main/res/values-tzm/strings.xml b/app/src/main/res/values-tzm/strings.xml index a62b37fa3..48a3ca921 100644 --- a/app/src/main/res/values-tzm/strings.xml +++ b/app/src/main/res/values-tzm/strings.xml @@ -39,7 +39,7 @@ %d wass %d wussan - Kkes ividyuten ittwannayen\? + Kkes ividyuten ittwannayen? 100+ ividyuten walu ividyuten Sɣur %s diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c0bc903a0..4526ea837 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -509,10 +509,9 @@ Не завантажено: %d Останнє оновлення: %s Через обмеження ExoPlayer точність перемотування становить %d секунд - Так, а також частково переглянуті відео - Відео, які Ви переглядали до та після додавання в добірку, вилучатимуться. -\nВи впевнені\? Це незворотна дія! - Видалити переглянуті відео\? + Так, а також частково переглянуті відео + Відео, які Ви переглядали до та після додавання в добірку, вилучатимуться. \nВи впевнені? Це незворотна дія! + Видалити переглянуті відео? Видалити переглянуті Створено автоматично (автора не знайдено) ∞ вiдео @@ -849,4 +848,24 @@ Пошук %1$s (%2$s) Сторінку SoundCloud Top 50 видалено SoundCloud припинив підтримку оригінальних чартів Топ-50. Відповідну вкладку видалено з вашої головної сторінки. + Видалено об’єднаний тренд YouTube + YouTube припинив підтримку об’єднаної сторінки трендів з 21 липня 2025 року. NewPipe замінив стандартну сторінку трендів на сторінку трендових прямих трансляцій.\n\nВи також можете вибрати різні сторінки трендів у розділі «Налаштування» > «Контент» > «Контент головної сторінки». + Ігрові тренди + Популярні подкасти + Популярні фільми та шоу + Популярна музика + %sтис + %sмлн + %sмлрд + Щоб використовувати спливаючий програвач, виберіть %1$s у наступному меню налаштувань Android та увімкніть %2$s. + “Дозволити показ поверх інших програм” + Видалити файл + Видалити запис + Запис видалено + Обліковий запис заблоковано\n\n%1$s вказує таку причину: %2$s + Під час відтворення від сервера отримано помилку HTTP 403, ймовірно, через закінчення терміну дії URL-адреси потокової передачі або заборону IP-адреси + Помилка HTTP %1$s отримана від сервера під час відтворення + Під час відтворення від сервера отримано помилку HTTP 403, ймовірно, через заборону IP-адреси або проблеми з деобфускацією URL-адреси потокової передачі + %1$s відмовився надати дані, запитуючи логін для підтвердження того, що запитувач не є ботом.\n\nВаша IP-адреса могла бути тимчасово заблокована %1$s. Ви можете почекати деякий час або перейти на іншу IP-адресу (наприклад, увімкнувши/вимкнувши VPN або переключившись з Wi-Fi на мобільні дані). + Цей контент недоступний для вибраної країни контенту.\n\nЗмініть свій вибір у розділі \"Налаштування > Контент > Країна контенту за замовчуванням\". diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index d145991bc..50ca67efc 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -6,7 +6,7 @@ Cài đặt Hủy Mở trong trình duyệt - Mở trong chế độ bật lên + Mở trong cửa sổ bật lên Chia sẻ Tải xuống Tìm kiếm @@ -120,7 +120,7 @@ Đã hủy đăng ký kênh Không thể thay đổi tình trạng đăng ký Không thể cập nhật tình trạng đăng ký - Không tìm thấy trình phát trực tuyến nào (bạn có thể cài đặt VLC để phát nó). + Không tìm thấy trình phát trực tuyến nào (bạn có thể cài đặt VLC để phát). Tải tệp luồng về Hiện thông tin Kênh đăng ký @@ -422,9 +422,8 @@ %d giây - Có, và video đã xem một phần - Những video đã xem trước và sau khi thêm vào danh sách phát sẽ bị loại bỏ. -\nBạn có chắc không? Điều này không thể được hoàn tác! + Có, và video đã xem một phần + Những video đã xem trước và sau khi thêm vào danh sách phát sẽ bị loại bỏ. \nBạn có chắc không? Điều này không thể được hoàn tác! Xóa các video đã xem? Loại bỏ đã xem Mặc định hệ thống @@ -797,12 +796,41 @@ Sao lưu và khôi phục Đặt lại cài đặt Đặt lại tất cả cài đặt về giá trị mặc định - Việc đặt lại tất cả cài đặt sẽ loại bỏ tất cả các cài đặt ưa thích của bạn và khởi động lại ứng dụng. -\n -\nBạn có chắc muốn tiếp tục? + Việc đặt lại tất cả cài đặt sẽ loại bỏ tất cả các cài đặt mà bạn đã đặt và khởi động lại ứng dụng. \n \nBạn có chắc muốn tiếp tục? Không NewPipe có thể tự động kiểm tra các phiên bản mới theo thời gian và thông báo cho bạn khi chúng có sẵn. \nBạn có muốn kích hoạt tính năng này không? Cài đặt trong xuất đang được nhập sử dụng định dạng dễ bị tấn công và không được dùng nữa kể từ NewPipe 0.27.0. Đảm bảo rằng bản xuất đang được nhập là từ một nguồn đáng tin cậy và chỉ ưu tiên sử dụng các bản xuất lấy từ NewPipe 0.27.0 hoặc mới hơn trong tương lai. Hỗ trợ nhập cài đặt ở định dạng dễ bị tấn công này sẽ sớm bị xóa hoàn toàn và khi đó các phiên bản cũ của NewPipe sẽ không thể nhập cài đặt xuất từ phiên bản mới nữa. + Tìm kiếm %1$s + Tìm kiếm %1$s (%2$s) + Danh sách phát + %sN + %sTr + %sTỷ + Chọn một nhóm nguồn cấp dữ liệu + Chưa có nhóm nguồn cấp dữ liệu nào được tạo + Trang nhóm kênh + phụ + Thích + Chia sẻ dưới dạng danh sách phát tạm thời của YouTube + SoundCloud 50 trang hàng đầu đã xóa + SoundCloud đã ngừng hiển thị bảng xếp hạng Top 50 ban đầu. Tab tương ứng đã bị xóa khỏi trang chính của bạn. + Đã xóa kết hợp đang thịnh hành của YouTube + YouTube đã ngừng cung cấp trang thịnh hành kết hợp kể từ ngày 21 tháng 7 năm 2025. NewPipe đã thay thế trang xu hướng mặc định bằng các buổi phát trực tiếp theo thịnh hành.\n\nBạn cũng có thể chọn các trang thịnh hành khác nhau trong \"Cài đặt > Nội dung > Nội dung của trang chính\". + Trò chơi thịnh hành + Podcasts đang thịnh hành + Phim và chương trình đang thịnh hành + Âm nhạc đang thịnh hành + Đã xảy ra lỗi HTTP 403 trong khi phát, có thể do URL phát sóng đã hết hạn hoặc bị ban IP + %1$s đã từ chối cung cấp dữ liệu, cần phải đăng nhập để xác nhận yêu cầu viên ko phải là bot.\n\nIP này có vẻ đã bị ban tạm thời bởi %1$s, bạn có thể đợi một lúc hoặc chuyển sang IP khác (ví dụ như việc tắt / bật lại VPN, hoặc là chuyển mạng từ WIFI sang 4G/5G). + Nội dung này không được hỗ trợ tại quốc gia mà bạn chọn.\n\nHãy đổi quốc gia trong phần \"Cài đặt > Nội dung > Nội dung quốc gia mặc định\". + Để sử dụng tính năng phát video nổi, hãy chọn %1$s trong Cài đặt Android và bật tính năng %2$s. + Đã xảy ra lỗi HTTP 403 trong khi phát, có thể IP này đã bị ban hoặc vấn đề phát URL deobfuscation + \"Cho phép hiển thị trên ứng dụng khác\" + Xóa file + Xóa entry + Tài khoản bị vô hiệu hóa. \n\n%1$s cung cấp lý do này: %2$s + Entry đã xóa + Đã xảy ra lỗi HTTP %1$s trong khi phát diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index c6e1538ec..7622cddcf 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -366,7 +366,7 @@ 找不到服务器 无法连接至服务器 服务器未发送数据 - 找不到 NOT FOUND + 找不到 后期处理失败 停止 最大重试次数 @@ -500,9 +500,8 @@ 由 %s 由 %s 创建 频道的头像缩略图 - 是的,包括没看完的视频 - 已经看过且在之后被加入播放列表的视频将被删除。 -\n您确定吗?操作不能被撤消! + 是的,包括没看完的视频 + 已经看过且在之后被加入播放列表的视频将被删除。 \n您确定吗?操作不能被撤消! 移除看过的视频? 移除看过的视频 来自服务的原始文本将在串流项目中可见 @@ -816,4 +815,24 @@ 搜索 %1$s (%2$s) 移除了 SoundCloud Top 50 页面 SoundCloud 已停止发布原创 Top 50 榜单。相应的标签页已从你的主页移除。 + 移除了 Youtube 合并的“时下流行”标签页 + 自 2025.7.21 起, Youtube 下线了合并的“时下流行”标签页。Newpipe 用“时下流行”的直播替代了默认的“时下流行”页。\n\n你也可以在 “设置 > 内容> 主页内容”中选择不同的“时下流行”页。 + “时下流行”的游戏视频 + “时下流行”的播客 + “时下流行”的电影和娱乐节目 + “时下流行”的音乐 + %s千 + %s百万 + %s十亿 + 要使用弹窗播放器,请在接下来的安卓设置中选择 %1$s 并开启 %2$s。 + “允许显示在其他应用上方” + 删除文件 + 删除条目 + 删除了条目 + 账户终止\n\n%1$s 提供了这个原因:%2$s + 播放时从服务器收到 HTTP 403 错误,可能因串流 URL 过期或 IP 封锁导致 + 播放时从服务器收到 HTTP %1$s 错误 + 播放时从服务器收到 HTTP 403 错误,可能因 IP 封锁或串流 URL 解密问题导致 + %1$s 拒绝提供数据, 要求登录确认请求方不是机器人。\n\n你的 IP 可能已经暂时被 %1$s 封禁,你可以等待一段时间或切换到不同 IP (比如开/关 VPN, 或者从 WiFi 连接切换到移动数据)。 + 此内容对当前选中的内容地区不可用。\n\n要更改选择,请前往 “设置 > 内容 > 默认内容地区”。 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 24f457c25..c483ca96b 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -538,7 +538,7 @@ 令個 app 閃退 顯示一則錯誤橫條 建立一則出現錯誤通知 - 好,包括埋睇過但未睇晒嘅影片 + 好,包括埋睇過但未睇晒嘅影片 礙於 ExoPlayer 所限,快轉長度經已改為 %d 秒 影片雜湊通知 排咗去隊尾 @@ -555,8 +555,7 @@ 每次下載都會問你要儲存去邊。 \n如果你想儲存落外置 SD 卡入面,請啟用系統資料夾揀選器 (SAF) 用系統資料夾揀選器 (SAF) - 加入去播放清單之前或之後睇過嘅影片都會剷走個囉喎。 -\n你肯定?剷走咗冇得掹個囉喎! + 加入去播放清單之前或之後睇過嘅影片都會剷走個囉喎。 \n你肯定?剷走咗冇得掹個囉喎! 「儲存空間存取框架」係畀你下載落外置 SD 卡嗰度 Android 10 打上,局住要用「儲存空間存取框架」 ExoPlayer 預設值 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 22dd24a33..d69f4e5a8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,7 +1,7 @@ 發佈於 %1$s - 未找到串流播放器。安裝 VLC? + 找不到串流播放器。是否安裝 VLC? 安裝 取消 以瀏覽器開啟 @@ -14,14 +14,14 @@ 使用外部影片播放器 使用外部音訊播放器 影片下載資料夾 - 下載好的影片檔案會儲存在這裡 + 下載完的影片檔案會儲存在這裡 選擇視訊檔案的下載資料夾 預設解析度 - 用 Kodi 播放 - 顯示用 Kodi 媒體中心播放影片的選項 + 使用 Kodi 播放 + 顯示使用 Kodi 媒體中心播放影片的選項 聲音 要安裝缺少的 Kore 應用程式嗎? - 顯示「用 Kodi 播放」的選項 + 顯示「使用 Kodi 播放」的選項 預設音訊格式 主題 深色 @@ -40,8 +40,8 @@ 不喜歡 音訊下載資料夾 下載好的音訊檔案會儲存在這裡 - 選擇音訊檔的下載資料夾 - 點選放大鏡即可開始。 + 選擇音訊檔案的下載資料夾 + 輕觸放大鏡即可開始。 以懸浮視窗開啟 移除某些解析度的音訊 背景播放 @@ -77,7 +77,7 @@ 資訊: 發生了什麼事: 發生了什麼:\\n請求:\\n內容語言:\\n內容國家:\\n應用程式語言:\\n服務:\\nGMT 時間:\\n套件:\\n版本:\\n系統版本: - 您的留言(請用英語): + 您的留言 (請用英語): 詳細資訊: 影片 音訊 @@ -111,9 +111,9 @@ 搜尋記錄 在本機儲存搜尋記錄 觀看記錄 - 記錄觀看過的影片 + 記錄已觀看的影片 恢復播放 - 在干擾結束後繼續播放(例如有來電) + 在干擾結束後繼續播放 (例如有來電) 播放器 行為 歷史記錄與快取 @@ -133,8 +133,8 @@ 沒有影片 下載 檔案名稱中允許的字元 - 不符合設定的字元將會被替換為此字串 - 替換為 + 無效字元將會被替換為此值 + 替換字元 字母與數字 大部分的特殊字元 關於 NewPipe @@ -145,13 +145,13 @@ Android 上自由且輕巧的串流播放器。 在 GitHub 上檢視 NewPipe 使用的授權條款 - 不管你有什麼點子──翻譯、設計、程式碼整理,或者程式碼撰寫──我們永遠歡迎你來幫忙。完成的越多,NewPipe 也會更好! + 不管您有什麼點子 ── 翻譯、設計、清理或撰寫大量程式碼 ── 我們永遠歡迎您來幫忙。做得越多,NewPipe 就會更好! 閱讀授權條款 貢獻 歷史記錄 歷史記錄 確定要刪除此項搜尋記錄嗎? - 找不到串流播放器(您可以安裝 VLC 來播放)。 + 找不到串流播放器 (您可以安裝 VLC 來播放)。 顯示「長按以新增」提示 預設內容國家 全部播放 @@ -172,7 +172,7 @@ 網站 匯入資料庫 匯出資料庫 - 覆蓋您目前的歷史記錄、訂閱與設定(選用) + 覆寫您目前的歷史記錄、訂閱與設定 (選用) 匯出歷史記錄、訂閱內容、播放清單、設定 回饋 如欲了解更多有關 NewPipe 的資訊和新聞,請造訪我們的網站。 @@ -207,7 +207,7 @@ 正在載入要求的內容 下載串流檔案 顯示資訊 - 書籤播放列表 + 書籤播放清單 新增至 拖曳以重新排序 建立 @@ -238,8 +238,8 @@ 強制報告在處理完片段或活動週期外發生的無法傳遞的 Rx 異常 使用粗略但快速的尋找 粗略的尋找能讓播放器以降低的精確度更快找到影片的進度位置。尋找 5、15 或 25 秒無法與其一同使用 - 自動排序下一個串流 - 透過加入相關的串流來繼續結束的(未重複)播放佇列 + 自動佇列至下一個串流 + 透過加入相關的串流來繼續結束的 (未重複) 播放佇列 檔案 無效的資料夾 無效的檔案或內容來源 @@ -254,17 +254,9 @@ 無法匯入訂閱內容 無法匯出訂閱內容 之前的匯出 - 檔案不存在或讀取或寫入權限不足 - 從 Google Takeout 匯入您的 YouTube 訂閱: -\n -\n1. 移至此網址:%1$s -\n2. 當被提示時登入帳號 -\n3. 按一下「包含所有資料」,接著「取消選取全部」,然後僅勾選「訂閱」並按一下「確定」 -\n4. 按一下「下一步」然後「建立匯出」 -\n5. 在「下載」按鈕出現後按一下它 -\n6. 點擊下方的「匯入檔案」並選取已下載的 zip 檔案 -\n7. [若 zip 匯入失敗] 擷取 .csv 檔案(通常位於「YouTube 與 YouTube Music/訂閱/訂閱.csv」),按一下下方的「匯入檔案」並選取擷取的 csv 檔案 - yourID, soundcloud.com/yourid + 檔案不存在或缺少讀寫檔案的權限 + 從 Google Takeout 匯入您的 YouTube 訂閱: \n \n1. 移至此網址:%1$s \n2. 當被提示時登入帳號 \n3. 按一下「包含所有資料」,接著「取消選取全部」,然後僅勾選「訂閱」並按一下「確定」 \n4. 按一下「下一步」然後「建立匯出」 \n5. 在「下載」按鈕出現後按一下它 \n6. 點擊下方的「匯入檔案」並選取已下載的 zip 檔案 \n7. [若 zip 匯入失敗] 擷取 .csv 檔案 (通常位於「YouTube 與 YouTube Music/訂閱/訂閱.csv」),按一下下方的「匯入檔案」並選取擷取的 csv 檔案 + 您的 ID, soundcloud.com/yourid 請記住,此操作可造成昂貴網路花費。 \n \n您是否希望繼續? @@ -275,13 +267,13 @@ \n3. 當被提示時登入帳號 \n4. 複製您被重新導向到的個人設定檔網址。 已清除圖片快取 - 清除已快取的後設資料 + 清除已快取的詮釋資料 移除所有已快取的網頁資料 - 已清除後設資料快取 + 已清除詮釋資料快取 播放速度控制 節奏 音高 - 解除掛鉤(可能導致失真) + 解除掛鉤 (可能導致失真) 偏好的「開啟」動作 開啟內容時的預設動作 ─ %s 沒有可供下載的串流 @@ -350,7 +342,7 @@ 下載失敗 生成獨特的名稱 覆寫 - 已有此名稱的已下載檔案 + 有已下載的同名檔案 已有進行中的下載與此同名 顯示錯誤 無法建立檔案 @@ -366,7 +358,7 @@ 最大重試次數 在取消下載前的最大嘗試數 在計量收費網路上時中斷 - 在切換到行動數據時很有用(雖然某些下載無法暫停) + 切換到行動數據時很有用,雖然某些下載無法暫停 事件 會議 連線已逾時 @@ -382,8 +374,8 @@ 在清單中顯示播放位置指示器 清除資料 播放位置已刪除 - 檔案已遭移動或刪除 - 與此同名的檔案已存在 + 檔案已被移動或刪除 + 同名的檔案已存在 無法覆寫檔案 已有擱置中的下載與此同名 NewPipe 在處理檔案時被關閉 @@ -416,21 +408,21 @@ %s 位聽眾 快轉/快退搜尋持續時間 - PeerTube 站臺 - 選取您最愛的 PeerTube 站臺 - 在 %s 上找到您喜愛的站臺 - 新增站臺 - 輸入站臺網址 - 無法驗證站臺 + PeerTube 實例 + 選取您最愛的 PeerTube 實例 + 在 %s 上找到您喜歡的實例 + 新增實例 + 輸入實例網址 + 無法驗證實例 僅支援 HTTPS 網址 - 站臺已存在 + 實例已存在 本機 最近新增 最喜歡 - 自動生成(未找到上傳者) + 自動生成 (未找到上傳者) 正在恢復 無法恢復此下載 - 選擇一個站臺 + 選擇一個實例 清除下載歷史記錄 刪除已下載的檔案 給予顯示在其他應用程式上層的權限 @@ -472,20 +464,10 @@ 上次更新後,訂閱被視為過時的時間 ─ %s 總是更新 在可用時從專用 feed 擷取 - 其在某些服務中可用,且通常較快速,但可能只會回傳有限的項目,而且資訊通常不完整(例如:沒有持續時間、項目類型、沒有即時狀態) + 其在某些服務中可用,且通常較快速,但可能只會回傳有限的項目,而且資訊通常不完整 (例如:沒有持續時間、項目類型、沒有即時狀態) 啟用快速模式 停用快速模式 - 您覺得 feed 載入太慢了嗎?如果是的話,試著啟用快速載入(您可以在設定中變更或按下下方的按鈕)。 -\n -\nNewPipe 提供兩個 feed 載入策略: -\n• 擷取整個訂閱頻道,慢但是完整。 -\n• 使用專用的伺服器端點,較快速但是通常不完整。 -\n -\n兩者之間的差別是,較快速的通常缺少部份資訊,如項目的持續時間或類型(無法區分直播影片或一般影片),而且其可能會回傳較少項目。 -\n -\nYouTube 是一種透過其 RSS feed 提供這種快速方式的例子。 -\n -\n因此,請選取您較偏好的:速度或準確的資訊。 + 您覺得 feed 載入太慢了嗎?如果是的話,試著啟用快速載入 (您可以在設定中變更或按下下方的按鈕)。 \n \nNewPipe 提供兩個 feed 載入策略: \n• 擷取整個訂閱頻道,慢但是完整。 \n• 使用專用的伺服器端點,較快速但是通常不完整。 \n \n兩者之間的差別是,較快速的通常缺少部份資訊,如項目的持續時間或類型(無法區分直播影片或一般影片),而且其可能會回傳較少項目。 \n \nYouTube 是一種透過其 RSS feed 提供這種快速方式的例子。 \n \n因此,請選取您較偏好的:速度或準確的資訊。 NewPipe 尚未支援此內容。 \n \n希望它會在未來的版本中支援。 @@ -497,11 +479,10 @@ 此影片設有年齡限制。 \n \n如果您想要觀看,請在設定中開啟「%1$s」。 - 是的,包括已部份觀看的影片 - 在新增到播放清單前和後已觀看的影片將被移除。 -\n您確定嗎?此動作無法復原! + 是的,包括已部份觀看的影片 + 已觀看過的影片在加入播放清單後將被移除。\n您確定嗎?此動作無法復原! 移除已觀看的影片? - 移除已觀看 + 移除已觀看的影片 來自服務的原始文字將在串流項目中可見 在項目上顯示原始時間 開啟 YouTube 的「嚴格篩選模式」 @@ -530,7 +511,7 @@ 隨機 循環 您可以選取最多三個動作來顯示在簡潔通知中! - 透過輕觸下方的通知來編輯它。使用右側的勾選框,最多可以選取三個在簡潔通知中顯示。 + 透過輕觸下方的通知動作來編輯它們。使用右側的勾選框,最多可以選取三個在簡潔通知中顯示。 第五動作按鈕 第四動作按鈕 第三動作按鈕 @@ -545,8 +526,8 @@ reCAPTCHA cookies 已被清除 清除 reCAPTCHA cookies YouTube 有提供「嚴格篩選模式」,可以隱藏潛在的成人內容 - 顯示可能不適於兒童的內容,因為其有年齡限制(如 18 歲以上等) - 讓 Android 根據縮圖中的主要色彩來自訂通知的顏色(請注意,此功能不是在所有裝置上都能正常運作) + 顯示可能不適於兒童的內容,因為其有年齡限制 (例如 18 歲以上) + 讓 Android 根據縮圖中的主要色彩來自訂通知的顏色 (請注意,此功能並不是在所有裝置上都能正常運作) 彩色通知 於鎖定畫面背景與通知使用縮圖 顯示縮圖 @@ -578,7 +559,7 @@ 下載已經開始 您可以在下方選取您最愛的夜間佈景主題 選取您最愛的夜間佈景主題 ─ %s - 自動(裝置佈景主題) + 自動 (裝置佈景主題) 深色主題 顯示頻道詳細資訊 如果您遇到黑畫面或影片播放停頓的現象,請停用媒體隧道。 @@ -614,11 +595,11 @@ 平板電腦模式 留言已停用 不要顯示 - 低品質(較小) - 高品質(較大) + 低品質 (較小) + 高品質 (較大) 拖動列縮圖預覽 被創作者加心號 - 標記為已看 + 標記為已觀看 在圖片頂部顯示畢卡索彩色絲帶,指示其來源:紅色代表網路、藍色代表磁碟、綠色代表記憶體 顯示圖片指示器 遠端搜尋建議 @@ -646,11 +627,9 @@ 回報錯誤的通知 顯示錯誤 SnackBar 建立錯誤通知 - 找不到適合此動作的檔案管理程式。 -\n請安裝相容於儲存空間存取框架的檔案管理員 - 找不到適合此動作的檔案管理程式。 -\n請安裝檔案管理程式或在下載設定嘗試停用「%s」 - NewPipe 遇到錯誤,點擊以回報 + 找不到適合此動作的檔案管理員。 \n請安裝相容於儲存空間存取框架的檔案管理員 + 找不到適合此動作的檔案管理員。 \n請安裝檔案管理員或在下載設定裡嘗試停用「%s」 + NewPipe 遭遇了一個錯誤,輕觸以回報 發生錯誤,請查看通知 釘選的留言 LeakCanary 無法使用 @@ -691,7 +670,7 @@ 排序 若您在使用此應用程式時遇到任何問題,請務必先看看常見問題的答案! 您正在執行最新版本的 NewPipe - 輕點以下載 %s + 輕觸以下載 %s 快速模式 從三點式選單匯入或匯出訂閱 此選項僅在主題選擇為 %s 時可用 @@ -705,7 +684,7 @@ 移除重複的? 顯示以下串流 顯示/隱藏串流 - 完全觀看 + 完全看完 部份觀看 即將到來 移除重複的 @@ -729,7 +708,7 @@ 原始 配音 描述性 - 變更漸進式內容的載入間隔大小(目前為 %s)。較低的值可能會加速初始載入速度 + 變更漸進式內容的載入間隔大小 (目前為 %s)。較低的值可能會加速初始載入速度 偏好描述性的音訊 若可用,為視障人士選取帶有描述的音訊軌道 無論語言都選取原始音訊軌道 @@ -749,7 +728,7 @@ 頻道頁面上顯示哪些分頁 頻道分頁 短片 - 正在載入後設資料…… + 正在載入詮釋資料…… 擷取頻道分頁 關於 專輯 @@ -792,7 +771,7 @@ 顯示更多 顯示較少 - 透過點擊下面的每個通知操作來編輯它。前三個動作(播放/暫停、上一個與下一個)由系統設定,無法自訂。 + 透過輕觸下方的通知動作來編輯它們。前三個動作 (播放/暫停、上一個與下一個) 由系統設定,無法自訂。 裝置上沒有足夠的空間 備份與還原 重設設定 @@ -816,4 +795,24 @@ 搜尋 %1$s (%2$s) 已移除 SoundCloud Top 50 頁面 SoundCloud 已停止原有的 Top 50 排行榜。對應的標籤已從您的首頁移除。 + %sK + %sM + %sB + 已移除 YouTube 合併熱門 + YouTube 自2025年7月21日起停止使用合併熱門頁面。NewPipe 用熱門直播取代預設熱門頁面。\n\n您也可以在「設定」→「內容」→「首頁內容」中選擇不同的熱門頁面。 + 遊戲熱門 + 熱門 podcast + 熱門電影與節目 + 熱門音樂 + 若要使用彈出式播放器,請在以下 Android 設定選單中選取 %1$s,並啟用 %2$s。 + 「顯示在其他應用程式上層」 + 刪除檔案 + 刪除條目 + 已刪除條目 + 帳號已終止\n\n%1$s 提供了理由:%2$s + 播放時收到來自伺服器的 HTTP 錯誤 403,可能因串流網址過期或 IP 封鎖所致 + 播放時收到來自伺服器的 HTTP 錯誤 %1$s + 播放時收到來自伺服器的 HTTP 錯誤 403,可能因 IP 封鎖或串流網址去混淆化問題所致 + %1$s 拒絕提供資料,要求登入以確認請求者並非機器人。\n\n您的 IP 位址可能已被 %1$s 暫時封鎖,您可稍候片刻或切換至其他 IP 位址(例如開啟/關閉 VPN,或從 Wi-Fi 切換至行動數據)。 + 此內容目前無法於您所選的國家/地區提供。\n\n請至「設定」→「內容」→「預設內容國家」變更您的選擇。 diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 352e4cec1..ab6e9e345 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -479,6 +479,7 @@ popup_player download add_to_playlist + enqueue always_ask_player @@ -488,6 +489,7 @@ @string/popup_player @string/download @string/add_to_playlist + @string/enqueue_stream @string/always_ask_open_action @@ -498,6 +500,7 @@ @string/download_key @string/add_to_playlist_key @string/always_ask_open_action_key + @string/enqueue_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 147c88938..1a2a5b6f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -667,13 +667,13 @@ App language System default Remove watched - Remove watched videos? + Remove watched streams? Remove duplicates Remove duplicates? Do you want to remove all duplicate streams in this playlist? - Videos that have been watched before and after being added to the playlist will be removed. -\nAre you sure\? This cannot be undone! - Yes, and partially watched videos + Streams that have been watched before and after being added to the playlist will be removed. +\nAre you sure\? + Remove partially watched streams Due to ExoPlayer constraints the seek duration was set to %d seconds diff --git a/app/src/main/res/xml/video_audio_settings.xml b/app/src/main/res/xml/video_audio_settings.xml index 727ce4df4..6e8e2979b 100644 --- a/app/src/main/res/xml/video_audio_settings.xml +++ b/app/src/main/res/xml/video_audio_settings.xml @@ -62,7 +62,7 @@ app:useSimpleSummaryProvider="true" /> localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(0, mergedPlaylists.size()); - } - - @Test - public void onlyLocalPlaylists() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - localPlaylists.add(new PlaylistMetadataEntry(1, "name1", "", false, -1, 0, 1)); - localPlaylists.add(new PlaylistMetadataEntry(2, "name2", "", false, -1, 1, 1)); - localPlaylists.add(new PlaylistMetadataEntry(3, "name3", "", false, -1, 3, 1)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(3, mergedPlaylists.size()); - assertEquals(0, mergedPlaylists.get(0).getDisplayIndex()); - assertEquals(1, mergedPlaylists.get(1).getDisplayIndex()); - assertEquals(3, mergedPlaylists.get(2).getDisplayIndex()); - } - - @Test - public void onlyRemotePlaylists() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - remotePlaylists.add(new PlaylistRemoteEntity( - 1, "name1", "url1", "", "", 1, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 2, "name2", "url2", "", "", 2, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 3, "name3", "url3", "", "", 4, 1L)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(3, mergedPlaylists.size()); - assertEquals(1, mergedPlaylists.get(0).getDisplayIndex()); - assertEquals(2, mergedPlaylists.get(1).getDisplayIndex()); - assertEquals(4, mergedPlaylists.get(2).getDisplayIndex()); - } - - @Test - public void sameIndexWithDifferentName() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - localPlaylists.add(new PlaylistMetadataEntry(1, "name1", "", false, -1, 0, 1)); - localPlaylists.add(new PlaylistMetadataEntry(2, "name2", "", false, -1, 1, 1)); - remotePlaylists.add(new PlaylistRemoteEntity( - 1, "name3", "url1", "", "", 0, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 2, "name4", "url2", "", "", 1, 1L)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(4, mergedPlaylists.size()); - assertTrue(mergedPlaylists.get(0) instanceof PlaylistMetadataEntry); - assertEquals("name1", ((PlaylistMetadataEntry) mergedPlaylists.get(0)).name); - assertTrue(mergedPlaylists.get(1) instanceof PlaylistRemoteEntity); - assertEquals("name3", ((PlaylistRemoteEntity) mergedPlaylists.get(1)).getName()); - assertTrue(mergedPlaylists.get(2) instanceof PlaylistMetadataEntry); - assertEquals("name2", ((PlaylistMetadataEntry) mergedPlaylists.get(2)).name); - assertTrue(mergedPlaylists.get(3) instanceof PlaylistRemoteEntity); - assertEquals("name4", ((PlaylistRemoteEntity) mergedPlaylists.get(3)).getName()); - } - - @Test - public void sameNameWithDifferentIndex() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - localPlaylists.add(new PlaylistMetadataEntry(1, "name1", "", false, -1, 1, 1)); - localPlaylists.add(new PlaylistMetadataEntry(2, "name2", "", false, -1, 3, 1)); - remotePlaylists.add(new PlaylistRemoteEntity( - 1, "name1", "url1", "", "", 0, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 2, "name2", "url2", "", "", 2, 1L)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(4, mergedPlaylists.size()); - assertTrue(mergedPlaylists.get(0) instanceof PlaylistRemoteEntity); - assertEquals("name1", ((PlaylistRemoteEntity) mergedPlaylists.get(0)).getName()); - assertTrue(mergedPlaylists.get(1) instanceof PlaylistMetadataEntry); - assertEquals("name1", ((PlaylistMetadataEntry) mergedPlaylists.get(1)).name); - assertTrue(mergedPlaylists.get(2) instanceof PlaylistRemoteEntity); - assertEquals("name2", ((PlaylistRemoteEntity) mergedPlaylists.get(2)).getName()); - assertTrue(mergedPlaylists.get(3) instanceof PlaylistMetadataEntry); - assertEquals("name2", ((PlaylistMetadataEntry) mergedPlaylists.get(3)).name); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.kt b/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.kt new file mode 100644 index 000000000..ace51e7e2 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.kt @@ -0,0 +1,102 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package org.schabi.newpipe.database.playlist + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity +import org.schabi.newpipe.local.bookmark.MergedPlaylistManager + +class PlaylistLocalItemTest { + + @Test + fun emptyPlaylists() { + val localPlaylists = listOf() + val remotePlaylists = listOf() + val mergedPlaylists = MergedPlaylistManager.merge(localPlaylists, remotePlaylists) + assertEquals(0, mergedPlaylists.size) + } + + @Test + fun onlyLocalPlaylists() { + val localPlaylists = listOf( + PlaylistMetadataEntry(1, "name1", "", 0, false, -1, 1), + PlaylistMetadataEntry(2, "name2", "", 1, false, -1, 1), + PlaylistMetadataEntry(3, "name3", "", 3, false, -1, 1) + ) + val remotePlaylists = listOf() + val mergedPlaylists = MergedPlaylistManager.merge(localPlaylists, remotePlaylists) + + assertEquals(3, mergedPlaylists.size) + assertEquals(0L, mergedPlaylists[0]!!.displayIndex) + assertEquals(1L, mergedPlaylists[1]!!.displayIndex) + assertEquals(3L, mergedPlaylists[2]!!.displayIndex) + } + + @Test + fun onlyRemotePlaylists() { + val localPlaylists = listOf() + val remotePlaylists = listOf( + PlaylistRemoteEntity(1, 1, "name1", "url1", "", "", 1, 1), + PlaylistRemoteEntity(2, 2, "name2", "url2", "", "", 2, 1), + PlaylistRemoteEntity(3, 3, "name3", "url3", "", "", 4, 1) + ) + val mergedPlaylists = MergedPlaylistManager.merge(localPlaylists, remotePlaylists) + + assertEquals(3, mergedPlaylists.size) + assertEquals(1L, mergedPlaylists[0]!!.displayIndex) + assertEquals(2L, mergedPlaylists[1]!!.displayIndex) + assertEquals(4L, mergedPlaylists[2]!!.displayIndex) + } + + @Test + fun sameIndexWithDifferentName() { + val localPlaylists = listOf( + PlaylistMetadataEntry(1, "name1", "", 0, false, -1, 1), + PlaylistMetadataEntry(2, "name2", "", 1, false, -1, 1) + ) + val remotePlaylists = listOf( + PlaylistRemoteEntity(1, 1, "name3", "url1", "", "", 0, 1), + PlaylistRemoteEntity(2, 2, "name4", "url2", "", "", 1, 1) + ) + val mergedPlaylists = MergedPlaylistManager.merge(localPlaylists, remotePlaylists) + + assertEquals(4, mergedPlaylists.size) + assertTrue(mergedPlaylists[0] is PlaylistMetadataEntry) + assertEquals("name1", (mergedPlaylists[0] as PlaylistMetadataEntry).orderingName) + assertTrue(mergedPlaylists[1] is PlaylistRemoteEntity) + assertEquals("name3", (mergedPlaylists[1] as PlaylistRemoteEntity).orderingName) + assertTrue(mergedPlaylists[2] is PlaylistMetadataEntry) + assertEquals("name2", (mergedPlaylists[2] as PlaylistMetadataEntry).orderingName) + assertTrue(mergedPlaylists[3] is PlaylistRemoteEntity) + assertEquals("name4", (mergedPlaylists[3] as PlaylistRemoteEntity).orderingName) + } + + @Test + fun sameNameWithDifferentIndex() { + val localPlaylists = listOf( + PlaylistMetadataEntry(1, "name1", "", 1, false, -1, 1), + PlaylistMetadataEntry(2, "name2", "", 3, false, -1, 1) + ) + val remotePlaylists = listOf( + PlaylistRemoteEntity(1, 1, "name1", "url1", "", "", 0, 1), + PlaylistRemoteEntity(2, 2, "name2", "url2", "", "", 2, 1) + ) + val mergedPlaylists = MergedPlaylistManager.merge(localPlaylists, remotePlaylists) + + assertEquals(4, mergedPlaylists.size) + assertTrue(mergedPlaylists[0] is PlaylistRemoteEntity) + assertEquals("name1", (mergedPlaylists[0] as PlaylistRemoteEntity).orderingName) + assertTrue(mergedPlaylists[1] is PlaylistMetadataEntry) + assertEquals("name1", (mergedPlaylists[1] as PlaylistMetadataEntry).orderingName) + assertTrue(mergedPlaylists[2] is PlaylistRemoteEntity) + assertEquals("name2", (mergedPlaylists[2] as PlaylistRemoteEntity).orderingName) + assertTrue(mergedPlaylists[3] is PlaylistMetadataEntry) + assertEquals("name2", (mergedPlaylists[3] as PlaylistMetadataEntry).orderingName) + } +} diff --git a/app/src/test/java/org/schabi/newpipe/ktx/ThrowableExtensionsTest.kt b/app/src/test/java/org/schabi/newpipe/ktx/ThrowableExtensionsTest.kt index ca2d04c85..fb7c1afe5 100644 --- a/app/src/test/java/org/schabi/newpipe/ktx/ThrowableExtensionsTest.kt +++ b/app/src/test/java/org/schabi/newpipe/ktx/ThrowableExtensionsTest.kt @@ -1,12 +1,12 @@ package org.schabi.newpipe.ktx -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test import java.io.IOException import java.io.InterruptedIOException import java.net.SocketException import javax.net.ssl.SSLException +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test class ThrowableExtensionsTest { @Test fun `assignable causes`() { diff --git a/app/src/test/java/org/schabi/newpipe/local/playlist/ExportPlaylistTest.kt b/app/src/test/java/org/schabi/newpipe/local/playlist/ExportPlaylistTest.kt index d9be2271e..de90061a4 100644 --- a/app/src/test/java/org/schabi/newpipe/local/playlist/ExportPlaylistTest.kt +++ b/app/src/test/java/org/schabi/newpipe/local/playlist/ExportPlaylistTest.kt @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + package org.schabi.newpipe.local.playlist import android.content.Context @@ -9,7 +14,6 @@ import org.schabi.newpipe.database.stream.model.StreamEntity import org.schabi.newpipe.extractor.stream.StreamType import org.schabi.newpipe.local.playlist.PlayListShareMode.JUST_URLS import org.schabi.newpipe.local.playlist.PlayListShareMode.YOUTUBE_TEMP_PLAYLIST -import java.util.stream.Stream class ExportPlaylistTest { @@ -41,9 +45,7 @@ class ExportPlaylistTest { */ val playlist = asPlaylist( - (10..70) - .map { id -> "https://www.youtube.com/watch?v=aaaaaaaaa$id" } // YouTube video IDs are 11 characters long - .stream() + (10..70).map { id -> "https://www.youtube.com/watch?v=aaaaaaaaa$id" } // YouTube video IDs are 11 characters long ) val url = export(YOUTUBE_TEMP_PLAYLIST, playlist, mock(Context::class.java)) @@ -78,13 +80,11 @@ class ExportPlaylistTest { } fun asPlaylist(vararg urls: String): List { - return asPlaylist(Stream.of(*urls)) + return asPlaylist(listOf(*urls)) } -fun asPlaylist(urls: Stream): List { - return urls - .map { url: String -> newPlaylistStreamEntry(url) } - .toList() +fun asPlaylist(urls: List): List { + return urls.map { newPlaylistStreamEntry(it) } } fun newPlaylistStreamEntry(url: String): PlaylistStreamEntry { diff --git a/app/src/test/java/org/schabi/newpipe/local/subscription/FeedGroupIconTest.kt b/app/src/test/java/org/schabi/newpipe/local/subscription/FeedGroupIconTest.kt index 2fc44d9b7..6db72255b 100644 --- a/app/src/test/java/org/schabi/newpipe/local/subscription/FeedGroupIconTest.kt +++ b/app/src/test/java/org/schabi/newpipe/local/subscription/FeedGroupIconTest.kt @@ -15,7 +15,8 @@ class FeedGroupIconTest { assertEquals( "Gap between ids detected (current item: ${currentIcon.name} - ${currentIcon.id} → should be: $shouldBeId)", - shouldBeId, currentIcon.id + shouldBeId, + currentIcon.id ) } } diff --git a/app/src/test/java/org/schabi/newpipe/settings/ImportAllCombinationsTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ImportAllCombinationsTest.kt index 862ac3b80..c7f53f3ac 100644 --- a/app/src/test/java/org/schabi/newpipe/settings/ImportAllCombinationsTest.kt +++ b/app/src/test/java/org/schabi/newpipe/settings/ImportAllCombinationsTest.kt @@ -1,6 +1,9 @@ package org.schabi.newpipe.settings import android.content.SharedPreferences +import java.io.File +import java.io.IOException +import java.nio.file.Files import org.junit.Assert import org.junit.Test import org.mockito.Mockito @@ -8,9 +11,6 @@ import org.schabi.newpipe.settings.export.BackupFileLocator import org.schabi.newpipe.settings.export.ImportExportManager import org.schabi.newpipe.streams.io.StoredFileHelper import us.shandian.giga.io.FileStream -import java.io.File -import java.io.IOException -import java.nio.file.Files class ImportAllCombinationsTest { @@ -21,7 +21,7 @@ class ImportAllCombinationsTest { private enum class Ser(val id: String) { YES("ser"), VULNERABLE("vulnser"), - NO("noser"); + NO("noser") } private data class FailData( @@ -29,7 +29,7 @@ class ImportAllCombinationsTest { val containsSer: Ser, val containsJson: Boolean, val filename: String, - val throwable: Throwable, + val throwable: Throwable ) private fun testZipCombination( @@ -37,7 +37,7 @@ class ImportAllCombinationsTest { containsSer: Ser, containsJson: Boolean, filename: String, - runTest: (test: () -> Unit) -> Unit, + runTest: (test: () -> Unit) -> Unit ) { val zipFile = File(classloader.getResource(filename)?.file!!) val zip = Mockito.mock(StoredFileHelper::class.java, Mockito.withSettings().stubOnly()) @@ -93,6 +93,7 @@ class ImportAllCombinationsTest { Mockito.verify(editor, Mockito.atLeastOnce()) .putInt(Mockito.anyString(), Mockito.anyInt()) } + Ser.VULNERABLE -> runTest { Assert.assertTrue(ImportExportManager(fileLocator).exportHasSerializedPrefs(zip)) Assert.assertThrows(ClassNotFoundException::class.java) { @@ -102,6 +103,7 @@ class ImportAllCombinationsTest { Mockito.verify(editor, Mockito.never()).clear() Mockito.verify(editor, Mockito.never()).commit() } + Ser.NO -> runTest { Assert.assertFalse(ImportExportManager(fileLocator).exportHasSerializedPrefs(zip)) Assert.assertThrows(IOException::class.java) { @@ -152,15 +154,18 @@ class ImportAllCombinationsTest { for (containsSer in Ser.entries) { for (containsJson in listOf(true, false)) { val filename = "settings/${if (containsDb) "db" else "nodb"}_${ - containsSer.id}_${if (containsJson) "json" else "nojson"}.zip" + containsSer.id}_${if (containsJson) "json" else "nojson"}.zip" testZipCombination(containsDb, containsSer, containsJson, filename) { test -> try { test() } catch (e: Throwable) { failedAssertions.add( FailData( - containsDb, containsSer, containsJson, - filename, e + containsDb, + containsSer, + containsJson, + filename, + e ) ) } @@ -173,7 +178,7 @@ class ImportAllCombinationsTest { for (a in failedAssertions) { println( "Assertion failed with containsDb=${a.containsDb}, containsSer=${ - a.containsSer}, containsJson=${a.containsJson}, filename=${a.filename}:" + a.containsSer}, containsJson=${a.containsJson}, filename=${a.filename}:" ) a.throwable.printStackTrace() println() diff --git a/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt index 5b8023561..e2ff22134 100644 --- a/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt +++ b/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt @@ -2,6 +2,10 @@ package org.schabi.newpipe.settings import android.content.SharedPreferences import com.grack.nanojson.JsonParser +import java.io.File +import java.io.ObjectInputStream +import java.nio.file.Files +import java.util.zip.ZipFile import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertThrows @@ -23,10 +27,6 @@ import org.schabi.newpipe.settings.export.BackupFileLocator import org.schabi.newpipe.settings.export.ImportExportManager import org.schabi.newpipe.streams.io.StoredFileHelper import us.shandian.giga.io.FileStream -import java.io.File -import java.io.ObjectInputStream -import java.nio.file.Files -import java.util.zip.ZipFile @RunWith(MockitoJUnitRunner::class) class ImportExportManagerTest { diff --git a/app/src/test/java/org/schabi/newpipe/streams/SrtFromTtmlWriterTest.java b/app/src/test/java/org/schabi/newpipe/streams/SrtFromTtmlWriterTest.java new file mode 100644 index 000000000..755724f68 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/streams/SrtFromTtmlWriterTest.java @@ -0,0 +1,320 @@ +package org.schabi.newpipe.streams; + +import org.junit.Test; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.jsoup.parser.Parser; +import java.io.ByteArrayInputStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import static org.junit.Assert.assertEquals; + +/** + * Unit tests for {@link SrtFromTtmlWriter}. + * + * Tests focus on {@code extractText()} and its handling of TTML

elements. + * Note: + * - Uses reflection to call the private {@code extractText()} method. + * - Update {@code EXTRACT_TEXT_METHOD} if renamed. + * + * --- + * NOTE ABOUT ENTITIES VS UNICODE ESCAPES + * + * - In short: + * * UNICODE ESCAPES → used in Java source (e.g. SrtFromTtmlWriter.java) + * * ENTITIES → used in TTML strings (this test file) + * + * - TTML is an XML-based format. Real TTML subtitles often encode special + * characters as XML entities (named or numeric), e.g.: + * & → '&' (\u0026) + * < → '<' (\u003C) + * → tab (\u0009) + * → line feed (\u000A) + * → carriage return (\u000D) + * + * - Java source code uses **Unicode escapes** (e.g. "\u00A0") which are resolved + * at compile time, so they do not represent real XML entities. + * + * - Purpose of these tests: + * We simulate *real TTML input* as NewPipe receives it — i.e., strings that + * still contain encoded XML entities ( , , , etc.). + * The production code (`decodeXmlEntities()`) must convert these into their + * actual Unicode characters before normalization. + */ +public class SrtFromTtmlWriterTest { + private static final String TTML_WRAPPER_START = "

"; + private static final String TTML_WRAPPER_END = "
"; + private static final String EXTRACT_TEXT_METHOD = "extractText"; + // Please keep the same definition from `SrtFromTtmlWriter` class. + private static final String NEW_LINE = "\r\n"; + + /* + * TTML example for simple paragraph

without nested tags. + *

Hello World!

+ */ + private static final String SIMPLE_TTML = "

Hello World!

"; + /** + * TTML example with nested tags with
. + *

Hello
World!

+ */ + private static final String NESTED_TTML = "

" + + "Hello
World!

"; + + /** + * TTML example with HTML entities. + * < → <, > → >, & → &, " → ", ' → ' + * ' → ' + *   → ' ' + */ + private static final String ENTITY_TTML = "

" + + "<tag> & "text"''''" + + "  " + + "

"; + /** + * TTML example with special characters: + * - Spaces appear at the beginning and end of the text. + * - Spaces are also present within the text (not just at the edges). + * - The text includes various HTML entities such as  , + * &, <, >, etc. + *   → non-breaking space (Unicode: '\u00A0', Entity: ' ') + */ + private static final String SPECIAL_TTML = "

" + + " ~~-Hello  &&<<>>World!! " + + "

"; + + /** + * TTML example with characters: tab. + * → \t + * They are separated by '+' for clarity. + */ + private static final String TAB_TTML = "

" + + " + + " + + "

"; + + /** + * TTML example with line endings. + * → \r + */ + private static final String LINE_ENDING_0_TTML = "

" + + " + + " + + "

"; + // → \n + private static final String LINE_ENDING_1_TTML = "

" + + " + + " + + "

"; + private static final String LINE_ENDING_2_TTML = + "

" + + " + + " + + "

"; + + /** + * TTML example with control characters. + * For example: + *  → \u0001 + *  → \u001F + * + * These control characters, if included as raw Unicode(e.g. '\u0001'), + * are either invalid in XML or rendered as '?' when processed. + * To avoid issues, they should be encoded(e.g. '') in TTML file. + * + * - Reference: + * Unicode Basic Latin (https://unicode.org/charts/PDF/U0000.pdf), + * ASCII Control (https://en.wikipedia.org/wiki/ASCII#Control_characters). + * and the defination of these characters can be known. + */ + private static final String CONTROL_CHAR_TTML = "

" + + "++ + ++" + + "

"; + + + + private static final String EMPTY_TTML = "

" + + "" + + "

"; + + /** + * TTML example with Unicode space characters. + * These characters are encoded using character references + * (&#xXXXX;). + * + * Includes: + * ( ) '\u202F' → Narrow no-break space + * ( ) '\u205F' → Medium mathematical space + * ( ) '\u3000' → Ideographic space + * '\u2000' ~ '\u200A' are whitespace characters: + * ( ) '\u2000' → En quad + * ( ) '\u2002' → En space + * ( ) '\u200A' → Hair space + * + * Each character is separated by '+' for clarity. + */ + private static final String UNICODE_SPACE_TTML = "

" + + " + + + + + " + + "

"; + + /** + * TTML example with non-spacing (invisible) characters. + * These are encoded using character references (&#xXXXX;). + * + * Includes: + * (​)'\u200B' → Zero-width space (ZWSP) + * (‎)'\u200E' → Left-to-right mark (LRM) + * (‏)'\u200F' → Right-to-left mark (RLM) + * + * They don't display any characters to the human eye. + * '+' is used between them for clarity in test output. + */ + private static final String NON_SPACING_TTML = "

" + + "​+‎+‏" + + "

"; + + /** + * Parses TTML string into a JSoup Document and selects the first

element. + * + * @param ttmlContent TTML content (e.g.,

...

) + * @return the first

element + * @throws Exception if parsing or reflection fails + */ + private Element parseTtmlParagraph(final String ttmlContent) throws Exception { + final String ttml = TTML_WRAPPER_START + ttmlContent + TTML_WRAPPER_END; + final Document doc = Jsoup.parse( + new ByteArrayInputStream(ttml.getBytes(StandardCharsets.UTF_8)), + "UTF-8", "", Parser.xmlParser()); + return doc.select("body > div > p").first(); + } + + /** + * Invokes private extractText method via reflection. + * + * @param writer SrtFromTtmlWriter instance + * @param paragraph

element to extract text from + * @param text StringBuilder to store extracted text + * @throws Exception if reflection fails + */ + private void invokeExtractText(final SrtFromTtmlWriter writer, final Element paragraph, + final StringBuilder text) throws Exception { + final Method method = writer.getClass() + .getDeclaredMethod(EXTRACT_TEXT_METHOD, Node.class, StringBuilder.class); + method.setAccessible(true); + method.invoke(writer, paragraph, text); + } + + private String extractTextFromTtml(final String ttmlInput) throws Exception { + final Element paragraph = parseTtmlParagraph(ttmlInput); + final StringBuilder text = new StringBuilder(); + final SrtFromTtmlWriter writer = new SrtFromTtmlWriter(null, false); + invokeExtractText(writer, paragraph, text); + + final String actualText = text.toString(); + return actualText; + } + + @Test + public void testExtractTextSimpleParagraph() throws Exception { + final String expected = "Hello World!"; + final String actual = extractTextFromTtml(SIMPLE_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextNestedTags() throws Exception { + final String expected = "Hello\r\nWorld!"; + final String actual = extractTextFromTtml(NESTED_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithEntity() throws Exception { + final String expected = " & \"text\"'''' "; + final String actual = extractTextFromTtml(ENTITY_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithSpecialCharacters() throws Exception { + final String expected = " ~~-Hello &&<<>>World!! "; + final String actual = extractTextFromTtml(SPECIAL_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithTab() throws Exception { + final String expected = " + + "; + final String actual = extractTextFromTtml(TAB_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithLineEnding0() throws Exception { + final String expected = NEW_LINE + NEW_LINE + "+" + + NEW_LINE + NEW_LINE + "+" + + NEW_LINE + NEW_LINE; + final String actual = extractTextFromTtml(LINE_ENDING_0_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithLineEnding1() throws Exception { + final String expected = NEW_LINE + NEW_LINE + "+" + + NEW_LINE + NEW_LINE + "+" + + NEW_LINE + NEW_LINE; + final String actual = extractTextFromTtml(LINE_ENDING_1_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithLineEnding2() throws Exception { + final String expected = NEW_LINE + "+" + + NEW_LINE + "+" + + NEW_LINE; + final String actual = extractTextFromTtml(LINE_ENDING_2_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithControlCharacters() throws Exception { + final String expected = "+++++"; + final String actual = extractTextFromTtml(CONTROL_CHAR_TTML); + assertEquals(expected, actual); + } + + /** + * Test case to ensure that extractText() does not throw an exception + * when there are no text in the TTML paragraph (i.e., the paragraph + * is empty). + * + * Note: + * In the NewPipe, *.srt files will contain empty text lines by default. + */ + @Test + public void testExtractTextWithEmpty() throws Exception { + final String expected = ""; + final String actual = extractTextFromTtml(EMPTY_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithUnicodeSpaces() throws Exception { + final String expected = " + + + + + "; + final String actual = extractTextFromTtml(UNICODE_SPACE_TTML); + assertEquals(expected, actual); + } + + @Test + public void testExtractTextWithNonSpacingCharacters() throws Exception { + final String expected = "++"; + final String actual = extractTextFromTtml(NON_SPACING_TTML); + assertEquals(expected, actual); + } +} diff --git a/app/src/test/java/org/schabi/newpipe/util/LocalizationTest.kt b/app/src/test/java/org/schabi/newpipe/util/LocalizationTest.kt index ab6396951..081d1c545 100644 --- a/app/src/test/java/org/schabi/newpipe/util/LocalizationTest.kt +++ b/app/src/test/java/org/schabi/newpipe/util/LocalizationTest.kt @@ -1,12 +1,12 @@ package org.schabi.newpipe.util -import org.junit.Assert.assertEquals -import org.junit.Test -import org.ocpsoft.prettytime.PrettyTime import java.time.LocalDate import java.time.OffsetDateTime import java.time.ZoneOffset import java.util.Locale +import org.junit.Assert.assertEquals +import org.junit.Test +import org.ocpsoft.prettytime.PrettyTime class LocalizationTest { @Test(expected = NullPointerException::class) diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 3cdc0dc59..000000000 --- a/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext.kotlin_version = '1.9.25' - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:8.13.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - maven { url "https://jitpack.io" } - maven { url "https://repo.clojars.org" } - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..2c9173f57 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.jetbrains.kotlin.kapt) apply false + alias(libs.plugins.google.ksp) apply false + alias(libs.plugins.jetbrains.kotlin.parcelize) apply false + alias(libs.plugins.sonarqube) apply false +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..713cead4b --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() +} diff --git a/buildSrc/src/main/kotlin/CheckDependenciesOrder.kt b/buildSrc/src/main/kotlin/CheckDependenciesOrder.kt new file mode 100644 index 000000000..8bf92d8cd --- /dev/null +++ b/buildSrc/src/main/kotlin/CheckDependenciesOrder.kt @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.TaskAction + +abstract class CheckDependenciesOrder : DefaultTask() { + + @get:InputFile + abstract val tomlFile: RegularFileProperty + + init { + group = "verification" + description = "Checks that each section in libs.versions.toml is sorted alphabetically" + } + + @TaskAction + fun run() { + val file = tomlFile.get().asFile + if (!file.exists()) error("TOML file not found") + + val lines = file.readLines() + val nonSortedBlocks = mutableListOf>() + var currentBlock = mutableListOf() + var prevLine = "" + var prevIndex = 0 + + lines.forEachIndexed { lineIndex, line -> + if (line.trim().isNotEmpty() && !line.startsWith("#")) { + if (line.startsWith("[")) { + prevLine = "" + } else { + val currIndex = lineIndex + 1 + if (prevLine > line) { + if (currentBlock.isNotEmpty() && currentBlock.last() == "$prevIndex: $prevLine") { + currentBlock.add("$currIndex: $line") + } else { + if (currentBlock.isNotEmpty()) { + nonSortedBlocks.add(currentBlock) + currentBlock = mutableListOf() + } + currentBlock.add("$prevIndex: $prevLine") + currentBlock.add("$currIndex: $line") + } + } + prevLine = line + prevIndex = lineIndex + 1 + } + } + } + + if (currentBlock.isNotEmpty()) { + nonSortedBlocks.add(currentBlock) + } + + if (nonSortedBlocks.isNotEmpty()) { + error( + "The following lines were not sorted:\n" + + nonSortedBlocks.joinToString("\n\n") { it.joinToString("\n") } + ) + } + } +} diff --git a/fastlane/metadata/android/ar/changelogs/1006.txt b/fastlane/metadata/android/ar/changelogs/1006.txt new file mode 100644 index 000000000..9466446c9 --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/1006.txt @@ -0,0 +1,16 @@ +# التحسينات +الإبقاء على المشغل الحالي عند الضغط على الزمن. +محاولة استعادة مهام التنزيل المعلقة قدر الإمكان. +إضافة خيار لحذف سجل التنزيل دون حذف الملف الفعلي. +إذن الظهور فوق التطبيقات: عرض مربع توضيحي لإصدارات أندرويد > R. +دعم فتح روابط على.soundcloud. +العديد من التحسينات. + +# الإصلاحات +إصلاح تنسيق الأرقام المختصرة لإصدارات أندرويد الأقدم من 7. +إصلاح الإشعارات الوهمية. +إصلاحات لملفات ترجمة SRT. +إصلاح عدد كبير من الأعطال. + +# التطوير +تحديث البنية البرمجية الداخلية. diff --git a/fastlane/metadata/android/ar/changelogs/1007.txt b/fastlane/metadata/android/ar/changelogs/1007.txt new file mode 100644 index 000000000..562f16944 --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/1007.txt @@ -0,0 +1 @@ +تم إصلاح YouTube الذي لا يقوم بتشغيل أي دفق diff --git a/fastlane/metadata/android/az/changelogs/1007.txt b/fastlane/metadata/android/az/changelogs/1007.txt new file mode 100644 index 000000000..16a2e1013 --- /dev/null +++ b/fastlane/metadata/android/az/changelogs/1007.txt @@ -0,0 +1 @@ +YouTube-un heç bir yayım oynatmaması düzəldildi diff --git a/fastlane/metadata/android/bg/changelogs/1000.txt b/fastlane/metadata/android/bg/changelogs/1000.txt new file mode 100644 index 000000000..fea57c3d5 --- /dev/null +++ b/fastlane/metadata/android/bg/changelogs/1000.txt @@ -0,0 +1,13 @@ +Подобрено +• Направи описанието на плейлиста възможно за избиране за показване на повече/по-малко съдържание +• [PeerTube] Поддръжка +`subscribeto.me` инстанцията се свързва автоматично +• Пускай само един обект в екрана за история +Поправено +• Поправи видимостта на RSS бутона +• Поправи сриване на предварителния преглед на полето за търсене +• Поправи показването на обект без обложка +• Поправено е излизането от диалоговия прозорец за изтегляне, преди да се появи +• Поправка на изскачащ прозорец за добавяне в опашката на списък със свързани елементи +• Поправка на реда в диалоговия прозорец за добавяне към плейлиста +• Регулиране на оформлението на елементите от отметките в плейлиста diff --git a/fastlane/metadata/android/bg/changelogs/63.txt b/fastlane/metadata/android/bg/changelogs/63.txt deleted file mode 100644 index be8865e6d..000000000 --- a/fastlane/metadata/android/bg/changelogs/63.txt +++ /dev/null @@ -1,8 +0,0 @@ -### Подобрения -- Импорт/ Експорт на настройки #1333 -- Редуциране на надхвърляне (подобрение на производителността) #1371 -- Малки подобрения в кода #1375 -- Добавяне на всичко за GDPR #1420 - -### Поправени -- Изтегляния: Поправен срив при зареждане на неприключени изтегляния от .giga файлове #1407 diff --git a/fastlane/metadata/android/bs/changelogs/1000.txt b/fastlane/metadata/android/bs/changelogs/1000.txt new file mode 100644 index 000000000..41bcd963e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1000.txt @@ -0,0 +1,13 @@ +Poboljšano +• Opis liste za reprodukciju učinite klikom za prikaz više/manje sadržaja +• [PeerTube] Automatski obrađuje linkove instanci `subscribeto.me` +• Pokreni reprodukciju samo jedne stavke na ekranu historije + +Ispravljeno +• Ispravljena vidljivost RSS dugmeta +• Ispravljeno rušenje pregleda trake za pretraživanje +• Ispravljena stavka bez sličice prilikom dodavanja na listu za reprodukciju +• Ispravljeno izlaženje iz dijaloga za preuzimanje prije nego što se pojavi +• Ispravljen skočni prozor za dodavanje u red čekanja za povezane stavke +• Ispravljen redoslijed u dijalogu za dodavanje na listu za reprodukciju +• Prilagodite raspored stavki označenih na listi za reprodukciju diff --git a/fastlane/metadata/android/bs/changelogs/1001.txt b/fastlane/metadata/android/bs/changelogs/1001.txt new file mode 100644 index 000000000..f798a0a78 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1001.txt @@ -0,0 +1,6 @@ +Poboljšano +• Uvijek dozvoli promjenu postavki obavještenja igrača na Androidu 13+ + +Ispravljeno +• Ispravljena greška izvoza baze podataka/pretplata koja nije skraćivala već postojeću datoteku, što je moglo dovesti do oštećenja izvoza +• Ispravljeno ponovno pokretanje igrača od početka klikom na vremensku oznaku diff --git a/fastlane/metadata/android/bs/changelogs/1002.txt b/fastlane/metadata/android/bs/changelogs/1002.txt new file mode 100644 index 000000000..5fc0b843a --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1002.txt @@ -0,0 +1,4 @@ +Ispravljena greška zbog koje YouTube nije reproducirao nijedan tok. + +Ovo izdanje rješava samo najhitniju grešku koja sprječava učitavanje detalja YouTube videa. +Svjesni smo da postoje i drugi problemi i uskoro ćemo objaviti zasebno izdanje kako bismo ih riješili. diff --git a/fastlane/metadata/android/bs/changelogs/1003.txt b/fastlane/metadata/android/bs/changelogs/1003.txt new file mode 100644 index 000000000..45a0e5739 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1003.txt @@ -0,0 +1,6 @@ +Ovo je hitna ispravka koja ispravlja greške na YouTubeu: +• [YouTube] Ispravljeno neučitavanje informacija o videozapisu, ispravljene greške HTTP 403 prilikom reprodukcije videozapisa i vraćanje reprodukcije nekih videozapisa s ograničenjem za uzrast +• Ispravljena veličina titlova koja se nije mijenjala +• Ispravljeno dvostruko preuzimanje informacija prilikom otvaranja toka +• [Soundcloud] Uklonjeni nereproducirani tokovi zaštićeni DRM-om +• Ažurirani prijevodi diff --git a/fastlane/metadata/android/bs/changelogs/1004.txt b/fastlane/metadata/android/bs/changelogs/1004.txt new file mode 100644 index 000000000..bbd4fb0a0 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1004.txt @@ -0,0 +1,3 @@ +Ovo izdanje ispravlja problem sa YouTube-om koji pruža samo 360p tok. + +Imajte na umu da je rješenje korišteno u ovoj verziji vjerovatno privremeno i da dugoročno gledano treba implementirati SABR video protokol, ali članovi TeamNewPipe-a su trenutno zauzeti, tako da bi svaka pomoć bila veoma cijenjena! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/bs/changelogs/1005.txt b/fastlane/metadata/android/bs/changelogs/1005.txt new file mode 100644 index 000000000..4d98c6dac --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1005.txt @@ -0,0 +1,17 @@ +Novo +• Dodata podrška za Android Auto +• Omogućeno postavljanje grupa feedova kao kartica na glavnom ekranu +• [YouTube] Dijeli kao privremenu listu za reprodukciju +• [SoundCloud] Kartica kanala sa sviđanjima + +Poboljšano +• Bolji savjeti u traci za pretragu +• Prikaz datuma preuzimanja u Preuzimanjema +• Korištenje jezika Androida 13 po aplikaciji + +Ispravljeno +• Ispravljene boje teksta koje ne rade u tamnom režimu +• [YouTube] Ispravljeno liste za reprodukciju koje ne učitavaju više od 100 stavki +• [YouTube] Ispravljeni nedostajući preporučeni videozapisi +• Ispravljeni rušenja u prikazu liste historije +• Ispravljene vremenske oznake u odgovorima na komentare diff --git a/fastlane/metadata/android/bs/changelogs/1007.txt b/fastlane/metadata/android/bs/changelogs/1007.txt new file mode 100644 index 000000000..acd29e47c --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/1007.txt @@ -0,0 +1 @@ +Ispravljeno je da YouTube ne reprodukuje nijedan tok diff --git a/fastlane/metadata/android/bs/changelogs/64.txt b/fastlane/metadata/android/bs/changelogs/64.txt new file mode 100644 index 000000000..f0fff6468 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/64.txt @@ -0,0 +1,8 @@ +### Poboljšanja +- Dodata je mogućnost ograničavanja kvalitete videa ako se koriste mobilni podaci. #1339 +- Zapamti svjetlinu za sesiju #1442 +- Poboljšane performanse preuzimanja za slabije procesore #1431 +- dodana (funkcionalna) podrška za medijsku sesiju #1433 + +### Ispravka +- Ispravljen pad sistema prilikom otvaranja preuzimanja (ispravka je sada dostupna za izdane verzije) #1441 diff --git a/fastlane/metadata/android/bs/changelogs/65.txt b/fastlane/metadata/android/bs/changelogs/65.txt new file mode 100644 index 000000000..9efa1420b --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/65.txt @@ -0,0 +1,26 @@ +### Poboljšanja + +- Onemogućavanje animacije ikone burgermenuja #1486 +- poništavanje brisanja preuzimanja #1472 +- Opcija preuzimanja u meniju za dijeljenje #1498 +- Dodata opcija dijeljenja u meni s dugim dodirom #1454 +- Minimiziranje glavnog playera pri izlasku #1354 +- Ispravka ažuriranja verzije biblioteke i sigurnosne kopije baze podataka #1510 +- Ažuriranje ExoPlayera 2.8.2 #1392 +- Prerađen dijalog za kontrolu brzine reprodukcije radi podrške za različite veličine koraka za bržu promjenu brzine. +- Dodan je prekidač za premotavanje unaprijed tokom tišina u kontroli brzine reprodukcije. Ovo bi trebalo biti korisno za audio knjige i određene muzičke žanrove, a može donijeti zaista besprijekorno iskustvo (i može prekinuti pjesmu s puno tišina =\\). +- Refaktorisana rezolucija izvora medija kako bi se omogućilo interno prosljeđivanje metapodataka uz medije u playeru, umjesto ručnog. Sada imamo jedan izvor metapodataka i direktno je dostupan kada reprodukcija počne. +- Ispravljeni metapodaci udaljene liste za reprodukciju koji se ne ažuriraju kada su novi metapodaci dostupni kada se otvori fragment liste za reprodukciju. +- Razne ispravke korisničkog interfejsa: #1383, kontrole obavještenja u pozadini playera sada su uvijek bijele, lakše je isključiti iskačući player prebacivanjem. +- Koristi se novi ekstraktor s refaktoriranom arhitekturom za više servisa. + +### Ispravke + +- Ispravka #1440 Neispravan raspored informacija o videu #1491 +- Ispravka historije pregleda #1497 +- #1495, ažuriranjem metapodataka (sličica, naslov i broj videa) čim korisnik pristupi listi za reprodukciju. +- #1475, registracijom pregleda u bazi podataka kada korisnik pokrene video na vanjskom playeru na fragmentu detalja. +- Ispravljeno vremensko ograničenje ekrana u slučaju iskačućeg načina rada. #1463 (Ispravljeno #640) +- Ispravka glavnog video playera #1509 +- [#1412] Ispravljen je način ponavljanja koji je uzrokovao NPE playera kada se primi nova namjera dok je aktivnost playera u pozadini. +- Ispravljena je greška minimiziranja playera u iskačući prozor koja ne uništava player kada nije odobrena dozvola za iskačući prozor. diff --git a/fastlane/metadata/android/bs/changelogs/66.txt b/fastlane/metadata/android/bs/changelogs/66.txt new file mode 100644 index 000000000..0562b9059 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/66.txt @@ -0,0 +1,33 @@ +# Dnevnik promjena v0.13.7 + +### Ispravljeno +- Ispravljeni problemi sa filterom sortiranja iz v0.13.6 + +# Dnevnik promjena v0.13.6 + +### Poboljšanja + +- Onemogućena animacija ikone burger menija #1486 +- poništavanje brisanja preuzimanja #1472 +- Opcija preuzimanja u meniju za dijeljenje #1498 +- Dodata opcija dijeljenja u meni dugog dodira #1454 +- Minimiziranje glavnog playera pri izlasku #1354 +- Ispravka ažuriranja verzije biblioteke i sigurnosne kopije baze podataka #1510 +- Ažuriranje ExoPlayera 2.8.2 #1392 +- Prerađen dijalog za kontrolu brzine reprodukcije kako bi se podržale različite veličine koraka za bržu promjenu brzine. +- Dodan je prekidač za premotavanje unaprijed tokom tišina u kontroli brzine reprodukcije. Ovo bi trebalo biti korisno za audio knjige i određene muzičke žanrove i može donijeti zaista besprijekorno iskustvo (i može prekinuti pjesmu s puno tišina =\\). +- Refaktorisana rezolucija izvora medija kako bi se omogućilo interno prosljeđivanje metapodataka zajedno s medijima u playeru, umjesto ručnog. Sada imamo jedan izvor metapodataka i on je direktno dostupan kada počne reprodukcija. +- Ispravljeni metapodaci udaljene liste za reprodukciju koji se nisu ažurirali kada su novi metapodaci dostupni prilikom otvaranja fragmenta liste za reprodukciju. +- Razne ispravke korisničkog interfejsa: #1383, kontrole obavještenja u pozadini playera sada su uvijek bijele, lakše je isključiti iskačući player prebacivanjem. +- Koristi se novi ekstraktor s refaktorisanom arhitekturom za više servisa. + +### Ispravke + +- Ispravka #1440 Neispravan raspored informacija o videu #1491 +- Ispravka historije pregleda #1497 +- #1495, ažuriranjem metapodataka (sličica, naslov i broj videa) čim korisnik pristupi listi za reprodukciju. +- #1475, registracijom pregleda u bazi podataka kada korisnik pokrene video na vanjskom playeru na fragmentu detalja. +- Ispravljeno vremensko ograničenje ekrana u slučaju iskačućeg načina rada. #1463 (Ispravljeno #640) +- Ispravka glavnog video plejera #1509 +- [#1412] Ispravljen je način ponavljanja koji je uzrokovao NPE plejera kada se primi nova namjera dok je aktivnost plejera u pozadini. +- Ispravljeno je minimiziranje plejera u skočni prozor koje nije uništilo plejer kada nije odobrena dozvola za skočni prozor. diff --git a/fastlane/metadata/android/bs/changelogs/68.txt b/fastlane/metadata/android/bs/changelogs/68.txt new file mode 100644 index 000000000..8d1b80a9e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/68.txt @@ -0,0 +1,31 @@ +# promjene v0.14.1 + +### Ispravljeno +- Ispravljeno neuspješno dešifriranje URL-a videa #1659 +- Ispravljeno nije dobro izdvajanje linka opisa #1657 + +# promjene v0.14.0 + +### Novo +- Novi dizajn ladice #1461 +- Nova prilagodljiva početna stranica #1461 + +### Poboljšanja +- Prerađene kontrole gestikulacije #1604 +- Novi način zatvaranja iskačućeg playera #1597 + +### Ispravljeno +- Ispravljena greška kada broj pretplata nije dostupan. Zatvara se #1649. +- Prikaži "Broj pretplatnika nije dostupan" u tim slučajevima +- Ispravljen NPE kada je YouTube lista za reprodukciju prazna +- Brzo rješenje za kioske u SoundCloudu +- Refaktoriranje i ispravka greške #1623 +- Ispravljen ciklički rezultat pretrage #1562 +- Ispravljena traka za pretraživanje koja nije statički postavljena +- Ispravljeno YT Premium videozapisi nisu ispravno blokirani +- Ispravljeno videozapisi koji se ponekad ne učitavaju (zbog DASH parsiranja) +- Ispravljeni linkovi u opisu videozapisa +- Prikaži upozorenje kada neko pokuša preuzeti na eksternu sd karticu +- ispravljen izuzetak koji se ne prikazuje, a pokreće izvještaj +- sličica se ne prikazuje u pozadinskom playeru za Android 8.1 [pogledajte ovdje](https://github.com/TeamNewPipe/NewPipe/issues/943) +- Ispravljeno registracija prijemnika emitiranja. Zatvoreno #1641. diff --git a/fastlane/metadata/android/bs/changelogs/69.txt b/fastlane/metadata/android/bs/changelogs/69.txt new file mode 100644 index 000000000..27172b680 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/69.txt @@ -0,0 +1,19 @@ +### Novo +- Dugi dodir za brisanje i dijeljenje u pretplatama #1516 +- Korisnički interfejs tableta i raspored mreže #1617 + +### Poboljšanja +- pohranjivanje i ponovno učitavanje posljednjeg korištenog omjera širine i visine #1748 +- Omogućavanje linearnog rasporeda u aktivnosti preuzimanja s punim nazivima videozapisa #1771 +- Brisanje i dijeljenje pretplata direktno iz kartice pretplata #1516 +- Stavljanje u red čekanja sada pokreće reprodukciju videozapisa ako je red čekanja za reprodukciju već završen #1783 +- Odvojene postavke za geste jačine zvuka i svjetline #1644 +- Dodana podrška za lokalizaciju #1792 + +### Ispravke +- Ispravljeno raščlanjivanje vremena za . format, tako da se NewPipe može koristiti u Finskoj +- Ispravljen broj pretplata +- Dodana dozvola za uslugu u prvom planu za API 28+ uređaje #1830 + +### Poznate greške +- Stanje reprodukcije se ne može sačuvati na Android P diff --git a/fastlane/metadata/android/bs/changelogs/70.txt b/fastlane/metadata/android/bs/changelogs/70.txt new file mode 100644 index 000000000..d72ac7a04 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/70.txt @@ -0,0 +1,25 @@ +PAŽNJA: Ova verzija je vjerovatno puna grešaka, baš kao i prethodna. Međutim, zbog potpunog gašenja od verzije 17, bolja je i pokvarena verzija nego nikakva. Zar ne? ¯\_(ツ)_/¯ + +### Poboljšanja +* preuzete datoteke se sada mogu otvoriti jednim klikom #1879 +* ukidanje podrške za Android 4.1 - 4.3 #1884 +* uklanjanje starog plejera #1884 +* uklanjanje tokova iz trenutnog reda čekanja prevlačenjem prsta udesno #1915 +* uklanjanje automatski dodanog toka u red čekanja kada se novi tok ručno doda u red čekanja #1878 +* Naknadna obrada preuzimanja i implementacija nedostajućih funkcija #1759 od @kapodamy +* Infrastruktura naknadne obrade +* Ispravna "infrastruktura" za rukovanje greškama (za program za preuzimanje) +* Stavljanje u red čekanja umjesto više preuzimanja +* Premještanje serijaliziranih preuzimanja na čekanju (`.giga` datoteke) u podatke aplikacije +* Implementacija maksimalnog broja ponovnih pokušaja preuzimanja +* Ispravno pauziranje preuzimanja u više niti +* Zaustavljanje preuzimanja prilikom prebacivanja na mobilnu mrežu (nikada ne radi, pogledajte 2. tačku) +* Sačuvanje broja niti za sljedeća preuzimanja +* Mnogo nedosljednosti ispravljeno + +### Ispravljeno +* Ispravljen pad sistema sa zadanom rezolucijom postavljenom na najbolju i ograničenom rezolucijom mobilnih podataka #1835 +* Ispravljen pad sistema prilikom iskačućeg plejera #1874 +* NPE pri pokušaju otvaranja pozadinskog plejera #1901 +* Ispravljeno umetanje novih tokova kada je omogućeno automatsko stavljanje u red #1878 +* Ispravljen problem sa dešifriranjem i isključivanjem sistema diff --git a/fastlane/metadata/android/bs/changelogs/71.txt b/fastlane/metadata/android/bs/changelogs/71.txt new file mode 100644 index 000000000..28a8ba733 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/71.txt @@ -0,0 +1,10 @@ +### Poboljšanja +* Dodana obavijest o ažuriranju aplikacije za GitHub verziju (#1608 od @krtkush) +* Različita poboljšanja programa za preuzimanje (#1944 od @kapodamy): +* dodane nedostajuće bijele ikone i korištenje ugrađenog načina za promjenu boja ikona +* provjera da li je iterator inicijaliziran (ispravke #2031) +* omogućava ponovni pokušaj preuzimanja s greškom "naknadna obrada nije uspjela" u novom multiplekseru +* novi MPEG-4 multiplekser ispravlja nesinhrone video i audio tokove (#2039) + +### Ispravljeno +* YouTube tokovi uživo prestaju s reprodukcijom nakon kratkog vremena (#1996 od @yausername) diff --git a/fastlane/metadata/android/bs/changelogs/730.txt b/fastlane/metadata/android/bs/changelogs/730.txt new file mode 100644 index 000000000..581435b63 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/730.txt @@ -0,0 +1,2 @@ +# Ispravljeno +- Ispravljena greška funkcije dešifriranja. diff --git a/fastlane/metadata/android/bs/changelogs/740.txt b/fastlane/metadata/android/bs/changelogs/740.txt new file mode 100644 index 000000000..ad72fe828 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/740.txt @@ -0,0 +1 @@ +

Poboljšanja

  • učinite linkove u komentarima klikabilnim, povećajte veličinu teksta
  • traži klikom na linkove vremenskih oznaka u komentarima
  • prikaži preferiranu karticu na osnovu nedavno odabranog stanja
  • dodaje listu pjesama u red čekanja kada se dugo klikne na 'Pozadina' u prozoru liste pjesama
  • traži dijeljeni tekst kada nije URL
  • Dodajte dugme "podijeli u trenutno vrijeme" u glavni video plejer
  • dodajte dugme za zatvaranje u glavni plejer kada se završi red čekanja za video
  • Dodajte "Reproduciraj direktno u pozadini" u meni s dugim pritiskom za stavke liste videozapisa
  • poboljšati engleske prijevode za naredbe Play/Enqueue
  • mala poboljšanja performansi
  • uklonite nekorištene datoteke
  • Ažurirajte ExoPlayer na verziju 2.9.6
  • dodajte podršku za Invidious linkove

Fiksno

  • Ispravljeno skrolovanje sa onemogućenim komentarima i povezanim tokovima
  • ispravljena greška prilikom izvršavanja CheckForNewAppVersionTask-a kada ne bi trebalo
  • Ispravljen uvoz pretplata na YouTube: ignorišite one sa nevažećim URL-om i zadržite one sa praznim naslovom
  • Ispravljen nevažeći YouTube URL: naziv oznake potpisa nije uvijek "potpis", što sprječava učitavanje tokova
diff --git a/fastlane/metadata/android/bs/changelogs/750.txt b/fastlane/metadata/android/bs/changelogs/750.txt new file mode 100644 index 000000000..dd043ae61 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/750.txt @@ -0,0 +1,21 @@ +Novo +Nastavak reprodukcije #2288 +• Nastavite tokove tamo gdje ste prošli put stali +Poboljšanja programa za preuzimanje #2149 +• Koristite okvir za pristup pohrani za pohranu preuzimanja na eksterne SD kartice +• Novi mp4 muxer +• Opcionalno promijenite direktorij za preuzimanje prije početka preuzimanja +• Poštujte mjerene mreže + +Poboljšano +• Uklonjeni gema stringovi #2295 +• Obrađuje promjene (automatske) rotacije tokom životnog ciklusa aktivnosti #2444 +• Učinite menije s dugim pritiskom konzistentnim #2368 + +Ispravljeno +• Ispravljeno neprikazivanje naziva odabrane pjesme s titlovima #2394 +• Nije došlo do pada programa kada provjera ažuriranja aplikacije ne uspije (GitHub verzija) #2423 +• Ispravljena preuzimanja zaglavljena na 99,9% #2440 +• Ažuriranje metapodataka reda čekanja za reprodukciju #2453 +• [SoundCloud] Ispravljen pad programa prilikom učitavanja lista za reprodukciju TeamNewPipe/NewPipeExtractor#170 +• [YouTube] Fiksno trajanje se ne može parsirati TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/bs/changelogs/760.txt b/fastlane/metadata/android/bs/changelogs/760.txt new file mode 100644 index 000000000..ba5f26b1e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/760.txt @@ -0,0 +1,40 @@ +Promjene u verziji 0.17.1 + +Novo +• Tajlandska lokalizacija + +Poboljšano + +• Ponovo dodana akcija "počni reprodukciju ovdje" u menijima dugog pritiska za liste za reprodukciju #2518 +• Dodan prekidač za SAF / birač starih datoteka #2521 + +Ispravljeno +• Ispravljeni dugmad koja nestaju u prikazu preuzimanja prilikom prebacivanja aplikacija #2487 +• Ispravljena je greška u poziciji reprodukcije koja se pohranjuje iako je historija gledanja onemogućena +• Ispravljene smanjene performanse uzrokovane pozicijom reprodukcije u prikazima liste #2517 +• [Extractor] Ispravljena je ReCaptchaActivity #2527, TeamNewPipe/NewPipeExtractor #186 +• [Extractor] [YouTube] Ispravljena je slučajna greška u pretrazi kada su liste za reprodukciju u rezultatima TeamNewPipe/NewPipeExtractor #185 + +Promjene u verziji 0.17.0 + +Novo +Nastavak reprodukcije #2288 +• Nastavite tokove tamo gdje ste zadnji put stali +Poboljšanja programa za preuzimanje #2149 +• Koristite okvir za pristup pohrani za pohranjivanje preuzimanja na eksterne SD kartice +• Novi mp4 muxer +• Opcionalno promijenite direktorij za preuzimanje prije početka preuzimanja +• Poštujte mjerene mreže + +Poboljšano +• Uklonjeni gema stringovi #2295 +• Obrađuje promjene (automatske) rotacije tokom životnog ciklusa aktivnosti #2444 +• Učinite menije s dugim pritiskom konzistentnim #2368 + +Ispravljeno +• Ispravljeno ime odabrane numere titlova koje se ne prikazuje #2394 +• Nije došlo do pada programa kada provjera ažuriranja aplikacije ne uspije (GitHub verzija) #2423 +• Ispravljena preuzimanja zaglavljena na 99,9% #2440 +• Ažuriranje metapodataka reda za reprodukciju #2453 +• [SoundCloud] Ispravljen pad programa prilikom učitavanja lista za reprodukciju TeamNewPipe/NewPipeExtractor#170 +• [YouTube] Fiksno trajanje se ne može parsirati TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/bs/changelogs/770.txt b/fastlane/metadata/android/bs/changelogs/770.txt new file mode 100644 index 000000000..e7d35d207 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/770.txt @@ -0,0 +1,4 @@ +Promjene u verziji 0.17.2 + +Ispravka +• Ispravka da nijedan video nije bio dostupan diff --git a/fastlane/metadata/android/bs/changelogs/780.txt b/fastlane/metadata/android/bs/changelogs/780.txt new file mode 100644 index 000000000..6a1074369 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/780.txt @@ -0,0 +1,12 @@ +Promjene u verziji 0.17.3 + +Poboljšano +• Dodata opcija za brisanje stanja reprodukcije #2550 +• Prikaz skrivenih direktorija u biraču datoteka #2591 +• Podrška za otvaranje URL-ova iz instanci `invidio.us` pomoću NewPipe #2488 +• Dodata podrška za URL-ove `music.youtube.com` TeamNewPipe/NewPipeExtractor#194 + +Ispravljeno +• [YouTube] Ispravljen 'java.lang.IllegalArgumentException #192 +• [YouTube] Ispravljen prenos uživo koji nije radio TeamNewPipe/NewPipeExtractor#195 +• Ispravljen problem s performansama u android pie-u prilikom preuzimanja prenosa #2592 diff --git a/fastlane/metadata/android/bs/changelogs/790.txt b/fastlane/metadata/android/bs/changelogs/790.txt new file mode 100644 index 000000000..28ec38810 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/790.txt @@ -0,0 +1,14 @@ +Poboljšano +• Dodavanje više naslova radi poboljšanja pristupačnosti za slijepe osobe #2655 +• Učiniti jezik postavki mape za preuzimanje konzistentnijim i manje dvosmislenim #2637 + +Ispravljeno +• Provjera da li je posljednji bajt u bloku preuzet #2646 +• Ispravljeno pomicanje u fragmentu detalja videa #2672 +• Uklanjanje dvostrukih animacija okvira za brisanje pretrage u jednu #2695 +• [SoundCloud] Ispravljanje ekstrakcije client_id-a #2745 + +Razvoj +• Dodavanje nedostajućih zavisnosti naslijeđenih iz NewPipeExtractor-a u NewPipe #2535 +• Migracija na AndroidX #2685 +• Ažuriranje na ExoPlayer 2.10.6 #2697, #2736 diff --git a/fastlane/metadata/android/bs/changelogs/800.txt b/fastlane/metadata/android/bs/changelogs/800.txt new file mode 100644 index 000000000..d3f8d5736 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/800.txt @@ -0,0 +1,27 @@ +Novo +• Podrška za PeerTube bez P2P-a (#2201) [Beta]: +◦ Gledajte i preuzimajte videozapise s PeerTube instanci +◦ Dodajte instance u postavkama za pristup cijelom PeerTube svijetu +◦ Moguće je da postoje problemi s SSL handshake-ovima na Androidu 4.4 i 7.1 prilikom pristupa određenim instancama, što rezultira mrežnom greškom. + +• Downloader (#2679): +◦ Izračunaj etalon preuzimanja (ETA) +◦ Preuzmi opus (webm datoteke) kao ogg +◦ Oporavi istekle linkove za preuzimanje kako bi se nastavilo preuzimanje nakon duge pauze + +Poboljšano +• Učini KioskFragment svjesnim promjena u željenoj zemlji sadržaja i poboljšaj performanse svih glavnih kartica #2742 +• Koristi nove implementacije lokalizacije i downloadera iz ekstraktora #2713 +• Učini niz "Default kiosk" prevodivim +• Crna navigacijska traka za crnu temu #2569 + +Ispravljeno +• Ispravljena greška koja nije mogla pomicati popup player ako je drugi prst postavljen tokom pomicanja popup playera #2772 +• Omogući liste za reprodukciju kojima nedostaje uploader i ispravi padove povezane s ovim problemom #2724, TeamNewPipe/NewPipeExtractor#219 +• Omogući TLS1.1/1.2 na Android 4.4 uređajima (API 19/KitKat) za ispravljanje TLS rukovanja s MediaCCC i nekim PeerTube instance #2792 +• [SoundCloud] Ispravljena ekstrakcija client_id-a TeamNewPipe/NewPipeExtractor #217 +• [SoundCloud] Ispravljena ekstrakcija audio toka + +Razvoj +• Ažuriranje ExoPlayera na 2.10.8 #2791, #2816 +• Ažuriranje Gradlea na 3.5.1 i dodavanje podrške za Kotlin #2714 diff --git a/fastlane/metadata/android/bs/changelogs/810.txt b/fastlane/metadata/android/bs/changelogs/810.txt new file mode 100644 index 000000000..52d9defbf --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/810.txt @@ -0,0 +1,20 @@ +Novo +• Prikaz minijature videa na zaključanom ekranu prilikom reprodukcije u pozadini + +Poboljšano + +• Dodavanje lokalne liste za reprodukciju u red čekanja prilikom dugog pritiska na dugme za pozadinu / skočni prozor +• Omogućavanje pomicanja kartica glavne stranice i njihovo skrivanje kada postoji samo jedna kartica +• Ograničavanje broja ažuriranja minijatura obavještenja u pozadinskom playeru +• Dodavanje lažne minijature za prazne lokalne liste za reprodukciju +• Korištenje ekstenzije datoteke *.opus umjesto *.webm i prikaz "opus" u oznaci formata umjesto "WebM Opus" u padajućem izborniku za preuzimanje +• Dodavanje dugmeta za brisanje preuzetih datoteka ili historije preuzimanja u "Preuzimanja" +• [YouTube] Dodana podrška za linkove kanala /c/shortened_url + +Ispravljeno +• Ispravljeno više problema prilikom dijeljenja videa na NewPipe i direktnog preuzimanja njegovih tokova +• Ispravljen pristup playeru izvan teme njegovog kreiranja +• Ispravljeno podjeljivanje rezultata pretrage +• [YouTube] Ispravljeno prebacivanje na null što je uzrokovalo NPE +• [YouTube] Ispravljeno pregledavanje komentara prilikom otvaranja invidio.us URL-a +• [SoundCloud] Ažuriran client_id diff --git a/fastlane/metadata/android/bs/changelogs/820.txt b/fastlane/metadata/android/bs/changelogs/820.txt new file mode 100644 index 000000000..ad9f1a5c2 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/820.txt @@ -0,0 +1 @@ +Ispravljen je regularni izraz naziva funkcije dešifriranja koji je YouTube činio neupotrebljivim. diff --git a/fastlane/metadata/android/bs/changelogs/830.txt b/fastlane/metadata/android/bs/changelogs/830.txt new file mode 100644 index 000000000..b4ba761fe --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/830.txt @@ -0,0 +1 @@ +Ažuriran je SoundCloud client_id kako bi se riješili problemi sa SoundCloudom. diff --git a/fastlane/metadata/android/bs/changelogs/840.txt b/fastlane/metadata/android/bs/changelogs/840.txt new file mode 100644 index 000000000..7820b4d05 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/840.txt @@ -0,0 +1,22 @@ +Novo +• Dodan je birač jezika za promjenu jezika aplikacije +• Dodano je dugme "pošalji na Kodi" u sklopivi meni plejera +• Dodana je mogućnost kopiranja komentara dugim pritiskom + +Poboljšano +• Ispravljena je ReCaptcha aktivnost i ispravno spremanje dobijenih kolačića +• Uklonjen je meni s tačkama u korist dugmeta "ladica" i "sakrivanje historije" kada historija gledanja nije omogućena u postavkama +• Ispravno traženje dozvole za prikaz preko drugih aplikacija u postavkama na Androidu 6 i novijim verzijama +• Preimenovanje lokalne liste za reprodukciju dugim klikom u BookmarkFragmentu +• Različita poboljšanja PeerTubea +• Poboljšano je nekoliko izvornih nizova na engleskom jeziku + +Ispravljeno +• Ispravljeno je ponovno pokretanje plejera iako je pauziran kada je omogućena opcija "minimiziraj pri prebacivanju aplikacija" i NewPipe je minimiziran +• Ispravljena je početna vrijednost svjetline za gestu +• Ispravljena su preuzimanja .srt titlova koja nisu sadržavala sve prijelome reda +• Ispravljeno je neuspješno preuzimanje na SD karticu jer neki Android 5 uređaji nisu kompatibilni sa CTF-om +• Ispravljeno je preuzimanje na Android KitKat-u +• Ispravljena je oštećena video .mp4 datoteka koja se prepoznaje kao audio datoteka +• Ispravljeni su višestruki problemi s lokalizacijom, uključujući pogrešne kineske jezičke kodove +• [YouTube] Vremenske oznake u opisu su ponovo dostupne za klikanje diff --git a/fastlane/metadata/android/bs/changelogs/850.txt b/fastlane/metadata/android/bs/changelogs/850.txt new file mode 100644 index 000000000..4f8c080f9 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/850.txt @@ -0,0 +1 @@ +U ovom izdanju ažurirana je verzija YouTube web stranice. Stara verzija web stranice bit će ukinuta u martu i stoga je potrebno nadograditi NewPipe. diff --git a/fastlane/metadata/android/bs/changelogs/860.txt b/fastlane/metadata/android/bs/changelogs/860.txt new file mode 100644 index 000000000..a2f051bb6 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/860.txt @@ -0,0 +1,7 @@ +Poboljšano +• Spremanje i vraćanje bez obzira da li su visina tona i tempo otkačeni ili ne +• Podrška za izrezivanje ekrana u playeru +• Kružni prikaz i broj pretplatnika +• Optimizovan YouTube za korištenje manje podataka + +U ovom izdanju ispravljeno je više od 15 grešaka povezanih s YouTubeom. diff --git a/fastlane/metadata/android/bs/changelogs/870.txt b/fastlane/metadata/android/bs/changelogs/870.txt new file mode 100644 index 000000000..3706dc130 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/870.txt @@ -0,0 +1,2 @@ +Ovo je hitna ispravka koja ažurira NewPipe kako bi se ponovo omogućilo korištenje SoundClouda bez većih problema. +SoundCloudov v2 API se sada koristi u ekstraktoru, a detekcija nevažećih ID-ova klijenata je poboljšana. diff --git a/fastlane/metadata/android/bs/changelogs/900.txt b/fastlane/metadata/android/bs/changelogs/900.txt new file mode 100644 index 000000000..c9a2c544d --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/900.txt @@ -0,0 +1,15 @@ +Novo +• Grupe pretplata i sortirani feedovi +• Dugme za isključivanje zvuka u playerima + +Poboljšano + +• Omogućeno otvaranje linkova music.youtube.com i media.ccc.de u NewPipe-u +• Premještanje dvije postavke iz Izgled u Sadržaj +• Sakrivanje opcija pretraživanja od 5, 15, 25 sekundi ako je omogućeno neprecizno pretraživanje + +Ispravljeno +• neki WebM videozapisi se ne mogu pretraživati +• sigurnosna kopija baze podataka na Android P +• rušenje prilikom dijeljenja preuzete datoteke +• mnoštvo problema s ekstrakcijom YouTubea i još mnogo toga ... diff --git a/fastlane/metadata/android/bs/changelogs/910.txt b/fastlane/metadata/android/bs/changelogs/910.txt new file mode 100644 index 000000000..d287ea12e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/910.txt @@ -0,0 +1 @@ +Ispravljena migracija baze podataka koja je u nekim rijetkim slučajevima sprečavala pokretanje NewPipe-a. diff --git a/fastlane/metadata/android/bs/changelogs/920.txt b/fastlane/metadata/android/bs/changelogs/920.txt new file mode 100644 index 000000000..b79042d51 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/920.txt @@ -0,0 +1,9 @@ +Poboljšano + +• Dodan datum otpremanja i broj pregleda za stavke mreže toka +• Poboljšanja za raspored zaglavlja ladice + +Ispravljeno + +• Ispravljeno dugme za isključivanje zvuka koje je uzrokovalo pad sistema na API 19 +• Ispravljeno preuzimanje dugih 1080p 60fps videa diff --git a/fastlane/metadata/android/bs/changelogs/930.txt b/fastlane/metadata/android/bs/changelogs/930.txt new file mode 100644 index 000000000..3ab5b5d04 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/930.txt @@ -0,0 +1,20 @@ +Novo +• Pretraga na YouTube Musicu +• Osnovna podrška za Android TV + +Poboljšano + +• Dodana je mogućnost uklanjanja svih gledanih videa s lokalne liste za reprodukciju +• Prikaz poruke kada sadržaj još nije podržan umjesto rušenja +• Poboljšana promjena veličine skočnog playera gestama štipanja +• Stavljanje tokova u red čekanja dugim pritiskom na pozadinu i skočne dugmad u kanalu +• Poboljšano rukovanje veličinom naslova zaglavlja ladice + +Ispravljeno +• Ispravljena postavka sadržaja s ograničenjem prema dobi koja nije radila +• Ispravljene određene vrste reCAPTCHA-a +• Ispravljen pad prilikom otvaranja oznaka dok je lista za reprodukciju `null` +• Ispravljeno otkrivanje izuzetaka povezanih s mrežom +• Ispravljena vidljivost dugmeta za sortiranje grupe u fragmentu pretplata + +i više diff --git a/fastlane/metadata/android/bs/changelogs/940.txt b/fastlane/metadata/android/bs/changelogs/940.txt new file mode 100644 index 000000000..28f0ab256 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/940.txt @@ -0,0 +1,16 @@ +Novo +• Dodana podrška za komentare na SoundCloudu +• Dodana postavka ograničenog načina rada na YouTubeu +• Prikaz detalja nadređenog kanala na PeerTubeu + +Poboljšano +• Prikaz dugmeta Kore samo za podržane usluge +• Blokiranje gestova igrača koji počinju na navigacijskoj traci ili statusnoj traci +• Promjena boje pozadine dugmadi za ponovni pokušaj i pretplatu na osnovu boje usluge + +Ispravljeno +• Ispravljeno zamrzavanje dijaloga za preuzimanje +• Dugme "Otvori u pregledniku" sada se zaista otvara u pregledniku +• Ispravljeno rušenje sistema pri otvaranju videa i "Nije moguće reproducirati ovaj tok" + +i još mnogo toga diff --git a/fastlane/metadata/android/bs/changelogs/950.txt b/fastlane/metadata/android/bs/changelogs/950.txt new file mode 100644 index 000000000..d3dc135a1 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/950.txt @@ -0,0 +1,4 @@ +Ovo izdanje donosi tri male ispravke: +• Ispravljen pristup pohrani na Androidu 10+ +• Ispravljeno otvaranje kioska +• Ispravljeno parsiranje dužih videa diff --git a/fastlane/metadata/android/bs/changelogs/951.txt b/fastlane/metadata/android/bs/changelogs/951.txt new file mode 100644 index 000000000..72077d172 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/951.txt @@ -0,0 +1,17 @@ +Novo +• Dodan je alat za odabir pretplata u dijalogu grupe feedova +• Dodan je filter u dijalog grupe feedova kako bi se prikazale samo negrupirane pretplate +• Dodana je kartica liste za reprodukciju na glavnu stranicu +• Premotavanje naprijed/nazad u pozadini/u redu čekanja playera +• Prikaz prijedloga za pretragu: da li ste mislili na & prikaz rezultata za + +Poboljšano +• Izostavljanje metapodataka aplikacije za pisanje u multipliciranim datotekama +• Ne uklanjanje neuspjelih tokova iz reda čekanja +• Ažuriranje boje statusne trake da odgovara boji alatne trake + +Ispravljeno +• Ispravljena je desinkronizacija zvuka/videa uzrokovana kumulativnim greškama s pomičnim zarezom +• [PeerTube] Obrada izbrisanih komentara + +i više diff --git a/fastlane/metadata/android/bs/changelogs/952.txt b/fastlane/metadata/android/bs/changelogs/952.txt new file mode 100644 index 000000000..9c8b5c617 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/952.txt @@ -0,0 +1,7 @@ +Poboljšano +• Automatska reprodukcija je dostupna za sve usluge (umjesto samo za YouTube) + +Ispravljeno +• Ispravljeni povezani tokovi podrškom za nove YouTube nastavke +• Ispravljeni YouTube videozapisi s ograničenjem za određene uzraste +• [Android TV] Ispravljeno dugotrajno preklapanje istaknutog fokusa diff --git a/fastlane/metadata/android/bs/changelogs/953.txt b/fastlane/metadata/android/bs/changelogs/953.txt new file mode 100644 index 000000000..075e3f47e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/953.txt @@ -0,0 +1 @@ +Ispravljena ekstrakcija funkcije dešifriranja na YouTubeu. diff --git a/fastlane/metadata/android/bs/changelogs/954.txt b/fastlane/metadata/android/bs/changelogs/954.txt new file mode 100644 index 000000000..7a57794fa --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/954.txt @@ -0,0 +1,10 @@ +• novi tijek rada aplikacije: reproducirajte videozapise na stranici s detaljima, prevucite prema dolje da biste minimizirali player + +• MediaStyle obavještenja: prilagodljive radnje u obavještenjima, poboljšanja performansi +• osnovna promjena veličine pri korištenju NewPipe-a kao desktop aplikacije + +• prikaži dijalog s otvorenim opcijama u slučaju nepodržanog URL tosta +• Poboljšano iskustvo prijedloga za pretraživanje kada se udaljeni URL-ovi ne mogu dohvatiti +• Povećan zadani kvalitet videozapisa na 720p60 (player u aplikaciji) i 480p (skočni player) + +• mnoštvo ispravki grešaka i još mnogo toga diff --git a/fastlane/metadata/android/bs/changelogs/955.txt b/fastlane/metadata/android/bs/changelogs/955.txt new file mode 100644 index 000000000..560aac290 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/955.txt @@ -0,0 +1,3 @@ +[YouTube] Ispravljena pretraga za neke korisnike +[YouTube] Ispravljeni izuzeci slučajnog dešifriranja +[SoundCloud] URL-ovi koji završavaju kosom crtom sada se ispravno parsiraju diff --git a/fastlane/metadata/android/bs/changelogs/956.txt b/fastlane/metadata/android/bs/changelogs/956.txt new file mode 100644 index 000000000..b153534eb --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/956.txt @@ -0,0 +1 @@ +[YouTube] Ispravljen pad aplikacije prilikom učitavanja bilo kojeg videa diff --git a/fastlane/metadata/android/bs/changelogs/957.txt b/fastlane/metadata/android/bs/changelogs/957.txt new file mode 100644 index 000000000..9bfe5ddd9 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/957.txt @@ -0,0 +1,10 @@ +• Ujedinite specifične radnje stavljanja u red u jednu +• Gesta dva prsta za zatvaranje playera +• Omogućite brisanje reCAPTCHA kolačića +• Opcija da se obavještenja ne oboje +• Poboljšajte način otvaranja detalja videa kako biste riješili beskonačno baferovanje, greške prilikom dijeljenja na NewPipe i druge nedosljednosti +• Ubrzajte YouTube videozapise i ispravite one s ograničenjem po uzrastu +• Ispravite pad sistema prilikom premotavanja unaprijed/unazad +• Nemojte preuređivati liste povlačenjem sličica +• Uvijek pamtite svojstva skočnih prozora +• Dodan je santalski jezik diff --git a/fastlane/metadata/android/bs/changelogs/958.txt b/fastlane/metadata/android/bs/changelogs/958.txt new file mode 100644 index 000000000..381065d98 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/958.txt @@ -0,0 +1,15 @@ +Novo i poboljšano: +• Ponovno dodana opcija za skrivanje sličice na zaključanom ekranu +• Povlačenje za osvježavanje feeda +• Poboljšane performanse prilikom preuzimanja lokalnih lista + +Ispravljeno: +• Ispravljen pad sistema prilikom pokretanja NewPipe-a nakon što je uklonjen iz RAM-a +• Ispravljen pad sistema prilikom pokretanja kada nema internet veze +• Ispravljeno u vezi s postavkama gestova za svjetlinu i jačinu zvuka +• [YouTube] Ispravljene duge liste reprodukcije + +Ostalo: +• Čišćenje koda i nekoliko internih poboljšanja +• Ažuriranja zavisnosti +• Ažuriranja prevoda diff --git a/fastlane/metadata/android/bs/changelogs/959.txt b/fastlane/metadata/android/bs/changelogs/959.txt new file mode 100644 index 000000000..4764f3fea --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/959.txt @@ -0,0 +1,3 @@ +Ispravljen beskonačan niz rušenja sistema nakon otvaranja izvještaja o greškama. +Ažurirana lista PeerTube instanci koje NewPipe može automatski otvoriti. +Ažurirani prijevodi. diff --git a/fastlane/metadata/android/bs/changelogs/960.txt b/fastlane/metadata/android/bs/changelogs/960.txt new file mode 100644 index 000000000..8c503be87 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/960.txt @@ -0,0 +1,3 @@ +• Poboljšan opis opcije izvoza baze podataka u postavkama. +• Ispravljeno parsiranje komentara na YouTubeu. +• Ispravljeno ime za prikaz servisa media.ccc.de. • Ažurirani prijevodi. diff --git a/fastlane/metadata/android/bs/changelogs/961.txt b/fastlane/metadata/android/bs/changelogs/961.txt new file mode 100644 index 000000000..dfe9db359 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/961.txt @@ -0,0 +1,12 @@ +• [YouTube] Podrška za Mix +• [YouTube] Prikaz informacija o javnim emiterima i Covid-19 +• [media.ccc.de] Dodani nedavni videozapisi +• Dodan prijevod na somalski jezik + +• Mnoga interna poboljšanja + +• Ispravljeno dijeljenje videozapisa iz playera +• Ispravljen prazan ReCaptcha web prikaz +• Ispravljen pad aplikacije koji se javljao prilikom uklanjanja toka s liste +• [PeerTube] Ispravljeni povezani tokovi +• [YouTube] Ispravljena pretraga YouTube muzike diff --git a/fastlane/metadata/android/bs/changelogs/962.txt b/fastlane/metadata/android/bs/changelogs/962.txt new file mode 100644 index 000000000..72c26f1be --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/962.txt @@ -0,0 +1,2 @@ +Dodani "nedavni" videozapisi na servis media.ccc.de. +Dodani su prijenosi uživo na servis media.ccc.de, kao i podrška za prijenos uživo. diff --git a/fastlane/metadata/android/bs/changelogs/963.txt b/fastlane/metadata/android/bs/changelogs/963.txt new file mode 100644 index 000000000..1799936e5 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/963.txt @@ -0,0 +1 @@ +• [YouTube] Ispravljen nastavak kanala diff --git a/fastlane/metadata/android/bs/changelogs/964.txt b/fastlane/metadata/android/bs/changelogs/964.txt new file mode 100644 index 000000000..3fd416ae6 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/964.txt @@ -0,0 +1,8 @@ +• Dodana podrška za poglavlja u kontrolama playera +• [PeerTube] Dodana pretraga u sepia boji +• Ponovo dodano dugme za dijeljenje u detaljnom prikazu videa i opis toka premješten u raspored kartica +• Onemogućeno vraćanje svjetline ako je gesta za svjetlinu onemogućena +• Dodana stavka liste za reprodukciju videa na Kodiju +• Ispravljen pad sistema kada na nekim uređajima nije postavljen zadani preglednik i poboljšani su dijalozi za dijeljenje +• Uključivanje/isključivanje reprodukcije/pauze pomoću hardverskog dugmeta za razmak u playeru preko cijelog ekrana +• [media.ccc.de] Razne ispravke i poboljšanja diff --git a/fastlane/metadata/android/bs/changelogs/965.txt b/fastlane/metadata/android/bs/changelogs/965.txt new file mode 100644 index 000000000..f010b66cb --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/965.txt @@ -0,0 +1,6 @@ +Ispravljen pad sistema koji se javljao prilikom promjene redoslijeda grupa kanala. +Ispravljeno dobijanje više YouTube videa sa kanala i plejlista. +Ispravljeno dobijanje YouTube komentara. +Dodana je podrška za podputanje /watch/, /v/ i /w/ u YouTube URL-ovima. +Ispravljeno izdvajanje SoundCloud klijentskog ID-a i geo-ograničenog sadržaja. +Dodana je lokalizacija za sjeverni kurdski jezik. diff --git a/fastlane/metadata/android/bs/changelogs/966.txt b/fastlane/metadata/android/bs/changelogs/966.txt new file mode 100644 index 000000000..7f47d9ac9 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/966.txt @@ -0,0 +1,14 @@ +Novo: +• Dodana nova usluga: Bandcamp + +Poboljšano: +• Dodana opcija da aplikacija prati temu uređaja +• Spriječeni su neki rušenji prikazivanjem poboljšane ploče s greškama +• Prikaz više informacija o tome zašto sadržaj nije dostupan +• Dugme za razmak na hardveru pokreće reprodukciju/pauzu +• Prikaz tosta "Preuzimanje započeto" + +Ispravljeno: +• Ispravljena je vrlo mala sličica u detaljima videa tokom reprodukcije u pozadini +• Ispravljen je prazan naslov u minimiziranom playeru +• Ispravljena je greška zbog koje se posljednji način promjene veličine nije ispravno vraćao diff --git a/fastlane/metadata/android/bs/changelogs/967.txt b/fastlane/metadata/android/bs/changelogs/967.txt new file mode 100644 index 000000000..039051547 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/967.txt @@ -0,0 +1 @@ +Ispravljen je problem sa neispravnim radom YouTubea u EU. Uzrok tome je bio novi sistem za pristanak na kolačiće i privatnost koji zahtijeva da NewPipe postavi kolačić PRISTANAK. diff --git a/fastlane/metadata/android/bs/changelogs/968.txt b/fastlane/metadata/android/bs/changelogs/968.txt new file mode 100644 index 000000000..d7e5be7b4 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/968.txt @@ -0,0 +1,7 @@ +Dodana je opcija za detalje kanala u meni s dugim pritiskom. +Dodana je funkcionalnost preimenovanja naziva liste za reprodukciju iz sučelja liste za reprodukciju. +Omogućeno korisniku pauziranje dok se video učitava. +Dotjerana je bijela tema. +Ispravljeno preklapanje fontova pri korištenju veće veličine fonta. +Ispravljen je problem s nedostatkom videa na Formuler i Zephier uređajima. +Ispravljeni su razni padovi sistema. diff --git a/fastlane/metadata/android/bs/changelogs/969.txt b/fastlane/metadata/android/bs/changelogs/969.txt new file mode 100644 index 000000000..804873f1e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/969.txt @@ -0,0 +1,8 @@ +• Dozvoljena instalacija na eksternu memoriju +• [Bandcamp] Dodata podrška za prikaz prva tri komentara na toku +• Prikaži samo obavijest 'preuzimanje je počelo' kada je preuzimanje pokrenuto +• Ne postavljaj reCaptcha kolačić kada nema pohranjenih kolačića +• [Player] Poboljšane performanse keša +• [Player] Ispravljena greška u reprodukciji u plejeru +• Odbaci prethodne Snackbarove prilikom brisanja preuzimanja +• Ispravljen pokušaj brisanja objekta koji nije na listi diff --git a/fastlane/metadata/android/bs/changelogs/970.txt b/fastlane/metadata/android/bs/changelogs/970.txt new file mode 100644 index 000000000..414f6c9c6 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/970.txt @@ -0,0 +1,11 @@ +Novo +• Prikaz metapodataka sadržaja (oznake, kategorije, licenca, ...) ispod opisa +• Dodana opcija "Prikaži detalje kanala" u udaljenim (nelokalnim) listama za reprodukciju +• Dodana opcija "Otvori u pregledniku" u meni s dugim pritiskom + +Ispravljeno +• Ispravljen pad sistema prilikom rotacije na stranici s detaljima videa +• Ispravljeno dugme "Reproduciraj s Kodijem" u playeru koje uvijek traži instalaciju Kore-a +• Ispravljeno i poboljšano podešavanje putanja uvoza i izvoza +• [YouTube] Ispravljen broj lajkova za komentare +I još mnogo toga diff --git a/fastlane/metadata/android/bs/changelogs/971.txt b/fastlane/metadata/android/bs/changelogs/971.txt new file mode 100644 index 000000000..f49116929 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/971.txt @@ -0,0 +1,3 @@ +Hitna ispravka +• Povećanje bafera za reprodukciju nakon ponovnog baferovanja +• Ispravljen pad sistema na tabletima i televizorima prilikom klika na ikonu reda za reprodukciju u plejeru diff --git a/fastlane/metadata/android/bs/changelogs/972.txt b/fastlane/metadata/android/bs/changelogs/972.txt new file mode 100644 index 000000000..e422201cf --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/972.txt @@ -0,0 +1,14 @@ +Novo +Prepoznavanje vremenskih oznaka i hashtagova u opisu +Dodano ručno podešavanje tablet režima +Dodana mogućnost skrivanja reprodukovanih stavki u feedu + +Poboljšano +Ispravno podržavanje okvira za pristup pohrani +Bolje rukovanje greškama nedostupnih i prekinutih kanala +Android tabela za dijeljenje za korisnike Androida 10+ sada prikazuje naslov sadržaja. +Ažurirane su Invidious instance i podrška za preusmjerene linkove. + +Ispravljeno +[YouTube] Sadržaj ograničen prema dobi +Spriječen izuzetak curenja prozora prilikom otvaranja dijaloga za izbor diff --git a/fastlane/metadata/android/bs/changelogs/973.txt b/fastlane/metadata/android/bs/changelogs/973.txt new file mode 100644 index 000000000..0e78a352e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/973.txt @@ -0,0 +1,4 @@ +Hitna ispravka +• Ispravljene sličice i naslovi koji su se skraćivali u rasporedu mreže, zbog pogrešnog izračuna koliko videozapisa može stati u jedan red +• Ispravljen dijalog za preuzimanje koji je nestajao bez ikakve radnje ako se otvori iz menija za dijeljenje +• Ažurirana biblioteka povezana s otvaranjem vanjskih aktivnosti kao što je birač datoteka Storage Access Frameworka diff --git a/fastlane/metadata/android/bs/changelogs/974.txt b/fastlane/metadata/android/bs/changelogs/974.txt new file mode 100644 index 000000000..991a16e09 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/974.txt @@ -0,0 +1,5 @@ +Hitna ispravka +• Ispravljeni problemi s baferovanjem uzrokovani ograničavanjem YouTubea +• Ispravljeno izdvajanje komentara na YouTubeu i rušenja aplikacije s onemogućenim komentarima +• Ispravljena pretraga muzike na YouTubeu +• Ispravljeni prenosi uživo na PeerTubeu diff --git a/fastlane/metadata/android/bs/changelogs/975.txt b/fastlane/metadata/android/bs/changelogs/975.txt new file mode 100644 index 000000000..ab5edb692 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/975.txt @@ -0,0 +1,17 @@ +Novo +• Prikaz pregleda sličice tokom pretraživanja +• Detekcija onemogućenih komentara +• Omogućeno označavanje stavke feeda kao gledane +• Prikaz srca u komentarima + +Poboljšano +• Poboljšan raspored metapodataka i oznaka +• Primjena boje usluge na UI komponente + +Ispravljeno +• Ispravljena sličica u mini playeru +• Ispravljeno beskonačno baferovanje duplih stavki reda čekanja +• Neke ispravke playera poput rotacije i bržeg zatvaranja +• Ispravljena ReCAPTCHA koja ostaje učitana u pozadini +• Onemogući klikove prilikom osvježavanja feeda +• Ispravljeni neki padovi preuzimanja diff --git a/fastlane/metadata/android/bs/changelogs/976.txt b/fastlane/metadata/android/bs/changelogs/976.txt new file mode 100644 index 000000000..86abfacf2 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/976.txt @@ -0,0 +1,10 @@ +• Dodana je opcija za direktno otvaranje playera preko cijelog ekrana +• Omogućen je odabir vrsta prijedloga za pretragu koji će se prikazivati +• Tamna tema je sada tamnija + dodan je tamniji početni ekran +• Poboljšan birač datoteka za sivo označavanje neželjenih datoteka +• Ispravljen uvoz YouTube pretplata +• Ponovna reprodukcija toka zahtijeva ponovni dodir dugmeta za reprodukciju +• Ispravljeno zatvaranje audio sesije +• [Android TV] Ispravljeni su dugi skokovi na traci za pretraživanje prilikom korištenja DPad-a + +Da biste vidjeli daljnje promjene, pogledajte dnevnik promjena (i objavu na blogu) na kartici Linkovi ispod. diff --git a/fastlane/metadata/android/bs/changelogs/977.txt b/fastlane/metadata/android/bs/changelogs/977.txt new file mode 100644 index 000000000..da79b791f --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/977.txt @@ -0,0 +1,10 @@ +• Dodano dugme "reproduciraj sljedeće" u meni dugog pritiska +• Dodan prefiks putanje YouTube kratkih videozapisa u filter namjere +• Ispravljen uvoz postavki +• Zamjena pozicije trake za pretraživanje s dugmadima playera na ekranu reda čekanja +• Razne ispravke vezane za MediasessionManager +• Ispravljena traka za pretraživanje koja se nije dovršila nakon završetka videa +• Onemogućeno tuneliranje medija na RealtekATV-u +• Prošireno područje za klik na minimizirana dugmad playera + +Da biste vidjeli daljnje promjene, pogledajte dnevnik promjena (i objavu na blogu) na kartici Linkovi ispod. diff --git a/fastlane/metadata/android/bs/changelogs/978.txt b/fastlane/metadata/android/bs/changelogs/978.txt new file mode 100644 index 000000000..132fa5cd4 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/978.txt @@ -0,0 +1 @@ +Ispravljeno izvršavanje provjere za novu verziju NewPipe-a. Ova provjera se ponekad izvršavala prerano i stoga je dovodila do pada aplikacije. To bi sada trebalo biti ispravljeno. diff --git a/fastlane/metadata/android/bs/changelogs/979.txt b/fastlane/metadata/android/bs/changelogs/979.txt new file mode 100644 index 000000000..50a39f3c7 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/979.txt @@ -0,0 +1,2 @@ +- Ispravljeno nastavljanje reprodukcije +- Poboljšanja kako bi se osiguralo da servis koji određuje da li NewPipe treba provjeravati nove verzije nije pokrenut u pozadini diff --git a/fastlane/metadata/android/bs/changelogs/980.txt b/fastlane/metadata/android/bs/changelogs/980.txt new file mode 100644 index 000000000..58fe99af8 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/980.txt @@ -0,0 +1,13 @@ +Novo +• Dodana je opcija "Dodaj na listu za reprodukciju" u meni za dijeljenje +• Dodana je podrška za kratke linkove na y2u.be i PeerTube + +Poboljšano +• Kontrole brzine reprodukcije su kompaktnije +• Feed sada ističe nove stavke +• Opcija "Prikaži gledane stavke" u feedu je sada sačuvana + +Ispravljeno +• Ispravljeno izdvajanje lajkova i nesviđanja na YouTubeu +• Ispravljena je automatska reprodukcija nakon povratka iz pozadine +I još mnogo toga diff --git a/fastlane/metadata/android/bs/changelogs/981.txt b/fastlane/metadata/android/bs/changelogs/981.txt new file mode 100644 index 000000000..d832a5ba0 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/981.txt @@ -0,0 +1,2 @@ +Uklonjena je podrška za MediaParser kako bi se riješio problem neuspjelog nastavka reprodukcije nakon baferovanja na Androidu 11+. +Onemogućeno je tuneliranje medija na Philips QM16XE uređaju kako bi se riješili problemi s reprodukcijom. diff --git a/fastlane/metadata/android/bs/changelogs/982.txt b/fastlane/metadata/android/bs/changelogs/982.txt new file mode 100644 index 000000000..39ccdd3e6 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/982.txt @@ -0,0 +1 @@ +Ispravljena greška zbog koje YouTube nije reprodukovao nijedan tok. diff --git a/fastlane/metadata/android/bs/changelogs/983.txt b/fastlane/metadata/android/bs/changelogs/983.txt new file mode 100644 index 000000000..ebf3841e1 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/983.txt @@ -0,0 +1,9 @@ +Dodati novi korisnički interfejs i ponašanje za pretraživanje dvostrukim dodirom +Omogućiti pretraživanje postavki +Istaknuti zakačene komentare kao takve +Dodati podršku za otvaranje s aplikacijom za FSFE-ovu PeerTube instancu +Dodati obavještenja o greškama +Ispraviti ponavljanje prve stavke reda čekanja pri promjeni igrača +Duže čekati prilikom učitavanja u međuspremniku tokom prijenosa uživo prije nego što dođe do greške +Ispraviti redoslijed lokalnih rezultata pretrage +Ispraviti prazna polja stavki u redu čekanja za reprodukciju diff --git a/fastlane/metadata/android/bs/changelogs/984.txt b/fastlane/metadata/android/bs/changelogs/984.txt new file mode 100644 index 000000000..300013d5e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/984.txt @@ -0,0 +1,7 @@ +Učitajte dovoljno početnih stavki u listama da popune cijeli ekran i da se riješi problem skrolovanja na tabletima i televizorima +Ispravite nasumična rušenja prilikom skrolovanja kroz liste +Neka se luk preklapanja brzog pretraživanja plejera nalazi ispod sistemskog korisničkog interfejsa +Vratite promjene izreza prilikom reprodukcije u više prozora, što je uzrokovalo regresiju pogrešno postavljenog plejera na nekim telefonima +Povećajte compileSdk sa 30 na 31 +Ažurirajte biblioteku za prijavljivanje grešaka +Refaktorišite dio koda u plejeru diff --git a/fastlane/metadata/android/bs/changelogs/985.txt b/fastlane/metadata/android/bs/changelogs/985.txt new file mode 100644 index 000000000..acd29e47c --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/985.txt @@ -0,0 +1 @@ +Ispravljeno je da YouTube ne reprodukuje nijedan tok diff --git a/fastlane/metadata/android/bs/changelogs/986.txt b/fastlane/metadata/android/bs/changelogs/986.txt new file mode 100644 index 000000000..f7a82bf00 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/986.txt @@ -0,0 +1,17 @@ +Novo +• Obavještenja za nove tokove +• Besprijekoran prijelaz između pozadinskog i video playera +• Promjena visine tona za polutone +• Dodavanje reda čekanja glavnog playera na listu za reprodukciju + +Poboljšano + +• Zapamti brzinu/veličinu koraka visine tona +• Ublaži početno dugo baferovanje u video playeru +• Poboljšan korisnički interfejs playera za Android TV +• Potvrdi prije brisanja svih preuzetih datoteka + +Ispravljeno +• Ispravljeno dugme za medije koje nije skrivalo kontrole playera +• Ispravljeno resetovanje reprodukcije pri promjeni tipa playera +• Ispravljeno rotiranje dijaloga liste za reprodukciju diff --git a/fastlane/metadata/android/bs/changelogs/987.txt b/fastlane/metadata/android/bs/changelogs/987.txt new file mode 100644 index 000000000..d14bfa7ee --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/987.txt @@ -0,0 +1,12 @@ +Novo +• Podrška za metode isporuke osim progresivnog HTTP-a: brže vrijeme učitavanja reprodukcije, ispravke za PeerTube i SoundCloud, reprodukcija nedavno završenih YouTube prijenosa uživo +• Dodano dugme za dodavanje udaljene liste za reprodukciju na lokalnu +• Pregled slike u Android 10+ listu za dijeljenje + +Poboljšano +• Poboljšan dijalog parametara reprodukcije +• Dugmad za uvoz/izvoz pretplate premještena u meni s tri tačke + +Ispravljeno +• Ispravljeno uklanjanje potpuno pregledanih videozapisa s liste za reprodukciju +• Ispravljena tema menija za dijeljenje i unos "dodaj na listu za reprodukciju" diff --git a/fastlane/metadata/android/bs/changelogs/988.txt b/fastlane/metadata/android/bs/changelogs/988.txt new file mode 100644 index 000000000..fa0f905ba --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/988.txt @@ -0,0 +1,2 @@ +[YouTube] Ispravljena greška "Nije moguće dobiti tok" prilikom pokušaja reprodukcije bilo kojeg videa +[YouTube] Ispravljena poruka "Sljedeći sadržaj nije dostupan u ovoj aplikaciji" koja se prikazuje umjesto traženog videa diff --git a/fastlane/metadata/android/bs/changelogs/989.txt b/fastlane/metadata/android/bs/changelogs/989.txt new file mode 100644 index 000000000..6c80f717e --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/989.txt @@ -0,0 +1,3 @@ +• [YouTube] Ispravljeno beskonačno učitavanje pri pokušaju reprodukcije bilo kojeg videa +• [YouTube] Ispravljeno ograničavanje reprodukcije nekih videa +• Nadogradite biblioteku jsoup na verziju 1.15.3, što uključuje sigurnosnu ispravku diff --git a/fastlane/metadata/android/bs/changelogs/990.txt b/fastlane/metadata/android/bs/changelogs/990.txt new file mode 100644 index 000000000..49f7ffe95 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/990.txt @@ -0,0 +1,15 @@ +Ovo izdanje ukida podršku za Android 4.4 KitKat, sada je minimalna verzija Android 5 Lollipop! + +Novo +• Preuzimanje iz menija s dugim pritiskom +• Skrivanje budućih videa u feedu +• Dijeljenje lokalnih lista za reprodukciju + +Poboljšano +• Refaktorisanje koda playera u male komponente: manje RAM-a se koristi, manje grešaka +• Poboljšan način skaliranja sličica +• Vektorska konverzija rezerviranih mjesta za slike + +Ispravljeno +• Ispravljeni razni problemi s obavještenjima playera: zastarjele/nedostajuće informacije o medijima, iskrivljena sličica +• Ispravljen prikaz preko cijelog ekrana koristeći 1/4 ekrana diff --git a/fastlane/metadata/android/bs/changelogs/991.txt b/fastlane/metadata/android/bs/changelogs/991.txt new file mode 100644 index 000000000..bdbb7a5b7 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/991.txt @@ -0,0 +1,14 @@ +Novo +• Dodano dugme "Otvori u pregledniku" u panelu s greškama +• Dodana opcija za prikaz grupa kanala kao liste +• [YouTube] Dugi klik na segmente toka za dijeljenje URL-a vremenske oznake +• Dodano dugme za red čekanja za reprodukciju u mini player + +Poboljšano + +• Dodana lokalizacija za islandski jezik i ažurirani mnogi drugi prijevodi +• Mnoga interna poboljšanja + +Ispravljeno +• Ispravljeno višestruko rušenje sistema +• [YouTube] Ispravljeno učitavanje kanala, nenamjenski feed i zaobilazno rješenje problema s reprodukcijom u nekim zemljama diff --git a/fastlane/metadata/android/bs/changelogs/992.txt b/fastlane/metadata/android/bs/changelogs/992.txt new file mode 100644 index 000000000..f101f68f0 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/992.txt @@ -0,0 +1,17 @@ +Novo +• Broj pretplatnika u detaljima videa +• Preuzimanje iz reda čekanja +• Trajno postavljanje sličice liste za reprodukciju +• Dugi pritisak na hashtagove i linkove +• Način prikaza kartice + +Poboljšano +• Veće dugme za zatvaranje mini-playera +• Glatko smanjenje sličica +• Ciljano za Android 13 (API 33) +• Traženje više ne pauzira player + +Ispravljeno +• Ispravljen prekrivač na DeX-u/mišu +• Omogućen pozadinski player bez odvojenih audio tokova +• Razne ispravke za YouTube i još mnogo toga… diff --git a/fastlane/metadata/android/bs/changelogs/993.txt b/fastlane/metadata/android/bs/changelogs/993.txt new file mode 100644 index 000000000..4677738e9 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/993.txt @@ -0,0 +1,12 @@ +Novo +• Dodano upozorenje prilikom dodavanja duplikata liste za reprodukciju i dodavanje dugmeta za njihovo uklanjanje +• Omogućeno ignorisanje hardverskih dugmadi +• Omogućeno skrivanje djelomično pregledanih videa u feedu + +Poboljšano +• Koristiti više kolona mreže na velikim ekranima +• Usaglasiti indikatore napretka s postavkama + +Ispravljeno +• Ispravljeno otvaranje URL-ova preglednika, preuzimanja i vanjskih playera na Androidu 11+ +• Ispravljena interakcija s cijelim ekranom koja zahtijeva dva dodira na MIUI-ju diff --git a/fastlane/metadata/android/bs/changelogs/994.txt b/fastlane/metadata/android/bs/changelogs/994.txt new file mode 100644 index 000000000..0440a2c94 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/994.txt @@ -0,0 +1,15 @@ +Novo +• Podrška za više audio zapisa/jezika +• Omogućeno podešavanje jačine zvuka i svjetline gestama sa bilo koje strane ekrana +• Podrška za prikaz glavnih kartica na dnu ekrana + +Poboljšano +• [Bandcamp] Rukovanje zapisima iza paywalla + +Ispravljeno +• [YouTube] 403 HTTP greške za tokove +• Crni plejer pri prelasku na glavni plejer sa prikaza liste za reprodukciju +• Curenje memorije servisa plejera +• [PeerTube] Avatari za uploader i podkanal su zamijenjeni + +i više diff --git a/fastlane/metadata/android/bs/changelogs/995.txt b/fastlane/metadata/android/bs/changelogs/995.txt new file mode 100644 index 000000000..68912e20d --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/995.txt @@ -0,0 +1,16 @@ +Novo +• Podrška za kartice kanala +• Odabir kvalitete slike +• Dobijanje URL-ova za sve slike + +Poboljšano +• Pristupačnost interfejsa playera +• Bolji odabir zvuka za preuzimanja samo videozapisa +• Opcija za uključivanje naziva popisa za reprodukciju i videozapisa u dijeljeni sadržaj popisa za reprodukciju + +Ispravljeno +• [YouTube] Ispravljeno dobijanje broja lajkova +• Ispravljeni skočni prozori i padovi sustava koji ne reagiraju na player +• Odabir pogrešnih jezika u biraču jezika +• Fokus zvuka playera nije poštovao zvuk +• Dodavanje stavki popisa za reprodukciju povremeno nije radilo diff --git a/fastlane/metadata/android/bs/changelogs/996.txt b/fastlane/metadata/android/bs/changelogs/996.txt new file mode 100644 index 000000000..0fa343ba2 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/996.txt @@ -0,0 +1,2 @@ +Ispravljen je NullPointerException prilikom otvaranja kanala/konferencije u media.ccc.de. +Grinch je pokušao da vam pokvari naš božićni poklon, ali smo ga ispravili. diff --git a/fastlane/metadata/android/bs/changelogs/997.txt b/fastlane/metadata/android/bs/changelogs/997.txt new file mode 100644 index 000000000..1703a1f7c --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/997.txt @@ -0,0 +1,17 @@ +Novo +• Dodajte odgovore na komentare +• Omogućite promjenu redoslijeda lista za reprodukciju +• Prikažite opis i trajanje liste za reprodukciju +• Omogućite resetiranje postavki + +Poboljšano +• [Android 13+] Vratite prilagođene radnje obavještenja +• Zatražite saglasnost za provjeru ažuriranja +• Omogućite reprodukciju/pauziranje obavještenja tokom učitavanja u međuspremnik +• Promijenite redoslijed nekih postavki + +Ispravljeno +• [YouTube] Ispravljen komentari koji se ne učitavaju, plus druge ispravke i poboljšanja +• Rješite ranjivost u uvozu postavki i prebacite se na JSON +• Razne ispravke preuzimanja +• Skratite tekst pretrage diff --git a/fastlane/metadata/android/bs/changelogs/998.txt b/fastlane/metadata/android/bs/changelogs/998.txt new file mode 100644 index 000000000..6a8cecc00 --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/998.txt @@ -0,0 +1,4 @@ +Ispravljena greška zbog koje YouTube nije reproducirao nijedan tok zbog HTTP 403 greške. + +Povremene HTTP 403 greške usred YouTube videa još nisu ispravljene. +Taj problem će biti riješen u drugom izdanju hitne ispravke što je prije moguće. diff --git a/fastlane/metadata/android/bs/changelogs/999.txt b/fastlane/metadata/android/bs/changelogs/999.txt new file mode 100644 index 000000000..864bf68ec --- /dev/null +++ b/fastlane/metadata/android/bs/changelogs/999.txt @@ -0,0 +1,12 @@ +Ovo izdanje hitne ispravke ispravlja HTTP 403 greške usred YouTube videa. + +Novo +• [SoundCloud] Dodata podrška za on.soundcloud.com URL-ove + +Poboljšano +• [Bandcamp] Prikaz dodatnih informacija u radio kiosku + +Ispravljeno +• [YouTube] Ispravljene povremene HTTP 403 greške na početku ili usred videa +• [YouTube] Izdvajanje avatara i banera iz više tipova zaglavlja kanala +• [Bandcamp] Ispravljene razne greške i uvijek korištenje HTTPS-a diff --git a/fastlane/metadata/android/cs/changelogs/1005.txt b/fastlane/metadata/android/cs/changelogs/1005.txt index 2059e43de..e8efaffad 100644 --- a/fastlane/metadata/android/cs/changelogs/1005.txt +++ b/fastlane/metadata/android/cs/changelogs/1005.txt @@ -1,17 +1,17 @@ -Novinky -• Přidána podpora pro Android Auto. -• Možnost nastavit skupiny kanálů jako záložky na hlavní obrazovce. -• [YouTube] Sdílení jako dočasný seznam skladeb. -• [SoundCloud] Záložka Oblíbené kanály +Nově +• Podpora pro Android Auto +• Možnost nastavit skupiny zdrojů jako záložky +• [YouTube] Sdílení jako dočasný playlist +• [SoundCloud] Záložka Oblíbené u kanálů Vylepšeno -• Lepší nápověda pro vyhledávací lištu -• Zobrazení data stažení v sekci Stažené soubory -• Použití jazyka Android 13 pro jednotlivé aplikace +• Lepší našeptávač vyhledávače +• Zobrazení data stažení ve Stažených +• Použití individuálního jazyka Opraveno • Oprava chybných barev textu v tmavém režimu -• [YouTube] Oprava seznamů skladeb, které nenačtou více než 100 položek +• [YouTube] Oprava nenačtení více než 100 položek v playlistech • [YouTube] Oprava chybějících doporučených videí -• Oprava pádů v zobrazení seznamu historie -• Oprava časových značek v odpovědích na komentáře +• Oprava pádů v Historii +• Oprava časů v odpovědích diff --git a/fastlane/metadata/android/cs/changelogs/1006.txt b/fastlane/metadata/android/cs/changelogs/1006.txt new file mode 100644 index 000000000..88c312e14 --- /dev/null +++ b/fastlane/metadata/android/cs/changelogs/1006.txt @@ -0,0 +1,12 @@ +# Vylepšení +Ponechání aktuálního přehrávače při klepnutí na časová razítka +Pokus o obnovení čekajících stahování, pokud to jde +Možnost odstranění stahování bez smazání souboru +Oprávnění Zobrazení přes ostatní aplikace: zobrazení vysvětlení pro Android > R +Podpora odkazů on.soundcloud + +# Opravy +Oprava formátování pro verze Androidu nižší než 7 +Oprava falešných oznámení +Opravy souborů titulků SRT +Oprava spousty pádů diff --git a/fastlane/metadata/android/cs/changelogs/1007.txt b/fastlane/metadata/android/cs/changelogs/1007.txt new file mode 100644 index 000000000..7035a1112 --- /dev/null +++ b/fastlane/metadata/android/cs/changelogs/1007.txt @@ -0,0 +1 @@ +Opraveno nepřehrávání jakéhokoli streamu ve službě YouTube diff --git a/fastlane/metadata/android/de/changelogs/1002.txt b/fastlane/metadata/android/de/changelogs/1002.txt index 6c6dc761a..23be04e80 100644 --- a/fastlane/metadata/android/de/changelogs/1002.txt +++ b/fastlane/metadata/android/de/changelogs/1002.txt @@ -1,4 +1,4 @@ Behoben: YouTube spielt keinen Stream ab. -Diese Version behebt nur den dringendsten Fehler, der das Laden von YouTube-Videodetails verhindert. +Diese Version behebt nur den dringenden Fehler, der das Laden von YouTube-Videodetails verhindert. Wir sind uns bewusst, dass es andere Probleme gibt, und wir werden bald eine separate Version erstellen, um sie zu lösen. diff --git a/fastlane/metadata/android/de/changelogs/1006.txt b/fastlane/metadata/android/de/changelogs/1006.txt new file mode 100644 index 000000000..1a76b6f0e --- /dev/null +++ b/fastlane/metadata/android/de/changelogs/1006.txt @@ -0,0 +1,13 @@ +# Verbesserungen +Aktuellen Player beim Klick auf Zeitstempel beibehalten +Wiederherstellen ausstehender Downloadaufträge +Downloads löschen, ohne gleichzeitiges Löschen der Datei +Overlay-Berechtigung: Erklärendes Dialogfeld für Android > R +Unterstützung von on.soundcloud-Links +Viele kleine Verbesserungen und Optimierungen + +# Behoben +Kurzformatierung für Android-Versionen unter 7 +Geisterbenachrichtigungen +SRT-Untertiteldateien +Zahlreiche Abstürze diff --git a/fastlane/metadata/android/de/changelogs/1007.txt b/fastlane/metadata/android/de/changelogs/1007.txt new file mode 100644 index 000000000..43623578f --- /dev/null +++ b/fastlane/metadata/android/de/changelogs/1007.txt @@ -0,0 +1 @@ +Behoben, dass YouTube keinen Stream abspielte diff --git a/fastlane/metadata/android/de/changelogs/63.txt b/fastlane/metadata/android/de/changelogs/63.txt index 3ccc56bc0..7ae7873fb 100644 --- a/fastlane/metadata/android/de/changelogs/63.txt +++ b/fastlane/metadata/android/de/changelogs/63.txt @@ -4,5 +4,5 @@ - Kleine Codeverbesserungen #1375 - Alles über DSGVO hinzugefügt #1420 -### Repariert +### Behoben - Downloader: Absturz beim Laden unvollendeter Downloads von .giga-Dateien behoben #1407 diff --git a/fastlane/metadata/android/de/changelogs/68.txt b/fastlane/metadata/android/de/changelogs/68.txt index f700b3d26..9d37a92fc 100644 --- a/fastlane/metadata/android/de/changelogs/68.txt +++ b/fastlane/metadata/android/de/changelogs/68.txt @@ -1,12 +1,12 @@ # Änderungen von v0.14.1 -### Fixed +### Behoben - nicht entschlüsselt Video url #1659 - Beschreibungs Link nicht extrahierbar #1657 # Änderungen von v0.14.0 -### New +### Neu - Neues Schubladendesign #1461 - Neue anpassbare Titelseite #1461 @@ -14,6 +14,6 @@ - Reworked Gesture Controls #1604 - Neue Möglichkeit, den Pop-up-Player #1597 zu schließen -### Fixed +### Behoben - Fehler beheben, wenn die Anzahl der Abonnements nicht verfügbar ist. Schließt #1649. - Zeigen Sie "Abonnentenzählung nicht verfügbar" in diesen Fällen. diff --git a/fastlane/metadata/android/de/changelogs/69.txt b/fastlane/metadata/android/de/changelogs/69.txt index 8802508a3..3e8cb3a6e 100644 --- a/fastlane/metadata/android/de/changelogs/69.txt +++ b/fastlane/metadata/android/de/changelogs/69.txt @@ -1,14 +1,15 @@ -### New -- Long-tap Löschen & Teilen in Abonnements #1516 -- Tablet UI & Rasterlistenlayout #1617 +### Neu +- Langes Tippen zum Löschen/Teilen in Abonnements #1516 +- Tablet-UI und Rasterlistenlayout #1617 ### Verbesserungen -- Speichern und Nachladen des zuletzt verwendeten Seitenverhältnisses #1748 -- Separate Einstellungen für Lautstärke & Helligkeitsgesten #1644 +- Speichern/Neuladen des zuletzt verwendeten Seitenverhältnisses #1748 +- Separate Einstellungen für Lautstärke-/Helligkeitsgesten #1644 +- Unterstützung für Lokalisierung #1792 -### Fixes +### Fehlerbehebungen - Anzahl der Abonnements -- Foreground Service Erlaubnis für API 28+ Geräte #1830 hinzugefügt +- Vordergrund-Dienstberechtigung für Geräte mit API 28+ hinzugefügt #1830 -### Known Bugs -- Wiedergabe kann nicht auf Android P gespeichert werden +### Bekannte Fehler +- Wiedergabestatus wird unter Android P nicht gespeichert diff --git a/fastlane/metadata/android/de/changelogs/70.txt b/fastlane/metadata/android/de/changelogs/70.txt index 59a09b210..b31f83720 100644 --- a/fastlane/metadata/android/de/changelogs/70.txt +++ b/fastlane/metadata/android/de/changelogs/70.txt @@ -5,6 +5,6 @@ ACHTUNG: Diese Version ist wahrscheinlich ein Bugfest. * Drop-Unterstützung für Android 4.1 - 4.3 #1884 * Streams aus der aktuellen Warteschlange entfernt, indem sie nach rechts swipen #1915 -### Fixed +### Behoben * Crash mit Standard-Auflösung eingestellt auf beste und begrenzte mobile Datenauflösung #1835 * Pop-up-Spieler-Absturz behoben #1874 diff --git a/fastlane/metadata/android/de/changelogs/71.txt b/fastlane/metadata/android/de/changelogs/71.txt index 0132de3c3..86d1d52d9 100644 --- a/fastlane/metadata/android/de/changelogs/71.txt +++ b/fastlane/metadata/android/de/changelogs/71.txt @@ -1,8 +1,10 @@ ### Verbesserungen -* App-Update-Benachrichtigung für GitHub build hinzufügen (#1608 von @krtkush) -* Verschiedene Verbesserungen des Downloaders (#1944 von @kapodamy): -* Fügen Sie fehlende weiße Icons hinzu und verwenden Sie hardcored Weg, um die Icon Farben zu ändern -* neue MPEG-4 muxer fixieren nicht-synchrone Video- und Audiostreams (#2039) +* Benachrichtigung über App-Updates für GitHub-Build (#1608 von @krtkush) +* Verschiedene Verbesserungen am Downloader (#1944 von @kapodamy): + * Weiße Symbole und Hardcoded-Methode zum Ändern der Symbolfarben + * Überprüfung, ob der Iterator initialisiert ist (behebt #2031) + * Erlaubt erneute Downloads mit dem Fehler „Nachbearbeitung fehlgeschlagen“ im neuen Muxer + * Neuer MPEG-4-Muxer (#2039) -### Fixed -* YouTube Live-Streams spielen nach kurzer Zeit (#1996 von @yausername) +### Behoben +* YouTube-Livestreams werden nicht abgespielt (#1996 von @yausername) diff --git a/fastlane/metadata/android/de/changelogs/730.txt b/fastlane/metadata/android/de/changelogs/730.txt index 12c5ffb16..dc534fea2 100644 --- a/fastlane/metadata/android/de/changelogs/730.txt +++ b/fastlane/metadata/android/de/changelogs/730.txt @@ -1,2 +1,2 @@ # Behoben -- erneuter Hotfix des Entschlüsselungsfunktionsfehlers. +- Fehler bei der Entschlüsselungsfunktion erneut behoben. diff --git a/fastlane/metadata/android/de/changelogs/740.txt b/fastlane/metadata/android/de/changelogs/740.txt index 0d28a157a..063e5a3c7 100644 --- a/fastlane/metadata/android/de/changelogs/740.txt +++ b/fastlane/metadata/android/de/changelogs/740.txt @@ -1,12 +1,12 @@

Verbesserungen

    -
  • Make Links in Kommentare klickbar, erhöhen Textgröße
  • -
  • seek zum Klicken von Zeitstempel-Links in Kommentare
  • -
  • Beliebte Registerkarte basierend auf kürzlich ausgewähltem Zustand anzeigen
  • -
  • Add-Unterstützung für Invidious links
  • +
  • Links in Kommentaren anklickbar machen, Textgröße erhöhen
  • +
  • Bei Anklicken von Zeitstempel-Links in Kommentaren suchen
  • +
  • Bevorzugte Registerkarte basierend auf zuletzt ausgewähltem Status anzeigen
  • +
  • Unterstützung für Invidious-Links
-

Fixed

+

Behoben

    -
  • fixed scroll w/kommentare und verwandten Streams deaktiviert
  • -
  • fixiert CheckForNewAppVersionTask wird ausgeführt, wenn es sollten't
  • +
  • Scrollen mit deaktivierten Kommentaren und verwandten Streams behoben
  • +
  • CheckForNewAppVersionTask wird nicht mehr ausgeführt, wenn es nicht sollte
diff --git a/fastlane/metadata/android/de/changelogs/750.txt b/fastlane/metadata/android/de/changelogs/750.txt index 78a25282a..5dd4766df 100644 --- a/fastlane/metadata/android/de/changelogs/750.txt +++ b/fastlane/metadata/android/de/changelogs/750.txt @@ -1,15 +1,15 @@ Neu -Playback Lebenslauf #2288 -• Resume Streams, wo Sie letztes Mal aufgehört haben -Downloader Verbesserungen #2149 - +Wiedergabe fortsetzen #2288 +Downloader-Verbesserungen #2149 Verbessert -• Gemaketten entfernen #2295 -• Handle (auto)Rotationsänderungen während des Aktivitätszyklus #2444 +• GEMA-Strings entfernt #2295 +• (Automatische) Rotationsänderungen #2444 +• Menüs bei langem Drücken #2368 Behoben -• Fixed Downloads bei 99,9% #2440 -• Aktualisieren der Spielwarteschlange Metadaten #2453 -• [SoundCloud] Fester Absturz beim Laden von Wiedergabelisten TeamNewPipe/NewPipeExtractor#170 -• [YouTube] Feste Dauer kann nicht paresd TeamNewPipe/NewPipeExtractor#177 +• Untertitelnamenanzeige #2394 +• Absturz, wenn die Überprüfung auf App-Updates fehlschlägt (GitHub-Version) #2423 +• Downloads, die bei 99,9 % hängen bleiben #2440 +• Metadaten der Wiedergabeliste aktualisieren #2453 +• [SoundCloud] Absturz beim Laden von Wiedergabelisten TeamNewPipe/NewPipeExtractor#170 diff --git a/fastlane/metadata/android/de/changelogs/952.txt b/fastlane/metadata/android/de/changelogs/952.txt index 309b02b09..33e1cbc23 100644 --- a/fastlane/metadata/android/de/changelogs/952.txt +++ b/fastlane/metadata/android/de/changelogs/952.txt @@ -1,7 +1,7 @@ -Verbesserungen +Verbessert • Autoplay ist nun für alle Services verfügbar (nicht nur für YouTube) -Reparaturen +Behoben • Verwandte Streams wurden behoben, indem die neuen Streamfortsetzungen von YouTube unterstützt werden • Altersbeschränkte Videos repariert • [Android TV] Überlagerung von Fokus-Hervorhebungen behoben diff --git a/fastlane/metadata/android/de/changelogs/972.txt b/fastlane/metadata/android/de/changelogs/972.txt index c05cf182f..0d5be70e8 100644 --- a/fastlane/metadata/android/de/changelogs/972.txt +++ b/fastlane/metadata/android/de/changelogs/972.txt @@ -1,11 +1,14 @@ Neu -Erkennung von Zeitstempeln und Hashtags in der Beschreibung -Manuelle Einstellung des Tablet-Modus hinzugefügt -Abgespielte Elemente können nun in einem Feed ausgeblendet werden +Erkennung von Zeitstempeln/Hashtags in der Beschreibung +Manuelle Einstellung des Tablet-Modus +Abgespielte Elemente können nun im Feed ausgeblendet werden Verbessert -Korrekte Unterstützung des Storage Access Framework -Bessere Fehlerbehandlung von nicht verfügbaren und beendeten Kanälen -Das Android Share Sheet für Android >=10 Nutzer zeigt nun den Titel des Inhalts an. -Aktualisierte Invidious Instanzen und Unterstützung von Piped Links. -... +Korrekte Unterstützung des Storage-Access-Frameworks +Bessere Fehlerbehandlung von nicht verfügbaren und geschlossenen Kanälen +Das Android-Freigabefenster für Nutzer von Android 10+ zeigt nun den Titel des Inhalts an +Invidious-Instanzen aktualisiert und Unterstützung von Piped-Links + +Behoben +[YouTube] Altersbeschränkte Inhalte +… diff --git a/fastlane/metadata/android/de/changelogs/986.txt b/fastlane/metadata/android/de/changelogs/986.txt index 044365eb8..a1bc3217a 100644 --- a/fastlane/metadata/android/de/changelogs/986.txt +++ b/fastlane/metadata/android/de/changelogs/986.txt @@ -1,16 +1,15 @@ -Neu: +Neu • Benachrichtigungen für neue Streams • Nahtloser Übergang zwischen Hintergrund- und Videoplayer -• Änderung der Tonhöhe um Halbtöne +• Ändern der Tonhöhe um Halbtöne • Warteschlange des Hauptplayers an Wiedergabeliste anfügen -Verbessert: -• Geschwindigkeit/Tonhöhenschrittgröße speichern +Verbessert +• Speichern der Geschwindigkeit/Tonhöhenschrittweite • Anfängliche lange Videoplayer-Pufferung verringert • Player-UI für Android TV -• Löschbestätigung für alle heruntergeladenen Dateien +• Löschbestätigung aller heruntergeladenen Dateien -Behoben: -• Medienschaltfläche blendet die Steuerelemente des Players nicht aus -• Rücksetzung der Wiedergabe bei Änderung des Playertyps -• Drehung des Wiedergabelisten-Dialogs +Behoben +• Medienschaltfläche blendet Player-Steuerelemente nicht aus +• … diff --git a/fastlane/metadata/android/de/changelogs/987.txt b/fastlane/metadata/android/de/changelogs/987.txt index f7bc9bd80..a03048973 100644 --- a/fastlane/metadata/android/de/changelogs/987.txt +++ b/fastlane/metadata/android/de/changelogs/987.txt @@ -1,12 +1,12 @@ -Neu: -• Unterstützung anderer Übertragungsmethoden als progressives HTTP: schnellere Ladezeit der Wiedergabe, Korrekturen für PeerTube und SoundCloud, Wiedergabe von kürzlich beendeten YouTube-Livestreams -• Schaltfläche um entfernte Wiedergabeliste einer lokalen Wiedergabeliste hinzuzufügen -• Bildvorschau im Android 10+ Teilen-Dialog +Neu +• Unterstützung anderer Übertragungsmethoden als progressives HTTP: schnellere Ladezeit bei Wiedergabe, Fehlerbehebungen für PeerTube/SoundCloud, Wiedergabe kürzlich beendeter YouTube-Livestreams +• Schaltfläche, um Remote-Wiedergabeliste einer Lokalen hinzuzufügen +• Bildvorschau im Teilen-Dialog von Android 10+ -Verbessert: +Verbessert • Wiedergabewerte-Dialog -• Import/Export-Schaltflächen für Abonnements in das Drei-Punkte-Menü verschoben +• Import/Export-Schaltflächen für Abos in Drei-Punkte-Menü verschoben -Behoben: -• Entfernung von vollständig angesehenen Videos aus der Wiedergabeliste -• Freigabemenü-Design und „Zur Wiedergabeliste hinzufügen“-Eintrag +Behoben +• Entfernen vollständig angesehener Videos aus Wiedergabeliste +• … diff --git a/fastlane/metadata/android/de/changelogs/997.txt b/fastlane/metadata/android/de/changelogs/997.txt index f55e72b05..fbb5727d8 100644 --- a/fastlane/metadata/android/de/changelogs/997.txt +++ b/fastlane/metadata/android/de/changelogs/997.txt @@ -1,17 +1,16 @@ Neu • Antwort auf Kommentar • Wiedergabelisten umordnen -• Wiedergabelisten-Beschreibung und -Dauer +• Wiedergabelisten-Beschreibung/-Dauer • Rücksetzen der Einstellungen Verbessert -• [Android 13+] Wiederherstellen benutzerdef. Benachrichtigungsaktionen -• Zustimmung zur Update-Prüfung -• Während Pufferung Abspielen/Pause über Benachrichtigung -• Neuordnung einiger Einstellungen +• [Android 13+] Wiederherstellen benutzerd. Benachrichtigungsaktionen +• Zustimmung zur Updateprüfung +• Wiedergabe/Pause von Benachrichtigungen während Pufferung +• Neuanordnung einiger Einstellungen Behoben -• [YouTube] Kommentare wurden nicht geladen, weitere Korrekturen und Verbesserungen +• [YouTube] Kommentare wurden nicht geladen, weitere Fehlerbehebungen/Verbesserungen • Sicherheitslücke beim Einstellungsimport und Umstellung auf JSON -• Verschiedene Download-Korrekturen -• Suchtext gekürzt +• … diff --git a/fastlane/metadata/android/de/changelogs/999.txt b/fastlane/metadata/android/de/changelogs/999.txt index 51cf80d3e..059b4e081 100644 --- a/fastlane/metadata/android/de/changelogs/999.txt +++ b/fastlane/metadata/android/de/changelogs/999.txt @@ -4,9 +4,9 @@ Neu • [SoundCloud] Unterstützung für on.soundcloud.com-URLs hinzugefügt Verbessert -• [Bandcamp]Anzeige zusätzlicher Informationen im Radio-Kiosk +• [Bandcamp] Anzeige zusätzlicher Informationen im Radio-Kiosk Behoben -• [YouTube] Behebung gelegentlicher HTTP 403-Fehler am Anfang oder in der Mitte von Videos +• [YouTube] Behebung gelegentlicher HTTP-403-Fehler am Anfang oder in der Mitte von Videos • [YouTube] Extrahieren von Avataren und Banner aus mehr Kanal-Header-Typen • [Bandcamp] Verschiedene Fehler behoben und HTTPS wird stets verwendet diff --git a/fastlane/metadata/android/de/short_description.txt b/fastlane/metadata/android/de/short_description.txt index ec47872eb..6afdb21ea 100644 --- a/fastlane/metadata/android/de/short_description.txt +++ b/fastlane/metadata/android/de/short_description.txt @@ -1 +1 @@ -Eine freie, leichte YouTube-App für Android. +Eine kostenlose, leichte YouTube-App für Android. diff --git a/fastlane/metadata/android/el/changelogs/1004.txt b/fastlane/metadata/android/el/changelogs/1004.txt new file mode 100644 index 000000000..d00799cfd --- /dev/null +++ b/fastlane/metadata/android/el/changelogs/1004.txt @@ -0,0 +1,3 @@ +Αυτή η έκδοση διορθώνει το πρόβλημα που παρουσίαζε το YouTube μόνο σε ροή 360p. + +Σημειώστε ότι η λύση που χρησιμοποιείται σε αυτήν την έκδοση είναι πιθανώς προσωρινή και μακροπρόθεσμα πρέπει να εφαρμοστεί το πρωτόκολλο βίντεο SABR, αλλά τα μέλη του TeamNewPipe είναι απασχολημένα αυτήν τη στιγμή, επομένως οποιαδήποτε βοήθεια θα εκτιμηθεί ιδιαίτερα! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/el/changelogs/1005.txt b/fastlane/metadata/android/el/changelogs/1005.txt new file mode 100644 index 000000000..286239c25 --- /dev/null +++ b/fastlane/metadata/android/el/changelogs/1005.txt @@ -0,0 +1,17 @@ +Νέο +• Προσθήκη υποστήριξης για το Android Auto +• Επιτρέπεται ο ορισμός ομάδων ροών ως καρτέλες κύριας οθόνης +• [YouTube] Κοινή χρήση ως προσωρινή λίστα αναπαραγωγής +• [SoundCloud] Καρτέλα καναλιού "Μου αρέσει" + +Βελτιωμένη +• Καλύτερες υποδείξεις γραμμής αναζήτησης +• Εμφάνιση ημερομηνίας λήψης στις Λήψεις +• Χρήση γλώσσας Android 13 ανά εφαρμογή + +Διορθώθηκε +• Διόρθωση σπασμένων χρωμάτων κειμένου σε σκοτεινή λειτουργία +• [YouTube] Διόρθωση λιστών αναπαραγωγής που δεν φόρτωναν περισσότερα από 100 στοιχεία +• [YouTube] Διόρθωση προτεινόμενων βίντεο που λείπουν +• Διόρθωση σφαλμάτων στην προβολή λίστας ιστορικού +• Διόρθωση χρονικών σημάνσεων στις απαντήσεις σχολίων diff --git a/fastlane/metadata/android/el/changelogs/70.txt b/fastlane/metadata/android/el/changelogs/70.txt new file mode 100644 index 000000000..7d1be05ff --- /dev/null +++ b/fastlane/metadata/android/el/changelogs/70.txt @@ -0,0 +1,25 @@ +ΠΡΟΣΟΧΗ: Αυτή η έκδοση πιθανότατα έχει πολλά bugs, όπως και η προηγούμενη. Ωστόσο, λόγω του πλήρους τερματισμού λειτουργίας από την έκδοση 17, μια προβληματική έκδοση είναι καλύτερη από καμία έκδοση. Σωστά; ¯\_(ツ)_/¯ + +### Βελτιώσεις +* τα ληφθέντα αρχεία μπορούν πλέον να ανοιχτούν με ένα κλικ #1879 +* κατάργηση υποστήριξης για android 4.1 - 4.3 #1884 +* κατάργηση παλιού προγράμματος αναπαραγωγής #1884 +* κατάργηση ροών από την τρέχουσα ουρά αναπαραγωγής σύροντάς τες προς τα δεξιά #1915 +* κατάργηση της αυτόματης ροής σε ουρά όταν μια νέα ροή μπαίνει στην ουρά χειροκίνητα #1878 +* Επεξεργασία μετά την επεξεργασία για λήψεις και εφαρμογή ελλειπουσών λειτουργιών #1759 από @kapodamy +* Υποδομή μετεπεξεργασίας +* Σωστός χειρισμός σφαλμάτων "υποδομής" (για πρόγραμμα λήψης) +* Ουρά αντί για πολλαπλές λήψεις +* Μετακίνηση σειριοποιημένων εκκρεμών λήψεων (αρχεία `.giga`) στα δεδομένα εφαρμογής +* Εφαρμογή μέγιστης επανάληψης λήψης +* Σωστή παύση λήψης πολλαπλών νημάτων +* Διακοπή λήψεων κατά τη μετάβαση σε δίκτυο κινητής τηλεφωνίας (δεν λειτουργεί ποτέ, δείτε το 2ο σημείο) +* Αποθήκευση του αριθμού νημάτων για τις επόμενες λήψεις +* Πολλά Διορθώθηκαν οι ασυνέπειες + +### Διορθώθηκε +* Διορθώθηκε το σφάλμα με την προεπιλεγμένη ανάλυση να έχει οριστεί στην καλύτερη και την περιορισμένη ανάλυση δεδομένων κινητής τηλεφωνίας #1835 +* διορθώθηκε το σφάλμα του αναδυόμενου προγράμματος αναπαραγωγής #1874 +* NPE κατά την προσπάθεια ανοίγματος του προγράμματος αναπαραγωγής φόντου #1901 +* Διορθώθηκε η εισαγωγή νέων ροών όταν είναι ενεργοποιημένη η αυτόματη ουρά #1878 +* Διορθώθηκε το πρόβλημα αποκρυπτογράφησης του shuttown diff --git a/fastlane/metadata/android/el/changelogs/71.txt b/fastlane/metadata/android/el/changelogs/71.txt new file mode 100644 index 000000000..30163bcb0 --- /dev/null +++ b/fastlane/metadata/android/el/changelogs/71.txt @@ -0,0 +1,10 @@ +### Βελτιώσεις +* Προσθήκη ειδοποίησης ενημέρωσης εφαρμογής για την έκδοση GitHub (#1608 από @krtkush) +* Διάφορες βελτιώσεις στο πρόγραμμα λήψης (#1944 από @kapodamy): +* προσθήκη λευκών εικονιδίων που λείπουν και χρήση σκληροπυρηνικής μεθόδου για αλλαγή των χρωμάτων των εικονιδίων +* έλεγχος εάν ο επαναλήπτης έχει αρχικοποιηθεί (διορθώσεις #2031) +* δυνατότητα επανάληψης λήψεων με σφάλμα "αποτυχία μετα-επεξεργασίας" στον νέο πολυπλέκτη +* νέος πολυπλέκτης MPEG-4 που διορθώνει μη σύγχρονες ροές βίντεο και ήχου (#2039) + +### Διορθώθηκε +* Οι ζωντανές ροές YouTube σταματούν να αναπαράγονται μετά από σύντομο χρονικό διάστημα (#1996 από @yausername) diff --git a/fastlane/metadata/android/en-US/changelogs/1006.txt b/fastlane/metadata/android/en-US/changelogs/1006.txt new file mode 100644 index 000000000..15b974b97 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/1006.txt @@ -0,0 +1,16 @@ +# Improved +Keep current player when clicking on timestamps +Try to recover pending download missions when possible +Add option to delete a download without also deleting file +Overlay Permission: display explanatory dialog for Android > R +Support on.soundcloud link opening +A lot of small improvements and optimizations + +# Fixed +Fix short count formatting for Android versions below 7 +Fix ghost notifications +Fixes for SRT subtitle files +Fixed tons of crashes + +# Development +Internal code modernization \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/1007.txt b/fastlane/metadata/android/en-US/changelogs/1007.txt new file mode 100644 index 000000000..f439ee1de --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/1007.txt @@ -0,0 +1,11 @@ +This hotfix release fixes the "Content not available" error: YouTube videos can now be played again! + +It also fixes a few bugs introduced in 0.28.1: +• Playlist items dragging to only neighbor positions +• Title/comments flickering between current and previous video +• "Start main player in fullscreen" option not working + +Other improvements: +• [YouTube] Allow rewinding livestreams up to 4 hours again +• Don't load livestream video when playing in background +• New UI for "Remove watched" \ No newline at end of file diff --git a/fastlane/metadata/android/en_GB/changelogs/1005.txt b/fastlane/metadata/android/en_GB/changelogs/1005.txt new file mode 100644 index 000000000..7d76f491a --- /dev/null +++ b/fastlane/metadata/android/en_GB/changelogs/1005.txt @@ -0,0 +1,17 @@ +New +• Add support for Android Auto +• Allow setting feed groups as main screen tabs +• [YouTube] Share as temporary playlist +• [SoundCloud] Likes channel tab + +Improved +• Better search bar hints +• Show download date in Downloads +• Use Android 13 per-app language + +Fixed +• Fix broken text colours in dark mode +• [YouTube] Fix playlists not loading more than 100 items +• [YouTube] Fix missing recommended videos +• Fix crashes in History list view +• Fix timestamps in comment replies diff --git a/fastlane/metadata/android/en_GB/changelogs/63.txt b/fastlane/metadata/android/en_GB/changelogs/63.txt new file mode 100644 index 000000000..9044e96bf --- /dev/null +++ b/fastlane/metadata/android/en_GB/changelogs/63.txt @@ -0,0 +1,8 @@ +### Improvements +- Import/export settings #1333 +- Reduce overdraw (performance improvement) #1371 +- Small code improvements #1375 +- Add everything about GDPR #1420 + +### Fixed +- Downloader: Fix crash on loading unfinished downloads from .giga files #1407 diff --git a/fastlane/metadata/android/en_GB/changelogs/64.txt b/fastlane/metadata/android/en_GB/changelogs/64.txt new file mode 100644 index 000000000..d2ab61203 --- /dev/null +++ b/fastlane/metadata/android/en_GB/changelogs/64.txt @@ -0,0 +1,8 @@ +### Improvements +- Added the ability to limit video quality if using mobile data. #1339 +- Remember brightness for the session #1442 +- Improve download performance for weaker CPUs #1431 +- add (working) support for media session #1433 + +### Fix +- Fix crash on opening downloads (fix now available for release builds) #1441 diff --git a/fastlane/metadata/android/es/changelogs/1005.txt b/fastlane/metadata/android/es/changelogs/1005.txt new file mode 100644 index 000000000..64e8353d4 --- /dev/null +++ b/fastlane/metadata/android/es/changelogs/1005.txt @@ -0,0 +1,17 @@ +Nuevo +Añadido soporte a Android Auto +Pemitir configurar grupos de feeds como pestaña en la pantalla principal +[YouTube] Compartir como playlist temporal +[SoundCloud] Pestaña de likes en el canal + +Mejoras +Mejores sugerencias en la barra de busqueda +Mostrar la fecha de descargas en Descargas +Usar el idioma por aplicacion en Android 13 + +Arreglos +Arreglado texto de colores rotos en el modo oscuro +[YouTube] Solucionado el problema que las playlist con mas de 100 elementos no cargaban +[YouTube] Solucionado problema de no mostrar los videos recomendados +Solucionado cierres inesperados en vista de listas en Historial +Arreglado marcas de tiempo en respuestas de comentarios diff --git a/fastlane/metadata/android/es/changelogs/1006.txt b/fastlane/metadata/android/es/changelogs/1006.txt new file mode 100644 index 000000000..b6b20370e --- /dev/null +++ b/fastlane/metadata/android/es/changelogs/1006.txt @@ -0,0 +1,16 @@ +#Mejoras +Mantener el reproductor actual al hacer clic en marcas de tiempo. +Intentar recuperar descargas pendientes cuando sea posible. +Añadir opción para eliminar una descarga sin borrar el archivo. +Permiso de superposición: mostrar diálogo explicativo en Android 11 y superior. +Soporte para abrir enlaces on.soundcloud. +Muchas pequeñas mejoras y optimizaciones. + +#Corregido +Formato corto de conteos en Android inferior a 7. +Notificaciones fantasma. +Problemas con archivos de subtítulos SRT. +Numerosos crashes. + +#Desarrollo +Modernización interna del código. diff --git a/fastlane/metadata/android/es/changelogs/1007.txt b/fastlane/metadata/android/es/changelogs/1007.txt new file mode 100644 index 000000000..80b4efa55 --- /dev/null +++ b/fastlane/metadata/android/es/changelogs/1007.txt @@ -0,0 +1 @@ +Arreglo en YouTube no reproduciendo flujos diff --git a/fastlane/metadata/android/eu/changelogs/1000.txt b/fastlane/metadata/android/eu/changelogs/1000.txt new file mode 100644 index 000000000..3fd477227 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1000.txt @@ -0,0 +1,13 @@ +Hobetua +• Zerrenda deskribapena klikagarria +• [PeerTube] subscribeto.me estekak auto-kudeatu +• Historia elementu bakarra hasi + +Konpondua +• RSS botoien ikusgarritasuna +• Bilaketa aurrebista matxurak +• Miniaturarik gabeko zerrenda +• Deskarga elkarrizketa irtetea +• Erlazionatutako elementuen leihoa +• Zerrendan gehitzeko ordena +• Laster-marken diseinua diff --git a/fastlane/metadata/android/eu/changelogs/1001.txt b/fastlane/metadata/android/eu/changelogs/1001.txt new file mode 100644 index 000000000..1658a021f --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1001.txt @@ -0,0 +1,6 @@ +Hobetua +• Onartu beti jokalarien jakinarazpenen hobespenak aldatzea Android 13+-n + +Konpondua +• Konpondu datu-basea/harpidetzak esportatzeak lehendik zegoen fitxategi bat ez mozten zuelako, eta horrek esportazio bat hondatzea eragin zezakeelako +• Denbora-zigilu batean klik egitean jokalaria hasieratik jarraitzea konpondu diff --git a/fastlane/metadata/android/eu/changelogs/1002.txt b/fastlane/metadata/android/eu/changelogs/1002.txt new file mode 100644 index 000000000..b1302f9ee --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1002.txt @@ -0,0 +1,4 @@ +Konpondu da YouTube-k ez zuela inolako stream-ik erreproduzitzen. + +Bertsio honek YouTube bideoen xehetasunak kargatzea eragozten duen errore larriena baino ez du konpontzen. +Badakigu beste arazo batzuk ere badaudela, eta laster beste argitalpen bat kaleratuko dugu horiek konpontzeko. diff --git a/fastlane/metadata/android/eu/changelogs/1003.txt b/fastlane/metadata/android/eu/changelogs/1003.txt new file mode 100644 index 000000000..e9c0ddb43 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1003.txt @@ -0,0 +1,6 @@ +YouTube-ko akatsak zuzentzen dituen zuzenketa-bertsio bat da hau: +• [YouTube] Bideoen informaziorik kargatzen ez zen arazoa konpondu, bideoak erreproduzitzean HTTP 403 erroreak konpondu eta adin-murrizketak dituzten bideo batzuen erreprodukzioa leheneratu +• Konpondu aldatzen ez ziren azpitituluen tamainak +• Konpondu informazioa bi aldiz deskargatzea erreprodukzio bat irekitzean +• [Soundcloud] Kendu erreproduziezinak diren DRM bidez babestutako erreprodukzioak +• Itzulpen eguneratuak diff --git a/fastlane/metadata/android/eu/changelogs/1004.txt b/fastlane/metadata/android/eu/changelogs/1004.txt new file mode 100644 index 000000000..e85b656ae --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1004.txt @@ -0,0 +1,3 @@ +Bertsio honek YouTube-k 360p-ko erreprodukzioa soilik eskaintzen zuen arazoa konpontzen du. + +Kontuan izan bertsio honetan erabilitako irtenbidea ziurrenik aldi baterakoa izango dela, eta epe luzera SABR bideo protokoloa inplementatu beharko dela, baina TeamNewPipe-ko kideak lanpetuta daude une honetan, beraz, edozein laguntza eskertzekoa izango litzateke! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/eu/changelogs/1005.txt b/fastlane/metadata/android/eu/changelogs/1005.txt new file mode 100644 index 000000000..8084d70f2 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1005.txt @@ -0,0 +1,17 @@ +Berria +• Android Auto laguntza +• Jario-taldeak fitxa gisa +• [YouTube] Partekatu zerrenda aldi baterako +• [SoundCloud] Atsegin dut fitxa + +Hobetua +• Bilaketa aholku hobeak +• Deskarga data erakutsi +• Android 13 hizkuntza + +Konpondua +• Testu-koloreak modu ilunean +• [YouTube] 100+ elementuko zerrendak +• [YouTube] Gomendatutako bideoak +• Historia ikuspegiko hutsegiteak +• Iruzkinen denbora-zigiluak diff --git a/fastlane/metadata/android/eu/changelogs/1006.txt b/fastlane/metadata/android/eu/changelogs/1006.txt new file mode 100644 index 000000000..89641bf2d --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1006.txt @@ -0,0 +1,16 @@ +# Hobetua +Erreproduzitzailea denbora-zigiluetan mantendu +Deskarga misioak berreskuratu +Ezabatu deskarga fitxategia gorde +Gainjartze baimena Android > R +.soundcloud estekak ireki +Hobekuntza txikiak + +# Konpondua +Android <7 zenbaketa laburrak +Mamu jakinarazpenak +SRT azpititulu fitxategiak +Istripu tona + +# Garapena +Kodearen modernizazioa diff --git a/fastlane/metadata/android/eu/changelogs/1007.txt b/fastlane/metadata/android/eu/changelogs/1007.txt new file mode 100644 index 000000000..68d0be7fc --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/1007.txt @@ -0,0 +1 @@ +Konpondu da YouTube-k ez zuela inolako erreprodukziorik erreproduzitzen diff --git a/fastlane/metadata/android/eu/changelogs/66.txt b/fastlane/metadata/android/eu/changelogs/66.txt new file mode 100644 index 000000000..52d930795 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/66.txt @@ -0,0 +1,22 @@ +# 0.13.7 bertsioaren aldaketa-erregistroa +### Konpondua +- Ordenazio-iragazkiak + +# 0.13.6 bertsioaren aldaketa-erregistroa +### Hobekuntzak +- Hanburgesa animazioa desgaitu +- Deskargak ezabaketa desegin +- Partekatu menuan deskarga +- Jokalaria minimizatu +- ExoPlayer 2.8.2 +- Abiadura kontrolak hobetuak +- Isilune saltoa +- Metadatu egitura berria +- UI konponketak + +### Konponketak + +- Bideoaren informazio diseinua +- Ikusi historia eguneraketa +- Pantaila denbora-muga leiho-moduan +- Jokalari NPE konpondua diff --git a/fastlane/metadata/android/eu/changelogs/800.txt b/fastlane/metadata/android/eu/changelogs/800.txt new file mode 100644 index 000000000..15457364c --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/800.txt @@ -0,0 +1,24 @@ +Berria +• PeerTube euskarria P2P gabe + ◦ Instantziak gehitu + ◦ PeerTube instantziak ikusi eta deskargatu +Deskargak + ◦ Deskarga ETA kalkulatu + ◦ Opus ogg gisa + ◦ Estekak berreskuratu + +Hobetua +• Fitxen errendimendua eta lokalizazioa +• Lokalizazio berriak +• Nabigazio barra beltza + +Konpondua +• Popup hatz-mugimendua +• Igotzailerik gabeko zerrendak +• TLS Android 4.4 +• [SoundCloud] Client_id +• Audio-jarioa + +Garapena +• ExoPlayer 2.10.8 +• Gradle 3.5.1 eta Kotlin onartu diff --git a/fastlane/metadata/android/eu/changelogs/810.txt b/fastlane/metadata/android/eu/changelogs/810.txt new file mode 100644 index 000000000..464b91958 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/810.txt @@ -0,0 +1,19 @@ +Berria +• Miniatura blokeatutako pantailan + +Hobetua +• Zerrenda ilaran botoia +• Fitxak korritzeko moduan +• Jakinarazpen miniatura mugatu +• Irudi zerrenda hutsentzat +• *.opus luzapena erabili +• Deskarga historia ezabatu +• [YouTube] /c/ estekak + +Konpondua +• Partekatzeko arazoak +• Erreproduzitzaile sarbidea +• Bilaketa orrialdekatzea +• [YouTube] NPE nulua +• [YouTube] invidio.us iruzkinak +• [SoundCloud] bezeroaren_id diff --git a/fastlane/metadata/android/eu/changelogs/820.txt b/fastlane/metadata/android/eu/changelogs/820.txt new file mode 100644 index 000000000..54d14152a --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/820.txt @@ -0,0 +1 @@ +YouTube erabilezin bihurtzen zuen funtzio-izenaren regex deszifratzea konpondu da. diff --git a/fastlane/metadata/android/eu/changelogs/830.txt b/fastlane/metadata/android/eu/changelogs/830.txt new file mode 100644 index 000000000..d699a9558 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/830.txt @@ -0,0 +1 @@ +SoundCloud client_id eguneratu da SoundCloud-eko arazoak konpontzeko. diff --git a/fastlane/metadata/android/eu/changelogs/840.txt b/fastlane/metadata/android/eu/changelogs/840.txt new file mode 100644 index 000000000..a17af893c --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/840.txt @@ -0,0 +1,21 @@ +Berria +• Hizkuntza hautatzailea +• Kodira bidali botoia +• Iruzkinak kopiatu + +Hobetua +• ReCaptcha eta cookieak +• Puntu-menua kendu +• Bistaratu baimena eskatu +• Zerrenda izena aldatu +• PeerTube hobekuntzak + +Konpondua +• Erreproduzitzailea abiarazi minimizatuta +• Keinu distira +• .srt lerro-jauziak +• SD txartel deskargak +• Android KitKat deskargak +• .mp4 ezagutza +• Lokalizazio arazoak +• [YouTube] Denbora-zigiluak diff --git a/fastlane/metadata/android/eu/changelogs/850.txt b/fastlane/metadata/android/eu/changelogs/850.txt new file mode 100644 index 000000000..614ab934e --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/850.txt @@ -0,0 +1 @@ +Bertsio honetan YouTube webgunearen bertsioa eguneratu da. Webgune zaharra martxoan eten egingo da eta, beraz, NewPipe eguneratu beharko duzu. diff --git a/fastlane/metadata/android/eu/changelogs/860.txt b/fastlane/metadata/android/eu/changelogs/860.txt new file mode 100644 index 000000000..bb1ae125a --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/860.txt @@ -0,0 +1,7 @@ +Hobetua +• Gorde eta leheneratu tonua eta tempoa deskonektatuta dauden ala ez +• Erreproduzitzailean pantailaren mozketa onartzen du +• Txanda-ikuspenak eta harpidedun kopurua +• YouTube optimizatu da datu gutxiago erabiltzeko + +Bertsio honetan YouTube-rekin lotutako 15 akats baino gehiago konpondu dira. diff --git a/fastlane/metadata/android/eu/changelogs/870.txt b/fastlane/metadata/android/eu/changelogs/870.txt new file mode 100644 index 000000000..f243bb1bf --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/870.txt @@ -0,0 +1,2 @@ +Hau NewPipe eguneratzen duen zuzenketa bat da, SoundCloud arazorik gabe berriro erabili ahal izateko. +SoundCloud-en v2 APIa erabiltzen da orain erauzgailuan eta bezero ID baliogabeen detekzioa hobetu da. diff --git a/fastlane/metadata/android/eu/changelogs/900.txt b/fastlane/metadata/android/eu/changelogs/900.txt new file mode 100644 index 000000000..ca11afb97 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/900.txt @@ -0,0 +1,14 @@ +Berria +• Harpidetza taldeak eta ordenatutako jarioak +• Isilarazteko botoia erreproduzitzaileetan + +Hobetua +• music.youtube.com eta media.ccc.de estekak irekitzeko aukera eman +• Bi ezarpen Itxuratik Edukira lekuz aldatu +• Ezkutatu 5, 15, 25 segundoko bilaketa aukerak bilaketa zehatza gaituta badago + +Konpondua +• WebM bideo batzuk ezin dira bilatu +• datu-basearen babeskopia Android P-n +• Deskargatutako fitxategi bat partekatzean huts egitea +• YouTube erauzketa arazo mordoa eta gehiago ... diff --git a/fastlane/metadata/android/eu/changelogs/920.txt b/fastlane/metadata/android/eu/changelogs/920.txt new file mode 100644 index 000000000..7954fcb37 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/920.txt @@ -0,0 +1,9 @@ +Hobetua + +• Gehitu dira igoera data eta ikustaldi kopurua erreprodukzio-sareko elementuetan +• Tiraderaren goiburuaren diseinuaren hobekuntzak + +Konpondua + +• API 19an huts egiteak eragiten zuen isilarazteko botoia konpondu da +• 1080p 60 fps-ko bideo luzeen deskarga konpondu da diff --git a/fastlane/metadata/android/eu/changelogs/930.txt b/fastlane/metadata/android/eu/changelogs/930.txt new file mode 100644 index 000000000..74ad72a44 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/930.txt @@ -0,0 +1,17 @@ +Berria +• YouTube Music bilaketa +• Android TV oinarrizkoa + +Hobetua +• Ikusitako bideoak kendu +• Mezua eduki onartzen ez +• Leiho tamaina keinuak +• Ilaran kanaleko botoiak +• Tiradera izenburu kudeaketa + +Konpondua +• Adin mugatuko edukia +• reCAPTCHA motak +• Laster-markak null +• Sareko salbuespena +• Harpidetza ordenatzea diff --git a/fastlane/metadata/android/eu/changelogs/940.txt b/fastlane/metadata/android/eu/changelogs/940.txt new file mode 100644 index 000000000..7627c5632 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/940.txt @@ -0,0 +1,16 @@ +Berria +• SoundCloud iruzkinak +• YouTube modu mugatua +• PeerTube guraso xehetasunak + +Hobetua +• Kore botoia onartutakoentzat +• Blokeatu keinuak barran +• Berriro saiatu/harpidetu koloreak + +Konpondua +• Deskarga elkarrizketa izoztea +• Ireki arakatzailean botoia +• Bideoak irekitzeko hutsegitea + +eta gehiago diff --git a/fastlane/metadata/android/eu/changelogs/951.txt b/fastlane/metadata/android/eu/changelogs/951.txt new file mode 100644 index 000000000..ed8f967cb --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/951.txt @@ -0,0 +1,15 @@ +Berria +• Harpidetzak bilatu jario-taldeetan +• Iragazkiak harpidetza taldekatu gabeak erakusteko +• Hasierako orrialdeko erreprodukzio-zerrenden fitxa +• Aurrera eta atzera egin atzeko planoan eta miniaturazko ilaran +• Bilaketa-iradokizunak + +Hobetua +• Aplikazioaren metadatuak ez dira idazten elkartutako fitxategietan +• Huts egindako erreprodukzioak ez dira ilaratik ezabatzen +• Egoera-barraren kolorea eguneratu da + +Konpondua +• Audio eta bideo desinkronizazioa +• [PeerTube] Ezabatutako iruzkinak diff --git a/fastlane/metadata/android/eu/changelogs/952.txt b/fastlane/metadata/android/eu/changelogs/952.txt new file mode 100644 index 000000000..aa8bdaa90 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/952.txt @@ -0,0 +1,7 @@ +Hobetua +• Erreprodukzio automatikoa zerbitzu guztietarako dago eskuragarri (YouTube-rako bakarrik izan beharrean) + +Konpondua +• YouTube-ren jarraipen berriak onartuz, erlazionatutako erreprodukzioak konpondu ziren. +• Adin-mugako YouTube bideoak konpondu dira +• [Android TV] Fokuaren nabarmentze-gainjartze iraunkorra konpondu da diff --git a/fastlane/metadata/android/eu/changelogs/954.txt b/fastlane/metadata/android/eu/changelogs/954.txt new file mode 100644 index 000000000..215e9f5a9 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/954.txt @@ -0,0 +1,9 @@ +• Ezaugarri berria: Ikusi bideoak xehetasunen orrian, irristatu behera erreproduzitzailea minimizatzeko +• MediaStyle jakinarazpenak: ekintza pertsonalizagarriak, errendimendu hobekuntzak +• Aldatu bideoaren tamaina NewPipe mahaigaineko aplikazio gisa erabiltzean + +• URL bateraezin baten kasuan aukerekin elkarrizketa-koadroa +• Bilaketa-iradokizunak hobetu dira emaitzak urrunetik lortu ezin direnean +• Bideoaren kalitatea 720p60ra (aplikazioan) eta 480p-ra (miniaturan) igo da + +• Akats asko konponduak diff --git a/fastlane/metadata/android/eu/changelogs/963.txt b/fastlane/metadata/android/eu/changelogs/963.txt new file mode 100644 index 000000000..6e4679c60 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/963.txt @@ -0,0 +1 @@ +• [YouTube] Kanalen jarraipena konpondu da diff --git a/fastlane/metadata/android/eu/changelogs/965.txt b/fastlane/metadata/android/eu/changelogs/965.txt new file mode 100644 index 000000000..142c96324 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/965.txt @@ -0,0 +1,6 @@ +Kanal taldeak berrantolatzean gertatzen zen hutsegitea konpondu da. +Konpondu da kanal eta erreprodukzio-zerrendetatik YouTube bideo gehiago lortzea. +YouTubeko iruzkinak jasotzea konpondu da. +YouTube URLetan /watch/, /v/ eta /w/ azpibideetarako laguntza gehitu da. +SoundCloud bezeroaren IDaren eta geo-murriztutako edukiaren erauzketa konpondu da. +Iparraldeko kurduera lokalizazioa gehitu da. diff --git a/fastlane/metadata/android/eu/changelogs/966.txt b/fastlane/metadata/android/eu/changelogs/966.txt new file mode 100644 index 000000000..9fe618e6c --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/966.txt @@ -0,0 +1,14 @@ +Berria: +• Zerbitzu berria gehitu: Bandcamp + +Hobetua: +• Aplikazioak gailuaren gaiari jarraitzeko aukera +• Errore-panel bat erakutsi hutsegiteak saihesteko +• Edukia erabilgarri ez dagoenaren informazio gehiago +• Hardware espazio botoiak erreproduzitu/pausatu aktibatzen du +• "Deskargatzen hasita" mezua erakutsi + +Konpondua: +• Miniatura txikiak atzeko planoan erreproduzitzen +• Erreproduzitzaile minimizatuan izenburu hutsa +• Tamaina aldatzeko modua leheneratzen ez zena diff --git a/fastlane/metadata/android/eu/changelogs/967.txt b/fastlane/metadata/android/eu/changelogs/967.txt new file mode 100644 index 000000000..0a7b974a4 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/967.txt @@ -0,0 +1 @@ +YouTube EBn behar bezala ez funtzionatzea konpondu da. Hau cookie eta pribatutasun baimen sistema berri batek eragin zuen, eta horrek NewPipe-k CONSENT cookie bat ezartzea eskatzen du. diff --git a/fastlane/metadata/android/eu/changelogs/968.txt b/fastlane/metadata/android/eu/changelogs/968.txt new file mode 100644 index 000000000..c3d54f0f1 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/968.txt @@ -0,0 +1,7 @@ +Kanalaren xehetasunen aukera gehitu da sakatuta edukitzeko menuan. +Erreprodukzio-zerrendaren izena erreprodukzio-zerrendaren interfazetik aldatzeko funtzionalitatea gehitu da. +Utzi erabiltzaileari bideoa bufferrean gordetzen ari den bitartean pausatzen. +Gai zuria leundu da. +Letra-tamaina handiagoa erabiltzean gainjarritako letra-tipoak konpondu dira. +Formuler eta Zephier gailuetan bideorik ez egotea konpondu da. +Hainbat hutsegite konpondu. diff --git a/fastlane/metadata/android/eu/changelogs/969.txt b/fastlane/metadata/android/eu/changelogs/969.txt new file mode 100644 index 000000000..be068dc50 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/969.txt @@ -0,0 +1,8 @@ +• Kanpoko biltegiratzean instalazioa baimendu +• [Bandcamp] Erreprodukzio bateko lehen hiru iruzkinak bistaratzeko laguntza gehitu da +• Deskargatzen hasten denean bakarrik erakutsi "deskarga hasi da" menua +• Ez ezarri reCaptcha cookierik cookierik gordeta ez dagoenean +• Cachearen errendimendua hobetu +• Jokalaria automatikoki ez jokatzea konpondu da +• Deskargak ezabatzean, baztertu aurreko Snackbar-ak +• Zerrendan ez zegoen objektua ezabatzen saiatzean izandako arazoa konpondu da diff --git a/fastlane/metadata/android/eu/changelogs/970.txt b/fastlane/metadata/android/eu/changelogs/970.txt new file mode 100644 index 000000000..4be4035ce --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/970.txt @@ -0,0 +1,10 @@ +Berria +• Erakutsi edukiaren metadatuak (etiketak, kategoriak, lizentzia) deskribapenaren azpian +• "Erakutsi kanalaren xehetasunak" aukera urruneko erreprodukzio-zerrendetan +• "Ireki arakatzailean" aukera sakatuta edukitzeko menuan + +Konpondua +• Bideoaren xehetasunen orrialdean errotazio-matxura +• "Jolastu Kodirekin" botoia Kore instalatzeko eskatzen zuena +• Inportazio eta esportazio bideak konpondu eta hobetu +• [YouTube] Iruzkinen "atsegin dut" kopurua diff --git a/fastlane/metadata/android/eu/changelogs/971.txt b/fastlane/metadata/android/eu/changelogs/971.txt new file mode 100644 index 000000000..f77ce5008 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/971.txt @@ -0,0 +1,3 @@ +Konponketa +• Bufferra handitu erreprodukziorako rebuffer-aren ondoren +• Tabletetan eta telebistetan erreproduzitzailearen erreprodukzio-ilararen ikonoan klik egitean gertatzen zen hutsegitea konpondu da diff --git a/fastlane/metadata/android/eu/changelogs/972.txt b/fastlane/metadata/android/eu/changelogs/972.txt new file mode 100644 index 000000000..03c28a763 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/972.txt @@ -0,0 +1,12 @@ +Berria +Denbora-zigiluen eta traolen ezagutza deskribapenean +Tableta moduaren eskuzko doikuntza gehitu da +Jarioan erreproduzitutako elementuak ezkutatzeko aukera gehitu da + +Hobetua +Biltegiratze sarbide sistemarako (SAF) laguntza egokia +Ezabatutako eta erabilgarri ez dauden kanaletako erroreen kudeaketa hobetua +Android 10+ erabiltzaileentzako partekatzeko menuak edukiaren izenburua erakusten du orain. +Invidious-en instantzia eguneratuak eta Piped estekak erabiltzeko laguntza + +...eta zuzenketak diff --git a/fastlane/metadata/android/eu/changelogs/973.txt b/fastlane/metadata/android/eu/changelogs/973.txt new file mode 100644 index 000000000..b2db943a3 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/973.txt @@ -0,0 +1,4 @@ +Konponketa +• Konpondu sareta-diseinuan moztutako miniaturak eta izenburuak, errenkada batean zenbat bideo sartu daitezkeen gaizki kalkulatzeagatik. +• Konpondu deskargatzeko elkarrizketa-koadroa ezer egin gabe desagertzea partekatzeko menutik irekitzean +• Kanpoko jarduerak irekitzearekin lotutako liburutegi bat eguneratu, hala nola Storage Access Framework fitxategi hautatzailea diff --git a/fastlane/metadata/android/eu/changelogs/974.txt b/fastlane/metadata/android/eu/changelogs/974.txt new file mode 100644 index 000000000..a515de2bc --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/974.txt @@ -0,0 +1,5 @@ +Konponketa +• Konpondu YouTube-ren mugatzeak eragindako buffering arazoak +• Konpondu YouTubeko iruzkinen erauzketa eta iruzkin desgaituekin matxurak +• Konpondu YouTubeko musika bilaketa +• Konpondu PeerTube zuzeneko emankizunak diff --git a/fastlane/metadata/android/eu/changelogs/975.txt b/fastlane/metadata/android/eu/changelogs/975.txt new file mode 100644 index 000000000..ccdfe2a55 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/975.txt @@ -0,0 +1,16 @@ +Berria +• Miniatura erakutsi bilatzen ari den bitartean +• Desgaitutako iruzkinak detektatu +• Jarioko elementua ikusita gisa markatu +• Bihotz-formako iruzkinak erakutsi + +Hobetua +• Metadatuen eta etiketen diseinua +• Zerbitzuaren kolorea UI osagai guztiei aplikatu + +Zuzenduta +• Mini erreproduzitzailean miniaturak konpondu +• Elementu bikoiztuen buffering infinitua konpondu +• Jokalarien zuzenketak: errotazioa eta itxiera +• ReCAPTCHA atzeko planoan kargatu +• Beste zuzenketa batzuk diff --git a/fastlane/metadata/android/eu/changelogs/976.txt b/fastlane/metadata/android/eu/changelogs/976.txt new file mode 100644 index 000000000..17076919c --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/976.txt @@ -0,0 +1,10 @@ +• Erreproduzitzailea pantaila osoan zuzenean ireki +• Bilaketa-iradokizun motak aukeratu +• Gai iluna ilunagoa + pantaila-aurreikuspen iluna +• Fitxategi-hautatzailea: nahi ez direnak gris koloreztatu +• YouTubeko harpidetzak inportatzea konpondu +• Berriro erreproduzitzeko botoia sakatu behar da +• Amaierako audio saioa konpondu +• [Android TV] Bilaketa-barraren jauzi luzeak DPad-ekin konpondu + +Aldaketa gehiago ikusteko, ikusi aldaketa-erregistroa beheko Estekak fitxan. diff --git a/fastlane/metadata/android/eu/changelogs/977.txt b/fastlane/metadata/android/eu/changelogs/977.txt new file mode 100644 index 000000000..138a957df --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/977.txt @@ -0,0 +1,10 @@ +• "Hurrengoa erreproduzitu" botoia sakatuta edukitzeko menuan +• YouTubeko bideo labur bide-aurrizkia asmo-iragazkian +• Ezarpen finkoak inportatu +• Bilaketa-barra eta jokalari botoiak trukatu Ilara-pantailan +• MediasessionManager konponketak +• Bilaketa-barra bideoa amaitu ondoren ez amaitzea konpondu +• RealtekATV multimedia tunela desgaituta +• Jokalari botoien klik eremua handitu + +Aldaketa gehiago ikusteko, ikusi aldaketa-erregistroa beheko Estekak fitxan. diff --git a/fastlane/metadata/android/eu/changelogs/978.txt b/fastlane/metadata/android/eu/changelogs/978.txt new file mode 100644 index 000000000..a01c898ef --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/978.txt @@ -0,0 +1 @@ +NewPipe bertsio berri baten egiaztapena exekutatzea konpondu da. Batzuetan egiaztapen hau goizegi exekutatzen zen eta, beraz, aplikazioaren kraskadura eragiten zuen. Hori orain konpondu beharko litzateke. diff --git a/fastlane/metadata/android/eu/changelogs/979.txt b/fastlane/metadata/android/eu/changelogs/979.txt new file mode 100644 index 000000000..15550832a --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/979.txt @@ -0,0 +1,2 @@ +- Erreprodukzioa berriro hasteko arazoa konpondu da +- Hobekuntzak NewPipe-k bertsio berri bat egiaztatu behar duen zehazten duen zerbitzua atzeko planoan abiarazten ez dela ziurtatzeko diff --git a/fastlane/metadata/android/eu/changelogs/980.txt b/fastlane/metadata/android/eu/changelogs/980.txt new file mode 100644 index 000000000..1e45b17ab --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/980.txt @@ -0,0 +1,13 @@ +Berria +- "Gehitu erreprodukzio-zerrendara" aukera gehitu da partekatzeko menuan +- y2u.be eta PeerTube esteka laburretarako laguntza gehitu da + +Hobetua +- Erreprodukzio-abiaduraren kontrol trinkoagoak +- Jarioak elementu berriak nabarmentzen ditu orain +- "Erakutsi ikusitako elementuak" aukera orain jarioan gordeta dago + +Zuzenduta +- YouTube-tik "atsegin dut" eta "ez dut" mezuen erauzketa konpondu da +- Errepikapen automatikoa konpondu da atzeko planotik itzuli ondoren +Eta askoz gehiago diff --git a/fastlane/metadata/android/eu/changelogs/981.txt b/fastlane/metadata/android/eu/changelogs/981.txt new file mode 100644 index 000000000..9ef0ddc88 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/981.txt @@ -0,0 +1,2 @@ +MediaParserren euskarria kendu da Android 11+-n bufferrean sartu ondoren erreprodukzioa berriro hasteko huts egitea konpontzeko. +Philips QM16XE-n multimedia tunelizazioa desgaitu da erreprodukzio arazoak konpontzeko. diff --git a/fastlane/metadata/android/eu/changelogs/982.txt b/fastlane/metadata/android/eu/changelogs/982.txt new file mode 100644 index 000000000..28b860901 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/982.txt @@ -0,0 +1 @@ +Konpondu da YouTube-k ez zuela inolako erreprodukziorik erreproduzitzen. diff --git a/fastlane/metadata/android/eu/changelogs/983.txt b/fastlane/metadata/android/eu/changelogs/983.txt new file mode 100644 index 000000000..1c9b31572 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/983.txt @@ -0,0 +1,9 @@ +Gehitu bi aldiz sakatuta bilatzeko interfazea eta portaera berriak +Egin ezarpenak bilagarri +Nabarmendu finkatutako iruzkinak horrela +Gehitu aplikazioarekin irekitzeko euskarria FSFEren PeerTube instantziarako +Gehitu errore-jakinarazpenak +Konpondu jokalaria aldatzean lehenengo ilarako elementuaren errepikapena +Itxaron denbora gehiago zuzeneko erreprodukzioetan bufferrean gordetzean huts egin aurretik +Tokiko bilaketa-emaitzen ordena konpondu +Konpondu erreprodukzio-ilarako elementu-eremu hutsak diff --git a/fastlane/metadata/android/eu/changelogs/984.txt b/fastlane/metadata/android/eu/changelogs/984.txt new file mode 100644 index 000000000..cef6b4c1b --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/984.txt @@ -0,0 +1,7 @@ +Kargatu elementu nahikoa pantaila betetzeko eta tableta/telebista korritzea konpondu +Zerrendetan mugitzeko ausazko hutsegiteak konpondu +Bilaketa azkarraren gainjartze-arkua sistemaren azpian jarri +Leiho anitzetan mozketen aldaketak leheneratu (kokapen okerreko atzerakada) +compileSdk 30etik 31ra handitu +Erroreen liburutegia eguneratu +Erreproduzitzailearen kodea berregituratu diff --git a/fastlane/metadata/android/eu/changelogs/985.txt b/fastlane/metadata/android/eu/changelogs/985.txt new file mode 100644 index 000000000..68d0be7fc --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/985.txt @@ -0,0 +1 @@ +Konpondu da YouTube-k ez zuela inolako erreprodukziorik erreproduzitzen diff --git a/fastlane/metadata/android/eu/changelogs/986.txt b/fastlane/metadata/android/eu/changelogs/986.txt new file mode 100644 index 000000000..b167f6092 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/986.txt @@ -0,0 +1,16 @@ +Berria +• Erreprodukzio berrien jakinarazpenak +• Trantsizio hobetua atzeko planoa/bideo artean +• Tonua erdi-tonuz aldatu +• Ilara erreprodukzio-zerrenda bati erantsi + +Hobetua +• Abiadura/tonu urratsaren tamaina gogoratu +• Hasierako buffering luzea arintu +• Android TV interfazea hobetu +• Fitxategi guztiak ezabatu aurretik berretsi + +Konpondua +• Multimedia botoiak kontrolak ezkutatzen ez zituen +• Erreprodukzioa berrezartzea mota aldatzean +• Erreprodukzio-zerrenda elkarrizketa biratzea diff --git a/fastlane/metadata/android/eu/changelogs/987.txt b/fastlane/metadata/android/eu/changelogs/987.txt new file mode 100644 index 000000000..4c03d4277 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/987.txt @@ -0,0 +1,12 @@ +Berria +• Beste bidalketa-metodoak: karga azkarragoa, PeerTube/SoundCloud konponketak, YouTube zuzeneko emankizunak +• Urruneko zerrenda tokikora gehitu botoia +• Irudi aurrebista Android 10+ partekatze-orrian + +Hobetua +• Erreprodukzio-parametroen elkarrizketa hobetu +• Harpidetza botoiak hiru puntuko menura eraman + +Konpondua +• Ikusitako bideoak kentzea zerrendatik +• Partekatzeko menuaren gaia eta zerrenda sarrera diff --git a/fastlane/metadata/android/eu/changelogs/991.txt b/fastlane/metadata/android/eu/changelogs/991.txt new file mode 100644 index 000000000..471f353dd --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/991.txt @@ -0,0 +1,13 @@ +Berria +• "Ireki arakatzailean" botoia errore-panelean +• Kanal taldeak zerrenda gisa bistaratzeko aukera +• [YouTube] Klik luze segmentuetan denbora-zigilu URLa partekatzeko +• Erreprodukzio-ilarako botoia erreproduzitzaile txikian + +Hobetua +• Islandierazko lokalizazioa eta itzulpen eguneraketak +• Barne-hobekuntza asko + +Konpondua +• Hainbat hutsegite konpondu +• [YouTube] Kanalak kargatzea, jario ez-dedikatuak eta erreprodukzio-konponbideak herrialde batzuetan diff --git a/fastlane/metadata/android/eu/changelogs/992.txt b/fastlane/metadata/android/eu/changelogs/992.txt index 5b0dd96ba..d7f52bf43 100644 --- a/fastlane/metadata/android/eu/changelogs/992.txt +++ b/fastlane/metadata/android/eu/changelogs/992.txt @@ -1,17 +1,17 @@ -Zer berri -• Harpidetza kopurua bideoen xehetasunetan -• Ilaratik deskargatu -• Erreprodukzio-zerrendei betirako izango den miniatura ezarri -• Luze sakatu traola eta estekentzako -• Txartel-bista modua +Berria +• Harpidedun kopurua bideoaren xehetasunetan +• Deskargatu ilaratik +• Zerrenda miniatura behin betiko ezarri +• Sakatu luze traolak eta estekak +• Txartelen ikuspegi modua -Hobekuntzak -• Mini-erreproduzitzailearen ixteko botoi handiago bat -• Miniaturen eskala murrizketa arinagoa -• Android 13 (API 33) -• Bilaketak ez du erreprodukzioa geldiaraziko +Hobetua +• Mini-erreproduzitzailearen ixteko botoia handiagoa +• Miniaturen eskala txikiagotzea leunagoa +• Helburua Android 13 (API 33) +• Bilatzeak ez du jokalaria pausatzen -Konponketak -• DeX/saguaren gainezarpena konpondua -• Bigarren planoko erreprodukzioa baimendu bereizitako bi audio-jariorik gabe -• YouTube-kin zeuden arazoak konpondu eta are gehiago… +Konpondua +• Gainjartzea DeX/saguaren gainean konpondu +• Atzeko planoan audio-jariorik gabe baimendu +• Hainbat YouTube konponketa eta gehiago diff --git a/fastlane/metadata/android/eu/changelogs/993.txt b/fastlane/metadata/android/eu/changelogs/993.txt new file mode 100644 index 000000000..c8d24db0f --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/993.txt @@ -0,0 +1,12 @@ +Berria +• Gehitu abisua erreprodukzio-zerrenda bikoiztuak gehitzean eta gehitu botoia kentzeko +• Hardware botoiak baztertzea baimendu +• Jarioan partzialki ikusitako bideoak ezkutatzea baimendu + +Hobetua +• Erabili sareta-zutabe gehiago pantaila handietan +• Aurrerapen adierazleak ezarpenekin bat etorriz egin + +Konpondua +• Konpondu arakatzailearen URLak, deskargak eta kanpoko erreproduzitzaileak irekitzeko arazoak Android 11+-n +• MIUI-n bi ukitu behar izatearen pantaila osoko interakzioa konpondu diff --git a/fastlane/metadata/android/eu/changelogs/994.txt b/fastlane/metadata/android/eu/changelogs/994.txt new file mode 100644 index 000000000..0b54ba569 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/994.txt @@ -0,0 +1,15 @@ +Berria +• Audio pista eta hizkuntza anitz onartzen ditu +• Bolumen eta distira keinuak pantailaren edozein aldetan ezarri +• Fitxa nagusiak pantailaren behealdean bistaratzeko laguntza + +Hobetua +• [Bandcamp] Ordainpeko hormaren atzean dauden abestiak kudeatu + +Konpondua +• [YouTube] 403 HTTP erroreak erreprodukzioetarako +• Jokalari beltza zerrendaren ikuspegitik nagusira aldatzean +• Jokalarien zerbitzuaren memoria-ihesa +• [PeerTube] Igotzailearen eta azpikanalaren avatarrak trukatu + +eta gehiago diff --git a/fastlane/metadata/android/eu/changelogs/995.txt b/fastlane/metadata/android/eu/changelogs/995.txt new file mode 100644 index 000000000..1db316b4c --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/995.txt @@ -0,0 +1,16 @@ +Berria +• Kanal fitxak laguntza +• Hautatu irudiaren kalitatea +• Irudi guztien URLak lortu + +Hobetua +• Jokalarien interfazeen irisgarritasuna +• Bideo-deskargetarako audio-hautaketa hobea +• Partekatutako zerrendetan izenak sartzeko aukera + +Konpondua +• [YouTube] Atsegin dut kopurua lortzea +• Erreproduzitzaileak erantzuten ez duen leihoak eta kraskadurak +• Hizkuntza hautatzailean hizkuntza okerrak hautatzea +• Audioaren fokuak isilaraztea errespetatu +• Zerrendako elementuen gehikuntzak diff --git a/fastlane/metadata/android/eu/changelogs/996.txt b/fastlane/metadata/android/eu/changelogs/996.txt new file mode 100644 index 000000000..8a3c936dd --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/996.txt @@ -0,0 +1,2 @@ +NullPointerException bat konpondu da media.ccc.de-n kanal/konferentzia bat irekitzean. +Grinch-a gure Gabonetako oparia apurtzen saiatu zen, baina konpondu dugu. diff --git a/fastlane/metadata/android/eu/changelogs/998.txt b/fastlane/metadata/android/eu/changelogs/998.txt new file mode 100644 index 000000000..931876cb5 --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/998.txt @@ -0,0 +1,4 @@ +Konpondu da YouTube-k ez zuela inolako erreprodukziorik erreproduzitzen HTTP 403 erroreengatik. + +YouTube bideo baten erdian noizbehinkako HTTP 403 erroreak ez dira oraindik konpondu. +Arazo hori ahalik eta azkarren konponduko da beste hotfix bertsio batean. diff --git a/fastlane/metadata/android/eu/changelogs/999.txt b/fastlane/metadata/android/eu/changelogs/999.txt new file mode 100644 index 000000000..b461e2b5b --- /dev/null +++ b/fastlane/metadata/android/eu/changelogs/999.txt @@ -0,0 +1,12 @@ +Bertsio honek YouTube bideoen erdian dauden HTTP 403 erroreak konpontzen ditu. + +Berria +• [SoundCloud] Gehitu URLaren euskarria on.soundcloud.com webgunean + +Hobetua +• [Bandcamp] Erakutsi informazio gehigarria irrati-kioskoan + +Zuzenduta +• [YouTube] Bideoen hasieran edo erdian noizbehinkako HTTP 403 erroreak konpondu dira. +• [YouTube] Atera avatarra eta bannerra kanal goiburu mota gehiagotatik +• [Bandcamp] Hainbat akats konpontzen ditu eta beti HTTPS erabiltzen du diff --git a/fastlane/metadata/android/fa/changelogs/1007.txt b/fastlane/metadata/android/fa/changelogs/1007.txt new file mode 100644 index 000000000..ba5413d49 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/1007.txt @@ -0,0 +1 @@ +مشکل عدم نمایش پخش‌زنده برطرف شد diff --git a/fastlane/metadata/android/fr/changelogs/1000.txt b/fastlane/metadata/android/fr/changelogs/1000.txt index d4e706e2e..994b6061d 100644 --- a/fastlane/metadata/android/fr/changelogs/1000.txt +++ b/fastlane/metadata/android/fr/changelogs/1000.txt @@ -1,13 +1,13 @@ -Amélioré -• Rendre la description de la playlist cliquable pour afficher plus / moins de contenu -• [PeerTube] Gérer automatiquement les liens d'instance `subscribeto.me` -• Ne commencer à lire qu'un seul élément dans l'écran d'historique +Améliorations +• La description de la playlist est désormais cliquable pour afficher plus ou moins de contenu. +• [PeerTube] Gestion automatique des liens d'instance `subscribeto.me` +• Lecture d'un seul élément à la fois depuis l'historique -Corrigé -• Correction de la visibilité du bouton RSS -• Correction des plantages de l'aperçu de la barre de recherche -• Correction de la mise en playlist d'un élément sans vignette -• Correction de la sortie de la boîte de dialogue de téléchargement avant qu'elle n'apparaisse -• Correction de la fenêtre contextuelle de mise en file d'attente de la liste des éléments associés -• Correction de l'ordre dans la boîte de dialogue d'ajout à la playlist -• Ajuster la disposition des éléments de signet de la playlist +Corrections +• Amélioration de la visibilité du bouton RSS +• Correction des plantages liés à l'aperçu de la barre de progression +• Correction de l'ajout d'un élément sans vignette à la playlist +• Correction de la fermeture prématurée de la boîte de dialogue de téléchargement +• Correction de la fenêtre contextuelle d'ajout à la file d'attente de la liste des éléments associés +• Amélioration de l'ordre d'affichage dans la boîte de dialogue « Ajouter à la playlist » +• Ajustement de la mise en page des signets de playlist diff --git a/fastlane/metadata/android/fr/changelogs/1003.txt b/fastlane/metadata/android/fr/changelogs/1003.txt index 161ee7fbb..917714bae 100644 --- a/fastlane/metadata/android/fr/changelogs/1003.txt +++ b/fastlane/metadata/android/fr/changelogs/1003.txt @@ -1,6 +1,6 @@ -Ceci est une version de correction qui résout les erreurs de YouTube : -• [YouTube] Correction du non-chargement des informations des vidéos, correction des erreurs HTTP 403 lors de la lecture des vidéos et restauration de la lecture de certaines vidéos à âge restreint -• Correction des tailles de sous-titres qui ne changent pas -• Correction du téléchargement des informations deux fois lors de l'ouverture d'un stream -• [Soundcloud] Suppression des streams protégés par DRM non lisibles -• Traductions mises à jour +Cette m.à.j corrective résout les problèmes suivants sur YouTube : +• [YouTube] Correction du problème de chargement des informations vidéo, des erreurs HTTP 403 lors de la lecture et restauration de la lecture de certaines vidéos à contenu restreint. +• Correction du problème d'affichage de la taille des sous-titres. +• Correction du double téléchargement des informations lors de l'ouverture d'un flux. +• [SoundCloud] Suppression des flux protégés par DRM et illisibles. +• Traductions mises à jour. diff --git a/fastlane/metadata/android/fr/changelogs/1005.txt b/fastlane/metadata/android/fr/changelogs/1005.txt index b7e5ff49f..269ba2105 100644 --- a/fastlane/metadata/android/fr/changelogs/1005.txt +++ b/fastlane/metadata/android/fr/changelogs/1005.txt @@ -1,17 +1,17 @@ -Nouveau -• Prise en charge d'Android Auto +Nouveautés +• Ajout de la compatibilité avec Android Auto • Possibilité de définir des groupes de flux comme onglets de l'écran principal • [YouTube] Partager comme playlist temporaire -• [SoundCloud] Onglet « J'aime » +• [SoundCloud] Onglet « J'aime » sur les chaînes -Amélioration -• Amélioration des astuces de la barre de recherche +Améliorations +• Amélioration des suggestions de la barre de recherche • Affichage de la date de téléchargement dans Téléchargements • Utilisation de la langue par application d'Android 13 -Corrigé +Corrections • Correction des couleurs de texte défectueuses en mode sombre -• [YouTube] Correction des playlists ne chargeant pas plus de 100 éléments -• [YouTube] Correction des vidéos recommandées manquantes -• Correction des plantages dans la vue Historique +• [YouTube] Correction du chargement des playlists de plus de 100 éléments +• [YouTube] Correction de l'affichage des vidéos recommandées manquantes +• Correction des plantages dans l'historique • Correction des horodatages dans les réponses aux commentaires diff --git a/fastlane/metadata/android/fr/changelogs/1006.txt b/fastlane/metadata/android/fr/changelogs/1006.txt new file mode 100644 index 000000000..65fbccfd5 --- /dev/null +++ b/fastlane/metadata/android/fr/changelogs/1006.txt @@ -0,0 +1,8 @@ +Conservation du lecteur en cours lors du clic sur les horodatages +Tentative de récupération des téléchargements en attente +Ajout d'une option pour supprimer un téléchargement sans supprimer le fichier +Autorisation de superposition : affichage d'une boîte de dialogue explicative pour Android > R + +Correction du formatage du nombre court pour les versions Android inférieures à 7 +Correction des notifications fantômes +Corrections pour les fichiers de sous-titres SRT diff --git a/fastlane/metadata/android/fr/changelogs/1007.txt b/fastlane/metadata/android/fr/changelogs/1007.txt new file mode 100644 index 000000000..3ad3bf279 --- /dev/null +++ b/fastlane/metadata/android/fr/changelogs/1007.txt @@ -0,0 +1 @@ +Correction de YouTube qui ne lisait aucun média diff --git a/fastlane/metadata/android/fr/changelogs/65.txt b/fastlane/metadata/android/fr/changelogs/65.txt index bb664a3cb..9d06cac17 100644 --- a/fastlane/metadata/android/fr/changelogs/65.txt +++ b/fastlane/metadata/android/fr/changelogs/65.txt @@ -1,26 +1,41 @@ ### Améliorations -- L'animation de l'icône du burgermenu a été désactivé #1486 -- Annulation de la suppression des téléchargements #1472 +- Désactivation de l'animation de l'icône du menu hamburger #1486 + +- Annulation de la suppression des téléchargements #1472 + - Option de téléchargement dans le menu de partage #1498 -- Ajout d'une option de partage dans le menu "long tap" #1454 -- Réduction du lecteur principal à la sortie #1354 -- Mise à jour de la version de la bibliothèque et correction de la sauvegarde de la base de données #1510 -- Mise à jour de ExoPlayer 2.8.2 #1392 - - La boîte de dialogue de contrôle de la vitesse de lecture a été retravaillée pour prendre en charge différentes tailles de pas pour un changement de vitesse plus rapide. - - Ajout d'une option d'avance rapide pendant les silences dans le contrôle de la vitesse de lecture. Cela devrait être utile pour les livres audio et certains genres musicaux, et peut apporter une véritable expérience transparente (et peut casser une chanson avec beaucoup de silences =\\). - - Refonte de la résolution des sources de médias pour permettre le passage des métadonnées avec les médias en interne dans le lecteur, plutôt que de le faire manuellement. Maintenant, nous avons une seule source de métadonnées et elles sont directement disponibles lorsque la lecture commence. - - Correction des métadonnées des listes de lecture distantes qui ne sont pas mises à jour lorsque de nouvelles métadonnées sont disponibles lors de l'ouverture du fragment de liste de lecture. - - Diverses corrections de l'interface utilisateur : #1383, les contrôles de notification du lecteur en arrière-plan sont maintenant toujours blancs, il est plus facile de fermer le lecteur popup en le lançant. + +- Ajout de l'option de partage au menu contextuel (appui long) #1454 + +- Réduction du lecteur principal à la fermeture #1354 + +- Mise à jour de la version de la bibliothèque et correction de la sauvegarde de la base de données #1510 + +- Mise à jour ExoPlayer 2.8.2 #1392 + +- Refonte de la boîte de dialogue de contrôle de la vitesse de lecture pour permettre des incréments différents et ainsi accélérer les changements de vitesse. + +- Ajout d'une option pour avancer rapidement pendant les silences dans le contrôle de la vitesse de lecture. Cette fonction devrait être utile pour les livres audio et certains genres musicaux, et peut offrir une expérience d'écoute parfaitement fluide (mais peut aussi perturber la lecture d'un morceau comportant de nombreux silences =\\). + +- Refonte de la résolution de la source multimédia pour permettre la transmission des métadonnées directement dans le lecteur, au lieu d'une saisie manuelle. Nous disposons désormais d'une source unique de métadonnées, directement disponible au démarrage de la lecture. - Correction du problème de mise à jour des métadonnées des listes de lecture distantes lors de la disponibilité de nouvelles métadonnées à l'ouverture d'un fragment de liste de lecture. + +- Diverses corrections d'interface utilisateur : #1383, les commandes de notification du lecteur en arrière-plan sont désormais toujours blanches, fermeture plus facile du lecteur contextuel par un mouvement brusque. + - Utilisation d'un nouvel extracteur avec une architecture remaniée pour le multiservice. ### Corrections -- Correction #1440 Disposition des informations vidéo cassée #1491 -- Correction de l'historique des vues #1497 - - #1495, en mettant à jour les métadonnées (vignette, titre et nombre de vidéos) dès que l'utilisateur accède à la liste de lecture. - - #1475, en enregistrant une vue dans la base de données lorsque l'utilisateur lance une vidéo sur un lecteur externe sur le fragment de détail. -- Correction du timeout de la fenêtre en cas de mode popup. #1463 (Corrigé #640) -- Correction du lecteur vidéo principal #1509 - - Correction du mode répétition entraînant un NPE du lecteur lorsqu'une nouvelle intention est reçue alors que l'activité du lecteur est en arrière-plan. - - Correction de la réduction du lecteur en popup ne détruisant pas le lecteur lorsque la permission de popup n'est pas accordée. +- Correction du problème #1440 : affichage incorrect des informations vidéo. #1491 + +- Correction de l'historique de visionnage. #1497 + +- #1495 : mise à jour des métadonnées (miniature, titre et nombre de vidéos) dès que l'utilisateur accède à la liste de lecture. + +- #1475 : enregistrement d'une vue dans la base de données lorsque l'utilisateur lance une vidéo sur un lecteur externe dans le fragment de détails. + +- Correction du délai d'expiration de l'écran en mode contextuel. #1463 (Correction du problème #640) + +- Correction du lecteur vidéo principal. #1509 + +- [#1412] Correction du mode répétition provoquant une exception NullPointerException (NPE) du lecteur lors de la réception d'une nouvelle intention alors que l'activité du lecteur est en arrière-plan. - Correction d'un problème où la réduction du lecteur dans une fenêtre contextuelle ne détruisait pas le lecteur lorsque l'autorisation d'afficher la fenêtre contextuelle n'était pas accordée. diff --git a/fastlane/metadata/android/fr/changelogs/66.txt b/fastlane/metadata/android/fr/changelogs/66.txt index 3a94c81e0..b6092f44f 100644 --- a/fastlane/metadata/android/fr/changelogs/66.txt +++ b/fastlane/metadata/android/fr/changelogs/66.txt @@ -1,28 +1,50 @@ +# Journal des modifications de la v0.13.7 + +### Corrigé +- Correction des problèmes de filtre de tri de la v0.13.6 + # Journal des modifications de la v0.13.6 ### Améliorations -- L'animation de l'icône du menu « hamburger » a été désactivée #1486 -- Annulation de la suppression des téléchargements #1472 +- Désactivation de l'animation de l'icône du menu hamburger #1486 + +- Annulation de la suppression des téléchargements #1472 + - Option de téléchargement dans le menu de partage #1498 -- Ajout d'une option de partage dans le menu "long tap" #1454 -- Réduction du lecteur principal à la sortie #1354 -- Mise à jour de la version de la bibliothèque et correction de la sauvegarde de la base de données #1510 -- Mise à jour de ExoPlayer 2.8.2 #1392 - - La boîte de dialogue de contrôle de la vitesse de lecture a été retravaillée pour prendre en charge différentes tailles de pas pour un changement de vitesse plus rapide. - - Ajout d'une option d'avance rapide pendant les silences dans le contrôle de la vitesse de lecture. Cela devrait être utile pour les livres audio et certains genres musicaux, et peut apporter une véritable expérience transparente (et peut casser une chanson avec beaucoup de silences =\\). - - Refonte de la résolution des sources de médias pour permettre le passage des métadonnées avec les médias en interne dans le lecteur, plutôt que de le faire manuellement. Maintenant, nous avons une seule source de métadonnées et elles sont directement disponibles lorsque la lecture commence. - - Correction des métadonnées des listes de lecture distantes qui ne sont pas mises à jour lorsque de nouvelles métadonnées sont disponibles lors de l'ouverture du fragment de liste de lecture. - - Diverses corrections de l'interface utilisateur : #1383, les contrôles de notification du lecteur en arrière-plan sont maintenant toujours blancs, il est plus facile de fermer le lecteur popup en le lançant. + +- Ajout de l'option de partage au menu contextuel (appui long) #1454 + +- Réduction du lecteur principal à la fermeture #1354 + +- Mise à jour de la version de la bibliothèque et correction de la sauvegarde de la base de données #1510 + +- Mise à jour ExoPlayer 2.8.2 #1392 + +- Refonte de la boîte de dialogue de contrôle de la vitesse de lecture pour permettre des incréments différents et ainsi accélérer les changements de vitesse. + +- Ajout d'une option pour avancer rapidement pendant les silences dans le contrôle de la vitesse de lecture. Ceci devrait être utile pour les livres audio et certains genres musicaux, et peut offrir une expérience d'écoute parfaitement fluide (mais peut aussi perturber une chanson avec de nombreux silences =\\). - Résolution de la source multimédia remaniée pour permettre la transmission interne des métadonnées au lecteur, au lieu d'une saisie manuelle. Les métadonnées proviennent désormais d'une source unique et sont directement disponibles au démarrage de la lecture. + +- Correction du problème de mise à jour des métadonnées des listes de lecture distantes lors de l'ouverture d'un fragment de liste de lecture, même lorsque de nouvelles métadonnées sont disponibles. + +- Diverses corrections d'interface : #1383, les commandes de notification du lecteur en arrière-plan sont désormais toujours blanches ; il est plus facile de fermer le lecteur contextuel en le faisant glisser. + - Utilisation d'un nouvel extracteur avec une architecture remaniée pour le multiservice. ### Corrections -- Correction #1440 Disposition des informations vidéo cassée #1491 -- Correction de l'historique des vues #1497 - - #1495, en mettant à jour les métadonnées (vignette, titre et nombre de vidéos) dès que l'utilisateur accède à la liste de lecture. - - #1475, en enregistrant une vue dans la base de données lorsque l'utilisateur lance une vidéo sur un lecteur externe sur le fragment de détail. -- Correction du timeout de la fenêtre en cas de mode popup. #1463 (Corrigé #640) -- Correction du lecteur vidéo principal #1509 - - Correction du mode répétition entraînant un NPE du lecteur lorsqu'une nouvelle intention est reçue alors que l'activité du lecteur est en arrière-plan. - - Correction de la réduction du lecteur en popup ne détruisant pas le lecteur lorsque la permission de popup n'est pas accordée. +- Correction du problème #1440 : affichage incorrect des informations vidéo ; #1491 + +- Correction de l'historique de visionnage ; #1497 + +- #1495 : mise à jour des métadonnées (miniature, titre et nombre de vidéos) dès que l'utilisateur accède à la liste de lecture. + +- #1475 : enregistrement d'une vue dans la base de données lorsque l'utilisateur lance une vidéo sur un lecteur externe dans le fragment de détails. + +- Correction du délai d'expiration de l'écran en mode fenêtre contextuelle. #1463 (Correction de #640) + +- Correction du lecteur vidéo principal #1509 + +- [#1412] Correction du mode de répétition provoquant une exception de pointeur nul (NPE) du lecteur lors de la réception d'une nouvelle intention alors que l'activité du lecteur est en arrière-plan. + +- Correction du problème suivant : la réduction du lecteur dans une fenêtre contextuelle ne le détruisait pas lorsque l'autorisation d'ouvrir une fenêtre contextuelle n'était pas accordée. diff --git a/fastlane/metadata/android/fr/changelogs/68.txt b/fastlane/metadata/android/fr/changelogs/68.txt index 9b2760c35..3c9c4446f 100644 --- a/fastlane/metadata/android/fr/changelogs/68.txt +++ b/fastlane/metadata/android/fr/changelogs/68.txt @@ -1,31 +1,44 @@ -# Modifications v0.14.1 +# Modifications de la v0.14.1 -### Corrections -- Échec du décryptage de l'URL vidéo #1659 -- Lien de description, ne s'extrayait pas bien #1657 +### Corrigé +- Correction du problème de décryptage de l'URL vidéo (#1659) +- Correction du problème d'extraction du lien de description (#1657) -# Modifications v0.14.0 +# Modifications de la v0.14.0 -### Nouveautés -- Design du dossier #1461 -- Page d'accueil personnalisable #1461 +### Nouveau +- Nouveau design du tiroir (#1461) +- Nouvelle page d'accueil personnalisable (#1461) ### Améliorations -- Contrôles gestuels retravaillés #1604 -- Nouvelle façon de fermer le lecteur popup #1597 +- Refonte des commandes gestuelles (#1604) +- Nouvelle méthode pour fermer le lecteur pop-up (#1597) -### Corrections -- Erreur lorsque le nombre d'abonnements n'est pas disponible. Ferme #1649. - - Affiche "le nombre d'abonnés non disponible" dans ces cas. -- NPE lorsqu'une liste de lecture YouTube est vide. -- Kiosques dans SoundCloud -- Refactor et correction du bug #1623 -- Résultat de recherche cyclique #1562 -- Barre de recherche qui n'est pas mise en page de manière statique -- Vidéos YT Premium qui ne sont pas bloquées correctement -- Vidéos qui ne se chargent pas toujours (à cause du parsing DASH) -- Liens dans la description des vidéos -- Afficher un avertissement lorsque quelqu'un essaie de télécharger vers une carte SD externe -- Exception "rien indiqué" qui déclenche un rapport -- La vignette ne s'affiche pas dans le lecteur de fond pour Android 8.1 [voir ici](https://github.com/TeamNewPipe/NewPipe/issues/943) -- Enregistrement du récepteur de diffusion. Ferme le dossier #1641. +### Corrigé +- Correction d'une erreur lorsque le nombre d'abonnements n'est pas disponible. Résout le problème n° 1649. + + - Afficher « Nombre d'abonnés indisponible » dans ces cas + +- Correction d'une exception NPE lorsqu'une playlist YouTube est vide + +- Correction rapide pour les bornes interactives sur SoundCloud + +- Refactorisation et correction du bug n° 1623 + +- Correction du résultat de recherche cyclique n° 1562 + +- Correction de la barre de progression (position statique) + +- Correction du blocage incorrect des vidéos YouTube Premium + +- Correction du chargement intempestif des vidéos (dû à l'analyse DASH) + +- Correction des liens dans la description des vidéos + +- Afficher un avertissement lors d'une tentative de téléchargement sur carte SD externe + +- Correction d'une exception déclenchant un rapport en cas d'absence d'affichage + +- Correction de l'affichage des miniatures dans le lecteur en arrière-plan sous Android 8.1 [voir ici](https://github.com/TeamNewPipe/NewPipe/issues/943) + +- Correction de l'enregistrement du récepteur de diffusion. Résout le problème n° 1641. diff --git a/fastlane/metadata/android/fr/changelogs/70.txt b/fastlane/metadata/android/fr/changelogs/70.txt index fccfccd2b..185f98f69 100644 --- a/fastlane/metadata/android/fr/changelogs/70.txt +++ b/fastlane/metadata/android/fr/changelogs/70.txt @@ -1,4 +1,4 @@ -ATTENTION : Cette version est probablement un festival de bugs, tout comme la dernière. Cependant, en raison de la fermeture complète depuis la 17. une version cassée est mieux que pas de version. N'est-ce pas ? ¯\_(ツ)_/¯ +ATTENTION : Cette version est probablement un festival de bugs, tout comme la dernière. Cependant, en raison de la fermeture complète depuis la 17. une version cassée est mieux que pas de version. N'est-ce pas ? ¯\_(ツ)_/¯ ### Améliorations * Les fichiers téléchargés peuvent maintenant être ouverts en un seul clic. diff --git a/fastlane/metadata/android/fr/changelogs/740.txt b/fastlane/metadata/android/fr/changelogs/740.txt index da4bdc2f8..167608b66 100644 --- a/fastlane/metadata/android/fr/changelogs/740.txt +++ b/fastlane/metadata/android/fr/changelogs/740.txt @@ -3,7 +3,7 @@
  • Rendre les liens dans les commentaires cliquables, augmenter la taille du texte
  • Rechercher en cliquant sur les liens d'horodatage dans les commentaires
  • Afficher l'onglet préféré en fonction de l'état récemment sélectionné
  • -
  • Ajouter la liste de lecture à la file d'attente lors d'un clic long sur 'Arrière-plan' dans la fenêtre de la liste de lecture
  • +
  • Ajouter la playlist à la file d'attente lors d'un clic long sur 'Arrière-plan' dans la fenêtre de la playlist
  • Rechercher le texte partagé lorsqu'il ne s'agit pas d'une URL
  • Ajouter "partager à l'heure actuelle" bouton au lecteur vidéo principal lecteur vidéo principal
  • Ajouter un bouton de fermeture du lecteur principal lorsque la file d'attente vidéo est terminée
  • @@ -18,6 +18,6 @@
    • Défilement avec les commentaires et les flux associés désactivés
    • CheckForNewAppVersionTask qui est exécuté alors qu'il ne devrait pas l'être'
    • -
    • Importation des abonnements YouTube : ignorer ceux dont l’URL est invalide et conserver ceux dont le titre est vide
    • -
    • URL YouTube invalide : le nom de la balise signature n'est pas toujours "signature", ce qui empêche le chargement des flux.
    • +
    • Importation des abonnements YouTube : ignorer ceux dont l’URL est invalide et conserver ceux dont le titre est vide
    • +
    • URL YouTube invalide : le nom de la balise signature n'est pas toujours "signature", ce qui empêche le chargement des flux.
    diff --git a/fastlane/metadata/android/fr/changelogs/750.txt b/fastlane/metadata/android/fr/changelogs/750.txt index 422529abf..7273ae1f0 100644 --- a/fastlane/metadata/android/fr/changelogs/750.txt +++ b/fastlane/metadata/android/fr/changelogs/750.txt @@ -1,22 +1,36 @@ -Nouveau -Reprise de lecture #2288 -• Reprise des flux où ils s'étaient arrêtés -Améliorations du téléchargeur #2149 -• Utilisation du Storage Access Framework pour stocker sur cartes SD -• Nouveau multiplexeur mp4 -• Peut changer le dossier de téléchargement -• Respect des réseaux tarifés +Nouveautés +Reprise de la lecture #2288 + +• Reprise des flux là où vous les avez interrompus +Améliorations du téléchargeur #2149 + +• Utilisation de Storage Access Framework pour stocker les téléchargements sur des cartes SD externes + +• Nouveau multiplexeur mp4 + +• Possibilité de modifier le répertoire de téléchargement avant de lancer un téléchargement + +• Respect des réseaux limités Améliorations + • Suppression des chaînes gema #2295 -• Gestion des changements de rotation #2444 -• Uniformisation des menus longue-pression #2368 + +• Gestion des changements de rotation (automatique) pendant le cycle de vie de l'activité #2444 + +• Harmonisation des menus accessibles par appui long #2368 Corrections -• Nom de la piste de sous-titres sélectionnée qui ne s'affiche pas #2394 -• Ne plante pas quand la vérification de la mise à jour de l'application échoue #2423 -• Téléchargements bloqués à 99,9 % #2440 -• Mise à jour des métadonnées de la file de lecture #2453 -• [SoundCloud] Ne plante pas lors du chargement des playlists TeamNewPipe/NewPipeExtractor#170 -• [YouTube] Durée pas analysée TeamNewPipe/NewPipeExtractor#177 + +• Correction de l'affichage du nom de la piste de sous-titres sélectionnée #2394 + +• Correction du plantage en cas d'échec de la vérification des mises à jour de l'application (version GitHub) #2423 + +• Correction du blocage des téléchargements à 99,9 % #2440 + +• Mise à jour des métadonnées de la file d'attente de lecture #2453 + +• [SoundCloud] Correction du plantage lors du chargement des playlists TeamNewPipe/NewPipeExtractor#170 + +• [YouTube] Correction de l'impossibilité d'afficher la durée paresd TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/fr/changelogs/760.txt b/fastlane/metadata/android/fr/changelogs/760.txt index 2f74c57b4..e0a225fce 100644 --- a/fastlane/metadata/android/fr/changelogs/760.txt +++ b/fastlane/metadata/android/fr/changelogs/760.txt @@ -5,7 +5,7 @@ Nouveauté Améliorations -• Ajout de l'action "Commencer à jouer ici" dans les menus qui s'appuient longuement pour les listes de lecture #2518 +• Ajout de l'action "Commencer à jouer ici" dans les menus qui s'appuient longuement pour les playlists #2518 • Ajout d'un commutateur pour le sélecteur de fichiers SAF / hérité #2521 Corrections @@ -13,7 +13,7 @@ Corrections • Correction de la position de lecture qui est enregistrée même si l'historique de visionnage est désactivé • Correction des performances réduites causées par la position de lecture dans les vues de liste #2517 • [Extractor] Correction de ReCaptchaActivity #2527, TeamNewPipe/NewPipeExtractor#186 -• [Extractor] [YouTube] Correction de l'erreur de recherche occasionnelle lorsque les listes de lecture sont dans les résultats TeamNewPipe/NewPipeExtractor#185 +• [Extractor] [YouTube] Correction de l'erreur de recherche occasionnelle lorsque les playlists sont dans les résultats TeamNewPipe/NewPipeExtractor#185 @@ -39,5 +39,5 @@ Corrections • Ne plante pas lorsque la vérification de la mise à jour de l'application échoue (version GitHub) #2423 • Correction des téléchargements bloqués à 99,9 % #2440 • Mise à jour des métadonnées de la file de lecture #2453 -• [SoundCloud] Correction du plantage lors du chargement des listes de lecture TeamNewPipe/NewPipeExtractor#170 +• [SoundCloud] Correction du plantage lors du chargement des playlists TeamNewPipe/NewPipeExtractor#170 • [YouTube] Correction de la durée qui ne peut pas être analysée TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/fr/changelogs/800.txt b/fastlane/metadata/android/fr/changelogs/800.txt index 91bd24d54..46fe1504e 100644 --- a/fastlane/metadata/android/fr/changelogs/800.txt +++ b/fastlane/metadata/android/fr/changelogs/800.txt @@ -1,10 +1,10 @@ Nouveau -- Support de PeerTube sans P2P (#2201) [Beta] : +- Support de PeerTube sans P2P (#2201) [Beta] : ◦ Regarder et télécharger des vidéos depuis des instances PeerTube ◦ Ajouter des instances dans les paramètres pour accéder à l'ensemble du monde PeerTube ◦ Il peut y avoir des problèmes avec les handshakes SSL sur Android 4.4 et 7.1 lors de l'accès à certaines instances, ce qui entraîne une erreur de réseau. -- Téléchargeur (#2679) : +- Téléchargeur (#2679) : ◦ Calculer l'heure d'arrivée du téléchargement ◦ Télécharger les opus (fichiers webm) en ogg ◦ Récupération des liens de téléchargement expirés pour reprendre les téléchargements après une longue pause @@ -17,7 +17,7 @@ Amélioré Correction - Correction d'un bogue qui ne permettait pas de déplacer le lecteur popup si un autre doigt était placé pendant le déplacement du lecteur popup #2772 -- Autorise les listes de lecture sans uploader et corrige les crashs liés à ce problème #2724, TeamNewPipe/NewPipeExtractor#219 +- Autorise les playlists sans uploader et corrige les crashs liés à ce problème #2724, TeamNewPipe/NewPipeExtractor#219 - Activation de TLS1.1/1.2 sur les appareils Android 4.4 (API 19/KitKat) pour corriger le handshake TLS avec MediaCCC et certaines instances PeerTube #2792 - SoundCloud] Correction de l'extraction de l'identifiant client TeamNewPipe/NewPipeExtractor#217 - [SoundCloud] Correction de l'extraction du flux audio diff --git a/fastlane/metadata/android/fr/changelogs/810.txt b/fastlane/metadata/android/fr/changelogs/810.txt index c40bea4af..573ea9889 100644 --- a/fastlane/metadata/android/fr/changelogs/810.txt +++ b/fastlane/metadata/android/fr/changelogs/810.txt @@ -2,10 +2,10 @@ Nouveautée : • Affiche la miniature de la vidéo sur l'écran de verrouillage lorsqu'elle est lu en arrière-plan Améliorations : -• Ajout de la liste de lecture locale à la file d'attente lors d'une pression longue sur le bouton arrière-plan / flottant +• Ajout de la playlist locale à la file d'attente lors d'une pression longue sur le bouton arrière-plan / flottant • Possibilité de faire défiler les onglets de la page principale et les masquent lorsqu'il n'y a qu'un seul onglet • Limite le nombre de mises à jour de la miniature des notifications avec le lecteur en arrière-plan -• Ajout d'une miniature fictive pour les listes de lecture locales vides +• Ajout d'une miniature fictive pour les playlists locales vides • Utilisation de l'extension de fichier *.opus au lieu de *.webm et affiche « opus » pour le nom du format au lieu de « WebM Opus » dans la liste déroulante de téléchargement. • Ajout d'un bouton pour supprimer les fichiers téléchargés ou l'historique de téléchargements dans les « Téléchargements » • [YouTube] Ajout de la prise en charge des liens de chaînes /c/shortened_url diff --git a/fastlane/metadata/android/fr/changelogs/840.txt b/fastlane/metadata/android/fr/changelogs/840.txt index fa7cf4986..240b77824 100644 --- a/fastlane/metadata/android/fr/changelogs/840.txt +++ b/fastlane/metadata/android/fr/changelogs/840.txt @@ -7,7 +7,7 @@ Amélioré • Corriger l'activité ReCaptcha et enregistrer correctement les cookies obtenus • Suppression du menu à points au profit du tiroir et du bouton Masquer l'historique lorsque l'historique de visionnage n'est pas activé dans les paramètres • Demander correctement l'autorisation d'affichage sur d'autres applications dans les paramètres sur Android 6 et versions ultérieures -• Renommer la liste de lecture locale en cliquant longuement dans BookmarkFragment +• Renommer la playlist locale en cliquant longuement dans BookmarkFragment • Diverses améliorations de PeerTube • Amélioration de plusieurs chaînes sources en anglais diff --git a/fastlane/metadata/android/fr/changelogs/958.txt b/fastlane/metadata/android/fr/changelogs/958.txt index 9f857d470..27908767f 100644 --- a/fastlane/metadata/android/fr/changelogs/958.txt +++ b/fastlane/metadata/android/fr/changelogs/958.txt @@ -1,13 +1,13 @@ -Nouveautés : +Nouveautés : • Tirer pour actualiser les abonnements • Option pour masquer la miniature sur l'écran de verrouillage de nouveau dispo. • Amélioration du chargement des listes locales (playlists, historique…) -Corrigé : +Corrigé : • Crash au démarrage quand NewPipe n'était plus dans la RAM • Crash au démarrage quand l'appareil n'était pas connecté à internet • Paramètres de luminosité et de volume -• [YouTube] Listes de lecture longues +• [YouTube] Playlists longues -Autres : +Autres : • Mise à jour des traductions diff --git a/fastlane/metadata/android/fr/changelogs/968.txt b/fastlane/metadata/android/fr/changelogs/968.txt index 06b84c7fd..abf53af53 100644 --- a/fastlane/metadata/android/fr/changelogs/968.txt +++ b/fastlane/metadata/android/fr/changelogs/968.txt @@ -1,5 +1,5 @@ Ajout d'une option de détails sur les chaînes dans le menu de pression longue. -Ajout d'une fonctionnalité permettant de renommer le nom de la liste de lecture à partir de l'interface de la liste de lecture. +Ajout d'une fonctionnalité permettant de renommer le nom de la playlist à partir de l'interface de la playlist. Permet à l'utilisateur de faire une pause pendant la mise en mémoire tampon d'une vidéo. Le thème blanc a été amélioré. Correction du chevauchement des polices lors de l'utilisation d'une taille de police plus grande. diff --git a/fastlane/metadata/android/fr/changelogs/980.txt b/fastlane/metadata/android/fr/changelogs/980.txt index 6835f70c8..149ff2eeb 100644 --- a/fastlane/metadata/android/fr/changelogs/980.txt +++ b/fastlane/metadata/android/fr/changelogs/980.txt @@ -1,5 +1,5 @@ Nouveautés -• Ajout option "Ajouter à la liste de lecture" au menu de partage +• Ajout option "Ajouter à la playlist" au menu de partage • Ajout prise en charge des liens courts y2u.be et PeerTube Améliorations diff --git a/fastlane/metadata/android/fr/changelogs/983.txt b/fastlane/metadata/android/fr/changelogs/983.txt index b9760a8a1..5079132f0 100644 --- a/fastlane/metadata/android/fr/changelogs/983.txt +++ b/fastlane/metadata/android/fr/changelogs/983.txt @@ -6,4 +6,4 @@ Ajoute les notifications d’erreur Corrige la relecture du premier item de la file lorsque le lecteur change Attend plus longtemps lors des directs avant d’échouer Corrige l’ordre des résultats d’une recherche locale -Corrige les champs d’item vides dans la liste de lecture +Corrige les champs d’item vides dans la playlist diff --git a/fastlane/metadata/android/fr/changelogs/986.txt b/fastlane/metadata/android/fr/changelogs/986.txt index b5f2af821..af6901a0a 100644 --- a/fastlane/metadata/android/fr/changelogs/986.txt +++ b/fastlane/metadata/android/fr/changelogs/986.txt @@ -2,7 +2,7 @@ Ajouts • Notifications pour les nouveaux flux • Transition fluide entre les lecteurs vidéo et en arrière-plan • Modification de la hauteur de son par demi-tons -• Ajout de la file du lecteur principal dans une liste de lecture +• Ajout de la file du lecteur principal dans une playlist Améliorations • Enregistrement du pas de la vitesse et de la hauteur audios diff --git a/fastlane/metadata/android/fr/changelogs/987.txt b/fastlane/metadata/android/fr/changelogs/987.txt index 1641d9a00..00000725d 100644 --- a/fastlane/metadata/android/fr/changelogs/987.txt +++ b/fastlane/metadata/android/fr/changelogs/987.txt @@ -1,6 +1,6 @@ Nouveautés -• Prise en charge d'autres méthodes de diffusion que le HTTP progressif : temps de chargement plus rapide, corrections pour PeerTube et SoundCloud, lecture des nouveaux flux en directs de YouTube -• Bouton pour ajouter une liste de lecture distante à une locale +• Prise en charge d'autres méthodes de diffusion que le HTTP progressif : temps de chargement plus rapide, corrections pour PeerTube et SoundCloud, lecture des nouveaux flux en directs de YouTube +• Bouton pour ajouter une playlist distante à une locale • Prévisualisation d'images lors d'un partage pour Andoid 10+ Améliorations diff --git a/fastlane/metadata/android/fr/changelogs/990.txt b/fastlane/metadata/android/fr/changelogs/990.txt index fcab79c3c..b941066e2 100644 --- a/fastlane/metadata/android/fr/changelogs/990.txt +++ b/fastlane/metadata/android/fr/changelogs/990.txt @@ -1,9 +1,9 @@ -Cette mise à jour abandonne la prise en charge d'Android 4.4 KitKat, la nouvelle version minimum est Android 5 Lollipop ! +Cette mise à jour abandonne la prise en charge d'Android 4.4 KitKat, la nouvelle version minimum est Android 5 Lollipop ! Nouveautés • Télécharger depuis le menu d'appuis long • Cacher les futures vidéos dans le flux -• Partager des listes de lecture locales +• Partager des playlists locales Améliorations • Réusinage du code du lecteur en petits composants : moins de mémoire vive utilisée, moins de bogues diff --git a/fastlane/metadata/android/fr/changelogs/992.txt b/fastlane/metadata/android/fr/changelogs/992.txt index 88e58db96..dc1fad35b 100644 --- a/fastlane/metadata/android/fr/changelogs/992.txt +++ b/fastlane/metadata/android/fr/changelogs/992.txt @@ -1,7 +1,7 @@ Nouveau • Nombre d'abonnés dans les détails de la vidéo • Télécharger depuis la file d'attente -• Définir de manière permanente une miniature de liste de lecture +• Définir de manière permanente une miniature de playlist • Hashtags et liens à appui long • Mode d'affichage de la carte diff --git a/fastlane/metadata/android/fr/changelogs/995.txt b/fastlane/metadata/android/fr/changelogs/995.txt index f8b55f3fd..b91f83875 100644 --- a/fastlane/metadata/android/fr/changelogs/995.txt +++ b/fastlane/metadata/android/fr/changelogs/995.txt @@ -13,4 +13,4 @@ Corrigé • Correction des fenêtres contextuelles et des plantages du lecteur • Sélection de mauvaises langues dans le sélecteur de langue • Le focus audio du lecteur ne respectait pas la fonction muet -• L'ajout d'éléments de liste de lecture ne fonctionnait parfois pas +• L'ajout d'éléments de playlist ne fonctionnait parfois pas diff --git a/fastlane/metadata/android/fr/changelogs/997.txt b/fastlane/metadata/android/fr/changelogs/997.txt index 87ca55570..b1a550577 100644 --- a/fastlane/metadata/android/fr/changelogs/997.txt +++ b/fastlane/metadata/android/fr/changelogs/997.txt @@ -1,7 +1,7 @@ Nouveau • Ajouter des réponses aux commentaires -• Autoriser la réorganisation des listes de lecture -• Afficher la description et la durée de la liste de lecture +• Autoriser la réorganisation des playlists +• Afficher la description et la durée de la playlist • Autoriser la réinitialisation des paramètres Amélioré diff --git a/fastlane/metadata/android/he/changelogs/1007.txt b/fastlane/metadata/android/he/changelogs/1007.txt new file mode 100644 index 000000000..50731171e --- /dev/null +++ b/fastlane/metadata/android/he/changelogs/1007.txt @@ -0,0 +1 @@ +תוקנה התקלה ש־YouTube לא מנגן אף תזרים diff --git a/fastlane/metadata/android/hi/changelogs/1000.txt b/fastlane/metadata/android/hi/changelogs/1000.txt index 67a819e0f..201a8a970 100644 --- a/fastlane/metadata/android/hi/changelogs/1000.txt +++ b/fastlane/metadata/android/hi/changelogs/1000.txt @@ -7,7 +7,3 @@ • RSS बटन दृश्यता को ठीक करें • सीकबार पूर्वावलोकन क्रैश को ठीक करें • थंबनेल-रहित आइटम को प्लेलिस्ट में डालना ठीक करें -• डाउनलोड डायलॉग के दिखाई देने से पहले बाहर निकलने को ठीक करें -• संबंधित आइटम सूची एनक्यू पॉपअप को ठीक करें -• प्लेलिस्ट में जोड़ें डायलॉग में क्रम को ठीक करें -• प्लेलिस्ट बुकमार्क आइटम लेआउट को समायोजित करें diff --git a/fastlane/metadata/android/hi/changelogs/1002.txt b/fastlane/metadata/android/hi/changelogs/1002.txt index d780f47a6..a0bc033fe 100644 --- a/fastlane/metadata/android/hi/changelogs/1002.txt +++ b/fastlane/metadata/android/hi/changelogs/1002.txt @@ -1,5 +1,4 @@ YouTube द्वारा कोई भी स्ट्रीम न चलाए जाने की समस्या को ठीक किया गया। यह रिलीज़ केवल सबसे ज़्यादा दबाव वाली त्रुटि को संबोधित करती है जो YouTube वीडियो विवरण को लोड होने से रोकती है। - हम जानते हैं कि अन्य समस्याएँ भी हैं, और हम जल्द ही उन्हें हल करने के लिए एक अलग रिलीज़ जारी करेंगे। diff --git a/fastlane/metadata/android/hi/changelogs/1004.txt b/fastlane/metadata/android/hi/changelogs/1004.txt index 071ab64e3..faf98d116 100644 --- a/fastlane/metadata/android/hi/changelogs/1004.txt +++ b/fastlane/metadata/android/hi/changelogs/1004.txt @@ -1 +1,3 @@ -फिक्स्ड YouTube कोई स्ट्रीम नहीं चला रहा है +इस रिलीज़ में YouTube सिर्फ़ 360p स्ट्रीम दे रहा था, इसे ठीक किया गया है। + +ध्यान दें कि इस वर्शन में इस्तेमाल किया गया सॉल्यूशन शायद टेम्पररी है, और लंबे समय में SABR वीडियो प्रोटोकॉल को लागू करने की ज़रूरत है, लेकिन TeamNewPipe के सदस्य अभी बिज़ी हैं, इसलिए किसी भी मदद की बहुत तारीफ़ होगी! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/hi/changelogs/1005.txt b/fastlane/metadata/android/hi/changelogs/1005.txt index 495894e76..4d72dc68f 100644 --- a/fastlane/metadata/android/hi/changelogs/1005.txt +++ b/fastlane/metadata/android/hi/changelogs/1005.txt @@ -1,17 +1,15 @@ नया -+ • Android Auto के लिए समर्थन जोड़ें -+ • फ़ीड समूहों को मुख्य स्क्रीन टैब के रूप में सेट करने की अनुमति दें -+ • [YouTube] अस्थायी प्लेलिस्ट के रूप में साझा करें -+ • [SoundCloud] "पसंद" चैनल टैब जोङी गई +• Android Auto के लिए समर्थन जोड़ें +• फ़ीड समूहों को मुख्य स्क्रीन टैब के रूप में सेट करने की अनुमति दें +• [YouTube] अस्थायी प्लेलिस्ट के रूप में साझा करें +• [SoundCloud] "पसंद" चैनल टैब जोङी गई बेहतर किए -+ • खोज बार संकेत -+ • डाउनलोडस स्क्रीन में डाउनलोड की तारीख दिखाएं -+ • Android 13+ पर प्रति-ऐप भाषा का उपयोग करें +• खोज बार संकेत +• डाउनलोडस स्क्रीन में डाउनलोड की तारीख दिखाएं +• Android 13+ पर प्रति-ऐप भाषा का उपयोग करें फिक्स किए -+ • डार्क मोड में पाठ के रंग ठीक करें -+ • [YouTube] 100 से अधिक आइटम लोड नहीं करने वाली प्लेलिस्ट को ठीक करें -+ • [YouTube] अनुपलब्ध अनुशंसित वीडियो को ठीक करें -+ • इतिहास सूची दृश्य में क्रैश ठीक करें -+ • टिप्पणी के उत्तरों में टाइमस्टैम्प को ठीक करें +• डार्क मोड में पाठ के रंग ठीक करें +• [YouTube] 100 से अधिक आइटम लोड नहीं करने वाली प्लेलिस्ट को ठीक करें +• टिप्पणी के उत्तरों में टाइमस्टैम्प को ठीक करें diff --git a/fastlane/metadata/android/hi/changelogs/1006.txt b/fastlane/metadata/android/hi/changelogs/1006.txt new file mode 100644 index 000000000..4545d60ed --- /dev/null +++ b/fastlane/metadata/android/hi/changelogs/1006.txt @@ -0,0 +1,10 @@ +# बेहतर किए +टाइमस्टैम्प पर क्लिक करते समय मौजूदा प्लेयर पर ही दिखाएं +जब हो सके तो पेंडिंग डाउनलोड मिशन को रिकवर करने की कोशिश करें +फ़ाइल डिलीट किए बिना डाउनलोड डिलीट करने का ऑप्शन जोड़ें +.soundcloud लिंक खोलने में सपोर्ट करें + +7 से कम Android वर्शन के लिए छोटे नंबर फ़ॉर्मेटिंग को ठीक किया गया +खाली नोटिफ़िकेशन को ठीक किया गया +SRT सबटाइटल फ़ाइलों के लिए ठीक किया गया +कई क्रैश ठीक किए गए diff --git a/fastlane/metadata/android/hi/changelogs/1007.txt b/fastlane/metadata/android/hi/changelogs/1007.txt new file mode 100644 index 000000000..071ab64e3 --- /dev/null +++ b/fastlane/metadata/android/hi/changelogs/1007.txt @@ -0,0 +1 @@ +फिक्स्ड YouTube कोई स्ट्रीम नहीं चला रहा है diff --git a/fastlane/metadata/android/hi/changelogs/65.txt b/fastlane/metadata/android/hi/changelogs/65.txt index d2c2b8c71..d870f8d03 100644 --- a/fastlane/metadata/android/hi/changelogs/65.txt +++ b/fastlane/metadata/android/hi/changelogs/65.txt @@ -1,26 +1,13 @@ ### सुधार -- बर्गरमेनू आइकन एनीमेशन को अक्षम करें #1486 -- डाउनलोड को पूर्ववत करें #1472 -- शेयर मेनू में डाउनलोड विकल्प #1498 -- लॉन्ग टैप मेनू में शेयर विकल्प जोड़ा गया #1454 -- बाहर निकलने पर मुख्य प्लेयर को छोटा करें #1354 -- लाइब्रेरी संस्करण अपडेट और डेटाबेस बैकअप फिक्स #1510 -- एक्सोप्लेयर 2.8.2 अपडेट #1392 -- तेज गति परिवर्तन के लिए विभिन्न चरण आकारों का समर्थन करने के लिए प्लेबैक गति नियंत्रण संवाद को फिर से तैयार किया गया। -- प्लेबैक गति नियंत्रण में मौन के दौरान तेजी से आगे बढ़ने के लिए एक टॉगल जोड़ा गया। यह ऑडियोबुक और कुछ संगीत शैलियों के लिए मददगार होना चाहिए, और एक सच्चा सहज अनुभव ला सकता है (और बहुत सारे मौन वाले गीत को तोड़ सकता है =\\)। -- मीडिया स्रोत रिज़ॉल्यूशन को फिर से तैयार किया गया ताकि प्लेयर में आंतरिक रूप से मीडिया के साथ मेटाडेटा को पास किया जा सके, बजाय मैन्युअल रूप से ऐसा करने के। अब हमारे पास मेटाडेटा का एक ही स्रोत है और प्लेबैक शुरू होने पर सीधे उपलब्ध है। -- जब प्लेलिस्ट का टुकड़ा खोला जाता है तो नया मेटाडेटा उपलब्ध होने पर रिमोट प्लेलिस्ट मेटाडेटा अपडेट नहीं होता है। -- विभिन्न UI फ़िक्सेस: #1383, बैकग्राउंड प्लेयर नोटिफिकेशन कंट्रोल अब हमेशा सफ़ेद रहता है, फ़्लिंगिंग के ज़रिए पॉपअप प्लेयर को बंद करना आसान है -- मल्टीसर्विस के लिए रीफ़ैक्टर्ड आर्किटेक्चर के साथ नए एक्सट्रैक्टर का उपयोग करें +- बर्गरमेनू आइकन एनिमेशन को डिसेबल करें #1486 +- डाउनलोड को अनडू करें #1472 +- शेयर मेनू में डाउनलोड ऑप्शन #1498 +- लॉन्ग टैप मेनू में शेयर ऑप्शन जोड़ा गया #1454 +- ExoPlayer 2.8.2 अपडेट #1392 +- कई UI फ़िक्स: #1383 -### फ़िक्सेस +### फ़िक्स -- फ़िक्स #1440 टूटी हुई वीडियो जानकारी लेआउट #1491 - व्यू हिस्ट्री फ़िक्स #1497 -- #1495, जैसे ही उपयोगकर्ता प्लेलिस्ट एक्सेस करता है मेटाडेटा (थंबनेल, शीर्षक और वीडियो काउंट) को अपडेट करके। -- #1475, जब उपयोगकर्ता डिटेल फ़्रैगमेंट पर बाहरी प्लेयर पर वीडियो शुरू करता है तो डेटाबेस में व्यू रजिस्टर करके। -- पॉपअप मोड के मामले में स्क्रीन टाइमआउट को ठीक करें। #1463 (फ़िक्स #640) -- मुख्य वीडियो प्लेयर फ़िक्स #1509 -- [#1412] प्लेयर गतिविधि के बैकग्राउंड में होने पर नया इंटेंट प्राप्त होने पर प्लेयर NPE का कारण बनने वाले रिपीट मोड को ठीक किया गया। -- पॉपअप के लिए प्लेयर को छोटा करने की सुविधा को ठीक किया गया, जब पॉपअप की अनुमति नहीं दी जाती है तो प्लेयर नष्ट नहीं होता है। +- #1495, जैसे ही यूज़र प्लेलिस्ट एक्सेस करता है, मेटाडेटा (थंबनेल, टाइटल और वीडियो काउंट) को अपडेट करके। diff --git a/fastlane/metadata/android/hi/changelogs/66.txt b/fastlane/metadata/android/hi/changelogs/66.txt index 30c20b0e8..e9ec1e3fa 100644 --- a/fastlane/metadata/android/hi/changelogs/66.txt +++ b/fastlane/metadata/android/hi/changelogs/66.txt @@ -1,33 +1,21 @@ -# Changelog of v0.13.7 +# v0.13.7 का चेंजलॉग -### Fixed -- Fix sort filter issues of v0.13.6 +### ठीक किया गया +- v0.13.6 के सॉर्ट फ़िल्टर की दिक्कतें ठीक की गईं -# Changelog of v0.13.6 +# v0.13.6 का चेंजलॉग -### Improvements +### सुधार -- Disable burgermenu icon animation #1486 -- undo delete of downloads #1472 -- Download option in share menu #1498 -- Added share option to long tap menu #1454 -- Minimize main player on exit #1354 -- Library version update and database backup fix #1510 -- ExoPlayer 2.8.2 Update #1392 - - Reworked the playback speed control dialog to support different step sizes for faster speed change. - - Added a toggle to fast-forward during silences in playback speed control. This should be helpful for audiobooks and certain music genres, and can bring a true seamless experience (and can break a song with lots of silences =\\). - - Refactored media source resolution to allow passing metadata alongside media internally in the player, rather than doing so manually. Now we have a single source of metadata and is directly available when playback starts. - - Fixed remote playlist metadata not updating when new metadata is available when playlist fragment is opened. - - Various UI fixes: #1383, background player notification controls now always white, easier to shutdown popup player through flinging -- Use new extractor with refactored architecture for multiservice +- बर्गरमेनू आइकन एनिमेशन डिसेबल करें #1486 +- डाउनलोड को अनडू डिलीट करें #1472 +- शेयर मेनू में डाउनलोड ऑप्शन #1498 +- लॉन्ग टैप मेनू में शेयर ऑप्शन जोड़ा गया #1454 +- ExoPlayer 2.8.2 अपडेट #1392 +कई UI फ़िक्स: #1383 -### Fixes +### फ़िक्स -- Fix #1440 Broken Video Info Layout #1491 -- View history fix #1497 - - #1495, by updating the metadata (thumbnail, title and video count) as soon as the user access the playlist. - - #1475, by registering a view in the database when the user starts a video on external player on detail fragment. -- Fix creen timeout in case of popup mode. #1463 (Fixed #640) -- Main video player fix #1509 - - [#1412] Fixed repeat mode causing player NPE when new intent is received while player activity is in background. - - Fixed minimizing player to popup does not destroy player when popup permission is not granted. +- फ़िक्स #1440 टूटा हुआ वीडियो इन्फ़ो लेआउट #1491 +- व्यू हिस्ट्री फ़िक्स #1497 +- मेन वीडियो प्लेयर फिक्स #1509। diff --git a/fastlane/metadata/android/hi/changelogs/68.txt b/fastlane/metadata/android/hi/changelogs/68.txt index 238b1e0b1..f0cc5bddb 100644 --- a/fastlane/metadata/android/hi/changelogs/68.txt +++ b/fastlane/metadata/android/hi/changelogs/68.txt @@ -1,31 +1,19 @@ -# changes of v0.14.1 +# v0.14.1 में बदलाव -### Fixed -- Fixed failed to decrypt video url #1659 -- Fixed description link not extract well #1657 +### ठीक किया गया +- वीडियो URL डिक्रिप्ट करने में फेल होना ठीक किया गया #1659 +- डिस्क्रिप्शन लिंक ठीक से एक्सट्रेक्ट नहीं हो रहा था, इसे ठीक किया गया #1657 -# changes of v0.14.0 +# v0.14.0 में बदलाव -### New -- New Drawer design #1461 -- New customizable front page #1461 +### नया +- नया ड्रॉअर डिज़ाइन #1461 +- नया कस्टमाइज़ेबल फ्रंट पेज #1461 -### Improvements -- Reworked Gesture controls #1604 -- New way to close the popup player #1597 +### सुधार +- पॉपअप प्लेयर बंद करने का नया तरीका #1597 -### Fixed -- Fix error when subscription count is not available. Closes #1649. - - Show "Subscriber count not available" in those cases -- Fix NPE when a YouTube playlist is empty -- Quick fix for the kiosks in SoundCloud -- Refactor and bugfix #1623 - - Fix Cyclic search result #1562 - - Fix Seek bar not statically lay outed - - Fix YT Premium video are not blocked correctly - - Fix Videos sometimes not loading (due to DASH parsing) - - Fix links in video description - - Show warning when someone tries to download to external sdcard - - fix nothing shown exception triggers report - - thumbnail not shown in background player for android 8.1 [see here](https://github.com/TeamNewPipe/NewPipe/issues/943) -- Fix registering of broadcast receiver. Closes #1641. +### ठीक किया गया +- जब YouTube प्लेलिस्ट खाली हो तो NPE को ठीक करें +- SoundCloud में कियोस्क के लिए क्विक फिक्स +- रीफैक्टर और बगफिक्स #1623। diff --git a/fastlane/metadata/android/hi/changelogs/69.txt b/fastlane/metadata/android/hi/changelogs/69.txt index c8262d1b0..8bdf96c8f 100644 --- a/fastlane/metadata/android/hi/changelogs/69.txt +++ b/fastlane/metadata/android/hi/changelogs/69.txt @@ -1,19 +1,15 @@ -### New -- Long-tap delete and share in subscriptions #1516 -- Tablet UI and grid list layout #1617 +### नया +- सब्सक्रिप्शन में लंबे समय तक टैप करके डिलीट और शेयर करें #1516 +- टैबलेट UI और ग्रिड लिस्ट लेआउट #1617 -### Improvements -- store and reload the last used aspect ratio #1748 -- Enable linear layout in Downloads activity with full video names #1771 -- Delete and share subscriptions directly from within the subscriptions tab #1516 -- Enqueuing now triggers video playing if the play queue has already ended #1783 -- Separate settings for volume and brightness gestures #1644 -- Add support for Localization #1792 +### सुधार +- वॉल्यूम और ब्राइटनेस जेस्चर के लिए अलग सेटिंग्स #1644 +- लोकलाइज़ेशन के लिए सपोर्ट जोड़ें #1792 -### Fixes -- Fix time parsing for . format, so NewPipe can be used in Finland -- Fix subscription count -- Add foreground service permission for API 28+ devices #1830 +### सुधार +- . फ़ॉर्मेट के लिए टाइम पार्सिंग ठीक करें, ताकि फ़िनलैंड में NewPipe का इस्तेमाल किया जा सके +- सब्सक्रिप्शन काउंट ठीक करें +- API 28+ डिवाइस के लिए फ़ोरग्राउंड सर्विस परमिशन जोड़ें #1830 -### Known Bugs -- Playback state can not be saved on Android P +### जाने-पहचाने बग +- Android P पर प्लेबैक स्टेट सेव नहीं किया जा सकता diff --git a/fastlane/metadata/android/hi/changelogs/70.txt b/fastlane/metadata/android/hi/changelogs/70.txt index ad87a4409..cfa334bdb 100644 --- a/fastlane/metadata/android/hi/changelogs/70.txt +++ b/fastlane/metadata/android/hi/changelogs/70.txt @@ -1,25 +1,11 @@ -ATTENTION: This version probably is a bugfest, just like the last one. However due to the full shutdown since the 17. a broken version is better then no version. Right? ¯\_(ツ)_/¯ +### सुधार +* डाउनलोड की गई फ़ाइलें अब एक क्लिक से खोली जा सकती हैं #1879 +* एंड्रॉयड 4.1 - 4.3 के लिए सपोर्ट हटा दिया गया #1884 +* पुराना प्लेयर हटाएँ #1884 +* मौजूदा प्ले क्यू से स्ट्रीम को दाईं ओर स्वाइप करके हटाएँ #1915 +* बहुत सारी डाउनलोड गड़बड़ियाँ ठीक करके सुधार किया गए -### Improvements -* downloaded files can now be opened with one click #1879 -* drop support for android 4.1 - 4.3 #1884 -* remove old player #1884 -* remove streams from current play queue by swiping them to the right #1915 -* remove auto queued stream when a new stream is enqueued manually #1878 -* Postprocessing for downloads and implement missing features #1759 by @kapodamy - * Post-processing infrastructure - * Proper error handling "infrastructure" (for downloader) - * Queue instead of multiple downloads - * Move serialized pending downloads (`.giga` files) to app data - * Implement max download retry - * Proper multi-thread download pausing - * Stop downloads when swicthing to mobile network (never works, see 2nd point) - * Save the thread count for next downloads - * A lot of incoherences fixed - -### Fixed -* Fix crash with default resolution set to best and limited mobile data resolution #1835 -* pop-up player crash fixed #1874 -* NPE when trying to open background player #1901 -* Fix for inserting new streams when auto queuing is enabled #1878 -* Fixed the decypering shuttown issue +### ठीक किया गया +* डिफ़ॉल्ट रिज़ॉल्यूशन को बेस्ट और लिमिटेड मोबाइल डेटा रिज़ॉल्यूशन पर सेट करने पर क्रैश को ठीक किया गया #1835 +* पॉप-अप प्लेयर क्रैश को ठीक किया गया #1874 +* बैकग्राउंड प्लेयर खोलने की कोशिश करते समय NPE #1901 diff --git a/fastlane/metadata/android/hi/changelogs/71.txt b/fastlane/metadata/android/hi/changelogs/71.txt index 5facfc05f..c9b9675b0 100644 --- a/fastlane/metadata/android/hi/changelogs/71.txt +++ b/fastlane/metadata/android/hi/changelogs/71.txt @@ -1,10 +1,7 @@ -### Improvements -* Add app update notification for GitHub build (#1608 by @krtkush) -* Various improvements to the downloader (#1944 by @kapodamy): - * add missing white icons and use hardcored way for change the icon colors - * check if the iterator is initialized (fixes #2031) - * allow retry downloads with "post-processing failed" error in the new muxer - * new MPEG-4 muxer fixing non-synchronous video and audio streams (#2039) +### सुधार +* GitHub बिल्ड के लिए ऐप अपडेट नोटिफ़िकेशन जोड़ें (#1608 @krtkush द्वारा) +* डाउनलोडर में कई सुधार #1944 +* नया MPEG-4 म्यूक्सर नॉन-सिंक्रोनस वीडियो और ऑडियो स्ट्रीम को ठीक करता है (#2039) -### Fixed -* YouTube live streams stop playing after a short time (#1996 by @yausername) +### फिकसड +* YouTube लाइव स्ट्रीम थोड़े समय बाद चलना बंद हो जाती हैं (#1996 @yausername द्वारा) diff --git a/fastlane/metadata/android/hi/changelogs/740.txt b/fastlane/metadata/android/hi/changelogs/740.txt index c795978a8..9380af1b0 100644 --- a/fastlane/metadata/android/hi/changelogs/740.txt +++ b/fastlane/metadata/android/hi/changelogs/740.txt @@ -1,23 +1,12 @@ -

    Improvements

    +

    सुधार

      -
    • make links in comments clickable, increase text size
    • -
    • seek on clicking timestamp links in comments
    • -
    • show preferred tab based on recently selected state
    • -
    • add playlist to queue when long clicking on 'Background' in playlist window
    • -
    • search for shared text when it is not an URL
    • -
    • add "share at current time" button to the main video player
    • -
    • add close button to main player when video queue is finished
    • -
    • add "Play directly in Background" to longpress menu for video list items
    • -
    • improve English translations for Play/Enqueue commands
    • -
    • small performance improvements
    • -
    • remove unused files
    • -
    • update ExoPlayer to 2.9.6
    • -
    • add support for Invidious links
    • -
    -

    Fixed

    +
  • कमेंट्स में लिंक को क्लिक करने लायक बनाएं, टेक्स्ट का साइज़ बढ़ाएं
  • +
  • कमेंट्स में टाइमस्टैम्प लिंक पर क्लिक करने पर खोजें
  • +
  • जब शेयर किया गया टेक्स्ट URL न हो तो उसे खोजें
  • +
  • मेन वीडियो प्लेयर में "अभी के समय शेयर करें" बटन जोड़ें
  • +
  • ExoPlayer को 2.9.6 पर अपडेट करना
  • +

    फिकसड

    +
      -
    • fixed scroll w/ comments and related streams disabled
    • -
    • fixed CheckForNewAppVersionTask being executed when it shouldn't
    • -
    • fixed youtube subscription import: ignore ones with invalid url and keep ones with empty title
    • -
    • fix invalid YouTube url: signature tag name is not always "signature" preventing streams from loading
    • +
    • गलत YouTube URL ठीक करें: सिग्नेचर टैग का नाम हमेशा "सिग्नेचर" नहीं होता, जिससे स्ट्रीम लोड नहीं हो पातीं
    diff --git a/fastlane/metadata/android/hi/changelogs/750.txt b/fastlane/metadata/android/hi/changelogs/750.txt index 39b77f7c3..13e965311 100644 --- a/fastlane/metadata/android/hi/changelogs/750.txt +++ b/fastlane/metadata/android/hi/changelogs/750.txt @@ -1,22 +1,13 @@ -New -Playback resume #2288 -• Resume streams where you stopped last time -Downloader Enhancements #2149 -• Use Storage Access Framework to store downloads on external SD-cards -• New mp4 muxer -• Optionally change the download directory before starting a download -• Respect metered networks +नया +प्लेबैक फिर से शुरू करें #2288 +• स्ट्रीम वहीं से फिर से शुरू करें जहाँ आपने पिछली बार रोका था +डाउनलोडर एन्हांसमेंट #2149 +• एक्सटर्नल SD-कार्ड पर डाउनलोड स्टोर करने के लिए स्टोरेज एक्सेस फ्रेमवर्क का इस्तेमाल करें +बेहतर +• एक्टिविटी लाइफसाइकल के दौरान (ऑटो) रोटेशन में बदलाव को हैंडल करें #2444 +• लॉन्ग-प्रेस मेनू को एक जैसा बनाएं #2368 -Improved -• Removed gema strings #2295 -• Handle (auto)rotation changes during activity lifecycle #2444 -• Make long-press menus consistent #2368 - -Fixed -• Fixed selected subtitle track name not being shown #2394 -• Do not crash when check for app update fails (GitHub version) #2423 -• Fixed downloads stuck at 99.9% #2440 -• Update play queue metadata #2453 -• [SoundCloud] Fixed crash when loading playlists TeamNewPipe/NewPipeExtractor#170 -• [YouTube] Fixed duration can not be paresd TeamNewPipe/NewPipeExtractor#177 +ठीक किया गया +• चुने हुए सबटाइटल ट्रैक का नाम नहीं दिखना ठीक किया गया #2394 +• 99.9% पर अटके डाउनलोड को ठीक किया गया #2440 diff --git a/fastlane/metadata/android/hi/changelogs/760.txt b/fastlane/metadata/android/hi/changelogs/760.txt index 6e000f6d9..c4b6d951f 100644 --- a/fastlane/metadata/android/hi/changelogs/760.txt +++ b/fastlane/metadata/android/hi/changelogs/760.txt @@ -1,43 +1,13 @@ -Changes in 0.17.1 +0.17.1 में बदलाव -New -• Thai localization +नया +• थाई लोकलाइज़ेशन +बेहतर +• प्लेलिस्ट के लिए लॉन्ग-प्रेस मेनू में फिर से 'यहाँ से प्ले करना शुरू करें' एक्शन जोड़ें #2518 +• SAF / लेगेसी फ़ाइल पिकर के लिए स्विच जोड़ें #2521 -Improved -• Add start playing here action in long-press menus for playlists again #2518 -• Add switch for SAF / legacy file picker #2521 - -Fixed -• Fix disappearing buttons in downloads view when switching apps #2487 -• Fix playback position is stored although watch history is disabled -• Fix reduced performance caused by playback position in list views #2517 -• [Extractor] Fix ReCaptchaActivity #2527, TeamNewPipe/NewPipeExtractor#186 -• [Extractor] [YouTube] Fix casual search error when playlists are in results TeamNewPipe/NewPipeExtractor#185 - - - -Changes in 0.17.0 - -New -Playback resume #2288 -• Resume streams where you stopped last time -Downloader Enhancements #2149 -• Use Storage Access Framework to store downloads on external SD-cards -• New mp4 muxer -• Optionally change the download directory before starting a download -• Respect metered networks - - -Improved -• Removed gema strings #2295 -• Handle (auto)rotation changes during activity lifecycle #2444 -• Make long-press menus consistent #2368 - -Fixed -• Fixed selected subtitle track name not being shown #2394 -• Do not crash when check for app update fails (GitHub version) #2423 -• Fixed downloads stuck at 99.9% #2440 -• Update play queue metadata #2453 -• [SoundCloud] Fixed crash when loading playlists TeamNewPipe/NewPipeExtractor#170 -• [YouTube] Fixed duration can not be paresd TeamNewPipe/NewPipeExtractor#177 +ठीक किया गया +• ऐप बदलते समय डाउनलोड व्यू में बटन गायब होने की समस्या ठीक करें #2487 +• लिस्ट व्यू में प्लेबैक पोज़िशन की वजह से परफॉर्मेंस में आई कमी को ठीक करें #2517 +• [एक्सट्रैक्टर] [YouTube] जब प्लेलिस्ट रिज़ल्ट में हों तो कैज़ुअल सर्च एरर को ठीक करें TeamNewPipe/NewPipeExtractor#185 diff --git a/fastlane/metadata/android/hi/changelogs/790.txt b/fastlane/metadata/android/hi/changelogs/790.txt index ec77b2acb..3b322f0af 100644 --- a/fastlane/metadata/android/hi/changelogs/790.txt +++ b/fastlane/metadata/android/hi/changelogs/790.txt @@ -1,14 +1,9 @@ -Improved -• Add more titles to improve accessibility for blind people #2655 -• Make language of download folder setting more consistent and less ambiguous #2637 +ठीक किया गया +• चेक करें कि ब्लॉक में आखिरी बाइट डाउनलोड हुआ है या नहीं #2646 +• वीडियो डिटेल फ़्रैगमेंट में स्क्रॉलिंग को ठीक किया गया #2672 +• [साउंडक्लाउड] client_id एक्सट्रैक्शन को ठीक करें #2745 -Fixed -• Check if last byte in the block is downloaded #2646 -• Fixed scrolling in video detail fragment #2672 -• Remove double search clear box animations to one #2695 -• [SoundCloud] Fix client_id extraction #2745 - -Development -• Add missing dependencies inherited from NewPipeExtractor into NewPipe #2535 -• Migrate to AndroidX #2685 -• Update to ExoPlayer 2.10.6 #2697, #2736 +डेवलपमेंट +• NewPipeExtractor से मिली गायब डिपेंडेंसी को NewPipe में जोड़ें #2535 +• AndroidX पर माइग्रेट करें #2685 +• ExoPlayer 2.10.6 पर अपडेट करें #2697, #2736 diff --git a/fastlane/metadata/android/hi/changelogs/800.txt b/fastlane/metadata/android/hi/changelogs/800.txt index 332b5c994..4df518086 100644 --- a/fastlane/metadata/android/hi/changelogs/800.txt +++ b/fastlane/metadata/android/hi/changelogs/800.txt @@ -1,27 +1,10 @@ -New -• PeerTube support without P2P (#2201) [Beta]: - ◦ Watch and download videos from PeerTube instances - ◦ Add instances in the settings to access the complete PeerTube world - ◦ There might be problems with SSL handshakes on Android 4.4 and 7.1 when accessing certain instances resulting in a network error. +नया +• P2P के बिना PeerTube सपोर्ट (#2201) [बीटा]: -• Downloader (#2679): - ◦ Calculate download ETA - ◦ Download opus (webm files) as ogg - ◦ Recover expired download links to resume downloads after a long pause +◦ लंबे समय तक रुकने के बाद डाउनलोड फिर से शुरू करने के लिए एक्सपायर हो चुके डाउनलोड लिंक रिकवर करें -Improved -• Make the KioskFragment aware of changes in the preferred content country and improve performance of all main tabs #2742 -• Use new Localization and Downloader implementations from extractor #2713 -• Make "Default kiosk" string translatable -• Black navigation bar for black theme #2569 +बेहतर +• KioskFragment को पसंदीदा कंटेंट देश में होने वाले बदलावों के बारे में बताएं और सभी मेन टैब की परफॉर्मेंस को बेहतर बनाएं #2742 -Fixed -• Fixed a bug that could not move the popup player if another finger was placed while moving the popup player #2772 -• Allow playlists missing an uploader and fix crashes related to this problem #2724, TeamNewPipe/NewPipeExtractor#219 -• Enabling TLS1.1/1.2 on Android 4.4 devices (API 19/KitKat) to fix TLS handshake with MediaCCC and some PeerTube instances #2792 -• [SoundCloud] Fixed client_id extraction TeamNewPipe/NewPipeExtractor#217 -• [SoundCloud] Fix audio stream extraction - -Development -• Update ExoPlayer to 2.10.8 #2791, #2816 -• Update Gradle to 3.5.1 and add Kotlin support #2714 +फिक्स किया गया +• Android 4.4 डिवाइस (API 19/KitKat) पर TLS1.1/1.2 इनेबल करें diff --git a/fastlane/metadata/android/hi/changelogs/810.txt b/fastlane/metadata/android/hi/changelogs/810.txt index c75855fd1..b3d4c7bd6 100644 --- a/fastlane/metadata/android/hi/changelogs/810.txt +++ b/fastlane/metadata/android/hi/changelogs/810.txt @@ -1,19 +1,11 @@ -New -• Show video thumbnail on the lock screen when playing in the background +नया +• बैकग्राउंड में चलने पर लॉक स्क्रीन पर वीडियो थंमनेल दिखाएं -Improved -• Add local playlist to queue when long pressing on background / popup button -• Make main page tabs scrollable and hide when there is only a single tab -• Limit amount of notification thumbnail updates in background player -• Add dummy thumbnail for empty local playlists -• Use *.opus file extension instead of *.webm and show "opus" in format label instead of "WebM Opus" in the download dropdown -• Add button to delete downloaded files or download history in "Downloads" -• [YouTube] Add support to /c/shortened_url channel links +बेहतर +• बैकग्राउंड / पॉपअप बटन पर देर तक दबाने पर लोकल प्लेलिस्ट को क्यू में जोड़ें +• [YouTube] /c/shortened_url चैनल लिंक के लिए सपोर्ट जोड़ें -Fixed -• Fixed multiple issues when sharing a video to NewPipe and downloading its streams directly -• Fixed player access out of its creation thread -• Fixed search result paging -• [YouTube] Fixed switching on null causing NPE -• [YouTube] Fixed viewing comments when opening an invidio.us url -• [SoundCloud] Updated client_id +फिकसड +• NewPipe पर वीडियो शेयर करते समय और सीधे उसकी स्ट्रीम डाउनलोड करते समय कई दिक्कतें ठीक की गईं +• सर्च रिज़ल्ट पेजिंग ठीक की गई +• [SoundCloud] client_id अपडेट किया गया diff --git a/fastlane/metadata/android/hi/changelogs/840.txt b/fastlane/metadata/android/hi/changelogs/840.txt index 95dc80844..5be8a8660 100644 --- a/fastlane/metadata/android/hi/changelogs/840.txt +++ b/fastlane/metadata/android/hi/changelogs/840.txt @@ -1,22 +1,10 @@ -New -• Added language selector to change the app language -• Added send to Kodi button to player collapsible menu -• Added ability to copy comments on long press +नया +• ऐप की भाषा बदलने के लिए भाशा सिलेक्टर जोड़ा गया +• प्लेयर कोलैप्सिबल मेनू में कोडी को भेजें बटन जोड़ा गया +• देर तक दबाने पर कमेंट्स कॉपी करने की सुविधा जोड़ी गई -Improved -• Fix ReCaptcha activity and correctly save obtained cookies -• Removed dot-menu in favour of drawer and hide history button when watch history is not enabled in settings -• Ask for display over other apps permission in settings correctly on Android 6 and later -• Rename local playlist by long-clicking in BookmarkFragment -• Various PeerTube improvements -• Improved several English source strings +बेहतर +• ReCaptcha एक्टिविटी को ठीक किया गया और मिली हुई कुकीज़ को सही ढंग से सेव किया गया -Fixed -• Fixed player starting again although it is paused when option "minimize on app switch" enabled and NewPipe is minimized -• Fix initial brightness value for gesture -• Fixed .srt subtitle downloads containing not all line breaks -• Fixed download to SD card failing because some Android 5 devices are not CTF compliant -• Fixed downloading on Android KitKat -• Fixed corrupt video .mp4 file being recognized as audio file -• Fixed multiple localization problems, including wrong Chinese language codes -• [YouTube] Timestamps in description are clickable again +ठीक किया गया +• Android KitKat पर डाउनलोडिंग ठीक की गई diff --git a/fastlane/metadata/android/hi/changelogs/930.txt b/fastlane/metadata/android/hi/changelogs/930.txt index b23b01ea8..457d1745b 100644 --- a/fastlane/metadata/android/hi/changelogs/930.txt +++ b/fastlane/metadata/android/hi/changelogs/930.txt @@ -1,19 +1,13 @@ -New -• Search on YouTube Music -• Basic Android TV support +नया +• YouTube Music पर सर्च करें +• बेसिक Android TV सपोर्ट -Improved -• Added the ability to remove all watched videos from a local playlist -• Show message when content isn't supported yet instead of crashing -• Improved popup player resize with pinch gestures -• Enqueue streams on long press on background and popup buttons in channel -• Improved size handling of the drawer header title +बेहतर +• लोकल प्लेलिस्ट से सभी देखे गए वीडियो हटाने की सुविधा जोड़ी गई +• जब कंटेंट अभी सपोर्टेड न हो, तो क्रैश होने के बजाय मैसेज दिखाएं -Fixed -• Fixed age restricted content setting not working -• Fixed certain kinds of reCAPTCHAs -• Fixed crash when opening bookmarks while playlist is `null` -• Fixed detection of network related exceptions -• Fixed visibility of group sort button in the subscriptions fragment +फिकसड +• उम्र पर रोक वाली कंटेंट सेटिंग काम नहीं कर रही थी, इसे ठीक किया गया +• कुछ तरह के reCAPTCHA को ठीक किया गया -and more +और भी बहुत कुछ diff --git a/fastlane/metadata/android/hi/changelogs/940.txt b/fastlane/metadata/android/hi/changelogs/940.txt index f9530bc68..6f9253a2f 100644 --- a/fastlane/metadata/android/hi/changelogs/940.txt +++ b/fastlane/metadata/android/hi/changelogs/940.txt @@ -1,16 +1,14 @@ -New -• Add support for SoundCloud comments -• Add YouTube restricted mode setting -• Show PeerTube parent channel details +नया +• SoundCloud कमेंट्स के लिए सपोर्ट जोड़ें +• YouTube रेस्ट्रिक्टेड मोड सेटिंग जोड़ें +• PeerTube पेरेंट चैनल की डिटेल्स दिखाएँ -Improved -• Show Kore button only for supported services -• Block player gestures that begin at the NavigationBar or StatusBar -• Change retry & subscribe buttons background color based on service color +बेहतर +• सिर्फ़ सपोर्टेड सर्विसेज़ के लिए Kore बटन दिखाएँ -Fixed -• Fix download dialog freeze -• Open in browser button now really opens in browser -• Fix crash on opening videos and "Could not play this stream" +फिक्स किया गया +• डाउनलोड डायलॉग फ़्रीज़ होने की समस्या को ठीक करें +• ब्राउज़र में खोलें बटन अब सच में ब्राउज़र में खुलता है +• वीडियो खोलने पर क्रैश और "यह स्ट्रीम नहीं चला सका" -and more +और भी बहुत कुछ diff --git a/fastlane/metadata/android/hi/changelogs/951.txt b/fastlane/metadata/android/hi/changelogs/951.txt index e933e5cbd..ffc1f8891 100644 --- a/fastlane/metadata/android/hi/changelogs/951.txt +++ b/fastlane/metadata/android/hi/changelogs/951.txt @@ -1,17 +1,13 @@ -New -• Add search for subscription picker in the feed group dialog -• Add filter to the feed group dialog to show only ungrouped subscriptions -• Add playlist tab to main page -• Fast forward/rewind in background/pop-up player queue -• Display search suggestion: did you mean & showing result for +नया +• फ़ीड ग्रुप डायलॉग में सब्सक्रिप्शन पिकर के लिए सर्च जोड़ें +• फ़ीड ग्रुप डायलॉग में फ़िल्टर जोड़ें ताकि सिर्फ़ अनग्रुप्ड सब्सक्रिप्शन दिखें +• मेन पेज पर प्लेलिस्ट टैब जोड़ें -Improved -• Drop writing application metadata in muxed files -• Do not remove failed streams from the queue -• Update status bar color to match toolbar color +बेहतर +• म्यूक्स की गई फ़ाइलों में एप्लीकेशन मेटाडेटा लिखना बंद करें +• फ़ेल स्ट्रीम को क्यू से न हटाएं -Fixed -• Fixed audio/video desync caused by floating point cumulative errors -• [PeerTube] Handle deleted comments +फिकसड +• फ़्लोटिंग पॉइंट क्यूमुलेटिव एरर के कारण होने वाले ऑडियो/वीडियो डीसिंक को ठीक किया गया -and more +और भी बहुत कुछ diff --git a/fastlane/metadata/android/hi/changelogs/995.txt b/fastlane/metadata/android/hi/changelogs/995.txt index 63ed335a4..7bd7341c2 100644 --- a/fastlane/metadata/android/hi/changelogs/995.txt +++ b/fastlane/metadata/android/hi/changelogs/995.txt @@ -1,16 +1,14 @@ नया • चैनल टैब्स का समर्थन करें • छवि गुणवत्ता का चयन करें -• सभी छवियों के यूआरएल प्राप्त करें सुधार किए • प्लेयर इंटरफ़ेस की पहुंच • केवल-वीडियो डाउनलोड के लिए बेहतर ऑडियो चयन -• साझा प्लेलिस्ट सामग्री में प्लेलिस्ट और वीडियो नाम शामिल करने का विकल्प ठीक किए • [यूट्यूब] लाइक पाने की संख्या ठीक करें • पॉपअप और क्रैश पर प्रतिक्रिया नहीं देने वाले प्लेयर को ठीक करें • भाषा चयनकर्ता में गलत भाषाओं का चयन ठीक करें • प्लेयर ऑडियो फोकस म्यूट का सम्मान नहीं कर रहा था -• प्लेलिस्ट में आइटम जोड़ना कभी-कभी काम नहीं कर रहा था +• प्लेलिस्ट में आइटम ना जुड़ना ठीक किया diff --git a/fastlane/metadata/android/hi/changelogs/997.txt b/fastlane/metadata/android/hi/changelogs/997.txt index 652935884..b47816231 100644 --- a/fastlane/metadata/android/hi/changelogs/997.txt +++ b/fastlane/metadata/android/hi/changelogs/997.txt @@ -6,12 +6,9 @@ सुधार • [एंड्रॉइड 13+] कस्टम अधिसूचना क्रियाएं पुनर्स्थापित करें -• अपडेटस की जांच के लिए सहमति का अनुरोध करें -• बफ़रिंग के दौरान नोटीफिकेशन से चलाने/रोकने की अनुमति दें • कुछ सेटिंग्स पुनः व्यवस्थित करें ठीक किए • [यूट्यूब] लोड न होने वाली टिप्पणियों को ठीक करें, साथ ही अन्य फिक्स और सुधार भी -• सेटिंग्स आयात में भेद्यता को हल करें और JSON पर स्विच करें • विभिन्न डाउनलोड सुधार • खोज पाठ को ट्रिम करें diff --git a/fastlane/metadata/android/hu/changelogs/1006.txt b/fastlane/metadata/android/hu/changelogs/1006.txt new file mode 100644 index 000000000..a5cbf76eb --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/1006.txt @@ -0,0 +1,13 @@ +# Továbbfejlesztve +Az aktuális lejátszó megmarad időbélyegre kattintáskor +Függőben lévő letöltések helyreállításának megkísérlése +Letöltés törlése a fájl megtartásával +Overlay engedélyhez magyarázó párbeszédablak (Android 11+) +on.soundcloud hivatkozások támogatása +Sok kisebb fejlesztés és optimalizálás + +# Javítva +Számozás javítása Android 7 alatt +Szellem értesítések javítása +SRT felirat javítások +Sok összeomlás javítva diff --git a/fastlane/metadata/android/hu/changelogs/1007.txt b/fastlane/metadata/android/hu/changelogs/1007.txt new file mode 100644 index 000000000..f4de95e68 --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/1007.txt @@ -0,0 +1 @@ +Immáron minden YouTube videó lejátszásra kerül diff --git a/fastlane/metadata/android/id/changelogs/1005.txt b/fastlane/metadata/android/id/changelogs/1005.txt new file mode 100644 index 000000000..885f25ddb --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/1005.txt @@ -0,0 +1,17 @@ +Baru +• Dukungan untuk Android Auto +• Grup umpan sebagai tab layar utama +• [YouTube] Bagikan sebagai daftar putar sementara +• [SoundCloud] Tab saluran suka + +Ditingkatkan +• Petunjuk bilah pencarian lebih baik +• Tanggal unduhan di Unduhan +• Bahasa per aplikasi Android 13 + +Diperbaiki +• Warna teks rusak di mode gelap +• [YouTube] Daftar putar tidak lebih dari 100 item +• [YouTube] Video rekomendasi hilang +• Kerusakan di tampilan Riwayat +• Cap waktu dalam balasan komentar diff --git a/fastlane/metadata/android/id/changelogs/1007.txt b/fastlane/metadata/android/id/changelogs/1007.txt new file mode 100644 index 000000000..d3fea84ab --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/1007.txt @@ -0,0 +1 @@ +Memperbaiki YouTube yang tidak memutar streaming apa pun diff --git a/fastlane/metadata/android/it/changelogs/1006.txt b/fastlane/metadata/android/it/changelogs/1006.txt new file mode 100644 index 000000000..f7cbbf868 --- /dev/null +++ b/fastlane/metadata/android/it/changelogs/1006.txt @@ -0,0 +1,16 @@ +# Migliorie +Tieni il player attuale se si cliccano le marche temporali +Recupera i download in sospeso se possibile +Opzione per eliminare un download senza anche eliminare il file +Autorizzazione di sovrapposizione: mostra finestra esplicativa per Android > R +Supporto per link on.soundcloud +Tanti piccoli miglioramenti e ottimizzazioni + +# Correzioni +Formattazione breve del conto per Android < 7 +Notifiche fantasma +File di sottotitoli SRT +Crash vari + +# Sviluppo +Ammodernamento del codice interno diff --git a/fastlane/metadata/android/it/changelogs/1007.txt b/fastlane/metadata/android/it/changelogs/1007.txt new file mode 100644 index 000000000..3b5044d15 --- /dev/null +++ b/fastlane/metadata/android/it/changelogs/1007.txt @@ -0,0 +1,11 @@ +Risolto l’errore "Contenuto non disponibile": i video YouTube ora funzionano di nuovo! + +Risolti vari bug introdotti nella 0.28.1: +• Trascinamento elementi playlist limitato a posizioni adiacenti +• Titoli/commenti si alternano tra video corrente e precedente +• Opzione "Avvia riproduzione a schermo intero" non funzionante + +Altri miglioramenti: +• [YouTube] Riavvolgimento dirette fino a 4 ore +• Non caricare il video delle dirette riprodotte in background +• Nuova UI per "Rimuovi visti" \ No newline at end of file diff --git a/fastlane/metadata/android/ka/changelogs/1000.txt b/fastlane/metadata/android/ka/changelogs/1000.txt new file mode 100644 index 000000000..c59dcdbd0 --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/1000.txt @@ -0,0 +1,12 @@ +გაუმჯობესებულია +• დასაკრავი სიის აღწერა დაწკაპუნებით გახდა შესაძლებელი მეტი/ნაკლები კონტენტის საჩვენებლად +• [PeerTube] `subscribeto.me` ეგზემპლარის ბმულების ავტომატურად დამუშავება +• ისტორიის ეკრანზე მხოლოდ ერთი ერთეულის დაკვრა იწყება +გამოსწორებულია +• RSS ღილაკის ხილვადობის გამოსწორება +• ძიების ზოლის გადახედვის შეცდომის გამოსწორება +• გამოსწორდა დასაკრავი სიის მინიატურების გარეშე ელემენტის პრობლემა +• გამოსწორდა ჩამოტვირთვის დიალოგური ფანჯრის გამოჩენამდე გამორთვის პრობლემა +• დაკავშირებული ერთეულების სიის რიგში ჩასმის ამომხტარი ფანჯარა გამოსწორდა +• დასაკრავ სიაში დამატების დიალოგში თანმიმდევრობა გამოსწორდა +• დასაკრავი სიის სანიშნეების ელემენტის განლაგების კორექტირება diff --git a/fastlane/metadata/android/ka/changelogs/1001.txt b/fastlane/metadata/android/ka/changelogs/1001.txt new file mode 100644 index 000000000..63574fa11 --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/1001.txt @@ -0,0 +1,5 @@ +გაუმჯობესებულია +• Android 13+-ზე მოთამაშის შეტყობინებების პარამეტრების შეცვლის ყოველთვის დაშვება +გამოსწორებულია +• გამოსწორდა მონაცემთა ბაზის/გამოწერების ექსპორტირებისას არსებული ფაილის შეკვეცა, რამაც შესაძლოა ექსპორტის დაზიანება გამოიწვიოს. +• დროის ნიშნულზე გამოსწორდა დაწკაპუნებისას მოთამაშის თავიდან განახლება diff --git a/fastlane/metadata/android/ka/changelogs/1002.txt b/fastlane/metadata/android/ka/changelogs/1002.txt new file mode 100644 index 000000000..5b2eb01a8 --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/1002.txt @@ -0,0 +1,4 @@ +გამოსწორდა YouTube-ის არცერთი სტრიმინგის ჩატვირთვის პრობლემა. + +ეს ვერსია მხოლოდ ყველაზე აქტუალურ შეცდომას აგვარებს, რომელიც YouTube ვიდეოს დეტალების ჩატვირთვას ხელს უშლიდა. +ჩვენ ვიცით, რომ არსებობს სხვა პრობლემებიც და მალე გამოვაქვეყნებთ ცალკე ვერსიას მათ გადასაჭრელად. diff --git a/fastlane/metadata/android/ka/changelogs/1003.txt b/fastlane/metadata/android/ka/changelogs/1003.txt new file mode 100644 index 000000000..209362e25 --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/1003.txt @@ -0,0 +1,6 @@ +ეს არის ცხელი შესწორების ვერსია, რომელიც ასწორებს YouTube-ის შეცდომებს: +• [YouTube] გამოსწორდა ვიდეოს ინფორმაციის ჩატვირთვის შეუძლებლობა, გამოსწორდა HTTP 403 შეცდომები ვიდეოების დაკვრის დროს და აღდგა ასაკობრივი შეზღუდვის მქონე ზოგიერთი ვიდეოს დაკვრა +• გამოსწორდა სუბტიტრების ზომის შეუცვლელობა +• გამოსწორდა ინფორმაციის ორჯერ ჩამოტვირთვის პრობლემა ნაკადის გახსნისას +• [Soundcloud] წაიშალა დაუკრავი DRM-ით დაცული ნაკადები +• განახლდა თარგმანები diff --git a/fastlane/metadata/android/ka/changelogs/1004.txt b/fastlane/metadata/android/ka/changelogs/1004.txt index d20512f17..31f488a16 100644 --- a/fastlane/metadata/android/ka/changelogs/1004.txt +++ b/fastlane/metadata/android/ka/changelogs/1004.txt @@ -1 +1,3 @@ -გაასწორა YouTube არ უკრავს არცერთ ნაკადს +ეს ვერსია ასწორებს YouTube-ი აჩვებებს მხოლოდ 360p სტრიმინგის პრობლემას. + +გაითვალისწინეთ, რომ ამ ვერსიაში გამოყენებული გადაწყვეტა, სავარაუდოდ, დროებითია და გრძელვადიან პერსპექტივაში SABR ვიდეო პროტოკოლის დანერგვაა საჭირო, თუმცა TeamNewPipe-ის წევრები ამჟამად დაკავებულები არიან, ამიტომ ნებისმიერი დახმარება დიდად დასაფასებელი იქნება! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/ka/changelogs/1005.txt b/fastlane/metadata/android/ka/changelogs/1005.txt new file mode 100644 index 000000000..e08f2639f --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/1005.txt @@ -0,0 +1,15 @@ +ახალი +• დაემატა Android Auto-ს მხარდაჭერა +• არხების ჯგუფების მთავარი ეკრანის ჩანართებად დაყენების დაშვება +• [YouTube] გაზიარება, როგორც დროებითი დასაკრავი სია +• [SoundCloud] მოწონებების არხის ჩანართი +გაუმჯობესებულია +• უკეთესი მინიშნებები ძიების ზოლში +• ჩამოტვირთვის თარიღის ჩვენება ჩამოტვირთვებში +• Android 13-ის თითოეული აპლიკაციის ენის გამოყენება +.გამოსწორებულია +• გამოსწორდა ტექსტის ფერების დარღვევა ბნელ რეჟიმში +• [YouTube] გამოსწორდა დასაკრავი სიების 100-ზე მეტი ერთეულს არ აჩვენებს +• [YouTube] გამოსწორდა დაკარგული რეკომენდებული ვიდეოები +• გამოსწორდა ისტორიის სიის ხედში ავარიების გამოსწორება +• გამოსწორდა დროის ნიშნულები კომენტარების პასუხებში diff --git a/fastlane/metadata/android/ka/changelogs/1007.txt b/fastlane/metadata/android/ka/changelogs/1007.txt new file mode 100644 index 000000000..d20512f17 --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/1007.txt @@ -0,0 +1 @@ +გაასწორა YouTube არ უკრავს არცერთ ნაკადს diff --git a/fastlane/metadata/android/ka/changelogs/63.txt b/fastlane/metadata/android/ka/changelogs/63.txt index 185bfd650..76d878325 100644 --- a/fastlane/metadata/android/ka/changelogs/63.txt +++ b/fastlane/metadata/android/ka/changelogs/63.txt @@ -1,8 +1,7 @@ ### გაუმჯობესებები - - იმპორტი/ექსპორტის პარამეტრები #1333 - - ზედრევის შემცირება (შესრულების გაუმჯობესება) #1371 - - მცირე კოდის გაუმჯობესება #1375 - - დაამატეთ ყველაფერი GDPR #1420-ის შესახებ - - ### გამოსწორდა - - Downloader: შეასწორეთ ავარია დაუმთავრებელი ჩამოტვირთვების ჩატვირთვისას .giga ფაილებიდან #1407 +- იმპორტის/ექსპორტის პარამეტრები #1333 +- ზედმეტად დიდი მოცულობის შეცდომის შემცირება (შესრულების გაუმჯობესება) #1371 +- კოდის მცირე გაუმჯობესებები #1375 +- GDPR-ის შესახებ ყველაფრის დამატება #1420 +### გამოსწორებულია +- ჩამომტვირთავი: გამოასწორეთ შეცდომის პრობლემა .giga ფაილებიდან დაუმთავრებელი ჩამოტვირთვების ჩატვირთვისას#1407 diff --git a/fastlane/metadata/android/ka/changelogs/65.txt b/fastlane/metadata/android/ka/changelogs/65.txt new file mode 100644 index 000000000..8ddbda2b7 --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/65.txt @@ -0,0 +1,23 @@ +### გაუმჯობესებები +- ბურგერის მენიუს ხატულას ანიმაციის გამორთვა #1486 +- ჩამოტვირთვების წაშლის გაუქმების ღილაკი #1472 +- ჩამოტვირთვის ღილაკი გაზიარების მენიუში #1498 +- ხანგრძლივი შეხების მენიუში #1454 დაემატა გაზიარების ღილაკი +- მთავარი პლეერის მინიმიზაცია გასვლისას #1354 +- ბიბლიოთეკის ვერსიის განახლება და მონაცემთა ბაზის სარეზერვო ასლის შესწორება #1510 +- ExoPlayer 2.8.2 განახლება #1392 +- გადამუშავდა დაკვრის სიჩქარის კონტროლის დიალოგი, რათა მხარდაჭერილიყო სხვადასხვა ნაბიჯების ზომები სიჩქარის უფრო სწრაფი ცვლილებისთვის. +- დაკვრის სიჩქარის კონტროლში დაემატა გადამრთველი სიჩუმის დროს წინ გადასართავად. ეს უნდა იყოს სასარგებლო აუდიოწიგნებისა და გარკვეული მუსიკალური ჟანრებისთვის და შეიძლება უზრუნველყოს ჭეშმარიტად შეუფერხებელი გამოცდილება (და შეიძლება დაარღვიოს სიმღერა, რომელსაც ბევრი სიჩუმე აქვს =\\). +- გადაკეთდა მედია წყაროს გარჩევადობა, რათა მეტამონაცემების გადაცემა მედიასთან ერთად პლეერში შიდა რეჟიმში მოხდეს, ხელით გაკეთების ნაცვლად. ახლა ჩვენ გვაქვს მეტამონაცემების ერთი წყარო და ის პირდაპირ ხელმისაწვდომია დაკვრის დაწყებისას. + - გამოსწორდა დისტანციური დასაკრავი სიის მეტამონაცემების განახლება, როდესაც ახალი მეტამონაცემები ხელმისაწვდომია დასაკრავი სიის ფრაგმენტის გახსნისას. +- სხვადასხვა ინტერფეისის გამოსწორება: #1383, ფონური პლეერის შეტყობინებების კონტროლი ახლა ყოველთვის თეთრია, უფრო ადვილია ამომხტარი პლეერის გამორთვა გადახვევით. +- გამოიყენეთ ახალი ექსტრაქტორი განახლებული არქიტექტურით მრავალსერვისისთვის. +### გამოსწორებები +- გამოსწორდა #1440 ვიდეო ინფორმაციის გაფუჭებული განლაგება #1491 +- გამოსწორდა ნახვის ისტორია#1497 +- #1495, მეტამონაცემების (მინიატურების, სათაურის და ვიდეოების რაოდენობის) განახლებით, როგორც კი მომხმარებელი წვდება დასაკრავ სიას. +- #1475, ხედვის რეგისტრაციით მონაცემთა ბაზაში, როდესაც მომხმარებელი იწყებს ვიდეოს გარე პლეერზე დეტალების ფრაგმენტზე. +- გამოსწორდა ეკრანის დროის ამოწურვა ამომხტარი რეჟიმის შემთხვევაში. #1463 (გამოსწორდა #640) +- მთავარი ვიდეო პლეერის გამოსწორება #1509 +- [#1412] გამოსწორდა გამეორების რეჟიმი, რომელიც იწვევდა პლეერის NPE-ს, როდესაც ახალი განზრახვა მიიღება, როდესაც მოთამაშის აქტივობა ფონურ რეჟიმშია. + - გამოსწორდა მოთამაშის ამომხტარ ფანჯარაში მინიმიზაციის შეცდომა, როდესაც ამომხტარ ფანჯარაში ნებართვა არ არის მინიჭებული. diff --git a/fastlane/metadata/android/ka/changelogs/996.txt b/fastlane/metadata/android/ka/changelogs/996.txt new file mode 100644 index 000000000..7da3ca0ed --- /dev/null +++ b/fastlane/metadata/android/ka/changelogs/996.txt @@ -0,0 +1,2 @@ +media.ccc.de-ზე არხის/კონფერენციის გახსნისას გამოსწორდა NullPointerException. +გრინჩმა სცადა თქვენთვის საშობაო საჩუქრის გატეხვა, მაგრამ ჩვენ გამოვასწორეთ. diff --git a/fastlane/metadata/android/ko/changelogs/1000.txt b/fastlane/metadata/android/ko/changelogs/1000.txt new file mode 100644 index 000000000..d2f5bf58a --- /dev/null +++ b/fastlane/metadata/android/ko/changelogs/1000.txt @@ -0,0 +1,13 @@ +개선됨 (Improved) +• 재생목록 설명을 클릭하여 더 보기 / 간단히 보기 전환 가능 +• [PeerTube] `subscribeto.me` 인스턴스 링크 자동 처리 +• 기록 화면에서 단일 항목만 재생 시작 + +수정됨 (Fixed) +• RSS 버튼 표시 문제 수정 +• 탐색바 미리보기 충돌 수정 +• 썸네일이 없는 항목 재생목록 추가 문제 수정 +• 다운로드 대화상자가 나타나기 전에 종료되는 문제 수정 +• 관련 항목 목록의 대기열 팝업 수정 +• 재생목록에 추가 대화상자의 순서 문제 수정 +• 재생목록 북마크 항목 레이아웃 조정 diff --git a/fastlane/metadata/android/ko/changelogs/1006.txt b/fastlane/metadata/android/ko/changelogs/1006.txt new file mode 100644 index 000000000..1729e9827 --- /dev/null +++ b/fastlane/metadata/android/ko/changelogs/1006.txt @@ -0,0 +1,16 @@ +# 개선됨 +타임스탬프를 클릭할 때 현재 플레이어를 유지합니다. +가능한 경우 보류 중인 다운로드 미션을 복구하세요. +파일 삭제 없이 다운로드를 삭제하는 옵션을 추가하세요. +오버레이 권한: Android > R에 대한 설명 대화 상자 표시 +사운드클라우드 링크 열기 지원 +많은 작은 개선과 최적화 + +# 고정 +7 이하의 안드로이드 버전에 대한 짧은 숫자 형식을 수정하세요. +고스트 알림 수정 +SRT 자막 파일 수정 +고정된 수많은 충돌 사고 + +# 개발 +내부 코드 현대화 diff --git a/fastlane/metadata/android/ko/changelogs/1007.txt b/fastlane/metadata/android/ko/changelogs/1007.txt new file mode 100644 index 000000000..39ea56541 --- /dev/null +++ b/fastlane/metadata/android/ko/changelogs/1007.txt @@ -0,0 +1 @@ +YouTube에서 스트림을 재생하지 않는 문제 수정 diff --git a/fastlane/metadata/android/lmo/full_description.txt b/fastlane/metadata/android/lmo/full_description.txt new file mode 100644 index 000000000..6a6055c29 --- /dev/null +++ b/fastlane/metadata/android/lmo/full_description.txt @@ -0,0 +1 @@ +NewPipe al drœva nissuna libreria framework del Google o l'API del YouTube. Al scandiss domà el sit web per ciapar su i informazione de qe n'ha bisogn. Per qella rexon qì qell'aplicazion qì la pœl vesser doperada ind aparecc senza i Servizi Google installad. G'è nanca bisogn d'haver-g un cunt YouTube per doperar NewPipe e a l'è FLOSS. diff --git a/fastlane/metadata/android/lmo/short_description.txt b/fastlane/metadata/android/lmo/short_description.txt new file mode 100644 index 000000000..417963085 --- /dev/null +++ b/fastlane/metadata/android/lmo/short_description.txt @@ -0,0 +1 @@ +Un frontend YouTube ligier per Android. diff --git a/fastlane/metadata/android/lv/changelogs/63.txt b/fastlane/metadata/android/lv/changelogs/63.txt index 94c6a06df..585d8b461 100644 --- a/fastlane/metadata/android/lv/changelogs/63.txt +++ b/fastlane/metadata/android/lv/changelogs/63.txt @@ -1,8 +1,8 @@ ### Uzlabojumi -- Iestatījumu importēšana/eksportēšana #1333 +- Ievietot/izgūt iestatījumus #1333 - Samazināts pārzīmēšanas skaits (veiktspējas uzlabojums) #1371 - Nelieli koda uzlabojumi #1375 -- Pievienots viss par GDPR #1420 +- Pievienota visa informācija par GDPR #1420 ### Salabots -- Lejupielādētājs: Salabota lietotnes nobrukšana turpinot lejupielādēt nepabeigtās .giga failu lejupielādes #1407 +- Lejupielādētājs: Salabota lietotnes nobrukšana ielādējot nepabeigtās .giga datņu lejupielādes #1407 diff --git a/fastlane/metadata/android/nl/changelogs/1007.txt b/fastlane/metadata/android/nl/changelogs/1007.txt new file mode 100644 index 000000000..9bd8adf86 --- /dev/null +++ b/fastlane/metadata/android/nl/changelogs/1007.txt @@ -0,0 +1 @@ +YouTube speelt geen stream af opgelost diff --git a/fastlane/metadata/android/pa/changelogs/1000.txt b/fastlane/metadata/android/pa/changelogs/1000.txt index 90d70c151..ddc239f32 100644 --- a/fastlane/metadata/android/pa/changelogs/1000.txt +++ b/fastlane/metadata/android/pa/changelogs/1000.txt @@ -3,11 +3,9 @@ • [PeerTube] `subscribeto.me` ਇੰਸਟੈਂਸ ਲਿੰਕਾਂ ਨੂੰ ਆਟੋਮੈਟਿਕ ਹੀ ਹੈਂਡਲ ਕਰੋ • ਇਤਿਹਾਸ ਸਕਰੀਨ ਵਿੱਚ ਸਿਰਫ਼ ਸਿੰਗਲ ਆਈਟਮ ਨੂੰ ਚਲਾਉਣਾ ਸ਼ੁਰੂ ਕਰੋ -ਠੀਕ ਕਰਿਆ +ਫਿਕਸਡ • RSS ਬਟਨ ਦੀ ਦਿੱਖ ਨੂੰ ਠੀਕ ਕਰੋ • ਸੀਕਬਾਰ ਪੂਰਵਦਰਸ਼ਨ ਕ੍ਰੈਸ਼ਾਂ ਨੂੰ ਠੀਕ ਕਰੋ • ਥੰਮਨੇਲ-ਰਹਿਤ ਆਈਟਮ ਦੀ ਪਲੇਲਿਸਟਿੰਗ ਨੂੰ ਠੀਕ ਕਰੋ -• ਡਾਉਨਲੋਡ ਡਾਇਲਾਗ ਦੇ ਦਿਸਣ ਤੋਂ ਪਹਿਲਾਂ ਇਸਨੂੰ ਬਾਹਰ ਕੱਢਣਾ ਠੀਕ ਕਰੋ -• ਸੰਬੰਧਿਤ ਆਈਟਮਾਂ ਦੀ ਸੂਚੀ ਐਨਕਿਊ ਪੌਪਅੱਪ ਨੂੰ ਠੀਕ ਕਰੋ -• ਪਲੇਲਿਸਟ ਡਾਇਲਾਗ ਵਿੱਚ ਜੋੜਨ ਦਾ ਕ੍ਰਮ ਠੀਕ ਕਰੋ -• ਪਲੇਲਿਸਟ ਬੁੱਕਮਾਰਕ ਆਈਟਮ ਖਾਕਾ ਵਿਵਸਥਿਤ ਕਰੋ +• ਸੰਬੰਧਿਤ ਆਈਟਮਾਂ ਦੀ ਸੂਚੀ ਐਨਕਿਊ ਪੌਪ-ਅਪ ਨੂੰ ਠੀਕ ਕਰੋ +• ਅਤੇ ਹੋਰ ਪਲੇਲਿਸਟ ਤੇ ਡਾਊਨਲੋਡ ਸਬੰਧਤ ਫਿਕਸ diff --git a/fastlane/metadata/android/pa/changelogs/1004.txt b/fastlane/metadata/android/pa/changelogs/1004.txt index fe62a1330..6d3d23b2e 100644 --- a/fastlane/metadata/android/pa/changelogs/1004.txt +++ b/fastlane/metadata/android/pa/changelogs/1004.txt @@ -1 +1,3 @@ -ਸਥਿਰ YouTube ਕੋਈ ਸਟ੍ਰੀਮ ਨਹੀਂ ਚਲਾ ਰਿਹਾ +ਇਹ ਰੀਲੀਜ਼ ਸਿਰਫ਼ 360p ਸਟ੍ਰੀਮ ਪ੍ਰਦਾਨ ਕਰਨ ਵਾਲੇ YouTube ਨੂੰ ਠੀਕ ਕਰਦੀ ਹੈ। + +ਧਿਆਨ ਦਿਓ ਕਿ ਇਸ ਸੰਸਕਰਣ ਵਿੱਚ ਵਰਤਿਆ ਗਿਆ ਹੱਲ ਸੰਭਾਵਤ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹੈ, ਅਤੇ ਲੰਬੇ ਸਮੇਂ ਵਿੱਚ SABR ਵੀਡੀਓ ਪ੍ਰੋਟੋਕੋਲ ਨੂੰ ਲਾਗੂ ਕਰਨ ਦੀ ਜ਼ਰੂਰਤ ਹੈ, ਪਰ TeamNewPipe ਮੈਂਬਰ ਇਸ ਸਮੇਂ ਰੁੱਝੇ ਹੋਏ ਹਨ ਇਸ ਲਈ ਕਿਸੇ ਵੀ ਮਦਦ ਦੀ ਬਹੁਤ ਪ੍ਰਸ਼ੰਸਾ ਕੀਤੀ ਜਾਵੇਗੀ! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/pa/changelogs/1005.txt b/fastlane/metadata/android/pa/changelogs/1005.txt index f1492a1ac..982b092a4 100644 --- a/fastlane/metadata/android/pa/changelogs/1005.txt +++ b/fastlane/metadata/android/pa/changelogs/1005.txt @@ -1,17 +1,10 @@ ਨਵਾਂ -+ • Android Auto ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਿਲ ਕਰੋ -+ • ਫੀਡ ਗਰੁੱਪਾਂ ਨੂੰ ਮੁੱਖ ਸਕ੍ਰੀਨ ਟੈਬਾਂ ਵਜੋਂ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ -+ • [YouTube] ਅਸਥਾਈ ਪਲੇਲਿਸਟ ਦੇ ਵਜੋਂ ਸਾਂਝਾ ਕਰੋ -+ • [SoundCloud] "ਪਸੰਦ" ਚੈਨਲ ਟੈਬ ਜੋੜੀ ਗਈ - -ਬਿਹਤਰ ਕੀਤੇ -+ • ਖੋਜ ਬਾਰ ਸੰਕੇਤ -+ • ਡਾਊਨਲੋਡਸ ਸੂਚੀ ਵਿੱਚ ਡਾਊਨਲੋਡ ਤਾਰੀਖ ਦਿਖਾਓ -+ • ਐਂਡਰਾਇਡ 13+ 'ਤੇ ਪ੍ਰਤੀ ਐਪ ਭਾਸ਼ਾ ਦੀ ਵਰਤੋਂ ਕਰੋ +• Android Auto ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਿਲ ਕਰਨ ਸਮੇਤ YouTube ਲਈ ਅਸਥਾਈ ਪਲੇਲਿਸਟ ਵਜੋਂ ਸ਼ੇਅਰ ਫੰਕਸ਼ਨ ਤੇ SoundCloud ਲਈ ਲਾਈਕਸ ਚੈਨਲ ਟੈਬ ਨਵੀਂ ਐਡ ਕੀਤੀ +• ਫੀਡ ਗਰੁੱਪਾਂ ਨੂੰ ਮੁੱਖ ਸਕ੍ਰੀਨ ਟੈਬਾਂ ਵਜੋਂ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ ਦਰੁਸਤ ਕੀਤੇ -+ • ਡਾਰਕ ਥੀਮਾਂ 'ਤੇ ਟੈਕਸਟ ਰੰਗਾਂ ਨੂੰ ਠੀਕ ਕਰੋ -+ • [YouTube] ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਠੀਕ ਕਰੋ ਜੋ 100 ਤੋਂ ਵੱਧ ਆਈਟਮਾਂ ਲੋਡ ਨਹੀਂ ਕਰਦੀਆਂ -+ • [YouTube] ਸਿਫਾਰਸ਼ ਕੀਤੀਆਂ ਵੀਡੀਓਜ਼ ਦੀ ਅਣਉਪਲੱਬਧਤਾ ਨੂੰ ਠੀਕ ਕਰੋ -+ • ਇਤਿਹਾਸ ਸੂਚੀ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਕ੍ਰੈਸ਼ ਨੂੰ ਠੀਕ ਕਰੋ -+ • ਟਿੱਪਣੀਆਂ ਦੇ ਜਵਾਬ ਵਿੱਚ ਟਾਈਮਸਟੈਂਪਾਂ ਨੂੰ ਠੀਕ ਕਰੋ +• ਡਾਰਕ ਥੀਮਾਂ 'ਤੇ ਟੈਕਸਟ ਰੰਗਾਂ ਨੂੰ ਠੀਕ ਕਰੋ +• [YouTube] ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਠੀਕ ਕਰੋ ਜੋ 100 ਤੋਂ ਵੱਧ ਆਈਟਮਾਂ ਲੋਡ ਨਹੀਂ ਕਰਦੀਆਂ +• [YouTube] ਸਿਫਾਰਸ਼ ਕੀਤੀਆਂ ਵੀਡੀਓਜ਼ ਦੀ ਅਣਉਪਲੱਬਧਤਾ ਨੂੰ ਠੀਕ ਕਰੋ +• ਟਿੱਪਣੀਆਂ ਦੇ ਜਵਾਬ ਵਿੱਚ ਟਾਈਮਸਟੈਂਪਾਂ ਨੂੰ ਠੀਕ ਕਰੋ +ਪੂਰੇ ਬਦਲਾਵਾਂ ਵਾਸਤੇ ਗਿਟਹੱਬ ਤੇ dev ਸ਼ਾਖਾ ਟੈਗ ਅਨੁਸਾਰ ਬਦਲਾਅ ਵੇਖੋ diff --git a/fastlane/metadata/android/pa/changelogs/1006.txt b/fastlane/metadata/android/pa/changelogs/1006.txt new file mode 100644 index 000000000..5046eaaa0 --- /dev/null +++ b/fastlane/metadata/android/pa/changelogs/1006.txt @@ -0,0 +1,9 @@ +# ਸੁਧਾਰਿਆ ਗਿਆ +ਟਾਈਮਸਟੈਂਪਾਂ 'ਤੇ ਕਲਿੱਕ ਕਰਦੇ ਸਮੇਂ ਮੌਜੂਦਾ ਪਲੇਅਰ ਰੱਖੋ +ਜਦੋਂ ਸੰਭਵ ਹੋਵੇ ਤਾਂ ਬਕਾਇਆ ਡਾਊਨਲੋਡ ਮਿਸ਼ਨਾਂ ਨੂੰ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ +ਫਾਈਲ ਨੂੰ ਮਿਟਾਏ ਬਿਨਾਂ ਡਾਊਨਲੋਡ ਨੂੰ ਮਿਟਾਉਣ ਦਾ ਵਿਕਲਪ ਸ਼ਾਮਿਲ ਕਰੋ +on.soundcloud ਲਿੰਕ ਖੋਲ੍ਹਣ ਦਾ ਸਮਰਥਨ ਕਰੋ +7 ਤੋਂ ਘੱਟ ਐਂਡਰਾਇਡ ਸੰਸਕਰਣਾਂ ਲਈ ਛੋਟੀ ਗਿਣਤੀ ਫਾਰਮੈਟਿੰਗ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ +ਖਾਲੀ ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ +SRT ਉਪਸਿਰਲੇਖ ਫਾਈਲਾਂ ਲਈ ਠੀਕ ਕੀਤਾ ਗਿਆ +ਬਹੁਤ ਸਾਰੇ ਕਰੈਸ਼ ਠੀਕ ਕੀਤੇ ਗਏ diff --git a/fastlane/metadata/android/pa/changelogs/1007.txt b/fastlane/metadata/android/pa/changelogs/1007.txt new file mode 100644 index 000000000..fe62a1330 --- /dev/null +++ b/fastlane/metadata/android/pa/changelogs/1007.txt @@ -0,0 +1 @@ +ਸਥਿਰ YouTube ਕੋਈ ਸਟ੍ਰੀਮ ਨਹੀਂ ਚਲਾ ਰਿਹਾ diff --git a/fastlane/metadata/android/pa/changelogs/65.txt b/fastlane/metadata/android/pa/changelogs/65.txt index 0fbf1147e..0f7f8fe7d 100644 --- a/fastlane/metadata/android/pa/changelogs/65.txt +++ b/fastlane/metadata/android/pa/changelogs/65.txt @@ -1 +1,13 @@ -### ਸੁਧਾਰ - ਬਰਗਰਮੇਨੂ ਆਈਕਨ ਐਨੀਮੇਸ਼ਨ #1486 ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ - ਡਾਉਨਲੋਡਸ #1472 ਨੂੰ ਮਿਟਾਉਣ ਨੂੰ ਅਨਡੂ ਕਰੋ - ਸ਼ੇਅਰ ਮੀਨੂ #1498 ਵਿੱਚ ਡਾਊਨਲੋਡ ਵਿਕਲਪ - ਲੰਬੇ ਟੈਪ ਮੀਨੂ #1454 ਵਿੱਚ ਸ਼ੇਅਰ ਵਿਕਲਪ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ - ਨਿਕਾਸ #1354 'ਤੇ ਮੁੱਖ ਪਲੇਅਰ ਨੂੰ ਛੋਟਾ ਕਰੋ - ਲਾਇਬ੍ਰੇਰੀ ਸੰਸਕਰਣ ਅਪਡੇਟ ਅਤੇ ਡੇਟਾਬੇਸ ਬੈਕਅਪ ਫਿਕਸ #1510 - ExoPlayer 2.8.2 ਅੱਪਡੇਟ #1392 - ਤੇਜ਼ ਗਤੀ ਤਬਦੀਲੀ ਲਈ ਵੱਖ-ਵੱਖ ਸਟੈਪ ਸਾਈਜ਼ ਦਾ ਸਮਰਥਨ ਕਰਨ ਲਈ ਪਲੇਬੈਕ ਸਪੀਡ ਕੰਟਰੋਲ ਡਾਇਲਾਗ ਨੂੰ ਦੁਬਾਰਾ ਬਣਾਇਆ ਗਿਆ। - ਪਲੇਬੈਕ ਸਪੀਡ ਨਿਯੰਤਰਣ ਵਿੱਚ ਚੁੱਪ ਦੌਰਾਨ ਫਾਸਟ-ਫਾਰਵਰਡ ਕਰਨ ਲਈ ਇੱਕ ਟੌਗਲ ਜੋੜਿਆ ਗਿਆ। ਇਹ ਆਡੀਓਬੁੱਕਾਂ ਅਤੇ ਕੁਝ ਸੰਗੀਤ ਸ਼ੈਲੀਆਂ ਲਈ ਮਦਦਗਾਰ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ, ਅਤੇ ਇੱਕ ਸੱਚਾ ਸਹਿਜ ਅਨੁਭਵ ਲਿਆ ਸਕਦਾ ਹੈ (ਅਤੇ ਬਹੁਤ ਸਾਰੀਆਂ ਚੁੱਪ =\\ ਨਾਲ ਗੀਤ ਤੋੜ ਸਕਦਾ ਹੈ)। - ਹੱਥੀਂ ਅਜਿਹਾ ਕਰਨ ਦੀ ਬਜਾਏ, ਪਲੇਅਰ ਵਿੱਚ ਅੰਦਰੂਨੀ ਤੌਰ 'ਤੇ ਮੀਡੀਆ ਦੇ ਨਾਲ-ਨਾਲ ਮੈਟਾਡੇਟਾ ਪਾਸ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣ ਲਈ ਰੀਫੈਕਟਰਡ ਮੀਡੀਆ ਸਰੋਤ ਰੈਜ਼ੋਲਿਊਸ਼ਨ। ਹੁਣ ਸਾਡੇ ਕੋਲ ਮੈਟਾਡੇਟਾ ਦਾ ਇੱਕ ਸਿੰਗਲ ਸਰੋਤ ਹੈ ਅਤੇ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋਣ 'ਤੇ ਸਿੱਧਾ ਉਪਲਬਧ ਹੁੰਦਾ ਹੈ। - ਸਥਿਰ ਰਿਮੋਟ ਪਲੇਲਿਸਟ ਮੈਟਾਡੇਟਾ ਅੱਪਡੇਟ ਨਹੀਂ ਹੋ ਰਿਹਾ ਹੈ ਜਦੋਂ ਪਲੇਲਿਸਟ ਫਰੈਗਮੈਂਟ ਖੋਲ੍ਹਿਆ ਜਾਂਦਾ ਹੈ ਤਾਂ ਨਵਾਂ ਮੈਟਾਡੇਟਾ ਉਪਲਬਧ ਹੁੰਦਾ ਹੈ। - ਕਈ UI ਫਿਕਸ: #1383, ਬੈਕਗਰਾਊਂਡ ਪਲੇਅਰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਕੰਟਰੋਲ ਹੁਣ ਹਮੇਸ਼ਾ ਸਫੈਦ, ਫਲਿੰਗਿੰਗ ਰਾਹੀਂ ਪੌਪਅੱਪ ਪਲੇਅਰ ਨੂੰ ਬੰਦ ਕਰਨਾ ਆਸਾਨ - ਮਲਟੀਸਰਵਿਸ ਲਈ ਰੀਫੈਕਟਰਡ ਆਰਕੀਟੈਕਚਰ ਦੇ ਨਾਲ ਨਵੇਂ ਐਕਸਟਰੈਕਟਰ ਦੀ ਵਰਤੋਂ ਕਰੋ ### ਫਿਕਸ - #1440 ਟੁੱਟੇ ਹੋਏ ਵੀਡੀਓ ਜਾਣਕਾਰੀ ਲੇਆਉਟ #1491 ਨੂੰ ਠੀਕ ਕਰੋ - ਇਤਿਹਾਸ ਫਿਕਸ #1497 ਦੇਖੋ - #1495, ਜਿਵੇਂ ਹੀ ਉਪਭੋਗਤਾ ਪਲੇਲਿਸਟ ਤੱਕ ਪਹੁੰਚ ਕਰਦਾ ਹੈ, ਮੈਟਾਡੇਟਾ (ਥੰਬਨੇਲ, ਸਿਰਲੇਖ ਅਤੇ ਵੀਡੀਓ ਗਿਣਤੀ) ਨੂੰ ਅਪਡੇਟ ਕਰਕੇ। - #1475, ਜਦੋਂ ਉਪਭੋਗਤਾ ਵੇਰਵੇ ਦੇ ਟੁਕੜੇ 'ਤੇ ਬਾਹਰੀ ਪਲੇਅਰ 'ਤੇ ਵੀਡੀਓ ਸ਼ੁਰੂ ਕਰਦਾ ਹੈ ਤਾਂ ਡੇਟਾਬੇਸ ਵਿੱਚ ਇੱਕ ਦ੍ਰਿਸ਼ ਨੂੰ ਰਜਿਸਟਰ ਕਰਕੇ। - ਪੌਪਅੱਪ ਮੋਡ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਕ੍ਰੀਨ ਟਾਈਮਆਊਟ ਫਿਕਸ ਕਰੋ। #1463 (ਸਥਿਰ #640) - ਮੁੱਖ ਵੀਡੀਓ ਪਲੇਅਰ ਫਿਕਸ #1509 - [#1412] ਫਿਕਸਡ ਰੀਪੀਟ ਮੋਡ ਜਿਸ ਨਾਲ ਪਲੇਅਰ ਐਨਪੀਈ ਦਾ ਕਾਰਨ ਬਣਦਾ ਹੈ ਜਦੋਂ ਪਲੇਅਰ ਦੀ ਗਤੀਵਿਧੀ ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਹੁੰਦੀ ਹੈ ਤਾਂ ਨਵਾਂ ਇਰਾਦਾ ਪ੍ਰਾਪਤ ਹੁੰਦਾ ਹੈ। - ਪੌਪਅੱਪ ਲਈ ਫਿਕਸਡ ਮਿਨੀਮਾਈਜ਼ਿੰਗ ਪਲੇਅਰ ਪਲੇਅਰ ਨੂੰ ਨਸ਼ਟ ਨਹੀਂ ਕਰਦਾ ਹੈ ਜਦੋਂ ਪੌਪਅੱਪ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। +### ਸੁਧਾਰ + +- ਬਰਗਰ ਮੀਨੂ ਆਈਕਨ ਐਨੀਮੇਸ਼ਨ ਨੂੰ ਅਯੋਗ ਕਰੋ #1486 +- ਡਾਊਨਲੋਡਸ ਨੂੰ ਅਨਡੂ ਕਰੋ #1472 +- ਸ਼ੇਅਰ ਮੀਨੂ ਵਿੱਚ ਡਾਊਨਲੋਡ ਵਿਕਲਪ #1498 +- ਲੰਬੇ ਟੈਪ ਮੀਨੂ ਵਿੱਚ ਸਾਂਝਾ ਵਿਕਲਪ ਜੋੜਿਆ ਗਿਆ #1454 +- ਐਕਸੋਪਲੇਅਰ 2.8.2 ਅਪਡੇਟ #1392 +- ਕਈ UI ਫਿਕਸ: #1383 + +### ਫਿਕਸ + +- ਵਿਊ ਹਿਸਟਰੀ ਫਿਕਸ #1497 +- #1495, ਜਿਵੇਂ ਹੀ ਉਪਭੋਗਤਾ ਪਲੇਲਿਸਟ ਤੱਕ ਪਹੁੰਚ ਕਰਦਾ ਹੈ, ਮੈਟਾਡੇਟਾ (ਥੰਬਨੇਲ, ਸਿਰਲੇਖ ਅਤੇ ਵੀਡੀਓ ਗਿਣਤੀ) ਨੂੰ ਅਪਡੇਟ ਕਰਕੇ। diff --git a/fastlane/metadata/android/pa/changelogs/66.txt b/fastlane/metadata/android/pa/changelogs/66.txt index aecf80cbc..f400eb137 100644 --- a/fastlane/metadata/android/pa/changelogs/66.txt +++ b/fastlane/metadata/android/pa/changelogs/66.txt @@ -1 +1,21 @@ -# v0.13.7 ਦਾ ਚੇਂਜਲਾਗ ### ਸਥਿਰ - v0.13.6 ਦੇ ਕ੍ਰਮਬੱਧ ਫਿਲਟਰ ਮੁੱਦਿਆਂ ਨੂੰ ਠੀਕ ਕਰੋ # v0.13.6 ਦਾ ਚੇਂਜਲਾਗ ### ਸੁਧਾਰ - ਬਰਗਰਮੇਨੂ ਆਈਕਨ ਐਨੀਮੇਸ਼ਨ #1486 ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ - ਡਾਉਨਲੋਡਸ #1472 ਨੂੰ ਮਿਟਾਉਣ ਨੂੰ ਅਨਡੂ ਕਰੋ - ਸ਼ੇਅਰ ਮੀਨੂ #1498 ਵਿੱਚ ਡਾਊਨਲੋਡ ਵਿਕਲਪ - ਲੰਬੇ ਟੈਪ ਮੀਨੂ #1454 ਵਿੱਚ ਸ਼ੇਅਰ ਵਿਕਲਪ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ - ਨਿਕਾਸ #1354 'ਤੇ ਮੁੱਖ ਪਲੇਅਰ ਨੂੰ ਛੋਟਾ ਕਰੋ - ਲਾਇਬ੍ਰੇਰੀ ਸੰਸਕਰਣ ਅਪਡੇਟ ਅਤੇ ਡੇਟਾਬੇਸ ਬੈਕਅਪ ਫਿਕਸ #1510 - ExoPlayer 2.8.2 ਅੱਪਡੇਟ #1392 - ਤੇਜ਼ ਗਤੀ ਤਬਦੀਲੀ ਲਈ ਵੱਖ-ਵੱਖ ਸਟੈਪ ਸਾਈਜ਼ ਦਾ ਸਮਰਥਨ ਕਰਨ ਲਈ ਪਲੇਬੈਕ ਸਪੀਡ ਕੰਟਰੋਲ ਡਾਇਲਾਗ ਨੂੰ ਦੁਬਾਰਾ ਬਣਾਇਆ ਗਿਆ। - ਪਲੇਬੈਕ ਸਪੀਡ ਨਿਯੰਤਰਣ ਵਿੱਚ ਚੁੱਪ ਦੌਰਾਨ ਫਾਸਟ-ਫਾਰਵਰਡ ਕਰਨ ਲਈ ਇੱਕ ਟੌਗਲ ਜੋੜਿਆ ਗਿਆ। ਇਹ ਆਡੀਓਬੁੱਕਾਂ ਅਤੇ ਕੁਝ ਸੰਗੀਤ ਸ਼ੈਲੀਆਂ ਲਈ ਮਦਦਗਾਰ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ, ਅਤੇ ਇੱਕ ਸੱਚਾ ਸਹਿਜ ਅਨੁਭਵ ਲਿਆ ਸਕਦਾ ਹੈ (ਅਤੇ ਬਹੁਤ ਸਾਰੀਆਂ ਚੁੱਪ =\\ ਨਾਲ ਗੀਤ ਤੋੜ ਸਕਦਾ ਹੈ)। - ਹੱਥੀਂ ਅਜਿਹਾ ਕਰਨ ਦੀ ਬਜਾਏ, ਪਲੇਅਰ ਵਿੱਚ ਅੰਦਰੂਨੀ ਤੌਰ 'ਤੇ ਮੀਡੀਆ ਦੇ ਨਾਲ-ਨਾਲ ਮੈਟਾਡੇਟਾ ਪਾਸ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣ ਲਈ ਰੀਫੈਕਟਰਡ ਮੀਡੀਆ ਸਰੋਤ ਰੈਜ਼ੋਲਿਊਸ਼ਨ। ਹੁਣ ਸਾਡੇ ਕੋਲ ਮੈਟਾਡੇਟਾ ਦਾ ਇੱਕ ਸਿੰਗਲ ਸਰੋਤ ਹੈ ਅਤੇ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋਣ 'ਤੇ ਸਿੱਧਾ ਉਪਲਬਧ ਹੁੰਦਾ ਹੈ। - ਸਥਿਰ ਰਿਮੋਟ ਪਲੇਲਿਸਟ ਮੈਟਾਡੇਟਾ ਅੱਪਡੇਟ ਨਹੀਂ ਹੋ ਰਿਹਾ ਹੈ ਜਦੋਂ ਪਲੇਲਿਸਟ ਫਰੈਗਮੈਂਟ ਖੋਲ੍ਹਿਆ ਜਾਂਦਾ ਹੈ ਤਾਂ ਨਵਾਂ ਮੈਟਾਡੇਟਾ ਉਪਲਬਧ ਹੁੰਦਾ ਹੈ। - ਕਈ UI ਫਿਕਸ: #1383, ਬੈਕਗਰਾਊਂਡ ਪਲੇਅਰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਕੰਟਰੋਲ ਹੁਣ ਹਮੇਸ਼ਾ ਸਫੈਦ, ਫਲਿੰਗਿੰਗ ਰਾਹੀਂ ਪੌਪਅੱਪ ਪਲੇਅਰ ਨੂੰ ਬੰਦ ਕਰਨਾ ਆਸਾਨ - ਮਲਟੀਸਰਵਿਸ ਲਈ ਰੀਫੈਕਟਰਡ ਆਰਕੀਟੈਕਚਰ ਦੇ ਨਾਲ ਨਵੇਂ ਐਕਸਟਰੈਕਟਰ ਦੀ ਵਰਤੋਂ ਕਰੋ ### ਫਿਕਸ - #1440 ਟੁੱਟੇ ਹੋਏ ਵੀਡੀਓ ਜਾਣਕਾਰੀ ਲੇਆਉਟ #1491 ਨੂੰ ਠੀਕ ਕਰੋ - ਇਤਿਹਾਸ ਫਿਕਸ #1497 ਦੇਖੋ - #1495, ਜਿਵੇਂ ਹੀ ਉਪਭੋਗਤਾ ਪਲੇਲਿਸਟ ਤੱਕ ਪਹੁੰਚ ਕਰਦਾ ਹੈ, ਮੈਟਾਡੇਟਾ (ਥੰਬਨੇਲ, ਸਿਰਲੇਖ ਅਤੇ ਵੀਡੀਓ ਗਿਣਤੀ) ਨੂੰ ਅਪਡੇਟ ਕਰਕੇ। - #1475, ਜਦੋਂ ਉਪਭੋਗਤਾ ਵੇਰਵੇ ਦੇ ਟੁਕੜੇ 'ਤੇ ਬਾਹਰੀ ਪਲੇਅਰ 'ਤੇ ਵੀਡੀਓ ਸ਼ੁਰੂ ਕਰਦਾ ਹੈ ਤਾਂ ਡੇਟਾਬੇਸ ਵਿੱਚ ਇੱਕ ਦ੍ਰਿਸ਼ ਨੂੰ ਰਜਿਸਟਰ ਕਰਕੇ। - ਪੌਪਅੱਪ ਮੋਡ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਕ੍ਰੀਨ ਟਾਈਮਆਊਟ ਫਿਕਸ ਕਰੋ। #1463 (ਸਥਿਰ #640) - ਮੁੱਖ ਵੀਡੀਓ ਪਲੇਅਰ ਫਿਕਸ #1509 - [#1412] ਫਿਕਸਡ ਰੀਪੀਟ ਮੋਡ ਜਿਸ ਨਾਲ ਪਲੇਅਰ ਐਨਪੀਈ ਦਾ ਕਾਰਨ ਬਣਦਾ ਹੈ ਜਦੋਂ ਪਲੇਅਰ ਦੀ ਗਤੀਵਿਧੀ ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਹੁੰਦੀ ਹੈ ਤਾਂ ਨਵਾਂ ਇਰਾਦਾ ਪ੍ਰਾਪਤ ਹੁੰਦਾ ਹੈ। - ਪੌਪਅੱਪ ਲਈ ਫਿਕਸਡ ਮਿਨੀਮਾਈਜ਼ਿੰਗ ਪਲੇਅਰ ਪਲੇਅਰ ਨੂੰ ਨਸ਼ਟ ਨਹੀਂ ਕਰਦਾ ਹੈ ਜਦੋਂ ਪੌਪਅੱਪ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। +# v0.13.7 ਲਈ ਚੇਂਜਲੌਗ + +### ਫਿਕਸ +- v0.13.6 ਤੋਂ ਸੌਰਟ ਫਿਲਟਰ ਨਾਲ ਸਮੱਸਿਆਵਾਂ ਹੱਲ ਕੀਤੀਆਂ ਗਈਆਂ। + +# v0.13.6 ਲਈ ਚੇਂਜਲੌਗ + +### ਸੁਧਾਰ + +- ਬਰਗਰ ਮੀਨੂ ਆਈਕਨ ਐਨੀਮੇਸ਼ਨ #1486 ਨੂੰ ਅਯੋਗ ਕਰੋ +- ਡਾਊਨਲੋਡਸ ਨੂੰ ਮਿਟਾਓ ਨੂੰ ਅਣਡੂ ਕਰੋ #1472 +- ਸ਼ੇਅਰ ਮੀਨੂ ਵਿੱਚ ਡਾਊਨਲੋਡ ਵਿਕਲਪ #1498 +- ਲੰਬੇ ਟੈਪ ਮੀਨੂ ਵਿੱਚ ਸ਼ੇਅਰ ਵਿਕਲਪ ਜੋੜਿਆ ਗਿਆ #1454 +- ਐਕਸੋਪਲੇਅਰ 2.8.2 ਅਪਡੇਟ #1392 +ਕਈ UI ਫਿਕਸ: #1383 + +### ਫਿਕਸ + +- ਫਿਕਸ ਕੀਤਾ ਗਿਆ #1440 ਟੁੱਟਿਆ ਹੋਇਆ ਵੀਡੀਓ ਜਾਣਕਾਰੀ ਲੇਆਉਟ #1491 +- ਇਤਿਹਾਸ ਦੇਖੋ ਫਿਕਸ #1497 +- ਮੁੱਖ ਵੀਡੀਓ ਪਲੇਅਰ ਫਿਕਸ #1509. diff --git a/fastlane/metadata/android/pa/changelogs/68.txt b/fastlane/metadata/android/pa/changelogs/68.txt index e8e54ea4f..7b98078df 100644 --- a/fastlane/metadata/android/pa/changelogs/68.txt +++ b/fastlane/metadata/android/pa/changelogs/68.txt @@ -1 +1,19 @@ -v0.14.1 ਦੇ # ਬਦਲਾਅ ### ਸਥਿਰ - ਵੀਡੀਓ url #1659 ਨੂੰ ਡੀਕ੍ਰਿਪਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਿਹਾ - ਸਥਿਰ ਵਰਣਨ ਲਿੰਕ #1657 ਨੂੰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਐਕਸਟਰੈਕਟ ਨਹੀਂ ਕਰਦਾ ਹੈ v0.14.0 ਦੀਆਂ # ਤਬਦੀਲੀਆਂ ### ਨਵਾਂ - ਨਵਾਂ ਦਰਾਜ਼ ਡਿਜ਼ਾਈਨ #1461 - ਨਵਾਂ ਅਨੁਕੂਲਿਤ ਫਰੰਟ ਪੇਜ #1461 ### ਸੁਧਾਰ - ਮੁੜ ਕੰਮ ਕੀਤਾ ਸੰਕੇਤ ਨਿਯੰਤਰਣ #1604 - ਪੌਪਅੱਪ ਪਲੇਅਰ #1597 ਨੂੰ ਬੰਦ ਕਰਨ ਦਾ ਨਵਾਂ ਤਰੀਕਾ ### ਸਥਿਰ - ਗਾਹਕੀ ਦੀ ਗਿਣਤੀ ਉਪਲਬਧ ਨਾ ਹੋਣ 'ਤੇ ਗਲਤੀ ਨੂੰ ਠੀਕ ਕਰੋ। #1649 ਬੰਦ ਹੁੰਦਾ ਹੈ। - ਉਹਨਾਂ ਮਾਮਲਿਆਂ ਵਿੱਚ "ਗਾਹਕ ਗਿਣਤੀ ਉਪਲਬਧ ਨਹੀਂ" ਦਿਖਾਓ - YouTube ਪਲੇਲਿਸਟ ਖਾਲੀ ਹੋਣ 'ਤੇ NPE ਨੂੰ ਠੀਕ ਕਰੋ - SoundCloud ਵਿੱਚ ਕਿਓਸਕ ਲਈ ਤੁਰੰਤ ਫਿਕਸ - ਰਿਫੈਕਟਰ ਅਤੇ ਬੱਗਫਿਕਸ #1623 - ਚੱਕਰੀ ਖੋਜ ਨਤੀਜੇ #1562 ਨੂੰ ਠੀਕ ਕਰੋ - ਸੀਕ ਬਾਰ ਨੂੰ ਸਥਿਰ ਤੌਰ 'ਤੇ ਬਾਹਰ ਨਾ ਕੱਢੋ - ਫਿਕਸ YT ਪ੍ਰੀਮੀਅਮ ਵੀਡੀਓ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਬਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ - ਕਈ ਵਾਰ ਲੋਡ ਨਾ ਹੋਣ ਵਾਲੇ ਵੀਡੀਓ ਨੂੰ ਠੀਕ ਕਰੋ (DASH ਪਾਰਸਿੰਗ ਦੇ ਕਾਰਨ) - ਵੀਡੀਓ ਵਰਣਨ ਵਿੱਚ ਲਿੰਕ ਫਿਕਸ ਕਰੋ - ਜਦੋਂ ਕੋਈ ਬਾਹਰੀ sdcard 'ਤੇ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਦਾ ਹੈ ਤਾਂ ਚੇਤਾਵਨੀ ਦਿਖਾਓ - ਅਪਵਾਦ ਟਰਿੱਗਰ ਰਿਪੋਰਟ ਦਿਖਾਈ ਗਈ ਕੁਝ ਵੀ ਠੀਕ ਨਾ ਕਰੋ - ਐਂਡਰਾਇਡ 8.1 ਲਈ ਬੈਕਗ੍ਰਾਉਂਡ ਪਲੇਅਰ ਵਿੱਚ ਥੰਬਨੇਲ ਨਹੀਂ ਦਿਖਾਇਆ ਗਿਆ [ਇੱਥੇ ਦੇਖੋ](https://github.com/TeamNewPipe/NewPipe/issues/943) - ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕਰਨ ਵਾਲੇ ਦੀ ਰਜਿਸਟਰੇਸ਼ਨ ਨੂੰ ਠੀਕ ਕਰੋ। #1641 ਬੰਦ ਹੁੰਦਾ ਹੈ। +# v0.14.1 ਵਿੱਚ ਬਦਲਾਅ + +### ਠੀਕ ਕੀਤਾ ਗਿਆ +- ਵੀਡੀਓ URL ਨੂੰ ਡੀਕ੍ਰਿਪਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲਤਾ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ #1659 +- ਵਰਣਨ ਲਿੰਕ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਐਕਸਟਰੈਕਟ ਨਾ ਕਰਨ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ #1657 + +# v0.14.0 ਵਿੱਚ ਬਦਲਾਅ + +### ਨਵਾਂ +- ਨਵਾਂ ਦਰਾਜ਼ ਡਿਜ਼ਾਈਨ #1461 +- ਨਵਾਂ ਅਨੁਕੂਲਿਤ ਫਰੰਟ ਪੇਜ #1461 + +### ਸੁਧਾਰ +- ਪੌਪਅੱਪ ਪਲੇਅਰ ਨੂੰ ਬੰਦ ਕਰਨ ਦਾ ਨਵਾਂ ਤਰੀਕਾ #1597 + +### ਠੀਕ ਕੀਤਾ ਗਿਆ +- YouTube ਪਲੇਲਿਸਟਾਂ ਖਾਲੀ ਹੋਣ 'ਤੇ NPE ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ +- SoundCloud ਵਿੱਚ ਕਿਓਸਕ ਲਈ ਤੁਰੰਤ ਠੀਕ ਕੀਤਾ ਗਿਆ +- ਰੀਫੈਕਟਰ ਅਤੇ ਬੱਗਫਿਕਸ #1623. diff --git a/fastlane/metadata/android/pa/changelogs/69.txt b/fastlane/metadata/android/pa/changelogs/69.txt index b6358991b..8956afb54 100644 --- a/fastlane/metadata/android/pa/changelogs/69.txt +++ b/fastlane/metadata/android/pa/changelogs/69.txt @@ -1 +1,15 @@ -### ਨਵਾਂ - ਮਿਟਾਓ ਅਤੇ ਸਬਸਕ੍ਰਿਪਸ਼ਨ #1516 ਵਿੱਚ ਸਾਂਝਾ ਕਰੋ - ਟੈਬਲੇਟ UI ਅਤੇ ਗਰਿੱਡ ਸੂਚੀ ਖਾਕਾ #1617 ### ਸੁਧਾਰ - ਆਖਰੀ ਵਰਤੇ ਗਏ ਆਸਪੈਕਟ ਰੇਸ਼ੋ #1748 ਨੂੰ ਸਟੋਰ ਅਤੇ ਰੀਲੋਡ ਕਰੋ - ਪੂਰੇ ਵੀਡੀਓ ਨਾਮ #1771 ਦੇ ਨਾਲ ਡਾਊਨਲੋਡ ਗਤੀਵਿਧੀ ਵਿੱਚ ਲੀਨੀਅਰ ਲੇਆਉਟ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ - ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਟੈਬ #1516 ਦੇ ਅੰਦਰੋਂ ਸਿੱਧਾ ਗਾਹਕੀਆਂ ਨੂੰ ਮਿਟਾਓ ਅਤੇ ਸਾਂਝਾ ਕਰੋ - ਜੇਕਰ ਪਲੇ ਕਤਾਰ ਪਹਿਲਾਂ ਹੀ #1783 ਖਤਮ ਹੋ ਗਈ ਹੈ ਤਾਂ ਹੁਣ ਏਨਕਿਊ ਕਰਨਾ ਵੀਡੀਓ ਚਲਾਉਣ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ - ਵਾਲੀਅਮ ਅਤੇ ਚਮਕ ਸੰਕੇਤ #1644 ਲਈ ਵੱਖਰੀ ਸੈਟਿੰਗ - ਸਥਾਨਕਕਰਨ #1792 ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ ### ਫਿਕਸ - ਲਈ ਪਾਰਸਿੰਗ ਸਮਾਂ ਫਿਕਸ ਕਰੋ। ਫਾਰਮੈਟ, ਇਸ ਲਈ ਨਿਊ ਪਾਈਪ ਨੂੰ ਫਿਨਲੈਂਡ ਵਿੱਚ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ - ਗਾਹਕੀ ਦੀ ਗਿਣਤੀ ਨੂੰ ਠੀਕ ਕਰੋ - API 28+ ਡਿਵਾਈਸਾਂ #1830 ਲਈ ਫੋਰਗਰਾਉਂਡ ਸੇਵਾ ਅਨੁਮਤੀ ਸ਼ਾਮਲ ਕਰੋ ### ਜਾਣੇ-ਪਛਾਣੇ ਬੱਗ - ਐਂਡ੍ਰਾਇਡ ਪੀ 'ਤੇ ਪਲੇਬੈਕ ਸਟੇਟ ਨੂੰ ਸੇਵ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ +### ਨਵਾਂ +- ਗਾਹਕੀਆਂ 'ਤੇ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਟੈਪ ਕਰਕੇ ਮਿਟਾਓ ਅਤੇ ਸਾਂਝਾ ਕਰੋ #1516 +- ਟੈਬਲੇਟ UI ਅਤੇ ਗਰਿੱਡ ਸੂਚੀ ਲੇਆਉਟ #1617 + +### ਸੁਧਾਰ +- ਵਾਲੀਅਮ ਅਤੇ ਚਮਕ ਸੰਕੇਤਾਂ ਲਈ ਵੱਖਰੀਆਂ ਸੈਟਿੰਗਾਂ #1644 +- ਸਥਾਨਕਕਰਨ ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ #1792 + +### ਸੁਧਾਰ +- . ਫਾਰਮੈਟ ਲਈ ਸਮਾਂ ਪਾਰਸਿੰਗ ਠੀਕ ਕਰੋ ਤਾਂ ਜੋ ਫਿਨਲੈਂਡ ਵਿੱਚ ਨਿਊਪਾਈਪ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਸਕੇ +- ਗਾਹਕੀ ਗਿਣਤੀ ਠੀਕ ਕਰੋ +- API 28+ ਡਿਵਾਈਸਾਂ ਲਈ ਫੋਰਗਰਾਉਂਡ ਸੇਵਾ ਅਨੁਮਤੀ ਸ਼ਾਮਲ ਕਰੋ #1830 + +### ਜਾਣੇ-ਪਛਾਣੇ ਬੱਗ +- ਪਲੇਬੈਕ ਸਥਿਤੀ ਨੂੰ ਐਂਡਰਾਇਡ ਪੀ 'ਤੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ diff --git a/fastlane/metadata/android/pa/changelogs/70.txt b/fastlane/metadata/android/pa/changelogs/70.txt index 97d781d4a..bedc91496 100644 --- a/fastlane/metadata/android/pa/changelogs/70.txt +++ b/fastlane/metadata/android/pa/changelogs/70.txt @@ -1 +1,10 @@ -ਧਿਆਨ ਦਿਓ: ਇਹ ਸੰਸਕਰਣ ਸ਼ਾਇਦ ਇੱਕ ਬੱਗਫੈਸਟ ਹੈ, ਬਿਲਕੁਲ ਪਿਛਲੇ ਇੱਕ ਵਾਂਗ। ਹਾਲਾਂਕਿ 17 ਤੋਂ ਪੂਰੀ ਤਰ੍ਹਾਂ ਬੰਦ ਹੋਣ ਦੇ ਕਾਰਨ. ਇੱਕ ਟੁੱਟਿਆ ਹੋਇਆ ਸੰਸਕਰਣ ਕੋਈ ਸੰਸਕਰਣ ਨਾਲੋਂ ਬਿਹਤਰ ਹੈ. ਸਹੀ? ¯\_(ツ)_/¯ ### ਸੁਧਾਰ * ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫਾਈਲਾਂ ਨੂੰ ਹੁਣ ਇੱਕ ਕਲਿੱਕ ਨਾਲ ਖੋਲ੍ਹਿਆ ਜਾ ਸਕਦਾ ਹੈ #1879 * ਐਂਡਰਾਇਡ 4.1 - 4.3 #1884 ਲਈ ਸਹਾਇਤਾ ਛੱਡੋ * ਪੁਰਾਣੇ ਪਲੇਅਰ #1884 ਨੂੰ ਹਟਾਓ * ਮੌਜੂਦਾ ਪਲੇ ਕਤਾਰ ਤੋਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਸੱਜੇ #1915 'ਤੇ ਸਵਾਈਪ ਕਰਕੇ ਹਟਾਓ * ਆਟੋ ਕਤਾਰਬੱਧ ਸਟ੍ਰੀਮ ਨੂੰ ਹਟਾਓ ਜਦੋਂ ਇੱਕ ਨਵੀਂ ਸਟ੍ਰੀਮ ਹੱਥੀਂ ਕਤਾਰਬੱਧ ਹੁੰਦੀ ਹੈ #1878 * @kapodamy ਦੁਆਰਾ ਡਾਉਨਲੋਡ ਕਰਨ ਅਤੇ ਗੁੰਮ ਹੋਈਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ #1759 ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਪੋਸਟ ਪ੍ਰੋਸੈਸਿੰਗ * ਪੋਸਟ-ਪ੍ਰੋਸੈਸਿੰਗ ਬੁਨਿਆਦੀ ਢਾਂਚਾ * "ਬੁਨਿਆਦੀ ਢਾਂਚੇ" ਨੂੰ ਸੰਭਾਲਣ ਲਈ ਸਹੀ ਤਰੁੱਟੀ (ਡਾਊਨਲੋਡਰ ਲਈ) * ਮਲਟੀਪਲ ਡਾਉਨਲੋਡਸ ਦੀ ਬਜਾਏ ਕਤਾਰ * ਲੜੀਬੱਧ ਲੰਬਿਤ ਡਾਉਨਲੋਡਸ (`ਗੀਗਾ` ਫਾਈਲਾਂ) ਨੂੰ ਐਪ ਡੇਟਾ ਵਿੱਚ ਮੂਵ ਕਰੋ * ਅਧਿਕਤਮ ਡਾਊਨਲੋਡ ਦੀ ਮੁੜ ਕੋਸ਼ਿਸ਼ ਨੂੰ ਲਾਗੂ ਕਰੋ * ਉਚਿਤ ਮਲਟੀ-ਥ੍ਰੈਡ ਡਾਊਨਲੋਡ ਵਿਰਾਮ * ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ 'ਤੇ ਜਾਣ ਵੇਲੇ ਡਾਊਨਲੋਡ ਬੰਦ ਕਰੋ (ਕਦੇ ਕੰਮ ਨਹੀਂ ਕਰਦਾ, ਦੂਜਾ ਪੁਆਇੰਟ ਦੇਖੋ) * ਅਗਲੇ ਡਾਉਨਲੋਡਸ ਲਈ ਥਰਿੱਡ ਗਿਣਤੀ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰੋ * ਬਹੁਤ ਸਾਰੀਆਂ ਅਸੰਗਤੀਆਂ ਹੱਲ ਕੀਤੀਆਂ ਗਈਆਂ ### ਸਥਿਰ * ਪੂਰਵ-ਨਿਰਧਾਰਤ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਨਾਲ ਕਰੈਸ਼ ਨੂੰ ਬਿਹਤਰ ਅਤੇ ਸੀਮਤ ਮੋਬਾਈਲ ਡਾਟਾ ਰੈਜ਼ੋਲਿਊਸ਼ਨ #1835 'ਤੇ ਸੈੱਟ ਕਰੋ * ਪੌਪ-ਅੱਪ ਪਲੇਅਰ ਕਰੈਸ਼ ਫਿਕਸਡ #1874 * ਬੈਕਗਰਾਊਂਡ ਪਲੇਅਰ #1901 ਨੂੰ ਖੋਲ੍ਹਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਦੇ ਸਮੇਂ NPE * ਜਦੋਂ ਆਟੋ ਕਤਾਰ ਯੋਗ ਹੁੰਦੀ ਹੈ ਤਾਂ ਨਵੀਆਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਸੰਮਿਲਿਤ ਕਰਨ ਲਈ ਠੀਕ ਕਰੋ #1878 * ਡੀਸਾਈਪਰਿੰਗ ਸ਼ੱਟਟਾਊਨ ਮੁੱਦੇ ਨੂੰ ਹੱਲ ਕੀਤਾ ਗਿਆ +ਸੁਧਾਰ +* ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫਾਈਲਾਂ ਹੁਣ ਇੱਕ ਕਲਿੱਕ ਨਾਲ ਖੋਲ੍ਹੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ #1879 +* ਐਂਡਰਾਇਡ 4.1 - 4.3 ਲਈ ਡ੍ਰੌਪ ਸਪੋਰਟ #1884 +* ਪੁਰਾਣੇ ਪਲੇਅਰ ਨੂੰ ਹਟਾਓ #1884 +* ਮੌਜੂਦਾ ਪਲੇ ਕਤਾਰ ਤੋਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਸੱਜੇ ਪਾਸੇ ਸਵਾਈਪ ਕਰਕੇ ਹਟਾਓ #1915 +* ਜਦੋਂ ਇੱਕ ਨਵੀਂ ਸਟ੍ਰੀਮ ਨੂੰ ਹੱਥੀਂ ਕਤਾਰਬੱਧ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਤਾਂ ਆਟੋ ਕਤਾਰਬੱਧ ਸਟ੍ਰੀਮ ਨੂੰ ਹਟਾਓ #1878 +* ਬਹੁਤ ਸਾਰੀਆਂ ਡਾਊਨਲੋਡ ਅਸੰਗਤੀਆਂ ਠੀਕ ਕੀਤੀਆਂ ਗਈਆਂ + +ਫਿਕਸਡ +* ਬਹੁਤ ਸਾਰੀਆਂ ਅਸੰਗਤੀਆਂ ਠੀਕ ਕੀਤੀਆਂ ਗਈਆਂ diff --git a/fastlane/metadata/android/pa/changelogs/71.txt b/fastlane/metadata/android/pa/changelogs/71.txt index bafa26f8c..2f11dea82 100644 --- a/fastlane/metadata/android/pa/changelogs/71.txt +++ b/fastlane/metadata/android/pa/changelogs/71.txt @@ -1 +1,8 @@ -### ਸੁਧਾਰ * GitHub ਬਿਲਡ ਲਈ ਐਪ ਅਪਡੇਟ ਨੋਟੀਫਿਕੇਸ਼ਨ ਸ਼ਾਮਲ ਕਰੋ (@krtkush ਦੁਆਰਾ #1608) * ਡਾਊਨਲੋਡਰ ਵਿੱਚ ਕਈ ਸੁਧਾਰ (@kapodamy ਦੁਆਰਾ #1944): * ਗੁੰਮ ਹੋਏ ਚਿੱਟੇ ਆਈਕਨ ਸ਼ਾਮਲ ਕਰੋ ਅਤੇ ਆਈਕਨ ਦੇ ਰੰਗਾਂ ਨੂੰ ਬਦਲਣ ਲਈ ਹਾਰਡਕੋਰਡ ਤਰੀਕੇ ਦੀ ਵਰਤੋਂ ਕਰੋ * ਜਾਂਚ ਕਰੋ ਕਿ ਕੀ ਇਟਰੇਟਰ ਸ਼ੁਰੂ ਕੀਤਾ ਗਿਆ ਹੈ (ਫਿਕਸ #2031) * ਨਵੇਂ ਮੁਕਸਰ ਵਿੱਚ "ਪੋਸਟ-ਪ੍ਰੋਸੈਸਿੰਗ ਫੇਲ੍ਹ" ਗਲਤੀ ਦੇ ਨਾਲ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ * ਨਵਾਂ MPEG-4 ਮੁਕਸਰ ਫਿਕਸਿੰਗ ਗੈਰ-ਸਿੰਕਰੋਨਸ ਵੀਡੀਓ ਅਤੇ ਆਡੀਓ ਸਟ੍ਰੀਮਜ਼ (#2039) ### ਸਥਿਰ * YouTube ਲਾਈਵ ਸਟ੍ਰੀਮਾਂ ਥੋੜ੍ਹੇ ਸਮੇਂ ਬਾਅਦ ਚੱਲਣੀਆਂ ਬੰਦ ਹੋ ਜਾਂਦੀਆਂ ਹਨ (@yausername ਦੁਆਰਾ #1996) +ਸੁਧਾਰ +* GitHub ਬਿਲਡ ਲਈ ਐਪ ਅੱਪਡੇਟ ਸੂਚਨਾ ਸ਼ਾਮਲ ਕਰੋ (#1608 @krtkush ਦੁਆਰਾ) +* ਡਾਊਨਲੋਡਰ ਵਿੱਚ ਕਈ ਸੁਧਾਰ (#1944 @kapodamy ਦੁਆਰਾ) +* ਨਵੇਂ ਮਕਸਰ ਵਿੱਚ "ਪੋਸਟ-ਪ੍ਰੋਸੈਸਿੰਗ ਅਸਫਲ" ਗਲਤੀ ਨਾਲ ਡਾਊਨਲੋਡਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ +* ਨਵਾਂ MPEG-4 ਮਕਸਰ ਗੈਰ-ਸਮਕਾਲੀ ਵੀਡੀਓ ਅਤੇ ਆਡੀਓ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਠੀਕ ਕਰਦਾ ਹੈ (#2039) + +ਫਿਕਸਡ +* YouTube ਲਾਈਵ ਸਟ੍ਰੀਮਾਂ ਥੋੜ੍ਹੇ ਸਮੇਂ ਬਾਅਦ ਚੱਲਣਾ ਬੰਦ ਕਰ ਦਿੰਦੀਆਂ ਹਨ (#1996 @yausername ਦੁਆਰਾ) diff --git a/fastlane/metadata/android/pa/changelogs/740.txt b/fastlane/metadata/android/pa/changelogs/740.txt index 6a2dbdc86..62da0f9c3 100644 --- a/fastlane/metadata/android/pa/changelogs/740.txt +++ b/fastlane/metadata/android/pa/changelogs/740.txt @@ -1 +1,8 @@ -ਬਦਲਾਅ ਸੂਚੀ ਅਨੁਵਾਦ ਕਰਣਯੋਗ ਨਹੀਂ। ਬਿਲਕੁਲ ਬਕਵਾਸ +

    ਸੁਧਾਰ

    +
      +
    • ਟਿੱਪਣੀਆਂ ਵਿੱਚ ਲਿੰਕਾਂ ਨੂੰ ਕਲਿੱਕ ਕਰਨ ਯੋਗ ਬਣਾਓ, ਟੈਕਸਟ ਦਾ ਆਕਾਰ ਵਧਾਓ
    • +
    • ਟਿੱਪਣੀਆਂ ਵਿੱਚ ਟਾਈਮਸਟੈਂਪ ਕੀਤੇ ਲਿੰਕਾਂ 'ਤੇ ਕਲਿੱਕ ਕੀਤੇ ਜਾਣ 'ਤੇ ਖੋਜ ਕਰੋ
    • +
    • ਜਦੋਂ ਸਾਂਝਾ ਕੀਤਾ ਟੈਕਸਟ URL ਨਾ ਹੋਵੇ ਤਾਂ ਖੋਜ ਕਰੋ
    • +
    • ਮੁੱਖ ਵੀਡੀਓ ਪਲੇਅਰ ਵਿੱਚ "ਹੁਣੇ ਸਾਂਝਾ ਕਰੋ" ਬਟਨ ਸ਼ਾਮਲ ਕਰੋ
    • +
    • ExoPlayer ਨੂੰ 2.9.6 'ਤੇ ਅੱਪਡੇਟ ਕਰਨਾ
    • +
    diff --git a/fastlane/metadata/android/pa/changelogs/750.txt b/fastlane/metadata/android/pa/changelogs/750.txt index 0b875b705..c24183ddb 100644 --- a/fastlane/metadata/android/pa/changelogs/750.txt +++ b/fastlane/metadata/android/pa/changelogs/750.txt @@ -1 +1,9 @@ -ਨਵਾਂ ਪਲੇਬੈਕ ਰੈਜ਼ਿਊਮੇ #2288 • ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਮੁੜ ਸ਼ੁਰੂ ਕਰੋ ਜਿੱਥੇ ਤੁਸੀਂ ਪਿਛਲੀ ਵਾਰ ਰੁਕੇ ਸੀ ਡਾਊਨਲੋਡਰ ਸੁਧਾਰ #2149 • ਬਾਹਰੀ SD-ਕਾਰਡਾਂ 'ਤੇ ਡਾਊਨਲੋਡ ਸਟੋਰ ਕਰਨ ਲਈ ਸਟੋਰੇਜ਼ ਐਕਸੈਸ ਫਰੇਮਵਰਕ ਦੀ ਵਰਤੋਂ ਕਰੋ • ਨਵਾਂ mp4 muxer • ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਵਿਕਲਪਿਕ ਤੌਰ 'ਤੇ ਡਾਉਨਲੋਡ ਡਾਇਰੈਕਟਰੀ ਨੂੰ ਬਦਲੋ • ਮੀਟਰਡ ਨੈੱਟਵਰਕਾਂ ਦਾ ਆਦਰ ਕਰੋ ਸੁਧਾਰ • gema ਸਤਰ #2295 ਨੂੰ ਹਟਾਇਆ • ਗਤੀਵਿਧੀ ਜੀਵਨ ਚੱਕਰ #2444 ਦੌਰਾਨ ਹੈਂਡਲ (ਆਟੋ) ਰੋਟੇਸ਼ਨ ਤਬਦੀਲੀਆਂ • ਲੰਬੇ-ਦਬਾਓ ਮੀਨੂ ਨੂੰ ਇਕਸਾਰ #2368 ਬਣਾਓ ਸਥਿਰ • ਫਿਕਸਡ ਚੁਣਿਆ ਹੋਇਆ ਉਪਸਿਰਲੇਖ ਟਰੈਕ ਨਾਮ #2394 ਨਹੀਂ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ • ਐਪ ਅੱਪਡੇਟ ਦੀ ਜਾਂਚ ਅਸਫਲ ਹੋਣ 'ਤੇ ਕ੍ਰੈਸ਼ ਨਾ ਹੋਵੋ (GitHub ਸੰਸਕਰਣ) #2423 • ਸਥਿਰ ਡਾਊਨਲੋਡ 99.9% #2440 'ਤੇ ਅਟਕ ਗਏ • ਪਲੇ ਕਤਾਰ ਮੈਟਾਡੇਟਾ #2453 ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ • [SoundCloud] ਪਲੇਲਿਸਟਸ ਲੋਡ ਕਰਨ ਵੇਲੇ ਸਥਿਰ ਕਰੈਸ਼ TeamNewPipe/NewPipeExtractor#170 • [YouTube] ਸਥਿਰ ਅਵਧੀ ਨੂੰ ਪਾਰਸਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ TeamNewPipe/NewPipeExtractor#177 +ਨਵਾਂ +ਪਲੇਬੈਕ ਰੈਜ਼ਿਊਮੇ #2288 +ਡਾਊਨਲੋਡਰ ਸੁਧਾਰ #2149 +• ਬਾਹਰੀ SD-ਕਾਰਡਾਂ 'ਤੇ ਡਾਊਨਲੋਡ ਸਟੋਰ ਕਰਨ ਲਈ ਸਟੋਰੇਜ ਐਕਸੈਸ ਫਰੇਮਵਰਕ ਦੀ ਵਰਤੋਂ ਕਰੋ +• ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਵਿਕਲਪਿਕ ਤੌਰ 'ਤੇ ਡਾਊਨਲੋਡ ਡਾਇਰੈਕਟਰੀ ਬਦਲੋ +• ਮੀਟਰ ਕੀਤੇ ਨੈੱਟਵਰਕਾਂ ਦਾ ਸਤਿਕਾਰ ਕਰੋ + +ਸਥਿਰ +• [YouTube] ਸਥਿਰ ਮਿਆਦ ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ TeamNewPipe/NewPipeExtractor#177 diff --git a/fastlane/metadata/android/pa/changelogs/760.txt b/fastlane/metadata/android/pa/changelogs/760.txt index fd4b8f2a4..6279139d0 100644 --- a/fastlane/metadata/android/pa/changelogs/760.txt +++ b/fastlane/metadata/android/pa/changelogs/760.txt @@ -1 +1,10 @@ -0.17.1 ਵਿੱਚ ਬਦਲਾਅ ਨਵਾਂ • ਥਾਈ ਸਥਾਨਕਕਰਨ ਸੁਧਾਰ • ਦੁਬਾਰਾ #2518 ਪਲੇਲਿਸਟਾਂ ਲਈ ਲੰਬੇ-ਦਬਾਓ ਮੀਨੂ ਵਿੱਚ ਇੱਥੇ ਪਲੇ ਸ਼ੁਰੂ ਕਰੋ ਐਕਸ਼ਨ ਸ਼ਾਮਲ ਕਰੋ • SAF / ਪੁਰਾਤਨ ਫਾਈਲ ਪਿਕਰ #2521 ਲਈ ਸਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ ਸਥਿਰ • ਐਪਸ #2487 ਨੂੰ ਬਦਲਦੇ ਸਮੇਂ ਡਾਊਨਲੋਡ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਗਾਇਬ ਹੋਣ ਵਾਲੇ ਬਟਨਾਂ ਨੂੰ ਠੀਕ ਕਰੋ • ਫਿਕਸ ਪਲੇਬੈਕ ਸਥਿਤੀ ਸਟੋਰ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਹਾਲਾਂਕਿ ਦੇਖਣ ਦਾ ਇਤਿਹਾਸ ਅਯੋਗ ਹੈ • ਸੂਚੀ ਦ੍ਰਿਸ਼ #2517 ਵਿੱਚ ਪਲੇਬੈਕ ਸਥਿਤੀ ਦੇ ਕਾਰਨ ਘਟੇ ਪ੍ਰਦਰਸ਼ਨ ਨੂੰ ਠੀਕ ਕਰੋ • [ਐਕਸਟ੍ਰੈਕਟਰ] ReCaptchaActivity #2527, TeamNewPipe/NewPipeExtractor#186 ਫਿਕਸ • [ਐਕਸਟ੍ਰੈਕਟਰ] [YouTube] ਜਦੋਂ ਪਲੇਲਿਸਟਾਂ ਨਤੀਜੇ ਵਿੱਚ ਹੋਣ ਤਾਂ ਆਮ ਖੋਜ ਗਲਤੀ ਨੂੰ ਠੀਕ ਕਰੋ TeamNewPipe/NewPipeExtractor#185 0.17.0 ਵਿੱਚ ਬਦਲਾਅ ਨਵਾਂ ਪਲੇਬੈਕ ਰੈਜ਼ਿਊਮੇ #2288 • ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਮੁੜ ਸ਼ੁਰੂ ਕਰੋ ਜਿੱਥੇ ਤੁਸੀਂ ਪਿਛਲੀ ਵਾਰ ਰੁਕੇ ਸੀ ਡਾਊਨਲੋਡਰ ਸੁਧਾਰ #2149 • ਬਾਹਰੀ SD-ਕਾਰਡਾਂ 'ਤੇ ਡਾਊਨਲੋਡ ਸਟੋਰ ਕਰਨ ਲਈ ਸਟੋਰੇਜ਼ ਐਕਸੈਸ ਫਰੇਮਵਰਕ ਦੀ ਵਰਤੋਂ ਕਰੋ • ਨਵਾਂ mp4 muxer • ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਵਿਕਲਪਿਕ ਤੌਰ 'ਤੇ ਡਾਉਨਲੋਡ ਡਾਇਰੈਕਟਰੀ ਨੂੰ ਬਦਲੋ • ਮੀਟਰਡ ਨੈੱਟਵਰਕਾਂ ਦਾ ਆਦਰ ਕਰੋ ਸੁਧਾਰ • gema ਸਤਰ #2295 ਨੂੰ ਹਟਾਇਆ • ਗਤੀਵਿਧੀ ਜੀਵਨ ਚੱਕਰ #2444 ਦੌਰਾਨ ਹੈਂਡਲ (ਆਟੋ) ਰੋਟੇਸ਼ਨ ਤਬਦੀਲੀਆਂ • ਲੰਬੇ-ਦਬਾਓ ਮੀਨੂ ਨੂੰ ਇਕਸਾਰ #2368 ਬਣਾਓ ਸਥਿਰ • ਫਿਕਸਡ ਚੁਣਿਆ ਹੋਇਆ ਉਪਸਿਰਲੇਖ ਟਰੈਕ ਨਾਮ #2394 ਨਹੀਂ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ • ਐਪ ਅੱਪਡੇਟ ਦੀ ਜਾਂਚ ਅਸਫਲ ਹੋਣ 'ਤੇ ਕ੍ਰੈਸ਼ ਨਾ ਹੋਵੋ (GitHub ਸੰਸਕਰਣ) #2423 • ਸਥਿਰ ਡਾਊਨਲੋਡ 99.9% #2440 'ਤੇ ਅਟਕ ਗਏ • ਪਲੇ ਕਤਾਰ ਮੈਟਾਡੇਟਾ #2453 ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ • [SoundCloud] ਪਲੇਲਿਸਟਸ ਲੋਡ ਕਰਨ ਵੇਲੇ ਸਥਿਰ ਕਰੈਸ਼ TeamNewPipe/NewPipeExtractor#170 • [YouTube] ਸਥਿਰ ਅਵਧੀ ਨੂੰ ਪਾਰਸਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ TeamNewPipe/NewPipeExtractor#177 +0.17.1 ਵਿੱਚ ਬਦਲਾਅ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਪਲੇਲਿਸਟਾਂ ਲਈ ਦੁਬਾਰਾ ਲੰਬੇ-ਦਬਾਓ ਵਾਲੇ ਮੀਨੂ ਵਿੱਚ ਇੱਥੇ ਚਲਾਉਣਾ ਸ਼ੁਰੂ ਕਰੋ ਐਕਸ਼ਨ ਸ਼ਾਮਲ ਕਰੋ +• SAF / ਲੀਗੇਸੀ ਫਾਈਲ ਪਿਕਰ #2521 ਲਈ ਸਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ +ਫਿਕਸਡ +• ਐਪਸ ਨੂੰ ਸਵਿੱਚ ਕਰਦੇ ਸਮੇਂ ਡਾਊਨਲੋਡ ਵਿਊ ਵਿੱਚ ਗਾਇਬ ਹੋਣ ਵਾਲੇ ਬਟਨਾਂ ਨੂੰ ਠੀਕ ਕਰੋ #2487 +• ਦੇਖਣ ਦੇ ਇਤਿਹਾਸ ਨੂੰ ਅਯੋਗ ਹੋਣ ਦੇ ਬਾਵਜੂਦ ਸਟੋਰ ਕੀਤੀ ਗਈ ਪਲੇਬੈਕ ਸਥਿਤੀ ਨੂੰ ਠੀਕ ਕਰੋ +• ਸੂਚੀ ਵਿਊ ਵਿੱਚ ਪਲੇਬੈਕ ਸਥਿਤੀ ਕਾਰਨ ਘਟੀ ਹੋਈ ਪ੍ਰਦਰਸ਼ਨ ਨੂੰ ਠੀਕ ਕਰੋ +• [ਐਕਸਟ੍ਰੈਕਟਰ] [YouTube] ਜਦੋਂ ਪਲੇਲਿਸਟਾਂ ਨਤੀਜਿਆਂ ਵਿੱਚ ਹੋਣ ਤਾਂ ਆਮ ਖੋਜ ਗਲਤੀ ਨੂੰ ਠੀਕ ਕਰੋ diff --git a/fastlane/metadata/android/pa/changelogs/780.txt b/fastlane/metadata/android/pa/changelogs/780.txt index 999a24468..923a0410a 100644 --- a/fastlane/metadata/android/pa/changelogs/780.txt +++ b/fastlane/metadata/android/pa/changelogs/780.txt @@ -1 +1,11 @@ -0.17.3 ਵਿੱਚ ਬਦਲਾਅ ਸੁਧਾਰ • ਪਲੇਬੈਕ ਸਥਿਤੀਆਂ #2550 ਨੂੰ ਸਾਫ਼ ਕਰਨ ਲਈ ਵਿਕਲਪ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ • ਫਾਈਲ ਪਿਕਰ #2591 ਵਿੱਚ ਲੁਕੀਆਂ ਹੋਈਆਂ ਡਾਇਰੈਕਟਰੀਆਂ ਦਿਖਾਓ • NewPipe #2488 ਨਾਲ ਖੋਲ੍ਹੇ ਜਾਣ ਵਾਲੇ `invidio.us` ਉਦਾਹਰਨਾਂ ਤੋਂ ਸਮਰਥਨ URL • `music.youtube.com` URLs TeamNewPipe/NewPipeExtractor#194 ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ ਸਥਿਰ • [YouTube] ਸਥਿਰ 'java.lang.IllegalArgumentException #192 • [YouTube] ਸਥਿਰ ਲਾਈਵ ਸਟ੍ਰੀਮਾਂ ਕੰਮ ਨਹੀਂ ਕਰ ਰਹੀਆਂ TeamNewPipe/NewPipeExtractor#195 • ਇੱਕ ਸਟ੍ਰੀਮ #2592 ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਵੇਲੇ ਐਂਡਰੌਇਡ ਪਾਈ ਵਿੱਚ ਸਥਿਰ ਪ੍ਰਦਰਸ਼ਨ ਸਮੱਸਿਆ +0.17.3 ਵਿੱਚ ਬਦਲਾਅ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਪਲੇਬੈਕ ਸਥਿਤੀਆਂ ਨੂੰ ਸਾਫ਼ ਕਰਨ ਲਈ ਵਿਕਲਪ ਜੋੜਿਆ ਗਿਆ #2550 +• ਫਾਈਲ ਚੋਣਕਾਰ #2591 ਵਿੱਚ ਲੁਕੀਆਂ ਹੋਈਆਂ ਡਾਇਰੈਕਟਰੀਆਂ ਦਿਖਾਓ +• NewPipe #2488 ਨਾਲ ਖੋਲ੍ਹੇ ਜਾਣ ਵਾਲੇ `invidio.us` ਉਦਾਹਰਣਾਂ ਤੋਂ URL ਦਾ ਸਮਰਥਨ ਕਰੋ +• `music.youtube.com` URL ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ + +ਸਥਿਰ +• [YouTube] ਫਿਕਸਡ ਲਾਈਵ ਸਟ੍ਰੀਮਾਂ ਕੰਮ ਨਹੀਂ ਕਰ ਰਹੀਆਂ +• ਸਟ੍ਰੀਮ ਡਾਊਨਲੋਡ ਕਰਦੇ ਸਮੇਂ ਐਂਡਰਾਇਡ ਪਾਈ ਵਿੱਚ ਪ੍ਰਦਰਸ਼ਨ ਸਮੱਸਿਆ ਹੱਲ ਕੀਤੀ ਗਈ #2592 diff --git a/fastlane/metadata/android/pa/changelogs/790.txt b/fastlane/metadata/android/pa/changelogs/790.txt index f841801eb..28627c7ec 100644 --- a/fastlane/metadata/android/pa/changelogs/790.txt +++ b/fastlane/metadata/android/pa/changelogs/790.txt @@ -1 +1,11 @@ -ਸੁਧਾਰ • ਅੰਨ੍ਹੇ ਲੋਕਾਂ #2655 ਲਈ ਪਹੁੰਚਯੋਗਤਾ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ ਹੋਰ ਸਿਰਲੇਖ ਸ਼ਾਮਲ ਕਰੋ • ਡਾਉਨਲੋਡ ਫੋਲਡਰ ਸੈਟਿੰਗ ਦੀ ਭਾਸ਼ਾ ਨੂੰ ਵਧੇਰੇ ਇਕਸਾਰ ਅਤੇ ਘੱਟ ਅਸਪਸ਼ਟ #2637 ਬਣਾਓ ਸਥਿਰ • ਜਾਂਚ ਕਰੋ ਕਿ ਕੀ ਬਲਾਕ ਵਿੱਚ ਆਖਰੀ ਬਾਈਟ #2646 ਡਾਊਨਲੋਡ ਕੀਤੀ ਗਈ ਹੈ • ਵੀਡੀਓ ਡਿਟੇਲ ਫਰੈਗਮੈਂਟ #2672 ਵਿੱਚ ਸਥਿਰ ਸਕ੍ਰੋਲਿੰਗ • ਡਬਲ ਸਰਚ ਕਲੀਅਰ ਬਾਕਸ ਐਨੀਮੇਸ਼ਨ ਨੂੰ ਇੱਕ #2695 ਵਿੱਚ ਹਟਾਓ • [SoundCloud] ਕਲਾਇਟ_ਆਈਡੀ ਐਕਸਟਰੈਕਸ਼ਨ #2745 ਨੂੰ ਠੀਕ ਕਰੋ ਵਿਕਾਸ • NewPipeExtractor ਤੋਂ ਵਿਰਾਸਤ ਵਿੱਚ ਮਿਲੀ ਗੁੰਮ ਨਿਰਭਰਤਾ ਨੂੰ NewPipe #2535 ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ • AndroidX #2685 'ਤੇ ਮਾਈਗ੍ਰੇਟ ਕਰੋ • ExoPlayer 2.10.6 #2697, #2736 ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ +ਸੁਧਾਰਿਆ ਗਿਆ +• ਹੋਰ ਸਿਰਲੇਖ ਸ਼ਾਮਲ ਕਰੋ + +ਠੀਕ ਕੀਤਾ ਗਿਆ +• ਜਾਂਚ ਕਰੋ ਕਿ ਕੀ ਬਲਾਕ ਵਿੱਚ ਆਖਰੀ ਬਾਈਟ ਡਾਊਨਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ #2646 +• ਵੀਡੀਓ ਵੇਰਵੇ ਵਾਲੇ ਟੁਕੜੇ #2672 ਵਿੱਚ ਸਕ੍ਰੌਲਿੰਗ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ +• [SoundCloud] client_id ਐਕਸਟਰੈਕਸ਼ਨ #2745 ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ + +ਵਿਕਾਸ +• AndroidX 'ਤੇ ਮਾਈਗ੍ਰੇਟ ਕਰੋ +• ExoPlayer 2.10.6 'ਤੇ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/800.txt b/fastlane/metadata/android/pa/changelogs/800.txt index 53868c894..08940d095 100644 --- a/fastlane/metadata/android/pa/changelogs/800.txt +++ b/fastlane/metadata/android/pa/changelogs/800.txt @@ -1 +1,10 @@ -ਨਵਾਂ • P2P (#2201) [ਬੀਟਾ] ਤੋਂ ਬਿਨਾਂ PeerTube ਸਮਰਥਨ: ◦ PeerTube ਉਦਾਹਰਨਾਂ ਤੋਂ ਵੀਡੀਓ ਦੇਖੋ ਅਤੇ ਡਾਊਨਲੋਡ ਕਰੋ ◦ ਪੂਰੀ PeerTube ਸੰਸਾਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਉਦਾਹਰਨਾਂ ਸ਼ਾਮਲ ਕਰੋ ◦ Android 4.4 ਅਤੇ 7.1 'ਤੇ SSL ਹੈਂਡਸ਼ੇਕ ਨਾਲ ਸਮੱਸਿਆਵਾਂ ਹੋ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਕੁਝ ਖਾਸ ਮੌਕਿਆਂ 'ਤੇ ਪਹੁੰਚ ਕਰਦੇ ਸਮੇਂ ਨੈੱਟਵਰਕ ਗੜਬੜ ਹੋ ਜਾਂਦੀ ਹੈ। • ਡਾਊਨਲੋਡਰ (#2679): ◦ ਡਾਊਨਲੋਡ ETA ਦੀ ਗਣਨਾ ਕਰੋ ◦ ਓਪਸ (ਵੈਬ ਫਾਈਲਾਂ) ਨੂੰ ogg ਵਜੋਂ ਡਾਊਨਲੋਡ ਕਰੋ ◦ ਲੰਬੇ ਵਿਰਾਮ ਤੋਂ ਬਾਅਦ ਡਾਊਨਲੋਡ ਮੁੜ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਮਿਆਦ ਪੁੱਗ ਚੁੱਕੇ ਡਾਊਨਲੋਡ ਲਿੰਕਾਂ ਨੂੰ ਮੁੜ-ਹਾਸਲ ਕਰੋ ਸੁਧਾਰ • ਕਿਓਸਕਫ੍ਰੈਗਮੈਂਟ ਨੂੰ ਤਰਜੀਹੀ ਸਮਗਰੀ ਵਾਲੇ ਦੇਸ਼ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਤੋਂ ਜਾਣੂ ਕਰਵਾਓ ਅਤੇ ਸਾਰੀਆਂ ਮੁੱਖ ਟੈਬਾਂ #2742 ਦੀ ਕਾਰਗੁਜ਼ਾਰੀ ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ। • ਐਕਸਟਰੈਕਟਰ #2713 ਤੋਂ ਨਵੇਂ ਸਥਾਨਕਕਰਨ ਅਤੇ ਡਾਉਨਲੋਡਰ ਲਾਗੂਕਰਨ ਦੀ ਵਰਤੋਂ ਕਰੋ • "ਡਿਫੌਲਟ ਕਿਓਸਕ" ਸਤਰ ਨੂੰ ਅਨੁਵਾਦਯੋਗ ਬਣਾਓ • ਬਲੈਕ ਥੀਮ #2569 ਲਈ ਬਲੈਕ ਨੈਵੀਗੇਸ਼ਨ ਪੱਟੀ ਸਥਿਰ • ਇੱਕ ਬੱਗ ਫਿਕਸ ਕੀਤਾ ਗਿਆ ਹੈ ਜੋ ਪੌਪਅੱਪ ਪਲੇਅਰ ਨੂੰ ਹਿਲਾ ਨਹੀਂ ਸਕਦਾ ਸੀ ਜੇਕਰ ਪੌਪਅੱਪ ਪਲੇਅਰ #2772 ਨੂੰ ਹਿਲਾਉਂਦੇ ਸਮੇਂ ਕੋਈ ਹੋਰ ਉਂਗਲ ਰੱਖੀ ਜਾਂਦੀ ਹੈ • ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਅਪਲੋਡਰ ਦੀ ਗੁੰਮਸ਼ੁਦਗੀ ਦੀ ਆਗਿਆ ਦਿਓ ਅਤੇ ਇਸ ਸਮੱਸਿਆ ਨਾਲ ਸਬੰਧਤ ਕ੍ਰੈਸ਼ਾਂ ਨੂੰ ਠੀਕ ਕਰੋ #2724, TeamNewPipe/NewPipeExtractor#219 • MediaCCC ਅਤੇ ਕੁਝ PeerTube ਉਦਾਹਰਨਾਂ #2792 ਨਾਲ TLS ਹੈਂਡਸ਼ੇਕ ਨੂੰ ਠੀਕ ਕਰਨ ਲਈ Android 4.4 ਡਿਵਾਈਸਾਂ (API 19/KitKat) 'ਤੇ TLS1.1/1.2 ਨੂੰ ਸਮਰੱਥ ਕਰਨਾ • [SoundCloud] ਫਿਕਸਡ ਕਲਾਈਂਟ_ਆਈਡੀ ਐਕਸਟ੍ਰੈਕਸ਼ਨ TeamNewPipe/NewPipeExtractor#217 • [SoundCloud] ਆਡੀਓ ਸਟ੍ਰੀਮ ਕੱਢਣ ਨੂੰ ਠੀਕ ਕਰੋ ਵਿਕਾਸ • ExoPlayer ਨੂੰ 2.10.8 #2791, #2816 'ਤੇ ਅੱਪਡੇਟ ਕਰੋ • Gradle ਨੂੰ 3.5.1 ਵਿੱਚ ਅੱਪਡੇਟ ਕਰੋ ਅਤੇ Kotlin ਸਹਿਯੋਗ #2714 ਸ਼ਾਮਲ ਕਰੋ +ਨਵਾਂ +• P2P ਤੋਂ ਬਿਨਾਂ PeerTube ਸਹਾਇਤਾ (#2201) [ਬੀਟਾ]: + +◦ ਲੰਬੇ ਵਿਰਾਮ ਤੋਂ ਬਾਅਦ ਡਾਊਨਲੋਡ ਮੁੜ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਮਿਆਦ ਪੁੱਗ ਚੁੱਕੇ ਡਾਊਨਲੋਡ ਲਿੰਕਾਂ ਨੂੰ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਪਸੰਦੀਦਾ ਸਮੱਗਰੀ ਦੇਸ਼ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਬਾਰੇ KioskFragment ਨੂੰ ਸੂਚਿਤ ਕਰੋ ਅਤੇ ਸਾਰੇ ਮੁੱਖ ਟੈਬਾਂ ਵਿੱਚ ਪ੍ਰਦਰਸ਼ਨ ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ #2742 + +ਸਥਿਰ +• Android 4.4 ਡਿਵਾਈਸਾਂ (API 19/KitKat) 'ਤੇ TLS1.1/1.2 ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ diff --git a/fastlane/metadata/android/pa/changelogs/810.txt b/fastlane/metadata/android/pa/changelogs/810.txt index 96a2b9da5..d10bc6913 100644 --- a/fastlane/metadata/android/pa/changelogs/810.txt +++ b/fastlane/metadata/android/pa/changelogs/810.txt @@ -1 +1,11 @@ -ਨਵਾਂ • ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਦੇ ਸਮੇਂ ਲੌਕ ਸਕ੍ਰੀਨ 'ਤੇ ਵੀਡੀਓ ਥੰਬਨੇਲ ਦਿਖਾਓ ਸੁਧਾਰ • ਬੈਕਗ੍ਰਾਉਂਡ / ਪੌਪਅੱਪ ਬਟਨ 'ਤੇ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਦਬਾਉਣ 'ਤੇ ਕਤਾਰ ਵਿੱਚ ਸਥਾਨਕ ਪਲੇਲਿਸਟ ਸ਼ਾਮਲ ਕਰੋ • ਮੁੱਖ ਪੰਨਾ ਟੈਬਾਂ ਨੂੰ ਸਕ੍ਰੋਲ ਕਰਨ ਯੋਗ ਬਣਾਓ ਅਤੇ ਸਿਰਫ਼ ਇੱਕ ਟੈਬ ਹੋਣ 'ਤੇ ਲੁਕਾਓ • ਬੈਕਗ੍ਰਾਉਂਡ ਪਲੇਅਰ ਵਿੱਚ ਸੂਚਨਾ ਥੰਬਨੇਲ ਅੱਪਡੇਟ ਦੀ ਸੀਮਾ ਮਾਤਰਾ • ਖਾਲੀ ਸਥਾਨਕ ਪਲੇਲਿਸਟਾਂ ਲਈ ਡਮੀ ਥੰਬਨੇਲ ਸ਼ਾਮਲ ਕਰੋ • *.webm ਦੀ ਬਜਾਏ *.opus ਫਾਈਲ ਐਕਸਟੈਂਸ਼ਨ ਦੀ ਵਰਤੋਂ ਕਰੋ ਅਤੇ ਡਾਊਨਲੋਡ ਡ੍ਰੌਪਡਾਉਨ ਵਿੱਚ "WebM Opus" ਦੀ ਬਜਾਏ ਫਾਰਮੈਟ ਲੇਬਲ ਵਿੱਚ "opus" ਦਿਖਾਓ • "ਡਾਊਨਲੋਡ" ਵਿੱਚ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ ਜਾਂ ਡਾਊਨਲੋਡ ਇਤਿਹਾਸ ਨੂੰ ਮਿਟਾਉਣ ਲਈ ਬਟਨ ਸ਼ਾਮਲ ਕਰੋ • [YouTube] /c/shortened_url ਚੈਨਲ ਲਿੰਕਾਂ ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ ਸਥਿਰ • NewPipe ਨਾਲ ਵੀਡੀਓ ਸਾਂਝਾ ਕਰਨ ਅਤੇ ਇਸ ਦੀਆਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਸਿੱਧੇ ਡਾਊਨਲੋਡ ਕਰਨ ਵੇਲੇ ਕਈ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਹੱਲ ਕੀਤਾ ਗਿਆ • ਇਸ ਦੇ ਸਿਰਜਣ ਥ੍ਰੈਡ ਤੋਂ ਬਾਹਰ ਸਥਿਰ ਪਲੇਅਰ ਪਹੁੰਚ • ਸਥਿਰ ਖੋਜ ਨਤੀਜੇ ਪੇਜਿੰਗ • [YouTube] ਨਿਸ਼ਚਤ ਸਵਿਚਿੰਗ ਚਾਲੂ ਕਰਨ ਨਾਲ NPE ਹੁੰਦਾ ਹੈ • [YouTube] ਇੱਕ invidio.us url ਖੋਲ੍ਹਣ ਵੇਲੇ ਟਿੱਪਣੀਆਂ ਦੇਖਣ ਲਈ ਸਥਿਰ • [SoundCloud] ਅੱਪਡੇਟ ਕੀਤਾ client_id +ਨਵਾਂ +• ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਦੇ ਸਮੇਂ ਲਾਕ ਸਕ੍ਰੀਨ 'ਤੇ ਵੀਡੀਓ ਥੰਬਨੇਲ ਦਿਖਾਓ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਬੈਕਗ੍ਰਾਊਂਡ/ਪੌਪਅੱਪ ਬਟਨ ਨੂੰ ਦੇਰ ਤੱਕ ਦਬਾਉਣ 'ਤੇ ਸਥਾਨਕ ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਕਤਾਰ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ +• [YouTube] /c/shortened_url ਚੈਨਲ ਲਿੰਕਾਂ ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ + +ਠੀਕ ਕੀਤਾ ਗਿਆ +• NewPipe 'ਤੇ ਵੀਡੀਓ ਸਾਂਝੇ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀਆਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਸਿੱਧਾ ਡਾਊਨਲੋਡ ਕਰਨ ਵੇਲੇ ਕਈ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਹੱਲ ਕੀਤਾ ਗਿਆ +• ਖੋਜ ਨਤੀਜਿਆਂ ਦੀ ਪੇਜਿੰਗ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ +• [SoundCloud] client_id ਨੂੰ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/840.txt b/fastlane/metadata/android/pa/changelogs/840.txt index 745098496..d05907bd6 100644 --- a/fastlane/metadata/android/pa/changelogs/840.txt +++ b/fastlane/metadata/android/pa/changelogs/840.txt @@ -1 +1,10 @@ -ਨਵਾਂ • ਐਪ ਦੀ ਭਾਸ਼ਾ ਬਦਲਣ ਲਈ ਭਾਸ਼ਾ ਚੋਣਕਾਰ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ • ਪਲੇਅਰ ਸਮੇਟਣਯੋਗ ਮੀਨੂ ਵਿੱਚ ਕੋਡੀ ਬਟਨ 'ਤੇ ਭੇਜੋ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ • ਲੰਬੀ ਪ੍ਰੈਸ 'ਤੇ ਟਿੱਪਣੀਆਂ ਨੂੰ ਕਾਪੀ ਕਰਨ ਦੀ ਸਮਰੱਥਾ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ ਹੈ ਸੁਧਾਰ • ਰੀਕੈਪਚਾ ਗਤੀਵਿਧੀ ਨੂੰ ਠੀਕ ਕਰੋ ਅਤੇ ਪ੍ਰਾਪਤ ਕੀਤੀਆਂ ਕੂਕੀਜ਼ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਸੁਰੱਖਿਅਤ ਕਰੋ • ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਦੇਖਣ ਦਾ ਇਤਿਹਾਸ ਚਾਲੂ ਨਾ ਹੋਣ 'ਤੇ ਦਰਾਜ਼ ਦੇ ਹੱਕ ਵਿੱਚ ਡਾਟ-ਮੀਨੂ ਨੂੰ ਹਟਾਇਆ ਗਿਆ ਅਤੇ ਇਤਿਹਾਸ ਨੂੰ ਲੁਕਾਓ ਬਟਨ • Android 6 ਅਤੇ ਬਾਅਦ ਵਾਲੇ 'ਤੇ ਸਹੀ ਢੰਗ ਨਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਹੋਰ ਐਪਾਂ ਦੀ ਇਜਾਜ਼ਤ ਦੇ ਉੱਪਰ ਡਿਸਪਲੇ ਲਈ ਪੁੱਛੋ • BookmarkFragment ਵਿੱਚ ਲੰਮਾ-ਕਲਿੱਕ ਕਰਕੇ ਸਥਾਨਕ ਪਲੇਲਿਸਟ ਦਾ ਨਾਮ ਬਦਲੋ • ਕਈ PeerTube ਸੁਧਾਰ • ਕਈ ਅੰਗਰੇਜ਼ੀ ਸਰੋਤ ਸਤਰਾਂ ਨੂੰ ਸੁਧਾਰਿਆ ਗਿਆ ਹੈ ਸਥਿਰ • ਫਿਕਸਡ ਪਲੇਅਰ ਦੁਬਾਰਾ ਸ਼ੁਰੂ ਹੋ ਰਿਹਾ ਹੈ ਹਾਲਾਂਕਿ ਇਹ ਉਦੋਂ ਰੋਕਿਆ ਜਾਂਦਾ ਹੈ ਜਦੋਂ ਵਿਕਲਪ "ਐਪ ਸਵਿੱਚ 'ਤੇ ਛੋਟਾ ਕਰੋ" ਯੋਗ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ ਨਿਊ ਪਾਈਪ ਨੂੰ ਛੋਟਾ ਕੀਤਾ ਜਾਂਦਾ ਹੈ • ਸੰਕੇਤ ਲਈ ਸ਼ੁਰੂਆਤੀ ਚਮਕ ਮੁੱਲ ਨੂੰ ਠੀਕ ਕਰੋ • ਸਥਿਰ .srt ਉਪਸਿਰਲੇਖ ਡਾਉਨਲੋਡ ਜਿਸ ਵਿੱਚ ਸਾਰੇ ਲਾਈਨ ਬ੍ਰੇਕ ਨਹੀਂ ਹਨ • SD ਕਾਰਡ 'ਤੇ ਸਥਿਰ ਡਾਊਨਲੋਡ ਅਸਫਲ ਹੋ ਰਿਹਾ ਹੈ ਕਿਉਂਕਿ ਕੁਝ Android 5 ਡਿਵਾਈਸਾਂ CTF ਅਨੁਕੂਲ ਨਹੀਂ ਹਨ • Android KitKat 'ਤੇ ਸਥਿਰ ਡਾਊਨਲੋਡਿੰਗ • ਸਥਿਰ ਭ੍ਰਿਸ਼ਟ ਵੀਡੀਓ .mp4 ਫਾਈਲ ਨੂੰ ਆਡੀਓ ਫਾਈਲ ਵਜੋਂ ਮਾਨਤਾ ਦਿੱਤੀ ਜਾ ਰਹੀ ਹੈ • ਗਲਤ ਚੀਨੀ ਭਾਸ਼ਾ ਕੋਡ ਸਮੇਤ, ਮਲਟੀਪਲ ਸਥਾਨੀਕਰਨ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਹੱਲ ਕੀਤਾ ਗਿਆ ਹੈ • [YouTube] ਵਰਣਨ ਵਿੱਚ ਟਾਈਮਸਟੈਂਪ ਦੁਬਾਰਾ ਕਲਿੱਕ ਕਰਨ ਯੋਗ ਹਨ +ਨਵਾਂ +• ਐਪ ਦੀ ਭਾਸ਼ਾ ਬਦਲਣ ਲਈ ਇੱਕ ਭਾਸ਼ਾ ਚੋਣਕਾਰ ਜੋੜਿਆ ਗਿਆ +• ਪਲੇਅਰ ਦੇ ਕੋਲੈਪਸੀਬਲ ਮੀਨੂ ਵਿੱਚ ਕੋਡੀ ਨੂੰ ਭੇਜੋ ਬਟਨ ਜੋੜਿਆ ਗਿਆ +• ਟਿੱਪਣੀਆਂ ਦੀ ਕਾਪੀ ਕਰਨ ਲਈ ਇੱਕ ਲੰਮਾ-ਦਬਾਓ ਵਿਸ਼ੇਸ਼ਤਾ ਜੋੜਿਆ ਗਿਆ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਰੀਕੈਪਚਾ ਗਤੀਵਿਧੀ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ ਅਤੇ ਪ੍ਰਾਪਤ ਕੂਕੀਜ਼ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ + +ਠੀਕ ਕੀਤਾ ਗਿਆ +• ਐਂਡਰਾਇਡ ਕਿਟਕੈਟ 'ਤੇ ਡਾਊਨਲੋਡਿੰਗ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/920.txt b/fastlane/metadata/android/pa/changelogs/920.txt index 04fc07937..94b1e74a0 100644 --- a/fastlane/metadata/android/pa/changelogs/920.txt +++ b/fastlane/metadata/android/pa/changelogs/920.txt @@ -1 +1,9 @@ -ਸੁਧਾਰ • ਸਟ੍ਰੀਮ ਗਰਿੱਡ ਆਈਟਮਾਂ 'ਤੇ ਅੱਪਲੋਡ ਦੀ ਮਿਤੀ ਅਤੇ ਦੇਖਣ ਦੀ ਗਿਣਤੀ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ • ਦਰਾਜ਼ ਹੈਡਰ ਲੇਆਉਟ ਲਈ ਸੁਧਾਰ ਸਥਿਰ • ਏਪੀਆਈ 19 'ਤੇ ਕ੍ਰੈਸ਼ ਹੋਣ ਕਾਰਨ ਫਿਕਸਡ ਮਿਊਟ ਬਟਨ • ਲੰਬੇ 1080p 60fps ਵੀਡੀਓ ਦੀ ਸਥਿਰ ਡਾਊਨਲੋਡਿੰਗ +ਸੁਧਾਰਿਆ ਗਿਆ + +• ਸਟ੍ਰੀਮ ਗਰਿੱਡ ਆਈਟਮਾਂ 'ਤੇ ਅਪਲੋਡ ਮਿਤੀ ਅਤੇ ਵਿਯੂ ਗਿਣਤੀ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ +• ਦਰਾਜ਼ ਹੈਡਰ ਲੇਆਉਟ ਲਈ ਸੁਧਾਰ + +ਠੀਕ ਕੀਤਾ ਗਿਆ + +• API 19 'ਤੇ ਕਰੈਸ਼ ਹੋਣ ਵਾਲੇ ਮਿਊਟ ਬਟਨ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ +• ਲੰਬੇ 1080p 60fps ਵੀਡੀਓਜ਼ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨਾ ਠੀਕ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/930.txt b/fastlane/metadata/android/pa/changelogs/930.txt index a067bfb58..96fc7d0b5 100644 --- a/fastlane/metadata/android/pa/changelogs/930.txt +++ b/fastlane/metadata/android/pa/changelogs/930.txt @@ -1 +1,14 @@ -ਨਵਾਂ • YouTube ਸੰਗੀਤ 'ਤੇ ਖੋਜੋ • ਬੁਨਿਆਦੀ Android TV ਸਮਰਥਨ ਸੁਧਾਰ • ਇੱਕ ਸਥਾਨਕ ਪਲੇਲਿਸਟ ਤੋਂ ਸਾਰੇ ਦੇਖੇ ਗਏ ਵੀਡੀਓ ਨੂੰ ਹਟਾਉਣ ਦੀ ਯੋਗਤਾ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ ਹੈ • ਕ੍ਰੈਸ਼ ਹੋਣ ਦੀ ਬਜਾਏ ਜਦੋਂ ਸਮੱਗਰੀ ਅਜੇ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ ਤਾਂ ਸੁਨੇਹਾ ਦਿਖਾਓ • ਚੁਟਕੀ ਇਸ਼ਾਰਿਆਂ ਨਾਲ ਪੌਪਅੱਪ ਪਲੇਅਰ ਦਾ ਆਕਾਰ ਬਦਲਿਆ ਗਿਆ ਹੈ • ਬੈਕਗ੍ਰਾਊਂਡ 'ਤੇ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਦਬਾਉਣ ਅਤੇ ਚੈਨਲ ਵਿੱਚ ਪੌਪਅੱਪ ਬਟਨਾਂ 'ਤੇ ਸਟ੍ਰੀਮ ਨੂੰ ਐਨਕਿਊ ਕਰੋ • ਦਰਾਜ਼ ਸਿਰਲੇਖ ਦੇ ਸਿਰਲੇਖ ਦੇ ਆਕਾਰ ਨੂੰ ਸੰਭਾਲਣ ਵਿੱਚ ਸੁਧਾਰ ਕੀਤਾ ਗਿਆ ਹੈ ਸਥਿਰ • ਨਿਸ਼ਚਿਤ ਉਮਰ ਪ੍ਰਤਿਬੰਧਿਤ ਸਮੱਗਰੀ ਸੈਟਿੰਗ ਕੰਮ ਨਹੀਂ ਕਰ ਰਹੀ • ਕੁਝ ਖਾਸ ਕਿਸਮ ਦੇ reCAPTCHA ਫਿਕਸ ਕੀਤੇ ਗਏ ਹਨ • ਪਲੇਲਿਸਟ `ਨੱਲ` ਹੋਣ 'ਤੇ ਬੁੱਕਮਾਰਕ ਖੋਲ੍ਹਣ ਵੇਲੇ ਸਥਿਰ ਕਰੈਸ਼ • ਨੈੱਟਵਰਕ ਸੰਬੰਧੀ ਅਪਵਾਦਾਂ ਦੀ ਸਥਿਰ ਖੋਜ • ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਫਰੈਗਮੈਂਟ ਵਿੱਚ ਗਰੁੱਪ ਸੌਰਟ ਬਟਨ ਦੀ ਸਥਿਰ ਦਿੱਖ ਅਤੇ ਹੋਰ +ਨਵਾਂ +• YouTube ਸੰਗੀਤ ਖੋਜੋ +• ਮੁੱਢਲਾ Android TV ਸਮਰਥਨ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਸਥਾਨਕ ਪਲੇਲਿਸਟਾਂ ਤੋਂ ਸਾਰੇ ਦੇਖੇ ਗਏ ਵੀਡੀਓ ਹਟਾਉਣ ਦੀ ਯੋਗਤਾ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ +• ਜਦੋਂ ਸਮੱਗਰੀ ਵਰਤਮਾਨ ਵਿੱਚ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ ਤਾਂ ਕ੍ਰੈਸ਼ ਹੋਣ ਦੀ ਬਜਾਏ ਇੱਕ ਸੁਨੇਹਾ ਦਿਖਾਓ + +ਠੀਕ ਕੀਤਾ ਗਿਆ +• ਉਮਰ-ਪ੍ਰਤੀਬੰਧਿਤ ਸਮੱਗਰੀ ਸੈਟਿੰਗਾਂ ਨਾਲ ਇੱਕ ਸਮੱਸਿਆ ਨੂੰ ਹੱਲ ਕੀਤਾ ਗਿਆ। + +ਕੁਝ reCAPTCHA ਗਲਤੀਆਂ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ। + +ਅਤੇ ਹੋਰ ਵੀ diff --git a/fastlane/metadata/android/pa/changelogs/940.txt b/fastlane/metadata/android/pa/changelogs/940.txt index b9d9b3fdf..3ea03ad03 100644 --- a/fastlane/metadata/android/pa/changelogs/940.txt +++ b/fastlane/metadata/android/pa/changelogs/940.txt @@ -1 +1,14 @@ -ਨਵਾਂ • SoundCloud ਟਿੱਪਣੀਆਂ ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ • YouTube ਪ੍ਰਤਿਬੰਧਿਤ ਮੋਡ ਸੈਟਿੰਗ ਸ਼ਾਮਲ ਕਰੋ • PeerTube ਮੂਲ ਚੈਨਲ ਦੇ ਵੇਰਵੇ ਦਿਖਾਓ ਸੁਧਾਰ • ਸਿਰਫ਼ ਸਮਰਥਿਤ ਸੇਵਾਵਾਂ ਲਈ ਕੋਰ ਬਟਨ ਦਿਖਾਓ • ਨੈਵੀਗੇਸ਼ਨਬਾਰ ਜਾਂ ਸਟੇਟਸਬਾਰ ਤੋਂ ਸ਼ੁਰੂ ਹੋਣ ਵਾਲੇ ਪਲੇਅਰ ਸੰਕੇਤਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ • ਸੇਵਾ ਦੇ ਰੰਗ ਦੇ ਆਧਾਰ 'ਤੇ ਮੁੜ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਅਤੇ ਗਾਹਕ ਬਣੋ ਬਟਨਾਂ ਦਾ ਪਿਛੋਕੜ ਰੰਗ ਬਦਲੋ ਸਥਿਰ • ਡਾਉਨਲੋਡ ਡਾਇਲਾਗ ਫ੍ਰੀਜ਼ ਨੂੰ ਠੀਕ ਕਰੋ • ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਖੋਲ੍ਹੋ ਬਟਨ ਹੁਣ ਅਸਲ ਵਿੱਚ ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਖੁੱਲ੍ਹਦਾ ਹੈ • ਵੀਡੀਓ ਖੋਲ੍ਹਣ 'ਤੇ ਕ੍ਰੈਸ਼ ਨੂੰ ਠੀਕ ਕਰੋ ਅਤੇ "ਇਸ ਸਟ੍ਰੀਮ ਨੂੰ ਚਲਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ" ਅਤੇ ਹੋਰ +ਨਵਾਂ +• SoundCloud ਟਿੱਪਣੀਆਂ ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਲ ਕਰੋ +• YouTube ਪ੍ਰਤਿਬੰਧਿਤ ਮੋਡ ਸੈਟਿੰਗ ਸ਼ਾਮਲ ਕਰੋ +• PeerTube ਪੇਰੈਂਟ ਚੈਨਲ ਵੇਰਵੇ ਦਿਖਾਓ + +ਸੁਧਾਰਿਆ ਗਿਆ +• ਸਿਰਫ਼ ਸਮਰਥਿਤ ਸੇਵਾਵਾਂ ਲਈ Kore ਬਟਨ ਦਿਖਾਓ + +ਠੀਕ ਕੀਤਾ ਗਿਆ +• ਇੱਕ ਸਮੱਸਿਆ ਨੂੰ ਹੱਲ ਕੀਤਾ ਗਿਆ ਜਿੱਥੇ ਡਾਊਨਲੋਡ ਡਾਇਲਾਗ ਫ੍ਰੀਜ਼ ਹੋ ਰਿਹਾ ਸੀ +• ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਖੋਲ੍ਹੋ ਬਟਨ ਹੁਣ ਅਸਲ ਵਿੱਚ ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਖੁੱਲ੍ਹਦਾ ਹੈ +• ਵੀਡੀਓ ਖੋਲ੍ਹਣ ਵੇਲੇ ਕਰੈਸ਼ ਅਤੇ "ਇਸ ਸਟ੍ਰੀਮ ਨੂੰ ਚਲਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ" + +ਅਤੇ ਹੋਰ diff --git a/fastlane/metadata/android/pa/changelogs/951.txt b/fastlane/metadata/android/pa/changelogs/951.txt index 2b1cd7933..f4dd14071 100644 --- a/fastlane/metadata/android/pa/changelogs/951.txt +++ b/fastlane/metadata/android/pa/changelogs/951.txt @@ -1,13 +1,13 @@ -ਨਵਾਂ -• ਫੀਡ ਗਰੁੱਪ ਡਾਇਲਾਗ ਵਿੱਚ ਗਾਹਕੀ ਚੋਣਕਾਰ ਲਈ ਖੋਜ ਸ਼ਾਮਲ ਕਰੋ -• ਸਿਰਫ਼ ਗੈਰ-ਗਰੁੱਪ ਕੀਤੀਆਂ ਗਾਹਕੀਆਂ ਨੂੰ ਦਿਖਾਉਣ ਲਈ ਫੀਡ ਗਰੁੱਪ ਡਾਇਲਾਗ ਵਿੱਚ ਫਿਲਟਰ ਸ਼ਾਮਲ ਕਰੋ -• ਪਲੇਲਿਸਟ ਟੈਬ ਨੂੰ ਮੁੱਖ ਪੰਨੇ 'ਤੇ ਸ਼ਾਮਲ ਕਰੋ -• ਬੈਕਗ੍ਰਾਊਂਡ/ਪੌਪ-ਅੱਪ ਪਲੇਅਰ ਕਤਾਰ ਵਿੱਚ ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ/ਰਿਵਾਈਂਡ ਕਰੋ -• ਖੋਜ ਸੁਝਾਅ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ: ਕੀ ਤੁਹਾਡਾ ਮਤਲਬ ਹੈ ਅਤੇ ਇਸ ਲਈ ਨਤੀਜਾ ਦਿਖਾ ਰਿਹਾ ਹੈ -ਸੁਧਾਰ -• ਮਿਕਸਡ ਫਾਈਲਾਂ ਵਿੱਚ ਐਪਲੀਕੇਸ਼ਨ ਮੈਟਾਡੇਟਾ ਲਿਖਣਾ ਛੱਡੋ • ਕਤਾਰ ਤੋਂ ਅਸਫਲ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਨਾ ਹਟਾਓ -• ਟੂਲਬਾਰ ਦੇ ਰੰਗ ਨਾਲ ਮੇਲ ਕਰਨ ਲਈ ਸਥਿਤੀ ਪੱਟੀ ਦਾ ਰੰਗ ਅੱਪਡੇਟ ਕਰੋ +ਨਵਾਂ +• ਫੀਡ ਗਰੁੱਪ ਡਾਇਲਾਗ ਵਿੱਚ ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਚੋਣਕਾਰ ਲਈ ਖੋਜ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ +• ਸਿਰਫ਼ ਅਣ-ਗਰੁੱਪ ਕੀਤੀਆਂ ਗਾਹਕੀਆਂ ਦਿਖਾਉਣ ਲਈ ਫੀਡ ਗਰੁੱਪ ਡਾਇਲਾਗ ਵਿੱਚ ਇੱਕ ਫਿਲਟਰ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ +• ਮੁੱਖ ਪੰਨੇ 'ਤੇ ਇੱਕ ਪਲੇਲਿਸਟ ਟੈਬ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ -ਠੀਕ ਕੀਤਾ -• ਫਲੋਟਿੰਗ ਪੁਆਇੰਟ ਸੰਚਤ ਤਰੁੱਟੀਆਂ ਦੇ ਕਾਰਨ ਫਿਕਸਡ ਆਡੀਓ/ਵੀਡੀਓ ਡੀਸਿੰਕ -• [PeerTube] ਮਿਟਾਈਆਂ ਗਈਆਂ ਟਿੱਪਣੀਆਂ ਨੂੰ ਸੰਭਾਲੋ ਅਤੇ ਹੋਰ +ਸੁਧਾਰਿਆ ਗਿਆ +• ਮਕਸਡ ਫਾਈਲਾਂ ਵਿੱਚ ਐਪਲੀਕੇਸ਼ਨ ਮੈਟਾਡੇਟਾ ਲਿਖਣਾ ਬੰਦ ਕੀਤਾ ਗਿਆ +• ਕਤਾਰ ਤੋਂ ਅਸਫਲ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਨਾ ਹਟਾਓ + +ਠੀਕ ਕੀਤਾ ਗਿਆ +• ਫਲੋਟਿੰਗ ਪੁਆਇੰਟ ਸੰਚਤ ਗਲਤੀਆਂ ਕਾਰਨ ਆਡੀਓ/ਵੀਡੀਓ ਡੀਸਿੰਕ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ + +ਅਤੇ ਹੋਰ diff --git a/fastlane/metadata/android/pa/changelogs/954.txt b/fastlane/metadata/android/pa/changelogs/954.txt index 3eb8dd68b..b5b0e78d8 100644 --- a/fastlane/metadata/android/pa/changelogs/954.txt +++ b/fastlane/metadata/android/pa/changelogs/954.txt @@ -1,8 +1,9 @@ -• ਨਵਾਂ ਐਪਲੀਕੇਸ਼ਨ ਵਰਕਫਲੋ: ਵੇਰਵੇ ਵਾਲੇ ਪੰਨੇ 'ਤੇ ਵੀਡੀਓ ਚਲਾਓ, ਪਲੇਅਰ ਨੂੰ ਛੋਟਾ ਕਰਨ ਲਈ ਹੇਠਾਂ ਵੱਲ ਸਵਾਈਪ ਕਰੋ -• ਮੀਡੀਆ ਸਟਾਈਲ ਸੂਚਨਾਵਾਂ: ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਅਨੁਕੂਲਿਤ ਕਾਰਵਾਈਆਂ, ਪ੍ਰਦਰਸ਼ਨ ਸੁਧਾਰ -• ਡੈਸਕਟੌਪ ਐਪ ਦੇ ਤੌਰ 'ਤੇ NewPipe ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਮੂਲ ਰੀਸਾਈਜ਼ ਕਰਨਾ +• ਨਵਾਂ ਐਪ ਵਰਕਫਲੋ: ਵੇਰਵੇ ਵਾਲੇ ਪੰਨੇ 'ਤੇ ਵੀਡੀਓ ਚਲਾਓ, ਪਲੇਅਰ ਨੂੰ ਛੋਟਾ ਕਰਨ ਲਈ ਹੇਠਾਂ ਵੱਲ ਸਵਾਈਪ ਕਰੋ +• ਮੀਡੀਆਸਟਾਈਲ ਸੂਚਨਾਵਾਂ: ਸੂਚਨਾਵਾਂ ਵਿੱਚ ਅਨੁਕੂਲਿਤ ਕਾਰਵਾਈਆਂ, ਪ੍ਰਦਰਸ਼ਨ ਸੁਧਾਰ +• ਡੈਸਕਟੌਪ ਐਪ ਦੇ ਤੌਰ 'ਤੇ NewPipe ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਮੂਲ ਆਕਾਰ ਬਦਲਣਾ -• ਇੱਕ ਅਸਮਰਥਿਤ URL ਟੋਸਟ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਖੁੱਲੇ ਵਿਕਲਪਾਂ ਨਾਲ ਡਾਇਲਾਗ ਦਿਖਾਓ -• ਜਦੋਂ ਰਿਮੋਟ ਨੂੰ ਪ੍ਰਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਤਾਂ ਖੋਜ ਸੁਝਾਅ ਅਨੁਭਵ ਨੂੰ ਬਿਹਤਰ ਬਣਾਓ -• ਡਿਫ਼ਾਲਟ ਵੀਡੀਓ ਗੁਣਵੱਤਾ ਨੂੰ 720p60 (ਇਨ-ਐਪ ਪਲੇਅਰ) ਅਤੇ 480p (ਪੌਪ-ਅੱਪ ਪਲੇਅਰ) ਤੱਕ ਵਧਾ ਦਿੱਤਾ ਗਿਆ ਹੈ -• ਬਹੁਤ ਸਾਰੇ ਬੱਗ ਫਿਕਸ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ +• ਇੱਕ ਅਸਮਰਥਿਤ URL ਟੋਸਟ ਦੀ ਸਥਿਤੀ ਵਿੱਚ ਖੁੱਲ੍ਹੇ ਵਿਕਲਪਾਂ ਦੇ ਨਾਲ ਇੱਕ ਡਾਇਲਾਗ ਦਿਖਾਓ +• ਰਿਮੋਟ ਸੁਝਾਅ ਉਪਲਬਧ ਨਾ ਹੋਣ 'ਤੇ ਸੁਧਾਰਾਂ ਦਾ ਅਨੁਭਵ ਕਰੋ +• ਡਿਫੌਲਟ ਵੀਡੀਓ ਗੁਣਵੱਤਾ 720p60 (ਇਨ-ਐਪ ਪਲੇਅਰ) ਅਤੇ 480p (ਪੌਪ-ਅੱਪ ਪਲੇਅਰ) ਤੱਕ ਵਧਾ ਦਿੱਤੀ ਗਈ + +• ਬੱਗ ਫਿਕਸ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ diff --git a/fastlane/metadata/android/pa/changelogs/957.txt b/fastlane/metadata/android/pa/changelogs/957.txt index eb66dacbc..2cf56525d 100644 --- a/fastlane/metadata/android/pa/changelogs/957.txt +++ b/fastlane/metadata/android/pa/changelogs/957.txt @@ -1,10 +1,7 @@ -• ਖਾਸ ਐਨਕਿਊ ਕਿਰਿਆਵਾਂ ਨੂੰ ਇੱਕ ਵਿੱਚ ਜੋੜੋ -• ਪਲੇਅਰ ਨੂੰ ਬੰਦ ਕਰਨ ਲਈ ਦੋ ਉਂਗਲਾਂ ਦੇ ਸੰਕੇਤ -• reCAPTCHA ਕੂਕੀਜ਼ ਨੂੰ ਕਲੀਅਰ ਕਰਨ ਦਿਓ -• ਨੋਟੀਫਿਕੇਸ਼ਨ ਨੂੰ ਰੰਗ ਨਾ ਕਰਨ ਦਾ ਵਿਕਲਪ -• ਅਨੰਤ ਬਫਰਿੰਗ ਨੂੰ ਠੀਕ ਕਰਨ ਲਈ ਵਿਡੀਓ ਵੇਰਵਿਆਂ ਨੂੰ ਕਿਵੇਂ ਖੋਲ੍ਹਿਆ ਜਾਂਦਾ ਹੈ ਇਸ ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ, ਨਿਊਪਾਈਪ ਨਾਲ ਸਾਂਝਾ ਕਰਨ ਵੇਲੇ ਬੱਗੀ ਵਿਵਹਾਰ ਅਤੇ ਹੋਰ ਅਸੰਗਤਤਾਵਾਂ -• YouTube ਵੀਡੀਓਜ਼ ਦੀ ਗਤੀ ਵਧਾਓ ਅਤੇ ਉਮਰ ਪ੍ਰਤੀਬੰਧਿਤ ਵੀਡੀਓ ਨੂੰ ਠੀਕ ਕਰੋ -• ਫਾਸਟ ਫਾਰਵਰਡ/ਰਿਵਾਇੰਡ 'ਤੇ ਕਰੈਸ਼ ਨੂੰ ਠੀਕ ਕਰੋ -• ਥੰਬਨੇਲ ਖਿੱਚ ਕੇ ਸੂਚੀਆਂ ਨੂੰ ਮੁੜ ਵਿਵਸਥਿਤ ਨਾ ਕਰੋ -• ਪੌਪਅੱਪ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਹਮੇਸ਼ਾ ਯਾਦ ਰੱਖੋ -• ਸੰਤਾਲੀ ਭਾਸ਼ਾ ਸ਼ਾਮਲ ਕਰੋ +• ਖਾਸ NQE ਕਿਰਿਆਵਾਂ ਨੂੰ ਇੱਕ ਵਿੱਚ ਏਕੀਕ੍ਰਿਤ ਕਰਨਾ। +• ਦੋ-ਉਂਗਲਾਂ ਵਾਲੇ ਇਸ਼ਾਰੇ ਨਾਲ ਵੀਡੀਓ ਪਲੇਅਰ ਨੂੰ ਬੰਦ ਕਰਨਾ। +• reCOPTCHA ਕੂਕੀਜ਼ ਨੂੰ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦੇਣਾ। +• ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੰਗੀਨ ਨਾ ਕਰਨ ਦਾ ਵਿਕਲਪ। +• NewPipe 'ਤੇ ਸਾਂਝਾ ਕਰਦੇ ਸਮੇਂ ਅਨੰਤ ਬਫਰਿੰਗ, ਗਲਤੀਆਂ ਅਤੇ ਹੋਰ ਅਸੰਗਤੀਆਂ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ। +• YouTube ਵੀਡੀਓ ਨੂੰ ਤੇਜ਼ ਕੀਤਾ ਗਿਆ ਅਤੇ ਉਮਰ-ਪ੍ਰਤੀਬੰਧਿਤ ਵੀਡੀਓ ਨੂੰ ਬਿਹਤਰ ਬਣਾਇਆ ਗਿਆ। +• ਫਾਸਟ ਫਾਰਵਰਡ/ਰਿਵਾਈਂਡ 'ਤੇ ਕਰੈਸ਼ਾਂ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/964.txt b/fastlane/metadata/android/pa/changelogs/964.txt index 85dc2c151..e94595673 100644 --- a/fastlane/metadata/android/pa/changelogs/964.txt +++ b/fastlane/metadata/android/pa/changelogs/964.txt @@ -1 +1,6 @@ -• ਪਲੇਅਰ ਨਿਯੰਤਰਣ ਵਿੱਚ ਅਧਿਆਵਾਂ ਲਈ ਸਮਰਥਨ ਜੋੜਿਆ ਗਿਆ • [PeerTube] ਸੇਪੀਆ ਖੋਜ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ • ਵੀਡੀਓ ਵੇਰਵੇ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਸ਼ੇਅਰ ਬਟਨ ਨੂੰ ਮੁੜ-ਜੋੜਿਆ ਗਿਆ ਅਤੇ ਟੈਬ ਲੇਆਉਟ ਵਿੱਚ ਸਟ੍ਰੀਮ ਵਰਣਨ ਨੂੰ ਤਬਦੀਲ ਕੀਤਾ ਗਿਆ • ਜੇਕਰ ਚਮਕ ਦਾ ਸੰਕੇਤ ਅਸਮਰੱਥ ਹੈ ਤਾਂ ਚਮਕ ਨੂੰ ਬਹਾਲ ਕਰਨਾ ਬੰਦ ਕਰੋ • ਕੋਡੀ 'ਤੇ ਵੀਡੀਓ ਚਲਾਉਣ ਲਈ ਸੂਚੀ ਆਈਟਮ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ • ਕੁਝ ਡਿਵਾਈਸਾਂ 'ਤੇ ਕੋਈ ਡਿਫੌਲਟ ਬ੍ਰਾਊਜ਼ਰ ਸੈੱਟ ਨਾ ਹੋਣ 'ਤੇ ਕ੍ਰੈਸ਼ ਦਾ ਹੱਲ ਕੀਤਾ ਗਿਆ ਹੈ ਅਤੇ ਸ਼ੇਅਰ ਡਾਇਲਾਗਸ ਨੂੰ ਬਿਹਤਰ ਬਣਾਓ • ਫੁੱਲਸਕ੍ਰੀਨ ਪਲੇਅਰ ਵਿੱਚ ਹਾਰਡਵੇਅਰ ਸਪੇਸ ਬਟਨ ਨਾਲ ਪਲੇ/ਪੌਜ਼ ਨੂੰ ਟੌਗਲ ਕਰੋ • [media.ccc.de] ਕਈ ਫਿਕਸ ਅਤੇ ਸੁਧਾਰ +• ਪਲੇਅਰ ਕੰਟਰੋਲਾਂ ਵਿੱਚ ਚੈਪਟਰਾਂ ਲਈ ਸਮਰਥਨ ਜੋੜਿਆ ਗਿਆ +• [PeerTube] ਸੇਪੀਆ ਖੋਜ ਜੋੜਿਆ ਗਿਆ +• ਵੀਡੀਓ ਵੇਰਵੇ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਸ਼ੇਅਰ ਬਟਨ ਨੂੰ ਦੁਬਾਰਾ ਜੋੜਿਆ ਗਿਆ ਅਤੇ ਸਟ੍ਰੀਮ ਵਰਣਨ ਨੂੰ ਟੈਬ ਲੇਆਉਟ ਵਿੱਚ ਤਬਦੀਲ ਕੀਤਾ ਗਿਆ +• ਜੇਕਰ ਚਮਕ ਸੰਕੇਤ ਅਯੋਗ ਹੈ ਤਾਂ ਚਮਕ ਨੂੰ ਬਹਾਲ ਕਰਨਾ ਅਯੋਗ ਕਰੋ +• ਕੋਡੀ 'ਤੇ ਵੀਡੀਓ ਚਲਾਉਣ ਲਈ ਸੂਚੀ ਆਈਟਮ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ +• ਕੁਝ ਡਿਵਾਈਸਾਂ 'ਤੇ ਕੋਈ ਡਿਫੌਲਟ ਬ੍ਰਾਊਜ਼ਰ ਸੈੱਟ ਨਾ ਹੋਣ 'ਤੇ ਕਰੈਸ਼ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ diff --git a/fastlane/metadata/android/pa/changelogs/975.txt b/fastlane/metadata/android/pa/changelogs/975.txt index c866df1e2..fe23991c7 100644 --- a/fastlane/metadata/android/pa/changelogs/975.txt +++ b/fastlane/metadata/android/pa/changelogs/975.txt @@ -3,14 +3,11 @@ • ਅਯੋਗ ਟਿੱਪਣੀਆਂ ਦਾ ਪਤਾ ਲਗਾਓ • ਫੀਡ ਆਈਟਮ ਨੂੰ ਦੇਖੇ ਗਏ ਵਜੋਂ ਨਿਸ਼ਾਨਬੱਧ ਕਰਨ ਦਿਓ • ਟਿੱਪਣੀ ਦਿਲ ਦਿਖਾਓ - ਸੁਧਾਰ • ਮੈਟਾਡੇਟਾ ਅਤੇ ਟੈਗਸ ਲੇਆਉਟ ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ • UI ਭਾਗਾਂ 'ਤੇ ਸੇਵਾ ਰੰਗ ਲਾਗੂ ਕਰੋ ਠੀਕ ਕੀਤਾ • ਮਿੰਨੀ ਪਲੇਅਰ ਵਿੱਚ ਥੰਬਨੇਲ ਠੀਕ ਕਰੋ • ਡੁਪਲੀਕੇਟ ਕਤਾਰ ਆਈਟਮਾਂ 'ਤੇ ਬੇਅੰਤ ਬਫਰਿੰਗ ਨੂੰ ਠੀਕ ਕਰੋ -• ਕੁਝ ਪਲੇਅਰ ਫਿਕਸ ਜਿਵੇਂ ਰੋਟੇਸ਼ਨ ਅਤੇ ਤੇਜ਼ੀ ਨਾਲ ਬੰਦ ਹੋਣਾ -• ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਲੋਡ ਕੀਤੇ ਬਾਕੀ ਬਚੇ ReCAPTCHA ਨੂੰ ਠੀਕ ਕਰੋ -• ਫੀਡ ਨੂੰ ਤਾਜ਼ਾ ਕਰਨ ਵੇਲੇ ਕਲਿੱਕਾਂ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ +• ਕੁਝ ਪਲੇਅਰ ਫਿਕਸ • ਕੁਝ ਡਾਊਨਲੋਡਰ ਕਰੈਸ਼ਾਂ ਨੂੰ ਠੀਕ ਕਰੋ diff --git a/fastlane/metadata/android/pa/changelogs/976.txt b/fastlane/metadata/android/pa/changelogs/976.txt index a1a1354ca..1f2a70887 100644 --- a/fastlane/metadata/android/pa/changelogs/976.txt +++ b/fastlane/metadata/android/pa/changelogs/976.txt @@ -1,10 +1 @@ -• ਪੂਰੀ ਸਕ੍ਰੀਨ ਵਿੱਚ ਪਲੇਅਰ ਨੂੰ ਸਿੱਧਾ ਖੋਲ੍ਹਣ ਲਈ ਵਿਕਲਪ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ -• ਇਹ ਚੁਣਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ ਕਿ ਕਿਸ ਕਿਸਮ ਦੇ ਖੋਜ ਸੁਝਾਅ ਦਿਖਾਉਣੇ ਹਨ -• ਗੂੜ੍ਹਾ ਥੀਮ ਹੁਣ ਗਹਿਰਾ ਗੂੜ੍ਹਾ + ਗੂੜ੍ਹਾ ਸਪਲੈਸ਼ ਸਕ੍ਰੀਨ ਜੋੜਿਆ ਗਿਆ ਹੈ -• ਅਣਚਾਹੀਆਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਸਲੇਟੀ ਕਰਨ ਲਈ ਬਿਹਤਰ ਫ਼ਾਈਲ ਚੋਣਕਾਰ -• ਸਥਿਰ YouTube ਗਾਹਕੀ ਆਯਾਤ - -• ਇੱਕ ਸਟ੍ਰੀਮ ਨੂੰ ਮੁੜ ਚਲਾਉਣ ਲਈ ਮੁੜ-ਪਲੇਅ ਬਟਨ 'ਤੇ ਟੈਪ ਕਰਨ ਦੀ ਲੋੜ ਹੈ -• ਸਥਿਰ ਸਮਾਪਤੀ ਆਡੀਓ ਸੈਸ਼ਨ -• [Android TV] DPad ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਸਥਿਰ ਲੰਬੀ ਸੀਕਬਾਰ ਜੰਪ -ਹੋਰ ਤਬਦੀਲੀਆਂ ਦੇਖਣ ਲਈ, ਹੇਠਾਂ ਦਿੱਤੇ ਲਿੰਕ ਟੈਬ ਤੋਂ ਚੇਂਜਲੌਗ (ਅਤੇ ਬਲੌਗ ਪੋਸਟ) ਦੇਖੋ। +• ਪੂਰੀ ਸਕ੍ਰੀਨ ਵਿੱਚ ਪਲੇਅਰ ਨੂੰ ਸਿੱਧਾ ਖੋਲ੍ਹਣ ਲਈ ਵਿਕਲਪ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ • ਇਹ ਚੁਣਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ ਕਿ ਕਿਸ ਕਿਸਮ ਦੇ ਖੋਜ ਸੁਝਾਅ ਦਿਖਾਉਣੇ ਹਨ • ਗੂੜ੍ਹਾ ਥੀਮ ਹੁਣ ਗੂੜ੍ਹਾ + ਗੂੜ੍ਹਾ ਸਪਲੈਸ਼ ਸਕ੍ਰੀਨ ਜੋੜਿਆ ਗਿਆ ਹੈ • ਅਣਚਾਹੀਆਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਸਲੇਟੀ ਕਰਨ ਲਈ ਬਿਹਤਰ ਫ਼ਾਈਲ ਚੋਣਕਾਰ • ਸਥਿਰ YouTube ਗਾਹਕੀ ਆਯਾਤ • ਇੱਕ ਸਟ੍ਰੀਮ ਨੂੰ ਮੁੜ ਚਲਾਉਣ ਲਈ ਮੁੜ-ਪਲੇਅ ਬਟਨ 'ਤੇ ਟੈਪ ਕਰਨ ਦੀ ਲੋੜ ਹੈ • ਸਥਿਰ ਸਮਾਪਤੀ ਆਡੀਓ ਸੈਸ਼ਨ • [Android TV] DPad ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ ਸਥਿਰ ਲੰਬੀ ਸੀਕਬਾਰ ਜੰਪ ਹੋਰ ਤਬਦੀਲੀਆਂ ਦੇਖਣ ਲਈ, ਹੇਠਾਂ ਦਿੱਤੇ ਲਿੰਕ ਟੈਬ ਤੋਂ ਚੇਂਜਲੌਗ (ਅਤੇ ਬਲੌਗ ਪੋਸਟ) ਦੇਖੋ। diff --git a/fastlane/metadata/android/pa/changelogs/986.txt b/fastlane/metadata/android/pa/changelogs/986.txt index b072d6cb9..3766ca8d1 100644 --- a/fastlane/metadata/android/pa/changelogs/986.txt +++ b/fastlane/metadata/android/pa/changelogs/986.txt @@ -1,15 +1,15 @@ ਨਵਾਂ -• ਨਵੀਆਂ ਸਟ੍ਰੀਮਾਂ ਲਈ ਸੂਚਨਾਵਾਂ -• ਬੈਕਗ੍ਰਾਊਂਡ ਅਤੇ ਵੀਡੀਓ ਪਲੇਅਰਾਂ ਵਿਚਕਾਰ ਅਰਾਮ ਨਾਲ ਤਬਦੀਲੀ -• ਸੈਮੀਟੋਨਸ ਦੁਆਰਾ ਪਿੱਚ ਬਦਲੋ -• ਇੱਕ ਪਲੇਲਿਸਟ ਵਿੱਚ ਮੁੱਖ ਪਲੇਅਰ ਕਤਾਰ ਜੋੜੋ +• ਨਵੀਆਂ ਸਟ੍ਰੀਮਾਂ ਲਈ ਸੂਚਨਾਵਾਂ +• ਬੈਕਗ੍ਰਾਊਂਡ ਅਤੇ ਵੀਡੀਓ ਪਲੇਅਰਾਂ ਵਿਚਕਾਰ ਅਰਾਮ ਨਾਲ ਤਬਦੀਲੀ +• ਸੈਮੀਟੋਨਸ ਦੁਆਰਾ ਪਿੱਚ ਬਦਲੋ +• ਇੱਕ ਪਲੇਲਿਸਟ ਵਿੱਚ ਮੁੱਖ ਪਲੇਅਰ ਕਤਾਰ ਜੋੜੋ ਸੁਧਾਰ -• ਸਪੀਡ/ਪਿਚ ਸਟੈਪ ਦਾ ਆਕਾਰ ਯਾਦ ਰੱਖੋ -• ਵੀਡੀਓ ਪਲੇਅਰ ਵਿੱਚ ਸ਼ੁਰੂਆਤੀ ਲੰਬੇ ਬਫਰਿੰਗ ਨੂੰ ਘੱਟ ਕਰੋ • Android TV ਲਈ ਪਲੇਅਰ UI ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ +• ਸਪੀਡ/ਪਿਚ ਸਟੈਪ ਦਾ ਆਕਾਰ ਯਾਦ ਰੱਖੋ +• ਵੀਡੀਓ ਪਲੇਅਰ ਵਿੱਚ ਸ਼ੁਰੂਆਤੀ ਲੰਬੇ ਬਫਰਿੰਗ ਨੂੰ ਘੱਟ ਕਰੋ +• Android TV ਲਈ ਪਲੇਅਰ UI ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ • ਸਾਰੀਆਂ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣ ਤੋਂ ਪਹਿਲਾਂ ਪੁਸ਼ਟੀ ਕਰੋ -ਠੀਕ ਕੀਤਾ -• ਮੀਡੀਆ ਬਟਨ ਨੂੰ ਫਿਕਸ ਕਰੋ ਜੋ ਪਲੇਅਰ ਨਿਯੰਤਰਣਾਂ ਨੂੰ ਨਹੀਂ ਲੁਕਾਉਂਦਾ ਹੈ +ਫਿਕਸਡ +• ਮੀਡੀਆ ਬਟਨ ਨੂੰ ਫਿਕਸ ਕਰੋ ਜੋ ਪਲੇਅਰ ਨਿਯੰਤਰਣਾਂ ਨੂੰ ਨਹੀਂ ਲੁਕਾਉਂਦਾ ਹੈ • ਪਲੇਅਰ ਦੀ ਕਿਸਮ ਬਦਲਣ 'ਤੇ ਪਲੇਬੈਕ ਰੀਸੈਟ ਨੂੰ ਠੀਕ ਕਰੋ -• ਪਲੇਲਿਸਟ ਡਾਇਲਾਗ ਨੂੰ ਘੁੰਮਾਉਣ ਨੂੰ ਠੀਕ ਕਰੋ diff --git a/fastlane/metadata/android/pa/changelogs/987.txt b/fastlane/metadata/android/pa/changelogs/987.txt index 93fc77a77..52d0bb828 100644 --- a/fastlane/metadata/android/pa/changelogs/987.txt +++ b/fastlane/metadata/android/pa/changelogs/987.txt @@ -6,6 +6,4 @@ ਸੁਧਾਰ • ਪਲੇਬੈਕ ਪੈਰਾਮੀਟਰ ਡਾਇਲਾਗ ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ • ਗਾਹਕੀ ਆਯਾਤ/ਨਿਰਯਾਤ ਬਟਨਾਂ ਨੂੰ ਤਿੰਨ-ਬਿੰਦੀਆਂ ਵਾਲੇ ਮੀਨੂ ਵਿੱਚ ਲੈ ਜਾਓ - -ਠੀਕ ਕੀਤਾ -• ਪਲੇਲਿਸਟ ਤੋਂ ਪੂਰੀ ਤਰ੍ਹਾਂ ਦੇਖੇ ਗਏ ਵੀਡੀਓ ਨੂੰ ਹਟਾਉਣਾ ਠੀਕ ਕਰੋ • ਸ਼ੇਅਰ ਮੀਨੂ ਥੀਮ ਅਤੇ "ਪਲੇਲਿਸਟ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ" ਐਂਟਰੀ ਨੂੰ ਠੀਕ ਕਰੋ +ਠੀਕ ਕੀਤਾ diff --git a/fastlane/metadata/android/pa/changelogs/990.txt b/fastlane/metadata/android/pa/changelogs/990.txt index bd532ecb0..90cd8b35c 100644 --- a/fastlane/metadata/android/pa/changelogs/990.txt +++ b/fastlane/metadata/android/pa/changelogs/990.txt @@ -1,13 +1,10 @@ -ਇਹ ਰੀਲੀਜ਼ Android 4.4 ਕਿਟਕੈਟ ਲਈ ਸਮਰਥਨ ਛੱਡਦੀ ਹੈ, ਹੁਣ ਘੱਟੋ-ਘੱਟ ਸੰਸਕਰਣ Android 5 Lollipop ਹੈ! -ਨਵਾਂ -• ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਦਬਾਉਣ ਵਾਲੇ ਮੀਨੂ ਤੋਂ ਡਾਊਨਲੋਡ ਕਰੋ -• ਫੀਡ ਵਿੱਚ ਭਵਿੱਖ ਦੇ ਵੀਡੀਓ ਲੁਕਾਓ -• ਸਥਾਨਕ ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਸਾਂਝਾ ਕਰੋ -ਸੁਧਾਰ -• ਪਲੇਅਰ ਕੋਡ ਨੂੰ ਛੋਟੇ ਹਿੱਸਿਆਂ ਵਿੱਚ ਰੀਫੈਕਟਰ ਕਰੋ: ਘੱਟ RAM ਵਰਤੀ ਗਈ, ਘੱਟ ਬੱਗ -• ਥੰਮਨੇਲ ਦੇ ਸਕੇਲ ਮੋਡ ਵਿੱਚ ਸੁਧਾਰ ਕਰੋ -• ਚਿੱਤਰ ਪਲੇਸਹੋਲਡਰ ਨੂੰ ਵੈਕਟਰਾਈਜ਼ ਕਰੋ - -ਠੀਕ ਕੀਤਾ -• ਪਲੇਅਰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਨਾਲ ਵੱਖ-ਵੱਖ ਮੁੱਦਿਆਂ ਨੂੰ ਹੱਲ ਕਰੋ: ਪੁਰਾਣੀ/ਗੁੰਮ ਮੀਡੀਆ ਜਾਣਕਾਰੀ, ਵਿਗੜਿਆ ਥੰਮਨੇਲ +ਇਹ ਰਿਲੀਜ਼ Android 4.4 ਕਿਟਕੈਟ ਲਈ ਸਮਰਥਨ ਛੱਡਦੀ ਹੈ, ਹੁਣ ਘੱਟੋ-ਘੱਟ ਸੰਸਕਰਣ Android 5 Lollipop ਹੈ! +ਨਵਾਂ +• ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਦਬਾਉਣ ਵਾਲੇ ਮੀਨੂ ਤੋਂ ਡਾਊਨਲੋਡ ਕਰੋ +• ਫੀਡ ਵਿੱਚ ਭਵਿੱਖ ਦੇ ਵੀਡੀਓ ਲੁਕਾਓ +• ਸਥਾਨਕ ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਸਾਂਝਾ ਕਰੋ +ਸੁਧਾਰ +• ਪਲੇਅਰ ਕੋਡ ਨੂੰ ਛੋਟੇ ਹਿੱਸਿਆਂ ਵਿੱਚ ਰੀਫੈਕਟਰ ਕਰੋ: ਘੱਟ RAM ਵਰਤੇਗੀ, ਘੱਟ ਬੱਗ ਹੋਣਗੇ + +ਠੀਕ ਕੀਤਾ • ਪੂਰੀ ਸਕ੍ਰੀਨ ਦੀ ਥਾਂ ਉਸਦੇ 1/4 ਹਿੱਸੇ ਦੀ ਵਰਤੋਂ ਨੂੰ ਠੀਕ ਕਰੋ diff --git a/fastlane/metadata/android/pa/changelogs/995.txt b/fastlane/metadata/android/pa/changelogs/995.txt index 0da0a4261..dc9c576c9 100644 --- a/fastlane/metadata/android/pa/changelogs/995.txt +++ b/fastlane/metadata/android/pa/changelogs/995.txt @@ -5,12 +5,10 @@ ਸੁਧਾਰ • ਪਲੇਅਰ ਇੰਟਰਫੇਸ ਦੀ ਪਹੁੰਚਯੋਗਤਾ -• ਸਿਰਫ਼-ਵੀਡੀਓ ਡਾਊਨਲੋਡਾਂ ਲਈ ਬਿਹਤਰ ਆਡੀਓ ਚੋਣ -• ਸਾਂਝੀ ਕੀਤੀ ਪਲੇਲਿਸਟ ਸਮੱਗਰੀ ਵਿੱਚ ਪਲੇਲਿਸਟ ਅਤੇ ਵੀਡੀਓ ਨਾਮ ਸ਼ਾਮਲ ਕਰਨ ਦਾ ਵਿਕਲਪ +• ਪਲੇਲਿਸਟ ਸ਼ੇਅਰਿੰਗ ਸਮੱਗਰੀ ਵਿੱਚ ਪਲੇਲਿਸਟ ਨਾਮ ਅਤੇ ਵੀਡੀਓ ਨਾਮ ਜੋੜਨ ਲਈ ਵਿਕਲਪ +• ਅੰਦਰੂਨੀ ਸੁਧਾਰ ਅਤੇ ਨਿਰਭਰਤਾ ਅੱਪਡੇਟ ਠੀਕ ਕੀਤੇ -• [ਯੂਟਿਊਬ] ਲਾਈਕ ਗਿਣਤੀ ਨੂੰ ਠੀਕ ਕਰੋ -• ਪਲੇਅਰ ਰਿਸਪੌੰਡ ਨਹੀਂ ਕਰ ਰਿਹਾ ਦੇ ਸੁਨੇਹੇ ਦੇਣ ਵਾਲੇ ਪੌਪਅੱਪ ਅਤੇ ਕਰੈਸ਼ਾਂ ਨੂੰ ਠੀਕ ਕਰੋ • ਭਾਸ਼ਾ ਚੋਣਕਾਰ ਵਿੱਚ ਗਲਤ ਭਾਸ਼ਾਵਾਂ ਦੀ ਚੋਣ • ਪਲੇਅਰ ਆਡੀਓ ਫੋਕਸ ਮਿਊਟ ਦਾ ਆਦਰ ਨਹੀਂ ਕਰ ਰਿਹਾ ਸੀ -• ਪਲੇਲਿਸਟਾਂ ਵਿੱਚ ਆਈਟਮਾਂ ਨੂੰ ਜੋੜਨਾ ਕਦੇ-ਕਦਾਈਂ ਕੰਮ ਨਹੀਂ ਕਰ ਰਿਹਾ ਸੀ +• ਖਾਸ ਮਾਮਲਿਆਂ ਵਿੱਚ ਪਲੇਲਿਸਟਾਂ ਵਿੱਚ ਆਈਟਮਾਂ ਨੂੰ ਜੋੜਨਾ ਕੰਮ ਨਹੀਂ ਕਰ ਰਿਹਾ ਸੀ diff --git a/fastlane/metadata/android/pa/changelogs/997.txt b/fastlane/metadata/android/pa/changelogs/997.txt index 8e0cb85f2..a33ff32af 100644 --- a/fastlane/metadata/android/pa/changelogs/997.txt +++ b/fastlane/metadata/android/pa/changelogs/997.txt @@ -12,6 +12,4 @@ ਠੀਕ ਕੀਤਾ • [ਯੂਟਿਊਬ] ਲੋਡ ਨਾ ਹੋਣ ਵਾਲੀਆਂ ਟਿੱਪਣੀਆਂ ਨੂੰ ਠੀਕ ਕਰੋ, ਨਾਲ ਹੀ ਹੋਰ ਫਿਕਸ ਅਤੇ ਸੁਧਾਰ -• ਸੈਟਿੰਗਾਂ ਆਯਾਤ ਕਰਨ ਵਿੱਚ ਕਮਜ਼ੋਰੀ ਨੂੰ ਹੱਲ ਕਰੋ ਅਤੇ JSON 'ਤੇ ਸਵਿੱਚ ਕਰੋ • ਕਈ ਡਾਊਨਲੋਡ ਫਿਕਸ -• ਖੋਜ ਟੈਕਸਟ ਨੂੰ ਟਰਿੱਮ ਕਰੋ diff --git a/fastlane/metadata/android/pl/changelogs/1006.txt b/fastlane/metadata/android/pl/changelogs/1006.txt new file mode 100644 index 000000000..a537d7c18 --- /dev/null +++ b/fastlane/metadata/android/pl/changelogs/1006.txt @@ -0,0 +1,16 @@ +Ulepszone +- Utrzymyw. bieżącego odtwarzacza przy naciskaniu znaczników czasu +- Próba odzysk. oczekuj. pobierań, jeśli to możliwe +- Dodano opcję usuwania pobierania bez usuwania pliku +- Uprawnienie na nakładkę: wyświetl. okna z objaśnieniami dla Androida powyżej R +- Obsługa otw. linków on.soundcloud +- Wiele drobnych ulepszeń i optymal. + +Naprawione +- Formatow. krótkich liczb na Androidzie poniżej 7 +- Puste powiadomienia +- Pliki napisów SRT +- Mnóstwo awarii + +Rozwój +- Modernizacja wewnętrznego kodu diff --git a/fastlane/metadata/android/pt-BR/changelogs/1005.txt b/fastlane/metadata/android/pt-BR/changelogs/1005.txt new file mode 100644 index 000000000..3ef1f3e2e --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/1005.txt @@ -0,0 +1,17 @@ +New +• Suporte adicionado para Android Auto +• Permitir configuração de grupos de feed como abas da tela principal +• [YouTube] Compartilhe como playlist temporária +• [SoundCloud] Aba de curtidas do canal + +Melhorado +• Melhor sugestão na barra de busca +• Mostra data do download em Downloads +• Usar idioma por aplicativo no Android 13 + +Consertado +• Texto no modo escuro consertado +• [YouTube] Conserta playlists não carregando mais do que 100 itens +• [YouTube] Conserta videos recomendados faltando +• Conserta lista de visualização do histórico +• Conserta registro de tempo na resposta de comentários diff --git a/fastlane/metadata/android/pt-BR/changelogs/1007.txt b/fastlane/metadata/android/pt-BR/changelogs/1007.txt new file mode 100644 index 000000000..59fc6a5cd --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/1007.txt @@ -0,0 +1 @@ +Corrigido YouTube não reproduzir qualquer transmissão diff --git a/fastlane/metadata/android/pt-BR/changelogs/966.txt b/fastlane/metadata/android/pt-BR/changelogs/966.txt new file mode 100644 index 000000000..13722dc34 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/966.txt @@ -0,0 +1,14 @@ +Novo: +- Acrescentado um novo serviço: Bandcamp + +Melhorado: +- Adicionada uma opção para que a aplicação siga o tema do dispositivo +- Previne alguns travamentos mostrando um painel de erros melhorado +- Mostra mais informações sobre as causas da indisponibilidade do conteúdo +- A tecla de espaço de hardware ativa play/pausa +- Mostra "Download iniciado" + +Resolvido: +- Miniaturas muito pequenas em detalhes de vídeo enquanto se reproduz em fundo +- Corrige título vazio em tocador minimizado +- O último modo de redimensionamento do tamanho não estava sendo restaurado corretamente diff --git a/fastlane/metadata/android/pt-BR/changelogs/967.txt b/fastlane/metadata/android/pt-BR/changelogs/967.txt new file mode 100644 index 000000000..96ce3c07f --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/967.txt @@ -0,0 +1 @@ +Corrigido o YouTube que não funcionava corretamente na UE. Foi causado por um novo cookie e sistema de consentimento de privacidade que requer que a NewPipe configure um cookie CONSENT. diff --git a/fastlane/metadata/android/pt-PT/changelogs/1005.txt b/fastlane/metadata/android/pt-PT/changelogs/1005.txt new file mode 100644 index 000000000..ea0f44608 --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/1005.txt @@ -0,0 +1,15 @@ +Novo +• Adicionado apoio para Android Auto +• Permite definir grupos de feeds como guias do ecrã principal +• [YouTube] Partilhar como lista de reprodução temporária +• [SoundCloud] Separador de gostos do canal + +Melhorado +• Melhores sugestões na barra de pesquisa +• Mostrar data da descarga em descargas +• Usar idioma por app do Android 13 + +Corrigido +• Corrigir cores de texto incorretas no modo escuro +• [YouTube] Corrigir listas de reprodução que não carregam mais de 100 elementos +... diff --git a/fastlane/metadata/android/pt-PT/changelogs/1007.txt b/fastlane/metadata/android/pt-PT/changelogs/1007.txt new file mode 100644 index 000000000..93519d64d --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/1007.txt @@ -0,0 +1 @@ +Corrigido YouTube não reproduzir nenhuma transmissão diff --git a/fastlane/metadata/android/pt/changelogs/1005.txt b/fastlane/metadata/android/pt/changelogs/1005.txt new file mode 100644 index 000000000..ea0f44608 --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/1005.txt @@ -0,0 +1,15 @@ +Novo +• Adicionado apoio para Android Auto +• Permite definir grupos de feeds como guias do ecrã principal +• [YouTube] Partilhar como lista de reprodução temporária +• [SoundCloud] Separador de gostos do canal + +Melhorado +• Melhores sugestões na barra de pesquisa +• Mostrar data da descarga em descargas +• Usar idioma por app do Android 13 + +Corrigido +• Corrigir cores de texto incorretas no modo escuro +• [YouTube] Corrigir listas de reprodução que não carregam mais de 100 elementos +... diff --git a/fastlane/metadata/android/pt/changelogs/1007.txt b/fastlane/metadata/android/pt/changelogs/1007.txt new file mode 100644 index 000000000..93519d64d --- /dev/null +++ b/fastlane/metadata/android/pt/changelogs/1007.txt @@ -0,0 +1 @@ +Corrigido YouTube não reproduzir nenhuma transmissão diff --git a/fastlane/metadata/android/ru/changelogs/1000.txt b/fastlane/metadata/android/ru/changelogs/1000.txt index 90c03f3cf..776041988 100644 --- a/fastlane/metadata/android/ru/changelogs/1000.txt +++ b/fastlane/metadata/android/ru/changelogs/1000.txt @@ -10,4 +10,4 @@ • Исправить выход из диалогового окна загрузки до его появления. • Исправить всплывающее окно с списком связанных элементов. • Исправлена последовательность в диалоговом окне добавления в плейлист. -• Настроена компоновка элементов закладок плейлиста. +• Настроена компоновка элементов закладок плейлиста diff --git a/fastlane/metadata/android/ru/changelogs/1001.txt b/fastlane/metadata/android/ru/changelogs/1001.txt index 11c3a1061..7b9f2be2f 100644 --- a/fastlane/metadata/android/ru/changelogs/1001.txt +++ b/fastlane/metadata/android/ru/changelogs/1001.txt @@ -1,10 +1,6 @@ Улучшенный - -- Всегда можно изменить настройки уведомлений игрока на Android 13+ - +• Всегда можно изменить настройки уведомлений игрока на Android 13+ Исправлено - -- Исправление экспорта базы данных/подписок, который не обрезал уже существующий файл, что могло привести к повреждению экспорта - -- Исправлено возобновление работы плеера с самого начала при нажатии на временную метку +• Исправление экспорта базы данных/подписок, который не обрезал уже существующий файл, что могло привести к повреждению экспорта +• Исправлено возобновление работы плеера с самого начала при нажатии на временную метку diff --git a/fastlane/metadata/android/ru/changelogs/1002.txt b/fastlane/metadata/android/ru/changelogs/1002.txt index d3978869d..efa895dbf 100644 --- a/fastlane/metadata/android/ru/changelogs/1002.txt +++ b/fastlane/metadata/android/ru/changelogs/1002.txt @@ -1 +1,4 @@ -Исправлено: YouTube не воспроизводил никакие потоки +Исправлена ошибка, из-за которой YouTube не воспроизводил ни одного потока. + +В этом выпуске исправлена только самая серьёзная ошибка, препятствующая загрузке информации о видео YouTube. +Мы знаем о существовании других проблем и вскоре выпустим отдельный выпуск для их решения. diff --git a/fastlane/metadata/android/ru/changelogs/1003.txt b/fastlane/metadata/android/ru/changelogs/1003.txt index d3978869d..4b8843d5c 100644 --- a/fastlane/metadata/android/ru/changelogs/1003.txt +++ b/fastlane/metadata/android/ru/changelogs/1003.txt @@ -1 +1,6 @@ -Исправлено: YouTube не воспроизводил никакие потоки +Это релиз исправления, исправляющий ошибки YouTube: +• [YouTube] Исправлена проблема с загрузкой видеоинформации, исправлены ошибки HTTP 403 при воспроизведении видео и восстановлено воспроизведение некоторых видео с возрастными ограничениями +• Исправлена проблема с отсутствием изменения размера субтитров +• Исправлена проблема с двойной загрузкой информации при открытии трансляции +• [Soundcloud] Удалены невоспроизводимые трансляции с защитой DRM +• Обновлены переводы diff --git a/fastlane/metadata/android/ru/changelogs/1004.txt b/fastlane/metadata/android/ru/changelogs/1004.txt index d3978869d..e6bef35b9 100644 --- a/fastlane/metadata/android/ru/changelogs/1004.txt +++ b/fastlane/metadata/android/ru/changelogs/1004.txt @@ -1 +1,3 @@ -Исправлено: YouTube не воспроизводил никакие потоки +В этом выпуске YouTube теперь поддерживает только трансляцию в формате 360p. + +Обратите внимание, что решение, используемое в этой версии, вероятно, временное, и в долгосрочной перспективе потребуется внедрение видеопротокола SABR. Участники TeamNewPipe сейчас заняты, поэтому любая помощь будет высоко оценена! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/ru/changelogs/1007.txt b/fastlane/metadata/android/ru/changelogs/1007.txt new file mode 100644 index 000000000..d3978869d --- /dev/null +++ b/fastlane/metadata/android/ru/changelogs/1007.txt @@ -0,0 +1 @@ +Исправлено: YouTube не воспроизводил никакие потоки diff --git a/fastlane/metadata/android/ru/changelogs/930.txt b/fastlane/metadata/android/ru/changelogs/930.txt index 58a849bf4..0ad761f55 100644 --- a/fastlane/metadata/android/ru/changelogs/930.txt +++ b/fastlane/metadata/android/ru/changelogs/930.txt @@ -7,7 +7,7 @@ • Показывать сообщение, когда контент еще не поддерживается, вместо сбоя • Улучшено изменение размера всплывающего проигрывателя с помощью пинч-жестов • Постановка потоков в очередь при длительном нажатии на фоновые и всплывающие кнопки в канале -• Улучшена обработка размера заголовка заголовка ящика +• Улучшена обработка размера заголовка Исправления • Исправлена ошибка, из-за которой не работает настройка контента с ограничением по возрасту diff --git a/fastlane/metadata/android/ru/changelogs/999.txt b/fastlane/metadata/android/ru/changelogs/999.txt index d3978869d..bf6e1c375 100644 --- a/fastlane/metadata/android/ru/changelogs/999.txt +++ b/fastlane/metadata/android/ru/changelogs/999.txt @@ -1 +1,12 @@ -Исправлено: YouTube не воспроизводил никакие потоки +Этот выпуск исправления исправляет ошибки HTTP 403 в середине видео на YouTube. + +Новое +• [SoundCloud] Добавлена поддержка URL-адресов on.soundcloud.com + +Улучшено +• [Bandcamp] Отображение дополнительной информации в радиокиоске + +Исправлено +• [YouTube] Исправлены случайные ошибки HTTP 403 в начале или середине видео +• [YouTube] Извлечение аватара и баннера из большего количества типов заголовков каналов +• [Bandcamp] Исправлены различные ошибки и всегда используется HTTPS diff --git a/fastlane/metadata/android/sat/short_description.txt b/fastlane/metadata/android/sat/short_description.txt new file mode 100644 index 000000000..9e7874738 --- /dev/null +++ b/fastlane/metadata/android/sat/short_description.txt @@ -0,0 +1 @@ +ᱮᱱᱰᱨᱳᱭᱮᱰ ᱞᱟᱹᱜᱤᱫ ᱢᱤᱫ ᱯᱷᱨᱤ ᱦᱟᱞᱠᱟ ᱚᱡᱚᱱ ᱭᱩᱴᱭᱩᱵᱽ ᱯᱷᱨᱚᱱᱴᱮᱱᱰ ᱾ diff --git a/fastlane/metadata/android/sk/changelogs/1005.txt b/fastlane/metadata/android/sk/changelogs/1005.txt index 8f2bfbfab..2bfdfca0e 100644 --- a/fastlane/metadata/android/sk/changelogs/1005.txt +++ b/fastlane/metadata/android/sk/changelogs/1005.txt @@ -1,18 +1,17 @@ -Novinky -• Pridaná podpora pre Android Auto -• Možnosť nastaviť skupiny kanálov ako hlavné karty na obrazovke -• [YouTube] Zdieľanie ako dočasný playlist +New +• Add support for Android Auto +• Allow setting feed groups as main screen tabs +• [YouTube] Share as temporary playlist +• [SoundCloud] Likes channel tab -• [SoundCloud] Karta „Páči sa“ kanál. +Improved +• Better search bar hints +• Show download date in Downloads +• Use Android 13 per-app language -Vylepšenia -• Lepšia nápoveda v paneli vyhľadávania -• Zobrazenie dátumu stiahnutia v sekcii „Stiahnuté” -• Použitie jazyka Android 13 pre jednotlivé aplikácie - -Opravy -• Oprava chybných farieb textu v tmavom režime -• [YouTube] Oprava playlistov, ktoré nenačítavajú viac ako 100 položiek -• [YouTube] Oprava chýbajúcich odporúčaných videí -• Oprava pádov v zobrazení zoznamu histórie -• Oprava časových značiek v odpovediach na komentáre. +Fixed +• Fix broken text colors in dark mode +• [YouTube] Fix playlists not loading more than 100 items +• [YouTube] Fix missing recommended videos +• Fix crashes in History list view +• Fix timestamps in comment replies diff --git a/fastlane/metadata/android/sk/changelogs/1006.txt b/fastlane/metadata/android/sk/changelogs/1006.txt new file mode 100644 index 000000000..6bc6f9a2b --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/1006.txt @@ -0,0 +1,16 @@ +# Improved +Keep current player when clicking on timestamps +Try to recover pending download missions when possible +Add option to delete a download without also deleting file +Overlay Permission: display explanatory dialog for Android > R +Support on.soundcloud link opening +A lot of small improvements and optimizations + +# Fixed +Fix short count formatting for Android versions below 7 +Fix ghost notifications +Fixes for SRT subtitle files +Fixed tons of crashes + +# Development +Internal code modernization diff --git a/fastlane/metadata/android/sk/changelogs/1007.txt b/fastlane/metadata/android/sk/changelogs/1007.txt new file mode 100644 index 000000000..2f96b8dc5 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/1007.txt @@ -0,0 +1 @@ +Fixed YouTube not playing any stream diff --git a/fastlane/metadata/android/sk/changelogs/65.txt b/fastlane/metadata/android/sk/changelogs/65.txt index c7cac2626..8570a056a 100644 --- a/fastlane/metadata/android/sk/changelogs/65.txt +++ b/fastlane/metadata/android/sk/changelogs/65.txt @@ -1,26 +1,26 @@ -### Zlepšenia +### Improvements -- Zakázanie animácie ikony burgermenu #1486 -- Zrušenie odstránenia stiahnutých súborov #1472 -- Možnosť sťahovania v ponuke zdieľania #1498 -- Pridaná možnosť zdieľania do ponuky dlhého ťuknutia #1454 -- Minimalizácia hlavného prehrávača pri ukončení #1354 -- Aktualizácia verzie knižnice a oprava zálohovania databázy #1510 -- Aktualizácia ExoPlayer 2.8.2 #1392 - - Prepracované dialógové okno na ovládanie rýchlosti prehrávania tak, aby podporovalo rôzne veľkosti krokov pre rýchlejšiu zmenu rýchlosti. - - Pridaný prepínač na rýchle prevíjanie dopredu počas ticha v ovládaní rýchlosti prehrávania. Toto by malo byť užitočné pre audioknihy a niektoré hudobné žánre a môže priniesť skutočne plynulý zážitok (a môže prerušiť skladbu s množstvom ticha =\). - - Prepracované rozlíšenie zdrojov médií, aby bolo možné odovzdávať metadáta spolu s médiami interne v prehrávači, namiesto toho, aby sa to robilo ručne. Teraz máme jediný zdroj metadát a je priamo k dispozícii pri spustení prehrávania. - - Opravené neaktualizovanie metadát vzdialeného zoznamu skladieb, keď sú k dispozícii nové metadáta pri otvorení fragmentu zoznamu skladieb. - - Rôzne opravy používateľského rozhrania: #1383, ovládacie prvky oznámenia prehrávača na pozadí sú teraz vždy biele, jednoduchšie vypnutie vyskakovacieho prehrávača prostredníctvom hodenia -- Použitie nového extraktora s preformulovanou architektúrou pre multiservis +- Disable burgermenu icon animation #1486 +- undo delete of downloads #1472 +- Download option in share menu #1498 +- Added share option to long tap menu #1454 +- Minimize main player on exit #1354 +- Library version update and database backup fix #1510 +- ExoPlayer 2.8.2 Update #1392 + - Reworked the playback speed control dialog to support different step sizes for faster speed change. + - Added a toggle to fast-forward during silences in playback speed control. This should be helpful for audiobooks and certain music genres, and can bring a true seamless experience (and can break a song with lots of silences =\\). + - Refactored media source resolution to allow passing metadata alongside media internally in the player, rather than doing so manually. Now we have a single source of metadata and is directly available when playback starts. + - Fixed remote playlist metadata not updating when new metadata is available when playlist fragment is opened. + - Various UI fixes: #1383, background player notification controls now always white, easier to shutdown popup player through flinging +- Use new extractor with refactored architecture for multiservice -### Opravy +### Fixes -- Oprava #1440 Nefunkčné rozloženie informácií o videu #1491 -- Oprava histórie zobrazenia #1497 - - #1495 aktualizáciou metadát (miniatúry, názov a počet videí) hneď, ako používateľ vstúpi do zoznamu skladieb. - - #1475, zaregistrovaním zobrazenia v databáze, keď používateľ spustí video v externom prehrávači na detailnom fragmente. -- Oprava časového limitu creen v prípade popup režimu. #1463 (Opravené #640) -- Oprava hlavného prehrávača videa č. 1509 - - #1412] Opravený režim opakovania spôsobujúci NPE prehrávača, keď je prijatý nový zámer, zatiaľ čo je činnosť prehrávača na pozadí. - - Opravené minimalizovanie prehrávača na vyskakovacie okno nezničí prehrávač, keď nie je udelené povolenie na vyskakovanie. +- Fix #1440 Broken Video Info Layout #1491 +- View history fix #1497 + - #1495, by updating the metadata (thumbnail, title and video count) as soon as the user access the playlist. + - #1475, by registering a view in the database when the user starts a video on external player on detail fragment. +- Fix creen timeout in case of popup mode. #1463 (Fixed #640) +- Main video player fix #1509 + - [#1412] Fixed repeat mode causing player NPE when new intent is received while player activity is in background. + - Fixed minimizing player to popup does not destroy player when popup permission is not granted. diff --git a/fastlane/metadata/android/sk/changelogs/66.txt b/fastlane/metadata/android/sk/changelogs/66.txt index ba9808cba..30c20b0e8 100644 --- a/fastlane/metadata/android/sk/changelogs/66.txt +++ b/fastlane/metadata/android/sk/changelogs/66.txt @@ -1,33 +1,33 @@ -# Zoznam zmien verzie v0.13.7 +# Changelog of v0.13.7 -### Opravené -- Oprava problémov s triediacim filtrom vo verzii v0.13.6 +### Fixed +- Fix sort filter issues of v0.13.6 -# Zoznam zmien verzie v0.13.6 +# Changelog of v0.13.6 -### Vylepšenia +### Improvements -- Zakázanie animácie ikony burgermenu #1486 -- Zrušenie odstránenia stiahnutých súborov #1472 -- Možnosť sťahovania v ponuke zdieľania #1498 -- Pridaná možnosť zdieľania do ponuky dlhého ťuknutia #1454 -- Minimalizácia hlavného prehrávača pri ukončení #1354 -- Aktualizácia verzie knižnice a oprava zálohovania databázy #1510 -- Aktualizácia ExoPlayer 2.8.2 #1392 - - Prepracované dialógové okno na ovládanie rýchlosti prehrávania tak, aby podporovalo rôzne veľkosti krokov pre rýchlejšiu zmenu rýchlosti. - - Pridaný prepínač na rýchle prevíjanie dopredu počas ticha v ovládaní rýchlosti prehrávania. Toto by malo byť užitočné pre audioknihy a niektoré hudobné žánre a môže priniesť skutočne plynulý zážitok (a môže prerušiť skladbu s množstvom ticha =\). - - Prepracované rozlíšenie zdrojov médií, aby bolo možné odovzdávať metadáta spolu s médiami interne v prehrávači, namiesto toho, aby sa to robilo ručne. Teraz máme jediný zdroj metadát a je priamo k dispozícii pri spustení prehrávania. - - Opravené neaktualizovanie metadát vzdialeného zoznamu skladieb, keď sú k dispozícii nové metadáta pri otvorení fragmentu zoznamu skladieb. - - Rôzne opravy používateľského rozhrania: #1383, ovládacie prvky oznámenia prehrávača na pozadí sú teraz vždy biele, jednoduchšie vypnutie vyskakovacieho prehrávača prostredníctvom hodenia -- Použitie nového extraktora s preformulovanou architektúrou pre multiservis +- Disable burgermenu icon animation #1486 +- undo delete of downloads #1472 +- Download option in share menu #1498 +- Added share option to long tap menu #1454 +- Minimize main player on exit #1354 +- Library version update and database backup fix #1510 +- ExoPlayer 2.8.2 Update #1392 + - Reworked the playback speed control dialog to support different step sizes for faster speed change. + - Added a toggle to fast-forward during silences in playback speed control. This should be helpful for audiobooks and certain music genres, and can bring a true seamless experience (and can break a song with lots of silences =\\). + - Refactored media source resolution to allow passing metadata alongside media internally in the player, rather than doing so manually. Now we have a single source of metadata and is directly available when playback starts. + - Fixed remote playlist metadata not updating when new metadata is available when playlist fragment is opened. + - Various UI fixes: #1383, background player notification controls now always white, easier to shutdown popup player through flinging +- Use new extractor with refactored architecture for multiservice -### Opravy +### Fixes -- Oprava #1440 Nefunkčné rozloženie informácií o videu #1491 -- Oprava histórie zobrazenia #1497 - - #1495 aktualizáciou metadát (miniatúry, názov a počet videí) hneď, ako používateľ vstúpi do zoznamu skladieb. - - #1475, zaregistrovaním zobrazenia v databáze, keď používateľ spustí video v externom prehrávači na detailnom fragmente. -- Oprava časového limitu creen v prípade popup režimu. #1463 (Opravené #640) -- Oprava hlavného prehrávača videa č. 1509 - - #1412] Opravený režim opakovania spôsobujúci NPE prehrávača, keď je prijatý nový zámer, zatiaľ čo je činnosť prehrávača na pozadí. - - Opravené minimalizovanie prehrávača na vyskakovacie okno nezničí prehrávač, keď nie je udelené povolenie na vyskakovanie. +- Fix #1440 Broken Video Info Layout #1491 +- View history fix #1497 + - #1495, by updating the metadata (thumbnail, title and video count) as soon as the user access the playlist. + - #1475, by registering a view in the database when the user starts a video on external player on detail fragment. +- Fix creen timeout in case of popup mode. #1463 (Fixed #640) +- Main video player fix #1509 + - [#1412] Fixed repeat mode causing player NPE when new intent is received while player activity is in background. + - Fixed minimizing player to popup does not destroy player when popup permission is not granted. diff --git a/fastlane/metadata/android/sr/changelogs/994.txt b/fastlane/metadata/android/sr/changelogs/994.txt index 3ed14410d..4fa4f102b 100644 --- a/fastlane/metadata/android/sr/changelogs/994.txt +++ b/fastlane/metadata/android/sr/changelogs/994.txt @@ -7,7 +7,7 @@ • [Bandcamp] Управљање нумерама иза платног зида Поправљено -• [YouTube] 403 HTTP грешке за стримове +• [YouTube] 403 HTTP грешке за токове • Црни плејер при преласку на главни плејер са приказа плејлисте • Цурење сервисне меморије плејера • [PeerTube] Аватари отпремаоца и подканала су замењени diff --git a/fastlane/metadata/android/sv/changelogs/1005.txt b/fastlane/metadata/android/sv/changelogs/1005.txt new file mode 100644 index 000000000..203cac267 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/1005.txt @@ -0,0 +1,17 @@ +Nytt +• Stöd för Android Auto +• Flödesgrupper kan ställas in som flikar på huvudskärmen +• [YouTube] Dela som tillfällig spellista +• [SoundCloud] Gilla-kanalflik + +Förbättrat +• Bättre tips för sökfältet +• Visa hämtningsdatum i Hämtningar +• Använd Android 13 per- app språk + +Fixat +• Fixade textfärger i mörkt läge +• [YouTube] Fixade att spellistor inte laddade mer än 100 objekt +• [YouTube] Fixade saknade rekommenderade videor +• Fixade krascher i historiklistvyn +• Fixade tidsstämplar i kommentarsvar diff --git a/fastlane/metadata/android/sv/changelogs/1006.txt b/fastlane/metadata/android/sv/changelogs/1006.txt new file mode 100644 index 000000000..5fae37d22 --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/1006.txt @@ -0,0 +1,9 @@ +# Förbättrat +Behåll aktuell spelare när du klickar på tidsstämplar +Försök att återställa väntande nedladdningsuppdrag när det är möjligt +Lägg till alternativ för att ta bort en nedladdning utan att också ta bort filen +Överläggsbehörighet: visa förklarande dialogruta för Android > R +Stöd för att öppna on.soundcloud-länkar +Åtgärdade formatering av korta antal för Android-versioner under 7 +Åtgärdade Ghost Notifications +Åtgärdade för SRT-undertextfiler diff --git a/fastlane/metadata/android/sv/changelogs/1007.txt b/fastlane/metadata/android/sv/changelogs/1007.txt new file mode 100644 index 000000000..35f298dbf --- /dev/null +++ b/fastlane/metadata/android/sv/changelogs/1007.txt @@ -0,0 +1 @@ +Åtgärdat att YouTube inte spelar någon stream diff --git a/fastlane/metadata/android/ta/changelogs/1007.txt b/fastlane/metadata/android/ta/changelogs/1007.txt new file mode 100644 index 000000000..e3c06dc59 --- /dev/null +++ b/fastlane/metadata/android/ta/changelogs/1007.txt @@ -0,0 +1 @@ +நிலையான யூடியூப் எந்த ச்ட்ரீமையும் இயக்கவில்லை diff --git a/fastlane/metadata/android/th/changelogs/1000.txt b/fastlane/metadata/android/th/changelogs/1000.txt new file mode 100644 index 000000000..f80fa2800 --- /dev/null +++ b/fastlane/metadata/android/th/changelogs/1000.txt @@ -0,0 +1,13 @@ +ที่มีการปรับปรุง +• สร้างรายการเพลงที่สามารถคลิกให้แสดงได้โดยมีเนื้อหาเพื่มขึ้น/ลดลง +• [PeerTube] แฮนเดิล `subscribeto.me` ลิงค์ของอินสแตนส์จะขึ้นอัตโนมัติ +• • • เริ่มต้นด้วยรายการเดียวในประวัติของหน้าจอ + +ที่มีการปรับปรุง +• ปุ่มการมองเห็นของ RSS +• พรีวิวแท็บตัวอย่างที่มีการขัดข้อง +• แก้ไขหน้าปกของเพลย์ลิสต์ที่ไม่ขึ้น +• แก้ไขการตั้งค่าการดาวน์โหลดก่อนที่จะปรากฏ +• แก้ไขรายการที่เกี่ยวข้องกับคิวป๊อปอัป +• แก้ไขลำดับในเพลย์ลิสต์ลงในรายการที่จะเล่น +• ปรับแต่งเค้าโครงรายการบุ๊กมาร์กของเพลย์ลิสต์ diff --git a/fastlane/metadata/android/th/full_description.txt b/fastlane/metadata/android/th/full_description.txt new file mode 100644 index 000000000..e75af94af --- /dev/null +++ b/fastlane/metadata/android/th/full_description.txt @@ -0,0 +1 @@ +NewPipe จะไม่ใช้เฟรมเวิร์กของกูเกิลที่มีหรือ API ของยูทูบ โดยแค่นำโครงสร้างของเว็บไซต์เพื่อนำข้อมูลที่ต้องการ ยังไงก็ตามตัวแอปก็สามารถใช้งานได้โดยไม่ต้องติดตั้งบริการของกูเกิล คุณไม่ต้องมีบัญชียูทูปเพื่อใช้ NewPipe, และตัว FLOSS diff --git a/fastlane/metadata/android/th/short_description.txt b/fastlane/metadata/android/th/short_description.txt new file mode 100644 index 000000000..211644bbc --- /dev/null +++ b/fastlane/metadata/android/th/short_description.txt @@ -0,0 +1 @@ +ยูทูปแบบฟรีที่เบาสําหรับแอนดรอยด์ diff --git a/fastlane/metadata/android/tr/changelogs/1005.txt b/fastlane/metadata/android/tr/changelogs/1005.txt new file mode 100644 index 000000000..46b3142f7 --- /dev/null +++ b/fastlane/metadata/android/tr/changelogs/1005.txt @@ -0,0 +1,17 @@ +Yeni +• Android Auto desteği eklendi +• Akış gruplarının ana ekran sekmeleri olarak ayarlanmasına izin verme +• [YouTube] Geçici oynatma listesi olarak paylaşma +• [SoundCloud] Beğenilen kanal sekmesi + +Geliştirildi +• Daha iyi arama çubuğu önerileri +• İndirilenler'de indirme tarihini gösterimi +• Android 13 uygulama başı dil kullanma + +Düzeltildi +• Karanlık modda bozuk metin renkleri düzeltildi +• [YouTube] 100'den fazla öğeyi yüklemeyen oynatma listeleri düzeltildi +• [YouTube] Eksik önerilen videolar düzeltildi +• Geçmiş listesi görünümündeki çökmeler düzeltildi +• Yorum yanıtlarındaki zaman damgaları düzeltildi diff --git a/fastlane/metadata/android/tr/changelogs/1006.txt b/fastlane/metadata/android/tr/changelogs/1006.txt new file mode 100644 index 000000000..9e5d704a4 --- /dev/null +++ b/fastlane/metadata/android/tr/changelogs/1006.txt @@ -0,0 +1,19 @@ +# Geliştirmeler (Improved) + +* Zaman damgalarına tıklandığında mevcut oynatıcıyı koru. +* Mümkün olduğunda bekleyen indirme görevlerini kurtarmayı dene. +* Dosyayı silmeden sadece indirme kaydını silme seçeneği ekle. +* Üstte Gösterim İzni: Android R ve üzeri için açıklayıcı iletişim kutusu göster. +* "on.soundcloud" bağlantılarını açma desteği. +* Çok sayıda küçük iyileştirme ve optimizasyon. + +# Düzeltmeler (Fixed) + +* Android 7 altı sürümler için kısa sayı formatını düzelt. +* Hayalet bildirimleri düzelt. +* SRT altyazı dosyaları için düzeltmeler. +* Çok sayıda çökme sorunu giderildi. + +# Geliştirme (Development) + +* Dahili kod modernizasyonu. diff --git a/fastlane/metadata/android/tr/changelogs/1007.txt b/fastlane/metadata/android/tr/changelogs/1007.txt new file mode 100644 index 000000000..e5979c68d --- /dev/null +++ b/fastlane/metadata/android/tr/changelogs/1007.txt @@ -0,0 +1 @@ +YouTube'un herhangi bir akışı oynatmaması düzeltildi diff --git a/fastlane/metadata/android/tr/changelogs/997.txt b/fastlane/metadata/android/tr/changelogs/997.txt index ef0368d18..0dfeb5dd4 100644 --- a/fastlane/metadata/android/tr/changelogs/997.txt +++ b/fastlane/metadata/android/tr/changelogs/997.txt @@ -1,17 +1,17 @@ -Yeni -• Yorum yanıtları ekle -• Oynatma listelerini yeniden sıralamaya izin ver -• Oynatma listesi açıklamasını ve süresini göster -• Ayarların sıfırlanmasına izin ver +# Yeni +• Yorum yanıtları eklendi +• Oynatma listelerini yeniden sıralama +• Liste açıklaması ve süresi gösterimi +• Ayarları sıfırlama özelliği -İyileştirildi -• [Android 13+] Özel bildirim eylemlerini geri yükle -• Güncelleme denetimi için onay iste -• Arabelleğe alma sırasında bildirim oynatma/duraklatmaya izin ver -• Bazı ayarları yeniden sırala +# İyileştirmeler +• [Android 13+] Özel bildirim eylemleri geri getirildi +• Güncelleme kontrolü için onay isteme +• Arabelleğe alma sırasında oynat/duraklat +• Ayarlar yeniden düzenlendi -Düzeltildi -• [YouTube] Yorumların yüklenmemesini düzelt, ayrıca diğer düzeltmeler ve iyileştirmeler -• Ayarların içe aktarılmasındaki güvenlik açığını çöz ve JSON'a geç -• Çeşitli indirme düzeltmeleri -• Arama metnini kırp +# Düzeltmeler +• [YouTube] Yorumların yüklenmeme sorunu giderildi +• Ayar içe aktarma güvenlik açığı giderildi, JSON'a geçildi +• İndirme sorunları giderildi +• Arama metni düzeltmeleri diff --git a/fastlane/metadata/android/uk/changelogs/1006.txt b/fastlane/metadata/android/uk/changelogs/1006.txt new file mode 100644 index 000000000..fd79de93a --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/1006.txt @@ -0,0 +1,12 @@ +# Покращено +Зберігати поточний програвач при натисканні на часові позначки +Намагатися відновлювати місії, що очікують завантаження, коли це можливо +Додано опцію видалення завантаження без одночасного видалення файлу +Дозвіл на накладання: відображення пояснювального діалогового вікна для Android > R +Підтримка відкриття посилання на .soundcloud + +# Виправлено +Виправлено форматування короткого лічильника для версій Android нижче 7 +Виправлено сповіщення-примари +Виправлення для файлів субтитрів SRT +Виправлено безліч збоїв diff --git a/fastlane/metadata/android/uk/changelogs/1007.txt b/fastlane/metadata/android/uk/changelogs/1007.txt new file mode 100644 index 000000000..a90cfff6b --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/1007.txt @@ -0,0 +1 @@ +Виправлено проблему невідтворюваності трансляцій YouTube diff --git a/fastlane/metadata/android/vi/changelogs/1000.txt b/fastlane/metadata/android/vi/changelogs/1000.txt index 209bef6f0..e812a4fea 100644 --- a/fastlane/metadata/android/vi/changelogs/1000.txt +++ b/fastlane/metadata/android/vi/changelogs/1000.txt @@ -1,4 +1,4 @@ -Đã cải thiện +Những cải thiện • Làm cho mô tả của danh sách phát có thể nhấp vào để hiển thị nhiều / ít nội dung hơn • [PeerTube] Tự động xử lý các liên kết như 'subscribeto.me' • Chỉ bắt đầu phát một mục trong màn hình lịch sử diff --git a/fastlane/metadata/android/vi/changelogs/1004.txt b/fastlane/metadata/android/vi/changelogs/1004.txt index d2086b62c..f3f9865f2 100644 --- a/fastlane/metadata/android/vi/changelogs/1004.txt +++ b/fastlane/metadata/android/vi/changelogs/1004.txt @@ -1 +1,3 @@ -Đã sửa lỗi YouTube không phát bất kỳ luồng nào +Bản phát hành này khắc phục lỗi YouTube chỉ cung cấp luồng 360p. + +Lưu ý rằng giải pháp được sử dụng trong phiên bản này có thể chỉ là tạm thời, và về lâu dài, giao thức video SABR cần được triển khai, nhưng hiện tại các thành viên TeamNewPipe đang rất bận rộn nên chúng tôi rất mong nhận được sự giúp đỡ! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/vi/changelogs/1005.txt b/fastlane/metadata/android/vi/changelogs/1005.txt new file mode 100644 index 000000000..7eeb567b7 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/1005.txt @@ -0,0 +1,17 @@ +Mới +• Hỗ trợ cho Android Auto +• Cho phép đặt nhóm nguồn cấp dữ liệu làm tab màn hình chính +• [YouTube] Chia sẻ dưới dạng danh sách phát tạm thời +• [SoundCloud] Tab kênh thích + +Cải thiện +• Gợi ý thanh tìm kiếm tốt hơn +• Hiển thị ngày tải xuống trong mục Tải xuống +• Sử dụng cài đặt ngôn ngữ cho từng ứng dụng (Android 13+) + +Đã sửa +• Màu chữ bị hỏng ở chế độ tối +• [YouTube] Danh sách phát không tải được hơn 100 mục +• [YouTube] Thiếu video được đề xuất +• Sập trong Lịch sử +• Dấu thời gian trong phần trả lời bình luận diff --git a/fastlane/metadata/android/vi/changelogs/1007.txt b/fastlane/metadata/android/vi/changelogs/1007.txt new file mode 100644 index 000000000..d2086b62c --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/1007.txt @@ -0,0 +1 @@ +Đã sửa lỗi YouTube không phát bất kỳ luồng nào diff --git a/fastlane/metadata/android/vi/changelogs/64.txt b/fastlane/metadata/android/vi/changelogs/64.txt index 3ba81c8e4..bd932e509 100644 --- a/fastlane/metadata/android/vi/changelogs/64.txt +++ b/fastlane/metadata/android/vi/changelogs/64.txt @@ -1,7 +1,7 @@ ### Cải thiện - Thêm tính năng giới hạn độ phân giải video nếu đang sử dụng dữ liệu di động (yêu cầu #1339) - Ghi nhớ độ sáng màn hình trong phiên (yêu cầu #1442) -- Cải thiện hiệu năng của trình tải cho các CPU có hiệu năng yếu (vấn đề #1431) +- Cải thiện tốc độ tải xuống cho các CPU có hiệu năng yếu (vấn đề #1431) - Hỗ trợ cho media session (yêu cầu #1433) ### Sửa lỗi diff --git a/fastlane/metadata/android/vi/changelogs/65.txt b/fastlane/metadata/android/vi/changelogs/65.txt index de47bd38b..3b25b25d7 100644 --- a/fastlane/metadata/android/vi/changelogs/65.txt +++ b/fastlane/metadata/android/vi/changelogs/65.txt @@ -1,10 +1,9 @@ -##Cải thiện: -### Cải tiến +### Cải thiện: - Tắt hoạt ảnh biểu tượng burgermenu #1486 -- hoàn tác xóa các bản tải xuống # 1472 +- Hoàn tác xóa các bản tải xuống # 1472 - Tùy chọn tải xuống trong menu chia sẻ #1498 -- Đã thêm tùy chọn chia sẻ vào menu nhấn dài #1454 +- Đã thêm tùy chọn chia sẻ vào menu nhấn giữ #1454 - Thu nhỏ trình phát chính ở lối ra #1354 - Cập nhật phiên bản thư viện và sửa lỗi sao lưu cơ sở dữ liệu #1510 - Cập nhật ExoPlayer 2.8.2 #1392 diff --git a/fastlane/metadata/android/vi/full_description.txt b/fastlane/metadata/android/vi/full_description.txt index 63f66cb18..81ecf1d63 100644 --- a/fastlane/metadata/android/vi/full_description.txt +++ b/fastlane/metadata/android/vi/full_description.txt @@ -1 +1 @@ -NewPipe không sử dụng bất kì thư viện nào của Google, hay API của YouTube. Nó chỉ đọc và phân tích trang web để lấy thông tin cần thiết. Vì thế, ứng dụng này có thể dùng được trên các thiết bị không có cài đặt Dịch vụ của Google Play. Bạn cũng không cần tài khoản YouTube để sử dụng NewPipe, và ứng dụng này là mã nguồn mở (FLOSS). +NewPipe không sử dụng bất kì thư viện nào của Google, hay API của YouTube. Nó chỉ đọc và phân tích trang web để lấy thông tin cần thiết. Vì thế, ứng dụng này có thể dùng được trên các thiết bị không có cài đặt Dịch vụ của Google. Bạn cũng không cần tài khoản YouTube để sử dụng NewPipe, và ứng dụng này là mã nguồn mở (FLOSS). diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1002.txt b/fastlane/metadata/android/zh-Hans/changelogs/1002.txt index 8a5424c9e..ae42beccc 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/1002.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/1002.txt @@ -1 +1,4 @@ -修复YouTube无法播放任何视频 +修复YouTube不播放任何串流的问题 + +此版本只解决了阻止最紧迫的阻止 YouTube 视频详情加载的错误。 +我们知道有其他问题,会在不久后发布另一个版本解决它们。 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1003.txt b/fastlane/metadata/android/zh-Hans/changelogs/1003.txt index 8a5424c9e..195ffeb58 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/1003.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/1003.txt @@ -1 +1,6 @@ -修复YouTube无法播放任何视频 +修复 YouTube 错误的热修复版本: +• [YouTube]修复不加载任何视频的问题,修复播放视频时的 HTTP 403 错误, 恢复某些年龄受限视频的播放 +• 修复字幕尺寸未被更改的问题 +• 修复打开串流时下载两次信息的问题 +• [Soundcloud] 删除不可播放的受 DRM 保护的串流 +• 更新翻译 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1004.txt b/fastlane/metadata/android/zh-Hans/changelogs/1004.txt index 8a5424c9e..8b667904a 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/1004.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/1004.txt @@ -1 +1,3 @@ -修复YouTube无法播放任何视频 +此版本修复 YouTube 只提供 360p 串流的问题。 + +注意此版本部署的解决方案可能是临时性的,长期来看需要使用 SABR 视频协议,但 Newpipe 团队成员目前没空,我们十分感谢任何帮助!https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1005.txt b/fastlane/metadata/android/zh-Hans/changelogs/1005.txt new file mode 100644 index 000000000..baf746b18 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/1005.txt @@ -0,0 +1,16 @@ +新增 +• 新增对 Android Auto 的支持 +• 允许将信息流分组设置为主屏幕标签页 +• [YouTube] 以临时播放列表的形式分享 +• [SoundCloud] 新增“喜欢”频道标签页 + +改进 +• 优化搜索栏提示 +• 在“下载”中显示下载日期 +• 使用 Android 13 的应用内语言 +修复 +• 修复深色模式下文本颜色显示错误 +• [YouTube] 修复播放列表加载超过 100 个项目时无法加载的问题 +• [YouTube] 修复推荐视频缺失的问题 +• 修复历史记录列表视图中的崩溃问题 +• 修复评论回复中的时间戳显示错误 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1006.txt b/fastlane/metadata/android/zh-Hans/changelogs/1006.txt new file mode 100644 index 000000000..a3a089068 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/1006.txt @@ -0,0 +1,16 @@ +# 改进 +单击时间戳时保持当前播放器 +尽可能恢复未完成的下载任务 +新增选项,允许删除下载项而不删除文件 +叠加层权限:在 Android R 及以上版本中显示说明对话框 +支持打开 on.soundcloud 链接 +大量小改进和优化 + +# 修复 +修复 Android 7 以下版本短计数格式问题 +修复幽灵通知 +修复 SRT 字幕文件问题 +修复大量崩溃问题 + +# 开发 +内部代码现代化 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1007.txt b/fastlane/metadata/android/zh-Hans/changelogs/1007.txt new file mode 100644 index 000000000..8a5424c9e --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/1007.txt @@ -0,0 +1 @@ +修复YouTube无法播放任何视频 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/991.txt b/fastlane/metadata/android/zh-Hans/changelogs/991.txt new file mode 100644 index 000000000..c4ca761f4 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/991.txt @@ -0,0 +1,13 @@ +新增 +• 在错误面板中添加“在浏览器中打开”按钮 +• 新增以列表形式显示频道组的选项 +• [YouTube] 长按视频片段即可分享时间戳 URL +• 在迷你播放器中添加播放队列按钮 + +改进 +• 新增冰岛语本地化并更新了其他多种语言的翻译 +• 多项内部改进 + +修复 +• 修复多个崩溃问题 +• [YouTube] 修复部分国家/地区频道加载、非专用源播放以及播放问题 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/992.txt b/fastlane/metadata/android/zh-Hans/changelogs/992.txt new file mode 100644 index 000000000..ca8e1733d --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/992.txt @@ -0,0 +1,17 @@ +新增 +• 视频详情页显示订阅者数量 +• 从播放队列下载 +• 永久设置播放列表缩略图 +• 长按话题标签和链接 +• 卡片视图模式 + +改进 +• 更大的迷你播放器关闭按钮 +• 更流畅的缩略图缩放 +• 目标平台:Android 13 (API 33) +• 快进/快退操作不再导致播放器暂停 + +修复 +• 修复 DeX/鼠标上的叠加层问题 +• 允许后台播放,无需单独的音频流 +• 其他 YouTube 相关问题修复及更多… diff --git a/fastlane/metadata/android/zh-Hans/changelogs/993.txt b/fastlane/metadata/android/zh-Hans/changelogs/993.txt new file mode 100644 index 000000000..abe5b8f27 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/993.txt @@ -0,0 +1,12 @@ +新增 +• 添加重复播放列表时发出警告,并添加删除按钮 +• 允许忽略硬件按钮 +• 允许在信息流中隐藏已观看但未完成的视频 + +改进 +• 在大屏幕上使用更多网格列 +• 使进度指示器与设置保持一致 + +修复 +• 修复在 Android 11 及更高版本上打开浏览器 URL、下载和外部播放器的问题 +• 修复在 MIUI 系统上全屏交互需要点击两次的问题 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/994.txt b/fastlane/metadata/android/zh-Hans/changelogs/994.txt new file mode 100644 index 000000000..38bfed7d0 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/994.txt @@ -0,0 +1,15 @@ +新增 +• 支持多音轨/多语言 +• 允许在屏幕任意一侧使用手势调节音量和亮度 +• 支持在屏幕底部显示主标签页 + +改进 +• [Bandcamp] 处理付费墙后的曲目 + +修复 +• [YouTube] 修复流媒体播放的 403 HTTP 错误 +• 修复从播放列表视图切换到主播放器时播放器黑屏的问题 +• 修复播放器服务内存泄漏问题 +• [PeerTube] 上传者和子频道头像互换的问题 + +以及更多 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/995.txt b/fastlane/metadata/android/zh-Hans/changelogs/995.txt new file mode 100644 index 000000000..4cd4d2b80 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/995.txt @@ -0,0 +1,16 @@ +新增 +• 支持频道标签页 +• 可选择图像质量 +• 获取所有图像的 URL + +改进 +• 播放器界面更易于访问 +• 改进仅下载视频时的音频选择 +• 可选择在共享播放列表内容中包含播放列表和视频名称 + +修复 +• [YouTube] 修复获取点赞数的问题 +• 修复播放器无响应的弹出窗口和崩溃问题 +• 修复语言选择器中选择错误语言的问题 +• 修复播放器音频焦点未响应静音设置的问题 +• 修复播放列表项目添加功能偶尔失效的问题 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/996.txt b/fastlane/metadata/android/zh-Hans/changelogs/996.txt new file mode 100644 index 000000000..4773b420b --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/996.txt @@ -0,0 +1,2 @@ +修复了在 media.ccc.de 中打开频道/会议时出现的 NullPointerException 异常。 +圣诞怪杰试图破坏我们送给大家的圣诞礼物,但我们已经解决了这个问题。 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/997.txt b/fastlane/metadata/android/zh-Hans/changelogs/997.txt new file mode 100644 index 000000000..a7cd06bd6 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/997.txt @@ -0,0 +1,17 @@ +新增 +• 添加评论回复 +• 允许重新排序播放列表 +• 显示播放列表描述和时长 +• 允许重置设置 + +改进 +• [Android 13+] 恢复自定义通知操作 +• 请求更新检查的同意 +• 允许在缓冲期间播放/暂停通知 +• 重新排序部分设置 + +修复 +• [YouTube] 修复评论无法加载的问题,以及其他修复和改进 +• 修复设置导入中的漏洞并切换到 JSON 格式 +• 修复各种下载问题 +• 精简搜索文本 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/998.txt b/fastlane/metadata/android/zh-Hans/changelogs/998.txt index 8a5424c9e..edffb7593 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/998.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/998.txt @@ -1 +1,4 @@ -修复YouTube无法播放任何视频 +修复 YouTube 因 HTTP 403 错误不播放任何串流的问题 + +还没修复 YouTube 视频中间偶尔的 403 错误. +该问题会尽快在另一个热修复版本中得以解决。 diff --git a/fastlane/metadata/android/zh-Hans/changelogs/999.txt b/fastlane/metadata/android/zh-Hans/changelogs/999.txt index 8a5424c9e..791c12314 100644 --- a/fastlane/metadata/android/zh-Hans/changelogs/999.txt +++ b/fastlane/metadata/android/zh-Hans/changelogs/999.txt @@ -1 +1,12 @@ -修复YouTube无法播放任何视频 +此热修复版本修复 YouTube 视频播放中的 HTTP 403 错误。 + +新功能 +• [SoundCloud] 支持 on.soundcloud.com URLs + +改进 +• [Bandcamp] 在电台 kiosk 中显示附加信息 + +修复 +• [YouTube] 视频开头或当中偶然的 403 错误 +• [YouTube] 从更多频道标头类型提取头像和横幅 +• [Bandcamp] 多个故障和始终使用 HTTPS diff --git a/fastlane/metadata/android/zh-Hant/changelogs/1007.txt b/fastlane/metadata/android/zh-Hant/changelogs/1007.txt new file mode 100644 index 000000000..4e8bf6537 --- /dev/null +++ b/fastlane/metadata/android/zh-Hant/changelogs/1007.txt @@ -0,0 +1 @@ +修正 YouTube 無法播放任何串流 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/1005.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/1005.txt new file mode 100644 index 000000000..8389ad0be --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/1005.txt @@ -0,0 +1,17 @@ +新功能 +• 加入咗對 Android Auto 應用程式嘅支援 +• 允許將資訊提供群組設定為主螢幕標籤 +• 【 YouTube 】可分享為臨時播放清單 +• 【 SoundCloud 】可設定為最喜愛頻道標籤 + +改善 +• 更好嘅搜尋列提示 +• 「下載」介面會顯示下載日期 +• 使用 Android 13為所有應用程式嘅語言 + +修復 +• 修復咗深色模式下破碎嘅文字顏色 +• 修復咗【 YouTube 】播放清單無法載入超過100 個項目嘅問題 +• 修復咗【 YouTube 】推薦影片消失嘅問題 +• 修復咗睇緊播放記錄期間會死機嘅問題 +• 修復咗留言同回覆入面嘅時間戳記 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/1007.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/1007.txt new file mode 100644 index 000000000..9a4721551 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/1007.txt @@ -0,0 +1 @@ +修正咗 YouTube 乜嘢實況串流都播唔到嘅問題 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/64.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/64.txt new file mode 100644 index 000000000..65e8afaf9 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/64.txt @@ -0,0 +1,8 @@ +### 改善 +- 加入咗喺使用流動數據時限制影片質素嘅功能。#1339 +- 會記錄並使用你設定嘅亮度。#1442 +- 改善在較弱CPU上嘅設備嘅下載效能。#1431 +- 加入咗(可用)媒體支援。#1433 + +### 修復 +- 修復咗打開下載時發生死機嘅問題(修復版本已推出)。#1441 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/65.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/65.txt new file mode 100644 index 000000000..eaa087920 --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/65.txt @@ -0,0 +1,26 @@ +### 改善 + +- 停用漢堡選單圖示動畫 #1486 +- 還原已刪除嘅下載項目 #1472 +- 喺分享選單中加入下載選項 #1498 +- 喺長按選單中加入分享選項 #1454 +- 離開時最小化主播放器 #1354 +- 更新資料庫版本並修復備份問題 #1510 +- ExoPlayer 2.8.2 更新 #1392 +- 重新設計播放速度控制對話框,支援更細緻嘅速度調整步幅。 +- 加入靜音時快轉嘅切換選項,有助於聽有聲書或某啲音樂類型,提供更流暢嘅體驗(但可能會令某啲有大量靜音段落嘅歌曲播放出現問題 =\\)。 +- 重構媒體來源解析方式,令播放器可以內部傳遞媒體同時附帶嘅中繼資料,而唔需要手動處理。播放一開始就可以直接使用統一來源嘅中繼資料。 +- 修復遠端播放清單中繼資料喺開啟播放清單片段時未能更新嘅問題。 +- 各種 UI 修復:#1383,例如背景播放器通知控制改為固定白色、彈出播放器更容易關閉。 +- 使用新架構重構嘅多服務擷取器 + +### 修復項目 + +- 修復咗 #1440 影片資訊版面錯誤配置 #1491 +- 修復咗無法觀看播放記錄問題 #1497 +- #1495:當使用者打開播放清單時即時更新中繼資料(縮圖、標題、影片數量)。 +- #1475:當使用者喺詳細頁面用外部播放器播放影片時,會喺資料庫中登記一次觀看記錄。 +- 修復咗彈出模式下螢幕逾時問題 #1463(已修復 #640) +- 主播放器修復 #1509 +- [#1412] 修復咗重複播放模式喺接收新指示時,播放器處於背景導致 NPE 嘅問題。 +- 修復咗未授權彈出權限時將播放器最小化到彈出視窗不會關掉播放器嘅問題。 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/66.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/66.txt new file mode 100644 index 000000000..d5a6d607a --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/66.txt @@ -0,0 +1,33 @@ +# v0.13.7 更新日誌 + +### 修復 +- 修復咗 v0.13.6 中排序篩選器嘅問題 + +# v0.13.6 更新日誌 + +### 改善 + +- 停用漢堡選單圖示動畫 #1486 +- 還原已刪除嘅下載項目 #1472 +- 喺分享選單中加入下載選項 #1498 +- 喺長按選單中加入分享選項 #1454 +- 離開時最小化主播放器 #1354 +- 更新資料庫版本並修復備份問題 #1510 +- ExoPlayer 2.8.2 更新 #1392 +- 重新設計播放速度控制對話框,支援更細緻嘅速度調整步幅。 +- 加入靜音時快轉嘅切換選項,有助於聽有聲書或某啲音樂類型,提供更流暢嘅體驗(但可能會令某啲有大量靜音段落嘅歌曲播放出現問題 =\\)。 +- 重構媒體來源解析方式,令播放器可以內部傳遞媒體同時附帶嘅中繼資料,而唔需要手動處理。播放一開始就可以直接使用統一來源嘅中繼資料。 +- 修復遠端播放清單中繼資料喺開啟播放清單片段時未能更新嘅問題。 +- 各種 UI 修復:#1383,例如背景播放器通知控制改為固定白色、彈出播放器更容易關閉。 +- 使用新架構重構嘅多服務擷取器 + +### 修復項目 + +- 修復咗 #1440 影片資訊版面錯誤配置 #1491 +- 修復咗無法觀看播放記錄問題 #1497 +- #1495:當使用者打開播放清單時即時更新中繼資料(縮圖、標題、影片數量)。 +- #1475:當使用者喺詳細頁面用外部播放器播放影片時,會喺資料庫中登記一次觀看記錄。 +- 修復咗彈出模式下螢幕逾時問題 #1463(已修復 #640) +- 主播放器修復 #1509 +- [#1412] 修復咗重複播放模式喺接收新指示時,播放器處於背景導致 NPE 嘅問題。 +- 修復咗未授權彈出權限時將播放器最小化到彈出視窗不會關掉播放器嘅問題。 diff --git a/fastlane/metadata/android/zh_Hant_HK/changelogs/68.txt b/fastlane/metadata/android/zh_Hant_HK/changelogs/68.txt new file mode 100644 index 000000000..00b67b1ea --- /dev/null +++ b/fastlane/metadata/android/zh_Hant_HK/changelogs/68.txt @@ -0,0 +1,31 @@ +# v0.14.1 更新內容 + +### 修復項目 +- 修復咗無法解密影片網址嘅問題 #1659 +- 修復咗影片描述連結擷取唔準確嘅問題 #1657 + +# v0.14.0 更新內容 + +### 新功能 +- 全新抽屜式選單設計 #1461 +- 可自訂嘅主頁介面 #1461 + +### 改善項目 +- 重新設計手勢控制功能 #1604 +- 加入新方式關閉彈出播放器 #1597 + +### 修復項目 +- 修復訂閱人數無法取得時出錯嘅問題。已關閉 #1649 + - 當無法取得訂閱人數時,會顯示「無法取得訂閱人數」 +- 修復 YouTube 播放清單為空時出現 NPE 錯誤 +- 快速修復 SoundCloud 互動資訊站問題 +- 重構並修復錯誤 #1623 + - 修復循環搜尋結果問題 #1562 + - 修復進度條未正確排版問題 + - 修復 YouTube Premium 影片未正確封鎖問題 + - 修復影片有時無法載入(因 DASH 解析問題) + - 修復影片描述中連結無法點擊問題 + - 當使用者嘗試下載至外置 SD 卡時顯示警告 + - 修復「無內容顯示」錯誤觸發回報問題 + - 修復 Android 8.1 背景播放器未顯示縮圖問題 [詳情請參閱](https://github.com/TeamNewPipe/NewPipe/issues/943) +- 修復廣播接收器註冊問題。已關閉 #1641 diff --git a/gradle.properties b/gradle.properties index ed32303da..01e1aa01f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,3 +4,6 @@ android.nonTransitiveRClass=true android.useAndroidX=true org.gradle.jvmargs=-Xmx2048M --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED systemProp.file.encoding=utf-8 + +# https://docs.gradle.org/current/userguide/configuration_cache.html +org.gradle.configuration-cache=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..5448848a2 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,139 @@ +# +# SPDX-FileCopyrightText: 2025 NewPipe e.V. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +[versions] +acra = "5.13.1" +agp = "8.13.2" +appcompat = "1.7.1" +assertj = "3.27.6" +autoservice-google = "1.1.1" +autoservice-zacsweers = "1.2.0" +bridge = "v2.0.2" +cardview = "1.0.0" +checkstyle = "13.0.0" +constraintlayout = "2.2.1" +core = "1.17.0" +desugar = "2.1.5" +documentfile = "1.1.0" +exoplayer = "2.19.1" +fragment = "1.8.9" +groupie = "2.10.1" +jsoup = "1.22.1" +junit = "4.13.2" +junit-ext = "1.3.0" +kotlin = "2.2.21" +ksp = "2.3.4" +ktlint = "1.8.0" +leakcanary = "2.14" +lifecycle = "2.9.4" # Newer versions require minSdk >= 23 +localbroadcastmanager = "1.1.0" +markwon = "4.6.2" +material = "1.11.0" # TODO: update to newer version after bug is fixed. See https://github.com/TeamNewPipe/NewPipe/pull/13018 +media = "1.7.1" +mockitoCore = "5.21.0" +okhttp = "5.3.2" +phoenix = "3.0.0" +#noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! +picasso = "2.8" +preference = "1.2.1" +prettytime = "5.0.8.Final" +recyclerview = "1.4.0" +room = "2.7.2" # Newer versions require minSdk >= 23 +runner = "1.7.0" +rxandroid = "3.0.2" +rxbinding = "4.0.0" +rxjava = "3.1.12" +sonarqube = "7.2.2.6593" +statesaver = "1.4.1" # TODO: Drop because it is deprecated and incompatible with KSP2 +stetho = "1.6.0" +swiperefreshlayout = "1.2.0" +# You can use a local version by uncommenting a few lines in settings.gradle +# Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub +# name and the commit hash with the commit hash of the (pushed) commit you want to test +# This works thanks to JitPack: https://jitpack.io/ +teamnewpipe-filepicker = "5.0.0" +teamnewpipe-nanojson = "e9d656ddb49a412a5a0a5d5ef20ca7ef09549996" +# WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.XX.Y` with +# the corresponding commit hash, since JitPack sometimes deletes artifacts. +# If there’s already a git hash, just add more of it to the end (or remove a letter) +# to cause jitpack to regenerate the artifact. +teamnewpipe-newpipe-extractor = "v0.25.1" +viewpager2 = "1.1.0" +webkit = "1.14.0" # Newer versions require minSdk >= 23 +work = "2.10.5" # Newer versions require minSdk >= 23 + +[libraries] +acra-core = { module = "ch.acra:acra-core", version.ref = "acra" } +android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } +androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } +androidx-core = { module = "androidx.core:core-ktx", version.ref = "core" } +androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "documentfile" } +androidx-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment" } +androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junit-ext" } +androidx-lifecycle-livedata = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycle" } +androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +androidx-localbroadcastmanager = { module = "androidx.localbroadcastmanager:localbroadcastmanager", version.ref = "localbroadcastmanager" } +androidx-media = { module = "androidx.media:media", version.ref = "media" } +androidx-preference = { module = "androidx.preference:preference", version.ref = "preference" } +androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +androidx-room-rxjava3 = { module = "androidx.room:room-rxjava3", version.ref = "room" } +androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "room" } +androidx-runner = { module = "androidx.test:runner", version.ref = "runner" } +androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "swiperefreshlayout" } +androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager2" } +androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } +androidx-work-runtime = { module = "androidx.work:work-runtime", version.ref = "work" } +androidx-work-rxjava3 = { module = "androidx.work:work-rxjava3", version.ref = "work" } +assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" } +evernote-statesaver-compiler = { module = "com.evernote:android-state-processor", version.ref = "statesaver" } +evernote-statesaver-core = { module = "com.evernote:android-state", version.ref = "statesaver" } +facebook-stetho-core = { module = "com.facebook.stetho:stetho", version.ref = "stetho" } +facebook-stetho-okhttp3 = { module = "com.facebook.stetho:stetho-okhttp3", version.ref = "stetho" } +google-android-material = { module = "com.google.android.material:material", version.ref = "material" } +google-autoservice-annotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoservice-google" } +google-exoplayer-core = { module = "com.google.android.exoplayer:exoplayer-core", version.ref = "exoplayer" } +google-exoplayer-dash = { module = "com.google.android.exoplayer:exoplayer-dash", version.ref = "exoplayer" } +google-exoplayer-database = { module = "com.google.android.exoplayer:exoplayer-database", version.ref = "exoplayer" } +google-exoplayer-datasource = { module = "com.google.android.exoplayer:exoplayer-datasource", version.ref = "exoplayer" } +google-exoplayer-hls = { module = "com.google.android.exoplayer:exoplayer-hls", version.ref = "exoplayer" } +google-exoplayer-mediasession = { module = "com.google.android.exoplayer:extension-mediasession", version.ref = "exoplayer" } +google-exoplayer-smoothstreaming = { module = "com.google.android.exoplayer:exoplayer-smoothstreaming", version.ref = "exoplayer" } +google-exoplayer-ui = { module = "com.google.android.exoplayer:exoplayer-ui", version.ref = "exoplayer" } +jakewharton-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "phoenix" } +jakewharton-rxbinding = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" } +jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } +junit = { module = "junit:junit", version.ref = "junit" } +lisawray-groupie-core = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" } +lisawray-groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" } +livefront-bridge = { module = "com.github.livefront:bridge", version.ref = "bridge" } +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } +newpipe-extractor = { module = "com.github.TeamNewPipe:NewPipeExtractor", version.ref = "teamnewpipe-newpipe-extractor" } +newpipe-filepicker = { module = "com.github.TeamNewPipe:NoNonsense-FilePicker", version.ref = "teamnewpipe-filepicker" } +newpipe-nanojson = { module = "com.github.TeamNewPipe:nanojson", version.ref = "teamnewpipe-nanojson" } +noties-markwon-core = { module = "io.noties.markwon:core", version.ref = "markwon" } +noties-markwon-linkify = { module = "io.noties.markwon:linkify", version.ref = "markwon" } +ocpsoft-prettytime = { module = "org.ocpsoft.prettytime:prettytime", version.ref = "prettytime" } +pinterest-ktlint = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "ktlint" } +puppycrawl-checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } +reactivex-rxandroid = { module = "io.reactivex.rxjava3:rxandroid", version.ref = "rxandroid" } +reactivex-rxjava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" } +squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" } +squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" } +squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" } +squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } +squareup-picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" } +zacsweers-autoservice-compiler = { module = "dev.zacsweers.autoservice:auto-service-ksp", version.ref = "autoservice-zacsweers" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +google-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } # Needed for statesaver +jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e..61285a659 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 57939822b..44ae9537e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,8 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionSha256Sum=0d585f69da091fc5b2beced877feab55a3064d43b8a1d46aeb07996b0915e0e0 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb4..adff685a0 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -111,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -130,10 +132,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +146,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -166,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -198,16 +202,15 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..e509b2dd8 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,22 +59,21 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 0338fde6c..000000000 --- a/settings.gradle +++ /dev/null @@ -1,11 +0,0 @@ -include ':app' - -// Use a local copy of NewPipe Extractor by uncommenting the lines below. -// We assume, that NewPipe and NewPipe Extractor have the same parent directory. -// If this is not the case, please change the path in includeBuild(). - -//includeBuild('../NewPipeExtractor') { -// dependencySubstitution { -// substitute module('com.github.TeamNewPipe:NewPipeExtractor') using project(':extractor') -// } -//} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..60a40c985 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") + maven(url = "https://repo.clojars.org") + } +} +include (":app") + +// Use a local copy of NewPipe Extractor by uncommenting the lines below. +// We assume, that NewPipe and NewPipe Extractor have the same parent directory. +// If this is not the case, please change the path in includeBuild(). + +//includeBuild("../NewPipeExtractor") { +// dependencySubstitution { +// substitute(module("com.github.TeamNewPipe:NewPipeExtractor")) +// .using(project(":extractor")) +// } +//}