File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -15,7 +15,8 @@ import {
1515 Eye ,
1616 EyeOff ,
1717 ChevronDown ,
18- ChevronRight
18+ ChevronRight ,
19+ Key
1920} from 'lucide-react' ;
2021import {
2122 AlertDialog ,
@@ -66,6 +67,7 @@ export function ProvidersPage() {
6667 executeDeleteAll,
6768 showDeleteAllConfirmation,
6869 setShowDeleteAllConfirmation,
70+ copyRefreshToken,
6971 } = useProvidersPresenter ( ) ;
7072
7173 if ( ! isAuthenticated ) {
@@ -262,15 +264,26 @@ export function ProvidersPage() {
262264 </ div >
263265 </ div >
264266
265- < Button
266- size = "icon"
267- variant = "ghost"
268- className = "h-8 w-8 text-destructive hover:bg-destructive/10 opacity-80 group-hover:opacity-100"
269- onClick = { ( ) => setFileToDelete ( file . id ) }
270- title = { t ( 'common.delete' ) }
271- >
272- < Trash2 className = "h-4 w-4" />
273- </ Button >
267+ < div className = "flex items-center gap-1" >
268+ < Button
269+ size = "icon"
270+ variant = "ghost"
271+ className = "h-8 w-8 text-primary hover:bg-primary/10 opacity-80 group-hover:opacity-100"
272+ onClick = { ( ) => copyRefreshToken ( file . name || file . filename || file . id ) }
273+ title = { t ( 'common.copyRefreshToken' , 'Copy Refresh Token' ) }
274+ >
275+ < Key className = "h-4 w-4" />
276+ </ Button >
277+ < Button
278+ size = "icon"
279+ variant = "ghost"
280+ className = "h-8 w-8 text-destructive hover:bg-destructive/10 opacity-80 group-hover:opacity-100"
281+ onClick = { ( ) => setFileToDelete ( file . id ) }
282+ title = { t ( 'common.delete' ) }
283+ >
284+ < Trash2 className = "h-4 w-4" />
285+ </ Button >
286+ </ div >
274287 </ div >
275288 ) ;
276289 } ) }
Original file line number Diff line number Diff line change @@ -347,6 +347,30 @@ export function useProvidersPresenter() {
347347 } catch { /* ignore */ }
348348 } , [ t ] ) ;
349349
350+ const copyRefreshToken = useCallback ( async ( filename : string | undefined | null ) => {
351+ try {
352+ if ( ! filename ) {
353+ toast . error ( 'Filename is missing' ) ;
354+ return ;
355+ }
356+ let name = filename ;
357+ if ( ! name . toLowerCase ( ) . endsWith ( '.json' ) ) {
358+ name = `${ name } .json` ;
359+ }
360+ const data = await authFilesApi . download ( name ) ;
361+ const refreshToken = data . refresh_token ;
362+
363+ if ( refreshToken ) {
364+ await navigator . clipboard . writeText ( refreshToken ) ;
365+ toast . success ( t ( 'common.copied' ) || 'Copied to clipboard!' ) ;
366+ } else {
367+ toast . error ( 'No refresh token found in this file' ) ;
368+ }
369+ } catch ( err ) {
370+ toast . error ( `Failed to copy refresh token: ${ ( err as Error ) . message } ` ) ;
371+ }
372+ } , [ t ] ) ;
373+
350374 const togglePrivacyMode = useCallback ( ( ) => {
351375 setIsPrivacyMode ( prev => ! prev ) ;
352376 } , [ ] ) ;
@@ -386,6 +410,7 @@ export function useProvidersPresenter() {
386410 submitCallback,
387411 updateProviderState,
388412 copyToClipboard,
413+ copyRefreshToken,
389414
390415 // Privacy
391416 isPrivacyMode,
Original file line number Diff line number Diff line change 1717 "upload" : " Upload" ,
1818 "deleteAll" : " Delete All" ,
1919 "deleting" : " Deleting..." ,
20- "deleteWarning" : " This action cannot be undone. This will permanently delete your account connection."
20+ "deleteWarning" : " This action cannot be undone. This will permanently delete your account connection." ,
21+ "copyRefreshToken" : " Copy Refresh Token"
2122 },
2223 "auth" : {
2324 "login" : " Login" ,
Original file line number Diff line number Diff line change 1717 "upload" : " Unggah" ,
1818 "deleteAll" : " Hapus Semua" ,
1919 "deleting" : " Menghapus..." ,
20- "deleteWarning" : " Tindakan ini tidak dapat dibatalkan. Ini akan menghapus koneksi akun Anda secara permanen."
20+ "deleteWarning" : " Tindakan ini tidak dapat dibatalkan. Ini akan menghapus koneksi akun Anda secara permanen." ,
21+ "copyRefreshToken" : " Salin Token Penyegaran"
2122 },
2223 "auth" : {
2324 "login" : " Masuk" ,
Original file line number Diff line number Diff line change 1717 "upload" : " アップロード" ,
1818 "deleteAll" : " すべて削除" ,
1919 "deleting" : " 削除中..." ,
20- "deleteWarning" : " この操作は取り消せません。アカウント接続が完全に削除されます。"
20+ "deleteWarning" : " この操作は取り消せません。アカウント接続が完全に削除されます。" ,
21+ "copyRefreshToken" : " リフレッシュトークンをコピー"
2122 },
2223 "auth" : {
2324 "login" : " ログイン" ,
Original file line number Diff line number Diff line change 1717 "upload" : " 업로드" ,
1818 "deleteAll" : " 모두 삭제" ,
1919 "deleting" : " 삭제 중..." ,
20- "deleteWarning" : " 이 작업은 취소할 수 없습니다. 계정 연결이 영구적으로 삭제됩니다."
20+ "deleteWarning" : " 이 작업은 취소할 수 없습니다. 계정 연결이 영구적으로 삭제됩니다." ,
21+ "copyRefreshToken" : " 갱신 토큰 복사"
2122 },
2223 "auth" : {
2324 "login" : " 로그인" ,
Original file line number Diff line number Diff line change 1717 "upload" : " อัปโหลด" ,
1818 "deleteAll" : " ลบทั้งหมด" ,
1919 "deleting" : " กำลังลบ..." ,
20- "deleteWarning" : " การดำเนินการนี้ไม่สามารถยกเลิกได้ การเชื่อมต่อบัญชีของคุณจะถูกลบอย่างถาวร"
20+ "deleteWarning" : " การดำเนินการนี้ไม่สามารถยกเลิกได้ การเชื่อมต่อบัญชีของคุณจะถูกลบอย่างถาวร" ,
21+ "copyRefreshToken" : " คัดลอกโทเค็นรีเฟรช"
2122 },
2223 "auth" : {
2324 "login" : " เข้าสู่ระบบ" ,
Original file line number Diff line number Diff line change 1717 "upload" : " Tải lên" ,
1818 "deleteAll" : " Xóa tất cả" ,
1919 "deleting" : " Đang xóa..." ,
20- "deleteWarning" : " Hành động này không thể hoàn tác. Việc này sẽ xóa vĩnh viễn kết nối tài khoản của bạn."
20+ "deleteWarning" : " Hành động này không thể hoàn tác. Việc này sẽ xóa vĩnh viễn kết nối tài khoản của bạn." ,
21+ "copyRefreshToken" : " Sao chép Token làm mới"
2122 },
2223 "auth" : {
2324 "login" : " Đăng nhập" ,
Original file line number Diff line number Diff line change 1717 "upload" : " 上传" ,
1818 "deleteAll" : " 全部删除" ,
1919 "deleting" : " 正在删除..." ,
20- "deleteWarning" : " 此操作无法撤销。这将永久删除您的帐户连接。"
20+ "deleteWarning" : " 此操作无法撤销。这将永久删除您的帐户连接。" ,
21+ "copyRefreshToken" : " 复制刷新令牌"
2122 },
2223 "auth" : {
2324 "login" : " 登录" ,
Original file line number Diff line number Diff line change @@ -11,4 +11,6 @@ export const authFilesApi = {
1111 deleteFile : ( name : string ) => apiClient . delete ( `/auth-files?name=${ encodeURIComponent ( name ) } ` ) ,
1212
1313 deleteAll : ( ) => apiClient . delete ( '/auth-files?all=true' ) ,
14+
15+ download : ( name : string ) => apiClient . get < any > ( `/auth-files/download?name=${ encodeURIComponent ( name ) } ` ) ,
1416} ;
You can’t perform that action at this time.
0 commit comments