Skip to content

Commit 490a942

Browse files
committed
Merge remote-tracking branch 'origin/master' into sagews-py-3.12
2 parents 8a0ec81 + 938adad commit 490a942

File tree

20 files changed

+328
-293
lines changed

20 files changed

+328
-293
lines changed

src/packages/frontend/chat/input.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,17 @@ export default function ChatInput({
156156
enableMentions={true}
157157
submitMentionsRef={submitMentionsRef}
158158
onChange={(input) => {
159+
/* BUG: in Markdown mode this stops getting
160+
called after you paste in an image. It works
161+
fine in Slate/Text mode. See
162+
https://github.com/sagemathinc/cocalc/issues/7728
163+
*/
159164
setInput(input);
160165
saveChat(input);
161166
}}
162167
onShiftEnter={(input) => {
168+
setInput(input);
169+
saveChat(input);
163170
saveChat.cancel();
164171
on_send(input);
165172
}}

src/packages/frontend/editors/markdown-input/component.tsx

Lines changed: 26 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,8 @@
77
Markdown editor
88
*/
99

10-
// Note -- the old file upload used .chat-images for everything,
11-
// rather than a directory for each file.
12-
const AUX_FILE_EXT = "upload";
13-
1410
import * as CodeMirror from "codemirror";
1511
import { debounce, isEqual } from "lodash";
16-
import { join } from "path";
1712
import {
1813
CSSProperties,
1914
MutableRefObject,
@@ -25,7 +20,6 @@ import {
2520
useRef,
2621
useState,
2722
} from "react";
28-
2923
import { alert_message } from "@cocalc/frontend/alerts";
3024
import {
3125
ReactDOM,
@@ -36,21 +30,16 @@ import {
3630
import { SubmitMentionsRef } from "@cocalc/frontend/chat/types";
3731
import { A } from "@cocalc/frontend/components";
3832
import { IS_MOBILE } from "@cocalc/frontend/feature";
39-
import { Dropzone, FileUploadWrapper } from "@cocalc/frontend/file-upload";
33+
import { Dropzone, BlobUpload } from "@cocalc/frontend/file-upload";
4034
import { Cursors, CursorsType } from "@cocalc/frontend/jupyter/cursors";
4135
import Fragment, { FragmentId } from "@cocalc/frontend/misc/fragment-id";
4236
import { useProjectHasInternetAccess } from "@cocalc/frontend/project/settings/has-internet-access-hook";
43-
import {
44-
aux_file,
45-
len,
46-
path_split,
47-
trunc,
48-
trunc_middle,
49-
} from "@cocalc/util/misc";
37+
import { len, trunc, trunc_middle } from "@cocalc/util/misc";
5038
import { Complete, Item } from "./complete";
5139
import { useMentionableUsers } from "./mentionable-users";
5240
import { submit_mentions } from "./mentions";
5341
import { EditorFunctions } from "./multimode";
42+
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
5443

5544
type EventHandlerFunction = (cm: CodeMirror.Editor) => void;
5645

@@ -162,6 +151,7 @@ export function MarkdownInput(props: Props) {
162151
unregisterEditor,
163152
value,
164153
} = props;
154+
const { actions } = useFrameContext();
165155
const cm = useRef<CodeMirror.Editor>();
166156
const textarea_ref = useRef<HTMLTextAreaElement>(null);
167157
const editor_settings = useRedux(["account", "editor_settings"]);
@@ -579,7 +569,7 @@ export function MarkdownInput(props: Props) {
579569
}
580570
if (cm.current == null) return;
581571
const input = cm.current.getValue();
582-
const s = upload_temp_link(path, file);
572+
const s = upload_temp_link(file);
583573
if (input.indexOf(s) != -1) {
584574
// already have link.
585575
return;
@@ -588,11 +578,7 @@ export function MarkdownInput(props: Props) {
588578
saveValue();
589579
}
590580

591-
function upload_complete(file: {
592-
type: string;
593-
name: string;
594-
status: string;
595-
}): void {
581+
function upload_complete(file): void {
596582
if (path == null) {
597583
throw Error("path must be set if enableUploads is set.");
598584
}
@@ -608,7 +594,7 @@ export function MarkdownInput(props: Props) {
608594
}
609595
if (cm.current == null) return;
610596
const input = cm.current.getValue();
611-
const s0 = upload_temp_link(path, file);
597+
const s0 = upload_temp_link(file);
612598
let s1: string;
613599
if (file.status == "error") {
614600
s1 = "";
@@ -617,43 +603,13 @@ export function MarkdownInput(props: Props) {
617603
// users can cancel files when they are being uploaded.
618604
s1 = "";
619605
} else {
620-
s1 = upload_link(path, file);
606+
s1 = upload_link(file);
621607
}
622608
const newValue = input.replace(s0, s1);
623609
setValueNoJump(newValue);
624610
saveValue();
625611
}
626612

627-
function upload_removed(file: { name: string; type: string }): void {
628-
if (cm.current == null) return;
629-
if (project_id == null || path == null) {
630-
throw Error("project_id and path must be set if enableUploads is set.");
631-
}
632-
if (!current_uploads_ref.current?.[file.name]) {
633-
// it actually succeeded if this is not set -- it was removed
634-
// via upload_complete above.
635-
return;
636-
}
637-
delete current_uploads_ref.current[file.name];
638-
if (onUploadEnd != null) {
639-
onUploadEnd();
640-
}
641-
642-
const input = cm.current.getValue();
643-
const s = upload_link(path, file);
644-
if (input.indexOf(s) == -1) {
645-
// not there anymore; maybe user already submitted -- do nothing further.
646-
return;
647-
}
648-
const newValue = input.replace(s, "");
649-
setValueNoJump(newValue);
650-
saveValue();
651-
// delete from project itself
652-
const target = join(aux_file(path, AUX_FILE_EXT), file.name);
653-
// console.log("deleting target", target, { paths: [target] });
654-
redux.getProjectActions(project_id).delete_files({ paths: [target] });
655-
}
656-
657613
function handle_paste_event(_, e): void {
658614
// console.log("handle_paste_event", e);
659615
const items = e.clipboardData.items;
@@ -926,49 +882,45 @@ export function MarkdownInput(props: Props) {
926882
const event_handlers = {
927883
complete: upload_complete,
928884
sending: upload_sending,
929-
removedfile: upload_removed,
885+
error: (_, message) => {
886+
actions?.set_error(`${message}`);
887+
},
930888
};
931889
if (project_id == null || path == null) {
932890
throw Error("project_id and path must be set if enableUploads is set.");
933891
}
934892
body = (
935-
<FileUploadWrapper
893+
<BlobUpload
894+
show_upload={false}
936895
project_id={project_id}
937-
dest_path={aux_file(path, AUX_FILE_EXT)}
938896
event_handlers={event_handlers}
939897
style={{ height: "100%", width: "100%" }}
940898
dropzone_ref={dropzone_ref}
941899
close_preview_ref={upload_close_preview_ref}
900+
config={
901+
// only images work since when pasting other doc types
902+
// things blow up (due to conflict with codemirror?)
903+
{ acceptedFiles: "image/*" }
904+
}
942905
>
943906
{body}
944-
</FileUploadWrapper>
907+
</BlobUpload>
945908
);
946909
}
947910

948911
return body;
949912
}
950913

951-
function upload_target(path: string, file: { name: string }): string {
952-
// path to our upload target, but relative to path.
953-
return join(path_split(aux_file(path, AUX_FILE_EXT)).tail, file.name);
954-
}
955-
956-
function upload_temp_link(path: string, file: { name: string }): string {
957-
return `[Uploading...]\(${upload_target(path, file)}\)`;
914+
function upload_temp_link(file): string {
915+
return `[Uploading...]\(${file.name ?? file.upload?.filename ?? ""}\)`;
958916
}
959917

960-
function upload_link(
961-
path: string,
962-
file: { name: string; type: string },
963-
): string {
964-
const target = upload_target(path, file);
965-
if (file.type.indexOf("image") !== -1) {
966-
return `<img src=\"${target}\" style="max-width:100%" />`;
918+
function upload_link(file): string {
919+
const { url, dataURL, height, upload } = file;
920+
if (!height && !dataURL?.startsWith("data:image")) {
921+
return `[${upload.filename ? upload.filename : "file"}](${url})`;
967922
} else {
968-
// We use an a tag instead of [${file.name}](${target}) because for
969-
// some files (e.g,. word doc files) our markdown renderer inexplicably
970-
// does NOT render them as links!? a tags work though.
971-
return `<a href=\"${target}\">${file.name}</a>`;
923+
return `![](${url})`;
972924
}
973925
}
974926

src/packages/frontend/editors/slate/upload.tsx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,10 @@
66
import { Transforms } from "slate";
77
import { SlateEditor } from "./editable-markdown";
88
import { useEffect, useMemo, useRef } from "react";
9-
import { Dropzone, FileUploadWrapper } from "@cocalc/frontend/file-upload";
10-
import { join } from "path";
11-
import { aux_file, path_split } from "@cocalc/util/misc";
12-
const AUX_FILE_EXT = "upload";
9+
import { Dropzone, BlobUpload } from "@cocalc/frontend/file-upload";
1310
import { getFocus } from "./format/commands";
1411
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
1512

16-
function uploadTarget(path: string, file: { name: string }): string {
17-
// path to our upload target, but relative to path.
18-
return join(path_split(aux_file(path, AUX_FILE_EXT)).tail, file.name);
19-
}
20-
2113
export default function useUpload(
2214
editor: SlateEditor,
2315
body: JSX.Element,
@@ -66,46 +58,54 @@ export default function useUpload(
6658
// depends on in a ref and only create it once.
6759
const updloadEventHandlers = useMemo(() => {
6860
return {
61+
error: (_, message) => {
62+
actions?.set_error(`${message}`);
63+
},
6964
sending: ({ name }) => {
7065
actionsRef.current?.set_status?.(`Uploading ${name}...`);
7166
},
72-
complete: (file: { type: string; name: string; status: string }) => {
67+
complete: (file) => {
7368
actionsRef.current?.set_status?.("");
69+
const { url } = file;
70+
if (!url) {
71+
// probably an error
72+
return;
73+
}
7474
let node;
75-
if (file.type.indexOf("image") == -1) {
75+
const { dataURL, height, upload } = file;
76+
if (!height && !dataURL?.startsWith("data:image")) {
7677
node = {
7778
type: "link",
7879
isInline: true,
79-
children: [{ text: file.name }],
80-
url: uploadTarget(pathRef.current, file),
81-
};
80+
children: [{ text: upload.filename ? upload.filename : "file" }],
81+
url,
82+
} as const;
8283
} else {
8384
node = {
8485
type: "image",
8586
isInline: true,
8687
isVoid: true,
87-
src: uploadTarget(pathRef.current, file),
88+
src: url,
8889
children: [{ text: "" }],
89-
};
90+
} as const;
9091
}
91-
Transforms.insertFragment(editor, [node as any], {
92+
Transforms.insertFragment(editor, [node], {
9293
at: getFocus(editor),
9394
});
9495
},
9596
};
9697
}, []);
9798

9899
return (
99-
<FileUploadWrapper
100+
<BlobUpload
101+
show_upload={false}
100102
className="smc-vfill"
101103
project_id={project_id}
102-
dest_path={aux_file(path, AUX_FILE_EXT)}
103104
event_handlers={updloadEventHandlers}
104105
style={{ height: "100%", width: "100%" }}
105106
dropzone_ref={dropzoneRef}
106-
show_upload={true}
107107
>
108108
{body}
109-
</FileUploadWrapper>
109+
</BlobUpload>
110110
);
111111
}

0 commit comments

Comments
 (0)