diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index a4ee01ccc..d0460c347 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -485,6 +485,8 @@ public class VideoDetailFragment extends BaseStateFragment implement private void showStreamDialog(final StreamInfoItem item) { final Context context = getContext(); + if (context == null || context.getResources() == null || getActivity() == null) return; + final String[] commands = new String[]{ context.getResources().getString(R.string.enqueue_on_background), context.getResources().getString(R.string.enqueue_on_popup) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index fd1e9ea63..ae17dafff 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -192,6 +192,8 @@ public abstract class BaseListFragment extends BaseStateFragment implem protected void showStreamDialog(final StreamInfoItem item) { final Context context = getContext(); + if (context == null || context.getResources() == null || getActivity() == null) return; + final String[] commands = new String[]{ context.getResources().getString(R.string.enqueue_on_background), context.getResources().getString(R.string.enqueue_on_popup) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index 348495079..857fb81e0 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -154,6 +154,8 @@ public class ChannelFragment extends BaseListInfoFragment { @Override protected void showStreamDialog(final StreamInfoItem item) { final Context context = getContext(); + if (context == null || context.getResources() == null || getActivity() == null) return; + final String[] commands = new String[]{ context.getResources().getString(R.string.enqueue_on_background), context.getResources().getString(R.string.enqueue_on_popup), diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 878dbf385..e7f7e9968 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -15,7 +15,6 @@ import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -109,6 +108,8 @@ public class PlaylistFragment extends BaseListInfoFragment { @Override protected void showStreamDialog(final StreamInfoItem item) { final Context context = getContext(); + if (context == null || context.getResources() == null || getActivity() == null) return; + final String[] commands = new String[]{ context.getResources().getString(R.string.enqueue_on_background), context.getResources().getString(R.string.enqueue_on_popup), diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java index 72152500f..1cc2ca19e 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java @@ -4,28 +4,44 @@ import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; public class InfoItemDialog { private final AlertDialog dialog; public InfoItemDialog(@NonNull final Activity activity, - @NonNull final InfoItem item, + @NonNull final StreamInfoItem info, @NonNull final String[] commands, @NonNull final DialogInterface.OnClickListener actions) { + this(activity, commands, actions, info.name, info.uploader_name); + } + + public InfoItemDialog(@NonNull final Activity activity, + @NonNull final String[] commands, + @NonNull final DialogInterface.OnClickListener actions, + @NonNull final String title, + @Nullable final String additionalDetail) { final LayoutInflater inflater = activity.getLayoutInflater(); final View bannerView = inflater.inflate(R.layout.dialog_title, null); bannerView.setSelected(true); + TextView titleView = bannerView.findViewById(R.id.itemTitleView); - titleView.setText(item.name); - TextView typeView = bannerView.findViewById(R.id.itemTypeView); - typeView.setText(item.info_type.name()); + titleView.setText(title); + + TextView detailsView = bannerView.findViewById(R.id.itemAdditionalDetails); + if (additionalDetail != null) { + detailsView.setText(additionalDetail); + detailsView.setVisibility(View.VISIBLE); + } else { + detailsView.setVisibility(View.GONE); + } dialog = new AlertDialog.Builder(activity) .setCustomTitle(bannerView) diff --git a/app/src/main/java/org/schabi/newpipe/util/InfoCache.java b/app/src/main/java/org/schabi/newpipe/util/InfoCache.java index 5b22af86a..a3fd7805a 100644 --- a/app/src/main/java/org/schabi/newpipe/util/InfoCache.java +++ b/app/src/main/java/org/schabi/newpipe/util/InfoCache.java @@ -26,6 +26,9 @@ import android.util.Log; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.extractor.Info; +import java.util.Map; +import java.util.concurrent.TimeUnit; + public final class InfoCache { private static final boolean DEBUG = MainActivity.DEBUG; @@ -37,9 +40,10 @@ public final class InfoCache { * Trim the cache to this size */ private static final int TRIM_CACHE_TO = 30; + private static final int DEFAULT_TIMEOUT_HOURS = 4; // TODO: Replace to one with timeout (like the one from guava) - private static final LruCache lruCache = new LruCache<>(MAX_ITEMS_ON_CACHE); + private static final LruCache lruCache = new LruCache<>(MAX_ITEMS_ON_CACHE); private InfoCache() { //no instance @@ -52,28 +56,29 @@ public final class InfoCache { public Info getFromKey(int serviceId, @NonNull String url) { if (DEBUG) Log.d(TAG, "getFromKey() called with: serviceId = [" + serviceId + "], url = [" + url + "]"); synchronized (lruCache) { - return lruCache.get(serviceId + url); + return getInfo(lruCache, keyOf(serviceId, url)); } } public void putInfo(@NonNull Info info) { if (DEBUG) Log.d(TAG, "putInfo() called with: info = [" + info + "]"); synchronized (lruCache) { - lruCache.put(info.service_id + info.url, info); + final CacheData data = new CacheData(info, DEFAULT_TIMEOUT_HOURS, TimeUnit.HOURS); + lruCache.put(keyOf(info), data); } } public void removeInfo(@NonNull Info info) { if (DEBUG) Log.d(TAG, "removeInfo() called with: info = [" + info + "]"); synchronized (lruCache) { - lruCache.remove(info.service_id + info.url); + lruCache.remove(keyOf(info)); } } public void removeInfo(int serviceId, @NonNull String url) { if (DEBUG) Log.d(TAG, "removeInfo() called with: serviceId = [" + serviceId + "], url = [" + url + "]"); synchronized (lruCache) { - lruCache.remove(serviceId + url); + lruCache.remove(keyOf(serviceId, url)); } } @@ -87,6 +92,7 @@ public final class InfoCache { public void trimCache() { if (DEBUG) Log.d(TAG, "trimCache() called"); synchronized (lruCache) { + removeStaleCache(lruCache); lruCache.trimToSize(TRIM_CACHE_TO); } } @@ -97,4 +103,51 @@ public final class InfoCache { } } + private static String keyOf(@NonNull final Info info) { + return keyOf(info.service_id, info.url); + } + + private static String keyOf(final int serviceId, @NonNull final String url) { + return serviceId + url; + } + + private static void removeStaleCache(@NonNull final LruCache cache) { + for (Map.Entry entry : cache.snapshot().entrySet()) { + final CacheData data = entry.getValue(); + if (data != null && data.isExpired()) { + cache.remove(entry.getKey()); + } + } + } + + private static Info getInfo(@NonNull final LruCache cache, + @NonNull final String key) { + final CacheData data = cache.get(key); + if (data == null) return null; + + if (data.isExpired()) { + cache.remove(key); + return null; + } + + return data.info; + } + + final private static class CacheData { + final private long expireTimestamp; + final private Info info; + + private CacheData(@NonNull final Info info, + final long timeout, + @NonNull final TimeUnit timeUnit) { + this.expireTimestamp = System.currentTimeMillis() + + TimeUnit.MILLISECONDS.convert(timeout, timeUnit); + + this.info = info; + } + + private boolean isExpired() { + return System.currentTimeMillis() > expireTimestamp; + } + } } diff --git a/app/src/main/res/layout/dialog_title.xml b/app/src/main/res/layout/dialog_title.xml index dc76a4f20..fa7e155d2 100644 --- a/app/src/main/res/layout/dialog_title.xml +++ b/app/src/main/res/layout/dialog_title.xml @@ -6,7 +6,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="false" - android:padding="@dimen/video_item_search_padding"> + android:paddingLeft="@dimen/video_item_search_padding" + android:paddingRight="@dimen/video_item_search_padding" + android:paddingTop="@dimen/video_item_search_padding"> \ No newline at end of file