Support non-ascii characters in entity names (#2610)

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2021-04-26 08:58:51 +03:00
1 parent 339502cf4f
commit bcdc0243f4
5 files changed
+60 -22

No files matched your search

+3
View File
@@ -19,3 +19,6 @@ export * from "./downloadFile";
export * from "./escapeRegExp";
export * from "./tar";
export * from "./type-narrowing";
import * as iter from "./iter";
export { iter };
+25
View File
@@ -0,0 +1,25 @@
/**
* Create a new type safe empty Iterable
* @returns An `Iterable` that yields 0 items
*/
export function* newEmpty<T>(): Iterable<T> {
return;
}
/**
* Creates a new `Iterable` that yields at most n items from src.
* Does not modify `src` which can be used later.
* @param src An initial iterator
* @param n The maximum number of elements to take from src. Yields up to the floor of `n` and 0 items if n < 0
*/
export function* take<T>(src: Iterable<T>, n: number): Iterable<T> {
outer: for (let i = 0; i < n; i += 1) {
for (const item of src) {
yield item;
continue outer;
}
// if we are here that means that `src` has been exhausted. Don't bother trying again.
break outer;
}
}
+30 -21
View File
@@ -2,18 +2,19 @@ import "./hotbar-icon.scss";
import React, { DOMAttributes } from "react";
import { observer } from "mobx-react";
import { cssNames, IClassName } from "../../utils";
import { cssNames, IClassName, iter } from "../../utils";
import { Tooltip } from "../tooltip";
import { Avatar } from "@material-ui/core";
import { CatalogEntity, CatalogEntityContextMenu, CatalogEntityContextMenuContext } from "../../../common/catalog";
import { Menu, MenuItem } from "../menu";
import { Icon } from "../icon";
import { observable } from "mobx";
import { computed, observable } from "mobx";
import { navigate } from "../../navigation";
import { HotbarStore } from "../../../common/hotbar-store";
import { ConfirmDialog } from "../confirm-dialog";
import randomColor from "randomcolor";
import { catalogCategoryRegistry } from "../../api/catalog-category-registry";
import GraphemeSplitter from "grapheme-splitter";
interface Props extends DOMAttributes<HTMLElement> {
entity: CatalogEntity;
@@ -23,6 +24,22 @@ interface Props extends DOMAttributes<HTMLElement> {
isActive?: boolean;
}
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(/@+/);
}
@observer
export class HotbarIcon extends React.Component<Props> {
@observable.deep private contextMenu: CatalogEntityContextMenuContext;
@@ -35,26 +52,18 @@ export class HotbarIcon extends React.Component<Props> {
};
}
get iconString() {
let splittedName = this.props.entity.metadata.name.split(" ");
@computed get iconString() {
const [rawFirst, rawSecond, rawThird] = getNameParts(this.props.entity.metadata.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();
if (splittedName.length === 1) {
splittedName = splittedName[0].split("-");
}
if (splittedName.length === 1) {
splittedName = splittedName[0].split("@");
}
splittedName = splittedName.map((part) => part.replace(/\W/g, ""));
if (splittedName.length === 1) {
return splittedName[0].substring(0, 2);
} else if (splittedName.length === 2) {
return splittedName[0].substring(0, 1) + splittedName[1].substring(0, 1);
} else {
return splittedName[0].substring(0, 1) + splittedName[1].substring(0, 1) + splittedName[2].substring(0, 1);
}
return [
...iter.take(first, 1),
...iter.take(second, 1),
...iter.take(third, 1),
].filter(Boolean).join("");
}
get badgeIcon() {