add all translations

This commit is contained in:
MathieuG-P
2022-12-11 23:11:23 +01:00
parent 6b724d8040
commit 055d8b2bcc
9 changed files with 323 additions and 46 deletions
@@ -4,13 +4,13 @@ import { MutableRefObject} from "react"
import { MAP_TYPES } from "renderer/partials/maps/map-tags/map-types"
import { MAP_STYLES } from "renderer/partials/maps/map-tags/map-styles"
import { BsmCheckbox } from "../shared/bsm-checkbox.component"
import { diffColors } from "./map-item.component"
import { min_to_s } from "renderer/helpers/time-utils"
import dateFormat from "dateformat"
import { BsmRange } from "../shared/bsm-range.component"
import { useTranslation } from "renderer/hooks/use-translation.hook"
import { MAP_SPECIFICITIES } from "renderer/partials/maps/map-general/map-specificity"
import { MAP_REQUIREMENTS } from "renderer/partials/maps/map-requirements/map-requirements"
import { MAP_DIFFICULTIES_COLORS } from "renderer/partials/maps/map-difficulties/map-difficulties-colors"
export type Props = {
className?: string,
@@ -136,11 +136,11 @@ export function FilterPanel({className, ref, playlist = false, filter, onChange}
return !playlist ? (
<motion.div ref={ref} className={className} initial={{opacity: 0}} animate={{opacity: 1}} exit={{opacity: 0}}>
<div className="w-full h-6 grid grid-cols-2 gap-x-10 px-4 mb-6 pt-2">
<div className="w-full h-6 grid grid-cols-2 gap-x-12 px-4 mb-6 pt-2">
<BsmRange min={MIN_NPS} max={MAX_NPS} values={npss} onChange={onNpssChange} renderLabel={renderNpsLabel} step={.1}/>
<BsmRange min={MIN_DURATION} max={MAX_DURATION} values={durations} onChange={onDurationsChange} renderLabel={renderDurationLabel} step={5}/>
</div>
<div className="w-full h-full flex gap-x-2"> {/* TODO TRADUIRE */}
<div className="w-full h-full flex gap-x-2">
<section className="shrink-0">
<h2 className="mb-1 uppercase text-sm">{t("maps.map-filter-panel.specificities")}</h2>
@@ -164,12 +164,12 @@ export function FilterPanel({className, ref, playlist = false, filter, onChange}
<h2 className="uppercase text-sm mb-1">{t("maps.map-filter-panel.tags")}</h2>
<div className="w-full flex flex-row flex-wrap items-start justify-start content-start gap-1 mb-2">
{MAP_TYPES.map(tag => (
<span key={tag} onClick={() => handleTagClick(tag)} className={`text-[12.5px] text-black rounded-md px-1 font-bold cursor-pointer ${(!isTagActivated(tag)) && "opacity-40 hover:opacity-90"}`} style={{backgroundColor: isTagExcluded(tag) ? diffColors.Expert : diffColors.Normal}}>{translateMapType(tag)}</span>
<span key={tag} onClick={() => handleTagClick(tag)} className={`text-[12.5px] text-black rounded-md px-1 font-bold cursor-pointer ${(!isTagActivated(tag)) && "opacity-40 hover:opacity-90"}`} style={{backgroundColor: isTagExcluded(tag) ? MAP_DIFFICULTIES_COLORS.Expert : MAP_DIFFICULTIES_COLORS.Normal}}>{translateMapType(tag)}</span>
))}
</div>
<div className="w-full flex flex-row flex-wrap items-start justify-start content-start gap-1">
{MAP_STYLES.map(tag => (
<span key={tag} onClick={() => handleTagClick(tag)} className={`text-[12.5px] text-black rounded-md px-1 font-bold cursor-pointer ${(!isTagActivated(tag)) && "opacity-40 hover:opacity-90"}`} style={{backgroundColor: isTagExcluded(tag) ? diffColors.Expert : diffColors.Easy}}>{translateMapStyle(tag)}</span>
<span key={tag} onClick={() => handleTagClick(tag)} className={`text-[12.5px] text-black rounded-md px-1 font-bold cursor-pointer ${(!isTagActivated(tag)) && "opacity-40 hover:opacity-90"}`} style={{backgroundColor: isTagExcluded(tag) ? MAP_DIFFICULTIES_COLORS.Expert : MAP_DIFFICULTIES_COLORS.Easy}}>{translateMapStyle(tag)}</span>
))}
</div>
@@ -17,6 +17,9 @@ import equal from "fast-deep-equal/es6";
import { getMapZipUrlFromHash } from "renderer/helpers/maps-utils";
import { BsmBasicSpinner } from "../shared/bsm-basic-spinner/bsm-basic-spinner.component";
import defaultImage from '../../../../assets/images/default-version-img.jpg'
import { useTranslation } from "renderer/hooks/use-translation.hook";
import { MAP_DIFFICULTIES } from "renderer/partials/maps/map-difficulties/map-difficulties";
import { MAP_DIFFICULTIES_COLORS } from "renderer/partials/maps/map-difficulties/map-difficulties-colors"
export type ParsedMapDiff = {type: BsvMapDifficultyType, name: string, stars: number}
@@ -51,6 +54,7 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
const audioPlayer = AudioPlayerService.getInstance();
const color = useThemeColor("first-color");
const t = useTranslation();
const [hovered, setHovered] = useState(false);
const [bottomBarHovered, setBottomBarHovered, cancelBottomBarHovered] = useDelayedState(false);
@@ -73,7 +77,9 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
})();
const parseDiffLabel = (diffLabel: string) => {
if(diffLabel === "ExpertPlus"){ return "Expert+" }
if(MAP_DIFFICULTIES.includes(diffLabel as BsvMapDifficultyType)){
return t(`maps.difficulties.${diffLabel}`);
}
return diffLabel;
}
@@ -115,7 +121,7 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
<BsmIcon className="h-4 w-4 mr-px" icon="bsMapDifficulty"/>
<div className="flex py-[2px] gap-[1px] h-full">
{diffSet.map(diff => (
<span key={diff.type} className="h-full w-[6px] rounded-full" style={{backgroundColor: diffColors[diff.type]}}/>
<span key={diff.type} className="h-full w-[6px] rounded-full" style={{backgroundColor: MAP_DIFFICULTIES_COLORS[diff.type]}}/>
))}
</div>
</>
@@ -142,16 +148,16 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
{diffSet.map(({type, name, stars}) => (
<li key={`${type}${name}${stars}`} className="w-full h-4 flex items-center gap-1">
<BsmIcon className="h-full w-fit p-px" icon={charac}/>
<span className="h-full px-2 flex items-center text-xs font-bold bg-current rounded-full" style={{color: diffColors[type]}}>
<span className="h-full px-2 flex items-center text-xs font-bold bg-current rounded-full" style={{color: MAP_DIFFICULTIES_COLORS[type]}}>
{
stars ? (
<span className="h-full block brightness-[.25]"> {stars}</span>
) : (
<span className="h-full brightness-[.25] leading-4 pb-[2px]">{parseDiffLabel(type)}</span>
<span className="h-full brightness-[.25] leading-4 pb-[2px] capitalize">{parseDiffLabel(type)}</span>
)
}
</span>
<span className="text-sm leading-4 pb-[2px]">{parseDiffLabel(name)}</span>
<span className="text-sm leading-4 pb-[2px] capitalize">{parseDiffLabel(name)}</span>
</li>
))}
</ol>
@@ -170,8 +176,8 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
<BsmImage className="absolute top-0 left-0 w-full h-full -z-[1] object-cover" image={coverUrl} placeholder={defaultImage} errorImage={defaultImage} loading="lazy"/>
<div className="pt-1 pl-2 pr-7 top-0 left-0 w-full h-full bg-gray-600 bg-opacity-80 flex flex-col justify-between group-hover:bg-main-color-1 group-hover:bg-opacity-80">
<h1 className="font-bold whitespace-nowrap text-ellipsis overflow-hidden w-full leading-5 tracking-wide text-lg" title={title}><BsmLink className="hover:underline" href={mapUrl}>{title}</BsmLink></h1>
<h2 className="font-bold whitespace-nowrap text-ellipsis overflow-hidden w-full text-sm mb-[3px]">par {songAutor}</h2>
<h3 className="font-bold whitespace-nowrap text-ellipsis overflow-hidden w-full text-xs">{autor && (<> mappée par <BsmLink href={authorUrl} className="brightness-150 hover:underline" style={{color}}>{autor}</BsmLink></>)}</h3>
<h2 className="font-bold whitespace-nowrap text-ellipsis overflow-hidden w-full text-sm mb-[3px]">{songAutor && t("maps.map-item.by", {songAutor})}</h2>
<h3 className="font-bold whitespace-nowrap text-ellipsis overflow-hidden w-full text-xs">{autor && (<> {t("maps.map-item.mapped-by")} <BsmLink href={authorUrl} className="brightness-150 hover:underline" style={{color}}>{autor}</BsmLink></>)}</h3>
<div className="w-full h-4 text-xs gap-2 flex opacity-0 group-hover:opacity-100">
{likesText && (
<div className="h-full flex items-center">
@@ -195,7 +201,7 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
<motion.div className="w-full h-5 pb-1 pr-7 flex items-center gap-1" onHoverStart={bottomBarHoverStart} onHoverEnd={bottomBarHoverEnd}>
{ranked && (
<div className="text-yellow-300 bg-current rounded-full px-1 h-full flex items-center justify-center">
<span className="uppercase text-xs font-bold tracking-wide brightness-[.25]">classée</span>
<span className="uppercase text-xs font-bold tracking-wide brightness-[.25]">{t("maps.map-specificities.ranked")}</span>
</div>
)}
<div className="h-full grow flex items-start content-start">
@@ -225,11 +231,3 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
function areEqual(prevProps: MapItemProps, nextProps: MapItemProps): boolean {
return equal(prevProps, nextProps);
}
export const diffColors: Record<BsvMapDifficultyType, string> = {
Easy: "#00FF9E",
Normal: "#00FFFF",
Hard: "#FFA700",
Expert: "#FF4319",
ExpertPlus: "#FF7EFF"
}
@@ -5,7 +5,6 @@ import { LocalMapsListPanel } from "./local-maps-list-panel.component"
import { BsmDropdownButton, DropDownItem } from "../shared/bsm-dropdown-button.component"
import { FilterPanel } from "./filter-panel.component"
import { MapFilter } from "shared/models/maps/beat-saver.model"
import { BsmButton } from "../shared/bsm-button.component"
import { useThemeColor } from "renderer/hooks/use-theme-color.hook"
import { MapsManagerService } from "renderer/services/maps-manager.service"
import { motion, Variants } from "framer-motion";
@@ -88,11 +87,11 @@ export function MapsPlaylistsPanel({version}: Props) {
<motion.div className="h-full p-0.5" variants={variants}>
<BsmIcon className="block h-full aspect-square brightness-150" icon="add"/>
</motion.div>
<span className="text-sm brightness-150">Ajouter</span>
<span className="text-sm brightness-150">{t("pages.version-viewer.maps.tabs.maps.actions.add-maps.text")}</span>
</motion.div>
)}
{(!!version) && (
<motion.div variants={variants} whileHover="hover" whileTap="tap" initial={{rotate: 0}} className="block p-0.5 h-[calc(100%-5px)] aspect-square blur-0 hover:brightness-75" title={mapsLinked ? "Délier les maps" : "Lier les maps"} onClick={e => {e.stopPropagation(); onClickLink(index)}}>
<motion.div variants={variants} whileHover="hover" whileTap="tap" initial={{rotate: 0}} className="block p-0.5 h-[calc(100%-5px)] aspect-square blur-0 hover:brightness-75" title={t(mapsLinked ? "pages.version-viewer.maps.tabs.maps.actions.link-maps.tooltips.unlink" : "pages.version-viewer.maps.tabs.maps.actions.link-maps.tooltips.link")} onClick={e => {e.stopPropagation(); onClickLink(index)}}>
<span className="absolute top-0 left-0 h-full w-full rounded-full opacity-20" style={{backgroundColor: linkedColor}}/>
<BsmIcon className="p-1 absolute top-0 left-0 h-full w-full !bg-transparent -rotate-45 brightness-150" icon={mapsLinked ? "link" : "unlink"} style={{color: linkedColor}} />
</motion.div>
@@ -119,7 +118,7 @@ export function MapsPlaylistsPanel({version}: Props) {
return (
<div className="w-full h-full flex flex-col items-center justify-center">
<nav className="w-full shrink-0 flex h-[35px] justify-center px-40 gap-2 mb-3">
<nav className="w-full shrink-0 flex h-9 justify-center px-40 gap-2 mb-3">
<div className="h-full rounded-full bg-main-color-2 grow p-[6px]">
<input type="text" className="h-full w-full bg-main-color-1 rounded-full px-2" placeholder={t("pages.version-viewer.maps.search-bar.search-placeholder")} value={tabIndex === 0 ? mapSearch : playlistSearch} onChange={e => handleSearch(e.target.value)}/>
</div>
@@ -129,7 +128,7 @@ export function MapsPlaylistsPanel({version}: Props) {
<BsmDropdownButton className="h-full flex aspect-square relative rounded-full z-[1] bg-main-color-3" buttonClassName="rounded-full h-full w-full p-[6px]" icon="three-dots" withBar={false} items={dropDownItems} menuTranslationY="6px" align="center"/>
</nav>
<div className="w-full h-full flex flex-col bg-main-color-2 rounded-md shadow-black shadow-md overflow-hidden">
<TabNavBar className="!rounded-none shadow-sm" tabsText={["misc.maps", "Playlists"]} onTabChange={setTabIndex} renderTab={renderTab}/>
<TabNavBar className="!rounded-none shadow-sm" tabsText={["misc.maps", "misc.playlists"]} onTabChange={setTabIndex} renderTab={renderTab}/>
<div className="w-full grow min-h-0 flex flex-row items-center transition-transform duration-300" style={{transform: `translate(${-(tabIndex * 100)}%, 0)`}}>
<LocalMapsListPanel ref={mapsRef} className="w-full h-full shrink-0 flex flex-col" version={version} filter={mapFilter} search={mapSearch}/>
<div className="w-full h-full shrink-0 flex flex-col justify-center items-center content-center gap-2 overflow-hidden">
@@ -1,5 +1,5 @@
import { motion } from "framer-motion";
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { FilterPanel } from "renderer/components/maps-mangement-components/filter-panel.component";
import { MapItem, ParsedMapDiff } from "renderer/components/maps-mangement-components/map-item.component";
import { BsmButton } from "renderer/components/shared/bsm-button.component";
@@ -16,6 +16,7 @@ import { BsvMapCharacteristic, BsvMapDetail, MapFilter, SearchOrder, SearchParam
import BeatWaitingImg from "../../../../../assets/images/apngs/beat-waiting.png";
import equal from "fast-deep-equal/es6";
import { ProgressBarService } from "renderer/services/progress-bar.service";
import { useTranslation } from "renderer/hooks/use-translation.hook";
export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
@@ -26,6 +27,7 @@ export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
const currentDownload = useObservable(mapsDownloader.currentMapDownload$);
const mapsInQueue = useObservable(mapsDownloader.mapsInQueue$);
const t = useTranslation();
const [filter, setFilter] = useState<MapFilter>({});
const [query, setQuery] = useState("");
const [maps, setMaps] = useState<BsvMapDetail[]>([]);
@@ -41,7 +43,7 @@ export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
const loaderRef = useRef(null);
const sortOptions: BsmSelectOption[] = (() => {
return BSV_SORT_ORDER.map(sort => ({text: sort, value: sort}));
return BSV_SORT_ORDER.map(sort => ({text: `beat-saver.maps-sorts.${sort}`, value: sort}));
})();
useEffect(() => {
@@ -152,19 +154,19 @@ export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
return (
<form className="text-gray-800 dark:text-gray-200 flex flex-col max-w-[95vw] w-[970px] h-[85vh] gap-3" onSubmit={e => {e.preventDefault(); handleSearch()}}>
<div className="flex h-8 gap-2 shrink-0">
<BsmDropdownButton className="shrink-0 h-full relative z-[1] flex justify-start" buttonClassName="flex items-center justify-center h-full rounded-full px-2 py-1 !bg-main-color-1" icon="search" text="Filtres" withBar={false}>
<div className="flex h-9 gap-2 shrink-0">
<BsmDropdownButton className="shrink-0 h-full relative z-[1] flex justify-start" buttonClassName="flex items-center justify-center h-full rounded-full px-2 py-1 !bg-main-color-1" icon="search" text="pages.version-viewer.maps.search-bar.filters-btn" withBar={false}>
<FilterPanel className="absolute top-[calc(100%+3px)] bg-main-color-3 origin-top w-[450px] h-fit p-2 rounded-md shadow-md shadow-black" filter={filter} onChange={setFilter}/>
</BsmDropdownButton>
<input className="h-full bg-main-color-1 rounded-full px-2 grow pb-0.5" type="text" name="" id="" placeholder="Rechercher une map" value={query} onChange={e => setQuery(e.target.value)}/>
<BsmButton className="shrink-0 rounded-full py-1 px-3 !bg-main-color-1 flex justify-center items-center" icon="search" text="Rechercher" withBar={false} onClick={e => {e.preventDefault(); handleSearch()}}/>
<BsmSelect className="bg-main-color-1 rounded-full px-2 pb-0.5" options={sortOptions} onChange={handleSortChange}/>
<input className="h-full bg-main-color-1 rounded-full px-2 grow pb-0.5" type="text" name="" id="" placeholder={t("pages.version-viewer.maps.search-bar.search-placeholder")} value={query} onChange={e => setQuery(e.target.value)}/>
<BsmButton className="shrink-0 rounded-full py-1 px-3 !bg-main-color-1 flex justify-center items-center capitalize" icon="search" text="modals.download-maps.search-btn" withBar={false} onClick={e => {e.preventDefault(); handleSearch()}}/>
<BsmSelect className="bg-main-color-1 rounded-full px-1 pb-0.5 text-center" options={sortOptions} onChange={handleSortChange}/>
</div>
<ul className="w-full grow flex content-start flex-wrap gap-2 px-2 overflow-y-scroll overflow-x-hidden scrollbar-thin scrollbar-thumb-rounded-full scrollbar-thumb-neutral-900" >
{maps.length === 0 ? (
<div className="w-full h-full flex flex-col items-center justify-center">
<img className="w-32 h-32 spin-loading" src={BeatWaitingImg}></img>
<span className="text-lg">Chargement des maps...</span> {/* TODO TRANSLATE */}
<span className="text-lg">{t("modals.download-maps.loading-maps")}</span>
</div>
) : (
<>
@@ -0,0 +1,9 @@
import { BsvMapDifficultyType } from "shared/models/maps/beat-saver.model";
export const MAP_DIFFICULTIES_COLORS: Record<BsvMapDifficultyType, string> = {
Easy: "#00FF9E",
Normal: "#00FFFF",
Hard: "#FFA700",
Expert: "#FF4319",
ExpertPlus: "#FF7EFF"
}
@@ -0,0 +1,9 @@
import { BsvMapDifficultyType } from "shared/models/maps/beat-saver.model";
export const MAP_DIFFICULTIES: BsvMapDifficultyType[] = [
"Easy",
"Normal",
"Hard",
"Expert",
"ExpertPlus"
];