Merge branch 'develop' into add-feed-no-subscribe

This commit is contained in:
ByteHamster 2024-04-19 18:46:07 +02:00
commit a424ca3219
6 changed files with 75 additions and 41 deletions

View File

@ -43,8 +43,8 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
private final View container;
public final ImageView dragHandle;
private final TextView placeholder;
private final ImageView cover;
public final TextView placeholder;
public final ImageView cover;
private final TextView title;
private final TextView pubDate;
private final TextView position;

View File

@ -6,7 +6,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Pair;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
@ -75,7 +74,8 @@ public class SearchFragment extends Fragment implements EpisodeItemListAdapter.O
private EpisodeItemListAdapter adapter;
private HorizontalFeedListAdapter adapterFeeds;
private Disposable disposable;
private Disposable disposableFeeds;
private Disposable disposableEpisodes;
private ProgressBar progressBar;
private EmptyViewHandler emptyViewHandler;
private EpisodeItemListRecyclerView recyclerView;
@ -127,8 +127,11 @@ public class SearchFragment extends Fragment implements EpisodeItemListAdapter.O
@Override
public void onStop() {
super.onStop();
if (disposable != null) {
disposable.dispose();
if (disposableFeeds != null) {
disposableFeeds.dispose();
}
if (disposableEpisodes != null) {
disposableEpisodes.dispose();
}
}
@ -373,44 +376,45 @@ public class SearchFragment extends Fragment implements EpisodeItemListAdapter.O
}
private void search() {
if (disposable != null) {
disposable.dispose();
if (disposableFeeds != null) {
disposableFeeds.dispose();
}
if (disposableEpisodes != null) {
disposableEpisodes.dispose();
}
adapterFeeds.setEndButton(R.string.search_online, this::searchOnline);
chip.setVisibility((getArguments().getLong(ARG_FEED, 0) == 0) ? View.GONE : View.VISIBLE);
disposable = Observable.fromCallable(this::performSearch)
long feed = getArguments().getLong(ARG_FEED, 0);
chip.setVisibility((feed == 0) ? View.GONE : View.VISIBLE);
String query = searchView.getQuery().toString();
if (query.isEmpty()) {
emptyViewHandler.setMessage(R.string.type_to_search);
return;
}
if (feed != 0) {
// Search within a feed
adapterFeeds.updateData(Collections.emptyList());
} else {
disposableFeeds = Observable.fromCallable(() -> DBReader.searchFeeds(query))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(results -> {
progressBar.setVisibility(View.GONE);
adapterFeeds.updateData(results);
emptyViewHandler.setMessage(getString(R.string.no_results_for_query, query));
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
disposableEpisodes = Observable.fromCallable(() -> DBReader.searchFeedItems(feed, query))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(results -> {
progressBar.setVisibility(View.GONE);
this.results = results.first;
adapter.updateItems(results.first);
if (getArguments().getLong(ARG_FEED, 0) == 0) {
adapterFeeds.updateData(results.second);
} else {
adapterFeeds.updateData(Collections.emptyList());
}
if (searchView.getQuery().toString().isEmpty()) {
emptyViewHandler.setMessage(R.string.type_to_search);
} else {
emptyViewHandler.setMessage(getString(R.string.no_results_for_query, searchView.getQuery()));
}
this.results = results;
adapter.updateItems(results);
emptyViewHandler.setMessage(getString(R.string.no_results_for_query, searchView.getQuery()));
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
@NonNull
private Pair<List<FeedItem>, List<Feed>> performSearch() {
String query = searchView.getQuery().toString();
if (query.isEmpty()) {
return new Pair<>(Collections.emptyList(), Collections.emptyList());
}
long feed = getArguments().getLong(ARG_FEED);
List<FeedItem> items = DBReader.searchFeedItems(feed, query);
List<Feed> feeds = DBReader.searchFeeds(query);
return new Pair<>(items, feeds);
}
private void showInputMethod(View view) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {

View File

@ -46,6 +46,7 @@ import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.ui.CoverLoader;
import de.danoeh.antennapod.ui.FeedItemFilterDialog;
import de.danoeh.antennapod.ui.MenuItemUtils;
import de.danoeh.antennapod.ui.TransitionEffect;
@ -70,16 +71,15 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Displays a list of FeedItems.
*/
@ -660,7 +660,18 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
@Override
protected void beforeBindViewHolder(EpisodeItemViewHolder holder, int pos) {
holder.coverHolder.setVisibility(View.GONE);
holder.coverHolder.setVisibility(View.GONE); // Load it ourselves
}
@Override
protected void afterBindViewHolder(EpisodeItemViewHolder holder, int pos) {
holder.coverHolder.setVisibility(View.VISIBLE);
new CoverLoader()
.withUri(holder.getFeedItem().getImageLocation()) // Ignore "Show episode cover" setting
.withFallbackUri(holder.getFeedItem().getFeed().getImageUrl())
.withPlaceholderView(holder.placeholder)
.withCoverView(holder.cover)
.load();
}
@Override

View File

@ -16,6 +16,8 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -148,7 +150,7 @@ public class NextcloudSyncService implements ISyncService {
.scheme(hostname.scheme)
.host(hostname.host)
.port(hostname.port)
.addPathSegments(hostname.subfolder + path);
.addPathSegments(StringUtils.stripStart(hostname.subfolder + path, "/"));
}
@Override

View File

@ -26,6 +26,7 @@ dependencies {
implementation project(':ui:chapters')
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
implementation "androidx.car.app:app:1.4.0-rc02"
implementation "androidx.core:core:$coreVersion"
implementation "androidx.appcompat:appcompat:$appcompatVersion"
implementation "androidx.media:media:$mediaVersion"

View File

@ -45,9 +45,12 @@ import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.car.app.connection.CarConnection;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.media.MediaBrowserServiceCompat;
import de.danoeh.antennapod.event.PlayerStatusEvent;
@ -170,6 +173,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private MediaSessionCompat mediaSession;
private static volatile MediaType currentMediaType = MediaType.UNKNOWN;
private LiveData<Integer> androidAutoConnectionState;
private boolean androidAutoConnected = false;
private Observer<Integer> androidAutoConnectionObserver;
private final IBinder mBinder = new LocalBinder();
@ -226,6 +232,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
stateManager = new PlaybackServiceStateManager(this);
notificationBuilder = new PlaybackServiceNotificationBuilder(this);
androidAutoConnectionState = new CarConnection(this).getType();
androidAutoConnectionObserver = connectionState -> {
androidAutoConnected = connectionState == CarConnection.CONNECTION_TYPE_PROJECTION;
};
androidAutoConnectionState.observeForever(androidAutoConnectionObserver);
ContextCompat.registerReceiver(this, autoStateUpdated,
new IntentFilter("com.google.android.gms.car.media.STATUS"), ContextCompat.RECEIVER_EXPORTED);
@ -318,6 +329,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
currentMediaType = MediaType.UNKNOWN;
castStateListener.destroy();
androidAutoConnectionState.removeObserver(androidAutoConnectionObserver);
cancelPositionObserver();
if (mediaSession != null) {
mediaSession.release();
@ -862,6 +874,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
int currentHour = now.get(Calendar.HOUR_OF_DAY);
autoEnableByTime = SleepTimerPreferences.isInTimeRange(fromSetting, toSetting, currentHour);
}
if (androidAutoConnected) {
Log.i(TAG, "Android Auto is connected, sleep timer will not be auto-enabled");
autoEnableByTime = false;
}
if (newInfo.getOldPlayerStatus() != null && newInfo.getOldPlayerStatus() != PlayerStatus.SEEKING
&& SleepTimerPreferences.autoEnable() && autoEnableByTime && !sleepTimerActive()) {