Action button prototype
This commit is contained in:
parent
3037dbe58a
commit
7e221ce5aa
@ -42,14 +42,14 @@ functions:
|
|||||||
path: ./page.ts:linkQueryProvider
|
path: ./page.ts:linkQueryProvider
|
||||||
events:
|
events:
|
||||||
- query:link
|
- query:link
|
||||||
indexItems:
|
# indexItems:
|
||||||
path: "./item.ts:indexItems"
|
# path: "./item.ts:indexItems"
|
||||||
events:
|
# events:
|
||||||
- page:index
|
# - page:index
|
||||||
itemQueryProvider:
|
# itemQueryProvider:
|
||||||
path: ./item.ts:queryProvider
|
# path: ./item.ts:queryProvider
|
||||||
events:
|
# events:
|
||||||
- query:item
|
# - query:item
|
||||||
deletePage:
|
deletePage:
|
||||||
path: "./page.ts:deletePage"
|
path: "./page.ts:deletePage"
|
||||||
command:
|
command:
|
||||||
@ -67,6 +67,9 @@ functions:
|
|||||||
name: "Page: Rename"
|
name: "Page: Rename"
|
||||||
mac: Cmd-Alt-r
|
mac: Cmd-Alt-r
|
||||||
key: Ctrl-Alt-r
|
key: Ctrl-Alt-r
|
||||||
|
button:
|
||||||
|
label: "📝"
|
||||||
|
tooltip: "Rename page"
|
||||||
pageComplete:
|
pageComplete:
|
||||||
path: "./page.ts:pageComplete"
|
path: "./page.ts:pageComplete"
|
||||||
events:
|
events:
|
||||||
@ -99,7 +102,20 @@ functions:
|
|||||||
path: ./page.ts:parsePageCommand
|
path: ./page.ts:parsePageCommand
|
||||||
command:
|
command:
|
||||||
name: "Debug: Parse Document"
|
name: "Debug: Parse Document"
|
||||||
|
insertPageMeta:
|
||||||
|
path: "./page.ts:insertPageMeta"
|
||||||
|
slashCommand:
|
||||||
|
name: meta
|
||||||
|
quickNoteCommand:
|
||||||
|
path: ./template.ts:quickNoteCommand
|
||||||
|
command:
|
||||||
|
name: "Template: Quick Note"
|
||||||
|
key: "Alt-Shift-n"
|
||||||
|
quickTaskCommand:
|
||||||
|
path: ./template.ts:quickTaskCommand
|
||||||
|
command:
|
||||||
|
name: "Template: Quick Task"
|
||||||
|
key: "Alt-Shift-t"
|
||||||
instantiateTemplateCommand:
|
instantiateTemplateCommand:
|
||||||
path: ./template.ts:instantiateTemplateCommand
|
path: ./template.ts:instantiateTemplateCommand
|
||||||
command:
|
command:
|
||||||
|
@ -9,8 +9,11 @@ import {
|
|||||||
import {
|
import {
|
||||||
flashNotification,
|
flashNotification,
|
||||||
getCurrentPage,
|
getCurrentPage,
|
||||||
|
getCursor,
|
||||||
getText,
|
getText,
|
||||||
|
insertAtCursor,
|
||||||
matchBefore,
|
matchBefore,
|
||||||
|
moveCursor,
|
||||||
navigate,
|
navigate,
|
||||||
prompt,
|
prompt,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||||
@ -247,3 +250,9 @@ export async function parsePageCommand() {
|
|||||||
export async function parsePage(text: string) {
|
export async function parsePage(text: string) {
|
||||||
console.log("AST", JSON.stringify(await parseMarkdown(text), null, 2));
|
console.log("AST", JSON.stringify(await parseMarkdown(text), null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function insertPageMeta() {
|
||||||
|
let cursorPos = await getCursor();
|
||||||
|
await insertAtCursor("```meta\n\n```");
|
||||||
|
await moveCursor(cursorPos + 8);
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||||
import {
|
import {
|
||||||
filterBox,
|
filterBox,
|
||||||
|
moveCursor,
|
||||||
navigate,
|
navigate,
|
||||||
prompt,
|
prompt,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||||
@ -35,7 +36,7 @@ export async function instantiateTemplateCommand() {
|
|||||||
let { text } = await readPage(selectedTemplate.name);
|
let { text } = await readPage(selectedTemplate.name);
|
||||||
|
|
||||||
let parseTree = await parseMarkdown(text);
|
let parseTree = await parseMarkdown(text);
|
||||||
let additionalPageMeta = extractMeta(parseTree, true);
|
let additionalPageMeta = extractMeta(parseTree, ["name"]);
|
||||||
console.log("Page meta", additionalPageMeta);
|
console.log("Page meta", additionalPageMeta);
|
||||||
|
|
||||||
let pageName = await prompt("Name of new page", additionalPageMeta.name);
|
let pageName = await prompt("Name of new page", additionalPageMeta.name);
|
||||||
@ -47,6 +48,7 @@ export async function instantiateTemplateCommand() {
|
|||||||
await navigate(pageName);
|
await navigate(pageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This should probably be replaced with handlebards somehow?
|
||||||
export function replaceTemplateVars(s: string, pageName: string): string {
|
export function replaceTemplateVars(s: string, pageName: string): string {
|
||||||
return s.replaceAll(/\{\{([^\}]+)\}\}/g, (match, v) => {
|
return s.replaceAll(/\{\{([^\}]+)\}\}/g, (match, v) => {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
@ -64,3 +66,22 @@ export function replaceTemplateVars(s: string, pageName: string): string {
|
|||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function quickNoteCommand() {
|
||||||
|
let isoDate = new Date().toISOString();
|
||||||
|
let [date, time] = isoDate.split("T");
|
||||||
|
time = time.split(".")[0];
|
||||||
|
let pageName = `📥 ${date} ${time}`;
|
||||||
|
await writePage(pageName, "");
|
||||||
|
await navigate(pageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function quickTaskCommand() {
|
||||||
|
let isoDate = new Date().toISOString();
|
||||||
|
let [date, time] = isoDate.split("T");
|
||||||
|
time = time.split(".")[0];
|
||||||
|
let pageName = `✅ ${date} ${time}`;
|
||||||
|
await writePage(pageName, "* [ ] ");
|
||||||
|
await navigate(pageName);
|
||||||
|
await moveCursor(6);
|
||||||
|
}
|
||||||
|
@ -5,6 +5,6 @@ functions:
|
|||||||
events:
|
events:
|
||||||
- query:gh-events
|
- query:gh-events
|
||||||
queryIssues:
|
queryIssues:
|
||||||
path: ./github.ts:queryIssues
|
path: ./github.ts:queryPulls
|
||||||
events:
|
events:
|
||||||
- query:gh-issues
|
- query:gh-pulls
|
||||||
|
@ -61,9 +61,13 @@ class GithubApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async listIssues(filter: string): Promise<any[]> {
|
async listPulls(
|
||||||
|
repo: string,
|
||||||
|
state: string = "all",
|
||||||
|
sort: string = "updated"
|
||||||
|
): Promise<any[]> {
|
||||||
return this.apiCall(
|
return this.apiCall(
|
||||||
`https://api.github.com/issues?q=${encodeURIComponent(filter)}`
|
`https://api.github.com/repos/${repo}/pulls?state=${state}&sort=${sort}&direction=desc&per_page=100`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,27 +130,40 @@ export async function queryEvents({
|
|||||||
return applyQuery(query, allEvents.map(mapEvent));
|
return applyQuery(query, allEvents.map(mapEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function queryIssues({
|
function mapPull(pull: any): any {
|
||||||
|
// console.log("Pull", Object.keys(pull));
|
||||||
|
return {
|
||||||
|
...pull,
|
||||||
|
username: pull.user.login,
|
||||||
|
// repo: pull.repo.name,
|
||||||
|
createdAt: pull.created_at.split("T")[0],
|
||||||
|
updatedAt: pull.updated_at.split("T")[0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function queryPulls({
|
||||||
query,
|
query,
|
||||||
}: QueryProviderEvent): Promise<any[]> {
|
}: QueryProviderEvent): Promise<any[]> {
|
||||||
let api = await GithubApi.fromConfig();
|
let api = await GithubApi.fromConfig();
|
||||||
let filter = query.filter.find((f) => f.prop === "filter");
|
let repo = query.filter.find((f) => f.prop === "repo");
|
||||||
if (!filter) {
|
if (!repo) {
|
||||||
throw Error("No 'filter' specified, this is mandatory");
|
throw Error("No 'repo' specified, this is mandatory");
|
||||||
}
|
}
|
||||||
let queries: string[] = [];
|
query.filter.splice(query.filter.indexOf(repo), 1);
|
||||||
if (filter.op === "=") {
|
let repos: string[] = [];
|
||||||
queries = [filter.value];
|
if (repo.op === "=") {
|
||||||
} else if (filter.op === "in") {
|
repos = [repo.value];
|
||||||
queries = filter.value;
|
} else if (repo.op === "in") {
|
||||||
|
repos = repo.value;
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unsupported operator ${filter.op}`);
|
throw new Error(`Unsupported operator ${repo.op}`);
|
||||||
}
|
}
|
||||||
let allIssues: any[] = [];
|
let allPulls: any[] = [];
|
||||||
for (let issuesList of await Promise.all(
|
for (let pullList of await Promise.all(
|
||||||
queries.map((query) => api.listIssues(query))
|
repos.map((repo) => api.listPulls(repo, "all", "updated"))
|
||||||
)) {
|
)) {
|
||||||
allIssues.push(...issuesList);
|
allPulls.push(...pullList);
|
||||||
}
|
}
|
||||||
return allIssues;
|
allPulls = applyQuery(query, allPulls.map(mapPull));
|
||||||
|
return allPulls;
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,14 @@ import {
|
|||||||
ParseTree,
|
ParseTree,
|
||||||
replaceNodesMatching,
|
replaceNodesMatching,
|
||||||
} from "@silverbulletmd/common/tree";
|
} from "@silverbulletmd/common/tree";
|
||||||
import { parse as parseYaml, parseAllDocuments } from "yaml";
|
import {
|
||||||
|
parse as parseYaml,
|
||||||
|
stringify as stringifyYaml,
|
||||||
|
parseAllDocuments,
|
||||||
|
} from "yaml";
|
||||||
import type { QueryProviderEvent } from "./engine";
|
import type { QueryProviderEvent } from "./engine";
|
||||||
import { applyQuery } from "./engine";
|
import { applyQuery } from "./engine";
|
||||||
import { jsonToMDTable, removeQueries } from "./util";
|
import { removeQueries } from "./util";
|
||||||
|
|
||||||
export async function indexData({ name, tree }: IndexTreeEvent) {
|
export async function indexData({ name, tree }: IndexTreeEvent) {
|
||||||
let dataObjects: { key: string; value: Object }[] = [];
|
let dataObjects: { key: string; value: Object }[] = [];
|
||||||
@ -58,8 +62,11 @@ export async function indexData({ name, tree }: IndexTreeEvent) {
|
|||||||
await batchSet(name, dataObjects);
|
await batchSet(name, dataObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractMeta(parseTree: ParseTree, remove = false): any {
|
export function extractMeta(
|
||||||
let data = {};
|
parseTree: ParseTree,
|
||||||
|
removeKeys: string[] = []
|
||||||
|
): any {
|
||||||
|
let data: any = {};
|
||||||
replaceNodesMatching(parseTree, (t) => {
|
replaceNodesMatching(parseTree, (t) => {
|
||||||
if (t.type !== "FencedCode") {
|
if (t.type !== "FencedCode") {
|
||||||
return;
|
return;
|
||||||
@ -78,7 +85,14 @@ export function extractMeta(parseTree: ParseTree, remove = false): any {
|
|||||||
}
|
}
|
||||||
let codeText = codeTextNode.children![0].text!;
|
let codeText = codeTextNode.children![0].text!;
|
||||||
data = parseYaml(codeText);
|
data = parseYaml(codeText);
|
||||||
return remove ? null : undefined;
|
if (removeKeys.length > 0) {
|
||||||
|
let newData = { ...data };
|
||||||
|
for (let key of removeKeys) {
|
||||||
|
delete newData[key];
|
||||||
|
}
|
||||||
|
codeTextNode.children![0].text = stringifyYaml(newData).trim();
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -174,6 +174,7 @@ export function FilterList({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Notification } from "../types";
|
import { ActionButton, Notification } from "../types";
|
||||||
|
|
||||||
function prettyName(s: string | undefined): string {
|
function prettyName(s: string | undefined): string {
|
||||||
if (!s) {
|
if (!s) {
|
||||||
@ -11,6 +11,7 @@ export function TopBar({
|
|||||||
pageName,
|
pageName,
|
||||||
unsavedChanges,
|
unsavedChanges,
|
||||||
notifications,
|
notifications,
|
||||||
|
actionButtons,
|
||||||
onClick,
|
onClick,
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
@ -18,6 +19,7 @@ export function TopBar({
|
|||||||
pageName?: string;
|
pageName?: string;
|
||||||
unsavedChanges: boolean;
|
unsavedChanges: boolean;
|
||||||
notifications: Notification[];
|
notifications: Notification[];
|
||||||
|
actionButtons: ActionButton[];
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
lhs?: React.ReactNode;
|
lhs?: React.ReactNode;
|
||||||
rhs?: React.ReactNode;
|
rhs?: React.ReactNode;
|
||||||
@ -27,24 +29,11 @@ export function TopBar({
|
|||||||
{lhs}
|
{lhs}
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<div className="inner">
|
<div className="inner">
|
||||||
{/*<span className={`icon ${unsavedChanges ? "unsaved" : "saved"}`}>*/}
|
|
||||||
{/* <FontAwesomeIcon icon={faFileLines} />*/}
|
|
||||||
{/*</span>*/}
|
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className={`current-page ${unsavedChanges ? "unsaved" : "saved"}`}
|
className={`current-page ${unsavedChanges ? "unsaved" : "saved"}`}
|
||||||
>
|
>
|
||||||
{prettyName(pageName)}
|
{prettyName(pageName)}
|
||||||
</span>
|
</span>
|
||||||
{/*<button*/}
|
|
||||||
{/* onClick={(e) => {*/}
|
|
||||||
{/* // @ts-ignore*/}
|
|
||||||
{/* window.syncer();*/}
|
|
||||||
{/* e.stopPropagation();*/}
|
|
||||||
{/* }}*/}
|
|
||||||
{/*>*/}
|
|
||||||
{/* Sync*/}
|
|
||||||
{/*</button>*/}
|
|
||||||
{notifications.length > 0 && (
|
{notifications.length > 0 && (
|
||||||
<div className="status">
|
<div className="status">
|
||||||
{notifications.map((notification) => (
|
{notifications.map((notification) => (
|
||||||
@ -52,6 +41,20 @@ export function TopBar({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div className="actions">
|
||||||
|
{actionButtons.map((actionButton, idx) => (
|
||||||
|
<button
|
||||||
|
key={idx}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
actionButton.run();
|
||||||
|
}}
|
||||||
|
title={actionButton.tooltip}
|
||||||
|
>
|
||||||
|
{actionButton.label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{rhs}
|
{rhs}
|
||||||
|
@ -99,10 +99,11 @@ export class Editor {
|
|||||||
// Command hook
|
// Command hook
|
||||||
this.commandHook = new CommandHook();
|
this.commandHook = new CommandHook();
|
||||||
this.commandHook.on({
|
this.commandHook.on({
|
||||||
commandsUpdated: (commandMap) => {
|
commandsUpdated: (commandMap, actionButtons) => {
|
||||||
this.viewDispatch({
|
this.viewDispatch({
|
||||||
type: "update-commands",
|
type: "update-commands",
|
||||||
commands: commandMap,
|
commands: commandMap,
|
||||||
|
actionButtons: actionButtons,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -603,6 +604,16 @@ export class Editor {
|
|||||||
pageName={viewState.currentPage}
|
pageName={viewState.currentPage}
|
||||||
notifications={viewState.notifications}
|
notifications={viewState.notifications}
|
||||||
unsavedChanges={viewState.unsavedChanges}
|
unsavedChanges={viewState.unsavedChanges}
|
||||||
|
actionButtons={[
|
||||||
|
{
|
||||||
|
label: "⚡️",
|
||||||
|
orderId: 0,
|
||||||
|
run: () => {
|
||||||
|
this.viewDispatch({ type: "show-palette" });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...viewState.actionButtons,
|
||||||
|
]}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dispatch({ type: "start-navigate" });
|
dispatch({ type: "start-navigate" });
|
||||||
}}
|
}}
|
||||||
|
100
packages/web/fonts/LICENSE.md
Normal file
100
packages/web/fonts/LICENSE.md
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# iA Writer Typeface
|
||||||
|
|
||||||
|
Copyright © 2018 Information Architects Inc. with Reserved Font Name "iA Writer"
|
||||||
|
|
||||||
|
# Based on IBM Plex Typeface
|
||||||
|
|
||||||
|
Copyright © 2017 IBM Corp. with Reserved Font Name "Plex"
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
packages/web/fonts/iAWriterMonoS-Bold.woff2
Normal file
BIN
packages/web/fonts/iAWriterMonoS-Bold.woff2
Normal file
Binary file not shown.
BIN
packages/web/fonts/iAWriterMonoS-BoldItalic.woff2
Normal file
BIN
packages/web/fonts/iAWriterMonoS-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
packages/web/fonts/iAWriterMonoS-Italic.woff2
Normal file
BIN
packages/web/fonts/iAWriterMonoS-Italic.woff2
Normal file
Binary file not shown.
BIN
packages/web/fonts/iAWriterMonoS-Regular.woff2
Normal file
BIN
packages/web/fonts/iAWriterMonoS-Regular.woff2
Normal file
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
import { Hook, Manifest } from "@plugos/plugos/types";
|
import { Hook, Manifest } from "@plugos/plugos/types";
|
||||||
import { System } from "@plugos/plugos/system";
|
import { System } from "@plugos/plugos/system";
|
||||||
import { EventEmitter } from "@plugos/plugos/event";
|
import { EventEmitter } from "@plugos/plugos/event";
|
||||||
|
import { ActionButton } from "../types";
|
||||||
|
|
||||||
export type CommandDef = {
|
export type CommandDef = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -10,6 +11,14 @@ export type CommandDef = {
|
|||||||
// Bind to keyboard shortcut
|
// Bind to keyboard shortcut
|
||||||
key?: string;
|
key?: string;
|
||||||
mac?: string;
|
mac?: string;
|
||||||
|
|
||||||
|
// Action button
|
||||||
|
button?: ButtonDef;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ButtonDef = {
|
||||||
|
label: string;
|
||||||
|
tooltip?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AppCommand = {
|
export type AppCommand = {
|
||||||
@ -22,7 +31,10 @@ export type CommandHookT = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type CommandHookEvents = {
|
export type CommandHookEvents = {
|
||||||
commandsUpdated(commandMap: Map<string, AppCommand>): void;
|
commandsUpdated(
|
||||||
|
commandMap: Map<string, AppCommand>,
|
||||||
|
appButtons: ActionButton[]
|
||||||
|
): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CommandHook
|
export class CommandHook
|
||||||
@ -30,9 +42,11 @@ export class CommandHook
|
|||||||
implements Hook<CommandHookT>
|
implements Hook<CommandHookT>
|
||||||
{
|
{
|
||||||
editorCommands = new Map<string, AppCommand>();
|
editorCommands = new Map<string, AppCommand>();
|
||||||
|
actionButtons: ActionButton[] = [];
|
||||||
|
|
||||||
buildAllCommands(system: System<CommandHookT>) {
|
buildAllCommands(system: System<CommandHookT>) {
|
||||||
this.editorCommands.clear();
|
this.editorCommands.clear();
|
||||||
|
this.actionButtons = [];
|
||||||
for (let plug of system.loadedPlugs.values()) {
|
for (let plug of system.loadedPlugs.values()) {
|
||||||
for (const [name, functionDef] of Object.entries(
|
for (const [name, functionDef] of Object.entries(
|
||||||
plug.manifest!.functions
|
plug.manifest!.functions
|
||||||
@ -47,9 +61,18 @@ export class CommandHook
|
|||||||
return plug.invoke(name, []);
|
return plug.invoke(name, []);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (cmd.button) {
|
||||||
|
this.actionButtons.push({
|
||||||
|
label: cmd.button.label,
|
||||||
|
tooltip: cmd.button.tooltip,
|
||||||
|
run: () => {
|
||||||
|
return plug.invoke(name, []);
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.emit("commandsUpdated", this.editorCommands);
|
}
|
||||||
|
this.emit("commandsUpdated", this.editorCommands, this.actionButtons);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(system: System<CommandHookT>): void {
|
apply(system: System<CommandHookT>): void {
|
||||||
|
@ -67,6 +67,7 @@ export default function reducer(
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
commands: action.commands,
|
commands: action.commands,
|
||||||
|
actionButtons: action.actionButtons,
|
||||||
};
|
};
|
||||||
case "show-notification":
|
case "show-notification":
|
||||||
return {
|
return {
|
||||||
|
@ -249,7 +249,7 @@
|
|||||||
color: #989797;
|
color: #989797;
|
||||||
background-color: rgba(210, 210, 210, 0.2);
|
background-color: rgba(210, 210, 210, 0.2);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-style: italic;
|
// font-style: italic;
|
||||||
font-size: 75%;
|
font-size: 75%;
|
||||||
line-height: 75%;
|
line-height: 75%;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,38 @@
|
|||||||
@use "filter_box.scss";
|
@use "filter_box.scss";
|
||||||
@import "constants";
|
@import "constants";
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "iA-Mono";
|
||||||
|
src: url("../fonts/iAWriterMonoS-Regular.woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "iA-Mono";
|
||||||
|
src: url("../fonts/iAWriterMonoS-Bold.woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "iA-Mono";
|
||||||
|
src: url("../fonts/iAWriterMonoS-Italic.woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "iA-Mono";
|
||||||
|
src: url("../fonts/iAWriterMonoS-BoldItalic.woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--ident: 18px;
|
--ident: 18px;
|
||||||
/* --editor-font: "Avenir"; */
|
/* --editor-font: "Avenir"; */
|
||||||
--editor-font: "Menlo";
|
--editor-font: "iA-Mono", "Menlo";
|
||||||
--ui-font: "Arial";
|
--ui-font: "Arial";
|
||||||
--top-bar-bg: rgb(41, 41, 41);
|
--top-bar-bg: rgb(41, 41, 41);
|
||||||
--highlight-color: #464cfc;
|
--highlight-color: #464cfc;
|
||||||
@ -73,6 +100,20 @@ body {
|
|||||||
color: #5e5e5e;
|
color: #5e5e5e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.actions {
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: 0;
|
||||||
|
// border-radius: 5px;
|
||||||
|
// background-color: rgba(77,141,255,0.07);
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 3px;
|
||||||
|
font-family: "IA-Mono", "Menlo";
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,13 @@ export type Notification = {
|
|||||||
date: Date;
|
date: Date;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ActionButton = {
|
||||||
|
label: string;
|
||||||
|
tooltip?: string;
|
||||||
|
orderId?: number;
|
||||||
|
run: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
export type AppViewState = {
|
export type AppViewState = {
|
||||||
currentPage?: string;
|
currentPage?: string;
|
||||||
showPageNavigator: boolean;
|
showPageNavigator: boolean;
|
||||||
@ -23,6 +30,7 @@ export type AppViewState = {
|
|||||||
allPages: Set<PageMeta>;
|
allPages: Set<PageMeta>;
|
||||||
commands: Map<string, AppCommand>;
|
commands: Map<string, AppCommand>;
|
||||||
notifications: Notification[];
|
notifications: Notification[];
|
||||||
|
actionButtons: ActionButton[];
|
||||||
|
|
||||||
showFilterBox: boolean;
|
showFilterBox: boolean;
|
||||||
filterBoxLabel: string;
|
filterBoxLabel: string;
|
||||||
@ -45,6 +53,7 @@ export const initialViewState: AppViewState = {
|
|||||||
allPages: new Set(),
|
allPages: new Set(),
|
||||||
commands: new Map(),
|
commands: new Map(),
|
||||||
notifications: [],
|
notifications: [],
|
||||||
|
actionButtons: [],
|
||||||
showFilterBox: false,
|
showFilterBox: false,
|
||||||
filterBoxHelpText: "",
|
filterBoxHelpText: "",
|
||||||
filterBoxLabel: "",
|
filterBoxLabel: "",
|
||||||
@ -60,7 +69,11 @@ export type Action =
|
|||||||
| { type: "page-saved" }
|
| { type: "page-saved" }
|
||||||
| { type: "start-navigate" }
|
| { type: "start-navigate" }
|
||||||
| { type: "stop-navigate" }
|
| { type: "stop-navigate" }
|
||||||
| { type: "update-commands"; commands: Map<string, AppCommand> }
|
| {
|
||||||
|
type: "update-commands";
|
||||||
|
commands: Map<string, AppCommand>;
|
||||||
|
actionButtons: ActionButton[];
|
||||||
|
}
|
||||||
| { type: "show-palette"; context?: string }
|
| { type: "show-palette"; context?: string }
|
||||||
| { type: "hide-palette" }
|
| { type: "hide-palette" }
|
||||||
| { type: "show-notification"; notification: Notification }
|
| { type: "show-notification"; notification: Notification }
|
||||||
|
Loading…
Reference in New Issue
Block a user