Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions dist/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
},
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["https://*.coupang.com/*"],
"js": ["js/contentScript.js"],
"run_at": "document_idle"
}
],
"background": {
"service_worker": "js/backgroundPage.js"
},
Expand Down
1 change: 1 addition & 0 deletions dist/popup.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Chrome Extension (built with TypeScript + React)</title>
<script src="js/popup.js"></script>
</head>
Expand Down
2 changes: 1 addition & 1 deletion src/popup/__tests__/test_popup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from "react";
import { Popup } from "../component";
import { Popup } from "../getProduct";
import renderer from "react-test-renderer";

it("component renders", () => {
Expand Down
74 changes: 0 additions & 74 deletions src/popup/component.tsx

This file was deleted.

33 changes: 33 additions & 0 deletions src/popup/controlFont.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";

const ControlFont = () => {
const sendMessage = (
type: "ENLARGE_CONTENT_FONT" | "RESET_CONTENT_FONT",
) => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]?.id) return;
chrome.tabs.sendMessage(tabs[0].id, { type }, (response) => {
console.log("λ©”μ‹œμ§€ 전솑됨:", response);
});
});
};
Comment on lines +4 to +13
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

Add error handling for message sending failures

The sendMessage function doesn't handle potential runtime errors that could occur during message sending. Adding proper error handling would improve robustness.

chrome.tabs.sendMessage(tabs[0].id, { type }, (response) => {
+    if (chrome.runtime.lastError) {
+        console.error("Error sending message:", chrome.runtime.lastError.message);
+        return;
+    }
    console.log("λ©”μ‹œμ§€ 전솑됨:", response);
});
πŸ“ 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
const sendMessage = (
type: "ENLARGE_CONTENT_FONT" | "RESET_CONTENT_FONT",
) => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]?.id) return;
chrome.tabs.sendMessage(tabs[0].id, { type }, (response) => {
console.log("λ©”μ‹œμ§€ 전솑됨:", response);
});
});
};
const sendMessage = (
type: "ENLARGE_CONTENT_FONT" | "RESET_CONTENT_FONT",
) => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]?.id) return;
chrome.tabs.sendMessage(tabs[0].id, { type }, (response) => {
if (chrome.runtime.lastError) {
console.error("Error sending message:", chrome.runtime.lastError.message);
return;
}
console.log("λ©”μ‹œμ§€ 전솑됨:", response);
});
});
};


return (
<div className="flex flex-col gap-2 mt-2">
<button
onClick={() => sendMessage("ENLARGE_CONTENT_FONT")}
className="w-full py-2 bg-green-500 hover:bg-green-600 text-white rounded text-sm"
>
글씨 크게
</button>
<button
onClick={() => sendMessage("RESET_CONTENT_FONT")}
className="w-full py-2 bg-gray-300 hover:bg-gray-400 text-gray-800 rounded text-sm"
>
μ›λž˜λŒ€λ‘œ
</button>
</div>
);
};

export default ControlFont;
67 changes: 67 additions & 0 deletions src/popup/getProduct.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useState } from "react";
import "../css/app.css";

const getProduct = () => {
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

Use PascalCase for React component names

React component names should follow PascalCase naming convention. Rename getProduct to GetProduct for consistency with React standards.

-const getProduct = () => {
+const GetProduct = () => {

Don't forget to also update the export at the bottom of the file:

-export default getProduct;
+export default GetProduct;
πŸ“ 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
const getProduct = () => {
const GetProduct = () => {
// component logic here
};
export default GetProduct;

const [productInfo, setProductInfo] = useState<{
productId: string;
productTitle: string;
} | null>(null);

const [error, setError] = useState("");

const getProductInfo = () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]?.id) return;

Comment on lines +13 to +15
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

Add error handling for query failure

The current implementation doesn't handle potential errors when querying tabs. Consider adding proper error handling.

- chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
-     if (!tabs[0]?.id) return;
+ chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
+     if (!tabs[0]?.id) {
+         setError("ν™œμ„±ν™”λœ 탭을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.");
+         return;
+     }
πŸ“ 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
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]?.id) return;
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs[0]?.id) {
setError("ν™œμ„±ν™”λœ 탭을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.");
return;
}

chrome.tabs.sendMessage(
tabs[0].id,
{ type: "GET_PRODUCT_INFO" },
(response) => {
if (response?.matched) {
const { productId, productTitle } = response;
setProductInfo({ productId, productTitle });
setError("");
const utterance = new SpeechSynthesisUtterance(
`μƒν’ˆλͺ…은 ${productTitle}이고, μƒν’ˆ μ•„μ΄λ””λŠ” ${productId}μž…λ‹ˆλ‹€.`,
);
utterance.lang = "ko-KR";
speechSynthesis.speak(utterance);
} else {
setProductInfo(null);
setError(
"❗ ν˜„μž¬ νŽ˜μ΄μ§€λŠ” 'μ‹ν’ˆ' μΉ΄ν…Œκ³ λ¦¬κ°€ μ•„λ‹™λ‹ˆλ‹€.",
);
}
},
);
Comment on lines +16 to +36
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

Add error handling for message sending failures

The current implementation doesn't handle the case where message sending fails or returns undefined. Add error handling for runtime.lastError.

chrome.tabs.sendMessage(
    tabs[0].id,
    { type: "GET_PRODUCT_INFO" },
    (response) => {
+       if (chrome.runtime.lastError) {
+           setError("λ©”μ‹œμ§€ 전솑 μ‹€νŒ¨: " + chrome.runtime.lastError.message);
+           return;
+       }
+       
+       if (!response) {
+           setError("응닡이 μ—†μŠ΅λ‹ˆλ‹€. νŽ˜μ΄μ§€μ—μ„œ μ½˜ν…μΈ  μŠ€ν¬λ¦½νŠΈκ°€ μ‹€ν–‰ 쀑인지 ν™•μΈν•˜μ„Έμš”.");
+           return;
+       }
        
        if (response?.matched) {
            const { productId, productTitle } = response;
            setProductInfo({ productId, productTitle });
            setError("");
            const utterance = new SpeechSynthesisUtterance(
                `μƒν’ˆλͺ…은 ${productTitle}이고, μƒν’ˆ μ•„μ΄λ””λŠ” ${productId}μž…λ‹ˆλ‹€.`,
            );
            utterance.lang = "ko-KR";
            speechSynthesis.speak(utterance);
        } else {
            setProductInfo(null);
            setError(
                "❗ ν˜„μž¬ νŽ˜μ΄μ§€λŠ” 'μ‹ν’ˆ' μΉ΄ν…Œκ³ λ¦¬κ°€ μ•„λ‹™λ‹ˆλ‹€.",
            );
        }
    },
);
πŸ“ 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
chrome.tabs.sendMessage(
tabs[0].id,
{ type: "GET_PRODUCT_INFO" },
(response) => {
if (response?.matched) {
const { productId, productTitle } = response;
setProductInfo({ productId, productTitle });
setError("");
const utterance = new SpeechSynthesisUtterance(
`μƒν’ˆλͺ…은 ${productTitle}이고, μƒν’ˆ μ•„μ΄λ””λŠ” ${productId}μž…λ‹ˆλ‹€.`,
);
utterance.lang = "ko-KR";
speechSynthesis.speak(utterance);
} else {
setProductInfo(null);
setError(
"❗ ν˜„μž¬ νŽ˜μ΄μ§€λŠ” 'μ‹ν’ˆ' μΉ΄ν…Œκ³ λ¦¬κ°€ μ•„λ‹™λ‹ˆλ‹€.",
);
}
},
);
chrome.tabs.sendMessage(
tabs[0].id,
{ type: "GET_PRODUCT_INFO" },
(response) => {
if (chrome.runtime.lastError) {
setError("λ©”μ‹œμ§€ 전솑 μ‹€νŒ¨: " + chrome.runtime.lastError.message);
return;
}
if (!response) {
setError("응닡이 μ—†μŠ΅λ‹ˆλ‹€. νŽ˜μ΄μ§€μ—μ„œ μ½˜ν…μΈ  μŠ€ν¬λ¦½νŠΈκ°€ μ‹€ν–‰ 쀑인지 ν™•μΈν•˜μ„Έμš”.");
return;
}
if (response?.matched) {
const { productId, productTitle } = response;
setProductInfo({ productId, productTitle });
setError("");
const utterance = new SpeechSynthesisUtterance(
`μƒν’ˆλͺ…은 ${productTitle}이고, μƒν’ˆ μ•„μ΄λ””λŠ” ${productId}μž…λ‹ˆλ‹€.`,
);
utterance.lang = "ko-KR";
speechSynthesis.speak(utterance);
} else {
setProductInfo(null);
setError(
"❗ ν˜„μž¬ νŽ˜μ΄μ§€λŠ” 'μ‹ν’ˆ' μΉ΄ν…Œκ³ λ¦¬κ°€ μ•„λ‹™λ‹ˆλ‹€.",
);
}
},
);

});
};
return (
<div className="w-72 p-4 bg-white rounded-lg shadow-lg">
<h1 className="text-xl font-semibold mb-3 text-gray-800">
VOIM μƒν’ˆ 리더기
</h1>

<button
onClick={getProductInfo}
className="w-full py-2 bg-blue-600 hover:bg-blue-700 text-white rounded text-sm mb-2"
>
μƒν’ˆ 정보 μ½μ–΄μ€˜!
</button>
{productInfo && (
<div className="mt-4 text-sm text-gray-700">
<p>
<strong>μƒν’ˆλͺ…:</strong> {productInfo.productTitle}
</p>
<p>
<strong>μƒν’ˆ ID:</strong> {productInfo.productId}
</p>
</div>
)}

{error && <p className="mt-4 text-red-500 text-sm">{error}</p>}
</div>
);
};

export default getProduct;
13 changes: 9 additions & 4 deletions src/popup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as React from "react";
import { createRoot } from "react-dom/client";
import browser from "webextension-polyfill";
import { Popup } from "./component";
import GetProduct from "./getProduct";
import "../css/app.css";

// // // //
import ControlFont from "./controlFont";

browser.tabs
.query({ active: true, currentWindow: true })
Expand All @@ -21,7 +20,13 @@ browser.tabs
const container = document.getElementById("popup");
if (container) {
const root = createRoot(container);
root.render(<Popup />);
root.render(
<div className="p-4 w-80">
<h1 className="text-lg font-bold mb-4">VOIM</h1>
<GetProduct />
<ControlFont />
</div>,
);
} else {
console.error("popupμ΄λΌλŠ” idλ₯Ό κ°€μ§„ μš”μ†Œκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•„μš”!");
}
Expand Down
2 changes: 1 addition & 1 deletion src/popup/stories/Popup.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from "react";
import { Popup } from "../component";
import { Popup } from "../getProduct";
import { Meta } from "@storybook/react";

// // // //
Expand Down