diff --git a/src/renderer/components/available-versions/available-version-item.component.css b/src/renderer/components/available-versions/available-version-item.component.css index 16135455..e69de29b 100644 --- a/src/renderer/components/available-versions/available-version-item.component.css +++ b/src/renderer/components/available-versions/available-version-item.component.css @@ -1,22 +0,0 @@ -.glow-on-hover { - border-radius: 10px; - background: linear-gradient(45deg, #ff0000, #ff7300, #fffb00, #48ff00, #00ffd5, #002bff, #7a00ff, #ff00c8, #ff0000); - position: absolute; - top: -4px; - left:-4px; - background-size: 400%; - z-index: -1; - filter: blur(3px); - width: calc(100% + 8px); - height: calc(100% + 8px); - animation: glowing 20s linear infinite; - opacity: 0; - transition: opacity .2s ease-in-out; - border-radius: 10px; -} - -@keyframes glowing { - 0% { background-position: 0 0; } - 50% { background-position: 400% 0; } - 100% { background-position: 0 0; } -} \ No newline at end of file diff --git a/src/renderer/components/available-versions/available-version-item.component.tsx b/src/renderer/components/available-versions/available-version-item.component.tsx index 15ef6173..ab7e68e1 100644 --- a/src/renderer/components/available-versions/available-version-item.component.tsx +++ b/src/renderer/components/available-versions/available-version-item.component.tsx @@ -40,7 +40,7 @@ export const AvailableVersionItem = memo(function AvailableVersionItem(props: {v return (
-
+
diff --git a/src/renderer/components/shared/bsm-button.component.tsx b/src/renderer/components/shared/bsm-button.component.tsx index 24327605..cdcc4090 100644 --- a/src/renderer/components/shared/bsm-button.component.tsx +++ b/src/renderer/components/shared/bsm-button.component.tsx @@ -4,6 +4,7 @@ import React from "react"; import { BsmImage } from "./bsm-image.component"; import { useTranslation } from "renderer/hooks/use-translation.hook"; import { useThemeColor } from "renderer/hooks/use-theme-color.hook"; +import { useBestTextColor } from "renderer/hooks/use-best-text-color.hook"; type BsmButtonType = "primary"|"success"|"cancel"|"error"; @@ -32,16 +33,7 @@ export function BsmButton({className, style, imgClassName, iconClassName, icon, const primaryColor = typeColor === "primary" ? useThemeColor("first-color") : null; - const textColor = !primaryColor ? null : (() => { - const hex = primaryColor.replaceAll("#", ""); - const uicolors = [parseInt(hex.substring(0, 2), 16) / 255, parseInt(hex.substring(0, 2), 16) / 255, parseInt(hex.substring(0, 2), 16) / 255]; - const c = uicolors.map(col => { - if (col <= 0.03928) { return col / 12.92; } - return Math.pow((col + 0.055) / 1.055, 2.4); - }); - const L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]); - return (L > 0.179) ? "#000" : "fff"; - })(); + const textColor = !primaryColor ? null : useBestTextColor(primaryColor); const renderTypeColor = (() => { if(typeColor === "primary"){ return ""; } @@ -57,7 +49,7 @@ export function BsmButton({className, style, imgClassName, iconClassName, icon,
onClick && onClick(e)} className={`${className} overflow-hidden cursor-pointer group ${(!withBar && (!!typeColor || !!color)) && "hover:brightness-[1.15]"} ${disabled && "brightness-75 cursor-not-allowed"} ${renderTypeColor}`} style={{...style, ...((!!primaryColor || !!color) && {backgroundColor: primaryColor ?? color})}}> { image && } { icon && } - {text && (type === "submit" ? : {t(text)})} + {text && (type === "submit" ? : {t(text)})} { withBar && (
diff --git a/src/renderer/components/shared/bsm-checkbox.component.tsx b/src/renderer/components/shared/bsm-checkbox.component.tsx new file mode 100644 index 00000000..204c0979 --- /dev/null +++ b/src/renderer/components/shared/bsm-checkbox.component.tsx @@ -0,0 +1,32 @@ +import { useState } from "react" +import { BsmIcon } from "../svgs/bsm-icon.component" +import { motion } from "framer-motion" +import { useThemeColor } from "renderer/hooks/use-theme-color.hook"; +import { useBestTextColor } from "renderer/hooks/use-best-text-color.hook"; + +type Props = {className?:string, checked?: boolean, onChange?: (val: boolean) => void, disabled?: boolean} + +export function BsmCheckbox({className, checked, onChange, disabled} : Props) { + + const [isChecked, setIsChecked] = useState(true); + const checkedColor = useThemeColor("first-color"); + const iconColor = useBestTextColor(checkedColor); + + const handleClick = () => { + if(disabled){ return; } + onChange && onChange(!checked); + setIsChecked(val => !val); + } + + return ( +
+ {!disabled &&
} + +
+ + + +
+
+ ) +} diff --git a/src/renderer/components/svgs/bsm-icon.component.tsx b/src/renderer/components/svgs/bsm-icon.component.tsx index d7c9530f..81b3106a 100644 --- a/src/renderer/components/svgs/bsm-icon.component.tsx +++ b/src/renderer/components/svgs/bsm-icon.component.tsx @@ -20,9 +20,10 @@ import EditIcon from "./icons/edit-icon.component"; import { ExportIcon } from "./icons/export-icon.component"; import PatreonIcon from "./icons/patreon-icon.component"; import { SearchIcon } from "./icons/search-icon.component"; +import { CheckIcon } from "./icons/check-icon.component"; export type BsmIconType = ( - "settings"|"trash"|"favorite"|"folder"|"bsNote"| + "settings"|"trash"|"favorite"|"folder"|"bsNote"|"check"| "terminal"|"desktop"|"oculus"|"add"|"cross"|"task"| "copy"|"steam"|"edit"|"export"|"patreon"|"search"| "fr-FR-flag"|"es-ES-flag"|"en-US-flag"|"en-EN-flag" @@ -52,6 +53,7 @@ export const BsmIcon = memo(({className, icon, style}: {className?: string, icon if(icon === "export"){ return } if(icon === "patreon"){ return } if(icon === "search"){ return } + if(icon === "check"){ return } return } diff --git a/src/renderer/components/svgs/icons/check-icon.component.tsx b/src/renderer/components/svgs/icons/check-icon.component.tsx new file mode 100644 index 00000000..08143498 --- /dev/null +++ b/src/renderer/components/svgs/icons/check-icon.component.tsx @@ -0,0 +1,9 @@ +import { CSSProperties } from "react"; + +export function CheckIcon(props: {className?: string, style?: CSSProperties}) { + return ( + + + + ) +} diff --git a/src/renderer/components/title-bar/title-bar.component.tsx b/src/renderer/components/title-bar/title-bar.component.tsx index f5d7670d..f46ee96d 100644 --- a/src/renderer/components/title-bar/title-bar.component.tsx +++ b/src/renderer/components/title-bar/title-bar.component.tsx @@ -31,7 +31,7 @@ export default function TitleBar({template = "main"} : {template?: "update"|"mai } return ( -
+
{template !== "update" && (
BSManager diff --git a/src/renderer/components/version-viewer/slides/mods/mod-item.component.tsx b/src/renderer/components/version-viewer/slides/mods/mod-item.component.tsx index 39cfbdc9..5c891652 100644 --- a/src/renderer/components/version-viewer/slides/mods/mod-item.component.tsx +++ b/src/renderer/components/version-viewer/slides/mods/mod-item.component.tsx @@ -1,3 +1,4 @@ +import { BsmCheckbox } from "renderer/components/shared/bsm-checkbox.component" import { Mod } from "shared/models/mods/mod.interface" type Props = {mod: Mod, installed: Mod} @@ -5,8 +6,8 @@ type Props = {mod: Mod, installed: Mod} export function ModItem({mod, installed}: Props) { return ( <> -
- +
+
{mod.name} {installed?.version || "-"} diff --git a/src/renderer/components/version-viewer/slides/mods/mods-grid.component.tsx b/src/renderer/components/version-viewer/slides/mods/mods-grid.component.tsx index d872d336..b5415382 100644 --- a/src/renderer/components/version-viewer/slides/mods/mods-grid.component.tsx +++ b/src/renderer/components/version-viewer/slides/mods/mods-grid.component.tsx @@ -11,8 +11,6 @@ export function ModsGrid({modsMap, installed}: Props) { const [filter, setFilter] = useState(""); const [filterEnabled, setFilterEnabled] = useState(false); - const inputRef = useRef(); - const installedMod = (key: string, mod: Mod): Mod => { if(!installed || !installed.get(key)){ return; } return installed.get(key).find(m => m.name === mod.name); @@ -27,29 +25,29 @@ export function ModsGrid({modsMap, installed}: Props) { return modsMap && ( <>
- +
-
+
{(filterEnabled ? ( - handleInput(e.target.value)}/> + handleInput(e.target.value)}/> ):( Nom ))}
- Installé - Dernière - Description + Installé + Dernière + Description { - Array.from(modsMap.keys()).map(key => ( - <> - {key} + Array.from(modsMap.keys()).map(key => modsMap.get(key).some(mod => mod.name.toLowerCase().includes(filter)) && ( +
+ {key} {modsMap.get(key).map(mod => mod.name.toLowerCase().includes(filter) && )} - +
)) }
diff --git a/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx b/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx index efe51e54..658f1a4a 100644 --- a/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx +++ b/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx @@ -22,14 +22,12 @@ export function ModsSlide({version}: {version: BSVersion}) { } useEffect(() => { - if(!isVisible){ return; } - if(!modsAvailable){ - console.log("OUI"); - modsManager.getAvailableMods(version).then(mods => setModsAvailable(modsToCategoryMap(mods))); - modsManager.getInstalledMods(version).then(mods => setModsInstalled(modsToCategoryMap(mods))); - } - }, [isVisible]); + if(!isVisible){ return; } + modsManager.getAvailableMods(version).then(mods => setModsAvailable(modsToCategoryMap(mods))); + modsManager.getInstalledMods(version).then(mods => setModsInstalled(modsToCategoryMap(mods))); + + }, [isVisible, version]); return ( diff --git a/src/renderer/hooks/use-best-text-color.hook.ts b/src/renderer/hooks/use-best-text-color.hook.ts new file mode 100644 index 00000000..5039cba5 --- /dev/null +++ b/src/renderer/hooks/use-best-text-color.hook.ts @@ -0,0 +1,14 @@ +export function useBestTextColor(bgHex: string): string{ + + return (() => { + const hex = bgHex.replaceAll("#", ""); + const uicolors = [parseInt(hex.substring(0, 2), 16) / 255, parseInt(hex.substring(0, 2), 16) / 255, parseInt(hex.substring(0, 2), 16) / 255]; + const c = uicolors.map(col => { + if (col <= 0.03928) { return col / 12.92; } + return (col + 0.055) / 1.055 ** 2.4; + }); + const L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]); + return (L > 0.255) ? "#000" : "fff"; + })(); + +} \ No newline at end of file diff --git a/src/renderer/index.css b/src/renderer/index.css index cbad61b2..71078041 100644 --- a/src/renderer/index.css +++ b/src/renderer/index.css @@ -33,6 +33,29 @@ animation: spin-loading 2s cubic-bezier(.46,-0.55,.49,1.52) 0s forwards infinite; } +.glow-on-hover { + border-radius: 10px; + background: linear-gradient(45deg, #ff0000, #ff7300, #fffb00, #48ff00, #00ffd5, #002bff, #7a00ff, #ff00c8, #ff0000); + position: absolute; + top: -4px; + left:-4px; + background-size: 400%; + z-index: -1; + filter: blur(3px); + width: calc(100% + 8px); + height: calc(100% + 8px); + animation: glowing 20s linear infinite; + opacity: 0; + transition: opacity .2s ease-in-out; + border-radius: 10px; +} + +@keyframes glowing { + 0% { background-position: 0 0; } + 50% { background-position: 400% 0; } + 100% { background-position: 0 0; } +} + @keyframes spin-loading{ 0%{ transform: rotate(-360deg); } 50%{ transform: rotate(-360deg); } diff --git a/src/renderer/services/i18n.service.ts b/src/renderer/services/i18n.service.ts index 58428316..c187d4c5 100644 --- a/src/renderer/services/i18n.service.ts +++ b/src/renderer/services/i18n.service.ts @@ -53,11 +53,10 @@ export class I18nService { public translate(translationKey: string, args?: Record): string{ let translated = this.cache.get(translationKey); if(!translated){ - console.log(translationKey); translated = getProperty(this.dictionary, translationKey); translated ? this.cache.set(translated, translationKey) : translated = translationKey; } - args && Object.keys(args).forEach(key => translated = translated.replaceAll(`{${key}}`, args[key])); + args && Object.keys(args).forEach(key => {translated = translated.replaceAll(`{${key}}`, args[key])}); return translated; }