mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Attachments: cleanup of ownership
This commit is contained in:
@@ -155,9 +155,9 @@ export function Composer(props: {
|
||||
|
||||
// attachments-overlay: comes from the attachments slice of the conversation overlay
|
||||
const {
|
||||
attachmentDrafts,
|
||||
attachAppendClipboardItems, attachAppendDataTransfer, attachAppendEgoContent, attachAppendFile,
|
||||
attachmentsClear, attachmentsTakeAllFragments, attachmentsTakeTextFragments,
|
||||
/* items */ attachmentDrafts,
|
||||
/* append */ attachAppendClipboardItems, attachAppendDataTransfer, attachAppendEgoContent, attachAppendFile,
|
||||
/* take */ attachmentsRemoveAll, attachmentsTakeAllFragments, attachmentsTakeTextFragments,
|
||||
} = useAttachmentDrafts(conversationOverlayStore, enableLoadURLsInComposer);
|
||||
|
||||
// attachments derived state
|
||||
@@ -216,9 +216,9 @@ export function Composer(props: {
|
||||
|
||||
const handleClear = React.useCallback(() => {
|
||||
setComposeText('');
|
||||
attachmentsClear();
|
||||
attachmentsRemoveAll();
|
||||
handleReplyToClear();
|
||||
}, [attachmentsClear, handleReplyToClear, setComposeText]);
|
||||
}, [attachmentsRemoveAll, handleReplyToClear, setComposeText]);
|
||||
|
||||
const handleSendAction = React.useCallback((_chatModeId: ChatModeId, composerText: string): boolean => {
|
||||
if (!isValidConversation(targetConversationId)) return false;
|
||||
@@ -228,8 +228,10 @@ export function Composer(props: {
|
||||
if (composerText)
|
||||
fragments.push(createTextContentFragment(composerText));
|
||||
const canAttach = chatModeCanAttach(_chatModeId);
|
||||
if (canAttach)
|
||||
fragments.push(...attachmentsTakeAllFragments(false));
|
||||
if (canAttach) {
|
||||
const attachmentFragments = await attachmentsTakeAllFragments('global', 'app-chat');
|
||||
fragments.push(...attachmentFragments);
|
||||
}
|
||||
if (!fragments.length) {
|
||||
// addSnackbar({ key: 'chat-composer-empty', message: 'Nothing to send', type: 'info' });
|
||||
return false;
|
||||
|
||||
@@ -74,7 +74,7 @@ export function LLMAttachmentsList(props: {
|
||||
const handleOverallClearConfirmed = React.useCallback(() => {
|
||||
handleOverallMenuHide();
|
||||
setConfirmClearAttachmentDrafts(false);
|
||||
props.attachmentDraftsStoreApi.getState().clearAttachmentsDrafts();
|
||||
props.attachmentDraftsStoreApi.getState().removeAllAttachmentDrafts();
|
||||
}, [handleOverallMenuHide, props.attachmentDraftsStoreApi]);
|
||||
|
||||
|
||||
|
||||
@@ -103,6 +103,15 @@ export async function removeAttachmentOwnedDBAsset(fragment: DMessageAttachmentF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the DBlob items associated with the given DMessageAttachmentFragment to a new context and scope
|
||||
*/
|
||||
export async function transferAttachmentOwnedDBAsset(fragment: DMessageAttachmentFragment, contextId: DBlobDBContextId, scopeId: DBlobDBScopeId) {
|
||||
if (fragment.part.pt === 'image_ref' && fragment.part.dataRef.reftype === 'dblob') {
|
||||
await transferDBAssetContextScope(fragment.part.dataRef.dblobAssetId, contextId, scopeId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GC Functions for Attachment DBlobs systems: remove leftover drafts
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { DMessageAttachmentFragment } from '~/common/stores/chat/chat.messa
|
||||
|
||||
import type { AttachmentDraft, AttachmentDraftId, AttachmentDraftSource } from './attachment.types';
|
||||
import { attachmentCreate, attachmentDefineConverters, attachmentLoadInputAsync, attachmentPerformConversion } from './attachment.pipeline';
|
||||
import { removeDBlobItemFromAttachmentFragment } from './attachment.dblobs';
|
||||
import { removeAttachmentOwnedDBAsset, transferAttachmentOwnedDBAsset } from './attachment.dblobs';
|
||||
|
||||
|
||||
/// Attachment Draft Slice: per-conversation attachments store ///
|
||||
@@ -21,15 +21,16 @@ interface AttachmentDraftsState {
|
||||
export interface AttachmentsDraftsStore extends AttachmentDraftsState {
|
||||
|
||||
createAttachmentDraft: (source: AttachmentDraftSource) => Promise<void>;
|
||||
clearAttachmentsDrafts: () => void;
|
||||
removeAllAttachmentDrafts: () => void;
|
||||
removeAttachmentDraft: (attachmentDraftId: AttachmentDraftId) => void;
|
||||
moveAttachmentDraft: (attachmentDraftId: AttachmentDraftId, delta: 1 | -1) => void;
|
||||
setAttachmentDraftConverterIdxAndConvert: (attachmentDraftId: AttachmentDraftId, converterIdx: number | null) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Extracts all fragments from the all drafts and clears the store.
|
||||
* Extracts all fragments from the all drafts and transfers ownership to the caller.
|
||||
* This store is cleared.
|
||||
*/
|
||||
takeAllFragments: (removeFragments: boolean) => DMessageAttachmentFragment[];
|
||||
takeAllFragments: (newContextId: DBlobDBContextId, newScopeId: DBlobDBScopeId) => Promise<DMessageAttachmentFragment[]>;
|
||||
|
||||
/**
|
||||
* Extracts text fragments from the attachment drafts and optionally removes them from the store.
|
||||
@@ -79,17 +80,17 @@ export const createAttachmentDraftsStoreSlice: StateCreator<AttachmentsDraftsSto
|
||||
await setAttachmentDraftConverterIdxAndConvert(attachmentDraftId, firstEnabledIndex > -1 ? firstEnabledIndex : 0);
|
||||
},
|
||||
|
||||
clearAttachmentsDrafts: () =>
|
||||
_set(_state => {
|
||||
// NOTE: commented because right now the attachments are not moved to a different scope
|
||||
// because this function is actually used to clear the attachments when the message is sent
|
||||
// TODO: do not use clearAttachments when the message is sent, figure out another way0
|
||||
// Remove the DBlob items associated with the removed fragments
|
||||
// for (let draft of _state.attachmentDrafts) {
|
||||
// for (let fragment of draft.outputFragments) {
|
||||
// void removeDBlobItemFromAttachmentFragment(fragment);
|
||||
// }
|
||||
// }
|
||||
removeAllAttachmentDrafts: () =>
|
||||
_set(state => {
|
||||
|
||||
// remove the associated DBlob items, as we still ahve
|
||||
for (const attachmentDraft of state.attachmentDrafts) {
|
||||
// Remove the DBlob items associated with the removed fragments
|
||||
for (let removedFragment of attachmentDraft.outputFragments) {
|
||||
void removeAttachmentOwnedDBAsset(removedFragment);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
attachmentDrafts: [],
|
||||
};
|
||||
@@ -103,7 +104,7 @@ export const createAttachmentDraftsStoreSlice: StateCreator<AttachmentsDraftsSto
|
||||
|
||||
// Remove the DBlob items associated with the removed fragments
|
||||
for (let removedFragment of attachment.outputFragments) {
|
||||
void removeDBlobItemFromAttachmentFragment(removedFragment);
|
||||
void removeAttachmentOwnedDBAsset(removedFragment);
|
||||
}
|
||||
|
||||
// Remove the draft
|
||||
@@ -136,16 +137,19 @@ export const createAttachmentDraftsStoreSlice: StateCreator<AttachmentsDraftsSto
|
||||
await attachmentPerformConversion(attachmentDraft, converterIdx, _editAttachment, _replaceAttachmentOutputFragments);
|
||||
},
|
||||
|
||||
takeAllFragments: (removeFragments: boolean): DMessageAttachmentFragment[] => {
|
||||
const allFragments: DMessageAttachmentFragment[] = [];
|
||||
_get().attachmentDrafts.forEach(draft => {
|
||||
allFragments.push(...draft.outputFragments);
|
||||
});
|
||||
takeAllFragments: async (newContextId: DBlobDBContextId, newScopeId: DBlobDBScopeId) => {
|
||||
// get all the fragments
|
||||
const transferredFragments: DMessageAttachmentFragment[] =
|
||||
_get().attachmentDrafts.flatMap(draft => draft.outputFragments);
|
||||
|
||||
if (removeFragments)
|
||||
_set({ attachmentDrafts: [] });
|
||||
// transfer ownership (await for transferAttachmentOwnedDBAsset)
|
||||
for (const transferredFragment of transferredFragments)
|
||||
await transferAttachmentOwnedDBAsset(transferredFragment, newContextId, newScopeId);
|
||||
|
||||
return allFragments;
|
||||
// clear state
|
||||
_set({ attachmentDrafts: [] });
|
||||
|
||||
return transferredFragments;
|
||||
},
|
||||
|
||||
takeTextFragments: (attachmentDraftId: AttachmentDraftId | null, removeFragments: boolean): DMessageAttachmentFragment[] => {
|
||||
@@ -174,7 +178,7 @@ export const createAttachmentDraftsStoreSlice: StateCreator<AttachmentsDraftsSto
|
||||
|
||||
// Removal: rmeove associated DBlob items
|
||||
for (let removedFragment of extractedTextFragments) {
|
||||
void removeDBlobItemFromAttachmentFragment(removedFragment);
|
||||
void removeAttachmentOwnedDBAsset(removedFragment);
|
||||
}
|
||||
|
||||
// Removal: leave non-text fragments in the draft
|
||||
@@ -216,7 +220,7 @@ export const createAttachmentDraftsStoreSlice: StateCreator<AttachmentsDraftsSto
|
||||
|
||||
// remove the DBlob items associated with the removed fragments
|
||||
for (let removedFragment of removedFragments) {
|
||||
void removeDBlobItemFromAttachmentFragment(removedFragment);
|
||||
void removeAttachmentOwnedDBAsset(removedFragment);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -21,10 +21,10 @@ const ATTACHMENTS_DEBUG_INTAKE = false;
|
||||
export const useAttachmentDrafts = (attachmentsStoreApi: AttachmentDraftsStoreApi | null, enableLoadURLs: boolean) => {
|
||||
|
||||
// state
|
||||
const { _createAttachmentDraft, attachmentDrafts, attachmentsClear, attachmentsTakeAllFragments, attachmentsTakeTextFragments } = useChatAttachmentsStore(attachmentsStoreApi, useShallow(state => ({
|
||||
const { _createAttachmentDraft, attachmentDrafts, attachmentsRemoveAll, attachmentsTakeAllFragments, attachmentsTakeTextFragments } = useChatAttachmentsStore(attachmentsStoreApi, useShallow(state => ({
|
||||
_createAttachmentDraft: state.createAttachmentDraft,
|
||||
attachmentDrafts: state.attachmentDrafts,
|
||||
attachmentsClear: state.clearAttachmentsDrafts,
|
||||
attachmentsRemoveAll: state.removeAllAttachmentDrafts,
|
||||
attachmentsTakeAllFragments: state.takeAllFragments,
|
||||
attachmentsTakeTextFragments: state.takeTextFragments,
|
||||
})));
|
||||
@@ -205,7 +205,7 @@ export const useAttachmentDrafts = (attachmentsStoreApi: AttachmentDraftsStoreAp
|
||||
attachAppendFile,
|
||||
|
||||
// manage attachments
|
||||
attachmentsClear,
|
||||
attachmentsRemoveAll,
|
||||
attachmentsTakeAllFragments,
|
||||
attachmentsTakeTextFragments,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user