mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
feat: finalize more of the new editor
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
"@rebass/forms": "^4.0.6",
|
||||
"@streetwriters/tinymce-plugins": "^1.5.18",
|
||||
"@tinymce/tinymce-react": "^3.13.0",
|
||||
"@tiptap/react": "^2.0.0-beta.108",
|
||||
"@tiptap/react": "^2.0.0-beta.109",
|
||||
"@types/rebass": "^4.0.10",
|
||||
"async-mutex": "^0.3.2",
|
||||
"axios": "^0.21.4",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/security#csp-meta-tag -->
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="script-src 'self' https://checkout.paddle.com https://analytics.streetwriters.co https://cdn.paddle.com https://cdnjs.cloudflare.com 'unsafe-inline' 'unsafe-eval';"
|
||||
content="script-src 'self' https://checkout.paddle.com https://analytics.streetwriters.co https://cdn.paddle.com https://cdnjs.cloudflare.com https://esm.sh 'unsafe-inline' 'unsafe-eval';"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
|
||||
@@ -91,6 +91,7 @@ textarea,
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
outline: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
*::-moz-focus-inner {
|
||||
|
||||
@@ -11,24 +11,24 @@ async function initializeDatabase(persistence) {
|
||||
db = new Database(new NNStorage(persistence), EventSource, FS);
|
||||
|
||||
// if (isTesting()) {
|
||||
// db.host({
|
||||
// API_HOST: "https://api.notesnook.com",
|
||||
// AUTH_HOST: "https://auth.streetwriters.co",
|
||||
// SSE_HOST: "https://events.streetwriters.co",
|
||||
// });
|
||||
db.host({
|
||||
API_HOST: "https://api.notesnook.com",
|
||||
AUTH_HOST: "https://auth.streetwriters.co",
|
||||
SSE_HOST: "https://events.streetwriters.co",
|
||||
});
|
||||
// } else {
|
||||
// db.host({
|
||||
// API_HOST: "http://localhost:5264",
|
||||
// AUTH_HOST: "http://localhost:8264",
|
||||
// SSE_HOST: "http://localhost:7264",
|
||||
// });
|
||||
db.host({
|
||||
API_HOST: "http://192.168.10.29:5264",
|
||||
AUTH_HOST: "http://192.168.10.29:8264",
|
||||
SSE_HOST: "http://192.168.10.29:7264",
|
||||
ISSUES_HOST: "http://192.168.10.29:2624",
|
||||
SUBSCRIPTIONS_HOST: "http://192.168.10.29:9264",
|
||||
});
|
||||
// db.host({
|
||||
// API_HOST: "http://192.168.10.29:5264",
|
||||
// AUTH_HOST: "http://192.168.10.29:8264",
|
||||
// SSE_HOST: "http://192.168.10.29:7264",
|
||||
// ISSUES_HOST: "http://192.168.10.29:2624",
|
||||
// SUBSCRIPTIONS_HOST: "http://192.168.10.29:9264",
|
||||
// });
|
||||
// }
|
||||
|
||||
await db.init();
|
||||
|
||||
@@ -23,7 +23,6 @@ import { FlexScrollContainer } from "../scroll-container";
|
||||
import { formatDate } from "notes-core/utils/date";
|
||||
import { debounce, debounceWithId } from "../../utils/debounce";
|
||||
import { showError } from "../../common/dialog-controller";
|
||||
import "./tiptap.css";
|
||||
import { CharacterCounter, IEditor } from "./tiptap";
|
||||
|
||||
const ReactMCE = React.lazy(() => import("./tinymce"));
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
.ProseMirror p.is-editor-empty:first-child::before {
|
||||
color: var(--placeholder);
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ProseMirror {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.ProseMirror code:not(pre code) {
|
||||
background-color: var(--bgSecondary);
|
||||
}
|
||||
|
||||
.ProseMirror code:not(pre code) {
|
||||
background-color: var(--bgSecondary);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 5px;
|
||||
padding: 3px 5px 0px 5px;
|
||||
font-family: ui-monospace, SFMono-Regular, SF Mono, Consolas, Liberation Mono,
|
||||
Menlo, monospace !important;
|
||||
font-size: 10pt !important;
|
||||
}
|
||||
|
||||
.ProseMirror li p {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.ProseMirror li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.ProseMirror a {
|
||||
color: var(--primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ProseMirror a:hover {
|
||||
filter: brightness(70%);
|
||||
}
|
||||
|
||||
.ProseMirror {
|
||||
position: relative;
|
||||
}
|
||||
.ProseMirror {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
white-space: break-spaces;
|
||||
-webkit-font-variant-ligatures: none;
|
||||
font-variant-ligatures: none;
|
||||
font-feature-settings: "liga" 0; /* the above doesn't seem to work in Edge */
|
||||
}
|
||||
.ProseMirror [contenteditable="false"] {
|
||||
white-space: normal;
|
||||
}
|
||||
.ProseMirror [contenteditable="false"] [contenteditable="true"] {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.ProseMirror pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
img.ProseMirror-separator {
|
||||
display: inline !important;
|
||||
border: none !important;
|
||||
margin: 0 !important;
|
||||
width: 1px !important;
|
||||
height: 1px !important;
|
||||
}
|
||||
.ProseMirror-gapcursor {
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
}
|
||||
.ProseMirror-gapcursor:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
width: 20px;
|
||||
border-top: 1px solid var(--text);
|
||||
animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
|
||||
}
|
||||
@keyframes ProseMirror-cursor-blink {
|
||||
to {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
.ProseMirror-hideselection *::selection {
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
}
|
||||
.ProseMirror-hideselection *::-moz-selection {
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
}
|
||||
.ProseMirror-hideselection * {
|
||||
caret-color: transparent;
|
||||
}
|
||||
.ProseMirror-focused .ProseMirror-gapcursor {
|
||||
display: block;
|
||||
}
|
||||
.tippy-box[data-animation="fade"][data-state="hidden"] {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.ProseMirror table {
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.ProseMirror table td,
|
||||
.ProseMirror table th {
|
||||
border: 1px solid var(--border);
|
||||
box-sizing: border-box;
|
||||
min-width: 1em;
|
||||
padding: 3px 5px;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.ProseMirror table td > *,
|
||||
.ProseMirror table th > * {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ProseMirror table th {
|
||||
background-color: var(--bgSecondary);
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ProseMirror table .selectedCell:after {
|
||||
background: var(--primary);
|
||||
content: "";
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.ProseMirror table .column-resize-handle {
|
||||
background-color: var(--primary);
|
||||
bottom: -2px;
|
||||
position: absolute;
|
||||
right: -2px;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.ProseMirror table p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tableWrapper {
|
||||
padding: 1rem 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.resize-cursor {
|
||||
cursor: ew-resize;
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.drop-cursor {
|
||||
background-color: var(--text) !important;
|
||||
}
|
||||
|
||||
.search-result {
|
||||
background-color: var(--disabled);
|
||||
}
|
||||
@@ -1,7 +1,17 @@
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import { useTheme } from "emotion-theming";
|
||||
import {
|
||||
Toolbar,
|
||||
useTiptap,
|
||||
PortalProvider,
|
||||
PortalProviderAPI,
|
||||
PortalRenderer,
|
||||
} from "notesnook-editor";
|
||||
import { EditorContent, HTMLContent } from "@tiptap/react";
|
||||
import { Toolbar, useTiptap } from "notesnook-editor";
|
||||
import { Box } from "rebass";
|
||||
import { useStore as useThemeStore } from "../../stores/theme-store";
|
||||
import { Flex } from "rebass";
|
||||
import "notesnook-editor/dist/styles.css";
|
||||
import React from "react";
|
||||
import useMobile from "../../utils/use-mobile";
|
||||
|
||||
export type CharacterCounter = {
|
||||
words: () => number;
|
||||
@@ -21,11 +31,11 @@ type TipTapProps = {
|
||||
onFocus?: () => void;
|
||||
};
|
||||
|
||||
function TipTap(props: TipTapProps) {
|
||||
const theme = useThemeStore((store) => store.theme);
|
||||
const accent = useThemeStore((store) => store.accent);
|
||||
function TipTap(props: TipTapProps & { portalProviderAPI: PortalProviderAPI }) {
|
||||
const theme: Theme = useTheme();
|
||||
const isMobile = useMobile();
|
||||
|
||||
const { onInit, onChange, onFocus, onDestroy } = props;
|
||||
const { onInit, onChange, onFocus, onDestroy, portalProviderAPI } = props;
|
||||
let counter: CharacterCounter | undefined;
|
||||
const editor = useTiptap(
|
||||
{
|
||||
@@ -48,25 +58,46 @@ function TipTap(props: TipTapProps) {
|
||||
if (onChange) onChange(editor.getHTML(), counter);
|
||||
},
|
||||
onDestroy,
|
||||
injectCSS: false,
|
||||
theme,
|
||||
accent,
|
||||
scale: 1,
|
||||
portalProviderAPI,
|
||||
onOpenAttachmentPicker: (type) => {
|
||||
console.log(type);
|
||||
return false;
|
||||
},
|
||||
},
|
||||
[theme, accent]
|
||||
[theme, portalProviderAPI]
|
||||
);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Toolbar editor={editor} theme={theme} accent={accent} />
|
||||
<Flex sx={{ flex: 1, flexDirection: "column" }}>
|
||||
<EditorContent
|
||||
style={{ flex: 1, cursor: "text" }}
|
||||
style={{ flex: 1, cursor: "text", color: theme.colors.text }}
|
||||
onClick={() => {
|
||||
editor?.commands.focus();
|
||||
}}
|
||||
editor={editor}
|
||||
/>
|
||||
</Box>
|
||||
<Toolbar
|
||||
editor={editor}
|
||||
theme={theme}
|
||||
location={isMobile ? "bottom" : "top"}
|
||||
isMobile={isMobile || false}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
export default TipTap;
|
||||
|
||||
function TiptapProvider(props: TipTapProps) {
|
||||
console.log("Rerendering tiptap provider");
|
||||
return (
|
||||
<PortalProvider
|
||||
render={(portalProviderAPI) => (
|
||||
<>
|
||||
<TipTap {...props} portalProviderAPI={portalProviderAPI} />
|
||||
<PortalRenderer portalProviderAPI={portalProviderAPI} />
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default React.memo(TiptapProvider);
|
||||
|
||||
@@ -169,6 +169,7 @@ class AppStore extends BaseStore {
|
||||
};
|
||||
|
||||
sync = async (full = true, force = false) => {
|
||||
return;
|
||||
clearTimeout(syncStatusTimeout);
|
||||
this.updateLastSynced();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user