Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/components/app/pixel-forge-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
@state() timelineHeight = 200;
@state() private isResizingTimeline = false;
@state() private hasLibraryProject = false;
@state() private projectSelectionRequired = false;
@state() private warningMessage: string | null = null;

private resizeStartY = 0;
Expand Down Expand Up @@ -347,15 +348,15 @@
private handlePaintByNumberDialogClose = () => {
this.showPaintByNumberDialog = false;

if (!this.hasLibraryProject) {
if (this.projectSelectionRequired) {
this.showProjectBrowser = true;
}
};

private handleNewProjectDialogClose = () => {
this.showNewProjectDialog = false;

if (!this.hasLibraryProject) {
if (this.projectSelectionRequired) {
this.showProjectBrowser = true;
}
};
Expand All @@ -370,7 +371,7 @@

private handleShowOpenFileDialog = () => {
// Trigger the menu bar's open file method
const menuBar = this.shadowRoot?.querySelector("pf-menu-bar") as any;

Check warning on line 374 in src/components/app/pixel-forge-app.ts

View workflow job for this annotation

GitHub Actions / checks

Unexpected any. Specify a different type
menuBar?.openFile();
};

Expand Down Expand Up @@ -400,25 +401,28 @@
};

private handleProjectBrowserClose = () => {
if (this.hasLibraryProject) {
if (!this.projectSelectionRequired) {
this.showProjectBrowser = false;
}
};

private handleProjectOpened = () => {
this.hasLibraryProject = true;
this.projectSelectionRequired = false;
this.showProjectBrowser = false;
};

private handleProjectCreated = () => {
this.hasLibraryProject = true;
this.projectSelectionRequired = false;
this.showNewProjectDialog = false;
this.showPaintByNumberDialog = false;
this.showProjectBrowser = false;
};

private handleCurrentProjectDeleted = () => {
this.hasLibraryProject = false;
this.projectSelectionRequired = true;
this.showProjectBrowser = true;
};

Expand Down Expand Up @@ -462,6 +466,7 @@
(await workspaceStore.restoreWorkspace(workspaceState))
) {
this.hasLibraryProject = true;
this.projectSelectionRequired = false;
this.showProjectBrowser = false;
return;
}
Expand All @@ -482,15 +487,18 @@
) {
historyStore.clear();
this.hasLibraryProject = true;
this.projectSelectionRequired = false;
this.showProjectBrowser = false;
} else {
this.hasLibraryProject = false;
this.showProjectBrowser = true;
this.projectSelectionRequired = false;
this.showProjectBrowser = false;
}
} catch (error) {
log.warn("Failed to load saved project, starting fresh:", error);
this.hasLibraryProject = false;
this.showProjectBrowser = true;
this.projectSelectionRequired = false;
this.showProjectBrowser = false;
}
}

Expand Down Expand Up @@ -681,7 +689,7 @@
${this.showProjectBrowser
? html`
<pf-project-browser
.canClose=${this.hasLibraryProject}
.canClose=${!this.projectSelectionRequired}
@show-new-project-dialog=${this.handleShowNewProjectDialog}
@show-paint-by-number-dialog=${this.handleShowPaintByNumberDialog}
@project-browser-close=${this.handleProjectBrowserClose}
Expand Down
90 changes: 88 additions & 2 deletions tests/components/app/pixel-forge-app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,28 @@ describe('pixel-forge-app project dialogs', () => {
expect(element.showProjectBrowser).toBe(false);
});

it('starts in the editor when no saved project can be restored', async () => {
await import('../../../src/components/app/pixel-forge-app');

const element = document.createElement('pixel-forge-app') as HTMLElement & {
hasLibraryProject: boolean;
showProjectBrowser: boolean;
updateComplete: Promise<unknown>;
};

document.body.append(element);

await vi.waitFor(() => {
expect(projectRepositoryMock.list).toHaveBeenCalled();
});
await element.updateComplete;

expect(element.hasLibraryProject).toBe(false);
expect(element.showProjectBrowser).toBe(false);
expect(element.shadowRoot?.querySelector('pf-project-browser')).toBeNull();
expect(element.shadowRoot?.querySelector('pf-drawing-canvas')).toBeTruthy();
});

it('opens the project browser from the project tab strip', async () => {
await import('../../../src/components/app/pixel-forge-app');

Expand All @@ -117,6 +139,9 @@ describe('pixel-forge-app project dialogs', () => {
};

document.body.append(element);
await vi.waitFor(() => {
expect(projectRepositoryMock.list).toHaveBeenCalled();
});
await element.updateComplete;

element.showProjectBrowser = false;
Expand All @@ -129,7 +154,52 @@ describe('pixel-forge-app project dialogs', () => {
await element.updateComplete;

expect(element.showProjectBrowser).toBe(true);
expect(element.shadowRoot?.querySelector('pf-project-browser')).toBeTruthy();
const browser = element.shadowRoot?.querySelector('pf-project-browser');
expect(browser).toBeTruthy();
expect(browser?.canClose).toBe(true);

browser?.dispatchEvent(
new CustomEvent('project-browser-close', { bubbles: true, composed: true })
);
await element.updateComplete;

expect(element.showProjectBrowser).toBe(false);
expect(element.shadowRoot?.querySelector('pf-project-browser')).toBeNull();
});

it('requires another project after deleting the active library project', async () => {
await import('../../../src/components/app/pixel-forge-app');

const element = document.createElement('pixel-forge-app') as HTMLElement & {
hasLibraryProject: boolean;
showProjectBrowser: boolean;
updateComplete: Promise<unknown>;
};

document.body.append(element);
await element.updateComplete;

element.hasLibraryProject = true;
element.showProjectBrowser = true;
await element.updateComplete;

const browser = element.shadowRoot?.querySelector('pf-project-browser');
browser?.dispatchEvent(
new CustomEvent('current-project-deleted', { bubbles: true, composed: true })
);
await element.updateComplete;

const requiredBrowser = element.shadowRoot?.querySelector('pf-project-browser');
expect(element.hasLibraryProject).toBe(false);
expect(element.showProjectBrowser).toBe(true);
expect(requiredBrowser?.canClose).toBe(false);

requiredBrowser?.dispatchEvent(
new CustomEvent('project-browser-close', { bubbles: true, composed: true })
);
await element.updateComplete;

expect(element.showProjectBrowser).toBe(true);
});

it('renders the canvas surface from the active project context', async () => {
Expand Down Expand Up @@ -183,6 +253,14 @@ describe('pixel-forge-app project dialogs', () => {
expect(element.showNewProjectDialog).toBe(true);
expect(element.shadowRoot?.querySelector('pf-project-browser')).toBeNull();
expect(element.shadowRoot?.querySelector('pf-new-project-dialog')?.open).toBe(true);

element.shadowRoot?.querySelector('pf-new-project-dialog')?.dispatchEvent(
new CustomEvent('close', { bubbles: true, composed: true })
);
await element.updateComplete;

expect(element.showNewProjectDialog).toBe(false);
expect(element.showProjectBrowser).toBe(false);
});

it('opens guided setup when the project browser requests it', async () => {
Expand All @@ -198,7 +276,7 @@ describe('pixel-forge-app project dialogs', () => {
document.body.append(element);
await element.updateComplete;

element.hasLibraryProject = true;
element.hasLibraryProject = false;
element.showProjectBrowser = true;
element.showPaintByNumberDialog = false;
await element.updateComplete;
Expand All @@ -213,5 +291,13 @@ describe('pixel-forge-app project dialogs', () => {
expect(element.showPaintByNumberDialog).toBe(true);
expect(element.shadowRoot?.querySelector('pf-project-browser')).toBeNull();
expect(element.shadowRoot?.querySelector('pf-paint-by-number-dialog')?.open).toBe(true);

element.shadowRoot?.querySelector('pf-paint-by-number-dialog')?.dispatchEvent(
new CustomEvent('close', { bubbles: true, composed: true })
);
await element.updateComplete;

expect(element.showPaintByNumberDialog).toBe(false);
expect(element.showProjectBrowser).toBe(false);
});
});
Loading