Skip to content

AI Chat: save images to backpack + overflow menu#72558

Open
sanchitmalhotra126 wants to merge 3 commits intostagingfrom
sanchit/aichat-backpack-save
Open

AI Chat: save images to backpack + overflow menu#72558
sanchitmalhotra126 wants to merge 3 commits intostagingfrom
sanchit/aichat-backpack-save

Conversation

@sanchitmalhotra126
Copy link
Copy Markdown
Contributor

Enables saving AI Chat images to the lab's backpack (and more) through a new overflow menu accessible by a three-dot overlay button on images in the chat. The menu also includes options for copying and downloading.

The overflow menu and button are built using Codebridge's existing PopupButton and PopupButtonOption components.

I also included a few tweaks to the Backpack Client API to make it easier to use in an async/await context (rather than having to pass in callbacks). However, callbacks are still supported so this doesn't affect existing users.

Demo (including keyboard nav):

aichat-asset-overflow-menu.mov

Error notification if saving to backpack or fetching backpack metadata fails:

Screenshot 2026-05-06 at 11 51 09 AM

Links

Testing story

Tested with AI Chat lab levels (technically this works with AI Tutor as well but only for user-added images).

@sanchitmalhotra126 sanchitmalhotra126 requested review from a team, cnbrenci, dju90 and fisher-alice May 6, 2026 18:53
@@ -104,33 +103,31 @@ export default class BackpackClientApi {
}

async getFileList(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI @molly-moen @fisher-alice updated this function to return the fetched file list in addition to passing it through the success callbacks so that callers can now just do const files = await backpackApi.getFileList(). Callbacks are still called so existing behavior is unchanged.

Similarly above I converted fetchChannelId to an async function so we can just do await this.fetchChannelId() here. Still calls the callback if provided.

<Snackbar
open
slots={{transition: React.Fragment}}
slots={{transition: SnackbarPassthrough}}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix for a react warning - not strictly related to this change.

Copy link
Copy Markdown
Contributor

@fisher-alice fisher-alice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! A couple small styling questions, but one wonder is about the backpack error notification and whether it warrants being added as a chat event. Nice job!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just confirming that you'll move this and related PopUpButton files to lab2 in a follow-up?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! Maybe getFileNameWithNumberSuffix too

const hour12 = rawHour % 12 || 12;
const hh = String(hour12).padStart(2, '0');
const mm = String(now.getMinutes()).padStart(2, '0');
return `${month}-${day}-${hh}${mm}${ampm}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could add a break (maybe underscore) between hour and min for easier readability.
cc: @dju90

Image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are colons not allowed characters for file names? I think underscore is fine if not.

Copy link
Copy Markdown
Contributor

@fisher-alice fisher-alice May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Colons not allowed in Web Lab 2 file names.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MacOS uses dots (Screenshot 2026-05-05 at 3.32.15 PM). May-7-10.12am.png? or with spaces May 7 10.12 AM.png?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, codebridge file names don't allow dots nor spaces. And I'm assuming these backpack images are intended to be used in Web Lab 2?

Comment thread apps/src/aichat/views/assets/AssetImageOverflowMenu.tsx Outdated

const ext = extFromFilename(filename) || extFromUrl(url) || DEFAULT_EXT;

const showBackpackError = useCallback(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This made me pause. In weblab2 we display errors in the backpack panel (a user attempts to add files to backpack from file browser). So I wonder if we want to be consistent across labs.

However, I do see that showing the error close to where the user is attempting to trigger the save to backpack is helpful. I do wonder about adding this kind of notification to chat history makes sense? It doesn't seem that relevant in terms of chat history with model.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like in Weblab2 we throw up an error dialog?

Screenshot 2026-05-07 at 10 43 07 AM

I could go either way, but personally find the in-chat notification a little less obtrusive? Defer to @dju90

And re: chat history, yep we filter out notifications (unless includeInChatHistory is true) so these aren't saved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh thanks for sharing! then yeah I think this is fine but defer to Bryan.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this a little more, and still leaning towards not notifying in chat stream since it's not related to chat with model (unlike clear chat, updating model customizations, etc).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering about the visibility of button for images with dark background. Maybe add a box shadow? Or could flip the colors (white background, dark dots with box-shadow)?

Copy link
Copy Markdown
Contributor

@fisher-alice fisher-alice May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's what it would look like with flipped colors:

Screen.Recording.2026-05-07.at.11.01.31.AM.mov

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'll play around with this, thanks!

Copy link
Copy Markdown
Contributor Author

@sanchitmalhotra126 sanchitmalhotra126 May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the branch! Adapted this and tweaked some of the colors (FYI @dju90):

aichat-button-overlay.mov

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvements!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants