mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Move HotbarStore to new format
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
4caf77aec6
commit
acefc037c1
@ -35,7 +35,7 @@ export interface BaseStoreParams<T> extends Omit<ConfOptions<T>, "migrations"> {
|
|||||||
*
|
*
|
||||||
* @param data the parsed information read from the stored JSON file
|
* @param data the parsed information read from the stored JSON file
|
||||||
*/
|
*/
|
||||||
fromStore(data: T): void;
|
fromStore(data: Partial<T>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* toJSON is called when syncing the store to the filesystem. It should
|
* toJSON is called when syncing the store to the filesystem. It should
|
||||||
|
|||||||
83
packages/core/src/common/catalog/helpers.ts
Normal file
83
packages/core/src/common/catalog/helpers.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { CatalogEntity } from "./catalog-entity";
|
||||||
|
import GraphemeSplitter from "grapheme-splitter";
|
||||||
|
import { hasOwnProperty, hasTypedProperty, isObject, isString, iter } from "@k8slens/utilities";
|
||||||
|
|
||||||
|
function getNameParts(name: string): string[] {
|
||||||
|
const byWhitespace = name.split(/\s+/);
|
||||||
|
|
||||||
|
if (byWhitespace.length > 1) {
|
||||||
|
return byWhitespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byDashes = name.split(/[-_]+/);
|
||||||
|
|
||||||
|
if (byDashes.length > 1) {
|
||||||
|
return byDashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name.split(/@+/);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function limitGraphemeLengthOf(src: string, count: number): string {
|
||||||
|
const splitter = new GraphemeSplitter();
|
||||||
|
|
||||||
|
return iter
|
||||||
|
.chain(splitter.iterateGraphemes(src))
|
||||||
|
.take(count)
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function computeDefaultShortName(name: string) {
|
||||||
|
if (!name || typeof name !== "string") {
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
|
||||||
|
const [rawFirst, rawSecond, rawThird] = getNameParts(name);
|
||||||
|
const splitter = new GraphemeSplitter();
|
||||||
|
const first = splitter.iterateGraphemes(rawFirst);
|
||||||
|
const second = rawSecond ? splitter.iterateGraphemes(rawSecond): first;
|
||||||
|
const third = rawThird ? splitter.iterateGraphemes(rawThird) : iter.newEmpty<string>();
|
||||||
|
|
||||||
|
return iter.chain(iter.take(first, 1))
|
||||||
|
.concat(iter.take(second, 1))
|
||||||
|
.concat(iter.take(third, 1))
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getShortName(entity: CatalogEntity): string {
|
||||||
|
return entity.metadata.shortName || computeDefaultShortName(entity.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIconColourHash(entity: CatalogEntity): string {
|
||||||
|
return `${entity.metadata.name}-${entity.metadata.source}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIconBackground(entity: CatalogEntity): string | undefined {
|
||||||
|
if (isObject(entity.spec.icon)) {
|
||||||
|
if (hasTypedProperty(entity.spec.icon, "background", isString)) {
|
||||||
|
return entity.spec.icon.background;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasOwnProperty(entity.spec.icon, "src")
|
||||||
|
? "transparent"
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIconMaterial(entity: CatalogEntity): string | undefined {
|
||||||
|
if (
|
||||||
|
isObject(entity.spec.icon)
|
||||||
|
&& hasTypedProperty(entity.spec.icon, "material", isString)
|
||||||
|
) {
|
||||||
|
return entity.spec.icon.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
@ -6,16 +6,10 @@ import { getInjectable } from "@ogre-tools/injectable";
|
|||||||
import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
|
import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
|
||||||
import { HotbarStore } from "./store";
|
import { HotbarStore } from "./store";
|
||||||
import loggerInjectable from "../logger.injectable";
|
import loggerInjectable from "../logger.injectable";
|
||||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
|
||||||
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
|
||||||
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
|
|
||||||
import storeMigrationsInjectable from "../base-store/migrations.injectable";
|
import storeMigrationsInjectable from "../base-store/migrations.injectable";
|
||||||
import { hotbarStoreMigrationInjectionToken } from "./migrations-token";
|
import { hotbarStoreMigrationInjectionToken } from "./migrations-token";
|
||||||
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
|
import createBaseStoreInjectable from "../base-store/create-base-store.injectable";
|
||||||
import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel-prefix";
|
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
|
||||||
import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
|
|
||||||
import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
|
|
||||||
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync";
|
|
||||||
|
|
||||||
const hotbarStoreInjectable = getInjectable({
|
const hotbarStoreInjectable = getInjectable({
|
||||||
id: "hotbar-store",
|
id: "hotbar-store",
|
||||||
@ -23,15 +17,9 @@ const hotbarStoreInjectable = getInjectable({
|
|||||||
instantiate: (di) => new HotbarStore({
|
instantiate: (di) => new HotbarStore({
|
||||||
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
|
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
|
||||||
logger: di.inject(loggerInjectable),
|
logger: di.inject(loggerInjectable),
|
||||||
directoryForUserData: di.inject(directoryForUserDataInjectable),
|
|
||||||
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
|
|
||||||
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
|
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
|
||||||
migrations: di.inject(storeMigrationsInjectable, hotbarStoreMigrationInjectionToken),
|
migrations: di.inject(storeMigrationsInjectable, hotbarStoreMigrationInjectionToken),
|
||||||
getBasenameOfPath: di.inject(getBasenameOfPathInjectable),
|
createBaseStore: di.inject(createBaseStoreInjectable),
|
||||||
ipcChannelPrefixes: di.inject(baseStoreIpcChannelPrefixesInjectionToken),
|
|
||||||
persistStateToConfig: di.inject(persistStateToConfigInjectionToken),
|
|
||||||
enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken),
|
|
||||||
shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken),
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -3,10 +3,9 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { action, comparer, observable, makeObservable, computed } from "mobx";
|
import type { IObservableValue } from "mobx";
|
||||||
import type { BaseStoreDependencies } from "../base-store/base-store";
|
import { runInAction, action, comparer, observable } from "mobx";
|
||||||
import { BaseStore } from "../base-store/base-store";
|
import type { BaseStore } from "../base-store/base-store";
|
||||||
import { toJS } from "../utils";
|
|
||||||
import type { CatalogEntity } from "../catalog";
|
import type { CatalogEntity } from "../catalog";
|
||||||
import { broadcastMessage } from "../ipc";
|
import { broadcastMessage } from "../ipc";
|
||||||
import type { Hotbar, CreateHotbarData, CreateHotbarOptions } from "./types";
|
import type { Hotbar, CreateHotbarData, CreateHotbarOptions } from "./types";
|
||||||
@ -15,34 +14,89 @@ import { hotbarTooManyItemsChannel } from "../ipc/hotbar";
|
|||||||
import type { GeneralEntity } from "../catalog-entities";
|
import type { GeneralEntity } from "../catalog-entities";
|
||||||
import type { Logger } from "../logger";
|
import type { Logger } from "../logger";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
|
import { getShortName } from "../catalog/helpers";
|
||||||
|
import type { Migrations } from "conf/dist/source/types";
|
||||||
|
import type { CreateBaseStore } from "../base-store/create-base-store.injectable";
|
||||||
|
|
||||||
export interface HotbarStoreModel {
|
export interface HotbarStoreModel {
|
||||||
hotbars: Hotbar[];
|
hotbars: Hotbar[];
|
||||||
activeHotbarId: string;
|
activeHotbarId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Dependencies extends BaseStoreDependencies {
|
interface Dependencies {
|
||||||
readonly catalogCatalogEntity: GeneralEntity;
|
readonly catalogCatalogEntity: GeneralEntity;
|
||||||
readonly logger: Logger;
|
readonly logger: Logger;
|
||||||
|
readonly storeMigrationVersion: string;
|
||||||
|
readonly migrations: Migrations<Record<string, unknown>>;
|
||||||
|
createBaseStore: CreateBaseStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
export class HotbarStore {
|
||||||
@observable hotbars: Hotbar[] = [];
|
private readonly store: BaseStore<HotbarStoreModel>;
|
||||||
@observable private _activeHotbarId!: string;
|
|
||||||
|
readonly hotbars = observable.array<Hotbar>();
|
||||||
|
|
||||||
|
readonly activeHotbarId = observable.box() as IObservableValue<string>;
|
||||||
|
|
||||||
constructor(protected readonly dependencies: Dependencies) {
|
constructor(protected readonly dependencies: Dependencies) {
|
||||||
super(dependencies, {
|
this.store = this.dependencies.createBaseStore({
|
||||||
configName: "lens-hotbar-store",
|
configName: "lens-hotbar-store",
|
||||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||||
syncOptions: {
|
syncOptions: {
|
||||||
equals: comparer.structural,
|
equals: comparer.structural,
|
||||||
},
|
},
|
||||||
});
|
projectVersion: this.dependencies.storeMigrationVersion,
|
||||||
makeObservable(this);
|
migrations: this.dependencies.migrations,
|
||||||
|
fromStore: action((data) => {
|
||||||
|
if (!data.hotbars || !data.hotbars.length) {
|
||||||
|
const hotbar = getEmptyHotbar("Default");
|
||||||
|
const {
|
||||||
|
metadata: {
|
||||||
|
uid,
|
||||||
|
name,
|
||||||
|
source,
|
||||||
|
},
|
||||||
|
} = this.dependencies.catalogCatalogEntity;
|
||||||
|
|
||||||
|
hotbar.items[0] = {
|
||||||
|
entity: {
|
||||||
|
uid,
|
||||||
|
name,
|
||||||
|
source,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.hotbars.replace([hotbar]);
|
||||||
|
} else {
|
||||||
|
this.hotbars.replace(data.hotbars);
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get activeHotbarId() {
|
for (const hotbar of this.hotbars) {
|
||||||
return this._activeHotbarId;
|
ensureExactHotbarItemLength(hotbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.activeHotbarId) {
|
||||||
|
this.activeHotbarId.set(data.activeHotbarId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.activeHotbarId.get()) {
|
||||||
|
this.activeHotbarId.set(this.hotbars[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeHotbarExists = this.hotbars.findIndex(hotbar => hotbar.id === this.activeHotbarId.get()) >= 0;
|
||||||
|
|
||||||
|
if (!activeHotbarExists) {
|
||||||
|
this.activeHotbarId.set(this.hotbars[0].id);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
toJSON: () => ({
|
||||||
|
hotbars: this.hotbars.toJSON(),
|
||||||
|
activeHotbarId: this.activeHotbarId.get(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
this.store.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,69 +104,29 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
* @param hotbar The hotbar instance, or the index, or its ID
|
* @param hotbar The hotbar instance, or the index, or its ID
|
||||||
*/
|
*/
|
||||||
setActiveHotbar(hotbar: Hotbar | number | string) {
|
setActiveHotbar(hotbar: Hotbar | number | string) {
|
||||||
|
runInAction(() => {
|
||||||
if (typeof hotbar === "number") {
|
if (typeof hotbar === "number") {
|
||||||
if (hotbar >= 0 && hotbar < this.hotbars.length) {
|
if (hotbar >= 0 && hotbar < this.hotbars.length) {
|
||||||
this._activeHotbarId = this.hotbars[hotbar].id;
|
this.activeHotbarId.set(this.hotbars[hotbar].id);
|
||||||
}
|
}
|
||||||
} else if (typeof hotbar === "string") {
|
} else if (typeof hotbar === "string") {
|
||||||
if (this.findById(hotbar)) {
|
if (this.findById(hotbar)) {
|
||||||
this._activeHotbarId = hotbar;
|
this.activeHotbarId.set(hotbar);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.hotbars.indexOf(hotbar) >= 0) {
|
if (this.hotbars.indexOf(hotbar) >= 0) {
|
||||||
this._activeHotbarId = hotbar.id;
|
this.activeHotbarId.set(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._activeHotbarId = data.activeHotbarId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._activeHotbarId) {
|
|
||||||
this._activeHotbarId = this.hotbars[0].id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(): HotbarStoreModel {
|
|
||||||
return toJS({
|
|
||||||
hotbars: this.hotbars,
|
|
||||||
activeHotbarId: this.activeHotbarId,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getActiveHotbarIndex() {
|
||||||
|
return this.hotbars.findIndex((hotbar) => hotbar.id === this.activeHotbarId.get());
|
||||||
|
}
|
||||||
|
|
||||||
getActive(): Hotbar {
|
getActive(): Hotbar {
|
||||||
const hotbar = this.findById(this.activeHotbarId);
|
const hotbar = this.findById(this.activeHotbarId.get());
|
||||||
|
|
||||||
assert(hotbar, "There MUST always be an active hotbar");
|
assert(hotbar, "There MUST always be an active hotbar");
|
||||||
|
|
||||||
@ -127,19 +141,20 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
return this.hotbars.find((hotbar) => hotbar.id === id);
|
return this.hotbars.find((hotbar) => hotbar.id === id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
add(data: CreateHotbarData, { setActive = false }: CreateHotbarOptions = {}) {
|
add(data: CreateHotbarData, { setActive = false }: CreateHotbarOptions = {}) {
|
||||||
|
runInAction(() => {
|
||||||
const hotbar = getEmptyHotbar(data.name, data.id);
|
const hotbar = getEmptyHotbar(data.name, data.id);
|
||||||
|
|
||||||
this.hotbars.push(hotbar);
|
this.hotbars.push(hotbar);
|
||||||
|
|
||||||
if (setActive) {
|
if (setActive) {
|
||||||
this._activeHotbarId = hotbar.id;
|
this.activeHotbarId.set(hotbar.id);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
setHotbarName(id: string, name: string): void {
|
setHotbarName(id: string, name: string): void {
|
||||||
|
runInAction(() => {
|
||||||
const index = this.hotbars.findIndex((hotbar) => hotbar.id === id);
|
const index = this.hotbars.findIndex((hotbar) => hotbar.id === id);
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
@ -150,24 +165,28 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.hotbars[index].name = name;
|
this.hotbars[index].name = name;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
remove(hotbar: Hotbar) {
|
remove(hotbar: Hotbar) {
|
||||||
|
runInAction(() => {
|
||||||
assert(this.hotbars.length >= 2, "Cannot remove the last hotbar");
|
assert(this.hotbars.length >= 2, "Cannot remove the last hotbar");
|
||||||
|
|
||||||
this.hotbars = this.hotbars.filter((h) => h !== hotbar);
|
this.hotbars.replace(this.hotbars.filter((h) => h.id !== hotbar.id));
|
||||||
|
|
||||||
if (this.activeHotbarId === hotbar.id) {
|
if (this.activeHotbarId.get() === hotbar.id) {
|
||||||
this.setActiveHotbar(0);
|
this.activeHotbarId.set(this.hotbars[0].id);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
addToHotbar(item: CatalogEntity, cellIndex?: number) {
|
addToHotbar(item: CatalogEntity, cellIndex?: number) {
|
||||||
|
runInAction(() => {
|
||||||
|
|
||||||
const hotbar = this.getActive();
|
const hotbar = this.getActive();
|
||||||
const uid = item.getId();
|
const uid = item.getId();
|
||||||
const name = item.getName();
|
const name = item.getName();
|
||||||
|
const shortName = getShortName(item);
|
||||||
|
|
||||||
if (typeof uid !== "string") {
|
if (typeof uid !== "string") {
|
||||||
throw new TypeError("CatalogEntity's ID must be a string");
|
throw new TypeError("CatalogEntity's ID must be a string");
|
||||||
@ -177,6 +196,10 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
throw new TypeError("CatalogEntity's NAME must be a string");
|
throw new TypeError("CatalogEntity's NAME must be a string");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof shortName !== "string") {
|
||||||
|
throw new TypeError("CatalogEntity's SHORT_NAME must be a string");
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isAddedToActive(item)) {
|
if (this.isAddedToActive(item)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -185,6 +208,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
uid,
|
uid,
|
||||||
name,
|
name,
|
||||||
source: item.metadata.source,
|
source: item.metadata.source,
|
||||||
|
shortName,
|
||||||
};
|
};
|
||||||
const newItem = { entity };
|
const newItem = { entity };
|
||||||
|
|
||||||
@ -205,10 +229,11 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
{ entityId: uid, hotbarId: hotbar.id, cellIndex },
|
{ entityId: uid, hotbarId: hotbar.id, cellIndex },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
removeFromHotbar(uid: string): void {
|
removeFromHotbar(uid: string): void {
|
||||||
|
runInAction(() => {
|
||||||
const hotbar = this.getActive();
|
const hotbar = this.getActive();
|
||||||
const index = hotbar.items.findIndex((item) => item?.entity.uid === uid);
|
const index = hotbar.items.findIndex((item) => item?.entity.uid === uid);
|
||||||
|
|
||||||
@ -217,6 +242,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hotbar.items[index] = null;
|
hotbar.items[index] = null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,8 +250,8 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
* @param uid The `EntityId` that each hotbar item refers to
|
* @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.
|
* @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) {
|
removeAllHotbarItems(uid: string) {
|
||||||
|
runInAction(() => {
|
||||||
for (const hotbar of this.hotbars) {
|
for (const hotbar of this.hotbars) {
|
||||||
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
||||||
|
|
||||||
@ -233,9 +259,10 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
hotbar.items[index] = null;
|
hotbar.items[index] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
findClosestEmptyIndex(from: number, direction = 1) {
|
private findClosestEmptyIndex(from: number, direction = 1) {
|
||||||
let index = from;
|
let index = from;
|
||||||
const hotbar = this.getActive();
|
const hotbar = this.getActive();
|
||||||
|
|
||||||
@ -246,8 +273,8 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
restackItems(from: number, to: number): void {
|
restackItems(from: number, to: number): void {
|
||||||
|
runInAction(() => {
|
||||||
const { items } = this.getActive();
|
const { items } = this.getActive();
|
||||||
const source = items[from];
|
const source = items[from];
|
||||||
const moveDown = from < to;
|
const moveDown = from < to;
|
||||||
@ -276,26 +303,31 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
items.splice(this.findClosestEmptyIndex(to, moveDown ? -1 : 1), 1);
|
items.splice(this.findClosestEmptyIndex(to, moveDown ? -1 : 1), 1);
|
||||||
items.splice(to, 0, source);
|
items.splice(to, 0, source);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switchToPrevious() {
|
switchToPrevious() {
|
||||||
let index = this.activeHotbarIndex - 1;
|
runInAction(() => {
|
||||||
|
let index = this.getActiveHotbarIndex() - 1;
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = this.hotbars.length - 1;
|
index = this.hotbars.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setActiveHotbar(index);
|
this.setActiveHotbar(index);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switchToNext() {
|
switchToNext() {
|
||||||
let index = this.activeHotbarIndex + 1;
|
runInAction(() => {
|
||||||
|
let index = this.getActiveHotbarIndex() + 1;
|
||||||
|
|
||||||
if (index >= this.hotbars.length) {
|
if (index >= this.hotbars.length) {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setActiveHotbar(index);
|
this.setActiveHotbar(index);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -316,7 +348,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getDisplayIndex(hotbar: Hotbar): string {
|
getDisplayIndex(hotbar: Hotbar): string {
|
||||||
const index = this.hotbarIndex(hotbar);
|
const index = this.hotbars.indexOf(hotbar);
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return "??";
|
return "??";
|
||||||
|
|||||||
@ -8,9 +8,9 @@ import styles from "./avatar.module.scss";
|
|||||||
import type { ImgHTMLAttributes, MouseEventHandler } from "react";
|
import type { ImgHTMLAttributes, MouseEventHandler } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import randomColor from "randomcolor";
|
import randomColor from "randomcolor";
|
||||||
import GraphemeSplitter from "grapheme-splitter";
|
|
||||||
import type { SingleOrMany } from "@k8slens/utilities";
|
import type { SingleOrMany } from "@k8slens/utilities";
|
||||||
import { cssNames, isDefined, iter } from "@k8slens/utilities";
|
import { cssNames } from "@k8slens/utilities";
|
||||||
|
import { computeDefaultShortName } from "../../../common/catalog/helpers";
|
||||||
|
|
||||||
export interface AvatarProps {
|
export interface AvatarProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -28,40 +28,6 @@ export interface AvatarProps {
|
|||||||
"data-testid"?: string;
|
"data-testid"?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNameParts(name: string): string[] {
|
|
||||||
const byWhitespace = name.split(/\s+/);
|
|
||||||
|
|
||||||
if (byWhitespace.length > 1) {
|
|
||||||
return byWhitespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byDashes = name.split(/[-_]+/);
|
|
||||||
|
|
||||||
if (byDashes.length > 1) {
|
|
||||||
return byDashes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return name.split(/@+/);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLabelFromTitle(title: string) {
|
|
||||||
if (!title) {
|
|
||||||
return "??";
|
|
||||||
}
|
|
||||||
|
|
||||||
const [rawFirst, rawSecond, rawThird] = getNameParts(title);
|
|
||||||
const splitter = new GraphemeSplitter();
|
|
||||||
const first = splitter.iterateGraphemes(rawFirst);
|
|
||||||
const second = rawSecond ? splitter.iterateGraphemes(rawSecond): first;
|
|
||||||
const third = rawThird ? splitter.iterateGraphemes(rawThird) : iter.newEmpty();
|
|
||||||
|
|
||||||
return [
|
|
||||||
...iter.take(first, 1),
|
|
||||||
...iter.take(second, 1),
|
|
||||||
...iter.take(third, 1),
|
|
||||||
].filter(isDefined).join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Avatar = ({
|
export const Avatar = ({
|
||||||
title,
|
title,
|
||||||
variant = "rounded",
|
variant = "rounded",
|
||||||
@ -104,6 +70,6 @@ export const Avatar = ({
|
|||||||
alt={title}
|
alt={title}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
: children || getLabelFromTitle(title)}
|
: children || computeDefaultShortName(title)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -59,7 +59,7 @@ const NonInjectedHotbarSelector = observer(({ hotbar, hotbarStore, openCommandOv
|
|||||||
<div className={styles.HotbarSelector}>
|
<div className={styles.HotbarSelector}>
|
||||||
<Icon
|
<Icon
|
||||||
material="arrow_left"
|
material="arrow_left"
|
||||||
className={cssNames(styles.Icon, styles.previous)}
|
className={cssNames(styles.Icon)}
|
||||||
onClick={onPrevClick}/>
|
onClick={onPrevClick}/>
|
||||||
<div className={styles.HotbarIndex}>
|
<div className={styles.HotbarIndex}>
|
||||||
<Badge
|
<Badge
|
||||||
|
|||||||
@ -14,6 +14,7 @@ interface Iterator<T> extends Iterable<T> {
|
|||||||
flatMap<U>(fn: (val: T) => U[]): Iterator<U>;
|
flatMap<U>(fn: (val: T) => U[]): Iterator<U>;
|
||||||
concat(src2: IterableIterator<T>): Iterator<T>;
|
concat(src2: IterableIterator<T>): Iterator<T>;
|
||||||
join(sep?: string): string;
|
join(sep?: string): string;
|
||||||
|
take(count: number): Iterator<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function chain<T>(src: IterableIterator<T>): Iterator<T> {
|
function chain<T>(src: IterableIterator<T>): Iterator<T> {
|
||||||
@ -26,6 +27,7 @@ function chain<T>(src: IterableIterator<T>): Iterator<T> {
|
|||||||
join: (sep) => join(src, sep),
|
join: (sep) => join(src, sep),
|
||||||
collect: (fn) => fn(src),
|
collect: (fn) => fn(src),
|
||||||
concat: (src2) => chain(concat(src, src2)),
|
concat: (src2) => chain(concat(src, src2)),
|
||||||
|
take: (count) => chain(take(src, count)),
|
||||||
[Symbol.iterator]: () => src,
|
[Symbol.iterator]: () => src,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user