Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e554c77
Comments: Put @ on the right side of right-to-left usernames
Profpatsch May 7, 2025
42a52b7
Merge pull request #12259 from Profpatsch/put-@-on-right-side-of-rtl-…
Profpatsch May 8, 2025
90e2f23
Initial commit for better handling of background crashes
Thompson3142 Dec 2, 2024
76202e6
Remove no longer needed dependency
Thompson3142 Dec 17, 2024
f3858e7
Merge pull request #11789 from Thompson3142/fix_background_crash_focus
Profpatsch May 9, 2025
7dd1abd
Add dev and refactor nightly build badges
absurdlylongusername May 20, 2025
c9155f7
Merge pull request #12298 from davidasunmo/add-dev-refactor-nightly-b…
Stypox May 20, 2025
16077de
Add matrix chat link to all READMEs
May 21, 2025
de3d115
Add nightly builds to all readmes
May 22, 2025
55bf74b
Fix CI status badge
absurdlylongusername May 24, 2025
aa0b45c
ChannelTab.equals fix comparison
dev-victoria May 30, 2025
86869f0
Copied SelectFeedGroupFragment from SelectChannelFragment
dev-victoria May 30, 2025
e6c4690
# Copied Layouts
dev-victoria May 30, 2025
7c3989f
# Change
dev-victoria May 30, 2025
436626f
# Change
dev-victoria May 30, 2025
f8ed8e5
# Change
dev-victoria May 30, 2025
279caac
# Change
dev-victoria May 30, 2025
fd09e61
# Fixed Feed Group Titlebar
dev-victoria May 30, 2025
7127242
added FeedGroup to Tab Settings UnitTest
dev-victoria May 30, 2025
205d18f
Use GroupName for the Settings Text.
dev-victoria May 31, 2025
033cc08
Merge pull request #12322 from dev-victoria/tiny-code-fixes
AudricV May 31, 2025
571b7bc
Improve layout of select_feed_group_item
Stypox Jun 4, 2025
8e036b5
Merge pull request #12325 from dev-victoria/FeedGroupTab
Stypox Jun 4, 2025
8c4a789
Merge pull request #12302 from davidasunmo/update-readmes
Stypox Jun 4, 2025
6efb92a
Merge branch 'dev' into Merge-dev-to-refactor
Isira-Seneviratne Jun 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-en.svg" alt="Get it on F-Droid" height=80/></a></p>

<p align="center">
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub NewPipe releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
<a href="https://github.com/TeamNewPipe/NewPipe-nightly/releases" alt="GitHub NewPipe nightly releases">
<img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-nightly.svg?labelColor=purple&label=dev%20nightly" >
</a>
<a href="https://github.com/TeamNewPipe/NewPipe-refactor-nightly/releases" alt="GitHub NewPipe refactor nightly releases">
<img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-refactor-nightly.svg?labelColor=purple&label=refactor%20nightly" >
</a>
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/actions/workflows/ci.yml/badge.svg?branch=dev&event=push"></a>
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
</p>

<p align="center">
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
<a href="https://matrix.to/#/#newpipe:matrix.newpipe-ev.de" alt="Matrix channel: #newpipe"><img src="https://img.shields.io/badge/Matrix%20chat-%23newpipe-blue"></a>
</p>

<hr>
<p align="center"><a href="#screenshots">Screenshots</a> &bull; <a href="#supported-services">Supported Services</a> &bull; <a href="#description">Description</a> &bull; <a href="#features">Features</a> &bull; <a href="#installation-and-updates">Installation and updates</a> &bull; <a href="#contribution">Contribution</a> &bull; <a href="#donate">Donate</a> &bull; <a href="#license">License</a></p>
<p align="center"><a href="https://newpipe.net">Website</a> &bull; <a href="https://newpipe.net/blog/">Blog</a> &bull; <a href="https://newpipe.net/FAQ/">FAQ</a> &bull; <a href="https://newpipe.net/press/">Press</a></p>
Expand Down
30 changes: 23 additions & 7 deletions app/src/main/java/org/schabi/newpipe/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ public class MainActivity extends AppCompatActivity {
private static final int ITEM_ID_ABOUT = 2;

private static final int ORDER = 0;
public static final String KEY_IS_IN_BACKGROUND = "is_in_background";

private SharedPreferences sharedPreferences;
private SharedPreferences.Editor sharedPrefEditor;
/*//////////////////////////////////////////////////////////////////////////
// Activity's LifeCycle
//////////////////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -152,6 +155,8 @@ protected void onCreate(final Bundle savedInstanceState) {

assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
sharedPrefEditor = sharedPreferences.edit();

mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
drawerLayoutBinding = mainBinding.drawerLayout;
Expand Down Expand Up @@ -195,16 +200,29 @@ protected void onPostCreate(final Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);

final App app = App.getInstance();
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);

if (prefs.getBoolean(app.getString(R.string.update_app_key), false)
&& prefs.getBoolean(app.getString(R.string.update_check_consent_key), false)) {
if (sharedPreferences.getBoolean(app.getString(R.string.update_app_key), false)
&& sharedPreferences
.getBoolean(app.getString(R.string.update_check_consent_key), false)) {
// Start the worker which is checking all conditions
// and eventually searching for a new version.
NewVersionWorker.enqueueNewVersionCheckingWork(app, false);
}
}

@Override
protected void onStart() {
super.onStart();
sharedPrefEditor.putBoolean(KEY_IS_IN_BACKGROUND, false).apply();
Log.d(TAG, "App moved to foreground");
}

@Override
protected void onStop() {
super.onStop();
sharedPrefEditor.putBoolean(KEY_IS_IN_BACKGROUND, true).apply();
Log.d(TAG, "App moved to background");
}
private void setupDrawer() throws ExtractionException {
addDrawerMenuForCurrentService();

Expand Down Expand Up @@ -504,21 +522,19 @@ protected void onResume() {
ErrorUtil.showUiErrorSnackbar(this, "Setting up service toggle", e);
}

final SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPreferences.getBoolean(Constants.KEY_THEME_CHANGE, false)) {
if (DEBUG) {
Log.d(TAG, "Theme has changed, recreating activity...");
}
sharedPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
sharedPrefEditor.putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
ActivityCompat.recreate(this);
}

if (sharedPreferences.getBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false)) {
if (DEBUG) {
Log.d(TAG, "main page has changed, recreating main fragment...");
}
sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply();
sharedPrefEditor.putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply();
NavigationHelper.openMainActivity(this);
}

Expand Down
12 changes: 11 additions & 1 deletion app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.PendingIntentCompat
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import org.schabi.newpipe.MainActivity
import org.schabi.newpipe.R

/**
Expand All @@ -35,12 +37,20 @@ class ErrorUtil {
* activity (since the workflow would be interrupted anyway in that case). So never use this
* for background services.
*
* If the crashed occurred while the app was in the background open a notification instead
*
* @param context the context to use to start the new activity
* @param errorInfo the error info to be reported
*/
@JvmStatic
fun openActivity(context: Context, errorInfo: ErrorInfo) {
context.startActivity(getErrorActivityIntent(context, errorInfo))
if (PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(MainActivity.KEY_IS_IN_BACKGROUND, true)
) {
createNotification(context, errorInfo)
} else {
context.startActivity(getErrorActivityIntent(context, errorInfo))
}
}

/**
Expand Down
15 changes: 13 additions & 2 deletions app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,12 @@ class FeedFragment : BaseStateFragment<FeedState>() {
@Deprecated("Deprecated in Java")
override fun onDestroyOptionsMenu() {
super.onDestroyOptionsMenu()
activity?.supportActionBar?.subtitle = null
if (
(groupName != "") &&
(activity?.supportActionBar?.subtitle == groupName)
) {
activity?.supportActionBar?.subtitle = null
}
}

override fun onDestroy() {
Expand All @@ -286,7 +291,13 @@ class FeedFragment : BaseStateFragment<FeedState>() {
}

super.onDestroy()
activity?.supportActionBar?.subtitle = null

if (
(groupName != "") &&
(activity?.supportActionBar?.subtitle == groupName)
) {
activity?.supportActionBar?.subtitle = null
}
}

override fun onDestroyView() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package org.schabi.newpipe.settings;

import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.AppDatabase;
import org.schabi.newpipe.database.feed.model.FeedGroupEntity;
import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.util.ThemeHelper;

import java.util.List;
import java.util.Vector;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

/**
* Created by Christian Schabesberger on 26.09.17.
* SelectChannelFragment.java is part of NewPipe.
* <p>
* 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.
* </p>
* <p>
* 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.
* </p>
* <p>
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
* </p>
*/

public class SelectFeedGroupFragment extends DialogFragment {

private OnSelectedListener onSelectedListener = null;
private OnCancelListener onCancelListener = null;

private ProgressBar progressBar;
private TextView emptyView;
private RecyclerView recyclerView;

private List<FeedGroupEntity> feedGroups = new Vector<>();

public void setOnSelectedListener(final OnSelectedListener listener) {
onSelectedListener = listener;
}

public void setOnCancelListener(final OnCancelListener listener) {
onCancelListener = listener;
}

/*//////////////////////////////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////////////////////////////*/

@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, ThemeHelper.getMinWidthDialogTheme(requireContext()));
}

@Override
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.select_feed_group_fragment, container, false);
recyclerView = v.findViewById(R.id.items_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
final SelectFeedGroupAdapter feedGroupAdapter = new SelectFeedGroupAdapter();
recyclerView.setAdapter(feedGroupAdapter);

progressBar = v.findViewById(R.id.progressBar);
emptyView = v.findViewById(R.id.empty_state_view);
progressBar.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.GONE);


final AppDatabase database = NewPipeDatabase.getInstance(requireContext());
database.feedGroupDAO().getAll().toObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getFeedGroupObserver());

return v;
}

/*//////////////////////////////////////////////////////////////////////////
// Handle actions
//////////////////////////////////////////////////////////////////////////*/

@Override
public void onCancel(@NonNull final DialogInterface dialogInterface) {
super.onCancel(dialogInterface);
if (onCancelListener != null) {
onCancelListener.onCancel();
}
}

private void clickedItem(final int position) {
if (onSelectedListener != null) {
final FeedGroupEntity entry = feedGroups.get(position);
onSelectedListener
.onFeedGroupSelected(entry.getUid(), entry.getName(),
entry.getIcon().getDrawableResource());
}
dismiss();
}

/*//////////////////////////////////////////////////////////////////////////
// Item handling
//////////////////////////////////////////////////////////////////////////*/

private void displayFeedGroups(final List<FeedGroupEntity> newFeedGroups) {
this.feedGroups = newFeedGroups;
progressBar.setVisibility(View.GONE);
if (newFeedGroups.isEmpty()) {
emptyView.setVisibility(View.VISIBLE);
return;
}
recyclerView.setVisibility(View.VISIBLE);

}

private Observer<List<FeedGroupEntity>> getFeedGroupObserver() {
return new Observer<List<FeedGroupEntity>>() {
@Override
public void onSubscribe(@NonNull final Disposable disposable) { }

@Override
public void onNext(@NonNull final List<FeedGroupEntity> newGroups) {
displayFeedGroups(newGroups);
}

@Override
public void onError(@NonNull final Throwable exception) {
ErrorUtil.showUiErrorSnackbar(SelectFeedGroupFragment.this,
"Loading Feed Groups", exception);
}

@Override
public void onComplete() { }
};
}

/*//////////////////////////////////////////////////////////////////////////
// Interfaces
//////////////////////////////////////////////////////////////////////////*/

public interface OnSelectedListener {
void onFeedGroupSelected(Long groupId, String name, int icon);
}

public interface OnCancelListener {
void onCancel();
}

private class SelectFeedGroupAdapter
extends RecyclerView.Adapter<SelectFeedGroupAdapter.SelectFeedGroupItemHolder> {
@NonNull
@Override
public SelectFeedGroupItemHolder onCreateViewHolder(final ViewGroup parent,
final int viewType) {
final View item = LayoutInflater.from(parent.getContext())
.inflate(R.layout.select_feed_group_item, parent, false);
return new SelectFeedGroupItemHolder(item);
}

@Override
public void onBindViewHolder(final SelectFeedGroupItemHolder holder, final int position) {
final FeedGroupEntity entry = feedGroups.get(position);
holder.titleView.setText(entry.getName());
holder.view.setOnClickListener(view -> clickedItem(position));
holder.thumbnailView.setImageResource(entry.getIcon().getDrawableResource());
}

@Override
public int getItemCount() {
return feedGroups.size();
}

public class SelectFeedGroupItemHolder extends RecyclerView.ViewHolder {
public final View view;
final ImageView thumbnailView;
final TextView titleView;
SelectFeedGroupItemHolder(final View v) {
super(v);
this.view = v;
thumbnailView = v.findViewById(R.id.itemThumbnailView);
titleView = v.findViewById(R.id.itemTitleView);
}
}
}
}
Loading