Fix translation language badges not updating after auto-translation (#54)
Co-authored-by: hugo <hugoms@me.com>
This commit is contained in:
@@ -2018,6 +2018,8 @@ export function registerEventForwarding(bundle: EngineBundle): void {
|
|||||||
postEngine.on('postCreated', forwardEvent('post:created'));
|
postEngine.on('postCreated', forwardEvent('post:created'));
|
||||||
postEngine.on('postUpdated', forwardEvent('post:updated'));
|
postEngine.on('postUpdated', forwardEvent('post:updated'));
|
||||||
postEngine.on('postDeleted', forwardEvent('post:deleted'));
|
postEngine.on('postDeleted', forwardEvent('post:deleted'));
|
||||||
|
postEngine.on('postTranslationCreated', forwardEvent('post:translationCreated'));
|
||||||
|
postEngine.on('postTranslationUpdated', forwardEvent('post:translationUpdated'));
|
||||||
postEngine.on('rebuildStarted', forwardEvent('posts:rebuildStarted'));
|
postEngine.on('rebuildStarted', forwardEvent('posts:rebuildStarted'));
|
||||||
postEngine.on('databaseRebuilt', forwardEvent('posts:databaseRebuilt'));
|
postEngine.on('databaseRebuilt', forwardEvent('posts:databaseRebuilt'));
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,24 @@ const App: React.FC = () => {
|
|||||||
}) || (() => {})
|
}) || (() => {})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Post translation events (refresh post to update availableLanguages for sidebar badges)
|
||||||
|
const handlePostTranslationChange = (data: unknown) => {
|
||||||
|
const translation = data as { translationFor?: string };
|
||||||
|
if (translation.translationFor) {
|
||||||
|
window.electronAPI?.posts.get(translation.translationFor).then((post) => {
|
||||||
|
if (post) {
|
||||||
|
updatePost((post as PostData).id, post as PostData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsubscribers.push(
|
||||||
|
window.electronAPI?.on('post:translationCreated', handlePostTranslationChange) || (() => {})
|
||||||
|
);
|
||||||
|
unsubscribers.push(
|
||||||
|
window.electronAPI?.on('post:translationUpdated', handlePostTranslationChange) || (() => {})
|
||||||
|
);
|
||||||
|
|
||||||
// Media events
|
// Media events
|
||||||
unsubscribers.push(
|
unsubscribers.push(
|
||||||
window.electronAPI?.on('media:imported', (media: unknown) => {
|
window.electronAPI?.on('media:imported', (media: unknown) => {
|
||||||
|
|||||||
@@ -416,6 +416,22 @@ export const PostEditor: React.FC<PostEditorProps> = ({ postId }) => {
|
|||||||
});
|
});
|
||||||
}, [loadTranslations]);
|
}, [loadTranslations]);
|
||||||
|
|
||||||
|
// Refresh translations when auto-translation completes for this post
|
||||||
|
useEffect(() => {
|
||||||
|
const handleTranslationEvent = (data: unknown) => {
|
||||||
|
const translation = data as { translationFor?: string };
|
||||||
|
if (translation.translationFor === postId) {
|
||||||
|
loadTranslations().catch(() => {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const unsubCreated = window.electronAPI?.on('post:translationCreated', handleTranslationEvent);
|
||||||
|
const unsubUpdated = window.electronAPI?.on('post:translationUpdated', handleTranslationEvent);
|
||||||
|
return () => {
|
||||||
|
unsubCreated?.();
|
||||||
|
unsubUpdated?.();
|
||||||
|
};
|
||||||
|
}, [loadTranslations, postId]);
|
||||||
|
|
||||||
// Debounce content for lightbox-only computations (not time-critical)
|
// Debounce content for lightbox-only computations (not time-critical)
|
||||||
const debouncedContent = useDebouncedValue(content, 500);
|
const debouncedContent = useDebouncedValue(content, 500);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ vi.mock('electron', () => ({
|
|||||||
handle: vi.fn((channel: string, handler: (...args: any[]) => Promise<any>) => {
|
handle: vi.fn((channel: string, handler: (...args: any[]) => Promise<any>) => {
|
||||||
registeredHandlers.set(channel, handler);
|
registeredHandlers.set(channel, handler);
|
||||||
}),
|
}),
|
||||||
|
emit: vi.fn(),
|
||||||
|
on: vi.fn(),
|
||||||
},
|
},
|
||||||
dialog: {
|
dialog: {
|
||||||
showOpenDialog: vi.fn(),
|
showOpenDialog: vi.fn(),
|
||||||
@@ -3718,4 +3720,49 @@ describe('IPC Handlers', () => {
|
|||||||
expect(mockTaskManager.runTask).not.toHaveBeenCalled();
|
expect(mockTaskManager.runTask).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('registerEventForwarding: post translation events', () => {
|
||||||
|
it('should forward postTranslationCreated to renderer', async () => {
|
||||||
|
const { registerEventForwarding } = await import('../../src/main/ipc/handlers');
|
||||||
|
mockPostEngine.on.mockClear();
|
||||||
|
registerEventForwarding(mockBundle as any);
|
||||||
|
|
||||||
|
const translationCreatedCalls = mockPostEngine.on.mock.calls.filter(
|
||||||
|
([event]: [string]) => event === 'postTranslationCreated'
|
||||||
|
);
|
||||||
|
expect(translationCreatedCalls.length).toBeGreaterThanOrEqual(1);
|
||||||
|
|
||||||
|
// Verify the handler calls ipcMain.emit to forward
|
||||||
|
const { ipcMain } = await import('electron');
|
||||||
|
(ipcMain.emit as any).mockClear();
|
||||||
|
const handler = translationCreatedCalls[translationCreatedCalls.length - 1][1];
|
||||||
|
handler({ id: 't1', translationFor: 'p1', language: 'fr' });
|
||||||
|
expect(ipcMain.emit).toHaveBeenCalledWith(
|
||||||
|
'forward-to-renderer',
|
||||||
|
'post:translationCreated',
|
||||||
|
{ id: 't1', translationFor: 'p1', language: 'fr' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward postTranslationUpdated to renderer', async () => {
|
||||||
|
const { registerEventForwarding } = await import('../../src/main/ipc/handlers');
|
||||||
|
mockPostEngine.on.mockClear();
|
||||||
|
registerEventForwarding(mockBundle as any);
|
||||||
|
|
||||||
|
const translationUpdatedCalls = mockPostEngine.on.mock.calls.filter(
|
||||||
|
([event]: [string]) => event === 'postTranslationUpdated'
|
||||||
|
);
|
||||||
|
expect(translationUpdatedCalls.length).toBeGreaterThanOrEqual(1);
|
||||||
|
|
||||||
|
const { ipcMain } = await import('electron');
|
||||||
|
(ipcMain.emit as any).mockClear();
|
||||||
|
const handler = translationUpdatedCalls[translationUpdatedCalls.length - 1][1];
|
||||||
|
handler({ id: 't2', translationFor: 'p1', language: 'de' });
|
||||||
|
expect(ipcMain.emit).toHaveBeenCalledWith(
|
||||||
|
'forward-to-renderer',
|
||||||
|
'post:translationUpdated',
|
||||||
|
{ id: 't2', translationFor: 'p1', language: 'de' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user