mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-10 23:05:59 +00:00
Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts: # app/src/main/AndroidManifest.xml
This commit is contained in:
@@ -435,6 +435,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<service
|
<service
|
||||||
android:name=".RouterActivity$FetcherService"
|
android:name=".RouterActivity$FetcherService"
|
||||||
|
android:foregroundServiceType="dataSync"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<!-- opting out of sending metrics to Google in Android System WebView -->
|
<!-- opting out of sending metrics to Google in Android System WebView -->
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package org.schabi.newpipe.local.feed.notifications
|
package org.schabi.newpipe.local.feed.notifications
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.ServiceInfo
|
||||||
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.work.Constraints
|
import androidx.work.Constraints
|
||||||
@@ -83,7 +85,9 @@ class NotificationWorker(
|
|||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
.setContentTitle(applicationContext.getString(R.string.feed_notification_loading))
|
.setContentTitle(applicationContext.getString(R.string.feed_notification_loading))
|
||||||
.build()
|
.build()
|
||||||
setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification))
|
// ServiceInfo constants are not used below Android Q, so 0 is set here
|
||||||
|
val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0
|
||||||
|
setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification, serviceType))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@@ -167,19 +167,17 @@ public final class NotificationUtil {
|
|||||||
&& notificationBuilder.mActions.get(2).actionIntent != null);
|
&& notificationBuilder.mActions.get(2).actionIntent != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void createNotificationAndStartForeground() {
|
public void createNotificationAndStartForeground() {
|
||||||
if (notificationBuilder == null) {
|
if (notificationBuilder == null) {
|
||||||
notificationBuilder = createNotification();
|
notificationBuilder = createNotification();
|
||||||
}
|
}
|
||||||
updateNotification();
|
updateNotification();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
// ServiceInfo constants are not used below Android Q, so 0 is set here
|
||||||
player.getService().startForeground(NOTIFICATION_ID, notificationBuilder.build(),
|
final int serviceType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
? ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK : 0;
|
||||||
} else {
|
ServiceCompat.startForeground(player.getService(), NOTIFICATION_ID,
|
||||||
player.getService().startForeground(NOTIFICATION_ID, notificationBuilder.build());
|
notificationBuilder.build(), serviceType);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelNotificationAndStopForeground() {
|
public void cancelNotificationAndStopForeground() {
|
||||||
|
@@ -9,9 +9,11 @@ import android.content.pm.PackageManager;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.text.Html;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
@@ -113,14 +115,47 @@ public final class PermissionHelper {
|
|||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
public static boolean checkSystemAlertWindowPermission(final Context context) {
|
public static boolean checkSystemAlertWindowPermission(final Context context) {
|
||||||
if (!Settings.canDrawOverlays(context)) {
|
if (!Settings.canDrawOverlays(context)) {
|
||||||
final Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
Uri.parse("package:" + context.getPackageName()));
|
final Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
Uri.parse("package:" + context.getPackageName()));
|
||||||
try {
|
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
context.startActivity(i);
|
try {
|
||||||
} catch (final ActivityNotFoundException ignored) {
|
context.startActivity(i);
|
||||||
|
} catch (final ActivityNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
// from Android R the ACTION_MANAGE_OVERLAY_PERMISSION will only point to the menu,
|
||||||
|
// so let’s add a dialog that points the user to the right setting.
|
||||||
|
} else {
|
||||||
|
final String appName = context.getApplicationInfo()
|
||||||
|
.loadLabel(context.getPackageManager()).toString();
|
||||||
|
final String title = context.getString(R.string.permission_display_over_apps);
|
||||||
|
final String permissionName =
|
||||||
|
context.getString(R.string.permission_display_over_apps_permission_name);
|
||||||
|
final String appNameItalic = "<i>" + appName + "</i>";
|
||||||
|
final String permissionNameItalic = "<i>" + permissionName + "</i>";
|
||||||
|
final String message =
|
||||||
|
context.getString(R.string.permission_display_over_apps_message,
|
||||||
|
appNameItalic,
|
||||||
|
permissionNameItalic
|
||||||
|
);
|
||||||
|
new AlertDialog.Builder(context)
|
||||||
|
.setTitle(title)
|
||||||
|
.setMessage(Html.fromHtml(message, Html.FROM_HTML_MODE_COMPACT))
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> {
|
||||||
|
// we don’t need the package name here, since it won’t do anything on >R
|
||||||
|
final Intent intent =
|
||||||
|
new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
|
||||||
|
try {
|
||||||
|
context.startActivity(intent);
|
||||||
|
} catch (final ActivityNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setCancelable(true)
|
||||||
|
.show();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -265,7 +265,7 @@ public class DownloadManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteMission(Mission mission) {
|
public void deleteMission(Mission mission, boolean alsoDeleteFile) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (mission instanceof DownloadMission) {
|
if (mission instanceof DownloadMission) {
|
||||||
mMissionsPending.remove(mission);
|
mMissionsPending.remove(mission);
|
||||||
@@ -274,7 +274,9 @@ public class DownloadManager {
|
|||||||
mFinishedMissionStore.deleteMission(mission);
|
mFinishedMissionStore.deleteMission(mission);
|
||||||
}
|
}
|
||||||
|
|
||||||
mission.delete();
|
if (alsoDeleteFile) {
|
||||||
|
mission.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -614,7 +614,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
Mission mission = i.next();
|
Mission mission = i.next();
|
||||||
if (mission != null) {
|
if (mission != null) {
|
||||||
mDownloadManager.deleteMission(mission);
|
mDownloadManager.deleteMission(mission, true);
|
||||||
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri()));
|
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri()));
|
||||||
}
|
}
|
||||||
i.remove();
|
i.remove();
|
||||||
@@ -667,7 +667,14 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
shareFile(h.item.mission);
|
shareFile(h.item.mission);
|
||||||
return true;
|
return true;
|
||||||
case R.id.delete:
|
case R.id.delete:
|
||||||
mDeleter.append(h.item.mission);
|
// delete the entry and the file
|
||||||
|
mDeleter.append(h.item.mission, true);
|
||||||
|
applyChanges();
|
||||||
|
checkMasterButtonsVisibility();
|
||||||
|
return true;
|
||||||
|
case R.id.delete_entry:
|
||||||
|
// just delete the entry
|
||||||
|
mDeleter.append(h.item.mission, false);
|
||||||
applyChanges();
|
applyChanges();
|
||||||
checkMasterButtonsVisibility();
|
checkMasterButtonsVisibility();
|
||||||
return true;
|
return true;
|
||||||
@@ -676,7 +683,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
|
|||||||
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();
|
||||||
mDeleter.append(h.item.mission);
|
mDeleter.append(h.item.mission, true);
|
||||||
applyChanges();
|
applyChanges();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,9 @@ import com.google.android.material.snackbar.Snackbar;
|
|||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import kotlin.Pair;
|
||||||
import us.shandian.giga.get.FinishedMission;
|
import us.shandian.giga.get.FinishedMission;
|
||||||
import us.shandian.giga.get.Mission;
|
import us.shandian.giga.get.Mission;
|
||||||
import us.shandian.giga.service.DownloadManager;
|
import us.shandian.giga.service.DownloadManager;
|
||||||
@@ -30,7 +32,8 @@ public class Deleter {
|
|||||||
private static final int DELAY_RESUME = 400;// ms
|
private static final int DELAY_RESUME = 400;// ms
|
||||||
|
|
||||||
private Snackbar snackbar;
|
private Snackbar snackbar;
|
||||||
private ArrayList<Mission> items;
|
// list of missions to be deleted, and whether to also delete the corresponding file
|
||||||
|
private ArrayList<Pair<Mission, Boolean>> items;
|
||||||
private boolean running = true;
|
private boolean running = true;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -51,7 +54,7 @@ public class Deleter {
|
|||||||
items = new ArrayList<>(2);
|
items = new ArrayList<>(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void append(Mission item) {
|
public void append(Mission item, boolean alsoDeleteFile) {
|
||||||
/* If a mission is removed from the list while the Snackbar for a previously
|
/* If a mission is removed from the list while the Snackbar for a previously
|
||||||
* removed item is still showing, commit the action for the previous item
|
* removed item is still showing, commit the action for the previous item
|
||||||
* immediately. This prevents Snackbars from stacking up in reverse order.
|
* immediately. This prevents Snackbars from stacking up in reverse order.
|
||||||
@@ -60,13 +63,13 @@ public class Deleter {
|
|||||||
commit();
|
commit();
|
||||||
|
|
||||||
mIterator.hide(item);
|
mIterator.hide(item);
|
||||||
items.add(0, item);
|
items.add(0, new Pair<>(item, alsoDeleteFile));
|
||||||
|
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forget() {
|
private void forget() {
|
||||||
mIterator.unHide(items.remove(0));
|
mIterator.unHide(items.remove(0).getFirst());
|
||||||
mAdapter.applyChanges();
|
mAdapter.applyChanges();
|
||||||
|
|
||||||
show();
|
show();
|
||||||
@@ -84,7 +87,19 @@ public class Deleter {
|
|||||||
private void next() {
|
private void next() {
|
||||||
if (items.size() < 1) return;
|
if (items.size() < 1) return;
|
||||||
|
|
||||||
String msg = mContext.getString(R.string.file_deleted).concat(":\n").concat(items.get(0).storage.getName());
|
final Optional<String> fileToBeDeleted = items.stream()
|
||||||
|
.filter(Pair::getSecond)
|
||||||
|
.map(p -> p.getFirst().storage.getName())
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
String msg;
|
||||||
|
if (fileToBeDeleted.isPresent()) {
|
||||||
|
msg = mContext.getString(R.string.file_deleted)
|
||||||
|
.concat(":\n")
|
||||||
|
.concat(fileToBeDeleted.get());
|
||||||
|
} else {
|
||||||
|
msg = mContext.getString(R.string.entry_deleted);
|
||||||
|
}
|
||||||
|
|
||||||
snackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE);
|
snackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE);
|
||||||
snackbar.setAction(R.string.undo, s -> forget());
|
snackbar.setAction(R.string.undo, s -> forget());
|
||||||
@@ -98,11 +113,13 @@ public class Deleter {
|
|||||||
if (items.size() < 1) return;
|
if (items.size() < 1) return;
|
||||||
|
|
||||||
while (items.size() > 0) {
|
while (items.size() > 0) {
|
||||||
Mission mission = items.remove(0);
|
Pair<Mission, Boolean> missionAndAlsoDeleteFile = items.remove(0);
|
||||||
|
Mission mission = missionAndAlsoDeleteFile.getFirst();
|
||||||
|
boolean alsoDeleteFile = missionAndAlsoDeleteFile.getSecond();
|
||||||
if (mission.deleted) continue;
|
if (mission.deleted) continue;
|
||||||
|
|
||||||
mIterator.unHide(mission);
|
mIterator.unHide(mission);
|
||||||
mDownloadManager.deleteMission(mission);
|
mDownloadManager.deleteMission(mission, alsoDeleteFile);
|
||||||
|
|
||||||
if (mission instanceof FinishedMission) {
|
if (mission instanceof FinishedMission) {
|
||||||
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri()));
|
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri()));
|
||||||
@@ -137,7 +154,11 @@ public class Deleter {
|
|||||||
|
|
||||||
pause();
|
pause();
|
||||||
|
|
||||||
for (Mission mission : items) mDownloadManager.deleteMission(mission);
|
for (Pair<Mission, Boolean> missionAndAlsoDeleteFile : items) {
|
||||||
|
Mission mission = missionAndAlsoDeleteFile.getFirst();
|
||||||
|
boolean alsoDeleteFile = missionAndAlsoDeleteFile.getSecond();
|
||||||
|
mDownloadManager.deleteMission(mission, alsoDeleteFile);
|
||||||
|
}
|
||||||
items = null;
|
items = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,11 @@
|
|||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
android:title="@string/delete" />
|
android:title="@string/delete_file" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/delete_entry"
|
||||||
|
android:title="@string/delete_entry" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/error_message_view"
|
android:id="@+id/error_message_view"
|
||||||
|
@@ -257,6 +257,8 @@
|
|||||||
<string name="restore_defaults">Restore defaults</string>
|
<string name="restore_defaults">Restore defaults</string>
|
||||||
<string name="restore_defaults_confirmation">Do you want to restore defaults?</string>
|
<string name="restore_defaults_confirmation">Do you want to restore defaults?</string>
|
||||||
<string name="permission_display_over_apps">Give permission to display over other apps</string>
|
<string name="permission_display_over_apps">Give permission to display over other apps</string>
|
||||||
|
<string name="permission_display_over_apps_message">In order to use the Popup Player, please select %1$s in the following Android settings menu and enable %2$s.</string>
|
||||||
|
<string name="permission_display_over_apps_permission_name">“Allow display over other apps”</string>
|
||||||
<!-- error activity -->
|
<!-- error activity -->
|
||||||
<string name="error_report_notification_title">NewPipe encountered an error, tap to report</string>
|
<string name="error_report_notification_title">NewPipe encountered an error, tap to report</string>
|
||||||
<string name="error_report_notification_toast">An error occurred, see the notification</string>
|
<string name="error_report_notification_toast">An error occurred, see the notification</string>
|
||||||
@@ -333,6 +335,8 @@
|
|||||||
<string name="pause">Pause</string>
|
<string name="pause">Pause</string>
|
||||||
<string name="create">Create</string>
|
<string name="create">Create</string>
|
||||||
<string name="delete">Delete</string>
|
<string name="delete">Delete</string>
|
||||||
|
<string name="delete_file">Delete file</string>
|
||||||
|
<string name="delete_entry">Delete entry</string>
|
||||||
<string name="checksum">Checksum</string>
|
<string name="checksum">Checksum</string>
|
||||||
<string name="dismiss">Dismiss</string>
|
<string name="dismiss">Dismiss</string>
|
||||||
<string name="rename">Rename</string>
|
<string name="rename">Rename</string>
|
||||||
@@ -889,4 +893,5 @@
|
|||||||
<string name="trending_podcasts">Trending podcasts</string>
|
<string name="trending_podcasts">Trending podcasts</string>
|
||||||
<string name="trending_movies">Trending movies and shows</string>
|
<string name="trending_movies">Trending movies and shows</string>
|
||||||
<string name="trending_music">Trending music</string>
|
<string name="trending_music">Trending music</string>
|
||||||
|
<string name="entry_deleted">Entry deleted</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Reference in New Issue
Block a user