mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Merge pull request #2517 from Stypox/list-slowdown-fix
List slowdown fix
This commit is contained in:
		| @@ -64,7 +64,6 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onDetach() { |     public void onDetach() { | ||||||
|         infoListAdapter.dispose(); |  | ||||||
|         super.onDetach(); |         super.onDetach(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -97,8 +96,6 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem | |||||||
|             } |             } | ||||||
|             updateFlags = 0; |             updateFlags = 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         itemsList.post(infoListAdapter::updateStates); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /*////////////////////////////////////////////////////////////////////////// |     /*////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -2,14 +2,11 @@ package org.schabi.newpipe.info_list; | |||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.util.Log; |  | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
|  |  | ||||||
| import com.nostra13.universalimageloader.core.ImageLoader; | import com.nostra13.universalimageloader.core.ImageLoader; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | ||||||
| import org.schabi.newpipe.extractor.comments.CommentsInfoItem; | import org.schabi.newpipe.extractor.comments.CommentsInfoItem; | ||||||
| @@ -24,6 +21,7 @@ import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder; | |||||||
| import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; | import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; | ||||||
| import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; | import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; | ||||||
| import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; | import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.OnClickGesture; | import org.schabi.newpipe.util.OnClickGesture; | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -61,14 +59,14 @@ public class InfoItemBuilder { | |||||||
|         this.context = context; |         this.context = context; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, @Nullable StreamStateEntity state) { |     public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         return buildView(parent, infoItem, state, false); |         return buildView(parent, infoItem, historyRecordManager, false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, |     public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, | ||||||
|                           @Nullable StreamStateEntity state, boolean useMiniVariant) { |                           final HistoryRecordManager historyRecordManager, boolean useMiniVariant) { | ||||||
|         InfoItemHolder holder = holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant); |         InfoItemHolder holder = holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant); | ||||||
|         holder.updateFromItem(infoItem, state); |         holder.updateFromItem(infoItem, historyRecordManager); | ||||||
|         return holder.itemView; |         return holder.itemView; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -83,7 +81,6 @@ public class InfoItemBuilder { | |||||||
|             case COMMENT: |             case COMMENT: | ||||||
|                 return useMiniVariant ? new CommentsMiniInfoItemHolder(this, parent) : new CommentsInfoItemHolder(this, parent); |                 return useMiniVariant ? new CommentsMiniInfoItemHolder(this, parent) : new CommentsInfoItemHolder(this, parent); | ||||||
|             default: |             default: | ||||||
|                 Log.e(TAG, "Trollolo"); |  | ||||||
|                 throw new RuntimeException("InfoType not expected = " + infoType.name()); |                 throw new RuntimeException("InfoType not expected = " + infoType.name()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| package org.schabi.newpipe.info_list; | package org.schabi.newpipe.info_list; | ||||||
|  |  | ||||||
| import android.app.Activity; | import android.content.Context; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.support.annotation.Nullable; | import android.support.annotation.Nullable; | ||||||
| import android.support.v7.widget.GridLayoutManager; | import android.support.v7.widget.GridLayoutManager; | ||||||
| @@ -27,6 +27,7 @@ import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; | |||||||
| import org.schabi.newpipe.info_list.holder.StreamGridInfoItemHolder; | import org.schabi.newpipe.info_list.holder.StreamGridInfoItemHolder; | ||||||
| import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; | import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; | ||||||
| import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; | import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.FallbackViewHolder; | import org.schabi.newpipe.util.FallbackViewHolder; | ||||||
| import org.schabi.newpipe.util.OnClickGesture; | import org.schabi.newpipe.util.OnClickGesture; | ||||||
|  |  | ||||||
| @@ -53,7 +54,7 @@ import java.util.List; | |||||||
|  * along with NewPipe.  If not, see <http://www.gnu.org/licenses/>. |  * along with NewPipe.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| public class InfoListAdapter extends StateObjectsListAdapter { | public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { | ||||||
|     private static final String TAG = InfoListAdapter.class.getSimpleName(); |     private static final String TAG = InfoListAdapter.class.getSimpleName(); | ||||||
|     private static final boolean DEBUG = false; |     private static final boolean DEBUG = false; | ||||||
|  |  | ||||||
| @@ -74,6 +75,8 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|  |  | ||||||
|     private final InfoItemBuilder infoItemBuilder; |     private final InfoItemBuilder infoItemBuilder; | ||||||
|     private final ArrayList<InfoItem> infoItemList; |     private final ArrayList<InfoItem> infoItemList; | ||||||
|  |     private final HistoryRecordManager recordManager; | ||||||
|  |  | ||||||
|     private boolean useMiniVariant = false; |     private boolean useMiniVariant = false; | ||||||
|     private boolean useGridVariant = false; |     private boolean useGridVariant = false; | ||||||
|     private boolean showFooter = false; |     private boolean showFooter = false; | ||||||
| @@ -89,9 +92,9 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public InfoListAdapter(Activity a) { |     public InfoListAdapter(Context context) { | ||||||
|         super(a.getApplicationContext()); |         this.recordManager = new HistoryRecordManager(context); | ||||||
|         infoItemBuilder = new InfoItemBuilder(a); |         infoItemBuilder = new InfoItemBuilder(context); | ||||||
|         infoItemList = new ArrayList<>(); |         infoItemList = new ArrayList<>(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -120,63 +123,52 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void addInfoItemList(@Nullable final List<InfoItem> data) { |     public void addInfoItemList(@Nullable final List<InfoItem> data) { | ||||||
|         if (data != null) { |         if (data == null) { | ||||||
|             loadStates(data, infoItemList.size(), () -> addInfoItemListImpl(data)); |             return; | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void addInfoItemListImpl(@NonNull List<InfoItem> data) { |  | ||||||
|         if (DEBUG) { |  | ||||||
|             Log.d(TAG, "addInfoItemList() before > infoItemList.size() = " + infoItemList.size() + ", data.size() = " + data.size()); |  | ||||||
|         } |         } | ||||||
|  |         if (DEBUG) Log.d(TAG, "addInfoItemList() before > infoItemList.size() = " + | ||||||
|  |                 infoItemList.size() + ", data.size() = " + data.size()); | ||||||
|  |  | ||||||
|         int offsetStart = sizeConsideringHeaderOffset(); |         int offsetStart = sizeConsideringHeaderOffset(); | ||||||
|         infoItemList.addAll(data); |         infoItemList.addAll(data); | ||||||
|  |  | ||||||
|         if (DEBUG) { |         if (DEBUG) Log.d(TAG, "addInfoItemList() after > offsetStart = " + offsetStart + | ||||||
|             Log.d(TAG, "addInfoItemList() after > offsetStart = " + offsetStart + ", infoItemList.size() = " + infoItemList.size() + ", header = " + header + ", footer = " + footer + ", showFooter = " + showFooter); |                 ", infoItemList.size() = " + infoItemList.size() + | ||||||
|         } |                 ", header = " + header + ", footer = " + footer + | ||||||
|  |                 ", showFooter = " + showFooter); | ||||||
|         notifyItemRangeInserted(offsetStart, data.size()); |         notifyItemRangeInserted(offsetStart, data.size()); | ||||||
|  |  | ||||||
|         if (footer != null && showFooter) { |         if (footer != null && showFooter) { | ||||||
|             int footerNow = sizeConsideringHeaderOffset(); |             int footerNow = sizeConsideringHeaderOffset(); | ||||||
|             notifyItemMoved(offsetStart, footerNow); |             notifyItemMoved(offsetStart, footerNow); | ||||||
|  |  | ||||||
|             if (DEBUG) Log.d(TAG, "addInfoItemList() footer from " + offsetStart + " to " + footerNow); |             if (DEBUG) Log.d(TAG, "addInfoItemList() footer from " + offsetStart + | ||||||
|  |                     " to " + footerNow); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void addInfoItem(@Nullable InfoItem data) { |     public void addInfoItem(@Nullable InfoItem data) { | ||||||
|         if (data != null) { |         if (data == null) { | ||||||
|             loadState(data, infoItemList.size(), () -> addInfoItemImpl(data)); |             return; | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void addInfoItemImpl(@NonNull InfoItem data) { |  | ||||||
|         if (DEBUG) { |  | ||||||
|             Log.d(TAG, "addInfoItem() before > infoItemList.size() = " + infoItemList.size() + ", thread = " + Thread.currentThread()); |  | ||||||
|         } |         } | ||||||
|  |         if (DEBUG) Log.d(TAG, "addInfoItem() before > infoItemList.size() = " + | ||||||
|  |                 infoItemList.size() + ", thread = " + Thread.currentThread()); | ||||||
|  |  | ||||||
|         int positionInserted = sizeConsideringHeaderOffset(); |         int positionInserted = sizeConsideringHeaderOffset(); | ||||||
|         infoItemList.add(data); |         infoItemList.add(data); | ||||||
|  |  | ||||||
|         if (DEBUG) { |         if (DEBUG) Log.d(TAG, "addInfoItem() after > position = " + positionInserted + | ||||||
|             Log.d(TAG, "addInfoItem() after > position = " + positionInserted + ", infoItemList.size() = " + infoItemList.size() + ", header = " + header + ", footer = " + footer + ", showFooter = " + showFooter); |                 ", infoItemList.size() = " + infoItemList.size() + | ||||||
|         } |                 ", header = " + header + ", footer = " + footer + | ||||||
|  |                 ", showFooter = " + showFooter); | ||||||
|         notifyItemInserted(positionInserted); |         notifyItemInserted(positionInserted); | ||||||
|  |  | ||||||
|         if (footer != null && showFooter) { |         if (footer != null && showFooter) { | ||||||
|             int footerNow = sizeConsideringHeaderOffset(); |             int footerNow = sizeConsideringHeaderOffset(); | ||||||
|             notifyItemMoved(positionInserted, footerNow); |             notifyItemMoved(positionInserted, footerNow); | ||||||
|  |  | ||||||
|             if (DEBUG) Log.d(TAG, "addInfoItem() footer from " + positionInserted + " to " + footerNow); |             if (DEBUG) Log.d(TAG, "addInfoItem() footer from " + positionInserted + | ||||||
|         } |                     " to " + footerNow); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void updateStates() { |  | ||||||
|         if (!infoItemList.isEmpty()) { |  | ||||||
|             updateAllStates(infoItemList); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -185,7 +177,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         infoItemList.clear(); |         infoItemList.clear(); | ||||||
|         clearStates(); |  | ||||||
|         notifyDataSetChanged(); |         notifyDataSetChanged(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -254,7 +245,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|             case COMMENT: |             case COMMENT: | ||||||
|                 return useMiniVariant ? MINI_COMMENT_HOLDER_TYPE : COMMENT_HOLDER_TYPE; |                 return useMiniVariant ? MINI_COMMENT_HOLDER_TYPE : COMMENT_HOLDER_TYPE; | ||||||
|             default: |             default: | ||||||
|                 Log.e(TAG, "Trollolo"); |  | ||||||
|                 return -1; |                 return -1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -292,7 +282,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|             case COMMENT_HOLDER_TYPE: |             case COMMENT_HOLDER_TYPE: | ||||||
|                 return new CommentsInfoItemHolder(infoItemBuilder, parent); |                 return new CommentsInfoItemHolder(infoItemBuilder, parent); | ||||||
|             default: |             default: | ||||||
|                 Log.e(TAG, "Trollolo"); |  | ||||||
|                 return new FallbackViewHolder(new View(parent.getContext())); |                 return new FallbackViewHolder(new View(parent.getContext())); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -304,7 +293,7 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|             // If header isn't null, offset the items by -1 |             // If header isn't null, offset the items by -1 | ||||||
|             if (header != null) position--; |             if (header != null) position--; | ||||||
|  |  | ||||||
|             ((InfoItemHolder) holder).updateFromItem(infoItemList.get(position), getState(position)); |             ((InfoItemHolder) holder).updateFromItem(infoItemList.get(position), recordManager); | ||||||
|         } else if (holder instanceof HFHolder && position == 0 && header != null) { |         } else if (holder instanceof HFHolder && position == 0 && header != null) { | ||||||
|             ((HFHolder) holder).view = header; |             ((HFHolder) holder).view = header; | ||||||
|         } else if (holder instanceof HFHolder && position == sizeConsideringHeaderOffset() && footer != null && showFooter) { |         } else if (holder instanceof HFHolder && position == sizeConsideringHeaderOffset() && footer != null && showFooter) { | ||||||
| @@ -317,11 +306,9 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|         if (!payloads.isEmpty() && holder instanceof InfoItemHolder) { |         if (!payloads.isEmpty() && holder instanceof InfoItemHolder) { | ||||||
|             for (Object payload : payloads) { |             for (Object payload : payloads) { | ||||||
|                 if (payload instanceof StreamStateEntity) { |                 if (payload instanceof StreamStateEntity) { | ||||||
|                     ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), |                     ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), recordManager); | ||||||
|                             (StreamStateEntity) payload); |  | ||||||
|                 } else if (payload instanceof Boolean) { |                 } else if (payload instanceof Boolean) { | ||||||
|                     ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), |                     ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), recordManager); | ||||||
|                             null); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
| @@ -329,11 +316,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) { |  | ||||||
|         notifyItemChanged(header == null ? position : position + 1, state != null ? state : false); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) { |     public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) { | ||||||
|         return new GridLayoutManager.SpanSizeLookup() { |         return new GridLayoutManager.SpanSizeLookup() { | ||||||
|             @Override |             @Override | ||||||
|   | |||||||
| @@ -1,180 +0,0 @@ | |||||||
| package org.schabi.newpipe.info_list; |  | ||||||
|  |  | ||||||
| import android.content.Context; |  | ||||||
| import android.content.SharedPreferences; |  | ||||||
| import android.preference.PreferenceManager; |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.support.v7.widget.RecyclerView; |  | ||||||
| import android.util.SparseArray; |  | ||||||
|  |  | ||||||
| import org.schabi.newpipe.BuildConfig; |  | ||||||
| import org.schabi.newpipe.R; |  | ||||||
| import org.schabi.newpipe.database.LocalItem; |  | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; |  | ||||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; |  | ||||||
| import org.schabi.newpipe.util.SparseArrayUtils; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Objects; |  | ||||||
|  |  | ||||||
| import io.reactivex.android.schedulers.AndroidSchedulers; |  | ||||||
| import io.reactivex.disposables.CompositeDisposable; |  | ||||||
|  |  | ||||||
| public abstract class StateObjectsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { |  | ||||||
|  |  | ||||||
| 	private final SparseArray<StreamStateEntity> states; |  | ||||||
| 	private final HistoryRecordManager recordManager; |  | ||||||
| 	private final CompositeDisposable stateLoaders; |  | ||||||
| 	private final Context context; |  | ||||||
|  |  | ||||||
| 	public StateObjectsListAdapter(Context context) { |  | ||||||
| 		this.states = new SparseArray<>(); |  | ||||||
| 		this.recordManager = new HistoryRecordManager(context); |  | ||||||
| 		this.context = context; |  | ||||||
| 		this.stateLoaders = new CompositeDisposable(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Nullable |  | ||||||
| 	public StreamStateEntity getState(int position) { |  | ||||||
| 		return states.get(position); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void clearStates() { |  | ||||||
| 		states.clear(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private void appendStates(List<StreamStateEntity> statesEntities, int offset) { |  | ||||||
| 		for (int i = 0; i < statesEntities.size(); i++) { |  | ||||||
| 			final StreamStateEntity state = statesEntities.get(i); |  | ||||||
| 			if (state != null) { |  | ||||||
| 				states.append(offset + i, state); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private void appendState(StreamStateEntity statesEntity, int offset) { |  | ||||||
| 		if (statesEntity != null) { |  | ||||||
| 			states.append(offset, statesEntity); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void removeState(int index) { |  | ||||||
| 		states.remove(index); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void moveState(int from, int to) { |  | ||||||
| 		final StreamStateEntity item = states.get(from); |  | ||||||
| 		if (from < to) { |  | ||||||
| 			SparseArrayUtils.shiftItemsDown(states, from, to); |  | ||||||
| 		} else { |  | ||||||
| 			SparseArrayUtils.shiftItemsUp(states, to, from); |  | ||||||
| 		} |  | ||||||
| 		states.put(to, item); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void loadStates(List<InfoItem> list, int offset, Runnable callback) { |  | ||||||
| 		if (isPlaybackStatesVisible()) { |  | ||||||
| 			List<StreamStateEntity> streamStateEntities = null; |  | ||||||
| 			try { |  | ||||||
| 				streamStateEntities = recordManager.loadStreamStateBatch(list).blockingGet(); |  | ||||||
| 			} catch (Exception e) { |  | ||||||
| 				if (BuildConfig.DEBUG) e.printStackTrace(); |  | ||||||
| 			} |  | ||||||
| 			if(streamStateEntities != null) appendStates(streamStateEntities, offset); |  | ||||||
| 			callback.run(); |  | ||||||
| 		} else { |  | ||||||
| 			callback.run(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void loadState(InfoItem item, int offset, Runnable callback) { |  | ||||||
| 		if (isPlaybackStatesVisible()) { |  | ||||||
| 			StreamStateEntity[] streamStateEntities = null; |  | ||||||
| 			try { |  | ||||||
| 				streamStateEntities = recordManager.loadStreamState(item).blockingGet(); |  | ||||||
| 			} catch (Exception e) { |  | ||||||
| 				if (BuildConfig.DEBUG) e.printStackTrace(); |  | ||||||
| 			} |  | ||||||
| 			if(streamStateEntities != null && streamStateEntities.length > 0) appendState(streamStateEntities[0], offset); |  | ||||||
| 			callback.run(); |  | ||||||
| 		} else { |  | ||||||
| 			callback.run(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void loadStatesForLocal(List<? extends LocalItem> list, int offset, Runnable callback) { |  | ||||||
| 		if (isPlaybackStatesVisible()) { |  | ||||||
| 			List<StreamStateEntity> streamStateEntities = null; |  | ||||||
| 			try { |  | ||||||
| 				streamStateEntities = recordManager.loadLocalStreamStateBatch(list).blockingGet(); |  | ||||||
| 			} catch (Exception e) { |  | ||||||
| 				if (BuildConfig.DEBUG) e.printStackTrace(); |  | ||||||
| 			} |  | ||||||
| 			if(streamStateEntities != null) appendStates(streamStateEntities, offset); |  | ||||||
| 			callback.run(); |  | ||||||
| 		} else { |  | ||||||
| 			callback.run(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private void processStatesUpdates(List<StreamStateEntity> streamStateEntities) { |  | ||||||
| 		for (int i = 0; i < streamStateEntities.size(); i++) { |  | ||||||
| 			final StreamStateEntity newState = streamStateEntities.get(i); |  | ||||||
| 			if (!Objects.equals(states.get(i), newState)) { |  | ||||||
| 				if (newState == null) { |  | ||||||
| 					states.remove(i); |  | ||||||
| 				} else { |  | ||||||
| 					states.put(i, newState); |  | ||||||
| 				} |  | ||||||
| 				onItemStateChanged(i, newState); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void updateAllStates(List<InfoItem> list) { |  | ||||||
| 		if (isPlaybackStatesVisible()) { |  | ||||||
| 			stateLoaders.add( |  | ||||||
| 					recordManager.loadStreamStateBatch(list) |  | ||||||
| 							.observeOn(AndroidSchedulers.mainThread()) |  | ||||||
| 							.subscribe(this::processStatesUpdates, throwable -> { |  | ||||||
| 								if (BuildConfig.DEBUG) throwable.printStackTrace(); |  | ||||||
| 							}) |  | ||||||
| 			); |  | ||||||
| 		} else { |  | ||||||
| 			final int[] positions = SparseArrayUtils.getKeys(states); |  | ||||||
| 			states.clear(); |  | ||||||
| 			for (int pos : positions) onItemStateChanged(pos, null); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected void updateAllLocalStates(List<? extends LocalItem> list) { |  | ||||||
| 		if (isPlaybackStatesVisible()) { |  | ||||||
| 			stateLoaders.add( |  | ||||||
| 					recordManager.loadLocalStreamStateBatch(list) |  | ||||||
| 							.observeOn(AndroidSchedulers.mainThread()) |  | ||||||
| 							.subscribe(this::processStatesUpdates, throwable -> { |  | ||||||
| 								if (BuildConfig.DEBUG) throwable.printStackTrace(); |  | ||||||
| 							}) |  | ||||||
| 			); |  | ||||||
| 		} else { |  | ||||||
| 			final int[] positions = SparseArrayUtils.getKeys(states); |  | ||||||
| 			states.clear(); |  | ||||||
| 			for (int pos : positions) onItemStateChanged(pos, null); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void dispose() { |  | ||||||
| 		stateLoaders.dispose(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected boolean isPlaybackStatesVisible() { |  | ||||||
| 		final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); |  | ||||||
| 		return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true) |  | ||||||
| 				&& prefs.getBoolean(context.getString(R.string.enable_playback_resume_key), true) |  | ||||||
| 				&& prefs.getBoolean(context.getString(R.string.enable_playback_state_lists_key), true); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected abstract void onItemStateChanged(int position, @Nullable StreamStateEntity state); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,14 +1,13 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -40,8 +39,8 @@ public class ChannelInfoItemHolder extends ChannelMiniInfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         super.updateFromItem(infoItem, state); |         super.updateFromItem(infoItem, historyRecordManager); | ||||||
|  |  | ||||||
|         if (!(infoItem instanceof ChannelInfoItem)) return; |         if (!(infoItem instanceof ChannelInfoItem)) return; | ||||||
|         final ChannelInfoItem item = (ChannelInfoItem) infoItem; |         final ChannelInfoItem item = (ChannelInfoItem) infoItem; | ||||||
|   | |||||||
| @@ -1,14 +1,13 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
|  |  | ||||||
| @@ -32,7 +31,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         if (!(infoItem instanceof ChannelInfoItem)) return; |         if (!(infoItem instanceof ChannelInfoItem)) return; | ||||||
|         final ChannelInfoItem item = (ChannelInfoItem) infoItem; |         final ChannelInfoItem item = (ChannelInfoItem) infoItem; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,14 +1,13 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.comments.CommentsInfoItem; | import org.schabi.newpipe.extractor.comments.CommentsInfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Created by Christian Schabesberger on 12.02.17. |  * Created by Christian Schabesberger on 12.02.17. | ||||||
| @@ -41,8 +40,8 @@ public class CommentsInfoItemHolder extends CommentsMiniInfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         super.updateFromItem(infoItem, state); |         super.updateFromItem(infoItem, historyRecordManager); | ||||||
|  |  | ||||||
|         if (!(infoItem instanceof CommentsInfoItem)) return; |         if (!(infoItem instanceof CommentsInfoItem)) return; | ||||||
|         final CommentsInfoItem item = (CommentsInfoItem) infoItem; |         final CommentsInfoItem item = (CommentsInfoItem) infoItem; | ||||||
|   | |||||||
| @@ -1,18 +1,16 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.support.v7.app.AppCompatActivity; | import android.support.v7.app.AppCompatActivity; | ||||||
| import android.text.util.Linkify; | import android.text.util.Linkify; | ||||||
| import android.view.View; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.jsoup.helper.StringUtil; | import org.jsoup.helper.StringUtil; | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.comments.CommentsInfoItem; | import org.schabi.newpipe.extractor.comments.CommentsInfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.report.ErrorActivity; | import org.schabi.newpipe.report.ErrorActivity; | ||||||
| import org.schabi.newpipe.util.CommentTextOnTouchListener; | import org.schabi.newpipe.util.CommentTextOnTouchListener; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
| @@ -48,7 +46,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { | |||||||
|             if(hours != null) timestamp += (Integer.parseInt(hours.replace(":", ""))*3600); |             if(hours != null) timestamp += (Integer.parseInt(hours.replace(":", ""))*3600); | ||||||
|             if(minutes != null) timestamp += (Integer.parseInt(minutes.replace(":", ""))*60); |             if(minutes != null) timestamp += (Integer.parseInt(minutes.replace(":", ""))*60); | ||||||
|             if(seconds != null) timestamp += (Integer.parseInt(seconds)); |             if(seconds != null) timestamp += (Integer.parseInt(seconds)); | ||||||
|             return streamUrl + url.replace(match.group(0), "#timestamp=" + String.valueOf(timestamp)); |             return streamUrl + url.replace(match.group(0), "#timestamp=" + timestamp); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -67,7 +65,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         if (!(infoItem instanceof CommentsInfoItem)) return; |         if (!(infoItem instanceof CommentsInfoItem)) return; | ||||||
|         final CommentsInfoItem item = (CommentsInfoItem) infoItem; |         final CommentsInfoItem item = (CommentsInfoItem) infoItem; | ||||||
|  |  | ||||||
| @@ -76,9 +74,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { | |||||||
|                         itemThumbnailView, |                         itemThumbnailView, | ||||||
|                         ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS); |                         ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS); | ||||||
|  |  | ||||||
|         itemThumbnailView.setOnClickListener(new View.OnClickListener() { |         itemThumbnailView.setOnClickListener(view -> { | ||||||
|             @Override |  | ||||||
|             public void onClick(View view) { |  | ||||||
|             if(StringUtil.isBlank(item.getAuthorEndpoint())) return; |             if(StringUtil.isBlank(item.getAuthorEndpoint())) return; | ||||||
|             try { |             try { | ||||||
|                 final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext(); |                 final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext(); | ||||||
| @@ -90,7 +86,6 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { | |||||||
|             } catch (Exception e) { |             } catch (Exception e) { | ||||||
|                 ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e); |                 ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e); | ||||||
|             } |             } | ||||||
|             } |  | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         streamUrl = item.getUrl(); |         streamUrl = item.getUrl(); | ||||||
| @@ -101,7 +96,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { | |||||||
|         itemContentView.setOnTouchListener(CommentTextOnTouchListener.INSTANCE); |         itemContentView.setOnTouchListener(CommentTextOnTouchListener.INSTANCE); | ||||||
|  |  | ||||||
|         if (itemContentView.getLineCount() == 0) { |         if (itemContentView.getLineCount() == 0) { | ||||||
|             itemContentView.post(() -> ellipsize()); |             itemContentView.post(this::ellipsize); | ||||||
|         } else { |         } else { | ||||||
|             ellipsize(); |             ellipsize(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,13 +1,12 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.support.v7.widget.RecyclerView; | import android.support.v7.widget.RecyclerView; | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Created by Christian Schabesberger on 12.02.17. |  * Created by Christian Schabesberger on 12.02.17. | ||||||
| @@ -37,8 +36,8 @@ public abstract class InfoItemHolder extends RecyclerView.ViewHolder { | |||||||
|         this.itemBuilder = infoItemBuilder; |         this.itemBuilder = infoItemBuilder; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public abstract void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state); |     public abstract void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager); | ||||||
|  |  | ||||||
|     public void updateState(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateState(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,15 +1,14 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; | import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
|  |  | ||||||
| public class PlaylistMiniInfoItemHolder extends InfoItemHolder { | public class PlaylistMiniInfoItemHolder extends InfoItemHolder { | ||||||
| @@ -32,7 +31,7 @@ public class PlaylistMiniInfoItemHolder extends InfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         if (!(infoItem instanceof PlaylistInfoItem)) return; |         if (!(infoItem instanceof PlaylistInfoItem)) return; | ||||||
|         final PlaylistInfoItem item = (PlaylistInfoItem) infoItem; |         final PlaylistInfoItem item = (PlaylistInfoItem) infoItem; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,15 +1,14 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.text.TextUtils; | import android.text.TextUtils; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.InfoItem; | import org.schabi.newpipe.extractor.InfoItem; | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -42,8 +41,8 @@ public class StreamInfoItemHolder extends StreamMiniInfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         super.updateFromItem(infoItem, state); |         super.updateFromItem(infoItem, historyRecordManager); | ||||||
|  |  | ||||||
|         if (!(infoItem instanceof StreamInfoItem)) return; |         if (!(infoItem instanceof StreamInfoItem)) return; | ||||||
|         final StreamInfoItem item = (StreamInfoItem) infoItem; |         final StreamInfoItem item = (StreamInfoItem) infoItem; | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| package org.schabi.newpipe.info_list.holder; | package org.schabi.newpipe.info_list.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.support.v4.content.ContextCompat; | import android.support.v4.content.ContextCompat; | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| @@ -13,6 +12,7 @@ import org.schabi.newpipe.extractor.InfoItem; | |||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||||||
| import org.schabi.newpipe.extractor.stream.StreamType; | import org.schabi.newpipe.extractor.stream.StreamType; | ||||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.AnimationUtils; | import org.schabi.newpipe.util.AnimationUtils; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
| @@ -43,7 +43,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         if (!(infoItem instanceof StreamInfoItem)) return; |         if (!(infoItem instanceof StreamInfoItem)) return; | ||||||
|         final StreamInfoItem item = (StreamInfoItem) infoItem; |         final StreamInfoItem item = (StreamInfoItem) infoItem; | ||||||
|  |  | ||||||
| @@ -55,10 +55,12 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { | |||||||
|             itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), |             itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), | ||||||
|                     R.color.duration_background_color)); |                     R.color.duration_background_color)); | ||||||
|             itemDurationView.setVisibility(View.VISIBLE); |             itemDurationView.setVisibility(View.VISIBLE); | ||||||
|             if (state != null) { |  | ||||||
|  |             StreamStateEntity state2 = historyRecordManager.loadStreamState(infoItem).blockingGet()[0]; | ||||||
|  |             if (state2 != null) { | ||||||
|                 itemProgressView.setVisibility(View.VISIBLE); |                 itemProgressView.setVisibility(View.VISIBLE); | ||||||
|                 itemProgressView.setMax((int) item.getDuration()); |                 itemProgressView.setMax((int) item.getDuration()); | ||||||
|                 itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime())); |                 itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state2.getProgressTime())); | ||||||
|             } else { |             } else { | ||||||
|                 itemProgressView.setVisibility(View.GONE); |                 itemProgressView.setVisibility(View.GONE); | ||||||
|             } |             } | ||||||
| @@ -101,8 +103,10 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateState(final InfoItem infoItem, @Nullable final StreamStateEntity state) { |     public void updateState(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { | ||||||
|         final StreamInfoItem item = (StreamInfoItem) infoItem; |         final StreamInfoItem item = (StreamInfoItem) infoItem; | ||||||
|  |  | ||||||
|  |         StreamStateEntity state = historyRecordManager.loadStreamState(infoItem).blockingGet()[0]; | ||||||
|         if (state != null && item.getDuration() > 0 && item.getStreamType() != StreamType.LIVE_STREAM) { |         if (state != null && item.getDuration() > 0 && item.getStreamType() != StreamType.LIVE_STREAM) { | ||||||
|             itemProgressView.setMax((int) item.getDuration()); |             itemProgressView.setMax((int) item.getDuration()); | ||||||
|             if (itemProgressView.getVisibility() == View.VISIBLE) { |             if (itemProgressView.getVisibility() == View.VISIBLE) { | ||||||
|   | |||||||
| @@ -76,8 +76,6 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I> | |||||||
|             } |             } | ||||||
|             updateFlags = 0; |             updateFlags = 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         itemsList.post(itemListAdapter::updateStates); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /*////////////////////////////////////////////////////////////////////////// |     /*////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -152,7 +150,6 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I> | |||||||
|     public void onDestroyView() { |     public void onDestroyView() { | ||||||
|         super.onDestroyView(); |         super.onDestroyView(); | ||||||
|         itemsList = null; |         itemsList = null; | ||||||
|         itemListAdapter.dispose(); |  | ||||||
|         itemListAdapter = null; |         itemListAdapter = null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| package org.schabi.newpipe.local; | package org.schabi.newpipe.local; | ||||||
|  |  | ||||||
| import android.app.Activity; | import android.content.Context; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.support.annotation.Nullable; | import android.support.annotation.Nullable; | ||||||
| import android.support.v7.widget.GridLayoutManager; | import android.support.v7.widget.GridLayoutManager; | ||||||
| @@ -11,7 +11,7 @@ import android.view.ViewGroup; | |||||||
|  |  | ||||||
| import org.schabi.newpipe.database.LocalItem; | import org.schabi.newpipe.database.LocalItem; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; | import org.schabi.newpipe.database.stream.model.StreamStateEntity; | ||||||
| import org.schabi.newpipe.info_list.StateObjectsListAdapter; | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.local.holder.LocalItemHolder; | import org.schabi.newpipe.local.holder.LocalItemHolder; | ||||||
| import org.schabi.newpipe.local.holder.LocalPlaylistGridItemHolder; | import org.schabi.newpipe.local.holder.LocalPlaylistGridItemHolder; | ||||||
| import org.schabi.newpipe.local.holder.LocalPlaylistItemHolder; | import org.schabi.newpipe.local.holder.LocalPlaylistItemHolder; | ||||||
| @@ -49,7 +49,7 @@ import java.util.List; | |||||||
|  * along with NewPipe.  If not, see <http://www.gnu.org/licenses/>. |  * along with NewPipe.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| public class LocalItemListAdapter extends StateObjectsListAdapter { | public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { | ||||||
|      |      | ||||||
|     private static final String TAG = LocalItemListAdapter.class.getSimpleName(); |     private static final String TAG = LocalItemListAdapter.class.getSimpleName(); | ||||||
|     private static final boolean DEBUG = false; |     private static final boolean DEBUG = false; | ||||||
| @@ -68,6 +68,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|  |  | ||||||
|     private final LocalItemBuilder localItemBuilder; |     private final LocalItemBuilder localItemBuilder; | ||||||
|     private final ArrayList<LocalItem> localItems; |     private final ArrayList<LocalItem> localItems; | ||||||
|  |     private final HistoryRecordManager recordManager; | ||||||
|     private final DateFormat dateFormat; |     private final DateFormat dateFormat; | ||||||
|  |  | ||||||
|     private boolean showFooter = false; |     private boolean showFooter = false; | ||||||
| @@ -75,12 +76,12 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|     private View header = null; |     private View header = null; | ||||||
|     private View footer = null; |     private View footer = null; | ||||||
|  |  | ||||||
|     public LocalItemListAdapter(Activity activity) { |     public LocalItemListAdapter(Context context) { | ||||||
|         super(activity.getApplicationContext()); |         recordManager = new HistoryRecordManager(context); | ||||||
|         localItemBuilder = new LocalItemBuilder(activity); |         localItemBuilder = new LocalItemBuilder(context); | ||||||
|         localItems = new ArrayList<>(); |         localItems = new ArrayList<>(); | ||||||
|         dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, |         dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, | ||||||
|                 Localization.getPreferredLocale(activity)); |                 Localization.getPreferredLocale(context)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void setSelectedListener(OnClickGesture<LocalItem> listener) { |     public void setSelectedListener(OnClickGesture<LocalItem> listener) { | ||||||
| @@ -92,27 +93,19 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void addItems(@Nullable List<? extends LocalItem> data) { |     public void addItems(@Nullable List<? extends LocalItem> data) { | ||||||
|         if (data != null) { |         if (data == null) { | ||||||
|             loadStatesForLocal(data, localItems.size(), () -> addItemsImpl(data)); |             return; | ||||||
|         } |         } | ||||||
|     } |         if (DEBUG) Log.d(TAG, "addItems() before > localItems.size() = " + | ||||||
|  |  | ||||||
|     private void addItemsImpl(@NonNull List<? extends LocalItem> data) { |  | ||||||
|         if (DEBUG) { |  | ||||||
|             Log.d(TAG, "addItems() before > localItems.size() = " + |  | ||||||
|                 localItems.size() + ", data.size() = " + data.size()); |                 localItems.size() + ", data.size() = " + data.size()); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         int offsetStart = sizeConsideringHeader(); |         int offsetStart = sizeConsideringHeader(); | ||||||
|         localItems.addAll(data); |         localItems.addAll(data); | ||||||
|  |  | ||||||
|         if (DEBUG) { |         if (DEBUG) Log.d(TAG, "addItems() after > offsetStart = " + offsetStart + | ||||||
|             Log.d(TAG, "addItems() after > offsetStart = " + offsetStart + |  | ||||||
|                 ", localItems.size() = " + localItems.size() + |                 ", localItems.size() = " + localItems.size() + | ||||||
|                 ", header = " + header + ", footer = " + footer + |                 ", header = " + header + ", footer = " + footer + | ||||||
|                 ", showFooter = " + showFooter); |                 ", showFooter = " + showFooter); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         notifyItemRangeInserted(offsetStart, data.size()); |         notifyItemRangeInserted(offsetStart, data.size()); | ||||||
|  |  | ||||||
|         if (footer != null && showFooter) { |         if (footer != null && showFooter) { | ||||||
| @@ -124,16 +117,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void updateStates() { |  | ||||||
|         if (!localItems.isEmpty()) { |  | ||||||
|             updateAllLocalStates(localItems); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void removeItem(final LocalItem data) { |     public void removeItem(final LocalItem data) { | ||||||
|         final int index = localItems.indexOf(data); |         final int index = localItems.indexOf(data); | ||||||
|         localItems.remove(index); |         localItems.remove(index); | ||||||
|         removeState(index); |  | ||||||
|         notifyItemRemoved(index + (header != null ? 1 : 0)); |         notifyItemRemoved(index + (header != null ? 1 : 0)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -145,7 +131,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|         if (actualFrom >= localItems.size() || actualTo >= localItems.size()) return false; |         if (actualFrom >= localItems.size() || actualTo >= localItems.size()) return false; | ||||||
|  |  | ||||||
|         localItems.add(actualTo, localItems.remove(actualFrom)); |         localItems.add(actualTo, localItems.remove(actualFrom)); | ||||||
|         moveState(actualFrom, actualTo); |  | ||||||
|         notifyItemMoved(fromAdapterPosition, toAdapterPosition); |         notifyItemMoved(fromAdapterPosition, toAdapterPosition); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -155,7 +140,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         localItems.clear(); |         localItems.clear(); | ||||||
|         clearStates(); |  | ||||||
|         notifyDataSetChanged(); |         notifyDataSetChanged(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -236,8 +220,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @NonNull | ||||||
|     @Override |     @Override | ||||||
|     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) { |     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int type) { | ||||||
|         if (DEBUG) Log.d(TAG, "onCreateViewHolder() called with: parent = [" + |         if (DEBUG) Log.d(TAG, "onCreateViewHolder() called with: parent = [" + | ||||||
|                 parent + "], type = [" + type + "]"); |                 parent + "], type = [" + type + "]"); | ||||||
|         switch (type) { |         switch (type) { | ||||||
| @@ -268,7 +253,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { |     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { | ||||||
|         if (DEBUG) Log.d(TAG, "onBindViewHolder() called with: holder = [" + |         if (DEBUG) Log.d(TAG, "onBindViewHolder() called with: holder = [" + | ||||||
|                 holder.getClass().getSimpleName() + "], position = [" + position + "]"); |                 holder.getClass().getSimpleName() + "], position = [" + position + "]"); | ||||||
|  |  | ||||||
| @@ -276,7 +261,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|             // If header isn't null, offset the items by -1 |             // If header isn't null, offset the items by -1 | ||||||
|             if (header != null) position--; |             if (header != null) position--; | ||||||
|  |  | ||||||
|             ((LocalItemHolder) holder).updateFromItem(localItems.get(position), getState(position), dateFormat); |             ((LocalItemHolder) holder).updateFromItem(localItems.get(position), recordManager, dateFormat); | ||||||
|         } else if (holder instanceof HeaderFooterHolder && position == 0 && header != null) { |         } else if (holder instanceof HeaderFooterHolder && position == 0 && header != null) { | ||||||
|             ((HeaderFooterHolder) holder).view = header; |             ((HeaderFooterHolder) holder).view = header; | ||||||
|         } else if (holder instanceof HeaderFooterHolder && position == sizeConsideringHeader() |         } else if (holder instanceof HeaderFooterHolder && position == sizeConsideringHeader() | ||||||
| @@ -290,11 +275,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|         if (!payloads.isEmpty() && holder instanceof LocalItemHolder) { |         if (!payloads.isEmpty() && holder instanceof LocalItemHolder) { | ||||||
|             for (Object payload : payloads) { |             for (Object payload : payloads) { | ||||||
|                 if (payload instanceof StreamStateEntity) { |                 if (payload instanceof StreamStateEntity) { | ||||||
|                     ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), |                     ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), recordManager); | ||||||
|                             (StreamStateEntity) payload); |  | ||||||
|                 } else if (payload instanceof Boolean) { |                 } else if (payload instanceof Boolean) { | ||||||
|                     ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), |                     ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), recordManager); | ||||||
|                             null); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
| @@ -302,11 +285,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) { |  | ||||||
|         notifyItemChanged(header == null ? position : position + 1, state != null ? state : false); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) { |     public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) { | ||||||
|         return new GridLayoutManager.SpanSizeLookup() { |         return new GridLayoutManager.SpanSizeLookup() { | ||||||
|             @Override |             @Override | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| package org.schabi.newpipe.local.dialog; | package org.schabi.newpipe.local.dialog; | ||||||
|  |  | ||||||
| import android.annotation.SuppressLint; |  | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
| import android.support.annotation.Nullable; | import android.support.annotation.Nullable; | ||||||
| @@ -28,7 +27,7 @@ import java.util.Collections; | |||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | import io.reactivex.android.schedulers.AndroidSchedulers; | ||||||
| import io.reactivex.disposables.Disposable; | import io.reactivex.disposables.CompositeDisposable; | ||||||
|  |  | ||||||
| public final class PlaylistAppendDialog extends PlaylistDialog { | public final class PlaylistAppendDialog extends PlaylistDialog { | ||||||
|     private static final String TAG = PlaylistAppendDialog.class.getCanonicalName(); |     private static final String TAG = PlaylistAppendDialog.class.getCanonicalName(); | ||||||
| @@ -36,7 +35,7 @@ public final class PlaylistAppendDialog extends PlaylistDialog { | |||||||
|     private RecyclerView playlistRecyclerView; |     private RecyclerView playlistRecyclerView; | ||||||
|     private LocalItemListAdapter playlistAdapter; |     private LocalItemListAdapter playlistAdapter; | ||||||
|  |  | ||||||
|     private Disposable playlistReactor; |     private CompositeDisposable playlistDisposables = new CompositeDisposable(); | ||||||
|  |  | ||||||
|     public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) { |     public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) { | ||||||
|         PlaylistAppendDialog dialog = new PlaylistAppendDialog(); |         PlaylistAppendDialog dialog = new PlaylistAppendDialog(); | ||||||
| @@ -99,9 +98,9 @@ public final class PlaylistAppendDialog extends PlaylistDialog { | |||||||
|         final View newPlaylistButton = view.findViewById(R.id.newPlaylist); |         final View newPlaylistButton = view.findViewById(R.id.newPlaylist); | ||||||
|         newPlaylistButton.setOnClickListener(ignored -> openCreatePlaylistDialog()); |         newPlaylistButton.setOnClickListener(ignored -> openCreatePlaylistDialog()); | ||||||
|  |  | ||||||
|         playlistReactor = playlistManager.getPlaylists() |         playlistDisposables.add(playlistManager.getPlaylists() | ||||||
|                 .observeOn(AndroidSchedulers.mainThread()) |                 .observeOn(AndroidSchedulers.mainThread()) | ||||||
|                 .subscribe(this::onPlaylistsReceived); |                 .subscribe(this::onPlaylistsReceived)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /*////////////////////////////////////////////////////////////////////////// |     /*////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -111,13 +110,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog { | |||||||
|     @Override |     @Override | ||||||
|     public void onDestroyView() { |     public void onDestroyView() { | ||||||
|         super.onDestroyView(); |         super.onDestroyView(); | ||||||
|         if (playlistReactor != null) playlistReactor.dispose(); |         playlistDisposables.dispose(); | ||||||
|         if (playlistAdapter != null) { |         if (playlistAdapter != null) { | ||||||
|             playlistAdapter.dispose(); |  | ||||||
|             playlistAdapter.unsetSelectedListener(); |             playlistAdapter.unsetSelectedListener(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         playlistReactor = null; |         playlistDisposables.clear(); | ||||||
|         playlistRecyclerView = null; |         playlistRecyclerView = null; | ||||||
|         playlistAdapter = null; |         playlistAdapter = null; | ||||||
|     } |     } | ||||||
| @@ -151,13 +149,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog { | |||||||
|                                     @NonNull List<StreamEntity> streams) { |                                     @NonNull List<StreamEntity> streams) { | ||||||
|         if (getStreams() == null) return; |         if (getStreams() == null) return; | ||||||
|  |  | ||||||
|         @SuppressLint("ShowToast") |  | ||||||
|         final Toast successToast = Toast.makeText(getContext(), |         final Toast successToast = Toast.makeText(getContext(), | ||||||
|                 R.string.playlist_add_stream_success, Toast.LENGTH_SHORT); |                 R.string.playlist_add_stream_success, Toast.LENGTH_SHORT); | ||||||
|  |  | ||||||
|         manager.appendToPlaylist(playlist.uid, streams) |         playlistDisposables.add(manager.appendToPlaylist(playlist.uid, streams) | ||||||
|                 .observeOn(AndroidSchedulers.mainThread()) |                 .observeOn(AndroidSchedulers.mainThread()) | ||||||
|                 .subscribe(ignored -> successToast.show()); |                 .subscribe(ignored -> successToast.show())); | ||||||
|  |  | ||||||
|         getDialog().dismiss(); |         getDialog().dismiss(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,13 +1,12 @@ | |||||||
| package org.schabi.newpipe.local.holder; | package org.schabi.newpipe.local.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.support.v7.widget.RecyclerView; | import android.support.v7.widget.RecyclerView; | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.database.LocalItem; | import org.schabi.newpipe.database.LocalItem; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.local.LocalItemBuilder; | import org.schabi.newpipe.local.LocalItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
|  |  | ||||||
| import java.text.DateFormat; | import java.text.DateFormat; | ||||||
|  |  | ||||||
| @@ -40,8 +39,8 @@ public abstract class LocalItemHolder extends RecyclerView.ViewHolder { | |||||||
|         this.itemBuilder = itemBuilder; |         this.itemBuilder = itemBuilder; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public abstract void updateFromItem(final LocalItem item, @Nullable final StreamStateEntity state, final DateFormat dateFormat); |     public abstract void updateFromItem(final LocalItem item, HistoryRecordManager historyRecordManager, final DateFormat dateFormat); | ||||||
|  |  | ||||||
|     public void updateState(final LocalItem localItem, @Nullable final StreamStateEntity state) { |     public void updateState(final LocalItem localItem, HistoryRecordManager historyRecordManager) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,13 +1,12 @@ | |||||||
| package org.schabi.newpipe.local.holder; | package org.schabi.newpipe.local.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.database.LocalItem; | import org.schabi.newpipe.database.LocalItem; | ||||||
| import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; | import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.local.LocalItemBuilder; | import org.schabi.newpipe.local.LocalItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
|  |  | ||||||
| import java.text.DateFormat; | import java.text.DateFormat; | ||||||
| @@ -23,7 +22,7 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { |     public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { | ||||||
|         if (!(localItem instanceof PlaylistMetadataEntry)) return; |         if (!(localItem instanceof PlaylistMetadataEntry)) return; | ||||||
|         final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem; |         final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem; | ||||||
|  |  | ||||||
| @@ -34,6 +33,6 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { | |||||||
|         itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, |         itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, | ||||||
|                 ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS); |                 ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS); | ||||||
|  |  | ||||||
|         super.updateFromItem(localItem, state, dateFormat); |         super.updateFromItem(localItem, historyRecordManager, dateFormat); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| package org.schabi.newpipe.local.holder; | package org.schabi.newpipe.local.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.support.v4.content.ContextCompat; | import android.support.v4.content.ContextCompat; | ||||||
| import android.view.MotionEvent; | import android.view.MotionEvent; | ||||||
| import android.view.View; | import android.view.View; | ||||||
| @@ -14,12 +13,14 @@ import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; | |||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; | import org.schabi.newpipe.database.stream.model.StreamStateEntity; | ||||||
| import org.schabi.newpipe.extractor.NewPipe; | import org.schabi.newpipe.extractor.NewPipe; | ||||||
| import org.schabi.newpipe.local.LocalItemBuilder; | import org.schabi.newpipe.local.LocalItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.AnimationUtils; | import org.schabi.newpipe.util.AnimationUtils; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
| import org.schabi.newpipe.views.AnimatedProgressBar; | import org.schabi.newpipe.views.AnimatedProgressBar; | ||||||
|  |  | ||||||
| import java.text.DateFormat; | import java.text.DateFormat; | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
| public class LocalPlaylistStreamItemHolder extends LocalItemHolder { | public class LocalPlaylistStreamItemHolder extends LocalItemHolder { | ||||||
| @@ -47,7 +48,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { |     public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { | ||||||
|         if (!(localItem instanceof PlaylistStreamEntry)) return; |         if (!(localItem instanceof PlaylistStreamEntry)) return; | ||||||
|         final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; |         final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; | ||||||
|  |  | ||||||
| @@ -60,6 +61,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { | |||||||
|             itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), |             itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), | ||||||
|                     R.color.duration_background_color)); |                     R.color.duration_background_color)); | ||||||
|             itemDurationView.setVisibility(View.VISIBLE); |             itemDurationView.setVisibility(View.VISIBLE); | ||||||
|  |  | ||||||
|  |             StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0); | ||||||
|             if (state != null) { |             if (state != null) { | ||||||
|                 itemProgressView.setVisibility(View.VISIBLE); |                 itemProgressView.setVisibility(View.VISIBLE); | ||||||
|                 itemProgressView.setMax((int) item.duration); |                 itemProgressView.setMax((int) item.duration); | ||||||
| @@ -94,9 +97,11 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) { |     public void updateState(LocalItem localItem, HistoryRecordManager historyRecordManager) { | ||||||
|         if (!(localItem instanceof PlaylistStreamEntry)) return; |         if (!(localItem instanceof PlaylistStreamEntry)) return; | ||||||
|         final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; |         final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; | ||||||
|  |  | ||||||
|  |         StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0); | ||||||
|         if (state != null && item.duration > 0) { |         if (state != null && item.duration > 0) { | ||||||
|             itemProgressView.setMax((int) item.duration); |             itemProgressView.setMax((int) item.duration); | ||||||
|             if (itemProgressView.getVisibility() == View.VISIBLE) { |             if (itemProgressView.getVisibility() == View.VISIBLE) { | ||||||
|   | |||||||
| @@ -13,12 +13,14 @@ import org.schabi.newpipe.database.stream.StreamStatisticsEntry; | |||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; | import org.schabi.newpipe.database.stream.model.StreamStateEntity; | ||||||
| import org.schabi.newpipe.extractor.NewPipe; | import org.schabi.newpipe.extractor.NewPipe; | ||||||
| import org.schabi.newpipe.local.LocalItemBuilder; | import org.schabi.newpipe.local.LocalItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.AnimationUtils; | import org.schabi.newpipe.util.AnimationUtils; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
| import org.schabi.newpipe.views.AnimatedProgressBar; | import org.schabi.newpipe.views.AnimatedProgressBar; | ||||||
|  |  | ||||||
| import java.text.DateFormat; | import java.text.DateFormat; | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -76,7 +78,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { |     public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { | ||||||
|         if (!(localItem instanceof StreamStatisticsEntry)) return; |         if (!(localItem instanceof StreamStatisticsEntry)) return; | ||||||
|         final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; |         final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; | ||||||
|  |  | ||||||
| @@ -88,6 +90,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { | |||||||
|             itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), |             itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), | ||||||
|                     R.color.duration_background_color)); |                     R.color.duration_background_color)); | ||||||
|             itemDurationView.setVisibility(View.VISIBLE); |             itemDurationView.setVisibility(View.VISIBLE); | ||||||
|  |  | ||||||
|  |             StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0); | ||||||
|             if (state != null) { |             if (state != null) { | ||||||
|                 itemProgressView.setVisibility(View.VISIBLE); |                 itemProgressView.setVisibility(View.VISIBLE); | ||||||
|                 itemProgressView.setMax((int) item.duration); |                 itemProgressView.setMax((int) item.duration); | ||||||
| @@ -124,9 +128,11 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) { |     public void updateState(LocalItem localItem, HistoryRecordManager historyRecordManager) { | ||||||
|         if (!(localItem instanceof StreamStatisticsEntry)) return; |         if (!(localItem instanceof StreamStatisticsEntry)) return; | ||||||
|         final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; |         final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; | ||||||
|  |  | ||||||
|  |         StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0); | ||||||
|         if (state != null && item.duration > 0) { |         if (state != null && item.duration > 0) { | ||||||
|             itemProgressView.setMax((int) item.duration); |             itemProgressView.setMax((int) item.duration); | ||||||
|             if (itemProgressView.getVisibility() == View.VISIBLE) { |             if (itemProgressView.getVisibility() == View.VISIBLE) { | ||||||
|   | |||||||
| @@ -1,14 +1,13 @@ | |||||||
| package org.schabi.newpipe.local.holder; | package org.schabi.newpipe.local.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.database.LocalItem; | import org.schabi.newpipe.database.LocalItem; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.local.LocalItemBuilder; | import org.schabi.newpipe.local.LocalItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
|  |  | ||||||
| import java.text.DateFormat; | import java.text.DateFormat; | ||||||
|  |  | ||||||
| @@ -33,7 +32,7 @@ public abstract class PlaylistItemHolder extends LocalItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { |     public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { | ||||||
|         itemView.setOnClickListener(view -> { |         itemView.setOnClickListener(view -> { | ||||||
|             if (itemBuilder.getOnItemSelectedListener() != null) { |             if (itemBuilder.getOnItemSelectedListener() != null) { | ||||||
|                 itemBuilder.getOnItemSelectedListener().selected(localItem); |                 itemBuilder.getOnItemSelectedListener().selected(localItem); | ||||||
|   | |||||||
| @@ -1,13 +1,12 @@ | |||||||
| package org.schabi.newpipe.local.holder; | package org.schabi.newpipe.local.holder; | ||||||
|  |  | ||||||
| import android.support.annotation.Nullable; |  | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.database.LocalItem; | import org.schabi.newpipe.database.LocalItem; | ||||||
| import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; | import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; | ||||||
| import org.schabi.newpipe.database.stream.model.StreamStateEntity; |  | ||||||
| import org.schabi.newpipe.extractor.NewPipe; | import org.schabi.newpipe.extractor.NewPipe; | ||||||
| import org.schabi.newpipe.local.LocalItemBuilder; | import org.schabi.newpipe.local.LocalItemBuilder; | ||||||
|  | import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | import org.schabi.newpipe.util.ImageDisplayConstants; | ||||||
| import org.schabi.newpipe.util.Localization; | import org.schabi.newpipe.util.Localization; | ||||||
|  |  | ||||||
| @@ -23,7 +22,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { |     public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { | ||||||
|         if (!(localItem instanceof PlaylistRemoteEntity)) return; |         if (!(localItem instanceof PlaylistRemoteEntity)) return; | ||||||
|         final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem; |         final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem; | ||||||
|  |  | ||||||
| @@ -35,6 +34,6 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { | |||||||
|         itemBuilder.displayImage(item.getThumbnailUrl(), itemThumbnailView, |         itemBuilder.displayImage(item.getThumbnailUrl(), itemThumbnailView, | ||||||
|                 ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS); |                 ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS); | ||||||
|  |  | ||||||
|         super.updateFromItem(localItem, state, dateFormat); |         super.updateFromItem(localItem, historyRecordManager, dateFormat); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -130,7 +130,6 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onDetach() { |     public void onDetach() { | ||||||
|         infoListAdapter.dispose(); |  | ||||||
|         super.onDetach(); |         super.onDetach(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -153,8 +152,6 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt | |||||||
|             } |             } | ||||||
|             updateFlags = 0; |             updateFlags = 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         itemsList.post(infoListAdapter::updateStates); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -382,7 +379,6 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt | |||||||
|  |  | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         //noinspection ConstantConditions |  | ||||||
|         whatsNewItemListHeader.setOnClickListener(v -> { |         whatsNewItemListHeader.setOnClickListener(v -> { | ||||||
|             FragmentManager fragmentManager = getFM(); |             FragmentManager fragmentManager = getFM(); | ||||||
|             NavigationHelper.openWhatsNewFragment(fragmentManager); |             NavigationHelper.openWhatsNewFragment(fragmentManager); | ||||||
| @@ -430,12 +426,12 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt | |||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void shareChannel (ChannelInfoItem selectedItem) { |     private void shareChannel(ChannelInfoItem selectedItem) { | ||||||
|         ShareUtils.shareUrl(this.getContext(), selectedItem.getName(), selectedItem.getUrl()); |         ShareUtils.shareUrl(getContext(), selectedItem.getName(), selectedItem.getUrl()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @SuppressLint("CheckResult") |     @SuppressLint("CheckResult") | ||||||
|     private void deleteChannel (ChannelInfoItem selectedItem) { |     private void deleteChannel(ChannelInfoItem selectedItem) { | ||||||
|         subscriptionService.subscriptionTable() |         subscriptionService.subscriptionTable() | ||||||
|                 .getSubscription(selectedItem.getServiceId(), selectedItem.getUrl()) |                 .getSubscription(selectedItem.getServiceId(), selectedItem.getUrl()) | ||||||
|                 .toObservable() |                 .toObservable() | ||||||
| @@ -447,7 +443,7 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     private Observer<List<SubscriptionEntity>> getDeleteObserver(){ |     private Observer<List<SubscriptionEntity>> getDeleteObserver() { | ||||||
|         return new Observer<List<SubscriptionEntity>>() { |         return new Observer<List<SubscriptionEntity>>() { | ||||||
|             @Override |             @Override | ||||||
|             public void onSubscribe(Disposable d) { |             public void onSubscribe(Disposable d) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Christian Schabesberger
					Christian Schabesberger