Skip to content

Commit

Permalink
refactor(ui): switch to vide sources for global ui state, remove charm
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxuum committed Nov 10, 2024
1 parent af227c0 commit 86684e2
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 144 deletions.
4 changes: 1 addition & 3 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@
"typescript": "5.5.3"
},
"dependencies": {
"@rbxts/charm": "^0.8.1",
"@rbxts/services": "^1.5.5",
"@rbxts/set-timeout": "^1.1.2",
"@rbxts/vide": "^0.5.0",
"@rbxts/vide-charm": "^0.1.1"
"@rbxts/vide": "^0.5.0"
},
"peerDependencies": {
"@rbxts/centurion": "workspace:^"
Expand Down
14 changes: 3 additions & 11 deletions packages/ui/src/app/centurion-app.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { CenturionClient } from "@rbxts/centurion";
import { UserInputService } from "@rbxts/services";
import Vide, { derive } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import { Suggestions, Terminal } from "../components";
import { Group } from "../components/ui/group";
import { Layer } from "../components/ui/layer";
import { useClient } from "../hooks/use-client";
import { useEvent } from "../hooks/use-event";
import { px, usePx } from "../hooks/use-px";
import {
interfaceOptions,
interfaceVisible,
mouseOverInterface,
} from "../store";
import { mouseOverInterface, options, visible } from "../store";

const MOUSE_INPUT_TYPES = new Set<Enum.UserInputType>([
Enum.UserInputType.MouseButton1,
Expand All @@ -24,20 +19,17 @@ export function CenturionApp(client: CenturionClient) {
useClient(client);
usePx();

const options = useAtom(interfaceOptions);
const visible = useAtom(interfaceVisible);

const validKeys = derive(() => new Set(options().activationKeys));

useEvent(UserInputService.InputBegan, (input, gameProcessed) => {
if (validKeys().has(input.KeyCode) && !gameProcessed) {
interfaceVisible(!visible());
visible(!visible());
} else if (
options().hideOnLostFocus &&
MOUSE_INPUT_TYPES.has(input.UserInputType) &&
!mouseOverInterface()
) {
interfaceVisible(false);
visible(false);
}
});

Expand Down
12 changes: 6 additions & 6 deletions packages/ui/src/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ContentProvider, Players } from "@rbxts/services";
import { mount } from "@rbxts/vide";
import { DEFAULT_INTERFACE_OPTIONS } from "../constants/options";
import { DefaultPalette } from "../palette";
import { interfaceOptions, interfaceVisible } from "../store";
import { options as uiOptions, visible as uiVisible } from "../store";
import { InterfaceOptions } from "../types";
import { CenturionApp } from "./centurion-app";

Expand All @@ -18,7 +18,7 @@ export namespace CenturionUI {
* @returns Whether the terminal UI is visible.
*/
export function isVisible() {
return interfaceVisible();
return uiVisible();
}

/**
Expand All @@ -27,7 +27,7 @@ export namespace CenturionUI {
* @param visible Whether the terminal UI should be visible.
*/
export function setVisible(visible: boolean) {
interfaceVisible(visible);
uiVisible(visible);
}

/**
Expand All @@ -36,11 +36,11 @@ export namespace CenturionUI {
* @param options The options to update.
*/
export function updateOptions(options: Partial<InterfaceOptions>) {
interfaceOptions((prev) => ({
uiOptions({
...DEFAULT_INTERFACE_OPTIONS,
...prev,
...uiOptions(),
...options,
}));
});
}

/**
Expand Down
5 changes: 1 addition & 4 deletions packages/ui/src/components/history/history-line.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { HistoryEntry } from "@rbxts/centurion";
import Vide, { Derivable, derive } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import { HISTORY_TEXT_SIZE } from "../../constants/text";
import { px } from "../../hooks/use-px";
import { interfaceOptions } from "../../store";
import { options } from "../../store";
import { Frame } from "../ui/frame";
import { Group } from "../ui/group";
import { Outline } from "../ui/outline";
Expand All @@ -18,8 +17,6 @@ interface HistoryLineProps {
}

export function HistoryLine({ data, size, position, order }: HistoryLineProps) {
const options = useAtom(interfaceOptions);

const date = derive(() => {
const dateTime = DateTime.fromUnixTimestamp(data.sentAt).FormatLocalTime(
"LT",
Expand Down
5 changes: 1 addition & 4 deletions packages/ui/src/components/history/history-list.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Vide, { Derivable, derive, For, read } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import { px } from "../../hooks/use-px";
import { interfaceOptions } from "../../store";
import { options } from "../../store";
import { HistoryData, HistoryLineData } from "../../types";
import { ScrollingFrame } from "../ui/scrolling-frame";
import { HistoryLine } from "./history-line";
Expand All @@ -20,8 +19,6 @@ export function HistoryList({
position,
maxHeight,
}: HistoryListProps) {
const options = useAtom(interfaceOptions);

const height = derive(() => read(data).height - px(8));
const exceedsMaxHeight = derive(
() => maxHeight !== undefined && height() > read(maxHeight),
Expand Down
5 changes: 1 addition & 4 deletions packages/ui/src/components/suggestions/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Vide, { Derivable, InstanceAttributes } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import { px } from "../../hooks/use-px";
import { interfaceOptions } from "../../store";
import { options } from "../../store";
import { Frame } from "../ui/frame";
import { Text } from "../ui/text";

Expand All @@ -20,8 +19,6 @@ interface BadgeProps {
}

export function Badge(props: BadgeProps) {
const options = useAtom(interfaceOptions);

return (
<Frame
backgroundColor={props.color}
Expand Down
5 changes: 1 addition & 4 deletions packages/ui/src/components/suggestions/main-suggestion.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import Vide, { Derivable, read, spring } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import {
SUGGESTION_TEXT_SIZE,
SUGGESTION_TITLE_TEXT_SIZE,
} from "../../constants/text";
import { px } from "../../hooks/use-px";
import { interfaceOptions, mouseOverInterface } from "../../store";
import { mouseOverInterface, options } from "../../store";
import { Suggestion } from "../../types";
import { Frame } from "../ui/frame";
import { Padding } from "../ui/padding";
Expand Down Expand Up @@ -34,8 +33,6 @@ export function MainSuggestion({
errorSize,
action,
}: MainSuggestionProps) {
const options = useAtom(interfaceOptions);

return (
<Frame
action={action}
Expand Down
4 changes: 1 addition & 3 deletions packages/ui/src/components/suggestions/suggestion-list.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { ArrayUtil } from "@rbxts/centurion/out/shared/util/data";
import Vide, { Derivable, derive, For, read } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import { SUGGESTION_TEXT_SIZE } from "../../constants/text";
import { px } from "../../hooks/use-px";
import { interfaceOptions, mouseOverInterface } from "../../store";
import { mouseOverInterface, options } from "../../store";
import { Suggestion } from "../../types";
import { Frame } from "../ui/frame";
import { Group } from "../ui/group";
Expand All @@ -24,7 +23,6 @@ export function SuggestionList({
currentText,
size,
}: SuggestionListProps) {
const options = useAtom(interfaceOptions);
const suggestions = derive(() => {
return ArrayUtil.slice(read(suggestion)?.others ?? [], 0, MAX_SUGGESTIONS);
});
Expand Down
36 changes: 14 additions & 22 deletions packages/ui/src/components/suggestions/suggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { TextService } from "@rbxts/services";
import Vide, { cleanup, derive, source, spring } from "@rbxts/vide";
import { useAtom } from "@rbxts/vide-charm";
import {
SUGGESTION_TEXT_SIZE,
SUGGESTION_TITLE_TEXT_SIZE,
} from "../../constants/text";
import { px } from "../../hooks/use-px";
import { useTextBounds } from "../../hooks/use-text-bounds";
import {
currentSuggestion,
currentTextPart,
interfaceOptions,
} from "../../store";
import { currentSuggestion, currentTextPart, options } from "../../store";
import { Group } from "../ui/group";
import { MainSuggestion } from "./main-suggestion";
import { SuggestionList } from "./suggestion-list";
Expand All @@ -20,9 +15,6 @@ const MAX_SUGGESTION_WIDTH = 180;
const PADDING = 8;

export function Suggestions() {
const options = useAtom(interfaceOptions);
const textPart = useAtom(currentTextPart);
const suggestion = useAtom(currentSuggestion);
const suggestionRef = source<Frame>();

const offset = (boundsState: () => Vector2) => () => {
Expand All @@ -31,33 +23,33 @@ export function Suggestions() {
};

const titleBounds = useTextBounds({
text: () => suggestion()?.title,
text: () => currentSuggestion()?.title,
font: () => options().font.bold,
size: () => px(SUGGESTION_TITLE_TEXT_SIZE),
});

const descriptionBounds = useTextBounds({
text: () => suggestion()?.description,
text: () => currentSuggestion()?.description,
font: () => options().font.regular,
size: () => px(SUGGESTION_TEXT_SIZE),
width: () => px(MAX_SUGGESTION_WIDTH),
});

const typeBadgeBounds = useTextBounds({
text: () => {
const currentSuggestion = suggestion();
if (currentSuggestion?.type === "command") return;
return currentSuggestion?.dataType;
const suggestion = currentSuggestion();
if (suggestion?.type === "command") return;
return suggestion?.dataType;
},
font: () => options().font.bold,
size: () => px(SUGGESTION_TEXT_SIZE),
});

const errorBounds = useTextBounds({
text: () => {
const current = suggestion();
if (current?.type === "command") return;
return current?.error;
const suggestion = currentSuggestion();
if (suggestion?.type === "command") return;
return suggestion?.error;
},
font: () => options().font.regular,
size: () => px(SUGGESTION_TEXT_SIZE),
Expand All @@ -70,7 +62,7 @@ export function Suggestions() {
const listBounds = derive(() => {
let width = 0;

const suggestions = suggestion()?.others ?? [];
const suggestions = currentSuggestion()?.others ?? [];
for (const value of suggestions) {
listBoundsParams.Text = value;
const suggestionBounds = TextService.GetTextBoundsAsync(listBoundsParams);
Expand Down Expand Up @@ -107,8 +99,8 @@ export function Suggestions() {
return (
<Group size={UDim2.fromScale(1, 1)}>
<MainSuggestion
suggestion={suggestion}
currentText={textPart}
suggestion={currentSuggestion}
currentText={currentTextPart}
size={spring(windowSize, 0.2)}
titleSize={offset(titleBounds)}
descriptionSize={offset(descriptionBounds)}
Expand All @@ -118,8 +110,8 @@ export function Suggestions() {
/>

<SuggestionList
suggestion={suggestion}
currentText={textPart}
suggestion={currentSuggestion}
currentText={currentTextPart}
size={spring(
() => UDim2.fromOffset(windowSize().X.Offset, listBounds().Y),
0.3,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { BaseRegistry } from "@rbxts/centurion";
import {
atNextPart,
commandArgIndex,
currentCommandPath,
currentTextPart,
terminalArgIndex,
terminalTextParts,
} from "../../../store";
import { Suggestion } from "../../../types";
import { formatPartsAsPath, getArgumentNames } from "../command";
Expand All @@ -22,9 +20,9 @@ function replaceTextPart(text: string, ...suggestions: string[]) {
export function completeCommand(
registry: BaseRegistry,
text: string,
textParts: string[],
suggestion: string,
) {
const textParts = terminalTextParts();
const atNextPart = text.sub(-1) === " ";
const pathParts = [...textParts];
if (!atNextPart) {
Expand Down Expand Up @@ -64,22 +62,23 @@ export function completeArgument(
export function getSuggestedText(
registry: BaseRegistry,
text: string,
textParts: string[],
atNextPart: boolean,
suggestion?: Suggestion,
) {
if (suggestion === undefined) return "";

let suggestionText: string;

const parts = terminalTextParts();
if (parts.isEmpty() || suggestion.type === "command") {
if (textParts.isEmpty() || suggestion.type === "command") {
suggestionText = suggestion.title;
} else {
const command = currentCommandPath();
const argIndex = terminalArgIndex();

if (command === undefined || argIndex === undefined) return "";

if (atNextPart() && argIndex === commandArgIndex()) {
if (atNextPart && argIndex === commandArgIndex()) {
suggestionText = suggestion.title;
} else if (!suggestion.others.isEmpty()) {
suggestionText = suggestion.others[0];
Expand Down
Loading

0 comments on commit 86684e2

Please sign in to comment.