mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	-Refactored Channel and Playlist PlayQueue into AbstractInfo playQueue.
-Increase list item action dropdown padding.
This commit is contained in:
		| @@ -63,7 +63,6 @@ import org.schabi.newpipe.fragments.BackPressable; | ||||
| import org.schabi.newpipe.fragments.BaseStateFragment; | ||||
| import org.schabi.newpipe.history.HistoryListener; | ||||
| import org.schabi.newpipe.info_list.InfoItemBuilder; | ||||
| import org.schabi.newpipe.player.BackgroundPlayer; | ||||
| import org.schabi.newpipe.player.MainVideoPlayer; | ||||
| import org.schabi.newpipe.player.PopupVideoPlayer; | ||||
| import org.schabi.newpipe.player.helper.PlayerHelper; | ||||
|   | ||||
| @@ -0,0 +1,131 @@ | ||||
| package org.schabi.newpipe.playlist; | ||||
|  | ||||
| import android.util.Log; | ||||
|  | ||||
| import org.schabi.newpipe.extractor.InfoItem; | ||||
| import org.schabi.newpipe.extractor.ListExtractor; | ||||
| import org.schabi.newpipe.extractor.ListInfo; | ||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|  | ||||
| import io.reactivex.SingleObserver; | ||||
| import io.reactivex.annotations.NonNull; | ||||
| import io.reactivex.disposables.Disposable; | ||||
|  | ||||
| abstract class AbstractInfoPlayQueue<T extends ListInfo, U extends InfoItem> extends PlayQueue { | ||||
|     boolean isInitial; | ||||
|     boolean isComplete; | ||||
|  | ||||
|     int serviceId; | ||||
|     String baseUrl; | ||||
|     String nextUrl; | ||||
|  | ||||
|     transient Disposable fetchReactor; | ||||
|  | ||||
|     AbstractInfoPlayQueue(final U item) { | ||||
|         this(item.service_id, item.url, item.url, Collections.<InfoItem>emptyList(), 0); | ||||
|     } | ||||
|  | ||||
|     AbstractInfoPlayQueue(final int serviceId, | ||||
|                                  final String url, | ||||
|                                  final String nextPageUrl, | ||||
|                                  final List<InfoItem> streams, | ||||
|                                  final int index) { | ||||
|         super(index, extractListItems(streams)); | ||||
|  | ||||
|         this.baseUrl = url; | ||||
|         this.nextUrl = nextPageUrl; | ||||
|         this.serviceId = serviceId; | ||||
|  | ||||
|         this.isInitial = streams.isEmpty(); | ||||
|         this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); | ||||
|     } | ||||
|  | ||||
|     abstract protected String getTag(); | ||||
|  | ||||
|     @Override | ||||
|     public boolean isComplete() { | ||||
|         return isComplete; | ||||
|     } | ||||
|  | ||||
|     SingleObserver<T> getHeadListObserver() { | ||||
|         return new SingleObserver<T>() { | ||||
|             @Override | ||||
|             public void onSubscribe(@NonNull Disposable d) { | ||||
|                 if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { | ||||
|                     d.dispose(); | ||||
|                 } else { | ||||
|                     fetchReactor = d; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull T result) { | ||||
|                 if (!result.has_more_streams) isComplete = true; | ||||
|                 nextUrl = result.next_streams_url; | ||||
|  | ||||
|                 append(extractListItems(result.related_streams)); | ||||
|  | ||||
|                 fetchReactor.dispose(); | ||||
|                 fetchReactor = null; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(@NonNull Throwable e) { | ||||
|                 Log.e(getTag(), "Error fetching more playlist, marking playlist as complete.", e); | ||||
|                 isComplete = true; | ||||
|                 append(); // Notify change | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     SingleObserver<ListExtractor.NextItemsResult> getNextItemsObserver() { | ||||
|         return new SingleObserver<ListExtractor.NextItemsResult>() { | ||||
|             @Override | ||||
|             public void onSubscribe(@NonNull Disposable d) { | ||||
|                 if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { | ||||
|                     d.dispose(); | ||||
|                 } else { | ||||
|                     fetchReactor = d; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { | ||||
|                 if (!result.hasMoreStreams()) isComplete = true; | ||||
|                 nextUrl = result.nextItemsUrl; | ||||
|  | ||||
|                 append(extractListItems(result.nextItemsList)); | ||||
|  | ||||
|                 fetchReactor.dispose(); | ||||
|                 fetchReactor = null; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(@NonNull Throwable e) { | ||||
|                 Log.e(getTag(), "Error fetching more playlist, marking playlist as complete.", e); | ||||
|                 isComplete = true; | ||||
|                 append(); // Notify change | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void dispose() { | ||||
|         super.dispose(); | ||||
|         if (fetchReactor != null) fetchReactor.dispose(); | ||||
|     } | ||||
|  | ||||
|     private static List<PlayQueueItem> extractListItems(final List<InfoItem> infos) { | ||||
|         List<PlayQueueItem> result = new ArrayList<>(); | ||||
|         for (final InfoItem stream : infos) { | ||||
|             if (stream instanceof StreamInfoItem) { | ||||
|                 result.add(new PlayQueueItem((StreamInfoItem) stream)); | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| } | ||||
| @@ -1,151 +1,45 @@ | ||||
| package org.schabi.newpipe.playlist; | ||||
|  | ||||
| import android.util.Log; | ||||
|  | ||||
| import org.schabi.newpipe.extractor.InfoItem; | ||||
| import org.schabi.newpipe.extractor.ListExtractor; | ||||
| import org.schabi.newpipe.extractor.channel.ChannelInfo; | ||||
| import org.schabi.newpipe.extractor.channel.ChannelInfoItem; | ||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||||
| import org.schabi.newpipe.util.ExtractorHelper; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|  | ||||
| import io.reactivex.SingleObserver; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.annotations.NonNull; | ||||
| import io.reactivex.disposables.Disposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
|  | ||||
| public final class ChannelPlayQueue extends PlayQueue { | ||||
|     private final String TAG = "ChannelPlayQueue@" + Integer.toHexString(hashCode()); | ||||
|  | ||||
|     private boolean isInitial; | ||||
|     private boolean isComplete; | ||||
|  | ||||
|     private int serviceId; | ||||
|     private String baseUrl; | ||||
|     private String nextUrl; | ||||
|  | ||||
|     private transient Disposable fetchReactor; | ||||
|  | ||||
| public final class ChannelPlayQueue extends AbstractInfoPlayQueue<ChannelInfo, ChannelInfoItem> { | ||||
|     public ChannelPlayQueue(final ChannelInfoItem item) { | ||||
|         this(item.service_id, item.url, item.url, Collections.<InfoItem>emptyList(), 0); | ||||
|         super(item); | ||||
|     } | ||||
|  | ||||
|     public ChannelPlayQueue(final int serviceId, | ||||
|                             final String url, | ||||
|                             final String nextPageUrl, | ||||
|                             final List<InfoItem> streams, | ||||
|                             final int index) { | ||||
|         super(index, extractChannelItems(streams)); | ||||
|  | ||||
|         this.baseUrl = url; | ||||
|         this.nextUrl = nextPageUrl; | ||||
|         this.serviceId = serviceId; | ||||
|  | ||||
|         this.isInitial = streams.isEmpty(); | ||||
|         this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); | ||||
|                              final String url, | ||||
|                              final String nextPageUrl, | ||||
|                              final List<InfoItem> streams, | ||||
|                              final int index) { | ||||
|         super(serviceId, url, nextPageUrl, streams, index); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean isComplete() { | ||||
|         return isComplete; | ||||
|     protected String getTag() { | ||||
|         return "ChannelPlayQueue@" + Integer.toHexString(hashCode()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void fetch() { | ||||
|         if (isInitial) { | ||||
|         if (this.isInitial) { | ||||
|             ExtractorHelper.getChannelInfo(this.serviceId, this.baseUrl, false) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(getChannelInitialObserver()); | ||||
|                     .subscribe(getHeadListObserver()); | ||||
|         } else { | ||||
|             ExtractorHelper.getMoreChannelItems(this.serviceId, this.baseUrl, this.nextUrl) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(getChannelNextItemsObserver()); | ||||
|                     .subscribe(getNextItemsObserver()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private SingleObserver<ChannelInfo> getChannelInitialObserver() { | ||||
|         return new SingleObserver<ChannelInfo>() { | ||||
|             @Override | ||||
|             public void onSubscribe(@NonNull Disposable d) { | ||||
|                 if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { | ||||
|                     d.dispose(); | ||||
|                 } else { | ||||
|                     fetchReactor = d; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull ChannelInfo result) { | ||||
|                 if (!result.has_more_streams) isComplete = true; | ||||
|                 nextUrl = result.next_streams_url; | ||||
|  | ||||
|                 append(extractChannelItems(result.related_streams)); | ||||
|  | ||||
|                 isInitial = false; | ||||
|                 fetchReactor.dispose(); | ||||
|                 fetchReactor = null; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(@NonNull Throwable e) { | ||||
|                 Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); | ||||
|                 isComplete = true; | ||||
|                 append(); // Notify change | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     private SingleObserver<ListExtractor.NextItemsResult> getChannelNextItemsObserver() { | ||||
|         return new SingleObserver<ListExtractor.NextItemsResult>() { | ||||
|             @Override | ||||
|             public void onSubscribe(@NonNull Disposable d) { | ||||
|                 if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { | ||||
|                     d.dispose(); | ||||
|                 } else { | ||||
|                     fetchReactor = d; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { | ||||
|                 if (!result.hasMoreStreams()) isComplete = true; | ||||
|                 nextUrl = result.nextItemsUrl; | ||||
|  | ||||
|                 append(extractChannelItems(result.nextItemsList)); | ||||
|  | ||||
|                 fetchReactor.dispose(); | ||||
|                 fetchReactor = null; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(@NonNull Throwable e) { | ||||
|                 Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); | ||||
|                 isComplete = true; | ||||
|                 append(); // Notify change | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void dispose() { | ||||
|         super.dispose(); | ||||
|         if (fetchReactor != null) fetchReactor.dispose(); | ||||
|     } | ||||
|  | ||||
|     private static List<PlayQueueItem> extractChannelItems(final List<InfoItem> infos) { | ||||
|         List<PlayQueueItem> result = new ArrayList<>(); | ||||
|         for (final InfoItem stream : infos) { | ||||
|             if (stream instanceof StreamInfoItem) { | ||||
|                 result.add(new PlayQueueItem((StreamInfoItem) stream)); | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,150 +1,45 @@ | ||||
| package org.schabi.newpipe.playlist; | ||||
|  | ||||
| import android.util.Log; | ||||
|  | ||||
| import org.schabi.newpipe.extractor.InfoItem; | ||||
| import org.schabi.newpipe.extractor.ListExtractor; | ||||
| import org.schabi.newpipe.extractor.playlist.PlaylistInfo; | ||||
| import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; | ||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||||
| import org.schabi.newpipe.util.ExtractorHelper; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|  | ||||
| import io.reactivex.SingleObserver; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.annotations.NonNull; | ||||
| import io.reactivex.disposables.Disposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
|  | ||||
| public final class PlaylistPlayQueue extends PlayQueue { | ||||
|     private final String TAG = "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); | ||||
|  | ||||
|     private boolean isInitial; | ||||
|     private boolean isComplete; | ||||
|  | ||||
|     private int serviceId; | ||||
|     private String baseUrl; | ||||
|     private String nextUrl; | ||||
|  | ||||
|     private transient Disposable fetchReactor; | ||||
|  | ||||
| public final class PlaylistPlayQueue extends AbstractInfoPlayQueue<PlaylistInfo, PlaylistInfoItem> { | ||||
|     public PlaylistPlayQueue(final PlaylistInfoItem item) { | ||||
|         this(item.service_id, item.url, item.url, Collections.<InfoItem>emptyList(), 0); | ||||
|         super(item); | ||||
|     } | ||||
|  | ||||
|     public PlaylistPlayQueue(final int serviceId, | ||||
|                              final String url, | ||||
|                              final String nextPageUrl, | ||||
|                              final List<InfoItem> streams, | ||||
|                              final int index) { | ||||
|         super(index, extractPlaylistItems(streams)); | ||||
|  | ||||
|         this.baseUrl = url; | ||||
|         this.nextUrl = nextPageUrl; | ||||
|         this.serviceId = serviceId; | ||||
|  | ||||
|         this.isInitial = streams.isEmpty(); | ||||
|         this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); | ||||
|                             final String url, | ||||
|                             final String nextPageUrl, | ||||
|                             final List<InfoItem> streams, | ||||
|                             final int index) { | ||||
|         super(serviceId, url, nextPageUrl, streams, index); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean isComplete() { | ||||
|         return isComplete; | ||||
|     protected String getTag() { | ||||
|         return "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void fetch() { | ||||
|         if (isInitial) { | ||||
|         if (this.isInitial) { | ||||
|             ExtractorHelper.getPlaylistInfo(this.serviceId, this.baseUrl, false) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(getInitialPlaylistObserver()); | ||||
|                     .subscribe(getHeadListObserver()); | ||||
|         } else { | ||||
|             ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(getPlaylistNextItemsObserver()); | ||||
|                     .subscribe(getNextItemsObserver()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private SingleObserver<PlaylistInfo> getInitialPlaylistObserver() { | ||||
|         return new SingleObserver<PlaylistInfo>() { | ||||
|             @Override | ||||
|             public void onSubscribe(@NonNull Disposable d) { | ||||
|                 if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { | ||||
|                     d.dispose(); | ||||
|                 } else { | ||||
|                     fetchReactor = d; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull PlaylistInfo result) { | ||||
|                 if (!result.has_more_streams) isComplete = true; | ||||
|                 nextUrl = result.next_streams_url; | ||||
|  | ||||
|                 append(extractPlaylistItems(result.related_streams)); | ||||
|  | ||||
|                 fetchReactor.dispose(); | ||||
|                 fetchReactor = null; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(@NonNull Throwable e) { | ||||
|                 Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); | ||||
|                 isComplete = true; | ||||
|                 append(); // Notify change | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     private SingleObserver<ListExtractor.NextItemsResult> getPlaylistNextItemsObserver() { | ||||
|         return new SingleObserver<ListExtractor.NextItemsResult>() { | ||||
|             @Override | ||||
|             public void onSubscribe(@NonNull Disposable d) { | ||||
|                 if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { | ||||
|                     d.dispose(); | ||||
|                 } else { | ||||
|                     fetchReactor = d; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { | ||||
|                 if (!result.hasMoreStreams()) isComplete = true; | ||||
|                 nextUrl = result.nextItemsUrl; | ||||
|  | ||||
|                 append(extractPlaylistItems(result.nextItemsList)); | ||||
|  | ||||
|                 fetchReactor.dispose(); | ||||
|                 fetchReactor = null; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(@NonNull Throwable e) { | ||||
|                 Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); | ||||
|                 isComplete = true; | ||||
|                 append(); // Notify change | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void dispose() { | ||||
|         super.dispose(); | ||||
|         if (fetchReactor != null) fetchReactor.dispose(); | ||||
|     } | ||||
|  | ||||
|     private static List<PlayQueueItem> extractPlaylistItems(final List<InfoItem> infos) { | ||||
|         List<PlayQueueItem> result = new ArrayList<>(); | ||||
|         for (final InfoItem stream : infos) { | ||||
|             if (stream instanceof StreamInfoItem) { | ||||
|                 result.add(new PlayQueueItem((StreamInfoItem) stream)); | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,13 +31,13 @@ | ||||
|         android:layout_alignParentEnd="true" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:layout_alignParentTop="true" | ||||
|         android:layout_marginLeft="@dimen/video_item_search_image_right_margin" | ||||
|         android:layout_marginStart="@dimen/video_item_search_image_right_margin" | ||||
|         android:paddingLeft="@dimen/video_item_search_padding" | ||||
|         android:paddingStart="@dimen/video_item_search_padding" | ||||
|         android:background="?attr/selectableItemBackground" | ||||
|         android:src="?attr/more_vertical" | ||||
|         android:visibility="gone" | ||||
|         tools:ignore="ContentDescription" | ||||
|         tools:visibility="visible" /> | ||||
|         tools:visibility="visible" | ||||
|         tools:ignore="ContentDescription,RtlSymmetry"/> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/itemTitleView" | ||||
|   | ||||
| @@ -29,13 +29,13 @@ | ||||
|         android:layout_centerVertical="true" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:layout_alignParentEnd="true" | ||||
|         android:layout_marginLeft="@dimen/video_item_search_image_right_margin" | ||||
|         android:layout_marginStart="@dimen/video_item_search_image_right_margin" | ||||
|         android:paddingLeft="@dimen/video_item_search_padding" | ||||
|         android:paddingStart="@dimen/video_item_search_padding" | ||||
|         android:background="?attr/selectableItemBackground" | ||||
|         android:src="?attr/more_vertical" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible" | ||||
|         tools:ignore="ContentDescription"/> | ||||
|         tools:ignore="ContentDescription,RtlSymmetry"/> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/itemTitleView" | ||||
|   | ||||
| @@ -32,13 +32,13 @@ | ||||
|         android:layout_centerVertical="true" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:layout_alignParentEnd="true" | ||||
|         android:layout_marginLeft="@dimen/video_item_search_image_right_margin" | ||||
|         android:layout_marginStart="@dimen/video_item_search_image_right_margin" | ||||
|         android:paddingLeft="@dimen/video_item_search_padding" | ||||
|         android:paddingStart="@dimen/video_item_search_padding" | ||||
|         android:background="?attr/selectableItemBackground" | ||||
|         android:src="?attr/more_vertical" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible" | ||||
|         tools:ignore="ContentDescription"/> | ||||
|         tools:ignore="ContentDescription,RtlSymmetry"/> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/itemStreamCountView" | ||||
|   | ||||
| @@ -52,13 +52,13 @@ | ||||
|         android:layout_centerVertical="true" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:layout_alignParentEnd="true" | ||||
|         android:layout_marginLeft="@dimen/video_item_search_image_right_margin" | ||||
|         android:layout_marginStart="@dimen/video_item_search_image_right_margin" | ||||
|         android:paddingLeft="@dimen/video_item_search_padding" | ||||
|         android:paddingStart="@dimen/video_item_search_padding" | ||||
|         android:background="?attr/selectableItemBackground" | ||||
|         android:src="?attr/more_vertical" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible" | ||||
|         tools:ignore="ContentDescription"/> | ||||
|         tools:ignore="ContentDescription,RtlSymmetry"/> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/itemVideoTitleView" | ||||
|   | ||||
| @@ -51,13 +51,13 @@ | ||||
|         android:layout_centerVertical="true" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:layout_alignParentEnd="true" | ||||
|         android:layout_marginLeft="@dimen/video_item_search_image_right_margin" | ||||
|         android:layout_marginStart="@dimen/video_item_search_image_right_margin" | ||||
|         android:paddingLeft="@dimen/video_item_search_padding" | ||||
|         android:paddingStart="@dimen/video_item_search_padding" | ||||
|         android:background="?attr/selectableItemBackground" | ||||
|         android:src="?attr/more_vertical" | ||||
|         android:visibility="gone" | ||||
|         tools:visibility="visible" | ||||
|         tools:ignore="ContentDescription"/> | ||||
|         tools:ignore="ContentDescription,RtlSymmetry"/> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/itemVideoTitleView" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 John Zhen Mo
					John Zhen Mo