mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-30 18:48:27 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07db14f6bf |
@@ -1128,8 +1128,9 @@ export const useActions = ({
|
||||
id: "add-reminder",
|
||||
title: strings.remindMe(),
|
||||
icon: "clock-plus-outline",
|
||||
onPress: () => {
|
||||
onPress: async () => {
|
||||
close();
|
||||
await sleep(100);
|
||||
AddReminder.present(undefined, item);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -95,7 +95,17 @@ const ReminderNotificationModes = {
|
||||
|
||||
export default function AddReminder(props: NavigationProps<"AddReminder">) {
|
||||
const { reminder, reference } = props.route.params;
|
||||
useNavigationFocus(props.navigation, { focusOnInit: true });
|
||||
useNavigationFocus(props.navigation, {
|
||||
focusOnInit: true,
|
||||
onFocus: () => {
|
||||
if (!props.route.params?.reminder) {
|
||||
setTimeout(() => {
|
||||
titleRef.current?.focus();
|
||||
}, 200);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const { colors, isDark } = useThemeColors();
|
||||
const weekFormat = useSettingStore((state) => state.weekFormat);
|
||||
const [reminderMode, setReminderMode] = useState<Reminder["mode"]>(
|
||||
@@ -282,7 +292,6 @@ export default function AddReminder(props: NavigationProps<"AddReminder">) {
|
||||
defaultValue={reminder?.title || referencedItem?.title}
|
||||
placeholder={strings.remindeMeOf()}
|
||||
onChangeText={(text) => (title.current = text)}
|
||||
autoFocus
|
||||
wrapperStyle={{
|
||||
marginTop: DefaultAppStyles.GAP_VERTICAL
|
||||
}}
|
||||
|
||||
@@ -286,8 +286,7 @@ class EditorStore extends BaseStore<EditorStore> {
|
||||
const clearIds: string[] = [];
|
||||
for (const session of sessions) {
|
||||
if (session.type === "new") continue;
|
||||
if (session.note.id !== item.id && session.note.contentId !== item.id)
|
||||
continue;
|
||||
if (session.note.id !== item.id && session.note.contentId !== item.id) continue;
|
||||
if (isDeleted(item) || isTrashItem(item))
|
||||
clearIds.push(session.tabId);
|
||||
// if a note becomes conflicted, reopen the session
|
||||
@@ -332,13 +331,6 @@ class EditorStore extends BaseStore<EditorStore> {
|
||||
!item.readonly
|
||||
)
|
||||
openSession(session.note.id, { force: true, silent: true });
|
||||
// if a note is made readonly, reopen the session
|
||||
else if (
|
||||
session.type !== "readonly" &&
|
||||
item.type === "note" &&
|
||||
item.readonly
|
||||
)
|
||||
openSession(session.note.id, { force: true, silent: true });
|
||||
// update the note in all sessions
|
||||
else if (item.type === "note") {
|
||||
updateSession(
|
||||
|
||||
@@ -404,9 +404,7 @@ class UserManager {
|
||||
const masterKey = await this.getMasterKey();
|
||||
if (!masterKey) return;
|
||||
|
||||
const dataEncryptionKey = await this.keyManager.get("dataEncryptionKey", {
|
||||
refetchUser: false
|
||||
});
|
||||
const dataEncryptionKey = await this.keyManager.get("dataEncryptionKey");
|
||||
if (!dataEncryptionKey)
|
||||
return [
|
||||
{
|
||||
@@ -417,10 +415,7 @@ class UserManager {
|
||||
const keys: { version: KeyVersion; key: SerializedKey }[] = [];
|
||||
|
||||
const legacyDataEncryptionKey = await this.keyManager.get(
|
||||
"legacyDataEncryptionKey",
|
||||
{
|
||||
refetchUser: false
|
||||
}
|
||||
"legacyDataEncryptionKey"
|
||||
);
|
||||
if (legacyDataEncryptionKey)
|
||||
keys.push({
|
||||
|
||||
@@ -113,19 +113,13 @@ function Tags(props: { settings: Settings; loading?: boolean }) {
|
||||
backgroundColor:
|
||||
index !== 0 ? "transparent" : "var(--nn_secondary_background)",
|
||||
borderRadius: 6,
|
||||
padding: "2px 4px",
|
||||
height: "25px",
|
||||
padding: "0px 4px",
|
||||
height: "24px",
|
||||
fontFamily: "Inter",
|
||||
fontSize: 12,
|
||||
color: "var(--nn_primary_icon)",
|
||||
userSelect: "none",
|
||||
WebkitUserSelect: "none",
|
||||
textAlign: "left",
|
||||
maxWidth: 150,
|
||||
textOverflow: "ellipsis",
|
||||
overflow: "hidden",
|
||||
wordWrap: "break-word",
|
||||
whiteSpace: "nowrap"
|
||||
WebkitUserSelect: "none"
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Extension } from "@tiptap/core";
|
||||
import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
|
||||
import { Decoration, DecorationSet } from "prosemirror-view";
|
||||
import {
|
||||
EditorState,
|
||||
Plugin,
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
} from "prosemirror-state";
|
||||
import { SearchSettings } from "../../toolbar/stores/search-store.js";
|
||||
import { tiptapKeys } from "@notesnook/common";
|
||||
import { toggleNodesUnderPos } from "../heading/index.js";
|
||||
|
||||
type DispatchFn = (tr: Transaction) => void;
|
||||
declare module "@tiptap/core" {
|
||||
@@ -296,11 +295,12 @@ export const SearchReplace = Extension.create<SearchOptions, SearchStorage>({
|
||||
)
|
||||
);
|
||||
|
||||
const domNode = this.editor.view.domAtPos(from).node;
|
||||
scrollIntoView(domNode);
|
||||
|
||||
this.storage.selectedIndex = nextIndex;
|
||||
tr.setMeta("isSearching", true);
|
||||
tr.setMeta("selectedIndex", nextIndex);
|
||||
if (dispatch) updateView(state, dispatch);
|
||||
|
||||
return true;
|
||||
},
|
||||
moveToPreviousResult:
|
||||
@@ -322,8 +322,10 @@ export const SearchReplace = Extension.create<SearchOptions, SearchStorage>({
|
||||
)
|
||||
);
|
||||
|
||||
const domNode = this.editor.view.domAtPos(from).node;
|
||||
scrollIntoView(domNode);
|
||||
|
||||
this.storage.selectedIndex = prevIndex;
|
||||
tr.setMeta("isSearching", true);
|
||||
tr.setMeta("selectedIndex", prevIndex);
|
||||
if (dispatch) updateView(state, dispatch);
|
||||
|
||||
@@ -468,90 +470,14 @@ export const SearchReplace = Extension.create<SearchOptions, SearchStorage>({
|
||||
decorations(state) {
|
||||
return key.getState(state).results;
|
||||
}
|
||||
},
|
||||
appendTransaction: (transactions, oldState, newState) => {
|
||||
const isSearchTransaction = transactions.find((t) =>
|
||||
t.getMeta("isSearching")
|
||||
);
|
||||
const selectedResult =
|
||||
this.storage.results?.[this.storage.selectedIndex];
|
||||
if (!isSearchTransaction || !selectedResult) return;
|
||||
|
||||
const tr = newState.tr;
|
||||
|
||||
scrollIntoView(this.editor.view, selectedResult.from);
|
||||
if (expandCollapsedParents(tr, selectedResult.from)) {
|
||||
return tr;
|
||||
}
|
||||
}
|
||||
})
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
function expandCollapsedParents(tr: Transaction, pos: number) {
|
||||
try {
|
||||
let changed = false;
|
||||
|
||||
const $pos = tr.doc.resolve(pos);
|
||||
|
||||
for (let depth = 1; depth <= $pos.depth; depth++) {
|
||||
const node = $pos.node(depth);
|
||||
const nodePos = $pos.before(depth);
|
||||
|
||||
if (
|
||||
(node.type.name === "callout" ||
|
||||
node.type.name === "outlineListItem") &&
|
||||
node.attrs.collapsed
|
||||
) {
|
||||
tr.setNodeAttribute(nodePos, "collapsed", false);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// expand collapsed heading that hid this node via hidden attribute
|
||||
if (node.attrs.hidden) {
|
||||
const parentNode = $pos.node(depth - 1);
|
||||
const parentContentStart = depth === 1 ? 0 : $pos.before(depth - 1) + 1;
|
||||
|
||||
let collapsedHeadingPos = -1;
|
||||
let collapsedHeadingLevel = -1;
|
||||
|
||||
parentNode.forEach((child, offset) => {
|
||||
const childAbsPos = parentContentStart + offset;
|
||||
if (childAbsPos >= nodePos) return;
|
||||
if (
|
||||
child.type.name === "heading" &&
|
||||
child.attrs.collapsed &&
|
||||
!child.attrs.hidden
|
||||
) {
|
||||
collapsedHeadingPos = childAbsPos;
|
||||
collapsedHeadingLevel = child.attrs.level;
|
||||
}
|
||||
});
|
||||
|
||||
if (collapsedHeadingPos !== -1) {
|
||||
tr.setNodeAttribute(collapsedHeadingPos, "collapsed", false);
|
||||
toggleNodesUnderPos(
|
||||
tr,
|
||||
collapsedHeadingPos,
|
||||
collapsedHeadingLevel,
|
||||
false
|
||||
);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) tr.setMeta("preventSave", true);
|
||||
return changed;
|
||||
} catch (e) {
|
||||
console.error("Error expanding collapsed parents: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
function scrollIntoView(view: EditorView, pos: number) {
|
||||
function scrollIntoView(domNode: Node) {
|
||||
setTimeout(() => {
|
||||
const domNode = view.domAtPos(pos).node;
|
||||
if ("scrollIntoView" in domNode) {
|
||||
(domNode as Element).scrollIntoView({
|
||||
behavior: "instant",
|
||||
|
||||
@@ -25,7 +25,6 @@ import { ToolButton } from "../components/tool-button.js";
|
||||
import { Editor } from "../../types.js";
|
||||
import { useEditorSearchStore } from "../stores/search-store.js";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { inlineDebounce } from "@notesnook/common";
|
||||
|
||||
export type SearchReplacePopupProps = { editor: Editor };
|
||||
export function SearchReplacePopup(props: SearchReplacePopupProps) {
|
||||
@@ -95,7 +94,7 @@ export function SearchReplacePopup(props: SearchReplacePopupProps) {
|
||||
sx={{ p: 0, fontFamily: "monospace" }}
|
||||
value={searchTerm}
|
||||
onChange={(e) => {
|
||||
inlineDebounce("search", () => search(e.target.value), 100);
|
||||
search(e.target.value);
|
||||
useEditorSearchStore.setState({ searchTerm: e.target.value });
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user