Skip to content
This repository was archived by the owner on Aug 17, 2025. It is now read-only.

Commit edd9722

Browse files
committed
- Began implementing command palette
- Improved plugin system
1 parent cdd0a83 commit edd9722

File tree

18 files changed

+365
-204
lines changed

18 files changed

+365
-204
lines changed
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
---
22
name: Bug report
33
about: Create a report to help us improve
4-
title: ''
5-
labels: ''
6-
assignees: ''
7-
4+
title: ""
5+
labels: ""
6+
assignees: ""
87
---
98

109
**Describe the bug**
1110
A clear and concise description of what the bug is.
1211

1312
**To Reproduce**
1413
Steps to reproduce the behavior:
14+
1515
1. Go to '...'
1616
2. Click on '....'
1717
3. Scroll down to '....'
@@ -24,7 +24,8 @@ A clear and concise description of what you expected to happen.
2424
If applicable, add screenshots to help explain your problem.
2525

2626
**Desktop (please complete the following information):**
27-
- OS: [e.g. iOS]
27+
28+
- OS: [e.g. iOS]
2829

2930
**Additional context**
3031
Add any other context about the problem here.

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
---
22
name: Feature request
33
about: Suggest an idea for this project
4-
title: ''
5-
labels: ''
6-
assignees: ''
7-
4+
title: ""
5+
labels: ""
6+
assignees: ""
87
---
98

109
**Is your feature request related to a problem? Please describe.**

.prettierrc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"semi": true,
3-
"singleQuote": false,
4-
"tabWidth": 2,
5-
"trailingComma": "es5"
2+
"semi": true,
3+
"trailingComma": "es5",
4+
"tabWidth": 2,
5+
"useTabs": false
66
}

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,3 @@ We welcome contributions from the community! Whether it's a bug fix, feature req
8080
---
8181

8282
> "Boardify is a desktop app for organizing reference material such as images, videos, and other media on an infinite board."
83-

src-tauri/capabilities/default.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
"$schema": "../gen/schemas/desktop-schema.json",
33
"identifier": "default",
44
"description": "Capability for the main window",
5-
"windows": [
6-
"main"
7-
],
5+
"windows": ["main"],
86
"permissions": [
97
"core:default",
108
"shell:allow-open",
@@ -16,4 +14,4 @@
1614
"log:default",
1715
"fs:default"
1816
]
19-
}
17+
}

src/assets/styles/base.css

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,102 @@
11
/* Global Reset */
22
* {
3-
margin: 0;
4-
padding: 0;
5-
box-sizing: border-box;
3+
margin: 0;
4+
padding: 0;
5+
box-sizing: border-box;
66
}
77

88
html,
99
body {
10-
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
11-
font-size: 16px;
12-
line-height: 24px;
13-
font-weight: 400;
14-
color: var(--text-color, #f6f6f6);
15-
background-color: transparent;
16-
width: 100%;
17-
height: 100%;
18-
overflow: hidden;
19-
font-synthesis: none;
20-
text-rendering: optimizeLegibility;
21-
-webkit-font-smoothing: antialiased;
22-
-moz-osx-font-smoothing: grayscale;
23-
-webkit-text-size-adjust: 100%;
10+
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
11+
font-size: 16px;
12+
line-height: 24px;
13+
font-weight: 400;
14+
color: var(--text-color, #f6f6f6);
15+
background-color: transparent;
16+
width: 100%;
17+
height: 100%;
18+
overflow: hidden;
19+
font-synthesis: none;
20+
text-rendering: optimizeLegibility;
21+
-webkit-font-smoothing: antialiased;
22+
-moz-osx-font-smoothing: grayscale;
23+
-webkit-text-size-adjust: 100%;
2424
}
2525

2626
body,
2727
#root {
28-
display: flex;
29-
flex-direction: column;
30-
flex: 1;
28+
display: flex;
29+
flex-direction: column;
30+
flex: 1;
3131
}
3232

3333
:root {
34-
/* Colors */
35-
--text-color: #f6f6f6;
36-
--card-color: #333436;
37-
--graph-bg: #222224;
34+
/* Colors */
35+
--text-color: #f6f6f6;
36+
--card-color: #333436;
37+
--graph-bg: #222224;
3838

39-
/* Spacing */
40-
--input-padding: 10px;
41-
--border-radius: 6px;
39+
/* Spacing */
40+
--input-padding: 10px;
41+
--border-radius: 6px;
4242

43-
/* Sizes */
44-
--slider-thumb-size: 18px;
43+
/* Sizes */
44+
--slider-thumb-size: 18px;
4545

46-
--z-index-base: 0;
47-
--z-index-sidebar: 10;
48-
--z-index-titlebar: 20;
49-
--z-index-dropdown: 30;
50-
--z-index-modal: 40;
51-
--z-index-settings: 50;
52-
--z-index-toast: 60;
53-
--z-index-tooltip: 70;
54-
--z-index-overlay: 80;
55-
--z-index-always-on-top: 9999;
46+
--z-index-base: 0;
47+
--z-index-sidebar: 10;
48+
--z-index-titlebar: 20;
49+
--z-index-dropdown: 30;
50+
--z-index-modal: 40;
51+
--z-index-settings: 50;
52+
--z-index-toast: 60;
53+
--z-index-tooltip: 70;
54+
--z-index-overlay: 80;
55+
--z-index-always-on-top: 9999;
5656
}
5757

5858
*:focus-visible {
59-
outline: none;
60-
box-shadow:
61-
0 0 0 3px rgba(255, 255, 255, 0.5),
62-
0 2px 4px rgba(0, 0, 0, 0.2);
59+
outline: none;
60+
box-shadow:
61+
0 0 0 3px rgba(255, 255, 255, 0.5),
62+
0 2px 4px rgba(0, 0, 0, 0.2);
6363
}
6464

6565
body,
6666
button,
6767
input,
6868
select,
6969
textarea {
70-
font-family: var(--font-family);
71-
font-size: var(--font-size);
72-
color: var(--text-color);
70+
font-family: var(--font-family);
71+
font-size: var(--font-size);
72+
color: var(--text-color);
7373
}
7474

7575
li {
76-
border: none;
77-
outline: none;
76+
border: none;
77+
outline: none;
78+
}
79+
80+
button {
81+
border: none;
82+
cursor: pointer;
7883
}
7984

8085
.expand-box {
81-
position: relative;
82-
display: flex;
83-
flex: 1;
86+
position: relative;
87+
display: flex;
88+
flex: 1;
8489
}
8590

8691
.app-container {
87-
display: flex;
88-
flex-direction: column;
89-
flex: 1;
90-
overflow: hidden;
92+
display: flex;
93+
flex-direction: column;
94+
flex: 1;
95+
overflow: hidden;
9196
}
9297

9398
.editor-container {
94-
display: flex;
95-
flex: 1;
96-
overflow: hidden;
99+
display: flex;
100+
flex: 1;
101+
overflow: hidden;
97102
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { store } from "@/store";
2+
import { Command, ICommandRegistry } from "./types";
3+
4+
type CommandRegistryEvent = "commandAdded" | "commandRemoved";
5+
type CommandRegistryListener = (commands: Command[]) => void;
6+
7+
export class CommandRegistry implements ICommandRegistry {
8+
private commands: Map<string, Command>;
9+
private listeners = new Map<
10+
CommandRegistryEvent,
11+
Set<CommandRegistryListener>
12+
>();
13+
14+
constructor() {
15+
this.commands = new Map<string, Command>();
16+
}
17+
18+
private emit(event: CommandRegistryEvent) {
19+
const listeners = this.listeners.get(event);
20+
if (!listeners) return;
21+
const commands = this.getCommands();
22+
for (const listener of listeners) {
23+
listener(commands);
24+
}
25+
}
26+
27+
on(event: CommandRegistryEvent, listener: CommandRegistryListener) {
28+
if (!this.listeners.has(event)) {
29+
this.listeners.set(event, new Set());
30+
}
31+
this.listeners.get(event)!.add(listener);
32+
}
33+
34+
off(event: CommandRegistryEvent, listener: CommandRegistryListener) {
35+
this.listeners.get(event)?.delete(listener);
36+
}
37+
38+
async executeCommand(commandId: string): Promise<void> {
39+
const command = this.commands.get(commandId);
40+
if (!command) {
41+
throw new Error(`Command with id ${commandId} does not exist.`);
42+
}
43+
await command.action({
44+
dispatch: store.dispatch,
45+
getState: store.getState,
46+
});
47+
}
48+
49+
addCommand(command: Command): void {
50+
if (this.commands.has(command.id)) {
51+
throw new Error(`Command with id ${command.id} already exists.`);
52+
}
53+
this.commands.set(command.id, command);
54+
this.emit("commandAdded");
55+
}
56+
57+
removeCommand(commandId: string): void {
58+
if (!this.commands.has(commandId)) {
59+
throw new Error(`Command with id ${commandId} does not exist.`);
60+
}
61+
this.commands.delete(commandId);
62+
this.emit("commandRemoved");
63+
}
64+
65+
getCommands(): Command[] {
66+
return Array.from(this.commands.values());
67+
}
68+
}
69+
70+
export const commandRegistry = new CommandRegistry();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { commandRegistry } from "../CommandRegistry";
2+
import { useCommands } from "../hooks/useCommands";
3+
4+
export const CommandList = () => {
5+
const commands = useCommands();
6+
7+
function executeCommand(id: string) {
8+
commandRegistry.executeCommand(id);
9+
}
10+
11+
return (
12+
<div className="command-list">
13+
<h1>Command List</h1>
14+
{commands.map((command) => (
15+
<button key={command.id} onClick={() => executeCommand(command.id)}>
16+
{command.name}
17+
</button>
18+
))}
19+
</div>
20+
);
21+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { useEffect, useState } from "react";
2+
import { Command } from "../types";
3+
import { commandRegistry } from "../CommandRegistry";
4+
5+
export function useCommands(): Command[] {
6+
const [commands, setCommands] = useState<Command[]>(
7+
commandRegistry.getCommands()
8+
);
9+
10+
useEffect(() => {
11+
const update = (cmds: Command[]) => setCommands(cmds);
12+
commandRegistry.on("commandAdded", update);
13+
commandRegistry.on("commandRemoved", update);
14+
15+
return () => {
16+
commandRegistry.off("commandAdded", update);
17+
commandRegistry.off("commandRemoved", update);
18+
};
19+
}, []);
20+
21+
return commands;
22+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { commandRegistry } from "./CommandRegistry";
2+
export * from "./types";
3+
export { useCommands } from "./hooks/useCommands";
4+
export { CommandPalette } from "./components/CommandPalette";

0 commit comments

Comments
 (0)