[Update] Config Window: Add WordFilter. (tmp data)
This commit is contained in:
@@ -17,6 +17,7 @@ export const Appearance = () => {
|
||||
RadioButtonContainer,
|
||||
DeeplAuthKeyContainer,
|
||||
MessageFormatContainer,
|
||||
WordFilterContainer,
|
||||
ActionButtonContainer,
|
||||
} = useSettingBox();
|
||||
|
||||
@@ -58,6 +59,8 @@ export const Appearance = () => {
|
||||
|
||||
<MessageFormatContainer label={t(`config_window.send_message_format_with_t.label`)} desc={t(`config_window.send_message_format_with_t.desc`)} id="received_with_t"/>
|
||||
|
||||
<WordFilterContainer label={t(`config_window.mic_word_filter.label`)} desc={t(`config_window.mic_word_filter.desc`)}/>
|
||||
|
||||
<ActionButtonContainer label={t(`config_window.open_config_filepath.label`)} IconComponent={FolderOpenSvg} OnclickFunction={()=>{}}/>
|
||||
|
||||
</>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { RadioButton } from "./radio_button/RadioButton";
|
||||
import { OpenWebpage_DeeplAuthKey, DeeplAuthKey } from "./deepl_auth_key/DeeplAuthKey";
|
||||
import { MessageFormat } from "./message_format/MessageFormat";
|
||||
import { ActionButton } from "./action_button/ActionButton";
|
||||
import { WordFilter } from "./word_filter/WordFilter";
|
||||
|
||||
export const useSettingBox = () => {
|
||||
const { updateIsOpenedDropdownMenu } = useIsOpenedDropdownMenu();
|
||||
@@ -126,6 +127,20 @@ export const useSettingBox = () => {
|
||||
};
|
||||
|
||||
|
||||
const WordFilterContainer = (props) => {
|
||||
return (
|
||||
<div className={styles.threshold_container}>
|
||||
<div className={styles.threshold_switch_section}>
|
||||
<LabelComponent label={props.label} desc={props.desc} />
|
||||
{/* <ActionButton {...props}/> */}
|
||||
</div>
|
||||
<div className={styles.threshold_section}>
|
||||
<WordFilter {...props}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
DropdownMenuContainer,
|
||||
SliderContainer,
|
||||
@@ -136,6 +151,7 @@ export const useSettingBox = () => {
|
||||
RadioButtonContainer,
|
||||
DeeplAuthKeyContainer,
|
||||
MessageFormatContainer,
|
||||
WordFilterContainer,
|
||||
ActionButtonContainer,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,103 @@
|
||||
import styles from "./WordFilter.module.scss";
|
||||
import { _Entry } from "../_atoms/_entry/_Entry";
|
||||
import { useState } from "react";
|
||||
import { useWordFilterList } from "@store";
|
||||
export const WordFilter = () => {
|
||||
const [input_value, setInputValue] = useState();
|
||||
const { currentWordFilterList, updateWordFilterList } = useWordFilterList();
|
||||
|
||||
const onChangeEntry = (e) => {
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
|
||||
const addWords = () => {
|
||||
const input_value_array = input_value.split(",");
|
||||
|
||||
let updated_list = [...currentWordFilterList];
|
||||
|
||||
for (let each_input_value of input_value_array) {
|
||||
each_input_value = each_input_value.trim();
|
||||
if (each_input_value) {
|
||||
const target_item = updated_list.find((item) => item.value === each_input_value);
|
||||
if (target_item === undefined) {
|
||||
// Add
|
||||
updated_list = [...updated_list, { value: each_input_value, is_redoable: false }];
|
||||
} else {
|
||||
// Update
|
||||
updated_list = updated_list.map(item =>
|
||||
item.value === each_input_value ? { ...item, is_redoable: false } : item
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateWordFilterList(updated_list);
|
||||
};
|
||||
|
||||
|
||||
const updateRedoable = (target_item_value, is_redoable) => {
|
||||
updateWordFilterList((prev_list) =>
|
||||
prev_list.map(item =>
|
||||
item.value === target_item_value ? { ...item, is_redoable: is_redoable } : item
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const deleteAction = (target_item_value) => {
|
||||
updateRedoable(target_item_value, true);
|
||||
};
|
||||
|
||||
const redoAction = (target_item_value) => {
|
||||
updateRedoable(target_item_value, false);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.list_section_wrapper}>
|
||||
{
|
||||
currentWordFilterList.map((item, index) => {
|
||||
return <WordFilterItem value={item.value} key={index} is_redoable={item.is_redoable} deleteAction={deleteAction} redoAction={redoAction}/>;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<div className={styles.entry_section_wrapper}>
|
||||
<_Entry width="30rem" onChange={onChangeEntry}/>
|
||||
<button className={styles.add_button} onClick={addWords}>Add</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
import DeleteSvg from "@images/cancel.svg?react";
|
||||
import RedoSvg from "@images/redo.svg?react";
|
||||
import clsx from "clsx";
|
||||
const WordFilterItem = (props) => {
|
||||
|
||||
|
||||
const item_wrapper_class_names = clsx(styles["item_wrapper"], {
|
||||
[styles["is_redoable"]]: props.is_redoable
|
||||
});
|
||||
|
||||
const item_text_class_names = clsx(styles["item_text"], {
|
||||
[styles["is_redoable"]]: props.is_redoable
|
||||
});
|
||||
|
||||
const target_item_value = props.value;
|
||||
|
||||
return (
|
||||
<div className={item_wrapper_class_names}>
|
||||
<p className={item_text_class_names}>{target_item_value}</p>
|
||||
{props.is_redoable
|
||||
?
|
||||
<button className={clsx(styles.action_button, styles.redo)} onClick={() => props.redoAction(target_item_value)}>
|
||||
<RedoSvg className={styles.redo_svg}/>
|
||||
</button>
|
||||
:
|
||||
<button className={clsx(styles.action_button, styles.delete)} onClick={() => props.deleteAction(target_item_value)}>
|
||||
<DeleteSvg className={styles.delete_svg}/>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
|
||||
.list_section_wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
gap: 0.6rem;
|
||||
overflow-y: auto;
|
||||
max-height: 20rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.item_wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
background-color: var(--dark_800_color);
|
||||
padding: 0.2rem 0.2rem 0.2rem 1rem;
|
||||
border-radius: 0.4rem;
|
||||
&.is_redoable {
|
||||
background-color: var(--dark_850_color);
|
||||
}
|
||||
}
|
||||
.item_text {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 300;
|
||||
color: var(--dark_basic_text_color);
|
||||
&.is_redoable {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.action_button {
|
||||
border-radius: 0.4rem;
|
||||
&:hover {
|
||||
background-color: var(--dark_750_color);
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--dark_850_color);
|
||||
}
|
||||
&.delete {
|
||||
padding: 0.2rem;
|
||||
}
|
||||
&.redo {
|
||||
padding: 0.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.delete_svg {
|
||||
width: 2.4rem;
|
||||
color: #bb4448;
|
||||
}
|
||||
|
||||
.redo_svg {
|
||||
width: 1.6rem;
|
||||
color: var(--dark_500_color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.entry_section_wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.add_button {
|
||||
padding: 0.8rem 1.2rem;
|
||||
background-color: var(--primary_600_color);
|
||||
color: var(--dark_basic_text_color);
|
||||
font-size: 1.4rem;
|
||||
border-radius: 0.4rem;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
&:hover {
|
||||
background-color: var(--primary_500_color);
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--primary_700_color);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user