// This goes in your migration.html's script
interface Data {
id: string;
blob: Blob;
type: 'image' | 'video';
}
const openDB = (): Promise => {
return new Promise((resolve, reject) => {
const request = indexedDB.open('MyDatabase', 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
});
};
const blobToBase64 = (blob: Blob): Promise => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
const base64 = reader.result as string;
resolve(base64.split(',')[1]); // Remove data URL prefix
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(blob);
});
};
const getAllBackgrounds = async (): Promise => {
const db = await openDB();
const tx = db.transaction('backgrounds', 'readonly');
const store = tx.objectStore('backgrounds');
const request = store.getAll();
return new Promise((resolve, reject) => {
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
};
const getSelectedBackground = (): string | null => {
return localStorage.getItem('selectedBackground');
};
const startMigration = async () => {
try {
console.info('Starting background extraction...');
let backgrounds: Data[];
try {
backgrounds = await getAllBackgrounds();
if (!backgrounds || backgrounds.length === 0) {
console.info('No backgrounds to migrate');
window.parent.postMessage({ type: 'MIGRATION_COMPLETE' }, '*');
return;
}
} catch (error: any) {
if (error.name === 'NotFoundError' && error.message.includes('object stores was not found')) {
console.info('No backgrounds to migrate: object store not found');
window.parent.postMessage({ type: 'MIGRATION_COMPLETE' }, '*');
return;
}
console.error('Error fetching backgrounds:', error);
throw new Error('Failed to fetch backgrounds');
}
const selectedBackground = getSelectedBackground();
console.info(`Found ${backgrounds.length} backgrounds`);
window.parent.postMessage({ type: 'GET_LAST_PROCESSED_ID' }, '*');
const lastProcessedId = await new Promise(resolve => {
const handler = (event: MessageEvent) => {
if (event.data.type === 'LAST_PROCESSED_ID') {
window.removeEventListener('message', handler);
resolve(event.data.id);
}
};
window.addEventListener('message', handler);
});
const remainingBackgrounds = lastProcessedId
? backgrounds.slice(backgrounds.findIndex(b => b.id === lastProcessedId) + 1)
: backgrounds;
console.info(`Processing ${remainingBackgrounds.length} remaining backgrounds`);
for (let i = 0; i < remainingBackgrounds.length; i++) {
const background = remainingBackgrounds[i];
const base64Data = await blobToBase64(background.blob);
window.parent.postMessage({
type: 'BACKGROUND_DATA',
payload: {
id: background.id,
data: base64Data,
mediaType: background.type,
total: backgrounds.length,
processed: i + 1,
isSelected: background.id === selectedBackground
}
}, '*');
await new Promise(resolve => setTimeout(resolve, 100));
}
window.parent.postMessage({ type: 'MIGRATION_COMPLETE' }, '*');
} catch (error: any) {
console.error('Extraction failed:', error);
window.parent.postMessage({
type: 'MIGRATION_ERROR',
error: error.message || 'Unknown error'
}, '*');
}
};
window.addEventListener('message', (event) => {
switch (event.data.type) {
case 'PING':
window.parent.postMessage({ type: 'PONG' }, '*');
break;
case 'START_MIGRATION':
startMigration();
break;
}
});