mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make legacy unit tests for hotbar green and more simple by using the new legacy helper
Signed-off-by: Iku-turso <mikko.aspiala@gmail.com>
This commit is contained in:
parent
b935dbca78
commit
eb756f4da4
@ -6,14 +6,17 @@
|
||||
import { anyObject } from "jest-mock-extended";
|
||||
import mockFs from "mock-fs";
|
||||
import logger from "../../main/logger";
|
||||
import type { CatalogEntity, CatalogEntityData, CatalogEntityKindData } from "../catalog";
|
||||
import type {
|
||||
CatalogEntity,
|
||||
CatalogEntityData,
|
||||
CatalogEntityKindData,
|
||||
} from "../catalog";
|
||||
import { HotbarStore } from "../hotbar-store";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import writeFileInjectable from "../fs/write-file.injectable";
|
||||
import hotbarStoreInjectable from "../hotbar-store.injectable";
|
||||
import catalogCatalogEntityInjectable
|
||||
from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
|
||||
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
jest.mock("../../main/catalog/catalog-entity-registry", () => ({
|
||||
catalogEntityRegistry: {
|
||||
@ -21,9 +24,11 @@ jest.mock("../../main/catalog/catalog-entity-registry", () => ({
|
||||
getMockCatalogEntity({
|
||||
apiVersion: "v1",
|
||||
kind: "Cluster",
|
||||
|
||||
status: {
|
||||
phase: "Running",
|
||||
},
|
||||
|
||||
metadata: {
|
||||
uid: "1dfa26e2ebab15780a3547e9c7fa785c",
|
||||
name: "mycluster",
|
||||
@ -31,12 +36,15 @@ jest.mock("../../main/catalog/catalog-entity-registry", () => ({
|
||||
labels: {},
|
||||
},
|
||||
}),
|
||||
|
||||
getMockCatalogEntity({
|
||||
apiVersion: "v1",
|
||||
kind: "Cluster",
|
||||
|
||||
status: {
|
||||
phase: "Running",
|
||||
},
|
||||
|
||||
metadata: {
|
||||
uid: "55b42c3c7ba3b04193416cda405269a5",
|
||||
name: "my_shiny_cluster",
|
||||
@ -44,12 +52,15 @@ jest.mock("../../main/catalog/catalog-entity-registry", () => ({
|
||||
labels: {},
|
||||
},
|
||||
}),
|
||||
|
||||
getMockCatalogEntity({
|
||||
apiVersion: "v1",
|
||||
kind: "Cluster",
|
||||
|
||||
status: {
|
||||
phase: "Running",
|
||||
},
|
||||
|
||||
metadata: {
|
||||
uid: "catalog-entity",
|
||||
name: "Catalog",
|
||||
@ -61,7 +72,9 @@ jest.mock("../../main/catalog/catalog-entity-registry", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
function getMockCatalogEntity(data: Partial<CatalogEntityData> & CatalogEntityKindData): CatalogEntity {
|
||||
function getMockCatalogEntity(
|
||||
data: Partial<CatalogEntityData> & CatalogEntityKindData,
|
||||
): CatalogEntity {
|
||||
return {
|
||||
getName: jest.fn(() => data.metadata?.name),
|
||||
getId: jest.fn(() => data.metadata?.uid),
|
||||
@ -116,275 +129,303 @@ const awsCluster = getMockCatalogEntity({
|
||||
});
|
||||
|
||||
describe("HotbarStore", () => {
|
||||
let di: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(writeFileInjectable, () => () => undefined);
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
// @ts-ignore
|
||||
di.permitSideEffects(hotbarStoreInjectable);
|
||||
|
||||
di.override(hotbarStoreInjectable, (di) =>
|
||||
HotbarStore.createInstance({
|
||||
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
|
||||
}),
|
||||
);
|
||||
// @ts-ignore
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
|
||||
mockFs({
|
||||
"some-directory-for-user-data": {
|
||||
"lens-hotbar-store.json": JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
|
||||
await di.runSetups();
|
||||
|
||||
di.inject(hotbarStoreInjectable);
|
||||
// @ts-ignore
|
||||
di.permitSideEffects(appVersionInjectable);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
HotbarStore.resetInstance();
|
||||
});
|
||||
|
||||
describe("load", () => {
|
||||
it("loads one hotbar by default", () => {
|
||||
expect(HotbarStore.getInstance().hotbars.length).toEqual(1);
|
||||
describe("given no migrations", () => {
|
||||
beforeEach(async () => {
|
||||
await di.runSetups();
|
||||
});
|
||||
|
||||
describe("load", () => {
|
||||
it("loads one hotbar by default", () => {
|
||||
expect(HotbarStore.getInstance().hotbars.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("add", () => {
|
||||
it("adds a hotbar", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.add({ name: "hottest" });
|
||||
expect(hotbarStore.hotbars.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hotbar items", () => {
|
||||
it("initially creates 12 empty cells", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(hotbarStore.getActive().items.length).toEqual(12);
|
||||
});
|
||||
|
||||
it("initially adds catalog entity as first item", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(hotbarStore.getActive().items[0].entity.name).toEqual("Catalog");
|
||||
});
|
||||
|
||||
it("adds items", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||
|
||||
expect(items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("removes items", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.removeFromHotbar("test");
|
||||
hotbarStore.removeFromHotbar("catalog-entity");
|
||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||
|
||||
expect(items).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("does nothing if removing with invalid uid", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.removeFromHotbar("invalid uid");
|
||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||
|
||||
expect(items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("moves item to empty cell", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
|
||||
expect(hotbarStore.getActive().items[6]).toBeNull();
|
||||
|
||||
hotbarStore.restackItems(1, 5);
|
||||
|
||||
expect(hotbarStore.getActive().items[5]).toBeTruthy();
|
||||
expect(hotbarStore.getActive().items[5].entity.uid).toEqual("test");
|
||||
});
|
||||
|
||||
it("moves items down", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
|
||||
// aws -> catalog
|
||||
hotbarStore.restackItems(3, 0);
|
||||
|
||||
const items = hotbarStore
|
||||
.getActive()
|
||||
.items.map((item) => item?.entity.uid || null);
|
||||
|
||||
expect(items.slice(0, 4)).toEqual([
|
||||
"aws",
|
||||
"catalog-entity",
|
||||
"test",
|
||||
"minikube",
|
||||
]);
|
||||
});
|
||||
|
||||
it("moves items up", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
|
||||
// test -> aws
|
||||
hotbarStore.restackItems(1, 3);
|
||||
|
||||
const items = hotbarStore
|
||||
.getActive()
|
||||
.items.map((item) => item?.entity.uid || null);
|
||||
|
||||
expect(items.slice(0, 4)).toEqual([
|
||||
"catalog-entity",
|
||||
"minikube",
|
||||
"aws",
|
||||
"test",
|
||||
]);
|
||||
});
|
||||
|
||||
it("logs an error if cellIndex is out of bounds", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.add({ name: "hottest", id: "hottest" });
|
||||
hotbarStore.setActiveHotbar("hottest");
|
||||
|
||||
const { error } = logger;
|
||||
const mocked = jest.fn();
|
||||
|
||||
logger.error = mocked;
|
||||
|
||||
hotbarStore.addToHotbar(testCluster, -1);
|
||||
expect(mocked).toBeCalledWith(
|
||||
"[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range",
|
||||
anyObject(),
|
||||
);
|
||||
|
||||
hotbarStore.addToHotbar(testCluster, 12);
|
||||
expect(mocked).toBeCalledWith(
|
||||
"[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range",
|
||||
anyObject(),
|
||||
);
|
||||
|
||||
hotbarStore.addToHotbar(testCluster, 13);
|
||||
expect(mocked).toBeCalledWith(
|
||||
"[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range",
|
||||
anyObject(),
|
||||
);
|
||||
|
||||
logger.error = error;
|
||||
});
|
||||
|
||||
it("throws an error if getId is invalid or returns not a string", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(() => hotbarStore.addToHotbar({} as any)).toThrowError(
|
||||
TypeError,
|
||||
);
|
||||
expect(() =>
|
||||
hotbarStore.addToHotbar({ getId: () => true } as any),
|
||||
).toThrowError(TypeError);
|
||||
});
|
||||
|
||||
it("throws an error if getName is invalid or returns not a string", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(() =>
|
||||
hotbarStore.addToHotbar({ getId: () => "" } as any),
|
||||
).toThrowError(TypeError);
|
||||
expect(() =>
|
||||
hotbarStore.addToHotbar({ getId: () => "", getName: () => 4 } as any),
|
||||
).toThrowError(TypeError);
|
||||
});
|
||||
|
||||
it("does nothing when item moved to same cell", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.restackItems(1, 1);
|
||||
|
||||
expect(hotbarStore.getActive().items[1].entity.uid).toEqual("test");
|
||||
});
|
||||
|
||||
it("new items takes first empty cell", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
hotbarStore.restackItems(0, 3);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
|
||||
expect(hotbarStore.getActive().items[0].entity.uid).toEqual("minikube");
|
||||
});
|
||||
|
||||
it("throws if invalid arguments provided", () => {
|
||||
// Prevent writing to stderr during this render.
|
||||
const { error, warn } = console;
|
||||
|
||||
console.error = jest.fn();
|
||||
console.warn = jest.fn();
|
||||
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
|
||||
expect(() => hotbarStore.restackItems(-5, 0)).toThrow();
|
||||
expect(() => hotbarStore.restackItems(2, -1)).toThrow();
|
||||
expect(() => hotbarStore.restackItems(14, 1)).toThrow();
|
||||
expect(() => hotbarStore.restackItems(11, 112)).toThrow();
|
||||
|
||||
// Restore writing to stderr.
|
||||
console.error = error;
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
it("checks if entity already pinned to hotbar", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
|
||||
expect(hotbarStore.isAddedToActive(testCluster)).toBeTruthy();
|
||||
expect(hotbarStore.isAddedToActive(awsCluster)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("add", () => {
|
||||
it("adds a hotbar", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.add({ name: "hottest" });
|
||||
expect(hotbarStore.hotbars.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hotbar items", () => {
|
||||
it("initially creates 12 empty cells", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(hotbarStore.getActive().items.length).toEqual(12);
|
||||
});
|
||||
|
||||
it("initially adds catalog entity as first item", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(hotbarStore.getActive().items[0].entity.name).toEqual("Catalog");
|
||||
});
|
||||
|
||||
it("adds items", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||
|
||||
expect(items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("removes items", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.removeFromHotbar("test");
|
||||
hotbarStore.removeFromHotbar("catalog-entity");
|
||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||
|
||||
expect(items).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("does nothing if removing with invalid uid", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.removeFromHotbar("invalid uid");
|
||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||
|
||||
expect(items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("moves item to empty cell", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
|
||||
expect(hotbarStore.getActive().items[6]).toBeNull();
|
||||
|
||||
hotbarStore.restackItems(1, 5);
|
||||
|
||||
expect(hotbarStore.getActive().items[5]).toBeTruthy();
|
||||
expect(hotbarStore.getActive().items[5].entity.uid).toEqual("test");
|
||||
});
|
||||
|
||||
it("moves items down", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
|
||||
// aws -> catalog
|
||||
hotbarStore.restackItems(3, 0);
|
||||
|
||||
const items = hotbarStore.getActive().items.map(item => item?.entity.uid || null);
|
||||
|
||||
expect(items.slice(0, 4)).toEqual(["aws", "catalog-entity", "test", "minikube"]);
|
||||
});
|
||||
|
||||
it("moves items up", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
|
||||
// test -> aws
|
||||
hotbarStore.restackItems(1, 3);
|
||||
|
||||
const items = hotbarStore.getActive().items.map(item => item?.entity.uid || null);
|
||||
|
||||
expect(items.slice(0, 4)).toEqual(["catalog-entity", "minikube", "aws", "test"]);
|
||||
});
|
||||
|
||||
it("logs an error if cellIndex is out of bounds", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.add({ name: "hottest", id: "hottest" });
|
||||
hotbarStore.setActiveHotbar("hottest");
|
||||
|
||||
const { error } = logger;
|
||||
const mocked = jest.fn();
|
||||
|
||||
logger.error = mocked;
|
||||
|
||||
hotbarStore.addToHotbar(testCluster, -1);
|
||||
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
|
||||
|
||||
hotbarStore.addToHotbar(testCluster, 12);
|
||||
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
|
||||
|
||||
hotbarStore.addToHotbar(testCluster, 13);
|
||||
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
|
||||
|
||||
logger.error = error;
|
||||
});
|
||||
|
||||
it("throws an error if getId is invalid or returns not a string", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(() => hotbarStore.addToHotbar({} as any)).toThrowError(TypeError);
|
||||
expect(() => hotbarStore.addToHotbar({ getId: () => true } as any)).toThrowError(TypeError);
|
||||
});
|
||||
|
||||
it("throws an error if getName is invalid or returns not a string", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
expect(() => hotbarStore.addToHotbar({ getId: () => "" } as any)).toThrowError(TypeError);
|
||||
expect(() => hotbarStore.addToHotbar({ getId: () => "", getName: () => 4 } as any)).toThrowError(TypeError);
|
||||
});
|
||||
|
||||
it("does nothing when item moved to same cell", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.restackItems(1, 1);
|
||||
|
||||
expect(hotbarStore.getActive().items[1].entity.uid).toEqual("test");
|
||||
});
|
||||
|
||||
it("new items takes first empty cell", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
hotbarStore.addToHotbar(awsCluster);
|
||||
hotbarStore.restackItems(0, 3);
|
||||
hotbarStore.addToHotbar(minikubeCluster);
|
||||
|
||||
expect(hotbarStore.getActive().items[0].entity.uid).toEqual("minikube");
|
||||
});
|
||||
|
||||
it("throws if invalid arguments provided", () => {
|
||||
// Prevent writing to stderr during this render.
|
||||
const { error, warn } = console;
|
||||
|
||||
console.error = jest.fn();
|
||||
console.warn = jest.fn();
|
||||
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
|
||||
expect(() => hotbarStore.restackItems(-5, 0)).toThrow();
|
||||
expect(() => hotbarStore.restackItems(2, -1)).toThrow();
|
||||
expect(() => hotbarStore.restackItems(14, 1)).toThrow();
|
||||
expect(() => hotbarStore.restackItems(11, 112)).toThrow();
|
||||
|
||||
// Restore writing to stderr.
|
||||
console.error = error;
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
it("checks if entity already pinned to hotbar", () => {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
|
||||
hotbarStore.addToHotbar(testCluster);
|
||||
|
||||
expect(hotbarStore.isAddedToActive(testCluster)).toBeTruthy();
|
||||
expect(hotbarStore.isAddedToActive(awsCluster)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("pre beta-5 migrations", () => {
|
||||
beforeEach(() => {
|
||||
const mockOpts = {
|
||||
"some-directory-for-user-data": {
|
||||
describe("given pre beta-5 configurations", () => {
|
||||
beforeEach(async () => {
|
||||
const configurationToBeMigrated = {
|
||||
"some-electron-app-path-for-user-data": {
|
||||
"lens-hotbar-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
version: "5.0.0-beta.3",
|
||||
},
|
||||
},
|
||||
"hotbars": [
|
||||
hotbars: [
|
||||
{
|
||||
"id": "3caac17f-aec2-4723-9694-ad204465d935",
|
||||
"name": "myhotbar",
|
||||
"items": [
|
||||
id: "3caac17f-aec2-4723-9694-ad204465d935",
|
||||
name: "myhotbar",
|
||||
items: [
|
||||
{
|
||||
"entity": {
|
||||
"uid": "1dfa26e2ebab15780a3547e9c7fa785c",
|
||||
entity: {
|
||||
uid: "1dfa26e2ebab15780a3547e9c7fa785c",
|
||||
},
|
||||
},
|
||||
{
|
||||
"entity": {
|
||||
"uid": "55b42c3c7ba3b04193416cda405269a5",
|
||||
entity: {
|
||||
uid: "55b42c3c7ba3b04193416cda405269a5",
|
||||
},
|
||||
},
|
||||
{
|
||||
"entity": {
|
||||
"uid": "176fd331968660832f62283219d7eb6e",
|
||||
entity: {
|
||||
uid: "176fd331968660832f62283219d7eb6e",
|
||||
},
|
||||
},
|
||||
{
|
||||
"entity": {
|
||||
"uid": "61c4fb45528840ebad1badc25da41d14",
|
||||
"name": "user1-context",
|
||||
"source": "local",
|
||||
entity: {
|
||||
uid: "61c4fb45528840ebad1badc25da41d14",
|
||||
name: "user1-context",
|
||||
source: "local",
|
||||
},
|
||||
},
|
||||
{
|
||||
"entity": {
|
||||
"uid": "27d6f99fe9e7548a6e306760bfe19969",
|
||||
"name": "foo2",
|
||||
"source": "local",
|
||||
entity: {
|
||||
uid: "27d6f99fe9e7548a6e306760bfe19969",
|
||||
name: "foo2",
|
||||
source: "local",
|
||||
},
|
||||
},
|
||||
null,
|
||||
{
|
||||
"entity": {
|
||||
"uid": "c0b20040646849bb4dcf773e43a0bf27",
|
||||
"name": "multinode-demo",
|
||||
"source": "local",
|
||||
entity: {
|
||||
uid: "c0b20040646849bb4dcf773e43a0bf27",
|
||||
name: "multinode-demo",
|
||||
source: "local",
|
||||
},
|
||||
},
|
||||
null,
|
||||
@ -399,15 +440,15 @@ describe("HotbarStore", () => {
|
||||
},
|
||||
};
|
||||
|
||||
mockFs(mockOpts);
|
||||
});
|
||||
mockFs(configurationToBeMigrated);
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
await di.runSetups();
|
||||
});
|
||||
|
||||
it("allows to retrieve a hotbar", () => {
|
||||
const hotbar = HotbarStore.getInstance().getById("3caac17f-aec2-4723-9694-ad204465d935");
|
||||
const hotbar = HotbarStore.getInstance().getById(
|
||||
"3caac17f-aec2-4723-9694-ad204465d935",
|
||||
);
|
||||
|
||||
expect(hotbar.id).toBe("3caac17f-aec2-4723-9694-ad204465d935");
|
||||
});
|
||||
|
||||
@ -2,16 +2,379 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { HotbarStore } from "./hotbar-store";
|
||||
import catalogCatalogEntityInjectable from "./catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
|
||||
import { action, comparer, observable, makeObservable, computed } from "mobx";
|
||||
import { BaseStore } from "./base-store";
|
||||
import migrations from "../migrations/hotbar-store";
|
||||
import { toJS } from "./utils";
|
||||
import { CatalogEntity } from "./catalog";
|
||||
import logger from "../main/logger";
|
||||
import { broadcastMessage } from "./ipc";
|
||||
import {
|
||||
defaultHotbarCells,
|
||||
getEmptyHotbar,
|
||||
Hotbar,
|
||||
CreateHotbarData,
|
||||
CreateHotbarOptions,
|
||||
} from "./hotbar-types";
|
||||
import { hotbarTooManyItemsChannel } from "./ipc/hotbar";
|
||||
import type { GeneralEntity } from "./catalog-entities";
|
||||
|
||||
export interface HotbarStoreModel {
|
||||
hotbars: Hotbar[];
|
||||
activeHotbarId: string;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
catalogCatalogEntity: GeneralEntity;
|
||||
}
|
||||
|
||||
export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
||||
readonly displayName = "HotbarStore";
|
||||
@observable hotbars: Hotbar[] = [];
|
||||
@observable private _activeHotbarId: string;
|
||||
|
||||
constructor(private dependencies: Dependencies) {
|
||||
super({
|
||||
configName: "lens-hotbar-store",
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
syncOptions: {
|
||||
equals: comparer.structural,
|
||||
},
|
||||
migrations,
|
||||
});
|
||||
makeObservable(this);
|
||||
this.load();
|
||||
}
|
||||
|
||||
@computed get activeHotbarId() {
|
||||
return this._activeHotbarId;
|
||||
}
|
||||
|
||||
/**
|
||||
* If `hotbar` points to a known hotbar, make it active. Otherwise, ignore
|
||||
* @param hotbar The hotbar instance, or the index, or its ID
|
||||
*/
|
||||
setActiveHotbar(hotbar: Hotbar | number | string) {
|
||||
if (typeof hotbar === "number") {
|
||||
if (hotbar >= 0 && hotbar < this.hotbars.length) {
|
||||
this._activeHotbarId = this.hotbars[hotbar].id;
|
||||
}
|
||||
} else if (typeof hotbar === "string") {
|
||||
if (this.getById(hotbar)) {
|
||||
this._activeHotbarId = hotbar;
|
||||
}
|
||||
} else {
|
||||
if (this.hotbars.indexOf(hotbar) >= 0) {
|
||||
this._activeHotbarId = hotbar.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private hotbarIndexById(id: string) {
|
||||
return this.hotbars.findIndex((hotbar) => hotbar.id === id);
|
||||
}
|
||||
|
||||
private hotbarIndex(hotbar: Hotbar) {
|
||||
return this.hotbars.indexOf(hotbar);
|
||||
}
|
||||
|
||||
@computed get activeHotbarIndex() {
|
||||
return this.hotbarIndexById(this.activeHotbarId);
|
||||
}
|
||||
|
||||
@action
|
||||
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
|
||||
if (!data.hotbars || !data.hotbars.length) {
|
||||
const hotbar = getEmptyHotbar("Default");
|
||||
const {
|
||||
metadata: { uid, name, source },
|
||||
} = this.dependencies.catalogCatalogEntity;
|
||||
const initialItem = { entity: { uid, name, source }};
|
||||
|
||||
hotbar.items[0] = initialItem;
|
||||
|
||||
this.hotbars = [hotbar];
|
||||
} else {
|
||||
this.hotbars = data.hotbars;
|
||||
}
|
||||
|
||||
this.hotbars.forEach(ensureExactHotbarItemLength);
|
||||
|
||||
if (data.activeHotbarId) {
|
||||
this.setActiveHotbar(data.activeHotbarId);
|
||||
}
|
||||
|
||||
if (!this.activeHotbarId) {
|
||||
this.setActiveHotbar(0);
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(): HotbarStoreModel {
|
||||
const model: HotbarStoreModel = {
|
||||
hotbars: this.hotbars,
|
||||
activeHotbarId: this.activeHotbarId,
|
||||
};
|
||||
|
||||
return toJS(model);
|
||||
}
|
||||
|
||||
getActive() {
|
||||
return this.getById(this.activeHotbarId);
|
||||
}
|
||||
|
||||
getByName(name: string) {
|
||||
return this.hotbars.find((hotbar) => hotbar.name === name);
|
||||
}
|
||||
|
||||
getById(id: string) {
|
||||
return this.hotbars.find((hotbar) => hotbar.id === id);
|
||||
}
|
||||
|
||||
add = action(
|
||||
(
|
||||
data: CreateHotbarData,
|
||||
{ setActive = false }: CreateHotbarOptions = {},
|
||||
) => {
|
||||
const hotbar = getEmptyHotbar(data.name, data.id);
|
||||
|
||||
this.hotbars.push(hotbar);
|
||||
|
||||
if (setActive) {
|
||||
this._activeHotbarId = hotbar.id;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
setHotbarName = action((id: string, name: string) => {
|
||||
const index = this.hotbars.findIndex((hotbar) => hotbar.id === id);
|
||||
|
||||
if (index < 0) {
|
||||
return void console.warn(
|
||||
`[HOTBAR-STORE]: cannot setHotbarName: unknown id`,
|
||||
{ id },
|
||||
);
|
||||
}
|
||||
|
||||
this.hotbars[index].name = name;
|
||||
});
|
||||
|
||||
remove = action((hotbar: Hotbar) => {
|
||||
if (this.hotbars.length <= 1) {
|
||||
throw new Error("Cannot remove the last hotbar");
|
||||
}
|
||||
|
||||
this.hotbars = this.hotbars.filter((h) => h !== hotbar);
|
||||
|
||||
if (this.activeHotbarId === hotbar.id) {
|
||||
this.setActiveHotbar(0);
|
||||
}
|
||||
});
|
||||
|
||||
@action
|
||||
addToHotbar(item: CatalogEntity, cellIndex?: number) {
|
||||
const hotbar = this.getActive();
|
||||
const uid = item.getId();
|
||||
const name = item.getName();
|
||||
|
||||
if (typeof uid !== "string") {
|
||||
throw new TypeError("CatalogEntity's ID must be a string");
|
||||
}
|
||||
|
||||
if (typeof name !== "string") {
|
||||
throw new TypeError("CatalogEntity's NAME must be a string");
|
||||
}
|
||||
|
||||
if (this.isAddedToActive(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entity = {
|
||||
uid,
|
||||
name,
|
||||
source: item.metadata.source,
|
||||
};
|
||||
const newItem = { entity };
|
||||
|
||||
if (cellIndex === undefined) {
|
||||
// Add item to empty cell
|
||||
const emptyCellIndex = hotbar.items.indexOf(null);
|
||||
|
||||
if (emptyCellIndex != -1) {
|
||||
hotbar.items[emptyCellIndex] = newItem;
|
||||
} else {
|
||||
broadcastMessage(hotbarTooManyItemsChannel);
|
||||
}
|
||||
} else if (0 <= cellIndex && cellIndex < hotbar.items.length) {
|
||||
hotbar.items[cellIndex] = newItem;
|
||||
} else {
|
||||
logger.error(
|
||||
`[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`,
|
||||
{ entityId: uid, hotbarId: hotbar.id, cellIndex },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
removeFromHotbar(uid: string): void {
|
||||
const hotbar = this.getActive();
|
||||
const index = hotbar.items.findIndex((item) => item?.entity.uid === uid);
|
||||
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
hotbar.items[index] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all hotbar items that reference the `uid`.
|
||||
* @param uid The `EntityId` that each hotbar item refers to
|
||||
* @returns A function that will (in an action) undo the removing of the hotbar items. This function will not complete if the hotbar has changed.
|
||||
*/
|
||||
@action
|
||||
removeAllHotbarItems(uid: string) {
|
||||
for (const hotbar of this.hotbars) {
|
||||
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
||||
|
||||
if (index >= 0) {
|
||||
hotbar.items[index] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findClosestEmptyIndex(from: number, direction = 1) {
|
||||
let index = from;
|
||||
|
||||
while (this.getActive().items[index] != null) {
|
||||
index += direction;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@action
|
||||
restackItems(from: number, to: number): void {
|
||||
const { items } = this.getActive();
|
||||
const source = items[from];
|
||||
const moveDown = from < to;
|
||||
|
||||
if (
|
||||
from < 0 ||
|
||||
to < 0 ||
|
||||
from >= items.length ||
|
||||
to >= items.length ||
|
||||
isNaN(from) ||
|
||||
isNaN(to)
|
||||
) {
|
||||
throw new Error("Invalid 'from' or 'to' arguments");
|
||||
}
|
||||
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
items.splice(from, 1, null);
|
||||
|
||||
if (items[to] == null) {
|
||||
items.splice(to, 1, source);
|
||||
} else {
|
||||
// Move cells up or down to closes empty cell
|
||||
items.splice(this.findClosestEmptyIndex(to, moveDown ? -1 : 1), 1);
|
||||
items.splice(to, 0, source);
|
||||
}
|
||||
}
|
||||
|
||||
switchToPrevious() {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
let index = hotbarStore.activeHotbarIndex - 1;
|
||||
|
||||
if (index < 0) {
|
||||
index = hotbarStore.hotbars.length - 1;
|
||||
}
|
||||
|
||||
hotbarStore.setActiveHotbar(index);
|
||||
}
|
||||
|
||||
switchToNext() {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
let index = hotbarStore.activeHotbarIndex + 1;
|
||||
|
||||
if (index >= hotbarStore.hotbars.length) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
hotbarStore.setActiveHotbar(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if entity already pinned to the active hotbar
|
||||
*/
|
||||
isAddedToActive(entity: CatalogEntity | null | undefined): boolean {
|
||||
if (!entity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
this.getActive().items.findIndex(
|
||||
(item) => item?.entity.uid === entity.getId(),
|
||||
) >= 0
|
||||
);
|
||||
}
|
||||
|
||||
getDisplayLabel(hotbar: Hotbar): string {
|
||||
return `${this.getDisplayIndex(hotbar)}: ${hotbar.name}`;
|
||||
}
|
||||
|
||||
getDisplayIndex(hotbar: Hotbar): string {
|
||||
const index = this.hotbarIndex(hotbar);
|
||||
|
||||
if (index < 0) {
|
||||
return "??";
|
||||
}
|
||||
|
||||
return `${index + 1}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function ensures that there are always exactly `defaultHotbarCells`
|
||||
* worth of items in the hotbar.
|
||||
* @param hotbar The hotbar to modify
|
||||
*/
|
||||
function ensureExactHotbarItemLength(hotbar: Hotbar) {
|
||||
// if there are not enough items
|
||||
while (hotbar.items.length < defaultHotbarCells) {
|
||||
hotbar.items.push(null);
|
||||
}
|
||||
|
||||
// if for some reason the hotbar was overfilled before, remove as many entries
|
||||
// as needed, but prefer empty slots and items at the end first.
|
||||
while (hotbar.items.length > defaultHotbarCells) {
|
||||
const lastNull = hotbar.items.lastIndexOf(null);
|
||||
|
||||
if (lastNull >= 0) {
|
||||
hotbar.items.splice(lastNull, 1);
|
||||
} else {
|
||||
hotbar.items.length = defaultHotbarCells;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hotbarStoreInjectable = getInjectable({
|
||||
id: "hotbar-store",
|
||||
|
||||
instantiate: (di) => HotbarStore.createInstance({
|
||||
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
|
||||
}),
|
||||
instantiate: (di) => {
|
||||
HotbarStore.resetInstance();
|
||||
|
||||
const instance = HotbarStore.createInstance({
|
||||
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
|
||||
});
|
||||
|
||||
return instance;
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
@ -3,330 +3,10 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { action, comparer, observable, makeObservable, computed } from "mobx";
|
||||
import { BaseStore } from "./base-store";
|
||||
import migrations from "../migrations/hotbar-store";
|
||||
import { toJS } from "./utils";
|
||||
import { CatalogEntity } from "./catalog";
|
||||
import logger from "../main/logger";
|
||||
import { broadcastMessage } from "./ipc";
|
||||
import { defaultHotbarCells, getEmptyHotbar, Hotbar, CreateHotbarData, CreateHotbarOptions } from "./hotbar-types";
|
||||
import { hotbarTooManyItemsChannel } from "./ipc/hotbar";
|
||||
import type { GeneralEntity } from "./catalog-entities";
|
||||
import hotbarStoreInjectable from "./hotbar-store.injectable";
|
||||
|
||||
export interface HotbarStoreModel {
|
||||
hotbars: Hotbar[];
|
||||
activeHotbarId: string;
|
||||
}
|
||||
import {
|
||||
asLegacyGlobalSingletonForExtensionApi,
|
||||
} from "../extensions/as-legacy-globals-for-extension-api/as-legacy-global-singleton-object-for-extension-api";
|
||||
|
||||
interface Dependencies {
|
||||
catalogCatalogEntity: GeneralEntity;
|
||||
}
|
||||
|
||||
export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
||||
readonly displayName = "HotbarStore";
|
||||
@observable hotbars: Hotbar[] = [];
|
||||
@observable private _activeHotbarId: string;
|
||||
|
||||
constructor(private dependencies: Dependencies) {
|
||||
super({
|
||||
configName: "lens-hotbar-store",
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
syncOptions: {
|
||||
equals: comparer.structural,
|
||||
},
|
||||
migrations,
|
||||
});
|
||||
makeObservable(this);
|
||||
this.load();
|
||||
}
|
||||
|
||||
@computed get activeHotbarId() {
|
||||
return this._activeHotbarId;
|
||||
}
|
||||
|
||||
/**
|
||||
* If `hotbar` points to a known hotbar, make it active. Otherwise, ignore
|
||||
* @param hotbar The hotbar instance, or the index, or its ID
|
||||
*/
|
||||
setActiveHotbar(hotbar: Hotbar | number | string) {
|
||||
if (typeof hotbar === "number") {
|
||||
if (hotbar >= 0 && hotbar < this.hotbars.length) {
|
||||
this._activeHotbarId = this.hotbars[hotbar].id;
|
||||
}
|
||||
} else if (typeof hotbar === "string") {
|
||||
if (this.getById(hotbar)) {
|
||||
this._activeHotbarId = hotbar;
|
||||
}
|
||||
} else {
|
||||
if (this.hotbars.indexOf(hotbar) >= 0) {
|
||||
this._activeHotbarId = hotbar.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private hotbarIndexById(id: string) {
|
||||
return this.hotbars.findIndex((hotbar) => hotbar.id === id);
|
||||
}
|
||||
|
||||
private hotbarIndex(hotbar: Hotbar) {
|
||||
return this.hotbars.indexOf(hotbar);
|
||||
}
|
||||
|
||||
@computed get activeHotbarIndex() {
|
||||
return this.hotbarIndexById(this.activeHotbarId);
|
||||
}
|
||||
|
||||
@action
|
||||
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
|
||||
if (!data.hotbars || !data.hotbars.length) {
|
||||
const hotbar = getEmptyHotbar("Default");
|
||||
const { metadata: { uid, name, source }} = this.dependencies.catalogCatalogEntity;
|
||||
const initialItem = { entity: { uid, name, source }};
|
||||
|
||||
hotbar.items[0] = initialItem;
|
||||
|
||||
this.hotbars = [hotbar];
|
||||
} else {
|
||||
this.hotbars = data.hotbars;
|
||||
}
|
||||
|
||||
this.hotbars.forEach(ensureExactHotbarItemLength);
|
||||
|
||||
if (data.activeHotbarId) {
|
||||
this.setActiveHotbar(data.activeHotbarId);
|
||||
}
|
||||
|
||||
if (!this.activeHotbarId) {
|
||||
this.setActiveHotbar(0);
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(): HotbarStoreModel {
|
||||
const model: HotbarStoreModel = {
|
||||
hotbars: this.hotbars,
|
||||
activeHotbarId: this.activeHotbarId,
|
||||
};
|
||||
|
||||
return toJS(model);
|
||||
}
|
||||
|
||||
getActive() {
|
||||
return this.getById(this.activeHotbarId);
|
||||
}
|
||||
|
||||
getByName(name: string) {
|
||||
return this.hotbars.find((hotbar) => hotbar.name === name);
|
||||
}
|
||||
|
||||
getById(id: string) {
|
||||
return this.hotbars.find((hotbar) => hotbar.id === id);
|
||||
}
|
||||
|
||||
add = action((data: CreateHotbarData, { setActive = false }: CreateHotbarOptions = {}) => {
|
||||
const hotbar = getEmptyHotbar(data.name, data.id);
|
||||
|
||||
this.hotbars.push(hotbar);
|
||||
|
||||
if (setActive) {
|
||||
this._activeHotbarId = hotbar.id;
|
||||
}
|
||||
});
|
||||
|
||||
setHotbarName = action((id: string, name: string) => {
|
||||
const index = this.hotbars.findIndex((hotbar) => hotbar.id === id);
|
||||
|
||||
if (index < 0) {
|
||||
return void console.warn(`[HOTBAR-STORE]: cannot setHotbarName: unknown id`, { id });
|
||||
}
|
||||
|
||||
this.hotbars[index].name = name;
|
||||
});
|
||||
|
||||
remove = action((hotbar: Hotbar) => {
|
||||
if (this.hotbars.length <= 1) {
|
||||
throw new Error("Cannot remove the last hotbar");
|
||||
}
|
||||
|
||||
this.hotbars = this.hotbars.filter((h) => h !== hotbar);
|
||||
|
||||
if (this.activeHotbarId === hotbar.id) {
|
||||
this.setActiveHotbar(0);
|
||||
}
|
||||
});
|
||||
|
||||
@action
|
||||
addToHotbar(item: CatalogEntity, cellIndex?: number) {
|
||||
const hotbar = this.getActive();
|
||||
const uid = item.getId();
|
||||
const name = item.getName();
|
||||
|
||||
if (typeof uid !== "string") {
|
||||
throw new TypeError("CatalogEntity's ID must be a string");
|
||||
}
|
||||
|
||||
if (typeof name !== "string") {
|
||||
throw new TypeError("CatalogEntity's NAME must be a string");
|
||||
}
|
||||
|
||||
if (this.isAddedToActive(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entity = {
|
||||
uid,
|
||||
name,
|
||||
source: item.metadata.source,
|
||||
};
|
||||
const newItem = { entity };
|
||||
|
||||
if (cellIndex === undefined) {
|
||||
// Add item to empty cell
|
||||
const emptyCellIndex = hotbar.items.indexOf(null);
|
||||
|
||||
if (emptyCellIndex != -1) {
|
||||
hotbar.items[emptyCellIndex] = newItem;
|
||||
} else {
|
||||
broadcastMessage(hotbarTooManyItemsChannel);
|
||||
}
|
||||
} else if (0 <= cellIndex && cellIndex < hotbar.items.length) {
|
||||
hotbar.items[cellIndex] = newItem;
|
||||
} else {
|
||||
logger.error(`[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`, { entityId: uid, hotbarId: hotbar.id, cellIndex });
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
removeFromHotbar(uid: string): void {
|
||||
const hotbar = this.getActive();
|
||||
const index = hotbar.items.findIndex(item => item?.entity.uid === uid);
|
||||
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
hotbar.items[index] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all hotbar items that reference the `uid`.
|
||||
* @param uid The `EntityId` that each hotbar item refers to
|
||||
* @returns A function that will (in an action) undo the removing of the hotbar items. This function will not complete if the hotbar has changed.
|
||||
*/
|
||||
@action
|
||||
removeAllHotbarItems(uid: string) {
|
||||
for (const hotbar of this.hotbars) {
|
||||
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
||||
|
||||
if (index >= 0) {
|
||||
hotbar.items[index] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findClosestEmptyIndex(from: number, direction = 1) {
|
||||
let index = from;
|
||||
|
||||
while(this.getActive().items[index] != null) {
|
||||
index += direction;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@action
|
||||
restackItems(from: number, to: number): void {
|
||||
const { items } = this.getActive();
|
||||
const source = items[from];
|
||||
const moveDown = from < to;
|
||||
|
||||
if (from < 0 || to < 0 || from >= items.length || to >= items.length || isNaN(from) || isNaN(to)) {
|
||||
throw new Error("Invalid 'from' or 'to' arguments");
|
||||
}
|
||||
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
items.splice(from, 1, null);
|
||||
|
||||
if (items[to] == null) {
|
||||
items.splice(to, 1, source);
|
||||
} else {
|
||||
// Move cells up or down to closes empty cell
|
||||
items.splice(this.findClosestEmptyIndex(to, moveDown ? -1 : 1), 1);
|
||||
items.splice(to, 0, source);
|
||||
}
|
||||
}
|
||||
|
||||
switchToPrevious() {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
let index = hotbarStore.activeHotbarIndex - 1;
|
||||
|
||||
if (index < 0) {
|
||||
index = hotbarStore.hotbars.length - 1;
|
||||
}
|
||||
|
||||
hotbarStore.setActiveHotbar(index);
|
||||
}
|
||||
|
||||
switchToNext() {
|
||||
const hotbarStore = HotbarStore.getInstance();
|
||||
let index = hotbarStore.activeHotbarIndex + 1;
|
||||
|
||||
if (index >= hotbarStore.hotbars.length) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
hotbarStore.setActiveHotbar(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if entity already pinned to the active hotbar
|
||||
*/
|
||||
isAddedToActive(entity: CatalogEntity | null | undefined): boolean {
|
||||
if (!entity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getActive().items.findIndex(item => item?.entity.uid === entity.getId()) >= 0;
|
||||
}
|
||||
|
||||
getDisplayLabel(hotbar: Hotbar): string {
|
||||
return `${this.getDisplayIndex(hotbar)}: ${hotbar.name}`;
|
||||
}
|
||||
|
||||
getDisplayIndex(hotbar: Hotbar): string {
|
||||
const index = this.hotbarIndex(hotbar);
|
||||
|
||||
if (index < 0) {
|
||||
return "??";
|
||||
}
|
||||
|
||||
return `${index + 1}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function ensures that there are always exactly `defaultHotbarCells`
|
||||
* worth of items in the hotbar.
|
||||
* @param hotbar The hotbar to modify
|
||||
*/
|
||||
function ensureExactHotbarItemLength(hotbar: Hotbar) {
|
||||
// if there are not enough items
|
||||
while (hotbar.items.length < defaultHotbarCells) {
|
||||
hotbar.items.push(null);
|
||||
}
|
||||
|
||||
// if for some reason the hotbar was overfilled before, remove as many entries
|
||||
// as needed, but prefer empty slots and items at the end first.
|
||||
while (hotbar.items.length > defaultHotbarCells) {
|
||||
const lastNull = hotbar.items.lastIndexOf(null);
|
||||
|
||||
if (lastNull >= 0) {
|
||||
hotbar.items.splice(lastNull, 1);
|
||||
} else {
|
||||
hotbar.items.length = defaultHotbarCells;
|
||||
}
|
||||
}
|
||||
}
|
||||
export const HotbarStore = asLegacyGlobalSingletonForExtensionApi(hotbarStoreInjectable);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user