google-drive-picker.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // Google Drive Picker API configuration
  2. const API_KEY = import.meta.env.VITE_GOOGLE_API_KEY;
  3. const CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;
  4. const SCOPE = ['https://www.googleapis.com/auth/drive.readonly'];
  5. // Validate required credentials
  6. const validateCredentials = () => {
  7. if (!API_KEY || !CLIENT_ID) {
  8. throw new Error('Google Drive API credentials not configured. Please set VITE_GOOGLE_API_KEY and VITE_GOOGLE_CLIENT_ID environment variables.');
  9. }
  10. };
  11. let pickerApiLoaded = false;
  12. let oauthToken: string | null = null;
  13. let initialized = false;
  14. export const loadGoogleDriveApi = () => {
  15. return new Promise((resolve, reject) => {
  16. if (typeof gapi === 'undefined') {
  17. const script = document.createElement('script');
  18. script.src = 'https://apis.google.com/js/api.js';
  19. script.onload = () => {
  20. gapi.load('picker', {
  21. callback: () => {
  22. pickerApiLoaded = true;
  23. resolve(true);
  24. }
  25. });
  26. };
  27. script.onerror = reject;
  28. document.body.appendChild(script);
  29. } else {
  30. gapi.load('picker', {
  31. callback: () => {
  32. pickerApiLoaded = true;
  33. resolve(true);
  34. }
  35. });
  36. }
  37. });
  38. };
  39. export const loadGoogleAuthApi = () => {
  40. return new Promise((resolve, reject) => {
  41. if (typeof google === 'undefined') {
  42. const script = document.createElement('script');
  43. script.src = 'https://accounts.google.com/gsi/client';
  44. script.onload = resolve;
  45. script.onerror = reject;
  46. document.body.appendChild(script);
  47. } else {
  48. resolve(true);
  49. }
  50. });
  51. };
  52. export const getAuthToken = async () => {
  53. if (!oauthToken) {
  54. const tokenClient = google.accounts.oauth2.initTokenClient({
  55. client_id: CLIENT_ID,
  56. scope: SCOPE.join(' '),
  57. callback: (response: any) => {
  58. if (response.access_token) {
  59. oauthToken = response.access_token;
  60. }
  61. },
  62. });
  63. await tokenClient.requestAccessToken();
  64. }
  65. return oauthToken;
  66. };
  67. const initialize = async () => {
  68. if (!initialized) {
  69. validateCredentials();
  70. await Promise.all([loadGoogleDriveApi(), loadGoogleAuthApi()]);
  71. initialized = true;
  72. }
  73. };
  74. export const createPicker = () => {
  75. return new Promise(async (resolve, reject) => {
  76. try {
  77. await initialize();
  78. const token = await getAuthToken();
  79. if (!token) {
  80. throw new Error('Unable to get OAuth token');
  81. }
  82. const picker = new google.picker.PickerBuilder()
  83. .addView(google.picker.ViewId.DOCS)
  84. .setOAuthToken(token)
  85. .setDeveloperKey(API_KEY)
  86. .setCallback((data: any) => {
  87. if (data[google.picker.Response.ACTION] === google.picker.Action.PICKED) {
  88. const doc = data[google.picker.Response.DOCUMENTS][0];
  89. const fileId = doc[google.picker.Document.ID];
  90. const fileName = doc[google.picker.Document.NAME];
  91. const fileUrl = doc[google.picker.Document.URL];
  92. resolve({
  93. id: fileId,
  94. name: fileName,
  95. url: fileUrl
  96. });
  97. } else if (data[google.picker.Response.ACTION] === google.picker.Action.CANCEL) {
  98. resolve(null);
  99. }
  100. })
  101. .build();
  102. picker.setVisible(true);
  103. } catch (error) {
  104. reject(error);
  105. }
  106. });
  107. };