Hotbar command palette + switching (#2552)

* fix initial hotbar not showing

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* hotbar command palette + switching

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* lint fix

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* add clickable index to switcher

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fixes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* cleanup

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* cleanup

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* refactor

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix typo

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fixes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* remote notifications

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix add to hotbar

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* don't show remove-from-hotbar on catalog context menu

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix bad merge

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix bad merge

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix bad merge

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen authored and GitHub committed 2021-04-22 10:07:14 +03:00
1 parent b63fdfaff3
commit da8cc889c4
14 files changed
+350 -24

No files matched your search

+1 -14
View File
@@ -57,7 +57,7 @@ export class Catalog extends React.Component {
}
addToHotbar(item: CatalogEntityItem) {
const hotbar = HotbarStore.getInstance().getByName("default"); // FIXME
const hotbar = HotbarStore.getInstance().getActive();
if (!hotbar) {
return;
@@ -66,16 +66,6 @@ export class Catalog extends React.Component {
hotbar.items.push({ entity: { uid: item.id }});
}
removeFromHotbar(item: CatalogEntityItem) {
const hotbar = HotbarStore.getInstance().getByName("default"); // FIXME
if (!hotbar) {
return;
}
hotbar.items = hotbar.items.filter((i) => i.entity.uid !== item.id);
}
onDetails(item: CatalogEntityItem) {
item.onRun(catalogEntityRunContext);
}
@@ -137,9 +127,6 @@ export class Catalog extends React.Component {
<MenuItem key="add-to-hotbar" onClick={() => this.addToHotbar(item) }>
<Icon material="add" small interactive={true} title="Add to hotbar"/> Add to Hotbar
</MenuItem>
<MenuItem key="remove-from-hotbar" onClick={() => this.removeFromHotbar(item) }>
<Icon material="clear" small interactive={true} title="Remove from hotbar"/> Remove from Hotbar
</MenuItem>
{ menuItems.map((menuItem, index) => {
return (
<MenuItem key={index} onClick={() => this.onMenuItemClick(menuItem)}>
@@ -0,0 +1,50 @@
import React from "react";
import { observer } from "mobx-react";
import { HotbarStore } from "../../../common/hotbar-store";
import { CommandOverlay } from "../command-palette";
import { Input, InputValidator } from "../input";
const uniqueHotbarName: InputValidator = {
condition: ({ required }) => required,
message: () => "Hotbar with this name already exists",
validate: value => !HotbarStore.getInstance().getByName(value),
};
@observer
export class HotbarAddCommand extends React.Component {
onSubmit(name: string) {
if (!name.trim()) {
return;
}
const hotbarStore = HotbarStore.getInstance();
const hotbar = hotbarStore.add({
name
});
hotbarStore.activeHotbarId = hotbar.id;
CommandOverlay.close();
}
render() {
return (
<>
<Input
placeholder="Hotbar name"
autoFocus={true}
theme="round-black"
data-test-id="command-palette-hotbar-add-name"
validators={[uniqueHotbarName]}
onSubmit={(v) => this.onSubmit(v)}
dirty={true}
showValidationLine={true} />
<small className="hint">
Please provide a new hotbar name (Press &quot;Enter&quot; to confirm or &quot;Escape&quot; to cancel)
</small>
</>
);
}
}
@@ -60,7 +60,7 @@ export class HotbarIcon extends React.Component<Props> {
}
removeFromHotbar(item: CatalogEntity) {
const hotbar = HotbarStore.getInstance().getByName("default"); // FIXME
const hotbar = HotbarStore.getInstance().getActive();
if (!hotbar) {
return;
@@ -22,4 +22,14 @@
display: none;
}
}
.HotbarSelector {
position: absolute;
bottom: 0;
width: 100%;
.Badge {
cursor: pointer;
}
}
}
+26 -2
View File
@@ -1,4 +1,5 @@
import "./hotbar-menu.scss";
import "./hotbar.commands";
import React from "react";
import { observer } from "mobx-react";
@@ -7,6 +8,10 @@ import { cssNames, IClassName } from "../../utils";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
import { HotbarStore } from "../../../common/hotbar-store";
import { catalogEntityRunContext } from "../../api/catalog-entity";
import { Icon } from "../icon";
import { Badge } from "../badge";
import { CommandOverlay } from "../command-palette";
import { HotbarSwitchCommand } from "./hotbar-switch-command";
interface Props {
className?: IClassName;
@@ -14,9 +19,8 @@ interface Props {
@observer
export class HotbarMenu extends React.Component<Props> {
get hotbarItems() {
const hotbar = HotbarStore.getInstance().getByName("default"); // FIXME
const hotbar = HotbarStore.getInstance().getActive();
if (!hotbar) {
return [];
@@ -25,8 +29,21 @@ export class HotbarMenu extends React.Component<Props> {
return hotbar.items.map((item) => catalogEntityRegistry.items.find((entity) => entity.metadata.uid === item.entity.uid)).filter(Boolean);
}
previous() {
HotbarStore.getInstance().switchToPrevious();
}
next() {
HotbarStore.getInstance().switchToNext();
}
openSelector() {
CommandOverlay.open(<HotbarSwitchCommand />);
}
render() {
const { className } = this.props;
const hotbarIndex = HotbarStore.getInstance().activeHotbarIndex + 1;
return (
<div className={cssNames("HotbarMenu flex column", className)}>
@@ -43,6 +60,13 @@ export class HotbarMenu extends React.Component<Props> {
);
})}
</div>
<div className="HotbarSelector flex gaps auto">
<Icon material="chevron_left" className="previous box" onClick={() => this.previous()} />
<div className="box">
<Badge small label={hotbarIndex} onClick={() => this.openSelector()} />
</div>
<Icon material="chevron_right" className="next box" onClick={() => this.next()} />
</div>
</div>
);
}
@@ -0,0 +1,57 @@
import React from "react";
import { observer } from "mobx-react";
import { Select } from "../select";
import { computed } from "mobx";
import { HotbarStore } from "../../../common/hotbar-store";
import { CommandOverlay } from "../command-palette";
import { ConfirmDialog } from "../confirm-dialog";
@observer
export class HotbarRemoveCommand extends React.Component {
@computed get options() {
return HotbarStore.getInstance().hotbars.map((hotbar) => {
return { value: hotbar.id, label: hotbar.name };
});
}
onChange(id: string): void {
const hotbarStore = HotbarStore.getInstance();
const hotbar = hotbarStore.getById(id);
if (!hotbar) {
return;
}
CommandOverlay.close();
ConfirmDialog.open({
okButtonProps: {
label: `Remove Hotbar`,
primary: false,
accent: true,
},
ok: () => {
hotbarStore.remove(hotbar);
},
message: (
<div className="confirm flex column gaps">
<p>
Are you sure you want remove hotbar <b>{hotbar.name}</b>?
</p>
</div>
),
});
}
render() {
return (
<Select
onChange={(v) => this.onChange(v.value)}
components={{ DropdownIndicator: null, IndicatorSeparator: null }}
menuIsOpen={true}
options={this.options}
autoFocus={true}
escapeClearsValue={false}
placeholder="Remove hotbar" />
);
}
}
@@ -0,0 +1,58 @@
import React from "react";
import { observer } from "mobx-react";
import { Select } from "../select";
import { computed } from "mobx";
import { HotbarStore } from "../../../common/hotbar-store";
import { CommandOverlay } from "../command-palette";
import { HotbarAddCommand } from "./hotbar-add-command";
import { HotbarRemoveCommand } from "./hotbar-remove-command";
@observer
export class HotbarSwitchCommand extends React.Component {
private static addActionId = "__add__";
private static removeActionId = "__remove__";
@computed get options() {
const hotbarStore = HotbarStore.getInstance();
const options = hotbarStore.hotbars.map((hotbar) => {
return { value: hotbar.id, label: hotbar.name };
});
options.push({ value: HotbarSwitchCommand.addActionId, label: "Add hotbar ..." });
if (hotbarStore.hotbars.length > 1) {
options.push({ value: HotbarSwitchCommand.removeActionId, label: "Remove hotbar ..." });
}
return options;
}
onChange(idOrAction: string): void {
switch(idOrAction) {
case HotbarSwitchCommand.addActionId:
CommandOverlay.open(<HotbarAddCommand />);
return;
case HotbarSwitchCommand.removeActionId:
CommandOverlay.open(<HotbarRemoveCommand />);
return;
default:
HotbarStore.getInstance().activeHotbarId = idOrAction;
CommandOverlay.close();
}
}
render() {
return (
<Select
onChange={(v) => this.onChange(v.value)}
components={{ DropdownIndicator: null, IndicatorSeparator: null }}
menuIsOpen={true}
options={this.options}
autoFocus={true}
escapeClearsValue={false}
placeholder="Switch to hotbar" />
);
}
}
@@ -0,0 +1,27 @@
import React from "react";
import { commandRegistry } from "../../../extensions/registries";
import { CommandOverlay } from "../command-palette";
import { HotbarAddCommand } from "./hotbar-add-command";
import { HotbarRemoveCommand } from "./hotbar-remove-command";
import { HotbarSwitchCommand } from "./hotbar-switch-command";
commandRegistry.add({
id: "hotbar.switchHotbar",
title: "Hotbar: Switch ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarSwitchCommand />)
});
commandRegistry.add({
id: "hotbar.addHotbar",
title: "Hotbar: Add Hotbar ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarAddCommand />)
});
commandRegistry.add({
id: "hotbar.removeHotbar",
title: "Hotbar: Remove Hotbar ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarRemoveCommand />)
});