Skip to content

Commit a0e8b2e

Browse files
Use contrast background for history date headers
1 parent 515bb6e commit a0e8b2e

6 files changed

Lines changed: 99 additions & 10 deletions

File tree

app/src/main/java/org/schabi/newpipe/database/LocalItem.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ interface LocalItem {
1414
PLAYLIST_REMOTE_ITEM,
1515

1616
PLAYLIST_STREAM_ITEM,
17-
STATISTIC_STREAM_ITEM
17+
STATISTIC_STREAM_ITEM,
18+
19+
DATE_HEADER
1820
}
1921
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.schabi.newpipe.database.history.model
2+
3+
import java.time.LocalDate
4+
import org.schabi.newpipe.database.LocalItem
5+
6+
data class DateHeaderItem(
7+
val date: LocalDate
8+
) : LocalItem {
9+
override val localItemType: LocalItem.LocalItemType
10+
get() = LocalItem.LocalItemType.DATE_HEADER
11+
}

app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@
22

33
import android.content.Context;
44
import android.util.Log;
5+
import android.view.LayoutInflater;
56
import android.view.View;
67
import android.view.ViewGroup;
8+
import android.widget.TextView;
79

810
import androidx.annotation.NonNull;
911
import androidx.annotation.Nullable;
1012
import androidx.recyclerview.widget.GridLayoutManager;
1113
import androidx.recyclerview.widget.RecyclerView;
1214

15+
import org.schabi.newpipe.R;
1316
import org.schabi.newpipe.database.LocalItem;
17+
import org.schabi.newpipe.database.history.model.DateHeaderItem;
1418
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
1519
import org.schabi.newpipe.info_list.ItemViewMode;
1620
import org.schabi.newpipe.local.history.HistoryRecordManager;
@@ -66,6 +70,8 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
6670
private static final int HEADER_TYPE = 0;
6771
private static final int FOOTER_TYPE = 1;
6872

73+
private static final int DATE_HEADER_HOLDER_TYPE = 0x4000;
74+
6975
private static final int STREAM_STATISTICS_HOLDER_TYPE = 0x1000;
7076
private static final int STREAM_PLAYLIST_HOLDER_TYPE = 0x1001;
7177
private static final int STREAM_STATISTICS_GRID_HOLDER_TYPE = 0x1002;
@@ -311,6 +317,8 @@ public int getItemViewType(int position) {
311317
} else {
312318
return STREAM_STATISTICS_HOLDER_TYPE;
313319
}
320+
case DATE_HEADER:
321+
return DATE_HEADER_HOLDER_TYPE;
314322
default:
315323
Log.e(TAG, "No holder type has been considered for item: ["
316324
+ item.getLocalItemType() + "]");
@@ -331,6 +339,9 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup paren
331339
return new HeaderFooterHolder(headerSupplier.get());
332340
case FOOTER_TYPE:
333341
return new HeaderFooterHolder(footer);
342+
case DATE_HEADER_HOLDER_TYPE:
343+
return new DateHeaderHolder(LayoutInflater.from(parent.getContext())
344+
.inflate(R.layout.list_date_header_item, parent, false));
334345
case LOCAL_PLAYLIST_HOLDER_TYPE:
335346
return new LocalPlaylistItemHolder(localItemBuilder, parent);
336347
case LOCAL_PLAYLIST_GRID_HOLDER_TYPE:
@@ -374,7 +385,18 @@ public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int
374385
+ "position = [" + position + "]");
375386
}
376387

377-
if (holder instanceof LocalItemHolder) {
388+
if (holder instanceof DateHeaderHolder) {
389+
// If header isn't null, offset the items by -1
390+
if (hasHeader()) {
391+
position--;
392+
}
393+
394+
final LocalItem localItem = localItems.get(position);
395+
if (localItem instanceof DateHeaderItem) {
396+
((DateHeaderHolder) holder).dateHeaderText.setText(
397+
dateTimeFormatter.format(((DateHeaderItem) localItem).getDate()));
398+
}
399+
} else if (holder instanceof LocalItemHolder) {
378400
// If header isn't null, offset the items by -1
379401
if (hasHeader()) {
380402
position--;
@@ -408,12 +430,23 @@ public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, fina
408430
}
409431
}
410432

433+
private static class DateHeaderHolder extends RecyclerView.ViewHolder {
434+
private final TextView dateHeaderText;
435+
436+
DateHeaderHolder(@NonNull final View itemView) {
437+
super(itemView);
438+
dateHeaderText = itemView.findViewById(R.id.dateHeaderText);
439+
}
440+
}
441+
442+
411443
public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) {
412444
return new GridLayoutManager.SpanSizeLookup() {
413445
@Override
414446
public int getSpanSize(final int position) {
415447
final int type = getItemViewType(position);
416-
return type == HEADER_TYPE || type == FOOTER_TYPE ? spanCount : 1;
448+
return type == HEADER_TYPE || type == FOOTER_TYPE
449+
|| type == DATE_HEADER_HOLDER_TYPE ? spanCount : 1;
417450
}
418451
};
419452
}

app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.reactivestreams.Subscription;
2222
import org.schabi.newpipe.R;
2323
import org.schabi.newpipe.database.LocalItem;
24+
import org.schabi.newpipe.database.history.model.DateHeaderItem;
2425
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
2526
import org.schabi.newpipe.database.stream.model.StreamEntity;
2627
import org.schabi.newpipe.databinding.PlaylistControlBinding;
@@ -39,6 +40,7 @@
3940
import org.schabi.newpipe.util.OnClickGesture;
4041
import org.schabi.newpipe.util.PlayButtonHelper;
4142

43+
import java.time.LocalDate;
4244
import java.util.ArrayList;
4345
import java.util.Collections;
4446
import java.util.Comparator;
@@ -65,7 +67,7 @@ public class StatisticsPlaylistFragment
6567
private Subscription databaseSubscription;
6668
private HistoryRecordManager recordManager;
6769

68-
private List<StreamStatisticsEntry> processResult(final List<StreamStatisticsEntry> results) {
70+
private List<LocalItem> processResult(final List<StreamStatisticsEntry> results) {
6971
final Comparator<StreamStatisticsEntry> comparator;
7072
switch (sortMode) {
7173
case LAST_PLAYED:
@@ -77,8 +79,26 @@ private List<StreamStatisticsEntry> processResult(final List<StreamStatisticsEnt
7779
default:
7880
return null;
7981
}
82+
8083
Collections.sort(results, comparator.reversed());
81-
return results;
84+
85+
if (sortMode == StatisticSortMode.MOST_PLAYED) {
86+
return new ArrayList<>(results);
87+
}
88+
89+
final List<LocalItem> itemsWithHeaders = new ArrayList<>(results.size());
90+
LocalDate lastDate = null;
91+
92+
for (final StreamStatisticsEntry entry : results) {
93+
final LocalDate entryDate = entry.getLatestAccessDate().toLocalDate();
94+
if (!entryDate.equals(lastDate)) {
95+
itemsWithHeaders.add(new DateHeaderItem(entryDate));
96+
lastDate = entryDate;
97+
}
98+
itemsWithHeaders.add(entry);
99+
}
100+
101+
return itemsWithHeaders;
82102
}
83103

84104
///////////////////////////////////////////////////////////////////////////
@@ -314,7 +334,22 @@ private void toggleSortMode() {
314334
}
315335

316336
private PlayQueue getPlayQueueStartingAt(final StreamStatisticsEntry infoItem) {
317-
return getPlayQueue(Math.max(itemListAdapter.getItemsList().indexOf(infoItem), 0));
337+
if (itemListAdapter == null) {
338+
return new SinglePlayQueue(Collections.emptyList(), 0);
339+
}
340+
341+
final List<LocalItem> items = itemListAdapter.getItemsList();
342+
int streamIndex = 0;
343+
for (final LocalItem item : items) {
344+
if (item == infoItem) {
345+
break;
346+
}
347+
if (item instanceof StreamStatisticsEntry) {
348+
streamIndex++;
349+
}
350+
}
351+
352+
return getPlayQueue(streamIndex);
318353
}
319354

320355
private void showInfoItemDialog(final StreamStatisticsEntry item) {

app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,10 @@ public LocalStatisticStreamItemHolder(final LocalItemBuilder itemBuilder,
6969
itemProgressView = itemView.findViewById(R.id.itemProgressView);
7070
}
7171

72-
private String getStreamInfoDetailLine(final StreamStatisticsEntry entry,
73-
final DateTimeFormatter dateTimeFormatter) {
72+
private String getStreamInfoDetailLine(final StreamStatisticsEntry entry) {
7473
return Localization.concatenateStrings(
7574
// watchCount
7675
Localization.shortViewCount(itemBuilder.getContext(), entry.getWatchCount()),
77-
dateTimeFormatter.format(entry.getLatestAccessDate()),
7876
// serviceName
7977
ServiceHelper.getNameOfServiceById(entry.getStreamEntity().getServiceId()));
8078
}
@@ -113,7 +111,7 @@ public void updateFromItem(final LocalItem localItem,
113111
}
114112

115113
if (itemAdditionalDetails != null) {
116-
itemAdditionalDetails.setText(getStreamInfoDetailLine(item, dateTimeFormatter));
114+
itemAdditionalDetails.setText(getStreamInfoDetailLine(item));
117115
}
118116

119117
// Default thumbnail is shown on error, while loading and if the url is empty
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:id="@+id/dateHeaderText"
4+
android:layout_width="match_parent"
5+
android:layout_height="wrap_content"
6+
android:background="?attr/contrast_background_color"
7+
android:paddingHorizontal="16dp"
8+
android:paddingVertical="12dp"
9+
android:textAppearance="?android:attr/textAppearanceMedium"
10+
android:textStyle="bold" />

0 commit comments

Comments
 (0)