soiz1 commited on
Commit
4eb332e
·
verified ·
1 Parent(s): a93bdcd

Update src/addons/addons/save-to-google/userscript.js

Browse files
src/addons/addons/save-to-google/userscript.js CHANGED
@@ -14,7 +14,8 @@ export default async ({ addon, console, msg }) => {
14
  const PROXY_URL = "https://soiz1-drive-proxy.hf.space/?file_id=";
15
  const SHORT_URL = "https://s4.rf.gd/";
16
 
17
- let accessToken = null;
 
18
 
19
  while (true) {
20
  const targetElem = await addon.tab.waitForElement(
@@ -37,24 +38,37 @@ export default async ({ addon, console, msg }) => {
37
  }
38
 
39
  function showMainModal(addon) {
40
- const modal = addon.tab.createModal("Googleドライブに保存", { isOpen: true, useEditorClasses: true });
 
 
 
 
 
41
 
42
  modal.content.innerHTML = `
43
- <div style="padding: 1rem;">
44
- <h1>Googleドライブに接続</h1>
45
- <p>Googleでログインして、プロジェクトを保存または更新します。</p>
46
- <button id="google-login-button" class="button">Googleでログイン</button>
47
- <div id="file-list-container" style="margin-top: 1rem; display: none;">
 
 
 
 
 
 
 
48
  <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
49
- <h2 style="margin: 0;">プロジェクト: <span id="project-title" style="cursor: pointer; border-bottom: 1px dashed #000;">${window.vm.runtime.projectName || "無題"}</span></h2>
50
  <button id="new-file-button" class="button">新規保存</button>
51
  </div>
52
- <div id="file-list" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem; margin-top: 1rem;"></div>
53
  </div>
54
  </div>
55
  `;
56
 
57
  const loginButton = modal.content.querySelector("#google-login-button");
 
58
  const fileListContainer = modal.content.querySelector("#file-list-container");
59
  const fileList = modal.content.querySelector("#file-list");
60
  const newFileButton = modal.content.querySelector("#new-file-button");
@@ -84,35 +98,22 @@ export default async ({ addon, console, msg }) => {
84
  });
85
  });
86
 
87
- loginButton?.addEventListener("click", () => {
88
- const messageListener = (event) => {
89
- if (event.origin === "https://soiz1-penguin-upload.hf.space" && event.data.token) {
90
- window.removeEventListener("message", messageListener);
91
- accessToken = event.data.token;
92
-
93
- loginButton.style.display = "none";
94
-
95
- fetchDriveFiles(accessToken)
96
- .then(files => {
97
- displayFileList(files, accessToken, modal, addon);
98
- fileListContainer.style.display = "block";
99
- })
100
- .catch(error => {
101
- console.error("ファイル一覧取得エラー:", error);
102
- showAlert(addon, "error", "ファイル一覧の取得に失敗しました");
103
- });
104
- }
105
- };
106
- window.addEventListener("message", messageListener);
107
 
108
- const authUrl = `https://accounts.google.com/o/oauth2/auth?` +
109
- `client_id=${CLIENT_ID}` +
110
- `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
111
- `&response_type=token` +
112
- `&scope=${encodeURIComponent(SCOPES)}`;
113
-
114
- window.open(authUrl, "_blank", "width=500,height=600");
115
- });
 
 
116
 
117
  newFileButton?.addEventListener("click", async () => {
118
  try {
@@ -123,10 +124,49 @@ export default async ({ addon, console, msg }) => {
123
  }
124
  });
125
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  modal.backdrop.addEventListener("click", modal.remove);
127
  modal.closeButton.addEventListener("click", modal.remove);
128
  }
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  async function fetchDriveFiles(accessToken) {
131
  const response = await fetch("https://www.googleapis.com/drive/v3/files?q=(mimeType='application/x-scratch' or mimeType='image/png')", {
132
  headers: {
@@ -169,11 +209,14 @@ export default async ({ addon, console, msg }) => {
169
  fileItem.style.flexDirection = "column";
170
  fileItem.style.gap = "0.75rem";
171
  fileItem.style.background = "#fff";
 
172
 
173
  // サムネイル表示
174
  const thumbnailContainer = document.createElement("div");
175
  thumbnailContainer.style.position = "relative";
176
  thumbnailContainer.style.aspectRatio = "4/3";
 
 
177
 
178
  if (thumbnail) {
179
  const thumbnailImg = document.createElement("img");
@@ -181,7 +224,8 @@ export default async ({ addon, console, msg }) => {
181
  thumbnailImg.style.width = "100%";
182
  thumbnailImg.style.height = "100%";
183
  thumbnailImg.style.borderRadius = "4px";
184
- thumbnailImg.style.objectFit = "cover";
 
185
  thumbnailContainer.appendChild(thumbnailImg);
186
  } else {
187
  const thumbnailPlaceholder = document.createElement("div");
@@ -209,23 +253,28 @@ export default async ({ addon, console, msg }) => {
209
  // 共有リンク
210
  const linkContainer = document.createElement("div");
211
  linkContainer.style.display = "flex";
212
- linkContainer.style.gap = "0.5rem";
213
- linkContainer.style.alignItems = "center";
214
- linkContainer.style.justifyContent = "center";
215
-
216
- const link = document.createElement("a");
217
- link.href = `${SHORT_URL}${project.id}`;
218
- link.textContent = "共有リンク";
219
- link.target = "_blank";
220
- link.rel = "noopener noreferrer";
221
- link.style.fontSize = "0.9em";
222
- link.style.color = "#4d97ff";
 
 
 
 
223
 
224
  const copyButton = document.createElement("button");
225
- copyButton.textContent = "コピー";
226
  copyButton.className = "button";
227
  copyButton.style.fontSize = "0.8em";
228
  copyButton.style.padding = "0.2rem 0.5rem";
 
229
 
230
  copyButton.addEventListener("click", (e) => {
231
  e.stopPropagation();
@@ -234,7 +283,6 @@ export default async ({ addon, console, msg }) => {
234
  .catch(() => showAlert(addon, "error", "リンクのコピーに失敗しました"));
235
  });
236
 
237
- linkContainer.appendChild(link);
238
  linkContainer.appendChild(copyButton);
239
  fileItem.appendChild(linkContainer);
240
 
 
14
  const PROXY_URL = "https://soiz1-drive-proxy.hf.space/?file_id=";
15
  const SHORT_URL = "https://s4.rf.gd/";
16
 
17
+ let accessToken = localStorage.getItem('googleDriveAccessToken') || null;
18
+ let currentAccountEmail = localStorage.getItem('googleDriveAccountEmail') || null;
19
 
20
  while (true) {
21
  const targetElem = await addon.tab.waitForElement(
 
38
  }
39
 
40
  function showMainModal(addon) {
41
+ const modal = addon.tab.createModal("Googleドライブに保存", {
42
+ isOpen: true,
43
+ useEditorClasses: true,
44
+ maxWidth: "800px",
45
+ maxHeight: "80vh"
46
+ });
47
 
48
  modal.content.innerHTML = `
49
+ <div style="padding: 1rem; max-height: 70vh; overflow-y: auto;">
50
+ <h1 style="font-size: 1.5rem; margin-bottom: 1rem;">Googleドライブに接続</h1>
51
+ ${accessToken ? `
52
+ <div style="margin-bottom: 1rem; display: flex; justify-content: space-between; align-items: center;">
53
+ <div>ログイン中: ${currentAccountEmail || 'Googleアカウント'}</div>
54
+ <button id="change-account-button" class="button" style="padding: 0.25rem 0.5rem; font-size: 0.9rem;">アカウントを変更</button>
55
+ </div>
56
+ ` : `
57
+ <p style="margin-bottom: 1rem;">Googleでログインして、プロジェクトを保存または更新します。</p>
58
+ <button id="google-login-button" class="button">Googleでログイン</button>
59
+ `}
60
+ <div id="file-list-container" style="margin-top: 1rem; ${accessToken ? '' : 'display: none;'}">
61
  <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
62
+ <h2 style="margin: 0; font-size: 1.2rem;">プロジェクト: <span id="project-title" style="cursor: pointer; border-bottom: 1px dashed #000;">${window.vm.runtime.projectName || "無題"}</span></h2>
63
  <button id="new-file-button" class="button">新規保存</button>
64
  </div>
65
+ <div id="file-list" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1rem; margin-top: 1rem;"></div>
66
  </div>
67
  </div>
68
  `;
69
 
70
  const loginButton = modal.content.querySelector("#google-login-button");
71
+ const changeAccountButton = modal.content.querySelector("#change-account-button");
72
  const fileListContainer = modal.content.querySelector("#file-list-container");
73
  const fileList = modal.content.querySelector("#file-list");
74
  const newFileButton = modal.content.querySelector("#new-file-button");
 
98
  });
99
  });
100
 
101
+ if (loginButton) {
102
+ loginButton.addEventListener("click", () => {
103
+ startGoogleLogin(modal, addon);
104
+ });
105
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
+ if (changeAccountButton) {
108
+ changeAccountButton.addEventListener("click", () => {
109
+ accessToken = null;
110
+ currentAccountEmail = null;
111
+ localStorage.removeItem('googleDriveAccessToken');
112
+ localStorage.removeItem('googleDriveAccountEmail');
113
+ showMainModal(addon);
114
+ modal.remove();
115
+ });
116
+ }
117
 
118
  newFileButton?.addEventListener("click", async () => {
119
  try {
 
124
  }
125
  });
126
 
127
+ if (accessToken) {
128
+ fetchDriveFiles(accessToken)
129
+ .then(files => {
130
+ displayFileList(files, accessToken, modal, addon);
131
+ fileListContainer.style.display = "block";
132
+ })
133
+ .catch(error => {
134
+ console.error("ファイル一覧取得エラー:", error);
135
+ showAlert(addon, "error", "ファイル一覧の取得に失敗しました");
136
+ });
137
+ }
138
+
139
  modal.backdrop.addEventListener("click", modal.remove);
140
  modal.closeButton.addEventListener("click", modal.remove);
141
  }
142
 
143
+ function startGoogleLogin(modal, addon) {
144
+ const messageListener = (event) => {
145
+ if (event.origin === "https://soiz1-penguin-upload.hf.space" && event.data.token) {
146
+ window.removeEventListener("message", messageListener);
147
+ accessToken = event.data.token;
148
+ currentAccountEmail = event.data.email || null;
149
+
150
+ localStorage.setItem('googleDriveAccessToken', accessToken);
151
+ if (currentAccountEmail) {
152
+ localStorage.setItem('googleDriveAccountEmail', currentAccountEmail);
153
+ }
154
+
155
+ showMainModal(addon);
156
+ modal.remove();
157
+ }
158
+ };
159
+ window.addEventListener("message", messageListener);
160
+
161
+ const authUrl = `https://accounts.google.com/o/oauth2/auth?` +
162
+ `client_id=${CLIENT_ID}` +
163
+ `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
164
+ `&response_type=token` +
165
+ `&scope=${encodeURIComponent(SCOPES)}`;
166
+
167
+ window.open(authUrl, "_blank", "width=500,height=600");
168
+ }
169
+
170
  async function fetchDriveFiles(accessToken) {
171
  const response = await fetch("https://www.googleapis.com/drive/v3/files?q=(mimeType='application/x-scratch' or mimeType='image/png')", {
172
  headers: {
 
209
  fileItem.style.flexDirection = "column";
210
  fileItem.style.gap = "0.75rem";
211
  fileItem.style.background = "#fff";
212
+ fileItem.style.height = "100%";
213
 
214
  // サムネイル表示
215
  const thumbnailContainer = document.createElement("div");
216
  thumbnailContainer.style.position = "relative";
217
  thumbnailContainer.style.aspectRatio = "4/3";
218
+ thumbnailContainer.style.maxHeight = "150px";
219
+ thumbnailContainer.style.overflow = "hidden";
220
 
221
  if (thumbnail) {
222
  const thumbnailImg = document.createElement("img");
 
224
  thumbnailImg.style.width = "100%";
225
  thumbnailImg.style.height = "100%";
226
  thumbnailImg.style.borderRadius = "4px";
227
+ thumbnailImg.style.objectFit = "contain";
228
+ thumbnailImg.style.backgroundColor = "#f0f0f0";
229
  thumbnailContainer.appendChild(thumbnailImg);
230
  } else {
231
  const thumbnailPlaceholder = document.createElement("div");
 
253
  // 共有リンク
254
  const linkContainer = document.createElement("div");
255
  linkContainer.style.display = "flex";
256
+ linkContainer.style.flexDirection = "column";
257
+ linkContainer.style.gap = "0.25rem";
258
+ linkContainer.style.marginBottom = "0.5rem";
259
+
260
+ const linkLabel = document.createElement("div");
261
+ linkLabel.textContent = "共有リンク:";
262
+ linkLabel.style.fontSize = "0.8em";
263
+ linkLabel.style.color = "#666";
264
+ linkContainer.appendChild(linkLabel);
265
+
266
+ const linkUrl = document.createElement("div");
267
+ linkUrl.textContent = `${SHORT_URL}${project.id}`;
268
+ linkUrl.style.fontSize = "0.9em";
269
+ linkUrl.style.wordBreak = "break-all";
270
+ linkContainer.appendChild(linkUrl);
271
 
272
  const copyButton = document.createElement("button");
273
+ copyButton.textContent = "リンクをコピー";
274
  copyButton.className = "button";
275
  copyButton.style.fontSize = "0.8em";
276
  copyButton.style.padding = "0.2rem 0.5rem";
277
+ copyButton.style.width = "100%";
278
 
279
  copyButton.addEventListener("click", (e) => {
280
  e.stopPropagation();
 
283
  .catch(() => showAlert(addon, "error", "リンクのコピーに失敗しました"));
284
  });
285
 
 
286
  linkContainer.appendChild(copyButton);
287
  fileItem.appendChild(linkContainer);
288