fix; tab bars didn't update on post creation without restart of app
This commit is contained in:
@@ -179,6 +179,7 @@ export const TabBar: React.FC = () => {
|
|||||||
const {
|
const {
|
||||||
tabs,
|
tabs,
|
||||||
activeTabId,
|
activeTabId,
|
||||||
|
posts,
|
||||||
media,
|
media,
|
||||||
activeProject,
|
activeProject,
|
||||||
dirtyPosts,
|
dirtyPosts,
|
||||||
@@ -199,6 +200,34 @@ export const TabBar: React.FC = () => {
|
|||||||
// Fetch post titles from database for post tabs
|
// Fetch post titles from database for post tabs
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const postTabs = tabs.filter(t => t.type === 'post');
|
const postTabs = tabs.filter(t => t.type === 'post');
|
||||||
|
const postTabIds = new Set(postTabs.map(t => t.id));
|
||||||
|
|
||||||
|
setPostTitles((previous) => {
|
||||||
|
const next = new Map(previous);
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
for (const id of Array.from(next.keys())) {
|
||||||
|
if (!postTabIds.has(id)) {
|
||||||
|
next.delete(id);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const post of posts) {
|
||||||
|
if (!postTabIds.has(post.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = post.title || 'Untitled';
|
||||||
|
if (next.get(post.id) !== title) {
|
||||||
|
next.set(post.id, title);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed ? next : previous;
|
||||||
|
});
|
||||||
|
|
||||||
if (postTabs.length === 0) return;
|
if (postTabs.length === 0) return;
|
||||||
|
|
||||||
const fetchTitles = async () => {
|
const fetchTitles = async () => {
|
||||||
@@ -206,7 +235,9 @@ export const TabBar: React.FC = () => {
|
|||||||
let changed = false;
|
let changed = false;
|
||||||
|
|
||||||
for (const tab of postTabs) {
|
for (const tab of postTabs) {
|
||||||
if (!postTitles.has(tab.id)) {
|
const postInStore = posts.find((post) => post.id === tab.id);
|
||||||
|
|
||||||
|
if (!postInStore) {
|
||||||
try {
|
try {
|
||||||
const post = await window.electronAPI?.posts.get(tab.id);
|
const post = await window.electronAPI?.posts.get(tab.id);
|
||||||
if (post) {
|
if (post) {
|
||||||
@@ -225,7 +256,7 @@ export const TabBar: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchTitles();
|
fetchTitles();
|
||||||
}, [tabs]); // Note: intentionally not including postTitles to avoid infinite loops
|
}, [tabs, posts]); // Note: intentionally not including postTitles to avoid infinite loops
|
||||||
|
|
||||||
// Listen for post updates to refresh titles
|
// Listen for post updates to refresh titles
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
import { render, screen } from '@testing-library/react';
|
import { act, render, screen } from '@testing-library/react';
|
||||||
import { TabBar } from '../../../src/renderer/components/TabBar/TabBar';
|
import { TabBar } from '../../../src/renderer/components/TabBar/TabBar';
|
||||||
import { useAppStore } from '../../../src/renderer/store';
|
import { useAppStore } from '../../../src/renderer/store';
|
||||||
|
|
||||||
@@ -97,4 +97,43 @@ describe('TabBar', () => {
|
|||||||
|
|
||||||
expect(await screen.findByText('Style')).toBeInTheDocument();
|
expect(await screen.findByText('Style')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('updates post tab title when post title changes in store', async () => {
|
||||||
|
useAppStore.setState({
|
||||||
|
tabs: [{ type: 'post', id: 'post-1', isTransient: false }],
|
||||||
|
activeTabId: 'post-1',
|
||||||
|
posts: [{
|
||||||
|
id: 'post-1',
|
||||||
|
title: '',
|
||||||
|
slug: 'post-1',
|
||||||
|
content: '',
|
||||||
|
excerpt: null,
|
||||||
|
author: null,
|
||||||
|
status: 'draft',
|
||||||
|
publishedAt: null,
|
||||||
|
scheduledAt: null,
|
||||||
|
tags: [],
|
||||||
|
categories: [],
|
||||||
|
metadata: {},
|
||||||
|
projectId: 'project-1',
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
(window as any).electronAPI.posts.get = vi.fn().mockResolvedValue({
|
||||||
|
id: 'post-1',
|
||||||
|
title: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<TabBar />);
|
||||||
|
|
||||||
|
expect(await screen.findByText('Untitled')).toBeInTheDocument();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
useAppStore.getState().updatePost('post-1', { title: 'Updated Title' });
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(await screen.findByText('Updated Title')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user