mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2026-02-11 04:30:15 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d42058d99e | ||
|
|
a06034f189 | ||
|
|
3635b40daa | ||
|
|
81ee67b03b | ||
|
|
b2d4fdb0fb | ||
|
|
e7b5231708 | ||
|
|
d0edb9482d | ||
|
|
4282f78dd4 | ||
|
|
3150cae5f6 | ||
|
|
2c3da68329 | ||
|
|
9830c55563 | ||
|
|
ead12cec74 | ||
|
|
ae7078e5b6 | ||
|
|
93d3909e19 | ||
|
|
7ae7cb3b7e |
@@ -79,7 +79,7 @@ configure<ApplicationExtension> {
|
|||||||
resValue("string", "app_name", "NewPipe $suffix")
|
resValue("string", "app_name", "NewPipe $suffix")
|
||||||
}
|
}
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
isShrinkResources = false // disabled to fix F-Droid"s reproducible build
|
isShrinkResources = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
@@ -88,13 +88,7 @@ configure<ApplicationExtension> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lint {
|
lint {
|
||||||
checkReleaseBuilds = false
|
lintConfig = file("lint.xml")
|
||||||
// Or, if you prefer, you can continue to check for errors in release builds,
|
|
||||||
// but continue the build even when errors are found:
|
|
||||||
abortOnError = false
|
|
||||||
// suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version
|
|
||||||
// 5.0, avoid using them in switch case statements"), which affects only library projects
|
|
||||||
disable += "NonConstantResourceId"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|||||||
10
app/lint.xml
Normal file
10
app/lint.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
|
||||||
|
~ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
-->
|
||||||
|
<lint>
|
||||||
|
<issue id="MissingTranslation" severity="ignore" />
|
||||||
|
<issue id="MissingQuantity" severity="ignore" />
|
||||||
|
<issue id="ImpliedQuantity" severity="ignore" />
|
||||||
|
</lint>
|
||||||
@@ -309,24 +309,20 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean drawerItemSelected(final MenuItem item) {
|
private boolean drawerItemSelected(final MenuItem item) {
|
||||||
switch (item.getGroupId()) {
|
final int groupId = item.getGroupId();
|
||||||
case R.id.menu_services_group:
|
if (groupId == R.id.menu_services_group) {
|
||||||
changeService(item);
|
changeService(item);
|
||||||
break;
|
} else if (groupId == R.id.menu_tabs_group) {
|
||||||
case R.id.menu_tabs_group:
|
|
||||||
tabSelected(item);
|
tabSelected(item);
|
||||||
break;
|
} else if (groupId == R.id.menu_kiosks_group) {
|
||||||
case R.id.menu_kiosks_group:
|
|
||||||
try {
|
try {
|
||||||
kioskSelected(item);
|
kioskSelected(item);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorUtil.showUiErrorSnackbar(this, "Selecting drawer kiosk", e);
|
ErrorUtil.showUiErrorSnackbar(this, "Selecting drawer kiosk", e);
|
||||||
}
|
}
|
||||||
break;
|
} else if (groupId == R.id.menu_options_about_group) {
|
||||||
case R.id.menu_options_about_group:
|
|
||||||
optionsAboutSelected(item);
|
optionsAboutSelected(item);
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,8 +82,10 @@ class NewVersionWorker(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val notificationManager = NotificationManagerCompat.from(applicationContext)
|
val notificationManager = NotificationManagerCompat.from(applicationContext)
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
notificationManager.notify(2000, notificationBuilder.build())
|
notificationManager.notify(2000, notificationBuilder.build())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ReCaptchaException::class)
|
@Throws(IOException::class, ReCaptchaException::class)
|
||||||
private fun checkNewVersion() {
|
private fun checkNewVersion() {
|
||||||
|
|||||||
@@ -41,18 +41,18 @@ public final class QueueItemMenuUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
popupMenu.setOnMenuItemClickListener(menuItem -> {
|
popupMenu.setOnMenuItemClickListener(menuItem -> {
|
||||||
switch (menuItem.getItemId()) {
|
final int itemId = menuItem.getItemId();
|
||||||
case R.id.menu_item_remove:
|
if (itemId == R.id.menu_item_remove) {
|
||||||
final int index = playQueue.indexOf(item);
|
final int index = playQueue.indexOf(item);
|
||||||
playQueue.remove(index);
|
playQueue.remove(index);
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_details:
|
} else if (itemId == R.id.menu_item_details) {
|
||||||
// playQueue is null since we don't want any queue change
|
// playQueue is null since we don't want any queue change
|
||||||
NavigationHelper.openVideoDetail(context, item.getServiceId(),
|
NavigationHelper.openVideoDetail(context, item.getServiceId(),
|
||||||
item.getUrl(), item.getTitle(), null,
|
item.getUrl(), item.getTitle(), null,
|
||||||
false);
|
false);
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_append_playlist:
|
} else if (itemId == R.id.menu_item_append_playlist) {
|
||||||
PlaylistDialog.createCorrespondingDialog(
|
PlaylistDialog.createCorrespondingDialog(
|
||||||
context,
|
context,
|
||||||
List.of(new StreamEntity(item)),
|
List.of(new StreamEntity(item)),
|
||||||
@@ -63,7 +63,7 @@ public final class QueueItemMenuUtil {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_channel_details:
|
} else if (itemId == R.id.menu_item_channel_details) {
|
||||||
SparseItemUtil.fetchUploaderUrlIfSparse(context, item.getServiceId(),
|
SparseItemUtil.fetchUploaderUrlIfSparse(context, item.getServiceId(),
|
||||||
item.getUrl(), item.getUploaderUrl(),
|
item.getUrl(), item.getUploaderUrl(),
|
||||||
// An intent must be used here.
|
// An intent must be used here.
|
||||||
@@ -73,11 +73,11 @@ public final class QueueItemMenuUtil {
|
|||||||
context, item.getServiceId(), uploaderUrl, item.getUploader()
|
context, item.getServiceId(), uploaderUrl, item.getUploader()
|
||||||
));
|
));
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_share:
|
} else if (itemId == R.id.menu_item_share) {
|
||||||
shareText(context, item.getTitle(), item.getUrl(),
|
shareText(context, item.getTitle(), item.getUrl(),
|
||||||
item.getThumbnails());
|
item.getThumbnails());
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_download:
|
} else if (itemId == R.id.menu_item_download) {
|
||||||
fetchStreamInfoAndSaveToDatabase(context, item.getServiceId(), item.getUrl(),
|
fetchStreamInfoAndSaveToDatabase(context, item.getServiceId(), item.getUrl(),
|
||||||
info -> {
|
info -> {
|
||||||
final DownloadDialog downloadDialog = new DownloadDialog(context,
|
final DownloadDialog downloadDialog = new DownloadDialog(context,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import android.os.IBinder;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
@@ -31,7 +32,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.view.menu.ActionMenuItemView;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.collection.SparseArrayCompat;
|
import androidx.collection.SparseArrayCompat;
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
@@ -113,7 +113,7 @@ public class DownloadDialog extends DialogFragment
|
|||||||
private StoredDirectoryHelper mainStorageAudio = null;
|
private StoredDirectoryHelper mainStorageAudio = null;
|
||||||
private StoredDirectoryHelper mainStorageVideo = null;
|
private StoredDirectoryHelper mainStorageVideo = null;
|
||||||
private DownloadManager downloadManager = null;
|
private DownloadManager downloadManager = null;
|
||||||
private ActionMenuItemView okButton = null;
|
private MenuItem okButton = null;
|
||||||
private Context context = null;
|
private Context context = null;
|
||||||
private boolean askForSavePath;
|
private boolean askForSavePath;
|
||||||
|
|
||||||
@@ -558,17 +558,13 @@ public class DownloadDialog extends DialogFragment
|
|||||||
}
|
}
|
||||||
boolean flag = true;
|
boolean flag = true;
|
||||||
|
|
||||||
switch (checkedId) {
|
if (checkedId == R.id.audio_button) {
|
||||||
case R.id.audio_button:
|
|
||||||
setupAudioSpinner();
|
setupAudioSpinner();
|
||||||
break;
|
} else if (checkedId == R.id.video_button) {
|
||||||
case R.id.video_button:
|
|
||||||
setupVideoSpinner();
|
setupVideoSpinner();
|
||||||
break;
|
} else if (checkedId == R.id.subtitle_button) {
|
||||||
case R.id.subtitle_button:
|
|
||||||
setupSubtitleSpinner();
|
setupSubtitleSpinner();
|
||||||
flag = false;
|
flag = false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogBinding.threads.setEnabled(flag);
|
dialogBinding.threads.setEnabled(flag);
|
||||||
@@ -585,28 +581,25 @@ public class DownloadDialog extends DialogFragment
|
|||||||
+ "position = [" + position + "], id = [" + id + "]");
|
+ "position = [" + position + "], id = [" + id + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (parent.getId()) {
|
final int parentId = parent.getId();
|
||||||
case R.id.quality_spinner:
|
if (parentId == R.id.quality_spinner) {
|
||||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
final int checkedRadioButtonId = dialogBinding.videoAudioGroup
|
||||||
case R.id.video_button:
|
.getCheckedRadioButtonId();
|
||||||
|
if (checkedRadioButtonId == R.id.video_button) {
|
||||||
selectedVideoIndex = position;
|
selectedVideoIndex = position;
|
||||||
onVideoStreamSelected();
|
onVideoStreamSelected();
|
||||||
break;
|
} else if (checkedRadioButtonId == R.id.subtitle_button) {
|
||||||
case R.id.subtitle_button:
|
|
||||||
selectedSubtitleIndex = position;
|
selectedSubtitleIndex = position;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
onItemSelectedSetFileName();
|
onItemSelectedSetFileName();
|
||||||
break;
|
} else if (parentId == R.id.audio_track_spinner) {
|
||||||
case R.id.audio_track_spinner:
|
|
||||||
final boolean trackChanged = selectedAudioTrackIndex != position;
|
final boolean trackChanged = selectedAudioTrackIndex != position;
|
||||||
selectedAudioTrackIndex = position;
|
selectedAudioTrackIndex = position;
|
||||||
if (trackChanged) {
|
if (trackChanged) {
|
||||||
updateSecondaryStreams();
|
updateSecondaryStreams();
|
||||||
fetchStreamsSize();
|
fetchStreamsSize();
|
||||||
}
|
}
|
||||||
break;
|
} else if (parentId == R.id.audio_stream_spinner) {
|
||||||
case R.id.audio_stream_spinner:
|
|
||||||
selectedAudioIndex = position;
|
selectedAudioIndex = position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -622,23 +615,20 @@ public class DownloadDialog extends DialogFragment
|
|||||||
|| prevFileName.startsWith(getString(R.string.caption_file_name, fileName, ""))) {
|
|| prevFileName.startsWith(getString(R.string.caption_file_name, fileName, ""))) {
|
||||||
// only update the file name field if it was not edited by the user
|
// only update the file name field if it was not edited by the user
|
||||||
|
|
||||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
final int radioButtonId = dialogBinding.videoAudioGroup
|
||||||
case R.id.audio_button:
|
.getCheckedRadioButtonId();
|
||||||
case R.id.video_button:
|
if (radioButtonId == R.id.audio_button || radioButtonId == R.id.video_button) {
|
||||||
if (!prevFileName.equals(fileName)) {
|
if (!prevFileName.equals(fileName)) {
|
||||||
// since the user might have switched between audio and video, the correct
|
// since the user might have switched between audio and video, the correct
|
||||||
// text might already be in place, so avoid resetting the cursor position
|
// text might already be in place, so avoid resetting the cursor position
|
||||||
dialogBinding.fileName.setText(fileName);
|
dialogBinding.fileName.setText(fileName);
|
||||||
}
|
}
|
||||||
break;
|
} else if (radioButtonId == R.id.subtitle_button) {
|
||||||
|
|
||||||
case R.id.subtitle_button:
|
|
||||||
final String setSubtitleLanguageCode = subtitleStreamsAdapter
|
final String setSubtitleLanguageCode = subtitleStreamsAdapter
|
||||||
.getItem(selectedSubtitleIndex).getLanguageTag();
|
.getItem(selectedSubtitleIndex).getLanguageTag();
|
||||||
// this will reset the cursor position, which is bad UX, but it can't be avoided
|
// this will reset the cursor position, which is bad UX, but it can't be avoided
|
||||||
dialogBinding.fileName.setText(getString(
|
dialogBinding.fileName.setText(getString(
|
||||||
R.string.caption_file_name, fileName, setSubtitleLanguageCode));
|
R.string.caption_file_name, fileName, setSubtitleLanguageCode));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -770,8 +760,8 @@ public class DownloadDialog extends DialogFragment
|
|||||||
|
|
||||||
filenameTmp = getNameEditText().concat(".");
|
filenameTmp = getNameEditText().concat(".");
|
||||||
|
|
||||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
final int checkedRadioButtonId = dialogBinding.videoAudioGroup.getCheckedRadioButtonId();
|
||||||
case R.id.audio_button:
|
if (checkedRadioButtonId == R.id.audio_button) {
|
||||||
selectedMediaType = getString(R.string.last_download_type_audio_key);
|
selectedMediaType = getString(R.string.last_download_type_audio_key);
|
||||||
mainStorage = mainStorageAudio;
|
mainStorage = mainStorageAudio;
|
||||||
format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat();
|
format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat();
|
||||||
@@ -783,8 +773,7 @@ public class DownloadDialog extends DialogFragment
|
|||||||
mimeTmp = format.mimeType;
|
mimeTmp = format.mimeType;
|
||||||
filenameTmp += format.getSuffix();
|
filenameTmp += format.getSuffix();
|
||||||
}
|
}
|
||||||
break;
|
} else if (checkedRadioButtonId == R.id.video_button) {
|
||||||
case R.id.video_button:
|
|
||||||
selectedMediaType = getString(R.string.last_download_type_video_key);
|
selectedMediaType = getString(R.string.last_download_type_video_key);
|
||||||
mainStorage = mainStorageVideo;
|
mainStorage = mainStorageVideo;
|
||||||
format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat();
|
format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat();
|
||||||
@@ -793,8 +782,7 @@ public class DownloadDialog extends DialogFragment
|
|||||||
mimeTmp = format.mimeType;
|
mimeTmp = format.mimeType;
|
||||||
filenameTmp += format.getSuffix();
|
filenameTmp += format.getSuffix();
|
||||||
}
|
}
|
||||||
break;
|
} else if (checkedRadioButtonId == R.id.subtitle_button) {
|
||||||
case R.id.subtitle_button:
|
|
||||||
selectedMediaType = getString(R.string.last_download_type_subtitle_key);
|
selectedMediaType = getString(R.string.last_download_type_subtitle_key);
|
||||||
mainStorage = mainStorageVideo; // subtitle & video files go together
|
mainStorage = mainStorageVideo; // subtitle & video files go together
|
||||||
format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat();
|
format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat();
|
||||||
@@ -808,8 +796,7 @@ public class DownloadDialog extends DialogFragment
|
|||||||
} else if (format != null) {
|
} else if (format != null) {
|
||||||
filenameTmp += format.getSuffix();
|
filenameTmp += format.getSuffix();
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
throw new RuntimeException("No stream selected");
|
throw new RuntimeException("No stream selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,8 +1044,8 @@ public class DownloadDialog extends DialogFragment
|
|||||||
long nearLength = 0;
|
long nearLength = 0;
|
||||||
|
|
||||||
// more download logic: select muxer, subtitle converter, etc.
|
// more download logic: select muxer, subtitle converter, etc.
|
||||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
final int checkedRadioButtonId = dialogBinding.videoAudioGroup.getCheckedRadioButtonId();
|
||||||
case R.id.audio_button:
|
if (checkedRadioButtonId == R.id.audio_button) {
|
||||||
kind = 'a';
|
kind = 'a';
|
||||||
selectedStream = audioStreamsAdapter.getItem(selectedAudioIndex);
|
selectedStream = audioStreamsAdapter.getItem(selectedAudioIndex);
|
||||||
|
|
||||||
@@ -1067,8 +1054,7 @@ public class DownloadDialog extends DialogFragment
|
|||||||
} else if (selectedStream.getFormat() == MediaFormat.WEBMA_OPUS) {
|
} else if (selectedStream.getFormat() == MediaFormat.WEBMA_OPUS) {
|
||||||
psName = Postprocessing.ALGORITHM_OGG_FROM_WEBM_DEMUXER;
|
psName = Postprocessing.ALGORITHM_OGG_FROM_WEBM_DEMUXER;
|
||||||
}
|
}
|
||||||
break;
|
} else if (checkedRadioButtonId == R.id.video_button) {
|
||||||
case R.id.video_button:
|
|
||||||
kind = 'v';
|
kind = 'v';
|
||||||
selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex);
|
selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex);
|
||||||
|
|
||||||
@@ -1094,21 +1080,19 @@ public class DownloadDialog extends DialogFragment
|
|||||||
nearLength = secondary.getSizeInBytes() + videoSize;
|
nearLength = secondary.getSizeInBytes() + videoSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
} else if (checkedRadioButtonId == R.id.subtitle_button) {
|
||||||
case R.id.subtitle_button:
|
|
||||||
threads = 1; // use unique thread for subtitles due small file size
|
threads = 1; // use unique thread for subtitles due small file size
|
||||||
kind = 's';
|
kind = 's';
|
||||||
selectedStream = subtitleStreamsAdapter.getItem(selectedSubtitleIndex);
|
selectedStream = subtitleStreamsAdapter.getItem(selectedSubtitleIndex);
|
||||||
|
|
||||||
if (selectedStream.getFormat() == MediaFormat.TTML) {
|
if (selectedStream.getFormat() == MediaFormat.TTML) {
|
||||||
psName = Postprocessing.ALGORITHM_TTML_CONVERTER;
|
psName = Postprocessing.ALGORITHM_TTML_CONVERTER;
|
||||||
psArgs = new String[] {
|
psArgs = new String[]{
|
||||||
selectedStream.getFormat().getSuffix(),
|
selectedStream.getFormat().getSuffix(),
|
||||||
"false" // ignore empty frames
|
"false" // ignore empty frames
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,17 +133,16 @@ public class ErrorActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
final int itemId = item.getItemId();
|
||||||
case android.R.id.home:
|
if (itemId == android.R.id.home) {
|
||||||
onBackPressed();
|
onBackPressed();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_share_error:
|
} else if (itemId == R.id.menu_item_share_error) {
|
||||||
ShareUtils.shareText(getApplicationContext(),
|
ShareUtils.shareText(getApplicationContext(),
|
||||||
getString(R.string.error_report_title), buildJson());
|
getString(R.string.error_report_title), buildJson());
|
||||||
return true;
|
return true;
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openPrivacyPolicyDialog(final Context context, final String action) {
|
private void openPrivacyPolicyDialog(final Context context, final String action) {
|
||||||
|
|||||||
@@ -134,8 +134,11 @@ class ErrorUtil {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
NotificationManagerCompat.from(context)
|
val notificationManager = NotificationManagerCompat.from(context)
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
|
notificationManager
|
||||||
.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build())
|
.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build())
|
||||||
|
}
|
||||||
|
|
||||||
ContextCompat.getMainExecutor(context).execute {
|
ContextCompat.getMainExecutor(context).execute {
|
||||||
// since the notification is silent, also show a toast, otherwise the user is confused
|
// since the notification is silent, also show a toast, otherwise the user is confused
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressLint("MissingSuperCall")
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
saveCookiesAndFinish();
|
saveCookiesAndFinish();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,33 +160,28 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemSelected(@NonNull final MenuItem item) {
|
public boolean onMenuItemSelected(@NonNull final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
final int itemId = item.getItemId();
|
||||||
case R.id.menu_item_notify:
|
if (itemId == R.id.menu_item_notify) {
|
||||||
final boolean value = !item.isChecked();
|
final boolean value = !item.isChecked();
|
||||||
item.setEnabled(false);
|
item.setEnabled(false);
|
||||||
setNotify(value);
|
setNotify(value);
|
||||||
break;
|
} else if (itemId == R.id.action_settings) {
|
||||||
case R.id.action_settings:
|
|
||||||
NavigationHelper.openSettings(requireContext());
|
NavigationHelper.openSettings(requireContext());
|
||||||
break;
|
} else if (itemId == R.id.menu_item_rss) {
|
||||||
case R.id.menu_item_rss:
|
|
||||||
if (currentInfo != null) {
|
if (currentInfo != null) {
|
||||||
ShareUtils.openUrlInApp(requireContext(), currentInfo.getFeedUrl());
|
ShareUtils.openUrlInApp(requireContext(), currentInfo.getFeedUrl());
|
||||||
}
|
}
|
||||||
break;
|
} else if (itemId == R.id.menu_item_openInBrowser) {
|
||||||
case R.id.menu_item_openInBrowser:
|
|
||||||
if (currentInfo != null) {
|
if (currentInfo != null) {
|
||||||
ShareUtils.openUrlInBrowser(requireContext(),
|
ShareUtils.openUrlInBrowser(requireContext(),
|
||||||
currentInfo.getOriginalUrl());
|
currentInfo.getOriginalUrl());
|
||||||
}
|
}
|
||||||
break;
|
} else if (itemId == R.id.menu_item_share) {
|
||||||
case R.id.menu_item_share:
|
|
||||||
if (currentInfo != null) {
|
if (currentInfo != null) {
|
||||||
ShareUtils.shareText(requireContext(), name,
|
ShareUtils.shareText(requireContext(), name,
|
||||||
currentInfo.getOriginalUrl(), currentInfo.getAvatars());
|
currentInfo.getOriginalUrl(), currentInfo.getAvatars());
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -232,21 +232,17 @@ public class PlaylistFragment extends BaseListInfoFragment<StreamInfoItem, Playl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
final int itemId = item.getItemId();
|
||||||
case R.id.action_settings:
|
if (itemId == R.id.action_settings) {
|
||||||
NavigationHelper.openSettings(requireContext());
|
NavigationHelper.openSettings(requireContext());
|
||||||
break;
|
} else if (itemId == R.id.menu_item_openInBrowser) {
|
||||||
case R.id.menu_item_openInBrowser:
|
|
||||||
ShareUtils.openUrlInBrowser(requireContext(), url);
|
ShareUtils.openUrlInBrowser(requireContext(), url);
|
||||||
break;
|
} else if (itemId == R.id.menu_item_share) {
|
||||||
case R.id.menu_item_share:
|
|
||||||
ShareUtils.shareText(requireContext(), name, url,
|
ShareUtils.shareText(requireContext(), name, url,
|
||||||
currentInfo == null ? List.of() : currentInfo.getThumbnails());
|
currentInfo == null ? List.of() : currentInfo.getThumbnails());
|
||||||
break;
|
} else if (itemId == R.id.menu_item_bookmark) {
|
||||||
case R.id.menu_item_bookmark:
|
|
||||||
onBookmarkClicked();
|
onBookmarkClicked();
|
||||||
break;
|
} else if (itemId == R.id.menu_item_append_playlist) {
|
||||||
case R.id.menu_item_append_playlist:
|
|
||||||
if (currentInfo != null) {
|
if (currentInfo != null) {
|
||||||
disposables.add(PlaylistDialog.createCorrespondingDialog(
|
disposables.add(PlaylistDialog.createCorrespondingDialog(
|
||||||
getContext(),
|
getContext(),
|
||||||
@@ -258,8 +254,7 @@ public class PlaylistFragment extends BaseListInfoFragment<StreamInfoItem, Playl
|
|||||||
dialog -> dialog.show(getFM(), TAG)
|
dialog -> dialog.show(getFM(), TAG)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
|
|||||||
viewModel.getShowFutureItemsFromPreferences()
|
viewModel.getShowFutureItemsFromPreferences()
|
||||||
)
|
)
|
||||||
|
|
||||||
AlertDialog.Builder(context!!)
|
AlertDialog.Builder(requireContext())
|
||||||
.setTitle(R.string.feed_hide_streams_title)
|
.setTitle(R.string.feed_hide_streams_title)
|
||||||
.setMultiChoiceItems(dialogItems, checkedDialogItems) { _, which, isChecked ->
|
.setMultiChoiceItems(dialogItems, checkedDialogItems) { _, which, isChecked ->
|
||||||
checkedDialogItems[which] = isChecked
|
checkedDialogItems[which] = isChecked
|
||||||
|
|||||||
@@ -92,8 +92,10 @@ class NotificationHelper(val context: Context) {
|
|||||||
// Show individual stream notifications, set channel icon only if there is actually
|
// Show individual stream notifications, set channel icon only if there is actually
|
||||||
// one
|
// one
|
||||||
showStreamNotifications(newStreams, data.serviceId, data.url, bitmap)
|
showStreamNotifications(newStreams, data.serviceId, data.url, bitmap)
|
||||||
// Show summary notification
|
// Show summary notification if enabled
|
||||||
|
if (manager.areNotificationsEnabled()) {
|
||||||
manager.notify(data.pseudoId, summaryBuilder.build())
|
manager.notify(data.pseudoId, summaryBuilder.build())
|
||||||
|
}
|
||||||
|
|
||||||
iconLoadingTargets.remove(this) // allow it to be garbage-collected
|
iconLoadingTargets.remove(this) // allow it to be garbage-collected
|
||||||
}
|
}
|
||||||
@@ -101,8 +103,10 @@ class NotificationHelper(val context: Context) {
|
|||||||
override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) {
|
override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) {
|
||||||
// Show individual stream notifications
|
// Show individual stream notifications
|
||||||
showStreamNotifications(newStreams, data.serviceId, data.url, null)
|
showStreamNotifications(newStreams, data.serviceId, data.url, null)
|
||||||
// Show summary notification
|
// Show summary notification if enabled
|
||||||
|
if (manager.areNotificationsEnabled()) {
|
||||||
manager.notify(data.pseudoId, summaryBuilder.build())
|
manager.notify(data.pseudoId, summaryBuilder.build())
|
||||||
|
}
|
||||||
iconLoadingTargets.remove(this) // allow it to be garbage-collected
|
iconLoadingTargets.remove(this) // allow it to be garbage-collected
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,9 +130,11 @@ class NotificationHelper(val context: Context) {
|
|||||||
) {
|
) {
|
||||||
for (stream in newStreams) {
|
for (stream in newStreams) {
|
||||||
val notification = createStreamNotification(stream, serviceId, channelUrl, channelIcon)
|
val notification = createStreamNotification(stream, serviceId, channelUrl, channelIcon)
|
||||||
|
if (manager.areNotificationsEnabled()) {
|
||||||
manager.notify(stream.url.hashCode(), notification)
|
manager.notify(stream.url.hashCode(), notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createStreamNotification(
|
private fun createStreamNotification(
|
||||||
item: StreamInfoItem,
|
item: StreamInfoItem,
|
||||||
|
|||||||
@@ -185,8 +185,10 @@ class FeedLoadService : Service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// /////////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
// Notification Actions
|
// Notification Actions
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||||||
private fun hideKeyboardSearch() {
|
private fun hideKeyboardSearch() {
|
||||||
inputMethodManager.hideSoftInputFromWindow(
|
inputMethodManager.hideSoftInputFromWindow(
|
||||||
searchLayoutBinding.toolbarSearchEditText.windowToken,
|
searchLayoutBinding.toolbarSearchEditText.windowToken,
|
||||||
InputMethodManager.RESULT_UNCHANGED_SHOWN
|
InputMethodManager.HIDE_NOT_ALWAYS
|
||||||
)
|
)
|
||||||
searchLayoutBinding.toolbarSearchEditText.clearFocus()
|
searchLayoutBinding.toolbarSearchEditText.clearFocus()
|
||||||
}
|
}
|
||||||
@@ -523,7 +523,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||||||
private fun hideKeyboard() {
|
private fun hideKeyboard() {
|
||||||
inputMethodManager.hideSoftInputFromWindow(
|
inputMethodManager.hideSoftInputFromWindow(
|
||||||
feedGroupCreateBinding.groupNameInput.windowToken,
|
feedGroupCreateBinding.groupNameInput.windowToken,
|
||||||
InputMethodManager.RESULT_UNCHANGED_SHOWN
|
InputMethodManager.HIDE_NOT_ALWAYS
|
||||||
)
|
)
|
||||||
feedGroupCreateBinding.groupNameInput.clearFocus()
|
feedGroupCreateBinding.groupNameInput.clearFocus()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,8 +144,10 @@ public abstract class BaseImportExportService extends Service {
|
|||||||
notificationBuilder.setContentText(text);
|
notificationBuilder.setContentText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
notificationManager.notify(getNotificationId(), notificationBuilder.build());
|
notificationManager.notify(getNotificationId(), notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void stopService() {
|
protected void stopService() {
|
||||||
postErrorResult(null, null);
|
postErrorResult(null, null);
|
||||||
@@ -174,8 +176,11 @@ public abstract class BaseImportExportService extends Service {
|
|||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(textOrEmpty))
|
.setStyle(new NotificationCompat.BigTextStyle().bigText(textOrEmpty))
|
||||||
.setContentText(textOrEmpty);
|
.setContentText(textOrEmpty);
|
||||||
|
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
notificationManager.notify(getNotificationId(), notificationBuilder.build());
|
notificationManager.notify(getNotificationId(), notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected NotificationCompat.Builder createNotification() {
|
protected NotificationCompat.Builder createNotification() {
|
||||||
return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
|
return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
|
||||||
|
|||||||
@@ -127,36 +127,36 @@ public final class PlayQueueActivity extends AppCompatActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
final int itemId = item.getItemId();
|
||||||
case android.R.id.home:
|
if (itemId == android.R.id.home) {
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_settings:
|
} else if (itemId == R.id.action_settings) {
|
||||||
NavigationHelper.openSettings(this);
|
NavigationHelper.openSettings(this);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_append_playlist:
|
} else if (itemId == R.id.action_append_playlist) {
|
||||||
PlaylistDialog.showForPlayQueue(player, getSupportFragmentManager());
|
PlaylistDialog.showForPlayQueue(player, getSupportFragmentManager());
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_playback_speed:
|
} else if (itemId == R.id.action_playback_speed) {
|
||||||
openPlaybackParameterDialog();
|
openPlaybackParameterDialog();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_mute:
|
} else if (itemId == R.id.action_mute) {
|
||||||
player.toggleMute();
|
player.toggleMute();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_system_audio:
|
} else if (itemId == R.id.action_system_audio) {
|
||||||
startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
|
startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_switch_main:
|
} else if (itemId == R.id.action_switch_main) {
|
||||||
this.player.setRecovery();
|
this.player.setRecovery();
|
||||||
NavigationHelper.playOnMainPlayer(this, player.getPlayQueue(), true);
|
NavigationHelper.playOnMainPlayer(this, player.getPlayQueue(), true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_switch_popup:
|
} else if (itemId == R.id.action_switch_popup) {
|
||||||
if (PermissionHelper.isPopupEnabledElseAsk(this)) {
|
if (PermissionHelper.isPopupEnabledElseAsk(this)) {
|
||||||
this.player.setRecovery();
|
this.player.setRecovery();
|
||||||
NavigationHelper.playOnPopupPlayer(this, player.getPlayQueue(), true);
|
NavigationHelper.playOnPopupPlayer(this, player.getPlayQueue(), true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_switch_background:
|
} else if (itemId == R.id.action_switch_background) {
|
||||||
this.player.setRecovery();
|
this.player.setRecovery();
|
||||||
NavigationHelper.playOnBackgroundPlayer(this, player.getPlayQueue(), true);
|
NavigationHelper.playOnBackgroundPlayer(this, player.getPlayQueue(), true);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -72,8 +72,10 @@ public final class NotificationUtil {
|
|||||||
notificationBuilder = createNotification();
|
notificationBuilder = createNotification();
|
||||||
}
|
}
|
||||||
updateNotification();
|
updateNotification();
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void updateThumbnail() {
|
public synchronized void updateThumbnail() {
|
||||||
if (notificationBuilder != null) {
|
if (notificationBuilder != null) {
|
||||||
@@ -84,9 +86,11 @@ public final class NotificationUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLargeIcon(notificationBuilder);
|
setLargeIcon(notificationBuilder);
|
||||||
|
if (notificationManager.areNotificationsEnabled()) {
|
||||||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized NotificationCompat.Builder createNotification() {
|
private synchronized NotificationCompat.Builder createNotification() {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public final class KeyboardUtil {
|
|||||||
final InputMethodManager imm = ContextCompat.getSystemService(activity,
|
final InputMethodManager imm = ContextCompat.getSystemService(activity,
|
||||||
InputMethodManager.class);
|
InputMethodManager.class);
|
||||||
imm.hideSoftInputFromWindow(editText.getWindowToken(),
|
imm.hideSoftInputFromWindow(editText.getWindowToken(),
|
||||||
InputMethodManager.RESULT_UNCHANGED_SHOWN);
|
InputMethodManager.HIDE_NOT_ALWAYS);
|
||||||
|
|
||||||
editText.clearFocus();
|
editText.clearFocus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import android.view.Window;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.appcompat.view.WindowCallbackWrapper;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
@@ -232,7 +231,7 @@ public final class FocusOverlayView extends Drawable implements
|
|||||||
// Unfortunately many such forms of "scrolling" do not count as scrolling for purpose
|
// Unfortunately many such forms of "scrolling" do not count as scrolling for purpose
|
||||||
// of dispatching ViewTreeObserver callbacks, so we have to intercept them by directly
|
// of dispatching ViewTreeObserver callbacks, so we have to intercept them by directly
|
||||||
// receiving keys from Window.
|
// receiving keys from Window.
|
||||||
window.setCallback(new WindowCallbackWrapper(window.getCallback()) {
|
window.setCallback(new SimpleWindowCallback(window.getCallback()) {
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchKeyEvent(final KeyEvent event) {
|
public boolean dispatchKeyEvent(final KeyEvent event) {
|
||||||
final boolean res = super.dispatchKeyEvent(event);
|
final boolean res = super.dispatchKeyEvent(event);
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.schabi.newpipe.views
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.KeyboardShortcutGroup
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.Window
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
|
||||||
|
open class SimpleWindowCallback(private val baseCallback: Window.Callback) :
|
||||||
|
Window.Callback by baseCallback {
|
||||||
|
|
||||||
|
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
||||||
|
return baseCallback.dispatchKeyEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
override fun onPointerCaptureChanged(hasCapture: Boolean) {
|
||||||
|
baseCallback.onPointerCaptureChanged(hasCapture)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
|
override fun onProvideKeyboardShortcuts(
|
||||||
|
data: List<KeyboardShortcutGroup?>?,
|
||||||
|
menu: Menu?,
|
||||||
|
deviceId: Int
|
||||||
|
) {
|
||||||
|
baseCallback.onProvideKeyboardShortcuts(data, menu, deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_FORBIDDEN;
|
|||||||
* Single-threaded fallback mode
|
* Single-threaded fallback mode
|
||||||
*/
|
*/
|
||||||
public class DownloadRunnableFallback extends Thread {
|
public class DownloadRunnableFallback extends Thread {
|
||||||
private static final String TAG = "DownloadRunnableFallback";
|
private static final String TAG = DownloadRunnableFallback.class.getSimpleName();
|
||||||
|
|
||||||
private final DownloadMission mMission;
|
private final DownloadMission mMission;
|
||||||
|
|
||||||
|
|||||||
@@ -102,14 +102,23 @@ public class FinishedMissionStore extends SQLiteOpenHelper {
|
|||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(KEY_SOURCE, cursor.getString(cursor.getColumnIndex(KEY_SOURCE)));
|
values.put(
|
||||||
values.put(KEY_DONE, cursor.getString(cursor.getColumnIndex(KEY_DONE)));
|
KEY_SOURCE,
|
||||||
values.put(KEY_TIMESTAMP, cursor.getLong(cursor.getColumnIndex(KEY_TIMESTAMP)));
|
cursor.getString(cursor.getColumnIndexOrThrow(KEY_SOURCE))
|
||||||
values.put(KEY_KIND, cursor.getString(cursor.getColumnIndex(KEY_KIND)));
|
);
|
||||||
|
values.put(
|
||||||
|
KEY_DONE,
|
||||||
|
cursor.getString(cursor.getColumnIndexOrThrow(KEY_DONE))
|
||||||
|
);
|
||||||
|
values.put(
|
||||||
|
KEY_TIMESTAMP,
|
||||||
|
cursor.getLong(cursor.getColumnIndexOrThrow(KEY_TIMESTAMP))
|
||||||
|
);
|
||||||
|
values.put(KEY_KIND, cursor.getString(cursor.getColumnIndexOrThrow(KEY_KIND)));
|
||||||
values.put(KEY_PATH, Uri.fromFile(
|
values.put(KEY_PATH, Uri.fromFile(
|
||||||
new File(
|
new File(
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_LOCATION)),
|
cursor.getString(cursor.getColumnIndexOrThrow(KEY_LOCATION)),
|
||||||
cursor.getString(cursor.getColumnIndex(KEY_NAME))
|
cursor.getString(cursor.getColumnIndexOrThrow(KEY_NAME))
|
||||||
)
|
)
|
||||||
).toString());
|
).toString());
|
||||||
|
|
||||||
@@ -141,7 +150,8 @@ public class FinishedMissionStore extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private FinishedMission getMissionFromCursor(Cursor cursor) {
|
private FinishedMission getMissionFromCursor(Cursor cursor) {
|
||||||
String kind = Objects.requireNonNull(cursor).getString(cursor.getColumnIndex(KEY_KIND));
|
String kind = Objects.requireNonNull(cursor)
|
||||||
|
.getString(cursor.getColumnIndexOrThrow(KEY_KIND));
|
||||||
if (kind == null || kind.isEmpty()) kind = "?";
|
if (kind == null || kind.isEmpty()) kind = "?";
|
||||||
|
|
||||||
String path = cursor.getString(cursor.getColumnIndexOrThrow(KEY_PATH));
|
String path = cursor.getString(cursor.getColumnIndexOrThrow(KEY_PATH));
|
||||||
|
|||||||
@@ -632,24 +632,23 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
DownloadMission mission = h.item.mission instanceof DownloadMission ? (DownloadMission) h.item.mission : null;
|
DownloadMission mission = h.item.mission instanceof DownloadMission ? (DownloadMission) h.item.mission : null;
|
||||||
|
|
||||||
if (mission != null) {
|
if (mission != null) {
|
||||||
switch (id) {
|
if (id == R.id.start) {
|
||||||
case R.id.start:
|
|
||||||
h.status.setText(UNDEFINED_PROGRESS);
|
h.status.setText(UNDEFINED_PROGRESS);
|
||||||
mDownloadManager.resumeMission(mission);
|
mDownloadManager.resumeMission(mission);
|
||||||
return true;
|
return true;
|
||||||
case R.id.pause:
|
} else if (id == R.id.pause) {
|
||||||
mDownloadManager.pauseMission(mission);
|
mDownloadManager.pauseMission(mission);
|
||||||
return true;
|
return true;
|
||||||
case R.id.error_message_view:
|
} else if (id == R.id.error_message_view) {
|
||||||
showError(mission);
|
showError(mission);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue:
|
} else if (id == R.id.queue) {
|
||||||
boolean flag = !h.queue.isChecked();
|
boolean flag = !h.queue.isChecked();
|
||||||
h.queue.setChecked(flag);
|
h.queue.setChecked(flag);
|
||||||
mission.setEnqueued(flag);
|
mission.setEnqueued(flag);
|
||||||
updateProgress(h);
|
updateProgress(h);
|
||||||
return true;
|
return true;
|
||||||
case R.id.retry:
|
} else if (id == R.id.retry) {
|
||||||
if (mission.isPsRunning()) {
|
if (mission.isPsRunning()) {
|
||||||
mission.psContinue(true);
|
mission.psContinue(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -660,30 +659,26 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
recoverMission(mission);
|
recoverMission(mission);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.cancel:
|
} else if (id == R.id.cancel) {
|
||||||
mission.psContinue(false);
|
mission.psContinue(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (id) {
|
if (id == R.id.menu_item_share) {
|
||||||
case R.id.menu_item_share:
|
|
||||||
shareFile(h.item.mission);
|
shareFile(h.item.mission);
|
||||||
return true;
|
return true;
|
||||||
case R.id.delete:
|
} else if (id == R.id.delete) {// delete the entry and the file
|
||||||
// delete the entry and the file
|
|
||||||
mDeleter.append(h.item.mission, true);
|
mDeleter.append(h.item.mission, true);
|
||||||
applyChanges();
|
applyChanges();
|
||||||
checkMasterButtonsVisibility();
|
checkMasterButtonsVisibility();
|
||||||
return true;
|
return true;
|
||||||
case R.id.delete_entry:
|
} else if (id == R.id.delete_entry) {// just delete the entry
|
||||||
// just delete the entry
|
|
||||||
mDeleter.append(h.item.mission, false);
|
mDeleter.append(h.item.mission, false);
|
||||||
applyChanges();
|
applyChanges();
|
||||||
checkMasterButtonsVisibility();
|
checkMasterButtonsVisibility();
|
||||||
return true;
|
return true;
|
||||||
case R.id.md5:
|
} else if (id == R.id.md5 || id == R.id.sha1) {
|
||||||
case R.id.sha1:
|
|
||||||
final StoredFileHelper storage = h.item.mission.storage;
|
final StoredFileHelper storage = h.item.mission.storage;
|
||||||
if (!storage.existsAsFile()) {
|
if (!storage.existsAsFile()) {
|
||||||
Toast.makeText(mContext, R.string.missing_file, Toast.LENGTH_SHORT).show();
|
Toast.makeText(mContext, R.string.missing_file, Toast.LENGTH_SHORT).show();
|
||||||
@@ -715,9 +710,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
case R.id.source:
|
} else if (id == R.id.source) {
|
||||||
/*Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(h.item.mission.source));
|
|
||||||
mContext.startActivity(intent);*/
|
|
||||||
try {
|
try {
|
||||||
Intent intent = NavigationHelper.getIntentByLink(mContext, h.item.mission.source);
|
Intent intent = NavigationHelper.getIntentByLink(mContext, h.item.mission.source);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
|
||||||
@@ -726,9 +719,8 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
Log.w(TAG, "Selected item has a invalid source", e);
|
Log.w(TAG, "Selected item has a invalid source", e);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyChanges() {
|
public void applyChanges() {
|
||||||
|
|||||||
@@ -186,23 +186,24 @@ public class MissionsFragment extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
int itemId = item.getItemId();
|
||||||
case R.id.switch_mode:
|
if (itemId == R.id.switch_mode) {
|
||||||
mLinear = !mLinear;
|
mLinear = !mLinear;
|
||||||
updateList();
|
updateList();
|
||||||
return true;
|
return true;
|
||||||
case R.id.clear_list:
|
} else if (itemId == R.id.clear_list) {
|
||||||
showClearDownloadHistoryPrompt();
|
showClearDownloadHistoryPrompt();
|
||||||
return true;
|
return true;
|
||||||
case R.id.start_downloads:
|
} else if (itemId == R.id.start_downloads) {
|
||||||
mBinder.getDownloadManager().startAllMissions();
|
mBinder.getDownloadManager().startAllMissions();
|
||||||
return true;
|
return true;
|
||||||
case R.id.pause_downloads:
|
} else if (itemId == R.id.pause_downloads) {
|
||||||
mBinder.getDownloadManager().pauseAllMissions(false);
|
mBinder.getDownloadManager().pauseAllMissions(false);
|
||||||
mAdapter.refreshMissionItems();// update items view
|
mAdapter.refreshMissionItems();// update items view
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showClearDownloadHistoryPrompt() {
|
public void showClearDownloadHistoryPrompt() {
|
||||||
|
|||||||
@@ -5,6 +5,6 @@
|
|||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:tint="@color/defaultIconTint">
|
android:tint="@color/defaultIconTint">
|
||||||
<path
|
<path
|
||||||
android:pathData="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM9.5 16.5v-9l7 4.5-7 4.5z"
|
android:pathData="M20 4H4c-1.1 0-2 0.9-2 2v12c0 1.1 0.9 2 2 2h16c1.1 0 2-0.9 2-2V6c0-1.1-0.9-2-2-2zM9.5 16.5v-9l7 4.5-7 4.5z"
|
||||||
android:fillColor="#FF000000"/>
|
android:fillColor="#FF000000"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -122,8 +122,8 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/exo_controls_rewind"
|
android:src="@drawable/exo_controls_rewind"
|
||||||
android:tint="?attr/colorAccent"
|
android:contentDescription="@string/rewind"
|
||||||
android:contentDescription="@string/rewind" />
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/control_play_pause"
|
android:id="@+id/control_play_pause"
|
||||||
@@ -139,8 +139,8 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/ic_pause"
|
android:src="@drawable/ic_pause"
|
||||||
android:tint="?attr/colorAccent"
|
android:contentDescription="@string/pause"
|
||||||
android:contentDescription="@string/pause" />
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/control_progress_bar"
|
android:id="@+id/control_progress_bar"
|
||||||
@@ -172,8 +172,8 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/exo_controls_fastforward"
|
android:src="@drawable/exo_controls_fastforward"
|
||||||
android:tint="?attr/colorAccent"
|
android:contentDescription="@string/forward"
|
||||||
android:contentDescription="@string/forward" />
|
app:tint="?attr/colorAccent" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
@@ -215,8 +215,8 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
android:tint="?attr/colorAccent"
|
android:contentDescription="@string/notification_action_repeat"
|
||||||
android:contentDescription="@string/notification_action_repeat" />
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/anchor"
|
android:id="@+id/anchor"
|
||||||
@@ -236,8 +236,8 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
android:tint="?attr/colorAccent"
|
android:contentDescription="@string/notification_action_shuffle"
|
||||||
android:contentDescription="@string/notification_action_shuffle" />
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageButton
|
<androidx.appcompat.widget.AppCompatImageButton
|
||||||
android:id="@+id/control_forward"
|
android:id="@+id/control_forward"
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:src="@drawable/ic_repeat"
|
android:src="@drawable/ic_repeat"
|
||||||
android:tint="?attr/colorAccent"
|
app:tint="?attr/colorAccent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageButton
|
<androidx.appcompat.widget.AppCompatImageButton
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/exo_controls_rewind"
|
android:src="@drawable/exo_controls_rewind"
|
||||||
android:tint="?attr/colorAccent" />
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/control_play_pause"
|
android:id="@+id/control_play_pause"
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/ic_pause"
|
android:src="@drawable/ic_pause"
|
||||||
android:tint="?attr/colorAccent"
|
app:tint="?attr/colorAccent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/exo_controls_fastforward"
|
android:src="@drawable/exo_controls_fastforward"
|
||||||
android:tint="?attr/colorAccent" />
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageButton
|
<androidx.appcompat.widget.AppCompatImageButton
|
||||||
android:id="@+id/control_forward"
|
android:id="@+id/control_forward"
|
||||||
@@ -285,7 +285,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:src="@drawable/ic_shuffle"
|
android:src="@drawable/ic_shuffle"
|
||||||
android:tint="?attr/colorAccent"
|
app:tint="?attr/colorAccent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@@ -309,6 +309,6 @@
|
|||||||
<string name="notification_action_nothing">কিছু না</string>
|
<string name="notification_action_nothing">কিছু না</string>
|
||||||
<string name="yes">হ্যাঁ</string>
|
<string name="yes">হ্যাঁ</string>
|
||||||
<string name="no">না</string>
|
<string name="no">না</string>
|
||||||
<string name="search_with_service_name">সার্চ</string>
|
<string name="search_with_service_name">সার্চ %1$s</string>
|
||||||
<string name="search_with_service_name_and_filter">খুঁজুন</string>
|
<string name="search_with_service_name_and_filter">খুঁজুন %1$s (%2$s)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
android.nonFinalResIds=false
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
org.gradle.jvmargs=-Xmx2048M --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
|
org.gradle.jvmargs=-Xmx2048M --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
|
||||||
systemProp.file.encoding=utf-8
|
systemProp.file.encoding=utf-8
|
||||||
|
|||||||
Reference in New Issue
Block a user