mirror of
https://github.com/revanced/revanced-patches
synced 2025-02-15 19:46:49 +01:00
Merge remote-tracking branch 'upstream/master' into feature/configurable-colors
# Conflicts: # app/src/main/java/pl/jakubweg/SponsorBlockPreferenceFragment.java
This commit is contained in:
commit
8c05b7f763
@ -1,12 +1,4 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="pl.jakubweg">
|
package="pl.jakubweg">
|
||||||
|
|
||||||
<application
|
|
||||||
android:allowBackup="true"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:supportsRtl="true"
|
|
||||||
tools:ignore="AllowBackup" />
|
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -4,7 +4,7 @@ import android.app.Application;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
public class YouTubeApplication extends Application {
|
public class YouTubeTikTokRoot_Application extends Application {
|
||||||
protected void onCreate(final Bundle bundle) {
|
protected void onCreate(final Bundle bundle) {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package fi.razerman.youtube.Helpers;
|
||||||
|
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
public class XSwipeHelper {
|
||||||
|
// Implementation in another repo
|
||||||
|
public static ViewGroup nextGenWatchLayout;
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
package fi.vanced.libraries.youtube.player;
|
package fi.vanced.libraries.youtube.player;
|
||||||
|
|
||||||
import fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView;
|
import fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView;
|
||||||
|
import pl.jakubweg.SponsorBlockUtils;
|
||||||
|
|
||||||
public class PlayerType {
|
public class PlayerType {
|
||||||
public static void playerTypeChanged(String playerType) {
|
public static void playerTypeChanged(String playerType) {
|
||||||
SponsorBlockView.playerTypeChanged(playerType);
|
SponsorBlockView.playerTypeChanged(playerType);
|
||||||
|
SponsorBlockUtils.playerTypeChanged(playerType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
package fi.vanced.libraries.youtube.sponsors.player.ui;
|
package fi.vanced.libraries.youtube.sponsors.player.ui;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.RippleDrawable;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -7,10 +7,12 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
import com.google.android.apps.youtube.app.YouTubeApplication;
|
import com.google.android.apps.youtube.app.YouTubeTikTokRoot_Application;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import fi.razerman.youtube.Helpers.XSwipeHelper;
|
||||||
|
|
||||||
import static fi.razerman.youtube.XGlobals.debug;
|
import static fi.razerman.youtube.XGlobals.debug;
|
||||||
|
|
||||||
public class SponsorBlockView {
|
public class SponsorBlockView {
|
||||||
@ -69,9 +71,9 @@ public class SponsorBlockView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void addView() {
|
private static void addView() {
|
||||||
inlineSponsorOverlay = new RelativeLayout(YouTubeApplication.getAppContext());
|
inlineSponsorOverlay = new RelativeLayout(YouTubeTikTokRoot_Application.getAppContext());
|
||||||
setLayoutParams(inlineSponsorOverlay);
|
setLayoutParams(inlineSponsorOverlay);
|
||||||
LayoutInflater.from(YouTubeApplication.getAppContext()).inflate(getIdentifier("inline_sponsor_overlay", "layout"), inlineSponsorOverlay);
|
LayoutInflater.from(YouTubeTikTokRoot_Application.getAppContext()).inflate(getIdentifier("inline_sponsor_overlay", "layout"), inlineSponsorOverlay);
|
||||||
|
|
||||||
_youtubeOverlaysLayout.addView(inlineSponsorOverlay, _youtubeOverlaysLayout.getChildCount() - 2);
|
_youtubeOverlaysLayout.addView(inlineSponsorOverlay, _youtubeOverlaysLayout.getChildCount() - 2);
|
||||||
|
|
||||||
@ -145,13 +147,31 @@ public class SponsorBlockView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void bringLayoutToFront() {
|
private static void bringLayoutToFront() {
|
||||||
|
checkLayout();
|
||||||
inlineSponsorOverlay.bringToFront();
|
inlineSponsorOverlay.bringToFront();
|
||||||
inlineSponsorOverlay.requestLayout();
|
inlineSponsorOverlay.requestLayout();
|
||||||
inlineSponsorOverlay.invalidate();
|
inlineSponsorOverlay.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkLayout() {
|
||||||
|
if (inlineSponsorOverlay.getHeight() == 0) {
|
||||||
|
View layout = XSwipeHelper.nextGenWatchLayout.findViewById(getIdentifier("player_overlays", "id"));
|
||||||
|
if (layout != null) {
|
||||||
|
|
||||||
|
initialize(layout);
|
||||||
|
|
||||||
|
if (debug){
|
||||||
|
Log.d("XGlobals", "player_overlays refreshed for SB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (debug){
|
||||||
|
Log.d("XGlobals", "player_overlays was not found for SB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static int getIdentifier(String name, String defType) {
|
private static int getIdentifier(String name, String defType) {
|
||||||
Context context = YouTubeApplication.getAppContext();
|
Context context = YouTubeTikTokRoot_Application.getAppContext();
|
||||||
return context.getResources().getIdentifier(name, defType, context.getPackageName());
|
return context.getResources().getIdentifier(name, defType, context.getPackageName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,6 @@ public class InjectedPlugin {
|
|||||||
Log.i(TAG, spacesStr + "Normal view: " + view);
|
Log.i(TAG, spacesStr + "Normal view: " + view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package pl.jakubweg;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -10,15 +11,22 @@ import android.os.Looper;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
|
||||||
|
import com.google.android.apps.youtube.app.YouTubeTikTokRoot_Application;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import fi.vanced.libraries.youtube.player.VideoInformation;
|
import fi.vanced.libraries.youtube.player.VideoInformation;
|
||||||
|
import pl.jakubweg.objects.SponsorSegment;
|
||||||
|
import pl.jakubweg.requests.Requester;
|
||||||
|
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.skippedSegments;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.skippedTime;
|
||||||
|
|
||||||
@SuppressLint({"LongLogTag"})
|
@SuppressLint({"LongLogTag"})
|
||||||
public class PlayerController {
|
public class PlayerController {
|
||||||
@ -36,12 +44,9 @@ public class PlayerController {
|
|||||||
private static String currentVideoId;
|
private static String currentVideoId;
|
||||||
private static long currentVideoLength = 1L;
|
private static long currentVideoLength = 1L;
|
||||||
private static long lastKnownVideoTime = -1L;
|
private static long lastKnownVideoTime = -1L;
|
||||||
private static final Runnable findAndSkipSegmentRunnable = new Runnable() {
|
private static final Runnable findAndSkipSegmentRunnable = () -> {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Log.d(TAG, "findAndSkipSegmentRunnable");
|
// Log.d(TAG, "findAndSkipSegmentRunnable");
|
||||||
findAndSkipSegment(false);
|
findAndSkipSegment(false);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
private static float sponsorBarLeft = 1f;
|
private static float sponsorBarLeft = 1f;
|
||||||
private static float sponsorBarRight = 1f;
|
private static float sponsorBarRight = 1f;
|
||||||
@ -54,20 +59,25 @@ public class PlayerController {
|
|||||||
|
|
||||||
public static void setCurrentVideoId(final String videoId) {
|
public static void setCurrentVideoId(final String videoId) {
|
||||||
if (videoId == null) {
|
if (videoId == null) {
|
||||||
Log.d(TAG, "setCurrentVideoId: videoId is null");
|
currentVideoId = null;
|
||||||
|
sponsorSegmentsOfCurrentVideo = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoInformation.currentVideoId = videoId;
|
VideoInformation.currentVideoId = videoId;
|
||||||
|
|
||||||
|
Context context = YouTubeTikTokRoot_Application.getAppContext();
|
||||||
|
if(context == null){
|
||||||
|
Log.e(TAG, "context is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SponsorBlockSettings.update(context);
|
||||||
|
|
||||||
if (!SponsorBlockSettings.isSponsorBlockEnabled) {
|
if (!SponsorBlockSettings.isSponsorBlockEnabled) {
|
||||||
currentVideoId = null;
|
currentVideoId = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Looper.myLooper() != Looper.getMainLooper()) // check if thread is not main
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (videoId.equals(currentVideoId))
|
if (videoId.equals(currentVideoId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -115,7 +125,7 @@ public class PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void executeDownloadSegments(String videoId) {
|
public static void executeDownloadSegments(String videoId) {
|
||||||
SponsorSegment[] segments = SponsorBlockUtils.getSegmentsForVideo(videoId);
|
SponsorSegment[] segments = Requester.getSegments(videoId);
|
||||||
Arrays.sort(segments);
|
Arrays.sort(segments);
|
||||||
|
|
||||||
if (VERBOSE)
|
if (VERBOSE)
|
||||||
@ -202,6 +212,12 @@ public class PlayerController {
|
|||||||
if (millis <= 0) return;
|
if (millis <= 0) return;
|
||||||
//findAndSkipSegment(false);
|
//findAndSkipSegment(false);
|
||||||
|
|
||||||
|
if (millis == currentVideoLength) {
|
||||||
|
SponsorBlockUtils.hideShieldButton();
|
||||||
|
SponsorBlockUtils.hideVoteButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SponsorSegment[] segments = sponsorSegmentsOfCurrentVideo;
|
SponsorSegment[] segments = sponsorSegmentsOfCurrentVideo;
|
||||||
if (segments == null || segments.length == 0) return;
|
if (segments == null || segments.length == 0) return;
|
||||||
|
|
||||||
@ -253,15 +269,21 @@ public class PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void sendViewRequestAsync(final long millis, final SponsorSegment segment) {
|
private static void sendViewRequestAsync(final long millis, final SponsorSegment segment) {
|
||||||
new Thread(new Runnable() {
|
if (segment.category != SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
|
||||||
@Override
|
Context context = YouTubeTikTokRoot_Application.getAppContext();
|
||||||
public void run() {
|
if (context != null) {
|
||||||
if (SponsorBlockSettings.countSkips &&
|
SharedPreferences preferences = SponsorBlockSettings.getPreferences(context);
|
||||||
segment.category != SponsorBlockSettings.SegmentInfo.Preview &&
|
long newSkippedTime = skippedTime + (segment.end - segment.start);
|
||||||
millis - segment.start < 2000) {
|
preferences.edit().putInt(SponsorBlockSettings.PREFERENCES_KEY_SKIPPED_SEGMENTS, skippedSegments + 1).apply();
|
||||||
// Only skips from the start should count as a view
|
preferences.edit().putLong(SponsorBlockSettings.PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME, newSkippedTime).apply();
|
||||||
SponsorBlockUtils.sendViewCountRequest(segment);
|
}
|
||||||
}
|
}
|
||||||
|
new Thread(() -> {
|
||||||
|
if (SponsorBlockSettings.countSkips &&
|
||||||
|
segment.category != SponsorBlockSettings.SegmentInfo.UNSUBMITTED &&
|
||||||
|
millis - segment.start < 2000) {
|
||||||
|
// Only skips from the start should count as a view
|
||||||
|
Requester.sendViewCountRequest(segment);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
@ -270,6 +292,10 @@ public class PlayerController {
|
|||||||
* Called very high frequency (once every about 100ms), also in background. It sometimes triggers when a video is paused (couple times in the row with the same value)
|
* Called very high frequency (once every about 100ms), also in background. It sometimes triggers when a video is paused (couple times in the row with the same value)
|
||||||
*/
|
*/
|
||||||
public static void setCurrentVideoTimeHighPrecision(final long millis) {
|
public static void setCurrentVideoTimeHighPrecision(final long millis) {
|
||||||
|
if ((millis < lastKnownVideoTime && lastKnownVideoTime >= currentVideoLength) || millis == 0) {
|
||||||
|
SponsorBlockUtils.showShieldButton(); // skipping from end to the video will show the buttons again
|
||||||
|
SponsorBlockUtils.showVoteButton();
|
||||||
|
}
|
||||||
if (lastKnownVideoTime > 0) {
|
if (lastKnownVideoTime > 0) {
|
||||||
lastKnownVideoTime = millis;
|
lastKnownVideoTime = millis;
|
||||||
VideoInformation.lastKnownVideoTime = lastKnownVideoTime;
|
VideoInformation.lastKnownVideoTime = lastKnownVideoTime;
|
||||||
@ -278,6 +304,10 @@ public class PlayerController {
|
|||||||
setCurrentVideoTime(millis);
|
setCurrentVideoTime(millis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getCurrentVideoLength() {
|
||||||
|
return currentVideoLength;
|
||||||
|
}
|
||||||
|
|
||||||
public static long getLastKnownVideoTime() {
|
public static long getLastKnownVideoTime() {
|
||||||
return lastKnownVideoTime;
|
return lastKnownVideoTime;
|
||||||
}
|
}
|
||||||
@ -305,7 +335,9 @@ public class PlayerController {
|
|||||||
|
|
||||||
public static void setSponsorBarRect(final Object self) {
|
public static void setSponsorBarRect(final Object self) {
|
||||||
try {
|
try {
|
||||||
Rect rect = ((Rect) self.getClass().getField("e").get(self));
|
Field field = self.getClass().getDeclaredField("replaceMeWithsetSponsorBarRect");
|
||||||
|
field.setAccessible(true);
|
||||||
|
Rect rect = (Rect) field.get(self);
|
||||||
if (rect != null) {
|
if (rect != null) {
|
||||||
setSponsorBarAbsoluteLeft(rect.left);
|
setSponsorBarAbsoluteLeft(rect.left);
|
||||||
setSponsorBarAbsoluteRight(rect.right);
|
setSponsorBarAbsoluteRight(rect.right);
|
||||||
@ -349,13 +381,10 @@ public class PlayerController {
|
|||||||
if (VERBOSE)
|
if (VERBOSE)
|
||||||
Log.d(TAG, "addSkipSponsorView15: view=" + view.toString());
|
Log.d(TAG, "addSkipSponsorView15: view=" + view.toString());
|
||||||
|
|
||||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||||
@Override
|
final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) view).getChildAt(2);
|
||||||
public void run() {
|
Activity context = ((Activity) viewGroup.getContext());
|
||||||
final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) view).getChildAt(2);
|
NewSegmentHelperLayout.context = context;
|
||||||
Activity context = ((Activity) viewGroup.getContext());
|
|
||||||
NewSegmentHelperLayout.context = context;
|
|
||||||
}
|
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,13 +392,10 @@ public class PlayerController {
|
|||||||
playerActivity = new WeakReference<>((Activity) view.getContext());
|
playerActivity = new WeakReference<>((Activity) view.getContext());
|
||||||
if (VERBOSE)
|
if (VERBOSE)
|
||||||
Log.d(TAG, "addSkipSponsorView14: view=" + view.toString());
|
Log.d(TAG, "addSkipSponsorView14: view=" + view.toString());
|
||||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||||
@Override
|
final ViewGroup viewGroup = (ViewGroup) view.getParent();
|
||||||
public void run() {
|
Activity activity = (Activity) viewGroup.getContext();
|
||||||
final ViewGroup viewGroup = (ViewGroup) view.getParent();
|
NewSegmentHelperLayout.context = activity;
|
||||||
Activity activity = (Activity) viewGroup.getContext();
|
|
||||||
NewSegmentHelperLayout.context = activity;
|
|
||||||
}
|
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,18 +459,15 @@ public class PlayerController {
|
|||||||
Log.d(TAG, String.format("Requesting skip to millis=%d on thread %s", millisecond, Thread.currentThread().toString()));
|
Log.d(TAG, String.format("Requesting skip to millis=%d on thread %s", millisecond, Thread.currentThread().toString()));
|
||||||
|
|
||||||
final long finalMillisecond = millisecond;
|
final long finalMillisecond = millisecond;
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
if (VERBOSE)
|
||||||
try {
|
Log.i(TAG, "Skipping to millis=" + finalMillisecond);
|
||||||
if (VERBOSE)
|
lastKnownVideoTime = finalMillisecond;
|
||||||
Log.i(TAG, "Skipping to millis=" + finalMillisecond);
|
VideoInformation.lastKnownVideoTime = lastKnownVideoTime;
|
||||||
lastKnownVideoTime = finalMillisecond;
|
setMillisecondMethod.invoke(currentObj, finalMillisecond);
|
||||||
VideoInformation.lastKnownVideoTime = lastKnownVideoTime;
|
} catch (Exception e) {
|
||||||
setMillisecondMethod.invoke(currentObj, finalMillisecond);
|
Log.e(TAG, "Cannot skip to millisecond", e);
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Cannot skip to millisecond", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -486,7 +509,7 @@ public class PlayerController {
|
|||||||
|
|
||||||
skipToMillisecond(segment.end + 2);
|
skipToMillisecond(segment.end + 2);
|
||||||
SkipSegmentView.hide();
|
SkipSegmentView.hide();
|
||||||
if (segment.category == SponsorBlockSettings.SegmentInfo.Preview) {
|
if (segment.category == SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
|
||||||
SponsorSegment[] newSegments = new SponsorSegment[sponsorSegmentsOfCurrentVideo.length - 1];
|
SponsorSegment[] newSegments = new SponsorSegment[sponsorSegmentsOfCurrentVideo.length - 1];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (SponsorSegment sponsorSegment : sponsorSegmentsOfCurrentVideo) {
|
for (SponsorSegment sponsorSegment : sponsorSegmentsOfCurrentVideo) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package pl.jakubweg;
|
package pl.jakubweg;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
@ -9,11 +8,13 @@ import android.view.animation.AnimationUtils;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
import com.google.android.apps.youtube.app.YouTubeApplication;
|
import com.google.android.apps.youtube.app.YouTubeTikTokRoot_Application;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
import static fi.razerman.youtube.XGlobals.debug;
|
import static fi.razerman.youtube.XGlobals.debug;
|
||||||
|
import static pl.jakubweg.PlayerController.getCurrentVideoLength;
|
||||||
|
import static pl.jakubweg.PlayerController.getLastKnownVideoTime;
|
||||||
|
|
||||||
public class ShieldButton {
|
public class ShieldButton {
|
||||||
static String TAG = "SHIELD";
|
static String TAG = "SHIELD";
|
||||||
@ -32,7 +33,6 @@ public class ShieldButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_youtubeControlsLayout = (RelativeLayout) viewStub;
|
_youtubeControlsLayout = (RelativeLayout) viewStub;
|
||||||
initButtonVisibilitySettings();
|
|
||||||
|
|
||||||
ImageView imageView = (ImageView)_youtubeControlsLayout
|
ImageView imageView = (ImageView)_youtubeControlsLayout
|
||||||
.findViewById(getIdentifier("sponsorblock_button", "id"));
|
.findViewById(getIdentifier("sponsorblock_button", "id"));
|
||||||
@ -79,6 +79,9 @@ public class ShieldButton {
|
|||||||
if (_youtubeControlsLayout == null || iView == null) return;
|
if (_youtubeControlsLayout == null || iView == null) return;
|
||||||
|
|
||||||
if (visible && shouldBeShown()) {
|
if (visible && shouldBeShown()) {
|
||||||
|
if (getLastKnownVideoTime() >= getCurrentVideoLength()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (debug) {
|
if (debug) {
|
||||||
Log.d(TAG, "Fading in");
|
Log.d(TAG, "Fading in");
|
||||||
}
|
}
|
||||||
@ -98,36 +101,22 @@ public class ShieldButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldBeShown() {
|
static boolean shouldBeShown() {
|
||||||
return SponsorBlockSettings.isSponsorBlockEnabled && SponsorBlockSettings.isAddNewSegmentEnabled;
|
return SponsorBlockUtils.isSettingEnabled(SponsorBlockSettings.isAddNewSegmentEnabled);
|
||||||
}
|
|
||||||
|
|
||||||
private static void initButtonVisibilitySettings() {
|
|
||||||
Context context = YouTubeApplication.getAppContext();
|
|
||||||
if(context == null){
|
|
||||||
Log.e(TAG, "context is null");
|
|
||||||
SponsorBlockSettings.isSponsorBlockEnabled = false;
|
|
||||||
SponsorBlockSettings.isAddNewSegmentEnabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPreferences sharedPreferences = context.getSharedPreferences(SponsorBlockSettings.PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
||||||
SponsorBlockSettings.isSponsorBlockEnabled = sharedPreferences.getBoolean(SponsorBlockSettings.PREFERENCES_KEY_SPONSOR_BLOCK_ENABLED, false);
|
|
||||||
SponsorBlockSettings.isAddNewSegmentEnabled = sharedPreferences.getBoolean(SponsorBlockSettings.PREFERENCES_KEY_NEW_SEGMENT_ENABLED, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Helpers
|
//region Helpers
|
||||||
private static int getIdentifier(String name, String defType) {
|
private static int getIdentifier(String name, String defType) {
|
||||||
Context context = YouTubeApplication.getAppContext();
|
Context context = YouTubeTikTokRoot_Application.getAppContext();
|
||||||
return context.getResources().getIdentifier(name, defType, context.getPackageName());
|
return context.getResources().getIdentifier(name, defType, context.getPackageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getInteger(String name) {
|
private static int getInteger(String name) {
|
||||||
return YouTubeApplication.getAppContext().getResources().getInteger(getIdentifier(name, "integer"));
|
return YouTubeTikTokRoot_Application.getAppContext().getResources().getInteger(getIdentifier(name, "integer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Animation getAnimation(String name) {
|
private static Animation getAnimation(String name) {
|
||||||
return AnimationUtils.loadAnimation(YouTubeApplication.getAppContext(), getIdentifier(name, "anim"));
|
return AnimationUtils.loadAnimation(YouTubeTikTokRoot_Application.getAppContext(), getIdentifier(name, "anim"));
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,13 @@ import android.util.DisplayMetrics;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.android.apps.youtube.app.YouTubeApplication;
|
import com.google.android.apps.youtube.app.YouTubeTikTokRoot_Application;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import pl.jakubweg.objects.SponsorSegment;
|
||||||
|
|
||||||
import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.hideSkipButton;
|
import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.hideSkipButton;
|
||||||
import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.showSkipButton;
|
import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.showSkipButton;
|
||||||
import static pl.jakubweg.PlayerController.VERBOSE;
|
import static pl.jakubweg.PlayerController.VERBOSE;
|
||||||
import static pl.jakubweg.StringRef.str;
|
|
||||||
|
|
||||||
@SuppressLint({"RtlHardcoded", "SetTextI18n", "LongLogTag", "AppCompatCustomView"})
|
@SuppressLint({"RtlHardcoded", "SetTextI18n", "LongLogTag", "AppCompatCustomView"})
|
||||||
public class SkipSegmentView {
|
public class SkipSegmentView {
|
||||||
@ -36,7 +35,7 @@ public class SkipSegmentView {
|
|||||||
}
|
}
|
||||||
lastNotifiedSegment = segment;
|
lastNotifiedSegment = segment;
|
||||||
String skipMessage = segment.category.skipMessage.toString();
|
String skipMessage = segment.category.skipMessage.toString();
|
||||||
Context context = YouTubeApplication.getAppContext();
|
Context context = YouTubeTikTokRoot_Application.getAppContext();
|
||||||
if (VERBOSE)
|
if (VERBOSE)
|
||||||
Log.d(TAG, String.format("notifySkipped; message=%s", skipMessage));
|
Log.d(TAG, String.format("notifySkipped; message=%s", skipMessage));
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package pl.jakubweg;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -18,28 +17,34 @@ import android.preference.SwitchPreference;
|
|||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import pl.jakubweg.requests.Requester;
|
||||||
|
|
||||||
import static pl.jakubweg.SponsorBlockSettings.DefaultBehaviour;
|
import static pl.jakubweg.SponsorBlockSettings.DefaultBehaviour;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_ADJUST_NEW_SEGMENT_STEP;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_ADJUST_NEW_SEGMENT_STEP;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_COUNT_SKIPS;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_COUNT_SKIPS;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_NEW_SEGMENT_ENABLED;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_NEW_SEGMENT_ENABLED;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_SHOW_TIME_WITHOUT_SEGMENTS;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_SPONSOR_BLOCK_ENABLED;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_SPONSOR_BLOCK_ENABLED;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_UUID;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_UUID;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_VOTING_ENABLED;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_NAME;
|
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_NAME;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.adjustNewSegmentMillis;
|
import static pl.jakubweg.SponsorBlockSettings.adjustNewSegmentMillis;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.countSkips;
|
import static pl.jakubweg.SponsorBlockSettings.countSkips;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.setSeenGuidelines;
|
import static pl.jakubweg.SponsorBlockSettings.setSeenGuidelines;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.showTimeWithoutSegments;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.showToastWhenSkippedAutomatically;
|
import static pl.jakubweg.SponsorBlockSettings.showToastWhenSkippedAutomatically;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.uuid;
|
import static pl.jakubweg.SponsorBlockSettings.uuid;
|
||||||
import static pl.jakubweg.StringRef.str;
|
import static pl.jakubweg.StringRef.str;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "deprecation"}) // injected
|
@SuppressWarnings({"unused", "deprecation"}) // injected
|
||||||
public class SponsorBlockPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public class SponsorBlockPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
public static final DecimalFormat FORMATTER = new DecimalFormat("#,###,###");
|
||||||
private ArrayList<Preference> preferencesToDisableWhenSBDisabled = new ArrayList<>();
|
public static final String SAVED_TEMPLATE = "%dh %.1f minutes";
|
||||||
|
private final ArrayList<Preference> preferencesToDisableWhenSBDisabled = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -53,6 +58,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context);
|
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context);
|
||||||
setPreferenceScreen(preferenceScreen);
|
setPreferenceScreen(preferenceScreen);
|
||||||
|
|
||||||
|
SponsorBlockSettings.update(context);
|
||||||
|
|
||||||
{
|
{
|
||||||
SwitchPreference preference = new SwitchPreference(context);
|
SwitchPreference preference = new SwitchPreference(context);
|
||||||
preferenceScreen.addPreference(preference);
|
preferenceScreen.addPreference(preference);
|
||||||
@ -61,13 +68,10 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
preference.setChecked(SponsorBlockSettings.isSponsorBlockEnabled);
|
preference.setChecked(SponsorBlockSettings.isSponsorBlockEnabled);
|
||||||
preference.setTitle(str("enable_sb"));
|
preference.setTitle(str("enable_sb"));
|
||||||
preference.setSummary(str("enable_sb_sum"));
|
preference.setSummary(str("enable_sb_sum"));
|
||||||
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||||
@Override
|
final boolean value = (Boolean) newValue;
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
enableCategoriesIfNeeded(value);
|
||||||
final boolean value = (Boolean) newValue;
|
return true;
|
||||||
enableCategoriesIfNeeded(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,30 +84,34 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
preference.setTitle(str("enable_segmadding"));
|
preference.setTitle(str("enable_segmadding"));
|
||||||
preference.setSummary(str("enable_segmadding_sum"));
|
preference.setSummary(str("enable_segmadding_sum"));
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
preference.setOnPreferenceChangeListener((preference12, o) -> {
|
||||||
@Override
|
final boolean value = (Boolean) o;
|
||||||
public boolean onPreferenceChange(Preference preference, Object o) {
|
if (value && !SponsorBlockSettings.seenGuidelinesPopup) {
|
||||||
final boolean value = (Boolean) o;
|
new AlertDialog.Builder(preference12.getContext())
|
||||||
if (value && !SponsorBlockSettings.seenGuidelinesPopup) {
|
.setTitle(str("sb_guidelines_popup_title"))
|
||||||
new AlertDialog.Builder(preference.getContext())
|
.setMessage(str("sb_guidelines_popup_content"))
|
||||||
.setTitle(str("sb_guidelines_popup_title"))
|
.setNegativeButton(str("sb_guidelines_popup_already_read"), null)
|
||||||
.setMessage(str("sb_guidelines_popup_content"))
|
.setPositiveButton(str("sb_guidelines_popup_open"), (dialogInterface, i) -> openGuidelines())
|
||||||
.setNegativeButton(str("sb_guidelines_popup_already_read"), null)
|
.show();
|
||||||
.setPositiveButton(str("sb_guidelines_popup_open"), new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
|
||||||
openGuidelines();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SwitchPreference preference = new SwitchPreference(context);
|
||||||
|
preferenceScreen.addPreference(preference);
|
||||||
|
preference.setTitle(str("enable_voting"));
|
||||||
|
preference.setSummary(str("enable_voting_sum"));
|
||||||
|
preference.setKey(PREFERENCES_KEY_VOTING_ENABLED);
|
||||||
|
preference.setDefaultValue(SponsorBlockSettings.isVotingEnabled);
|
||||||
|
preference.setChecked(SponsorBlockSettings.isVotingEnabled);
|
||||||
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
|
}
|
||||||
|
|
||||||
addGeneralCategory(context, preferenceScreen);
|
addGeneralCategory(context, preferenceScreen);
|
||||||
addSegmentsCategory(context, preferenceScreen);
|
addSegmentsCategory(context, preferenceScreen);
|
||||||
|
addStatsCategory(context, preferenceScreen);
|
||||||
addAboutCategory(context, preferenceScreen);
|
addAboutCategory(context, preferenceScreen);
|
||||||
|
|
||||||
enableCategoriesIfNeeded(SponsorBlockSettings.isSponsorBlockEnabled);
|
enableCategoriesIfNeeded(SponsorBlockSettings.isSponsorBlockEnabled);
|
||||||
@ -145,7 +153,7 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
entryValues[i] = behaviour.key;
|
entryValues[i] = behaviour.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SponsorBlockSettings.SegmentInfo segmentInfo : SponsorBlockSettings.SegmentInfo.valuesWithoutPreview()) {
|
for (SponsorBlockSettings.SegmentInfo segmentInfo : SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted()) {
|
||||||
ListPreference preference = new ListPreference(context);
|
ListPreference preference = new ListPreference(context);
|
||||||
preference.setTitle(segmentInfo.getTitleWithDot());
|
preference.setTitle(segmentInfo.getTitleWithDot());
|
||||||
preference.setSummary(segmentInfo.description.toString());
|
preference.setSummary(segmentInfo.description.toString());
|
||||||
@ -167,6 +175,21 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addStatsCategory(Context context, PreferenceScreen screen) {
|
||||||
|
PreferenceCategory category = new PreferenceCategory(context);
|
||||||
|
screen.addPreference(category);
|
||||||
|
category.setTitle(str("stats"));
|
||||||
|
preferencesToDisableWhenSBDisabled.add(category);
|
||||||
|
|
||||||
|
{
|
||||||
|
Preference preference = new Preference(context);
|
||||||
|
category.addPreference(preference);
|
||||||
|
preference.setTitle(str("stats_loading"));
|
||||||
|
|
||||||
|
Requester.retrieveUserStats(category, preference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addAboutCategory(Context context, PreferenceScreen screen) {
|
private void addAboutCategory(Context context, PreferenceScreen screen) {
|
||||||
PreferenceCategory category = new PreferenceCategory(context);
|
PreferenceCategory category = new PreferenceCategory(context);
|
||||||
screen.addPreference(category);
|
screen.addPreference(category);
|
||||||
@ -177,14 +200,11 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
preference.setTitle(str("about_api"));
|
preference.setTitle(str("about_api"));
|
||||||
preference.setSummary(str("about_api_sum"));
|
preference.setSummary(str("about_api_sum"));
|
||||||
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
preference.setOnPreferenceClickListener(preference1 -> {
|
||||||
@Override
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
i.setData(Uri.parse("https://sponsor.ajay.app"));
|
||||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
preference1.getContext().startActivity(i);
|
||||||
i.setData(Uri.parse("http://sponsor.ajay.app"));
|
return false;
|
||||||
preference.getContext().startActivity(i);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,12 +226,9 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
Preference preference = new Preference(context);
|
Preference preference = new Preference(context);
|
||||||
preference.setTitle(str("sb_guidelines_preference_title"));
|
preference.setTitle(str("sb_guidelines_preference_title"));
|
||||||
preference.setSummary(str("sb_guidelines_preference_sum"));
|
preference.setSummary(str("sb_guidelines_preference_sum"));
|
||||||
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
preference.setOnPreferenceClickListener(preference1 -> {
|
||||||
@Override
|
openGuidelines();
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
return false;
|
||||||
openGuidelines();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
}
|
}
|
||||||
@ -222,12 +239,9 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
preference.setSummary(str("general_skiptoast_sum"));
|
preference.setSummary(str("general_skiptoast_sum"));
|
||||||
preference.setKey(PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP);
|
preference.setKey(PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP);
|
||||||
preference.setDefaultValue(showToastWhenSkippedAutomatically);
|
preference.setDefaultValue(showToastWhenSkippedAutomatically);
|
||||||
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
preference.setOnPreferenceClickListener(preference12 -> {
|
||||||
@Override
|
Toast.makeText(preference12.getContext(), str("skipped_sponsor"), Toast.LENGTH_SHORT).show();
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
return false;
|
||||||
Toast.makeText(preference.getContext(), str("skipped_sponsor"), Toast.LENGTH_SHORT).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
preferencesToDisableWhenSBDisabled.add(preference);
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
@ -243,6 +257,16 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
|
|||||||
screen.addPreference(preference);
|
screen.addPreference(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Preference preference = new SwitchPreference(context);
|
||||||
|
preference.setTitle(str("general_time_without_sb"));
|
||||||
|
preference.setSummary(str("general_time_without_sb_sum"));
|
||||||
|
preference.setKey(PREFERENCES_KEY_SHOW_TIME_WITHOUT_SEGMENTS);
|
||||||
|
preference.setDefaultValue(showTimeWithoutSegments);
|
||||||
|
preferencesToDisableWhenSBDisabled.add(preference);
|
||||||
|
screen.addPreference(preference);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
EditTextPreference preference = new EditTextPreference(context);
|
EditTextPreference preference = new EditTextPreference(context);
|
||||||
preference.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
|
preference.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
|
||||||
|
@ -24,20 +24,25 @@ public class SponsorBlockSettings {
|
|||||||
public static final String PREFERENCES_KEY_SPONSOR_BLOCK_ENABLED = "sb-enabled";
|
public static final String PREFERENCES_KEY_SPONSOR_BLOCK_ENABLED = "sb-enabled";
|
||||||
public static final String PREFERENCES_KEY_SEEN_GUIDELINES = "sb-seen-gl";
|
public static final String PREFERENCES_KEY_SEEN_GUIDELINES = "sb-seen-gl";
|
||||||
public static final String PREFERENCES_KEY_NEW_SEGMENT_ENABLED = "sb-new-segment-enabled";
|
public static final String PREFERENCES_KEY_NEW_SEGMENT_ENABLED = "sb-new-segment-enabled";
|
||||||
public static final String sponsorBlockSkipSegmentsUrl = "https://sponsor.ajay.app/api/skipSegments";
|
public static final String PREFERENCES_KEY_VOTING_ENABLED = "sb-voting-enabled";
|
||||||
public static final String sponsorBlockViewedUrl = "https://sponsor.ajay.app/api/viewedVideoSponsorTime";
|
public static final String PREFERENCES_KEY_SKIPPED_SEGMENTS = "sb-skipped-segments";
|
||||||
|
public static final String PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME = "sb-skipped-segments-time";
|
||||||
|
public static final String PREFERENCES_KEY_SHOW_TIME_WITHOUT_SEGMENTS = "sb-length-without-segments";
|
||||||
|
|
||||||
|
public static final SegmentBehaviour DefaultBehaviour = SegmentBehaviour.SKIP_AUTOMATICALLY;
|
||||||
public static final SegmentBehaviour DefaultBehaviour = SegmentBehaviour.SkipAutomatically;
|
|
||||||
|
|
||||||
public static boolean isSponsorBlockEnabled = false;
|
public static boolean isSponsorBlockEnabled = false;
|
||||||
public static boolean seenGuidelinesPopup = false;
|
public static boolean seenGuidelinesPopup = false;
|
||||||
public static boolean isAddNewSegmentEnabled = false;
|
public static boolean isAddNewSegmentEnabled = false;
|
||||||
|
public static boolean isVotingEnabled = true;
|
||||||
public static boolean showToastWhenSkippedAutomatically = true;
|
public static boolean showToastWhenSkippedAutomatically = true;
|
||||||
public static boolean countSkips = true;
|
public static boolean countSkips = true;
|
||||||
|
public static boolean showTimeWithoutSegments = true;
|
||||||
public static int adjustNewSegmentMillis = 150;
|
public static int adjustNewSegmentMillis = 150;
|
||||||
public static String uuid = "<invalid>";
|
public static String uuid = "<invalid>";
|
||||||
private static String sponsorBlockUrlCategories = "[]";
|
public static String sponsorBlockUrlCategories = "[]";
|
||||||
|
public static int skippedSegments;
|
||||||
|
public static long skippedTime;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -45,14 +50,6 @@ public class SponsorBlockSettings {
|
|||||||
Log.e("jakubweg.Settings", "Do not call SponsorBlockSettings constructor!");
|
Log.e("jakubweg.Settings", "Do not call SponsorBlockSettings constructor!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSponsorBlockUrlWithCategories(String videoId) {
|
|
||||||
return sponsorBlockSkipSegmentsUrl + "?videoID=" + videoId + "&categories=" + sponsorBlockUrlCategories;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getSponsorBlockViewedUrl(String UUID) {
|
|
||||||
return sponsorBlockViewedUrl + "?UUID=" + UUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SharedPreferences getPreferences(Context context) {
|
public static SharedPreferences getPreferences(Context context) {
|
||||||
return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
|
return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||||
}
|
}
|
||||||
@ -72,23 +69,30 @@ public class SponsorBlockSettings {
|
|||||||
if (!isSponsorBlockEnabled) {
|
if (!isSponsorBlockEnabled) {
|
||||||
SkipSegmentView.hide();
|
SkipSegmentView.hide();
|
||||||
NewSegmentHelperLayout.hide();
|
NewSegmentHelperLayout.hide();
|
||||||
SponsorBlockUtils.hideButton();
|
SponsorBlockUtils.hideShieldButton();
|
||||||
|
SponsorBlockUtils.hideVoteButton();
|
||||||
PlayerController.sponsorSegmentsOfCurrentVideo = null;
|
PlayerController.sponsorSegmentsOfCurrentVideo = null;
|
||||||
} else if (/*isAddNewSegmentEnabled*/false) {
|
} else { /*isAddNewSegmentEnabled*/
|
||||||
SponsorBlockUtils.showButton();
|
SponsorBlockUtils.showShieldButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
isAddNewSegmentEnabled = preferences.getBoolean(PREFERENCES_KEY_NEW_SEGMENT_ENABLED, isAddNewSegmentEnabled);
|
isAddNewSegmentEnabled = preferences.getBoolean(PREFERENCES_KEY_NEW_SEGMENT_ENABLED, isAddNewSegmentEnabled);
|
||||||
if (!/*isAddNewSegmentEnabled*/false) {
|
if (!isAddNewSegmentEnabled) {
|
||||||
NewSegmentHelperLayout.hide();
|
NewSegmentHelperLayout.hide();
|
||||||
SponsorBlockUtils.hideButton();
|
SponsorBlockUtils.hideShieldButton();
|
||||||
} else {
|
} else {
|
||||||
SponsorBlockUtils.showButton();
|
SponsorBlockUtils.showShieldButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVotingEnabled = preferences.getBoolean(PREFERENCES_KEY_VOTING_ENABLED, isVotingEnabled);
|
||||||
|
if (!isVotingEnabled)
|
||||||
|
SponsorBlockUtils.hideVoteButton();
|
||||||
|
else
|
||||||
|
SponsorBlockUtils.showVoteButton();
|
||||||
|
|
||||||
SegmentBehaviour[] possibleBehaviours = SegmentBehaviour.values();
|
SegmentBehaviour[] possibleBehaviours = SegmentBehaviour.values();
|
||||||
final ArrayList<String> enabledCategories = new ArrayList<>(possibleBehaviours.length);
|
final ArrayList<String> enabledCategories = new ArrayList<>(possibleBehaviours.length);
|
||||||
for (SegmentInfo segment : SegmentInfo.valuesWithoutPreview()) {
|
for (SegmentInfo segment : SegmentInfo.valuesWithoutUnsubmitted()) {
|
||||||
SegmentBehaviour behaviour = null;
|
SegmentBehaviour behaviour = null;
|
||||||
String value = preferences.getString(segment.key, null);
|
String value = preferences.getString(segment.key, null);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
@ -112,18 +116,22 @@ public class SponsorBlockSettings {
|
|||||||
segment.setColor(Integer.parseInt(tmp));
|
segment.setColor(Integer.parseInt(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
//"[%22sponsor%22,%22outro%22,%22music_offtopic%22,%22intro%22,%22selfpromo%22,%22interaction%22]";
|
//"[%22sponsor%22,%22outro%22,%22music_offtopic%22,%22intro%22,%22selfpromo%22,%22interaction%22,%22preview%22]";
|
||||||
if (enabledCategories.size() == 0)
|
if (enabledCategories.size() == 0)
|
||||||
sponsorBlockUrlCategories = "[]";
|
sponsorBlockUrlCategories = "[]";
|
||||||
else
|
else
|
||||||
sponsorBlockUrlCategories = "[%22" + TextUtils.join("%22,%22", enabledCategories) + "%22]";
|
sponsorBlockUrlCategories = "[%22" + TextUtils.join("%22,%22", enabledCategories) + "%22]";
|
||||||
|
|
||||||
|
skippedSegments = preferences.getInt(PREFERENCES_KEY_SKIPPED_SEGMENTS, skippedSegments);
|
||||||
|
skippedTime = preferences.getLong(PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME, skippedTime);
|
||||||
|
|
||||||
showToastWhenSkippedAutomatically = preferences.getBoolean(PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP, showToastWhenSkippedAutomatically);
|
showToastWhenSkippedAutomatically = preferences.getBoolean(PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP, showToastWhenSkippedAutomatically);
|
||||||
String tmp1 = preferences.getString(PREFERENCES_KEY_ADJUST_NEW_SEGMENT_STEP, null);
|
String tmp1 = preferences.getString(PREFERENCES_KEY_ADJUST_NEW_SEGMENT_STEP, null);
|
||||||
if (tmp1 != null)
|
if (tmp1 != null)
|
||||||
adjustNewSegmentMillis = Integer.parseInt(tmp1);
|
adjustNewSegmentMillis = Integer.parseInt(tmp1);
|
||||||
|
|
||||||
|
countSkips = preferences.getBoolean(PREFERENCES_KEY_COUNT_SKIPS, countSkips);
|
||||||
|
showTimeWithoutSegments = preferences.getBoolean(PREFERENCES_KEY_SHOW_TIME_WITHOUT_SEGMENTS, showTimeWithoutSegments);
|
||||||
|
|
||||||
uuid = preferences.getString(PREFERENCES_KEY_UUID, null);
|
uuid = preferences.getString(PREFERENCES_KEY_UUID, null);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
@ -136,9 +144,9 @@ public class SponsorBlockSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum SegmentBehaviour {
|
public enum SegmentBehaviour {
|
||||||
SkipAutomatically("skip", sf("skip_automatically"), true, true),
|
SKIP_AUTOMATICALLY("skip", sf("skip_automatically"), true, true),
|
||||||
ManualSkip("manual-skip", sf("skip_showbutton"), false, true),
|
MANUAL_SKIP("manual-skip", sf("skip_showbutton"), false, true),
|
||||||
Ignore("ignore", sf("skip_ignore"), false, false);
|
IGNORE("ignore", sf("skip_ignore"), false, false);
|
||||||
|
|
||||||
public final String key;
|
public final String key;
|
||||||
public final StringRef name;
|
public final StringRef name;
|
||||||
@ -157,27 +165,28 @@ public class SponsorBlockSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum SegmentInfo {
|
public enum SegmentInfo {
|
||||||
Sponsor("sponsor", sf("segments_sponsor"), sf("skipped_sponsor"), sf("segments_sponsor_sum"), null, 0xFF00d400),
|
SPONSOR("sponsor", sf("segments_sponsor"), sf("skipped_sponsor"), sf("segments_sponsor_sum"), null, 0xFF00d400),
|
||||||
Intro("intro", sf("segments_intermission"), sf("skipped_intermission"), sf("segments_intermission_sum"), null, 0xFF00ffff),
|
INTRO("intro", sf("segments_intermission"), sf("skipped_intermission"), sf("segments_intermission_sum"), null, 0xFF00ffff),
|
||||||
Outro("outro", sf("segments_endcards"), sf("skipped_endcard"), sf("segments_endcards_sum"), null, 0xFF0202ed),
|
OUTRO("outro", sf("segments_endcards"), sf("skipped_endcard"), sf("segments_endcards_sum"), null, 0xFF0202ed),
|
||||||
Interaction("interaction", sf("segments_subscribe"), sf("skipped_subscribe"), sf("segments_subscribe_sum"), null, 0xFFcc00ff),
|
INTERACTION("interaction", sf("segments_subscribe"), sf("skipped_subscribe"), sf("segments_subscribe_sum"), null, 0xFFcc00ff),
|
||||||
SelfPromo("selfpromo", sf("segments_selfpromo"), sf("skipped_selfpromo"), sf("segments_selfpromo_sum"), null, 0xFFffff00),
|
SELF_PROMO("selfpromo", sf("segments_selfpromo"), sf("skipped_selfpromo"), sf("segments_selfpromo_sum"), null, 0xFFffff00),
|
||||||
MusicOfftopic("music_offtopic", sf("segments_nomusic"), sf("skipped_nomusic"), sf("segments_nomusic_sum"), null, 0xFFff9900),
|
MUSIC_OFFTOPIC("music_offtopic", sf("segments_nomusic"), sf("skipped_nomusic"), sf("segments_nomusic_sum"), null, 0xFFff9900),
|
||||||
Preview("preview", StringRef.empty, sf("skipped_preview"), StringRef.empty, SegmentBehaviour.SkipAutomatically, 0xFF000000),
|
PREVIEW("preview", sf("segments_preview"), sf("skipped_preview"), sf("segments_preview_sum"), null, 0xFF008fd6),
|
||||||
;
|
UNSUBMITTED("unsubmitted", StringRef.empty, sf("skipped_unsubmitted"), StringRef.empty, SegmentBehaviour.SKIP_AUTOMATICALLY, 0xFFFFFFFF);
|
||||||
|
|
||||||
private static SegmentInfo[] mValuesWithoutPreview = new SegmentInfo[]{
|
private static final SegmentInfo[] mValuesWithoutUnsubmitted = new SegmentInfo[]{
|
||||||
Sponsor,
|
SPONSOR,
|
||||||
Intro,
|
INTRO,
|
||||||
Outro,
|
OUTRO,
|
||||||
Interaction,
|
INTERACTION,
|
||||||
SelfPromo,
|
SELF_PROMO,
|
||||||
MusicOfftopic
|
MUSIC_OFFTOPIC,
|
||||||
|
PREVIEW
|
||||||
};
|
};
|
||||||
private static Map<String, SegmentInfo> mValuesMap = new HashMap<>(7);
|
private static final Map<String, SegmentInfo> mValuesMap = new HashMap<>(values().length);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (SegmentInfo value : valuesWithoutPreview())
|
for (SegmentInfo value : valuesWithoutUnsubmitted())
|
||||||
mValuesMap.put(value.key, value);
|
mValuesMap.put(value.key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +215,8 @@ public class SponsorBlockSettings {
|
|||||||
this.paint = new Paint();
|
this.paint = new Paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SegmentInfo[] valuesWithoutPreview() {
|
public static SegmentInfo[] valuesWithoutUnsubmitted() {
|
||||||
return mValuesWithoutPreview;
|
return mValuesWithoutUnsubmitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SegmentInfo byCategoryKey(String key) {
|
public static SegmentInfo byCategoryKey(String key) {
|
||||||
|
@ -4,41 +4,48 @@ import android.annotation.SuppressLint;
|
|||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.Handler;
|
import android.content.Intent;
|
||||||
import android.os.Looper;
|
import android.net.Uri;
|
||||||
|
import android.preference.EditTextPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.preference.PreferenceCategory;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import pl.jakubweg.objects.SponsorSegment;
|
||||||
|
import pl.jakubweg.objects.UserStats;
|
||||||
|
import pl.jakubweg.requests.Requester;
|
||||||
|
|
||||||
|
import static android.text.Html.fromHtml;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static fi.razerman.youtube.XGlobals.debug;
|
import static fi.razerman.youtube.XGlobals.debug;
|
||||||
import static pl.jakubweg.PlayerController.VERBOSE;
|
|
||||||
import static pl.jakubweg.PlayerController.getCurrentVideoId;
|
import static pl.jakubweg.PlayerController.getCurrentVideoId;
|
||||||
import static pl.jakubweg.PlayerController.getLastKnownVideoTime;
|
import static pl.jakubweg.PlayerController.getLastKnownVideoTime;
|
||||||
import static pl.jakubweg.PlayerController.sponsorSegmentsOfCurrentVideo;
|
import static pl.jakubweg.PlayerController.sponsorSegmentsOfCurrentVideo;
|
||||||
import static pl.jakubweg.SponsorBlockSettings.sponsorBlockSkipSegmentsUrl;
|
import static pl.jakubweg.SponsorBlockPreferenceFragment.FORMATTER;
|
||||||
|
import static pl.jakubweg.SponsorBlockPreferenceFragment.SAVED_TEMPLATE;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.isSponsorBlockEnabled;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.showTimeWithoutSegments;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.skippedSegments;
|
||||||
|
import static pl.jakubweg.SponsorBlockSettings.skippedTime;
|
||||||
import static pl.jakubweg.StringRef.str;
|
import static pl.jakubweg.StringRef.str;
|
||||||
|
import static pl.jakubweg.requests.Requester.voteForSegment;
|
||||||
|
|
||||||
@SuppressWarnings({"LongLogTag"})
|
@SuppressWarnings({"LongLogTag"})
|
||||||
public abstract class SponsorBlockUtils {
|
public abstract class SponsorBlockUtils {
|
||||||
@ -46,15 +53,20 @@ public abstract class SponsorBlockUtils {
|
|||||||
public static final String DATE_FORMAT = "HH:mm:ss.SSS";
|
public static final String DATE_FORMAT = "HH:mm:ss.SSS";
|
||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
|
public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
|
||||||
|
public static boolean videoHasSegments = false;
|
||||||
|
public static String timeWithoutSegments = "";
|
||||||
private static final int sponsorBtnId = 1234;
|
private static final int sponsorBtnId = 1234;
|
||||||
public static final View.OnClickListener sponsorBlockBtnListener = new View.OnClickListener() {
|
public static final View.OnClickListener sponsorBlockBtnListener = v -> {
|
||||||
@Override
|
if (debug) {
|
||||||
public void onClick(View v) {
|
Log.d(TAG, "Shield button clicked");
|
||||||
if (debug) {
|
|
||||||
Log.d(TAG, "Shield button clicked");
|
|
||||||
}
|
|
||||||
NewSegmentHelperLayout.toggle();
|
|
||||||
}
|
}
|
||||||
|
NewSegmentHelperLayout.toggle();
|
||||||
|
};
|
||||||
|
public static final View.OnClickListener voteButtonListener = v -> {
|
||||||
|
if (debug) {
|
||||||
|
Log.d(TAG, "Vote button clicked");
|
||||||
|
}
|
||||||
|
SponsorBlockUtils.onVotingClicked(v.getContext());
|
||||||
};
|
};
|
||||||
private static int shareBtnId = -1;
|
private static int shareBtnId = -1;
|
||||||
private static long newSponsorSegmentDialogShownMillis;
|
private static long newSponsorSegmentDialogShownMillis;
|
||||||
@ -84,7 +96,7 @@ public abstract class SponsorBlockUtils {
|
|||||||
private static final DialogInterface.OnClickListener segmentTypeListener = new DialogInterface.OnClickListener() {
|
private static final DialogInterface.OnClickListener segmentTypeListener = new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockSettings.SegmentInfo.valuesWithoutPreview()[which];
|
SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted()[which];
|
||||||
boolean enableButton;
|
boolean enableButton;
|
||||||
if (!segmentType.behaviour.showOnTimeBar) {
|
if (!segmentType.behaviour.showOnTimeBar) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
@ -114,7 +126,7 @@ public abstract class SponsorBlockUtils {
|
|||||||
Context context = ((AlertDialog) dialog).getContext();
|
Context context = ((AlertDialog) dialog).getContext();
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
|
|
||||||
SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutPreview();
|
SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
|
||||||
CharSequence[] titles = new CharSequence[values.length];
|
CharSequence[] titles = new CharSequence[values.length];
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
// titles[i] = values[i].title;
|
// titles[i] = values[i].title;
|
||||||
@ -145,102 +157,88 @@ public abstract class SponsorBlockUtils {
|
|||||||
new Thread(submitRunnable).start();
|
new Thread(submitRunnable).start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private static boolean isShown = false;
|
public static String messageToToast = "";
|
||||||
private static WeakReference<ImageView> sponsorBlockBtn = new WeakReference<>(null);
|
private static final EditByHandSaveDialogListener editByHandSaveDialogListener = new EditByHandSaveDialogListener();
|
||||||
private static String messageToToast = "";
|
private static final DialogInterface.OnClickListener editByHandDialogListener = (dialog, which) -> {
|
||||||
private static EditByHandSaveDialogListener editByHandSaveDialogListener = new EditByHandSaveDialogListener();
|
Context context = ((AlertDialog) dialog).getContext();
|
||||||
private static final DialogInterface.OnClickListener editByHandDialogListener = new DialogInterface.OnClickListener() {
|
|
||||||
@SuppressLint("DefaultLocale")
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
Context context = ((AlertDialog) dialog).getContext();
|
|
||||||
|
|
||||||
final boolean isStart = DialogInterface.BUTTON_NEGATIVE == which;
|
final boolean isStart = DialogInterface.BUTTON_NEGATIVE == which;
|
||||||
|
|
||||||
final EditText textView = new EditText(context);
|
final EditText textView = new EditText(context);
|
||||||
textView.setHint(DATE_FORMAT);
|
textView.setHint(DATE_FORMAT);
|
||||||
if (isStart) {
|
if (isStart) {
|
||||||
if (newSponsorSegmentStartMillis >= 0)
|
if (newSponsorSegmentStartMillis >= 0)
|
||||||
textView.setText(dateFormatter.format(new Date(newSponsorSegmentStartMillis)));
|
textView.setText(dateFormatter.format(new Date(newSponsorSegmentStartMillis)));
|
||||||
} else {
|
} else {
|
||||||
if (newSponsorSegmentEndMillis >= 0)
|
if (newSponsorSegmentEndMillis >= 0)
|
||||||
textView.setText(dateFormatter.format(new Date(newSponsorSegmentEndMillis)));
|
textView.setText(dateFormatter.format(new Date(newSponsorSegmentEndMillis)));
|
||||||
}
|
|
||||||
|
|
||||||
editByHandSaveDialogListener.settingStart = isStart;
|
|
||||||
editByHandSaveDialogListener.editText = new WeakReference<>(textView);
|
|
||||||
new AlertDialog.Builder(context)
|
|
||||||
.setTitle(str(isStart ? "new_segment_time_start" : "new_segment_time_end"))
|
|
||||||
.setView(textView)
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.setNeutralButton(str("new_segment_now"), editByHandSaveDialogListener)
|
|
||||||
.setPositiveButton(android.R.string.ok, editByHandSaveDialogListener)
|
|
||||||
.show();
|
|
||||||
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editByHandSaveDialogListener.settingStart = isStart;
|
||||||
|
editByHandSaveDialogListener.editText = new WeakReference<>(textView);
|
||||||
|
new AlertDialog.Builder(context)
|
||||||
|
.setTitle(str(isStart ? "new_segment_time_start" : "new_segment_time_end"))
|
||||||
|
.setView(textView)
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.setNeutralButton(str("new_segment_now"), editByHandSaveDialogListener)
|
||||||
|
.setPositiveButton(android.R.string.ok, editByHandSaveDialogListener)
|
||||||
|
.show();
|
||||||
|
|
||||||
|
dialog.dismiss();
|
||||||
};
|
};
|
||||||
private static Runnable toastRunnable = new Runnable() {
|
private static final Runnable toastRunnable = () -> {
|
||||||
@Override
|
Context context = appContext.get();
|
||||||
public void run() {
|
if (context != null && messageToToast != null)
|
||||||
Context context = appContext.get();
|
Toast.makeText(context, messageToToast, Toast.LENGTH_LONG).show();
|
||||||
if (context != null && messageToToast != null)
|
|
||||||
Toast.makeText(context, messageToToast, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
private static final Runnable submitRunnable = new Runnable() {
|
private static final DialogInterface.OnClickListener segmentVoteClickListener = (dialog, which) -> {
|
||||||
@Override
|
final Context context = ((AlertDialog) dialog).getContext();
|
||||||
public void run() {
|
final SponsorSegment segment = sponsorSegmentsOfCurrentVideo[which];
|
||||||
messageToToast = null;
|
|
||||||
final String uuid = SponsorBlockSettings.uuid;
|
|
||||||
final long start = newSponsorSegmentStartMillis;
|
|
||||||
final long end = newSponsorSegmentEndMillis;
|
|
||||||
final String videoId = getCurrentVideoId();
|
|
||||||
final SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockUtils.newSponsorBlockSegmentType;
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (start < 0 || end < 0 || start >= end || segmentType == null || videoId == null || uuid == null) {
|
final VoteOption[] voteOptions = VoteOption.values();
|
||||||
Log.e(TAG, "Unable to submit times, invalid parameters");
|
String[] items = new String[voteOptions.length];
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
URL url = new URL(String.format(Locale.US,
|
for (int i = 0; i < voteOptions.length; i++) {
|
||||||
sponsorBlockSkipSegmentsUrl + "?videoID=%s&userID=%s&startTime=%.3f&endTime=%.3f&category=%s",
|
items[i] = voteOptions[i].title;
|
||||||
videoId, uuid, ((float) start) / 1000f, ((float) end) / 1000f, segmentType.key));
|
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
switch (connection.getResponseCode()) {
|
|
||||||
default:
|
|
||||||
messageToToast = String.format(str("submit_failed_unknown_error"), connection.getResponseCode(), connection.getResponseMessage());
|
|
||||||
break;
|
|
||||||
case 429:
|
|
||||||
messageToToast = str("submit_failed_rate_limit");
|
|
||||||
break;
|
|
||||||
case 403:
|
|
||||||
messageToToast = str("submit_failed_forbidden");
|
|
||||||
break;
|
|
||||||
case 409:
|
|
||||||
messageToToast = str("submit_failed_duplicate");
|
|
||||||
break;
|
|
||||||
case 200:
|
|
||||||
messageToToast = str("submit_succeeded");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.i(TAG, "Segment submitted with status: " + connection.getResponseCode() + ", " + messageToToast);
|
|
||||||
new Handler(Looper.getMainLooper()).post(toastRunnable);
|
|
||||||
|
|
||||||
connection.disconnect();
|
|
||||||
|
|
||||||
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = -1;
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Unable to submit segment", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (videoId != null)
|
|
||||||
PlayerController.executeDownloadSegments(videoId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new AlertDialog.Builder(context)
|
||||||
|
.setItems(items, (dialog1, which1) -> {
|
||||||
|
appContext = new WeakReference<>(context.getApplicationContext());
|
||||||
|
switch (voteOptions[which1]) {
|
||||||
|
case UPVOTE:
|
||||||
|
voteForSegment(segment, VoteOption.UPVOTE, appContext.get(), toastRunnable);
|
||||||
|
break;
|
||||||
|
case DOWNVOTE:
|
||||||
|
voteForSegment(segment, VoteOption.DOWNVOTE, appContext.get(), toastRunnable);
|
||||||
|
break;
|
||||||
|
case CATEGORY_CHANGE:
|
||||||
|
onNewCategorySelect(segment, context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
};
|
||||||
|
private static final Runnable submitRunnable = () -> {
|
||||||
|
messageToToast = null;
|
||||||
|
final String uuid = SponsorBlockSettings.uuid;
|
||||||
|
final long start = newSponsorSegmentStartMillis;
|
||||||
|
final long end = newSponsorSegmentEndMillis;
|
||||||
|
final String videoId = getCurrentVideoId();
|
||||||
|
final SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockUtils.newSponsorBlockSegmentType;
|
||||||
|
try {
|
||||||
|
if (start < 0 || end < 0 || start >= end || segmentType == null || videoId == null || uuid == null) {
|
||||||
|
Log.e(TAG, "Unable to submit times, invalid parameters");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Requester.submitSegments(videoId, uuid, ((float) start) / 1000f, ((float) end) / 1000f, segmentType.key, toastRunnable);
|
||||||
|
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = -1;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Unable to submit segment", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoId != null)
|
||||||
|
PlayerController.executeDownloadSegments(videoId);
|
||||||
};
|
};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -250,21 +248,32 @@ public abstract class SponsorBlockUtils {
|
|||||||
private SponsorBlockUtils() {
|
private SponsorBlockUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showButton() {
|
public static void showShieldButton() {
|
||||||
if (isShown) return;
|
View i = ShieldButton._shieldBtn.get();
|
||||||
isShown = true;
|
if (i == null || !ShieldButton.shouldBeShown()) return;
|
||||||
View i = sponsorBlockBtn.get();
|
|
||||||
if (i == null) return;
|
|
||||||
i.setVisibility(VISIBLE);
|
i.setVisibility(VISIBLE);
|
||||||
i.bringToFront();
|
i.bringToFront();
|
||||||
i.requestLayout();
|
i.requestLayout();
|
||||||
i.invalidate();
|
i.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hideButton() {
|
public static void hideShieldButton() {
|
||||||
if (!isShown) return;
|
View i = ShieldButton._shieldBtn.get();
|
||||||
isShown = false;
|
if (i != null)
|
||||||
View i = sponsorBlockBtn.get();
|
i.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showVoteButton() {
|
||||||
|
View i = VotingButton._votingButton.get();
|
||||||
|
if (i == null || !VotingButton.shouldBeShown()) return;
|
||||||
|
i.setVisibility(VISIBLE);
|
||||||
|
i.bringToFront();
|
||||||
|
i.requestLayout();
|
||||||
|
i.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void hideVoteButton() {
|
||||||
|
View i = VotingButton._votingButton.get();
|
||||||
if (i != null)
|
if (i != null)
|
||||||
i.setVisibility(GONE);
|
i.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
@ -275,7 +284,7 @@ public abstract class SponsorBlockUtils {
|
|||||||
|
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setTitle(str("new_segment_title"))
|
.setTitle(str("new_segment_title"))
|
||||||
.setMessage(String.format(str("new_segment_mark_time_as_question"),
|
.setMessage(str("new_segment_mark_time_as_question",
|
||||||
newSponsorSegmentDialogShownMillis / 60000,
|
newSponsorSegmentDialogShownMillis / 60000,
|
||||||
newSponsorSegmentDialogShownMillis / 1000 % 60,
|
newSponsorSegmentDialogShownMillis / 1000 % 60,
|
||||||
newSponsorSegmentDialogShownMillis % 1000))
|
newSponsorSegmentDialogShownMillis % 1000))
|
||||||
@ -293,7 +302,7 @@ public abstract class SponsorBlockUtils {
|
|||||||
long end = (newSponsorSegmentEndMillis) / 1000;
|
long end = (newSponsorSegmentEndMillis) / 1000;
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setTitle(str("new_segment_confirm_title"))
|
.setTitle(str("new_segment_confirm_title"))
|
||||||
.setMessage(String.format(str("new_segment_confirm_content"),
|
.setMessage(str("new_segment_confirm_content",
|
||||||
start / 60, start % 60,
|
start / 60, start % 60,
|
||||||
end / 60, end % 60,
|
end / 60, end % 60,
|
||||||
length / 60, length % 60))
|
length / 60, length % 60))
|
||||||
@ -301,10 +310,51 @@ public abstract class SponsorBlockUtils {
|
|||||||
.setPositiveButton(android.R.string.yes, segmentReadyDialogButtonListener)
|
.setPositiveButton(android.R.string.yes, segmentReadyDialogButtonListener)
|
||||||
.show();
|
.show();
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, "Mark two locations on the time bar first", Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, str("new_segment_mark_locations_first"), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void onVotingClicked(final Context context) {
|
||||||
|
if (sponsorSegmentsOfCurrentVideo == null || sponsorSegmentsOfCurrentVideo.length == 0) {
|
||||||
|
Toast.makeText(context.getApplicationContext(), str("vote_no_segments"), Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int segmentAmount = sponsorSegmentsOfCurrentVideo.length;
|
||||||
|
List<CharSequence> titles = new ArrayList<>(segmentAmount); // I've replaced an array with a list to prevent null elements in the array as unsubmitted segments get filtered out
|
||||||
|
for (int i = 0; i < segmentAmount; i++) {
|
||||||
|
SponsorSegment segment = sponsorSegmentsOfCurrentVideo[i];
|
||||||
|
if (segment.category == SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String start = dateFormatter.format(new Date(segment.start));
|
||||||
|
String end = dateFormatter.format(new Date(segment.end));
|
||||||
|
StringBuilder htmlBuilder = new StringBuilder();
|
||||||
|
htmlBuilder.append(String.format("<b><font color=\"#%06X\">⬤</font> %s<br> %s to %s",
|
||||||
|
segment.category.color, segment.category.title, start, end));
|
||||||
|
if (i + 1 != segmentAmount) // prevents trailing new line after last segment
|
||||||
|
htmlBuilder.append("<br>");
|
||||||
|
titles.add(Html.fromHtml(htmlBuilder.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
new AlertDialog.Builder(context)
|
||||||
|
.setItems(titles.toArray(new CharSequence[0]), segmentVoteClickListener)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void onNewCategorySelect(final SponsorSegment segment, Context context) {
|
||||||
|
final SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
|
||||||
|
CharSequence[] titles = new CharSequence[values.length];
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
titles[i] = values[i].getTitleWithDot();
|
||||||
|
}
|
||||||
|
|
||||||
|
new AlertDialog.Builder(context)
|
||||||
|
.setTitle(str("new_segment_choose_category"))
|
||||||
|
.setItems(titles, (dialog, which) -> voteForSegment(segment, VoteOption.CATEGORY_CHANGE, appContext.get(), toastRunnable, values[which].key))
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
public static void onPreviewClicked(Context context) {
|
public static void onPreviewClicked(Context context) {
|
||||||
if (newSponsorSegmentStartMillis >= 0 && newSponsorSegmentStartMillis < newSponsorSegmentEndMillis) {
|
if (newSponsorSegmentStartMillis >= 0 && newSponsorSegmentStartMillis < newSponsorSegmentEndMillis) {
|
||||||
@ -316,7 +366,7 @@ public abstract class SponsorBlockUtils {
|
|||||||
final SponsorSegment[] segments = original == null ? new SponsorSegment[1] : Arrays.copyOf(original, original.length + 1);
|
final SponsorSegment[] segments = original == null ? new SponsorSegment[1] : Arrays.copyOf(original, original.length + 1);
|
||||||
|
|
||||||
segments[segments.length - 1] = new SponsorSegment(newSponsorSegmentStartMillis, newSponsorSegmentEndMillis,
|
segments[segments.length - 1] = new SponsorSegment(newSponsorSegmentStartMillis, newSponsorSegmentEndMillis,
|
||||||
SponsorBlockSettings.SegmentInfo.Preview, null);
|
SponsorBlockSettings.SegmentInfo.UNSUBMITTED, null);
|
||||||
|
|
||||||
Arrays.sort(segments);
|
Arrays.sort(segments);
|
||||||
sponsorSegmentsOfCurrentVideo = segments;
|
sponsorSegmentsOfCurrentVideo = segments;
|
||||||
@ -340,86 +390,134 @@ public abstract class SponsorBlockUtils {
|
|||||||
if (v.getId() != shareBtnId || !/*SponsorBlockSettings.isAddNewSegmentEnabled*/false) return;
|
if (v.getId() != shareBtnId || !/*SponsorBlockSettings.isAddNewSegmentEnabled*/false) return;
|
||||||
// if (VERBOSE)
|
// if (VERBOSE)
|
||||||
// Log.d(TAG, "VISIBILITY CHANGED of view " + v);
|
// Log.d(TAG, "VISIBILITY CHANGED of view " + v);
|
||||||
ImageView sponsorBtn = sponsorBlockBtn.get();
|
ImageView sponsorBtn = ShieldButton._shieldBtn.get();
|
||||||
if (sponsorBtn != null) {
|
if (sponsorBtn != null) {
|
||||||
sponsorBtn.setVisibility(v.getVisibility());
|
sponsorBtn.setVisibility(v.getVisibility());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized static SponsorSegment[] getSegmentsForVideo(String videoId) {
|
public static String appendTimeWithoutSegments(String totalTime) {
|
||||||
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = -1;
|
if (videoHasSegments && isSettingEnabled(showTimeWithoutSegments) && !TextUtils.isEmpty(totalTime)) {
|
||||||
|
if (timeWithoutSegments.isEmpty()) {
|
||||||
ArrayList<SponsorSegment> sponsorSegments = new ArrayList<>();
|
timeWithoutSegments = getTimeWithoutSegments(sponsorSegmentsOfCurrentVideo);
|
||||||
try {
|
|
||||||
if (VERBOSE)
|
|
||||||
Log.i(TAG, "Trying to download segments for videoId=" + videoId);
|
|
||||||
|
|
||||||
URL url = new URL(SponsorBlockSettings.getSponsorBlockUrlWithCategories(videoId));
|
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
||||||
switch (connection.getResponseCode()) {
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unable to download segments: Status: " + connection.getResponseCode() + " " + connection.getResponseMessage());
|
|
||||||
break;
|
|
||||||
case 404:
|
|
||||||
Log.w(TAG, "No segments for this video (ERR404)");
|
|
||||||
break;
|
|
||||||
case 200:
|
|
||||||
if (VERBOSE)
|
|
||||||
Log.i(TAG, "Received status 200 OK, parsing response...");
|
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
stringBuilder.append(line);
|
|
||||||
}
|
|
||||||
connection.getInputStream().close();
|
|
||||||
|
|
||||||
|
|
||||||
JSONArray responseArray = new JSONArray(stringBuilder.toString());
|
|
||||||
int length = responseArray.length();
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
JSONObject obj = ((JSONObject) responseArray.get(i));
|
|
||||||
JSONArray segments = obj.getJSONArray("segment");
|
|
||||||
long start = (long) (segments.getDouble(0) * 1000);
|
|
||||||
long end = (long) (segments.getDouble(1) * 1000);
|
|
||||||
String category = obj.getString("category");
|
|
||||||
String UUID = obj.getString("UUID");
|
|
||||||
|
|
||||||
SponsorBlockSettings.SegmentInfo segmentCategory = SponsorBlockSettings.SegmentInfo.byCategoryKey(category);
|
|
||||||
if (segmentCategory != null && segmentCategory.behaviour.showOnTimeBar) {
|
|
||||||
SponsorSegment segment = new SponsorSegment(start, end, segmentCategory, UUID);
|
|
||||||
sponsorSegments.add(segment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VERBOSE)
|
|
||||||
Log.v(TAG, "Parsing done");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return totalTime + timeWithoutSegments;
|
||||||
connection.disconnect();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "download segments failed", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sponsorSegments.toArray(new SponsorSegment[0]);
|
return totalTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendViewCountRequest(SponsorSegment segment) {
|
public static String getTimeWithoutSegments(SponsorSegment[] sponsorSegmentsOfCurrentVideo) {
|
||||||
|
long currentVideoLength = PlayerController.getCurrentVideoLength();
|
||||||
|
if (!isSettingEnabled(showTimeWithoutSegments) || sponsorSegmentsOfCurrentVideo == null || currentVideoLength == 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
long timeWithoutSegments = currentVideoLength + 500; // YouTube:tm:
|
||||||
|
for (SponsorSegment segment : sponsorSegmentsOfCurrentVideo) {
|
||||||
|
timeWithoutSegments -= segment.end - segment.start;
|
||||||
|
}
|
||||||
|
long hours = timeWithoutSegments / 3600000;
|
||||||
|
long minutes = (timeWithoutSegments / 60000) % 60;
|
||||||
|
long seconds = (timeWithoutSegments / 1000) % 60;
|
||||||
|
String format = (hours > 0 ? "%d:%02" : "%") + "d:%02d"; // mmLul
|
||||||
|
String formatted = hours > 0 ? String.format(format, hours, minutes, seconds) : String.format(format, minutes, seconds);
|
||||||
|
return String.format(" (%s)", formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playerTypeChanged(String playerType) {
|
||||||
try {
|
try {
|
||||||
URL url = new URL(SponsorBlockSettings.getSponsorBlockViewedUrl(segment.UUID));
|
if (videoHasSegments && (playerType.equalsIgnoreCase("NONE"))) {
|
||||||
|
PlayerController.setCurrentVideoId(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Log.e(TAG, "Player type changed caused a crash.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("sponsorblock", "requesting: " + url.getPath());
|
public static int countMatches(CharSequence seq, char c) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < seq.length(); i++) {
|
||||||
|
if (seq.charAt(i) == c)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
@SuppressWarnings("deprecation")
|
||||||
connection.setRequestMethod("POST");
|
public static void addUserStats(PreferenceCategory category, Preference loadingPreference, UserStats stats) {
|
||||||
connection.getInputStream().close();
|
category.removePreference(loadingPreference);
|
||||||
connection.disconnect();
|
|
||||||
} catch (IOException e) {
|
Context context = category.getContext();
|
||||||
e.printStackTrace();
|
|
||||||
|
{
|
||||||
|
EditTextPreference preference = new EditTextPreference(context);
|
||||||
|
category.addPreference(preference);
|
||||||
|
String userName = stats.getUserName();
|
||||||
|
preference.setTitle(fromHtml(str("stats_username", userName)));
|
||||||
|
preference.setSummary(str("stats_username_change"));
|
||||||
|
preference.setText(userName);
|
||||||
|
preference.setOnPreferenceChangeListener((preference1, newUsername) -> {
|
||||||
|
appContext = new WeakReference<>(context.getApplicationContext());
|
||||||
|
Requester.setUsername((String) newUsername, toastRunnable);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Preference preference = new Preference(context);
|
||||||
|
category.addPreference(preference);
|
||||||
|
String formatted = FORMATTER.format(stats.getSegmentCount());
|
||||||
|
preference.setTitle(fromHtml(str("stats_submissions", formatted)));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Preference preference = new Preference(context);
|
||||||
|
category.addPreference(preference);
|
||||||
|
String formatted = FORMATTER.format(stats.getViewCount());
|
||||||
|
|
||||||
|
double saved = stats.getMinutesSaved();
|
||||||
|
int hoursSaved = (int) (saved / 60);
|
||||||
|
double minutesSaved = saved % 60;
|
||||||
|
String formattedSaved = String.format(SAVED_TEMPLATE, hoursSaved, minutesSaved);
|
||||||
|
|
||||||
|
preference.setTitle(fromHtml(str("stats_saved", formatted)));
|
||||||
|
preference.setSummary(fromHtml(str("stats_saved_sum", formattedSaved)));
|
||||||
|
preference.setOnPreferenceClickListener(preference1 -> {
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse("https://sponsor.ajay.app/stats/"));
|
||||||
|
preference1.getContext().startActivity(i);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Preference preference = new Preference(context);
|
||||||
|
category.addPreference(preference);
|
||||||
|
String formatted = FORMATTER.format(skippedSegments);
|
||||||
|
|
||||||
|
long hoursSaved = skippedTime / 3600000;
|
||||||
|
double minutesSaved = (skippedTime / 60000d) % 60;
|
||||||
|
String formattedSaved = String.format(SAVED_TEMPLATE, hoursSaved, minutesSaved);
|
||||||
|
|
||||||
|
preference.setTitle(fromHtml(str("stats_self_saved", formatted)));
|
||||||
|
preference.setSummary(fromHtml(str("stats_self_saved_sum", formattedSaved)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSettingEnabled(boolean setting) {
|
||||||
|
return isSponsorBlockEnabled && setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VoteOption {
|
||||||
|
UPVOTE(str("vote_upvote")),
|
||||||
|
DOWNVOTE(str("vote_downvote")),
|
||||||
|
CATEGORY_CHANGE(str("vote_category"));
|
||||||
|
|
||||||
|
public final String title;
|
||||||
|
|
||||||
|
VoteOption(String title) {
|
||||||
|
this.title = title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,5 +553,4 @@ public abstract class SponsorBlockUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public class StringRef {
|
|||||||
packageName = context.getPackageName();
|
packageName = context.getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HashMap<String, StringRef> strings = new HashMap<>();
|
private static final HashMap<String, StringRef> strings = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets strings reference from shared collection or creates if not exists yet,
|
* Gets strings reference from shared collection or creates if not exists yet,
|
||||||
@ -52,6 +52,18 @@ public class StringRef {
|
|||||||
return sf(id).toString();
|
return sf(id).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets string value by string id, shorthand for <code>sf(id).toString()</code> and formats the string
|
||||||
|
* with given args.
|
||||||
|
* @param id string resource name/id
|
||||||
|
* @param args the args to format the string with
|
||||||
|
* @return String value from string.xml formatted with given args
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String str(@NonNull String id, Object... args) {
|
||||||
|
return String.format(str(id), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a StringRef object that'll not change it's value
|
* Creates a StringRef object that'll not change it's value
|
||||||
|
122
integrations/java/pl/jakubweg/VotingButton.java
Normal file
122
integrations/java/pl/jakubweg/VotingButton.java
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
package pl.jakubweg;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import com.google.android.apps.youtube.app.YouTubeTikTokRoot_Application;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import static fi.razerman.youtube.XGlobals.debug;
|
||||||
|
import static pl.jakubweg.PlayerController.getCurrentVideoLength;
|
||||||
|
import static pl.jakubweg.PlayerController.getLastKnownVideoTime;
|
||||||
|
|
||||||
|
public class VotingButton {
|
||||||
|
static String TAG = "VOTING";
|
||||||
|
static RelativeLayout _youtubeControlsLayout;
|
||||||
|
static WeakReference<ImageView> _votingButton = new WeakReference<>(null);
|
||||||
|
static int fadeDurationFast;
|
||||||
|
static int fadeDurationScheduled;
|
||||||
|
static Animation fadeIn;
|
||||||
|
static Animation fadeOut;
|
||||||
|
static boolean isShowing;
|
||||||
|
|
||||||
|
public static void initialize(Object viewStub) {
|
||||||
|
try {
|
||||||
|
if(debug){
|
||||||
|
Log.d(TAG, "initializing voting button");
|
||||||
|
}
|
||||||
|
|
||||||
|
_youtubeControlsLayout = (RelativeLayout) viewStub;
|
||||||
|
|
||||||
|
ImageView imageView = (ImageView)_youtubeControlsLayout
|
||||||
|
.findViewById(getIdentifier("voting_button", "id"));
|
||||||
|
|
||||||
|
if (debug && imageView == null){
|
||||||
|
Log.d(TAG, "Couldn't find imageView with tag \"voting_button\"");
|
||||||
|
}
|
||||||
|
if (imageView == null) return;
|
||||||
|
imageView.setOnClickListener(SponsorBlockUtils.voteButtonListener);
|
||||||
|
_votingButton = new WeakReference<>(imageView);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
fadeDurationFast = getInteger("fade_duration_fast");
|
||||||
|
fadeDurationScheduled = getInteger("fade_duration_scheduled");
|
||||||
|
fadeIn = getAnimation("fade_in");
|
||||||
|
fadeIn.setDuration(fadeDurationFast);
|
||||||
|
fadeOut = getAnimation("fade_out");
|
||||||
|
fadeOut.setDuration(fadeDurationScheduled);
|
||||||
|
isShowing = true;
|
||||||
|
changeVisibilityImmediate(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Log.e(TAG, "Unable to set RelativeLayout", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
|
changeVisibility(visible, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeVisibilityNegatedImmediate(boolean visible) {
|
||||||
|
changeVisibility(!visible, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeVisibility(boolean visible) {
|
||||||
|
changeVisibility(visible, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeVisibility(boolean visible, boolean immediate) {
|
||||||
|
if (isShowing == visible) return;
|
||||||
|
isShowing = visible;
|
||||||
|
|
||||||
|
ImageView iView = _votingButton.get();
|
||||||
|
if (_youtubeControlsLayout == null || iView == null) return;
|
||||||
|
|
||||||
|
if (visible && shouldBeShown()) {
|
||||||
|
if (getLastKnownVideoTime() >= getCurrentVideoLength()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (debug) {
|
||||||
|
Log.d(TAG, "Fading in");
|
||||||
|
}
|
||||||
|
iView.setVisibility(View.VISIBLE);
|
||||||
|
if (!immediate)
|
||||||
|
iView.startAnimation(fadeIn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iView.getVisibility() == View.VISIBLE) {
|
||||||
|
if (debug) {
|
||||||
|
Log.d(TAG, "Fading out");
|
||||||
|
}
|
||||||
|
if (!immediate)
|
||||||
|
iView.startAnimation(fadeOut);
|
||||||
|
iView.setVisibility(shouldBeShown() ? View.INVISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean shouldBeShown() {
|
||||||
|
return SponsorBlockUtils.isSettingEnabled(SponsorBlockSettings.isVotingEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
//region Helpers
|
||||||
|
private static int getIdentifier(String name, String defType) {
|
||||||
|
Context context = YouTubeTikTokRoot_Application.getAppContext();
|
||||||
|
return context.getResources().getIdentifier(name, defType, context.getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getInteger(String name) {
|
||||||
|
return YouTubeTikTokRoot_Application.getAppContext().getResources().getInteger(getIdentifier(name, "integer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Animation getAnimation(String name) {
|
||||||
|
return AnimationUtils.loadAnimation(YouTubeTikTokRoot_Application.getAppContext(), getIdentifier(name, "anim"));
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
package pl.jakubweg;
|
package pl.jakubweg.objects;
|
||||||
|
|
||||||
|
import pl.jakubweg.SponsorBlockSettings;
|
||||||
|
|
||||||
public class SponsorSegment implements Comparable<SponsorSegment> {
|
public class SponsorSegment implements Comparable<SponsorSegment> {
|
||||||
public final long start;
|
public final long start;
|
||||||
@ -26,5 +28,4 @@ public class SponsorSegment implements Comparable<SponsorSegment> {
|
|||||||
public int compareTo(SponsorSegment o) {
|
public int compareTo(SponsorSegment o) {
|
||||||
return (int) (this.start - o.start);
|
return (int) (this.start - o.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
31
integrations/java/pl/jakubweg/objects/UserStats.java
Normal file
31
integrations/java/pl/jakubweg/objects/UserStats.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package pl.jakubweg.objects;
|
||||||
|
|
||||||
|
public class UserStats {
|
||||||
|
private final String userName;
|
||||||
|
private final double minutesSaved;
|
||||||
|
private final int segmentCount;
|
||||||
|
private final int viewCount;
|
||||||
|
|
||||||
|
public UserStats(String userName, double minutesSaved, int segmentCount, int viewCount) {
|
||||||
|
this.userName = userName;
|
||||||
|
this.minutesSaved = minutesSaved;
|
||||||
|
this.segmentCount = segmentCount;
|
||||||
|
this.viewCount = viewCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName() {
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMinutesSaved() {
|
||||||
|
return minutesSaved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSegmentCount() {
|
||||||
|
return segmentCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getViewCount() {
|
||||||
|
return viewCount;
|
||||||
|
}
|
||||||
|
}
|
206
integrations/java/pl/jakubweg/requests/Requester.java
Normal file
206
integrations/java/pl/jakubweg/requests/Requester.java
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
package pl.jakubweg.requests;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.preference.PreferenceCategory;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import pl.jakubweg.SponsorBlockSettings;
|
||||||
|
import pl.jakubweg.SponsorBlockUtils;
|
||||||
|
import pl.jakubweg.SponsorBlockUtils.VoteOption;
|
||||||
|
import pl.jakubweg.objects.SponsorSegment;
|
||||||
|
import pl.jakubweg.objects.UserStats;
|
||||||
|
|
||||||
|
import static pl.jakubweg.SponsorBlockUtils.timeWithoutSegments;
|
||||||
|
import static pl.jakubweg.SponsorBlockUtils.videoHasSegments;
|
||||||
|
import static pl.jakubweg.StringRef.str;
|
||||||
|
|
||||||
|
public class Requester {
|
||||||
|
private static final String SPONSORBLOCK_API_URL = "https://sponsor.ajay.app/api/";
|
||||||
|
private static final String TIME_TEMPLATE = "%.3f";
|
||||||
|
|
||||||
|
private Requester() {}
|
||||||
|
|
||||||
|
public static synchronized SponsorSegment[] getSegments(String videoId) {
|
||||||
|
List<SponsorSegment> segments = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = getConnectionFromRoute(Route.GET_SEGMENTS, videoId, SponsorBlockSettings.sponsorBlockUrlCategories);
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
videoHasSegments = false;
|
||||||
|
timeWithoutSegments = "";
|
||||||
|
|
||||||
|
if (responseCode == 200) {
|
||||||
|
JSONArray responseArray = new JSONArray(parseJson(connection));
|
||||||
|
int length = responseArray.length();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
JSONObject obj = ((JSONObject) responseArray.get(i));
|
||||||
|
JSONArray segment = obj.getJSONArray("segment");
|
||||||
|
long start = (long) (segment.getDouble(0) * 1000);
|
||||||
|
long end = (long) (segment.getDouble(1) * 1000);
|
||||||
|
String category = obj.getString("category");
|
||||||
|
String uuid = obj.getString("UUID");
|
||||||
|
|
||||||
|
SponsorBlockSettings.SegmentInfo segmentCategory = SponsorBlockSettings.SegmentInfo.byCategoryKey(category);
|
||||||
|
if (segmentCategory != null && segmentCategory.behaviour.showOnTimeBar) {
|
||||||
|
SponsorSegment sponsorSegment = new SponsorSegment(start, end, segmentCategory, uuid);
|
||||||
|
segments.add(sponsorSegment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
videoHasSegments = true;
|
||||||
|
timeWithoutSegments = SponsorBlockUtils.getTimeWithoutSegments(segments.toArray(new SponsorSegment[0]));
|
||||||
|
}
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return segments.toArray(new SponsorSegment[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void submitSegments(String videoId, String uuid, float startTime, float endTime, String category, Runnable toastRunnable) {
|
||||||
|
try {
|
||||||
|
String start = String.format(TIME_TEMPLATE, startTime);
|
||||||
|
String end = String.format(TIME_TEMPLATE, endTime);
|
||||||
|
HttpURLConnection connection = getConnectionFromRoute(Route.SUBMIT_SEGMENTS, videoId, uuid, start, end, category);
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
|
||||||
|
switch (responseCode) {
|
||||||
|
case 200:
|
||||||
|
SponsorBlockUtils.messageToToast = str("submit_succeeded");
|
||||||
|
break;
|
||||||
|
case 409:
|
||||||
|
SponsorBlockUtils.messageToToast = str("submit_failed_duplicate");
|
||||||
|
break;
|
||||||
|
case 403:
|
||||||
|
SponsorBlockUtils.messageToToast = str("submit_failed_forbidden");
|
||||||
|
break;
|
||||||
|
case 429:
|
||||||
|
SponsorBlockUtils.messageToToast = str("submit_failed_rate_limit");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SponsorBlockUtils.messageToToast = str("submit_failed_unknown_error", responseCode, connection.getResponseMessage());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
new Handler(Looper.getMainLooper()).post(toastRunnable);
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendViewCountRequest(SponsorSegment segment) {
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = getConnectionFromRoute(Route.VIEWED_SEGMENT, segment.UUID);
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void voteForSegment(SponsorSegment segment, VoteOption voteOption, Context context, Runnable toastRunnable, String... args) {
|
||||||
|
try {
|
||||||
|
String segmentUuid = segment.UUID;
|
||||||
|
String uuid = SponsorBlockSettings.uuid;
|
||||||
|
String vote = Integer.toString(voteOption == VoteOption.UPVOTE ? 1 : 0);
|
||||||
|
|
||||||
|
Toast.makeText(context, str("vote_started"), Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
HttpURLConnection connection = voteOption == VoteOption.CATEGORY_CHANGE
|
||||||
|
? getConnectionFromRoute(Route.VOTE_ON_SEGMENT_CATEGORY, segmentUuid, uuid, args[0])
|
||||||
|
: getConnectionFromRoute(Route.VOTE_ON_SEGMENT_QUALITY, segmentUuid, uuid, vote);
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
|
||||||
|
switch (responseCode) {
|
||||||
|
case 200:
|
||||||
|
SponsorBlockUtils.messageToToast = str("vote_succeeded");
|
||||||
|
break;
|
||||||
|
case 403:
|
||||||
|
SponsorBlockUtils.messageToToast = str("vote_failed_forbidden");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SponsorBlockUtils.messageToToast = str("vote_failed_unknown_error", responseCode, connection.getResponseMessage());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
new Handler(Looper.getMainLooper()).post(toastRunnable);
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void retrieveUserStats(PreferenceCategory category, Preference loadingPreference) {
|
||||||
|
if (!SponsorBlockSettings.isSponsorBlockEnabled) {
|
||||||
|
loadingPreference.setTitle(str("stats_sb_disabled"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = getConnectionFromRoute(Route.GET_USER_STATS, SponsorBlockSettings.uuid);
|
||||||
|
JSONObject json = new JSONObject(parseJson(connection));
|
||||||
|
connection.disconnect();
|
||||||
|
UserStats stats = new UserStats(json.getString("userName"), json.getDouble("minutesSaved"), json.getInt("segmentCount"),
|
||||||
|
json.getInt("viewCount"));
|
||||||
|
SponsorBlockUtils.addUserStats(category, loadingPreference, stats);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUsername(String username, Runnable toastRunnable) {
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = getConnectionFromRoute(Route.CHANGE_USERNAME, SponsorBlockSettings.uuid, username);
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
|
||||||
|
if (responseCode == 200) {
|
||||||
|
SponsorBlockUtils.messageToToast = str("stats_username_changed");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SponsorBlockUtils.messageToToast = str("stats_username_change_unknown_error", responseCode, connection.getResponseMessage());
|
||||||
|
}
|
||||||
|
new Handler(Looper.getMainLooper()).post(toastRunnable);
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpURLConnection getConnectionFromRoute(Route route, String... params) throws IOException {
|
||||||
|
String url = SPONSORBLOCK_API_URL + route.compile(params).getCompiledRoute();
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
connection.setRequestMethod(route.getMethod().name());
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String parseJson(HttpURLConnection connection) throws IOException {
|
||||||
|
StringBuilder jsonBuilder = new StringBuilder();
|
||||||
|
InputStream inputStream = connection.getInputStream();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
jsonBuilder.append(line);
|
||||||
|
}
|
||||||
|
inputStream.close();
|
||||||
|
return jsonBuilder.toString();
|
||||||
|
}
|
||||||
|
}
|
73
integrations/java/pl/jakubweg/requests/Route.java
Normal file
73
integrations/java/pl/jakubweg/requests/Route.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package pl.jakubweg.requests;
|
||||||
|
|
||||||
|
import pl.jakubweg.SponsorBlockUtils;
|
||||||
|
|
||||||
|
import static pl.jakubweg.requests.Route.Method.*;
|
||||||
|
|
||||||
|
public class Route {
|
||||||
|
public static final Route GET_SEGMENTS = new Route(GET, "skipSegments?videoID={video_id}&categories={categories}");
|
||||||
|
public static final Route VIEWED_SEGMENT = new Route(POST, "viewedVideoSponsorTime?UUID={segment_id}");
|
||||||
|
public static final Route GET_USER_STATS = new Route(GET, "userInfo?userID={user_id}&values=[\"userName\", \"minutesSaved\", \"segmentCount\", \"viewCount\"]");
|
||||||
|
public static final Route CHANGE_USERNAME = new Route(POST, "setUsername?userID={user_id}&username={username}");
|
||||||
|
public static final Route SUBMIT_SEGMENTS = new Route(POST, "skipSegments?videoID={video_id}&userID={user_id}&startTime={start_time}&endTime={end_time}&category={category}");
|
||||||
|
public static final Route VOTE_ON_SEGMENT_QUALITY = new Route(POST, "voteOnSponsorTime?UUID={segment_id}&userID={user_id}&type={type}");
|
||||||
|
public static final Route VOTE_ON_SEGMENT_CATEGORY = new Route(POST, "voteOnSponsorTime?UUID={segment_id}&userID={user_id}&category={category}");
|
||||||
|
|
||||||
|
private final String route;
|
||||||
|
private final Method method;
|
||||||
|
private final int paramCount;
|
||||||
|
|
||||||
|
private Route(Method method, String route) {
|
||||||
|
this.method = method;
|
||||||
|
this.route = route;
|
||||||
|
this.paramCount = SponsorBlockUtils.countMatches(route, '{');
|
||||||
|
|
||||||
|
if (paramCount != SponsorBlockUtils.countMatches(route, '}'))
|
||||||
|
throw new IllegalArgumentException("Not enough parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompiledRoute compile(String... params) {
|
||||||
|
if (params.length != paramCount)
|
||||||
|
throw new IllegalArgumentException("Error compiling route [" + route + "], incorrect amount of parameters provided. " +
|
||||||
|
"Expected: " + paramCount + ", provided: " + params.length);
|
||||||
|
|
||||||
|
StringBuilder compiledRoute = new StringBuilder(route);
|
||||||
|
for (int i = 0; i < paramCount; i++) {
|
||||||
|
int paramStart = compiledRoute.indexOf("{");
|
||||||
|
int paramEnd = compiledRoute.indexOf("}");
|
||||||
|
compiledRoute.replace(paramStart, paramEnd + 1, params[i]);
|
||||||
|
}
|
||||||
|
return new CompiledRoute(this, compiledRoute.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CompiledRoute {
|
||||||
|
private final Route baseRoute;
|
||||||
|
private final String compiledRoute;
|
||||||
|
|
||||||
|
private CompiledRoute(Route baseRoute, String compiledRoute) {
|
||||||
|
this.baseRoute = baseRoute;
|
||||||
|
this.compiledRoute = compiledRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Route getBaseRoute() {
|
||||||
|
return baseRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCompiledRoute() {
|
||||||
|
return compiledRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getMethod() {
|
||||||
|
return baseRoute.method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Method {
|
||||||
|
GET,
|
||||||
|
POST
|
||||||
|
}
|
||||||
|
}
|
5
integrations/res/drawable/ic_sb_voting.xml
Normal file
5
integrations/res/drawable/ic_sb_voting.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,6c0,-0.55 -0.45,-1 -1,-1L5.82,5l0.66,-3.18 0.02,-0.23c0,-0.31 -0.13,-0.59 -0.33,-0.8L5.38,0 0.44,4.94C0.17,5.21 0,5.59 0,6v6.5c0,0.83 0.67,1.5 1.5,1.5h6.75c0.62,0 1.15,-0.38 1.38,-0.91l2.26,-5.29c0.07,-0.17 0.11,-0.36 0.11,-0.55L12,6zM22.5,10h-6.75c-0.62,0 -1.15,0.38 -1.38,0.91l-2.26,5.29c-0.07,0.17 -0.11,0.36 -0.11,0.55L12,18c0,0.55 0.45,1 1,1h5.18l-0.66,3.18 -0.02,0.24c0,0.31 0.13,0.59 0.33,0.8l0.79,0.78 4.94,-4.94c0.27,-0.27 0.44,-0.65 0.44,-1.06v-6.5c0,-0.83 -0.67,-1.5 -1.5,-1.5z"/>
|
||||||
|
</vector>
|
@ -143,12 +143,16 @@
|
|||||||
<string name="enable_sb_sum">Switch this on for very cool sponsor segments skipping</string>
|
<string name="enable_sb_sum">Switch this on for very cool sponsor segments skipping</string>
|
||||||
<string name="enable_segmadding">Enable new segment adding</string>
|
<string name="enable_segmadding">Enable new segment adding</string>
|
||||||
<string name="enable_segmadding_sum">Switch this on to enable experimental segment adding (has button visibility issues).</string>
|
<string name="enable_segmadding_sum">Switch this on to enable experimental segment adding (has button visibility issues).</string>
|
||||||
|
<string name="enable_voting">Enable voting</string>
|
||||||
|
<string name="enable_voting_sum">Switch this on to enable voting.</string>
|
||||||
<string name="diff_segments">What to do with different segments</string>
|
<string name="diff_segments">What to do with different segments</string>
|
||||||
<string name="general">General</string>
|
<string name="general">General</string>
|
||||||
<string name="general_skiptoast">Show a toast when skipping segment automatically</string>
|
<string name="general_skiptoast">Show a toast when skipping segment automatically</string>
|
||||||
<string name="general_skiptoast_sum">Click to see an example toast</string>
|
<string name="general_skiptoast_sum">Click to see an example toast</string>
|
||||||
<string name="general_skipcount">Skip count tracking</string>
|
<string name="general_skipcount">Skip count tracking</string>
|
||||||
<string name="general_skipcount_sum">This lets SponsorBlock leaderboard system know how much time people have saved. The extension sends a message to the server each time you skip a segment.</string>
|
<string name="general_skipcount_sum">This lets SponsorBlock leaderboard system know how much time people have saved. The extension sends a message to the server each time you skip a segment.</string>
|
||||||
|
<string name="general_time_without_sb">Show time without segments</string>
|
||||||
|
<string name="general_time_without_sb_sum">This time appears in brackets next to the current time. This shows the total video duration minus any segments.</string>
|
||||||
<string name="general_adjusting">Adjusting new segment step</string>
|
<string name="general_adjusting">Adjusting new segment step</string>
|
||||||
<string name="general_adjusting_sum">This is the number of milliseconds you can move when you use the time adjustment buttons while adding new segment</string>
|
<string name="general_adjusting_sum">This is the number of milliseconds you can move when you use the time adjustment buttons while adding new segment</string>
|
||||||
<string name="general_uuid">Your unique user id</string>
|
<string name="general_uuid">Your unique user id</string>
|
||||||
@ -165,6 +169,8 @@
|
|||||||
<string name="segments_selfpromo_sum">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="segments_selfpromo_sum">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="segments_nomusic">Music: Non-Music Section</string>
|
<string name="segments_nomusic">Music: Non-Music Section</string>
|
||||||
<string name="segments_nomusic_sum">Only for use in music videos. This includes introductions or outros in music videos</string>
|
<string name="segments_nomusic_sum">Only for use in music videos. This includes introductions or outros in music videos</string>
|
||||||
|
<string name="segments_preview">Preview/Recap</string>
|
||||||
|
<string name="segments_preview_sum">Quick recap of previous episodes, or a preview of what\'s coming up later in the current video. Meant for edited together clips, not for spoken summaries.</string>
|
||||||
<string name="skipped_sponsor">Skipped sponsor</string>
|
<string name="skipped_sponsor">Skipped sponsor</string>
|
||||||
<string name="skipped_intermission">Skipped intro</string>
|
<string name="skipped_intermission">Skipped intro</string>
|
||||||
<string name="skipped_endcard">Skipped outro</string>
|
<string name="skipped_endcard">Skipped outro</string>
|
||||||
@ -172,12 +178,27 @@
|
|||||||
<string name="skipped_selfpromo">Skipped self promotion</string>
|
<string name="skipped_selfpromo">Skipped self promotion</string>
|
||||||
<string name="skipped_nomusic">Skipped silence</string>
|
<string name="skipped_nomusic">Skipped silence</string>
|
||||||
<string name="skipped_preview">Skipped preview</string>
|
<string name="skipped_preview">Skipped preview</string>
|
||||||
|
<string name="skipped_unsubmitted">Skipped unsubmitted segment</string>
|
||||||
<string name="skip_automatically">Skip automatically</string>
|
<string name="skip_automatically">Skip automatically</string>
|
||||||
<string name="skip_showbutton">Show a skip button</string>
|
<string name="skip_showbutton">Show a skip button</string>
|
||||||
<string name="skip_ignore">Don\'t do anything</string>
|
<string name="skip_ignore">Don\'t do anything</string>
|
||||||
|
|
||||||
|
<string name="stats">Stats</string>
|
||||||
|
<string name="stats_loading">Loading..</string>
|
||||||
|
<string name="stats_sb_disabled">SponsorBlock is disabled</string>
|
||||||
|
<string name="stats_username" formatted="false">Your username: <b>%s</b></string>
|
||||||
|
<string name="stats_username_change">Click to change your username</string>
|
||||||
|
<string name="stats_username_change_unknown_error" formatted="false">Unable to change username: Status: %d %s</string>
|
||||||
|
<string name="stats_username_changed">Username changed successfully</string>
|
||||||
|
<string name="stats_submissions" formatted="false">Submissions: <b>%s</b></string>
|
||||||
|
<string name="stats_saved" formatted="false">You\'ve saved people from <b>%s</b> segments.</string>
|
||||||
|
<string name="stats_saved_sum" formatted="false">That\'s <b>%s</b> of their lives. Click to see the leaderboard</string>
|
||||||
|
<string name="stats_self_saved" formatted="false">You\'ve skipped <b>%s</b> segments.</string>
|
||||||
|
<string name="stats_self_saved_sum" formatted="false">That\'s <b>%s</b>.</string>
|
||||||
|
|
||||||
<string name="about">About</string>
|
<string name="about">About</string>
|
||||||
<string name="about_api">This app uses the API from Sponsor Block</string>
|
<string name="about_api">This app uses the API from SponsorBlock</string>
|
||||||
<string name="about_api_sum">Tap to learn more at: sponsor.ajay.app</string>
|
<string name="about_api_sum">Tap to learn more, and see downloads for other platforms at: sponsor.ajay.app</string>
|
||||||
<string name="about_madeby">Integration made by JakubWeg</string>
|
<string name="about_madeby">Integration made by JakubWeg</string>
|
||||||
<string name="tap_skip">Tap to skip</string>
|
<string name="tap_skip">Tap to skip</string>
|
||||||
|
|
||||||
@ -188,6 +209,15 @@
|
|||||||
<string name="submit_succeeded">Segment submitted successfully</string>
|
<string name="submit_succeeded">Segment submitted successfully</string>
|
||||||
<string name="submit_started">Submitting segment…</string>
|
<string name="submit_started">Submitting segment…</string>
|
||||||
|
|
||||||
|
<string name="vote_failed_unknown_error" formatted="false">Unable to vote for segment: Status: %d %s</string>
|
||||||
|
<string name="vote_failed_forbidden">Can\'t vote for segment.\nA moderator has decided that this segment is correct</string>
|
||||||
|
<string name="vote_succeeded">Voted successfully</string>
|
||||||
|
<string name="vote_started">Voting for segment…</string>
|
||||||
|
<string name="vote_upvote">Upvote</string>
|
||||||
|
<string name="vote_downvote">Downvote</string>
|
||||||
|
<string name="vote_category">Change category</string>
|
||||||
|
<string name="vote_no_segments">There are no segments to vote for</string>
|
||||||
|
|
||||||
<string name="new_segment_choose_category">Choose the segment category</string>
|
<string name="new_segment_choose_category">Choose the segment category</string>
|
||||||
<string name="new_segment_disabled_category">You\'ve disabled this category in the settings, enable it to be able to submit</string>
|
<string name="new_segment_disabled_category">You\'ve disabled this category in the settings, enable it to be able to submit</string>
|
||||||
<string name="new_segment_title">New Sponsor Block segment</string>
|
<string name="new_segment_title">New Sponsor Block segment</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user