Skip to content

Feature/ux #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Nov 25, 2024
Merged

Feature/ux #101

merged 19 commits into from
Nov 25, 2024

Conversation

guesung
Copy link
Owner

@guesung guesung commented Nov 25, 2024

Summary by CodeRabbit

  • 새로운 기능

    • ExtensionDialog 컴포넌트 추가: 확장 프로그램 설치 및 업데이트 관련 대화 상자를 표시합니다.
    • useGetExtensionManifest 훅 추가: 확장 프로그램의 매니페스트를 가져오는 기능을 제공합니다.
    • 새로운 타입 MemoInputCategoryInput 추가: 메모 및 카테고리 입력 데이터를 구조적으로 표현합니다.
  • 버그 수정

    • 로컬 스토리지 키 관리 개선: LocalStorage 유틸리티를 통해 로컬 스토리지 접근 및 검증 로직을 단순화했습니다.
  • 문서화

    • 번역 JSON 파일 업데이트: 새로운 메시지 및 수정된 문구 추가로 사용자 인터페이스 개선.

Copy link

coderabbitai bot commented Nov 25, 2024

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

이번 변경 사항은 EXTENSION_ID라는 상수를 EXTENSION 객체로 대체하여 여러 관련 값을 포함하도록 수정했습니다. 이 객체는 idlastVersion 속성을 포함합니다. 또한 여러 파일에서 이 새로운 구조를 사용하도록 업데이트되었으며, 새로운 ExtensionDialog 구성 요소와 관련된 여러 기능이 추가되었습니다. 이 외에도 여러 타입과 유틸리티 함수가 새로 추가되거나 수정되었습니다.

Changes

파일 경로 변경 요약
packages/shared/src/constants/Extension.ts EXTENSION_IDEXTENSION 객체로 변경, idlastVersion 속성 추가
packages/shared/src/utils/extension/bridge/getExtensionManifest.ts EXTENSION_IDEXTENSION으로 변경, 메시지 전송 시 EXTENSION.id 사용
packages/shared/src/utils/extension/bridge/getSidePanelOpen.ts EXTENSION_IDEXTENSION으로 변경, 메시지 전송 시 EXTENSION.id 사용
packages/shared/src/utils/extension/bridge/refetchTheMemos.ts EXTENSION_IDEXTENSION으로 변경, 메시지 전송 시 EXTENSION.id 사용
packages/web/src/app/[lng]/layout.tsx ExtensionDialog 구성 요소 추가, lng prop 전달
packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx 상태 관리 제거, useGetExtensionManifest 사용하여 버전 표시 로직 간소화
packages/web/src/app/[lng]/login/components/LoginSection/index.tsx ExtensionVersion 구성 요소 제거
packages/web/src/app/[lng]/memos/components/Header/RefreshButton.tsx window.localStorage.setItemLocalStorage.setTrue로 변경
packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx InputTypeMemoInput으로 변경, useForm에서 새로운 타입 사용
packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx CategoryFormInputCategoryInput으로 변경, useForm에서 새로운 타입 사용
packages/web/src/app/[lng]/memos/components/MemoView/MemoItem.tsx MemoOption의 prop idmemoId로 변경
packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx idmemoId로 변경, 관련 로직 수정
packages/web/src/app/[lng]/memos/constants/guide.ts IS_USER_SEEN_GUIDE 상수 파일 삭제
packages/web/src/app/[lng]/memos/constants/index.ts guide 모듈의 재수출 파일 삭제
packages/web/src/app/[lng]/memos/hooks/useGuide.ts IS_USER_SEEN_GUIDELocalStorage.check로 변경
packages/web/src/app/[lng]/memos/types/Input.ts CategoryInputMemoInput 타입 추가
packages/web/src/app/[lng]/memos/types/index.ts Input 모듈의 모든 엔티티 재수출
packages/web/src/app/[lng]/memos/utils/guide.ts IS_USER_SEEN_GUIDELocalStorage로 변경
packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts getExtensionDialogInfo 함수 추가
packages/web/src/app/components/ExtensionDialog/index.tsx ExtensionDialog 구성 요소 추가
packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts useExtensionDialog 커스텀 훅 추가
packages/web/src/app/components/index.ts ExtensionDialog의 새로운 재수출 추가
packages/web/src/app/i18n/client.js useTranslation 함수 수정, 언어 변경 처리 로직 추가
packages/web/src/app/i18n/locales/en/translation.json 여러 새로운 키 및 수정된 번역 추가
packages/web/src/app/i18n/locales/ko/translation.json 한국어 번역에 여러 새로운 키 및 수정된 번역 추가
packages/web/src/hooks/index.ts useGetExtensionManifest 훅 추가
packages/web/src/hooks/useGetExtensionManifest.ts useGetExtensionManifest 커스텀 훅 추가
packages/web/src/utils/LocalStorage.ts 로컬 스토리지 관리 유틸리티 추가
packages/web/src/utils/index.ts LocalStorage 모듈의 모든 엔티티 재수출
packages/web/tsconfig.json TypeScript 설정에 target 속성 추가
pages/side-panel/src/components/MemoForm.tsx InputTypeMemoInput으로 변경
pages/side-panel/src/types/Input.ts MemoInput 인터페이스 추가

Poem

🐰 변화의 바람이 불어와
새로운 길을 열어주네,
확장된 대화의 창이 열리니,
우리 함께 나아가요,
메모의 세계로,
새로운 시작을 축하해요! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@guesung
Copy link
Owner Author

guesung commented Nov 25, 2024

@coderabbitai review

Copy link

coderabbitai bot commented Nov 25, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@guesung
Copy link
Owner Author

guesung commented Nov 25, 2024

@coderabbitai full review

Copy link

coderabbitai bot commented Nov 25, 2024

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Outside diff range and nitpick comments (33)
packages/web/src/app/[lng]/memos/types/index.ts (1)

1-1: 배럴 파일 패턴이 잘 적용되었습니다!

배럴 파일을 사용하여 타입을 재내보내는 것은 좋은 방식입니다. 이는 다음과 같은 이점이 있습니다:

  • 타입 가져오기를 단순화
  • 코드 구성을 개선
  • 향후 타입 확장 시 유연성 제공
pages/side-panel/src/types/Input.ts (1)

1-4: 인터페이스 구조가 명확하고 잘 정의되어 있습니다.

인터페이스의 구조가 간단하면서도 목적에 맞게 잘 설계되어 있습니다. 하지만 더 나은 문서화를 위해 JSDoc 주석을 추가하는 것을 제안드립니다.

다음과 같이 JSDoc 주석을 추가하는 것을 고려해보세요:

+/**
+ * 메모 입력을 위한 인터페이스
+ * @property {string} memo - 메모 내용
+ * @property {boolean} isWish - 소원 메모 여부
+ */
 export interface MemoInput {
   memo: string;
   isWish: boolean;
 }
packages/shared/src/constants/Extension.ts (1)

3-3: 버전 관리 방식 개선이 필요합니다

하드코딩된 버전 문자열은 유지보수에 어려움을 줄 수 있습니다.

다음과 같은 개선 방안을 고려해보시기 바랍니다:

  1. 패키지의 version 필드에서 동적으로 버전을 가져오기
  2. 환경 변수를 통한 버전 관리
  3. 빌드 시점에 자동으로 버전을 주입하는 방식 도입

이러한 방식을 통해 버전 관리의 일관성을 유지하고 실수를 방지할 수 있습니다.

packages/web/src/app/[lng]/memos/types/Input.ts (2)

1-3: 인터페이스에 JSDoc 문서를 추가하는 것이 좋습니다.

인터페이스의 목적과 사용 사례를 명확히 하기 위해 JSDoc 문서를 추가하는 것을 권장드립니다.

다음과 같이 문서를 추가해보세요:

+/**
+ * 카테고리 입력을 위한 인터페이스
+ * @property category - 카테고리 이름
+ */
export interface CategoryInput {
  category: string;
}

5-7: 타입 정의의 일관성 개선이 필요합니다.

CategoryInput과의 일관성을 위해 type 대신 interface를 사용하고, JSDoc 문서를 추가하는 것이 좋습니다.

다음과 같이 수정해보세요:

-export type MemoInput = {
-  memo: string;
-};
+/**
+ * 메모 입력을 위한 인터페이스
+ * @property memo - 메모 내용
+ */
+export interface MemoInput {
+  memo: string;
+}
packages/web/tsconfig.json (1)

15-15: 더 최신 버전의 ECMAScript 타겟 사용을 고려해보세요.

ES2015는 상대적으로 오래된 버전입니다. 최신 브라우저들은 더 새로운 ECMAScript 기능들을 지원하므로, 다음과 같은 최신 타겟 버전 사용을 고려해보시기 바랍니다:

  • ES2020: 최신 기능 지원과 브라우저 호환성의 좋은 균형
  • ES2022: 가장 최신 기능 활용 가능

더 새로운 타겟을 사용하면 다음과 같은 이점이 있습니다:

  • 더 간결하고 현대적인 코드 작성 가능
  • 더 효율적인 JavaScript 출력
  • 새로운 JavaScript 기능들의 활용
-    "target": "ES2015"
+    "target": "ES2020"
packages/web/src/hooks/useGetExtensionManifest.ts (2)

10-10: 매니페스트 요청 실패 시 재시도 로직 추가 검토

확장 프로그램 매니페스트 요청이 실패할 경우를 대비한 재시도 로직 추가를 고려해보시는 것이 좋을 것 같습니다.


6-6: 타입 안전성 개선이 필요합니다.

매니페스트의 타입을 더 구체적으로 정의하면 좋을 것 같습니다.

interface ExtensionManifest extends chrome.runtime.Manifest {
  // 필요한 추가 필드들을 정의
  version: string;
  name: string;
  description?: string;
}
packages/shared/src/utils/extension/bridge/getExtensionManifest.ts (1)

Line range hint 1-11: 코드의 전반적인 구조와 에러 처리 개선이 필요합니다.

현재 구현에서 몇 가지 개선할 부분이 있습니다:

  1. Chrome API 호출 시 에러 처리가 없습니다
  2. 콜백 함수의 타입 안전성을 높일 수 있습니다

다음과 같은 개선을 제안드립니다:

 import { EXTENSION } from '@src/constants';
 import { Runtime } from '../module';
 
+type ManifestCallback = (response: chrome.runtime.Manifest) => void;
+
 export const BRIDGE_TYPE_GET_EXTENSION_MANIFEST = 'BRIDGE_TYPE_GET_EXTENSION_MANIFEST';
-export const requestGetExtensionManifest = (callbackFn: (response: chrome.runtime.Manifest) => void) => {
-  chrome.runtime.sendMessage(EXTENSION.id, { type: BRIDGE_TYPE_GET_EXTENSION_MANIFEST }, callbackFn);
+export const requestGetExtensionManifest = (callbackFn: ManifestCallback) => {
+  try {
+    chrome.runtime.sendMessage(
+      EXTENSION.id,
+      { type: BRIDGE_TYPE_GET_EXTENSION_MANIFEST },
+      (response: chrome.runtime.Manifest | undefined) => {
+        if (chrome.runtime.lastError) {
+          console.error('Extension manifest request failed:', chrome.runtime.lastError);
+          return;
+        }
+        if (response) callbackFn(response);
+      }
+    );
+  } catch (error) {
+    console.error('Failed to send message to extension:', error);
+  }
 };
packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx (2)

13-15: 매니페스트 처리 로직 개선이 필요합니다

매니페스트가 없을 때 단순히 반환하는 것보다 사용자에게 더 명확한 피드백을 제공하는 것이 좋을 것 같습니다.

다음과 같이 수정하는 것을 제안드립니다:

  const manifest = useGetExtensionManifest();

-  if (!manifest) return;
+  if (!manifest) return (
+    <p className="absolute bottom-2 right-2 w-full text-end text-sm text-red-500">
+      {t('version.extensionNotFound')}
+    </p>
+  );

17-21: 접근성 개선이 필요합니다

버전 정보를 표시하는 UI가 잘 구현되어 있지만, 스크린 리더 사용자를 위한 접근성 개선이 필요합니다.

다음과 같이 수정하는 것을 제안드립니다:

-    <p className="absolute bottom-2 right-2 w-full text-end text-sm">
+    <p className="absolute bottom-2 right-2 w-full text-end text-sm" role="status" aria-live="polite">

또한, 버전 비교 로직에 대한 타입 안전성을 위해 버전 문자열 비교 대신 semver 비교를 고려해보시는 것은 어떨까요?

packages/web/src/app/[lng]/memos/components/Header/RefreshButton.tsx (1)

22-22: 로컬 스토리지 처리 방식 개선됨

LocalStorage.setTrue() 메서드를 사용하여 스토리지 관리를 중앙화한 것은 좋은 개선입니다. 하지만 오류 처리를 추가하면 좋을 것 같습니다.

다음과 같이 try-catch 블록을 추가하는 것을 고려해보세요:

   const handleRefreshClick = async () => {
     driverObj.moveNext();
-    LocalStorage.setTrue(LOCAL_STORAGE_KEY_MAP.guide);
+    try {
+      LocalStorage.setTrue(LOCAL_STORAGE_KEY_MAP.guide);
+    } catch (error) {
+      console.error('가이드 상태 저장 중 오류 발생:', error);
+      // 로컬 스토리지 오류가 전체 기능을 중단시키지 않도록 함
+    }

     await queryClient.invalidateQueries({ queryKey: QUERY_KEY.memos() });
     toast({ title: t('toastMessage.refresh') });
   };
packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx (2)

Line range hint 13-17: 폼 유효성 검사와 에러 처리를 추가하면 좋을 것 같습니다.

현재 구현은 잘 작동하지만, 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  • 카테고리 이름에 대한 유효성 검사 (필수 입력, 최소/최대 길이 등)
  • 뮤테이션 에러 처리 및 사용자 피드백

다음과 같이 개선해보시는 건 어떨까요?

-  const { register, handleSubmit } = useForm<CategoryInput>({
+  const { register, handleSubmit, formState: { errors } } = useForm<CategoryInput>({
     defaultValues: {
       category: '',
     },
+    resolver: zodResolver(categorySchema),
   });

-  const { mutate: mutateCategoryPost } = useCategoryPostMutation({ supabaseClient: getSupabaseClient() });
+  const { mutate: mutateCategoryPost, error } = useCategoryPostMutation({ 
+    supabaseClient: getSupabaseClient(),
+    onError: (error) => {
+      toast.error('카테고리 생성에 실패했습니다.');
+    }
+  });

Also applies to: 21-23


Line range hint 31-38: 접근성과 사용자 경험 개선이 필요합니다.

UI/UX 측면에서 다음과 같은 개선사항을 제안드립니다:

  • 폼 입력 필드에 적절한 레이블과 placeholder 추가
  • 키보드 접근성 개선
  • 폼 제출 후 피드백 제공

다음과 같이 수정해보시는 건 어떨까요?

   return (
     <form onSubmit={onSubmit}>
-      <Input {...register('category')} />
+      <Input
+        {...register('category')}
+        aria-label="새 카테고리 이름"
+        placeholder="카테고리 이름을 입력하세요"
+        onKeyDown={(e) => {
+          if (e.key === 'Escape') {
+            setIsEditMode(false);
+          }
+        }}
+      />
     </form>
   );
packages/web/src/utils/LocalStorage.ts (2)

1-7: 버전 유효성 검사 개선이 필요합니다

현재 버전 검증이 기본적인 형식만 확인하고 있습니다. 각 숫자의 범위나 유효성을 검증하는 로직을 추가하는 것이 좋겠습니다.

다음과 같이 개선할 수 있습니다:

-const REGEXR_UPDATE_VERSION_VERSION = /^updateVersion\d+\.\d+\.\d+$/;
+const REGEXR_UPDATE_VERSION_VERSION = /^updateVersion([0-9]|[1-9][0-9]+)\.([0-9]|[1-9][0-9]+)\.([0-9]|[1-9][0-9]+)$/;

9-17: 불리언 값 처리 개선이 필요합니다

LOCAL_STORAGE_VALUE_MAPtrue 값만 정의되어 있어 false 케이스 처리가 명확하지 않습니다.

다음과 같이 개선하는 것을 제안합니다:

 export const LOCAL_STORAGE_VALUE_MAP = {
   true: 'true',
+  false: 'false',
 } as const;
packages/web/src/app/[lng]/memos/utils/guide.ts (2)

40-42: 가이드 완료 처리에 대한 에러 처리 추가 검토가 필요합니다.

가이드 완료는 중요한 사용자 플로우이므로, 로컬 스토리지 저장 실패에 대한 대비가 필요합니다.

다음과 같은 에러 처리 추가를 고려해보세요:

 onNextClick: () => {
-  LocalStorage.setTrue(LOCAL_STORAGE_KEY_MAP.guide);
+  try {
+    LocalStorage.setTrue(LOCAL_STORAGE_KEY_MAP.guide);
+  } catch (error) {
+    console.error('가이드 완료 상태 저장 실패:', error);
+    // 사용자에게 알림 표시 또는 대체 로직 실행
+  }
   driverObj.destroy();
 },

Line range hint 1-46: 접근성 및 크로스 플랫폼 지원 개선이 필요합니다.

현재 가이드는 특정 키보드 단축키(Option + S, Command + S)에 의존하고 있습니다. 이는 다음과 같은 문제를 야기할 수 있습니다:

  1. Windows 사용자의 경우 다른 단축키를 사용해야 함
  2. 키보드를 사용할 수 없는 사용자의 접근성 문제

다음과 같은 개선을 제안드립니다:

  1. 플랫폼별 단축키 표시 로직 추가
  2. 마우스 클릭으로도 동일한 작업이 가능하도록 대체 수단 제공
  3. 접근성 지원을 위한 ARIA 레이블 추가
packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts (3)

1-7: 타입 정의에 JSDoc 문서를 추가하는 것이 좋습니다

DialogType에 대한 JSDoc 문서를 추가하여 각 타입 값의 의미와 사용 사례를 명확히 설명하면 좋을 것 같습니다.

+/**
+ * 확장 프로그램 다이얼로그의 타입을 정의합니다.
+ * - 'install': 확장 프로그램 설치 다이얼로그
+ * - 'update': 확장 프로그램 업데이트 다이얼로그
+ */
export type DialogType = 'install' | 'update';

13-29: 버전 비교 로직을 개선하고 코드를 단순화할 수 있습니다

  1. 버전 비교 시 semver 라이브러리를 사용하여 더 안정적인 버전 비교를 구현하는 것이 좋습니다.
  2. 조건문 구조를 단순화하여 가독성을 높일 수 있습니다.
+ import semver from 'semver';

useEffect(() => {
    if (manifest === null) return;

    const isExtensionInstalled = manifest !== undefined;
-   const isExtensionNotLastVersion = isExtensionInstalled && manifest.version !== EXTENSION.lastVersion;
+   const isExtensionNotLastVersion = isExtensionInstalled && 
+     semver.lt(manifest.version, EXTENSION.lastVersion);

+   const shouldShowDialog = (
+     (!isExtensionInstalled && !LocalStorage.check(LOCAL_STORAGE_KEY_MAP.install)) ||
+     (isExtensionNotLastVersion && !LocalStorage.check(LOCAL_STORAGE_KEY_MAP.updateVersion))
+   );

+   if (shouldShowDialog) {
+     setDialogType(!isExtensionInstalled ? 'install' : 'update');
+     setOpen(true);
+   }
-   if (!isExtensionInstalled && !LocalStorage.check(LOCAL_STORAGE_KEY_MAP.install)) {
-     setDialogType('install');
-     setOpen(true);
-     return;
-   }
-   if (isExtensionNotLastVersion && !LocalStorage.check(LOCAL_STORAGE_KEY_MAP.updateVersion)) {
-     setDialogType('update');
-     setOpen(true);
-     return;
-   }
  }, [manifest]);

36-43: 반환값의 성능 최적화가 필요합니다

handleClose 함수를 useCallback으로 메모이제이션하여 불필요한 리렌더링을 방지할 수 있습니다.

+ const memoizedHandleClose = useCallback(handleClose, []);

  return {
    open,
    setOpen,
    dialogType,
    manifest,
-   handleClose,
+   handleClose: memoizedHandleClose,
  };
packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts (2)

12-14: 타입 안전성 개선이 필요합니다.

undefined를 반환하는 부분에서 타입 안전성을 높일 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

-  if (!dialogType) return;
+  if (!dialogType) return undefined;

41-41: 타입 안전성을 위한 타입 단언이 필요합니다.

dialogType이 'install' 또는 'update'로 제한되어 있지만, 타입스크립트는 이를 보장하지 않습니다.

다음과 같이 수정하는 것을 제안합니다:

-  return EXTENSION_DIALOG_INFO_ALL[dialogType];
+  return EXTENSION_DIALOG_INFO_ALL[dialogType as keyof typeof EXTENSION_DIALOG_INFO_ALL];
packages/web/src/app/[lng]/layout.tsx (1)

47-47: ExtensionDialog 배치가 적절합니다.

전역적으로 접근 가능한 위치에 배치되어 있으며, lng prop이 올바르게 전달되고 있습니다. 다만, 다음 사항들을 고려해보시기 바랍니다:

  1. 다이얼로그가 전역적으로 필요한지 재확인
  2. 성능 최적화를 위해 필요한 경우에만 렌더링되도록 조건부 렌더링 고려
packages/web/src/app/components/ExtensionDialog/index.tsx (1)

18-23: 빈 div 대신 null을 반환하는 것이 좋습니다

빈 div를 렌더링하는 대신 null을 반환하면 불필요한 DOM 노드를 줄일 수 있습니다.

다음과 같이 수정하는 것을 추천드립니다:

-  if (!dialogType || !extensionDialogInfo) return <div></div>;
+  if (!dialogType || !extensionDialogInfo) return null;
packages/web/src/app/i18n/locales/en/translation.json (1)

31-35: 환영 메시지를 더 매력적으로 개선할 수 있습니다.

현재 환영 메시지가 다소 단순합니다. 서비스의 주요 가치나 특징을 포함하여 더 매력적으로 작성하는 것을 고려해보세요.

다음과 같은 방식으로 개선할 수 있습니다:

-    "welcomeDescription": "Web Memo is a convenient tool for writing memos.",
+    "welcomeDescription": "Web Memo helps you capture and organize your thoughts effortlessly across the web.",
packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx (2)

Line range hint 47-56: 접근성 개선이 필요합니다.

키보드 단축키와 관련하여 몇 가지 개선사항을 제안드립니다:

  1. Windows 사용자를 위해 Ctrl+S도 지원해야 합니다
  2. 스크린 리더 사용자를 위한 ARIA 레이블 추가가 필요합니다

다음과 같이 수정을 제안드립니다:

  const handleKeyDown = async (
    event: React.KeyboardEvent<HTMLTextAreaElement> | React.KeyboardEvent<HTMLInputElement>,
  ) => {
-   if (event.metaKey && event.key === 's') {
+   if ((event.metaKey || event.ctrlKey) && event.key === 's') {
      event.preventDefault();
      saveMemo();
    }
  };

그리고 Textarea에 aria-label을 추가해주세요:

  <Textarea 
    rows={row} 
    onKeyDown={handleKeyDown} 
+   aria-label={t('memo.edit.textarea.label')}
    {...register('memo')} 
  />

MemoInput 타입 불일치 문제가 발견되었습니다

MemoInput 타입이 두 위치에서 서로 다르게 정의되어 있습니다:

  • packages/web/src/app/[lng]/memos/types/Input.ts:
    export type MemoInput = {
      memo: string;
    };
  • pages/side-panel/src/types/Input.ts:
    export interface MemoInput {
      memo: string;
      isWish: boolean;
    }

사이드 패널의 MemoInputisWish 필드를 추가로 포함하고 있어 타입 정의가 일치하지 않습니다. 두 컴포넌트 간의 일관성을 위해 타입 정의를 통일하거나, 의도적인 차이라면 타입 이름을 다르게 지정해야 합니다.

🔗 Analysis chain

Line range hint 32-36: 폼 타입 변경이 적절하나 검증이 필요합니다.

MemoInput 타입으로 변경된 것은 좋은 개선이지만, 다른 컴포넌트들에서도 일관되게 사용되는지 확인이 필요합니다.

다른 컴포넌트들의 타입 사용을 확인하기 위해 다음 스크립트를 실행하세요:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# MemoInput 타입의 사용처를 검색합니다
rg "MemoInput" --type typescript

# InputType이 아직 남아있는지 확인합니다
rg "InputType" --type typescript

Length of output: 135


Script:

#!/bin/bash
# Search for MemoInput type usage
rg "MemoInput"

# Search for InputType usage
rg "InputType"

# Find all TypeScript files that might contain form types
fd "\.(tsx|ts)$" packages/web/src/app/\[lng\]/memos/

Length of output: 2323


Script:

#!/bin/bash
# Check the content of MemoInput type definitions
cat packages/web/src/app/[lng]/memos/types/Input.ts
cat pages/side-panel/src/types/Input.ts

# Check if there are any other form implementations in memos components
rg "useForm" packages/web/src/app/\[lng\]/memos/

Length of output: 826

packages/web/src/app/[lng]/memos/components/MemoView/MemoItem.tsx (1)

121-121: prop 이름 변경이 잘 되었습니다!

id에서 memoId로의 prop 이름 변경은 코드의 명확성을 향상시킵니다. 이는 prop의 목적을 더 구체적으로 나타내는 좋은 변경사항입니다.

일관성을 위해 컴포넌트 내의 다른 부분들도 검토해보시면 좋을 것 같습니다. 예를 들어:

- const handleIsWishClick: MouseEventHandler<SVGSVGElement> = event => {
-   mutateMemoPatch(
-     {
-       id: memo.id,
-       memoRequest: {
+ const handleIsWishClick: MouseEventHandler<SVGSVGElement> = event => {
+   mutateMemoPatch(
+     {
+       memoId: memo.id,
+       memoRequest: {
pages/side-panel/src/components/MemoForm.tsx (2)

Line range hint 65-73: 에러 처리 개선 제안

saveMemo 함수의 구현은 전반적으로 잘 되어 있으나, 다음과 같은 개선사항을 제안드립니다:

  1. 빈 메모 저장 시 유효성 검사 추가
  2. 네트워크 오류 시 재시도 로직 구현 고려

다음과 같이 수정을 제안드립니다:

  const saveMemo = async (data?: MemoInput) => {
    const memo = data?.memo ?? watch('memo');
    const isWish = data?.isWish ?? watch('isWish');

+   if (!memo.trim()) {
+     toast({ title: I18n.get('toast_error_empty_memo') });
+     return;
+   }

    const formattedMemo = await getFormattedMemo({ memo, isWish });

-   if (currentMemo) mutateMemoPatch({ id: currentMemo.id, memoRequest: formattedMemo });
-   else mutateMemoPost(formattedMemo);
+   try {
+     if (currentMemo) {
+       await mutateMemoPatch({ id: currentMemo.id, memoRequest: formattedMemo });
+     } else {
+       await mutateMemoPost(formattedMemo);
+     }
+   } catch (error) {
+     setIsSaved(false);
+     throw error;
+   }
  };

Line range hint 134-150: 접근성 개선 제안

위시리스트 아이콘의 접근성을 개선할 수 있습니다:

다음과 같은 수정을 제안드립니다:

        <HeartIcon
          size={16}
          fill={watch('isWish') ? 'pink' : ''}
          fillOpacity={watch('isWish') ? 100 : 0}
          onClick={handleWishClick}
          role="button"
+         aria-label={watch('isWish') ? I18n.get('remove_from_wishlist') : I18n.get('add_to_wishlist')}
+         tabIndex={0}
+         onKeyPress={(e) => {
+           if (e.key === 'Enter' || e.key === ' ') {
+             e.preventDefault();
+             handleWishClick();
+           }
+         }}
        />
packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx (2)

Line range hint 71-92: 카테고리 변경 로직의 에러 처리를 개선하면 좋겠습니다.

카테고리를 찾지 못했을 때 단순히 return하는 대신, 사용자에게 적절한 에러 메시지를 표시하는 것이 좋을 것 같습니다.

다음과 같이 개선하는 것을 제안드립니다:

  const category = categories?.find(category => category.id === Number(categoryId));
- if (!category) return;
+ if (!category) {
+   toast({
+     title: t('toastMessage.categoryNotFound'),
+     variant: 'destructive'
+   });
+   return;
+ }

Line range hint 30-92: 성능 최적화를 위한 제안사항이 있습니다.

  1. 이벤트 핸들러들을 useCallback으로 메모이제이션하면 불필요한 리렌더링을 방지할 수 있습니다.
  2. categories 필터링 로직을 useMemo로 최적화할 수 있습니다.

예시 코드:

const handleDeleteMemo = useCallback<MouseEventHandler<HTMLDivElement>>(
  event => {
    event.stopPropagation();
    mutateDeleteMemo(memoId, {
      // ... existing logic
    });
  },
  [memoId, mutateDeleteMemo, t]
);

const handleCategoryChange = useCallback(
  (categoryId: string) => {
    // ... existing logic
  },
  [categories, memoId, mutatePatchMemo, queryClient, router, t]
);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8c2603a and 45de68f.

📒 Files selected for processing (32)
  • packages/shared/src/constants/Extension.ts (1 hunks)
  • packages/shared/src/utils/extension/bridge/getExtensionManifest.ts (1 hunks)
  • packages/shared/src/utils/extension/bridge/getSidePanelOpen.ts (1 hunks)
  • packages/shared/src/utils/extension/bridge/refetchTheMemos.ts (1 hunks)
  • packages/web/src/app/[lng]/layout.tsx (2 hunks)
  • packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx (1 hunks)
  • packages/web/src/app/[lng]/login/components/LoginSection/index.tsx (0 hunks)
  • packages/web/src/app/[lng]/memos/components/Header/RefreshButton.tsx (2 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx (1 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoView/MemoItem.tsx (1 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx (4 hunks)
  • packages/web/src/app/[lng]/memos/constants/guide.ts (0 hunks)
  • packages/web/src/app/[lng]/memos/constants/index.ts (0 hunks)
  • packages/web/src/app/[lng]/memos/hooks/useGuide.ts (1 hunks)
  • packages/web/src/app/[lng]/memos/types/Input.ts (1 hunks)
  • packages/web/src/app/[lng]/memos/types/index.ts (1 hunks)
  • packages/web/src/app/[lng]/memos/utils/guide.ts (2 hunks)
  • packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts (1 hunks)
  • packages/web/src/app/components/ExtensionDialog/index.tsx (1 hunks)
  • packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts (1 hunks)
  • packages/web/src/app/components/index.ts (1 hunks)
  • packages/web/src/app/i18n/client.js (0 hunks)
  • packages/web/src/app/i18n/locales/en/translation.json (1 hunks)
  • packages/web/src/app/i18n/locales/ko/translation.json (2 hunks)
  • packages/web/src/hooks/index.ts (1 hunks)
  • packages/web/src/hooks/useGetExtensionManifest.ts (1 hunks)
  • packages/web/src/utils/LocalStorage.ts (1 hunks)
  • packages/web/src/utils/index.ts (1 hunks)
  • packages/web/tsconfig.json (1 hunks)
  • pages/side-panel/src/components/MemoForm.tsx (3 hunks)
  • pages/side-panel/src/types/Input.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • packages/web/src/app/[lng]/login/components/LoginSection/index.tsx
  • packages/web/src/app/[lng]/memos/constants/guide.ts
  • packages/web/src/app/[lng]/memos/constants/index.ts
  • packages/web/src/app/i18n/client.js
🧰 Additional context used
🪛 Biome (1.9.4)
packages/web/src/utils/LocalStorage.ts

[error] 21-37: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 31-31: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 35-35: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🔇 Additional comments (35)
packages/shared/src/constants/Extension.ts (1)

2-2: 확장 프로그램 ID 사용 검증이 필요합니다

확장 프로그램 ID가 코드베이스 전체에서 일관되게 사용되고 있는지 확인이 필요합니다.

다음 스크립트를 실행하여 확장 프로그램 ID의 사용을 검증합니다:

✅ Verification successful

확장 프로그램 ID가 일관되게 사용되고 있음을 확인했습니다

확장 프로그램 ID 'eaiojpmgklfngpjddhoalgcpkepgkclh'가 다음 위치에서 일관되게 사용되고 있습니다:

  • packages/shared/src/constants/Extension.ts: 확장 프로그램 상수로 정의
  • packages/shared/src/constants/Url.ts: Chrome 웹 스토어 URL에서 사용
  • tests/e2e/fixtures.ts: E2E 테스트에서 확장 프로그램 페이지 URL로 사용
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 확장 프로그램 ID 사용 검증
echo "확장 프로그램 ID 사용 검색 중..."
rg -l "eaiojpmgklfngpjddhoalgcpkepgkclh"

# manifest.json 파일에서 ID 확인
echo "manifest.json 파일에서 ID 확인 중..."
fd -g "manifest.json" --exec cat {} \; | grep "id"

Length of output: 329


Script:

#!/bin/bash
# 확장 프로그램 ID가 사용된 컨텍스트 확인
echo "Extension.ts 파일의 ID 사용 컨텍스트:"
rg -A 2 -B 2 "eaiojpmgklfngpjddhoalgcpkepgkclh" packages/shared/src/constants/Extension.ts

echo "\nUrl.ts 파일의 ID 사용 컨텍스트:"
rg -A 2 -B 2 "eaiojpmgklfngpjddhoalgcpkepgkclh" packages/shared/src/constants/Url.ts

echo "\nE2E 테스트에서의 ID 사용 컨텍스트:"
rg -A 2 -B 2 "eaiojpmgklfngpjddhoalgcpkepgkclh" tests/e2e/fixtures.ts

# 크롬 확장 프로그램 매니페스트 파일 검색
echo "\n크롬 확장 프로그램 매니페스트 파일 검색:"
fd -g "manifest.json" -x cat {}

Length of output: 1065

packages/web/src/utils/index.ts (2)

4-4: LocalStorage 유틸리티 내보내기가 추가되었습니다.

중앙 집중식 로컬 스토리지 관리를 위한 좋은 접근 방식입니다. 직접적인 window.localStorage 접근을 대체하는 것은 일관성과 유지보수성을 향상시킵니다.


4-4: LocalStorage 유틸리티의 사용 현황을 확인하세요.

새로운 LocalStorage 유틸리티로의 마이그레이션이 완전히 이루어졌는지 확인이 필요합니다.

다음 스크립트를 실행하여 직접적인 localStorage 사용 여부를 확인하세요:

✅ Verification successful

LocalStorage 유틸리티가 적절히 사용되고 있음을 확인했습니다.

코드베이스 분석 결과:

  • localStorage의 직접 사용은 오직 LocalStorage 유틸리티 내부에서만 발견됨
  • LocalStorage 유틸리티는 여러 컴포넌트에서 일관되게 사용되고 있음
  • 모든 localStorage 접근이 타입 안전성이 보장된 방식으로 이루어짐
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 직접적인 localStorage 사용 검사

# window.localStorage 직접 사용 검색
echo "직접적인 window.localStorage 사용 검사:"
rg "window\.localStorage\." -t ts -t tsx

# localStorage 직접 사용 검색
echo "\n일반 localStorage 직접 사용 검사:"
rg "localStorage\." -t ts -t tsx

# LocalStorage 유틸리티 사용 검색
echo "\nLocalStorage 유틸리티 사용 검사:"
rg "LocalStorage\." -t ts -t tsx

Length of output: 397


Script:

#!/bin/bash
# Description: localStorage 사용 현황 검사 (수정된 버전)

# window.localStorage 직접 사용 검색
echo "직접적인 window.localStorage 사용 검사:"
rg "window\.localStorage"

# localStorage 직접 사용 검색
echo -e "\n일반 localStorage 직접 사용 검사:"
rg "localStorage\."

# LocalStorage 유틸리티 사용 검색
echo -e "\nLocalStorage 유틸리티 사용 검사:"
rg "LocalStorage\."

# LocalStorage 파일 내용 확인
echo -e "\nLocalStorage 유틸리티 파일 내용:"
cat packages/web/src/utils/LocalStorage.ts

Length of output: 2531

packages/web/src/app/components/index.ts (1)

2-2: 배럴(barrel) 내보내기가 올바르게 구현되었습니다.

컴포넌트 내보내기 패턴이 기존 Introduction 컴포넌트와 일관성 있게 유지되었으며, 적절한 위치에 추가되었습니다.

packages/web/src/hooks/index.ts (1)

3-3: 내보내기 구문이 일관된 패턴을 따르고 있습니다.

새로운 useGetExtensionManifest 훅의 내보내기가 기존 훅들과 동일한 패턴을 따르고 있어 코드의 일관성이 잘 유지되었습니다.

다음 스크립트를 실행하여 훅의 구현을 확인하겠습니다:

✅ Verification successful

useGetExtensionManifest 훅이 적절하게 구현되어 있고 일관되게 사용되고 있습니다.

훅의 구현과 사용 패턴을 검토한 결과:

  • 훅이 Chrome 확장 프로그램의 매니페스트를 안전하게 가져오는 로직을 구현
  • ExtensionDialogExtensionVersion 컴포넌트에서 일관된 방식으로 사용
  • 오류 처리와 상태 관리가 적절히 구현됨
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: useGetExtensionManifest 훅의 구현 확인

# 훅 구현 파일 확인
fd "useGetExtensionManifest.ts" --type f

# 훅 사용처 확인
rg "useGetExtensionManifest" -l

Length of output: 352


Script:

#!/bin/bash
# useGetExtensionManifest 훅의 구현과 사용 패턴 확인

# 훅 구현 내용 확인
cat packages/web/src/hooks/useGetExtensionManifest.ts

# 사용 컨텍스트 확인 (각 파일에서 어떻게 사용되는지)
echo "=== ExtensionDialog 사용 컨텍스트 ==="
rg "useGetExtensionManifest" packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts -A 2 -B 2

echo "=== ExtensionVersion 컴포넌트 사용 컨텍스트 ==="
rg "useGetExtensionManifest" packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx -A 2 -B 2

Length of output: 1789

packages/web/src/app/[lng]/memos/hooks/useGuide.ts (2)

3-3: 로컬 스토리지 유틸리티 도입으로 코드 개선

중앙 집중화된 로컬 스토리지 관리를 위해 유틸리티 함수를 도입한 것은 좋은 접근 방식입니다.


7-7: 로컬 스토리지 접근 방식 개선 확인

LocalStorage 유틸리티를 사용하여 코드가 더 간결해지고 일관성이 향상되었습니다. 다만, 다음 사항들을 확인해 주시기 바랍니다:

  1. 가이드 표시 로직이 이전과 동일하게 작동하는지
  2. LocalStorage.check가 이전 구현과 동일한 결과를 반환하는지

다음 스크립트로 LocalStorage 구현을 확인해보겠습니다:

✅ Verification successful

Let me check the LocalStorage utility implementation to verify its behavior.


Let me check the check method implementation and the previous implementation to compare them.


LocalStorage 구현이 안전하게 확인되었습니다

LocalStorage 유틸리티의 구현을 검토한 결과:

  • check 메서드는 LOCAL_STORAGE_VALUE_MAP.true와 정확히 비교하여 일관된 결과를 반환합니다
  • 가이드 완료 시 setTrue 메서드를 통해 동일한 값이 저장됩니다
  • 이전 구현과 동일한 키(LOCAL_STORAGE_KEY_MAP.guide)를 사용하여 호환성이 유지됩니다

따라서 가이드 표시 로직이 이전과 동일하게 작동할 것으로 확인됩니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# LocalStorage 유틸리티 구현 확인
rg -A 5 "LocalStorage.check" --type ts

Length of output: 1510


Script:

#!/bin/bash
# Check LocalStorage utility implementation
rg -A 10 "class LocalStorage" --type ts

# Check for any related test files
fd "LocalStorage.*test" --type f

Length of output: 801


Script:

#!/bin/bash
# Check complete LocalStorage implementation including the check method
rg -A 20 "class LocalStorage" --type ts

# Check git history for the previous implementation
rg -B 5 "LOCAL_STORAGE_KEY_MAP.guide" --type ts

Length of output: 2810

packages/shared/src/utils/extension/bridge/refetchTheMemos.ts (2)

1-1: 상수 구조 변경이 올바르게 적용되었습니다.

EXTENSION 객체를 사용하도록 변경한 것이 확장성 있는 구조로 개선되었습니다.


6-6: Chrome 확장 프로그램 메시징 구현이 적절합니다.

EXTENSION.id를 사용하여 메시지를 전송하는 방식이 올바르게 구현되었습니다. 이는 확장 프로그램 식별자를 더 체계적으로 관리할 수 있게 해줍니다.

확장 프로그램 메시징이 일관되게 적용되었는지 확인하기 위해 다음 스크립트를 실행합니다:

✅ Verification successful

Chrome 확장 프로그램 메시징이 일관되게 구현되었음을 확인했습니다.

검증 결과, 모든 브릿지 구현에서 EXTENSION.idchrome.runtime.sendMessage를 일관되게 사용하고 있습니다:

  • packages/shared/src/utils/extension/bridge/refetchTheMemos.ts
  • packages/shared/src/utils/extension/bridge/getSidePanelOpen.ts
  • packages/shared/src/utils/extension/bridge/getExtensionManifest.ts

각 구현이 동일한 패턴을 따르고 있어 확장 프로그램 메시징이 체계적으로 관리되고 있음을 확인했습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 모든 Chrome 확장 프로그램 메시징 구현을 확인합니다.

# chrome.runtime.sendMessage 사용 패턴 검색
rg "chrome\.runtime\.sendMessage" -A 2

# EXTENSION 상수 사용 확인
rg "EXTENSION\.id" -A 2

Length of output: 2742

packages/shared/src/utils/extension/bridge/getSidePanelOpen.ts (2)

1-1: 상수 구조 변경이 올바르게 적용되었습니다.

EXTENSION 객체를 사용하도록 변경한 것은 확장 프로그램 관련 설정을 더 체계적으로 관리할 수 있게 해줍니다.


6-6: Chrome 확장 프로그램 메시징 기능 검증이 필요합니다.

EXTENSION.id를 사용하는 메시지 전송 기능이 올바르게 작동하는지 확인해주세요.

다음 스크립트를 실행하여 다른 파일들에서도 동일한 방식으로 EXTENSION.id를 사용하고 있는지 확인하겠습니다:

✅ Verification successful

Let me gather more information about the EXTENSION constant and its usage.


Chrome 확장 프로그램 메시징 구현이 일관되게 적용되어 있습니다.

검증 결과:

  • EXTENSION.idpackages/shared/src/constants/Extension.ts에 상수로 정의되어 있으며, 모든 브릿지 통신에서 동일한 방식으로 사용되고 있습니다.
  • 메시지 전송 패턴이 getSidePanelOpen, getExtensionManifest, refetchTheMemos 등 모든 브릿지 모듈에서 일관되게 구현되어 있습니다.
  • 확장 프로그램 ID가 하드코딩되어 있지만, 이는 Chrome 웹 스토어에 등록된 확장 프로그램의 고유 ID이므로 적절합니다.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of EXTENSION.id across the codebase

# Check for any remaining uses of the old EXTENSION_ID
rg "EXTENSION_ID"

# Check the pattern of using EXTENSION.id in chrome.runtime.sendMessage
rg -A 2 "chrome\.runtime\.sendMessage\(EXTENSION"

Length of output: 1273


Script:

#!/bin/bash
# Check the definition and usage of EXTENSION constant
ast-grep --pattern 'const EXTENSION = $_'

# Check imports of EXTENSION
rg "import.*EXTENSION.*from"

# Check if there are any other message patterns using chrome.runtime
rg "chrome\.runtime\.(sendMessage|connect)"

Length of output: 2016

packages/web/src/hooks/useGetExtensionManifest.ts (1)

1-3: 임포트 구문이 깔끔하고 적절합니다!

필요한 훅과 유틸리티 함수들이 잘 임포트되어 있습니다.

packages/shared/src/utils/extension/bridge/getExtensionManifest.ts (2)

1-1: 상수 구조 개선이 잘 이루어졌습니다.

EXTENSION_ID에서 EXTENSION 객체로의 전환이 잘 이루어졌습니다. 이는 확장 프로그램 관련 상수들을 더 체계적으로 관리할 수 있게 해줍니다.


6-6: EXTENSION.id 사용이 올바르게 적용되었는지 확인이 필요합니다.

EXTENSION.id를 사용하는 변경이 올바르게 이루어졌지만, 다른 파일들에서도 이 변경이 일관되게 적용되었는지 확인이 필요합니다.

✅ Verification successful

EXTENSION.id 사용이 일관되게 적용되었음을 확인했습니다.

코드베이스 검사 결과, EXTENSION.id가 모든 관련 파일에서 일관되게 사용되고 있습니다:

  • packages/shared/src/constants/Extension.ts에서 EXTENSION 객체가 올바르게 정의되어 있음
  • chrome.runtime.sendMessage 호출 시 모든 곳에서 EXTENSION.id를 사용
  • 이전 EXTENSION_ID 상수 사용이 완전히 제거되었음을 확인
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: EXTENSION_ID에서 EXTENSION.id로의 변경이 일관되게 적용되었는지 확인

# chrome.runtime.sendMessage 호출에서 EXTENSION_ID 사용 여부 확인
rg "chrome\.runtime\.sendMessage\(EXTENSION_ID" 

# EXTENSION_ID import 문 확인
rg "import.*EXTENSION_ID.*from.*constants"

Length of output: 94


Script:

#!/bin/bash
# Let's search for any usage of EXTENSION_ID or EXTENSION.id in the codebase
rg "EXTENSION_ID|EXTENSION\.id" -A 2

# Also search for any imports or definitions of EXTENSION
rg "import.*EXTENSION.*from|const.*EXTENSION.*=|type.*EXTENSION.*=" -A 2

Length of output: 4759

packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx (2)

3-3: 임포트 구조가 개선되었습니다

상수와 훅의 구조가 더 명확해졌습니다. EXTENSION 객체를 사용함으로써 확장 프로그램 관련 상수들을 더 체계적으로 관리할 수 있게 되었습니다.

Also applies to: 6-6


13-13: 확장 프로그램 매니페스트 검색 구현을 확인해주세요

useGetExtensionManifest 훅의 구현을 확인하여 매니페스트 검색이 올바르게 처리되는지 확인이 필요합니다.

✅ Verification successful

Let me check the implementation of requestGetExtensionManifest which is used in the hook.


확장 프로그램 매니페스트 검색 구현이 적절하게 되어 있습니다

useGetExtensionManifest 훅은 Chrome 확장 프로그램의 매니페스트를 안전하게 검색하고 있습니다:

  • 브릿지 패턴을 사용하여 확장 프로그램과 웹 애플리케이션 간의 통신을 처리
  • 오류 처리가 적절히 구현되어 있음
  • Chrome API를 올바르게 활용하여 매니페스트 정보를 가져옴
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of useGetExtensionManifest hook
rg -A 10 "useGetExtensionManifest"

Length of output: 5084


Script:

#!/bin/bash
# Check the implementation of requestGetExtensionManifest
rg -A 10 "requestGetExtensionManifest"

Length of output: 2186

packages/web/src/app/[lng]/memos/components/Header/RefreshButton.tsx (1)

11-11: 로컬 스토리지 유틸리티 추가 승인

중앙 집중식 로컬 스토리지 관리를 위한 유틸리티 import 추가는 코드의 일관성과 유지보수성을 향상시킵니다.

packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx (1)

9-9: 타입 리팩토링이 잘 이루어졌습니다!

로컬 인터페이스를 제거하고 중앙화된 타입 정의를 사용하도록 변경한 것이 좋은 개선사항입니다. 이는 타입의 일관성을 유지하고 재사용성을 높이는데 도움이 됩니다.

Also applies to: 13-13

packages/web/src/utils/LocalStorage.ts (1)

19-19: 타입 정의가 잘 되어있습니다!

LocalStorageType이 키 맵과 버전 타입을 효과적으로 결합하여 정의되어 있습니다.

packages/web/src/app/[lng]/memos/utils/guide.ts (1)

4-4: 로컬 스토리지 관리 개선이 잘 이루어졌습니다!

중앙 집중식 로컬 스토리지 관리로의 전환은 유지보수성과 일관성 측면에서 좋은 개선입니다.

packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts (1)

1-11: 함수 시그니처와 임포트가 잘 구성되어 있습니다!

타입스크립트 타입 정의가 명확하고 임포트가 잘 구성되어 있습니다.

packages/web/src/app/[lng]/layout.tsx (1)

13-13: ExtensionDialog 컴포넌트 import 검증이 필요합니다.

import 문이 올바르게 작성되었습니다. 다만, 컴포넌트의 존재 여부를 확인해야 합니다.

다음 스크립트로 컴포넌트 파일의 존재를 확인하겠습니다:

✅ Verification successful

ExtensionDialog 컴포넌트가 올바르게 구현되어 있습니다

컴포넌트가 packages/web/src/app/components/ExtensionDialog/index.tsx에 정의되어 있고, components/index.ts에서 올바르게 export 되고 있어 import 문이 정상적으로 동작할 것입니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# ExtensionDialog 컴포넌트 파일 확인
fd -e tsx -e ts "ExtensionDialog" "packages/web/src/app/components"

Length of output: 209


Script:

#!/bin/bash
# ExtensionDialog 컴포넌트 파일 자체를 찾기
fd -e tsx "ExtensionDialog" "packages/web/src/app/components" --full-path

# ExtensionDialog 컴포넌트가 index 파일에서 export되는지 확인
rg "export.*ExtensionDialog" "packages/web/src/app/components" -g "*.{ts,tsx}"

Length of output: 675

packages/web/src/app/i18n/locales/ko/translation.json (3)

16-16: 카테고리 수정 메시지가 적절하게 추가되었습니다.

기존 토스트 메시지들과 일관된 문체를 유지하면서 자연스러운 한국어 표현을 사용했습니다.


37-42: 확장 프로그램 설치 관련 다이얼로그 메시지가 잘 구성되었습니다.

사용자에게 필요한 정보를 명확하게 전달하면서, 긍정/부정 버튼의 텍스트가 적절하게 작성되었습니다.


43-50: 버전 정보 다이얼로그의 메시지가 체계적으로 구성되었습니다.

버전 정보를 표시하는 방식이 명확하며, 사용자가 취할 수 있는 액션이 이해하기 쉽게 작성되었습니다. 플레이스홀더 {{currentVersion}}{{lastVersion}}의 사용이 적절합니다.

packages/web/src/app/components/ExtensionDialog/index.tsx (1)

1-17: 타입 정의와 임포트 구조가 깔끔합니다!

컴포넌트에 필요한 모든 의존성이 명확하게 정의되어 있으며, LanguageType을 확장한 props 인터페이스가 간단명료합니다.

packages/web/src/app/i18n/locales/en/translation.json (4)

16-23: 토스트 메시지 구조가 일관성 있게 작성되었습니다.

모든 메시지가 명확하고 간결하며, 문장 끝에 마침표를 포함하고 있어 일관된 형식을 유지하고 있습니다.


26-27: 옵션 텍스트가 현대적인 UI 관행에 맞게 수정되었습니다.

첫 글자를 소문자로 변경하고 문구를 간소화한 것이 적절합니다.


37-49: 새로운 다이얼로그 섹션이 잘 구성되어 있습니다.

설치 및 버전 업데이트 다이얼로그가 일관된 구조로 잘 구현되어 있습니다. 사용자에게 명확한 선택지를 제공하고 있습니다.


52-53: 툴팁이 행동 중심적으로 잘 작성되었습니다.

사용자 동작을 명확하게 설명하는 방식으로 작성되어 있어 적절합니다.

packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx (1)

14-14: 타입 임포트 변경이 적절합니다!

InputType에서 MemoInput으로의 타입 변경이 잘 이루어졌습니다.

pages/side-panel/src/components/MemoForm.tsx (1)

Line range hint 38-43: 폼 초기화 구현이 적절해 보입니다

useForm 훅의 타입과 기본값이 잘 설정되어 있습니다. MemoInput 타입의 모든 필수 필드가 기본값으로 적절히 초기화되어 있습니다.

packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx (3)

10-24: 임포트 구조가 깔끔하게 정리되었습니다!

공유 상수와 훅을 분리하여 임포트하고, 관련 있는 컴포넌트들을 그룹화하여 가독성이 향상되었습니다.


27-27: 프로퍼티 이름이 더 명확해졌습니다!

id에서 memoId로 변경함으로써 프로퍼티의 목적이 더 명확해졌습니다.


Line range hint 52-65: 메모 삭제 처리가 개선되었습니다!

  • memoId를 사용하여 일관성이 유지되었습니다
  • 토스트 메시지가 다국어 지원을 통해 개선되었습니다

Comment on lines +8 to +12
export default function useExtensionDialog() {
const manifest = useGetExtensionManifest();
const [open, setOpen] = useState(false);
const [dialogType, setDialogType] = useState<DialogType | undefined>(undefined);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

매니페스트 가져오기 실패에 대한 에러 처리가 필요합니다

useGetExtensionManifest 호출 시 발생할 수 있는 오류 상황에 대한 처리가 없습니다. 사용자에게 적절한 피드백을 제공하기 위해 에러 상태를 추가하는 것이 좋을 것 같습니다.

export default function useExtensionDialog() {
  const manifest = useGetExtensionManifest();
+ const [error, setError] = useState<Error | null>(null);
  const [open, setOpen] = useState(false);
  const [dialogType, setDialogType] = useState<DialogType | undefined>(undefined);

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🧹 Outside diff range and nitpick comments (24)
pages/side-panel/src/types/Input.ts (1)

1-4: 인터페이스 구조가 명확하고 간단합니다!

인터페이스의 구조가 잘 정의되어 있습니다. 다만 몇 가지 개선 사항을 제안드립니다:

  1. memo 필드가 빈 문자열을 허용하는지 고려해보시면 좋을 것 같습니다.
  2. isWish 속성의 용도와 의미를 설명하는 JSDoc 주석을 추가하면 좋을 것 같습니다.

다음과 같이 개선해 보시는 건 어떨까요?:

+/**
+ * 메모 입력을 위한 인터페이스
+ */
 export interface MemoInput {
+  /** 메모 내용 (빈 문자열 불가) */
   memo: string;
+  /** 
+   * 위시리스트 여부
+   * true: 위시리스트로 저장
+   * false: 일반 메모로 저장
+   */
   isWish: boolean;
 }
packages/shared/src/constants/Extension.ts (1)

1-4: 객체 구조로의 리팩토링이 잘 되었습니다.

상수값을 객체로 구조화하여 관련 데이터를 그룹화한 것이 좋습니다. 다만 타입 안전성과 유지보수성을 위해 몇 가지 개선사항을 제안드립니다.

다음과 같이 타입 정의와 버전 상수를 추가하는 것을 고려해보세요:

+type ExtensionType = {
+  readonly id: string;
+  readonly lastVersion: string;
+};
+
+const CURRENT_VERSION = '1.6.4' as const;
+
-export const EXTENSION = {
+export const EXTENSION: ExtensionType = {
   id: 'eaiojpmgklfngpjddhoalgcpkepgkclh',
-  lastVersion: '1.6.4',
+  lastVersion: CURRENT_VERSION,
};
packages/web/src/app/[lng]/memos/types/Input.ts (1)

5-7: 타입 정의 스타일의 일관성 개선이 필요합니다.

CategoryInput은 interface로 정의되어 있는 반면, MemoInput은 type alias로 정의되어 있습니다. 코드베이스의 일관성을 위해 동일한 스타일을 사용하는 것이 좋습니다.

다음과 같이 수정하는 것을 제안드립니다:

-export type MemoInput = {
-  memo: string;
-};
+export interface MemoInput {
+  memo: string;
+}
packages/shared/src/utils/extension/bridge/refetchTheMemos.ts (1)

5-8: 메시지 처리에 대한 에러 핸들링 개선이 필요합니다.

크롬 익스텐션 메시징에서 발생할 수 있는 에러 상황(익스텐션이 설치되지 않은 경우, 통신 실패 등)에 대한 처리가 누락되어 있습니다.

다음과 같은 개선을 제안드립니다:

 export const requestRefetchTheMemos = () =>
-  chrome.runtime.sendMessage(EXTENSION.id, { type: BRIDGE_TYPE_REFETCH_THE_MEMO_LIST });
+  chrome.runtime.sendMessage(EXTENSION.id, { type: BRIDGE_TYPE_REFETCH_THE_MEMO_LIST })
+    .catch(error => {
+      console.error('메모 목록 새로고침 요청 실패:', error);
+      // 필요한 경우 사용자에게 에러 알림
+    });

 export const responseRefetchTheMemos = (callbackFn: () => void) =>
-  Runtime.onMessageExternal(BRIDGE_TYPE_REFETCH_THE_MEMO_LIST, callbackFn);
+  Runtime.onMessageExternal(BRIDGE_TYPE_REFETCH_THE_MEMO_LIST, async () => {
+    try {
+      await callbackFn();
+    } catch (error) {
+      console.error('메모 목록 새로고침 처리 실패:', error);
+      throw error; // 에러를 발신자에게 전파
+    }
+  });
packages/web/src/hooks/useGetExtensionManifest.ts (1)

6-6: 상태 타입을 더 명확하게 개선할 수 있습니다.

현재 상태 타입이 chrome.runtime.Manifest | undefined | null로 되어있는데, null과 undefined를 모두 사용할 필요가 없어 보입니다.

다음과 같이 개선해보세요:

-const [manifest, setManifest] = useState<chrome.runtime.Manifest | undefined | null>(null);
+const [manifest, setManifest] = useState<chrome.runtime.Manifest | undefined>(undefined);
packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx (2)

Line range hint 1-40: 컴포넌트 구조에 대한 제안사항이 있습니다.

다음과 같은 개선사항을 고려해보시기 바랍니다:

  1. 폼 제출 후 입력 필드를 초기화하고 편집 모드를 해제하는 로직이 누락되어 있습니다.
  2. 입력 필드에 대한 유효성 검사가 없습니다.
  3. 에러 처리 로직이 없습니다.

다음과 같이 수정하는 것을 제안드립니다:

 const { register, handleSubmit } = useForm<CategoryInput>({
   defaultValues: {
     category: '',
   },
 });

 const { mutate: mutateCategoryPost } = useCategoryPostMutation({ supabaseClient: getSupabaseClient() });

 const onSubmit = handleSubmit(({ category }) => {
-  mutateCategoryPost({ name: category });
+  mutateCategoryPost(
+    { name: category },
+    {
+      onSuccess: () => {
+        setIsEditMode(false);
+        reset({ category: '' });
+      },
+      onError: (error) => {
+        console.error('카테고리 추가 실패:', error);
+        // TODO: 에러 메시지 표시 로직 추가
+      },
+    }
+  );
 });

Line range hint 31-33: 접근성 개선이 필요합니다.

PlusIcon에 적절한 aria 레이블이 없어 스크린 리더 사용자가 기능을 이해하기 어려울 수 있습니다.

다음과 같이 수정하는 것을 제안드립니다:

 <p className="flex cursor-pointer justify-center">
-  <PlusIcon size={16} onClick={handlePlusIconClick} />
+  <PlusIcon
+    size={16}
+    onClick={handlePlusIconClick}
+    role="button"
+    aria-label="카테고리 추가"
+  />
 </p>
packages/web/src/utils/LocalStorage.ts (2)

1-7: 타입 정의와 유효성 검사 로직 개선 필요

버전 형식에 대한 유효성 검사가 잘 구현되어 있지만, 다음과 같은 개선사항을 제안합니다:

  1. 각 숫자 부분에 대한 범위 제한 추가
  2. 타입과 함수에 대한 JSDoc 문서화 추가
+/**
+ * 업데이트 버전을 나타내는 문자열 타입
+ * @example 'updateVersion1.0.0'
+ */
 type UpdateVersionType = `updateVersion${number}.${number}.${number}`;

 const REGEXR_UPDATE_VERSION_VERSION = /^updateVersion\d+\.\d+\.\d+$/;
+/**
+ * 문자열이 유효한 업데이트 버전 형식인지 확인
+ * @param value - 검사할 문자열
+ * @returns 유효한 업데이트 버전인 경우 true
+ */
 export const checkUpdateVersionKey = (value: string): value is UpdateVersionType =>
   REGEXR_UPDATE_VERSION_VERSION.test(value);

9-18: 상수 정의 개선 및 문서화 필요

상수 정의가 잘 되어 있으나, 다음과 같은 개선사항을 제안합니다:

  1. 각 키의 용도에 대한 설명 추가
  2. 값 타입을 더 명확하게 정의
+/**
+ * 로컬 스토리지 키 맵
+ * @property guide - 가이드 표시 여부
+ * @property updateVersion - 기본 업데이트 버전
+ * @property install - 설치 상태
+ */
 export const LOCAL_STORAGE_KEY_MAP = {
   guide: 'guide',
   updateVersion: 'updateVersion',
   install: 'install',
 } as const;

+/**
+ * 로컬 스토리지 값 맵
+ */
 export const LOCAL_STORAGE_VALUE_MAP = {
   true: 'true',
 } as const;
packages/web/src/app/[lng]/memos/utils/guide.ts (1)

Line range hint 19-24: setInterval에 대한 정리(cleanup) 로직이 필요합니다.

onPopoverRender에서 설정된 interval이 정리되지 않아 메모리 누수가 발생할 수 있습니다.

다음과 같이 수정하는 것을 제안드립니다:

        onPopoverRender: () => {
-         setInterval(() => {
+         const intervalId = setInterval(() => {
            requestGetSidePanelOpen(() => {
              if (driverObj.getActiveIndex() !== 0) return;
              driverObj.moveNext();
            });
          }, 500);
+         return () => clearInterval(intervalId);
        },
packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts (2)

8-12: 초기 상태 값 개선이 필요합니다

dialogType의 초기값으로 undefined 대신 명시적인 값을 사용하는 것이 좋습니다. 이는 타입 안정성을 높이고 예측 가능한 동작을 보장합니다.

다음과 같이 수정하는 것을 제안합니다:

-  const [dialogType, setDialogType] = useState<DialogType | undefined>(undefined);
+  const [dialogType, setDialogType] = useState<DialogType>('install');

31-34: handleClose 함수의 타입 안정성 개선이 필요합니다

localStorageKey 매개변수의 타입을 구체적으로 지정하면 런타임 오류를 방지할 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

-  const handleClose = (localStorageKey: string) => {
+  const handleClose = (localStorageKey: keyof typeof LOCAL_STORAGE_KEY_MAP) => {
    setOpen(false);
-    if (checkLocalStorageKey(localStorageKey)) LocalStorage.setTrue(localStorageKey);
+    LocalStorage.setTrue(localStorageKey);
  };
packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts (1)

19-22: 번역 키를 상수로 관리하는 것이 좋습니다

현재 번역 키들이 문자열 리터럴로 하드코딩되어 있습니다. 유지보수성을 높이기 위해 상수로 분리하는 것을 제안합니다.

const TRANSLATION_KEYS = {
  INSTALL: {
    TITLE: 'dialogInstall.title',
    DESCRIPTION: 'dialogInstall.description',
    OK: 'dialogInstall.ok',
    CANCEL: 'dialogInstall.cancel',
  },
  VERSION: {
    TITLE: 'dialogVersion.title',
    DESCRIPTION: 'dialogVersion.description',
    OK: 'dialogVersion.ok',
    CANCEL: 'dialogVersion.cancel',
  },
} as const;

Also applies to: 29-35

packages/web/src/app/[lng]/layout.tsx (1)

47-47: ExtensionDialog의 조건부 렌더링 검토 필요

ExtensionDialog가 항상 렌더링되고 있습니다. 다이얼로그가 필요한 경우에만 렌더링되도록 최적화하는 것이 좋습니다.

다음과 같이 상태를 사용하여 조건부 렌더링을 구현하는 것을 고려해보세요:

- <ExtensionDialog lng={lng} />
+ {isExtensionDialogNeeded && <ExtensionDialog lng={lng} />}
packages/web/src/app/i18n/locales/ko/translation.json (1)

37-42: 설치 다이얼로그의 문구를 더 친근하게 개선하면 좋겠습니다.

현재 문구가 다소 딱딱한 느낌이 있습니다. 사용자 경험 향상을 위해 더 친근한 톤으로 수정을 제안드립니다.

다음과 같이 수정하는 것을 고려해보세요:

   "dialogInstall": {
-    "title": "확장 프로그램 미설치",
-    "description": "설치해야 메모 기능을 이용하실 수 있습니다. 설치하러 가시겠습니까?",
+    "title": "확장 프로그램이 필요해요",
+    "description": "메모 기능을 사용하기 위해서는 확장 프로그램이 필요합니다. 지금 설치하시겠어요?",
     "cancel": "설치하지 않고 이용하기",
     "ok": "설치하러 가기"
   }
packages/web/src/app/components/ExtensionDialog/index.tsx (2)

16-16: 인터페이스 문서화 개선 필요

ExtensionDialogProps 인터페이스가 LanguageType을 확장하고 있지만, 이 컴포넌트의 목적과 사용법을 명확히 하기 위해 JSDoc 문서화가 필요합니다.

다음과 같이 문서화를 추가하는 것을 제안합니다:

+/**
+ * ExtensionDialog 컴포넌트의 프로퍼티
+ * @extends LanguageType - 다국어 지원을 위한 언어 타입
+ */
interface ExtensionDialogProps extends LanguageType {}

34-51: 접근성 및 사용자 경험 개선 필요

다이얼로그 컴포넌트의 접근성과 사용자 경험을 개선할 수 있습니다.

다음과 같은 개선을 제안합니다:

 <Dialog open={open} onOpenChange={setOpen}>
-  <DialogContent>
+  <DialogContent
+    aria-labelledby="extension-dialog-title"
+    aria-describedby="extension-dialog-description"
+  >
     <DialogHeader>
-      <DialogTitle>{extensionDialogInfo.message.title}</DialogTitle>
+      <DialogTitle id="extension-dialog-title">
+        {extensionDialogInfo.message.title}
+      </DialogTitle>
-      <DialogDescription>{extensionDialogInfo.message.description}</DialogDescription>
+      <DialogDescription id="extension-dialog-description">
+        {extensionDialogInfo.message.description}
+      </DialogDescription>
     </DialogHeader>
     <DialogFooter>
       {extensionDialogInfo.message.cancel && (
         <Button onClick={handleCloseClick} variant="secondary">
           {extensionDialogInfo.message?.cancel}
         </Button>
       )}
-      <Button onClick={handleUpdateClick}>{extensionDialogInfo.message.ok}</Button>
+      <Button
+        onClick={handleUpdateClick}
+        aria-label={`${extensionDialogInfo.message.ok} - 새 탭에서 열림`}
+      >
+        {extensionDialogInfo.message.ok}
+      </Button>
     </DialogFooter>
   </DialogContent>
 </Dialog>
packages/web/src/app/i18n/locales/en/translation.json (1)

37-49: 취소 버튼 문구의 일관성 개선이 필요합니다.

취소 버튼의 패턴이 다릅니다:

  • dialogInstall.cancel: "Use without installing"
  • dialogVersion.cancel: "Continue without updating"

하나의 패턴으로 통일하는 것을 제안드립니다:

-    "cancel": "Use without installing",
+    "cancel": "Continue without installing",
packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx (1)

MemoInput 타입 정의가 서로 다르므로 주의가 필요합니다

두 개의 서로 다른 MemoInput 타입이 발견되었습니다:

  • packages/web/src/app/[lng]/memos/types/Input.ts:
    export type MemoInput = {
      memo: string;
    };
  • pages/side-panel/src/types/Input.ts:
    export interface MemoInput {
      memo: string;
      isWish: boolean;
    }

사이드 패널의 MemoInputisWish 필드를 포함하고 있지만, 웹 패키지의 MemoInput은 이를 포함하고 있지 않습니다. 이는 의도된 차이인지 확인이 필요합니다.

🔗 Analysis chain

Line range hint 32-36: Form 타입 변경이 적절하게 이루어졌습니다만, 검증이 필요합니다.

InputType에서 MemoInput으로의 타입 변경이 올바르게 이루어졌습니다. 하지만 이 변경이 다른 컴포넌트에 영향을 미치지 않는지 확인이 필요합니다.

다음 스크립트를 실행하여 InputType의 다른 사용처를 확인하세요:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the impact of InputType to MemoInput change

# Search for any remaining usage of InputType
rg "InputType" --type ts --type tsx

# Search for MemoInput usage to ensure consistency
rg "MemoInput" --type ts --type tsx

Length of output: 127


Script:

#!/bin/bash
# Search for InputType and MemoInput without file type restrictions
rg "InputType"
rg "MemoInput"

# Find all TypeScript and TypeScript React files
fd "\.(ts|tsx)$" -x rg -l "InputType|MemoInput" {}

Length of output: 948


Script:

#!/bin/bash
# Let's check the content of Input.ts files to see the type definitions
cat "./pages/side-panel/src/types/Input.ts"
cat "./packages/web/src/app/[lng]/memos/types/Input.ts"

# Check if there are any other files importing from these Input.ts files
rg -l "from.*Input'"

Length of output: 387


Script:

#!/bin/bash
# Let's check the content of the importing files
cat "packages/web/src/app/[lng]/memos/types/index.ts"
cat "pages/side-panel/src/components/MemoForm.tsx"

# Also check if there are any other references to these types
rg "type.*=.*MemoInput" -A 2
rg "interface.*MemoInput" -A 2

Length of output: 4555

packages/web/src/app/[lng]/memos/components/MemoView/MemoItem.tsx (1)

121-121: prop 이름 변경이 잘 되었습니다!

id에서 memoId로의 prop 이름 변경은 더 명확한 의미를 전달하며 좋은 변경입니다. 코드의 일관성을 위해 다른 부분에서도 비슷한 패턴을 적용하면 좋을 것 같습니다.

예를 들어, 다음과 같은 부분들도 더 구체적인 이름으로 변경을 고려해보세요:

- const handleContentClick = (event: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>) => {
-   const id = event.currentTarget.id;
+ const handleMemoContentClick = (event: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>) => {
+   const memoId = event.currentTarget.id;
pages/side-panel/src/components/MemoForm.tsx (1)

Line range hint 65-72: 저장 로직 개선을 제안드립니다.

현재 구현은 잘 작동하지만, 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  1. 저장 중 로딩 상태 표시
  2. 에러 발생 시 더 자세한 에러 처리

다음과 같은 개선된 구현을 제안드립니다:

+ const [isLoading, setIsLoading] = useState(false);

  const saveMemo = async (data?: MemoInput) => {
+   setIsLoading(true);
    try {
      const memo = data?.memo ?? watch('memo');
      const isWish = data?.isWish ?? watch('isWish');

      const formattedMemo = await getFormattedMemo({ memo, isWish });

      if (currentMemo) mutateMemoPatch({ id: currentMemo.id, memoRequest: formattedMemo });
      else mutateMemoPost(formattedMemo);
+   } catch (error) {
+     toast({ 
+       title: I18n.get('toast_error_save'),
+       description: error instanceof Error ? error.message : undefined
+     });
+   } finally {
+     setIsLoading(false);
    }
  };
packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx (3)

10-24: 임포트 구문 개선 제안

임포트 구문을 다음과 같은 순서로 그룹화하면 코드 가독성이 향상될 것 같습니다:

  1. 외부 라이브러리 (React, Next.js)
  2. 내부 공통 컴포넌트
  3. 확장 관련 임포트
  4. 유틸리티 및 훅

Line range hint 51-66: 에러 처리 개선이 필요합니다

mutateDeleteMemo 호출 시 에러 처리가 누락되어 있습니다. 사용자에게 삭제 실패에 대한 피드백을 제공하는 것이 좋겠습니다.

다음과 같이 에러 처리를 추가하는 것을 제안합니다:

  mutateDeleteMemo(memoId, {
    onSuccess: ({ data }) => {
      if (!data) return;
      const saveMemo = () => mutatePostMemo(data[0]);
      toast({
        title: t('toastMessage.memoDeleted'),
        action: (
          <ToastAction altText={t('toastActionMessage.memoDeleteCancle')} onClick={saveMemo}>
            {t('toastActionMessage.memoDeleteCancle')}
          </ToastAction>
        ),
      });
    },
+   onError: (error) => {
+     toast({
+       title: t('toastMessage.error'),
+       description: t('toastMessage.memoDeleteFailed'),
+       variant: 'destructive',
+     });
+   },
  });

Line range hint 71-93: 카테고리 ID 타입 변환 안전성 개선 필요

Number() 함수를 사용한 타입 변환은 잘못된 입력값에 대해 취약할 수 있습니다. 더 안전한 방식으로 처리하는 것이 좋겠습니다.

다음과 같은 개선을 제안합니다:

- const handleCategoryChange = (categoryId: string) => {
+ const handleCategoryChange = (categoryId: string) => {
+   const parsedCategoryId = parseInt(categoryId, 10);
+   if (isNaN(parsedCategoryId)) {
+     toast({
+       title: t('toastMessage.error'),
+       description: t('toastMessage.invalidCategory'),
+       variant: 'destructive',
+     });
+     return;
+   }
    mutatePatchMemo(
-     { id: memoId, memoRequest: { category_id: Number(categoryId) } },
+     { id: memoId, memoRequest: { category_id: parsedCategoryId } },
      {
        onSuccess: () => {
-         const category = categories?.find(category => category.id === Number(categoryId));
+         const category = categories?.find(category => category.id === parsedCategoryId);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8c2603a and 45de68f.

📒 Files selected for processing (32)
  • packages/shared/src/constants/Extension.ts (1 hunks)
  • packages/shared/src/utils/extension/bridge/getExtensionManifest.ts (1 hunks)
  • packages/shared/src/utils/extension/bridge/getSidePanelOpen.ts (1 hunks)
  • packages/shared/src/utils/extension/bridge/refetchTheMemos.ts (1 hunks)
  • packages/web/src/app/[lng]/layout.tsx (2 hunks)
  • packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx (1 hunks)
  • packages/web/src/app/[lng]/login/components/LoginSection/index.tsx (0 hunks)
  • packages/web/src/app/[lng]/memos/components/Header/RefreshButton.tsx (2 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx (2 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx (1 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoView/MemoItem.tsx (1 hunks)
  • packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx (4 hunks)
  • packages/web/src/app/[lng]/memos/constants/guide.ts (0 hunks)
  • packages/web/src/app/[lng]/memos/constants/index.ts (0 hunks)
  • packages/web/src/app/[lng]/memos/hooks/useGuide.ts (1 hunks)
  • packages/web/src/app/[lng]/memos/types/Input.ts (1 hunks)
  • packages/web/src/app/[lng]/memos/types/index.ts (1 hunks)
  • packages/web/src/app/[lng]/memos/utils/guide.ts (2 hunks)
  • packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts (1 hunks)
  • packages/web/src/app/components/ExtensionDialog/index.tsx (1 hunks)
  • packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts (1 hunks)
  • packages/web/src/app/components/index.ts (1 hunks)
  • packages/web/src/app/i18n/client.js (0 hunks)
  • packages/web/src/app/i18n/locales/en/translation.json (1 hunks)
  • packages/web/src/app/i18n/locales/ko/translation.json (2 hunks)
  • packages/web/src/hooks/index.ts (1 hunks)
  • packages/web/src/hooks/useGetExtensionManifest.ts (1 hunks)
  • packages/web/src/utils/LocalStorage.ts (1 hunks)
  • packages/web/src/utils/index.ts (1 hunks)
  • packages/web/tsconfig.json (1 hunks)
  • pages/side-panel/src/components/MemoForm.tsx (3 hunks)
  • pages/side-panel/src/types/Input.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • packages/web/src/app/[lng]/login/components/LoginSection/index.tsx
  • packages/web/src/app/[lng]/memos/constants/guide.ts
  • packages/web/src/app/[lng]/memos/constants/index.ts
  • packages/web/src/app/i18n/client.js
✅ Files skipped from review due to trivial changes (1)
  • packages/web/src/app/[lng]/memos/types/index.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/web/src/utils/LocalStorage.ts

[error] 21-37: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 31-31: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 35-35: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🔇 Additional comments (32)
packages/shared/src/constants/Extension.ts (2)

2-2: Chrome 확장 프로그램 ID의 유효성을 확인하세요.

확장 프로그램 ID가 하드코딩되어 있습니다. 이는 보안상 민감한 정보일 수 있으며, 환경에 따라 다른 값이 필요할 수 있습니다.

다음 스크립트로 확장 프로그램 ID의 사용처를 확인해보세요:


3-3: 버전 관리 방식을 검토하세요.

lastVersion 값이 하드코딩되어 있습니다. 이는 배포 프로세스와 연동되어 자동으로 관리되어야 할 수 있습니다.

다음 스크립트로 버전 관리 방식을 확인해보세요:

✅ Verification successful

Let me check if there are any build or version management scripts that might be handling this version synchronization.


Let me check the update_version.sh script since it was referenced in the package.json scripts.


버전 관리가 적절히 구현되어 있습니다.

현재 버전 관리는 다음과 같이 구현되어 있습니다:

  • update_version.sh 스크립트를 통해 모든 package.json 파일의 버전을 일괄 업데이트
  • pnpm update-version 명령어로 스크립트 실행 가능
  • EXTENSION.lastVersion은 웹 애플리케이션에서 확장 프로그램의 최신 버전 확인용으로 사용됨

버전 값이 하드코딩되어 있지만, 이는 의도된 설계로 보입니다. 확장 프로그램 사용자에게 업데이트 알림을 제공하기 위한 용도입니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 버전 정보 관리 방식 확인

# package.json의 버전과 일치하는지 확인
fd -g "package.json" --exec cat {} \; | jq -r '.version // empty'

# manifest.json의 버전과 일치하는지 확인
fd -g "manifest.json" --exec cat {} \; | jq -r '.version // empty'

Length of output: 228


Script:

#!/bin/bash
# Check for version management related scripts
fd -e js -e ts -g "*version*" --exec echo "=== {} ===" \; --exec cat {} \;

# Check package.json scripts for version management
fd -g "package.json" --exec echo "=== {} ===" \; --exec jq '.scripts | select(. != null)' {} \;

# Check for any GitHub Actions workflows that might handle versioning
fd -g "*.yml" -g "*.yaml" -p ".github/workflows" --exec echo "=== {} ===" \; --exec cat {} \;

Length of output: 6100


Script:

#!/bin/bash
# Check the version update script
fd -g "update_version.sh" --exec echo "=== {} ===" \; --exec cat {} \;

# Also check for any version-related constants or configurations
rg -g '!node_modules' -g '!dist' -A 5 -B 5 "lastVersion|version" --type ts

Length of output: 4594

packages/web/src/utils/index.ts (1)

4-4: LocalStorage 유틸리티 통합이 잘 되었습니다!

로컬 스토리지 관련 기능들을 중앙 집중화하여 관리하는 것은 좋은 접근 방식입니다. 이를 통해 코드의 일관성과 유지보수성이 향상될 것으로 기대됩니다.

packages/web/src/app/[lng]/memos/types/Input.ts (1)

1-3: 구현이 명확하고 깔끔합니다!

카테고리 입력을 위한 타입 정의가 잘 되어있습니다.

packages/web/src/app/components/index.ts (1)

2-2: 코드가 적절해 보입니다!

새로운 ExtensionDialog 컴포넌트의 내보내기가 기존 패턴을 잘 따르고 있습니다.

ExtensionDialog 컴포넌트의 존재 여부를 확인하기 위해 다음 스크립트를 실행합니다:

✅ Verification successful

ExtensionDialog 컴포넌트가 올바르게 구현되어 있습니다

ExtensionDialog 컴포넌트가 packages/web/src/app/components/ExtensionDialog/index.tsx에 존재하며, 필요한 모든 관련 파일들(useExtensionDialog.ts, getExtensionDialogInfo.ts)이 적절히 구현되어 있습니다. 컴포넌트 내보내기가 정상적으로 작동할 것입니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: ExtensionDialog 컴포넌트 파일의 존재 여부 확인

# ExtensionDialog.tsx 또는 ExtensionDialog/index.tsx 파일 검색
fd -e tsx -e ts "ExtensionDialog" packages/web/src/app/components

Length of output: 209


Script:

#!/bin/bash
# Check for the main ExtensionDialog component file
fd -e tsx "ExtensionDialog" packages/web/src/app/components

# Check the content of getExtensionDialogInfo.ts
cat packages/web/src/app/components/ExtensionDialog/getExtensionDialogInfo.ts

# Check the content of useExtensionDialog.ts
cat packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts

Length of output: 2893


Script:

#!/bin/bash
# Check for index.tsx in ExtensionDialog directory
fd -e tsx "index" packages/web/src/app/components/ExtensionDialog

# Check for ExtensionDialog.tsx in the components directory
fd -e tsx "ExtensionDialog.tsx" packages/web/src/app/components

Length of output: 187


Script:

#!/bin/bash
# Check the content of ExtensionDialog/index.tsx
cat packages/web/src/app/components/ExtensionDialog/index.tsx

Length of output: 1726

packages/web/src/hooks/index.ts (1)

3-3: 새로운 훅 내보내기가 올바르게 추가되었습니다.

코드가 기존 패턴을 잘 따르고 있습니다. 다만 새로 추가된 useGetExtensionManifest 훅이 실제로 존재하는지 확인이 필요합니다.

다음 스크립트를 실행하여 훅 파일의 존재 여부를 확인하겠습니다:

✅ Verification successful

useGetExtensionManifest 훅이 정상적으로 구현되어 있고 올바르게 사용되고 있습니다.

  • 훅이 packages/web/src/hooks/useGetExtensionManifest.ts에 구현되어 있습니다.
  • ExtensionDialogExtensionVersion 컴포넌트에서 이미 사용 중입니다.
  • 구현이 React 훅 규칙을 준수하고 있으며, 확장 프로그램 매니페스트를 가져오는 기능이 올바르게 구현되어 있습니다.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 새로 추가된 훅 파일의 존재 여부 확인

# packages/web/src/hooks 디렉토리에서 useGetExtensionManifest 파일 검색
fd "useGetExtensionManifest\.(ts|tsx)$" packages/web/src/hooks

# 파일 내용에서 default export 확인
rg "export default" -A 3 packages/web/src/hooks/useGetExtensionManifest

Length of output: 275


Script:

#!/bin/bash
# Check if the file exists in the PR branch
git ls-files packages/web/src/hooks/useGetExtensionManifest.ts

# Check if this is a newly added file
git status packages/web/src/hooks/useGetExtensionManifest.ts

# Try to find any references to this hook in the codebase
rg "useGetExtensionManifest" --type ts --type tsx

Length of output: 318


Script:

#!/bin/bash
# Check the content of the hook file
cat packages/web/src/hooks/useGetExtensionManifest.ts

# Find references without file type specification
rg "useGetExtensionManifest"

Length of output: 1296

packages/web/src/app/[lng]/memos/hooks/useGuide.ts (2)

3-3: 유틸리티 함수 임포트 추가 적절

로컬 스토리지 관련 작업을 중앙화된 유틸리티로 관리하는 것은 좋은 접근 방식입니다. 코드의 일관성과 유지보수성이 향상될 것으로 예상됩니다.


7-7: 로컬 스토리지 접근 방식 개선됨

직접적인 localStorage 접근 대신 유틸리티 함수를 사용하는 방식으로 개선되었습니다. 이는 다음과 같은 이점이 있습니다:

  • 스토리지 접근 로직의 중앙화
  • 키 관리의 일관성
  • 코드 재사용성 향상

로컬 스토리지 키가 일관되게 사용되는지 확인하겠습니다:

✅ Verification successful

로컬 스토리지 접근이 일관되게 개선되었음을 확인했습니다

검증 결과:

  • LocalStorage 유틸리티를 통한 일관된 접근 방식이 확인됨
  • 직접적인 localStorage 접근은 오직 LocalStorage.ts 유틸리티 내부에서만 발생
  • LOCAL_STORAGE_KEY_MAP이 중앙에서 관리되며 일관되게 사용됨
  • 키 값들이 상수로 잘 정의되어 있음 (guide, updateVersion, install)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of localStorage keys across the codebase

# Check for any direct localStorage access
rg "localStorage\." --type ts --type tsx

# Check for consistent usage of LOCAL_STORAGE_KEY_MAP
rg "LOCAL_STORAGE_KEY_MAP\.guide" --type ts --type tsx

Length of output: 155


Script:

#!/bin/bash
# Description: Verify consistent usage of localStorage keys across the codebase

# Check for any direct localStorage access
rg "localStorage\."

# Check for consistent usage of LOCAL_STORAGE_KEY_MAP
rg "LOCAL_STORAGE_KEY_MAP"

# Find the definition of LOCAL_STORAGE_KEY_MAP
ast-grep --pattern 'const LOCAL_STORAGE_KEY_MAP = $_'

Length of output: 2544

packages/shared/src/utils/extension/bridge/refetchTheMemos.ts (1)

1-1: EXTENSION 객체로의 마이그레이션이 올바르게 수행되었습니다.

상수 EXTENSION_ID에서 EXTENSION 객체로의 변경이 일관성 있게 적용되었습니다.

크롬 익스텐션 메시징 기능이 다른 파일들에서도 올바르게 업데이트되었는지 확인하겠습니다:

Also applies to: 6-6

✅ Verification successful

Let me gather more information about the EXTENSION constant usage to ensure the migration is complete.


EXTENSION 객체로의 마이그레이션이 성공적으로 완료되었습니다

코드베이스 전체 검사 결과:

  • 모든 EXTENSION_ID 참조가 EXTENSION.id로 성공적으로 대체되었습니다
  • EXTENSION 상수가 일관되게 @src/constants 또는 @extension/shared/constants에서 올바르게 임포트되고 있습니다
  • Chrome 익스텐션 메시징 기능에서 EXTENSION.id가 정상적으로 사용되고 있습니다
  • EXTENSION 객체의 다른 속성들(lastVersion 등)도 적절하게 활용되고 있습니다
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 모든 파일에서 EXTENSION_ID 사용 여부 확인 및 EXTENSION.id 사용 검증

# EXTENSION_ID가 여전히 사용되고 있는지 확인
echo "Checking for remaining EXTENSION_ID usage:"
rg "EXTENSION_ID"

# EXTENSION.id 사용 패턴 확인
echo -e "\nVerifying EXTENSION.id usage in chrome.runtime.sendMessage calls:"
ast-grep --pattern 'chrome.runtime.sendMessage($EXTENSION.id, $_)'

Length of output: 481


Script:

#!/bin/bash
# Check EXTENSION constant imports and usage
echo "Checking EXTENSION imports:"
rg "import.*EXTENSION.*from.*constants"

echo -e "\nChecking EXTENSION object usage:"
rg "EXTENSION\." -A 2

Length of output: 3528

packages/shared/src/utils/extension/bridge/getSidePanelOpen.ts (2)

1-1: 상수에서 객체로의 마이그레이션이 올바르게 수행되었습니다.

EXTENSION_ID 상수를 EXTENSION 객체로 변경한 것이 적절합니다. 이는 확장 프로그램 관련 설정을 더 체계적으로 관리할 수 있게 해줍니다.


6-6: Chrome 메시징 로직이 새로운 구조에 맞게 업데이트되었는지 확인이 필요합니다.

EXTENSION.id를 사용하도록 변경된 부분이 올바르게 작동하는지 확인해주세요.

다음 스크립트를 실행하여 다른 파일들에서도 동일한 패턴으로 변경되었는지 확인하겠습니다:

✅ Verification successful

Chrome 메시징 구조가 일관되게 업데이트되었음을 확인했습니다

모든 Chrome 메시징 관련 코드가 EXTENSION.id를 사용하도록 올바르게 구현되어 있습니다:

  • packages/shared/src/constants/Extension.ts에 정의된 EXTENSION.id가 일관되게 사용됨
  • refetchTheMemos, getSidePanelOpen, getExtensionManifest 등 모든 브릿지 모듈에서 동일한 패턴으로 구현됨
  • Runtime 모듈을 통한 메시지 처리도 정상적으로 구성됨
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of EXTENSION.id across the codebase
# Check for any remaining instances of EXTENSION_ID
rg "EXTENSION_ID"

# Check for the new pattern usage
rg "EXTENSION\.id.*chrome\.runtime\.sendMessage"

Length of output: 68


Script:

#!/bin/bash
# Let's check for all chrome.runtime.sendMessage usages and EXTENSION related imports/constants
rg -A 2 "chrome\.runtime\.sendMessage" 

# Check for EXTENSION constant definition and usage
rg "EXTENSION.*=.*{" -A 3
rg "import.*EXTENSION.*from"

Length of output: 2560


Script:

#!/bin/bash
# Let's check the EXTENSION constant definition
rg -l "export.*const.*EXTENSION" 
rg -A 5 "export.*const.*EXTENSION"

# Check if there are any other chrome messaging patterns
rg "chrome\.runtime\." -g "!*.test.*" -g "!*.spec.*" -g "!*.md"

Length of output: 4294

packages/web/src/hooks/useGetExtensionManifest.ts (1)

1-3: 임포트 구문이 깔끔하게 정리되어 있습니다!

필요한 훅과 유틸리티 함수들이 잘 임포트되어 있습니다.

packages/shared/src/utils/extension/bridge/getExtensionManifest.ts (2)

1-1: 상수 구조 개선이 잘 이루어졌습니다.

EXTENSION 객체를 사용하여 관련 속성들을 그룹화하는 방식으로 변경한 것이 좋은 개선입니다. 이는 확장성과 유지보수성을 향상시킵니다.


6-6: Chrome API 호출 업데이트가 올바르게 적용되었습니다.

EXTENSION.id를 사용하도록 변경된 부분이 일관성 있게 잘 적용되었습니다. 다만, 이 변경이 다른 파일들에도 올바르게 적용되었는지 확인이 필요합니다.

✅ Verification successful

Based on the results, I can generate the final response as all the necessary information has been gathered. The search results show consistent usage of EXTENSION.id in message passing across the codebase, and there are no remaining instances of EXTENSION_ID.

Chrome API 호출이 전체 코드베이스에서 일관되게 적용되었습니다.

모든 chrome.runtime.sendMessage 호출에서 EXTENSION.id가 올바르게 사용되고 있으며, 이전 EXTENSION_ID 사용이 완전히 제거되었음을 확인했습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of EXTENSION.id across the codebase

# Check for any remaining usage of EXTENSION_ID
rg "EXTENSION_ID" 

# Check for consistent usage of EXTENSION.id in message passing
ast-grep --pattern 'chrome.runtime.sendMessage($EXTENSION.id, $$$)'

Length of output: 575

packages/web/src/app/[lng]/login/components/LoginSection/ExtensionVersion.tsx (1)

18-20: 버전 비교 로직이 명확하고 깔끔합니다

버전 비교 로직이 이해하기 쉽고, 국제화도 잘 적용되어 있습니다. 조건부 렌더링을 통해 적절한 메시지를 표시하고 있습니다.

packages/web/src/app/[lng]/memos/components/Header/RefreshButton.tsx (2)

11-11: 로컬 스토리지 유틸리티 추가 👍

로컬 스토리지 관련 작업을 중앙화된 유틸리티로 관리하는 것은 좋은 접근 방식입니다.


22-22: 로컬 스토리지 접근 방식 개선 ✨

직접적인 localStorage 접근 대신 LocalStorage.setTrue() 유틸리티 메서드를 사용하는 것으로 변경된 점이 좋습니다. 이는 다음과 같은 이점이 있습니다:

  • 타입 안정성 향상
  • 스토리지 키 관리 일원화
  • 코드 일관성 유지

하나 확인해 주실 점이 있습니다:

✅ Verification successful

가이드 기능의 로컬 스토리지 접근이 일관되게 구현되었습니다 ✨

검증 결과, 모든 가이드 관련 로컬 스토리지 접근이 LocalStorage 유틸리티 클래스와 LOCAL_STORAGE_KEY_MAP.guide를 일관되게 사용하고 있습니다:

  • useGuide.ts: LocalStorage.check() 사용
  • RefreshButton.tsx: LocalStorage.setTrue() 사용
  • guide.ts: LocalStorage.setTrue() 사용

직접적인 localStorage 접근은 발견되지 않았습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the guide functionality is consistently implemented across components

# Search for any remaining direct localStorage access for guide functionality
rg "localStorage.*guide" --type ts --type tsx

# Search for consistent usage of LOCAL_STORAGE_KEY_MAP.guide
rg "LOCAL_STORAGE_KEY_MAP\.guide" --type ts --type tsx

Length of output: 160


Script:

#!/bin/bash
# Search for any remaining direct localStorage access for guide functionality
rg "localStorage.*guide"

# Search for consistent usage of LOCAL_STORAGE_KEY_MAP.guide
rg "LOCAL_STORAGE_KEY_MAP\.guide"

# Search for LocalStorage utility class usage with guide
rg "LocalStorage.*guide"

Length of output: 787

packages/web/src/app/[lng]/memos/components/MemoSidebar/SidebarMenuItemAddCategory.tsx (1)

9-9: 타입 리팩토링이 잘 이루어졌습니다.

인라인 인터페이스를 별도의 타입 파일로 분리하여 재사용성과 유지보수성이 향상되었습니다. useForm 훅의 타입도 적절하게 업데이트되었습니다.

Also applies to: 13-13

packages/web/src/utils/LocalStorage.ts (1)

19-19: 타입 정의가 명확하고 적절합니다.

키 맵과 업데이트 버전 타입을 결합한 방식이 타입 안전성을 잘 보장합니다.

packages/web/src/app/[lng]/memos/utils/guide.ts (2)

4-4: 로컬 스토리지 관리를 위한 유틸리티 함수 사용이 적절합니다.

중앙 집중화된 유틸리티를 사용함으로써 코드의 일관성과 유지보수성이 향상되었습니다.


40-40: 로컬 스토리지 접근 방식이 개선되었습니다.

타입 안정성이 향상되고 키 관리가 중앙화되어 오타나 중복 사용의 위험이 줄어들었습니다.

packages/web/src/app/components/ExtensionDialog/useExtensionDialog.ts (1)

1-7: 코드가 깔끔하고 잘 구성되어 있습니다!

임포트문이 잘 정리되어 있고, DialogType의 타입 정의가 명확합니다.

packages/web/src/app/[lng]/layout.tsx (1)

13-13: 임포트 구문이 적절히 추가되었습니다.

컴포넌트 임포트가 기존 임포트 그룹과 일관성있게 작성되었습니다.

packages/web/src/app/i18n/locales/ko/translation.json (1)

16-16: 토스트 메시지의 일관성이 잘 유지되었습니다.

메시지가 간결하고 명확하며, 기존 토스트 메시지들과 문체가 잘 통일되어 있습니다.

Also applies to: 21-24

packages/web/src/app/i18n/locales/en/translation.json (3)

16-23: 토스트 메시지가 일관성 있게 작성되었습니다!

각 메시지가 명확하고 간결하며, 문장 구조와 마침표 사용이 일관됩니다.


26-27: 옵션 텍스트의 대소문자 수정이 적절합니다!

현대적인 UI 작성 가이드라인에 맞게 소문자로 통일하고, 간결하게 수정되었습니다.


52-53: 툴팁 텍스트가 적절하게 개선되었습니다!

간결하고 명확한 설명으로 수정되었으며, 현대적인 UI 작성 방식과 일치합니다.

packages/web/src/app/[lng]/memos/components/MemoDialog/index.tsx (1)

14-14: 타입 임포트가 올바르게 추가되었습니다.

상대 경로를 사용한 타입 임포트가 적절하게 구현되었습니다.

pages/side-panel/src/components/MemoForm.tsx (2)

21-21: 타입 구조 개선이 잘 이루어졌습니다!

타입을 별도의 파일로 분리하여 관리하는 것은 좋은 구조적 개선입니다.


Line range hint 38-43: 폼 필드 타입 검증이 필요합니다.

MemoInput 타입으로 변경된 폼이 모든 필수 필드를 올바르게 처리하는지 확인이 필요합니다.

다음 스크립트로 MemoInput 타입 정의를 확인하겠습니다:

✅ Verification successful

폼 필드가 타입 정의와 일치함을 확인했습니다.

pages/side-panel/src/types/Input.ts에 정의된 MemoInput 인터페이스와 폼의 기본값이 정확히 일치합니다:

  • memo: string
  • isWish: boolean
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# MemoInput 타입 정의 확인
rg -t typescript "type MemoInput" -A 5

Length of output: 75


Script:

#!/bin/bash
# Search for MemoInput type definition using ast-grep
ast-grep --pattern 'type MemoInput = {
  $$$
}'

# Also search for interface definition
ast-grep --pattern 'interface MemoInput {
  $$$
}'

# Search for any file containing MemoInput
rg "MemoInput"

Length of output: 1192

packages/web/src/app/[lng]/memos/components/MemoView/MemoOption.tsx (2)

26-28: Props 인터페이스 변경이 적절합니다

id에서 memoId로의 이름 변경은 프로퍼티의 목적을 더 명확하게 표현하며, 다른 ID들과의 혼동을 방지할 수 있습니다.


Line range hint 95-124: UI 구현이 잘 되어있습니다

드롭다운 메뉴와 선택 컴포넌트의 구현이 깔끔하고, 번역 키가 적절히 사용되었습니다.

Comment on lines +7 to +11
export const getExtensionDialogInfo = (
lng: Language,
manifest: ReturnType<typeof useExtensionDialog>['manifest'],
dialogType?: DialogType,
) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

타입 안전성 개선이 필요합니다

dialogType 매개변수의 타입 안전성을 높이기 위해 다음과 같은 수정을 제안합니다:

 export const getExtensionDialogInfo = (
   lng: Language,
   manifest: ReturnType<typeof useExtensionDialog>['manifest'],
-  dialogType?: DialogType,
+  dialogType: DialogType,
 ) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getExtensionDialogInfo = (
lng: Language,
manifest: ReturnType<typeof useExtensionDialog>['manifest'],
dialogType?: DialogType,
) => {
export const getExtensionDialogInfo = (
lng: Language,
manifest: ReturnType<typeof useExtensionDialog>['manifest'],
dialogType: DialogType,
) => {

@guesung guesung merged commit 527ddc3 into develop Nov 25, 2024
8 checks passed
@guesung guesung deleted the feature/ux branch November 25, 2024 03:43
@coderabbitai coderabbitai bot mentioned this pull request Nov 26, 2024
Copy link

사용자 경험 개선

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant