From 5f432375c95d6601e6747a16e796503723fb4a91 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Thu, 7 Nov 2024 00:25:33 +0900 Subject: [PATCH 01/34] =?UTF-8?q?feat:=20=EC=9B=B9=EB=B7=B0=20=EB=B8=8C?= =?UTF-8?q?=EB=A6=BF=EC=A7=80=20=EC=9E=91=EC=97=85=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pnp.cjs | 20 ++++ README.md | 1 + apps/admin/package.json | 1 + .../ShowBasicInfoFormContent.tsx | 42 ++++--- .../ShowDetailInfoFormContent.tsx | 38 ++++--- .../ShowInfoFormContent.styles.ts | 8 +- .../ShowTicketInfoFormContent.tsx | 107 ++++++++++-------- .../src/pages/HomePage/HomePage.styles.ts | 4 +- .../src/pages/ShowAddCompletePage/index.tsx | 2 +- apps/admin/src/pages/ShowAddPage/index.tsx | 2 +- .../src/pages/ShowPreviewPage/index.tsx | 28 +++-- packages/birdge/package.json | 20 ++++ packages/birdge/src/command.ts | 18 +++ packages/birdge/src/index.ts | 3 + packages/birdge/src/types.d.ts | 15 +++ .../birdge/src/utils.ts | 2 + packages/birdge/tsconfig.json | 10 ++ packages/icon/package.json | 5 +- packages/icon/src/components/Discord.tsx | 41 +++++-- packages/ui/package.json | 5 +- .../components/ShowPreview/ShowInfoDetail.tsx | 10 +- .../ShowPreview/ShowPreview.styles.ts | 4 +- .../ui/src/components/ShowPreview/index.tsx | 4 +- yarn.lock | 13 +++ 24 files changed, 295 insertions(+), 108 deletions(-) create mode 100644 packages/birdge/package.json create mode 100644 packages/birdge/src/command.ts create mode 100644 packages/birdge/src/index.ts create mode 100644 packages/birdge/src/types.d.ts rename apps/admin/src/utils/webview.ts => packages/birdge/src/utils.ts (91%) create mode 100644 packages/birdge/tsconfig.json diff --git a/.pnp.cjs b/.pnp.cjs index 23326a13..e4eac8f9 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -33,6 +33,10 @@ const RAW_RUNTIME_STATE = "name": "@boolti/api",\ "reference": "workspace:packages/api"\ },\ + {\ + "name": "@boolti/bridge",\ + "reference": "workspace:packages/birdge"\ + },\ {\ "name": "@boolti/eslint-config",\ "reference": "workspace:packages/config-eslint"\ @@ -54,6 +58,7 @@ const RAW_RUNTIME_STATE = "ignorePatternData": "(^(?:\\\\.yarn\\\\/sdks(?:\\\\/(?!\\\\.{1,2}(?:\\\\/|$))(?:(?:(?!(?:^|\\\\/)\\\\.{1,2}(?:\\\\/|$)).)*?)|$))$)",\ "fallbackExclusionList": [\ ["@boolti/api", ["workspace:packages/api"]],\ + ["@boolti/bridge", ["workspace:packages/birdge"]],\ ["@boolti/eslint-config", ["workspace:packages/config-eslint"]],\ ["@boolti/icon", ["workspace:packages/icon"]],\ ["@boolti/typescript-config", ["workspace:packages/config-typescript"]],\ @@ -2945,6 +2950,20 @@ const RAW_RUNTIME_STATE = "linkType": "SOFT"\ }]\ ]],\ + ["@boolti/bridge", [\ + ["workspace:packages/birdge", {\ + "packageLocation": "./packages/birdge/",\ + "packageDependencies": [\ + ["@boolti/bridge", "workspace:packages/birdge"],\ + ["@boolti/eslint-config", "workspace:packages/config-eslint"],\ + ["@boolti/typescript-config", "workspace:packages/config-typescript"],\ + ["@types/react", "npm:18.2.48"],\ + ["@types/react-dom", "npm:18.2.18"],\ + ["typescript", "patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@boolti/eslint-config", [\ ["workspace:packages/config-eslint", {\ "packageLocation": "./packages/config-eslint/",\ @@ -8537,6 +8556,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["admin", "workspace:apps/admin"],\ ["@boolti/api", "workspace:packages/api"],\ + ["@boolti/bridge", "workspace:packages/birdge"],\ ["@boolti/eslint-config", "workspace:packages/config-eslint"],\ ["@boolti/icon", "workspace:packages/icon"],\ ["@boolti/typescript-config", "workspace:packages/config-typescript"],\ diff --git a/README.md b/README.md index 9a331bbd..69508b57 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,4 @@ - `packages/config-typescript`: 각 패키지에서 공통적으로 사용될 TypeScript 관련 설정이 포함된 패키지입니다. - `packages/icon`: 공통적으로 사용될 아이콘 컴포넌트가 포함된 패키지입니다. - `packages/ui`: 공통적으로 사용될 디자인 컴포넌트가 포함된 패키지입니다. +- `packages/ui`: 공통적으로 사용될 웹뷰 브릿지가 포함된 패키지입니다. diff --git a/apps/admin/package.json b/apps/admin/package.json index 9432d0e0..f3fd44d0 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@boolti/api": "*", + "@boolti/bridge": "*", "@boolti/icon": "*", "@boolti/ui": "*", "@emotion/react": "^11.11.3", diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx index 1c03fa55..d5b25df8 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx +++ b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx @@ -12,7 +12,7 @@ import { ShowInfoFormInputs } from './types'; import { useBodyScrollLock } from '~/hooks/useBodyScrollLock'; const MAX_IMAGE_COUNT = 3; -const MIN_DATE = format(add(new Date(), { days: 1 }), 'yyyy-MM-dd') +const MIN_DATE = format(add(new Date(), { days: 1 }), 'yyyy-MM-dd'); interface ShowBasicInfoFormContentProps { form: UseFormReturn; @@ -32,7 +32,13 @@ const ShowBasicInfoFormContent = ({ const { open, close, isOpen } = useDialog(); const detailAddressInputRef = useRef(null); - const { control, setValue, formState: { errors }, setError, clearErrors } = form; + const { + control, + setValue, + formState: { errors }, + setError, + clearErrors, + } = form; const { getRootProps, getInputProps } = useDropzone({ accept: { @@ -76,7 +82,8 @@ const ShowBasicInfoFormContent = ({ 공연 포스터 원하시는 노출 순서대로 이미지를 업로드해주세요.  - 표준 종이규격(A, B)의 이미지를 권장합니다.
+ 표준 종이규격(A, B)의 이미지를 권장합니다. +
(최소 1장, 최대 {MAX_IMAGE_COUNT}장 업로드 가능 / jpg, png 형식)
@@ -141,7 +148,7 @@ const ShowBasicInfoFormContent = ({ if (!value) { setError('name', { type: 'required', message: '필수 입력사항입니다.' }); - return + return; } }} value={value ?? ''} @@ -173,7 +180,7 @@ const ShowBasicInfoFormContent = ({ if (new Date(event.target.value) < new Date(MIN_DATE)) { setError('date', { type: 'min', message: '오늘 이후부터 선택 가능합니다.' }); - return + return; } }} onBlur={() => { @@ -181,7 +188,7 @@ const ShowBasicInfoFormContent = ({ if (!value) { setError('date', { type: 'required', message: '필수 입력사항입니다.' }); - return + return; } }} placeholder={value} @@ -218,8 +225,11 @@ const ShowBasicInfoFormContent = ({ onBlur(); if (!value) { - setError('startTime', { type: 'required', message: '필수 입력사항입니다.' }); - return + setError('startTime', { + type: 'required', + message: '필수 입력사항입니다.', + }); + return; } }} value={value} @@ -254,8 +264,11 @@ const ShowBasicInfoFormContent = ({ onBlur(); if (!value) { - setError('runningTime', { type: 'required', message: '필수 입력사항입니다.' }); - return + setError('runningTime', { + type: 'required', + message: '필수 입력사항입니다.', + }); + return; } }} value={value ?? ''} @@ -293,7 +306,7 @@ const ShowBasicInfoFormContent = ({ if (!value) { setError('placeName', { type: 'required', message: '필수 입력사항입니다.' }); - return + return; } }} value={value ?? ''} @@ -355,8 +368,11 @@ const ShowBasicInfoFormContent = ({ onBlur(); if (!value) { - setError('placeDetailAddress', { type: 'required', message: '필수 입력사항입니다.' }); - return + setError('placeDetailAddress', { + type: 'required', + message: '필수 입력사항입니다.', + }); + return; } }} value={value ?? ''} diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowDetailInfoFormContent.tsx b/apps/admin/src/components/ShowInfoFormContent/ShowDetailInfoFormContent.tsx index 584a9c6d..91e24e65 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowDetailInfoFormContent.tsx +++ b/apps/admin/src/components/ShowInfoFormContent/ShowDetailInfoFormContent.tsx @@ -9,10 +9,15 @@ interface ShowDetailInfoFormContentProps { disabled?: boolean; } -const phoneNumberRegExp = /^\d{3}-\d{3,4}-\d{4}$/ +const phoneNumberRegExp = /^\d{3}-\d{3,4}-\d{4}$/; const ShowDetailInfoFormContent = ({ form, disabled }: ShowDetailInfoFormContentProps) => { - const { control, formState: { errors }, setError, clearErrors } = form; + const { + control, + formState: { errors }, + setError, + clearErrors, + } = form; return ( @@ -70,10 +75,10 @@ const ShowDetailInfoFormContent = ({ form, disabled }: ShowDetailInfoFormContent rules={{ required: true, validate: (fieldValue) => { - if (!fieldValue) return '필수 입력사항입니다.' + if (!fieldValue) return '필수 입력사항입니다.'; - return true - } + return true; + }, }} render={({ field: { onChange, onBlur, value } }) => ( { onChange(event); - clearErrors('hostName') + clearErrors('hostName'); }} onBlur={() => { onBlur(); @@ -117,26 +122,33 @@ const ShowDetailInfoFormContent = ({ form, disabled }: ShowDetailInfoFormContent required disabled={disabled} onChange={(event) => { - if (event.target.value.length > 13) return + if (event.target.value.length > 13) return; event.target.value = event.target.value .replace(/[^0-9]/g, '') - .replace(/^(\d{0,3})(\d{0,4})(\d{0,4})$/g, '$1-$2-$3').replace(/(-{1,2})$/g, '') + .replace(/^(\d{0,3})(\d{0,4})(\d{0,4})$/g, '$1-$2-$3') + .replace(/(-{1,2})$/g, ''); onChange(event); - clearErrors('hostPhoneNumber') + clearErrors('hostPhoneNumber'); }} onBlur={() => { onBlur(); if (!value) { - setError('hostPhoneNumber', { type: 'required', message: '필수 입력사항입니다.' }); - return + setError('hostPhoneNumber', { + type: 'required', + message: '필수 입력사항입니다.', + }); + return; } if (!phoneNumberRegExp.test(value)) { - setError('hostPhoneNumber', { type: 'pattern', message: '유효한 전화번호 형식이 아닙니다.' }); - return + setError('hostPhoneNumber', { + type: 'pattern', + message: '유효한 전화번호 형식이 아닙니다.', + }); + return; } }} value={value ?? ''} diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowInfoFormContent.styles.ts b/apps/admin/src/components/ShowInfoFormContent/ShowInfoFormContent.styles.ts index d50ac25a..8ffca730 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowInfoFormContent.styles.ts +++ b/apps/admin/src/components/ShowInfoFormContent/ShowInfoFormContent.styles.ts @@ -89,7 +89,7 @@ const ShowInfoFormResponsiveRowColumn = styled.div` &:last-of-type { margin-bottom: 0; } -` +`; const ShowInfoFormContent = styled.div` flex: 1; @@ -136,7 +136,7 @@ const ShowInfoFormButtonContainer = styled.div` gap: 8px; `; -const ShowInfoFormButton = styled(Button) ` +const ShowInfoFormButton = styled(Button)` width: ${({ width }) => width}; `; @@ -304,7 +304,7 @@ const TextArea = styled.textarea` padding: 12px; border: 1px solid ${({ theme, hasError }) => - hasError ? `${theme.palette.status.error} !important` : theme.palette.grey.g20}; + hasError ? `${theme.palette.status.error} !important` : theme.palette.grey.g20}; border-radius: 4px; background-color: ${({ theme }) => theme.palette.grey.w}; color: ${({ theme }) => theme.palette.grey.g90}; @@ -556,7 +556,7 @@ const MobileTicketAction = styled.div` width: 24px; height: 24px; stroke: ${({ theme, disabled }) => - disabled ? theme.palette.grey.g40 : theme.palette.grey.g90}; + disabled ? theme.palette.grey.g40 : theme.palette.grey.g90}; } } } diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowTicketInfoFormContent.tsx b/apps/admin/src/components/ShowInfoFormContent/ShowTicketInfoFormContent.tsx index 0910f375..eeb70488 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowTicketInfoFormContent.tsx +++ b/apps/admin/src/components/ShowInfoFormContent/ShowTicketInfoFormContent.tsx @@ -21,64 +21,77 @@ const ShowTicketInfoFormContent = ({ salesStartTime, disabled, }: ShowTicketInfoFormContentProps) => { - const { watch, control, formState: { errors }, setError, clearErrors } = form; - - const minStartDate = format(showCreatedAt ?? new Date(), 'yyyy-MM-dd') + const { + watch, + control, + formState: { errors }, + setError, + clearErrors, + } = form; + + const minStartDate = format(showCreatedAt ?? new Date(), 'yyyy-MM-dd'); const minEndDate = format( - watch('startDate') || - (salesStartTime ? new Date(salesStartTime) : new Date()), + watch('startDate') || (salesStartTime ? new Date(salesStartTime) : new Date()), 'yyyy-MM-dd', - ) + ); const maxDate = format( sub(showDate ? new Date(showDate) : new Date(), { days: 1 }), 'yyyy-MM-dd', - ) - - const validateStartDate = useCallback((value: string) => { - if (!value) { - setError('startDate', { type: 'required', message: '필수 입력사항입니다.' }); - return - } - - if (new Date(value) > new Date(maxDate)) { - setError('startDate', { type: 'max', message: '공연일 이전까지 선택 가능합니다.' }); - return - } - - if (new Date(value) < new Date(minStartDate)) { - const message = showCreatedAt ? `공연 등록일부터 선택 가능합니다. (${format(showCreatedAt, 'yy.MM.dd')})` : '오늘부터 선택 가능합니다.'; - setError('startDate', { type: 'min', message }); - return - } - - clearErrors('startDate') - }, [clearErrors, maxDate, minStartDate, setError, showCreatedAt]) - - const validateEndDate = useCallback((value: string) => { - if (!value) { - setError('endDate', { type: 'required', message: '필수 입력사항입니다.' }); - return - } - - if (new Date(value) > new Date(maxDate)) { - setError('endDate', { type: 'max', message: '공연일 이전까지 선택 가능합니다.' }); - return - } - - if (new Date(value) < new Date(minEndDate)) { - setError('endDate', { type: 'min', message: '시작일부터 선택 가능합니다.' }); - return - } - - clearErrors('endDate') - }, [clearErrors, maxDate, minEndDate, setError]) + ); + + const validateStartDate = useCallback( + (value: string) => { + if (!value) { + setError('startDate', { type: 'required', message: '필수 입력사항입니다.' }); + return; + } + + if (new Date(value) > new Date(maxDate)) { + setError('startDate', { type: 'max', message: '공연일 이전까지 선택 가능합니다.' }); + return; + } + + if (new Date(value) < new Date(minStartDate)) { + const message = showCreatedAt + ? `공연 등록일부터 선택 가능합니다. (${format(showCreatedAt, 'yy.MM.dd')})` + : '오늘부터 선택 가능합니다.'; + setError('startDate', { type: 'min', message }); + return; + } + + clearErrors('startDate'); + }, + [clearErrors, maxDate, minStartDate, setError, showCreatedAt], + ); + + const validateEndDate = useCallback( + (value: string) => { + if (!value) { + setError('endDate', { type: 'required', message: '필수 입력사항입니다.' }); + return; + } + + if (new Date(value) > new Date(maxDate)) { + setError('endDate', { type: 'max', message: '공연일 이전까지 선택 가능합니다.' }); + return; + } + + if (new Date(value) < new Date(minEndDate)) { + setError('endDate', { type: 'min', message: '시작일부터 선택 가능합니다.' }); + return; + } + + clearErrors('endDate'); + }, + [clearErrors, maxDate, minEndDate, setError], + ); useEffect(() => { if (!watch('startDate') || !watch('endDate')) return; validateStartDate(watch('startDate')); validateEndDate(watch('endDate')); - }, [validateEndDate, validateStartDate, watch]) + }, [validateEndDate, validateStartDate, watch]); return ( diff --git a/apps/admin/src/pages/HomePage/HomePage.styles.ts b/apps/admin/src/pages/HomePage/HomePage.styles.ts index 27500ca6..d340bca8 100644 --- a/apps/admin/src/pages/HomePage/HomePage.styles.ts +++ b/apps/admin/src/pages/HomePage/HomePage.styles.ts @@ -49,8 +49,8 @@ const Container = styled.main` `; const BannerContainer = styled.div` - border-bottom: 1px solid #C5E1FF; -` + border-bottom: 1px solid #c5e1ff; +`; const Banner = styled.div` max-width: ${({ theme }) => theme.breakpoint.desktop}; diff --git a/apps/admin/src/pages/ShowAddCompletePage/index.tsx b/apps/admin/src/pages/ShowAddCompletePage/index.tsx index c4887f74..b8b455a1 100644 --- a/apps/admin/src/pages/ShowAddCompletePage/index.tsx +++ b/apps/admin/src/pages/ShowAddCompletePage/index.tsx @@ -1,12 +1,12 @@ import { ArrowLeftIcon } from '@boolti/icon'; import { Button } from '@boolti/ui'; +import { checkIsWebView } from '@boolti/bridge'; import { useNavigate } from 'react-router-dom'; import congratulationSvgUrl from '~/assets/svg/congratulation.svg'; import { PATH } from '~/constants/routes'; import Styled from './ShowAddCompletePage.styles'; -import { checkIsWebView } from '~/utils/webview'; const ShowAddCompletePage = () => { const navigate = useNavigate(); diff --git a/apps/admin/src/pages/ShowAddPage/index.tsx b/apps/admin/src/pages/ShowAddPage/index.tsx index df7dc4ac..25505cbe 100644 --- a/apps/admin/src/pages/ShowAddPage/index.tsx +++ b/apps/admin/src/pages/ShowAddPage/index.tsx @@ -26,7 +26,7 @@ import Styled from './ShowAddPage.styles'; import ShowCastInfoFormContent from '~/components/ShowInfoFormContent/ShowCastInfoFormContent'; import ShowCastInfo from '~/components/ShowCastInfo'; import { TempShowCastInfoFormInput } from '~/components/ShowCastInfoFormDialogContent'; -import { checkIsWebView } from '~/utils/webview'; +import { checkIsWebView } from '@boolti/bridge'; interface ShowAddPageProps { step: 'info' | 'ticket'; diff --git a/apps/preview/src/pages/ShowPreviewPage/index.tsx b/apps/preview/src/pages/ShowPreviewPage/index.tsx index 194a44e5..585382b0 100644 --- a/apps/preview/src/pages/ShowPreviewPage/index.tsx +++ b/apps/preview/src/pages/ShowPreviewPage/index.tsx @@ -13,13 +13,20 @@ setDefaultOptions({ locale: ko }); const getDynamicLink = (showId: number) => { return `https://boolti.page.link/?link=https://preview.boolti.in/show/${showId}&apn=com.nexters.boolti&ibi=com.nexters.boolti&isi=6476589322`; -} +}; const getPreviewLink = (showId: number) => { - return `${window.location.origin}/show/${showId}` -} + return `${window.location.origin}/show/${showId}`; +}; -const getShareText = (show: { id: number, title: string, date: Date, placeName: string, streetAddress: string, detailAddress: string }) => { +const getShareText = (show: { + id: number; + title: string; + date: Date; + placeName: string; + streetAddress: string; + detailAddress: string; +}) => { return ` 공연 정보를 공유드려요! @@ -29,8 +36,8 @@ const getShareText = (show: { id: number, title: string, date: Date, placeName: 공연 상세 정보 ▼ ${getPreviewLink(show.id)} - ` -} + `; +}; const ShowPreviewPage = () => { const loaderData = useLoaderData() as @@ -65,7 +72,14 @@ const ShowPreviewPage = () => { try { await navigator.share({ title, - text: getShareText({ id, title, date: new Date(date), placeName, streetAddress, detailAddress }), + text: getShareText({ + id, + title, + date: new Date(date), + placeName, + streetAddress, + detailAddress, + }), url: getPreviewLink(id), }); } catch (error) { diff --git a/packages/birdge/package.json b/packages/birdge/package.json new file mode 100644 index 00000000..45b1d9e5 --- /dev/null +++ b/packages/birdge/package.json @@ -0,0 +1,20 @@ +{ + "name": "@boolti/bridge", + "private": true, + "version": "0.0.0", + "type": "module", + "main": "src/index.ts", + "types": "src/index.ts", + "scripts": { + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "TIMING=1 eslint . --ext ts,tsx --fix", + "type-check": "tsc --noEmit" + }, + "devDependencies": { + "@boolti/eslint-config": "*", + "@boolti/typescript-config": "*", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "typescript": "^5.2.2" + } +} diff --git a/packages/birdge/src/command.ts b/packages/birdge/src/command.ts new file mode 100644 index 00000000..f886b24f --- /dev/null +++ b/packages/birdge/src/command.ts @@ -0,0 +1,18 @@ +import { WebViewCommand } from './types'; +import { checkIsAndroid, checkIsIOS, getUserAgent } from './utils'; + +export function sendCommand(webViewCommand: WebViewCommand) { + return window?.webkit?.messageHandlers?.boolti?.postMessage(webViewCommand); +} + +export function closeWebView() { + const userAgent = getUserAgent(); + + if (checkIsIOS(userAgent)) { + return; + } + + if (checkIsAndroid(userAgent)) { + return; + } +} diff --git a/packages/birdge/src/index.ts b/packages/birdge/src/index.ts new file mode 100644 index 00000000..f3225b5c --- /dev/null +++ b/packages/birdge/src/index.ts @@ -0,0 +1,3 @@ +export * from './command'; +export * from './types'; +export * from './utils'; diff --git a/packages/birdge/src/types.d.ts b/packages/birdge/src/types.d.ts new file mode 100644 index 00000000..51b6b277 --- /dev/null +++ b/packages/birdge/src/types.d.ts @@ -0,0 +1,15 @@ +type CloseWebview = { command: 'CLOSE_WEBVIEW'; data: string }; + +export type WebViewCommand = CloseWebview; + +declare global { + interface Window { + webkit?: { + messageHandlers?: { + boolti: { + postMessage?: (command: WebViewCommand) => void; + }; + }; + }; + } +} diff --git a/apps/admin/src/utils/webview.ts b/packages/birdge/src/utils.ts similarity index 91% rename from apps/admin/src/utils/webview.ts rename to packages/birdge/src/utils.ts index 917e7f86..8d22f262 100644 --- a/apps/admin/src/utils/webview.ts +++ b/packages/birdge/src/utils.ts @@ -1,6 +1,8 @@ export const WEBVIEW_REGEX = /BOOLTI\/(ANDROID|IOS)/; export const OS_REGEX = /(?<=BOOLTI\/).*/; +export const getUserAgent = () => window.navigator.userAgent; + export const checkIsWebView = (userAgent: string) => WEBVIEW_REGEX.test(userAgent); export const getWebViewOS = (userAgent: string) => { diff --git a/packages/birdge/tsconfig.json b/packages/birdge/tsconfig.json new file mode 100644 index 00000000..482ab669 --- /dev/null +++ b/packages/birdge/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@boolti/typescript-config/vite.json", + "compilerOptions": { + "moduleResolution": "node", + "jsxImportSource": "@emotion/react" + }, + "include": [ + "src" + ] +} diff --git a/packages/icon/package.json b/packages/icon/package.json index 0842ebfe..74e0c02e 100644 --- a/packages/icon/package.json +++ b/packages/icon/package.json @@ -6,8 +6,9 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "lint": "TIMING=1 eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "lint:fix": "TIMING=1 eslint . --ext ts,tsx --fix" + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "TIMING=1 eslint . --ext ts,tsx --fix", + "type-check": "tsc --noEmit" }, "dependencies": { "@emotion/react": "^11.11.3", diff --git a/packages/icon/src/components/Discord.tsx b/packages/icon/src/components/Discord.tsx index 2c8937ee..12740da3 100644 --- a/packages/icon/src/components/Discord.tsx +++ b/packages/icon/src/components/Discord.tsx @@ -1,7 +1,22 @@ export const Discord = () => ( - + - + @@ -9,14 +24,26 @@ export const Discord = () => ( - - + + - + - -) +); diff --git a/packages/ui/package.json b/packages/ui/package.json index 8a1d0a4e..1b9cd54e 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -6,8 +6,9 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "lint": "TIMING=1 eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "lint:fix": "TIMING=1 eslint . --ext ts,tsx --fix" + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "TIMING=1 eslint . --ext ts,tsx --fix", + "type-check": "tsc --noEmit" }, "dependencies": { "@boolti/icon": "*", diff --git a/packages/ui/src/components/ShowPreview/ShowInfoDetail.tsx b/packages/ui/src/components/ShowPreview/ShowInfoDetail.tsx index 1857a574..30b858f5 100644 --- a/packages/ui/src/components/ShowPreview/ShowInfoDetail.tsx +++ b/packages/ui/src/components/ShowPreview/ShowInfoDetail.tsx @@ -57,7 +57,10 @@ const ShowInfoDetail = ({ 일시 - {date} / {startTime}{runningTime}분 + + {date} / {startTime} + + {runningTime}분 @@ -111,10 +114,7 @@ const ShowInfoDetail = ({ 내용 {hasNoticePage && ( - + 전체보기 )} diff --git a/packages/ui/src/components/ShowPreview/ShowPreview.styles.ts b/packages/ui/src/components/ShowPreview/ShowPreview.styles.ts index 995c3499..55c89ccb 100644 --- a/packages/ui/src/components/ShowPreview/ShowPreview.styles.ts +++ b/packages/ui/src/components/ShowPreview/ShowPreview.styles.ts @@ -50,7 +50,7 @@ const ShowPreviewNavbar = styled.div` const LogoLink = styled.a` display: flex; align-items: center; - cursor: ${({ href }) => href ? 'pointer' : 'default'}; + cursor: ${({ href }) => (href ? 'pointer' : 'default')}; svg { width: 53px; @@ -243,7 +243,7 @@ const ShowInfoDescriptionBadge = styled.div` border-radius: 999px; position: relative; top: -1.5px; -` +`; const ShowInfoBox = styled.div` height: 56px; diff --git a/packages/ui/src/components/ShowPreview/index.tsx b/packages/ui/src/components/ShowPreview/index.tsx index 0e5a6549..b520ce19 100644 --- a/packages/ui/src/components/ShowPreview/index.tsx +++ b/packages/ui/src/components/ShowPreview/index.tsx @@ -53,7 +53,7 @@ const ShowPreview = ({ containerRef, onClickLink, onClickLinkMobile, - onClickShareButton + onClickShareButton, }: ShowPreviewProps) => { const { images, name } = show; @@ -119,7 +119,7 @@ const ShowPreview = ({ onClickLink={onClickLink} onClickLinkMobile={onClickLinkMobile} onClickViewNotice={() => { - containerScrollTop.current = containerRef?.current?.scrollTop ?? null + containerScrollTop.current = containerRef?.current?.scrollTop ?? null; containerRef?.current?.scrollTo(0, 0); setNoticeOpen(true); }} diff --git a/yarn.lock b/yarn.lock index 2e91e843..d6d4965b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1679,6 +1679,18 @@ __metadata: languageName: unknown linkType: soft +"@boolti/bridge@npm:*, @boolti/bridge@workspace:packages/birdge": + version: 0.0.0-use.local + resolution: "@boolti/bridge@workspace:packages/birdge" + dependencies: + "@boolti/eslint-config": "npm:*" + "@boolti/typescript-config": "npm:*" + "@types/react": "npm:^18.2.43" + "@types/react-dom": "npm:^18.2.17" + typescript: "npm:^5.2.2" + languageName: unknown + linkType: soft + "@boolti/eslint-config@npm:*, @boolti/eslint-config@workspace:packages/config-eslint": version: 0.0.0-use.local resolution: "@boolti/eslint-config@workspace:packages/config-eslint" @@ -5364,6 +5376,7 @@ __metadata: resolution: "admin@workspace:apps/admin" dependencies: "@boolti/api": "npm:*" + "@boolti/bridge": "npm:*" "@boolti/eslint-config": "npm:*" "@boolti/icon": "npm:*" "@boolti/typescript-config": "npm:*" From 53e1d6462131e22f80794a354f1252a6c9cb23af Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:15:40 +0900 Subject: [PATCH 02/34] =?UTF-8?q?feat:=20=EB=B8=8C=EB=A6=BF=EC=A7=80=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=A0=95=EC=9D=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pnp.cjs | 22 ++++-- packages/birdge/src/command.ts | 18 ----- packages/birdge/src/types.d.ts | 15 ---- packages/{birdge => bridge}/package.json | 3 + packages/bridge/src/command.ts | 94 +++++++++++++++++++++++ packages/{birdge => bridge}/src/index.ts | 0 packages/bridge/src/types.d.ts | 41 ++++++++++ packages/{birdge => bridge}/src/utils.ts | 0 packages/{birdge => bridge}/tsconfig.json | 6 +- yarn.lock | 14 +++- 10 files changed, 167 insertions(+), 46 deletions(-) delete mode 100644 packages/birdge/src/command.ts delete mode 100644 packages/birdge/src/types.d.ts rename packages/{birdge => bridge}/package.json (91%) create mode 100644 packages/bridge/src/command.ts rename packages/{birdge => bridge}/src/index.ts (100%) create mode 100644 packages/bridge/src/types.d.ts rename packages/{birdge => bridge}/src/utils.ts (100%) rename packages/{birdge => bridge}/tsconfig.json (62%) diff --git a/.pnp.cjs b/.pnp.cjs index 553d4047..a6142ce3 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -35,7 +35,7 @@ const RAW_RUNTIME_STATE = },\ {\ "name": "@boolti/bridge",\ - "reference": "workspace:packages/birdge"\ + "reference": "workspace:packages/bridge"\ },\ {\ "name": "@boolti/eslint-config",\ @@ -58,7 +58,7 @@ const RAW_RUNTIME_STATE = "ignorePatternData": "(^(?:\\\\.yarn\\\\/sdks(?:\\\\/(?!\\\\.{1,2}(?:\\\\/|$))(?:(?:(?!(?:^|\\\\/)\\\\.{1,2}(?:\\\\/|$)).)*?)|$))$)",\ "fallbackExclusionList": [\ ["@boolti/api", ["workspace:packages/api"]],\ - ["@boolti/bridge", ["workspace:packages/birdge"]],\ + ["@boolti/bridge", ["workspace:packages/bridge"]],\ ["@boolti/eslint-config", ["workspace:packages/config-eslint"]],\ ["@boolti/icon", ["workspace:packages/icon"]],\ ["@boolti/typescript-config", ["workspace:packages/config-typescript"]],\ @@ -2951,15 +2951,16 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@boolti/bridge", [\ - ["workspace:packages/birdge", {\ - "packageLocation": "./packages/birdge/",\ + ["workspace:packages/bridge", {\ + "packageLocation": "./packages/bridge/",\ "packageDependencies": [\ - ["@boolti/bridge", "workspace:packages/birdge"],\ + ["@boolti/bridge", "workspace:packages/bridge"],\ ["@boolti/eslint-config", "workspace:packages/config-eslint"],\ ["@boolti/typescript-config", "workspace:packages/config-typescript"],\ ["@types/react", "npm:18.2.48"],\ ["@types/react-dom", "npm:18.2.18"],\ - ["typescript", "patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7"]\ + ["typescript", "patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7"],\ + ["uuid", "npm:11.0.3"]\ ],\ "linkType": "SOFT"\ }]\ @@ -8706,7 +8707,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["admin", "workspace:apps/admin"],\ ["@boolti/api", "workspace:packages/api"],\ - ["@boolti/bridge", "workspace:packages/birdge"],\ + ["@boolti/bridge", "workspace:packages/bridge"],\ ["@boolti/eslint-config", "workspace:packages/config-eslint"],\ ["@boolti/icon", "workspace:packages/icon"],\ ["@boolti/typescript-config", "workspace:packages/config-typescript"],\ @@ -19253,6 +19254,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["uuid", [\ + ["npm:11.0.3", {\ + "packageLocation": "./.yarn/cache/uuid-npm-11.0.3-abcb5b16c0-cee762fc76.zip/node_modules/uuid/",\ + "packageDependencies": [\ + ["uuid", "npm:11.0.3"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:9.0.1", {\ "packageLocation": "./.yarn/cache/uuid-npm-9.0.1-39a8442bc6-1607dd32ac.zip/node_modules/uuid/",\ "packageDependencies": [\ diff --git a/packages/birdge/src/command.ts b/packages/birdge/src/command.ts deleted file mode 100644 index f886b24f..00000000 --- a/packages/birdge/src/command.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { WebViewCommand } from './types'; -import { checkIsAndroid, checkIsIOS, getUserAgent } from './utils'; - -export function sendCommand(webViewCommand: WebViewCommand) { - return window?.webkit?.messageHandlers?.boolti?.postMessage(webViewCommand); -} - -export function closeWebView() { - const userAgent = getUserAgent(); - - if (checkIsIOS(userAgent)) { - return; - } - - if (checkIsAndroid(userAgent)) { - return; - } -} diff --git a/packages/birdge/src/types.d.ts b/packages/birdge/src/types.d.ts deleted file mode 100644 index 51b6b277..00000000 --- a/packages/birdge/src/types.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -type CloseWebview = { command: 'CLOSE_WEBVIEW'; data: string }; - -export type WebViewCommand = CloseWebview; - -declare global { - interface Window { - webkit?: { - messageHandlers?: { - boolti: { - postMessage?: (command: WebViewCommand) => void; - }; - }; - }; - } -} diff --git a/packages/birdge/package.json b/packages/bridge/package.json similarity index 91% rename from packages/birdge/package.json rename to packages/bridge/package.json index 45b1d9e5..2c68c1cd 100644 --- a/packages/birdge/package.json +++ b/packages/bridge/package.json @@ -16,5 +16,8 @@ "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "typescript": "^5.2.2" + }, + "dependencies": { + "uuid": "^11.0.3" } } diff --git a/packages/bridge/src/command.ts b/packages/bridge/src/command.ts new file mode 100644 index 00000000..ac8a8b07 --- /dev/null +++ b/packages/bridge/src/command.ts @@ -0,0 +1,94 @@ +import { + Command, + NavigateToShowDetailRequestData, + RequestTokenResponseData, + WebViewCommand, +} from './types'; +import { checkIsAndroid, checkIsIOS, getUserAgent } from './utils'; +import { v4 as uuidv4 } from 'uuid'; + +const getTimeStamp = () => new Date().valueOf().toString(); + +const getUuid = () => uuidv4(); + +const getBaseCommand = (command: WebViewCommand) => ({ + timestamp: getTimeStamp(), + id: getUuid(), + command, +}); + +const navigateToShowDetail = async ({ + showId, +}: NavigateToShowDetailRequestData): Promise => { + const userAgent = getUserAgent(); + const baseCommand: Command = getBaseCommand('NAVIGATE_TO_SHOW_DETAIL'); + + try { + if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { + const result = + await window.webkit.messageHandlers.boolti.postMessage({ + ...baseCommand, + data: { + showId, + }, + }); + return new Promise((resolve) => resolve(result)); + } else if (checkIsAndroid(userAgent) && window.boolti?.navigateToShowDeatil) { + const result = await window.boolti.navigateToShowDeatil({ + ...baseCommand, + data: { + showId, + }, + }); + return new Promise((resolve) => resolve(result)); + } + return new Promise((_, reject) => reject(baseCommand)); + } catch (e) { + return new Promise((_, reject) => reject(baseCommand)); + } +}; + +const navigateBack = async (): Promise => { + const userAgent = getUserAgent(); + const baseCommand: Command = getBaseCommand('NAVIGATE_BACK'); + + try { + if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { + const result = await window.webkit.messageHandlers.boolti.postMessage(baseCommand); + return new Promise((resolve) => resolve(result)); + } else if (checkIsAndroid(userAgent) && window.boolti?.naviagteBack) { + const result = await window.boolti?.naviagteBack(baseCommand); + return new Promise((resolve) => resolve(result)); + } + return new Promise((_, reject) => reject(baseCommand)); + } catch (e) { + return new Promise((_, reject) => reject(baseCommand)); + } +}; + +const requestToken = async (): Promise> => { + const userAgent = getUserAgent(); + const baseCommand: Command = getBaseCommand('REQUEST_TOKEN'); + + try { + if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { + const result = await window.webkit.messageHandlers.boolti.postMessage< + undefined, + RequestTokenResponseData + >(baseCommand); + return new Promise((resolve) => resolve(result)); + } else if (checkIsAndroid(userAgent) && window.boolti?.requestToken) { + const result = await window.boolti?.requestToken(baseCommand); + return new Promise((resolve) => resolve(result)); + } + return new Promise((_, reject) => reject(baseCommand)); + } catch (e) { + return new Promise((_, reject) => reject(baseCommand)); + } +}; + +export const Bridge = { + navigateToShowDetail, + navigateBack, + requestToken, +}; diff --git a/packages/birdge/src/index.ts b/packages/bridge/src/index.ts similarity index 100% rename from packages/birdge/src/index.ts rename to packages/bridge/src/index.ts diff --git a/packages/bridge/src/types.d.ts b/packages/bridge/src/types.d.ts new file mode 100644 index 00000000..3ad732a2 --- /dev/null +++ b/packages/bridge/src/types.d.ts @@ -0,0 +1,41 @@ +type WebViewCommand = 'NAVIGATE_TO_SHOW_DETAIL' | 'NAVIGATE_BACK' | 'REQUEST_TOKEN'; + +type BaseCommand = { + id: string; + timestamp: string; + command: WebViewCommand; +}; + +export type Command = Data extends undefined + ? BaseCommand + : BaseCommand & { data: Data }; + +type CommandFnToAndroid = ( + command: Command, +) => Promise>; + +type CommandFnToIoS = ( + command: Command, +) => Promise>; + +export type NavigateToShowDetailRequestData = { showId: number }; + +export type RequestTokenResponseData = { token: string }; + +declare global { + interface Window { + webkit?: { + messageHandlers?: { + boolti: { + postMessage?: CommandFnToIoS; + }; + }; + }; + + boolti?: { + navigateToShowDeatil?: CommandFnToAndroid; + naviagteBack?: CommandFnToAndroid; + requestToken?: CommandFnToAndroid; + }; + } +} diff --git a/packages/birdge/src/utils.ts b/packages/bridge/src/utils.ts similarity index 100% rename from packages/birdge/src/utils.ts rename to packages/bridge/src/utils.ts diff --git a/packages/birdge/tsconfig.json b/packages/bridge/tsconfig.json similarity index 62% rename from packages/birdge/tsconfig.json rename to packages/bridge/tsconfig.json index 482ab669..aa3c4850 100644 --- a/packages/birdge/tsconfig.json +++ b/packages/bridge/tsconfig.json @@ -2,9 +2,7 @@ "extends": "@boolti/typescript-config/vite.json", "compilerOptions": { "moduleResolution": "node", - "jsxImportSource": "@emotion/react" + "jsxImportSource": "@emotion/react", }, - "include": [ - "src" - ] + "include": ["src"], } diff --git a/yarn.lock b/yarn.lock index 8d7cf5c2..9ca96361 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1679,15 +1679,16 @@ __metadata: languageName: unknown linkType: soft -"@boolti/bridge@npm:*, @boolti/bridge@workspace:packages/birdge": +"@boolti/bridge@npm:*, @boolti/bridge@workspace:packages/bridge": version: 0.0.0-use.local - resolution: "@boolti/bridge@workspace:packages/birdge" + resolution: "@boolti/bridge@workspace:packages/bridge" dependencies: "@boolti/eslint-config": "npm:*" "@boolti/typescript-config": "npm:*" "@types/react": "npm:^18.2.43" "@types/react-dom": "npm:^18.2.17" typescript: "npm:^5.2.2" + uuid: "npm:^11.0.3" languageName: unknown linkType: soft @@ -14000,6 +14001,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^11.0.3": + version: 11.0.3 + resolution: "uuid@npm:11.0.3" + bin: + uuid: dist/esm/bin/uuid + checksum: 10c0/cee762fc76d949a2ff9205770334699e0043d52bb766472593a25f150077c9deed821230251ea3d6ab3943a5ea137d2826678797f1d5f6754c7ce5ce27e9f7a6 + languageName: node + linkType: hard + "uuid@npm:^9.0.0": version: 9.0.1 resolution: "uuid@npm:9.0.1" From 5af8091c0b03399d7f0b1e1797a39c1c07d5e9be Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:22:41 +0900 Subject: [PATCH 03/34] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=ED=99=95?= =?UTF-8?q?=EC=9E=A5=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bridge/src/{types.d.ts => types.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/bridge/src/{types.d.ts => types.ts} (100%) diff --git a/packages/bridge/src/types.d.ts b/packages/bridge/src/types.ts similarity index 100% rename from packages/bridge/src/types.d.ts rename to packages/bridge/src/types.ts From 1401bd11f60e27b9a76a927cee51f3ebefa8f5b7 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:25:28 +0900 Subject: [PATCH 04/34] =?UTF-8?q?chore:=20=EC=9B=B9=EB=B7=B0=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9A=A9=20=EB=B2=84=ED=8A=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShowInfoFormContent/ShowBasicInfoFormContent.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx index b7522952..5735c781 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx +++ b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx @@ -5,6 +5,7 @@ import { add, format } from 'date-fns'; import { useRef } from 'react'; import { useDropzone } from 'react-dropzone'; import { Controller, UseFormReturn } from 'react-hook-form'; +import { Bridge } from '@boolti/bridge'; import DaumPostcode from 'react-daum-postcode'; import Styled from './ShowInfoFormContent.styles'; @@ -73,6 +74,15 @@ const ShowBasicInfoFormContent = ({ return ( + 기본 정보 From b06027ff21373c3ff28a629c7486f91656f5b114 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:30:13 +0900 Subject: [PATCH 05/34] =?UTF-8?q?feat:=20=EC=95=88=EB=93=9C=EB=A1=9C?= =?UTF-8?q?=EC=9D=B4=EB=93=9C=EC=97=90=EC=84=9C=EB=8F=84=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=9D=B4=EB=A6=84=20=ED=95=98=EB=82=98=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShowBasicInfoFormContent.tsx | 6 +++++- packages/bridge/src/command.ts | 14 ++++++++------ packages/bridge/src/types.ts | 16 +++++----------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx index 5735c781..05121c3f 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx +++ b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx @@ -78,7 +78,11 @@ const ShowBasicInfoFormContent = ({ colorTheme="primary" size="medium" onClick={() => { - Bridge.navigateToShowDetail({ showId: 144 }); + try { + Bridge.navigateToShowDetail({ showId: 144 }); + } catch (e) { + alert(e); + } }} > 웹뷰 테스트 diff --git a/packages/bridge/src/command.ts b/packages/bridge/src/command.ts index ac8a8b07..c296dd94 100644 --- a/packages/bridge/src/command.ts +++ b/packages/bridge/src/command.ts @@ -33,8 +33,8 @@ const navigateToShowDetail = async ({ }, }); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.navigateToShowDeatil) { - const result = await window.boolti.navigateToShowDeatil({ + } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { + const result = await window.boolti.sendCommand({ ...baseCommand, data: { showId, @@ -56,8 +56,8 @@ const navigateBack = async (): Promise => { if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { const result = await window.webkit.messageHandlers.boolti.postMessage(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.naviagteBack) { - const result = await window.boolti?.naviagteBack(baseCommand); + } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { + const result = await window.boolti?.sendCommand(baseCommand); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); @@ -77,8 +77,10 @@ const requestToken = async (): Promise> => { RequestTokenResponseData >(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.requestToken) { - const result = await window.boolti?.requestToken(baseCommand); + } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { + const result = await window.boolti?.sendCommand( + baseCommand, + ); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts index 3ad732a2..f5da01e2 100644 --- a/packages/bridge/src/types.ts +++ b/packages/bridge/src/types.ts @@ -1,6 +1,6 @@ -type WebViewCommand = 'NAVIGATE_TO_SHOW_DETAIL' | 'NAVIGATE_BACK' | 'REQUEST_TOKEN'; +export type WebViewCommand = 'NAVIGATE_TO_SHOW_DETAIL' | 'NAVIGATE_BACK' | 'REQUEST_TOKEN'; -type BaseCommand = { +export type BaseCommand = { id: string; timestamp: string; command: WebViewCommand; @@ -10,11 +10,7 @@ export type Command = Data extends undefined ? BaseCommand : BaseCommand & { data: Data }; -type CommandFnToAndroid = ( - command: Command, -) => Promise>; - -type CommandFnToIoS = ( +type CommandFn = ( command: Command, ) => Promise>; @@ -27,15 +23,13 @@ declare global { webkit?: { messageHandlers?: { boolti: { - postMessage?: CommandFnToIoS; + postMessage?: CommandFn; }; }; }; boolti?: { - navigateToShowDeatil?: CommandFnToAndroid; - naviagteBack?: CommandFnToAndroid; - requestToken?: CommandFnToAndroid; + sendCommand?: CommandFn; }; } } From 21e557b60489046f927bd1658feb14eb2f8e9906 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:44:26 +0900 Subject: [PATCH 06/34] =?UTF-8?q?feat:=20=EC=95=88=EB=93=9C=EB=A1=9C?= =?UTF-8?q?=EC=9D=B4=EB=93=9C=EC=97=90=EC=84=9C=20=EB=AC=B8=EC=9E=90?= =?UTF-8?q?=EC=97=B4=EB=A1=9C=20=EB=B0=94=EA=BF=94=EC=84=9C=20=EC=A0=84?= =?UTF-8?q?=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bridge/src/command.ts | 26 +++++++++++++------------- packages/bridge/src/types.ts | 12 +++++++++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/bridge/src/command.ts b/packages/bridge/src/command.ts index c296dd94..a49f0f54 100644 --- a/packages/bridge/src/command.ts +++ b/packages/bridge/src/command.ts @@ -33,13 +33,15 @@ const navigateToShowDetail = async ({ }, }); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { - const result = await window.boolti.sendCommand({ - ...baseCommand, - data: { - showId, - }, - }); + } else if (checkIsAndroid(userAgent) && window.boolti?.navigateToShowDeatil) { + const result = await window.boolti?.navigateToShowDeatil( + JSON.stringify({ + ...baseCommand, + data: { + showId, + }, + }), + ); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); @@ -56,8 +58,8 @@ const navigateBack = async (): Promise => { if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { const result = await window.webkit.messageHandlers.boolti.postMessage(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { - const result = await window.boolti?.sendCommand(baseCommand); + } else if (checkIsAndroid(userAgent) && window.boolti?.naviagteBack) { + const result = await window.boolti?.naviagteBack(JSON.stringify(baseCommand)); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); @@ -77,10 +79,8 @@ const requestToken = async (): Promise> => { RequestTokenResponseData >(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { - const result = await window.boolti?.sendCommand( - baseCommand, - ); + } else if (checkIsAndroid(userAgent) && window.boolti?.requestToken) { + const result = await window.boolti?.requestToken(JSON.stringify(baseCommand)); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts index f5da01e2..3c79bd82 100644 --- a/packages/bridge/src/types.ts +++ b/packages/bridge/src/types.ts @@ -10,7 +10,11 @@ export type Command = Data extends undefined ? BaseCommand : BaseCommand & { data: Data }; -type CommandFn = ( +type CommandFnToAndroid = ( + command: string, +) => Promise>; + +type CommandFnToIoS = ( command: Command, ) => Promise>; @@ -23,13 +27,15 @@ declare global { webkit?: { messageHandlers?: { boolti: { - postMessage?: CommandFn; + postMessage?: CommandFnToIoS; }; }; }; boolti?: { - sendCommand?: CommandFn; + navigateToShowDeatil?: CommandFnToAndroid; + naviagteBack?: CommandFnToAndroid; + requestToken?: CommandFnToAndroid; }; } } From 220b8a19a67efa6fe454554c08e51dfdbf9dada6 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:48:54 +0900 Subject: [PATCH 07/34] =?UTF-8?q?feat:=20sendCommand=20=EB=8F=84=20?= =?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bridge/src/command.ts | 8 ++++---- packages/bridge/src/types.ts | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/bridge/src/command.ts b/packages/bridge/src/command.ts index a49f0f54..4789eec8 100644 --- a/packages/bridge/src/command.ts +++ b/packages/bridge/src/command.ts @@ -33,8 +33,8 @@ const navigateToShowDetail = async ({ }, }); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.navigateToShowDeatil) { - const result = await window.boolti?.navigateToShowDeatil( + } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { + const result = await window.boolti?.sendCommand( JSON.stringify({ ...baseCommand, data: { @@ -58,8 +58,8 @@ const navigateBack = async (): Promise => { if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { const result = await window.webkit.messageHandlers.boolti.postMessage(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.naviagteBack) { - const result = await window.boolti?.naviagteBack(JSON.stringify(baseCommand)); + } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { + const result = await window.boolti?.sendCommand(JSON.stringify(baseCommand)); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts index 3c79bd82..05e32e89 100644 --- a/packages/bridge/src/types.ts +++ b/packages/bridge/src/types.ts @@ -14,8 +14,8 @@ type CommandFnToAndroid = ( command: string, ) => Promise>; -type CommandFnToIoS = ( - command: Command, +type CommandFn = ( + command: Command | string, ) => Promise>; export type NavigateToShowDetailRequestData = { showId: number }; @@ -27,12 +27,13 @@ declare global { webkit?: { messageHandlers?: { boolti: { - postMessage?: CommandFnToIoS; + postMessage?: CommandFn; }; }; }; boolti?: { + sendCommand?: CommandFn; navigateToShowDeatil?: CommandFnToAndroid; naviagteBack?: CommandFnToAndroid; requestToken?: CommandFnToAndroid; From b7856f647a9cfce4be90ac15472f5af8ae3c7495 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:52:37 +0900 Subject: [PATCH 08/34] =?UTF-8?q?feat:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20postMessage=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bridge/src/command.ts | 14 ++++++++------ packages/bridge/src/types.ts | 9 +-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/bridge/src/command.ts b/packages/bridge/src/command.ts index 4789eec8..5a793e0b 100644 --- a/packages/bridge/src/command.ts +++ b/packages/bridge/src/command.ts @@ -33,8 +33,8 @@ const navigateToShowDetail = async ({ }, }); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { - const result = await window.boolti?.sendCommand( + } else if (checkIsAndroid(userAgent) && window.boolti?.postMessage) { + const result = await window.boolti?.postMessage( JSON.stringify({ ...baseCommand, data: { @@ -58,8 +58,8 @@ const navigateBack = async (): Promise => { if (checkIsIOS(userAgent) && window.webkit?.messageHandlers?.boolti.postMessage) { const result = await window.webkit.messageHandlers.boolti.postMessage(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.sendCommand) { - const result = await window.boolti?.sendCommand(JSON.stringify(baseCommand)); + } else if (checkIsAndroid(userAgent) && window.boolti?.postMessage) { + const result = await window.boolti?.postMessage(JSON.stringify(baseCommand)); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); @@ -79,8 +79,10 @@ const requestToken = async (): Promise> => { RequestTokenResponseData >(baseCommand); return new Promise((resolve) => resolve(result)); - } else if (checkIsAndroid(userAgent) && window.boolti?.requestToken) { - const result = await window.boolti?.requestToken(JSON.stringify(baseCommand)); + } else if (checkIsAndroid(userAgent) && window.boolti?.postMessage) { + const result = await window.boolti?.postMessage( + JSON.stringify(baseCommand), + ); return new Promise((resolve) => resolve(result)); } return new Promise((_, reject) => reject(baseCommand)); diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts index 05e32e89..9f7fc610 100644 --- a/packages/bridge/src/types.ts +++ b/packages/bridge/src/types.ts @@ -10,10 +10,6 @@ export type Command = Data extends undefined ? BaseCommand : BaseCommand & { data: Data }; -type CommandFnToAndroid = ( - command: string, -) => Promise>; - type CommandFn = ( command: Command | string, ) => Promise>; @@ -33,10 +29,7 @@ declare global { }; boolti?: { - sendCommand?: CommandFn; - navigateToShowDeatil?: CommandFnToAndroid; - naviagteBack?: CommandFnToAndroid; - requestToken?: CommandFnToAndroid; + postMessage?: CommandFn; }; } } From 77a24138cf4da0df6740f00b94c7b0f1cf3d4cb2 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 7 Dec 2024 17:58:48 +0900 Subject: [PATCH 09/34] =?UTF-8?q?feat:=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EB=B0=9B=EC=95=98=EC=9D=84=20=EB=95=8C=20=EC=96=BC=EB=9F=BF=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShowInfoFormContent/ShowBasicInfoFormContent.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx index 05121c3f..a08a1b49 100644 --- a/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx +++ b/apps/admin/src/components/ShowInfoFormContent/ShowBasicInfoFormContent.tsx @@ -77,9 +77,10 @@ const ShowBasicInfoFormContent = ({ 기본 정보 diff --git a/apps/admin/src/pages/ShowAddPage/index.tsx b/apps/admin/src/pages/ShowAddPage/index.tsx index 5d06692c..1781e530 100644 --- a/apps/admin/src/pages/ShowAddPage/index.tsx +++ b/apps/admin/src/pages/ShowAddPage/index.tsx @@ -29,12 +29,7 @@ import Styled from './ShowAddPage.styles'; import ShowCastInfoFormContent from '~/components/ShowInfoFormContent/ShowCastInfoFormContent'; import ShowCastInfo from '~/components/ShowCastInfo'; import { TempShowCastInfoFormInput } from '~/components/ShowCastInfoFormDialogContent'; -import { - checkIsWebView, - isWebViewBridgeAvailable, - navigateBack, - navigateToShowDetail, -} from '@boolti/bridge'; +import { checkIsWebView, isWebViewBridgeAvailable, navigateToShowDetail } from '@boolti/bridge'; import useCastTeamListOrder from '~/hooks/useCastTeamListOrder'; interface ShowAddPageProps { @@ -110,9 +105,7 @@ const ShowAddPage = ({ step }: ShowAddPageProps) => { }); if (isWebView && isWebViewBridgeAvailable()) { - navigateBack().then(() => { - navigateToShowDetail({ showId }); - }); + navigateToShowDetail({ showId }); return; } From 830988775a9afbf778c4a39248930ba443a4540a Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Tue, 31 Dec 2024 11:12:52 +0900 Subject: [PATCH 34/34] =?UTF-8?q?fix:=20=ED=83=80=EC=9E=85=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/src/pages/ShowAddPage/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/admin/src/pages/ShowAddPage/index.tsx b/apps/admin/src/pages/ShowAddPage/index.tsx index bbad2659..384746e0 100644 --- a/apps/admin/src/pages/ShowAddPage/index.tsx +++ b/apps/admin/src/pages/ShowAddPage/index.tsx @@ -29,8 +29,7 @@ import { PATH } from '~/constants/routes'; import Styled from './ShowAddPage.styles'; import ShowCastInfoFormContent from '~/components/ShowInfoFormContent/ShowCastInfoFormContent'; import { TempShowCastInfoFormInput } from '~/components/ShowCastInfoFormDialogContent'; -import { checkIsWebView } from '~/utils/webview'; -import { isWebViewBridgeAvailable, navigateToShowDetail } from '@boolti/bridge'; +import { checkIsWebView, isWebViewBridgeAvailable, navigateToShowDetail } from '@boolti/bridge'; const stepItems = [ { key: 'basic', title: '기본 정보' },