Skip to content

Commit 75a4623

Browse files
authored
Configure external sources (#149)
* Split actions component and fix scroll. * Allow configuration of remote sources. * Save remote sources to local storage. * Make dollar katex delimiter more strict. * Update lockfile. * Display labels on notes. * Change default zoom and delay closing highlights on hover. * Review fixes. * Avoid pre-wrap issues in labels. * Format. * Explicitly override white-space on labels.
1 parent 9e7f9c2 commit 75a4623

File tree

29 files changed

+617
-157
lines changed

29 files changed

+617
-157
lines changed

package-lock.json

Lines changed: 74 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"pdfjs-dist": "^4.5.136",
2626
"react": "^18.3.1",
2727
"react-dom": "^18.3.1",
28+
"react-modal": "^3.16.3",
2829
"react-tooltip": "^5.27.1"
2930
},
3031
"devDependencies": {
@@ -33,6 +34,7 @@
3334
"@types/katex": "^0.16.7",
3435
"@types/react": "^18.3.3",
3536
"@types/react-dom": "^18.3.0",
37+
"@types/react-modal": "^3.16.3",
3638
"@vitejs/plugin-react": "^4.3.1",
3739
"typescript": "^5.2.2",
3840
"vite": "^5.3.4",

src/components/Label/Label.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.label {
2+
white-space: nowrap;
3+
}

src/components/Label/Label.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import "./Label.css";
12
import { useMemo } from "react";
23

34
export function Label({ label, prefix = "" }: { label: string; prefix?: string }) {
45
const backgroundColor = useMemo(() => labelToColor(label), [label]);
56
return (
6-
<span style={{ backgroundColor }}>
7+
<span style={{ backgroundColor }} className="label">
78
{prefix} {label}
89
</span>
910
);

src/components/NoteManager/NoteManager.css

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
.notes-wrapper {
2+
height: 100%;
3+
display: flex;
4+
flex-direction: column;
5+
}
6+
7+
.notes-wrapper .note-manager {
8+
flex: 1;
9+
overflow: auto;
10+
}
11+
12+
.notes-wrapper .notes-actions {
13+
margin-top: 2rem;
14+
display: flex;
15+
gap: 1rem;
16+
font-size: 0.8rem;
17+
}
18+
119
.note-manager .new-note button {
220
width: 100%;
321
}
@@ -35,7 +53,6 @@
3553
.note-manager .icon {
3654
margin-right: 3px;
3755
color: #e22;
38-
background-color: lightyellow;
3956
padding: 2px;
4057
}
4158

@@ -53,7 +70,8 @@
5370

5471
.note-manager .note {
5572
padding: 8px;
56-
border: 1px solid #eee;
73+
border: 1px solid;
74+
border-color: light-dark(#eee, #444);
5775
margin-top: 5px;
5876
border-radius: 6px;
5977
}
@@ -62,12 +80,6 @@
6280
font-weight: bold;
6381
}
6482

65-
.note-manager .notes-actions {
66-
margin-top: 2rem;
67-
display: flex;
68-
gap: 2rem;
69-
}
70-
7183
.note-manager .note .actions {
7284
display: flex;
7385
}
Lines changed: 15 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,32 @@
1-
import { type ChangeEventHandler, useCallback, useContext, useEffect, useRef, useState } from "react";
1+
import { useCallback, useContext, useEffect, useState } from "react";
22
import "./NoteManager.css";
3-
import { Tooltip } from "react-tooltip";
43
import { validateMath } from "../../utils/validateMath";
54
import { LabelsFilter } from "../LabelsFilter/LabelsFilter";
65
import { type ILocationContext, LocationContext } from "../LocationProvider/LocationProvider";
7-
import { LEGACY_READER_HOST } from "../MetadataProvider/MetadataProvider";
86
import { type INotesContext, NotesContext } from "../NotesProvider/NotesProvider";
97
import { LABEL_LOCAL } from "../NotesProvider/consts/labels";
108
import type { IStorageNote } from "../NotesProvider/types/StorageNote";
119
import { type ISelectionContext, SelectionContext } from "../SelectionProvider/SelectionProvider";
1210
import { Note } from "./components/Note";
11+
import { NotesActions } from "./components/NotesActions";
1312

1413
const DEFAULT_AUTHOR = "";
1514

1615
export function NoteManager() {
16+
return (
17+
<div className="notes-wrapper">
18+
<Notes />
19+
<NotesActions />
20+
</div>
21+
);
22+
}
23+
24+
function Notes() {
1725
const [noteContent, setNoteContent] = useState("");
1826
const [noteContentError, setNoteContentError] = useState("");
1927
const { locationParams } = useContext(LocationContext) as ILocationContext;
20-
const {
21-
notesReady,
22-
notes,
23-
labels,
24-
canUndo,
25-
canRedo,
26-
hasLegacyNotes,
27-
handleAddNote,
28-
handleDeleteNote,
29-
handleUpdateNote,
30-
handleUndo,
31-
handleRedo,
32-
handleImport,
33-
handleExport,
34-
handleLegacyExport,
35-
handleToggleLabel,
36-
} = useContext(NotesContext) as INotesContext;
28+
const { notesReady, notes, labels, handleAddNote, handleDeleteNote, handleUpdateNote, handleToggleLabel } =
29+
useContext(NotesContext) as INotesContext;
3730
const { selectedBlocks, pageNumber, handleClearSelection } = useContext(SelectionContext) as ISelectionContext;
3831

3932
const handleAddNoteClick = useCallback(() => {
@@ -78,33 +71,6 @@ export function NoteManager() {
7871
}
7972
}, [selectedBlocks]);
8073

81-
const fileImport = useRef<HTMLInputElement>(null);
82-
const onImport = useCallback(() => {
83-
fileImport.current?.click();
84-
}, []);
85-
86-
const handleFileSelected = useCallback<ChangeEventHandler<HTMLInputElement>>(
87-
(ev) => {
88-
if (!ev.target?.files?.length) {
89-
return;
90-
}
91-
const fileToImport = ev.target.files[0];
92-
93-
const f = new FileReader();
94-
f.onload = (e) => {
95-
const fileContent = e.target?.result?.toString() || "";
96-
try {
97-
handleImport(fileContent, fileToImport.name.substring(0, 12));
98-
} catch (e) {
99-
console.error(e);
100-
alert("Unable to load the notes file. Check console for details.");
101-
}
102-
};
103-
f.readAsText(fileToImport);
104-
},
105-
[handleImport],
106-
);
107-
10874
return (
10975
<div className="note-manager" style={{ opacity: notesReady ? 1.0 : 0.3 }}>
11076
<div className="new-note">
@@ -116,37 +82,17 @@ export function NoteManager() {
11682
onChange={(ev) => setNoteContent(ev.currentTarget.value)}
11783
placeholder="Add a note to the selected fragment. Math typesetting is supported! Use standard delimiters such as $...$, \[...\] or \begin{equation}...\end{equation}."
11884
/>
85+
11986
{noteContentError ? <div className="validation-message">{noteContentError}</div> : null}
12087
<button disabled={noteContent.length < 1} onClick={handleAddNoteClick}>
12188
Add
12289
</button>
12390
</div>
91+
12492
<LabelsFilter labels={labels} onToggleLabel={handleToggleLabel} />
12593
{notes.map((note) => (
12694
<Note key={note.key} note={note} onEditNote={handleUpdateNote} onDeleteNote={handleDeleteNote} />
12795
))}
128-
<div className="notes-actions">
129-
<button onClick={handleUndo} disabled={!canUndo}>
130-
undo
131-
</button>
132-
<button onClick={handleRedo} disabled={!canRedo}>
133-
redo
134-
</button>
135-
<button onClick={onImport}>import notes</button>
136-
<button onClick={handleExport}>export notes</button>
137-
{hasLegacyNotes ? (
138-
<button
139-
data-tooltip-id="legacy-export-tooltip"
140-
data-tooltip-content={`Notes from the old version of graypaper reader have been detected. You may export them for use with ${LEGACY_READER_HOST}.`}
141-
data-tooltip-place="bottom"
142-
onClick={handleLegacyExport}
143-
>
144-
export old notes
145-
</button>
146-
) : null}
147-
</div>
148-
<input ref={fileImport} onChange={handleFileSelected} type="file" style={{ opacity: 0 }} />
149-
<Tooltip id="legacy-export-tooltip" />
15096
</div>
15197
);
15298
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.settings-close {
2+
float: right;
3+
}
4+
.settings-title {
5+
font-size: 1.5rem;
6+
font-weight: bold;
7+
}
8+
9+
@media (prefers-color-scheme: dark) {
10+
.ReactModal__Overlay {
11+
background: rgba(32, 32, 32, 0.8) !important;
12+
}
13+
14+
.ReactModal__Content {
15+
background: rgb(32, 32, 32) !important;
16+
border-color: rgb(132, 132, 132) !important;
17+
}
18+
}

0 commit comments

Comments
 (0)