continue script setup refactoring

This commit is contained in:
Alexander Drozdov
2025-01-06 13:37:58 +02:00
committed by kvan7
parent d1b8b9393e
commit f07df3aa10
8 changed files with 205 additions and 245 deletions

View File

@@ -1,18 +1,18 @@
<template>
<div class="max-w-md p-2">
<div class="mb-4 flex">
<div class="flex flex-col gap-4 p-2 max-w-md">
<div class="flex">
<label class="flex-1">{{ t("item.open_on_wiki") }}</label>
<hotkey-input v-model="wikiKey" class="w-48" />
</div>
<div class="mb-4 flex">
<div class="flex">
<label class="flex-1">{{ t("item.open_on_poedb") }}</label>
<hotkey-input v-model="poedbKey" class="w-48" />
</div>
<div v-if="isEnglish" class="mb-4 flex">
<div v-if="isEnglish" class="flex">
<label class="flex-1">Open base item on Craft of Exile</label>
<hotkey-input v-model="craftOfExileKey" class="w-48" />
</div>
<div class="mb-4 flex">
<div class="flex">
<label class="flex-1">{{ t("item.find_in_stash") }}</label>
<hotkey-input v-model="stashSearchKey" class="w-48" />
</div>
@@ -20,39 +20,37 @@
</template>
<script lang="ts">
import { defineComponent, computed } from "vue";
export default {
name: "item.info",
};
</script>
<script setup lang="ts">
import { defineProps, computed } from "vue";
import { useI18n } from "vue-i18n";
import { configProp, configModelValue, findWidget } from "../settings/utils.js";
import type { ItemCheckWidget } from "./widget.js";
import HotkeyInput from "../settings/HotkeyInput.vue";
export default defineComponent({
name: "item.info",
components: { HotkeyInput },
props: configProp(),
setup(props) {
const { t } = useI18n();
const props = defineProps(configProp());
return {
t,
isEnglish: computed(() => props.config.language === "en"),
wikiKey: configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"wikiKey",
),
poedbKey: configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"poedbKey",
),
craftOfExileKey: configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"craftOfExileKey",
),
stashSearchKey: configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"stashSearchKey",
),
};
},
});
const isEnglish = computed(() => props.config.language === "en");
const wikiKey = configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"wikiKey",
);
const poedbKey = configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"poedbKey",
);
const craftOfExileKey = configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"craftOfExileKey",
);
const stashSearchKey = configModelValue(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
"stashSearchKey",
);
const { t } = useI18n();
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="max-w-md p-2">
<div class="mb-4 flex">
<div class="flex flex-col gap-4 p-2 max-w-md">
<div class="flex">
<label class="flex-1">{{ t("item_search.ocr_gems_key") }}</label>
<hotkey-input v-model="ocrGemsKey" class="w-48" />
</div>
@@ -8,26 +8,24 @@
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default {
name: "item_search.name",
};
</script>
<script setup lang="ts">
import { defineProps } from "vue";
import { useI18n } from "vue-i18n";
import { configProp, configModelValue, findWidget } from "../settings/utils.js";
import { ItemSearchWidget } from "./widget.js";
import HotkeyInput from "../settings/HotkeyInput.vue";
export default defineComponent({
name: "item_search.name",
components: { HotkeyInput },
props: configProp(),
setup(props) {
const { t } = useI18n();
const props = defineProps(configProp());
return {
t,
ocrGemsKey: configModelValue(
() => findWidget<ItemSearchWidget>("item-search", props.config)!,
"ocrGemsKey",
),
};
},
});
const ocrGemsKey = configModelValue(
() => findWidget<ItemSearchWidget>("item-search", props.config)!,
"ocrGemsKey",
);
const { t } = useI18n();
</script>

View File

@@ -53,8 +53,7 @@ import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { ItemRarity, ParsedItem } from "@/parser";
import { prepareMapStats } from "./prepare-map-stats";
import { STAT_BY_MATCH_STR } from "@/assets/data";
import { MapCheckConfig } from "./common.js";
import { type MapCheckConfig, isOutdated } from "./common.js";
import MapStatButton from "./MapStatButton.vue";
import FullscreenImage from "@/web/ui/FullscreenImage.vue";
@@ -68,13 +67,8 @@ const props = defineProps<{
const { t } = useI18n();
const hasOutdatedTranslation = computed<boolean>(() => {
const idx = props.config.profile - 1;
return props.config.selectedStats.some(
(entry) =>
entry.decision[idx] !== "-" &&
entry.decision[idx] !== "s" &&
STAT_BY_MATCH_STR(entry.matcher) == null,
);
const { profile } = props.config;
return props.config.selectedStats.some((entry) => isOutdated(profile, entry));
});
const mapName = computed(() => props.item.info.name);

View File

@@ -56,7 +56,7 @@ import {
StatTag,
decisionHasColor,
decisionCreate,
MapCheckConfig,
MapCheckStat,
} from "./common.js";
export default defineComponent({
@@ -68,7 +68,7 @@ export default defineComponent({
required: true,
},
selectedStats: {
type: Array as PropType<MapCheckConfig["selectedStats"]>,
type: Array as PropType<MapCheckStat[]>,
required: true,
},
profile: {

View File

@@ -1,10 +1,14 @@
import { STAT_BY_MATCH_STR } from "@/assets/data";
export interface MapCheckConfig {
profile: number;
showNewStats: boolean;
selectedStats: Array<{
matcher: string;
decision: string;
}>;
selectedStats: MapCheckStat[];
}
export interface MapCheckStat {
matcher: string;
decision: string;
}
export enum StatTag {
@@ -51,3 +55,10 @@ export function decisionCreate(
split[idx] = value;
return split.join("");
}
export function isOutdated(profileName: number, stat: MapCheckStat): boolean {
return (
decisionHasColor(stat.decision, profileName) &&
STAT_BY_MATCH_STR(stat.matcher) == null
);
}

View File

@@ -1,17 +1,17 @@
<template>
<div class="flex flex-col overflow-hidden h-full">
<div class="p-1 flex">
<div class="flex p-1">
<input
:placeholder="t('Search') + '...'"
v-model="search"
class="bg-gray-900 rounded px-1"
/>
<ui-toggle v-model="onlySelected" class="mx-2">{{
<UiToggle v-model="onlySelected" class="mx-2">{{
t(":search_selected")
}}</ui-toggle>
<ui-toggle v-model="showNewStats" class="ml-12">{{
}}</UiToggle>
<UiToggle v-model="showNewStats" class="ml-12">{{
t(":new_mods_icon")
}}</ui-toggle>
}}</UiToggle>
</div>
<div class="flex items-baseline py-1 shadow">
<div class="flex-1 px-2 leading-none">
@@ -44,15 +44,17 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref } from "vue";
import { useI18nNs } from "@/web/i18n";
import UiToggle from "@/web/ui/UiToggle.vue";
import { configProp, findWidget } from "../settings/utils";
import type { ItemCheckWidget } from "../item-check/widget.js";
import { STATS_ITERATOR, STAT_BY_MATCH_STR } from "@/assets/data";
import SettingsMatcherEntry from "./SettingsMatcherEntry.vue";
import VirtualScroll from "../ui/VirtualScroll.vue";
import { StatMatcher, StatTag, decisionHasColor } from "./common.js";
import { STATS_ITERATOR } from "@/assets/data";
import {
StatMatcher,
StatTag,
decisionHasColor,
isOutdated,
} from "./common.js";
export default {
name: "map_check.name",
};
function tagToShowOrder(tag?: StatTag): number {
switch (tag) {
@@ -64,105 +66,87 @@ function tagToShowOrder(tag?: StatTag): number {
return 0;
}
export default defineComponent({
name: "map_check.name",
components: {
SettingsMatcherEntry,
VirtualScroll,
UiToggle,
},
props: configProp(),
setup(props) {
const search = ref("");
const onlySelected = ref(false);
function findAllAreaMods(): StatMatcher[] {
const out: StatMatcher[] = [];
for (const stat of STATS_ITERATOR("AreaMods")) {
if (!stat.fromAreaMods && !stat.fromUberAreaMods && !stat.fromHeistAreaMods)
continue;
const widget = computed(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
);
const tag =
stat.fromHeistAreaMods && !stat.fromAreaMods
? StatTag.HeistExclusive
: stat.fromUberAreaMods && !stat.fromAreaMods
? StatTag.UberMapExclusive
: undefined;
const areaStatsDb = computed(() => {
const out: StatMatcher[] = [];
for (const stat of STATS_ITERATOR("AreaMods")) {
if (
!stat.fromAreaMods &&
!stat.fromUberAreaMods &&
!stat.fromHeistAreaMods
)
continue;
const tag =
stat.fromHeistAreaMods && !stat.fromAreaMods
? StatTag.HeistExclusive
: stat.fromUberAreaMods && !stat.fromAreaMods
? StatTag.UberMapExclusive
: undefined;
for (const c of stat.matchers) {
out.push({ matchStr: c.string, tag });
}
}
out.sort(
(a, b) =>
tagToShowOrder(a.tag) - tagToShowOrder(b.tag) ||
a.matchStr.localeCompare(b.matchStr),
);
return out;
});
const selectedProfileMatchers = computed(() => {
const { profile } = widget.value.maps;
return new Set(
widget.value.maps.selectedStats
.filter((entry) => decisionHasColor(entry.decision, profile))
.map((entry) => entry.matcher),
);
});
const showNewStats = computed<boolean>({
get() {
return widget.value.maps.showNewStats;
},
set(value) {
widget.value.maps.showNewStats = value;
},
});
const outdatedTranslationList = computed<StatMatcher[]>(() => {
const { profile } = widget.value.maps;
return widget.value.maps.selectedStats
.filter(
(entry) =>
decisionHasColor(entry.decision, profile) &&
STAT_BY_MATCH_STR(entry.matcher) == null,
)
.map((entry) => ({ matchStr: entry.matcher, tag: StatTag.Outdated }));
});
const { t } = useI18nNs("map_check");
return {
t,
search,
onlySelected,
showNewStats,
filteredStats: computed<StatMatcher[]>(() => {
const q = search.value.toLowerCase().split(" ");
const filtered = areaStatsDb.value.filter((stat) => {
const searchStr = stat.matchStr.toLowerCase();
if (!q.every((part) => searchStr.includes(part))) return false;
if (onlySelected.value) {
return selectedProfileMatchers.value.has(stat.matchStr);
}
return true;
});
return [...outdatedTranslationList.value, ...filtered];
}),
selectedStats: computed(() => widget.value.maps.selectedStats),
profile: computed(() => widget.value.maps.profile),
fontSize: computed(() => props.config.fontSize),
};
},
});
for (const c of stat.matchers) {
out.push({ matchStr: c.string, tag });
}
}
out.sort(
(a, b) =>
tagToShowOrder(a.tag) - tagToShowOrder(b.tag) ||
a.matchStr.localeCompare(b.matchStr),
);
return out;
}
</script>
<script setup lang="ts">
import { computed, defineProps, ref } from "vue";
import { useI18nNs } from "@/web/i18n";
import { configProp, findWidget, configModelValue } from "../settings/utils";
import type { ItemCheckWidget } from "../item-check/widget.js";
import UiToggle from "@/web/ui/UiToggle.vue";
import VirtualScroll from "@/web/ui/VirtualScroll.vue";
import SettingsMatcherEntry from "./SettingsMatcherEntry.vue";
const props = defineProps(configProp());
const widget = computed(
() => findWidget<ItemCheckWidget>("item-check", props.config)!,
);
const selectedProfileMatchers = computed(() => {
const { profile } = widget.value.maps;
const matchers = new Set<string>();
for (const entry of widget.value.maps.selectedStats) {
if (decisionHasColor(entry.decision, profile)) {
matchers.add(entry.matcher);
}
}
return matchers;
});
const outdatedTranslationList = computed<StatMatcher[]>(() => {
const { profile } = widget.value.maps;
return widget.value.maps.selectedStats
.filter((entry) => isOutdated(profile, entry))
.map((entry) => ({ matchStr: entry.matcher, tag: StatTag.Outdated }));
});
const areaStatsDb = computed(() => findAllAreaMods());
const search = ref("");
const onlySelected = ref(false);
const filteredStats = computed<StatMatcher[]>(() => {
const q = search.value.toLowerCase().split(" ");
const filtered = areaStatsDb.value.filter((stat) => {
const searchStr = stat.matchStr.toLowerCase();
if (!q.every((part) => searchStr.includes(part))) return false;
if (onlySelected.value) {
return selectedProfileMatchers.value.has(stat.matchStr);
}
return true;
});
return [...outdatedTranslationList.value, ...filtered];
});
const selectedStats = computed(() => widget.value.maps.selectedStats);
const profile = computed(() => widget.value.maps.profile);
const fontSize = computed(() => props.config.fontSize);
const showNewStats = configModelValue(() => widget.value.maps, "showNewStats");
const { t } = useI18nNs("map_check");
</script>

View File

@@ -13,36 +13,23 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed } from "vue";
<script setup lang="ts">
import { defineProps, shallowRef, computed } from "vue";
export default defineComponent({
name: "FullscreenImage",
props: {
src: {
type: String,
required: true,
},
disabled: {
type: Boolean,
default: false,
},
},
setup(props) {
const isHovered = ref(false);
return {
isHovered,
resolvedSrc: computed(() => {
if (props.src.includes("://")) {
return props.src;
} else {
return props.src.length < 32
? `${import.meta.env.BASE_URL}images/${props.src}`
: `/uploads/${props.src}`;
}
}),
};
},
const props = defineProps<{
src: string;
disabled?: boolean;
}>();
const isHovered = shallowRef(false);
const resolvedSrc = computed(() => {
if (props.src.includes("://")) {
return props.src;
} else {
return props.src.length < 32
? `${import.meta.env.BASE_URL}images/${props.src}`
: `/uploads/${props.src}`;
}
});
</script>

View File

@@ -12,43 +12,31 @@
</span>
</template>
<script lang="ts">
import { computed, defineComponent } from "vue";
<script setup lang="ts">
import { computed, defineProps } from "vue";
export default defineComponent({
props: {
text: {
type: String,
required: true,
},
roll: {
type: Number,
default: undefined,
},
},
setup(props) {
return {
parts: computed(() => {
const res = [] as Array<{ text: string; placeholder?: boolean }>;
props.text.split(/(?<![#])[+-]?[#]/gm).forEach((text, idx, parts) => {
if (text !== "") {
res.push({ text });
}
if (idx !== parts.length - 1) {
if (props.roll == null) {
res.push({ text: "#" });
} else {
res.push({
text: String(props.roll),
placeholder: true,
});
}
}
const props = defineProps<{
text: string;
roll?: number;
}>();
const parts = computed(() => {
const res = [] as Array<{ text: string; placeholder?: boolean }>;
props.text.split(/(?<![#])[+-]?[#]/gm).forEach((text, idx, parts) => {
if (text !== "") {
res.push({ text });
}
if (idx !== parts.length - 1) {
if (props.roll == null) {
res.push({ text: "#" });
} else {
res.push({
text: String(props.roll),
placeholder: true,
});
return res;
}),
};
},
}
}
});
return res;
});
</script>