From f45de71d88d4834fde6199c004ce3dde9e2eb854 Mon Sep 17 00:00:00 2001 From: "leojoseph.r" <58416454+rleojoseph@users.noreply.github.com> Date: Wed, 18 Oct 2023 13:22:55 +0900 Subject: [PATCH] [MINI-6324] Create interfaces to share Cookie info to MiniApp (#276) * Cookies from Host app * Sample app changes * Theme changed * Update Helper class * Updated Readme and Changelog --- js-miniapp-bridge/src/common-bridge.ts | 27 ++ js-miniapp-bridge/src/index.ts | 2 + js-miniapp-bridge/src/types/cookie-info.ts | 5 + js-miniapp-sample/package.json | 2 +- js-miniapp-sample/src/pages/cookie-manager.js | 356 ++++++++++++++++++ js-miniapp-sample/src/pages/helper.js | 4 +- js-miniapp-sample/src/routes.js | 26 +- js-miniapp-sample/src/theme.js | 4 +- js-miniapp-sdk/CHANGELOG.md | 4 + js-miniapp-sdk/README.md | 38 ++ js-miniapp-sdk/src/index.ts | 2 + js-miniapp-sdk/src/miniapp.ts | 2 + js-miniapp-sdk/src/modules/cookie-manager.ts | 30 ++ 13 files changed, 485 insertions(+), 17 deletions(-) create mode 100644 js-miniapp-bridge/src/types/cookie-info.ts create mode 100644 js-miniapp-sample/src/pages/cookie-manager.js create mode 100644 js-miniapp-sdk/src/modules/cookie-manager.ts diff --git a/js-miniapp-bridge/src/common-bridge.ts b/js-miniapp-bridge/src/common-bridge.ts index 239926c0b..c90aee48a 100644 --- a/js-miniapp-bridge/src/common-bridge.ts +++ b/js-miniapp-bridge/src/common-bridge.ts @@ -31,6 +31,7 @@ import { ProductInfo, PurchasedProductInfo } from './types/in-app-purchase'; import { HostThemeColor } from './types/host-color-scheme'; import { MAAnalyticsInfo } from './types/analytics/analytics'; import { UniversalBridgeInfo } from './types/universal-bridge'; +import { CookieInfo } from './types/cookie-info'; /** @internal */ const mabMessageQueue: Callback[] = []; @@ -801,6 +802,32 @@ export class MiniAppBridge { ); }); } + + getAllCookies() { + return new Promise<[CookieInfo]>((resolve, reject) => { + return this.executor.exec( + 'getAllCookies', + null, + response => { + resolve(JSON.parse(response) as [CookieInfo]); + }, + error => reject(parseMiniAppError(error)) + ); + }); + } + + getCookies(cookieNameList: string[]) { + return new Promise<[CookieInfo]>((resolve, reject) => { + return this.executor.exec( + 'getCookies', + { cookieList: cookieNameList }, + response => { + resolve(JSON.parse(response) as [CookieInfo]); + }, + error => reject(parseMiniAppError(error)) + ); + }); + } } /** diff --git a/js-miniapp-bridge/src/index.ts b/js-miniapp-bridge/src/index.ts index 5a66566b9..0b67129c7 100644 --- a/js-miniapp-bridge/src/index.ts +++ b/js-miniapp-bridge/src/index.ts @@ -62,6 +62,7 @@ import { PurchasedProductInfo, ProductPrice, } from './types/in-app-purchase'; +import { CookieInfo } from './types/cookie-info'; export { MiniAppBridge, @@ -111,4 +112,5 @@ export { MAAnalyticsActionType, MAAnalyticsEventType, UniversalBridgeInfo, + CookieInfo, }; diff --git a/js-miniapp-bridge/src/types/cookie-info.ts b/js-miniapp-bridge/src/types/cookie-info.ts new file mode 100644 index 000000000..f7445c378 --- /dev/null +++ b/js-miniapp-bridge/src/types/cookie-info.ts @@ -0,0 +1,5 @@ +/** CookieInfo type. */ +export interface CookieInfo { + name?: string; + value?: string; +} diff --git a/js-miniapp-sample/package.json b/js-miniapp-sample/package.json index 23636eca0..a3badd48f 100644 --- a/js-miniapp-sample/package.json +++ b/js-miniapp-sample/package.json @@ -25,7 +25,7 @@ "format": "prettier --config ./prettier.config.js --write 'src/**/*.js'", "prettify": "prettier --config ./prettier.config.js --check src/**/*.js", "lint": "eslint src/ --fix-dry-run", - "start": "react-scripts start", + "start": "react-scripts --openssl-legacy-provider start", "build": "react-scripts build && npm run zip", "dockerBuild": "cd ci && make build", "eject": "react-scripts eject", diff --git a/js-miniapp-sample/src/pages/cookie-manager.js b/js-miniapp-sample/src/pages/cookie-manager.js new file mode 100644 index 000000000..9822915d7 --- /dev/null +++ b/js-miniapp-sample/src/pages/cookie-manager.js @@ -0,0 +1,356 @@ +import React, { useReducer, useState } from 'react'; + +import MiniApp from 'js-miniapp-sdk'; + +import { + Button, + CardContent, + CardActions, + makeStyles, + Typography, + ListItem, + ListItemText, + Container, + TextField, +} from '@material-ui/core'; +import { red, green } from '@material-ui/core/colors'; +import GreyCard from '../components/GreyCard'; +import Tab from '@material-ui/core/Tab'; +import TabContext from '@material-ui/lab/TabContext'; +import TabList from '@material-ui/lab/TabList'; +import TabPanel from '@material-ui/lab/TabPanel'; + +const useStyles = makeStyles((theme) => ({ + card: { + width: '100%', + height: 'auto', + display: 'grid', + }, + content: { + height: 'auto', + justifyContent: 'center', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + fontSize: 18, + color: theme.color.primary, + fontWeight: 'bold', + wordBreak: 'break-word', + }, + actions: { + justifyContent: 'center', + }, + scrollable: { + overflowY: 'auto', + width: '100%', + paddingTop: 20, + paddingBottom: 20, + }, + root: { + background: theme.color.secondary, + height: '90%', + width: '100%', + }, + wrapper: { + position: 'relative', + marginTop: 10, + }, + buttonSuccess: { + backgroundColor: green[500], + '&:hover': { + backgroundColor: green[700], + }, + }, + buttonFailure: { + backgroundColor: red[500], + '&:hover': { + backgroundColor: red[700], + }, + }, + buttonProgress: { + position: 'absolute', + top: 'calc(50% - 10px)', + left: 'calc(50% - 10px)', + }, + error: { + color: red[500], + marginTop: 10, + }, + success: { + color: green[500], + marginTop: 20, + }, + rootUserGroup: { + alignItems: 'center', + }, + formInput: { + width: '90%', + marginTop: 10, + }, + rootCardActions: { + justifyContent: 'center', + }, + caseSelector: { + marginTop: 5, + }, + button: { + marginBottom: 15, + }, + dataFormsWrapper: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + }, + paper: { + width: '100%', + paddingBottom: 10, + marginBottom: 20, + '&:last-child': { + marginBottom: 0, + }, + }, + red: { + color: red[500], + }, + displayInlineBlock: { + display: 'inline-block', + }, + listItemStyle: { + overflowWrap: 'anywhere', + }, + wrapperContainer: { + height: '100%', + display: 'flex', + flexDirection: 'column', + paddingLeft: 0, + }, + label: { + display: 'block', + fontSize: 12, + width: '100%', + color: theme.color.primary, + }, +})); + +export const initialState = { + isLoading: false, + isError: false, + error: null, +}; + +type State = { + isLoading: ?boolean, + isError: ?boolean, +}; + +type Action = { + type: string, + miniAppError: MiniAppError, + cookieInfo: CookieInfo[], +}; + +export const dataFetchReducer = (state: State, action: Action) => { + switch (action.type) { + case 'COOKIE_FETCH_INIT': + return { + isLoading: true, + isError: false, + error: null, + cookieInfo: null, + }; + case 'COOKIE_FETCH_SUCCESS': + return { + ...state, + isLoading: false, + isError: false, + error: null, + cookieInfo: action.cookieInfo, + }; + case 'COOKIE_FETCH_FAILURE': + return { + ...state, + isLoading: false, + isError: false, + error: null, + cookieInfo: null, + }; + + default: + throw Error('Unknown action type'); + } +}; + +function CookieManagerComponent() { + const classes = useStyles(); + const [state, dispatch] = useReducer(dataFetchReducer, initialState); + let [infoInputName, setInfoInputName] = useState(); + let [infoInputName1, setInfoInputName1] = useState(); + + const clearInfoSendInput = () => { + setInfoInputName(''); + setInfoInputName1(''); + dispatch({ + type: 'COOKIE_FETCH_INIT', + miniAppError: null, + inputError: null, + }); + }; + + function getAllCookies() { + MiniApp.cookieManager + .getAllCookies() + .then((response) => { + dispatch({ + type: 'COOKIE_FETCH_SUCCESS', + miniAppError: null, + cookieInfo: response, + }); + console.log('getAllCookies SUCCESS: ', response); + }) + .catch((error) => { + console.log('getAllCookies ERROR: ', error); + }); + } + + function getCookies() { + MiniApp.cookieManager + .getCookies([infoInputName, infoInputName1]) + .then((response) => { + dispatch({ + type: 'COOKIE_FETCH_SUCCESS', + miniAppError: null, + cookieInfo: response, + }); + }) + .catch((error) => { + console.log('getCookies ERROR: ', error); + }); + } + + function ShowCookieDetails() { + return ( +
+ {state.cookieInfo && + state.cookieInfo.map((cookie) => ( + + + + {cookie.value && cookie.value !== '' && ( + {'Value: ' + cookie.value} + )} + + + } + /> + + ))} +
+ ); + } + + function GetAllCookiesTab() { + return ( +
+ + {!state.isLoading && state.cookieInfo && ( + {ShowCookieDetails()} + )} + + + + +
+ ); + } + + function GetSpecificCookiesTab() { + return ( +
+
+ setInfoInputName(e.target.value)} + /> + setInfoInputName1(e.target.value)} + /> +
+ + + + + + + {!state.isLoading && state.cookieInfo && ( + {ShowCookieDetails()} + )} + +
+ ); + } + + const [tabValue, setTabValue] = React.useState('1'); + + const handleTabChange = (event: Event, newValue: string) => { + dispatch({ + type: 'COOKIE_FETCH_INIT', + miniAppError: null, + inputError: null, + }); + setTabValue(newValue); + }; + + return ( + + + + + + + {GetAllCookiesTab()} + {GetSpecificCookiesTab()} + + + ); +} + +export default CookieManagerComponent; diff --git a/js-miniapp-sample/src/pages/helper.js b/js-miniapp-sample/src/pages/helper.js index 337b26953..024183c87 100644 --- a/js-miniapp-sample/src/pages/helper.js +++ b/js-miniapp-sample/src/pages/helper.js @@ -20,5 +20,7 @@ export function sendAnalytics( elementType: elementType, data: data, }; - return MiniApp.miniappUtils.sendAnalytics(analyticsInfo); + if (MiniApp.miniappUtils) { + MiniApp.miniappUtils.sendAnalytics(analyticsInfo); + } } diff --git a/js-miniapp-sample/src/routes.js b/js-miniapp-sample/src/routes.js index b51912ec4..ab47168db 100644 --- a/js-miniapp-sample/src/routes.js +++ b/js-miniapp-sample/src/routes.js @@ -19,9 +19,9 @@ import PhotoCamera from '@material-ui/icons/PhotoCamera'; import SecurityIcon from '@material-ui/icons/Security'; import SendIcon from '@material-ui/icons/SendSharp'; import ShareIcon from '@material-ui/icons/Share'; -import ShoppingCartIcon from '@material-ui/icons/ShoppingCart'; import StorageIcon from '@material-ui/icons/Storage'; import VpnKeyIcon from '@material-ui/icons/VpnKey'; +import ArtTrackIcon from '@material-ui/icons/ArtTrack'; import Ads from './pages/ads'; import { CloseConfirmAlert } from './pages/app-close-alert'; @@ -32,7 +32,6 @@ import EventListener from './pages/event-listener'; import FileDownload from './pages/file-download'; import FileUploader from './pages/file-upload'; import GifPage from './pages/gifs'; -import { PurchaseProductComponent } from './pages/in-app-purchase'; import Landing from './pages/landing'; import LocalStorage from './pages/local-storage'; import Media from './pages/media'; @@ -45,6 +44,7 @@ import UserDetails from './pages/user-details'; import UuidFetcher from './pages/uuid-sdk'; import WebLocation from './pages/web-location'; import WindowActions from './pages/window-actions'; +import CookieManagerComponent from './pages/cookie-manager'; //default root location when using ios const iosHomeNavLink = { navLink: '/index.html', label: 'Home' }; @@ -103,14 +103,14 @@ const universalBridgeNavLink = { navLink: '/universal-bridge', label: 'Universal Bridge', }; -const inAppPurchaseNavLink = { - navLink: '/in-app-purchase', - label: 'Purchase', -}; const colorThemeNavLink = { navLink: '/color-theme', label: 'Color Theme', }; +const cookieManagerNavLink = { + navLink: '/cookies', + label: 'Cookie Manager', +}; const navLinks = [ iosHomeNavLink, @@ -136,8 +136,8 @@ const navLinks = [ secureStorageNavLink, closeAlertNavLink, universalBridgeNavLink, - inAppPurchaseNavLink, colorThemeNavLink, + cookieManagerNavLink, ]; const homeItem = [ @@ -264,18 +264,18 @@ const appItems = [ navLink: universalBridgeNavLink.navLink, element: , }, - { - icon: , - label: inAppPurchaseNavLink.label, - navLink: inAppPurchaseNavLink.navLink, - element: , - }, { icon: , label: colorThemeNavLink.label, navLink: colorThemeNavLink.navLink, element: , }, + { + icon: , + label: cookieManagerNavLink.label, + navLink: cookieManagerNavLink.navLink, + element: , + }, ]; const navItems: Object[] = homeItem.concat( diff --git a/js-miniapp-sample/src/theme.js b/js-miniapp-sample/src/theme.js index ff7b4fbfc..57d88b45a 100644 --- a/js-miniapp-sample/src/theme.js +++ b/js-miniapp-sample/src/theme.js @@ -4,12 +4,12 @@ import { grey } from '@material-ui/core/colors'; export default createTheme({ palette: { primary: { - main: '#bf0000', + main: '#000000', }, secondary: grey, }, color: { - primary: '#bf0000', + primary: '#000000', secondary: 'lightgrey', }, }); diff --git a/js-miniapp-sdk/CHANGELOG.md b/js-miniapp-sdk/CHANGELOG.md index 31ca60aba..a0939d39b 100644 --- a/js-miniapp-sdk/CHANGELOG.md +++ b/js-miniapp-sdk/CHANGELOG.md @@ -1,5 +1,9 @@ ## CHANGELOG +### 1.18.0 (2023-10-13) +- **Feature:** Added new interface `getAllCookies()` to get `CookieInfo` which contains `name` and `value` of the cookie +- **Feature:** Added new interface `getCookies(cookieNameList:)` that requests for certain cookies to host application that will get `CookieInfo` which contains `name` and `value` of the cookie + ### 1.18.0 (2023-07-25) - **Feature:** Added new interface `getHostAppThemeColors()` to get `HostThemeColor` which contains primary & secondary color set by the Host app - **Feature:** Added new interface `isDarkMode()`. Interface to know if the Hostapp/Device is set to use the Dark diff --git a/js-miniapp-sdk/README.md b/js-miniapp-sdk/README.md index bf6e2c708..39dd67afa 100644 --- a/js-miniapp-sdk/README.md +++ b/js-miniapp-sdk/README.md @@ -144,6 +144,7 @@ Here is the example of manifest. You can also see [it](https://github.com/rakute - [Host app theme colors](#host-theme-colors) - [isDarkMode](#dark-mode) - [Send Analytics](#send-analytics) +- [Get Cookies](#get-cookies) ### Retrieve a unique ID @@ -1189,6 +1190,43 @@ import MiniApp from 'js-miniapp-sdk'; MiniApp.miniappUtils.sendAnalytics(analyticsInfo); ``` +
+ +## Get Cookies from host application Available from v1.19.0 + +You can use the following interface to get all Cookies from Host app using the following interface + +```javascript +import MiniApp from 'js-miniapp-sdk'; + + MiniApp.cookieManager + .getAllCookies() + .then((response) => { + // Response will be [CookieInfo] + console.log(response); + }) + .catch((error) => { + console.log(error); + }); + +``` + +You can also request the host app to provide specific cookies by sharing the list of keys as `string[]` + +```javascript +import MiniApp from 'js-miniapp-sdk'; + + MiniApp.cookieManager + .getCookies(['user-token', `user-last-session`]) + .then((response) => { + // Response will be [CookieInfo] + console.log(response); + }) + .catch((error) => { + console.log(error); + }); + +``` ## Advanced Usage diff --git a/js-miniapp-sdk/src/index.ts b/js-miniapp-sdk/src/index.ts index 002d8b0d9..a84bf4aba 100644 --- a/js-miniapp-sdk/src/index.ts +++ b/js-miniapp-sdk/src/index.ts @@ -46,6 +46,7 @@ import { MAAnalyticsActionType, MAAnalyticsEventType, UniversalBridgeInfo, + CookieInfo, } from '../../js-miniapp-bridge/src'; import { MiniApp } from './miniapp'; @@ -104,4 +105,5 @@ export { MAAnalyticsActionType, MAAnalyticsEventType, UniversalBridgeInfo, + CookieInfo, }; diff --git a/js-miniapp-sdk/src/miniapp.ts b/js-miniapp-sdk/src/miniapp.ts index 42b99807e..62fceb9d2 100644 --- a/js-miniapp-sdk/src/miniapp.ts +++ b/js-miniapp-sdk/src/miniapp.ts @@ -21,6 +21,7 @@ import { SecureStorageService } from './modules/secure-storage'; import { UniversalBridge } from './modules/universal-bridge'; import { MiniAppUtils } from './modules/utils'; import { Purchases } from './modules/in-app-purchase'; +import { CookieManager } from './modules/cookie-manager'; /** * A module layer for webapps and mobile native interaction. @@ -170,6 +171,7 @@ export class MiniApp implements MiniAppFeatures, Ad, Platform { universalBridge = new UniversalBridge(); miniappUtils = new MiniAppUtils(); purchaseService = new Purchases(); + cookieManager = new CookieManager(); private requestPermission(permissionType: DevicePermission): Promise { return getBridge().requestPermission(permissionType); diff --git a/js-miniapp-sdk/src/modules/cookie-manager.ts b/js-miniapp-sdk/src/modules/cookie-manager.ts new file mode 100644 index 000000000..93ae5a595 --- /dev/null +++ b/js-miniapp-sdk/src/modules/cookie-manager.ts @@ -0,0 +1,30 @@ +import { CookieInfo } from '../../../js-miniapp-bridge/src'; +import { getBridge } from '../sdkbridge'; + +/** + * Interfaces to retrieve Cookies from Host app + */ +export interface CookieProvider { + /** + * Fetches all cookies from host app. + * @returns List of Cookies with name and value details + */ + getAllCookies(): Promise<[CookieInfo]>; + + /** + * Fetches the cookies for the provided name list + * @returns List of Cookies with name and value details + */ + getCookies(cookieNameList: string[]): Promise<[CookieInfo]>; +} + +/** @internal */ +export class CookieManager implements CookieProvider { + getAllCookies(): Promise<[CookieInfo]> { + return getBridge().getAllCookies(); + } + + getCookies(cookieNameList: string[]): Promise<[CookieInfo]> { + return getBridge().getCookies(cookieNameList); + } +}