Skip to content

Commit

Permalink
[MINI-5753] [MINI-5756] Universal Bridge: SDK interfaces and sample a…
Browse files Browse the repository at this point in the history
…pp (#230)

* add universal bridge module

* add function to send json string

* add sample app changes

* fix issues

* add changes for receiving json info

* add documentation

* add testcases

* cleanup

* fix issues

* remove implementation of response back

* address feedback and improve UI
  • Loading branch information
khairul-alam-licon authored Dec 1, 2022
1 parent 0fb096a commit ca744a5
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 3 deletions.
16 changes: 16 additions & 0 deletions js-miniapp-bridge/src/common-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,22 @@ export class MiniAppBridge {
);
});
}

/**
* Associating sendJsonToHostapp function to MiniAppBridge object.
* @param {info} JSON/String information that you would like to send to HostApp.
* @see {sendJsonToHostapp}
*/
sendJsonToHostapp(info: string) {
return new Promise<string>((resolve, reject) => {
return this.executor.exec(
'sendJsonToHostapp',
{ jsonInfo: info },
success => resolve(success),
error => reject(parseMiniAppError(error))
);
});
}
}

/**
Expand Down
12 changes: 12 additions & 0 deletions js-miniapp-bridge/test/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,18 @@ function createCloseAlertInfo(): CloseAlertInfo {
};
}

describe('sendJsonToHostapp', () => {
it('will return the send json string response', () => {
const bridge = new Bridge.MiniAppBridge(mockExecutor);
const response = 'success';
mockExecutor.exec.callsArgWith(2, response);

return expect(
bridge.sendJsonToHostapp('{"data":"This is a sample json information"}')
).to.eventually.deep.equal(response);
});
});

describe('console.log', () => {
const logger = new Logger.MiniAppSDKLogger(mockLogger);
window.MiniAppSDKLogger = logger;
Expand Down
1 change: 1 addition & 0 deletions js-miniapp-sample/src/pages/event-listener.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const useStyles = makeStyles((theme) => ({
width: '90%',
marginTop: 10,
marginBottom: 10,
background: 'white',
},
}));

Expand Down
152 changes: 152 additions & 0 deletions js-miniapp-sample/src/pages/universal-bridge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import React, { useState } from 'react';
import MiniApp from 'js-miniapp-sdk';
import { HostAppEvents } from 'js-miniapp-sdk';

import {
Button,
TextField,
CardContent,
CardActions,
makeStyles,
} from '@material-ui/core';

import GreyCard from '../components/GreyCard';

const useStyles = makeStyles((theme) => ({
scrollable: {
overflowY: 'auto',
width: '100%',
paddingTop: 20,
paddingBottom: 20,
},
card: {
width: '100%',
height: 'auto',
},
actions: {
justifyContent: 'center',
},
content: {
justifyContent: 'center',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
fontSize: 18,
color: theme.color.primary,
fontWeight: 'bold',
paddingBottom: 0,
},
sendInput: {
width: '90%',
marginTop: 10,
marginBottom: 10,
background: 'white',
},
receiveInput: {
width: '90%',
marginTop: 10,
marginBottom: 10,
disabled: 'disabled',
caretColor: 'transparent',
},
}));

const UniversalBridge = () => {
const classes = useStyles();
const defaultJsonValue = '{"data":"This is a sample json information"}';
let [inputValue, setInputValue] = useState(defaultJsonValue);
let [receiveJsonInfo, setReceiveJsonInfo] = useState('');

window.addEventListener(HostAppEvents.RECEIVE_JSON_INFO, function (e) {
let message = e.detail.message;
console.log(message);
receiveJsonInfo = message;
setReceiveJsonInfo(message);
});

const handleInput = (e: SyntheticInputEvent<HTMLInputElement>) => {
e.preventDefault();
setInputValue(e.currentTarget.value);
};

const clearSendInput = () => {
setInputValue('');
};

const sendJson = () => {
const info = { content: inputValue };
MiniApp.universalBridge
.sendJsonToHostapp(info)
.then((success) => {
console.log(success);
window.alert(success);
})
.catch((miniAppError) => {
console.error(miniAppError);
window.alert(miniAppError);
});
};

return (
<div className={classes.scrollable}>
<GreyCard className={classes.card}>
<CardContent className={classes.content}>
<p>Send JSON/String to HostApp</p>
</CardContent>
<CardContent className={classes.content}>
<TextField
type="text"
className={classes.sendInput}
onChange={handleInput}
placeholder="Input JSON/String here..."
value={inputValue}
variant="outlined"
color="primary"
multiline="true"
inputProps={{
'data-testid': 'input-field',
}}
/>
</CardContent>
<CardActions className={classes.actions}>
<Button
color="primary"
className={classes.button}
onClick={sendJson}
variant="contained"
>
Send Json
</Button>
<Button
className={classes.button}
onClick={clearSendInput}
variant="contained"
>
Clear
</Button>
</CardActions>
<hr
style={{
borderColor: 'primary',
}}
/>
<CardContent className={classes.content}>
<p>Receive JSON/String from HostApp</p>
</CardContent>
<CardContent className={classes.content}>
<TextField
type="text"
className={classes.receiveInput}
placeholder="Received JSON/String here"
value={receiveJsonInfo}
variant="outlined"
color="primary"
multiline="true"
/>
</CardContent>
</GreyCard>
</div>
);
};

export default UniversalBridge;
8 changes: 8 additions & 0 deletions js-miniapp-sample/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import PhotoCamera from '@material-ui/icons/PhotoCamera';
import SecurityIcon from '@material-ui/icons/Security';
import NotificationImportantOutlinedIcon from '@material-ui/icons/NotificationImportantOutlined';
import ShoppingCartIcon from '@material-ui/icons/ShoppingCart';
import SendIcon from '@material-ui/icons/SendSharp';

import Ads from './pages/ads';
import AuthToken from './pages/auth-token';
Expand All @@ -41,6 +42,7 @@ import WindowActions from './pages/window-actions';
import SecureStorageComponent from './pages/secure-storage';
import { CloseConfirmAlert } from './pages/app-close-alert';
import Purchases from './pages/inapp-purchases';
import UniversalBridge from './pages/universal-bridge';

const homeItem = [
{
Expand Down Expand Up @@ -166,6 +168,12 @@ const appItems = [
navLink: '/close-confirm-alert',
element: <CloseConfirmAlert />,
},
{
icon: <SendIcon />,
label: 'Universal Bridge',
navLink: '/universal-bridge',
element: <UniversalBridge />,
},
];

const navItems: Object[] = homeItem.concat(
Expand Down
2 changes: 1 addition & 1 deletion js-miniapp-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## CHANGELOG
### 1.16.0 (TBD)
- **Feature:** Added In-app purchases related interfaces. `prepareProductsList()` , `purchaseProductWith(id: string)`. These interfaces can be used to prepare the list of products and make a in-app purchase with product id from associated with Google Play™ or Apple App Store™.
- **Feature:** Added Universal Bridge related interface e.g. `sendJsonToHostapp` to send any JSON/String to the HostApp. Also, added support with `HostAppEvents` to receive any JSON/String to MiniApp from the HostApp.

---
### 1.15.0 (2022-06-24)
- **Feature:** Added `setCloseAlert(alertInfo: CloseAlertInfo)` interface support to Mini Apps share info about Close confirm alert
- **Feature:** Added Secure storage related interfaces. `setItems(items: MiniAppSecureStorageKeyValues)` , `getItem(key: string)`, `removeItems(key: [string])`, `clear()`, `size()`. These interfaces can be used to storage items in the SDK.
Expand Down
31 changes: 31 additions & 0 deletions js-miniapp-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,37 @@ miniApp.purchases
});
```
### Universal Bridge
MiniApp users can send any JSON/String from MiniApp to HostApp as well as receive any JSON/String from HostApp to MiniApp.
#### Send a JSON/String from MiniApp to HostApp
Please use the following example in the MiniApp:
```javascript
import miniApp from 'js-miniapp-sdk';
const inputValue = '{"data":"This is a sample json information"}';
const info = { content: inputValue };
miniApp.universalBridge
.sendJsonToHostapp(info)
.then((success) => {
console.log(success);
})
.catch((error) => {
console.error(error);
});
```
#### Receive a JSON/String from HostApp to MiniApp
Please use the following example in the MiniApp:
```javascript
import HostAppEvents from 'js-miniapp-sdk';
window.addEventListener(HostAppEvents.RECEIVE_JSON_INFO, function (e) {
let message = e.detail.message;
console.log(message);
});
```
## Advanced Usage
### Errors management
Expand Down
10 changes: 10 additions & 0 deletions js-miniapp-sdk/src/event-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ export enum MiniAppEvents {
RESUME = 'miniappresume',
}

/**
* Enum for supported keyboard event types
*/
export enum MiniAppKeyboardEvents {
KEYBOARDSHOWN = 'miniappkeyboardshown',
KEYBOARDHIDDEN = 'miniappkeyboardhidden',
}

/**
* Enum for supported HostApp event types
*/
export enum HostAppEvents {
RECEIVE_JSON_INFO = 'miniappreceivejsoninfo',
}
7 changes: 6 additions & 1 deletion js-miniapp-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ import {
} from '../../js-miniapp-bridge/src';

import { MiniApp } from './miniapp';
import { MiniAppEvents, MiniAppKeyboardEvents } from './event-types';
import {
MiniAppEvents,
MiniAppKeyboardEvents,
HostAppEvents,
} from './event-types';

/** @internal */
const miniAppInstance = new MiniApp();
Expand Down Expand Up @@ -71,6 +75,7 @@ export {
ScopesNotSupportedError,
MiniAppEvents,
MiniAppKeyboardEvents,
HostAppEvents,
SecureStorageFullError,
SecureStorageBusyError,
SecureStorageUnavailableError,
Expand Down
2 changes: 2 additions & 0 deletions js-miniapp-sdk/src/miniapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { getBridge } from './utils';
import { deprecate } from 'util';
import { SecureStorageService } from './modules/secure-storage';
import { Purchases } from './modules/inapp-purchases';
import { UniversalBridge } from './modules/universal-bridge';

/**
* A module layer for webapps and mobile native interaction.
Expand Down Expand Up @@ -163,6 +164,7 @@ export class MiniApp implements MiniAppFeatures, Ad, Platform {
chatService = new ChatService();
secureStorageService = new SecureStorageService();
purchases = new Purchases();
universalBridge = new UniversalBridge();

private requestPermission(permissionType: DevicePermission): Promise<string> {
return getBridge().requestPermission(permissionType);
Expand Down
18 changes: 18 additions & 0 deletions js-miniapp-sdk/src/modules/universal-bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { getBridge } from '../utils';

/**
* Interface to send JSON/String to Host app
*/
export interface UniversalBridgeProvider {
/**
* Send JSON/String information to HostApp.
*/
sendJsonToHostapp(info: string): Promise<string>;
}

/** @internal */
export class UniversalBridge implements UniversalBridgeProvider {
sendJsonToHostapp(info: string): Promise<string> {
return getBridge().sendJsonToHostapp(info);
}
}
22 changes: 22 additions & 0 deletions js-miniapp-sdk/test/miniapp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ window.MiniAppBridge = {
getSecureStorageItem: sandbox.stub(),
removeSecureStorageItems: sandbox.stub(),
isSecureStorageReady: sandbox.stub(),
sendJsonToHostapp: sandbox.stub(),
};
const miniApp = new MiniApp();
const messageToContact: MessageToContact = {
Expand Down Expand Up @@ -845,3 +846,24 @@ describe('setCloseAlert', () => {
return expect(miniApp.setCloseAlert(alertInfo)).to.eventually.equal(error);
});
});

describe('sendJsonToHostapp', () => {
it('should retrieve null from the MiniAppBridge once sendJsonToHostapp call is successful', () => {
const jsonToHostapp = 'test content';
const response = null;

window.MiniAppBridge.sendJsonToHostapp.resolves(response);
return expect(
miniApp.universalBridge.sendJsonToHostapp(jsonToHostapp)
).to.eventually.equal(response);
});
it('should retrive error response from the MiniAppBridge once there is errors', () => {
const jsonToHostapp = 'test content';
const error = 'Bridge error';

window.MiniAppBridge.sendJsonToHostapp.resolves(error);
return expect(
miniApp.universalBridge.sendJsonToHostapp(jsonToHostapp)
).to.eventually.equal(error);
});
});
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15308,4 +15308,4 @@
"yocto-queue@^0.1.0":
"integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
"resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
"version" "0.1.0"
"version" "0.1.0"

0 comments on commit ca744a5

Please sign in to comment.