Significant performance improvements to the 'Loading media...' phase: - Reduced client-server round trips by consolidating the initial handshake (diagnostics + media fetch) into a single backend call: getMediaManagerInitialState. - Implemented batched Google Drive metadata retrieval in GASDriveService using the Advanced Drive API, eliminating per-file property fetching calls. - Switched to HtmlService templates in showMediaManager to pass initial SKU/Title data directly, enabling the UI shell to appear instantly upon opening. - Updated documentation (ARCHITECTURE.md, MEMORY.md) to clarify Webpack global assignment requirements for GAS functions. - Verified with comprehensive updates to unit and integration tests.
139 lines
5.2 KiB
TypeScript
139 lines
5.2 KiB
TypeScript
import { IDriveService } from "../interfaces/IDriveService"
|
|
|
|
export class MockDriveService implements IDriveService {
|
|
private folders: Map<string, any> = new Map() // id -> folder
|
|
private files: Map<string, any[]> = new Map() // folderId -> files
|
|
|
|
constructor() {
|
|
// Setup root folder mock if needed or just handle dynamic creation
|
|
}
|
|
|
|
getOrCreateFolder(folderName: string, parentFolderId: string): GoogleAppsScript.Drive.Folder {
|
|
// Mock implementation finding by name "under" parent
|
|
const key = `${parentFolderId}/${folderName}`
|
|
if (!this.folders.has(key)) {
|
|
const id = `mock_folder_${folderName}_id`
|
|
const newFolder = {
|
|
getId: () => id,
|
|
getName: () => folderName,
|
|
getUrl: () => `https://mock.drive/folders/${folderName}`,
|
|
createFile: (blob) => this.saveFile(blob, id),
|
|
addFile: (file) => {
|
|
console.log(`[MockDrive] addFile: Adding ${file.getId()} to ${id}`)
|
|
// Remove from all other folders (simplification) or just 'root'
|
|
for (const [fId, files] of this.files.entries()) {
|
|
const idx = files.findIndex(f => f.getId() === file.getId())
|
|
if (idx !== -1) {
|
|
console.log(`[MockDrive] Removed ${file.getId()} from ${fId}`)
|
|
files.splice(idx, 1)
|
|
}
|
|
}
|
|
// Add to this folder
|
|
if (!this.files.has(id)) {
|
|
this.files.set(id, [])
|
|
}
|
|
this.files.get(id).push(file)
|
|
return newFolder
|
|
}
|
|
} as unknown as GoogleAppsScript.Drive.Folder;
|
|
this.folders.set(key, newFolder)
|
|
}
|
|
return this.folders.get(key)
|
|
}
|
|
|
|
saveFile(blob: GoogleAppsScript.Base.Blob, folderId: string): GoogleAppsScript.Drive.File {
|
|
const id = `mock_file_${Date.now()}_${Math.floor(Math.random() * 1000)}`
|
|
|
|
const newFile = {
|
|
getId: () => id,
|
|
getName: () => blob.getName(),
|
|
getBlob: () => blob,
|
|
getUrl: () => `https://mock.drive/files/${blob.getName()}`,
|
|
getLastUpdated: () => new Date(),
|
|
getThumbnail: () => (blob as any).getThumbnail ? (blob as any).getThumbnail() : ({ getBytes: () => [] }),
|
|
getMimeType: () => (blob as any).getContentType ? (blob as any).getContentType() : "image/jpeg",
|
|
getDownloadUrl: () => `https://drive.google.com/uc?export=download&id=${id}`,
|
|
getSize: () => blob.getBytes ? blob.getBytes().length : 0,
|
|
getAppProperty: (key) => (newFile as any)._properties?.[key],
|
|
// Placeholder methods to be overridden safely
|
|
setDescription: null as any,
|
|
getDescription: null as any
|
|
} as unknown as GoogleAppsScript.Drive.File
|
|
|
|
// Initialize state
|
|
;(newFile as any)._properties = {};
|
|
;(newFile as any)._description = "";
|
|
|
|
// Attach methods safely
|
|
newFile.setDescription = (desc: string) => {
|
|
(newFile as any)._description = desc;
|
|
return newFile;
|
|
};
|
|
newFile.getDescription = () => (newFile as any)._description || "";
|
|
|
|
if (!this.files.has(folderId)) {
|
|
this.files.set(folderId, [])
|
|
}
|
|
this.files.get(folderId).push(newFile)
|
|
return newFile
|
|
}
|
|
|
|
getFiles(folderId: string): GoogleAppsScript.Drive.File[] {
|
|
return this.files.get(folderId) || []
|
|
}
|
|
|
|
getFileById(id: string): GoogleAppsScript.Drive.File {
|
|
// Naive lookup for mock
|
|
for (const fileList of this.files.values()) {
|
|
const found = fileList.find(f => f.getId() === id)
|
|
if (found) return found
|
|
}
|
|
throw new Error("File not found in mock")
|
|
}
|
|
|
|
renameFile(fileId: string, newName: string): void {
|
|
const file = this.getFileById(fileId)
|
|
// Mock setName
|
|
// We can't easily mutate the mock object created in saveFile without refactoring
|
|
// But for type satisfaction it's void.
|
|
console.log(`[MockDrive] Renaming ${fileId} to ${newName}`)
|
|
// Assuming we can mutate if we kept ref?
|
|
}
|
|
|
|
trashFile(fileId: string): void {
|
|
console.log(`[MockDrive] Trashing ${fileId}`)
|
|
}
|
|
|
|
updateFileProperties(fileId: string, properties: any): void {
|
|
console.log(`[MockDrive] Updating properties for ${fileId}`, properties)
|
|
const file = this.getFileById(fileId)
|
|
const mockFile = file as any
|
|
if (!mockFile._properties) {
|
|
mockFile._properties = {}
|
|
}
|
|
Object.assign(mockFile._properties, properties)
|
|
}
|
|
|
|
createFile(blob: GoogleAppsScript.Base.Blob): GoogleAppsScript.Drive.File {
|
|
// Create in "root" or similar
|
|
return this.saveFile(blob, "root")
|
|
}
|
|
|
|
getFileProperties(fileId: string): {[key: string]: string} {
|
|
try {
|
|
const file = this.getFileById(fileId)
|
|
return (file as any)._properties || {}
|
|
} catch (e) {
|
|
return {}
|
|
}
|
|
}
|
|
|
|
getFilesWithProperties(folderId: string): { file: GoogleAppsScript.Drive.File, properties: { [key: string]: string } }[] {
|
|
const files = this.getFiles(folderId)
|
|
return files.map(f => ({
|
|
file: f,
|
|
properties: (f as any)._properties || {}
|
|
}))
|
|
}
|
|
}
|