Skip to content

Commit 6842712

Browse files
committed
Wire up auto-convert long pasted text to file attachment
1 parent 766401b commit 6842712

File tree

2 files changed

+76
-22
lines changed

2 files changed

+76
-22
lines changed

apps/twig/src/main/trpc/routers/os.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,28 @@ export const osRouter = router({
192192
}
193193
}),
194194

195+
/**
196+
* Save pasted text to a temp file
197+
* Returns the file path for use as a file attachment
198+
*/
199+
saveClipboardText: publicProcedure
200+
.input(
201+
z.object({
202+
text: z.string(),
203+
}),
204+
)
205+
.mutation(async ({ input }) => {
206+
const filename = `pasted-text-${Date.now()}.txt`;
207+
const tempDir = path.join(os.tmpdir(), "twig-clipboard");
208+
209+
await fsPromises.mkdir(tempDir, { recursive: true });
210+
const filePath = path.join(tempDir, filename);
211+
212+
await fsPromises.writeFile(filePath, input.text, "utf-8");
213+
214+
return { path: filePath, name: "pasted-text.txt" };
215+
}),
216+
195217
/**
196218
* Save clipboard image data to a temp file
197219
* Returns the file path for use as a file attachment

apps/twig/src/renderer/features/message-editor/tiptap/useTiptapEditor.ts

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { sessionStoreSetters } from "@features/sessions/stores/sessionStore";
2+
import { useSettingsStore as useFeatureSettingsStore } from "@features/settings/stores/settingsStore";
23
import { trpcVanilla } from "@renderer/trpc/client";
34
import { toast } from "@renderer/utils/toast";
45
import { useSettingsStore } from "@stores/settingsStore";
@@ -238,41 +239,72 @@ export function useTiptapEditor(options: UseTiptapEditorOptions) {
238239
}
239240
}
240241

241-
if (imageItems.length === 0) return false;
242+
if (imageItems.length > 0) {
243+
event.preventDefault();
242244

243-
event.preventDefault();
245+
(async () => {
246+
for (const item of imageItems) {
247+
const file = item.getAsFile();
248+
if (!file) continue;
249+
250+
try {
251+
const arrayBuffer = await file.arrayBuffer();
252+
const base64 = btoa(
253+
new Uint8Array(arrayBuffer).reduce(
254+
(data, byte) => data + String.fromCharCode(byte),
255+
"",
256+
),
257+
);
258+
259+
const result = await trpcVanilla.os.saveClipboardImage.mutate(
260+
{
261+
base64Data: base64,
262+
mimeType: file.type,
263+
originalName: file.name,
264+
},
265+
);
266+
267+
setAttachments((prev) => {
268+
if (prev.some((a) => a.id === result.path)) return prev;
269+
return [...prev, { id: result.path, label: result.name }];
270+
});
271+
} catch (_error) {
272+
toast.error("Failed to paste image");
273+
}
274+
}
275+
})();
244276

245-
(async () => {
246-
for (const item of imageItems) {
247-
const file = item.getAsFile();
248-
if (!file) continue;
277+
return true;
278+
}
249279

250-
try {
251-
const arrayBuffer = await file.arrayBuffer();
252-
const base64 = btoa(
253-
new Uint8Array(arrayBuffer).reduce(
254-
(data, byte) => data + String.fromCharCode(byte),
255-
"",
256-
),
257-
);
280+
// Auto-convert long pasted text into a file attachment
281+
const pastedText = event.clipboardData?.getData("text/plain");
282+
if (
283+
pastedText &&
284+
pastedText.length > 500 &&
285+
useFeatureSettingsStore.getState().autoConvertLongText
286+
) {
287+
event.preventDefault();
258288

259-
const result = await trpcVanilla.os.saveClipboardImage.mutate({
260-
base64Data: base64,
261-
mimeType: file.type,
262-
originalName: file.name,
289+
(async () => {
290+
try {
291+
const result = await trpcVanilla.os.saveClipboardText.mutate({
292+
text: pastedText,
263293
});
264294

265295
setAttachments((prev) => {
266296
if (prev.some((a) => a.id === result.path)) return prev;
267297
return [...prev, { id: result.path, label: result.name }];
268298
});
269299
} catch (_error) {
270-
toast.error("Failed to paste image");
300+
toast.error("Failed to convert pasted text to attachment");
271301
}
272-
}
273-
})();
302+
})();
274303

275-
return true;
304+
return true;
305+
}
306+
307+
return false;
276308
},
277309
},
278310
onCreate: () => {

0 commit comments

Comments
 (0)