mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
feat: improve properties UI and add attachments section
This commit is contained in:
@@ -170,7 +170,7 @@ function Editor({ noteId, nonce }) {
|
||||
</Suspense>
|
||||
</Animated.Flex>
|
||||
</Flex>
|
||||
<Properties />
|
||||
<Properties noteId={noteId} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export const Plus = createIcon(Icons.mdiPlus);
|
||||
export const Note = createIcon(Icons.mdiHomeVariantOutline);
|
||||
export const Minus = createIcon(Icons.mdiMinus);
|
||||
export const Notebook = createIcon(Icons.mdiBookOutline);
|
||||
export const Notebook2 = createIcon(Icons.mdiBookOutline);
|
||||
export const Notebook2 = createIcon(Icons.mdiNotebookOutline);
|
||||
export const ArrowLeft = createIcon(Icons.mdiArrowLeft);
|
||||
export const ArrowRight = createIcon(Icons.mdiArrowRight);
|
||||
export const ArrowDown = createIcon(Icons.mdiArrowDown);
|
||||
@@ -128,8 +128,8 @@ export const Error = createIcon(Icons.mdiAlertCircle);
|
||||
export const Warn = createIcon(Icons.mdiAlert);
|
||||
export const Info = createIcon(Icons.mdiInformation);
|
||||
|
||||
export const ToggleUnchecked = createIcon(Icons.mdiToggleSwitchOff);
|
||||
export const ToggleChecked = createIcon(Icons.mdiToggleSwitch);
|
||||
export const ToggleUnchecked = createIcon(Icons.mdiToggleSwitchOffOutline);
|
||||
export const ToggleChecked = createIcon(Icons.mdiToggleSwitchOutline);
|
||||
|
||||
export const Backup = createIcon(Icons.mdiBackupRestore);
|
||||
export const Buy = createIcon(Icons.mdiCurrencyUsdCircleOutline);
|
||||
@@ -179,3 +179,6 @@ export const Twitter = createIcon(Icons.mdiTwitter);
|
||||
export const Reddit = createIcon(Icons.mdiReddit);
|
||||
|
||||
export const Dismiss = createIcon(Icons.mdiClose);
|
||||
|
||||
export const File = createIcon(Icons.mdiFileOutline);
|
||||
export const Download = createIcon(Icons.mdiArrowDown);
|
||||
|
||||
@@ -1,33 +1,37 @@
|
||||
import React, { useCallback } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import * as Icon from "../icons";
|
||||
import { Flex, Text, Button } from "rebass";
|
||||
import { Flex, Text, Button, Box } from "rebass";
|
||||
import { useStore } from "../../stores/editor-store";
|
||||
import { COLORS } from "../../common";
|
||||
import { AppEventManager, AppEvents, COLORS } from "../../common";
|
||||
import { db } from "../../common/db";
|
||||
import { useStore as useAppStore } from "../../stores/app-store";
|
||||
import Animated from "../animated";
|
||||
import Toggle from "./toggle";
|
||||
import { showMoveNoteDialog } from "../../common/dialog-controller";
|
||||
import { navigate } from "../../navigation";
|
||||
import IconTag from "../icon-tag";
|
||||
import FileSaver from "file-saver";
|
||||
|
||||
const tools = [
|
||||
{ key: "pinned", icons: { on: Icon.PinFilled, off: Icon.Pin }, label: "Pin" },
|
||||
{ key: "pinned", icon: Icon.Pin, label: "Pin" },
|
||||
{
|
||||
key: "favorite",
|
||||
icons: { on: Icon.Star, off: Icon.StarOutline },
|
||||
icon: Icon.StarOutline,
|
||||
label: "Favorite",
|
||||
},
|
||||
{ key: "locked", icons: { on: Icon.Lock, off: Icon.Unlock }, label: "Lock" },
|
||||
{ key: "locked", icon: Icon.Unlock, label: "Lock" },
|
||||
];
|
||||
|
||||
function Properties() {
|
||||
const color = useStore((store) => store.session.color);
|
||||
const toggleLocked = useStore((store) => store.toggleLocked);
|
||||
const sessionId = useStore((store) => store.session.id);
|
||||
const notebooks = useStore((store) => store.session.notebooks);
|
||||
const setSession = useStore((store) => store.setSession);
|
||||
const setColor = useStore((store) => store.setColor);
|
||||
function Properties({ noteId }) {
|
||||
const [attachmentsStatus, setAttachmentsStatus] = useState({});
|
||||
const arePropertiesVisible = useStore((store) => store.arePropertiesVisible);
|
||||
const color = useStore((store) => store.session.color);
|
||||
const notebooks = useStore((store) => store.session.notebooks);
|
||||
const attachments = useStore((store) => store.session.attachments);
|
||||
|
||||
const toggleLocked = useStore((store) => store.toggleLocked);
|
||||
const setSession = useStore((store) => store.setSession);
|
||||
const sessionId = useStore((store) => store.session.id);
|
||||
const setColor = useStore((store) => store.setColor);
|
||||
const toggleProperties = useStore((store) => store.toggleProperties);
|
||||
const isFocusMode = useAppStore((store) => store.isFocusMode);
|
||||
|
||||
@@ -44,183 +48,328 @@ function Properties() {
|
||||
[setSession, toggleLocked]
|
||||
);
|
||||
|
||||
return (
|
||||
!isFocusMode && (
|
||||
<>
|
||||
<Animated.Flex
|
||||
animate={{
|
||||
x: arePropertiesVisible ? 0 : 800,
|
||||
display: arePropertiesVisible ? "flex" : "none",
|
||||
}}
|
||||
transition={{
|
||||
duration: 0.3,
|
||||
bounceDamping: 1,
|
||||
bounceStiffness: 1,
|
||||
ease: "easeOut",
|
||||
}}
|
||||
initial={false}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
zIndex: 3,
|
||||
height: "100%",
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden",
|
||||
height: "100%",
|
||||
width: "300px",
|
||||
borderLeft: "1px solid",
|
||||
borderLeftColor: "border",
|
||||
}}
|
||||
flexDirection="column"
|
||||
bg="background"
|
||||
px={3}
|
||||
py={0}
|
||||
>
|
||||
<Text
|
||||
variant="title"
|
||||
my={2}
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
sx={{ display: "flex" }}
|
||||
>
|
||||
Properties
|
||||
<Text
|
||||
data-test-id="properties-close"
|
||||
as="span"
|
||||
onClick={() => toggleProperties()}
|
||||
sx={{
|
||||
color: "red",
|
||||
height: 24,
|
||||
":active": { color: "darkRed" },
|
||||
}}
|
||||
>
|
||||
<Icon.Close />
|
||||
</Text>
|
||||
</Text>
|
||||
{sessionId ? (
|
||||
<>
|
||||
<Flex>
|
||||
{tools.map((tool, _) => (
|
||||
<Toggle
|
||||
{...tool}
|
||||
key={tool.key}
|
||||
toggleKey={tool.key}
|
||||
onToggle={(state) => changeState(tool.key, state)}
|
||||
testId={`properties-${tool.key}`}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
<Flex flexDirection="column">
|
||||
{COLORS.map((label) => (
|
||||
<Flex
|
||||
key={label}
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
onClick={() => setColor(label)}
|
||||
sx={{ cursor: "pointer" }}
|
||||
mt={4}
|
||||
data-test-id={`properties-${label}`}
|
||||
>
|
||||
<Flex key={label} alignItems="center">
|
||||
<Icon.Circle size={14} color={label.toLowerCase()} />
|
||||
<Text ml={1} color="text" variant="body">
|
||||
{label}
|
||||
</Text>
|
||||
</Flex>
|
||||
{label.toLowerCase() === color?.toLowerCase() && (
|
||||
<Icon.Checkmark
|
||||
color="primary"
|
||||
size={20}
|
||||
data-test-id={`properties-${label}-check`}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
{notebooks?.length && (
|
||||
<>
|
||||
<Text variant="subtitle" mt={4} mb={1}>
|
||||
Referenced in {notebooks.length} notebook(s):
|
||||
</Text>
|
||||
{notebooks.map((ref) => {
|
||||
const notebook = db.notebooks.notebook(ref.id);
|
||||
if (!notebook) return null;
|
||||
const topics = ref.topics.reduce((topics, topicId) => {
|
||||
const topic = notebook.topics.topic(topicId);
|
||||
if (!!topic && !!topic._topic)
|
||||
topics.push(topic._topic);
|
||||
return topics;
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const event = AppEventManager.subscribe(
|
||||
AppEvents.UPDATE_ATTACHMENT_PROGRESS,
|
||||
({ hash, type, total, loaded }) => {
|
||||
if (!attachments.find((a) => a.metadata.hash === hash)) return;
|
||||
setAttachmentsStatus((status) => {
|
||||
const copy = { ...status };
|
||||
copy[hash] = {
|
||||
type,
|
||||
progress: Math.round((loaded / total) * 100),
|
||||
};
|
||||
return copy;
|
||||
});
|
||||
}
|
||||
);
|
||||
return () => {
|
||||
event.unsubscribe();
|
||||
};
|
||||
}, [attachments]);
|
||||
|
||||
return (
|
||||
<Flex flexDirection="column" my={1}>
|
||||
<Flex
|
||||
onClick={() => {
|
||||
navigate(`/notebooks/${notebook.data.id}`);
|
||||
}}
|
||||
mb={1}
|
||||
>
|
||||
<Icon.Notebook size={12} />
|
||||
<Text
|
||||
variant="body"
|
||||
ml={1}
|
||||
sx={{ cursor: "pointer" }}
|
||||
>
|
||||
{notebook.title}
|
||||
</Text>
|
||||
</Flex>
|
||||
{topics.map((topic) => (
|
||||
<Flex
|
||||
mb={1}
|
||||
ml={2}
|
||||
onClick={() => {
|
||||
navigate(
|
||||
`/notebooks/${notebook.data.id}/${topic.id}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Icon.Topic size={12} />
|
||||
<Text
|
||||
variant="body"
|
||||
ml={1}
|
||||
sx={{ cursor: "pointer" }}
|
||||
>
|
||||
{topic.title}
|
||||
</Text>
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={async () => {
|
||||
await showMoveNoteDialog([sessionId]);
|
||||
}}
|
||||
data-test-id="properties-add-to-nb"
|
||||
mt={notebooks?.length ? 0 : 3}
|
||||
>
|
||||
Add to notebook
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<Text
|
||||
variant="body"
|
||||
sx={{ justifySelf: "center", alignSelf: "center" }}
|
||||
if (isFocusMode || !sessionId) return null;
|
||||
return (
|
||||
<>
|
||||
<Animated.Flex
|
||||
animate={{
|
||||
x: arePropertiesVisible ? 0 : 800,
|
||||
display: arePropertiesVisible ? "flex" : "none",
|
||||
}}
|
||||
transition={{
|
||||
duration: 0.3,
|
||||
bounceDamping: 1,
|
||||
bounceStiffness: 1,
|
||||
ease: "easeOut",
|
||||
}}
|
||||
initial={false}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
zIndex: 3,
|
||||
height: "100%",
|
||||
width: "300px",
|
||||
borderLeft: "1px solid",
|
||||
borderLeftColor: "border",
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden",
|
||||
}}
|
||||
flexDirection="column"
|
||||
bg="background"
|
||||
// px={2}
|
||||
>
|
||||
<Card title="Properties">
|
||||
{tools.map((tool, _) => (
|
||||
<Toggle
|
||||
{...tool}
|
||||
key={tool.key}
|
||||
toggleKey={tool.key}
|
||||
onToggle={(state) => changeState(tool.key, state)}
|
||||
testId={`properties-${tool.key}`}
|
||||
/>
|
||||
))}
|
||||
<Flex
|
||||
py={2}
|
||||
px={2}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
}}
|
||||
justifyContent="center"
|
||||
>
|
||||
{COLORS.map((label) => (
|
||||
<Flex
|
||||
key={label}
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
onClick={() => setColor(label)}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
}}
|
||||
data-test-id={`properties-${label}`}
|
||||
>
|
||||
Start writing to make a new note.
|
||||
</Text>
|
||||
)}
|
||||
<Icon.Circle size={35} color={label.toLowerCase()} />
|
||||
{label.toLowerCase() === color?.toLowerCase() && (
|
||||
<Icon.Checkmark
|
||||
color="static"
|
||||
size={18}
|
||||
sx={{ position: "absolute", left: "8px" }}
|
||||
data-test-id={`properties-${label}-check`}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
</Animated.Flex>
|
||||
</>
|
||||
)
|
||||
</Card>
|
||||
{notebooks?.length && (
|
||||
<Card title="Referenced In">
|
||||
{notebooks.map((ref) => {
|
||||
const notebook = db.notebooks.notebook(ref.id);
|
||||
if (!notebook) return null;
|
||||
const topics = ref.topics.reduce((topics, topicId) => {
|
||||
const topic = notebook.topics.topic(topicId);
|
||||
if (!!topic && !!topic._topic) topics.push(topic._topic);
|
||||
return topics;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
py={2}
|
||||
px={2}
|
||||
sx={{
|
||||
borderBottom: "1px solid var(--border)",
|
||||
":last-of-type": { borderBottom: "none" },
|
||||
cursor: "pointer",
|
||||
":hover": {
|
||||
bg: "hover",
|
||||
},
|
||||
}}
|
||||
flexDirection="column"
|
||||
onClick={() => {
|
||||
navigate(`/notebooks/${notebook.data.id}`);
|
||||
}}
|
||||
>
|
||||
<Text variant="body" display="flex" alignItems="center">
|
||||
<Icon.Notebook size={13} sx={{ flexShrink: 0, mr: 1 }} />
|
||||
{notebook.title}
|
||||
</Text>
|
||||
|
||||
<Flex
|
||||
sx={{
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
mt="2.5px"
|
||||
>
|
||||
{topics.map((topic) => (
|
||||
<IconTag
|
||||
title={topic.title}
|
||||
text={topic.title}
|
||||
key={topic.id}
|
||||
icon={Icon.Topic}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
navigate(
|
||||
`/notebooks/${notebook.data.id}/${topic.id}`
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Card>
|
||||
)}
|
||||
{attachments.length > 0 && (
|
||||
<Card title="Attachments">
|
||||
{attachments.map((attachment) => {
|
||||
const attachmentStatus =
|
||||
attachmentsStatus[attachment.metadata.hash];
|
||||
return (
|
||||
<Flex
|
||||
//py={2}
|
||||
py={0}
|
||||
px={2}
|
||||
sx={{
|
||||
borderBottom: "1px solid var(--border)",
|
||||
":last-of-type": { borderBottom: "none" },
|
||||
":hover .attachment-actions": {
|
||||
display: "flex",
|
||||
},
|
||||
":hover .attachment-size": {
|
||||
display: "none",
|
||||
},
|
||||
}}
|
||||
title={attachment.metadata.filename}
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Flex flexDirection="column">
|
||||
<Text
|
||||
variant="body"
|
||||
sx={{
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{formatFilename(attachment.metadata.filename)}
|
||||
</Text>
|
||||
{attachmentStatus && (
|
||||
<Box
|
||||
sx={{
|
||||
my: 1,
|
||||
bg: "primary",
|
||||
height: "2px",
|
||||
width: `${attachmentStatus.progress}%`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<Text
|
||||
className="attachment-size"
|
||||
variant="subBody"
|
||||
flexShrink={0}
|
||||
p={1}
|
||||
m={1}
|
||||
>
|
||||
{formatBytes(attachment.length, 1)}
|
||||
</Text>
|
||||
<Box display="none" className="attachment-actions">
|
||||
{attachmentStatus ? (
|
||||
<Button
|
||||
title="Cancel download"
|
||||
variant="tool"
|
||||
p={1}
|
||||
m={1}
|
||||
bg="transparent"
|
||||
sx={{ ":hover": { bg: "hover" } }}
|
||||
onClick={async () => {
|
||||
await db.fs.cancel(
|
||||
attachment.metadata.hash,
|
||||
"download"
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Icon.Close size={16} />
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
title="Download attachment"
|
||||
variant="tool"
|
||||
p={1}
|
||||
m={1}
|
||||
bg="transparent"
|
||||
sx={{ ":hover": { bg: "hover" } }}
|
||||
onClick={async () => {
|
||||
await db.fs.downloadFile(
|
||||
attachment.metadata.hash,
|
||||
attachment.metadata.hash
|
||||
);
|
||||
const data = await db.fs.readEncrypted(
|
||||
attachment.metadata.hash,
|
||||
await db.user.getEncryptionKey(),
|
||||
{
|
||||
iv: attachment.iv,
|
||||
salt: attachment.salt,
|
||||
length: attachment.length,
|
||||
alg: attachment.alg,
|
||||
outputType: "uint8array",
|
||||
}
|
||||
);
|
||||
// download(
|
||||
// attachment.metadata.filename,
|
||||
// data,
|
||||
// attachment.metadata.type
|
||||
// );
|
||||
FileSaver.saveAs(
|
||||
new Blob([data], {
|
||||
type: attachment.metadata.type,
|
||||
}),
|
||||
attachment.metadata.filename
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Icon.Download size={16} />
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Card>
|
||||
)}
|
||||
</Animated.Flex>
|
||||
</>
|
||||
);
|
||||
}
|
||||
export default React.memo(Properties);
|
||||
|
||||
function Card({ title, children }) {
|
||||
return (
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
//mx={1}
|
||||
//mt={2}
|
||||
sx={{
|
||||
//border: "1px solid var(--border)",
|
||||
borderRadius: "default",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
variant="subtitle"
|
||||
fontSize="subtitle"
|
||||
mx={2}
|
||||
my={2}
|
||||
color="fontTertiary"
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
function formatBytes(bytes, decimals = 2) {
|
||||
if (bytes === 0) return "0B";
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ["B", "K", "M", "G", "T", "P", "E", "Z", "Y"];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i];
|
||||
}
|
||||
|
||||
function formatFilename(filename) {
|
||||
const MAX_LENGTH = 28;
|
||||
if (filename.length > MAX_LENGTH) {
|
||||
return (
|
||||
filename.substr(0, MAX_LENGTH / 2) +
|
||||
"..." +
|
||||
filename.substr(-(MAX_LENGTH / 3))
|
||||
);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
34
apps/web/src/components/properties/toggle.css
Normal file
34
apps/web/src/components/properties/toggle.css
Normal file
@@ -0,0 +1,34 @@
|
||||
.react-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.react-toggle-thumb {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.react-toggle-track {
|
||||
width: 30px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.react-toggle-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 0px;
|
||||
left: 1px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.react-toggle--checked .react-toggle-thumb {
|
||||
left: 18px;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.react-toggle:active:not(.react-toggle--disabled) .react-toggle-thumb {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.react-toggle--focus .react-toggle-thumb {
|
||||
box-shadow: none;
|
||||
}
|
||||
@@ -1,24 +1,37 @@
|
||||
import React from "react";
|
||||
import { Flex, Text } from "rebass";
|
||||
import { useStore } from "../../stores/editor-store";
|
||||
import ReactToggle from "react-toggle";
|
||||
import "react-toggle/style.css";
|
||||
import { Label } from "@rebass/forms";
|
||||
import "./toggle.css";
|
||||
|
||||
function Toggle(props) {
|
||||
const { icons, label, onToggle, toggleKey } = props;
|
||||
const { icon: ToggleIcon, label, onToggle, toggleKey } = props;
|
||||
const isOn = useStore((store) => store.session[toggleKey]);
|
||||
return (
|
||||
<Flex
|
||||
variant="columnCenter"
|
||||
width="33%"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
py={2}
|
||||
mr={1}
|
||||
sx={{ borderRadius: "default", cursor: "pointer" }}
|
||||
px={2}
|
||||
sx={{
|
||||
borderBottom: "1px solid var(--border)",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => onToggle(!isOn)}
|
||||
data-test-id={props.testId}
|
||||
>
|
||||
{isOn ? <icons.on color="primary" /> : <icons.off />}
|
||||
<Text mt={1} variant="body" color={isOn ? "primary" : "text"}>
|
||||
<Text
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
variant="body"
|
||||
color={isOn ? "primary" : "text"}
|
||||
>
|
||||
<ToggleIcon size={13} sx={{ flexShrink: 0, mr: 1 }} />
|
||||
{label}
|
||||
</Text>
|
||||
<ReactToggle size={20} defaultChecked={isOn} icons={false} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ const getDefaultSession = () => {
|
||||
color: undefined,
|
||||
dateEdited: 0,
|
||||
totalWords: 0,
|
||||
attachments: [],
|
||||
content: {
|
||||
type: "tiny",
|
||||
data: "",
|
||||
@@ -102,6 +103,7 @@ class EditorStore extends BaseStore {
|
||||
content: content || defaultSession.content,
|
||||
totalWords: state.session.totalWords,
|
||||
state: SESSION_STATES.new,
|
||||
attachments: db.attachments.get(note.id) || [],
|
||||
};
|
||||
});
|
||||
appStore.setIsEditorOpen(true);
|
||||
@@ -146,6 +148,7 @@ class EditorStore extends BaseStore {
|
||||
state.session.title = note.title;
|
||||
state.session.isSaving = false;
|
||||
state.session.notebooks = note.notebooks;
|
||||
state.session.attachments = db.attachments.get(note.id) || [];
|
||||
});
|
||||
|
||||
noteStore.refresh();
|
||||
|
||||
Reference in New Issue
Block a user