Merge pull request #5187 from TiA4f8R/share-improvements
Share improvements + fix crash when no default browser is set on some devices
This commit is contained in:
commit
8c9f2af855
|
@ -10,6 +10,7 @@ import android.widget.OverScroller;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
|
@ -6,26 +6,16 @@ import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.multidex.MultiDexApplication;
|
import androidx.multidex.MultiDexApplication;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache;
|
import com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
|
||||||
import io.reactivex.rxjava3.exceptions.CompositeException;
|
|
||||||
import io.reactivex.rxjava3.exceptions.MissingBackpressureException;
|
|
||||||
import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException;
|
|
||||||
import io.reactivex.rxjava3.exceptions.UndeliverableException;
|
|
||||||
import io.reactivex.rxjava3.functions.Consumer;
|
|
||||||
import io.reactivex.rxjava3.plugins.RxJavaPlugins;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InterruptedIOException;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import org.acra.ACRA;
|
import org.acra.ACRA;
|
||||||
import org.acra.config.ACRAConfigurationException;
|
import org.acra.config.ACRAConfigurationException;
|
||||||
import org.acra.config.CoreConfiguration;
|
import org.acra.config.CoreConfiguration;
|
||||||
|
@ -41,6 +31,21 @@ import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.util.ServiceHelper;
|
import org.schabi.newpipe.util.ServiceHelper;
|
||||||
import org.schabi.newpipe.util.StateSaver;
|
import org.schabi.newpipe.util.StateSaver;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
import io.reactivex.rxjava3.exceptions.CompositeException;
|
||||||
|
import io.reactivex.rxjava3.exceptions.MissingBackpressureException;
|
||||||
|
import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException;
|
||||||
|
import io.reactivex.rxjava3.exceptions.UndeliverableException;
|
||||||
|
import io.reactivex.rxjava3.functions.Consumer;
|
||||||
|
import io.reactivex.rxjava3.plugins.RxJavaPlugins;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||||
* App.java is part of NewPipe.
|
* App.java is part of NewPipe.
|
||||||
|
|
|
@ -2,10 +2,10 @@ package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.extractor.downloader.Request;
|
import org.schabi.newpipe.extractor.downloader.Request;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
|
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -43,6 +41,7 @@ import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||||
|
@ -53,10 +52,9 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import org.schabi.newpipe.databinding.ActivityMainBinding;
|
import org.schabi.newpipe.databinding.ActivityMainBinding;
|
||||||
import org.schabi.newpipe.databinding.DrawerHeaderBinding;
|
import org.schabi.newpipe.databinding.DrawerHeaderBinding;
|
||||||
import org.schabi.newpipe.databinding.DrawerLayoutBinding;
|
import org.schabi.newpipe.databinding.DrawerLayoutBinding;
|
||||||
|
@ -89,6 +87,12 @@ import org.schabi.newpipe.util.TLSSocketFactoryCompat;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
import org.schabi.newpipe.views.FocusOverlayView;
|
import org.schabi.newpipe.views.FocusOverlayView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||||
|
|
|
@ -188,7 +188,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
.setPositiveButton(R.string.open_in_browser,
|
.setPositiveButton(R.string.open_in_browser,
|
||||||
(dialog, which) -> ShareUtils.openUrlInBrowser(this, url))
|
(dialog, which) -> ShareUtils.openUrlInBrowser(this, url))
|
||||||
.setNegativeButton(R.string.share,
|
.setNegativeButton(R.string.share,
|
||||||
(dialog, which) -> ShareUtils.shareUrl(this, "", url)) // no subject
|
(dialog, which) -> ShareUtils.shareText(this, "", url)) // no subject
|
||||||
.setNeutralButton(R.string.cancel, null)
|
.setNeutralButton(R.string.cancel, null)
|
||||||
.setOnDismissListener(dialog -> finish())
|
.setOnDismissListener(dialog -> finish())
|
||||||
.show();
|
.show();
|
||||||
|
|
|
@ -146,16 +146,17 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
aboutBinding.appVersion.setText(BuildConfig.VERSION_NAME);
|
aboutBinding.appVersion.setText(BuildConfig.VERSION_NAME);
|
||||||
|
|
||||||
aboutBinding.githubLink.setOnClickListener(nv ->
|
aboutBinding.githubLink.setOnClickListener(nv ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.github_url)));
|
openUrlInBrowser(context, context.getString(R.string.github_url), false));
|
||||||
|
|
||||||
aboutBinding.donationLink.setOnClickListener(v ->
|
aboutBinding.donationLink.setOnClickListener(v ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.donation_url)));
|
openUrlInBrowser(context, context.getString(R.string.donation_url), false));
|
||||||
|
|
||||||
aboutBinding.websiteLink.setOnClickListener(nv ->
|
aboutBinding.websiteLink.setOnClickListener(nv ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.website_url)));
|
openUrlInBrowser(context, context.getString(R.string.website_url), false));
|
||||||
|
|
||||||
aboutBinding.privacyPolicyLink.setOnClickListener(v ->
|
aboutBinding.privacyPolicyLink.setOnClickListener(v ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url)));
|
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url),
|
||||||
|
false));
|
||||||
|
|
||||||
return aboutBinding.getRoot();
|
return aboutBinding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.util.Linkify;
|
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -101,6 +100,7 @@ import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
import org.schabi.newpipe.util.PermissionHelper;
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
import org.schabi.newpipe.util.ShareUtils;
|
import org.schabi.newpipe.util.ShareUtils;
|
||||||
|
import org.schabi.newpipe.util.TextLinkifier;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
import org.schabi.newpipe.views.AnimatedProgressBar;
|
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||||
import org.schabi.newpipe.views.LargeTextMovementMethod;
|
import org.schabi.newpipe.views.LargeTextMovementMethod;
|
||||||
|
@ -112,10 +112,7 @@ import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
import io.noties.markwon.Markwon;
|
|
||||||
import io.noties.markwon.linkify.LinkifyPlugin;
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.core.Single;
|
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
@ -1232,28 +1229,20 @@ public final class VideoDetailFragment
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (description.getType() == Description.HTML) {
|
switch (description.getType()) {
|
||||||
disposables.add(Single.just(description.getContent())
|
case Description.HTML:
|
||||||
.map(descriptionText ->
|
disposables.add(TextLinkifier.createLinksFromHtmlBlock(requireContext(),
|
||||||
HtmlCompat.fromHtml(descriptionText,
|
description.getContent(), videoDescriptionView,
|
||||||
HtmlCompat.FROM_HTML_MODE_LEGACY))
|
HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||||
.subscribeOn(Schedulers.computation())
|
break;
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
case Description.MARKDOWN:
|
||||||
.subscribe(spanned -> {
|
disposables.add(TextLinkifier.createLinksFromMarkdownText(requireContext(),
|
||||||
videoDescriptionView.setText(spanned);
|
description.getContent(), videoDescriptionView));
|
||||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
break;
|
||||||
}));
|
case Description.PLAIN_TEXT: default:
|
||||||
} else if (description.getType() == Description.MARKDOWN) {
|
disposables.add(TextLinkifier.createLinksFromPlainText(requireContext(),
|
||||||
final Markwon markwon = Markwon.builder(requireContext())
|
description.getContent(), videoDescriptionView));
|
||||||
.usePlugin(LinkifyPlugin.create())
|
break;
|
||||||
.build();
|
|
||||||
markwon.setMarkdown(videoDescriptionView, description.getContent());
|
|
||||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
//== Description.PLAIN_TEXT
|
|
||||||
videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS);
|
|
||||||
videoDescriptionView.setText(description.getContent(), TextView.BufferType.SPANNABLE);
|
|
||||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1569,8 +1558,8 @@ public final class VideoDetailFragment
|
||||||
prepareDescription(info.getDescription());
|
prepareDescription(info.getDescription());
|
||||||
updateProgressInfo(info);
|
updateProgressInfo(info);
|
||||||
initThumbnailViews(info);
|
initThumbnailViews(info);
|
||||||
showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView, detailMetaInfoSeparator);
|
disposables.add(showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView,
|
||||||
|
detailMetaInfoSeparator));
|
||||||
|
|
||||||
if (player == null || player.isStopped()) {
|
if (player == null || player.isStopped()) {
|
||||||
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
|
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package org.schabi.newpipe.fragments.list.channel;
|
package org.schabi.newpipe.fragments.list.channel;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -188,8 +186,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
private void openRssFeed() {
|
private void openRssFeed() {
|
||||||
final ChannelInfo info = currentInfo;
|
final ChannelInfo info = currentInfo;
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(info.getFeedUrl()));
|
ShareUtils.openUrlInBrowser(requireContext(), info.getFeedUrl(), false);
|
||||||
startActivity(intent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +206,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
break;
|
break;
|
||||||
case R.id.menu_item_share:
|
case R.id.menu_item_share:
|
||||||
if (currentInfo != null) {
|
if (currentInfo != null) {
|
||||||
ShareUtils.shareUrl(requireContext(), name, currentInfo.getOriginalUrl());
|
ShareUtils.shareText(requireContext(), name, currentInfo.getOriginalUrl());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -242,7 +242,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
ShareUtils.openUrlInBrowser(requireContext(), url);
|
ShareUtils.openUrlInBrowser(requireContext(), url);
|
||||||
break;
|
break;
|
||||||
case R.id.menu_item_share:
|
case R.id.menu_item_share:
|
||||||
ShareUtils.shareUrl(requireContext(), name, url);
|
ShareUtils.shareText(requireContext(), name, url);
|
||||||
break;
|
break;
|
||||||
case R.id.menu_item_bookmark:
|
case R.id.menu_item_bookmark:
|
||||||
onBookmarkClicked();
|
onBookmarkClicked();
|
||||||
|
|
|
@ -280,8 +280,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
|
|
||||||
handleSearchSuggestion();
|
handleSearchSuggestion();
|
||||||
|
|
||||||
showMetaInfoInTextView(metaInfo == null ? null : Arrays.asList(metaInfo),
|
disposables.add(showMetaInfoInTextView(metaInfo == null ? null : Arrays.asList(metaInfo),
|
||||||
metaInfoTextView, metaInfoSeparator);
|
metaInfoTextView, metaInfoSeparator));
|
||||||
|
|
||||||
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) {
|
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) {
|
||||||
initSuggestionObserver();
|
initSuggestionObserver();
|
||||||
|
@ -1002,11 +1002,11 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
// List<MetaInfo> cannot be bundled without creating some containers
|
// List<MetaInfo> cannot be bundled without creating some containers
|
||||||
metaInfo = new MetaInfo[result.getMetaInfo().size()];
|
metaInfo = new MetaInfo[result.getMetaInfo().size()];
|
||||||
metaInfo = result.getMetaInfo().toArray(metaInfo);
|
metaInfo = result.getMetaInfo().toArray(metaInfo);
|
||||||
|
disposables.add(showMetaInfoInTextView(result.getMetaInfo(), metaInfoTextView,
|
||||||
|
metaInfoSeparator));
|
||||||
|
|
||||||
handleSearchSuggestion();
|
handleSearchSuggestion();
|
||||||
|
|
||||||
showMetaInfoInTextView(result.getMetaInfo(), metaInfoTextView, metaInfoSeparator);
|
|
||||||
|
|
||||||
lastSearchedString = searchString;
|
lastSearchedString = searchString;
|
||||||
nextPage = result.getNextPage();
|
nextPage = result.getNextPage();
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,14 @@ import android.widget.TextView;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
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.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
|
||||||
import org.schabi.newpipe.util.CommentTextOnTouchListener;
|
import org.schabi.newpipe.util.CommentTextOnTouchListener;
|
||||||
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
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.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package org.schabi.newpipe.info_list.holder;
|
package org.schabi.newpipe.info_list.holder;
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
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 androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
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;
|
||||||
|
|
|
@ -4,16 +4,15 @@ import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
|
@ -33,9 +33,9 @@ import org.schabi.newpipe.util.OnClickGesture;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
import io.reactivex.rxjava3.core.Single;
|
import io.reactivex.rxjava3.core.Single;
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||||
|
|
||||||
val actions = DialogInterface.OnClickListener { _, i ->
|
val actions = DialogInterface.OnClickListener { _, i ->
|
||||||
when (i) {
|
when (i) {
|
||||||
0 -> ShareUtils.shareUrl(requireContext(), selectedItem.name, selectedItem.url)
|
0 -> ShareUtils.shareText(requireContext(), selectedItem.name, selectedItem.url)
|
||||||
1 -> deleteChannel(selectedItem)
|
1 -> deleteChannel(selectedItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@ import android.view.WindowManager;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import org.schabi.newpipe.databinding.PlayerBinding;
|
|
||||||
import org.schabi.newpipe.App;
|
import org.schabi.newpipe.App;
|
||||||
|
import org.schabi.newpipe.databinding.PlayerBinding;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
|
|
@ -46,6 +46,7 @@ import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
import static org.schabi.newpipe.util.ShareUtils.shareText;
|
||||||
|
|
||||||
public final class PlayQueueActivity extends AppCompatActivity
|
public final class PlayQueueActivity extends AppCompatActivity
|
||||||
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
|
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
|
||||||
|
@ -311,7 +312,7 @@ public final class PlayQueueActivity extends AppCompatActivity
|
||||||
final MenuItem share = popupMenu.getMenu().add(RECYCLER_ITEM_POPUP_MENU_GROUP_ID, 3,
|
final MenuItem share = popupMenu.getMenu().add(RECYCLER_ITEM_POPUP_MENU_GROUP_ID, 3,
|
||||||
Menu.NONE, R.string.share);
|
Menu.NONE, R.string.share);
|
||||||
share.setOnMenuItemClickListener(menuItem -> {
|
share.setOnMenuItemClickListener(menuItem -> {
|
||||||
shareUrl(item.getTitle(), item.getUrl());
|
shareText(getApplicationContext(), item.getTitle(), item.getUrl());
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -505,18 +506,6 @@ public final class PlayQueueActivity extends AppCompatActivity
|
||||||
() -> PlaylistCreationDialog.newInstance(d).show(getSupportFragmentManager(), TAG));
|
() -> PlaylistCreationDialog.newInstance(d).show(getSupportFragmentManager(), TAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Share
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void shareUrl(final String subject, final String url) {
|
|
||||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
|
||||||
intent.setType("text/plain");
|
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, url);
|
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Binding Service Listener
|
// Binding Service Listener
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -3553,7 +3553,7 @@ public final class Player implements
|
||||||
&& currentMetadata.getMetadata().getServiceId() == YouTube.getServiceId()) {
|
&& currentMetadata.getMetadata().getServiceId() == YouTube.getServiceId()) {
|
||||||
videoUrl += ("&t=" + ts);
|
videoUrl += ("&t=" + ts);
|
||||||
}
|
}
|
||||||
ShareUtils.shareUrl(context, getVideoTitle(), videoUrl);
|
ShareUtils.shareText(context, getVideoTitle(), videoUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPlayWithKodiClicked() {
|
private void onPlayWithKodiClicked() {
|
||||||
|
|
|
@ -6,9 +6,12 @@ import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.schabi.newpipe.player.helper;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
|
@ -14,6 +13,7 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.util.SliderStrategy;
|
import org.schabi.newpipe.util.SliderStrategy;
|
||||||
|
|
|
@ -21,8 +21,8 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.BackpressureStrategy;
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.core.BackpressureStrategy;
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
@ -207,8 +206,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
openPrivacyPolicyDialog(this, "EMAIL"));
|
openPrivacyPolicyDialog(this, "EMAIL"));
|
||||||
|
|
||||||
activityErrorBinding.errorReportCopyButton.setOnClickListener(v -> {
|
activityErrorBinding.errorReportCopyButton.setOnClickListener(v -> {
|
||||||
ShareUtils.copyToClipboard(this, buildMarkdown());
|
ShareUtils.copyToClipboard(this, buildMarkdown());
|
||||||
Toast.makeText(this, R.string.msg_copied, Toast.LENGTH_SHORT).show();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
activityErrorBinding.errorReportGitHubButton.setOnClickListener(v ->
|
activityErrorBinding.errorReportGitHubButton.setOnClickListener(v ->
|
||||||
|
@ -246,11 +244,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
goToReturnActivity();
|
goToReturnActivity();
|
||||||
break;
|
break;
|
||||||
case R.id.menu_item_share_error:
|
case R.id.menu_item_share_error:
|
||||||
final Intent intent = new Intent();
|
ShareUtils.shareText(this, getString(R.string.error_report_title), buildJson());
|
||||||
intent.setAction(Intent.ACTION_SEND);
|
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, buildJson());
|
|
||||||
intent.setType("text/plain");
|
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -273,10 +267,10 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
|
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
|
||||||
.putExtra(Intent.EXTRA_TEXT, buildJson());
|
.putExtra(Intent.EXTRA_TEXT, buildJson());
|
||||||
if (i.resolveActivity(getPackageManager()) != null) {
|
if (i.resolveActivity(getPackageManager()) != null) {
|
||||||
startActivity(i);
|
ShareUtils.openIntentInApp(context, i);
|
||||||
}
|
}
|
||||||
} else if (action.equals("GITHUB")) { // open the NewPipe issue page on GitHub
|
} else if (action.equals("GITHUB")) { // open the NewPipe issue page on GitHub
|
||||||
ShareUtils.openUrlInBrowser(this, ERROR_GITHUB_ISSUE_URL);
|
ShareUtils.openUrlInBrowser(this, ERROR_GITHUB_ISSUE_URL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,12 +2,12 @@ package org.schabi.newpipe.settings;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
|
@ -30,8 +30,8 @@ import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
import io.reactivex.rxjava3.core.Observer;
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.core.Observer;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import android.widget.RadioButton;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
|
@ -22,7 +23,7 @@ import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
import androidx.core.widget.TextViewCompat;
|
import androidx.core.widget.TextViewCompat;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
import java.util.List;
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.player.MainPlayer;
|
import org.schabi.newpipe.player.MainPlayer;
|
||||||
import org.schabi.newpipe.player.NotificationConstants;
|
import org.schabi.newpipe.player.NotificationConstants;
|
||||||
|
@ -30,6 +31,8 @@ import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
import org.schabi.newpipe.views.FocusOverlayView;
|
import org.schabi.newpipe.views.FocusOverlayView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class NotificationActionsPreference extends Preference {
|
public class NotificationActionsPreference extends Preference {
|
||||||
|
|
||||||
public NotificationActionsPreference(final Context context, final AttributeSet attrs) {
|
public NotificationActionsPreference(final Context context, final AttributeSet attrs) {
|
||||||
|
|
|
@ -2,9 +2,10 @@ package org.schabi.newpipe.settings.tabs;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -23,8 +23,8 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Single;
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.core.Single;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
public class CommentTextOnTouchListener implements View.OnTouchListener {
|
public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
|
@ -69,7 +69,8 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
handled = handleUrl(v.getContext(), (URLSpan) link[0]);
|
handled = handleUrl(v.getContext(), (URLSpan) link[0]);
|
||||||
}
|
}
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
link[0].onClick(widget);
|
ShareUtils.openUrlInBrowser(v.getContext(),
|
||||||
|
((URLSpan) link[0]).getURL(), false);
|
||||||
}
|
}
|
||||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||||
Selection.setSelection(buffer,
|
Selection.setSelection(buffer,
|
||||||
|
|
|
@ -22,7 +22,6 @@ package org.schabi.newpipe.util;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.method.LinkMovementMethod;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -68,6 +67,7 @@ import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Maybe;
|
import io.reactivex.rxjava3.core.Maybe;
|
||||||
import io.reactivex.rxjava3.core.Single;
|
import io.reactivex.rxjava3.core.Single;
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||||
|
|
||||||
|
@ -325,10 +325,11 @@ public final class ExtractorHelper {
|
||||||
* @param metaInfos a list of meta information, can be null or empty
|
* @param metaInfos a list of meta information, can be null or empty
|
||||||
* @param metaInfoTextView the text view in which to show the formatted HTML
|
* @param metaInfoTextView the text view in which to show the formatted HTML
|
||||||
* @param metaInfoSeparator another view to be shown or hidden accordingly to the text view
|
* @param metaInfoSeparator another view to be shown or hidden accordingly to the text view
|
||||||
|
* @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed
|
||||||
*/
|
*/
|
||||||
public static void showMetaInfoInTextView(@Nullable final List<MetaInfo> metaInfos,
|
public static Disposable showMetaInfoInTextView(@Nullable final List<MetaInfo> metaInfos,
|
||||||
final TextView metaInfoTextView,
|
final TextView metaInfoTextView,
|
||||||
final View metaInfoSeparator) {
|
final View metaInfoSeparator) {
|
||||||
final Context context = metaInfoTextView.getContext();
|
final Context context = metaInfoTextView.getContext();
|
||||||
final boolean showMetaInfo = PreferenceManager.getDefaultSharedPreferences(context)
|
final boolean showMetaInfo = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getBoolean(context.getString(R.string.show_meta_info_key), true);
|
.getBoolean(context.getString(R.string.show_meta_info_key), true);
|
||||||
|
@ -336,6 +337,7 @@ public final class ExtractorHelper {
|
||||||
if (!showMetaInfo || metaInfos == null || metaInfos.isEmpty()) {
|
if (!showMetaInfo || metaInfos == null || metaInfos.isEmpty()) {
|
||||||
metaInfoTextView.setVisibility(View.GONE);
|
metaInfoTextView.setVisibility(View.GONE);
|
||||||
metaInfoSeparator.setVisibility(View.GONE);
|
metaInfoSeparator.setVisibility(View.GONE);
|
||||||
|
return Disposable.empty();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final StringBuilder stringBuilder = new StringBuilder();
|
final StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
@ -365,11 +367,9 @@ public final class ExtractorHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metaInfoTextView.setText(HtmlCompat.fromHtml(stringBuilder.toString(),
|
|
||||||
HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
|
|
||||||
metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
metaInfoTextView.setVisibility(View.VISIBLE);
|
|
||||||
metaInfoSeparator.setVisibility(View.VISIBLE);
|
metaInfoSeparator.setVisibility(View.VISIBLE);
|
||||||
|
return TextLinkifier.createLinksFromHtmlBlock(context, stringBuilder.toString(),
|
||||||
|
metaInfoTextView, HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
|
@ -4,11 +4,10 @@ import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
|
|
|
@ -9,10 +9,19 @@ import android.icu.text.CompactDecimalFormat;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.PluralsRes;
|
import androidx.annotation.PluralsRes;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.ocpsoft.prettytime.PrettyTime;
|
||||||
|
import org.ocpsoft.prettytime.units.Decade;
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.localization.ContentCountry;
|
||||||
|
import org.schabi.newpipe.ktx.OffsetDateTimeKt;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
|
@ -24,12 +33,6 @@ import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import org.ocpsoft.prettytime.PrettyTime;
|
|
||||||
import org.ocpsoft.prettytime.units.Decade;
|
|
||||||
import org.schabi.newpipe.R;
|
|
||||||
import org.schabi.newpipe.extractor.ListExtractor;
|
|
||||||
import org.schabi.newpipe.extractor.localization.ContentCountry;
|
|
||||||
import org.schabi.newpipe.ktx.OffsetDateTimeKt;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.schabi.newpipe.util;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
@ -46,9 +45,9 @@ import org.schabi.newpipe.local.history.StatisticsPlaylistFragment;
|
||||||
import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
|
import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionFragment;
|
import org.schabi.newpipe.local.subscription.SubscriptionFragment;
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionsImportFragment;
|
import org.schabi.newpipe.local.subscription.SubscriptionsImportFragment;
|
||||||
|
import org.schabi.newpipe.player.MainPlayer;
|
||||||
import org.schabi.newpipe.player.PlayQueueActivity;
|
import org.schabi.newpipe.player.PlayQueueActivity;
|
||||||
import org.schabi.newpipe.player.Player;
|
import org.schabi.newpipe.player.Player;
|
||||||
import org.schabi.newpipe.player.MainPlayer;
|
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHolder;
|
import org.schabi.newpipe.player.helper.PlayerHolder;
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
|
@ -57,6 +56,8 @@ import org.schabi.newpipe.settings.SettingsActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.util.ShareUtils.installApp;
|
||||||
|
|
||||||
public final class NavigationHelper {
|
public final class NavigationHelper {
|
||||||
public static final String MAIN_FRAGMENT_TAG = "main_fragment_tag";
|
public static final String MAIN_FRAGMENT_TAG = "main_fragment_tag";
|
||||||
public static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag";
|
public static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag";
|
||||||
|
@ -246,16 +247,14 @@ public final class NavigationHelper {
|
||||||
|
|
||||||
public static void resolveActivityOrAskToInstall(final Context context, final Intent intent) {
|
public static void resolveActivityOrAskToInstall(final Context context, final Intent intent) {
|
||||||
if (intent.resolveActivity(context.getPackageManager()) != null) {
|
if (intent.resolveActivity(context.getPackageManager()) != null) {
|
||||||
context.startActivity(intent);
|
ShareUtils.openIntentInApp(context, intent);
|
||||||
} else {
|
} else {
|
||||||
if (context instanceof Activity) {
|
if (context instanceof Activity) {
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setMessage(R.string.no_player_found)
|
.setMessage(R.string.no_player_found)
|
||||||
.setPositiveButton(R.string.install, (dialog, which) -> {
|
.setPositiveButton(R.string.install, (dialog, which) -> {
|
||||||
final Intent i = new Intent();
|
ShareUtils.openUrlInBrowser(context,
|
||||||
i.setAction(Intent.ACTION_VIEW);
|
context.getString(R.string.fdroid_vlc_url), false);
|
||||||
i.setData(Uri.parse(context.getString(R.string.fdroid_vlc_url)));
|
|
||||||
context.startActivity(i);
|
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.cancel, (dialog, which)
|
.setNegativeButton(R.string.cancel, (dialog, which)
|
||||||
-> Log.i("NavigationHelper", "You unlocked a secret unicorn."))
|
-> Log.i("NavigationHelper", "You unlocked a secret unicorn."))
|
||||||
|
@ -568,30 +567,6 @@ public final class NavigationHelper {
|
||||||
return getOpenIntent(context, url, service.getServiceId(), linkType);
|
return getOpenIntent(context, url, service.getServiceId(), linkType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Uri openMarketUrl(final String packageName) {
|
|
||||||
return Uri.parse("market://details")
|
|
||||||
.buildUpon()
|
|
||||||
.appendQueryParameter("id", packageName)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Uri getGooglePlayUrl(final String packageName) {
|
|
||||||
return Uri.parse("https://play.google.com/store/apps/details")
|
|
||||||
.buildUpon()
|
|
||||||
.appendQueryParameter("id", packageName)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void installApp(final Context context, final String packageName) {
|
|
||||||
try {
|
|
||||||
// Try market:// scheme
|
|
||||||
context.startActivity(new Intent(Intent.ACTION_VIEW, openMarketUrl(packageName)));
|
|
||||||
} catch (final ActivityNotFoundException e) {
|
|
||||||
// Fall back to google play URL (don't worry F-Droid can handle it :)
|
|
||||||
context.startActivity(new Intent(Intent.ACTION_VIEW, getGooglePlayUrl(packageName)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an activity to install Kore.
|
* Start an activity to install Kore.
|
||||||
*
|
*
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonArray;
|
import com.grack.nanojson.JsonArray;
|
||||||
|
|
|
@ -2,10 +2,10 @@ package org.schabi.newpipe.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.schabi.newpipe.util;
|
package org.schabi.newpipe.util;
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -17,26 +17,107 @@ public final class ShareUtils {
|
||||||
private ShareUtils() {
|
private ShareUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open an Intent to install an app.
|
||||||
|
* <p>
|
||||||
|
* This method will first try open to Google Play Store with the market scheme and falls back to
|
||||||
|
* Google Play Store web url if this first cannot be found.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param packageName the package to be installed
|
||||||
|
*/
|
||||||
|
public static void installApp(final Context context, final String packageName) {
|
||||||
|
try {
|
||||||
|
// Try market:// scheme
|
||||||
|
openIntentInApp(context, new Intent(Intent.ACTION_VIEW,
|
||||||
|
Uri.parse("market://details?id=" + packageName)));
|
||||||
|
} catch (final ActivityNotFoundException e) {
|
||||||
|
// Fall back to Google Play Store Web URL (don't worry, F-Droid can handle it :))
|
||||||
|
openUrlInBrowser(context,
|
||||||
|
"https://play.google.com/store/apps/details?id=" + packageName, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the url with the system default browser.
|
* Open the url with the system default browser.
|
||||||
* <p>
|
* <p>
|
||||||
* If no browser is set as default, fallbacks to
|
* If no browser is set as default, fallbacks to
|
||||||
* {@link ShareUtils#openInDefaultApp(Context, String)}
|
* {@link ShareUtils#openInDefaultApp(Context, Intent)}
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param url the url to browse
|
||||||
|
* @param httpDefaultBrowserTest the boolean to set if the test for the default browser will be
|
||||||
|
* for HTTP protocol or for the created intent
|
||||||
|
*/
|
||||||
|
public static void openUrlInBrowser(final Context context, final String url,
|
||||||
|
final boolean httpDefaultBrowserTest) {
|
||||||
|
final String defaultPackageName;
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||||
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (httpDefaultBrowserTest) {
|
||||||
|
defaultPackageName = getDefaultBrowserPackageName(context);
|
||||||
|
} else {
|
||||||
|
defaultPackageName = getDefaultAppPackageName(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultPackageName.equals("android")) {
|
||||||
|
// No browser set as default (doesn't work on some devices)
|
||||||
|
openInDefaultApp(context, intent);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
intent.setPackage(defaultPackageName);
|
||||||
|
context.startActivity(intent);
|
||||||
|
} catch (final ActivityNotFoundException e) {
|
||||||
|
// Not a browser but an app chooser because of OEMs changes
|
||||||
|
intent.setPackage(null);
|
||||||
|
openInDefaultApp(context, intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the url with the system default browser.
|
||||||
|
* <p>
|
||||||
|
* If no browser is set as default, fallbacks to
|
||||||
|
* {@link ShareUtils#openInDefaultApp(Context, Intent)}
|
||||||
|
* <p>
|
||||||
|
* This calls {@link ShareUtils#openUrlInBrowser(Context, String, boolean)} with true
|
||||||
|
* for the boolean parameter
|
||||||
*
|
*
|
||||||
* @param context the context to use
|
* @param context the context to use
|
||||||
* @param url the url to browse
|
* @param url the url to browse
|
||||||
*/
|
**/
|
||||||
public static void openUrlInBrowser(final Context context, final String url) {
|
public static void openUrlInBrowser(final Context context, final String url) {
|
||||||
final String defaultBrowserPackageName = getDefaultBrowserPackageName(context);
|
openUrlInBrowser(context, url, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (defaultBrowserPackageName.equals("android")) {
|
/**
|
||||||
// no browser set as default
|
* Open an intent with the system default app.
|
||||||
openInDefaultApp(context, url);
|
* <p>
|
||||||
|
* The intent can be of every type, excepted a web intent for which
|
||||||
|
* {@link ShareUtils#openUrlInBrowser(Context, String, boolean)} should be used.
|
||||||
|
* <p>
|
||||||
|
* If no app is set as default, fallbacks to
|
||||||
|
* {@link ShareUtils#openInDefaultApp(Context, Intent)}
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param intent the intent to open
|
||||||
|
*/
|
||||||
|
public static void openIntentInApp(final Context context, final Intent intent) {
|
||||||
|
final String defaultAppPackageName = getDefaultAppPackageName(context, intent);
|
||||||
|
|
||||||
|
if (defaultAppPackageName.equals("android")) {
|
||||||
|
// No app set as default (doesn't work on some devices)
|
||||||
|
openInDefaultApp(context, intent);
|
||||||
} else {
|
} else {
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
try {
|
||||||
.setPackage(defaultBrowserPackageName)
|
intent.setPackage(defaultAppPackageName);
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
context.startActivity(intent);
|
||||||
context.startActivity(intent);
|
} catch (final ActivityNotFoundException e) {
|
||||||
|
// Not an app to open the intent but an app chooser because of OEMs changes
|
||||||
|
intent.setPackage(null);
|
||||||
|
openInDefaultApp(context, intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,20 +126,38 @@ public final class ShareUtils {
|
||||||
* <p>
|
* <p>
|
||||||
* If no app is set as default, it will open a chooser
|
* If no app is set as default, it will open a chooser
|
||||||
*
|
*
|
||||||
* @param context the context to use
|
* @param context the context to use
|
||||||
* @param url the url to browse
|
* @param viewIntent the intent to open
|
||||||
*/
|
*/
|
||||||
private static void openInDefaultApp(final Context context, final String url) {
|
private static void openInDefaultApp(final Context context, final Intent viewIntent) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
final Intent intent = new Intent(Intent.ACTION_CHOOSER);
|
||||||
context.startActivity(Intent.createChooser(
|
intent.putExtra(Intent.EXTRA_INTENT, viewIntent);
|
||||||
intent, context.getString(R.string.share_dialog_title))
|
intent.putExtra(Intent.EXTRA_TITLE, context.getString(R.string.open_with));
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default app package name.
|
||||||
|
* <p>
|
||||||
|
* If no app is set as default, it will return "android".
|
||||||
|
* <p>
|
||||||
|
* Note: it doesn't return "android" on some devices because some OEMs changed the app chooser.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param intent the intent to get default app
|
||||||
|
* @return the package name of the default app, or the app chooser if there's no default
|
||||||
|
*/
|
||||||
|
private static String getDefaultAppPackageName(final Context context, final Intent intent) {
|
||||||
|
return context.getPackageManager().resolveActivity(intent,
|
||||||
|
PackageManager.MATCH_DEFAULT_ONLY).activityInfo.packageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default browser package name.
|
* Get the default browser package name.
|
||||||
* <p>
|
* <p>
|
||||||
* If no browser is set as default, it will return "android"
|
* If no browser is set as default, it will return "android"
|
||||||
|
* Note: it doesn't return "android" on some devices because some OEMs changed the app chooser.
|
||||||
*
|
*
|
||||||
* @param context the context to use
|
* @param context the context to use
|
||||||
* @return the package name of the default browser, or "android" if there's no default
|
* @return the package name of the default browser, or "android" if there's no default
|
||||||
|
@ -66,9 +165,8 @@ public final class ShareUtils {
|
||||||
private static String getDefaultBrowserPackageName(final Context context) {
|
private static String getDefaultBrowserPackageName(final Context context) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"))
|
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"))
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
final ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(
|
return context.getPackageManager().resolveActivity(intent,
|
||||||
intent, PackageManager.MATCH_DEFAULT_ONLY);
|
PackageManager.MATCH_DEFAULT_ONLY).activityInfo.packageName;
|
||||||
return resolveInfo.activityInfo.packageName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,14 +176,17 @@ public final class ShareUtils {
|
||||||
* @param subject the url subject, typically the title
|
* @param subject the url subject, typically the title
|
||||||
* @param url the url to share
|
* @param url the url to share
|
||||||
*/
|
*/
|
||||||
public static void shareUrl(final Context context, final String subject, final String url) {
|
public static void shareText(final Context context, final String subject, final String url) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.setType("text/plain");
|
shareIntent.setType("text/plain");
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, url);
|
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||||
context.startActivity(Intent.createChooser(
|
|
||||||
intent, context.getString(R.string.share_dialog_title))
|
final Intent intent = new Intent(Intent.ACTION_CHOOSER);
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
intent.putExtra(Intent.EXTRA_INTENT, shareIntent);
|
||||||
|
intent.putExtra(Intent.EXTRA_TITLE, context.getString(R.string.share_dialog_title));
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,14 +201,11 @@ public final class ShareUtils {
|
||||||
ContextCompat.getSystemService(context, ClipboardManager.class);
|
ContextCompat.getSystemService(context, ClipboardManager.class);
|
||||||
|
|
||||||
if (clipboardManager == null) {
|
if (clipboardManager == null) {
|
||||||
Toast.makeText(context,
|
Toast.makeText(context, R.string.permission_denied, Toast.LENGTH_LONG).show();
|
||||||
R.string.permission_denied,
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text));
|
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||||
Toast.makeText(context, R.string.msg_copied, Toast.LENGTH_SHORT)
|
Toast.makeText(context, R.string.msg_copied, Toast.LENGTH_SHORT).show();
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ public enum StreamDialogEntry {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
share(R.string.share, (fragment, item) ->
|
share(R.string.share, (fragment, item) ->
|
||||||
ShareUtils.shareUrl(fragment.getContext(), item.getName(), item.getUrl()));
|
ShareUtils.shareText(fragment.getContext(), item.getName(), item.getUrl()));
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
package org.schabi.newpipe.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
|
import android.text.style.URLSpan;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.text.HtmlCompat;
|
||||||
|
|
||||||
|
import io.noties.markwon.Markwon;
|
||||||
|
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.core.Single;
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
|
public final class TextLinkifier {
|
||||||
|
public static final String TAG = TextLinkifier.class.getSimpleName();
|
||||||
|
|
||||||
|
private TextLinkifier() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create web links for contents with an HTML description.
|
||||||
|
* <p>
|
||||||
|
* This will call
|
||||||
|
* {@link TextLinkifier#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView)}
|
||||||
|
* after having linked the URLs with {@link HtmlCompat#fromHtml(String, int)}.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param htmlBlock the htmlBlock to be linked
|
||||||
|
* @param textView the TextView to set the htmlBlock linked
|
||||||
|
* @param htmlCompatFlag the int flag to be set when {@link HtmlCompat#fromHtml(String, int)}
|
||||||
|
* will be called
|
||||||
|
* @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed
|
||||||
|
*/
|
||||||
|
public static Disposable createLinksFromHtmlBlock(final Context context,
|
||||||
|
final String htmlBlock,
|
||||||
|
final TextView textView,
|
||||||
|
final int htmlCompatFlag) {
|
||||||
|
return changeIntentsOfDescriptionLinks(context,
|
||||||
|
HtmlCompat.fromHtml(htmlBlock, htmlCompatFlag), textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create web links for contents with a plain text description.
|
||||||
|
* <p>
|
||||||
|
* This will call
|
||||||
|
* {@link TextLinkifier#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView)}
|
||||||
|
* after having linked the URLs with {@link TextView#setAutoLinkMask(int)} and
|
||||||
|
* {@link TextView#setText(CharSequence, TextView.BufferType)}.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param plainTextBlock the block of plain text to be linked
|
||||||
|
* @param textView the TextView to set the plain text block linked
|
||||||
|
* @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed
|
||||||
|
*/
|
||||||
|
public static Disposable createLinksFromPlainText(final Context context,
|
||||||
|
final String plainTextBlock,
|
||||||
|
final TextView textView) {
|
||||||
|
textView.setAutoLinkMask(Linkify.WEB_URLS);
|
||||||
|
textView.setText(plainTextBlock, TextView.BufferType.SPANNABLE);
|
||||||
|
return changeIntentsOfDescriptionLinks(context, textView.getText(), textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create web links for contents with a markdown description.
|
||||||
|
* <p>
|
||||||
|
* This will call
|
||||||
|
* {@link TextLinkifier#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView)}
|
||||||
|
* after creating an {@link Markwon} object and using
|
||||||
|
* {@link Markwon#setMarkdown(TextView, String)}.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param markdownBlock the block of markdown text to be linked
|
||||||
|
* @param textView the TextView to set the plain text block linked
|
||||||
|
* @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed
|
||||||
|
*/
|
||||||
|
public static Disposable createLinksFromMarkdownText(final Context context,
|
||||||
|
final String markdownBlock,
|
||||||
|
final TextView textView) {
|
||||||
|
final Markwon markwon = Markwon.builder(context).usePlugin(LinkifyPlugin.create()).build();
|
||||||
|
markwon.setMarkdown(textView, markdownBlock);
|
||||||
|
return changeIntentsOfDescriptionLinks(context, textView.getText(), textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change links generated by libraries in the description of a content to a custom link action.
|
||||||
|
* <p>
|
||||||
|
* Instead of using an {@link android.content.Intent#ACTION_VIEW} intent in the description of a
|
||||||
|
* content, this method will parse the {@link CharSequence} and replace all current web links
|
||||||
|
* with {@link ShareUtils#openUrlInBrowser(Context, String, boolean)}.
|
||||||
|
* <p>
|
||||||
|
* This method is required in order to intercept links and e.g. show a confirmation dialog
|
||||||
|
* before opening a web link.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param chars the CharSequence to be parsed
|
||||||
|
* @param textView the TextView in which the converted CharSequence will be applied
|
||||||
|
* @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed
|
||||||
|
*/
|
||||||
|
private static Disposable changeIntentsOfDescriptionLinks(final Context context,
|
||||||
|
final CharSequence chars,
|
||||||
|
final TextView textView) {
|
||||||
|
return Single.fromCallable(() -> {
|
||||||
|
final SpannableStringBuilder textBlockLinked = new SpannableStringBuilder(chars);
|
||||||
|
final URLSpan[] urls = textBlockLinked.getSpans(0, chars.length(), URLSpan.class);
|
||||||
|
|
||||||
|
for (final URLSpan span : urls) {
|
||||||
|
final ClickableSpan clickableSpan = new ClickableSpan() {
|
||||||
|
public void onClick(@NonNull final View view) {
|
||||||
|
ShareUtils.openUrlInBrowser(context, span.getURL(), false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
textBlockLinked.setSpan(clickableSpan, textBlockLinked.getSpanStart(span),
|
||||||
|
textBlockLinked.getSpanEnd(span), textBlockLinked.getSpanFlags(span));
|
||||||
|
textBlockLinked.removeSpan(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
return textBlockLinked;
|
||||||
|
}).subscribeOn(Schedulers.computation())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
textBlockLinked -> setTextViewCharSequence(textView, textBlockLinked),
|
||||||
|
throwable -> {
|
||||||
|
Log.e(TAG, "Unable to linkify text", throwable);
|
||||||
|
// this should never happen, but if it does, just fallback to it
|
||||||
|
setTextViewCharSequence(textView, chars);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setTextViewCharSequence(final TextView textView,
|
||||||
|
final CharSequence charSequence) {
|
||||||
|
textView.setText(charSequence);
|
||||||
|
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
textView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,6 @@ package org.schabi.newpipe.util;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
|
|
||||||
|
@ -32,6 +31,7 @@ import androidx.annotation.StyleRes;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
|
|
@ -2,10 +2,12 @@ package org.schabi.newpipe.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||||
|
|
||||||
public class CustomCollapsingToolbarLayout extends CollapsingToolbarLayout {
|
public class CustomCollapsingToolbarLayout extends CollapsingToolbarLayout {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FIT;
|
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FIT;
|
||||||
|
|
|
@ -24,11 +24,12 @@ import android.os.Build;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
public final class FocusAwareCoordinator extends CoordinatorLayout {
|
public final class FocusAwareCoordinator extends CoordinatorLayout {
|
||||||
|
|
|
@ -24,10 +24,6 @@ import android.os.Handler.Callback;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import androidx.core.app.ServiceCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -37,6 +33,9 @@ import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationCompat.Builder;
|
import androidx.core.app.NotificationCompat.Builder;
|
||||||
|
import androidx.core.app.ServiceCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.download.DownloadActivity;
|
import org.schabi.newpipe.download.DownloadActivity;
|
||||||
|
|
|
@ -2,6 +2,7 @@ package us.shandian.giga.ui.adapter;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
@ -44,6 +45,7 @@ import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.ErrorInfo;
|
import org.schabi.newpipe.report.ErrorInfo;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.ShareUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -346,10 +348,9 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
||||||
if (BuildConfig.DEBUG)
|
if (BuildConfig.DEBUG)
|
||||||
Log.v(TAG, "Mime: " + mimeType + " package: " + BuildConfig.APPLICATION_ID + ".provider");
|
Log.v(TAG, "Mime: " + mimeType + " package: " + BuildConfig.APPLICATION_ID + ".provider");
|
||||||
|
|
||||||
Uri uri = resolveShareableUri(mission);
|
final Uri uri = resolveShareableUri(mission);
|
||||||
|
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
|
||||||
intent.setDataAndType(uri, mimeType);
|
intent.setDataAndType(uri, mimeType);
|
||||||
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
|
||||||
|
@ -363,7 +364,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
||||||
//mContext.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
//mContext.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
|
||||||
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
||||||
mContext.startActivity(intent);
|
ShareUtils.openIntentInApp(mContext, intent);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(mContext, R.string.toast_no_player, Toast.LENGTH_LONG).show();
|
Toast.makeText(mContext, R.string.toast_no_player, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -372,12 +373,23 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
||||||
private void shareFile(Mission mission) {
|
private void shareFile(Mission mission) {
|
||||||
if (checkInvalidFile(mission)) return;
|
if (checkInvalidFile(mission)) return;
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.setType(resolveMimeType(mission));
|
shareIntent.setType(resolveMimeType(mission));
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, resolveShareableUri(mission));
|
shareIntent.putExtra(Intent.EXTRA_STREAM, resolveShareableUri(mission));
|
||||||
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
shareIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_CHOOSER);
|
||||||
|
intent.putExtra(Intent.EXTRA_INTENT, shareIntent);
|
||||||
|
intent.putExtra(Intent.EXTRA_TITLE, mContext.getString(R.string.share_dialog_title));
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
||||||
mContext.startActivity(Intent.createChooser(intent, null));
|
try {
|
||||||
|
intent.setPackage("android");
|
||||||
|
mContext.startActivity(intent);
|
||||||
|
} catch (final ActivityNotFoundException e) {
|
||||||
|
// falling back to OEM chooser if Android's system chooser was removed by the OEM
|
||||||
|
intent.setPackage(null);
|
||||||
|
mContext.startActivity(intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
@ -21,6 +20,7 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
|
@ -651,4 +651,5 @@
|
||||||
<string name="notification_colorize_summary">Demander à Android de personnaliser la couleur de la notification en fonction de la couleur principale de la miniature (noter que cela n’est pas disponible sur tous les appareils)</string>
|
<string name="notification_colorize_summary">Demander à Android de personnaliser la couleur de la notification en fonction de la couleur principale de la miniature (noter que cela n’est pas disponible sur tous les appareils)</string>
|
||||||
<string name="show_thumbnail_title">Afficher la miniature</string>
|
<string name="show_thumbnail_title">Afficher la miniature</string>
|
||||||
<string name="show_thumbnail_summary">Utiliser la miniature pour l\'arrière-plan de l’écran de verrouillage et les notifications</string>
|
<string name="show_thumbnail_summary">Utiliser la miniature pour l\'arrière-plan de l’écran de verrouillage et les notifications</string>
|
||||||
|
<string name="open_with">Ouvrir avec</string>
|
||||||
</resources>
|
</resources>
|
|
@ -11,6 +11,7 @@
|
||||||
<string name="fdroid_vlc_url" translatable="false">https://f-droid.org/repository/browse/?fdfilter=vlc&fdid=org.videolan.vlc</string>
|
<string name="fdroid_vlc_url" translatable="false">https://f-droid.org/repository/browse/?fdfilter=vlc&fdid=org.videolan.vlc</string>
|
||||||
<string name="open_in_browser">Open in browser</string>
|
<string name="open_in_browser">Open in browser</string>
|
||||||
<string name="open_in_popup_mode">Open in popup mode</string>
|
<string name="open_in_popup_mode">Open in popup mode</string>
|
||||||
|
<string name="open_with">Open with</string>
|
||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
<string name="download">Download</string>
|
<string name="download">Download</string>
|
||||||
<string name="controls_download_desc">Download stream file</string>
|
<string name="controls_download_desc">Download stream file</string>
|
||||||
|
|
|
@ -12,21 +12,20 @@
|
||||||
lines="253,325"/>
|
lines="253,325"/>
|
||||||
|
|
||||||
<suppress checks="FinalParameters"
|
<suppress checks="FinalParameters"
|
||||||
files="ListHelper.java"
|
files="ListHelper.java"
|
||||||
lines="281,313"/>
|
lines="280,312"/>
|
||||||
|
|
||||||
<suppress checks="EmptyBlock"
|
<suppress checks="EmptyBlock"
|
||||||
files="ContentSettingsFragment.java"
|
files="ContentSettingsFragment.java"
|
||||||
lines="227,245"/>
|
lines="227,245"/>
|
||||||
|
|
||||||
<!-- org.schabi.newpipe.streams -->
|
|
||||||
<suppress checks="LineLength"
|
<suppress checks="LineLength"
|
||||||
files="WebMWriter.java"
|
files="WebMWriter.java"
|
||||||
lines="156,158"/>
|
lines="156,158"/>
|
||||||
|
|
||||||
<suppress checks="FileLength"
|
<suppress checks="FileLength"
|
||||||
files="Player.java"/>
|
files="Player.java"/>
|
||||||
|
|
||||||
<suppress checks="FileLength"
|
<suppress checks="FileLength"
|
||||||
files="VideoDetailFragment.java"/>
|
files="VideoDetailFragment.java"/>
|
||||||
</suppressions>
|
</suppressions>
|
||||||
|
|
Loading…
Reference in New Issue