[Update] Combine in one window. Rename Main/Config Window to Main/Config Page accordingly.

For now, I put Config Page to below the main page temporary. Open Config Button does not work.
This commit is contained in:
Sakamoto Shiina
2024-08-09 12:23:17 +09:00
parent af1cdd2d7b
commit 3ed3d5eb40
118 changed files with 175 additions and 192 deletions

View File

@@ -0,0 +1,101 @@
import { useTranslation } from "react-i18next";
import styles from "./LanguageSettings.module.scss";
import { PresetTabSelector } from "./preset_tab_selector/PresetTabSelector";
import { LanguageSelectorOpenButton } from "./language_selector_open_button/LanguageSelectorOpenButton";
import { LanguageSwapButton } from "./language_swap_button/LanguageSwapButton";
import { TranslatorSelectorOpenButton } from "./translator_selector_open_button/TranslatorSelectorOpenButton";
import { useIsOpenedTranslatorSelector } from "@store";
export const LanguageSettings = () => {
const { updateIsOpenedTranslatorSelector} = useIsOpenedTranslatorSelector();
const closeTranslatorSelector = () => updateIsOpenedTranslatorSelector(false);
return (
<div className={styles.container} onMouseLeave={closeTranslatorSelector} >
<p className={styles.title}>Language Settings</p>
<PresetTabSelector />
<PresetContainer />
</div>
);
};
import MicSvg from "@images/mic.svg?react";
import HeadphonesSvg from "@images/headphones.svg?react";
import { useIsOpenedLanguageSelector } from "@store";
import { useMainFunction } from "@logics/useMainFunction";
const PresetContainer = () => {
const { t } = useTranslation();
const { updateIsOpenedLanguageSelector, currentIsOpenedLanguageSelector } = useIsOpenedLanguageSelector();
const {
currentTranscriptionSendStatus,
currentTranscriptionReceiveStatus,
} = useMainFunction();
const closeLanguageSelector = () => {
updateIsOpenedLanguageSelector({
your_language: false,
target_language: false,
});
};
const toggleYourLanguageSelector = () => {
if (currentIsOpenedLanguageSelector.your_language === true) {
closeLanguageSelector();
} else {
updateIsOpenedLanguageSelector({
your_language: true,
target_language: false,
});
}
};
const toggleTargetLanguageSelector = () => {
if (currentIsOpenedLanguageSelector.target_language === true) {
closeLanguageSelector();
} else {
updateIsOpenedLanguageSelector({
your_language: false,
target_language: true,
});
}
};
const handleLanguageSelectorClick = (selector) => {
if (selector === "your_language") {
toggleYourLanguageSelector();
} else if (selector === "target_language") {
toggleTargetLanguageSelector();
}
};
const your_language_settings = {
title: t("main_page.your_language"),
is_opened: currentIsOpenedLanguageSelector.your_language,
onClickFunction: () => handleLanguageSelectorClick("your_language"),
TurnedOnSvgComponent: <MicSvg />,
is_turned_on: currentTranscriptionSendStatus.data,
};
const target_language_settings = {
title: t("main_page.target_language"),
is_opened: currentIsOpenedLanguageSelector.target_language,
onClickFunction: () => handleLanguageSelectorClick("target_language"),
TurnedOnSvgComponent: <HeadphonesSvg />,
is_turned_on: currentTranscriptionReceiveStatus.data,
};
return (
<div className={styles.preset_container}>
<LanguageSelectorOpenButton {...your_language_settings} />
<LanguageSwapButton />
<LanguageSelectorOpenButton {...target_language_settings} />
<TranslatorSelectorOpenButton />
</div>
);
};

View File

@@ -0,0 +1,21 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.title {
font-size: 1.4rem;
padding-top: 1rem;
padding-bottom: 0.8rem;
color: var(--dark_400_color);
}
.preset_container {
width: 100%;
padding-top: 0.8rem;
background-color: var(--dark_800_color);
display: flex;
flex-direction: column;
align-items: center;
}

View File

@@ -0,0 +1,34 @@
import clsx from "clsx";
import styles from "./LanguageSelectorOpenButton.module.scss";
import ArrowLeftSvg from "@images/arrow_left.svg?react";
import { useSvg } from "@utils/useSvg";
export const LanguageSelectorOpenButton = (props) => {
const toggleLanguageSelector = () => {
props.onClickFunction();
};
const class_names = clsx(styles["arrow_left_svg"], {
[styles["reverse"]]: props.is_opened
});
const SvgComponent = useSvg(props.TurnedOnSvgComponent,
{className: clsx(styles["category_svg"], {
[styles["is_turned_on"]]: props.is_turned_on
})}
);
return (
<div className={styles.container}>
<div className={styles.title_container}>
{SvgComponent}
<p className={styles.title}>{props.title}</p>
</div>
<div className={styles.dropdown_menu_container} onClick={toggleLanguageSelector}>
<p className={styles.selected_language}>Japanese</p>
<p className={styles.selected_language}>(Japan)</p>
<ArrowLeftSvg className={class_names} />
</div>
</div>
);
};

View File

@@ -0,0 +1,73 @@
.container {
width: 100%;
background-color: var(--dark_825_color);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0.8rem;
gap: 0.8rem;
}
.title_container {
position: relative;
width: 100%;
display: flex;
justify-content: center;
text-align: center;
}
.category_svg {
position: absolute;
top: 50%;
left: 1.2rem;
transform: translate(-50%, -50%);
width: 1.4rem;
color: var(--dark_400_color);
display: none;
&.is_turned_on {
display: block;
}
}
.title {
font-size: 1.6rem;
color: var(--dark_400_color);
}
.dropdown_menu_container {
position: relative;
background-color: var(--dark_888_color);
width: 100%;
padding: 0.2rem 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 0.4rem;
gap: 0.2rem;
cursor: pointer;
&:hover {
background-color: var(--dark_875_color);
}
&:active {
background-color: var(--dark_900_color);
}
}
.selected_language {
font-size: 1.2rem;
color: var(--dark_basic_text_color);
}
.arrow_left_svg {
position: absolute;
right: 0;
margin: 0 0.2rem;
transform: rotate(180deg);
width: 1.6rem;
color: var(--dark_basic_text_color);
&.reverse {
transform: rotate(0deg);
}
}

View File

@@ -0,0 +1,37 @@
import { useState } from "react";
import clsx from "clsx";
import { useTranslation } from "react-i18next";
import styles from "./LanguageSwapButton.module.scss";
import NarrowArrowDownSvg from "@images/narrow_arrow_down.svg?react";
export const LanguageSwapButton = () => {
const [isHovered, setIsHovered] = useState(false);
const { t } = useTranslation();
const label = isHovered
? t("main_page.swap_button_label")
: t("main_page.translate_each_other_label");
const labelClassName = clsx(styles["label"], {
[styles["is_hovered"]]: isHovered
});
const handleMouseEnter = () => setIsHovered(true);
const handleMouseLeave = () => setIsHovered(false);
return (
<div className={styles.container}>
<div
className={styles.swap_button_wrapper}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<NarrowArrowDownSvg className={clsx(styles.narrow_arrow_down_svg, styles.reverse)} />
<p className={labelClassName}>{label}</p>
<NarrowArrowDownSvg className={styles.narrow_arrow_down_svg} />
</div>
</div>
);
};

View File

@@ -0,0 +1,36 @@
.container {
width: 100%;
}
.swap_button_wrapper {
width: auto;
display: flex;
justify-content: space-between;
align-items: center;
margin: 0.8rem 2rem;
padding: 0.4rem 0.8rem;
border-radius: 0.6rem;
cursor: pointer;
&:hover {
background-color: var(--dark_750_color);
}
&:active {
background-color: var(--dark_850_color);
}
}
.narrow_arrow_down_svg {
width: 1.6rem;
color: var(--dark_500_color);
&.reverse {
transform: rotate(180deg);
}
}
.label {
font-size: 1.2rem;
color: var(--dark_500_color);
&.is_hovered {
color: var(--dark_basic_text_color);
}
}

View File

@@ -0,0 +1,32 @@
import styles from "./PresetTabSelector.module.scss";
export const PresetTabSelector = () => {
return (
<div className={styles.container}>
<Tab preset_number={1} />
<Tab preset_number={2} />
<Tab preset_number={3} />
</div>
);
};
import clsx from "clsx";
import { useSelectedPresetTabStatus } from "@store";
const Tab = (props) => {
const { updateSelectedPresetTabStatus, currentSelectedPresetTabStatus } = useSelectedPresetTabStatus();
const onclickFunction = () => {
updateSelectedPresetTabStatus(props.preset_number);
};
const class_names = clsx(styles["tab_container"], {
[styles["is_selected"]]: (currentSelectedPresetTabStatus === props.preset_number) ? true : false
});
return (
<div className={class_names} onClick={onclickFunction}>
<p className={styles.tab_number}>{props.preset_number}</p>
</div>
);
};

View File

@@ -0,0 +1,32 @@
.container {
width: 100%;
display: flex;
justify-content: space-between;
}
.tab_container {
height: 3rem;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 0.6rem 0.6rem 0 0;
color: var(--dark_600_color);
cursor: pointer;
&:hover {
background-color: var(--dark_825_color);
}
&:active {
background-color: var(--dark_875_color);
}
&.is_selected {
background-color: var(--dark_800_color);
color: var(--dark_basic_text_color);
cursor: default;
pointer-events: none;
}
}
.tab_number {
font-size: 1.6rem;
}

View File

@@ -0,0 +1,28 @@
import { useTranslation } from "react-i18next";
import styles from "./TranslatorSelectorOpenButton.module.scss";
import { TranslatorSelector } from "./translator_selector/TranslatorSelector";
import { useTranslatorListStatus, useSelectedTranslatorIdStatus, useIsOpenedTranslatorSelector } from "@store";
export const TranslatorSelectorOpenButton = () => {
const { t } = useTranslation();
const { currentSelectedTranslatorIdStatus } = useSelectedTranslatorIdStatus();
const { currentTranslatorListStatus } = useTranslatorListStatus();
const currentTranslator = currentTranslatorListStatus.find(
translator_data => translator_data.translator_key === currentSelectedTranslatorIdStatus
);
const { currentIsOpenedTranslatorSelector, updateIsOpenedTranslatorSelector} = useIsOpenedTranslatorSelector();
const openTranslatorSelector = () => updateIsOpenedTranslatorSelector(!currentIsOpenedTranslatorSelector);
return (
<div className={styles.container}>
<div className={styles.translator_selector_button} onClick={openTranslatorSelector}>
<p className={styles.label}>{t("main_page.translator")}</p>
<p className={styles.label}>{currentTranslator?.translator_name}</p>
</div>
{currentIsOpenedTranslatorSelector && <TranslatorSelector />}
</div>
);
};

View File

@@ -0,0 +1,27 @@
.container {
position: relative;
width: 100%;
}
.translator_selector_button {
width: auto;
display: flex;
justify-content: center;
align-items: center;
gap: 0.2rem;
margin: 0.4rem;
padding: 0.6rem 0;
border-radius: 0.6rem;
cursor: pointer;
&:hover {
background-color: var(--dark_875_color);
}
&:active {
background-color: var(--dark_900_color);
}
}
.label {
font-size: 1.2rem;
color: var(--dark_basic_text_color);
}

View File

@@ -0,0 +1,49 @@
import styles from "./TranslatorSelector.module.scss";
import { chunkArray } from "@utils/chunkArray";
import { useTranslatorListStatus, useSelectedTranslatorIdStatus, useIsOpenedTranslatorSelector } from "@store";
export const TranslatorSelector = () => {
const { currentTranslatorListStatus } = useTranslatorListStatus();
const columns = chunkArray(currentTranslatorListStatus, 2);
return (
<div className={styles.container}>
<div className={styles.wrapper}>
{columns.map((column, column_index) => (
<div className={styles.column_wrapper} key={`column_${column_index}`}>
{column.map(({ translator_key, translator_name, is_available }) => (
<TranslatorBox
key={translator_key}
translator_id={translator_key}
translator_name={translator_name}
is_available={is_available}
/>
))}
</div>
))}
</div>
</div>
);
};
import clsx from "clsx";
const TranslatorBox = (props) => {
const { currentSelectedTranslatorIdStatus, updateSelectedTranslatorIdStatus} = useSelectedTranslatorIdStatus();
const { updateIsOpenedTranslatorSelector} = useIsOpenedTranslatorSelector();
const box_class_name = clsx(
styles.box,
{ [styles["is_selected"]]: (currentSelectedTranslatorIdStatus === props.translator_id) ? true : false },
{ [styles["is_available"]]: (props.is_available === true) ? true : false }
);
const selectTranslator = () => {
updateSelectedTranslatorIdStatus(props.translator_id);
updateIsOpenedTranslatorSelector(false);
};
return (
<div className={box_class_name} onClick={selectTranslator}>
<p className={styles.translator_name}>{props.translator_name}</p>
</div>
);
};

View File

@@ -0,0 +1,63 @@
.container {
position: absolute;
bottom: 100%;
width: 100%;
height: 26rem;
padding: 1rem;
background-color: (#000000dd);
// background-color: (var(--dark_875_color) + 80);
backdrop-filter: blur(0.1rem);
display: flex;
justify-content: center;
align-items: center;
}
.wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 1rem;
}
.column_wrapper {
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
}
$box_size: 6.8rem;
.box {
width: $box_size;
height: $box_size;
background-color: var(--dark_875_color);
display: flex;
justify-content: center;
align-items: center;
white-space: pre-wrap;
text-align: center;
border-radius: 0.6rem;
cursor: pointer;
&:hover {
background-color: var(--dark_825_color);
}
&:active {
background-color: var(--dark_900_color);
border: 0.1rem solid var(--primary_300_color);
}
&.is_selected {
border: 0.2rem solid var(--primary_300_color);
}
&:not(.is_available) {
pointer-events: none;
background-color: var(--dark_950_color);
& .translator_name {
color: var(--dark_600_color);
}
}
}
.translator_name {
font-size: 1.4rem;
}