mirror of
https://github.com/MaintainTeam/LastPipeBender.git
synced 2025-03-04 15:28:21 +03:00
SponsorBlock: Added segment categories
Added category preferences with customizable colors. Also did some related preference/strings refactoring and updated the API calls to SponsorBlock to no longer use legacy versions.
This commit is contained in:
parent
ed831376ff
commit
a029c0ef9e
14 changed files with 508 additions and 147 deletions
|
@ -4,18 +4,21 @@ import android.app.Application;
|
|||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonParser;
|
||||
|
||||
import org.schabi.newpipe.util.SponsorTimeInfo;
|
||||
import org.schabi.newpipe.util.TimeFrame;
|
||||
import org.schabi.newpipe.util.VideoSegment;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class SponsorBlockApiTask extends AsyncTask<String, Void, JsonObject> {
|
||||
public class SponsorBlockApiTask extends AsyncTask<String, Void, JsonArray> {
|
||||
private static final Application APP = App.getApp();
|
||||
private String apiUrl;
|
||||
private static final String TAG = SponsorBlockApiTask.class.getSimpleName();
|
||||
|
@ -25,30 +28,67 @@ public class SponsorBlockApiTask extends AsyncTask<String, Void, JsonObject> {
|
|||
this.apiUrl = apiUrl;
|
||||
}
|
||||
|
||||
public SponsorTimeInfo getYouTubeVideoSponsorTimes(final String videoId)
|
||||
throws ExecutionException, InterruptedException {
|
||||
public VideoSegment[] getYouTubeVideoSegments(final String videoId,
|
||||
final boolean includeSponsorCategory,
|
||||
final boolean includeIntroCategory,
|
||||
final boolean includeOutroCategory,
|
||||
final boolean includeInteractionCategory,
|
||||
final boolean includeSelfPromoCategory,
|
||||
final boolean includeMusicCategory)
|
||||
throws ExecutionException, InterruptedException, UnsupportedEncodingException {
|
||||
|
||||
JsonObject obj = execute("getVideoSponsorTimes?videoID=" + videoId).get();
|
||||
JsonArray arrayObj = obj.getArray("sponsorTimes");
|
||||
ArrayList<String> categoryParamList = new ArrayList<>();
|
||||
|
||||
SponsorTimeInfo result = new SponsorTimeInfo();
|
||||
|
||||
for (int i = 0; i < arrayObj.size(); i++) {
|
||||
JsonArray subArrayObj = arrayObj.getArray(i);
|
||||
|
||||
double startTime = subArrayObj.getDouble(0) * 1000;
|
||||
double endTime = subArrayObj.getDouble(1) * 1000;
|
||||
|
||||
TimeFrame timeFrame = new TimeFrame(startTime, endTime);
|
||||
|
||||
result.timeFrames.add(timeFrame);
|
||||
if (includeSponsorCategory) {
|
||||
categoryParamList.add("sponsor");
|
||||
}
|
||||
if (includeIntroCategory) {
|
||||
categoryParamList.add("intro");
|
||||
}
|
||||
if (includeOutroCategory) {
|
||||
categoryParamList.add("outro");
|
||||
}
|
||||
if (includeInteractionCategory) {
|
||||
categoryParamList.add("interaction");
|
||||
}
|
||||
if (includeSelfPromoCategory) {
|
||||
categoryParamList.add("selfpromo");
|
||||
}
|
||||
if (includeMusicCategory) {
|
||||
categoryParamList.add("music_offtopic");
|
||||
}
|
||||
|
||||
return result;
|
||||
if (categoryParamList.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String categoryParams = "[\"" + TextUtils.join("\",\"", categoryParamList) + "\"]";
|
||||
categoryParams = URLEncoder.encode(categoryParams, "utf-8");
|
||||
|
||||
String params = "skipSegments?videoID=" + videoId + "&categories=" + categoryParams;
|
||||
|
||||
JsonArray arrayObj = execute(params).get();
|
||||
|
||||
ArrayList<VideoSegment> result = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < arrayObj.size(); i++) {
|
||||
JsonObject obj = (JsonObject) arrayObj.get(i);
|
||||
JsonArray segments = (JsonArray) obj.get("segment");
|
||||
|
||||
double startTime = segments.getDouble(0) * 1000;
|
||||
double endTime = segments.getDouble(1) * 1000;
|
||||
String category = obj.getString("category");
|
||||
|
||||
VideoSegment segment = new VideoSegment(startTime, endTime, category);
|
||||
|
||||
result.add(segment);
|
||||
}
|
||||
|
||||
return result.toArray(new VideoSegment[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsonObject doInBackground(final String... strings) {
|
||||
protected JsonArray doInBackground(final String... strings) {
|
||||
if (isCancelled() || !isConnected()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -60,7 +100,7 @@ public class SponsorBlockApiTask extends AsyncTask<String, Void, JsonObject> {
|
|||
.get(apiUrl + strings[0])
|
||||
.responseBody();
|
||||
|
||||
return JsonParser.object().from(responseBody);
|
||||
return JsonParser.array().from(responseBody);
|
||||
|
||||
} catch (Exception ex) {
|
||||
if (DEBUG) {
|
||||
|
|
|
@ -77,7 +77,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
|||
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.SerializedCache;
|
||||
import org.schabi.newpipe.util.SponsorTimeInfo;
|
||||
import org.schabi.newpipe.util.VideoSegment;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -114,9 +114,9 @@ public abstract class BasePlayer implements
|
|||
public static final int STATE_COMPLETED = 128;
|
||||
|
||||
@NonNull
|
||||
private final SharedPreferences mPrefs;
|
||||
protected final SharedPreferences mPrefs;
|
||||
|
||||
private SponsorTimeInfo sponsorTimeInfo;
|
||||
private VideoSegment[] videoSegments;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Intent
|
||||
|
@ -716,9 +716,8 @@ public abstract class BasePlayer implements
|
|||
simpleExoPlayer.getBufferedPercentage()
|
||||
);
|
||||
|
||||
if (mPrefs.getBoolean(context.getString(R.string.sponsorblock_enable), false)
|
||||
&& sponsorTimeInfo != null) {
|
||||
int skipTo = sponsorTimeInfo.getSponsorEndTimeFromProgress(currentProgress);
|
||||
if (mPrefs.getBoolean(context.getString(R.string.sponsorblock_enable_key), false)) {
|
||||
int skipTo = getSponsorEndTimeFromProgress(currentProgress);
|
||||
|
||||
if (skipTo == 0) {
|
||||
return;
|
||||
|
@ -726,8 +725,9 @@ public abstract class BasePlayer implements
|
|||
|
||||
seekTo(skipTo);
|
||||
|
||||
if (mPrefs.getBoolean(context.getString(R.string.sponsorblock_notifications), false)) {
|
||||
String toastText = context.getString(R.string.sponsorblock_skipped_sponsor);
|
||||
if (mPrefs.getBoolean(
|
||||
context.getString(R.string.sponsorblock_notifications_key), false)) {
|
||||
String toastText = context.getString(R.string.sponsorblock_skipped_segment);
|
||||
Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
|
@ -738,6 +738,26 @@ public abstract class BasePlayer implements
|
|||
}
|
||||
}
|
||||
|
||||
private int getSponsorEndTimeFromProgress(final int progress) {
|
||||
if (videoSegments == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (VideoSegment segment : videoSegments) {
|
||||
if (progress < segment.startTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (progress > segment.endTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return (int) Math.ceil((segment.endTime));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private Disposable getProgressReactor() {
|
||||
return Observable.interval(PROGRESS_LOOP_INTERVAL_MILLIS, MILLISECONDS, mainThread())
|
||||
.observeOn(mainThread())
|
||||
|
@ -1101,14 +1121,56 @@ public abstract class BasePlayer implements
|
|||
|
||||
if (info.getUrl().startsWith("https://www.youtube.com")) {
|
||||
String apiUrl = mPrefs
|
||||
.getString(context.getString(R.string.sponsorblock_api_url), null);
|
||||
.getString(context.getString(R.string.sponsorblock_api_url_key), null);
|
||||
boolean isSponsorBlockEnabled = mPrefs
|
||||
.getBoolean(context.getString(R.string.sponsorblock_enable), false);
|
||||
.getBoolean(context.getString(R.string.sponsorblock_enable_key), false);
|
||||
|
||||
if (apiUrl != null && !apiUrl.isEmpty() && isSponsorBlockEnabled) {
|
||||
try {
|
||||
sponsorTimeInfo = new SponsorBlockApiTask(apiUrl)
|
||||
.getYouTubeVideoSponsorTimes(info.getId());
|
||||
boolean includeSponsorCategory =
|
||||
mPrefs.getBoolean(
|
||||
context.getString(
|
||||
R.string.sponsorblock_category_sponsor_key),
|
||||
false);
|
||||
|
||||
boolean includeIntroCategory =
|
||||
mPrefs.getBoolean(
|
||||
context.getString(
|
||||
R.string.sponsorblock_category_intro_key),
|
||||
false);
|
||||
|
||||
boolean includeOutroCategory =
|
||||
mPrefs.getBoolean(
|
||||
context.getString(
|
||||
R.string.sponsorblock_category_outro_key),
|
||||
false);
|
||||
|
||||
boolean includeInteractionCategory =
|
||||
mPrefs.getBoolean(
|
||||
context.getString(
|
||||
R.string.sponsorblock_category_interaction_key),
|
||||
false);
|
||||
|
||||
boolean includeSelfPromoCategory =
|
||||
mPrefs.getBoolean(
|
||||
context.getString(
|
||||
R.string.sponsorblock_category_self_promo_key),
|
||||
false);
|
||||
|
||||
boolean includeMusicCategory =
|
||||
mPrefs.getBoolean(
|
||||
context.getString(
|
||||
R.string.sponsorblock_category_music_key),
|
||||
false);
|
||||
|
||||
videoSegments = new SponsorBlockApiTask(apiUrl)
|
||||
.getYouTubeVideoSegments(info.getId(),
|
||||
includeSponsorCategory,
|
||||
includeIntroCategory,
|
||||
includeOutroCategory,
|
||||
includeInteractionCategory,
|
||||
includeSelfPromoCategory,
|
||||
includeMusicCategory);
|
||||
} catch (Exception e) {
|
||||
Log.e("SPONSOR_BLOCK", "Error getting YouTube video sponsor times.", e);
|
||||
}
|
||||
|
@ -1653,11 +1715,7 @@ public abstract class BasePlayer implements
|
|||
&& prefs.getBoolean(context.getString(R.string.enable_playback_resume_key), true);
|
||||
}
|
||||
|
||||
public SponsorTimeInfo getSponsorTimeInfo() {
|
||||
return sponsorTimeInfo;
|
||||
}
|
||||
|
||||
public void setSponsorTimeInfo(final SponsorTimeInfo sponsorTimeInfo) {
|
||||
this.sponsorTimeInfo = sponsorTimeInfo;
|
||||
public VideoSegment[] getVideoSegments() {
|
||||
return videoSegments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,9 +69,8 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
|||
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
||||
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
||||
import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.VideoSegment;
|
||||
import org.schabi.newpipe.views.ExpandableSurfaceView;
|
||||
import org.schabi.newpipe.util.SponsorTimeInfo;
|
||||
import org.schabi.newpipe.util.TimeFrame;
|
||||
import org.schabi.newpipe.views.MarkableSeekBar;
|
||||
import org.schabi.newpipe.views.SeekBarMarker;
|
||||
|
||||
|
@ -625,9 +624,9 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
}
|
||||
|
||||
private void markSponsorTimes() {
|
||||
SponsorTimeInfo sponsorTimeInfo = getSponsorTimeInfo();
|
||||
VideoSegment[] segments = getVideoSegments();
|
||||
|
||||
if (sponsorTimeInfo == null) {
|
||||
if (segments == null || segments.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -637,10 +636,17 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
|
||||
MarkableSeekBar markableSeekBar = (MarkableSeekBar) playbackSeekBar;
|
||||
|
||||
for (TimeFrame timeFrame : sponsorTimeInfo.timeFrames) {
|
||||
for (VideoSegment segment : segments) {
|
||||
Integer color = parseSegmentCategory(segment.category);
|
||||
|
||||
// if null, then this category should not be marked
|
||||
if (color == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SeekBarMarker seekBarMarker =
|
||||
new SeekBarMarker(timeFrame.startTime, timeFrame.endTime,
|
||||
(int) simpleExoPlayer.getDuration(), Color.GREEN);
|
||||
new SeekBarMarker(segment.startTime, segment.endTime,
|
||||
(int) simpleExoPlayer.getDuration(), color);
|
||||
markableSeekBar.seekBarMarkers.add(seekBarMarker);
|
||||
markableSeekBar.invalidate();
|
||||
|
||||
|
@ -649,6 +655,75 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
}
|
||||
}
|
||||
|
||||
private Integer parseSegmentCategory(final String category) {
|
||||
String key;
|
||||
String colorStr;
|
||||
switch (category) {
|
||||
case "sponsor":
|
||||
key = context.getString(R.string.sponsorblock_category_sponsor_key);
|
||||
if (mPrefs.getBoolean(key, false)) {
|
||||
key = context.getString(R.string.sponsorblock_category_sponsor_color_key);
|
||||
colorStr = mPrefs.getString(key, null);
|
||||
return colorStr == null
|
||||
? context.getResources().getColor(R.color.sponsor_segment)
|
||||
: Color.parseColor(colorStr);
|
||||
}
|
||||
break;
|
||||
case "intro":
|
||||
key = context.getString(R.string.sponsorblock_category_intro_key);
|
||||
if (mPrefs.getBoolean(key, false)) {
|
||||
key = context.getString(R.string.sponsorblock_category_intro_color_key);
|
||||
colorStr = mPrefs.getString(key, null);
|
||||
return colorStr == null
|
||||
? context.getResources().getColor(R.color.intro_segment)
|
||||
: Color.parseColor(colorStr);
|
||||
}
|
||||
break;
|
||||
case "outro":
|
||||
key = context.getString(R.string.sponsorblock_category_outro_key);
|
||||
if (mPrefs.getBoolean(key, false)) {
|
||||
key = context.getString(R.string.sponsorblock_category_outro_color_key);
|
||||
colorStr = mPrefs.getString(key, null);
|
||||
return colorStr == null
|
||||
? context.getResources().getColor(R.color.outro_segment)
|
||||
: Color.parseColor(colorStr);
|
||||
}
|
||||
break;
|
||||
case "interaction":
|
||||
key = context.getString(R.string.sponsorblock_category_interaction_key);
|
||||
if (mPrefs.getBoolean(key, false)) {
|
||||
key = context.getString(R.string.sponsorblock_category_interaction_color_key);
|
||||
colorStr = mPrefs.getString(key, null);
|
||||
return colorStr == null
|
||||
? context.getResources().getColor(R.color.interaction_segment)
|
||||
: Color.parseColor(colorStr);
|
||||
}
|
||||
break;
|
||||
case "selfpromo":
|
||||
key = context.getString(R.string.sponsorblock_category_self_promo_key);
|
||||
if (mPrefs.getBoolean(key, false)) {
|
||||
key = context.getString(R.string.sponsorblock_category_self_promo_color_key);
|
||||
colorStr = mPrefs.getString(key, null);
|
||||
return colorStr == null
|
||||
? context.getResources().getColor(R.color.self_promo_segment)
|
||||
: Color.parseColor(colorStr);
|
||||
}
|
||||
break;
|
||||
case "music_offtopic":
|
||||
key = context.getString(R.string.sponsorblock_category_music_key);
|
||||
if (mPrefs.getBoolean(key, false)) {
|
||||
key = context.getString(R.string.sponsorblock_category_music_color_key);
|
||||
colorStr = mPrefs.getString(key, null);
|
||||
return colorStr == null
|
||||
? context.getResources().getColor(R.color.music_offtopic_segment)
|
||||
: Color.parseColor(colorStr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
|
|
@ -82,17 +82,20 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(final Preference preference) {
|
||||
if (preference.getKey().equals(thumbnailLoadToggleKey)) {
|
||||
String key = preference.getKey();
|
||||
if (key != null) {
|
||||
if (key.equals(thumbnailLoadToggleKey)) {
|
||||
final ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
imageLoader.stop();
|
||||
imageLoader.clearDiskCache();
|
||||
imageLoader.clearMemoryCache();
|
||||
imageLoader.resume();
|
||||
Toast.makeText(preference.getContext(), R.string.thumbnail_cache_wipe_complete_notice,
|
||||
Toast.makeText(preference.getContext(),
|
||||
R.string.thumbnail_cache_wipe_complete_notice,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
if (preference.getKey().equals(youtubeRestrictedModeEnabledKey)) {
|
||||
if (key.equals(youtubeRestrictedModeEnabledKey)) {
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
DownloaderImpl.getInstance().updateYoutubeRestrictedModeCookies(context);
|
||||
|
@ -100,6 +103,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
Log.w(TAG, "onPreferenceTreeClick: null context");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
@ -142,7 +146,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
});
|
||||
|
||||
Preference sponsorBlockWebsitePreference =
|
||||
findPreference(getString(R.string.sponsorblock_home_page));
|
||||
findPreference(getString(R.string.sponsorblock_home_page_key));
|
||||
sponsorBlockWebsitePreference.setOnPreferenceClickListener((Preference p) -> {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse(getString(R.string.sponsorblock_homepage_url)));
|
||||
|
@ -151,7 +155,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
});
|
||||
|
||||
Preference sponsorBlockPrivacyPreference =
|
||||
findPreference(getString(R.string.sponsorblock_privacy));
|
||||
findPreference(getString(R.string.sponsorblock_privacy_key));
|
||||
sponsorBlockPrivacyPreference.setOnPreferenceClickListener((Preference p) -> {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse(getString(R.string.sponsorblock_privacy_policy_url)));
|
||||
|
@ -160,17 +164,10 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
});
|
||||
|
||||
Preference sponsorBlockApiUrlPreference =
|
||||
findPreference(getString(R.string.sponsorblock_api_url));
|
||||
|
||||
// workaround to force dependency updates due to using a custom preference
|
||||
findPreference(getString(R.string.sponsorblock_api_url_key));
|
||||
sponsorBlockApiUrlPreference
|
||||
.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
findPreference(getString(R.string.sponsorblock_enable))
|
||||
.onDependencyChanged(preference,
|
||||
newValue == null || newValue.equals(""));
|
||||
findPreference(getString(R.string.sponsorblock_notifications))
|
||||
.onDependencyChanged(preference,
|
||||
newValue == null || newValue.equals(""));
|
||||
updateDependencies(preference, newValue);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -179,21 +176,13 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// workaround to force dependency updates due to using a custom preference
|
||||
Preference sponsorBlockApiUrlPreference =
|
||||
findPreference(getString(R.string.sponsorblock_api_url));
|
||||
findPreference(getString(R.string.sponsorblock_api_url_key));
|
||||
String sponsorBlockApiUrlPreferenceValue =
|
||||
getPreferenceManager()
|
||||
.getSharedPreferences()
|
||||
.getString(getString(R.string.sponsorblock_api_url), null);
|
||||
findPreference(getString(R.string.sponsorblock_enable))
|
||||
.onDependencyChanged(sponsorBlockApiUrlPreference,
|
||||
sponsorBlockApiUrlPreferenceValue == null
|
||||
|| sponsorBlockApiUrlPreferenceValue.equals(""));
|
||||
findPreference(getString(R.string.sponsorblock_notifications))
|
||||
.onDependencyChanged(sponsorBlockApiUrlPreference,
|
||||
sponsorBlockApiUrlPreferenceValue == null
|
||||
|| sponsorBlockApiUrlPreferenceValue.equals(""));
|
||||
.getString(getString(R.string.sponsorblock_api_url_key), null);
|
||||
updateDependencies(sponsorBlockApiUrlPreference, sponsorBlockApiUrlPreferenceValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -394,6 +383,23 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateDependencies(final Preference preference, final Object newValue) {
|
||||
// This is a workaround to force dependency updates for custom preferences.
|
||||
|
||||
// sponsorblock_api_url_key
|
||||
if (preference.getKey().equals(getString(R.string.sponsorblock_api_url_key))) {
|
||||
findPreference(getString(R.string.sponsorblock_enable_key))
|
||||
.onDependencyChanged(preference,
|
||||
newValue == null || newValue.equals(""));
|
||||
findPreference(getString(R.string.sponsorblock_notifications_key))
|
||||
.onDependencyChanged(preference,
|
||||
newValue == null || newValue.equals(""));
|
||||
findPreference(getString(R.string.sponsorblock_categories_key))
|
||||
.onDependencyChanged(preference,
|
||||
newValue == null || newValue.equals(""));
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Error
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
|
@ -45,6 +45,7 @@ public final class NewPipeSettings {
|
|||
PreferenceManager.setDefaultValues(context, R.xml.main_settings, true);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.video_audio_settings, true);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.debug_settings, true);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.sponsor_block_category_settings, true);
|
||||
|
||||
getVideoDownloadFolder(context);
|
||||
getAudioDownloadFolder(context);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
public class SponsorBlockCategoriesSettingsFragment extends BasePreferenceFragment {
|
||||
@Override
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.sponsor_block_category_settings);
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SponsorTimeInfo {
|
||||
public ArrayList<TimeFrame> timeFrames = new ArrayList<>();
|
||||
|
||||
public int getSponsorEndTimeFromProgress(final int progress) {
|
||||
if (timeFrames == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (TimeFrame t : timeFrames) {
|
||||
if (progress < t.startTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (progress > t.endTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return (int) Math.ceil((t.endTime));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
public class TimeFrame {
|
||||
public double startTime;
|
||||
public double endTime;
|
||||
public Object tag;
|
||||
|
||||
public TimeFrame(final double startTime, final double endTime) {
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
}
|
||||
}
|
13
app/src/main/java/org/schabi/newpipe/util/VideoSegment.java
Normal file
13
app/src/main/java/org/schabi/newpipe/util/VideoSegment.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
public class VideoSegment {
|
||||
public double startTime;
|
||||
public double endTime;
|
||||
public String category;
|
||||
|
||||
public VideoSegment(final double startTime, final double endTime, final String category) {
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.category = category;
|
||||
}
|
||||
}
|
|
@ -83,4 +83,11 @@
|
|||
<color name="black">#000</color>
|
||||
<color name="gray_transparent">#be757575</color>
|
||||
|
||||
<!-- default SponsorBlock segment colors -->
|
||||
<color name="sponsor_segment">#00d400</color>
|
||||
<color name="intro_segment">#00ffff</color>
|
||||
<color name="outro_segment">#0202ed</color>
|
||||
<color name="interaction_segment">#cc00ff</color>
|
||||
<color name="self_promo_segment">#ffff00</color>
|
||||
<color name="music_offtopic_segment">#ff9900</color>
|
||||
</resources>
|
||||
|
|
|
@ -239,11 +239,24 @@
|
|||
<string name="downloads_storage_ask" translatable="false">downloads_storage_ask</string>
|
||||
<string name="storage_use_saf" translatable="false">storage_use_saf</string>
|
||||
|
||||
<string name="sponsorblock_home_page" translatable="false">sponsorblock_home_page</string>
|
||||
<string name="sponsorblock_enable" translatable="false">sponsorblock_enable</string>
|
||||
<string name="sponsorblock_api_url" translatable="false">sponsorblock_api_url</string>
|
||||
<string name="sponsorblock_notifications" translatable="false">sponsorblock_notifications</string>
|
||||
<string name="sponsorblock_privacy" translatable="false">sponsorblock_privacy</string>
|
||||
<string name="sponsorblock_home_page_key" translatable="false">sponsorblock_home_page</string>
|
||||
<string name="sponsorblock_enable_key" translatable="false">sponsorblock_enable</string>
|
||||
<string name="sponsorblock_api_url_key" translatable="false">sponsorblock_api_url</string>
|
||||
<string name="sponsorblock_notifications_key" translatable="false">sponsorblock_notifications</string>
|
||||
<string name="sponsorblock_privacy_key" translatable="false">sponsorblock_privacy</string>
|
||||
<string name="sponsorblock_categories_key" translatable="false">sponsorblock_categories</string>
|
||||
<string name="sponsorblock_category_sponsor_key" translatable="false">sponsorblock_category_sponsor</string>
|
||||
<string name="sponsorblock_category_sponsor_color_key" translatable="false">sponsorblock_category_sponsor_color</string>
|
||||
<string name="sponsorblock_category_intro_key" translatable="false">sponsorblock_category_intro</string>
|
||||
<string name="sponsorblock_category_intro_color_key" translatable="false">sponsorblock_category_intro_color</string>
|
||||
<string name="sponsorblock_category_outro_key" translatable="false">sponsorblock_category_outro</string>
|
||||
<string name="sponsorblock_category_outro_color_key" translatable="false">sponsorblock_category_outro_color</string>
|
||||
<string name="sponsorblock_category_interaction_key" translatable="false">sponsorblock_category_interaction</string>
|
||||
<string name="sponsorblock_category_interaction_color_key" translatable="false">sponsorblock_category_interaction_color</string>
|
||||
<string name="sponsorblock_category_self_promo_key" translatable="false">sponsorblock_category_self_promo</string>
|
||||
<string name="sponsorblock_category_self_promo_color_key" translatable="false">sponsorblock_category_self_promo_color</string>
|
||||
<string name="sponsorblock_category_music_key" translatable="false">sponsorblock_category_music</string>
|
||||
<string name="sponsorblock_category_music_color_key" translatable="false">sponsorblock_category_music_color</string>
|
||||
|
||||
<!-- FileName Downloads -->
|
||||
<string name="settings_file_charset_key" translatable="false">file_rename_charset</string>
|
||||
|
|
|
@ -132,7 +132,23 @@
|
|||
<string name="settings_category_other_title">Other</string>
|
||||
<string name="settings_category_debug_title">Debug</string>
|
||||
<string name="settings_category_updates_title">Updates</string>
|
||||
<string name="settings_category_sponsorblock">SponsorBlock (beta, third party service)</string>
|
||||
<string name="settings_category_sponsorblock_title">SponsorBlock (beta, third party service)</string>
|
||||
<string name="settings_category_sponsorblock_categories_title">SponsorBlock Categories</string>
|
||||
<string name="settings_category_sponsorblock_categories_summary">Customize which video segments to skip, along with their color markings on the seek bar.</string>
|
||||
<string name="settings_category_sponsorblock_category_enable">Enable</string>
|
||||
<string name="settings_category_sponsorblock_category_color">Seek Bar Color</string>
|
||||
<string name="settings_category_sponsorblock_category_sponsor_title">Sponsor</string>
|
||||
<string name="settings_category_sponsorblock_category_sponsor_summary">Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like.</string>
|
||||
<string name="settings_category_sponsorblock_category_intro_title">Intermission/Intro Animation</string>
|
||||
<string name="settings_category_sponsorblock_category_intro_summary">An interval without actual content. Could be a pause, static frame, repeating animation. This should not be used for transitions containing information or be used on music videos.</string>
|
||||
<string name="settings_category_sponsorblock_category_outro_title">Endcards/Credits</string>
|
||||
<string name="settings_category_sponsorblock_category_outro_summary">Credits or when the YouTube endcards appear. Not for spoken conclusions. This should not include useful content. This should not be used on music videos.</string>
|
||||
<string name="settings_category_sponsorblock_category_interaction_title">Interaction Reminds (Subscribe)</string>
|
||||
<string name="settings_category_sponsorblock_category_interaction_summary">When there is a short reminder to like, subscribe or follow them in the middle of content. If it is long or about something specific, it should be under self promotion instead.</string>
|
||||
<string name="settings_category_sponsorblock_category_self_promo_title">Unpaid/Self Promotion</string>
|
||||
<string name="settings_category_sponsorblock_category_self_promo_summary">Similar to "sponsor" except for unpaid or self promotion. This includes sections about merchandise, donations, or information about who they collaborated with.</string>
|
||||
<string name="settings_category_sponsorblock_category_music_title">Music: Non-Music Section</string>
|
||||
<string name="settings_category_sponsorblock_category_music_summary">Only for use in music videos. This includes introductions or outros in music videos.</string>
|
||||
<string name="background_player_playing_toast">Playing in background</string>
|
||||
<string name="popup_playing_toast">Playing in popup mode</string>
|
||||
<string name="background_player_append">Queued on background player</string>
|
||||
|
@ -617,7 +633,7 @@
|
|||
<string name="remove_watched_popup_warning">Videos that have been watched before and after being added to the playlist will be removed.\nAre you sure? This cannot be undone!</string>
|
||||
<string name="remove_watched_popup_yes_and_partially_watched_videos">Yes, and partially watched videos</string>
|
||||
<string name="new_seek_duration_toast">Due to ExoPlayer constraints the seek duration was set to %d seconds</string>
|
||||
<string name="sponsorblock_skipped_sponsor">Sponsor skipped</string>
|
||||
<string name="sponsorblock_skipped_segment">Segment skipped</string>
|
||||
<!-- Time duration plurals -->
|
||||
<plurals name="seconds">
|
||||
<item quantity="one">%d second</item>
|
||||
|
|
|
@ -120,41 +120,49 @@
|
|||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock">
|
||||
android:title="@string/settings_category_sponsorblock_title">
|
||||
|
||||
<Preference
|
||||
android:key="@string/sponsorblock_home_page"
|
||||
app:iconSpaceReserved="false"
|
||||
android:key="@string/sponsorblock_home_page_key"
|
||||
android:summary="@string/sponsorblock_home_page_summary"
|
||||
android:title="@string/sponsorblock_home_page_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
android:title="@string/sponsorblock_home_page_title"/>
|
||||
|
||||
<Preference
|
||||
android:key="@string/sponsorblock_privacy"
|
||||
app:iconSpaceReserved="false"
|
||||
android:key="@string/sponsorblock_privacy_key"
|
||||
android:summary="@string/sponsorblock_privacy_summary"
|
||||
android:title="@string/sponsorblock_privacy_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
android:title="@string/sponsorblock_privacy_title"/>
|
||||
|
||||
<org.schabi.newpipe.settings.custom.SponsorBlockApiUrlPreference
|
||||
android:key="@string/sponsorblock_api_url"
|
||||
app:iconSpaceReserved="false"
|
||||
android:key="@string/sponsorblock_api_url_key"
|
||||
android:summary="@string/sponsorblock_api_url_summary"
|
||||
android:title="@string/sponsorblock_api_url_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
android:title="@string/sponsorblock_api_url_title"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:dependency="@string/sponsorblock_api_url"
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_api_url_key"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/sponsorblock_enable"
|
||||
android:key="@string/sponsorblock_enable_key"
|
||||
android:summary="@string/sponsorblock_enable_summary"
|
||||
android:title="@string/sponsorblock_enable_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
android:title="@string/sponsorblock_enable_title"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="true"
|
||||
android:dependency="@string/sponsorblock_api_url"
|
||||
android:key="@string/sponsorblock_notifications"
|
||||
android:dependency="@string/sponsorblock_api_url_key"
|
||||
android:key="@string/sponsorblock_notifications_key"
|
||||
android:summary="@string/sponsorblock_notifications_summary"
|
||||
android:title="@string/sponsorblock_notifications_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
android:title="@string/sponsorblock_notifications_title"/>
|
||||
|
||||
<PreferenceScreen
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_api_url_key"
|
||||
android:fragment="org.schabi.newpipe.settings.SponsorBlockCategoriesSettingsFragment"
|
||||
android:key="@string/sponsorblock_categories_key"
|
||||
android:title="@string/settings_category_sponsorblock_categories_title"
|
||||
android:summary="@string/settings_category_sponsorblock_categories_summary"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
|
151
app/src/main/res/xml/sponsor_block_category_settings.xml
Normal file
151
app/src/main/res/xml/sponsor_block_category_settings.xml
Normal file
|
@ -0,0 +1,151 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/settings_category_sponsorblock_categories_title">
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock_category_sponsor_title">
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
android:summary="@string/settings_category_sponsorblock_category_sponsor_summary"
|
||||
android:selectable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="true"
|
||||
android:key="@string/sponsorblock_category_sponsor_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_enable"/>
|
||||
|
||||
<EditTextPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_category_sponsor_key"
|
||||
android:defaultValue="@color/sponsor_segment"
|
||||
android:key="@string/sponsorblock_category_sponsor_color_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_color"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock_category_intro_title">
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
android:summary="@string/settings_category_sponsorblock_category_intro_summary"
|
||||
android:selectable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/sponsorblock_category_intro_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_enable"/>
|
||||
|
||||
<EditTextPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_category_intro_key"
|
||||
android:defaultValue="@color/intro_segment"
|
||||
android:key="@string/sponsorblock_category_intro_color_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_color"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock_category_outro_title">
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
android:summary="@string/settings_category_sponsorblock_category_outro_summary"
|
||||
android:selectable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/sponsorblock_category_outro_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_enable"/>
|
||||
|
||||
<EditTextPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_category_outro_key"
|
||||
android:defaultValue="@color/outro_segment"
|
||||
android:key="@string/sponsorblock_category_outro_color_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_color"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock_category_interaction_title">
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
android:summary="@string/settings_category_sponsorblock_category_interaction_summary"
|
||||
android:selectable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/sponsorblock_category_interaction_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_enable"/>
|
||||
|
||||
<EditTextPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_category_interaction_key"
|
||||
android:defaultValue="@color/interaction_segment"
|
||||
android:key="@string/sponsorblock_category_interaction_color_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_color"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock_category_self_promo_title">
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
android:summary="@string/settings_category_sponsorblock_category_self_promo_summary"
|
||||
android:selectable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/sponsorblock_category_self_promo_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_enable"/>
|
||||
|
||||
<EditTextPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_category_self_promo_key"
|
||||
android:defaultValue="@color/self_promo_segment"
|
||||
android:key="@string/sponsorblock_category_self_promo_color_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_color"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:layout="@layout/settings_category_header_layout"
|
||||
android:title="@string/settings_category_sponsorblock_category_music_title">
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
android:summary="@string/settings_category_sponsorblock_category_music_summary"
|
||||
android:selectable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/sponsorblock_category_music_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_enable"/>
|
||||
|
||||
<EditTextPreference
|
||||
app:iconSpaceReserved="false"
|
||||
android:dependency="@string/sponsorblock_category_music_key"
|
||||
android:defaultValue="@color/music_offtopic_segment"
|
||||
android:key="@string/sponsorblock_category_music_color_key"
|
||||
android:title="@string/settings_category_sponsorblock_category_color"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
Loading…
Add table
Reference in a new issue