1
1
package app .revanced .extension .youtube .patches .overlaybutton ;
2
2
3
- import static app .revanced .extension .shared .utils .StringRef .str ;
4
- import static app .revanced .extension .shared .utils .Utils .showToastLong ;
5
- import static app .revanced .extension .shared .utils .Utils .showToastShort ;
6
-
7
- import android .app .AlertDialog ;
8
3
import android .content .Context ;
9
- import android .os .Build ;
10
- import android .os .Handler ;
11
- import android .os .Looper ;
12
- import android .text .TextUtils ;
13
4
import android .view .View ;
14
5
import android .view .ViewGroup ;
15
-
16
6
import androidx .annotation .Nullable ;
17
- import androidx .annotation .RequiresApi ;
18
-
19
7
import app .revanced .extension .shared .utils .Logger ;
20
8
import app .revanced .extension .youtube .settings .Settings ;
21
- import app .revanced .extension .youtube .utils .GeminiUtils ;
9
+ import app .revanced .extension .youtube .utils .GeminiManager ;
22
10
import app .revanced .extension .youtube .utils .VideoUtils ;
23
11
24
12
@ SuppressWarnings ("unused" )
25
13
public class GeminiSummarize extends BottomControlButton {
26
14
@ Nullable
27
15
private static GeminiSummarize instance ;
28
- @ Nullable
29
- private AlertDialog progressDialog ;
30
- private boolean isCancelled = false ;
31
-
32
- // Timer related variables
33
- private final Handler timerHandler ;
34
- private Runnable timerRunnable ;
35
- private long startTimeMillis ;
36
- private String baseLoadingMessage ;
37
- private int totalSummarizationTimeSeconds = -1 ;
38
16
39
17
public GeminiSummarize (ViewGroup bottomControlsViewGroup ) {
40
18
super (
41
19
bottomControlsViewGroup ,
42
20
"gemini_summarize_button" ,
43
21
Settings .OVERLAY_BUTTON_GEMINI_SUMMARIZE ,
44
22
view -> handleSummarizeClick (view .getContext ()),
45
- null
23
+ view -> {
24
+ handleTranscribeClick (view .getContext ());
25
+ return true ;
26
+ }
46
27
);
47
- timerHandler = new Handler (Looper .getMainLooper ());
48
28
}
49
29
50
- // region Generate Summary
51
- private static void handleSummarizeClick (Context context ) {
52
- if (instance == null ) return ;
53
-
54
- final String apiKey = Settings .GEMINI_API_KEY .get ();
55
- if (TextUtils .isEmpty (apiKey )) {
56
- showToastLong (str ("revanced_gemini_error_no_api_key" ));
30
+ public static void handleSummarizeClick (Context context ) {
31
+ if (instance == null ) {
32
+ Logger .printException (() -> "GeminiSummarize button instance is null, cannot proceed with summarize." );
57
33
return ;
58
34
}
59
-
60
35
final String videoUrl = VideoUtils .getVideoUrl (false );
61
- if (TextUtils .isEmpty (videoUrl ) || videoUrl .equals (VideoUtils .VIDEO_URL )) {
62
- showToastShort (str ("revanced_gemini_error_no_video" ));
63
- return ;
64
- }
65
-
66
- instance .isCancelled = false ;
67
- instance .totalSummarizationTimeSeconds = -1 ;
68
- instance .showProgressDialog (context );
69
-
70
- GeminiUtils .getVideoSummary (videoUrl , apiKey , new GeminiUtils .SummaryCallback () {
71
- @ RequiresApi (api = Build .VERSION_CODES .P )
72
- @ Override
73
- public void onSuccess (String summary ) {
74
- context .getMainExecutor ().execute (() -> {
75
- if (instance == null || instance .isCancelled ) {
76
- Logger .printDebug (() -> "Gemini request succeeded but was cancelled by user." );
77
- instance .dismissProgressDialog ();
78
- return ;
79
- }
80
- // Calculate total time *before* dismissing progress dialog
81
- long endTimeMillis = System .currentTimeMillis ();
82
- if (instance .startTimeMillis > 0 ) {
83
- long elapsedMillis = endTimeMillis - instance .startTimeMillis ;
84
- instance .totalSummarizationTimeSeconds = (int ) (elapsedMillis / 1000 );
85
- }
86
-
87
- instance .dismissProgressDialog ();
88
- instance .showSummaryDialog (context , summary , instance .totalSummarizationTimeSeconds );
89
- });
90
- }
91
-
92
- @ RequiresApi (api = Build .VERSION_CODES .P )
93
- @ Override
94
- public void onFailure (String error ) {
95
- context .getMainExecutor ().execute (() -> {
96
- if (instance == null || instance .isCancelled ) {
97
- Logger .printDebug (() -> "Gemini request failed but was cancelled by user." );
98
- instance .dismissProgressDialog ();
99
- return ;
100
- }
101
- instance .dismissProgressDialog ();
102
- showToastLong (str ("revanced_gemini_error_api_failed" , error ));
103
- });
104
- }
105
- });
106
- }
107
-
108
- private void showProgressDialog (Context context ) {
109
- stopTimer ();
110
- dismissProgressDialog ();
111
-
112
- baseLoadingMessage = str ("revanced_gemini_loading" );
113
- startTimeMillis = -1 ; // Reset start time until timer actually starts
114
-
115
- AlertDialog .Builder builder = new AlertDialog .Builder (context );
116
- // Set initial message without time
117
- builder .setMessage (baseLoadingMessage );
118
- builder .setCancelable (false );
119
-
120
- builder .setNegativeButton (str ("revanced_cancel" ), (dialog , which ) -> {
121
- isCancelled = true ;
122
- stopTimer ();
123
- dismissProgressDialog ();
124
- showToastShort (str ("revanced_gemini_cancelled" ));
125
- Logger .printDebug (() -> "Gemini summarization cancelled by user." );
126
- });
127
-
128
- progressDialog = builder .create ();
129
- progressDialog .show ();
130
-
131
- // Start the timer which will update the message
132
- startTimer ();
133
- }
134
-
135
- private void dismissProgressDialog () {
136
- stopTimer ();
137
- if (progressDialog != null && progressDialog .isShowing ()) {
138
- try {
139
- progressDialog .dismiss ();
140
- } catch (IllegalArgumentException e ) {
141
- Logger .printException (() -> "Error dismissing progress dialog" , e );
142
- }
143
- }
144
- progressDialog = null ;
36
+ GeminiManager .getInstance ().startSummarization (context , videoUrl );
145
37
}
146
38
147
- private void showSummaryDialog (Context context , String summary , int secondsTaken ) {
148
- dismissProgressDialog ();
149
-
150
- String finalMessage = summary ;
151
- if (secondsTaken >= 0 ) {
152
- finalMessage += "\n \n " + str ("revanced_gemini_time_taken" , secondsTaken );
39
+ public static void handleTranscribeClick (Context context ) {
40
+ if (instance == null ) {
41
+ Logger .printException (() -> "GeminiSummarize button instance is null, cannot proceed with transcribe." );
42
+ return ;
153
43
}
44
+ final String videoUrl = VideoUtils .getVideoUrl (false );
154
45
155
- new AlertDialog .Builder (context )
156
- .setTitle (str ("revanced_gemini_summary_title" ))
157
- .setMessage (finalMessage )
158
- .setPositiveButton (android .R .string .ok , (dialog , which ) -> dialog .dismiss ())
159
- .setNeutralButton (str ("revanced_copy" ), (dialog , which ) -> {
160
- // Copy only the summary part, not the time taken text
161
- VideoUtils .setClipboard (summary , str ("revanced_gemini_copy_success" ));
162
- })
163
- .show ();
164
- }
165
- // endregion Generate Summary
166
-
167
- // region Timer
168
- private void startTimer () {
169
- startTimeMillis = System .currentTimeMillis ();
170
- timerRunnable = new Runnable () {
171
- @ Override
172
- public void run () {
173
- if (progressDialog != null && progressDialog .isShowing () && !isCancelled ) {
174
- long elapsedMillis = System .currentTimeMillis () - startTimeMillis ;
175
- int elapsedSeconds = (int ) (elapsedMillis / 1000 );
176
-
177
- String timeString = elapsedSeconds + "s" ;
178
- progressDialog .setMessage (baseLoadingMessage + "\n " + timeString );
179
-
180
- timerHandler .postDelayed (this , 1000 );
181
- }
182
- }
183
- };
184
- // Start the first update slightly delayed to ensure dialog is visible
185
- timerHandler .postDelayed (timerRunnable , 500 );
186
- }
187
-
188
- private void stopTimer () {
189
- if (timerHandler != null && timerRunnable != null ) {
190
- timerHandler .removeCallbacks (timerRunnable );
191
- }
192
- // Don't reset startTimeMillis here, we need it in onSuccess
46
+ GeminiManager .getInstance ().startTranscription (context , videoUrl );
193
47
}
194
- // endregion Timer
195
48
196
- // region Lifecycle and Visibility
197
49
public static void initialize (View bottomControlsViewGroup ) {
198
50
try {
199
51
if (bottomControlsViewGroup instanceof ViewGroup viewGroup ) {
200
- instance = new GeminiSummarize (viewGroup );
52
+ if (instance == null ) {
53
+ instance = new GeminiSummarize (viewGroup );
54
+ Logger .printDebug (() -> "GeminiSummarize button initialized (with long click)." );
55
+ } else {
56
+ Logger .printInfo (() -> "GeminiSummarize initialize called multiple times." );
57
+ }
201
58
}
202
59
} catch (Exception ex ) {
203
- Logger .printException (() -> "initialize failure" , ex );
60
+ Logger .printException (() -> "GeminiSummarize.initialize failure" , ex );
61
+ instance = null ;
204
62
}
205
63
}
206
64
@@ -211,5 +69,4 @@ public static void changeVisibility(boolean showing, boolean animation) {
211
69
public static void changeVisibilityNegatedImmediate () {
212
70
if (instance != null ) instance .setVisibilityNegatedImmediate ();
213
71
}
214
- // endregion Lifecycle and Visibility
215
72
}
0 commit comments