2020-08-24 17:47:57 +02:00
package pl.jakubweg ;
2021-07-30 19:30:00 +02:00
import static android.text.Html.fromHtml ;
import static android.view.View.GONE ;
import static android.view.View.VISIBLE ;
import static fi.razerman.youtube.XGlobals.debug ;
import static pl.jakubweg.PlayerController.getCurrentVideoId ;
import static pl.jakubweg.PlayerController.getCurrentVideoLength ;
import static pl.jakubweg.PlayerController.getLastKnownVideoTime ;
import static pl.jakubweg.PlayerController.sponsorSegmentsOfCurrentVideo ;
import static pl.jakubweg.SponsorBlockPreferenceFragment.FORMATTER ;
import static pl.jakubweg.SponsorBlockPreferenceFragment.SAVED_TEMPLATE ;
2022-02-07 16:29:42 +01:00
import static pl.jakubweg.SponsorBlockSettings.DEFAULT_API_URL ;
import static pl.jakubweg.SponsorBlockSettings.DEFAULT_SERVER_URL ;
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_API_URL ;
2021-07-30 19:30:00 +02:00
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX ;
2021-08-03 16:23:44 +02:00
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_COUNT_SKIPS ;
2022-02-07 16:15:22 +01:00
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_IS_VIP ;
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_LAST_VIP_CHECK ;
2022-01-24 17:22:21 +01:00
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_MIN_DURATION ;
2021-08-03 16:23:44 +02:00
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_UUID ;
2022-01-27 23:05:46 +01:00
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_NAME ;
2022-02-07 16:29:42 +01:00
import static pl.jakubweg.SponsorBlockSettings.apiUrl ;
2021-08-03 16:23:44 +02:00
import static pl.jakubweg.SponsorBlockSettings.countSkips ;
import static pl.jakubweg.SponsorBlockSettings.getPreferences ;
2021-07-30 19:30:00 +02:00
import static pl.jakubweg.SponsorBlockSettings.isSponsorBlockEnabled ;
2022-02-07 16:15:22 +01:00
import static pl.jakubweg.SponsorBlockSettings.lastVipCheck ;
2022-01-24 17:22:21 +01:00
import static pl.jakubweg.SponsorBlockSettings.minDuration ;
2021-07-30 19:30:00 +02:00
import static pl.jakubweg.SponsorBlockSettings.showTimeWithoutSegments ;
2021-08-03 16:23:44 +02:00
import static pl.jakubweg.SponsorBlockSettings.showToastWhenSkippedAutomatically ;
2021-07-30 19:30:00 +02:00
import static pl.jakubweg.SponsorBlockSettings.skippedSegments ;
import static pl.jakubweg.SponsorBlockSettings.skippedTime ;
2021-08-03 16:23:44 +02:00
import static pl.jakubweg.SponsorBlockSettings.uuid ;
2022-02-07 16:15:22 +01:00
import static pl.jakubweg.SponsorBlockSettings.vip ;
2021-07-30 19:30:00 +02:00
import static pl.jakubweg.StringRef.str ;
2022-01-17 14:54:11 +01:00
import static pl.jakubweg.requests.SBRequester.voteForSegment ;
2021-07-30 19:30:00 +02:00
2020-08-24 17:47:57 +02:00
import android.annotation.SuppressLint ;
import android.app.AlertDialog ;
import android.content.Context ;
import android.content.DialogInterface ;
2021-07-23 14:56:54 +02:00
import android.content.Intent ;
2021-07-27 19:58:14 +02:00
import android.content.SharedPreferences ;
2021-07-23 14:56:54 +02:00
import android.net.Uri ;
import android.preference.EditTextPreference ;
import android.preference.Preference ;
import android.preference.PreferenceCategory ;
2021-04-22 18:43:14 +02:00
import android.text.Html ;
2021-07-24 00:24:51 +03:00
import android.text.TextUtils ;
2020-08-24 17:47:57 +02:00
import android.util.Log ;
import android.view.View ;
import android.widget.EditText ;
import android.widget.ImageView ;
import android.widget.Toast ;
2021-08-03 16:23:44 +02:00
import org.json.JSONArray ;
import org.json.JSONObject ;
2020-08-24 17:47:57 +02:00
import java.lang.ref.WeakReference ;
import java.text.ParseException ;
import java.text.SimpleDateFormat ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Date ;
2021-06-18 14:46:55 +02:00
import java.util.List ;
2020-08-24 17:47:57 +02:00
import java.util.Objects ;
import java.util.TimeZone ;
2022-01-27 23:05:46 +01:00
import fi.vanced.utils.SharedPrefUtils ;
2021-07-19 16:19:47 +02:00
import pl.jakubweg.objects.SponsorSegment ;
2021-07-23 14:56:54 +02:00
import pl.jakubweg.objects.UserStats ;
2022-01-17 14:54:11 +01:00
import pl.jakubweg.requests.SBRequester ;
2021-07-19 16:19:47 +02:00
2020-08-24 17:47:57 +02:00
@SuppressWarnings ( { " LongLogTag " } )
public abstract class SponsorBlockUtils {
public static final String TAG = " jakubweg.SponsorBlockUtils " ;
public static final String DATE_FORMAT = " HH:mm:ss.SSS " ;
@SuppressLint ( " SimpleDateFormat " )
public static final SimpleDateFormat dateFormatter = new SimpleDateFormat ( DATE_FORMAT ) ;
2021-07-23 23:50:57 +02:00
public static boolean videoHasSegments = false ;
public static String timeWithoutSegments = " " ;
2020-08-24 17:47:57 +02:00
private static final int sponsorBtnId = 1234 ;
2022-02-07 16:15:22 +01:00
private static final String LOCKED_COLOR = " #FFC83D " ;
2021-07-19 16:19:47 +02:00
public static final View . OnClickListener sponsorBlockBtnListener = v - > {
if ( debug ) {
Log . d ( TAG , " Shield button clicked " ) ;
2020-08-24 17:47:57 +02:00
}
2021-07-19 16:19:47 +02:00
NewSegmentHelperLayout . toggle ( ) ;
2020-08-24 17:47:57 +02:00
} ;
2021-07-19 16:19:47 +02:00
public static final View . OnClickListener voteButtonListener = v - > {
if ( debug ) {
Log . d ( TAG , " Vote button clicked " ) ;
2021-04-22 18:43:14 +02:00
}
2021-07-19 16:19:47 +02:00
SponsorBlockUtils . onVotingClicked ( v . getContext ( ) ) ;
2021-04-22 18:43:14 +02:00
} ;
2020-08-24 17:47:57 +02:00
private static int shareBtnId = - 1 ;
private static long newSponsorSegmentDialogShownMillis ;
private static long newSponsorSegmentStartMillis = - 1 ;
private static long newSponsorSegmentEndMillis = - 1 ;
private static final DialogInterface . OnClickListener newSponsorSegmentDialogListener = new DialogInterface . OnClickListener ( ) {
@SuppressLint ( " DefaultLocale " )
@Override
public void onClick ( DialogInterface dialog , int which ) {
Context context = ( ( AlertDialog ) dialog ) . getContext ( ) ;
switch ( which ) {
case DialogInterface . BUTTON_NEGATIVE :
// start
newSponsorSegmentStartMillis = newSponsorSegmentDialogShownMillis ;
2020-08-25 13:19:27 +02:00
Toast . makeText ( context . getApplicationContext ( ) , str ( " new_segment_time_start_set " ) , Toast . LENGTH_LONG ) . show ( ) ;
2020-08-24 17:47:57 +02:00
break ;
case DialogInterface . BUTTON_POSITIVE :
// end
newSponsorSegmentEndMillis = newSponsorSegmentDialogShownMillis ;
2020-08-25 13:19:27 +02:00
Toast . makeText ( context . getApplicationContext ( ) , str ( " new_segment_time_end_set " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2020-08-24 17:47:57 +02:00
break ;
}
dialog . dismiss ( ) ;
}
} ;
private static SponsorBlockSettings . SegmentInfo newSponsorBlockSegmentType ;
private static final DialogInterface . OnClickListener segmentTypeListener = new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
2021-06-18 14:46:55 +02:00
SponsorBlockSettings . SegmentInfo segmentType = SponsorBlockSettings . SegmentInfo . valuesWithoutUnsubmitted ( ) [ which ] ;
2020-08-24 17:47:57 +02:00
boolean enableButton ;
if ( ! segmentType . behaviour . showOnTimeBar ) {
Toast . makeText (
( ( AlertDialog ) dialog ) . getContext ( ) . getApplicationContext ( ) ,
2020-08-25 13:19:27 +02:00
str ( " new_segment_disabled_category " ) ,
2020-08-24 17:47:57 +02:00
Toast . LENGTH_SHORT ) . show ( ) ;
enableButton = false ;
} else {
Toast . makeText (
( ( AlertDialog ) dialog ) . getContext ( ) . getApplicationContext ( ) ,
2020-08-25 13:19:27 +02:00
segmentType . description . toString ( ) ,
2020-08-24 17:47:57 +02:00
Toast . LENGTH_SHORT ) . show ( ) ;
newSponsorBlockSegmentType = segmentType ;
enableButton = true ;
}
( ( AlertDialog ) dialog )
. getButton ( DialogInterface . BUTTON_POSITIVE )
. setEnabled ( enableButton ) ;
}
} ;
private static final DialogInterface . OnClickListener segmentReadyDialogButtonListener = new DialogInterface . OnClickListener ( ) {
@SuppressLint ( " DefaultLocale " )
@Override
public void onClick ( DialogInterface dialog , int which ) {
NewSegmentHelperLayout . hide ( ) ;
Context context = ( ( AlertDialog ) dialog ) . getContext ( ) ;
dialog . dismiss ( ) ;
2021-06-18 14:46:55 +02:00
SponsorBlockSettings . SegmentInfo [ ] values = SponsorBlockSettings . SegmentInfo . valuesWithoutUnsubmitted ( ) ;
2020-08-24 17:47:57 +02:00
CharSequence [ ] titles = new CharSequence [ values . length ] ;
for ( int i = 0 ; i < values . length ; i + + ) {
// titles[i] = values[i].title;
titles [ i ] = values [ i ] . getTitleWithDot ( ) ;
}
newSponsorBlockSegmentType = null ;
new AlertDialog . Builder ( context )
2020-08-25 13:19:27 +02:00
. setTitle ( str ( " new_segment_choose_category " ) )
2020-08-24 17:47:57 +02:00
. setSingleChoiceItems ( titles , - 1 , segmentTypeListener )
. setNegativeButton ( android . R . string . cancel , null )
. setPositiveButton ( android . R . string . ok , segmentCategorySelectedDialogListener )
. show ( )
. getButton ( DialogInterface . BUTTON_POSITIVE )
. setEnabled ( false ) ;
}
} ;
private static WeakReference < Context > appContext = new WeakReference < > ( null ) ;
private static final DialogInterface . OnClickListener segmentCategorySelectedDialogListener = new DialogInterface . OnClickListener ( ) {
@SuppressLint ( " DefaultLocale " )
@Override
public void onClick ( DialogInterface dialog , int which ) {
dialog . dismiss ( ) ;
Context context = ( ( AlertDialog ) dialog ) . getContext ( ) . getApplicationContext ( ) ;
2020-08-25 13:19:27 +02:00
Toast . makeText ( context , str ( " submit_started " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2020-08-24 17:47:57 +02:00
appContext = new WeakReference < > ( context ) ;
new Thread ( submitRunnable ) . start ( ) ;
}
} ;
2021-07-19 16:19:47 +02:00
public static String messageToToast = " " ;
private static final EditByHandSaveDialogListener editByHandSaveDialogListener = new EditByHandSaveDialogListener ( ) ;
private static final DialogInterface . OnClickListener editByHandDialogListener = ( dialog , which ) - > {
Context context = ( ( AlertDialog ) dialog ) . getContext ( ) ;
final boolean isStart = DialogInterface . BUTTON_NEGATIVE = = which ;
final EditText textView = new EditText ( context ) ;
textView . setHint ( DATE_FORMAT ) ;
if ( isStart ) {
if ( newSponsorSegmentStartMillis > = 0 )
textView . setText ( dateFormatter . format ( new Date ( newSponsorSegmentStartMillis ) ) ) ;
} else {
if ( newSponsorSegmentEndMillis > = 0 )
textView . setText ( dateFormatter . format ( new Date ( newSponsorSegmentEndMillis ) ) ) ;
}
2020-08-24 17:47:57 +02:00
2021-07-19 16:19:47 +02:00
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 ( ) ;
2020-08-24 17:47:57 +02:00
2021-07-19 16:19:47 +02:00
dialog . dismiss ( ) ;
2020-08-24 17:47:57 +02:00
} ;
2021-07-19 16:19:47 +02:00
private static final Runnable toastRunnable = ( ) - > {
Context context = appContext . get ( ) ;
if ( context ! = null & & messageToToast ! = null )
Toast . makeText ( context , messageToToast , Toast . LENGTH_LONG ) . show ( ) ;
} ;
private static final DialogInterface . OnClickListener segmentVoteClickListener = ( dialog , which ) - > {
final Context context = ( ( AlertDialog ) dialog ) . getContext ( ) ;
final SponsorSegment segment = sponsorSegmentsOfCurrentVideo [ which ] ;
2021-04-22 20:19:00 +02:00
2021-07-19 16:19:47 +02:00
final VoteOption [ ] voteOptions = VoteOption . values ( ) ;
2022-02-07 16:15:22 +01:00
CharSequence [ ] items = new CharSequence [ voteOptions . length ] ;
2021-04-22 20:19:00 +02:00
2021-07-19 16:19:47 +02:00
for ( int i = 0 ; i < voteOptions . length ; i + + ) {
2022-02-07 16:15:22 +01:00
VoteOption voteOption = voteOptions [ i ] ;
String title = voteOption . title ;
if ( vip & & segment . isLocked & & voteOption . shouldHighlight ) {
items [ i ] = Html . fromHtml ( String . format ( " <font color= \" %s \" >%s</font> " , LOCKED_COLOR , title ) ) ;
}
else {
items [ i ] = title ;
}
2021-04-22 18:43:14 +02:00
}
2020-08-24 17:47:57 +02:00
2021-07-19 16:19:47 +02:00
new AlertDialog . Builder ( context )
. setItems ( items , ( dialog1 , which1 ) - > {
appContext = new WeakReference < > ( context . getApplicationContext ( ) ) ;
2022-01-25 22:52:11 +01:00
VoteOption voteOption = voteOptions [ which1 ] ;
switch ( voteOption ) {
2021-07-19 16:19:47 +02:00
case UPVOTE :
case DOWNVOTE :
2022-01-25 22:52:11 +01:00
voteForSegment ( segment , voteOption , appContext . get ( ) ) ;
2021-07-19 16:19:47 +02:00
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 ;
2020-08-24 17:47:57 +02:00
}
2022-01-17 14:54:11 +01:00
SBRequester . submitSegments ( videoId , uuid , ( ( float ) start ) / 1000f , ( ( float ) end ) / 1000f , segmentType . key , toastRunnable ) ;
2021-07-19 16:19:47 +02:00
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = - 1 ;
} catch ( Exception e ) {
Log . e ( TAG , " Unable to submit segment " , e ) ;
2020-08-24 17:47:57 +02:00
}
2021-07-19 16:19:47 +02:00
if ( videoId ! = null )
PlayerController . executeDownloadSegments ( videoId ) ;
2020-08-24 17:47:57 +02:00
} ;
static {
dateFormatter . setTimeZone ( TimeZone . getTimeZone ( " UTC " ) ) ;
}
private SponsorBlockUtils ( ) {
}
2021-04-22 18:43:14 +02:00
public static void showShieldButton ( ) {
2021-04-28 22:39:23 +02:00
View i = ShieldButton . _shieldBtn . get ( ) ;
2021-04-29 23:05:23 +02:00
if ( i = = null | | ! ShieldButton . shouldBeShown ( ) ) return ;
2020-08-24 17:47:57 +02:00
i . setVisibility ( VISIBLE ) ;
i . bringToFront ( ) ;
i . requestLayout ( ) ;
i . invalidate ( ) ;
}
2021-04-22 18:43:14 +02:00
public static void hideShieldButton ( ) {
2021-04-28 22:39:23 +02:00
View i = ShieldButton . _shieldBtn . get ( ) ;
2020-08-24 17:47:57 +02:00
if ( i ! = null )
i . setVisibility ( GONE ) ;
}
2021-04-22 18:43:14 +02:00
public static void showVoteButton ( ) {
2021-04-28 22:39:23 +02:00
View i = VotingButton . _votingButton . get ( ) ;
2021-04-29 23:05:23 +02:00
if ( i = = null | | ! VotingButton . shouldBeShown ( ) ) return ;
2021-04-22 18:43:14 +02:00
i . setVisibility ( VISIBLE ) ;
i . bringToFront ( ) ;
i . requestLayout ( ) ;
i . invalidate ( ) ;
}
public static void hideVoteButton ( ) {
2021-04-28 22:39:23 +02:00
View i = VotingButton . _votingButton . get ( ) ;
2021-04-22 18:43:14 +02:00
if ( i ! = null )
i . setVisibility ( GONE ) ;
}
2020-08-24 17:47:57 +02:00
@SuppressLint ( " DefaultLocale " )
public static void onMarkLocationClicked ( Context context ) {
newSponsorSegmentDialogShownMillis = PlayerController . getLastKnownVideoTime ( ) ;
new AlertDialog . Builder ( context )
2020-08-25 13:19:27 +02:00
. setTitle ( str ( " new_segment_title " ) )
2021-07-19 21:51:26 +02:00
. setMessage ( str ( " new_segment_mark_time_as_question " ,
2020-08-24 17:47:57 +02:00
newSponsorSegmentDialogShownMillis / 60000 ,
newSponsorSegmentDialogShownMillis / 1000 % 60 ,
newSponsorSegmentDialogShownMillis % 1000 ) )
2020-08-25 13:19:27 +02:00
. setNeutralButton ( android . R . string . cancel , null )
. setNegativeButton ( str ( " new_segment_mark_start " ) , newSponsorSegmentDialogListener )
. setPositiveButton ( str ( " new_segment_mark_end " ) , newSponsorSegmentDialogListener )
2020-08-24 17:47:57 +02:00
. show ( ) ;
}
@SuppressLint ( " DefaultLocale " )
public static void onPublishClicked ( Context context ) {
if ( newSponsorSegmentStartMillis > = 0 & & newSponsorSegmentStartMillis < newSponsorSegmentEndMillis ) {
long length = ( newSponsorSegmentEndMillis - newSponsorSegmentStartMillis ) / 1000 ;
long start = ( newSponsorSegmentStartMillis ) / 1000 ;
long end = ( newSponsorSegmentEndMillis ) / 1000 ;
new AlertDialog . Builder ( context )
2020-08-25 13:19:27 +02:00
. setTitle ( str ( " new_segment_confirm_title " ) )
2021-07-19 21:51:26 +02:00
. setMessage ( str ( " new_segment_confirm_content " ,
2020-08-24 17:47:57 +02:00
start / 60 , start % 60 ,
end / 60 , end % 60 ,
length / 60 , length % 60 ) )
. setNegativeButton ( android . R . string . no , null )
. setPositiveButton ( android . R . string . yes , segmentReadyDialogButtonListener )
. show ( ) ;
} else {
2021-04-22 21:13:39 +02:00
Toast . makeText ( context , str ( " new_segment_mark_locations_first " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2020-08-24 17:47:57 +02:00
}
}
2021-04-22 18:43:14 +02:00
public static void onVotingClicked ( final Context context ) {
2021-04-25 15:20:31 +02:00
if ( sponsorSegmentsOfCurrentVideo = = null | | sponsorSegmentsOfCurrentVideo . length = = 0 ) {
Toast . makeText ( context . getApplicationContext ( ) , str ( " vote_no_segments " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2021-04-22 18:43:14 +02:00
return ;
2021-04-25 15:20:31 +02:00
}
2021-04-25 16:32:35 +02:00
int segmentAmount = sponsorSegmentsOfCurrentVideo . length ;
2021-06-18 14:46:55 +02:00
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
2021-04-25 16:32:35 +02:00
for ( int i = 0 ; i < segmentAmount ; i + + ) {
2021-04-22 18:43:14 +02:00
SponsorSegment segment = sponsorSegmentsOfCurrentVideo [ i ] ;
2021-07-19 17:32:06 +02:00
if ( segment . category = = SponsorBlockSettings . SegmentInfo . UNSUBMITTED ) {
2021-06-18 14:46:55 +02:00
continue ;
}
2021-04-22 18:43:14 +02:00
String start = dateFormatter . format ( new Date ( segment . start ) ) ;
String end = dateFormatter . format ( new Date ( segment . end ) ) ;
2021-04-25 16:32:35 +02:00
StringBuilder htmlBuilder = new StringBuilder ( ) ;
2021-07-24 20:22:31 +02:00
htmlBuilder . append ( String . format ( " <b><font color= \" #%06X \" >⬤</font> %s<br> %s to %s " ,
2021-04-22 18:43:14 +02:00
segment . category . color , segment . category . title , start , end ) ) ;
2021-04-25 16:32:35 +02:00
if ( i + 1 ! = segmentAmount ) // prevents trailing new line after last segment
htmlBuilder . append ( " <br> " ) ;
2021-06-18 14:46:55 +02:00
titles . add ( Html . fromHtml ( htmlBuilder . toString ( ) ) ) ;
2021-04-22 18:43:14 +02:00
}
new AlertDialog . Builder ( context )
2021-06-18 14:46:55 +02:00
. setItems ( titles . toArray ( new CharSequence [ 0 ] ) , segmentVoteClickListener )
2021-04-22 18:43:14 +02:00
. show ( ) ;
}
private static void onNewCategorySelect ( final SponsorSegment segment , Context context ) {
2021-06-18 14:46:55 +02:00
final SponsorBlockSettings . SegmentInfo [ ] values = SponsorBlockSettings . SegmentInfo . valuesWithoutUnsubmitted ( ) ;
2021-04-22 18:43:14 +02:00
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 " ) )
2022-01-24 13:45:07 +01:00
. setItems ( titles , ( dialog , which ) - > voteForSegment ( segment , VoteOption . CATEGORY_CHANGE , appContext . get ( ) , values [ which ] . key ) )
2021-04-22 18:43:14 +02:00
. show ( ) ;
}
2020-08-24 17:47:57 +02:00
@SuppressLint ( " DefaultLocale " )
public static void onPreviewClicked ( Context context ) {
if ( newSponsorSegmentStartMillis > = 0 & & newSponsorSegmentStartMillis < newSponsorSegmentEndMillis ) {
2020-08-25 13:19:27 +02:00
// Toast t = Toast.makeText(context, "Preview", Toast.LENGTH_SHORT);
// t.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP, t.getXOffset(), t.getYOffset());
// t.show();
2020-08-24 17:47:57 +02:00
PlayerController . skipToMillisecond ( newSponsorSegmentStartMillis - 3000 ) ;
final SponsorSegment [ ] original = PlayerController . sponsorSegmentsOfCurrentVideo ;
final SponsorSegment [ ] segments = original = = null ? new SponsorSegment [ 1 ] : Arrays . copyOf ( original , original . length + 1 ) ;
segments [ segments . length - 1 ] = new SponsorSegment ( newSponsorSegmentStartMillis , newSponsorSegmentEndMillis ,
2022-02-07 16:15:22 +01:00
SponsorBlockSettings . SegmentInfo . UNSUBMITTED , null , false ) ;
2020-08-24 17:47:57 +02:00
Arrays . sort ( segments ) ;
sponsorSegmentsOfCurrentVideo = segments ;
} else {
2020-08-25 13:19:27 +02:00
Toast . makeText ( context , str ( " new_segment_mark_locations_first " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2020-08-24 17:47:57 +02:00
}
}
@SuppressLint ( " DefaultLocale " )
public static void onEditByHandClicked ( Context context ) {
new AlertDialog . Builder ( context )
2020-08-25 13:19:27 +02:00
. setTitle ( str ( " new_segment_edit_by_hand_title " ) )
. setMessage ( str ( " new_segment_edit_by_hand_content " ) )
2020-08-24 17:47:57 +02:00
. setNeutralButton ( android . R . string . cancel , null )
2020-08-25 13:19:27 +02:00
. setNegativeButton ( str ( " new_segment_mark_start " ) , editByHandDialogListener )
. setPositiveButton ( str ( " new_segment_mark_end " ) , editByHandDialogListener )
2020-08-24 17:47:57 +02:00
. show ( ) ;
}
public static void notifyShareBtnVisibilityChanged ( View v ) {
2020-09-03 00:07:52 +03:00
if ( v . getId ( ) ! = shareBtnId | | ! /*SponsorBlockSettings.isAddNewSegmentEnabled*/ false ) return ;
2020-08-24 17:47:57 +02:00
// if (VERBOSE)
// Log.d(TAG, "VISIBILITY CHANGED of view " + v);
2021-04-28 22:39:23 +02:00
ImageView sponsorBtn = ShieldButton . _shieldBtn . get ( ) ;
2020-08-24 17:47:57 +02:00
if ( sponsorBtn ! = null ) {
sponsorBtn . setVisibility ( v . getVisibility ( ) ) ;
}
}
2021-07-23 23:50:57 +02:00
public static String appendTimeWithoutSegments ( String totalTime ) {
2021-07-31 20:03:09 +02:00
if ( videoHasSegments & & isSettingEnabled ( showTimeWithoutSegments ) & & ! TextUtils . isEmpty ( totalTime ) & & getCurrentVideoLength ( ) > 1 ) {
2021-07-26 00:13:33 +02:00
if ( timeWithoutSegments . isEmpty ( ) ) {
timeWithoutSegments = getTimeWithoutSegments ( sponsorSegmentsOfCurrentVideo ) ;
}
2021-07-23 23:50:57 +02:00
return totalTime + timeWithoutSegments ;
}
return totalTime ;
}
2021-07-26 00:13:33 +02:00
public static String getTimeWithoutSegments ( SponsorSegment [ ] sponsorSegmentsOfCurrentVideo ) {
2021-07-28 13:31:27 +02:00
long currentVideoLength = getCurrentVideoLength ( ) ;
2021-07-31 20:03:09 +02:00
if ( ! isSettingEnabled ( showTimeWithoutSegments ) | | sponsorSegmentsOfCurrentVideo = = null | | currentVideoLength < = 1 ) {
2021-07-23 23:50:57 +02:00
return " " ;
}
2021-07-26 00:13:33 +02:00
long timeWithoutSegments = currentVideoLength + 500 ; // YouTube:tm:
2021-07-23 23:50:57 +02:00
for ( SponsorSegment segment : sponsorSegmentsOfCurrentVideo ) {
timeWithoutSegments - = segment . end - segment . start ;
}
2021-07-24 20:14:47 +02:00
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 ) ;
2021-07-23 23:50:57 +02:00
}
public static void playerTypeChanged ( String playerType ) {
try {
if ( videoHasSegments & & ( playerType . equalsIgnoreCase ( " NONE " ) ) ) {
PlayerController . setCurrentVideoId ( null ) ;
}
}
catch ( Exception ex ) {
Log . e ( TAG , " Player type changed caused a crash. " , ex ) ;
}
}
2021-07-27 17:26:59 +02:00
public static String formatColorString ( int color ) {
return String . format ( " #%06X " , color ) ;
}
2021-07-23 14:56:54 +02:00
@SuppressWarnings ( " deprecation " )
public static void addUserStats ( PreferenceCategory category , Preference loadingPreference , UserStats stats ) {
category . removePreference ( loadingPreference ) ;
Context context = category . getContext ( ) ;
2021-07-30 19:30:00 +02:00
String minutesStr = str ( " minutes " ) ;
2021-07-23 14:56:54 +02:00
{
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 ) - > {
2021-07-24 18:53:59 +02:00
appContext = new WeakReference < > ( context . getApplicationContext ( ) ) ;
2022-01-24 13:45:07 +01:00
SBRequester . setUsername ( ( String ) newUsername , preference , toastRunnable ) ;
2021-07-23 14:56:54 +02:00
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 ;
2021-07-30 19:30:00 +02:00
String formattedSaved = String . format ( SAVED_TEMPLATE , hoursSaved , minutesSaved , minutesStr ) ;
2021-07-23 14:56:54 +02:00
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 ;
2021-07-30 19:30:00 +02:00
String formattedSaved = String . format ( SAVED_TEMPLATE , hoursSaved , minutesSaved , minutesStr ) ;
2021-07-23 14:56:54 +02:00
preference . setTitle ( fromHtml ( str ( " stats_self_saved " , formatted ) ) ) ;
preference . setSummary ( fromHtml ( str ( " stats_self_saved_sum " , formattedSaved ) ) ) ;
}
}
2021-08-03 16:23:44 +02:00
public static void importSettings ( String json , Context context ) {
try {
JSONObject settingsJson = new JSONObject ( json ) ;
JSONObject barTypesObject = settingsJson . getJSONObject ( " barTypes " ) ;
JSONArray categorySelectionsArray = settingsJson . getJSONArray ( " categorySelections " ) ;
SharedPreferences . Editor editor = getPreferences ( context ) . edit ( ) ;
SponsorBlockSettings . SegmentInfo [ ] categories = SponsorBlockSettings . SegmentInfo . valuesWithoutUnsubmitted ( ) ;
for ( SponsorBlockSettings . SegmentInfo category : categories ) {
String categoryKey = category . key ;
JSONObject categoryObject = barTypesObject . getJSONObject ( categoryKey ) ;
String color = categoryObject . getString ( " color " ) ;
editor . putString ( categoryKey + PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX , color ) ;
editor . putString ( categoryKey , SponsorBlockSettings . SegmentBehaviour . IGNORE . key ) ;
}
for ( int i = 0 ; i < categorySelectionsArray . length ( ) ; i + + ) {
JSONObject categorySelectionObject = categorySelectionsArray . getJSONObject ( i ) ;
String categoryKey = categorySelectionObject . getString ( " name " ) ;
SponsorBlockSettings . SegmentInfo category = SponsorBlockSettings . SegmentInfo . byCategoryKey ( categoryKey ) ;
2021-08-27 17:59:32 +02:00
if ( category = = null ) {
continue ;
}
2021-08-03 16:23:44 +02:00
int desktopKey = categorySelectionObject . getInt ( " option " ) ;
SponsorBlockSettings . SegmentBehaviour behaviour = SponsorBlockSettings . SegmentBehaviour . byDesktopKey ( desktopKey ) ;
editor . putString ( category . key , behaviour . key ) ;
}
editor . putBoolean ( PREFERENCES_KEY_SHOW_TOAST_WHEN_SKIP , ! settingsJson . getBoolean ( " dontShowNotice " ) ) ;
editor . putBoolean ( PREFERENCES_KEY_SHOW_TIME_WITHOUT_SEGMENTS , settingsJson . getBoolean ( " showTimeWithSkips " ) ) ;
editor . putBoolean ( PREFERENCES_KEY_COUNT_SKIPS , settingsJson . getBoolean ( " trackViewCount " ) ) ;
2022-02-07 16:15:22 +01:00
editor . putBoolean ( PREFERENCES_KEY_IS_VIP , settingsJson . getBoolean ( " isVip " ) ) ;
2022-01-24 17:22:21 +01:00
editor . putString ( PREFERENCES_KEY_MIN_DURATION , settingsJson . getString ( " minDuration " ) ) ;
2021-08-03 16:23:44 +02:00
editor . putString ( PREFERENCES_KEY_UUID , settingsJson . getString ( " userID " ) ) ;
2022-02-07 16:15:22 +01:00
editor . putString ( PREFERENCES_KEY_LAST_VIP_CHECK , settingsJson . getString ( " lastIsVipUpdate " ) ) ;
2022-02-07 16:29:42 +01:00
String serverAddress = settingsJson . getString ( " serverAddress " ) ;
if ( serverAddress . equalsIgnoreCase ( DEFAULT_SERVER_URL ) ) {
serverAddress = DEFAULT_API_URL ;
}
editor . putString ( PREFERENCES_KEY_API_URL , serverAddress ) ;
2021-08-03 16:23:44 +02:00
editor . apply ( ) ;
Toast . makeText ( context , str ( " settings_import_successful " ) , Toast . LENGTH_SHORT ) . show ( ) ;
}
catch ( Exception ex ) {
Toast . makeText ( context , str ( " settings_import_failed " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2021-08-03 19:22:12 +02:00
ex . printStackTrace ( ) ;
2021-08-03 16:23:44 +02:00
}
}
2021-08-03 16:38:38 +02:00
public static String exportSettings ( Context context ) {
2021-08-03 16:23:44 +02:00
try {
JSONObject json = new JSONObject ( ) ;
JSONObject barTypesObject = new JSONObject ( ) ; // categories' colors
JSONArray categorySelectionsArray = new JSONArray ( ) ; // categories' behavior
SponsorBlockSettings . SegmentInfo [ ] categories = SponsorBlockSettings . SegmentInfo . valuesWithoutUnsubmitted ( ) ;
for ( SponsorBlockSettings . SegmentInfo category : categories ) {
JSONObject categoryObject = new JSONObject ( ) ;
String categoryKey = category . key ;
categoryObject . put ( " color " , formatColorString ( category . color ) ) ;
barTypesObject . put ( categoryKey , categoryObject ) ;
int desktopKey = category . behaviour . desktopKey ;
if ( desktopKey ! = - 1 ) {
JSONObject behaviorObject = new JSONObject ( ) ;
behaviorObject . put ( " name " , categoryKey ) ;
behaviorObject . put ( " option " , desktopKey ) ;
categorySelectionsArray . put ( behaviorObject ) ;
}
}
json . put ( " dontShowNotice " , ! showToastWhenSkippedAutomatically ) ;
json . put ( " barTypes " , barTypesObject ) ;
json . put ( " showTimeWithSkips " , showTimeWithoutSegments ) ;
2022-01-24 17:22:21 +01:00
json . put ( " minDuration " , minDuration ) ;
2021-08-03 16:23:44 +02:00
json . put ( " trackViewCount " , countSkips ) ;
json . put ( " categorySelections " , categorySelectionsArray ) ;
json . put ( " userID " , uuid ) ;
2022-02-07 16:15:22 +01:00
json . put ( " isVip " , vip ) ;
json . put ( " lastIsVipUpdate " , lastVipCheck ) ;
2021-08-03 16:23:44 +02:00
2022-02-07 16:29:42 +01:00
String apiAddress = apiUrl ;
if ( apiAddress . equalsIgnoreCase ( DEFAULT_API_URL ) ) {
apiAddress = DEFAULT_SERVER_URL ;
}
json . put ( " serverAddress " , apiAddress ) ;
2021-08-03 16:23:44 +02:00
return json . toString ( ) ;
}
catch ( Exception ex ) {
2021-08-03 16:38:38 +02:00
Toast . makeText ( context , str ( " settings_export_failed " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2021-08-03 16:23:44 +02:00
ex . printStackTrace ( ) ;
return " " ;
}
}
2021-07-26 00:13:33 +02:00
public static boolean isSettingEnabled ( boolean setting ) {
return isSponsorBlockEnabled & & setting ;
}
2022-01-27 23:05:46 +01:00
public static boolean isSBButtonEnabled ( Context context , String key ) {
return isSettingEnabled ( SharedPrefUtils . getBoolean ( context , PREFERENCES_NAME , key , false ) ) ;
}
2021-07-19 16:19:47 +02:00
public enum VoteOption {
2022-02-07 16:15:22 +01:00
UPVOTE ( str ( " vote_upvote " ) , false ) ,
DOWNVOTE ( str ( " vote_downvote " ) , true ) ,
CATEGORY_CHANGE ( str ( " vote_category " ) , true ) ;
2021-04-22 20:19:00 +02:00
public final String title ;
2022-02-07 16:15:22 +01:00
public final boolean shouldHighlight ;
2021-04-22 20:19:00 +02:00
2022-02-07 16:15:22 +01:00
VoteOption ( String title , boolean shouldHighlight ) {
2021-04-22 20:19:00 +02:00
this . title = title ;
2022-02-07 16:15:22 +01:00
this . shouldHighlight = shouldHighlight ;
2021-04-22 20:19:00 +02:00
}
}
2020-08-24 17:47:57 +02:00
private static class EditByHandSaveDialogListener implements DialogInterface . OnClickListener {
public boolean settingStart ;
public WeakReference < EditText > editText ;
@SuppressLint ( " DefaultLocale " )
@Override
public void onClick ( DialogInterface dialog , int which ) {
final EditText editText = this . editText . get ( ) ;
if ( editText = = null ) return ;
Context context = ( ( AlertDialog ) dialog ) . getContext ( ) ;
try {
long time = ( which = = DialogInterface . BUTTON_NEUTRAL ) ?
getLastKnownVideoTime ( ) :
( Objects . requireNonNull ( dateFormatter . parse ( editText . getText ( ) . toString ( ) ) ) . getTime ( ) ) ;
if ( settingStart )
newSponsorSegmentStartMillis = Math . max ( time , 0 ) ;
else
newSponsorSegmentEndMillis = time ;
if ( which = = DialogInterface . BUTTON_NEUTRAL )
editByHandDialogListener . onClick ( dialog , settingStart ?
DialogInterface . BUTTON_NEGATIVE :
DialogInterface . BUTTON_POSITIVE ) ;
else
2020-08-25 13:19:27 +02:00
Toast . makeText ( context . getApplicationContext ( ) , str ( " new_segment_edit_by_hand_saved " ) , Toast . LENGTH_SHORT ) . show ( ) ;
2020-08-24 17:47:57 +02:00
} catch ( ParseException e ) {
2020-08-25 13:19:27 +02:00
Toast . makeText ( context . getApplicationContext ( ) , str ( " new_segment_edit_by_hand_parse_error " ) , Toast . LENGTH_LONG ) . show ( ) ;
2020-08-24 17:47:57 +02:00
}
}
}
}