WIP: Feature Rewrite #87

Draft
thepaperpilot wants to merge 35 commits from feat/ure-rewrite into main
10 changed files with 51 additions and 60 deletions
Showing only changes of commit 6c8dd66677 - Show all commits

View file

@ -4,10 +4,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { RegisterNodeInjectionKey, UnregisterNodeInjectionKey } from "game/layers"; import { RegisterNodeInjectionKey, UnregisterNodeInjectionKey } from "game/layers";
import { computed, inject, onUnmounted, shallowRef, toRefs, unref, watch } from "vue"; import { computed, inject, onUnmounted, shallowRef, toRef, unref, watch } from "vue";
const _props = defineProps<{ id: string }>(); const props = defineProps<{ id: string }>();
const props = toRefs(_props);
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
const register = inject(RegisterNodeInjectionKey, () => {}); const register = inject(RegisterNodeInjectionKey, () => {});
@ -17,7 +16,7 @@ const unregister = inject(UnregisterNodeInjectionKey, () => {});
const node = shallowRef<HTMLElement | null>(null); const node = shallowRef<HTMLElement | null>(null);
const parentNode = computed(() => node.value && node.value.parentElement); const parentNode = computed(() => node.value && node.value.parentElement);
watch([parentNode, props.id], ([newNode, newID], [prevNode, prevID]) => { watch([parentNode, toRef(props, "id")], ([newNode, newID], [prevNode, prevID]) => {
if (prevNode) { if (prevNode) {
unregister(unref(prevID)); unregister(unref(prevID));
} }
@ -26,7 +25,7 @@ watch([parentNode, props.id], ([newNode, newID], [prevNode, prevID]) => {
} }
}); });
onUnmounted(() => unregister(unref(props.id))); onUnmounted(() => unregister(props.id));
</script> </script>
<style scoped> <style scoped>

View file

@ -10,13 +10,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRefs, unref, watch } from "vue"; import { ref, watch } from "vue";
const _props = defineProps<{ const props = defineProps<{
disabled?: boolean; disabled?: boolean;
skipConfirm?: boolean; skipConfirm?: boolean;
}>(); }>();
const props = toRefs(_props);
const emit = defineEmits<{ const emit = defineEmits<{
(e: "click"): void; (e: "click"): void;
(e: "confirmingChanged", value: boolean): void; (e: "confirmingChanged", value: boolean): void;
@ -29,7 +29,7 @@ watch(isConfirming, isConfirming => {
}); });
function click() { function click() {
if (unref(props.skipConfirm)) { if (props.skipConfirm) {
emit("click"); emit("click");
return; return;
} }

View file

@ -11,22 +11,22 @@
import "components/common/fields.css"; import "components/common/fields.css";
import Tooltip from "features/tooltips/Tooltip.vue"; import Tooltip from "features/tooltips/Tooltip.vue";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { computed, toRefs, unref } from "vue"; import { computed } from "vue";
const _props = defineProps<{ const props = defineProps<{
title?: string; title?: string;
modelValue?: number; modelValue?: number;
min?: number; min?: number;
max?: number; max?: number;
}>(); }>();
const props = toRefs(_props);
const emit = defineEmits<{ const emit = defineEmits<{
(e: "update:modelValue", value: number): void; (e: "update:modelValue", value: number): void;
}>(); }>();
const value = computed({ const value = computed({
get() { get() {
return String(unref(props.modelValue) ?? 0); return String(props.modelValue ?? 0);
}, },
set(value: string) { set(value: string) {
emit("update:modelValue", Number(value)); emit("update:modelValue", Number(value));

View file

@ -67,13 +67,12 @@ import player from "game/player";
import { infoComponents } from "game/settings"; import { infoComponents } from "game/settings";
import { formatTime } from "util/bignum"; import { formatTime } from "util/bignum";
import { coerceComponent, render } from "util/vue"; import { coerceComponent, render } from "util/vue";
import { computed, ref, toRefs, unref } from "vue"; import { computed, ref } from "vue";
import Modal from "./Modal.vue"; import Modal from "./Modal.vue";
const { title, logo, author, discordName, discordLink, versionNumber, versionTitle } = projInfo; const { title, logo, author, discordName, discordLink, versionNumber, versionTitle } = projInfo;
const _props = defineProps<{ changelog: typeof Changelog | null }>(); const props = defineProps<{ changelog: typeof Changelog | null }>();
const props = toRefs(_props);
const isOpen = ref(false); const isOpen = ref(false);
@ -90,7 +89,7 @@ defineExpose({
}); });
function openChangelog() { function openChangelog() {
unref(props.changelog)?.open(); props.changelog?.open();
} }
</script> </script>

View file

@ -41,22 +41,22 @@
<script setup lang="ts"> <script setup lang="ts">
import type { FeatureNode } from "game/layers"; import type { FeatureNode } from "game/layers";
import { computed, ref, toRefs, unref } from "vue"; import { computed, ref } from "vue";
import Context from "../Context.vue"; import Context from "../Context.vue";
const _props = defineProps<{ const props = defineProps<{
modelValue: boolean; modelValue: boolean;
preventClosing?: boolean; preventClosing?: boolean;
width?: string; width?: string;
}>(); }>();
const props = toRefs(_props);
const emit = defineEmits<{ const emit = defineEmits<{
(e: "update:modelValue", value: boolean): void; (e: "update:modelValue", value: boolean): void;
}>(); }>();
const isOpen = computed(() => unref(props.modelValue) || isAnimating.value); const isOpen = computed(() => props.modelValue || isAnimating.value);
function close() { function close() {
if (unref(props.preventClosing) !== true) { if (props.preventClosing !== true) {
emit("update:modelValue", false); emit("update:modelValue", false);
} }
} }

View file

@ -78,18 +78,18 @@
import Tooltip from "features/tooltips/Tooltip.vue"; import Tooltip from "features/tooltips/Tooltip.vue";
import player from "game/player"; import player from "game/player";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { computed, ref, toRefs, unref, watch } from "vue"; import { galaxy, syncedSaves } from "util/galaxy";
import { computed, ref, watch } from "vue";
import DangerButton from "../fields/DangerButton.vue"; import DangerButton from "../fields/DangerButton.vue";
import FeedbackButton from "../fields/FeedbackButton.vue"; import FeedbackButton from "../fields/FeedbackButton.vue";
import Text from "../fields/Text.vue"; import Text from "../fields/Text.vue";
import type { LoadablePlayerData } from "./SavesManager.vue"; import type { LoadablePlayerData } from "./SavesManager.vue";
import { galaxy, syncedSaves } from "util/galaxy";
const _props = defineProps<{ const props = defineProps<{
save: LoadablePlayerData; save: LoadablePlayerData;
readonly?: boolean; readonly?: boolean;
}>(); }>();
const { save, readonly } = toRefs(_props);
const emit = defineEmits<{ const emit = defineEmits<{
(e: "export"): void; (e: "export"): void;
(e: "open"): void; (e: "open"): void;
@ -111,19 +111,19 @@ const isEditing = ref(false);
const isConfirming = ref(false); const isConfirming = ref(false);
const newName = ref(""); const newName = ref("");
watch(isEditing, () => (newName.value = save.value.name ?? "")); watch(isEditing, () => (newName.value = props.save.name ?? ""));
const isActive = computed( const isActive = computed(
() => save.value != null && save.value.id === player.id && !unref(readonly) () => props.save != null && props.save.id === player.id && !props.readonly
); );
const currentTime = computed(() => const currentTime = computed(() =>
isActive.value ? player.time : (save.value != null && save.value.time) ?? 0 isActive.value ? player.time : (props.save != null && props.save.time) ?? 0
); );
const synced = computed( const synced = computed(
() => () =>
!unref(readonly) && !props.readonly &&
galaxy.value?.loggedIn === true && galaxy.value?.loggedIn === true &&
syncedSaves.value.includes(save.value.id) syncedSaves.value.includes(props.save.id)
); );
function changeName() { function changeName() {

View file

@ -14,47 +14,46 @@
import type { Link } from "features/links/links"; import type { Link } from "features/links/links";
import type { FeatureNode } from "game/layers"; import type { FeatureNode } from "game/layers";
import { kebabifyObject } from "util/vue"; import { kebabifyObject } from "util/vue";
import { computed, toRefs } from "vue"; import { computed } from "vue";
const _props = defineProps<{ const props = defineProps<{
link: Link; link: Link;
startNode: FeatureNode; startNode: FeatureNode;
endNode: FeatureNode; endNode: FeatureNode;
boundingRect: DOMRect | undefined; boundingRect: DOMRect | undefined;
}>(); }>();
const props = toRefs(_props);
const startPosition = computed(() => { const startPosition = computed(() => {
const rect = props.startNode.value.rect; const rect = props.startNode.rect;
const boundingRect = props.boundingRect.value; const boundingRect = props.boundingRect;
const position = boundingRect const position = boundingRect
? { ? {
x: rect.x + rect.width / 2 - boundingRect.x, x: rect.x + rect.width / 2 - boundingRect.x,
y: rect.y + rect.height / 2 - boundingRect.y y: rect.y + rect.height / 2 - boundingRect.y
} }
: { x: 0, y: 0 }; : { x: 0, y: 0 };
if (props.link.value.offsetStart) { if (props.link.offsetStart) {
position.x += props.link.value.offsetStart.x; position.x += props.link.offsetStart.x;
position.y += props.link.value.offsetStart.y; position.y += props.link.offsetStart.y;
} }
return position; return position;
}); });
const endPosition = computed(() => { const endPosition = computed(() => {
const rect = props.endNode.value.rect; const rect = props.endNode.rect;
const boundingRect = props.boundingRect.value; const boundingRect = props.boundingRect;
const position = boundingRect const position = boundingRect
? { ? {
x: rect.x + rect.width / 2 - boundingRect.x, x: rect.x + rect.width / 2 - boundingRect.x,
y: rect.y + rect.height / 2 - boundingRect.y y: rect.y + rect.height / 2 - boundingRect.y
} }
: { x: 0, y: 0 }; : { x: 0, y: 0 };
if (props.link.value.offsetEnd) { if (props.link.offsetEnd) {
position.x += props.link.value.offsetEnd.x; position.x += props.link.offsetEnd.x;
position.y += props.link.value.offsetEnd.y; position.y += props.link.offsetEnd.y;
} }
return position; return position;
}); });
const linkProps = computed(() => kebabifyObject(_props.link as unknown as Record<string, unknown>)); const linkProps = computed(() => kebabifyObject(props.link as unknown as Record<string, unknown>));
</script> </script>

View file

@ -16,11 +16,10 @@
import type { Link } from "features/links/links"; import type { Link } from "features/links/links";
import type { FeatureNode } from "game/layers"; import type { FeatureNode } from "game/layers";
import { BoundsInjectionKey, NodesInjectionKey } from "game/layers"; import { BoundsInjectionKey, NodesInjectionKey } from "game/layers";
import { computed, inject, onMounted, ref, toRef, watch } from "vue"; import { computed, inject, onMounted, ref, watch } from "vue";
import LinkVue from "./Link.vue"; import LinkVue from "./Link.vue";
const _props = defineProps<{ links?: Link[] }>(); const props = defineProps<{ links?: Link[] }>();
const links = toRef(_props, "links");
const resizeListener = ref<Element | null>(null); const resizeListener = ref<Element | null>(null);
@ -36,7 +35,7 @@ onMounted(() => (boundingRect.value = resizeListener.value?.getBoundingClientRec
const validLinks = computed(() => { const validLinks = computed(() => {
const n = nodes.value; const n = nodes.value;
return ( return (
links.value?.filter(link => n[link.startNode.id]?.rect && n[link.endNode.id]?.rect) ?? [] props.links?.filter(link => n[link.startNode.id]?.rect && n[link.endNode.id]?.rect) ?? []
); );
}); });
</script> </script>

View file

@ -25,23 +25,19 @@ import type { Resource } from "features/resources/resource";
import ResourceVue from "features/resources/Resource.vue"; import ResourceVue from "features/resources/Resource.vue";
import Decimal from "util/bignum"; import Decimal from "util/bignum";
import { computeOptionalComponent } from "util/vue"; import { computeOptionalComponent } from "util/vue";
import { ComponentPublicInstance, ref, Ref, StyleValue } from "vue"; import { ComponentPublicInstance, computed, ref, StyleValue, toRef } from "vue";
import { computed, toRefs } from "vue";
const _props = defineProps<{ const props = defineProps<{
resource: Resource; resource: Resource;
color?: string; color?: string;
classes?: Record<string, boolean>; classes?: Record<string, boolean>;
style?: StyleValue; style?: StyleValue;
effectDisplay?: CoercableComponent; effectDisplay?: CoercableComponent;
}>(); }>();
const props = toRefs(_props);
const effectRef = ref<ComponentPublicInstance | null>(null); const effectRef = ref<ComponentPublicInstance | null>(null);
const effectComponent = computeOptionalComponent( const effectComponent = computeOptionalComponent(toRef(props, "effectDisplay"));
props.effectDisplay as Ref<CoercableComponent | undefined>
);
const showPrefix = computed(() => { const showPrefix = computed(() => {
return Decimal.lt(props.resource.value, "1e1000"); return Decimal.lt(props.resource.value, "1e1000");

View file

@ -5,9 +5,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { CoercableComponent } from "features/feature"; import type { CoercableComponent } from "features/feature";
import { computeComponent } from "util/vue"; import { computeComponent } from "util/vue";
import { toRefs } from "vue"; import { toRef } from "vue";
const _props = defineProps<{ display: CoercableComponent }>(); const props = defineProps<{ display: CoercableComponent }>();
const { display } = toRefs(_props); const component = computeComponent(toRef(props, "display"));
const component = computeComponent(display);
</script> </script>