fix: get notified menu option on all tabs

This commit is contained in:
ThetaDev 2022-10-23 11:28:34 +02:00 committed by Stypox
parent 6d13cf5e71
commit 8627efd0a1
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
4 changed files with 118 additions and 90 deletions

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe.fragments.list.channel; package org.schabi.newpipe.fragments.list.channel;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -14,6 +15,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.database.subscription.NotificationMode;
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
import org.schabi.newpipe.databinding.FragmentChannelBinding; import org.schabi.newpipe.databinding.FragmentChannelBinding;
import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.error.UserAction;
@ -21,14 +24,21 @@ import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.linkhandler.ChannelTabHandler; import org.schabi.newpipe.extractor.linkhandler.ChannelTabHandler;
import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.fragments.detail.TabAdapter; import org.schabi.newpipe.fragments.detail.TabAdapter;
import org.schabi.newpipe.local.feed.notifications.NotificationHelper;
import org.schabi.newpipe.local.subscription.SubscriptionManager;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.List;
import icepick.State; import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
public class ChannelFragment extends BaseStateFragment<ChannelInfo> { public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
@ -41,8 +51,12 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
private ChannelInfo currentInfo; private ChannelInfo currentInfo;
private Disposable currentWorker; private Disposable currentWorker;
private Disposable subscriptionMonitor;
private final CompositeDisposable disposables = new CompositeDisposable();
private SubscriptionManager subscriptionManager;
private MenuItem menuRssButton; private MenuItem menuRssButton;
private MenuItem menuNotifyButton;
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Views // Views
@ -78,6 +92,12 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
setHasOptionsMenu(true); setHasOptionsMenu(true);
} }
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
subscriptionManager = new SubscriptionManager(activity);
}
@Override @Override
public View onCreateView(@NonNull final LayoutInflater inflater, public View onCreateView(@NonNull final LayoutInflater inflater,
@Nullable final ViewGroup container, @Nullable final ViewGroup container,
@ -98,6 +118,13 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
if (currentWorker != null) {
currentWorker.dispose();
}
if (subscriptionMonitor != null) {
subscriptionMonitor.dispose();
}
disposables.clear();
binding = null; binding = null;
} }
@ -116,12 +143,19 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
+ "menu = [" + menu + "], inflater = [" + inflater + "]"); + "menu = [" + menu + "], inflater = [" + inflater + "]");
} }
menuRssButton = menu.findItem(R.id.menu_item_rss); menuRssButton = menu.findItem(R.id.menu_item_rss);
menuNotifyButton = menu.findItem(R.id.menu_item_notify);
updateRssButton(); updateRssButton();
monitorSubscription();
} }
@Override @Override
public boolean onOptionsItemSelected(final MenuItem item) { public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.menu_item_notify:
final boolean value = !item.isChecked();
item.setEnabled(false);
setNotify(value);
break;
case R.id.action_settings: case R.id.action_settings:
NavigationHelper.openSettings(requireContext()); NavigationHelper.openSettings(requireContext());
break; break;
@ -153,6 +187,62 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
} }
} }
private void monitorSubscription() {
if (currentInfo != null) {
final Observable<List<SubscriptionEntity>> observable = subscriptionManager
.subscriptionTable()
.getSubscriptionFlowable(currentInfo.getServiceId(), currentInfo.getUrl())
.toObservable();
if (subscriptionMonitor != null) {
subscriptionMonitor.dispose();
}
subscriptionMonitor = observable
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSubscribeUpdateMonitor());
}
}
private Consumer<List<SubscriptionEntity>> getSubscribeUpdateMonitor() {
return (List<SubscriptionEntity> subscriptionEntities) -> {
if (subscriptionEntities.isEmpty()) {
updateNotifyButton(null);
} else {
final SubscriptionEntity subscription = subscriptionEntities.get(0);
updateNotifyButton(subscription);
}
};
}
private void updateNotifyButton(@Nullable final SubscriptionEntity subscription) {
if (menuNotifyButton == null) {
return;
}
if (subscription != null) {
menuNotifyButton.setEnabled(
NotificationHelper.areNewStreamsNotificationsEnabled(requireContext())
);
menuNotifyButton.setChecked(
subscription.getNotificationMode() == NotificationMode.ENABLED
);
}
menuNotifyButton.setVisible(subscription != null);
}
private void setNotify(final boolean isEnabled) {
disposables.add(
subscriptionManager
.updateNotificationMode(
currentInfo.getServiceId(),
currentInfo.getUrl(),
isEnabled ? NotificationMode.ENABLED : NotificationMode.DISABLED)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
);
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Init // Init
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -213,5 +303,6 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo> {
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName()); setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
updateTabs(); updateTabs();
updateRssButton(); updateRssButton();
monitorSubscription();
} }
} }

View File

@ -2,6 +2,8 @@ package org.schabi.newpipe.fragments.list.channel;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -45,6 +47,12 @@ public class ChannelTabFragment extends BaseListInfoFragment<InfoItem, ChannelTa
// LifeCycle // LifeCycle
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
@Override @Override
public View onCreateView(@NonNull final LayoutInflater inflater, public View onCreateView(@NonNull final LayoutInflater inflater,
@Nullable final ViewGroup container, @Nullable final ViewGroup container,

View File

@ -11,16 +11,12 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
@ -51,7 +47,6 @@ import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -89,8 +84,6 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
private ChannelHeaderBinding headerBinding; private ChannelHeaderBinding headerBinding;
private PlaylistControlBinding playlistControlBinding; private PlaylistControlBinding playlistControlBinding;
private MenuItem menuNotifyButton;
public static ChannelVideosFragment getInstance(@NonNull final ChannelInfo channelInfo) { public static ChannelVideosFragment getInstance(@NonNull final ChannelInfo channelInfo) {
final ChannelVideosFragment instance = new ChannelVideosFragment(); final ChannelVideosFragment instance = new ChannelVideosFragment();
instance.setInitialData(channelInfo.getServiceId(), channelInfo.getUrl(), instance.setInitialData(channelInfo.getServiceId(), channelInfo.getUrl(),
@ -123,6 +116,12 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
// LifeCycle // LifeCycle
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
@Override @Override
public void onAttach(@NonNull final Context context) { public void onAttach(@NonNull final Context context) {
super.onAttach(context); super.onAttach(context);
@ -176,71 +175,6 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
headerBinding.subChannelAvatarView.setOnClickListener(this); headerBinding.subChannelAvatarView.setOnClickListener(this);
} }
/*//////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onCreateOptionsMenu(@NonNull final Menu menu,
@NonNull final MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
final ActionBar supportActionBar = activity.getSupportActionBar();
if (useAsFrontPage && supportActionBar != null) {
supportActionBar.setDisplayHomeAsUpEnabled(false);
} else {
inflater.inflate(R.menu.menu_channel_videos, menu);
if (DEBUG) {
Log.d(TAG, "onCreateOptionsMenu() called with: "
+ "menu = [" + menu + "], inflater = [" + inflater + "]");
}
menuNotifyButton = menu.findItem(R.id.menu_item_notify);
}
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_notify:
final boolean value = !item.isChecked();
item.setEnabled(false);
setNotify(value);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private void updateNotifyButton(@Nullable final SubscriptionEntity subscription) {
if (menuNotifyButton == null) {
return;
}
if (subscription != null) {
menuNotifyButton.setEnabled(
NotificationHelper.areNewStreamsNotificationsEnabled(requireContext())
);
menuNotifyButton.setChecked(
subscription.getNotificationMode() == NotificationMode.ENABLED
);
}
menuNotifyButton.setVisible(subscription != null);
}
private void setNotify(final boolean isEnabled) {
disposables.add(
subscriptionManager
.updateNotificationMode(
currentInfo.getServiceId(),
currentInfo.getUrl(),
isEnabled ? NotificationMode.ENABLED : NotificationMode.DISABLED)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
);
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Channel Subscription // Channel Subscription
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -357,7 +291,6 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
info.getAvatarUrl(), info.getAvatarUrl(),
info.getDescription(), info.getDescription(),
info.getSubscriberCount()); info.getSubscriberCount());
updateNotifyButton(null);
subscribeButtonMonitor = monitorSubscribeButton( subscribeButtonMonitor = monitorSubscribeButton(
headerBinding.channelSubscribeButton, mapOnSubscribe(channel, info)); headerBinding.channelSubscribeButton, mapOnSubscribe(channel, info));
} else { } else {
@ -365,7 +298,6 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
Log.d(TAG, "Found subscription to this channel!"); Log.d(TAG, "Found subscription to this channel!");
} }
final SubscriptionEntity subscription = subscriptionEntities.get(0); final SubscriptionEntity subscription = subscriptionEntities.get(0);
updateNotifyButton(subscription);
subscribeButtonMonitor = monitorSubscribeButton( subscribeButtonMonitor = monitorSubscribeButton(
headerBinding.channelSubscribeButton, mapOnUnsubscribe(subscription)); headerBinding.channelSubscribeButton, mapOnUnsubscribe(subscription));
} }
@ -418,6 +350,19 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
.show(); .show();
} }
private void setNotify(final boolean isEnabled) {
disposables.add(
subscriptionManager
.updateNotificationMode(
currentInfo.getServiceId(),
currentInfo.getUrl(),
isEnabled ? NotificationMode.ENABLED : NotificationMode.DISABLED)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
);
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Load and handle // Load and handle
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -502,8 +447,6 @@ public class ChannelVideosFragment extends BaseListInfoFragment<StreamInfoItem,
headerBinding.subChannelTitleView.setVisibility(View.GONE); headerBinding.subChannelTitleView.setVisibility(View.GONE);
} }
// updateRssButton();
// PlaylistControls should be visible only if there is some item in // PlaylistControls should be visible only if there is some item in
// infoListAdapter other than header // infoListAdapter other than header
if (infoListAdapter.getItemCount() != 1) { if (infoListAdapter.getItemCount() != 1) {

View File

@ -1,14 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".fragments.list.impl.ChannelFragment">
<item
android:id="@+id/menu_item_notify"
android:checkable="true"
android:orderInCategory="1"
android:title="@string/get_notified"
android:visible="false"
app:showAsAction="never"
tools:visible="true" />
</menu>