[Update] Config Window: Add WordFilter. (tmp data)
This commit is contained in:
56
data.js
56
data.js
@@ -89,3 +89,59 @@ export const generateTestData = (num) => {
|
|||||||
|
|
||||||
return testDataArray;
|
return testDataArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const word_filter_list = [
|
||||||
|
{ value: "りんご", is_redoable: false },
|
||||||
|
{ value: "forest", is_redoable: false },
|
||||||
|
{ value: "もり", is_redoable: false },
|
||||||
|
{ value: "elephant", is_redoable: false },
|
||||||
|
{ value: "penguin", is_redoable: false },
|
||||||
|
{ value: "やま", is_redoable: false },
|
||||||
|
{ value: "notebook", is_redoable: false },
|
||||||
|
{ value: "zebra", is_redoable: false },
|
||||||
|
{ value: "ちょう", is_redoable: false },
|
||||||
|
{ value: "dinosaur", is_redoable: false },
|
||||||
|
{ value: "たいこ", is_redoable: false },
|
||||||
|
{ value: "カンガルー", is_redoable: false },
|
||||||
|
{ value: "ふうせん", is_redoable: false },
|
||||||
|
{ value: "candle", is_redoable: false },
|
||||||
|
{ value: "tiger", is_redoable: false },
|
||||||
|
{ value: "umbrella", is_redoable: false },
|
||||||
|
{ value: "garden", is_redoable: false },
|
||||||
|
{ value: "ペンギン", is_redoable: false },
|
||||||
|
{ value: "ひまわり", is_redoable: false },
|
||||||
|
{ value: "kangaroo", is_redoable: false },
|
||||||
|
{ value: "とうだい", is_redoable: false },
|
||||||
|
{ value: "シロフォン", is_redoable: false },
|
||||||
|
{ value: "ひこうき", is_redoable: false },
|
||||||
|
{ value: "しろ", is_redoable: false },
|
||||||
|
{ value: "しあわせ", is_redoable: false },
|
||||||
|
{ value: "xylophone", is_redoable: false },
|
||||||
|
{ value: "volcano", is_redoable: false },
|
||||||
|
{ value: "drum", is_redoable: false },
|
||||||
|
{ value: "lighthouse", is_redoable: false },
|
||||||
|
{ value: "quicksand", is_redoable: false },
|
||||||
|
{ value: "airplane", is_redoable: false },
|
||||||
|
{ value: "しまうま", is_redoable: false },
|
||||||
|
{ value: "sunflower", is_redoable: false },
|
||||||
|
{ value: "ジャングル", is_redoable: false },
|
||||||
|
{ value: "くじら", is_redoable: false },
|
||||||
|
{ value: "apple", is_redoable: false },
|
||||||
|
{ value: "island", is_redoable: false },
|
||||||
|
{ value: "ocean", is_redoable: false },
|
||||||
|
{ value: "rainbow", is_redoable: false },
|
||||||
|
{ value: "castle", is_redoable: false },
|
||||||
|
{ value: "かさ", is_redoable: false },
|
||||||
|
{ value: "ぞう", is_redoable: false },
|
||||||
|
{ value: "balloon", is_redoable: false },
|
||||||
|
{ value: "happiness", is_redoable: false },
|
||||||
|
{ value: "whale", is_redoable: false },
|
||||||
|
{ value: "にじ", is_redoable: false },
|
||||||
|
{ value: "ヨット", is_redoable: false },
|
||||||
|
{ value: "しま", is_redoable: false },
|
||||||
|
{ value: "かざん", is_redoable: false },
|
||||||
|
{ value: "ノート", is_redoable: false },
|
||||||
|
{ value: "mountain", is_redoable: false },
|
||||||
|
{ value: "うみ", is_redoable: false },
|
||||||
|
{ value: "ジャングル", is_redoable: false },
|
||||||
|
];
|
||||||
1
src-ui/assets/cancel.svg
Normal file
1
src-ui/assets/cancel.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 10.93 5.719-5.72c.146-.146.339-.219.531-.219.404 0 .75.324.75.749 0 .193-.073.385-.219.532l-5.72 5.719 5.719 5.719c.147.147.22.339.22.531 0 .427-.349.75-.75.75-.192 0-.385-.073-.531-.219l-5.719-5.719-5.719 5.719c-.146.146-.339.219-.531.219-.401 0-.75-.323-.75-.75 0-.192.073-.384.22-.531l5.719-5.719-5.72-5.719c-.146-.147-.219-.339-.219-.532 0-.425.346-.749.75-.749.192 0 .385.073.531.219z"/></svg>
|
||||||
|
After Width: | Height: | Size: 557 B |
1
src-ui/assets/redo.svg
Normal file
1
src-ui/assets/redo.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 0c3.31 0 6.291 1.353 8.459 3.522l2.48-2.48 1.061 7.341-7.437-.966 2.489-2.489c-1.808-1.807-4.299-2.928-7.052-2.928-5.514 0-10 4.486-10 10s4.486 10 10 10c3.872 0 7.229-2.216 8.89-5.443l1.717 1.046c-2.012 3.803-6.005 6.397-10.607 6.397-6.627 0-12-5.373-12-12s5.373-12 12-12z"/></svg>
|
||||||
|
After Width: | Height: | Size: 354 B |
@@ -4,7 +4,12 @@ import {
|
|||||||
useSetAtom
|
useSetAtom
|
||||||
} from "jotai";
|
} from "jotai";
|
||||||
|
|
||||||
import { translator_list, test_device_list, generateTestData } from "@data";
|
import {
|
||||||
|
translator_list,
|
||||||
|
test_device_list,
|
||||||
|
generateTestData,
|
||||||
|
word_filter_list,
|
||||||
|
} from "@data";
|
||||||
|
|
||||||
export const store = {
|
export const store = {
|
||||||
backend_subprocess: null,
|
backend_subprocess: null,
|
||||||
@@ -133,6 +138,8 @@ export const { atomInstance: Atom_ReceivedMessageFormatWithT, useHook: useReceiv
|
|||||||
is_message_first: true,
|
is_message_first: true,
|
||||||
}, "ReceivedMessageFormatWithT");
|
}, "ReceivedMessageFormatWithT");
|
||||||
|
|
||||||
|
export const { atomInstance: Atom_WordFilterList, useHook: useWordFilterList } = createAtomWithHook(word_filter_list, "WordFilterList");
|
||||||
|
|
||||||
|
|
||||||
export const { atomInstance: Atom_TranslatorListStatus, useHook: useTranslatorListStatus } = createAtomWithHook(translator_list, "TranslatorListStatus");
|
export const { atomInstance: Atom_TranslatorListStatus, useHook: useTranslatorListStatus } = createAtomWithHook(translator_list, "TranslatorListStatus");
|
||||||
export const { atomInstance: Atom_SelectedTranslatorIdStatus, useHook: useSelectedTranslatorIdStatus } = createAtomWithHook("CTranslate2", "SelectedTranslatorIdStatus");
|
export const { atomInstance: Atom_SelectedTranslatorIdStatus, useHook: useSelectedTranslatorIdStatus } = createAtomWithHook("CTranslate2", "SelectedTranslatorIdStatus");
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const Appearance = () => {
|
|||||||
RadioButtonContainer,
|
RadioButtonContainer,
|
||||||
DeeplAuthKeyContainer,
|
DeeplAuthKeyContainer,
|
||||||
MessageFormatContainer,
|
MessageFormatContainer,
|
||||||
|
WordFilterContainer,
|
||||||
ActionButtonContainer,
|
ActionButtonContainer,
|
||||||
} = useSettingBox();
|
} = 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"/>
|
<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={()=>{}}/>
|
<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 { OpenWebpage_DeeplAuthKey, DeeplAuthKey } from "./deepl_auth_key/DeeplAuthKey";
|
||||||
import { MessageFormat } from "./message_format/MessageFormat";
|
import { MessageFormat } from "./message_format/MessageFormat";
|
||||||
import { ActionButton } from "./action_button/ActionButton";
|
import { ActionButton } from "./action_button/ActionButton";
|
||||||
|
import { WordFilter } from "./word_filter/WordFilter";
|
||||||
|
|
||||||
export const useSettingBox = () => {
|
export const useSettingBox = () => {
|
||||||
const { updateIsOpenedDropdownMenu } = useIsOpenedDropdownMenu();
|
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 {
|
return {
|
||||||
DropdownMenuContainer,
|
DropdownMenuContainer,
|
||||||
SliderContainer,
|
SliderContainer,
|
||||||
@@ -136,6 +151,7 @@ export const useSettingBox = () => {
|
|||||||
RadioButtonContainer,
|
RadioButtonContainer,
|
||||||
DeeplAuthKeyContainer,
|
DeeplAuthKeyContainer,
|
||||||
MessageFormatContainer,
|
MessageFormatContainer,
|
||||||
|
WordFilterContainer,
|
||||||
ActionButtonContainer,
|
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