NatoBoram/eldarya-enhancements

View on GitHub
src/appearance/favourites_actions.ts

Summary

Maintainability
C
1 day
Test Coverage
import type { Avatar } from "../eldarya/avatar"
import type { Item } from "../eldarya/item"
import { translate } from "../i18n/translate"
import { exportOutfit } from "../outfit"
import type { ParsableItem } from "./interfaces/parsable_item"

export function exportPreview(): void {
    exportOutfit("#appearance-preview")
}

export function importOutfit(): void {
    const input = document.createElement("input")
    input.setAttribute("type", "file")
    input.setAttribute("accept", "application/json")
    input.click()

    input.addEventListener("input", event => {
        if (!event.target) return
        const files = (event.target as HTMLInputElement).files
        if (!files) return
        const file = files[0]
        if (!file) return
        void file.text().then(async value => {
            if (!value) return

            const outfit: ParsableItem[] = JSON.parse(value)
            const avatar = Sacha.Avatar.avatars["#appearance-preview"]
            if (!avatar) return

            await wearOutfit(avatar, outfit)
        })
    })
}

function removeClothes(): void {
    const avatar = Sacha.Avatar.avatars["#appearance-preview"]
    if (!avatar) return

    for (let i = avatar.children.length - 1; i >= 0; i--) {
        const itemRender = avatar.children[i]
        if (!itemRender) continue

        const item = itemRender.getItem()
        if (Sacha.Avatar.removeItemFromAllAvatars(item)) {
            $(`#appearance-item-${item._id}`).removeClass("selected")
        }
    }
}

export async function openGroup(group: number): Promise<HTMLDivElement | null> {
    return new Promise<HTMLDivElement | null>((resolve): void => {
        const groupContainer = document.querySelector<HTMLDivElement>(
            `#appearance-items-group-${group}`,
        )
        if (groupContainer) {
            resolve(groupContainer)
            return
        }

        const avatar = Sacha.Avatar.avatars["#appearance-preview"]
        if (!avatar) {
            resolve(null)
            return
        }

        void $.get(
            `/player/openGroup/${group}`,
            { wornItems: avatar.getItemsToSave() },
            (view: string): void => {
                $(view).hide().appendTo("#appearance-items")
                resolve(
                    document.querySelector<HTMLDivElement>(
                        `#appearance-items-group-${group}`,
                    ),
                )
            },
        )
    })
}

export async function openCategory(
    category: string,
): Promise<HTMLDivElement | null> {
    return new Promise<HTMLDivElement | null>((resolve): void => {
        const categoryContainer = document.querySelector<HTMLDivElement>(
            `#appearance-items-category-${category}`,
        )
        if (categoryContainer) {
            resolve(categoryContainer)
            return
        }

        void $.post(`/player/openCategory/${category}`, (view: string): void => {
            $(view).hide().appendTo("#appearance-items")
            resolve(
                document.querySelector<HTMLDivElement>(
                    `#appearance-items-category-${category}`,
                ),
            )
        })
    })
}

export async function wearOutfit(
    avatar: Avatar,
    outfit: ParsableItem[],
): Promise<void> {
    $.flavrNotif(translate.appearance.favourites.importing)

    // Get all categories
    const categories = new Set<string>()
    for (const clothing of outfit)
        if (!availableItems[clothing.id]) categories.add(clothing.type)

    // Open all categories
    await Promise.all(
        Array.from(categories.values()).map(async category =>
            openCategory(category),
        ),
    )

    // Get all groups
    const groups = new Set<number>()
    for (const clothing of outfit)
        if (
            document.querySelector(`[data-group="${clothing.group}"]`) &&
            !availableItems[clothing.id]
        )
            groups.add(clothing.group)

    // Open all groups
    await Promise.all(
        Array.from(groups.values()).map(async group => openGroup(group)),
    )

    // Get the items from `availableItems`
    const wornItems: Item[] = []
    for (const clothing of outfit) {
        const item = availableItems[clothing.id]
        if (item) wornItems.push(item)
    }

    removeClothes()
    avatar.addItems(wornItems)
    initializeSelectedItems()
    initializeHiddenCategories()

    const avatarActions = document.getElementById("avatar-actions")
    if (avatarActions) avatarActions.style.display = "initial"

    $.flavrNotif(translate.appearance.favourites.imported)
}