-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Media library #2840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Media library #2840
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
d2925b5
library homepage
azizmejri1 e759ee9
Adding media section
azizmejri1 cb57256
media library improvements
azizmejri1 a405ae8
image generator
azizmejri1 91b474d
improvements
azizmejri1 88f8797
improvements
azizmejri1 b339c62
Address PR review comments
azizmejri1 1f29221
improvements and fixing e2e tests
azizmejri1 c5bc152
Address PR review comments
azizmejri1 d49c6db
fixing media referencing
azizmejri1 0d2d472
Address PR review comments
azizmejri1 1c17400
Update E2E snapshots
azizmejri1 d943c9c
adding non-pro generator ui and improving images handling
azizmejri1 4d31f7e
cleanup
azizmejri1 0607194
Address PR review comments
azizmejri1 be55f5f
fix: sync package-lock.json with package.json after rebase
azizmejri1 0f6a77c
addressing comments and making some improvements
azizmejri1 0a753c1
Address PR review comments
azizmejri1 9bb095b
fix: formatting in mime_utils.ts
azizmejri1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| import fs from "fs"; | ||
| import path from "path"; | ||
| import { expect } from "@playwright/test"; | ||
| import { testSkipIfWindows } from "./helpers/test_helper"; | ||
| import type { PageObject } from "./helpers/test_helper"; | ||
|
|
||
| const IMAGE_FIXTURE_PATH = path.join( | ||
| __dirname, | ||
| "fixtures", | ||
| "images", | ||
| "logo.png", | ||
| ); | ||
|
|
||
| async function importAppAndSeedMedia({ | ||
| po, | ||
| fixtureName, | ||
| files, | ||
| }: { | ||
| po: PageObject; | ||
| fixtureName: string; | ||
| files: string[]; | ||
| }) { | ||
| await po.navigation.goToAppsTab(); | ||
| await po.appManagement.importApp(fixtureName); | ||
|
|
||
| // Wait for the title bar to show the imported app name. | ||
| // getCurrentAppName() only checks "not 'no app selected'", which races | ||
| // on subsequent imports where the title bar already shows a previous app. | ||
| await expect(po.appManagement.getTitleBarAppNameButton()).toContainText( | ||
| fixtureName, | ||
| { timeout: 15000 }, | ||
| ); | ||
|
|
||
| const appName = await po.appManagement.getCurrentAppName(); | ||
| if (!appName) { | ||
| throw new Error("Failed to get app name after import"); | ||
| } | ||
| const appPath = await po.appManagement.getCurrentAppPath(); | ||
| const mediaDirPath = path.join(appPath, ".dyad", "media"); | ||
| fs.mkdirSync(mediaDirPath, { recursive: true }); | ||
|
|
||
| for (const fileName of files) { | ||
| fs.copyFileSync(IMAGE_FIXTURE_PATH, path.join(mediaDirPath, fileName)); | ||
| } | ||
|
|
||
| return { appName, appPath, mediaDirPath }; | ||
| } | ||
|
|
||
| async function openMediaFolderByAppName(po: PageObject, appName: string) { | ||
| const collapsedFolder = po.page | ||
| .locator('[data-testid^="media-folder-"]') | ||
| .filter({ hasText: appName }) | ||
| .first(); | ||
|
|
||
| await expect(collapsedFolder).toBeVisible({ timeout: 15000 }); | ||
| await collapsedFolder.click(); | ||
| await expect(po.page.getByTestId("media-folder-back-button")).toBeVisible(); | ||
| } | ||
|
|
||
| async function openMediaActionsForFile(po: PageObject, fileName: string) { | ||
| const thumbnail = po.page | ||
| .getByTestId("media-thumbnail") | ||
| .filter({ hasText: fileName }) | ||
| .first(); | ||
|
|
||
| await expect(thumbnail).toBeVisible(); | ||
| await thumbnail.getByTestId("media-file-actions-trigger").click(); | ||
| } | ||
|
|
||
| testSkipIfWindows( | ||
| "media library - rename, move, delete, and start a new chat with image reference", | ||
| async ({ po }) => { | ||
| await po.setUp(); | ||
|
|
||
| const sourceApp = await importAppAndSeedMedia({ | ||
| po, | ||
| fixtureName: "minimal", | ||
| files: ["chat-image.png", "move-image.png"], | ||
| }); | ||
| const targetApp = await importAppAndSeedMedia({ | ||
| po, | ||
| fixtureName: "astro", | ||
| files: [], | ||
| }); | ||
|
|
||
| await po.navigation.goToLibraryTab(); | ||
| await po.page.getByRole("link", { name: "Media" }).click(); | ||
|
|
||
| await openMediaFolderByAppName(po, sourceApp.appName); | ||
|
|
||
| await openMediaActionsForFile(po, "move-image.png"); | ||
| await po.page.getByTestId("media-rename-image").click(); | ||
| await po.page.getByTestId("media-rename-input").fill("renamed-image"); | ||
| await po.page.getByTestId("media-rename-confirm-button").click(); | ||
|
|
||
| const sourceRenamedPath = path.join( | ||
| sourceApp.mediaDirPath, | ||
| "renamed-image.png", | ||
| ); | ||
| const sourceOldPath = path.join(sourceApp.mediaDirPath, "move-image.png"); | ||
|
|
||
| await expect.poll(() => fs.existsSync(sourceRenamedPath)).toBe(true); | ||
| await expect.poll(() => fs.existsSync(sourceOldPath)).toBe(false); | ||
|
|
||
| await openMediaActionsForFile(po, "renamed-image.png"); | ||
| await po.page.getByTestId("media-move-to-submenu").click(); | ||
| await po.page.getByRole("menuitem", { name: targetApp.appName }).click(); | ||
|
|
||
| const targetMovedPath = path.join( | ||
| targetApp.mediaDirPath, | ||
| "renamed-image.png", | ||
| ); | ||
|
|
||
| await expect.poll(() => fs.existsSync(sourceRenamedPath)).toBe(false); | ||
| await expect.poll(() => fs.existsSync(targetMovedPath)).toBe(true); | ||
|
|
||
| await po.page.getByTestId("media-folder-back-button").click(); | ||
| await openMediaFolderByAppName(po, targetApp.appName); | ||
|
|
||
| await openMediaActionsForFile(po, "renamed-image.png"); | ||
| await po.page.getByTestId("media-delete-image").click(); | ||
| await po.page.getByTestId("media-delete-confirm-button").click(); | ||
|
|
||
| await expect.poll(() => fs.existsSync(targetMovedPath)).toBe(false); | ||
|
|
||
| // After deleting the last file from the target folder, the folder | ||
| // disappears from the listing and the view returns to the folder list. | ||
| await openMediaFolderByAppName(po, sourceApp.appName); | ||
|
|
||
| await openMediaActionsForFile(po, "chat-image.png"); | ||
| await po.page.getByTestId("media-start-chat-with-image").click(); | ||
|
|
||
| await expect(po.chatActions.getChatInput()).toBeVisible(); | ||
| await expect(po.chatActions.getChatInput()).toContainText( | ||
| `@chat-image.png`, | ||
| ); | ||
| expect(await po.appManagement.getCurrentAppName()).toBe(sourceApp.appName); | ||
| }, | ||
| ); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 7 additions & 4 deletions
11
...add_prompt_deep_link.spec.ts_add-prompt-via-deep-link-with-base64-encoded-data-1.aria.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| - img | ||
| - text: Prompt | ||
| - img | ||
| - heading "Deep Link Test Prompt" [level=3] | ||
| - paragraph: A prompt created via deep link | ||
| - button: | ||
| - text: "You are a helpful assistant. Please help with: [task here]" | ||
| - button "Edit prompt": | ||
| - img | ||
| - button: | ||
| - img | ||
| - text: "You are a helpful assistant. Please help with: [task here]" | ||
| - button "Delete prompt": | ||
| - img |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { describe, expect, it } from "vitest"; | ||
| import { | ||
| parseMediaMentions, | ||
| stripResolvedMediaMentions, | ||
| } from "../shared/parse_media_mentions"; | ||
|
|
||
| describe("parseMediaMentions", () => { | ||
| it("parses @media mentions from prompt text", () => { | ||
| const prompt = "Check @media:cat.png and @media:dog.png please"; | ||
|
|
||
| expect(parseMediaMentions(prompt)).toEqual(["cat.png", "dog.png"]); | ||
| }); | ||
|
|
||
| it("parses @media mentions with URL-encoded filenames (e.g. spaces)", () => { | ||
| const prompt = "Check @media:my%20photo.png please"; | ||
|
|
||
| expect(parseMediaMentions(prompt)).toEqual(["my%20photo.png"]); | ||
| }); | ||
| }); | ||
|
|
||
| describe("stripResolvedMediaMentions", () => { | ||
| it("keeps user text when media mention is followed by adjacent text", () => { | ||
| const prompt = "@media:cat.pngdescribe this image"; | ||
|
|
||
| expect(stripResolvedMediaMentions(prompt, ["cat.png"])).toBe( | ||
| "describe this image", | ||
| ); | ||
| }); | ||
|
|
||
| it("strips only resolved mentions and preserves unresolved ones", () => { | ||
| const prompt = "Use @media:cat.png and @media:missing.png now"; | ||
|
|
||
| expect(stripResolvedMediaMentions(prompt, ["cat.png"])).toBe( | ||
| "Use and @media:missing.png now", | ||
| ); | ||
| }); | ||
|
|
||
| it("strips URL-encoded mentions (filenames with spaces)", () => { | ||
| const prompt = "Check @media:my%20photo.png please"; | ||
|
|
||
| expect(stripResolvedMediaMentions(prompt, ["my%20photo.png"])).toBe( | ||
| "Check please", | ||
| ); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.