Skip to content

Commit

Permalink
Merge pull request #377 from penge/fix
Browse files Browse the repository at this point in the history
Fix missing scrollbar in Sidebar, Sort Command palette notes same as in Sidebar
  • Loading branch information
penge authored May 24, 2022
2 parents c29be8a + 5adf761 commit a8e6078
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 50 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "My Notes",
"description": "Simple and fast note-taking.",
"version": "3.21",
"version": "3.21.1",
"homepage_url": "https://github.com/penge/my-notes",
"icons": {
"128": "images/icon128.png"
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "my-notes",
"version": "3.21.0",
"version": "3.21.1",
"description": "Simple and fast note-taking.",
"author": "Pavel Bucka",
"license": "MIT",
Expand Down
8 changes: 6 additions & 2 deletions src/notes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,10 @@ const Notes = (): h.JSX.Element => {
// Command Palette
const [setOnToggleCommandPaletteHandler] = useKeyboardShortcut(KeyboardShortcut.OnToggleCommandPalette);
useEffect(() => {
if (!notesOrder) {
return;
}

// Detach when there are no notes
if (!Object.keys(notesProps.notes).length) {
setOnToggleCommandPaletteHandler(undefined);
Expand All @@ -518,7 +522,7 @@ const Notes = (): h.JSX.Element => {

// Props for Command Palette
const props: CommandPaletteProps = {
notes: notesProps.notes,
notes: notesToSidebarNotes(notesProps.notes, notesOrder, order),
commands,
onActivateNote: (noteName: string) => {
setCommandPaletteProps(null);
Expand Down Expand Up @@ -551,7 +555,7 @@ const Notes = (): h.JSX.Element => {

// Update props for already visible Command Palette
setCommandPaletteProps((prev) => !prev ? prev : props);
}, [os, notesProps, handleOnActivateNote, commandPaletteCommands]);
}, [os, notesProps, notesOrder, order, handleOnActivateNote, commandPaletteCommands]);

// Automatically show modal to create a new note if there are 0 notes
useEffect(() => {
Expand Down
119 changes: 94 additions & 25 deletions src/notes/adapters/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,98 @@
import { NotesObject, NotesOrder } from "shared/storage/schema";
import { notesToSidebarNotes } from "../";

test("notesToSidebarNotes() returns notes suitable for the Sidebar", () => {
const notes: NotesObject = {
Todo: {
content: "my todo",
createdTime: "CT-TODO",
modifiedTime: "MT-TODO",
},
Article: {
content: "my article",
createdTime: "CT-ARTICLE",
modifiedTime: "MT-ARTICLE",
},
Shopping: {
content: "my shopping",
createdTime: "CT-SHOPPING",
modifiedTime: "MT-SHOPPING",
},
};

const sidebarNotes = notesToSidebarNotes(notes, NotesOrder.Alphabetical);
expect(sidebarNotes).toEqual([
{ name: "Article", ...notes.Article },
{ name: "Shopping", ...notes.Shopping },
{ name: "Todo", ...notes.Todo },
]);
describe("notesToSidebarNotes()", () => {
describe("unpinned notes only", () => {
it("returns notes in correct order", () => {
const notes: NotesObject = {
Todo: {
content: "my todo",
createdTime: "CT-TODO",
modifiedTime: "MT-TODO",
},
Article: {
content: "my article",
createdTime: "CT-ARTICLE",
modifiedTime: "MT-ARTICLE",
},
Shopping: {
content: "my shopping",
createdTime: "CT-SHOPPING",
modifiedTime: "MT-SHOPPING",
},
};

const sidebarNotes = notesToSidebarNotes(notes, NotesOrder.Alphabetical);
expect(sidebarNotes).toEqual([
{ name: "Article", ...notes.Article },
{ name: "Shopping", ...notes.Shopping },
{ name: "Todo", ...notes.Todo },
]);
});
});

describe("pinned and unpinned notes", () => {
it("returns notes in correct order", () => {
const notes: NotesObject = {
Todo: {
content: "my todo",
createdTime: "CT-TODO",
modifiedTime: "MT-3",
},
Shopping: {
content: "my shopping",
createdTime: "CT-SHOPPING",
modifiedTime: "MT-9",
pinnedTime: "PT-SHOPPING",
},
Article: {
content: "my article",
createdTime: "CT-ARTICLE",
modifiedTime: "MT-2",
},
Clipboard: {
content: "my clipboard",
createdTime: "CT-CLIPBOARD",
modifiedTime: "MT-8",
pinnedTime: "PT-CLIPBOARD",
},
};

const sidebarNotes = notesToSidebarNotes(notes, NotesOrder.Alphabetical);
expect(sidebarNotes).toEqual([
{ name: "Clipboard", ...notes.Clipboard },
{ name: "Shopping", ...notes.Shopping },

{ name: "Article", ...notes.Article },
{ name: "Todo", ...notes.Todo },
]);

const sidebarNotes2 = notesToSidebarNotes(notes, NotesOrder.NewestFirst);
expect(sidebarNotes2).toEqual([
{ name: "Shopping", ...notes.Shopping },
{ name: "Clipboard", ...notes.Clipboard },

{ name: "Todo", ...notes.Todo },
{ name: "Article", ...notes.Article },
]);

const sidebarNotes3 = notesToSidebarNotes(notes, NotesOrder.Custom, ["Shopping", "Article"]);
expect(sidebarNotes3).toEqual([
{ name: "Clipboard", ...notes.Clipboard },
{ name: "Shopping", ...notes.Shopping },

{ name: "Todo", ...notes.Todo },
{ name: "Article", ...notes.Article },
]);

const sidebarNotes4 = notesToSidebarNotes(notes, NotesOrder.Custom, []);
expect(sidebarNotes4).toEqual([
{ name: "Shopping", ...notes.Shopping },
{ name: "Clipboard", ...notes.Clipboard },

{ name: "Todo", ...notes.Todo },
{ name: "Article", ...notes.Article },
]);
});
});
});
24 changes: 16 additions & 8 deletions src/notes/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { h } from "preact";
import { useRef, useState, useMemo, useCallback, useEffect } from "preact/hooks";
import { useBodyClass } from "notes/hooks/use-body-class";
import { NotesObject } from "shared/storage/schema";
import clsx from "clsx";
import { useBodyClass } from "notes/hooks/use-body-class";
import { SidebarNote } from "notes/adapters";
import { t, tString } from "i18n";

export interface CommandPaletteProps {
notes: NotesObject
notes: SidebarNote[]
commands: { name: string, translation: h.JSX.Element }[]
onActivateNote: (noteName: string) => void
onExecuteCommand: (commandName: string) => void
Expand Down Expand Up @@ -56,26 +56,34 @@ export const prepareFilter = (rawInput: string): Filter => {
};
};

export const prepareItems = (notes: NotesObject, commands: string[], filter: Filter | undefined): string[] => {
export const prepareItems = (notes: SidebarNote[], commands: string[], filter: Filter | undefined): string[] => {
const noteNames = notes.map((note) => note.name);

if (!filter) {
return Object.keys(notes); // by default, list notes
return noteNames;
}

const input = filter.input.trim();
const prepareFilterPredicate = (input: string) => (item: string) => input ? item.toLowerCase().includes(input) : item;

// A) CommandsByName
if (filter.type === FilterType.CommandsByName) {
return commands.filter(prepareFilterPredicate(input)); // commands that include the input in their name
return commands.filter(prepareFilterPredicate(input));
}

// B) NotesByContent
if (filter.type === FilterType.NotesByContent) {
return input ? Object.keys(notes).filter((noteName) => prepareFilterPredicate(input)(notes[noteName].content)) : Object.keys(notes); // notes that include the input in their content
const filter = prepareFilterPredicate(input);
return input
? noteNames.filter((noteName) => {
const foundNote = notes.find((note) => note.name === noteName);
return foundNote && filter(foundNote.content);
})
: noteNames;
}

// C) NotesByName
return Object.keys(notes).filter(prepareFilterPredicate(input)); // notes that include the input in their name
return noteNames.filter(prepareFilterPredicate(input));
};

const CommandPalette = ({ notes, commands, onActivateNote, onExecuteCommand }: CommandPaletteProps): h.JSX.Element => {
Expand Down
15 changes: 9 additions & 6 deletions src/notes/components/__tests__/CommandPalette.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NotesObject } from "shared/storage/schema";
import { SidebarNote } from "notes/adapters";
import { Filter, FilterType, prepareFilter, prepareItems } from "../CommandPalette";

describe("prepareFilter", () => {
Expand Down Expand Up @@ -38,23 +38,26 @@ describe("prepareItems", () => {
const createdTime = "CT"; // not relevant for the test
const modifiedTime = "MT"; // not relevant for the test

const notes: NotesObject = {
Clipboard: {
const notes: SidebarNote[] = [
{
name: "Clipboard",
content: "",
createdTime,
modifiedTime,
},
Article: {
{
name: "Article",
content: "This is an interesting article",
createdTime,
modifiedTime,
},
TODO: {
{
name: "TODO",
content: "buy milk, buy coffee",
createdTime,
modifiedTime,
},
};
];

const commands = [
"Insert current Date",
Expand Down
26 changes: 22 additions & 4 deletions src/notes/sort/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,35 @@ import { SidebarNote } from "notes/adapters";
import { NotesOrder } from "shared/storage/schema";

export const sortNotes = (notes: SidebarNote[], notesOrder: NotesOrder, custom?: string[]): SidebarNote[] => {
const pinnedNotes = notes.filter((note) => note.pinnedTime);
const unpinnedNotes = notes.filter((note) => !note.pinnedTime);

if (notesOrder === NotesOrder.Alphabetical) {
return notes.sort((a, b) => a.name.localeCompare(b.name));
const alphabeticalCompare = (a: SidebarNote, b: SidebarNote) => a.name.localeCompare(b.name);
return [
...pinnedNotes.sort(alphabeticalCompare),
...unpinnedNotes.sort(alphabeticalCompare),
];
}

if (notesOrder === NotesOrder.NewestFirst) {
return notes.sort((a, b) => -a.modifiedTime.localeCompare(b.modifiedTime));
const newestFirstCompare = (a: SidebarNote, b: SidebarNote) => -a.modifiedTime.localeCompare(b.modifiedTime);
return [
...pinnedNotes.sort(newestFirstCompare),
...unpinnedNotes.sort(newestFirstCompare),
];
}

if (custom?.length) {
return notes.sort((a, b) => custom.indexOf(a.name) - custom.indexOf(b.name));
const customCompare = (a: SidebarNote, b: SidebarNote) => custom.indexOf(a.name) - custom.indexOf(b.name);
return [
...pinnedNotes.sort(customCompare),
...unpinnedNotes.sort(customCompare),
];
}

return notes;
return [
...pinnedNotes,
...unpinnedNotes,
];
};
2 changes: 1 addition & 1 deletion static/notes.css
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ body:not(.with-sidebar) { left: 0 !important; }
flex-grow: 1;
background: var(--sidebar-notes-background-color);
color: var(--sidebar-notes-text-color);
overflow-y: auto;
}

#sidebar-notes-separator {
Expand All @@ -154,7 +155,6 @@ body:not(.with-sidebar) { left: 0 !important; }

.sidebar-notes {
padding: .5em;
overflow-y: auto;
}

.sidebar-notes .note {
Expand Down

0 comments on commit a8e6078

Please sign in to comment.