Skip to content

Commit

Permalink
v1.0.0 beta.4 (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
woong-jae authored Jan 1, 2024
1 parent badf715 commit 450d2d7
Show file tree
Hide file tree
Showing 13 changed files with 261 additions and 23 deletions.
10 changes: 7 additions & 3 deletions src/app/chrome-extension/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,23 @@ const solutionTracker = createSolutionTracker();
solutionTracker.onSolve(async (solution) => {
const isConfirm = await crossContextConfirm(
'background',
'[Code-Vault]\n정답입니다!🎉 풀이를 저장하겠습니까?',
'정답입니다!🎉 풀이를 저장하겠습니까?',
);

if (!isConfirm) return;

const accessToken = await accessTokenStorage.retrieve();
if (!accessToken) {
alertToWorld('저장에 실패했습니다');
alertToWorld('저장에 실패했습니다. 깃허브 계정과 연동을 진행해주세요.');
return;
}

const isSuccess = await saveSolution({ solution, accessToken });
alertToWorld(isSuccess ? '성공적으로 저장했습니다' : '저장에 실패했습니다');
alertToWorld(
isSuccess
? '성공적으로 저장했습니다.'
: '저장에 실패했습니다. 선택된 저장소가 있는지 확인해주세요.',
);
});

/* Chrome extension 아이콘 클릭시 설정 페이지 탭 열기 */
Expand Down
11 changes: 2 additions & 9 deletions src/app/chrome-extension/scripts/common-isolated/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { onAlert, onCrossContextConfirm } from '~/base/infra/chrome-extension';
import createEventBus from '~/base/infra/event-bus';
import { runApp } from './runApp';

createEventBus('isolated');

onCrossContextConfirm('isolated', (message) => {
const isConfirm = confirm(message);
return isConfirm;
});

onAlert((message) => {
alert(message);
});
runApp();
4 changes: 4 additions & 0 deletions src/app/chrome-extension/scripts/common-isolated/isolated.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* 백준 전역 css override */
html {
font-size: initial;
}
28 changes: 28 additions & 0 deletions src/app/chrome-extension/scripts/common-isolated/runApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { ReactElement } from 'react';
import { createRoot } from 'react-dom/client';
import { AlertProvider } from '@base/components/Alert';
import { ConfirmProvider } from '@base/components/Confirm';
import { ProblemSolvingPage } from '~/pages/problem-solving';
import '~/app/index.css';
import './isolated.css';

function Panel({ children }: { children: ReactElement }) {
return (
<div className="fixed right-5 top-5 z-[100] min-w-[350px]">{children}</div>
);
}

export function runApp() {
const $div = document.createElement('div');

document.body.append($div);

const root = createRoot($div);
root.render(
<AlertProvider Wrapper={Panel}>
<ConfirmProvider Wrapper={Panel}>
<ProblemSolvingPage />
</ConfirmProvider>
</AlertProvider>,
);
}
4 changes: 2 additions & 2 deletions src/assets/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"manifest_version": 3,
"name": "Code-Vault",
"description": "Code-Vault에서 제공하는 크롬 확장도구입니다.",
"version": "1.0.0.3",
"version_name": "1.0.0-beta.3",
"version": "1.0.0.4",
"version_name": "1.0.0-beta.4",
"author": "[email protected]",
"homepage_url": "https://github.com/woong-jae/code-vault",
"action": {},
Expand Down
80 changes: 80 additions & 0 deletions src/base/components/Alert/alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { createPortal } from 'react-dom';
import {
Card,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '../Card';
import { Button } from '../Button';
import {
createContext,
useContext,
useState,
type ReactElement,
useCallback,
} from 'react';

type AlertContent = {
title: string;
description: string;
};

const AlertContext = createContext<{
alert: (content: AlertContent) => void;
}>({
alert: () => {},
});

export function AlertProvider({
children,
Wrapper,
}: {
children: ReactElement;
Wrapper: (prop: { children: ReactElement }) => ReactElement;
}) {
const [isAlerting, setIsAlerting] = useState(false);
const [content, setContent] = useState<AlertContent>({
title: '',
description: '',
});

const alert = useCallback(
(props: AlertContent) => {
setContent(props);
setIsAlerting(true);
},
[setIsAlerting, setContent],
);

return (
<AlertContext.Provider
value={{
alert,
}}
>
{children}
{isAlerting &&
createPortal(
<Wrapper>
<Card>
<CardHeader>
<CardTitle>{content.title}</CardTitle>
<CardDescription>{content.description}</CardDescription>
</CardHeader>
<CardFooter className="flex flex-row-reverse">
<Button size="sm" onClick={() => setIsAlerting(false)}>
확인
</Button>
</CardFooter>
</Card>
</Wrapper>,
document.body,
)}
</AlertContext.Provider>
);
}

export function useAlert() {
return useContext(AlertContext);
}
1 change: 1 addition & 0 deletions src/base/components/Alert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './alert';
98 changes: 98 additions & 0 deletions src/base/components/Confirm/confirm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { createPortal } from 'react-dom';
import {
Card,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '../Card';
import { Button } from '../Button';
import {
createContext,
useContext,
useState,
type ReactElement,
useCallback,
} from 'react';

type ConfirmProps = {
title: string;
description: string;
onConfirm: (isConfirmed: boolean) => void;
};

const ConfirmContext = createContext<{
confirm: (props: ConfirmProps) => void;
}>({
confirm: () => false,
});

export function ConfirmProvider({
children,
Wrapper,
}: {
children: ReactElement;
Wrapper: (prop: { children: ReactElement }) => ReactElement;
}) {
const [isConfirming, setIsConfirming] = useState(false);
const [props, setProps] = useState<ConfirmProps>({
title: '',
description: '',
onConfirm: () => false,
});

const confirm = useCallback(
(props: ConfirmProps) => {
setProps(props);
setIsConfirming(true);
},
[setIsConfirming, setProps],
);

return (
<ConfirmContext.Provider
value={{
confirm,
}}
>
{children}
{isConfirming &&
createPortal(
<Wrapper>
<Card>
<CardHeader>
<CardTitle>{props.title}</CardTitle>
<CardDescription>{props.description}</CardDescription>
</CardHeader>
<CardFooter className="flex flex-row justify-end space-x-2">
<Button
size="sm"
variant={'outline'}
onClick={() => {
setIsConfirming(false);
props.onConfirm(false);
}}
>
취소
</Button>
<Button
size="sm"
onClick={() => {
setIsConfirming(false);
props.onConfirm(true);
}}
>
확인
</Button>
</CardFooter>
</Card>
</Wrapper>,
document.body,
)}
</ConfirmContext.Provider>
);
}

export function useConfirm() {
return useContext(ConfirmContext);
}
1 change: 1 addition & 0 deletions src/base/components/Confirm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './confirm';
2 changes: 1 addition & 1 deletion src/base/components/Loading/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function Loading() {

return (
<>
{isMutating &&
{Boolean(isMutating) &&
createPortal(
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="flex flex-col items-center space-y-2 pb-3">
Expand Down
2 changes: 1 addition & 1 deletion src/base/infra/chrome-extension/alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const alertToWorld = (message: string) => {
};

export const onAlert = (alert: (message: string) => void) => {
createEventBus('world').listen(({ type, payload }) => {
createEventBus('isolated').listen(({ type, payload }) => {
if (type !== 'ALERT') return;

const message = payload ?? '';
Expand Down
13 changes: 6 additions & 7 deletions src/base/infra/chrome-extension/confirm.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { Context } from '~/_shared/kernel';
import createEventBus from '../event-bus';

export const crossContextConfirm = async (
Expand Down Expand Up @@ -27,7 +26,7 @@ export const crossContextConfirm = async (

export const onCrossContextConfirm = (
context: Context,
confirm: (message: string) => boolean,
confirm: (message: string, onConfirm: (isConfirmed: boolean) => void) => void,
) => {
const eventBus = createEventBus(context);

Expand All @@ -36,11 +35,11 @@ export const onCrossContextConfirm = (

const message = payload ?? '';

const isConfirm = confirm(message);

eventBus.emit({
type: 'CROSS_CONTEXT_CONFIRM_RESPONSE',
payload: JSON.stringify(isConfirm),
confirm(message, (isConfirmed) => {
eventBus.emit({
type: 'CROSS_CONTEXT_CONFIRM_RESPONSE',
payload: JSON.stringify(isConfirmed),
});
});
});
};
30 changes: 30 additions & 0 deletions src/pages/problem-solving/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect } from 'react';
import { useAlert } from '@base/components/Alert';
import { useConfirm } from '@base/components/Confirm';
import { onAlert, onCrossContextConfirm } from '@base/infra/chrome-extension';

export function ProblemSolvingPage() {
const { alert } = useAlert();
const { confirm } = useConfirm();

useEffect(() => {
onAlert((message) => {
alert({
title: '알림',
description: message,
});
});
}, [alert]);

useEffect(() => {
onCrossContextConfirm('isolated', (message, onConfirm) => {
confirm({
title: '알림',
description: message,
onConfirm,
});
});
}, [confirm]);

return <></>;
}

0 comments on commit 450d2d7

Please sign in to comment.