Skip to content

Commit

Permalink
Implement Overview
Browse files Browse the repository at this point in the history
Overview is a page showing
all notes with their content,
making it easy to find content.

See bottom-left for new a icon
to open Overview in a new tab.
  • Loading branch information
penge committed Sep 8, 2022
1 parent 4e63d63 commit 2837783
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 46 deletions.
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,26 @@

## Context menu

Context menu allows you to quickly save selected text from any website to My Notes, or to transfer selected text to My Notes on other computers.
Context menu can be displayed on right-click on any website and based on the context used to quickly save:

To use Context menu, select the text on website, right-click and see "My Notes" Context menu.
<ol type="a">
<li>selected text</li>
<li>current page URL (right-click on an empty space)</li>
<li>image</li>
</ol>

Destination can be any local note, or My Notes on other computers.

Options are based on the context but in general are:

Context menu has these options:
- `Save to [note name]` – Option for every note. My Notes doesn't have to be open. Google Drive Sync is not required.
- `Save to remotely open My Notes` – My Notes on other computers needs to be open. The same Google Account needs to be used. Google Drive Sync is not required. The destination note will be named `@received`.

- `Save to [note name]` – Option for every note. As you create new notes, they are automatically added to the list. My Notes doesn't have to be open. Google Drive Sync is not required.
- `Save to remotely open My Notes` – My Notes on other computers needs to be open. The same Google Account needs to be used. Google Drive Sync is not required. The destination note to save the text will be named **"@received"** (created automatically if it doesn't exist, otherwise updated).
There is a few general purpose notes that can be used as destination. Their name starts with `@` and they are created automatically when needed:

Context menu also allows you to save current page URL (no text selected) to **"@clipboard"** (created automatically if it doesn't exist, otherwise updated).
- `@received`
- `@clipboard`
- `@images`

<br><br>

Expand All @@ -87,17 +97,11 @@ Click on the **"Save"** button to save the custom theme.

## Command palette

Command palette is a window which you can open with `Cmd + P` (or `Ctrl + P`) and use your keyboard to quickly perform any of the following actions:

<ol type="A">
<li>Find note(s) <b>by their name,</b> and open one. (default behavior)</li>
<li>Find note(s) <b>by their content,</b> and open one. (type <code>?</code> first, then continue)</li>
<li>Find <b>commands,</b> and execute one. (type <code>></code> first, then continue)</li>
</ol>
Command palette is a window which you can open with `Cmd + P` (or `Ctrl + P`) and use your keyboard to quickly find <b>commands,</b> and execute one.

To navigate between the results, use `Up` and `Down` arrow keys.
To navigate between the commands, use `Up` and `Down` arrow keys.

To open a selected note or execute a selected command, press `Enter`.
To execute a selected command, press `Enter`.

The last executed command can be repeated with `Cmd + Shift + P` (or `Ctrl + Shift + P`).

Expand Down
33 changes: 18 additions & 15 deletions src/notes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ import {
} from "notes/content/save";
import sendMessage from "shared/messages/send";

import { getActiveFromUrl, getFocusOverride } from "notes/location";
import { getActiveFromUrl, getFocusOverride, isOverview } from "notes/location";
import Overview from "notes/overview/Overview";
import getFirstAvailableNoteName from "notes/filters/get-first-available-note-name";
import notesHistory from "notes/history";
import keyboardShortcuts, { KeyboardShortcut } from "notes/keyboard-shortcuts";
import { useKeyboardShortcut } from "notes/hooks/use-keyboard-shortcut";
import { Command, toggleSidebar, toggleToolbar } from "notes/commands";
import {
Command, toggleSidebar, toggleToolbar, toggleFocusMode,
} from "notes/commands";
import { exportNote } from "notes/export";
import { notesToSidebarNotes } from "notes/adapters";

Expand All @@ -64,6 +67,8 @@ const Notes = (): h.JSX.Element => {
const [tabId, setTabId] = useState<number | undefined>(undefined);
const [initialized, setInitialized] = useState<boolean>(false);

const [view] = useState<"default" | "overview">(isOverview() ? "overview" : "default");

// Notifications
const [notification, setNotification] = useState<Notification | undefined>(undefined);

Expand Down Expand Up @@ -378,8 +383,8 @@ const Notes = (): h.JSX.Element => {

// Sidebar
useEffect(() => {
document.body.classList.toggle("with-sidebar", sidebar);
}, [sidebar]);
document.body.classList.toggle("with-sidebar", view === "default" && sidebar);
}, [sidebar, view]);

// Sidebar width
useEffect(() => {
Expand Down Expand Up @@ -429,8 +434,8 @@ const Notes = (): h.JSX.Element => {
raw: note.raw || false,
});

document.title = note ? notesProps.active : "My Notes";
}, [notesProps.active]);
document.title = (view === "default" && note) ? notesProps.active : "My Notes";
}, [notesProps.active, view]);

// Toolbar
useEffect(() => {
Expand All @@ -455,18 +460,10 @@ const Notes = (): h.JSX.Element => {
});
});
keyboardShortcuts.subscribe(KeyboardShortcut.OnOpenOptions, chrome.runtime.openOptionsPage);
keyboardShortcuts.subscribe(KeyboardShortcut.OnToggleFocusMode, () => {
if (getFocusOverride()) {
return;
}
chrome.storage.local.get(["focus"], (local) => {
chrome.storage.local.set({ focus: !local.focus });
});
});

keyboardShortcuts.subscribe(KeyboardShortcut.OnToggleSidebar, toggleSidebar);

keyboardShortcuts.subscribe(KeyboardShortcut.OnToggleToolbar, toggleToolbar);
keyboardShortcuts.subscribe(KeyboardShortcut.OnToggleFocusMode, toggleFocusMode);

keyboardShortcuts.subscribe(KeyboardShortcut.OnSync, () => sendMessage(MessageType.SYNC));
}, [os]);
Expand Down Expand Up @@ -572,6 +569,12 @@ const Notes = (): h.JSX.Element => {
}, 6000); // and then Auto Sync every 6 seconds
}, [initialized, autoSync]);

if (view === "overview" && notesOrder && order) {
return (
<Overview notes={notesToSidebarNotes(notesProps.notes, notesOrder, order)} />
);
}

return (
<Fragment>
{notification && (
Expand Down
23 changes: 18 additions & 5 deletions src/notes/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dateUtils from "shared/date/date-utils";
import { getFocusOverride } from "notes/location";
import { getFocusOverride, isOverview } from "notes/location";
import table from "./table";
import highlight from "./highlight";

Expand Down Expand Up @@ -94,32 +94,44 @@ const commands: { [key in AvailableCommand]: Command } = {
RemoveFormat,
};

const canToggle = () => !getFocusOverride() && !isOverview();

const toggleSidebar: Command = () => {
if (getFocusOverride()) {
if (!canToggle()) {
return;
}

chrome.storage.local.get(["focus"], (local) => {
if (!local.focus) { // toggle only if not in focus mode
if (!local.focus) { // toggle only if NOT in focus mode
const hasSidebar = document.body.classList.toggle("with-sidebar");
chrome.storage.local.set({ sidebar: hasSidebar });
}
});
};

const toggleToolbar: Command = () => {
if (getFocusOverride()) {
if (!canToggle()) {
return;
}

chrome.storage.local.get(["focus"], (local) => {
if (!local.focus) { // toggle only if not in focus mode
if (!local.focus) { // toggle only if NOT in focus mode
const hasToolbar = document.body.classList.toggle("with-toolbar");
chrome.storage.local.set({ toolbar: hasToolbar });
}
});
};

const toggleFocusMode: Command = () => {
if (!canToggle()) {
return;
}

chrome.storage.local.get(["focus"], (local) => {
chrome.storage.local.set({ focus: !local.focus });
});
};

export {
commands,

Expand All @@ -133,4 +145,5 @@ export {

toggleSidebar,
toggleToolbar,
toggleFocusMode,
};
8 changes: 8 additions & 0 deletions src/notes/components/SidebarButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import SVG from "notes/components/SVG";
import FileSvgText from "svg/file.svg";
import GearSvgText from "svg/gear.svg";
import RefreshSvgText from "svg/refresh.svg";
import GridSvgText from "svg/grid.svg";
import { importNoteFromTextFile } from "notes/import";
import sendMessage from "shared/messages/send";
import formatDate from "shared/date/format-date";
Expand All @@ -23,6 +24,7 @@ const SidebarButtons = ({
}: SidebarButtonsProps): h.JSX.Element => {
const [dragOver, setDragOver] = useState<boolean>(false);
const openOptions = useCallback(() => chrome.runtime.openOptionsPage(), []);
const openOverview = useCallback(() => window.open("notes.html?overview", "_blank"), []);

return (
<div
Expand Down Expand Up @@ -80,6 +82,12 @@ const SidebarButtons = ({
<SVG text={RefreshSvgText} />
</div>
</Tooltip>

<Tooltip tooltip="Overview">
<div id="open-overview" className="button" onClick={openOverview}>
<SVG text={GridSvgText} />
</div>
</Tooltip>
</div>
);
};
Expand Down
19 changes: 12 additions & 7 deletions src/notes/history.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { isOverview } from "./location";

type NoteNameFunc = (noteName: string) => void;

// Use replace when a note is renamed or deleted
const replace = (noteName: string): void =>
const replace: NoteNameFunc = (noteName: string): void =>
window.history.replaceState({ noteName }, noteName, `?note=${noteName}`);

// Use push when a note is created
const push = (noteName: string): void =>
const push: NoteNameFunc = (noteName: string): void =>
window.history.pushState({ noteName }, noteName, `?note=${noteName}`);

let attached = false;
const attach = (onPop: (noteName: string) => void): void => {
const attach = (onPop: NoteNameFunc): void => {
if (attached) {
return;
}
Expand All @@ -22,9 +26,10 @@ const attach = (onPop: (noteName: string) => void): void => {
attached = true;
};

export default {
replace,
push,
const canProxy = () => !isOverview();

attach,
export default {
replace: (noteName: string) => canProxy() && replace(noteName),
push: (noteName: string) => canProxy() && push(noteName),
attach: (onPop: NoteNameFunc) => canProxy() && attach(onPop),
};
7 changes: 5 additions & 2 deletions src/notes/location.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export const getFocusOverride = (): boolean => new URL(window.location.href).searchParams.get("focus") === "";
export const getActiveFromUrl = (): string => new URL(window.location.href).searchParams.get("note") || ""; // Bookmark
const getParam = (name: string) => new URL(window.location.href).searchParams.get(name);

export const getFocusOverride = (): boolean => getParam("focus") === "";
export const getActiveFromUrl = (): string => getParam("note") || "";
export const isOverview = (): boolean => getParam("overview") === "";
25 changes: 25 additions & 0 deletions src/notes/overview/Overview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { h } from "preact";
import { SidebarNote } from "notes/adapters";

interface OverviewProps {
notes: SidebarNote[]
}

const Overview = ({ notes }: OverviewProps): h.JSX.Element => (
<div id="notes-overview">
{notes.map((note) => (
<div className="note-tile">
<div className="note-tile-title">
<a href={`notes.html?note=${note.name}`}>{note.name}</a>
</div>
<div
className="note-tile-content"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: note.content }}
/>
</div>
))}
</div>
);

export default Overview;
6 changes: 6 additions & 0 deletions src/svg/grid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 40 additions & 2 deletions static/notes.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,44 @@ hr {
border-bottom: 1px solid var(--notification-border-color);
}

/* Overview */

#notes-overview {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
column-gap: 1em;
row-gap: 1em;
padding: 1em;
overflow-y: auto;
}

.note-tile {
display: inline-block;
height: 400px;
border: 1px solid var(--overview-tile-border-color);
border-radius: 3px;
overflow: auto;
}

.note-tile::-webkit-scrollbar-track,
.note-tile::-webkit-scrollbar-thumb {
border-radius: 3px;
}

.note-tile-title {
position: sticky;
left: 0;
top: 0;
background: var(--background-color);
padding: 1em;
font-size: 1.2em;
font-weight: bold;
}

.note-tile-content {
padding: 1em;
}

/* Bar (for #sidebar-buttons and #toolbar) */

#toolbar, #sidebar-buttons {
Expand Down Expand Up @@ -164,8 +202,8 @@ body:not(.with-sidebar) { left: 0 !important; }
align-items: center;
cursor: pointer;
font-weight: bold;
padding: .5em 1em;
margin-top: 3px;
padding: .5em;
margin-bottom: 3px;
border-radius: 3px;
}

Expand Down
4 changes: 4 additions & 0 deletions static/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
--command-palette-active-item-text-color: white;


/* Overview */
--overview-tile-border-color: #454545;


/* Only in Options */

--keyboard-shortcut-background-color: #222;
Expand Down
4 changes: 4 additions & 0 deletions static/themes/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
--command-palette-active-item-text-color: black;


/* Overview */
--overview-tile-border-color: #dfe1e5;


/* Only in Options */

--keyboard-shortcut-background-color: #e1e1e1;
Expand Down

0 comments on commit 2837783

Please sign in to comment.