From 542638f4d43bce6fb9cfa0cd39aa506ca3866ef9 Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Sun, 22 Mar 2026 23:20:08 +0900 Subject: [PATCH 01/23] =?UTF-8?q?fix:=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20ui?= =?UTF-8?q?=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EB=B2=84=EA=B7=B8=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/popup/index.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/popup/index.css b/src/pages/popup/index.css index 07af1a2..738f9aa 100644 --- a/src/pages/popup/index.css +++ b/src/pages/popup/index.css @@ -68,6 +68,11 @@ button { .popup-container .funcList { padding: 0.5em; max-width: 240px; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + width: 100%; } /* 토글 스위치 스타일 */ @@ -121,10 +126,6 @@ button { margin-top: 3px; } -.popup-container .funcList li { - margin: 0 auto; -} - .btnWrapper button { padding: 4px 20px; border-radius: 3px; From 50b10e779bec9f29528d03fe15efc3f78423f48f Mon Sep 17 00:00:00 2001 From: JeongwooSeo Date: Sun, 22 Mar 2026 23:28:00 +0900 Subject: [PATCH 02/23] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=8A=A5=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=ED=85=8D=EC=8A=A4=ED=8A=B8,=20?= =?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=A5=BC=20=EC=9D=BC=EC=9B=90=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/content/injected/statusIndicator.ts | 21 ++++++++----- src/pages/popup/components/FuncList.tsx | 30 +++++++------------ src/shared/config/features.ts | 13 ++++++++ 3 files changed, 38 insertions(+), 26 deletions(-) create mode 100644 src/shared/config/features.ts diff --git a/src/pages/content/injected/statusIndicator.ts b/src/pages/content/injected/statusIndicator.ts index 273595c..bf38a3f 100644 --- a/src/pages/content/injected/statusIndicator.ts +++ b/src/pages/content/injected/statusIndicator.ts @@ -1,5 +1,6 @@ import { $, create$ } from '@root/utils/dom/utilDOM'; import { AltTag, Command, ImageScale, SEO, TextCounter } from '@pages/content/injected/components/SVG'; +import { FEATURES } from '@src/shared/config/features'; interface FunctionStatus { id: string; @@ -8,15 +9,21 @@ interface FunctionStatus { enabled: boolean; } +const FEATURE_ICONS: Record = { + func_0: Command, + func_1: AltTag, + func_2: ImageScale, + func_3: TextCounter, + func_4: SEO, +}; + const statusIndicator = async () => { // 기능 정의 - const functions: Omit[] = [ - { id: 'func_0', name: chrome.i18n.getMessage('feature_extra_shortcuts'), icon: Command }, - { id: 'func_1', name: chrome.i18n.getMessage('feature_alt_tagger'), icon: AltTag }, - { id: 'func_2', name: chrome.i18n.getMessage('feature_image_resizer'), icon: ImageScale }, - { id: 'func_3', name: chrome.i18n.getMessage('feature_text_counter'), icon: TextCounter }, - { id: 'func_4', name: chrome.i18n.getMessage('feature_seo_checker'), icon: SEO }, - ]; + const functions: Omit[] = FEATURES.map(f => ({ + id: f.key, + name: chrome.i18n.getMessage(f.messageKey), + icon: FEATURE_ICONS[f.key], + })); // 컨테이너 스타일 const containerStyle = { diff --git a/src/pages/popup/components/FuncList.tsx b/src/pages/popup/components/FuncList.tsx index 1b190c5..c8a276c 100644 --- a/src/pages/popup/components/FuncList.tsx +++ b/src/pages/popup/components/FuncList.tsx @@ -1,24 +1,17 @@ import { useState, useEffect } from 'react'; import { getMessage, getAriaLabel } from '@src/shared/utils/i18n'; import NewBadge from './NewBadge'; - -interface FunctionItem { - name: string; - isNew?: boolean; -} +import { FEATURES } from '@src/shared/config/features'; const FuncList = () => { - const funcList: FunctionItem[] = [ - { name: getMessage('feature_extra_shortcuts'), isNew: false }, - { name: getMessage('feature_alt_tagger'), isNew: false }, - { name: getMessage('feature_image_resizer'), isNew: false }, - { name: getMessage('feature_text_counter'), isNew: false }, - { name: getMessage('feature_seo_checker'), isNew: true }, - ]; + const funcList = FEATURES.map(f => ({ + key: f.key, + name: getMessage(f.messageKey), + isNew: f.isNew, + })); const [checkedList, setCheckedList] = useState>({}); - const onChangeCheckBox = (event: React.ChangeEvent, index: number) => { - const funcKey: string = `func_${index}`; + const onChangeCheckBox = (event: React.ChangeEvent, funcKey: string) => { const target = event.target as HTMLInputElement; setCheckedList(prev => { @@ -29,7 +22,7 @@ const FuncList = () => { }; const loadPreChecked = (): void => { - const arr = funcList.map((_, i) => `func_${i}`); + const arr = funcList.map(f => f.key); chrome.storage.local.get(arr, result => { setCheckedList(result); }); @@ -43,16 +36,15 @@ const FuncList = () => {
    {funcList.map((func, i) => { - const key = `func_${i}`; const checkboxId = `feature-checkbox-${i}`; return ( -
  • +
  • onChangeCheckBox(event, i)} + checked={checkedList[func.key] || false} + onChange={event => onChangeCheckBox(event, func.key)} aria-label={getMessage('aria_feature_toggle', [func.name])} />