diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..2c79d62cd --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +liberapay: TeamNewPipe diff --git a/app/build.gradle b/app/build.gradle index 2ddfecabe..c70d583b2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "org.schabi.newpipe" minSdkVersion 19 targetSdkVersion 28 - versionCode 750 - versionName "0.17.0" + versionCode 760 + versionName "0.17.1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -57,7 +57,7 @@ dependencies { exclude module: 'support-annotations' }) - implementation 'com.github.TeamNewPipe:NewPipeExtractor:5f65788a2f89e' + implementation 'com.github.teamnewpipe:NewPipeExtractor:430da57350c587828' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.23.0' diff --git a/app/src/main/java/org/schabi/newpipe/Downloader.java b/app/src/main/java/org/schabi/newpipe/Downloader.java index ff274a91a..11209a01e 100644 --- a/app/src/main/java/org/schabi/newpipe/Downloader.java +++ b/app/src/main/java/org/schabi/newpipe/Downloader.java @@ -164,7 +164,7 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader { final ResponseBody body = response.body(); if (response.code() == 429) { - throw new ReCaptchaException("reCaptcha Challenge requested"); + throw new ReCaptchaException("reCaptcha Challenge requested", siteUrl); } if (body == null) { @@ -214,7 +214,7 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader { final ResponseBody body = response.body(); if (response.code() == 429) { - throw new ReCaptchaException("reCaptcha Challenge requested"); + throw new ReCaptchaException("reCaptcha Challenge requested", siteUrl); } if (body == null) { @@ -268,7 +268,7 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader { final ResponseBody body = response.body(); if (response.code() == 429) { - throw new ReCaptchaException("reCaptcha Challenge requested"); + throw new ReCaptchaException("reCaptcha Challenge requested", siteUrl); } if (body == null) { diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index bf538cc65..a9f2e9622 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -60,6 +60,7 @@ import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.StateSaver; import org.schabi.newpipe.util.ThemeHelper; @@ -421,6 +422,17 @@ public class MainActivity extends AppCompatActivity { return; } } + switch (requestCode) { + case PermissionHelper.DOWNLOADS_REQUEST_CODE: + NavigationHelper.openDownloads(this); + break; + case PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE: + Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder); + if (fragment instanceof VideoDetailFragment) { + ((VideoDetailFragment) fragment).openDownloadDialog(); + } + break; + } } /** diff --git a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java index 74c818bf9..55deeec5f 100644 --- a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java +++ b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java @@ -37,15 +37,24 @@ import android.webkit.WebViewClient; */ public class ReCaptchaActivity extends AppCompatActivity { public static final int RECAPTCHA_REQUEST = 10; + public static final String RECAPTCHA_URL_EXTRA = "recaptcha_url_extra"; public static final String TAG = ReCaptchaActivity.class.toString(); public static final String YT_URL = "https://www.youtube.com"; + private String url; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recaptcha); + url = getIntent().getStringExtra(RECAPTCHA_URL_EXTRA); + if (url == null || url.isEmpty()) { + url = YT_URL; + } + + // Set return to Cancel by default setResult(RESULT_CANCELED); @@ -73,15 +82,12 @@ public class ReCaptchaActivity extends AppCompatActivity { myWebView.clearHistory(); android.webkit.CookieManager cookieManager = CookieManager.getInstance(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - cookieManager.removeAllCookies(new ValueCallback() { - @Override - public void onReceiveValue(Boolean aBoolean) {} - }); + cookieManager.removeAllCookies(aBoolean -> {}); } else { cookieManager.removeAllCookie(); } - myWebView.loadUrl(YT_URL); + myWebView.loadUrl(url); } private class ReCaptchaWebViewClient extends WebViewClient { diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 88f6bdb2b..89de0d0ef 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -74,10 +74,13 @@ import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr; */ public class RouterActivity extends AppCompatActivity { - @State protected int currentServiceId = -1; + @State + protected int currentServiceId = -1; private StreamingService currentService; - @State protected LinkType currentLinkType; - @State protected int selectedRadioPosition = -1; + @State + protected LinkType currentLinkType; + @State + protected int selectedRadioPosition = -1; protected int selectedPreviously = -1; protected String currentUrl; @@ -257,7 +260,7 @@ public class RouterActivity extends AppCompatActivity { .setNegativeButton(R.string.just_once, dialogButtonsClickListener) .setPositiveButton(R.string.always, dialogButtonsClickListener) .setOnDismissListener((dialog) -> { - if(!selectionIsDownload) finish(); + if (!selectionIsDownload) finish(); }) .create(); @@ -358,13 +361,13 @@ public class RouterActivity extends AppCompatActivity { positiveButton.setEnabled(state); } - private void handleText(){ + private void handleText() { String searchString = getIntent().getStringExtra(Intent.EXTRA_TEXT); int serviceId = getIntent().getIntExtra(Constants.KEY_SERVICE_ID, 0); Intent intent = new Intent(getThemeWrapperContext(), MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); - NavigationHelper.openSearch(getThemeWrapperContext(),serviceId,searchString); + NavigationHelper.openSearch(getThemeWrapperContext(), serviceId, searchString); } private void handleChoice(final String selectedChoiceKey) { @@ -382,8 +385,10 @@ public class RouterActivity extends AppCompatActivity { } if (selectedChoiceKey.equals(getString(R.string.download_key))) { - selectionIsDownload = true; - openDownloadDialog(); + if (PermissionHelper.checkStoragePermissions(this, PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) { + selectionIsDownload = true; + openDownloadDialog(); + } return; } @@ -395,7 +400,7 @@ public class RouterActivity extends AppCompatActivity { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(intent -> { - if(!internalRoute){ + if (!internalRoute) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); } @@ -445,17 +450,21 @@ public class RouterActivity extends AppCompatActivity { @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - for (int i: grantResults){ - if (i == PackageManager.PERMISSION_DENIED){ + for (int i : grantResults) { + if (i == PackageManager.PERMISSION_DENIED) { finish(); return; } } + if (requestCode == PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE) { + openDownloadDialog(); + } } private static class AdapterChoiceItem { final String description, key; - @DrawableRes final int icon; + @DrawableRes + final int icon; AdapterChoiceItem(String key, String description, int icon) { this.description = description; @@ -553,7 +562,8 @@ public class RouterActivity extends AppCompatActivity { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); boolean isExtVideoEnabled = preferences.getBoolean(getString(R.string.use_external_video_player_key), false); - boolean isExtAudioEnabled = preferences.getBoolean(getString(R.string.use_external_audio_player_key), false);; + boolean isExtAudioEnabled = preferences.getBoolean(getString(R.string.use_external_audio_player_key), false); + ; PlayQueue playQueue; String playerChoice = choice.playerChoice; diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java index 41971dfd4..2bc200f05 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java @@ -61,6 +61,7 @@ public class DownloadActivity extends AppCompatActivity { .commit(); } + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); @@ -86,9 +87,4 @@ public class DownloadActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } } - - @Override - public void onRestoreInstanceState(Bundle inState){ - super.onRestoreInstanceState(inState); - } } diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index ea212e1e8..f77daa092 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -8,6 +8,7 @@ import android.content.ServiceConnection; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.annotation.IdRes; @@ -33,6 +34,8 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; +import com.nononsenseapps.filepicker.Utils; + import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.MediaFormat; @@ -45,13 +48,17 @@ import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.UserAction; +import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.util.FilePickerActivityHelper; import org.schabi.newpipe.util.FilenameUtils; import org.schabi.newpipe.util.ListHelper; +import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.SecondaryStreamHelper; import org.schabi.newpipe.util.StreamItemAdapter; import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper; import org.schabi.newpipe.util.ThemeHelper; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -72,7 +79,7 @@ import us.shandian.giga.service.MissionState; public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheckedChangeListener, AdapterView.OnItemSelectedListener { private static final String TAG = "DialogFragment"; private static final boolean DEBUG = MainActivity.DEBUG; - private static final int REQUEST_DOWNLOAD_PATH_SAF = 0x1230; + private static final int REQUEST_DOWNLOAD_SAVE_AS = 0x1230; @State protected StreamInfo currentInfo; @@ -173,6 +180,11 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]"); + if (!PermissionHelper.checkStoragePermissions(getActivity(), PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) { + getDialog().dismiss(); + return; + } + context = getContext(); setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context)); @@ -311,12 +323,18 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_DOWNLOAD_PATH_SAF && resultCode == Activity.RESULT_OK) { + if (requestCode == REQUEST_DOWNLOAD_SAVE_AS && resultCode == Activity.RESULT_OK) { if (data.getData() == null) { showFailedDialog(R.string.general_error); return; } + if (FilePickerActivityHelper.isOwnFileUri(context, data.getData())) { + File file = Utils.getFileForUri(data.getData()); + checkSelectedDownload(null, Uri.fromFile(file), file.getName(), StoredFileHelper.DEFAULT_MIME); + return; + } + DocumentFile docFile = DocumentFile.fromSingleUri(context, data.getData()); if (docFile == null) { showFailedDialog(R.string.general_error); @@ -569,12 +587,27 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck // This part is called if with SAF preferred: // * older android version running // * save path not defined (via download settings) - // * the user as checked the "ask where to download" option + // * the user checked the "ask where to download" option if (!askForSavePath) Toast.makeText(context, getString(R.string.no_available_dir), Toast.LENGTH_LONG).show(); - StoredFileHelper.requestSafWithFileCreation(this, REQUEST_DOWNLOAD_PATH_SAF, filename, mime); + if (NewPipeSettings.useStorageAccessFramework(context)) { + StoredFileHelper.requestSafWithFileCreation(this, REQUEST_DOWNLOAD_SAVE_AS, filename, mime); + } else { + File initialSavePath; + if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.audio_button) + initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MUSIC); + else + initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MOVIES); + + initialSavePath = new File(initialSavePath, filename); + startActivityForResult( + FilePickerActivityHelper.chooseFileToSave(context, initialSavePath.getAbsolutePath()), + REQUEST_DOWNLOAD_SAVE_AS + ); + } + return; } @@ -624,6 +657,11 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck // This part is called if: // * using SAF on older android version // * save path not defined + // * if the file exists overwrite it, is not necessary ask + if (!storage.existsAsFile() && !storage.create()) { + showFailedDialog(R.string.error_file_creation); + return; + } continueSelectedDownload(storage); return; } else if (targetFile == null) { @@ -728,7 +766,7 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck try { if (storage.length() > 0) storage.truncate(); } catch (IOException e) { - Log.e(TAG, "failed to overwrite the file: " + storage.getUri().toString(), e); + Log.e(TAG, "failed to truncate the file: " + storage.getUri().toString(), e); showFailedDialog(R.string.overwrite_failed); return; } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java index 4546483d2..e2bf9fb73 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java @@ -180,7 +180,7 @@ public abstract class BaseStateFragment extends BaseFragment implements ViewC } if (exception instanceof ReCaptchaException) { - onReCaptchaException(); + onReCaptchaException((ReCaptchaException) exception); return true; } else if (exception instanceof IOException) { showError(getString(R.string.network_error), true); @@ -190,11 +190,13 @@ public abstract class BaseStateFragment extends BaseFragment implements ViewC return false; } - public void onReCaptchaException() { + public void onReCaptchaException(ReCaptchaException exception) { if (DEBUG) Log.d(TAG, "onReCaptchaException() called"); Toast.makeText(activity, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show(); // Starting ReCaptcha Challenge Activity - startActivityForResult(new Intent(activity, ReCaptchaActivity.class), ReCaptchaActivity.RECAPTCHA_REQUEST); + Intent intent = new Intent(activity, ReCaptchaActivity.class); + intent.putExtra(ReCaptchaActivity.RECAPTCHA_URL_EXTRA, exception.getUrl()); + startActivityForResult(intent, ReCaptchaActivity.RECAPTCHA_REQUEST); showError(getString(R.string.recaptcha_request_toast), false); } 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 9d8481251..d0ed04279 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 @@ -384,7 +384,10 @@ public class VideoDetailFragment } break; case R.id.detail_controls_download: - this.openDownloadDialog(); + if (PermissionHelper.checkStoragePermissions(activity, + PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) { + this.openDownloadDialog(); + } break; case R.id.detail_uploader_root_layout: if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) { 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 279b396df..38a322285 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 @@ -64,7 +64,6 @@ public abstract class BaseListFragment extends BaseStateFragment implem @Override public void onDetach() { - infoListAdapter.dispose(); super.onDetach(); } @@ -97,8 +96,6 @@ public abstract class BaseListFragment extends BaseStateFragment implem } updateFlags = 0; } - - itemsList.post(infoListAdapter::updateStates); } /*////////////////////////////////////////////////////////////////////////// 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 1bac54df8..b469be3b8 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 @@ -1,8 +1,11 @@ package org.schabi.newpipe.fragments.list.playlist; +import android.app.Activity; +import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; @@ -26,7 +29,9 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; +import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; +import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue; @@ -36,6 +41,7 @@ import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ShareUtils; +import org.schabi.newpipe.util.StreamDialogEntry; import org.schabi.newpipe.util.ThemeHelper; import java.util.ArrayList; @@ -130,6 +136,42 @@ public class PlaylistFragment extends BaseListInfoFragment { infoListAdapter.useMiniItemVariants(true); } + private PlayQueue getPlayQueueStartingAt(StreamInfoItem infoItem) { + return getPlayQueue(Math.max(infoListAdapter.getItemsList().indexOf(infoItem), 0)); + } + + @Override + protected void showStreamDialog(StreamInfoItem item) { + final Context context = getContext(); + final Activity activity = getActivity(); + if (context == null || context.getResources() == null || activity == null) return; + + if (item.getStreamType() == StreamType.AUDIO_STREAM) { + StreamDialogEntry.setEnabledEntries( + StreamDialogEntry.enqueue_on_background, + StreamDialogEntry.start_here_on_background, + StreamDialogEntry.append_playlist, + StreamDialogEntry.share); + } else { + StreamDialogEntry.setEnabledEntries( + StreamDialogEntry.enqueue_on_background, + StreamDialogEntry.enqueue_on_popup, + StreamDialogEntry.start_here_on_background, + StreamDialogEntry.start_here_on_popup, + StreamDialogEntry.append_playlist, + StreamDialogEntry.share); + + StreamDialogEntry.start_here_on_popup.setCustomAction( + (fragment, infoItem) -> NavigationHelper.playOnPopupPlayer(context, getPlayQueueStartingAt(infoItem), true)); + } + + StreamDialogEntry.start_here_on_background.setCustomAction( + (fragment, infoItem) -> NavigationHelper.playOnBackgroundPlayer(context, getPlayQueueStartingAt(infoItem), true)); + + new InfoItemDialog(activity, item, StreamDialogEntry.getCommands(context), (dialog, which) -> + StreamDialogEntry.clickOn(which, this, item)).show(); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java index 39f7971dd..e279ee21b 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java @@ -2,14 +2,11 @@ package org.schabi.newpipe.info_list; import android.content.Context; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import com.nostra13.universalimageloader.core.ImageLoader; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; @@ -24,6 +21,7 @@ import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder; import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.OnClickGesture; /* @@ -61,14 +59,14 @@ public class InfoItemBuilder { this.context = context; } - public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, @Nullable StreamStateEntity state) { - return buildView(parent, infoItem, state, false); + public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { + return buildView(parent, infoItem, historyRecordManager, false); } public View buildView(@NonNull ViewGroup parent, @NonNull final InfoItem infoItem, - @Nullable StreamStateEntity state, boolean useMiniVariant) { + final HistoryRecordManager historyRecordManager, boolean useMiniVariant) { InfoItemHolder holder = holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant); - holder.updateFromItem(infoItem, state); + holder.updateFromItem(infoItem, historyRecordManager); return holder.itemView; } @@ -83,7 +81,6 @@ public class InfoItemBuilder { case COMMENT: return useMiniVariant ? new CommentsMiniInfoItemHolder(this, parent) : new CommentsInfoItemHolder(this, parent); default: - Log.e(TAG, "Trollolo"); throw new RuntimeException("InfoType not expected = " + infoType.name()); } } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java index 7f5b07dbe..d8515e4ba 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java @@ -1,6 +1,6 @@ package org.schabi.newpipe.info_list; -import android.app.Activity; +import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.GridLayoutManager; @@ -27,6 +27,7 @@ import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamGridInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.FallbackViewHolder; import org.schabi.newpipe.util.OnClickGesture; @@ -53,7 +54,7 @@ import java.util.List; * along with NewPipe. If not, see . */ -public class InfoListAdapter extends StateObjectsListAdapter { +public class InfoListAdapter extends RecyclerView.Adapter { private static final String TAG = InfoListAdapter.class.getSimpleName(); private static final boolean DEBUG = false; @@ -74,6 +75,8 @@ public class InfoListAdapter extends StateObjectsListAdapter { private final InfoItemBuilder infoItemBuilder; private final ArrayList infoItemList; + private final HistoryRecordManager recordManager; + private boolean useMiniVariant = false; private boolean useGridVariant = false; private boolean showFooter = false; @@ -89,9 +92,9 @@ public class InfoListAdapter extends StateObjectsListAdapter { } } - public InfoListAdapter(Activity a) { - super(a.getApplicationContext()); - infoItemBuilder = new InfoItemBuilder(a); + public InfoListAdapter(Context context) { + this.recordManager = new HistoryRecordManager(context); + infoItemBuilder = new InfoItemBuilder(context); infoItemList = new ArrayList<>(); } @@ -120,63 +123,52 @@ public class InfoListAdapter extends StateObjectsListAdapter { } public void addInfoItemList(@Nullable final List data) { - if (data != null) { - loadStates(data, infoItemList.size(), () -> addInfoItemListImpl(data)); - } - } - - private void addInfoItemListImpl(@NonNull List data) { - if (DEBUG) { - Log.d(TAG, "addInfoItemList() before > infoItemList.size() = " + infoItemList.size() + ", data.size() = " + data.size()); + if (data == null) { + return; } + if (DEBUG) Log.d(TAG, "addInfoItemList() before > infoItemList.size() = " + + infoItemList.size() + ", data.size() = " + data.size()); int offsetStart = sizeConsideringHeaderOffset(); infoItemList.addAll(data); - if (DEBUG) { - Log.d(TAG, "addInfoItemList() after > offsetStart = " + offsetStart + ", infoItemList.size() = " + infoItemList.size() + ", header = " + header + ", footer = " + footer + ", showFooter = " + showFooter); - } - + if (DEBUG) Log.d(TAG, "addInfoItemList() after > offsetStart = " + offsetStart + + ", infoItemList.size() = " + infoItemList.size() + + ", header = " + header + ", footer = " + footer + + ", showFooter = " + showFooter); notifyItemRangeInserted(offsetStart, data.size()); if (footer != null && showFooter) { int footerNow = sizeConsideringHeaderOffset(); notifyItemMoved(offsetStart, footerNow); - if (DEBUG) Log.d(TAG, "addInfoItemList() footer from " + offsetStart + " to " + footerNow); + if (DEBUG) Log.d(TAG, "addInfoItemList() footer from " + offsetStart + + " to " + footerNow); } } public void addInfoItem(@Nullable InfoItem data) { - if (data != null) { - loadState(data, infoItemList.size(), () -> addInfoItemImpl(data)); - } - } - - private void addInfoItemImpl(@NonNull InfoItem data) { - if (DEBUG) { - Log.d(TAG, "addInfoItem() before > infoItemList.size() = " + infoItemList.size() + ", thread = " + Thread.currentThread()); + if (data == null) { + return; } + if (DEBUG) Log.d(TAG, "addInfoItem() before > infoItemList.size() = " + + infoItemList.size() + ", thread = " + Thread.currentThread()); int positionInserted = sizeConsideringHeaderOffset(); infoItemList.add(data); - if (DEBUG) { - Log.d(TAG, "addInfoItem() after > position = " + positionInserted + ", infoItemList.size() = " + infoItemList.size() + ", header = " + header + ", footer = " + footer + ", showFooter = " + showFooter); - } + if (DEBUG) Log.d(TAG, "addInfoItem() after > position = " + positionInserted + + ", infoItemList.size() = " + infoItemList.size() + + ", header = " + header + ", footer = " + footer + + ", showFooter = " + showFooter); notifyItemInserted(positionInserted); if (footer != null && showFooter) { int footerNow = sizeConsideringHeaderOffset(); notifyItemMoved(positionInserted, footerNow); - if (DEBUG) Log.d(TAG, "addInfoItem() footer from " + positionInserted + " to " + footerNow); - } - } - - public void updateStates() { - if (!infoItemList.isEmpty()) { - updateAllStates(infoItemList); + if (DEBUG) Log.d(TAG, "addInfoItem() footer from " + positionInserted + + " to " + footerNow); } } @@ -185,7 +177,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { return; } infoItemList.clear(); - clearStates(); notifyDataSetChanged(); } @@ -254,7 +245,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { case COMMENT: return useMiniVariant ? MINI_COMMENT_HOLDER_TYPE : COMMENT_HOLDER_TYPE; default: - Log.e(TAG, "Trollolo"); return -1; } } @@ -292,7 +282,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { case COMMENT_HOLDER_TYPE: return new CommentsInfoItemHolder(infoItemBuilder, parent); default: - Log.e(TAG, "Trollolo"); return new FallbackViewHolder(new View(parent.getContext())); } } @@ -304,7 +293,7 @@ public class InfoListAdapter extends StateObjectsListAdapter { // If header isn't null, offset the items by -1 if (header != null) position--; - ((InfoItemHolder) holder).updateFromItem(infoItemList.get(position), getState(position)); + ((InfoItemHolder) holder).updateFromItem(infoItemList.get(position), recordManager); } else if (holder instanceof HFHolder && position == 0 && header != null) { ((HFHolder) holder).view = header; } else if (holder instanceof HFHolder && position == sizeConsideringHeaderOffset() && footer != null && showFooter) { @@ -317,11 +306,9 @@ public class InfoListAdapter extends StateObjectsListAdapter { if (!payloads.isEmpty() && holder instanceof InfoItemHolder) { for (Object payload : payloads) { if (payload instanceof StreamStateEntity) { - ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), - (StreamStateEntity) payload); + ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), recordManager); } else if (payload instanceof Boolean) { - ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), - null); + ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1), recordManager); } } } else { @@ -329,11 +316,6 @@ public class InfoListAdapter extends StateObjectsListAdapter { } } - @Override - protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) { - notifyItemChanged(header == null ? position : position + 1, state != null ? state : false); - } - public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) { return new GridLayoutManager.SpanSizeLookup() { @Override diff --git a/app/src/main/java/org/schabi/newpipe/info_list/StateObjectsListAdapter.java b/app/src/main/java/org/schabi/newpipe/info_list/StateObjectsListAdapter.java deleted file mode 100644 index 17ac919d9..000000000 --- a/app/src/main/java/org/schabi/newpipe/info_list/StateObjectsListAdapter.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.schabi.newpipe.info_list; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.util.SparseArray; - -import org.schabi.newpipe.BuildConfig; -import org.schabi.newpipe.R; -import org.schabi.newpipe.database.LocalItem; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; -import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.SparseArrayUtils; - -import java.util.List; -import java.util.Objects; - -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.CompositeDisposable; - -public abstract class StateObjectsListAdapter extends RecyclerView.Adapter { - - private final SparseArray states; - private final HistoryRecordManager recordManager; - private final CompositeDisposable stateLoaders; - private final Context context; - - public StateObjectsListAdapter(Context context) { - this.states = new SparseArray<>(); - this.recordManager = new HistoryRecordManager(context); - this.context = context; - this.stateLoaders = new CompositeDisposable(); - } - - @Nullable - public StreamStateEntity getState(int position) { - return states.get(position); - } - - protected void clearStates() { - states.clear(); - } - - private void appendStates(List statesEntities, int offset) { - for (int i = 0; i < statesEntities.size(); i++) { - final StreamStateEntity state = statesEntities.get(i); - if (state != null) { - states.append(offset + i, state); - } - } - } - - private void appendState(StreamStateEntity statesEntity, int offset) { - if (statesEntity != null) { - states.append(offset, statesEntity); - } - } - - protected void removeState(int index) { - states.remove(index); - } - - protected void moveState(int from, int to) { - final StreamStateEntity item = states.get(from); - if (from < to) { - SparseArrayUtils.shiftItemsDown(states, from, to); - } else { - SparseArrayUtils.shiftItemsUp(states, to, from); - } - states.put(to, item); - } - - protected void loadStates(List list, int offset, Runnable callback) { - if (isPlaybackStatesVisible()) { - List streamStateEntities = null; - try { - streamStateEntities = recordManager.loadStreamStateBatch(list).blockingGet(); - } catch (Exception e) { - if (BuildConfig.DEBUG) e.printStackTrace(); - } - if(streamStateEntities != null) appendStates(streamStateEntities, offset); - callback.run(); - } else { - callback.run(); - } - } - - protected void loadState(InfoItem item, int offset, Runnable callback) { - if (isPlaybackStatesVisible()) { - StreamStateEntity[] streamStateEntities = null; - try { - streamStateEntities = recordManager.loadStreamState(item).blockingGet(); - } catch (Exception e) { - if (BuildConfig.DEBUG) e.printStackTrace(); - } - if(streamStateEntities != null && streamStateEntities.length > 0) appendState(streamStateEntities[0], offset); - callback.run(); - } else { - callback.run(); - } - } - - protected void loadStatesForLocal(List list, int offset, Runnable callback) { - if (isPlaybackStatesVisible()) { - List streamStateEntities = null; - try { - streamStateEntities = recordManager.loadLocalStreamStateBatch(list).blockingGet(); - } catch (Exception e) { - if (BuildConfig.DEBUG) e.printStackTrace(); - } - if(streamStateEntities != null) appendStates(streamStateEntities, offset); - callback.run(); - } else { - callback.run(); - } - } - - private void processStatesUpdates(List streamStateEntities) { - for (int i = 0; i < streamStateEntities.size(); i++) { - final StreamStateEntity newState = streamStateEntities.get(i); - if (!Objects.equals(states.get(i), newState)) { - if (newState == null) { - states.remove(i); - } else { - states.put(i, newState); - } - onItemStateChanged(i, newState); - } - } - } - - protected void updateAllStates(List list) { - if (isPlaybackStatesVisible()) { - stateLoaders.add( - recordManager.loadStreamStateBatch(list) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::processStatesUpdates, throwable -> { - if (BuildConfig.DEBUG) throwable.printStackTrace(); - }) - ); - } else { - final int[] positions = SparseArrayUtils.getKeys(states); - states.clear(); - for (int pos : positions) onItemStateChanged(pos, null); - } - } - - protected void updateAllLocalStates(List list) { - if (isPlaybackStatesVisible()) { - stateLoaders.add( - recordManager.loadLocalStreamStateBatch(list) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::processStatesUpdates, throwable -> { - if (BuildConfig.DEBUG) throwable.printStackTrace(); - }) - ); - } else { - final int[] positions = SparseArrayUtils.getKeys(states); - states.clear(); - for (int pos : positions) onItemStateChanged(pos, null); - } - } - - public void dispose() { - stateLoaders.dispose(); - } - - protected boolean isPlaybackStatesVisible() { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true) - && prefs.getBoolean(context.getString(R.string.enable_playback_resume_key), true) - && prefs.getBoolean(context.getString(R.string.enable_playback_state_lists_key), true); - } - - protected abstract void onItemStateChanged(int position, @Nullable StreamStateEntity state); - -} diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelInfoItemHolder.java index 317934455..956bc47a6 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelInfoItemHolder.java @@ -1,14 +1,13 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.view.ViewGroup; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.Localization; /* @@ -40,8 +39,8 @@ public class ChannelInfoItemHolder extends ChannelMiniInfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { - super.updateFromItem(infoItem, state); + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { + super.updateFromItem(infoItem, historyRecordManager); if (!(infoItem instanceof ChannelInfoItem)) return; final ChannelInfoItem item = (ChannelInfoItem) infoItem; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java index a191707c0..3f4e4e398 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java @@ -1,14 +1,13 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.view.ViewGroup; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.Localization; @@ -32,7 +31,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { if (!(infoItem instanceof ChannelInfoItem)) return; final ChannelInfoItem item = (ChannelInfoItem) infoItem; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java index 4ecf86961..90212ea31 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsInfoItemHolder.java @@ -1,14 +1,13 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.view.ViewGroup; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; /* * Created by Christian Schabesberger on 12.02.17. @@ -41,8 +40,8 @@ public class CommentsInfoItemHolder extends CommentsMiniInfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { - super.updateFromItem(infoItem, state); + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { + super.updateFromItem(infoItem, historyRecordManager); if (!(infoItem instanceof CommentsInfoItem)) return; final CommentsInfoItem item = (CommentsInfoItem) infoItem; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java index 3d3a9bb09..4794ce3fd 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java @@ -1,18 +1,16 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.text.util.Linkify; -import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import org.jsoup.helper.StringUtil; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.util.CommentTextOnTouchListener; import org.schabi.newpipe.util.ImageDisplayConstants; @@ -48,7 +46,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { if(hours != null) timestamp += (Integer.parseInt(hours.replace(":", ""))*3600); if(minutes != null) timestamp += (Integer.parseInt(minutes.replace(":", ""))*60); if(seconds != null) timestamp += (Integer.parseInt(seconds)); - return streamUrl + url.replace(match.group(0), "#timestamp=" + String.valueOf(timestamp)); + return streamUrl + url.replace(match.group(0), "#timestamp=" + timestamp); } }; @@ -67,7 +65,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { if (!(infoItem instanceof CommentsInfoItem)) return; final CommentsInfoItem item = (CommentsInfoItem) infoItem; @@ -76,20 +74,17 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { itemThumbnailView, ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS); - itemThumbnailView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if(StringUtil.isBlank(item.getAuthorEndpoint())) return; - try { - final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext(); - NavigationHelper.openChannelFragment( - activity.getSupportFragmentManager(), - item.getServiceId(), - item.getAuthorEndpoint(), - item.getAuthorName()); - } catch (Exception e) { - ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e); - } + itemThumbnailView.setOnClickListener(view -> { + if(StringUtil.isBlank(item.getAuthorEndpoint())) return; + try { + final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext(); + NavigationHelper.openChannelFragment( + activity.getSupportFragmentManager(), + item.getServiceId(), + item.getAuthorEndpoint(), + item.getAuthorName()); + } catch (Exception e) { + ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e); } }); @@ -101,7 +96,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder { itemContentView.setOnTouchListener(CommentTextOnTouchListener.INSTANCE); if (itemContentView.getLineCount() == 0) { - itemContentView.post(() -> ellipsize()); + itemContentView.post(this::ellipsize); } else { ellipsize(); } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java index 3bc0d9e54..e06419126 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java @@ -1,13 +1,12 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.ViewGroup; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; /* * Created by Christian Schabesberger on 12.02.17. @@ -37,8 +36,8 @@ public abstract class InfoItemHolder extends RecyclerView.ViewHolder { this.itemBuilder = infoItemBuilder; } - public abstract void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state); + public abstract void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager); - public void updateState(final InfoItem infoItem, @Nullable final StreamStateEntity state) { + public void updateState(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { } } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java index f9d617e66..b73f22d93 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java @@ -1,15 +1,14 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.ImageDisplayConstants; public class PlaylistMiniInfoItemHolder extends InfoItemHolder { @@ -32,7 +31,7 @@ public class PlaylistMiniInfoItemHolder extends InfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { if (!(infoItem instanceof PlaylistInfoItem)) return; final PlaylistInfoItem item = (PlaylistInfoItem) infoItem; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamInfoItemHolder.java index 25502bc81..ea058bc0e 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamInfoItemHolder.java @@ -1,15 +1,14 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.ViewGroup; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.Localization; /* @@ -42,8 +41,8 @@ public class StreamInfoItemHolder extends StreamMiniInfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { - super.updateFromItem(infoItem, state); + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { + super.updateFromItem(infoItem, historyRecordManager); if (!(infoItem instanceof StreamInfoItem)) return; final StreamInfoItem item = (StreamInfoItem) infoItem; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java index aa2a3f878..6c685c6cf 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.info_list.holder; -import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.view.View; import android.view.ViewGroup; @@ -13,6 +12,7 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.Localization; @@ -43,7 +43,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } @Override - public void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state) { + public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { if (!(infoItem instanceof StreamInfoItem)) return; final StreamInfoItem item = (StreamInfoItem) infoItem; @@ -55,10 +55,12 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), R.color.duration_background_color)); itemDurationView.setVisibility(View.VISIBLE); - if (state != null) { + + StreamStateEntity state2 = historyRecordManager.loadStreamState(infoItem).blockingGet()[0]; + if (state2 != null) { itemProgressView.setVisibility(View.VISIBLE); itemProgressView.setMax((int) item.getDuration()); - itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime())); + itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state2.getProgressTime())); } else { itemProgressView.setVisibility(View.GONE); } @@ -101,8 +103,10 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } @Override - public void updateState(final InfoItem infoItem, @Nullable final StreamStateEntity state) { + public void updateState(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { final StreamInfoItem item = (StreamInfoItem) infoItem; + + StreamStateEntity state = historyRecordManager.loadStreamState(infoItem).blockingGet()[0]; if (state != null && item.getDuration() > 0 && item.getStreamType() != StreamType.LIVE_STREAM) { itemProgressView.setMax((int) item.getDuration()); if (itemProgressView.getVisibility() == View.VISIBLE) { @@ -130,4 +134,4 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { itemView.setLongClickable(false); itemView.setOnLongClickListener(null); } -} +} \ No newline at end of file diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java index 94672bd49..abdf82353 100644 --- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java @@ -76,8 +76,6 @@ public abstract class BaseLocalListFragment extends BaseStateFragment } updateFlags = 0; } - - itemsList.post(itemListAdapter::updateStates); } /*////////////////////////////////////////////////////////////////////////// @@ -152,7 +150,6 @@ public abstract class BaseLocalListFragment extends BaseStateFragment public void onDestroyView() { super.onDestroyView(); itemsList = null; - itemListAdapter.dispose(); itemListAdapter = null; } diff --git a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java index d29e85ee3..4b1a1f363 100644 --- a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java @@ -1,6 +1,6 @@ package org.schabi.newpipe.local; -import android.app.Activity; +import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.GridLayoutManager; @@ -11,7 +11,7 @@ import android.view.ViewGroup; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.stream.model.StreamStateEntity; -import org.schabi.newpipe.info_list.StateObjectsListAdapter; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.holder.LocalItemHolder; import org.schabi.newpipe.local.holder.LocalPlaylistGridItemHolder; import org.schabi.newpipe.local.holder.LocalPlaylistItemHolder; @@ -49,7 +49,7 @@ import java.util.List; * along with NewPipe. If not, see . */ -public class LocalItemListAdapter extends StateObjectsListAdapter { +public class LocalItemListAdapter extends RecyclerView.Adapter { private static final String TAG = LocalItemListAdapter.class.getSimpleName(); private static final boolean DEBUG = false; @@ -68,6 +68,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { private final LocalItemBuilder localItemBuilder; private final ArrayList localItems; + private final HistoryRecordManager recordManager; private final DateFormat dateFormat; private boolean showFooter = false; @@ -75,12 +76,12 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { private View header = null; private View footer = null; - public LocalItemListAdapter(Activity activity) { - super(activity.getApplicationContext()); - localItemBuilder = new LocalItemBuilder(activity); + public LocalItemListAdapter(Context context) { + recordManager = new HistoryRecordManager(context); + localItemBuilder = new LocalItemBuilder(context); localItems = new ArrayList<>(); dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, - Localization.getPreferredLocale(activity)); + Localization.getPreferredLocale(context)); } public void setSelectedListener(OnClickGesture listener) { @@ -92,27 +93,19 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { } public void addItems(@Nullable List data) { - if (data != null) { - loadStatesForLocal(data, localItems.size(), () -> addItemsImpl(data)); - } - } - - private void addItemsImpl(@NonNull List data) { - if (DEBUG) { - Log.d(TAG, "addItems() before > localItems.size() = " + - localItems.size() + ", data.size() = " + data.size()); + if (data == null) { + return; } + if (DEBUG) Log.d(TAG, "addItems() before > localItems.size() = " + + localItems.size() + ", data.size() = " + data.size()); int offsetStart = sizeConsideringHeader(); localItems.addAll(data); - if (DEBUG) { - Log.d(TAG, "addItems() after > offsetStart = " + offsetStart + - ", localItems.size() = " + localItems.size() + - ", header = " + header + ", footer = " + footer + - ", showFooter = " + showFooter); - } - + if (DEBUG) Log.d(TAG, "addItems() after > offsetStart = " + offsetStart + + ", localItems.size() = " + localItems.size() + + ", header = " + header + ", footer = " + footer + + ", showFooter = " + showFooter); notifyItemRangeInserted(offsetStart, data.size()); if (footer != null && showFooter) { @@ -124,16 +117,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { } } - public void updateStates() { - if (!localItems.isEmpty()) { - updateAllLocalStates(localItems); - } - } - public void removeItem(final LocalItem data) { final int index = localItems.indexOf(data); localItems.remove(index); - removeState(index); notifyItemRemoved(index + (header != null ? 1 : 0)); } @@ -145,7 +131,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { if (actualFrom >= localItems.size() || actualTo >= localItems.size()) return false; localItems.add(actualTo, localItems.remove(actualFrom)); - moveState(actualFrom, actualTo); notifyItemMoved(fromAdapterPosition, toAdapterPosition); return true; } @@ -155,7 +140,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { return; } localItems.clear(); - clearStates(); notifyDataSetChanged(); } @@ -236,8 +220,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { } } + @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) { + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int type) { if (DEBUG) Log.d(TAG, "onCreateViewHolder() called with: parent = [" + parent + "], type = [" + type + "]"); switch (type) { @@ -268,7 +253,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { } @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (DEBUG) Log.d(TAG, "onBindViewHolder() called with: holder = [" + holder.getClass().getSimpleName() + "], position = [" + position + "]"); @@ -276,7 +261,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { // If header isn't null, offset the items by -1 if (header != null) position--; - ((LocalItemHolder) holder).updateFromItem(localItems.get(position), getState(position), dateFormat); + ((LocalItemHolder) holder).updateFromItem(localItems.get(position), recordManager, dateFormat); } else if (holder instanceof HeaderFooterHolder && position == 0 && header != null) { ((HeaderFooterHolder) holder).view = header; } else if (holder instanceof HeaderFooterHolder && position == sizeConsideringHeader() @@ -290,11 +275,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { if (!payloads.isEmpty() && holder instanceof LocalItemHolder) { for (Object payload : payloads) { if (payload instanceof StreamStateEntity) { - ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), - (StreamStateEntity) payload); + ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), recordManager); } else if (payload instanceof Boolean) { - ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), - null); + ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), recordManager); } } } else { @@ -302,11 +285,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter { } } - @Override - protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) { - notifyItemChanged(header == null ? position : position + 1, state != null ? state : false); - } - public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) { return new GridLayoutManager.SpanSizeLookup() { @Override diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java index 5973ad920..656570943 100644 --- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistAppendDialog.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.local.dialog; -import android.annotation.SuppressLint; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -28,7 +27,7 @@ import java.util.Collections; import java.util.List; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; +import io.reactivex.disposables.CompositeDisposable; public final class PlaylistAppendDialog extends PlaylistDialog { private static final String TAG = PlaylistAppendDialog.class.getCanonicalName(); @@ -36,7 +35,7 @@ public final class PlaylistAppendDialog extends PlaylistDialog { private RecyclerView playlistRecyclerView; private LocalItemListAdapter playlistAdapter; - private Disposable playlistReactor; + private CompositeDisposable playlistDisposables = new CompositeDisposable(); public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) { PlaylistAppendDialog dialog = new PlaylistAppendDialog(); @@ -99,9 +98,9 @@ public final class PlaylistAppendDialog extends PlaylistDialog { final View newPlaylistButton = view.findViewById(R.id.newPlaylist); newPlaylistButton.setOnClickListener(ignored -> openCreatePlaylistDialog()); - playlistReactor = playlistManager.getPlaylists() + playlistDisposables.add(playlistManager.getPlaylists() .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onPlaylistsReceived); + .subscribe(this::onPlaylistsReceived)); } /*////////////////////////////////////////////////////////////////////////// @@ -111,13 +110,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog { @Override public void onDestroyView() { super.onDestroyView(); - if (playlistReactor != null) playlistReactor.dispose(); + playlistDisposables.dispose(); if (playlistAdapter != null) { - playlistAdapter.dispose(); playlistAdapter.unsetSelectedListener(); } - playlistReactor = null; + playlistDisposables.clear(); playlistRecyclerView = null; playlistAdapter = null; } @@ -151,13 +149,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog { @NonNull List streams) { if (getStreams() == null) return; - @SuppressLint("ShowToast") final Toast successToast = Toast.makeText(getContext(), R.string.playlist_add_stream_success, Toast.LENGTH_SHORT); - manager.appendToPlaylist(playlist.uid, streams) + playlistDisposables.add(manager.appendToPlaylist(playlist.uid, streams) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(ignored -> successToast.show()); + .subscribe(ignored -> successToast.show())); getDialog().dismiss(); } diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index f70da31d9..149dcfbdf 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -22,6 +22,7 @@ import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; +import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; import org.schabi.newpipe.database.stream.StreamStatisticsEntry; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; @@ -357,6 +358,10 @@ public class StatisticsPlaylistFragment startLoading(true); } + private PlayQueue getPlayQueueStartingAt(StreamStatisticsEntry infoItem) { + return getPlayQueue(Math.max(itemListAdapter.getItemsList().indexOf(infoItem), 0)); + } + private void showStreamDialog(final StreamStatisticsEntry item) { final Context context = getContext(); final Activity activity = getActivity(); @@ -379,8 +384,13 @@ public class StatisticsPlaylistFragment StreamDialogEntry.delete, StreamDialogEntry.append_playlist, StreamDialogEntry.share); + + StreamDialogEntry.start_here_on_popup.setCustomAction( + (fragment, infoItemDuplicate) -> NavigationHelper.playOnPopupPlayer(context, getPlayQueueStartingAt(item), true)); } + StreamDialogEntry.start_here_on_background.setCustomAction( + (fragment, infoItemDuplicate) -> NavigationHelper.playOnBackgroundPlayer(context, getPlayQueueStartingAt(item), true)); StreamDialogEntry.delete.setCustomAction((fragment, infoItemDuplicate) -> deleteEntry(Math.max(itemListAdapter.getItemsList().indexOf(item), 0))); diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java index c00fa1fb4..ed6a9b4cd 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java @@ -1,13 +1,12 @@ package org.schabi.newpipe.local.holder; -import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.ViewGroup; import org.schabi.newpipe.database.LocalItem; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.local.LocalItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import java.text.DateFormat; @@ -40,8 +39,8 @@ public abstract class LocalItemHolder extends RecyclerView.ViewHolder { this.itemBuilder = itemBuilder; } - public abstract void updateFromItem(final LocalItem item, @Nullable final StreamStateEntity state, final DateFormat dateFormat); + public abstract void updateFromItem(final LocalItem item, HistoryRecordManager historyRecordManager, final DateFormat dateFormat); - public void updateState(final LocalItem localItem, @Nullable final StreamStateEntity state) { + public void updateState(final LocalItem localItem, HistoryRecordManager historyRecordManager) { } } diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java index 0e6eca9ba..1366bd02e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java @@ -1,13 +1,12 @@ package org.schabi.newpipe.local.holder; -import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.local.LocalItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.ImageDisplayConstants; import java.text.DateFormat; @@ -23,7 +22,7 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { } @Override - public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { + public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { if (!(localItem instanceof PlaylistMetadataEntry)) return; final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem; @@ -34,6 +33,6 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS); - super.updateFromItem(localItem, state, dateFormat); + super.updateFromItem(localItem, historyRecordManager, dateFormat); } } diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java index 0c4e66c9d..c5d9a6428 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.local.holder; -import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.view.MotionEvent; import android.view.View; @@ -14,12 +13,14 @@ import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.local.LocalItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.views.AnimatedProgressBar; import java.text.DateFormat; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; public class LocalPlaylistStreamItemHolder extends LocalItemHolder { @@ -47,7 +48,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { } @Override - public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { + public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { if (!(localItem instanceof PlaylistStreamEntry)) return; final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; @@ -60,6 +61,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), R.color.duration_background_color)); itemDurationView.setVisibility(View.VISIBLE); + + StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList() {{ add(localItem); }}).blockingGet().get(0); if (state != null) { itemProgressView.setVisibility(View.VISIBLE); itemProgressView.setMax((int) item.duration); @@ -94,9 +97,11 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { } @Override - public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) { + public void updateState(LocalItem localItem, HistoryRecordManager historyRecordManager) { if (!(localItem instanceof PlaylistStreamEntry)) return; final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; + + StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList() {{ add(localItem); }}).blockingGet().get(0); if (state != null && item.duration > 0) { itemProgressView.setMax((int) item.duration); if (itemProgressView.getVisibility() == View.VISIBLE) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java index b24051a4f..05717392c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java @@ -13,12 +13,14 @@ import org.schabi.newpipe.database.stream.StreamStatisticsEntry; import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.local.LocalItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.views.AnimatedProgressBar; import java.text.DateFormat; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; /* @@ -76,7 +78,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { } @Override - public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { + public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { if (!(localItem instanceof StreamStatisticsEntry)) return; final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; @@ -88,6 +90,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(), R.color.duration_background_color)); itemDurationView.setVisibility(View.VISIBLE); + + StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList() {{ add(localItem); }}).blockingGet().get(0); if (state != null) { itemProgressView.setVisibility(View.VISIBLE); itemProgressView.setMax((int) item.duration); @@ -124,9 +128,11 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { } @Override - public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) { + public void updateState(LocalItem localItem, HistoryRecordManager historyRecordManager) { if (!(localItem instanceof StreamStatisticsEntry)) return; final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; + + StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList() {{ add(localItem); }}).blockingGet().get(0); if (state != null && item.duration > 0) { itemProgressView.setMax((int) item.duration); if (itemProgressView.getVisibility() == View.VISIBLE) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/PlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/PlaylistItemHolder.java index 2a81f9571..c5f1813c7 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/PlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/PlaylistItemHolder.java @@ -1,14 +1,13 @@ package org.schabi.newpipe.local.holder; -import android.support.annotation.Nullable; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.local.LocalItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import java.text.DateFormat; @@ -33,7 +32,7 @@ public abstract class PlaylistItemHolder extends LocalItemHolder { } @Override - public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { + public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { itemView.setOnClickListener(view -> { if (itemBuilder.getOnItemSelectedListener() != null) { itemBuilder.getOnItemSelectedListener().selected(localItem); diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java index bdcd42f67..f9542850e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java @@ -1,13 +1,12 @@ package org.schabi.newpipe.local.holder; -import android.support.annotation.Nullable; import android.view.ViewGroup; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.local.LocalItemBuilder; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.Localization; @@ -23,7 +22,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { } @Override - public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) { + public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) { if (!(localItem instanceof PlaylistRemoteEntity)) return; final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem; @@ -35,6 +34,6 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { itemBuilder.displayImage(item.getThumbnailUrl(), itemThumbnailView, ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS); - super.updateFromItem(localItem, state, dateFormat); + super.updateFromItem(localItem, historyRecordManager, dateFormat); } } diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 640174ab7..a8750ed47 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -511,6 +511,10 @@ public class LocalPlaylistFragment extends BaseLocalListFragment NavigationHelper.playOnPopupPlayer(context, getPlayQueueStartingAt(item), true)); } + StreamDialogEntry.start_here_on_background.setCustomAction( + (fragment, infoItemDuplicate) -> NavigationHelper.playOnBackgroundPlayer(context, getPlayQueueStartingAt(item), true)); StreamDialogEntry.set_as_playlist_thumbnail.setCustomAction( (fragment, infoItemDuplicate) -> changeThumbnailUrl(item.thumbnailUrl)); StreamDialogEntry.delete.setCustomAction( diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java index 9a53e7e94..a2727c29b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java @@ -130,7 +130,6 @@ public class SubscriptionFragment extends BaseStateFragment { FragmentManager fragmentManager = getFM(); NavigationHelper.openWhatsNewFragment(fragmentManager); @@ -430,12 +426,12 @@ public class SubscriptionFragment extends BaseStateFragment> getDeleteObserver(){ + private Observer> getDeleteObserver() { return new Observer>() { @Override public void onSubscribe(Disposable d) { diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 62be71995..e256070ca 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -1049,27 +1049,33 @@ public abstract class BasePlayer implements private void savePlaybackState(final StreamInfo info, final long progress) { if (info == null) return; if (DEBUG) Log.d(TAG, "savePlaybackState() called"); - final Disposable stateSaver = recordManager.saveStreamState(info, progress) - .observeOn(AndroidSchedulers.mainThread()) - .doOnError((e) -> { - if (DEBUG) e.printStackTrace(); - }) - .onErrorComplete() - .subscribe(); - databaseUpdateReactor.add(stateSaver); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)) { + final Disposable stateSaver = recordManager.saveStreamState(info, progress) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError((e) -> { + if (DEBUG) e.printStackTrace(); + }) + .onErrorComplete() + .subscribe(); + databaseUpdateReactor.add(stateSaver); + } } private void resetPlaybackState(final PlayQueueItem queueItem) { if (queueItem == null) return; - final Disposable stateSaver = queueItem.getStream() - .flatMapCompletable(info -> recordManager.saveStreamState(info, 0)) - .observeOn(AndroidSchedulers.mainThread()) - .doOnError((e) -> { - if (DEBUG) e.printStackTrace(); - }) - .onErrorComplete() - .subscribe(); - databaseUpdateReactor.add(stateSaver); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)) { + final Disposable stateSaver = queueItem.getStream() + .flatMapCompletable(info -> recordManager.saveStreamState(info, 0)) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError((e) -> { + if (DEBUG) e.printStackTrace(); + }) + .onErrorComplete() + .subscribe(); + databaseUpdateReactor.add(stateSaver); + } } public void resetPlaybackState(final StreamInfo info) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index 4212f4cb8..7c2cb46e9 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -35,8 +35,6 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { private String DOWNLOAD_PATH_VIDEO_PREFERENCE; private String DOWNLOAD_PATH_AUDIO_PREFERENCE; - private String DOWNLOAD_STORAGE_ASK; - private Preference prefPathVideo; private Preference prefPathAudio; private Preference prefStorageAsk; @@ -49,14 +47,14 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { DOWNLOAD_PATH_VIDEO_PREFERENCE = getString(R.string.download_path_video_key); DOWNLOAD_PATH_AUDIO_PREFERENCE = getString(R.string.download_path_audio_key); - DOWNLOAD_STORAGE_ASK = getString(R.string.downloads_storage_ask); + final String downloadStorageAsk = getString(R.string.downloads_storage_ask); prefPathVideo = findPreference(DOWNLOAD_PATH_VIDEO_PREFERENCE); prefPathAudio = findPreference(DOWNLOAD_PATH_AUDIO_PREFERENCE); - prefStorageAsk = findPreference(DOWNLOAD_STORAGE_ASK); + prefStorageAsk = findPreference(downloadStorageAsk); updatePreferencesSummary(); - updatePathPickers(!defaultPreferences.getBoolean(DOWNLOAD_STORAGE_ASK, false)); + updatePathPickers(!defaultPreferences.getBoolean(downloadStorageAsk, false)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { prefStorageAsk.setSummary(R.string.downloads_storage_ask_summary); @@ -180,7 +178,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { } Intent i; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && NewPipeSettings.useStorageAccessFramework(ctx)) { i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) .putExtra("android.content.extra.SHOW_ADVANCED", true) .addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | StoredDirectoryHelper.PERMISSION_FLAGS); @@ -221,16 +219,17 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { return; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - // steps: - // 1. revoke permissions on the old save path - // 2. acquire permissions on the new save path - // 3. save the new path, if step(2) was successful - final Context ctx = getContext(); - if (ctx == null) throw new NullPointerException("getContext()"); - forgetSAFTree(ctx, defaultPreferences.getString(key, "")); + // revoke permissions on the old save path (required for SAF only) + final Context ctx = getContext(); + if (ctx == null) throw new NullPointerException("getContext()"); + forgetSAFTree(ctx, defaultPreferences.getString(key, "")); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !FilePickerActivityHelper.isOwnFileUri(ctx, uri)) { + // steps to acquire the selected path: + // 1. acquire permissions on the new save path + // 2. save the new path, if step(2) was successful try { ctx.grantUriPermission(ctx.getPackageName(), uri, StoredDirectoryHelper.PERMISSION_FLAGS); @@ -245,7 +244,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { return; } } else { - File target = Utils.getFileForUri(data.getData()); + File target = Utils.getFileForUri(uri); if (!target.canWrite()) { showMessageDialog(R.string.download_to_sdcard_error_title, R.string.download_to_sdcard_error_message); return; diff --git a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java index dc0a5fbf0..cf5425a50 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java @@ -18,7 +18,7 @@ import io.reactivex.disposables.Disposable; public class HistorySettingsFragment extends BasePreferenceFragment { private String cacheWipeKey; - private String viewsHistroyClearKey; + private String viewsHistoryClearKey; private String searchHistoryClearKey; private HistoryRecordManager recordManager; private CompositeDisposable disposables; @@ -27,7 +27,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment { public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); cacheWipeKey = getString(R.string.metadata_cache_wipe_key); - viewsHistroyClearKey = getString(R.string.clear_views_history_key); + viewsHistoryClearKey = getString(R.string.clear_views_history_key); searchHistoryClearKey = getString(R.string.clear_search_history_key); recordManager = new HistoryRecordManager(getActivity()); disposables = new CompositeDisposable(); @@ -46,7 +46,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment { Toast.LENGTH_SHORT).show(); } - if (preference.getKey().equals(viewsHistroyClearKey)) { + if (preference.getKey().equals(viewsHistoryClearKey)) { new AlertDialog.Builder(getActivity()) .setTitle(R.string.delete_view_history_alert) .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss())) diff --git a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java index a0f3b6063..44da38c35 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java +++ b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java @@ -22,7 +22,6 @@ package org.schabi.newpipe.settings; import android.content.Context; import android.content.SharedPreferences; -import android.os.Build; import android.os.Environment; import android.preference.PreferenceManager; import android.support.annotation.NonNull; @@ -67,10 +66,8 @@ public class NewPipeSettings { PreferenceManager.setDefaultValues(context, R.xml.video_audio_settings, true); PreferenceManager.setDefaultValues(context, R.xml.debug_settings, true); - if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - getVideoDownloadFolder(context); - getAudioDownloadFolder(context); - } + getVideoDownloadFolder(context); + getAudioDownloadFolder(context); } private static void getVideoDownloadFolder(Context context) { @@ -93,11 +90,19 @@ public class NewPipeSettings { } @NonNull - private static File getDir(String defaultDirectoryName) { + public static File getDir(String defaultDirectoryName) { return new File(Environment.getExternalStorageDirectory(), defaultDirectoryName); } private static String getNewPipeChildFolderPathForDir(File dir) { return new File(dir, "NewPipe").toURI().toString(); } + + public static boolean useStorageAccessFramework(Context context) { + final String key = context.getString(R.string.storage_use_saf); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + return prefs.getBoolean(key, false); + } + } diff --git a/app/src/main/java/org/schabi/newpipe/util/FilePickerActivityHelper.java b/app/src/main/java/org/schabi/newpipe/util/FilePickerActivityHelper.java index 20554ce59..8e70e4f8d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/FilePickerActivityHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/FilePickerActivityHelper.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.util; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.support.annotation.NonNull; @@ -29,7 +30,7 @@ public class FilePickerActivityHelper extends com.nononsenseapps.filepicker.File @Override public void onCreate(Bundle savedInstanceState) { - if(ThemeHelper.isLightThemeSelected(this)) { + if (ThemeHelper.isLightThemeSelected(this)) { this.setTheme(R.style.FilePickerThemeLight); } else { this.setTheme(R.style.FilePickerThemeDark); @@ -73,6 +74,11 @@ public class FilePickerActivityHelper extends com.nononsenseapps.filepicker.File .putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_NEW_FILE); } + public static boolean isOwnFileUri(@NonNull Context context, @NonNull Uri uri) { + if (uri.getAuthority() == null) return false; + return uri.getAuthority().startsWith(context.getPackageName()); + } + /*////////////////////////////////////////////////////////////////////////// // Internal //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index bb176166b..89c4b33fe 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -446,6 +446,9 @@ public class NavigationHelper { } public static boolean openDownloads(Activity activity) { + if (!PermissionHelper.checkStoragePermissions(activity, PermissionHelper.DOWNLOADS_REQUEST_CODE)) { + return false; + } Intent intent = new Intent(activity, DownloadActivity.class); activity.startActivity(intent); return true; diff --git a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java index 1367b895c..2fe5f95e4 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java @@ -18,10 +18,12 @@ import android.widget.Toast; import org.schabi.newpipe.R; public class PermissionHelper { + public static final int DOWNLOAD_DIALOG_REQUEST_CODE = 778; + public static final int DOWNLOADS_REQUEST_CODE = 777; public static boolean checkStoragePermissions(Activity activity, int requestCode) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - if(!checkReadStoragePermissions(activity, requestCode)) return false; + if (!checkReadStoragePermissions(activity, requestCode)) return false; } return checkWriteStoragePermissions(activity, requestCode); } @@ -89,7 +91,7 @@ public class PermissionHelper { i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); return false; - }else return true; + } else return true; } public static boolean isPopupEnabled(Context context) { diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManager.java b/app/src/main/java/us/shandian/giga/service/DownloadManager.java index c2bba7396..beb5e6dc9 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -35,8 +35,8 @@ public class DownloadManager { public final static int SPECIAL_PENDING = 1; public final static int SPECIAL_FINISHED = 2; - static final String TAG_AUDIO = "audio"; - static final String TAG_VIDEO = "video"; + public static final String TAG_AUDIO = "audio"; + public static final String TAG_VIDEO = "video"; private final FinishedMissionStore mFinishedMissionStore; @@ -666,9 +666,9 @@ public class DownloadManager { continue; if (mission.running) - paused = true; - else running = true; + else + paused = true; } } diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index ebc6e94c2..e53ab4f1f 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -122,14 +122,8 @@ public class MissionAdapter extends Adapter { break; } - if (mStartButton != null && mPauseButton != null) switch (msg.what) { - case DownloadManagerService.MESSAGE_DELETED: - case DownloadManagerService.MESSAGE_ERROR: - case DownloadManagerService.MESSAGE_FINISHED: - case DownloadManagerService.MESSAGE_PAUSED: - checkMasterButtonsVisibility(); - break; - } + if (mStartButton != null && mPauseButton != null) + checkMasterButtonsVisibility(); } }; @@ -163,8 +157,7 @@ public class MissionAdapter extends Adapter { mPendingDownloadsItems.remove(h); if (mPendingDownloadsItems.size() < 1) { setAutoRefresh(false); - if (mStartButton != null) mStartButton.setVisible(false); - if (mPauseButton != null) mPauseButton.setVisible(false); + checkMasterButtonsVisibility(); } } @@ -664,11 +657,11 @@ public class MissionAdapter extends Adapter { if (mEmptyMessage.getVisibility() != flag) mEmptyMessage.setVisibility(flag); } - private void checkMasterButtonsVisibility() { + public void checkMasterButtonsVisibility() { boolean[] state = mIterator.hasValidPendingMissions(); - mStartButton.setVisible(state[0]); - mPauseButton.setVisible(state[1]); + mPauseButton.setVisible(state[0]); + mStartButton.setVisible(state[1]); } public void ensurePausedMissions() { diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index f8cecbed9..2b2c09750 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -7,7 +7,9 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; +import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.annotation.NonNull; @@ -22,9 +24,14 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Toast; +import com.nononsenseapps.filepicker.Utils; + import org.schabi.newpipe.R; +import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.util.FilePickerActivityHelper; import org.schabi.newpipe.util.ThemeHelper; +import java.io.File; import java.io.IOException; import us.shandian.giga.get.DownloadMission; @@ -37,7 +44,7 @@ import us.shandian.giga.ui.adapter.MissionAdapter; public class MissionsFragment extends Fragment { private static final int SPAN_SIZE = 2; - private static final int REQUEST_DOWNLOAD_PATH_SAF = 0x1230; + private static final int REQUEST_DOWNLOAD_SAVE_AS = 0x1230; private SharedPreferences mPrefs; private boolean mLinear; @@ -138,6 +145,7 @@ public class MissionsFragment extends Fragment { * deprecated in API level 23, * but must remain to allow compatibility with api<23 */ + @SuppressWarnings("deprecation") @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -241,12 +249,28 @@ public class MissionsFragment extends Fragment { private void recoverMission(@NonNull DownloadMission mission) { unsafeMissionTarget = mission; - StoredFileHelper.requestSafWithFileCreation( - MissionsFragment.this, - REQUEST_DOWNLOAD_PATH_SAF, - mission.storage.getName(), - mission.storage.getType() - ); + + if (NewPipeSettings.useStorageAccessFramework(mContext)) { + StoredFileHelper.requestSafWithFileCreation( + MissionsFragment.this, + REQUEST_DOWNLOAD_SAVE_AS, + mission.storage.getName(), + mission.storage.getType() + ); + + } else { + File initialSavePath; + if (DownloadManager.TAG_VIDEO.equals(mission.storage.getType())) + initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MOVIES); + else + initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MUSIC); + + initialSavePath = new File(initialSavePath, mission.storage.getName()); + startActivityForResult( + FilePickerActivityHelper.chooseFileToSave(mContext, initialSavePath.getAbsolutePath()), + REQUEST_DOWNLOAD_SAVE_AS + ); + } } @Override @@ -273,6 +297,7 @@ public class MissionsFragment extends Fragment { } mBinder.addMissionEventListener(mAdapter.getMessenger()); + mAdapter.checkMasterButtonsVisibility(); } if (mBinder != null) mBinder.enableNotifications(false); } @@ -288,15 +313,20 @@ public class MissionsFragment extends Fragment { public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode != REQUEST_DOWNLOAD_PATH_SAF || resultCode != Activity.RESULT_OK) return; + if (requestCode != REQUEST_DOWNLOAD_SAVE_AS || resultCode != Activity.RESULT_OK) return; if (unsafeMissionTarget == null || data.getData() == null) { - return;// unsafeMissionTarget cannot be null + return; } try { + Uri fileUri = data.getData(); + if (fileUri.getAuthority() != null && FilePickerActivityHelper.isOwnFileUri(mContext, fileUri)) { + fileUri = Uri.fromFile(Utils.getFileForUri(fileUri)); + } + String tag = unsafeMissionTarget.storage.getTag(); - unsafeMissionTarget.storage = new StoredFileHelper(mContext, null, data.getData(), tag); + unsafeMissionTarget.storage = new StoredFileHelper(mContext, null, fileUri, tag); mAdapter.recoverMission(unsafeMissionTarget); } catch (IOException e) { Toast.makeText(mContext, R.string.general_error, Toast.LENGTH_LONG).show(); diff --git a/app/src/main/res/layout/activity_recaptcha.xml b/app/src/main/res/layout/activity_recaptcha.xml index 7a4971cd9..1016210ec 100644 --- a/app/src/main/res/layout/activity_recaptcha.xml +++ b/app/src/main/res/layout/activity_recaptcha.xml @@ -1,16 +1,27 @@ - + + + + - - \ No newline at end of file diff --git a/app/src/main/res/menu/download_menu.xml b/app/src/main/res/menu/download_menu.xml index 4e4549957..f91f8ad7b 100644 --- a/app/src/main/res/menu/download_menu.xml +++ b/app/src/main/res/menu/download_menu.xml @@ -1,11 +1,13 @@ - + tools:ignore="AlwaysShowAction" + app:showAsAction="always" /> مسار حفظ تنزيلات الفيديو في مسار ملفات الفيديو المحفوظة "لا يمكن إنشاء مجلد للتنزيلات في '%1$s'" - "تم إنشاء مجلد تنزيلات في '%1$s'" + إنشاء دليل التنزيل \'%1$s\' تثبيت تطبيق Kore غير موجود. هل تريد تثبيته ؟ مضيء @@ -42,7 +42,7 @@ مشاركة مشاركة بواسطة عرض مقاطع الفيديو \"التالية\" و \"المشابهة\" - عرض خيار لتشغيل الفيديو بواسطة مشغل كودي + عرض خيار تشغيل الفيديو عبر مركز وسائط Kodi عرض خيار التشغيل بواسطة كودي السمة تم النشر يوم %1$s @@ -66,11 +66,11 @@ في الخلفية تشغيل تلقائي اسود - التاريخ وذاكرة التخزين المؤقت + مراقبة السجل التاريخ و ذاكرة التخزين المؤقت محتوى - التنزيلات - التحميل + التحميلات + التحميلات الكل القناة الفيديو @@ -80,7 +80,7 @@ التاريخ التاريخ فتح في وضع منبثق - يزيل الصوت في بعض الخيارات + "يزيل الصوت في بعض قرارات الدقة" وضع النوافذ المنبثقة NewPipe تم إلغاء الاشتراك في القناة تعذر تغيير حالة الاشتراك @@ -113,11 +113,11 @@ محتوى مقيد بحسب العمر "إظهار الفيديو المقيد بحسب العمر. يمكن السماح باستخدام هذه المواد من \"الإعدادات\"." بث مباشر - تقرير الخطأ + أبلغ عن خطأ قائمة التشغيل نعم لاحقاً - مُعطل + معطل فلتر تحديث تنظيف @@ -158,11 +158,11 @@ بليون ليس هناك مشترِكون - %s لا يوجد مشترك + %s لا يوجد مشارك %s مشترك - %s اثنتين مشتركين + "%s مشتركتين" %s اشتراكات - %s مشتركين + %s مشاركين %s مشتركون دون مشاهدات @@ -184,7 +184,7 @@ انقر للحصول على التفاصيل يُرجى الإنتظار… تم نسخه إلى الحافظة - الرجاء تحديد مجلد لحفظ التنزيلات + يرجى تحديد مجلد التنزيل لاحقًا في الإعدادات هذا الإذن مطلوب \nللفتح في وضع النافذة المنبثقة اختبار reCAPTCHA @@ -200,7 +200,7 @@ فتح الموقع المساهمون التراخيص - تطبيق حُر و خفيف لتشغيل اليوتيوب على نظام الأندرويد. + تطبيق مجاني خفيف الوزن وبث حي على نظام أندرويد. ساهم إذا كانت لديك أفكار؛ أو ترجمة، أو تغييرات تخص التصميم، أو تنظيف و تحسين الشفرة البرمجية ، أو تعديلات عميقة عليها، فتذكر أنّ مساعدتك دائما موضع ترحيب. وكلما أتممنا شيئا كلما كان ذلك أفضل ! عرض على GitHub @@ -234,7 +234,7 @@ التفاصيل الإعدادات الصوتية تشغيل هنا - تشغيل في وضع النافذة المنبثقة + تشغيل في وضع نافذة منبثقة تحدي الكابتشا اضغط للإدراج في قائمة الانتظار @@ -307,11 +307,6 @@ لا يمكن حذف قائمة التشغيل. ملئ الشاشة تكبير - حجم خط التسمية - أصغر خط - خط عادي - خط ذو حجم كبير - مُزامَنة تنزيل ملف البث الإشارات المرجعية استعمال التقديم السريع الغير دقيق @@ -430,11 +425,11 @@ تتبيه تحديث التطبيق إيماءة التحكم بالصوت الأحداث - التنبيه بإصدارات newpipe الجديدة - ذاكرة التخزين الخارجي غير متوفرة - التحميل إلى بطاقة الذاكرة الخارجية ليس متاحا حتى الآن. إعادة تعيين موقع مجلد التحميل؟ - باستخدام علامات الجدولة الافتراضية، حدث خطأ أثناء قراءة علامات التبويب المحفوظة - استعادة الافتراضيات + الإخطارات عند تواجد إصدار newpipe جديد + وحدة التخزين الخارجية غير متوفرة + "التنزيل على بطاقة SD الخارجية غير ممكن. إعادة تعيين موقع مجلد التحميل؟" + عند إستخدام علامات التبويب الافتراضية ، وقع خطأ أثناء قراءة علامات التبويب المحفوظة + استعادة الضبط الافتراضي هل تريد استعادة الإعدادات الافتراضية؟ عدد المشتركين غير متاح ما هي التبويبات التي تظهر على الصفحة الرئيسية @@ -481,8 +476,8 @@ توقف أقصى عدد للمحاولات الحد الأقصى لعدد محاولات قبل إلغاء التحميل - "ايقاف عند التحويل إلى البيانات المتنقلة" - سيتم إعادة تحميل التنزيلات التي لا يمكن إيقافها + "إنقطع الإتصال بالشبكة عند التحويل إلى البيانات المتنقلة" + مفيد عند التبديل إلى بيانات الجوال ، على الرغم من أنه لا يمكن تعليق بعض التنزيلات إظهار التعليقات تعطيل لإيقاف عرض التعليقات تشغيل تلقائي @@ -496,6 +491,28 @@ لا توجد تعليقات تعذر تحميل التعليقات - التشغيل مباشرة في الخلفية إغلاق + استئناف التشغيل + استعادة آخر موقف التشغيل + واضع القوائم + إظهار مؤشرات وضع التشغيل في القوائم + امسح البيانات + تم حذف وضع التشغيل. + نقل الملف أو حذفه + يوجد ملف بهذا الاسم مسبقاً + لا يمكن الكتابة فوق الملف + هناك تنزيل معلق بهذا الاسم + تم إغلاق NewPipe أثناء العمل على الملف + لم يتبقى مساحة في الجهاز + تم فقد التقدم بسبب حذف الملف + انتهى وقت الاتصال + هل أنت واثق؟ + حد قائمة انتظار التنزيل + سيتم تشغيل تنزيل واحد في نفس الوقت + بدء التنزيلات + إيقاف التحميل مؤقتا + اسأل عن مكان التنزيل + سيُطلب منك مكان حفظ كل تنزيل + سوف يطلب منك مكان حفظ كل تحميل. +\nقم بتشغيل هذا إذا كنت تريد التنزيل إلى بطاقة SD خارجية. \ No newline at end of file diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index b256888cb..e371e03ff 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -368,11 +368,6 @@ RELLENAR ZOOM - Tamañu de fonte de sotítulos - Fonte más pequeña - Fonte media - Fonte más grande - Activar LeakCanary La supervisión d\'escapes de memoria podría facer que l\'aplicación nun respuenda al volquiar la pila diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 1107657ff..08d74d525 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -405,5 +405,4 @@ Фонавы плэер Плэер у акне Адпісацца - Іграць \"у фоне\" \ No newline at end of file diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 37a511c9a..223e604d6 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -305,7 +305,7 @@ Nova missió L\'URL té un format incorrecte o no hi ha connexió a internet Toqueu aquí per a més detalls - Trieu una carpeta de baixades disponible + Definiu una carpeta de baixades més endavant a la configuració Es necessita aquest permís per a obrir el mode emergent Camp reCAPTCHA S\'ha sol·licitat l\'emplenament d\'un camp reCAPTCHA @@ -333,18 +333,13 @@ Omple Escala Generats automàticament - Mida dels subtítols - Mida més petita - Mida normal - Mida més gran Habilita el LeakCanary Darrera exportació No s\'han pogut importar les subscripcions No s\'han pogut exportar les subscripcions Desvincula (pot provocar distorsió) - Nightcore Elimina totes les dades de llocs web de la memòria cau - Afegeix a la cua un vídeo relacionat quan es reprodueix l\'últim vídeo en una cua sense repetició. + Afegeix a la cua un vídeo relacionat quan es reprodueix l\'últim vídeo en una cua sense repetició Mostra els missatges d\'ajuda Mostra un missatge d\'ajuda quan el botó de mode en segon pla o emergent estigui premut a la pàgina de detalls d\'un vídeo Què ha passat:\\nPetició:\\nIdioma del contingut:\\nServei:\\nHora GMT:\\nPaquet:\\nVersió:\\nVersió del SO: @@ -456,7 +451,7 @@ Intents màxims Nombre màxim d\'intents abans de cancel·lar la baixada Pausa en canviar a dades mòbils - Les baixades que no es puguin pausar es tornaran a iniciar + Útil en canviar a les dades mòbils, tot i que algunes baixades no es poden aturar Elimina la subscripció Sobreescriu No s\'ha trobat @@ -465,6 +460,25 @@ Reproducció automàtica No hi ha comentaris No s\'han pogut carregar els comentaris - Reprodueix directament en segon pla Tanca + S\'estan utilitzant les pestanyes per defecte, s\'ha produït un error en llegir les pestanyes desades + Mostra una notificació per demanar l\'actualització de l\'aplicació si hi ha una nova versió disponible + Toca per baixar + El servidor no està enviant dades + + Comentaris + + + Notificació d\'actualització de l\'aplicació + Reprèn la reproducció + No es pot sobreescriure el fitxer + Hi ha una baixada pendent amb aquest nom + No hi ha espai disponible al dispositiu + S\'ha perdut el progrés perquè s\'ha eliminat el fitxer + S\'ha excedit el temps d\'espera de la connexió + Segur\? + Limita la cua de baixades + Inicia les baixades + Pausa les baixades + Se us demanarà la ubicació de cada baixada \ No newline at end of file diff --git a/app/src/main/res/values-cmn/strings.xml b/app/src/main/res/values-cmn/strings.xml index 74d39b1b0..d402bbd84 100644 --- a/app/src/main/res/values-cmn/strings.xml +++ b/app/src/main/res/values-cmn/strings.xml @@ -92,7 +92,7 @@ 第三方执照 打开网页 删除书签 - 确定要删除该播放列表吗? + 确定删除该播放列表吗? 已创建播放列表 播放列表 步骤 @@ -115,14 +115,14 @@ 已清除缓存的元数据 不加载缩略图时,可以节省数据和存储空间。更改后将清除存储空间和扩展空间的缓存。 自动排列下一个媒体 - 在非重复排列中播放最后一个媒体时,自动推荐相关媒体。 + 在非重复排列中播放最后一个媒体时自动推荐相关媒体 玩家手势控制 使用手势控制播放器的亮度和音量 搜索建议 搜索时显示建议 搜索历史记录 在本地存储搜索 - 历史记录和缓存数据 + 观看历史 记录观看过的视频 取得视窗焦点时继续播放 在被打断后继续播放(例如有来电) @@ -134,7 +134,6 @@ 不支持该网址 默认内容的国家 服务 - 默认内容的语言 播放器 行为 视频与音频 @@ -256,7 +255,7 @@ 没有视频 部视频 - + 删除 校验 @@ -267,7 +266,7 @@ 错误的网址或网络不可用 点按以查看详细信息 复制到剪贴板 - 请选择下载文件夹 + 请稍后在设置中定义一个下载文件夹 在悬浮窗模式打开 \n需要此权限 已删除一个项目。 @@ -337,19 +336,19 @@ 详细 音频设置 长按以新增至队列 - 转到后台时排列 - 排列新的悬浮窗 + 加入后台播放列表 + 加入悬浮窗播放列表 从这里开始播放 - 转到后台时从这里开始 - 从新的悬浮窗开始 + 开始在后台播放 + 开始在新悬浮窗播放 打开抽屉 关闭抽屉 - 某些东西即将在此出现;D + 很快就会出现在这里 ;D 偏好的「开启」动作 开启内容时的默认动作 - %s 视频播放器 - 转到后台播放 - 悬浮窗播放 + 后台播放器 + 悬浮窗播放器 总是询问 正在获取信息… 正在载入请求的内容 @@ -363,12 +362,12 @@ 播放列表缩略图已更改。 无法删除播放列表。 没有字幕 - 合适的 + 合适 填满 缩放 自动生成 字幕 - 修改播放器标题文本比例和背景样式。需要重启才能生效。 + 修改播放器字幕文本比列和背景样式。需要重启才能生效。 启用 LeakCanary 内存泄漏监视可能导致应用程序在存储时无响应 报告活动周期外错误 @@ -416,7 +415,7 @@ 应用升级通知 新 NewPipe 版本通知 外储存不可行 - 下载至外置SD卡还未可行。重置下载文件夹位置? + 无法下载到外部SD卡。重置下载文件夹位置? 恢复默认 您真的要恢复至默认吗? 选择 @@ -452,7 +451,7 @@ 重试上限 取消下载前可以尝试的最多次数 - 换成手机数据时暂停 + 换成手机数据时中断 事件 使用默认选项卡, 读取保存的选项卡时出错 订阅者计数不可用 @@ -464,8 +463,41 @@ 切换视图 NewPipe 更新可用! 无法创建目标文件夹 - 服务器不接受多线程下载, 请重试使用 @string/msg_threads = 1 + 服务器不接受多线程下载, 请使用 @string/msg_threads = 1重试 请求范围无法满足 继续进行%s个待下载转移 - 无法暂停的下载将重新开始 + 切换至移动数据时有用,尽管一些下载无法被暂停 + 显示评论 + 禁用停止显示评论 + 自动播放 + + 评论 + + + 没有评论 + 无法加载评论 + 关闭 + 继续播放 + 恢复上次播放位置 + 列表中的位置 + 在列表中显示播放位置指示符 + 清除数据 + 播放位置已删除。 + 文件被移动或删除 + 已存在具有此名称的文件 + 无法覆盖该文件 + 同名文件正在等待下载 + 处理此文件时 NewPipe 已关闭 + 设备上没有剩余空间 + 进度丢失,因为文件已被删除 + 连接超时 + 你确定吗? + 限制下载队列 + 同时只有一个下载进行 + 开始全部下载 + 暂停全部下载 + 询问下载位置 + 每次下载将询问保存的位置 + 每次下载将询问保存的位置。 +\n如果要下载到外部SD卡,请选中。 \ No newline at end of file diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 97e8c406f..19e662ee7 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -316,13 +316,7 @@ otevření ve vyskakovacím okně Přizpůsobit Vyplnit Zvětšit - Velikost písma nadpisu - Menší písmo - Normální písmo - Větší písmo Sledovat únik paměti - Sledování úniku paměti vypnuto - Sledování úniku paměti povoleno, aplikace může při zátěži přestat reagovat Ladění "Automaticky generováno " Povolit službu LeakCanary @@ -377,7 +371,6 @@ otevření ve vyskakovacím okně Rychlost Výška tónu Rozpojit (může způsobit zkreslení) - Nightcore mód Výchozí nastavení Ke stažení nejsou dostupné žádné streamy Preferovaná \'otevřít\' akce @@ -456,7 +449,7 @@ otevření ve vyskakovacím okně Akce odmítnuta systémem Stahování se nezdařilo Stahování dokončeno - % s stahování dokončeno + %s stahování dokončeno Vytvořit jedinečný název Přepsat Stažený soubor s tímto názvem již existuje @@ -492,7 +485,6 @@ otevření ve vyskakovacím okně Žádné komentáře Nelze načíst komentáře - Přehrát přímo na pozadí Zavřít Stahování na externí SD kartu ještě není možné. Resetovat umístění složky pro stahování\? - \ No newline at end of file + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index ea735f518..7cbfdca92 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -58,7 +58,6 @@ Konnte Video-URL-Signatur nicht entschlüsseln Konnte Webseite nicht analysieren Inhalt nicht verfügbar - Inhalt Altersbeschränkte Inhalte Altersbeschränktes Video anzeigen. Das Zulassen dieses Materials ist von den Einstellungen aus möglich. @@ -98,7 +97,7 @@ Datei existiert bereits Bitte warten… In Zwischenablage kopiert - Bitte wähle ein verfügbares Downloadverzeichnis + Bitte gib später in den Einstellungen einen Downloadverzeichnis an Starten Pause Abspielen @@ -166,12 +165,12 @@ Buchstaben und Zahlen Abonnieren Abonniert - Abonnement beendet + Kanal abbestellt Abos Neuigkeiten Suchverlauf Suchanfragen lokal speichern - Verlauf & Cache + Verlauf ansehen Speichere den Wiedergabeverlauf Verlauf Gesucht @@ -277,7 +276,7 @@ Keine gültige ZIP-Datei Warnung: Nicht alle Dateien konnten importiert werden. Dies wird deine aktuellen Einstellungen überschreiben. - Info anzeigen + Infos anzeigen Lesezeichen für Wiedergabelisten Hinzufügen zu Zum Neuordnen ziehen @@ -302,9 +301,7 @@ Vorschaubild der Wiedergabeliste geändert. Konnte Wiedergabeliste nicht löschen. Keine Untertitel - Schriftgröße der Untertitel Abbrechen - Normale Schriftgröße Stream-Datei herunterladen Schnelle, ungenaue Suche verwenden Mit ungenauem Suchen kann die Abspielposition schneller erreicht werden, aber auf Kosten der Genauigkeit @@ -314,8 +311,6 @@ Dateiname darf nicht leer sein Ein Fehler ist aufgetreten: %1$s Automatisch erzeugt - Kleinere Schrift - Größere Schrift LeakCanary aktivieren Import von Export nach @@ -344,7 +339,6 @@ Geschwindigkeit Tonhöhe Verknüpfung aufheben (kann zu Verzerrungen führen) - Nightcore Standard Abschalten, um das Laden von Miniaturansichten zu verhindern, was Daten- und Speicherverbrauch spart. Änderungen löschen den Bildzwischenspeicher sowohl im Arbeitsspeicher als auch auf dem internen Speicher. Nächsten Stream automatisch einreihen @@ -408,7 +402,7 @@ Wiedergabelisten Titel Benutzer - Deabonnieren + Abbestellen Neuer Tab Tab wählen Gestensteuerung für Lautstärke @@ -420,7 +414,7 @@ Aktualisierungsbenachrichtigung Benachrichtigung bei neuer NewPipe-Version Kein externer Speicher verfügbar - Herunterladen auf externe SD-Karte ist noch nicht möglich. Zielverzeichnis zurücksetzen\? + Herunterladen auf externe SD-Karte ist nicht möglich. Downloadverzeichnis zurücksetzen\? Fehler beim Lesen der gespeicherten Tabs – es werden die Voreinstellungen benutzt Voreinstellungen wiederherstellen Möchtest du die Voreinstellungen wiederherstellen\? @@ -453,7 +447,7 @@ Fehler anzeigen Code Die Datei kann nicht erstellt werden - Der Zielordner kann nicht erstellt werden + Das Zielverzeichnis kann nicht erstellt werden System verweigert den Zugriff Sichere Verbindung fehlgeschlagen Der Server konnte nicht gefunden werden @@ -468,8 +462,8 @@ Anhalten Maximale Wiederholungen Maximalanzahl der Versuche, bevor der Download abgebrochen wird - Beim Umschalten auf mobile Daten pausieren - Downloads, die nicht pausiert werden können, werden wiederholt + Unterbrechen bei kostenpflichtigen Netzwerken + Nützlich beim Wechsel zu mobilen Daten, obwohl einige Downloads nicht unterbrochen werden können Konferenzen Ereignisse Verbindungszeitüberschreitung @@ -478,10 +472,31 @@ Autoplay Kommentare - + Keine Kommentare Kommentare konnten nicht geladen werden - Direkt im Hintergrund wiedergeben Schließen + Wiedergabe fortsetzen + Wiederherstellen der letzten Wiedergabeposition + Positionen in Listen + Wiedergabepositionsanzeigen in Listen anzeigen + Daten löschen + Wiedergabeposition gelöscht. + Datei verschoben oder gelöscht + Eine heruntergeladene Datei mit diesem Namen existiert bereits + kann die Datei nicht überschreiben + Es gibt einen ausstehenden Download mit diesem Namen + NewPipe wurde während der Verarbeitung der Datei geschlossen + Kein Speicherplatz mehr auf dem Gerät + Vorgang abgebrochen, da die Datei gelöscht wurde + Bist du sicher\? + Downloadwarteschlange begrenzen + Ein Download wird zur gleichen Zeit ausgeführt + Downloads starten + Downloads anhalten + Frage, wohin heruntergeladen werden soll + Du wirst gefragt, wohin du jeden Download speichern willst + Du wirst gefragt, wohin du jeden Download speichern willst. +\nAktiviere diese Option, wenn du auf die externe SD-Karte herunterladen möchtest \ No newline at end of file diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 90e8f331d..3484c0e58 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -475,6 +475,5 @@ Χωρίς σχόλια Δεν ήταν δυνατή η φόρτωση σχολίων - Αναπαραγωγή απευθείας στο παρασκήνιο Κλείσιμο \ No newline at end of file diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 668708130..42d46cb95 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -1,4 +1,4 @@ - + %1$s vidoj Eldonita je %1$s @@ -15,7 +15,6 @@ turno Uzi eksteran videoludilon Uzi eksteran sonludilon - Defaŭlta distingivo Ludi per Kodi Montri \"Ludi per Kodi\"-opcion @@ -24,7 +23,6 @@ Etoso Malluma Luma - Elŝuti Sekva video Ligilo ne subtenita @@ -37,7 +35,6 @@ Eraro Reteraro Enhavo ne estas disponebla - Ŝatoj Malŝatoj Uzi la programon Tor @@ -55,27 +52,22 @@ Elŝutujo por videoj Elŝutujo por muziko (Eksperimenta) Devigi elŝuttrafikon tra Tor por pli bona privateco (elsendfluaj videoj estas ankoraŭ ne subtenitaj). - Montri opcion por ludi videon per la aplikaĵo Kodi Dosierujo por konservi elŝutitajn videojn Dosierujo por konservi elŝutitan muzikon Elektu lokon por konservi elŝutitajn videojn - Elektu lokon por konservi elŝutitan muzikon - Enhavo Raporti eraron per retpoŝto RAPORTI Informoj: Via komento (en la angla): Detaloj: - - Raporti eraron Video Reprovi -Tapu serĉo por komenci - Neniu elsendlflua ludilo trovita (instalu VLC por ludi ĝin) + Tapu serĉo por komenci + Neniu elsendlflua ludilo trovita (instalu VLC por ludi ĝin). Malfermi en ŝprucfenestron modon Iuj rezolucioj NE havos aŭdion kiam ĉi tiu eblo estas ebligita NewPipe ŝprucfenestron modon @@ -83,20 +75,16 @@ Abonita Kanalo malabonita Neebla ŝanĝi abonon - Elŝutu dosieron. + Elŝutu dosieron Ne eblas ĝisdatigi abonon Montri informon - Ĉefa Abonoj Legosigno - Kio novas - Fono ŝprucfenestron Aldonu al - Aŭtomata play Ludas video kiam NewPipe vokas de alia programo Defaŭlta popup rezolucio @@ -109,4 +97,4 @@ Uzu rapide, ne preciza serĉon Ne preciza serĉo permesas al la ludanto serĉi poziciojn pli rapide kun malalta precizeco Ŝarĝi bildetojn - + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index faf88a652..028f146fc 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -322,8 +322,6 @@ abrir en modo popup La búsqueda inexacta permite al reproductor buscar posiciones más rápido con menor precisión Auto-encolar la siguiente transmisión Añadir de forma automática un vídeo relacionado con el último vídeo reproducido en una cola no repetitiva - DIRECTO - SINCRONIZAR Archivo Archivo movido o eliminado No existe el directorio @@ -460,7 +458,9 @@ abrir en modo popup Preguntar dónde descargar Se preguntará dónde guardar cada descarga - Se preguntará dónde guardar cada descarga.\nHabilita esta opción si quieres descargar en la tarjeta SD externa + Se preguntará dónde guardar cada descarga.\nHabilita esta opción junto con SAF si quieres descargar en la tarjeta SD externa + Usar SAF + El Framework de Acceso al Almacenamiento permite descargar en la tarjeta SD externa.\nNota: Algunos los dispositivos no son compatibles Desuscribirse Nueva pestaña @@ -498,6 +498,5 @@ abrir en modo popup Sin comentarios No se pudo cargar comentarios - Reproducir directamente en segundo plano Cerrar \ No newline at end of file diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index d66087a35..1db244c22 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -136,7 +136,7 @@ Ukitu xehetasunetarako Itxaron mesedez… Arbelera kopiatuta - Aukeratu eskuragarri dagoen karpeta bat deskargetarako + Ezarri deskargetarako karpeta bat ezarpenetan geroago Baimen hau beharrezkoa da \nlaster-leiho moduan irekitzeko reCAPTCHA @@ -176,7 +176,7 @@ Karaktere berezi gehienak Bilaketa historiala Gorde bilaketak lokalki - Historiala eta katxea + Ikustaldien historiala Gorde ikusitako bideoen historiala NewPipe jakinarazpena Erreproduzigailua @@ -374,7 +374,6 @@ Tempoa Tonua Deslotu (distortsioa sor lezake) - Nightcore Lehenetsia Ezarpenak ere inportatu nahi dituzu? Bilaketa ez zehatzak posizioak azkarrago baina prezisio gutxiagoz bilatzea ahalbidetzen du @@ -416,7 +415,7 @@ Aplikazioaren eguneraketaren jakinarazpena NewPipe aplikazioaren bertsio berrien jakinarazpena Kanpo biltegiratzea ez dago eskuragarri - Oraindik ezin da SD txartel batera deskargatu. Deskargen karpeta berrezarri\? + Ezin da SD txartel batera deskargatu. Deskargen karpeta berrezarri nahi duzu\? Lehenetsitako fitxak erabiltzen, errorea gordetako fitxak irakurtzean Berrezarri lehenetsitakoak Lehenetsitakoak berrezarri nahi dituzu\? @@ -465,18 +464,39 @@ Gelditu Gehienezko saiakerak Deskarga ezeztatu aurretik saiatu beharreko aldi kopurua - Pausatu datu mugikorretara aldatzean - Pausatu ezin daitezkeen deskargak berrekingo dira + Eten sare neurtuetan + Erabilgarria datu mugikorretara aldatzean, hala ere deskarga batzuk ezin dira pausatu Konexioaren denbora muga Erakutsi iruzkinak Desgaitu iruzkinak erakusteari erakusteko Erreprodukzio automatikoa Iruzkinak - + Iruzkinik ez Ezin izan dira iruzkinak kargatu - Erreproduzitu zuzenean bigarren planoan Itxi + Berrekin erreprodukzioa + Berrezarri azken erreprodukzio-posizioa + Posizioak zerrendetan + Erakutsi erreprodukzio-posizioen adierazleak zerrendetan + Garbitu datuak + Erreprodukzio-posizioak ezabatuta. + Fitxategia lekuz aldatu edo ezabatu da + Badago izen bereko fitxategi bat + ezin da fitxategia gainidatzi + Badago izen bereko deskarga bat burutzeke + NewPipe itxi egin da fitxategian lanean zegoela + Ez dago lekurik gailuan + Progresioa galdu da, fitxategia ezabatu delako + Ziur al zaude\? + Mugatu deskargen ilara + Deskarga bakarra aldi berean + Hasi deskargak + Pausatu deskargak + Galdetu non deskargatu + Non gorde galdetuko zaizu deskarga bakoitzean + Non gorde galdetuko zaizu deskarga bakoitzean. +\nGaitu aukera hau kanpo SD txartelean gorde nahi baduzu \ No newline at end of file diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index cfee00176..7646eb437 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -55,10 +55,10 @@ خطا خطای شبکه نمی‌توان تمام بندانگشتی‌ها را بار کرد - نمی‌توان امضای نشانی اینترنتی ویدیو را رمزگشایی کرد. - نمی‌توان پایگاه وب را تجزیه کرد. - نمی‌توان پایگاه وب را به صورت کامل تجزیه کرد. - محتوا در دسترس نیست. + نمی‌توان امضای نشانی اینترنتی ویدیو را رمزگشایی کرد + نمی‌توان پایگاه وب را تجزیه کرد + نمی‌توان پایگاه وب را به صورت کامل تجزیه کرد + محتوا در دسترس نیست نمی‌توان فهرست بارگیری را برپا ساخت. جریان‌های زنده هنوز پشتیبانی نمی‌شوند نمی‌توان هیچ جریانی را گرفت diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ae5abb76e..15b3a5a9b 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -55,7 +55,6 @@ Erreur Impossible d\'analyser le site web Contenu non disponible - Désolé, des erreurs se sont produites. Contenu Contenu avec limite d\'âge @@ -103,7 +102,7 @@ Appuyer pour plus de détails Veuillez patienter… Copié dans le presse-papiers - Sélectionner un dossier de téléchargement disponible + Veuillez définir un dossier de téléchargement plus tard dans les paramètres Impossible de charger l\'image L’application a crashé reCAPTCHA @@ -175,7 +174,7 @@ Caractère de remplacement Historique de recherche Conserver les recherches sur l\'appareil - Historique et cache + Voir l \'historique Historique Recherché Regardé @@ -308,10 +307,6 @@ Aucuns sous-titres Ajuster Zoom - Taille des sous-titres - Petite - Normale - Grande Recherche rapide approximative Permettre au lecteur d\'accéder plus rapidement à une position au détriment de la précision Charger les miniatures @@ -373,7 +368,6 @@ Sous-titres Modifier la taille du texte et les styles d\'arrière-plan du lecteur. Redémarrage requis pour prendre effet. Ton - Nightcore Aucune application installée pour lire ce fichier Effacer l\'historique Supprimer l\'historique des flux regardés @@ -426,7 +420,7 @@ Sélection Arrêter Événements - Télécharger vers la carte SD n\'est pas encore possible. Voulez-vous réinitialiser l\'emplacement du dossier \? + Télécharger vers la carte SD n\'est pas possible. Voulez-vous réinitialiser l\'emplacement du dossier \? Quels onglets seront visibles sur la page principale Mises à jour Afficher une notification pour proposer une mise à jour de l\'application lorsqu\'une nouvelle version est disponible @@ -437,7 +431,7 @@ Une mise à jour de NewPipe disponible ! Appuyez pour télécharger Terminé - Dans la file d\'attente + En attente En pause Téléchargement échoué Délai de connection dépassé @@ -452,8 +446,8 @@ Il y a un téléchargement en cours avec ce nom Afficher l\'erreur Code - Le fichier ne peut pas être créé - Le dossier de destination ne peut pas être créé + Le dossier de destination ne peut pas être créé + Le fichier ne peut pas être créé Autorisation refusée par le système Échoué de la connexion sécurisée Le serveur est introuvable @@ -462,7 +456,7 @@ Introuvable Effacer les téléchargements terminés Mettre en pause lors du passage en données mobiles - Les téléchargements qui ne peuvent pas être mis en pause seront redémarrés + Utile lors du passage aux données mobiles, bien que certains téléchargements ne peuvent pas être suspendus Mode liste post-traitement File d’attente @@ -483,6 +477,22 @@ Pas de commentaires Impossible de charger les commentaires - Jouer directement en arrière-plan Fermer + Reprendre la lecture + Effacer les données + Fichier déplacé ou supprimé + ne peut pas remplacer le fichier + Il y a déjà un téléchargement en attente avec ce nom + NewPipe a été fermé alors qu\'il travaillait sur le fichier + Aucun espace disponible sur le périphérique + Progression perdue, car le fichier a été effacé + Êtes-vous certain \? + Limiter la file d\'attente de téléchargement + Un téléchargement s\'exécutera en même temps + Démarrer les téléchargements + Mettre en pause les téléchargements + Demander où télécharger + On vous demandera où enregistrer chaque téléchargement + On vous demandera où enregistrer chaque téléchargement. +\nActivez cette option si vous voulez télécharger sur la carte SD externe \ No newline at end of file diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 798d5833b..899a9be10 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -93,7 +93,6 @@ Este URL non está soportado País predeterminado para o contido Servizo - Idioma predeterminado do contido Reprodutor Comportamento Vídeo e audio diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 767a1445a..aed3fda64 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -52,7 +52,7 @@ הצעות חיפוש הצגת הצעות בעת החיפוש הורדה - הבא בתור + הבא להציג סרטונים דומים ובאים בתור כתובת לא נתמכת שפת התוכן המועדפת @@ -108,7 +108,7 @@ מה חדש היסטוריית חיפוש שמירת שאילתות החיפוש מקומית - היסטוריה ומטמון + היסטוריית צפייה תיעוד הסרטונים שנצפו להמשיך את הניגון עם החזרת המיקוד להמשיך לנגן לאחר הפרעות (למשל: שיחות טלפון) @@ -168,9 +168,9 @@ אין סרטונים סרטון - שני סרטונים - %s סרטונים - %s סרטונים + סרטונים + סרטונים + סרטונים התחלה השהיה @@ -189,7 +189,7 @@ יש לגעת לפרטים נוספים נא להמתין… הועתק ללוח - נא לבחור תיקיית הורדה זמינה + נא לציין תיקיית הורדה בהגדרות בהמשך הרשאה זו נדרשת לטובת \nפתיחה בחלון צף reCAPTCHA @@ -407,7 +407,7 @@ התראת עדכון יישומון התראות על גרסה חדשה של NewPipe האחסון החיצוני אינו זמין - אין עדיין אפשרות להוריד לכרטיס SD. לאפס את מיקום תיקיית ההורדה\? + אין אפשרות להוריד לכרטיס SD. לאפס את מיקום תיקיית ההורדה\? נעשה שימוש בלשוניות בררת המחדל, אירעה שגיאה בעת קריאת הלשוניות שנשמרו שחזור בררות מחדל לשחזר את בררות המחדל\? @@ -469,20 +469,42 @@ עצירה מספר הניסיונות החוזרים המרבי מספר הניסיונות החוזרים המרבי בטרם ביטול ההורדה - להשהות בעת מעבר לתקשורת נתונים סלולרית - הורדות שלא ניתן להשהות יופעלו מחדש - בהמתנה + לייצר הפרעה ברשתות מדודות + שימושי בעת מעבר לחיבור רשת סלולרית, למרות שישנן הורדות שלא ניתן להשהות הצגת תגובות יש להשבית כדי להפסיק הצגת תגובות ניגון אוטומטי תגובות - - - + + + אין תגובות לא ניתן לטעון תגובות - לנגן ישירות ברקע סגירה + בהמתנה + להמשיך בנגינה + לשחזר את מיקום הנגינה האחרון + מיקומים ברשימות + להציג מחווני מיקומי נגינה ברשימות + לנקות את הנתונים + מיקומי הנגינה נמחקו. + הקובץ הועבר או נמחק + כבר קיים קובץ בשם הזה + לא ניתן לשכתב על הקובץ + כבר יש הורדה ממתינה בשם הזה + NewPipe נסגר בזמן העבודה על הקובץ + לא נשאר מקום במכשיר + התהליך אבד כיוון שהקובץ נמחק + החיבור המתין זמן רב מדי + בוודאות\? + הגבלת תור ההורדה + רק הורדה אחת תרוץ בו־זמנית + התחלת הורדות + השהיית הורדות + לשאול לאן להוריד + תופיע שאלה לאן לשמור כל הורדה + תוצג שאלה היכן לשמור כל הורדה. +\nיש להפעיל זאת אם ברצונך להוריד לכרטיס SD חיצוני. \ No newline at end of file diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 89aaacb00..44edee145 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -310,10 +310,6 @@ फिट भरें ज़ूम करें - कैप्शन फ़ॉंट आकार - छोटे फ़ॉंट - सामांय फ़ॉंट - बड़ा फ़ॉंट डीबग करें ऑटो-जनरेटेड LeakCanary सक्षम करें diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index b31060ba9..e85d5810e 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -276,10 +276,6 @@ Ispuniti Povećaj Auto generirano - Veličina fonta naslova - Manji font - Normalni font - Veći font Omogući \"LeakCanary\" Monitoring curenja memorije može uzrokovati greške u radu aplikacije prilikom odlaganje gomile Izvijestite o pogreškama izvan životnog ciklusa @@ -478,7 +474,6 @@ Nema komentara Komentare nije moguće učitati - Sviraj izravno u pozadini Zatvori NewPipe je copyleft libre software: možete ga koristiti, proučavati i poboljšavati po volji. Konkretno, možete ga redistribuirati i / ili modificirati pod uvjetima GNU opće javne licence koju je objavila Free Software Foundation, bilo verzije 3 Licence, ili (po vašem izboru) bilo koje kasnije verzije. "Projekt NewPipe ozbiljno shvaća vašu privatnost. Stoga aplikacija ne prikuplja nikakve podatke bez vašeg pristanka. diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 5e11fdf6d..e00cbd2e3 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -97,7 +97,7 @@ Sentuh untuk detail Mohon tunggu… Disalin ke papan klip - Silakan pilih direktori unduhan yang tersedia + Silakan pilih folder unduhan di pengaturan Pemutar stream tidak ditemukan. Apakah anda ingin memasang VLC\? Tidak bisa dekripsi tanda tangan URL video App/UI rusak @@ -171,7 +171,7 @@ Utama Riwayat pencarian Simpan pencarian secara lokal - Riwayat & Cache + Riwayat tontonan Notifikasi NewPipe Riwayat Riwayat dinonaktifkan @@ -312,12 +312,7 @@ Isi Perbesar Otomatis dibuat - Ukuran fon deskripsi - Fon lebih kecil - Fon normal - Fon lebih besar Aktifkan LeakCanary - Nightcore Bawaan Pemutar stream tidak ditemukan (anda bisa memasang VLC untuk memutarnya). Unduh berkas stream @@ -417,7 +412,7 @@ Notifikasi Pembaruan Apl Notifikasi untuk versi NewPipe baru Penyimpanan eksternal tidak tersedia - Belum bisa mengunduh ke kartu SD eksternal. Setel ulang lokasi folder unduhan\? + Tidak bisa mengunduh ke kartu SD eksternal. Atur ulang lokasi folder unduhan\? Menggunakan tab baku, ralat saat membaca tab yang disimpan Kembali ke awal Apakah anda ingin kembali ke awal\? @@ -466,8 +461,8 @@ Berhenti Percobaan maksimum Jumlah upaya maksimum sebelum membatalkan unduhan - Berhenti ketika beralih ke data seluler - Unduhan yang tidak dapat dijeda akan diulang dari awal + Berhenti pada jaringan terbatas + Berguna saat beralih ke data seluler, walaupun beberapa unduhan tidak bisa ditangguhkan Tampilkan komentar Nonaktifkan untuk berhenti menampilkan komentar Otomatis putar @@ -476,6 +471,27 @@ Tidak ada komentar Tidak bisa memuat komentar - Putar di latar belakang Tutup + Lanjutkan pemutaran + Pulihkan posisi pemutaran terakhir + Posisi dalam daftar + Tampilkan indikator posisi pemutaran di dalam daftar + Hapus data + Posisi pemutaran dihapus. + Berkas dipindah atau dihapus + Berkas dengan nama yang sama sudah ada + tidak bisa menimpa ulang berkas + Ada unduhan yang dijeda dengan nama ini + NewPipe telah ditutup saat sedang memproses berkas + Tidak ada ruang kosong tersisa pada perangkat + Kehilangan laju, karena berkas telah dihapus + Apakah anda yakin\? + Batasi antrean unduhan + Satu unduhan akan berjalan pada waktu yang bersamaan + Mulai unduh + Jeda unduh + Tanyakan lokasi unduhan + Anda akan ditanya lokasi penyimpanan berkas unduhan + Anda akan ditanya lokasi penyimpanan berkas unduhan. +\nAktifkan opsi ini jika anda ingin mengunduh ke kartu SD eksternal \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index e217a4ee5..f9308ec8f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -310,10 +310,6 @@ Rientrato Pieno Ingrandito - Dimensione dei caratteri dei sottotitoli - Carattere più piccolo - Carattere normale - Carattere più grande A breve qualcosa apparirà qui ;D Debug Generato automaticamente @@ -325,7 +321,6 @@ La ricerca imprecisa permette al lettore multimediale di spostarsi nelle posizioni più velocemente con una precisione ridotta Metti in coda automaticamente il prossimo flusso Aggiungi automaticamente uno stream correlato raggiunta la fine della coda se la ripetizione è disattivata - SINCRONIZZAZIONE File Nessuna cartella Nessun file o cartella che contiene sorgenti @@ -367,7 +362,6 @@ Tempo Tono Scollega (può causare distorsione) - Nightcore Valore predefinito Nessun flusso disponibile per il download \'Apri\' preferibilmente con @@ -482,6 +476,5 @@ Nessun commento Impossibile caricare i commenti - Riproduci direttamente in sottofondo Chiudi \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 5375c09a7..296e6e217 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -57,7 +57,6 @@ 動画のURLを復号できませんでした Webサイトを解析できませんでした コンテンツが利用できません - 保存メニューを設定できませんでした 生放送にはまだ対応していません コンテンツ @@ -100,7 +99,7 @@ タップして詳細を表示 お待ちください… クリップボードにコピーしました - ダウンロードフォルダを選択して下さい + 後ほど設定でダウンロードフォルダを定義してください ダウンロード ダウンロード 不具合報告 @@ -169,7 +168,7 @@ 新着 検索履歴 検索した履歴を記憶します - 再生履歴とキャッシュ + 視聴履歴 再生した履歴を記憶します オーディオフォーカス復帰で再開する 電話などによる中断の後、再生を再開します @@ -294,7 +293,6 @@ プレイリストのサムネイルを変更しました。 プレイリストを削除できませんでした。 字幕表示なし - 字幕の文字サイズ インポート/エクスポート インポート インポート元 @@ -437,8 +435,8 @@ 同じ名前を持つダウンロードが既に進行中です エラーを表示する コード - ファイルを作成できません - 宛先フォルダを作成できません + 宛先のフォルダーを作成できません + ファイルを作成できません 権限がシステムによって拒否されました 安全な接続に失敗しました サーバが見つかりませんでした @@ -458,14 +456,14 @@ ジェスチャーを使用して、プレーヤーの明るさを制御します ファイルを削除しました アプリの更新通知 - まだ外部 SD カードにダウンロードできません。ダウンロードフォルダーの場所をリセットしますか\? + 外部 SD カードにダウンロードできません。ダウンロードフォルダーの場所をリセットしますか\? デフォルトのタブを使用します。保存されたタブの読み込みエラーが発生しました メインページに表示されるタブ 新しいバージョンが利用可能なときにアプリの更新を確認する通知を表示します ダウンロードから %s の保留中の転送を続行します - モバイルデータ通信に切り替え時に休止 - 休止できないダウンロードが再開されます - 接続タイムアウト + 従量制課金ネットワークの割り込み + モバイルデータ通信に切り替える場合に便利ですが、一部のダウンロードは一時停止できません + コメントを表示 無効にするとコメントの表示を停止します 自動再生 @@ -473,7 +471,27 @@ コメントはありません コメントを読み込めませんでした - バックグラウンドで直接再生 閉じる - コメントを表示 + 接続タイムアウト + 再生を再開 + 最後に再生した位置を復元します + リスト内の位置 + リストに再生位置インジケーターを表示します + データをクリア + 再生位置を削除しました。 + ファイルが移動または削除されました + ファイルを上書きできません + この名前の保留中のダウンロードがあります + ファイルの作業中に NewPipe が閉じられました + デバイスに空き容量がありません + ファイルが削除されたため、進行状況が失われました + よろしいですか\? + ダウンロード キューの制限 + 同時に1つのダウンロードが実行されます + ダウンロードの開始 + ダウンロードの一時停止 + ダウンロード先を尋ねる + ダウンロードのたびに保存する場所を尋ねます + ダウンロードのたびに保存する場所を尋ねます。 +\n外部 SD カードにダウンロードする場合は、このオプションをオンにしてください。 \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 494a0789b..c82e0044b 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -257,7 +257,6 @@ 기본 콘텐츠 국가 서비스 디버그 - 라이브 (LIVE) 항상 한번만 디바이스 방향 토글 @@ -315,11 +314,6 @@ 채우기 확대 자동 생성됨 - 자막 폰트 크기 - 작은 폰트 - 보통 폰트 - 큰 폰트 - 동기화 LeakCanary 할성화 힙 덤프 중 메모리 누수 점검으로 앱이 불안정해질 수 있습니다 out-of-lifecycle 오류 보고 @@ -368,7 +362,6 @@ 템포 피치 영상과 소리 분리 (소리가 깨질 수 있음) - 나이트코어 기본 다운로드 가능한 스트림이 없습니다 이 파일을 재생할 수 있는 플레이어 앱이 없습니다 @@ -481,6 +474,5 @@ 댓글 없음 댓글을 불러올 수 없음 - 백그라운드에서 바로 재생 닫기 \ No newline at end of file diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index edb78cc3c..43fe9d862 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -362,10 +362,6 @@ Priartinti Automatiškai sugeneruotas - Antraštės šrifto dydis - Mažesnis šriftas - Normalus šriftas - Didesnis šriftas Įjungti LeakCanary Atminties nutekėjimo stebėjimas gali padaryti programėlę nestabilią diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index f1c8a943e..ca1721115 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -368,10 +368,6 @@ Зумирај Автоматски создадено - Големина на преводот - Помал фонт - Нормален фонт - Поголем фонт Вклучи LeakCanary Следењето на мемориските грешки може да ја прикочува апликацијата @@ -414,7 +410,6 @@ Темпо Тон Откачи (може да создаде мутации) - „Nightcore“ Стандардно Избриши историја на гледаност Ја брише историјата на пуштени видеа diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 3729fc086..ee7dd9e95 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -105,7 +105,7 @@ Start Nytt mål Feilaktig nettadresse eller manglende internettilknytning - Velg ei tilgjengelig nedlastingsmappe + Velg nedlastingsmappe senere i innstillingene reCAPTCHA reCAPTCHA-oppgave Åpne i oppsprettsmodus @@ -143,7 +143,7 @@ Vis søkeforslag ved søk Søkehistorikk Lagre søkemønster lokalt - Historikk og mellomlagring + Visningshistorikk Lagre visningshistorikk Oppsprett Filter @@ -310,10 +310,6 @@ Tilpass Fyll Forstørr - Bildetekstens størrelse - Mindre skrift - Normal skrift - Større skrift Bruk raskt unøyaktig blafring Feilretting Fil @@ -383,7 +379,6 @@ Rapporter feil som opptrer utenfor sin levetid Tving rapportering av uleverbare Rx-unntak utenom fragment eller aktivitetslevetid etter forkastelse Avhekt (kan forårsake forvrenging) - Nightcore NewPipes personvernspraksis NewPipe-prosjektet tar ditt personvern veldig alvorlig. Derfor samler ikke programmet inn data uten ditt samtykke. \nNewPipes personvernspraksis forklarer i detalj hvilken deta som sendes og lagres når du sender en kræsjrapport. @@ -419,7 +414,7 @@ Programoppgraderingsmerknad Merknader for nye NewPipe-versjoner Ekstern lagring utilgjengelig - Nedlasting til eksternt SD-kort er ikke mulig enda. Tilbakestill plassering av nedlastingsmappe\? + Nedlasting til eksternt SD-kort er ikke mulig. Tilbakestill plassering av nedlastingsmappe\? Bruker forvalgte faner, feil under lagring av lagrede faner. Gjenopprett forvalg Ønsker du å gjenopprette alt til forvalgene\? @@ -467,8 +462,8 @@ Stopp Maksimalt antall forsøk Maksimalt antall tilkoblingsforsøk før nedlastingen avblåses - Pause ved veksling til mobildata - Nedlastinger som ikke kan pauses vil bli startet på nytt + Pause ved veksling til kvotebasert nett + Nyttig ved veksling til mobildata, selv om noen nedlastinger ikke kan settes på pause Vis kommentarer Skru av for å stoppe visning i kommentarer Spill av automatisk @@ -478,6 +473,29 @@ Ingen kommenterer Kunne ikke laste inn kommentarer - Spill direkte i bakgrunnen Lukk + Venter + Gjenoppta avspilling + Fortsett der du slapp + Posisjon i lister + Vis avspillingsposisjonsindikator i lister + Tøm data + Avspillingsposisjon slettet + Fil flyttet eller slettet + En fil ved dette navnet finnes allerede + Kan ikke overskrive filen + Det finnes en ventende nedlasting ved dette navnet + NewPipe ble lukket under arbeid med filen + Ingen ledig plass på enheten + Framdrift gikk tapt, fordi filen ble slettet + Tilkoblingsavbrudd + Er du sikker\? + Begrens nedlastingskø + Én nedlasting av gangen + Start nedlastinger + Sett nedlastinger på pause + Spør om hvor ting skal lastes ned til + Du vil bli spurt om hvor hver nedlasting skal plasseres + Du vil bli spurt om hvor hver nedlasting skal plasseres. +\nSkru på dette valget hvis du vil laste ned til eksternt SD-kort. \ No newline at end of file diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index 9ddba1bcb..2dd854acf 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -367,7 +367,6 @@ Tempo Toon Ontkoppelen (kan ruis veroorzaken) - Nightcore Standaard Kijkgeschiedenis wissen Verwijdert de geschiedenis van afgespeelde streams @@ -474,6 +473,5 @@ Geen commentaren Kan commentaren niet laden - Rechtstreeks in achtergrond afspelen Sluiten \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index d4c86a297..b53ed1d90 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -310,10 +310,6 @@ Inpassen Opvullen Inzoomen - Lettergrootte van bijschrift - Kleiner lettertype - Normaal lettertype - Groter lettertype Hier zal binnenkort iets verschijnen ;D Foutopsporing Automatisch gegenereerd @@ -325,7 +321,6 @@ Minder exact spoelen laat de speler sneller posities zoeken met verminderde precisie Volgende stream automatisch in wachtrij plaatsen Automatisch een gerelateerde stream toekennen bij het afspelen van de laatste stream in een niet-herhalende afspeelwachtlijst - SYNCHRONISEREN Bestand Deze map bestaat niet Bestand/Inhoudsbron bestaat niet @@ -367,7 +362,6 @@ Tempo Toon Ontlinken (kan ruis veroorzaken) - Nightcore Standaard Voorkeursactie voor openen Standaardactie bij openen van inhoud — %s @@ -482,6 +476,5 @@ Geen reacties Kan reacties niet laden - Direct spelen in achtergrond Sluiten \ No newline at end of file diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index c307caead..ccaae00b3 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -1,31 +1,500 @@ - -ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਸਰਚ ਦਬਾਓ - %1$s ਦੇਖੇ - %1$s ਤੇ ਪਬਲਿਸ਼ ਕੀਤਾ - ਸਟਰੀਮ ਪਲੇਅਰ ਨਹੀਂ ਮਿਲਿਆ . ਤੁਸੀ VLC ਭਰਨਾ ਚਾਹੋਗੇ? - ਸਟਰੀਮ ਪਲੇਅਰ ਨਹੀਂ ਮਿਲਿਆ (ਤੁਸੀਂ vlc ਇੰਸਟਾਲ ਕਰ ਸਕਦੇ ਹੋ) - ਭਰੋ - ਨਹੀਂ - Browser ਚ ਖੋਲੋ - Popup ਚ ਖੋਲੋ - ਭੇਜੋ + + + ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਸਰਚ ਦਬਾਓ + %1$s VIEWS + %1$s ਨੂੰ ਪਬਲਿਸ਼ ਕੀਤੀ ਗਈ + "ਸਟ੍ਰੀਮ ਪਲੇਅਰ ਨਹੀਂ ਮਿਲਿਆ। ਤੁਸੀਂ VLC ਭਰਨਾ ਚਾਹੋਗੇ \?" + ਸਟ੍ਰੀਮ ਪਲੇਅਰ ਨਹੀਂ ਮਿਲਿਆ ਤੁਸੀਂ VLC ਇੰਸਟਾਲ ਕਰ ਸਕਦੇ ਹੋ. + ਇੰਸਟਾਲ + ਰੱਦ ਕਰੋ + ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਖੋਲੋ + ਪੌਪ-ਅਪ ਵਿਚ ਖੋਲੋ + ਸਾਂਝਾ ਕਰੋ ਡਾਊਨਲੋਡ - ਡਾਊਨਲੋਡ ਸਟਰੀਮ ਫਾਈਲ. + ਡਾਊਨਲੋਡ ਸਟ੍ਰੀਮ ਫਾਈਲ ਖੋਜੋ - ਸੇਟਿੰਗਾਂ + ਸੈਟਿੰਗਾਂ ਕੀ ਤੁਹਾਡਾ ਮਤਲਬ: %1$s\? - ਭੇਜੋ - Browser ਚੁਣੋ - ਉਲਟਾਨਾ - ਹੋਰ ਪਲੇਅਰ ਵਰਤਤੋ - ਕੁਝ ਵੀਡੀਓ ਰੈਸੋਲੂਸ਼ਨ ਚੁਣਨ ਨਾਲ ਆਡੀਓ ਮੌਜੂਦ ਨਹੀਂ ਹੋਵੇਗੀ + ਸਾਂਝਾ ਕਰੋ + ਬ੍ਰਾਊਜ਼ਰ ਚੁਣੋ + ਰੋਟੇਸ਼ਨ + ਹੋਰ ਵੀਡੀਓ ਪਲੇਅਰ ਦੀ ਵਰਤੋਂ ਕਰੋ + ਕੁਝ ਰੇਸੋਲਿਯੁਸ਼ਨ ਤੇ ਆਵਾਜ਼ ਨੂੰ ਹਟਾਉਂਦਾ ਹੈ ਬਾਹਰੀ ਆਡੀਓ ਪਲੇਅਰ ਦੀ ਵਰਤੋਂ ਕਰੋ - NewPipe ਪੋਪਉਪ ਮੋਡ - ਸਅਬਸਕਰਾਇਬ - ਮੈਂਬਰ ਬਣਏ - ਚੈਨਲ ਸਦੱਸਤਾ ਰੱਦ ਕੀਤੀ ਗਈ - ਸਦੱਸਤਾ ਨੂੰ ਬਦਲਣ ਵਿਚ ਅਸਮਰੱਥ ਹੈ - ਜਾਣਕਾਰੀ - + NewPipe ਪੌਪ-ਅਪ ਮੋਡ + ਸਬਸਕ੍ਰਾਈਬ + ਸਬਸਕ੍ਰਾਈਬ ਕੀਤਾ ਹੈ + ਚੈਨਲ ਅਨ-ਸਬਸਕ੍ਰਾਈਬ + ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਨੂੰ ਬਦਲਣ ਵਿਚ ਅਸਮਰੱਥ + ਜਾਣਕਾਰੀ ਵੇਖੋ ਮੁੱਖ - + ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਅੱਪਡੇਟ ਕਰਨ ਵਿਚ ਅਸਮਰੱਥ + ਸਬਸਕ੍ਰਿਪਸ਼ਨ + ਬੁੱਕਮਾਰਕ ਪਲੇਲਿਸਟਾਂ + ਨਵਾਂ ਕੀ ਹੈ + ਬੈਕਗਰਾਊਂਡ + ਪੋਪ-ਅਪ + ਸ਼ਾਮਿਲ ਕਰੋ + ਵੀਡੀਓ ਦਾ ਡਾਊਨਲੋਡ ਮਾਰਗ + ਡਾਉਨਲੋਡ ਕੀਤੇ ਵੀਡੀਓ ਨੂੰ ਸਟੋਰ ਕਰਨ ਦਾ ਮਾਰਗ + ਵੀਡੀਓ ਲਈ ਡਾਊਨਲੋਡ ਮਾਰਗ ਭਰੋ + ਆਡੀਓ ਦਾ ਡਾਊਨਲੋਡ ਫੋਲਡਰ + ਡਾਊਨਲੋਡ ਕੀਤੇ ਆਡੀਓ ਇੱਥੇ ਸਟੋਰ ਹਨ + ਆਡੀਓ ਫਾਈਲਾਂ ਲਈ ਡਾਊਨਲੋਡ ਮਾਰਗ ਭਰੋ + ਆਟੋ ਪਲੇ + ਜਦੋਂ ਕਿਸੇ ਹੋਰ ਐਪ ਜਰੀਏ NewPipe ਨੂੰ ਖੋਲਿਆ ਜਾਂਦਾ ਹੈ ਤਾਂ ਇਹ ਵੀਡੀਓ ਚਲਾਉਂਦਾ ਹੈ + Default Resolution + Default ਪੌਪ-ਅਪ Resolution + ਉੱਚ ਰੇਸੋਲਿਯੁਸ਼ਨਾਂ ਵੀ ਦਿਖਾਓ + ਸਿਰਫ ਕੁੱਝ ਉਪਕਰਣ ਹੀ 2K/4K ਵੀਡੀਓ ਵਿਖਾਉਣ ਵਿਚ ਸਮਰਥਨ ਹੁੰਦੇ ਹਨ + Kodi ਨਾਲ ਚਲਾਓ + Kore ਐਪ ਮੌਜੂਦ ਨਹੀਂ ਹੈ। ਕੀ ਤੁਸੀਂ ਇਸਨੂੰ ਇੰਸਟਾਲ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ \? + \"Kodi ਨਾਲ ਚਲਾਓ\" ਵਿਕਲਪ ਦਿਖਾਓ + Kodi ਮੀਡੀਆ ਸੈਂਟਰ ਰਾਹੀਂ ਵੀਡੀਓ ਚਲਾਉਣ ਲਈ ਇੱਕ ਵਿਕਲਪ ਵਿਖਾਓ + ਆਡੀਓ + Default ਆਡੀਓ ਫਾਰਮੈਟ + "Default ਵੀਡੀਓ ਫਾਰਮੈਟ" + ਥੀਮ + ਸਫੈਦ + ਗੂੜਾ + ਕਾਲਾ + ਪੌਪ-ਅਪ ਦਾ ਆਕਾਰ ਅਤੇ ਸਥਿਤੀ ਯਾਦ ਰੱਖੋ + ਪੌਪ-ਅਪ ਦਾ ਆਖਰੀ ਅਕਾਰ ਅਤੇ ਸਥਿਤੀ ਯਾਦ ਰੱਖੋ + ਤੇਜ਼ ਪਰ inexact seek ਵਰਤੋ + Inexact seek ਵੀਡੀਓ ਨੂੰ ਤੇਜ਼ ਪਰ ਅਣ-ਸਟੀਕ ਢੰਗ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ ਲਿਜਾਂਦਾ ਹੈ + ਥੰਬਨੇਲ ਲੋਡ ਕਰੋ + ਥੰਬਨੇਲ ਲੋਡ, ਡਾਟਾ ਦੀ ਬਚਤ ਅਤੇ ਮੈਮੋਰੀ ਦੀ ਵਰਤੋਂ ਨੂੰ ਰੋਕਣ ਲਈ ਇਸਨੂੰ ਬੰਦ ਕਰੋ। ਇਸ ਵਿਚ ਤਬਦੀਲੀ ਕਰਨ ਨਾਲ ਇਨ-ਮੈਮੋਰੀ ਅਤੇ ਆਨ-ਡਿਸਕ ਚਿੱਤਰ cache ਦੋਵੇਂ ਮਿਟ ਜਾਣਗੇ। + ਚਿੱਤਰ cache ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ + Cached metadata ਮਿਟਾਓ + ਸਾਰੇ cached ਵੈੱਬ-ਪੇਜਾਂ ਦਾ ਡਾਟਾ ਮਿਟਾਓ + Metadata cache ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ + ਅਗਲੀ ਸਟ੍ਰੀਮ ਨੂੰ ਆਟੋ-ਕਤਾਰਬੱਧ ਕਰੋ + "ਇੱਕ ਨਾ-ਦੁਹਰਾਉਣ ਵਾਲੀ ਕਤਾਰ ਵਿੱਚ ਆਖਰੀ ਸਟ੍ਰੀਮ ਨੂੰ ਚਲਾਉਣ ਵੇਲੇ ਆਪਣੇ-ਆਪ ਸ਼ਾਮਿਲ ਕਰੋ" + ਵੀਡੀਓ ਪਲੇਯਰ gesture ਕੰਟਰੋਲ + ਸਕ੍ਰੀਨ ਲਾਈਟ ਅਤੇ ਆਵਾਜ਼ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ gestures ਦੀ ਵਰਤੋਂ ਕਰੋ + ਖੋਜ ਸੁਝਾਅ + ਖੋਜ ਕਰਨ ਵੇਲੇ ਸੁਝਾਅ ਦਿਖਾਓ + ਖੋਜ ਸੂਚੀ + ਖੋਜ ਸੂਚੀ ਨੂੰ locally ਸਟੋਰ ਕਰੋ + ਪਹਿਲਾਂ ਤੋਂ ਵੇਖੀਆਂ ਹੋਈਆਂ ਚੀਜ਼ਾਂ ਦੀ ਸੂਚੀ + ਦੇਖੇ ਗਏ ਵਿਡੀਓਜ਼ ਦੀ ਸੂਚੀ ਰੱਖੋ + Focus gain ਹੋਣ ਤੇ ਦੋਬਾਰਾ ਚਲਾਓ + ਰੁਕਾਵਟਾਂ (ਜਿਵੇਂ ਕਿ ਫੋਨ ਕਾਲਾਂ,ਮੈਸੇਜ) ਤੋਂ ਬਾਅਦ ਪਲੇਅ-ਬੈਕ ਜਾਰੀ ਰੱਖੋ + ਡਾਊਨਲੋਡ + ਅੱਗੇ + \'ਅੱਗੇ\' ਅਤੇ \'ਸਮਾਨਅੰਤਰ\' ਵੀਡੀਓ ਦਿਖਾਓ + \"Hold to append\" ਸੁਝਾਅ ਦਿਖਾਓ + ਵੀਡੀਓ ਵੇਰਵੇ ਪੰਨੇ ਤੇ ਬੈਕਗ੍ਰਾਉਂਡ ਜਾਂ ਪੌਪ-ਅਪ ਬਟਨ ਦਬਾਉਣ ਤੇ ਸੰਕੇਤ ਦਿਖਾਓ + ਅਣ-ਸਹਾਇਕ URL + ਮੂਲ ਦੇਸ਼ Content + ਸੇਵਾ + ਪਲੇਯਰ + ਵਿਵਹਾਰ + ਵੀਡੀਓ ਅਤੇ ਆਡੀਓ + ਹਿਸਟਰੀ ਅਤੇ cache + ਪੌਪ-ਅਪ + ਦਿੱਖ + ਹੋਰ + ਡੀ-ਬੱਗ + ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ + ਪੌਪ-ਅਪ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ + ਬੈਕਗ੍ਰਾਉਂਡ ਪਲੇਅਰ ਵਿੱਚ ਕਤਾਰਬੱਧ + ਪੌਪ-ਅਪ ਪਲੇਯਰ ਵਿੱਚ ਕਤਾਰਬੱਧ + ਪਲੇ + Content + ਉਮਰ ਪ੍ਰਤੀਬੰਧਿਤ Content + ਉਮਰ ਪ੍ਰਤੀਬੰਧਿਤ ਵੀਡੀਓ ਦਿਖਾਓ ਸੈਟਿੰਗਸ ਤੋਂ ਅਜਿਹੀ ਸਮੱਗਰੀ ਦੀ ਆਗਿਆ ਦੇਣੀ ਸੰਭਵ ਹੈ. + ਲਾਈਵ + ਡਾਊਨਲੋਡਸ + ਡਾਊਨਲੋਡਸ + Error ਰਿਪੋਰਟ + ਸਾਰੇ + ਚੈਨਲ + ਪਲੇ ਸੂਚੀ + ਹਾਂ + ਬਾਅਦ ਵਿੱਚ + ਬੰਦ ਕੀਤਾ + ਫਿਲਟਰ + ਤਾਜ਼ਾ ਕਰੋ + ਮਿਟਾਓ + ਮੁੜ ਆਕਾਰ + ਵਧੀਆ Resolution + ਵਾਪਿਸ + ਸਾਰੇ ਚਲਾਓ + ਹਮੇਸ਼ਾ + ਸਿਰਫ਼ ਇਸ ਬਾਰ + ਫਾਈਲ + NewPipe ਨੋਟੀਫਿਕੇਸ਼ਨ + NewPipe ਬੈਕਗ੍ਰਾਉਂਡ ਅਤੇ ਪੌਪ-ਅਪ ਪਲੇਅਰਾਂ ਲਈ ਸੂਚਨਾਵਾਂ + ਅਣਜਾਣ + Orientation ਬਦਲੋ + ਬੈਕਗਰਾਊਂਡ ਵਿੱਚ ਬਦਲੋ + ਪੌਪ-ਅਪ ਵਿੱਚ ਬਦਲੋ + ਮੁੱਖ ਵਿੱਚ ਬਦਲੋ + Database ਆਯਾਤ ਕਰੋ + Database ਨਿਰਯਾਤ ਕਰੋ + ਤੁਹਾਡੀ ਮੌਜੂਦਾ ਹਿਸਟਰੀ ਅਤੇ ਸਬਸਕ੍ਰਿਪਸ਼ਨਸ ਨੂੰ Override ਕਰਦਾ ਹੈ + ਹਿਸਟਰੀ, ਸੁਬਸਕ੍ਰਿਪਸ਼ਨਸ ਅਤੇ ਪਲੇ-ਸੂਚੀ ਨਿਰਯਾਤ ਕਰੋ + Watch ਹਿਸਟਰੀ ਮਿਟਾਓ + ਚਲਾਈਆਂ ਗਈਆਂ ਸਟ੍ਰੀਮਾਂ ਦੀ ਸੂਚੀ ਮਿਟਾਉਂਦਾ ਹੈ + ਕੀ ਸਾਰੀ watch ਹਿਸਟਰੀ ਮਿਟਾ ਦਿੱਤੀ ਜਾਵੇ \? + ਖੋਜ ਸੂਚੀ ਮਿਟਾਓ + ਖੋਜ ਸ਼ਬਦਾਂ ਦੀ ਸੂਚੀ ਮਿਟਾਉਂਦਾ ਹੈ + ਕੀ ਸਾਰੀ ਖੋਜ ਸੂਚੀ ਮਿਟਾ ਦਿਤੀ ਜਾਵੇ \? + ਖੋਜ ਸੂਚੀ ਮਿਟਾ ਦਿਤੀ ਗਈ ਹੈ. + ERROR + ਨੈੱਟਵਰਕ ERROR + ਸਾਰੇ ਥੰਬਨੇਲ ਲੋਡ ਨਹੀਂ ਹੋ ਸਕੇ + ਵੀਡੀਓ URL ਦਸਤਖਤ ਡੀਕ੍ਰਿਪਟ ਨਹੀਂ ਹੋ ਸਕਿਆ + ਵੈਬਸਾਈਟ parse ਨਹੀਂ ਹੋ ਸਕੀ + ਵੈਬਸਾਈਟ ਪੂਰੀ ਤਰਾਂ Parse ਨਹੀਂ ਹੋ ਸਕੀ + Content ਉਪਲਬਧ ਨਹੀਂ ਹੈ + ਡਾਊਨਲੋਡ ਮੀਨੂੰ ਸੈਟ-ਅਪ ਨਹੀਂ ਹੋ ਸਕਿਆ + ਲਾਈਵ ਸਟ੍ਰੀਮ ਅਜੇ supported ਨਹੀਂ ਹਨ + ਕੋਈ ਸਟ੍ਰੀਮ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋ ਸਕੀ + ਚਿੱਤਰ ਲੋਡ ਨਹੀਂ ਹੋ ਸਕਿਆ + ਐਪ/UI crashed + ਇਸ ਸਟ੍ਰੀਮ ਨੂੰ ਚਲਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ + ਅਣਚਾਹਾ ਪਲੇਅਰ ERROR ਆਇਆ ਹੈ + ਪਲੇਅਰ ERROR ਤੋਂ Recover ਹੋ ਰਿਹਾ ਹੈ + External ਪਲੇਅਰ ਇਸ ਕਿਸਮ ਦੇ ਲਿੰਕਾਂ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੇ + ਅਵੈਧ URL + ਕੋਈ ਵੀ ਵੀਡੀਓ ਸਟ੍ਰੀਮ ਨਹੀਂ ਮਿਲੀ + ਕੋਈ ਵੀ ਆਡੀਓ ਸਟ੍ਰੀਮ ਨਹੀਂ ਮਿਲੀ + ਅਜਿਹਾ ਕੋਈ ਫੋਲਡਰ ਨਹੀਂ + ਅਜਿਹਾ ਕੋਈ ਫਾਈਲ/Content ਸਰੋਤ ਨਹੀਂ ਹੈ + ਫਾਈਲ ਮੌਜੂਦ ਨਹੀਂ ਹੈ ਜਾਂ ਇਸ ਨੂੰ ਪੜ੍ਹਨ ਜਾਂ ਲਿਖਣ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ + ਫਾਈਲ ਨਾਮ ਖਾਲੀ ਨਹੀਂ ਹੋ ਸਕਦਾ + ਇੱਕ ERROR ਆਇਆ ਹੈ: %1$s + ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਕੋਈ ਸਟ੍ਰੀਮ ਉਪਲਬਧ ਨਹੀਂ ਹੈ + ਮੁਆਫ ਕਰਨਾ, ਅਜਿਹਾ ਨਹੀਂ ਹੋਣਾ ਚਾਹੀਦਾ ਸੀ. + ਈ-ਮੇਲ ਦੁਆਰਾ ERROR ਦੀ ਰਿਪੋਰਟ ਕਰੋ + ਮੁਆਫ ਕਰਨਾ, ਕੁਝ ERROR ਹੋਏ ਹਨ. + ਰਿਪੋਰਟ + ਜਾਣਕਾਰੀ: + ਕੀ ਹੋਇਆ ਹੈ: + ਕਿਸ ਬਾਰੇ:\\nRequest:\\nContent ਭਾਸ਼ਾ:\\nService:\\nGMT ਸਮਾਂ:\\nPackage:\\nVersion:\\nOS version: + ਤੁਹਾਡੀ ਟਿੱਪਣੀ (ਅੰਗਰੇਜ਼ੀ ਵਿਚ): + ਵੇਰਵੇ: + ਵੀਡੀਓ preview thumbnail + ਵੀਡੀਓ preview thumbnail + ਅਪਲੋਡਰ ਦਾ ਅਵਤਾਰ thumbnail + ਪਸੰਦ + ਨਾਪਸੰਦ + TOR ਦੀ ਵਰਤੋਂ ਕਰੋ + (ਪ੍ਰਯੋਗ ਅਧੀਨ) ਗੋਪਨੀਯਤਾ ਲਈ TOR ਦੁਆਰਾ ਟਰੈਫਿਕ ਨੂੰ ਜਬਰੀ Download ਹੋਣ ਲਈ ਮਜਬੂਰ ਕਰੋ (ਸਟ੍ਰੀਮਿੰਗ ਵੀਡੀਓ ਅਜੇ supported ਨਹੀਂ ਹਨ). + ERROR ਰਿਪੋਰਟ ਕਰੋ + ਯੂਸਰ ਰਿਪੋਰਟ + ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ + ਇਥੇ ਦਾ ਸੁੰਨਾਪਨ ਦੂਰ ਕਰਨ ਲਈ ਕੋਈ ਚੈਨਲ ਸਬਸਕ੍ਰਾਇਬ ਕਰੋ + ਕਤਾਰਬੱਧ ਕਰਨ ਲਈ ਖਿੱਚੋ + ਡਾਊਨਲੋਡ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ ਬਣਾਈ ਜਾ ਸਕਦੀ \'%1$s\' + ਡਾਊਨਲੋਡ ਡਾਇਰੈਕਟਰੀ ਬਣਾਈ ਗਈ \'%1$s\' + ਵੀਡੀਓ + ਆਡੀਓ + ਦੋਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ + ਸਟੋਰੇਜ਼ Access ਨੂੰ ਅਸਵੀਕਾਰ ਕੀਤਾ ਗਿਆ + ਹਜ਼ਾਰ + ਮਿਲੀਅਨ + ਬਿਲੀਅਨ + ਕੋਈ ਸਬਸਕ੍ਰਾਇਬਰ ਨਹੀਂ + + ਸਬਸਕ੍ਰਾਇਬਰ + ਸਬਸਕ੍ਰਾਇਬਰਸ + + ਕੋਈ views ਨਹੀਂ + + %s view + %s views + + ਕੋਈ ਵੀਡੀਓ ਨਹੀਂ + + ਵੀਡੀਓ + ਵੀਡੀਓਜ਼ + + ਸ਼ੁਰੂ ਕਰੋ + ਰੋਕੋ + ਪਲੇ + ਬਣਾਓ + ਮਿਟਾਓ + ਇੱਕ ਮਿਟਾਓ + ਸਾਰਾ ਮਿਟਾਓ + ਚੈੱਕ-ਸਮ + ਬਰਖਾਸਤ ਕਰੋ + ਨਾਮ ਬਦਲੋ + ਨਵਾਂ ਮਿਸ਼ਨ + ਠੀਕ ਹੈ + ਫਾਈਲ ਦਾ ਨਾਮ + threads + ERROR + Unsupported ਸਰਵਰ + ਫਾਈਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ + ਖਰਾਬ URL ਜਾਂ ਇੰਟਰਨੈਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ + NewPipe ਡਾਊਨਲੋਡ ਹੋ ਰਿਹਾ ਹੈ + ਵੇਰਵਿਆਂ ਲਈ ਖੋਲੋ + ਕ੍ਰਿਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ… + ਕਲਿਪ-ਬੋਰਡ ਵਿੱਚ ਕਾਪੀ ਹੋ ਗਿਆ ਹੈ + ਬਾਅਦ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਵਿਚੋਂ ਇੱਕ ਡਾਉਨਲੋਡ ਫੋਲਡਰ ਨੂੰ ਚੁਣੋ + ਪੌਪ-ਅਪ ਮੋਡ ਵਿੱਚ ਖੋਲ੍ਹਣ ਵਾਸਤੇ ਇਸ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ + 1 ਆਈਟਮ ਮਿਟਾਈ ਗਈ. + ReCaptcha + ReCaptcha ਚੁਣੌਤੀ + ReCaptcha ਚੁਣੌਤੀ ਲਈ ਬੇਨਤੀ + ਡਾਊਨਲੋਡ + ਫਾਈਲ ਨਾਮ ਵਿੱਚ ਪ੍ਰਵਾਨਿਤ ਅੱਖਰ + ਗਲਤ ਅੱਖਰ ਇਸ Value ਨਾਲ ਤਬਦੀਲ ਕੀਤੇ ਜਾਣਗੇ + Replacement ਅੱਖਰ + ਅੱਖਰ ਅਤੇ ਅੰਕ + ਬਹੁਤੇ ਖ਼ਾਸ ਅੱਖਰ + ਇਸ ਫਾਈਲ ਨੂੰ ਚਲਾਉਣ ਲਈ ਕੋਈ ਐਪ ਇੰਸਟਾਲ ਨਹੀਂ ਹੈ + NewPipe ਬਾਰੇ + ਸੈਟਿੰਗਾਂ + ਐਪ ਬਾਰੇ + ਥਰਡ-ਪਾਰਟੀ ਲਾਇਸੈਂਸ + © %1$s ਵਲੋਂ %2$s, %3$s ਅਧੀਨ + ਲਾਇਸੈਂਸ ਲੋਡ ਨਹੀਂ ਹੋ ਸਕਿਆ + ਵੈਬਸਾਈਟ ਖੋਲ੍ਹੋ + ਐਪ ਬਾਰੇ + ਯੋਗਦਾਨ ਪਾਉਣ ਵਾਲੇ + ਲਾਇਸੈਂਸ + ਐਂਡਰਾਇਡ ਤੇ ਮੁਫਤ ਲਾਈਟਵੇਟ ਸਟ੍ਰੀਮਿੰਗ. + ਯੋਗਦਾਨ ਪਾਓ + ਭਾਵੇਂ ਤੁਹਾਡੇ ਕੋਲ ਵਿਚਾਰ ਹਨ; ਅਨੁਵਾਦ, ਡਿਜ਼ਾਈਨ ਬਦਲਾਵ, ਕੋਡ ਦੀ ਸਫਾਈ, ਜਾਂ ਅਸਲ ਭਾਰੀ ਕੋਡ ਬਦਲਾਵ — ਹਰ ਮਦਦ ਦਾ ਸਦਾ ਸਵਾਗਤ ਹੈ. ਜਿੰਨਾ ਇਸ ਨੂੰ ਜ਼ਿਆਦਾ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਉੱਨਾ ਹੀ ਇਹ ਬਿਹਤਰ ਹੁੰਦਾ ਹੈ! + GitHub ਤੇ ਵੇਖੋ + ਦਾਨ ਕਰੋ + NewPipe ਵਲੰਟੀਅਰਾਂ ਦੁਆਰਾ ਵਿਕਸਤ ਕੀਤੀ ਗਈ ਹੈ ਜੋ ਤੁਹਾਡੇ ਲਈ ਬਿਹਤਰ ਅਨੁਭਵ ਲਿਆਉਣ ਲਈ ਸਮਾਂ ਬਿਤਾਉਂਦੇ ਹਨ. ਇੱਕ ਕੱਪ ਕਾਫੀ ਦਾ ਆਨੰਦ ਲੈਂਦੇ ਹੋਏ ਡਿਵੈਲਪਰਾਂ ਨੂੰ NewPipe ਨੂੰ ਹੋਰ ਵਧੀਆ ਬਣਾਉਣ ਵਿੱਚ ਸਹਾਇਤਾ ਲਈ ਵਾਪਸ ਦਿਓ. + ਵਾਪਸ ਦਿਓ + ਵੈਬਸਾਈਟ + ਵਧੇਰੇ ਜਾਣਕਾਰੀ ਅਤੇ ਖ਼ਬਰਾਂ ਲਈ NewPipe ਵੈਬਸਾਈਟ ਵੇਖੋ. + NewPipe\'s ਲਾਇਸੈਂਸ + NewPipe ਇੱਕ ਕਾੱਪੀਲਿਫਟ ਮੁਫ਼ਤ ਸਾੱਫਟਵੇਅਰ ਹੈ: ਤੁਸੀਂ ਇਸ ਦੀ ਵਰਤੋਂ, ਅਧਿਐਨ ਅਤੇ ਇਸ ਨੂੰ ਸਾਂਝਾ ਕਰ ਸਕਦੇ ਹੋ ਅਤੇ ਇਸ ਵਿੱਚ ਆਪਣੀ ਮਰਜ਼ੀ ਅਨੁਸਾਰ ਸੁਧਾਰ ਸਕਦੇ ਹੋ. ਖਾਸ ਤੌਰ \'ਤੇ ਤੁਸੀਂ ਇਸ ਨੂੰ GNU ਜਨਰਲ ਪਬਲਿਕ ਲਾਇਸੈਂਸ ਦੀਆਂ ਸ਼ਰਤਾਂ ਦੇ ਅਧੀਨ ਵੰਡ ਸਕਦੇ ਹੋ / ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰ ਸਕਦੇ ਹੋ ਜਿਵੇਂ ਕਿ ਮੁਫਤ ਸਾੱਫਟਵੇਅਰ ਫਾਊਂਡੇਸ਼ਨ ਦੁਆਰਾ ਪ੍ਰਕਾਸ਼ਤ ਕੀਤਾ ਗਿਆ ਹੈ, ਜਾਂ ਤਾਂ ਲਾਇਸੈਂਸ ਦਾ ਵਰਜ਼ਨ 3, ਜਾਂ (ਤੁਹਾਡੇ ਵਿਕਲਪ\' ਤੇ) ਬਾਅਦ ਦਾ ਕੋਈ ਸੰਸਕਰਣ. + ਲਾਇਸੈਂਸ ਪੜ੍ਹੋ + ਹਿਸਟਰੀ + ਖੋਜਿਆ ਗਿਆ + ਵੇਖਿਆ ਗਿਆ + ਹਿਸਟਰੀ ਬੰਦ ਕੀਤੀ ਹੋਈ ਹੈ + ਹਿਸਟਰੀ + ਹਿਸਟਰੀ ਖ਼ਾਲੀ ਹੈ + ਹਿਸਟਰੀ ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ + ਆਈਟਮ ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ + ਕੀ ਤੁਸੀਂ ਇਸ ਚੀਜ਼ ਨੂੰ ਖੋਜ ਸੂਚੀ ਵਿੱਚੋਂ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ\? + ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਵੇਖੀ ਗਈ ਸੂਚੀ ਵਿੱਚੋਂ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ \? + ਕੀ ਤੁਸੀਂ ਸੱਚਮੁੱਚ ਹਿਸਟਰੀ ਤੋਂ ਸਾਰੀਆਂ ਆਈਟਮਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ\? + ਆਖਰੀ ਚਲਾਈ ਗਈ + ਸਭ ਤੋਂ ਜਿਆਦਾ ਚਲਾਈ ਗਈ + ਮੁੱਖ ਪੰਨੇ ਦੀ ਸਮੱਗਰੀ + ਖਾਲੀ ਪੇਜ + Kiosk ਪੇਜ + ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਪੇਜ + ਫੀਡ ਪੇਜ + ਚੈਨਲ ਪੇਜ + ਚੈਨਲ ਚੁਣੋ + ਅਜੇ ਤੱਕ ਕੋਈ ਚੈਨਲ ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਨਹੀਂ + ਇੱਕ Kiosk ਚੁਣੋ + ਐਕਸਪੋਰਟ ਕੀਤਾ ਗਿਆ + ਇੰਪੋਰਟ ਕੀਤਾ ਗਿਆ + ਕੋਈ ਵੈਧ ZIP ਫਾਈਲ ਨਹੀਂ ਹੈ + ਚੇਤਾਵਨੀ: ਸਾਰੀਆਂ ਫਾਈਲਾਂ ਇੰਪੋਰਟ ਨਹੀਂ ਕੀਤੀਆਂ ਜਾ ਸਕੀਆਂ. + ਇਹ ਤੁਹਾਡੇ ਮੌਜੂਦਾ ਸੈਟ-ਅਪ ਨੂੰ Override ਕਰ ਦੇਵੇਗਾ. + kiosk + ਰੁਝਾਨ ਵਿੱਚ + ਟੌਪ 50 + ਨਵਾਂ ਅਤੇ ਗਰਮਾ-ਗਰਮ + ਬੈਕਗ੍ਰਾਉਂਡ ਪਲੇਅਰ + ਪੌਪ-ਅਪ ਪਲੇਅਰ + ਹਟਾਓ + ਵੇਰਵੇ + ਆਡੀਓ ਸੈਟਿੰਗਾਂ + ਕਤਾਰਬੱਧ ਕਰਨ ਵਾਸਤੇ ਦਬਾ ਕੇ ਰੱਖੋ + ਬੈਕਗ੍ਰਆਊਂਡ ਵਿੱਚ ਕਤਾਰਬੱਧ ਕਰੋ + ਨਵੇਂ ਪੌਪ-ਅਪ ਵਿੱਚ ਕਤਾਰਬੱਧ ਕਰੋ + ਇਥੇ ਚਲਾਉ + "ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚਲਾਉ" + ਨਵੇਂ ਪੌਪ-ਅਪ ਵਿੱਚ ਚਲਾਓ + Drawer ਖੋਲੋ + Drawer ਬੰਦ ਕਰੋ + ਜਲਦੀ ਹੀ ਇੱਥੇ ਕੁੱਝ ਦਿਖਾਈ ਦੇਵੇਗਾ ;D + ਤਰਜੀਹੀ \'OPEN\' ਐਕਸ਼ਨ + Content ਖੋਲ੍ਹਣ ਵੇਲੇ Default ਕਾਰਵਾਈ — %s + ਵੀਡੀਓ ਪਲੇਅਰ + ਬੈਕਗ੍ਰਾਊਂਡ ਪਲੇਅਰ + ਪੌਪ-ਅਪ ਪਲੇਅਰ + ਹਮੇਸ਼ਾ ਪੁੱਛੋ + ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰ ਰਹੇ ਹਾਂ… + ਬੇਨਤੀ ਕੀਤਾ Content ਲੋਡ ਕੀਤੀ ਜਾ ਰਿਹਾ ਹੈ + ਨਵੀਂ ਪਲੇ-ਲਿਸਟ + ਮਿਟਾਓ + ਨਾਮ ਬਦਲੋ + ਨਾਮ + ਪਲੇ-ਲਿਸਟ ਵਿੱਚ ਸ਼ਾਮਿਲ ਕਰੋ + ਪਲੇ-ਲਿਸਟ thumbnail ਦੇ ਤੌਰ ਤੇ ਸੈੱਟ ਕਰੋ + ਬੁੱਕਮਾਰਕ ਪਲੇ-ਲਿਸਟ + ਬੁੱਕਮਾਰਕ ਹਟਾਓ + ਇਸ ਪਲੇ-ਲਿਸਟ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ \? + ਪਲੇ-ਲਿਸਟ ਬਣਾਈ ਗਈ + ਪਲੇ-ਲਿਸਟ ਕੀਤਾ ਗਿਆ + ਪਲੇ-ਲਿਸਟ thumbnail ਬਦਲਿਆ ਗਿਆ. + ਪਲੇ-ਲਿਸਟ ਨੂੰ ਮਿਟਾ ਨਹੀਂ ਸਕੇ. + No captions + ਫਿੱਟ + ਭਰੋ + ਜ਼ੂਮ + Auto-Generated + captions + ਪਲੇਅਰ caption, text ਸਕੇਲ ਅਤੇ ਬੈਕਗ੍ਰਾਉਂਡ ਸਟਾਈਲ ਨੂੰ ਸੋਧੋ. ਪ੍ਰਭਾਵ ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਐਪ ਨੂੰ ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਜ਼ਰੂਰਤ ਹੈ. + LeakCanary ਚਲਾਓ + ਮੈਮੋਰੀ ਲੀਕ monitoring, ਐਪ ਨੂੰ Unresponsive ਬਣਾ ਸਕਦੀ ਹੈ ਜਦੋਂ ਹੀਪ dumping ਹੁੰਦੀ ਹੈ + Out-of-lifecycle ERROR ਰਿਪੋਰਟ ਕਰੋ + ਨਿਪਟਾਰੇ ਦੇ ਬਾਅਦ ਟੁਕੜੇ ਜਾਂ ਗਤੀਵਿਧੀਆਂ ਦੇ lifecycle ਤੋਂ ਬਾਹਰ undeliverable Rx ਅਪਵਾਦਾਂ ਬਾਰੇ ਜ਼ਬਰੀ ਰਿਪੋਰਟ ਕਰਨਾ + ਇੰਪੋਰਟ/ਐਕਸਪੋਰਟ + ਇੰਪੋਰਟ + ਇੰਪੋਰਟ ਕਰੋ + ਐਕਸਪੋਰਟ ਕਰੋ + ਇੰਪੋਰਟ ਹੋ ਰਿਹਾ ਹੈ… + ਐਕਸਪੋਰਟ ਹੋ ਰਿਹਾ ਹੈ… + ਇੰਪੋਰਟ ਫਾਈਲ + ਪਿੱਛਲਾ ਐਕਸਪੋਰਟ + ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਨਹੀਂ ਹੋ ਸਕੀਆਂ + ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਐਕਸਪੋਰਟ ਨਹੀਂ ਹੋ ਸਕੀਆਂ + ਯੂ ਟਿਊਬ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਐਕਸਪੋਰਟ ਫਾਈਲ ਡਾਊਨਲੋਡ ਕਰੋ: +\n +\n1. ਇਸ URL ਤੇ ਜਾਓ: %1$s +\n2. ਆਪਣੇ ਖਾਤੇ ਚ ਲੌਗ-ਇਨ ਕਰੋ +\n3. ਇੱਕ ਡਾਉਨਲੋਡ ਸ਼ੁਰੂ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ (ਇਹੀ ਐਕਸਪੋਰਟ ਫਾਈਲ ਹੈ) + URL ਜਾਂ ਆਪਣੀ ID ਟਾਈਪ ਕਰਕੇ ਸਾਉੰਡ ਕਲਾਉਡ ਪ੍ਰੋਫਾਈਲ ਇੰਪੋਰਟ ਕਰੋ: +\n +\n1. ਇੱਕ ਵੈਬ-ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ \"ਡੈਸਕਟਾਪ ਮੋਡ\" ਨੂੰ ਚਾਲੂ ਕਰੋ (ਸਾਈਟ ਮੋਬਾਈਲ ਉਪਕਰਣਾਂ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ) +\n2. ਇਸ URL ਤੇ ਜਾਓ: %1$s +\n3. ਆਪਣੇ ਖਾਤੇ ਚ ਲੌਗ-ਇਨ ਕਰੋ +\n4. ਨਿਰਦੇਸ਼ਤ ਕੀਤੇ ਗਏ ਪ੍ਰੋਫਾਈਲ URL ਨੂੰ ਕਾਪੀ ਕਰੋ. + yourID, Soundcloud.com/yourid + ਯਾਦ ਰੱਖੋ ਕਿ ਇਹ ਕਾਰਜ ਡਾਟਾ consuming ਹੋ ਸਕਦਾ ਹੈ. +\n +\nਕੀ ਤੁਸੀਂ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ\? + ਪਲੇਅਬੈਕ ਸਪੀਡ ਕੰਟਰੋਲ + tempo + pitch + ਅਨਲਿੰਕ (distortion ਪੈਦਾ ਹੋ ਸਕਦੀ ਹੈ) + ਕੀ ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵੀ ਇੰਪੋਰਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ\? + NewPipe\'s ਗੋਪਨੀਯਤਾ ਨੀਤੀ + NewPipe ਪ੍ਰੋਜੈਕਟ ਤੁਹਾਡੀ ਗੋਪਨੀਯਤਾ ਨੂੰ ਬਹੁਤ ਗੰਭੀਰਤਾ ਨਾਲ ਲੈਂਦਾ ਹੈ. ਇਸ ਲਈ ਐਪ ਤੁਹਾਡੀ ਸਹਿਮਤੀ ਤੋਂ ਬਿਨਾਂ ਕੋਈ ਵੀ ਡਾਟਾ ਇੱਕਠਾ ਨਹੀਂ ਕਰਦਾ. +\nNewPipe ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਵਿਸਥਾਰ ਵਿੱਚ ਦੱਸਦੀ ਹੈ ਕਿ ਜਦੋਂ ਤੁਸੀਂ ਕਰੈਸ਼ ਰਿਪੋਰਟ ਭੇਜਦੇ ਹੋ ਤਾਂ ਕਿਹੜਾ ਡੇਟਾ ਭੇਜਿਆ ਜਾਂ ਸਟੋਰ ਕੀਤਾ ਜਾਂਦਾ ਹੈ. + ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਪੜ੍ਹੋ + ਯੂਰਪੀਅਨ ਜਨਰਲ ਡੇਟਾ ਪ੍ਰੋਟੈਕਸ਼ਨ ਰੈਗੂਲੇਸ਼ਨ (ਜੀਡੀਪੀਆਰ) ਦੀ ਪਾਲਣਾ ਕਰਨ ਲਈ, ਅਸੀਂ ਤੁਹਾਡਾ ਧਿਆਨ NewPipe ਦੀ ਗੋਪਨੀਯਤਾ ਨੀਤੀ ਵੱਲ ਖਿੱਚਦੇ ਹਾਂ. ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਧਿਆਨ ਨਾਲ ਪੜ੍ਹੋ. +\nਸਾਨੂੰ BUG ਰਿਪੋਰਟ ਭੇਜਣ ਲਈ ਤੁਹਾਨੂੰ ਇਸ ਨੂੰ ਸਵੀਕਾਰ ਕਰਨਾ ਪਵੇਗਾ. + ਸਵੀਕਾਰ ਕਰੋ + ਅਸਵੀਕਾਰ + ਕੋਈ ਸੀਮਾ ਨਹੀਂ + ਮੋਬਾਈਲ ਡਾਟਾ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਸਮੇਂ Resolution ਨੂੰ ਸੀਮਿਤ ਕਰੋ + ਐਪ switch ਕਰਨ ਤੇ minimize ਕਰੋ + ਮੁੱਖ ਵੀਡੀਓ ਪਲੇਅਰ ਤੋਂ ਦੂਜੇ ਐਪ \'ਤੇ ਜਾਣ ਵੇਲੇ ਐਕਸ਼ਨ + ਕੋਈ ਨਹੀਂ + ਬੈਕਗ੍ਰਾਉਂਡ ਪਲੇਅਰ ਵਿੱਚ Minimize ਕਰੋ + ਪੌਪ-ਅਪ ਪਲੇਅਰ ਵਿੱਚ minimize ਕਰੋ + ਚੁੱਪ ਦੌਰਾਨ ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ ਕਰੋ + ਸਟੇਪ + ਰੀਸੈੱਟ + ਚੈਨਲਾਂ + ਪਲੇ ਸੂਚੀਆਂ + ਟਰੈਕਸ + ਯੂਜ਼ਰਸ + ਅਨ-ਸਬਸਕ੍ਰਾਈਬ + ਨਵਾਂ ਟੈਬ + ਟੈਬ ਚੁਣੋ + ਆਵਾਜ਼ gesture ਕੰਟਰੋਲ + ਆਵਾਜ਼ ਕੰਟਰੋਲ ਕਰਨ ਲਈ gestures ਦੀ ਵਰਤੋਂ ਕਰੋ + ਸਕ੍ਰੀਨ ਲਾਈਟ gesture ਕੰਟਰੋਲ + ਵੀਡੀਓ ਸਕ੍ਰੀਨ ਲਾਈਟ ਕੰਟਰੋਲ ਕਰਨ ਲਈ gestures ਦੀ ਵਰਤੋਂ ਕਰੋ + ਮੂਲ ਭਾਸ਼ਾ Content + ਅਪਡੇਟਾਂ + ਫਾਈਲ ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ + ਐਪ ਅੱਪਡੇਟ ਨੋਟੀਫਿਕੇਸ਼ਨ + ਨਵੇਂ NewPipe ਸੰਸਕਰਣ ਲਈ ਸੂਚਨਾਵਾਂ + ਬਾਹਰੀ ਸਟੋਰੇਜ ਉਪਲਬਧ ਨਹੀਂ ਹੈ + ਬਾਹਰੀ SD ਕਾਰਡ ਤੇ ਡਾਊਨਲੋਡ ਕਰਨਾ ਸੰਭਵ ਨਹੀਂ ਹੈ. ਕੀ ਡਾਊਨਲੋਡ ਫੋਲਡਰ ਦੀ ਸਥਿਤੀ ਨੂੰ ਰੀਸੈਟ ਕੀਤਾ ਜਾਵੇ \? + Default ਟੈਬ ਦੀ ਵਰਤੋਂ ਕਰਦਿਆਂ, save ਕੀਤੇ ਟੈਬਾਂ ਨੂੰ ਪੜ੍ਹਨ ਵੇਲੇ ERROR + Default ਮੁੜ-ਪ੍ਰਾਪਤ ਕਰੋ + ਕੀ ਤੁਸੀਂ Default ਲਾਗੂ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ \? + ਸਬਸਕ੍ਰਾਇਬਰਾਂ ਦੀ ਗਿਣਤੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ + ਮੁੱਖ ਪੰਨੇ ਤੇ ਕਿਹੜੇ ਟੈਬ ਦਿਖਾਏ ਜਾਣਗੇ + ਚੋਣ + ਅਪਡੇਟਾਂ + ਜਦੋਂ ਨਵਾਂ ਸੰਸਕਰਣ ਉਪਲਬਧ ਹੁੰਦਾ ਹੈ ਤਾਂ ਐਪ ਅਪਡੇਟ ਨੂੰ ਪੁੱਛਣ ਲਈ ਇੱਕ ਨੋਟੀਫਿਕੇਸ਼ਨ ਦਿਖਾਓ + ਲਿਸਟ view ਮੋਡ + ਲਿਸਟ + ਗਰਿੱਡ + ਆਟੋ + ਸਵਿੱਚ view + NewPipe ਅੱਪਡੇਟ ਉਪਲਬੱਧ! + ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਦਬਾਓ + ਮੁਕੰਮਲ ਹੋਇਆ + ਬਕਾਇਆ + ਰੁਕਿਆ + ਕਤਾਰਬੱਧ + Post-processing + ਕਤਾਰ + ਸਿਸਟਮ ਦੁਆਰਾ ਕਾਰਵਾਈ ਤੋਂ ਇਨਕਾਰ ਕੀਤਾ ਗਿਆ + ਡਾਊਨਲੋਡ ਫੇਲ੍ਹ + ਡਾਊਨਲੋਡ ਮੁਕੰਮਲ + %s ਡਾਊਨਲੋਡ ਮੁਕੰਮਲ + ਵਿਲੱਖਣ ਨਾਮ Generate ਕਰੋ + overwrite + ਇਸ ਨਾਮ ਦੇ ਨਾਲ ਇੱਕ ਡਾਊਨਲੋਡ ਪਹਿਲਾਂ ਤੋਂ ਜਾਰੀ ਹੈ + ERROR ਵਿਖਾਓ + ਕੋਡ + Destination ਫੋਲਡਰ ਬਣਾਇਆ ਨਹੀਂ ਜਾ ਸਕਦਾ + ਫਾਈਲ ਨਹੀਂ ਬਣਾਈ ਜਾ ਸਕਦੀ + ਸਿਸਟਮ ਦੁਆਰਾ permission Deny ਕੀਤੀ ਗਈ + ਸੁਰੱਖਿਅਤ ਕੁਨੈਕਸ਼ਨ ਫੇਲ੍ਹ + ਸਰਵਰ ਨਹੀਂ ਲੱਭ ਸਕਿਆ + ਸਰਵਰ ਨਾਲ ਜੁੜ ਨਹੀਂ ਸਕਦਾ + ਸਰਵਰ ਨੇ ਡਾਟਾ ਨਹੀਂ ਭੇਜਿਆ + ਸਰਵਰ ਮਲਟੀ-Threaded ਡਾਊਨਲੋਡਸ ਨੂੰ ਸਵੀਕਾਰ ਨਹੀਂ ਕਰਦਾ, ਇਸ ਨਾਲ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ @string/msg_threads = 1 + ਬੇਨਤੀ ਕੀਤੀ ਸੀਮਾ ਤਸੱਲੀਬਖਸ਼ ਨਹੀਂ ਹੈ + ਨਹੀਂ ਲਭਿਆ + Post-processing ਫੇਲ੍ਹ + ਮੁਕੰਮਲ ਹੋਈਆਂ ਡਾਊਨਲੋਡ ਸਾਫ਼ ਕਰੋ + ਡਾਉਨਲੋਡਸ ਤੋਂ ਆਪਣੀਆਂ %s ਬਕਾਇਆ ਟ੍ਰਾਂਸਫਰ ਜਾਰੀ ਰੱਖੋ + ਰੁੱਕੋ + ਵੱਧ ਤੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ + ਡਾਉਨਲੋਡ ਰੱਦ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਵੱਧ ਤੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ + Metered ਨੈਟਵਰਕਸ ਤੇ ਰੁਕਾਵਟ + ਮੋਬਾਈਲ ਡਾਟਾ ਤੇ switch ਕਰਨ ਵੇਲੇ ਲਾਭਦਾਇਕ ਹੈ, ਹਾਲਾਂਕਿ ਕੁਝ ਡਾਉਨਲੋਡਾਂ ਨੂੰ suspend ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ + ਇਵੇੰਟਸ + ਕਾਨਫਰੰਸਾਂ + ਟਿੱਪਣੀਆਂ ਦਿਖਾਓ + ਟਿੱਪਣੀਆਂ ਵਿਖਾਉਣਾ ਬੰਦ ਕਰਨ ਲਈ ਇਸਨੂੰ ਬੰਦ ਕਰੋ + ਆਟੋ-ਪਲੇ + + ਟਿਪਣੀਆਂ + + + ਕੋਈ ਟਿੱਪਣੀ ਨਹੀਂ ਕੀਤੀ ਗਈ + ਟਿੱਪਣੀਆਂ ਲੋਡ ਨਹੀਂ ਹੋ ਸਕੀਆਂ + ਬੰਦ ਕਰੋ + ਪਲੇਅਬੈਕ ਦੋਬਾਰਾ ਸ਼ੁਰੂ ਕਰੋ + ਪਿਛਲੀ ਪਲੇਅਬੈਕ ਸਥਿਤੀ ਤੋਂ ਮੁੜ ਚਲਾਓ + ਸੂਚੀਆਂ ਦੀ ਸਥਿਤੀ + ਸੂਚੀਆਂ ਵਿੱਚ ਪਲੇਅਬੈਕ ਸਥਿਤੀ ਸੂਚਕ ਦਿਖਾਓ + ਡਾਟਾ ਮਿਟਾਓ + Watch ਹਿਸਟਰੀ ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈ. + ਪਲੇਬੈਕ ਸਥਿਤੀ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ. + ਫਾਈਲ ਮੂਵ ਕੀਤੀ ਜਾਂ ਮਿਟਾਈ ਗਈ ਹੈ + ਇਸ ਨਾਮ ਵਾਲੀ ਇੱਕ ਫਾਈਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ + ਇਸ ਨਾਮ ਨਾਲ ਡਾਉਨਲੋਡ ਕੀਤੀ ਫਾਈਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ + ਫਾਈਲ Overwrite ਨਹੀਂ ਹੋ ਸਕਦੀ + ਇਸ ਨਾਮ ਦੇ ਨਾਲ ਇੱਥੇ ਇੱਕ ਬਕਾਇਆ ਡਾਊਨਲੋਡ ਹੈ + ਫਾਈਲ ਤੇ ਕੰਮ ਕਰਦੇ ਸਮੇਂ NewPipe ਬੰਦ ਕੀਤੀ ਗਈ ਸੀ + ਡਿਵਾਈਸ ਤੇ ਕੋਈ ਜਗ੍ਹਾ ਨਹੀਂ ਬਚੀ ਹੈ + Progress lost, ਕਿਉਂਕਿ ਫਾਈਲ ਮਿਟ ਗਈ ਸੀ + ਕੁਨੈਕਸ਼ਨ timeout + are you sure\? + ਡਾਊਨਲੋਡ ਸੀਮਾ ਕਤਾਰ ਵਿੱਚ + one download will run at the same time + ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਕਰੋ + ਡਾਊਨਲੋਡਸ ਰੋਕੋ + ਪੁੱਛੋ ਕਿੱਥੇ ਡਾਊਨਲੋਡ ਕਰਨਾ ਹੈ + ਤੁਹਾਨੂੰ ਪੁੱਛਿਆ ਜਾਵੇਗਾ ਕਿ ਹਰ ਡਾਉਨਲੋਡ ਨੂੰ ਕਿੱਥੇ save ਕਰਨਾ ਹੈ + ਤੁਹਾਨੂੰ ਪੁੱਛਿਆ ਜਾਵੇਗਾ ਕਿ ਹਰ ਡਾਉਨਲੋਡ ਨੂੰ ਕਿੱਥੇ save ਕਰਨਾ ਹੈ. +\nਜੇ ਤੁਸੀਂ ਬਾਹਰੀ SD ਕਾਰਡ ਤੇ ਡਾਊਨਲੋਡ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ ਤਾਂ ਇਸ ਨੂੰ ਚਾਲੂ ਕਰੋ. + \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 2830ce17f..11ecf9d96 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -479,6 +479,5 @@ Brak komentarzy Nie można załadować komentarzy - Odtwarzaj bezpośrednio w tle Zamknij \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index a7f287957..5ae8392a1 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -96,7 +96,7 @@ Arquivo já existe Threads URL inválida ou internet indisponível - Selecione uma pasta para download + Selecione uma pasta para download posteriormente nas configurações Nenhum player de stream encontrado. Deseja instalar o VLC? Não foi possível interpretar o site Áudio @@ -177,7 +177,7 @@ abrir em modo popup Continuar reproduzindo depois de interrupções (exemplo: ligações) Histórico de pesquisas Armazenar histórico de pesquisa localmente - Histórico & Cache + Histórico de visualização Armazenar histórico de vídeos assistidos Histórico Pesquisado @@ -416,7 +416,7 @@ abrir em modo popup Notificação de Atualização do Aplicativo Notificações para a versão do NewPipe Armazenamento externo indisponível - Baixar para o cartão SD externo ainda não é possivel. Resetar o local da pasta de download\? + Não é possivel baixar para o cartão SD externo . Resetar o local da pasta de download\? Usando abas padrão, erro ao ler abas salvas Restaurar padrões Deseja restaurar os padrões\? @@ -465,7 +465,7 @@ abrir em modo popup Tentativas máximas Número máximo de tentativas antes de cancelar o download Pausar quando trocar para dados móveis - Downloads que não puderem ser pausados serão reiniciados + Útil quando trocar para dados móveis, porém alguns downloads não podem ser suspensos Pendente Exibir comentários Desabilitar para parar de exibir comentários @@ -476,6 +476,28 @@ abrir em modo popup Não há comentários Não foi possível carregar comentários - Reproduzir diretamente em segundo plano Fechar + Retomar a reprodução + Restaurar para a última posição da reprodução + Posições em listas + Mostrar indicadoers de posição da reprodução nas listas + Limpar dados + Posições da reprodução apagadas. + Arquivo movido ou apagado + Já existe um arquivo com este nome + não é possível sobrescrever o arquivo + Existe um download pendente com este nome + NewPipe foi fechado enquanto manipulava o arquivo + Não há espaço disponível no dispositivo + Progresso perdido devido ao arquivo ter sido apagado + Tempo limite de conexão + Tem certeza\? + Limitar tamanho da fila de download + Um download será executado ao mesmo tempo + Iniciar downloads + Pausar downloads + Perguntar onde salvar o arquivo do download + Você será questionado onde salvar o arquivo a cada download + Você será questionado onde salvar o arquivo a cada download +\nAtive esta opção caso queira fazer o download para um cartão de memória SD externo. \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 73cbc5430..c0da2af66 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -27,7 +27,7 @@ Áudio Formato áudio padrão Descarregar - A seguir + Seguinte Mostrar vídeos \'Seguintes\' e \'Semelhantes\' URL não suportado Idioma padrão do conteúdo @@ -57,7 +57,6 @@ Incapaz de descodificar a assinatura do vídeo Incapaz de processar o site Conteúdo não disponível - Conteúdo Restringir conteúdo por idade Mostrar vídeo com restrição de idade. É possível permitir tal material nas Configurações. @@ -100,7 +99,7 @@ Toque para detalhes Por favor aguarde… Copiado para a área de transferência - Por favor selecione a pasta para as descargas + Por favor selecione nas configurações a pasta para as descargas OK Processos Descarga do NewPipe @@ -169,7 +168,7 @@ Novidades Histórico de pesquisa Guardar termos de pesquisa localmente - Histórico e cache + Ver história Guardar histórico de vídeos assistidos Retomar ao ganhar foco Continuar reprodução após interrupções (ex. chamadas) @@ -194,8 +193,8 @@ Sem vídeos - vídeo - vídeos + Vídeo + Vídeos Descarregar Caracteres permitidos em nomes de ficheiros @@ -398,7 +397,7 @@ Ilimitado Limitar resolução se estiver a usar dados móveis Minimizar ao trocar de aplicação - Ação a executar ao trocar para outra aplicação a partir do menu principal - % s + Ação a executar ao trocar para outra aplicação a partir do menu principal - %s Nenhuma Ativar o reprodutor em segundo plano Ativar o reprodutor \'popup\' @@ -414,7 +413,7 @@ Notificação de atualização Notificações para uma nova versão do NewPipe Armazenamento externo indisponível - Ainda não é possível descarrgar ao cartão SD. Repor localização da pasta de descargas\? + Não é possível descarregar ao cartão SD. Repor a localização da pasta de descargas\? Erro ao ler os separadores guardados e serão usados os separadores padrão Restaurar predefinições Deseja restaurar as predefinições\? @@ -461,8 +460,8 @@ Parar Tentativas máximas Número máximo de tentativas antes de cancelar a descarga - Pausa na comutação para dados móveis - Descarregamentos que não podem ser pausados serão reiniciados + Interromper em redes limitadas + Útil ao mudar para dados móveis, embora alguns descarregamentos não possam ser suspensos Eventos Conferências Pendente @@ -471,10 +470,32 @@ Reprodução automática Comentários - + Sem comentários Não foi possível carregar comentários - Reproduzir diretamente no fundo Fechar + Continuar a reprodução + Restaurar a última posição de reprodução + Posições nas listas + Mostrar indicadores de posição de reprodução em listas + Limpar dados + Posições de reprodução apagadas. + Ficheiro movido ou apagado + Um ficheiro com este nome já existe + não é possível sobrescrever o ficheiro + Há um descarregamento pendente com este nome + NewPipe foi fechado enquanto trabalhava no ficheiro + Não há espaço disponível no aparelho + Progresso perdido, porque o fiheiro foi apagado + Tempo limite de conexão + Tem certeza\? + Limitar a fila de descarregamentos + Descarregar um só ao mesmo tempo + Iniciar descarregamentos + Pausa descarregamentos + Perguntar para onde descarregar + Você será perguntado para onde gravar cada descarregamento + Você será perguntado para onde gravar cada descarregamento. +\nAtive-o se pretender descarregar para um cartão SD externo. \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index e087809b5..fb2abaec1 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -15,7 +15,7 @@ Выбор браузера поворот Путь для скачанного видео - Путь для сохранения скачанного видео + Папка для хранения загруженных видео Введите путь к папке для скачивания видео Разрешение по умолчанию Воспроизвести в Kodi @@ -27,7 +27,7 @@ Скачать Следующее URL не поддерживается - Показывать \"Следующее\" и \"Похожие\" видео + \"Следующее\" и \"Похожие\" видео Язык контента по умолчанию Видео и аудио Внешний вид @@ -239,8 +239,8 @@ Удалить Вы подписаны Подписка отменена - Показывать \"Зажмите, чтобы добавить\" - Показывать подсказку при нажатии кнопок всплывающего окна или фонового воспроизведения на странице сведений о видео + \"Зажмите, чтобы добавить\" + Показать подсказку при нажатии \"В окне\" или \"В фоне\" на странице сведений о видео [Неизвестно] Восстановление после ошибки плеера В фоне @@ -331,7 +331,6 @@ Заполнить Приблизить Созданы автоматически - Синхронизировать Включить LeakCanary Мониторинг утечки памяти может привести к зависанию приложения Сообщать об ошибках жизненного цикла @@ -487,5 +486,4 @@ Нет комментариев Не удалось загрузить комментарии - Играть сейчас в фоне \ No newline at end of file diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 67b0628f0..1760e8ade 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -314,10 +314,6 @@ Prispôsobiť Vyplniť Zväčšiť - Veľkosť písma titulkov - Menšie Písmo - Normálne Písmo - Väčšie Písmo Používať rýchly posun Rýchly posun umožňuje prejsť na novú pozíciu rýchlejšie, ale s menšou presnosťou Načítanie miniatúr @@ -380,7 +376,6 @@ Rýchlosť Výška "Spomalenie (môže spôsobovať skreslenie)" - Nightcore režim Predvolené Vymazať históriu pozretí Odstráni históriu prehrávaných streamov diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 0fef06279..d5f031ad8 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -47,9 +47,9 @@ Светла Изглед Грешка мреже - Одредиште преузимања за аудио + Фолдер преузимања за аудио Унесите путању за преузимање аудио фајлова - Путања за упис преузетих аудио фајлова + Овде се чувају преузети аудио-снимци Направљен директоријум за преузимање „%1$s“ Не могу да направим директоријум за преузимање„ %1$s“ Грешка @@ -133,7 +133,7 @@ Очисти Позадина Прозорче - Неке резолуције биће БЕЗ звука када је ова опција укључена + Уклања звук на неким резолуцијама Упамти величину и позицију искачућег прозора Памти последњу величину и позицију искачућег прозорчета Контроле прејера потезом @@ -243,7 +243,7 @@ Нема плејера тока (можете инсталирати ВЛЦ). Преузимање фајла тока Прикажи податке - Обележивачи + Сачуване плејлисте Додај у Подразумевана држава за садржај Услуга @@ -259,4 +259,16 @@ Да бисте добили више информација и најновије вести о ЊуПајпу посетите наш вебсајт. Задржи за стављање у ред Пусти одавде + Користи брзо, али непрецизно премотавање + Омогућава плејеру да брже долази до позиције уз смањену прецизност + Учитавање слика + Искључите како се не би преузимале слике, чиме ћете смањити количину пренетог саобраћаја и потрошњу меморије. Промена ове опције ће уклонити слике из радне и трајне меморије. + Очишћен кеш са сликама + Уклони кеширане метаподатке + Уклони све податке о кешираним веб-странама + Откажи претплату + Нова картица + Одабери картицу + Приказивање коментара + Искључите како се не би приказивали коментари \ No newline at end of file diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 9f777391b..6f71a8b97 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -121,7 +121,6 @@ தேடப்பட்ட வாக்கியத்தை அமைவிடத்தில் சேமிக்கவும் ஆதரிக்கப்படாத URL இயல்புநிலை தகவல்களின் நாடு - தகவல்களின் இயல்பு மொழி பிழைதிருத்து உள்ளடக்கம் வயது வரம்புக்கு உட்பட்டது diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml new file mode 100644 index 000000000..494125237 --- /dev/null +++ b/app/src/main/res/values-th/strings.xml @@ -0,0 +1,447 @@ + + + แตะที่ปุ่มค้นหาเพื่อเริ่มต้น + %1$s วิว + เผยแพร่เมื่อ %1$s + ไม่พบแอปที่สามารถสตรีมสื่อวีดีโอได้ คุณต้องการติดตั้ง VLC หรือไม่\? + ไม่พบแอปที่สามารถสตรีมสื่อวีดีโอได้ (คุณสามารถติดตั้ง VLC เพื่อดูวีดีโอ) + ติดตั้ง + ยกเลิก + เปิดด้วยเว็บบราวเซอร์ + เปิดในโหมดป๊อปอัพ + แชร์ + ดาวน์โหลด + ดาวน์โหลดไฟล์สตรีม + ค้นหา + ตั้งค่า + หรือคุณหมายถึง: %1$s\? + แชร์ด้วย + เลือกบราวเซอร์ + หมุน + ใช้แอปเล่นวีดีโอภายนอก + ใช้แอปเล่นเสียงภายนอก + NewPipe โหมดป๊อปอัพ + บอกรับ + บอกรับแล้ว + ยกเลิกการบอกรับ + ยกเลิกการบอกรับช่องแล้ว + ไม่สามารถเปลี่ยนสถานะการบอกรับได้ + ไม่สามารถอัปเดตการบอกรับข้อมูล + แสดงข้อมูล + หน้าหลัก + การสมัครรับข้อมูล + เพลย์ลิสต์ที่เก็บไว้ + แท็บใหม่ + เลือกแท็บ + มีอะไรใหม่ + พื้นหลัง + ป๊อปอัพ + เพิ่มไปยัง + เส้นทางการดาวน์โหลดวิดีโอ + เส้นทางในการจัดเก็บวิดีโอที่ดาวน์โหลดมา + ป้อนเส้นทางการดาวน์โหลดสำหรับวิดีโอ + โฟลเดอร์ที่ดาวน์โหลดเสียง + เสียงที่ดาวน์โหลดจะถูกเก็บไว้ที่นี่ + ป้อนเส้นทางการดาวน์โหลดสำหรับไฟล์เสียง + เล่นอัตโนมัติ + เล่นวิดีโอเมื่อ NewPipe ถูกเรียกจากแอปอื่น + ความละเอียดเริ่มต้น + ความละเอียดเริ่มต้นในโหมดป๊อปอัพ + แสดงความละเอียดที่สูงขึ้น + เฉพาะบางอุปกรณ์ที่รองรับการเล่นวิดีโอ 2K/4K + เปิดด้วย Kodi + ไม่พบแอป Kore จะติดตั้งหรือไม่\? + แสดงตัวเลือก \"เปิดด้วย Kodi\" + แสดงตัวเลือกในการเล่นวิดีโอผ่าน Kodi media center + เสียง + ฟอร์แมตเสียงเริ่มต้น + ฟอร์แมตวีดีโอเริ่มต้น + ธีม + สว่าง + มืด + สีดำ + จำขนาดและตำแหน่งของป๊อปอัพ + จำขนาดและตำแหน่งสุดท้ายของป๊อปอัพ + ใช้การข้ามที่ไม่แม่นยำ + การข้ามช่วงที่ไม่แม่นยำจะทำให้เลื่อนไปยังตำแหน่งเวลาที่ต้องการได้เร็วขึ้น แต่จะลดความแม่นยำในการลากตำแหน่งลง + โหลดภาพขนาดย่อ + แสดงความคิดเห็น + ปิดใช้งานเพื่อซ่อนความคิดเห็น + ปิดเพื่อป้องกันการโหลดรูปขนาดย่อ ลดการใช้ข้อมูลและหน่วยความจำ การเปลี่ยนแปลงล้างแคชภาพในหน่วยความจำและบนดิสก์ + ล้างแคชของรูปภาพแล้ว + ลบข้อมูลเว็บเพจที่แคชไว้ทั้งหมด + คิววีดีโอถัดไปโดยอัตโนมัติ + ต่อท้ายวีดีโอที่เกี่ยวข้องโดยอัตโนมัติเมื่อเล่นถึงรายการสุดท้ายในกรณีที่ไม่ได้ตั้งให้เล่นซ้ำ + การควบคุมระดับเสียงด้วยท่าทาง + ใช้ท่าทางสัมผัสเพื่อควบคุมระดับเสียงของเครื่องเล่น + การควบคุมความสว่างด้วยท่าทาง + ใช้ท่าทางสัมผัสเพื่อควบคุมความสว่างของเครื่องเล่น + ตัวควบคุมท่าทางของโปรแกรมเล่น + ใช้ท่าทางสัมผัสเพื่อควบคุมความสว่างและระดับเสียงของเครื่องเล่น + คำแนะนำการค้นหา + แสดงคำแนะนำเมื่อทำการค้นหา + ประวัติการค้นหา + จัดเก็บคำที่เคยค้นหาไว้ในเครื่อง + ประวัติและแคช + ติดตามวิดีโอที่ดคยดู + เล่นต่อหลังการขัดจังหวะ (เช่น การรับโทรศัพท์) + ดาวน์โหลด + วีดีโอถัดไป + เล่นอัตโนมัติ + แสดงวิดีโอ \'ถัดไป\' และ \'ที่คล้ายกัน\' + แสดงเคล็ดลับ \"แตะค้างเพื่อเพิ่ม\" + แสดงเคล็ดลับเมื่อกดปุ่มพื้นหลังหรือป๊อปอัพในหน้ารายละเอียดวิดีโอ + URL ที่ไม่สนับสนุน + ประเทศเริ่มต้นของเนื้อหา + บริการ + ภาษาของเนื้อหาเริ่มต้น + เครื่องเล่น + พฤติกรรม + วิดีโอและเสียง + ประวัติและแคช + ป๊อปอัพ + ลักษณะ + อื่นๆ + แก้จุดบกพร่อง + อัพเดท + กำลังเล่นในโหมดพื้นหลัง + กำลังเล่นในโหมดป๊อปอัพ + จัดคิวลงในการเล่นโหมดพื้นหลังแล้ว + จัดคิวลงในการเล่นโหมดป๊อปอัพแล้ว + เล่น + เนื้อหา + เนื้อหาที่จำกัดอายุ + แสดงวิดีโอที่จำกัดอายุ การอนุญาตดังกล่าวเป็นไปได้จากการตั้งค่า + สด + ดาวน์โหลด + ดาวน์โหลด + รายงานข้อผิดพลาด + ทั้งหมด + ช่อง + ช่อง + เพลย์ลิสต์ + เพลย์ลิสต์ + + วิดีโอ + + + ความคิดเห็น + + แทร็ค + ผู้ใช้ + เหตุการณ์ + ใช่ + ในภายหลัง + ปิดการใช้งาน + ตัวกรอง + เรียกใหม่ + ล้าง + กำลังปรับขนาด + ความละเอียดที่ดีที่สุด + เลิกทำ + ลบไฟล์แล้ว + เล่นทั้งหมด + ตลอดเวลา + เพียงครั้งเดียว + ไฟล์ + การแจ้งเตือน NewPipe + การแจ้งเตือนของแอป NewPipe เมื่อเล่นสื่อในโหมดพื้นหลังและป๊อปอัพ + การแจ้งเตือนการอัปเดตแอป + การแจ้งเตือนสำหรับ NewPipe เวอร์ชั่นใหม่ + [ไม่ทราบ] + เปลี่ยนการวางแนว + สลับไปยังโหมดพื้นหลัง + สลับไปยังโหมดป๊อปอัพ + สลับไปยังโหมดหลัก + นำเข้าฐานข้อมูล + ส่งออกฐานข้อมูล + แทนที่ประวัติการดูและการสมัครรับข้อมูลของคุณ + ส่งออกประวัติการดู ช่องที่ได้บอกรับและเพลย์ลิสต์ + ล้างประวัติการดู + ลบประวัติของวีดีโอที่เคยเล่น + ลบประวัติการดูทั้งหมดหรือไม่\? + ลบประวัติการดูแล้ว + ล้างประวัติการค้นหา + ลบประวัติของคำที่เคยค้นหา + ลบประวัติการค้นหาทั้งหมดหรือไม่\? + ลบประวัติการค้นหาแล้ว + เกิดข้อผิดพลาด + พื้นที่เก็บข้อมูลภายนอกไม่พร้อมใช้งาน + การดาวน์โหลดไปยังการ์ดความจำภายนอกยังไม่สามารถทำได้ รีเซ็ตตำแหน่งโฟลเดอร์ดาวน์โหลดหรือไม่\? + ข้อผิดพลาดของเครือข่าย + ไม่สามารถโหลดรูปขนาดย่อทั้งหมด + ไม่สามารถถอดรหัสลายเซ็น URL ของวิดีโอ + ไม่สามารถแยกวิเคราะห์เว็บไซต์ + ไม่สามารถแยกวิเคราะห์เว็บไซต์ได้อย่างสมบูรณ์ + เนื้อหาไม่พร้อมใช้งาน + ถูกบล็อกโดย GEMA + ไม่สามารถตั้งค่าเมนูดาวน์โหลด + ยังไม่รองรับสตรีมแบบสดในขณะนี้ + ไม่สามารถรับสตรีมใดๆ + ไม่สามารถโหลดรูปภาพ + แอป / UI ขัดข้อง + ไม่สามารถเล่นสตรีมนี้ + เกิดข้อผิดพลาดของตัวเล่นที่ไม่สามารถกู้คืนได้ + กำลังกู้คืนจากข้อผิดพลาดของตัวเล่น + ตัวเล่นภายนอกไม่สนับสนุนลิงก์ประเภทนี้ + URL ไม่ถูกต้อง + ไม่พบสตรีมวิดีโอ + ไม่พบสตรีมเสียง + ไม่มีโฟลเดอร์ตามที่ระบุ + ไม่มีแหล่งแฟ้ม/เนื้อหาดังกล่าว + ไฟล์นี้ไม่มีอยู่หรือไม่ได้รับอนุญาตให้อ่านหรือเขียนไฟล์ + ชื่อไฟล์ต้องไม่ว่างเปล่า + เกิดข้อผิดพลาด: %1$s + ไม่มีสตรีมให้ดาวน์โหลด + เรียกคืนการวางตำแหน่งแท็บเป็นค่าเดิม เนื่องจากพบข้อผิดพลาดในการอ่านการวางตำแหน่งแท็บที่บันทึกไว้ + คืนค่าเริ่มต้น + คุณต้องการคืนค่าเริ่มต้นหรือไม่\? + รายงานข้อผิดพลาดผ่านทาง e-mail + ข้อมูล: + เกิดอะไรขึ้น: + ความคิดเห็นของคุณ (เป็นภาษาอังกฤษ): + รายละเอียด: + ภาพขนาดย่อของตัวอย่างวิดีโอ + ภาพของตัวอย่างวิดีโอขนาดย่อ + รูปขนาดย่อของผู้อัปโหลด + ชอบ + ไม่ชอบ + ใช้ Tor + (ทดลอง) บังคับให้ใช้การเชื่อมต่อผ่าน Tor เพื่อเพิ่มความเป็นส่วนตัว (ยังไม่รองรับวิดีโอสตรีมมิ่ง) + รายงานข้อผิดพลาด + ไม่มีผลลัพธ์ + ไม่มีอะไรที่นี่นอกจากจิ้งหรีด + ลากเพื่อจัดลำดับใหม่ + ไม่สามารถสร้างไดเรกทอรีดาวน์โหลด \'%1$s\' + สร้างไดเรกทอรีดาวน์โหลด \'%1$s\' + วิดีโอ + เสียง + ลองอีกครั้ง + สิทธิ์การเข้าถึงการจัดเก็บข้อมูลถูกปฏิเสธ + พัน + ล้าน + พันล้าน + ไม่มีสมาชิกที่สมัครรับ + + %s บอกรับ + + ไม่สามารถนับจำนวนสมาชิกได้ + ไม่มียอดวิว + + %s วิว + + ไม่มีวิดีโอ + ไม่มีความคิดเห็น + เริ่ม + หยุดพัก + เล่น + สร้าง + ลบ + ลบหนึ่งรายการ + ลบทั้งหมด + ไม่สนใจ + เปลี่ยนชื่อ + ภารกิจใหม่ + ชื่อไฟล์ + เซิร์ฟเวอร์ที่ไม่รองรับ + ไฟล์มีอยู่แล้ว + NewPipe กำลังดาวน์โหลด + แตะเพื่อดูรายละเอียด + โปรดรอ… + คัดลอกไปที่คลิปบอร์ดแล้ว + โปรดเลือกโฟลเดอร์ดาวน์โหลดที่พร้อมใช้งาน + การอนุญาตนี้เป็นสิ่งจำเป็นเพื่อ +\nเปิดในโหมดป๊อปอัป + ลบ 1 รายการแล้ว + ดาวน์โหลด + อักขระที่อนุญาตในชื่อไฟล์ + อักขระที่ไม่ถูกต้องจะถูกแทนที่ด้วยค่านี้ + อักขระทดแทน + ตัวอักษรและตัวเลข + อักขระพิเศษส่วนใหญ่ + ไม่มีแอพที่ติดตั้งเพื่อให้เล่นไฟล์นี้ได้ + เกี่ยวกับ NewPipe + การตั้งค่า + เกี่ยวกับ + สัญญาอนุญาตของบุคคลที่สาม + © %1$s โดย %2$s ภายใต้ %3$s + ไม่สามารถโหลดสัญญาอนุญาต + เปิดเว็บไซต์ + เกี่ยวกับ + ผู้มีส่วนร่วม + สัญญาอนุญาต + แอปสตรีมมิ่งที่เล็กและเสรีบน Android + สนับสนุน + ไม่ว่าคุณจะมีความคิดที่จะช่วยแปลภาษา เปลี่ยนดีไซน์ แก้ไขโค้ดของโปรแกรมให้ดีขึ้นทั้งในระดับเล็กน้อยหรือจะเปลี่ยนแปลงกันแบบขนานใหญ่ เรายินดีให้คุณได้ร่วมช่วยเหลือเสมอ… ยิ่งทำมาก ยิ่งช่วยให้ดีขึ้นมาก! + ดูบน GitHub + บริจาค + คืนให้ + เว็บไซต์ + เยี่ยมชมเว็บไซต์ NewPipe สำหรับข้อมูลเพิ่มเติมและข่าวสาร + นโยบายความเป็นส่วนตัวของ NewPipe + โครงการ NewPipe คำนึงถึงความเป็นส่วนตัวของคุณอย่างจริงจัง ดังนั้นแอปจะไม่เก็บรวบรวมข้อมูลใดๆ โดยไม่ได้รับความยินยอมจากคุณ +\nนโยบายความเป็นส่วนตัวของ NewPipe มีการอธิบายในรายละเอียดเกี่ยวกับข้อมูลที่จะถูกส่งออกไปและเก็บไว้เมื่อคุณรายงานความผิดพลาดของแอป + อ่านนโยบายความเป็นส่วนตัว + สัญญาอนุญาตของ NewPipe + อ่านสัญญาอนุญาต + ประวัติ + สืบค้นแล้ว + ดูแล้ว + ประวัติการดูได้ปิดใช้งานอยู่ + ประวัติ + ประวัติว่างเปล่า + ล้างประวัติแล้ว + ลบรายการแล้ว + คุณต้องการลบรายการนี้ออกจากประวัติการค้นหาหรือไม่\? + คุณต้องการลบรายการนี้ออกจากประวัติการดูหรือไม่\? + คุณแน่ใจหรือไม่ว่าต้องการลบรายการประวัติทั้งหมด\? + เล่นครั้งล่าสุด + เล่นมากที่สุด + เนื้อหาของหน้าหลัก + แท็บใดบ้างที่ต้องการให้แสดงบนหน้าหลัก + การเลือก + หน้าว่าง + หน้า Kiosk + หน้าการสมัครสมาชิก + หน้าฟีด + หน้าของช่อง + เลือกช่อง + ยังไม่มีการสมัครรับข้อมูลช่องในตอนนี้ + เลือกหน้า Kiosk + ส่งออกแล้ว + นำเข้าแล้ว + ไม่มีไฟล์ ZIP ที่ถูกต้อง + คำเตือน: ไม่สามารถนำเข้าไฟล์ทั้งหมดได้ + สิ่งนี้จะแทนที่การตั้งค่าปัจจุบันของคุณ + คุณยังต้องการนำเข้าการตั้งค่าด้วยหรือไม่\? + ไม่สามารถโหลดความคิดเห็นได้ + ได้รับความนิยม + 50 อันดับแรก + ใหม่และมาแรง + การประชุม + เครื่องเล่นพื้นหลัง + เครื่องเล่นป๊อปอัพ + เอาออก + รายละเอียด + การตั้งค่าเสียง + กดค้างไว้เพื่อเพิ่มลงในคิว + เล่นโดยตรงในโหมดพื้นหลัง + เพิ่มคิวในโหมดพื้นหลัง + เพิ่มคิวในโหมดป๊อปอัพ + เริ่มเล่นจากตรงนี้ + เล่นจากจุดนี้ในโหมดพื้นหลัง + เล่นจากจุดนี้ในโหมดป๊อปอัพ + บางสิ่งบางอย่างจะปรากฏที่นี่เร็วๆ นี้ ;D + การดำเนินการ \'เปิด\' ที่ต้องการ + การดำเนินการเริ่มต้นเมื่อเปิดเนื้อหา — %s + เครื่องเล่นวิดีโอ + เครื่องเล่นพื้นหลัง + เครื่องเล่นป๊อปอัพ + ถามเสมอ + กำลังรับข้อมูล… + กำลังโหลดเนื้อหาที่ร้องขอ + เพลย์ลิสต์ใหม่ + ลบ + เปลี่ยนชื่อ + ชื่อ + เพิ่มในเพลย์ลิสต์ + ตั้งเป็นรูปขนาดย่อของเพลย์ลิสต์ + เก็บเพลย์ลิสต์ + เอาที่คั่นหน้าออก + ลบเพลย์ลิสต์นี้หรือไม่\? + สร้างเพลย์ลิสต์แล้ว + เพิ่มลงในเพลย์ลิสต์แล้ว + เปลี่ยนภาพย่อของเพลย์ลิสต์แล้ว + ไม่สามารถลบเพลย์ลิสต์ได้ + ไม่มีคำอธิบายภาพ + พอดี + เติม + ขยาย + สร้างขึ้นโดยอัตโนมัติ + คำบรรยายภาพ + ปรับเปลี่ยนขนาดตัวอักษร สีของข้อความหรือพื้นหลังของคำอธิบายภาพ (จำเป็นตองปิดและเปิดแอปใหม่เพื่อให้การเปลี่ยนแปลงมีผล) + เปิดใช้งาน LeakCanary + การตรวจสอบการรั่วไหลของหน่วยความจำอาจทำให้แอปจะไม่ตอบสนองเมื่อมีการดึงข้อมูลจากหน่วยความจำ + นำเข้า/ส่งออก + นำเข้า + นำเข้าจาก + ส่งออกไปยัง + กำลังนำเข้า… + กำลังส่งออก… + นำเข้าไฟล์ + การส่งออกก่อนหน้านี้ + ไม่สามารถนำเข้าการสมัครรับข้อมูล + ไม่สามารถส่งออกการสมัครรับข้อมูล + นำเข้ารายการช่องที่บอกรับใน YouTube โดยการดาวน์โหลดไฟล์การส่งออก: +\n +\n1. ไปที่ URL นี้: %1$s +\n2. เข้าสู่ระบบเมื่อระบบถาม +\n3. การดาวน์โหลดควรเริ่มต้น (นั่นคือไฟล์ที่ส่งออก) + นำเข้าโปรไฟล์ SoundCloud โดยการพิมพ์ URL หรือรหัสไอดีผู้ใช้ของคุณ: +\n +\n1. เปิดใช้งาน \"โหมดเดสก์ท็อป\" ในเว็บเบราว์เซอร์ (เว็บไซต์ไม่สามารถใช้ได้สำหรับอุปกรณ์มือถือ) +\n2. ไปที่ URL นี้: %1$s +\n3. เข้าสู่ระบบเมื่อระบบถาม +\n4. คัดลอก URL ของโปรไฟล์ที่คุณถูกเปลี่ยนเส้นทางไป + โปรดทราบว่าการดำเนินการนี้อาจใช้งานข้อมูลมือถือที่มีค่าใช้จ่าย +\n +\nคุณต้องการที่จะทำต่อไปหรือไม่\? + การควบคุมความเร็วในการเล่น + จังหวะ + เสียงสูงต่ำ + ยกเลิกการเชื่อมโยง (อาจทำให้เสียงมีการบิดเบือน) + กรอไปข้างหน้าระหว่างความเงียบ + ทีละ + รีเซ็ต + เพื่อให้สอดคล้องกับระเบียบข้อบังคับว่าด้วยการป้องกันข้อมูลทั่วไปของยุโรป (GDPR) เราขอแนะนำให้คุณอ่านนโยบายความเป็นส่วนตัวของ NewPipe อย่างระมัดระวังและถี่ถ้วน +\nคุณต้องยอมรับข้อตกลงเพื่ออนุญาตให้ส่งรายงานข้อผิดพลาดถึงเรา + ยอมรับ + ปฏิเสธ + ไม่จำกัด + จำกัดความละเอียดเมื่อใช้ข้อมูลมือถือ + อัพเดท + แสดงการแจ้งเตือนการปรับปรุงให้ทราบก่อนอัพเดทแอพ เมื่อมีเวอร์ชั่นใหม่ให้พร้อมใช้งาน + ย่อเล็กสุดเมื่อสลับแอป + การดำเนินการเมื่อสลับไปยังแอปอื่นๆ จากโปรแกรมเล่นวิดีโอหลัก — %s + ไม่มี + ย่อเล็กสุดไปยังการเล่นพื้นหลัง + ย่อเล็กสุดไปยังการเล่นป๊อปอัพ + โหมดมุมมองรายการ + รายการ + ตาราง + อัตโนมัติ + สลับมุมมอง + NewPipe พร้อมให้อัพเดทแล้ว! + แตะเพื่อดาวน์โหลด + เสร็จแล้ว + อยู่ในคิว + หยุดชั่วคราว + อยู่ในคิวแล้ว + คิว + การดำเนินการถูกปฏิเสธโดยระบบ + การดาวน์โหลดล้มเหลว + การดาวน์โหลดเสร็จสิ้น + %s การดาวน์โหลดเสร็จสิ้น + สร้างชื่อเฉพาะ + เขียนทับ + ไฟล์ที่ดาวน์โหลดด้วยชื่อนี้มีอยู่แล้ว + มีการดาวน์โหลดที่กำลังดำเนินการอยู่ด้วยไฟล์ชื่อนี้อยู่แล้ว + แสดงข้อผิดพลาด + โค้ด + ไม่สามารถสร้างไฟล์ได้ + ไม่สามารถสร้างโฟลเดอร์ปลายทางได้ + การอนุญาตถูกปฏิเสธโดยระบบ + ล้มเหลวในการสร้างการเชื่อมต่อที่ปลอดภัย + ไม่พบเซิร์ฟเวอร์ + ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ + เซิร์ฟเวอร์ไม่ส่งข้อมูล + เซิร์ฟเวอร์ไม่รองรับการดาวน์โหลดแบบพร้อมกันหลายส่วน โปรดลองอีกครั้งด้วย @string/msg_threads = 1 + ไม่พบ + ล้างการดาวน์โหลดที่เสร็จสิ้นแล้ว + หยุด + จำนวนครั้งสูงสุดที่จะลองใหม่ + จำนวนครั้งสูงสุดที่จะลองใหม่ก่อนจะยกเลิกการดาวน์โหลด + หยุดชั่วคราวเมื่อเปลี่ยนเป็นข้อมูลมือถือ + การดาวน์โหลดที่ไม่สามารถหยุดพักได้จะเริ่มต้นใหม่ + ปิด + \ No newline at end of file diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a42aaac6d..a64dc320f 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -310,10 +310,6 @@ Sığdır Doldur Yakınlaştır - Alt yazı boyutu - Daha küçük yazı tipi - Normal yazı tipi - Daha büyük yazı tipi Hata ayıklama Yakında bir şeyler burada görünecek ;D Kendiliğinden Oluşturulan @@ -325,7 +321,6 @@ İsabetsiz konumlama, oynatıcının daha düşük hassasiyetle daha hızlı pozisyon aramasını sağlar Sonraki akışı otomatik kuyruğa ekle Yinelenmeyen bir kuyruktaki son akışı oynatırken, ilgili bir akışı kendiliğinden ekle - EŞZAMANLA Dosya Böyle bir dizin yok Dosya/içerik kaynağı değil @@ -368,7 +363,6 @@ Öntanımlı Ses titreşimi Bağlantısız (bozulmaya neden olabilir) - Nightcore İndirilebilecek akış yok Tercih edilen \'aç\' eylemi İçerik açılırken öntanımlı eylem — %s @@ -481,6 +475,5 @@ Yorum yok Yorumlar yüklenemedi - Arka planda direkt başlat Kapat \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c2ab26e1e..7312003c6 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -107,7 +107,7 @@ Подробиці Зачекайте… Скопійовано до буферу обміну - Оберіть доступну теку для завантажень + Вкажіть теку для завантажень пізніше у налаштуваннях Програвач потокового відео не знайдений (ви можете встановити VLC для програвання). Відкрити у віконному режимі Прибирає звук при ПЕВНИХ роздільних здатностях @@ -436,7 +436,7 @@ Доступна нова версія NewPipe! Натисніть для завантаження Завершено - У черзі + Очікує призупинено додано в чергу пост-обробка @@ -452,8 +452,8 @@ Файл з такою назвою вже завантажується Показати помилку Код - Файл не може бути створений - Цільова тека не може бути створена + Цільова тека не може бути створена + Файл не може бути створений Доступ заборонено системою Захищене з\'єднання не встановлено Сервер не знайдено @@ -466,24 +466,40 @@ Зупинити Максимум спроб Максимальна кількість спроб перед скасуванням завантаження - Призупиняти завантаження при переході на стільникові дані - Завантаження до зовнішньої SD-карти поки що неможливе. Скинути розташування теки для завантажень\? + Переривати завантаження на небезлімітних з\'єднаннях + Завантаження до зовнішньої SD-карти неможливе. Скинути розташування теки для завантажень\? Помилка зчитування збережених вкладок. Використовую типові вкладки. Вкладки, що відображаються на головній сторінці Показувати сповіщення з пропозицією оновити застосунок за наявності нової версії Запитуваний діапазон неприпустимий Продовжити ваші %s відкладених переміщень із Завантажень - Завантаження, що не можуть бути призупинені, будуть перезапущені + Корисно під час переходу на мобільні дані, хоча деякі завантаження не можуть бути призупинені Показувати коментарі Вимнути відображення дописів Автопрогравання Коментарі - - + + Коментарі відсутні Не вдалося підвантажити коментарів - Програвати у фоні Закрити + Позиції відтворення видалено. + Файл переміщено або видалено + не можу перезаписати файл + Завантаження з таким ім\'ям вже є в черзі + NewPipe був закритий під час роботи над файлом + На пристрої не залишилося вільного місця + Прогрес втрачено через видалення файлу + Час очікування з\'єднання вичерпано + Ви впевнені\? + Обмежити чергу завантажень + В кожен момент часу виконуватиметься одне завантаження + Почати завантаження + Призупинити завантаження + Запитувати, куди завантажувати + Вас питатимуть, куди зберігати кожне завантаження + Вас питатимуть, куди зберігати кожне завантаження. +\nУвімкніть цю опцію, якщо бажаєте завантажувати на зовнішню SD-картку \ No newline at end of file diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 16171429e..6888f7b8d 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -12,11 +12,11 @@ Tải về Tìm kiếm Cài đặt - Ý của bạn là %1$s\? + Ý của bạn là: %1$s\? Chia sẻ với Chọn trình duyệt Sử dụng trình phát video bên ngoài - Âm thanh có thể không có ở *một vài* độ phân giải video + Loại bỏ âm thanh trên *MỘT SỐ* độ phân giải video Sử dụng trình phát audio bên ngoài Chế độ popup của NewPipe Trình phát nổi @@ -45,13 +45,13 @@ Tối Đen Nhớ kích thước và vị trí của popup - Nhớ kích thước và vị trí cuối của popup + Nhớ kích thước và vị trí lần trước của popup Điều khiển cử chỉ trình phát Sử dụng cử chỉ để kiểm soát độ sáng và âm lượng của trình phát Đề xuất tìm kiếm Hiển thị các đề xuất khi tìm kiếm Tải về - Tiếp + Tiếp theo Hiển thị video \"Tiếp theo\" và \"Tương tự\" URL không được hỗ trợ Hiển thị @@ -78,7 +78,7 @@ Độ phân giải tốt nhất Lỗi Lỗi kết nối mạng - Không thể tải tất cả các thumbnails + Không thể tải tất cả hình thu nhỏ Không thể giải mã chữ ký URL video Không thể phân tích cú pháp trang web Không thể phân tích cú pháp hoàn toàn trang web @@ -132,7 +132,7 @@ Chạm để biết chi tiết Vui lòng đợi … Sao chép vào clipboard - Chọn một thư mục tải về có sẵn + Chọn một thư mục tải về có sẵn trong cài đặt Cần quyền này để \nmở trong chế độ popup ReCAPTCHA @@ -158,7 +158,7 @@ Ngôn ngữ nội dung ưu tiên Video & âm thanh Trình phát nổi - Lịch sử & bộ nhớ cache + Lịch sử xem Lịch sử & bộ nhớ cache Playlist Không tìm thấy @@ -170,13 +170,13 @@ Không tìm thấy trình phát luồng nào (bạn có thể cài đặt VLC để phát). Tải về tệp luồng Hiển thị thông tin - main + Trang chủ Đăng ký - Playlist đã đánh dấu + Danh sách phát được đánh dấu Có gì mới Thêm vào Sử dụng tìm kiếm nhanh không chính xác - Tìm kiếm không chính xác cho phép trình phát tua đến vị trí nhanh hơn với độ chính xác bị hạn chế + Tìm kiếm không chính xác cho phép trình phát tìm đến vị trí nhanh hơn với độ chính xác bị hạn chế Tải hình thu nhỏ Tắt để không tải về các hình thu nhỏ, tiết kiệm lưu lượng mạng và bộ nhớ. Thay đổi điều này sẽ xóa bộ nhớ đệm hình ảnh cả trong RAM và trong bộ nhớ. Đã xóa bộ nhớ cache hình ảnh @@ -184,7 +184,7 @@ Xóa tất cả dữ liệu trang web được lưu trong bộ nhớ cache Đã xóa bộ nhớ cache siêu dữ liệu Tự động phát tiếp theo theo hàng - Tự động thêm một luồng có liên quan khi phát luồng cuối cùng trong hàng đợi không lặp lại. + Tự động thêm một luồng có liên quan khi phát luồng cuối cùng trong hàng đợi không lặp lại Lịch sử tìm kiếm Lưu trữ truy vấn tìm kiếm cục bộ Theo dõi các video đã xem @@ -252,7 +252,7 @@ Không có video nào - Video + Videos Tạo nên Xóa một @@ -315,10 +315,10 @@ Cài đặt âm thanh Giữ để nối tiếp Thêm vào trình phát nền - Thêm vào trình phát popup + Thêm vào trình phát popup mới Bắt đầu phát ở đây - Bắt đầu từ đây trong nền - Bắt đầu từ đây trên trình phát popup + Bắt đầu phát từ đây trong nền + Bắt đầu phát từ đây trên trình phát popup mới Mở ngăn kéo Đóng ngăn Một cái gì đó sẽ xuất hiện ở đây sớm ;D @@ -409,7 +409,7 @@ Thông báo cập nhật ứng dụng Thông báo phiên bản NewPipe mới Bộ nhớ ngoài không khả dụng - Hiện tại chưa thể tải vào thẻ SD ngoài. Đặt lại vị trí tải về\? + Không thể tải vào thẻ SD ngoài. Đặt lại vị trí tải về\? Khôi phục lại các tab mặc định do danh sách các tab đã lưu không hợp lệ Khôi phục về mặc định Bạn có muốn khôi phục về mặc định\? @@ -457,9 +457,41 @@ Dừng Số lượt thử lại tối đa Số lượt thử lại trước khi hủy tải về - Tạm dừng tải khi chuyển qua dữ liệu di động - Các tải về không thể tạm dừng được sẽ bắt đầu lại từ đầu + Tạm dừng tải khi trên dữ liệu di động + Hữu ích khi chuyển sang dữ liệu di động, nhưng một số tải xuống không thể bị đình chỉ Đang chờ xử lý Hội thảo + Hiện nhận xét + Vô hiệu hoá để dừng nhận xét xuất hiện + Tự động phát + + Nhận xét + + Không có nhận xét + Không thể tải nhận xét + Đóng + Tiếp tục phát + Phục hồi vị trí phát lại + Vị trí phát trong danh sách + Hiện vị trí phát lại trong danh sách + Xoá dữ liệu + Đã xoá vị trí phát lại. + Tệp đã di chuyển hoặc đã xoá + Tên file này đã tồn tại + Không thể ghi đè lên tệp + Có một bản tải xuống đang chờ xử lí với tên này + Newpipe đã bị đóng khi đang xử lí tệp + Không đủ dung lượng trên máy + Quá trình mất, vì tập tin đã bị xoá + Kết nối hết thời gian + Bạn có chắc không\? + Giới hạn hàng chờ tải xuống + Chỉ một tải xuống sẽ chạy + Bắt đầu tải xuống + Tạm dừng tải xuống + Hỏi vị trí tải xuống + Bạn sẽ được hỏi vị trí lưu mỗi lần tải xuống + Bạn sẽ được hỏi vị trí lưu mỗi lần tải xuống. +\nBật tính năng này nếu bạn muốn tải xuống sang thẻ SD ngoài. \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d3f39b1ec..9aa4b9245 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -383,10 +383,6 @@ 放大填充 自动生成 - 字幕字体大小 - 小字体 - 中等字体 - 大字体 启用 LeakCanary 内存泄露监测可能会在heap dumping时导致应用失去响应 @@ -426,7 +422,6 @@ 速度 音调 Unhook(可能导致失真) - Nightcore 默认 未安装能播放此文件的应用 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 854a191a6..50e16464e 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -306,10 +306,6 @@ 合適的 填滿 縮放 - 標題字體大小 - 縮小字體 - 正常字體 - 加大字體 某些東西即將在此出現 ;D 除錯 自動產生 @@ -321,7 +317,6 @@ 粗略的尋找能讓播放器以降低的精確度更快找到影片的進度位置 自動將下一部影片新增至佇列 在非重複播放佇列中最後一個串流開始播放時,自動新增相關串流 - 同步 檔案 無效的資料夾 無效的檔案/內容來源 @@ -363,7 +358,6 @@ 節奏 音高 解除連結(可能導致失真) - Nightcore 預設 偏好的「開啟」動作 開啟內容時的預設動作 — %s @@ -477,6 +471,5 @@ 沒有留言 無法載入留言 - 直接在背景播放 關閉 \ No newline at end of file diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 49f38b667..6c51fbb1c 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -163,6 +163,7 @@ clear_search_history downloads_storage_ask + storage_use_saf file_rename_charset diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 91b0953cc..fd7a440bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -99,7 +99,7 @@ Resume on focus gain Continue playing after interruptions (e.g. phone calls) Download - Up next + Next Autoplay Show \'Next\' and \'Similar\' videos Show \"Hold to append\" tip @@ -260,16 +260,14 @@ No videos - Video - Videos - - + Videos + Videos + No comments %s comment %s comments - Start Pause @@ -295,7 +293,7 @@ Tap for details Please wait… Copied to clipboard - Please define an download folder later in settings + Please define a download folder later in settings This permission is needed to\nopen in popup mode 1 item deleted. @@ -310,7 +308,6 @@ Allowed characters in filenames Invalid characters are replaced with this value Replacement character - Letters and digits Most special characters No app installed to play this file @@ -377,7 +374,6 @@ This will override your current setup. Do you want to also import settings? Could not load comments - Kiosk Trending @@ -397,7 +393,6 @@ Start playing here Start playing in the background Start playing in a new popup - Open Drawer Close Drawer @@ -520,7 +515,6 @@ cannot overwrite the file There is a download in progress with this name There is a pending download with this name - Show error Code @@ -539,7 +533,6 @@ No space left on device Progress lost, because the file was deleted Connection timeout - Clear finished downloads Are you sure? Continue your %s pending transfers from Downloads @@ -553,9 +546,9 @@ One download will run at the same time Start downloads Pause downloads - Ask where to download You will be asked where to save each download - You will be asked where to save each download.\nEnable this option if you want download to the external SD Card - - + You will be asked where to save each download.\nChoose SAF if you want to download to an external SD card + Use SAF + The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible + \ No newline at end of file diff --git a/app/src/main/res/xml/download_settings.xml b/app/src/main/res/xml/download_settings.xml index 7a6fab841..0df021842 100644 --- a/app/src/main/res/xml/download_settings.xml +++ b/app/src/main/res/xml/download_settings.xml @@ -12,6 +12,13 @@ android:summary="@string/downloads_storage_ask_summary_kitkat" android:title="@string/downloads_storage_ask_title" /> + +