2222import org .schabi .newpipe .NewPipeDatabase ;
2323import org .schabi .newpipe .R ;
2424import org .schabi .newpipe .database .AppDatabase ;
25+ import org .schabi .newpipe .database .history .model .StreamHistoryEntry ;
2526import org .schabi .newpipe .database .playlist .PlaylistMetadataEntry ;
2627import org .schabi .newpipe .database .playlist .PlaylistStreamEntry ;
2728import org .schabi .newpipe .local .playlist .LocalPlaylistManager ;
@@ -64,6 +65,10 @@ public void release() {
6465 private static final String ID_ROOT = "//${BuildConfig.APPLICATION_ID}/r" ;
6566 @ NonNull
6667 private static final String ID_BOOKMARKS = ID_ROOT + "/playlists" ;
68+ @ NonNull
69+ private static final String ID_HISTORY = ID_ROOT + "/history" ;
70+ @ NonNull
71+ private static final String ID_STREAM = ID_ROOT + "/stream" ;
6772
6873 private MediaItem createRootMediaItem (final String mediaId , final String folderName ) {
6974 final var builder = new MediaDescriptionCompat .Builder ();
@@ -130,7 +135,9 @@ public void onLoadChildren(@NonNull final String parentId,
130135 mediaItems .add (
131136 createRootMediaItem (ID_BOOKMARKS ,
132137 playerService .getResources ().getString (R .string .tab_bookmarks )));
133-
138+ mediaItems .add (
139+ createRootMediaItem (ID_HISTORY ,
140+ playerService .getResources ().getString (R .string .action_history )));
134141 } else if (parentId .startsWith (ID_BOOKMARKS )) {
135142 final var path = parentIdUri .getPathSegments ();
136143 if (path .size () == 2 ) {
@@ -141,16 +148,38 @@ public void onLoadChildren(@NonNull final String parentId,
141148 } else {
142149 Log .w (TAG , "Unknown playlist uri " + parentId );
143150 }
151+ } else if (parentId .equals (ID_HISTORY )) {
152+ populateHistory (mediaItems );
144153 }
145154 result .sendResult (mediaItems );
146155 }
147156
148- private LocalPlaylistManager getPlaylistManager () {
157+ private void populateHistory (final List <MediaItem > mediaItems ) {
158+ final var streamHistory = getDatabase ().streamHistoryDAO ();
159+ final var history = streamHistory .getHistory ().blockingFirst ();
160+ mediaItems .addAll (history .stream ().map (this ::createHistoryMediaItem )
161+ .collect (Collectors .toList ()));
162+ }
163+
164+ private MediaItem createHistoryMediaItem (@ NonNull final StreamHistoryEntry streamHistoryEntry ) {
165+ final var builder = new MediaDescriptionCompat .Builder ();
166+ builder .setMediaId (ID_STREAM + '/' + streamHistoryEntry .getStreamId ())
167+ .setTitle (streamHistoryEntry .getStreamEntity ().getTitle ())
168+ .setIconUri (Uri .parse (streamHistoryEntry .getStreamEntity ().getThumbnailUrl ()));
169+
170+ return new MediaItem (builder .build (), MediaItem .FLAG_PLAYABLE );
171+ }
172+
173+ private AppDatabase getDatabase () {
149174 if (database == null ) {
150175 database = NewPipeDatabase .getInstance (playerService );
151176 }
177+ return database ;
178+ }
179+
180+ private LocalPlaylistManager getPlaylistManager () {
152181 if (localPlaylistManager == null ) {
153- localPlaylistManager = new LocalPlaylistManager (database );
182+ localPlaylistManager = new LocalPlaylistManager (getDatabase () );
154183 }
155184 return localPlaylistManager ;
156185 }
@@ -202,6 +231,15 @@ private PlayQueue extractPlayQueueFromMediaId(final String mediaId) {
202231
203232 return new SinglePlayQueue (items , index );
204233 }
234+ } else if (mediaId .startsWith (ID_STREAM )) {
235+ final var path = mediaIdUri .getPathSegments ();
236+ if (path .size () == 3 ) {
237+ final long streamId = Long .parseLong (path .get (2 ));
238+ final var items = getDatabase ().streamHistoryDAO ().getHistory ()
239+ .blockingFirst ().stream ().filter (it -> it .getStreamId () == streamId )
240+ .map (StreamHistoryEntry ::toStreamInfoItem ).collect (Collectors .toList ());
241+ return new SinglePlayQueue (items , 0 );
242+ }
205243 }
206244
207245 playbackError (R .string .error_http_not_found ,
0 commit comments