@@ -28,8 +28,8 @@ enum SegmentListTab {
28
28
Chapter
29
29
}
30
30
31
- interface segmentWithNesting extends SponsorTime {
32
- innerChapters ?: ( segmentWithNesting | SponsorTime ) [ ] ;
31
+ interface SegmentWithNesting extends SponsorTime {
32
+ innerChapters ?: ( SegmentWithNesting | SponsorTime ) [ ] ;
33
33
}
34
34
35
35
export const SegmentListComponent = ( props : SegmentListComponentProps ) => {
@@ -58,37 +58,41 @@ export const SegmentListComponent = (props: SegmentListComponentProps) => {
58
58
}
59
59
} ;
60
60
61
- const segmentsWithNesting : segmentWithNesting [ ] = [ ] ;
62
- let nbTrailingNonChapters = 0 ;
63
- function nestChapters ( segments : segmentWithNesting [ ] , seg : SponsorTime , topLevel ?: boolean ) {
64
- if ( seg . actionType === ActionType . Chapter && segments . length ) {
65
- // trailing non-chapters can only exist at top level
66
- const lastElement = segments [ segments . length - ( topLevel ? nbTrailingNonChapters + 1 : 1 ) ]
67
-
68
- if ( lastElement . actionType === ActionType . Chapter
69
- && lastElement . segment [ 0 ] <= seg . segment [ 0 ]
70
- && lastElement . segment [ 1 ] >= seg . segment [ 1 ] ) {
71
- if ( lastElement . innerChapters ) {
72
- nestChapters ( lastElement . innerChapters , seg ) ;
61
+ const segmentsWithNesting = React . useMemo ( ( ) => {
62
+ const result : SegmentWithNesting [ ] = [ ] ;
63
+ let nbTrailingNonChapters = 0 ;
64
+ function nestChapters ( segments : SegmentWithNesting [ ] , seg : SponsorTime , topLevel ?: boolean ) {
65
+ if ( seg . actionType === ActionType . Chapter && segments . length ) {
66
+ // trailing non-chapters can only exist at top level
67
+ const lastElement = segments [ segments . length - ( topLevel ? nbTrailingNonChapters + 1 : 1 ) ]
68
+
69
+ if ( lastElement . actionType === ActionType . Chapter
70
+ && lastElement . segment [ 0 ] <= seg . segment [ 0 ]
71
+ && lastElement . segment [ 1 ] >= seg . segment [ 1 ] ) {
72
+ if ( lastElement . innerChapters ) {
73
+ nestChapters ( lastElement . innerChapters , seg ) ;
74
+ } else {
75
+ lastElement . innerChapters = [ seg ] ;
76
+ }
73
77
} else {
74
- lastElement . innerChapters = [ seg ] ;
75
- }
76
- } else {
77
- if ( topLevel ) {
78
- nbTrailingNonChapters = 0 ;
79
- }
78
+ if ( topLevel ) {
79
+ nbTrailingNonChapters = 0 ;
80
+ }
80
81
81
- segments . push ( seg ) ;
82
+ segments . push ( seg ) ;
83
+ }
84
+ } else {
85
+ if ( seg . actionType !== ActionType . Chapter ) {
86
+ nbTrailingNonChapters ++ ;
82
87
}
83
- } else {
84
- if ( seg . actionType !== ActionType . Chapter ) {
85
- nbTrailingNonChapters ++ ;
86
- }
87
88
88
- segments . push ( seg ) ;
89
+ segments . push ( seg ) ;
90
+ }
89
91
}
90
- }
91
- props . segments . forEach ( ( seg ) => nestChapters ( segmentsWithNesting , { ...seg } , true ) ) ;
92
+ props . segments . forEach ( ( seg ) => nestChapters ( result , { ...seg } , true ) ) ;
93
+ return result ;
94
+ } , [ props . segments ] )
95
+
92
96
93
97
return (
94
98
< div id = "issueReporterContainer" >
@@ -136,7 +140,7 @@ export const SegmentListComponent = (props: SegmentListComponentProps) => {
136
140
} ;
137
141
138
142
function SegmentListItem ( { segment, videoID, currentTime, isVip, loopedChapter, tabFilter, sendMessage } : {
139
- segment : segmentWithNesting ;
143
+ segment : SegmentWithNesting ;
140
144
videoID : VideoID ;
141
145
currentTime : number ;
142
146
isVip : boolean ;
@@ -146,18 +150,32 @@ function SegmentListItem({ segment, videoID, currentTime, isVip, loopedChapter,
146
150
sendMessage : ( request : Message ) => Promise < MessageResponse > ;
147
151
} ) {
148
152
const [ voteMessage , setVoteMessage ] = React . useState < string | null > ( null ) ;
149
- const [ hidden , setHidden ] = React . useState ( segment . hidden || SponsorHideType . Visible ) ;
153
+ const [ hidden , setHidden ] = React . useState ( segment . hidden ?? SponsorHideType . Visible ) ; // undefined ?? undefined lol
150
154
const [ isLooped , setIsLooped ] = React . useState ( loopedChapter === segment . UUID ) ;
151
155
152
- let extraInfo = "" ;
153
- if ( segment . hidden === SponsorHideType . Downvoted ) {
154
- // This one is downvoted
155
- extraInfo = " (" + chrome . i18n . getMessage ( "hiddenDueToDownvote" ) + ")" ;
156
- } else if ( segment . hidden === SponsorHideType . MinimumDuration ) {
157
- // This one is too short
158
- extraInfo = " (" + chrome . i18n . getMessage ( "hiddenDueToDuration" ) + ")" ;
159
- } else if ( segment . hidden === SponsorHideType . Hidden ) {
160
- extraInfo = " (" + chrome . i18n . getMessage ( "manuallyHidden" ) + ")" ;
156
+ // Update internal state if the hidden property of the segment changes
157
+ React . useEffect ( ( ) => {
158
+ setHidden ( segment . hidden ?? SponsorHideType . Visible ) ;
159
+ } , [ segment . hidden ] )
160
+
161
+ let extraInfo : string ;
162
+ switch ( hidden ) {
163
+ case SponsorHideType . Visible :
164
+ extraInfo = "" ;
165
+ break ;
166
+ case SponsorHideType . Downvoted :
167
+ extraInfo = " (" + chrome . i18n . getMessage ( "hiddenDueToDownvote" ) + ")" ;
168
+ break ;
169
+ case SponsorHideType . MinimumDuration :
170
+ extraInfo = " (" + chrome . i18n . getMessage ( "hiddenDueToDuration" ) + ")" ;
171
+ break ;
172
+ case SponsorHideType . Hidden :
173
+ extraInfo = " (" + chrome . i18n . getMessage ( "manuallyHidden" ) + ")" ;
174
+ break ;
175
+ default :
176
+ // hidden satisfies never; // need to upgrade TS
177
+ console . warn ( `[SB] Unhandled variant of SponsorHideType in SegmentListItem: ${ hidden } ` ) ;
178
+ extraInfo = "" ;
161
179
}
162
180
163
181
return (
@@ -279,7 +297,7 @@ function SegmentListItem({ segment, videoID, currentTime, isVip, loopedChapter,
279
297
{
280
298
( segment . actionType === ActionType . Skip || segment . actionType === ActionType . Mute
281
299
|| segment . actionType === ActionType . Poi
282
- && [ SponsorHideType . Visible , SponsorHideType . Hidden ] . includes ( segment . hidden ) ) &&
300
+ && [ SponsorHideType . Visible , SponsorHideType . Hidden ] . includes ( hidden ) ) &&
283
301
< img
284
302
className = "voteButton"
285
303
title = { chrome . i18n . getMessage ( "hideSegment" ) }
@@ -288,17 +306,11 @@ function SegmentListItem({ segment, videoID, currentTime, isVip, loopedChapter,
288
306
const stopAnimation = AnimationUtils . applyLoadingAnimation ( e . currentTarget , 0.4 ) ;
289
307
stopAnimation ( ) ;
290
308
291
- if ( segment . hidden === SponsorHideType . Hidden ) {
292
- segment . hidden = SponsorHideType . Visible ;
293
- setHidden ( SponsorHideType . Visible ) ;
294
- } else {
295
- segment . hidden = SponsorHideType . Hidden ;
296
- setHidden ( SponsorHideType . Hidden ) ;
297
- }
298
-
309
+ const newState = hidden === SponsorHideType . Hidden ? SponsorHideType . Visible : SponsorHideType . Hidden ;
310
+ setHidden ( newState ) ;
299
311
sendMessage ( {
300
312
message : "hideSegment" ,
301
- type : segment . hidden ,
313
+ type : newState ,
302
314
UUID : segment . UUID
303
315
} ) ;
304
316
} } />
@@ -343,7 +355,7 @@ function SegmentListItem({ segment, videoID, currentTime, isVip, loopedChapter,
343
355
}
344
356
345
357
function InnerChapterList ( { chapters, videoID, currentTime, isVip, loopedChapter, tabFilter, sendMessage } : {
346
- chapters : ( segmentWithNesting ) [ ] ;
358
+ chapters : ( SegmentWithNesting ) [ ] ;
347
359
videoID : VideoID ;
348
360
currentTime : number ;
349
361
isVip : boolean ;
0 commit comments