Skip to content

Commit

Permalink
Merge pull request #206 from Telegram-Mini-Apps/feature/request-phone
Browse files Browse the repository at this point in the history
Feature/request phone
  • Loading branch information
heyqbnk authored Dec 15, 2023
2 parents 0053adc + 8a63011 commit 5da4529
Show file tree
Hide file tree
Showing 27 changed files with 652 additions and 232 deletions.
5 changes: 5 additions & 0 deletions .changeset/neat-fans-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tma.js/sdk": minor
---

Implemented MiniApp.requestContact method, reworked MiniApp.requestWriteAccess and MiniApp.requestPhoneAccess methods. Add invokeCustomMethod function.
4 changes: 4 additions & 0 deletions apps/docs/.vitepress/packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ export const packagesSidebar = {
text: 'QRScanner',
link: prefixed('/typescript/tma-js-sdk/components/qr-scanner'),
},
{
text: 'SettingsButton',
link: prefixed('/typescript/tma-js-sdk/components/settings-button'),
},
{
text: 'ThemeParams',
link: prefixed('/typescript/tma-js-sdk/components/theme-params'),
Expand Down
5 changes: 4 additions & 1 deletion apps/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ hero:
tagline: Simple, flexible, native-like web applications to enhance user experience
actions:
- theme: brand
text: Documentation
text: Platform
link: /platform/about-platform
- theme: alt
text: Packages
link: /packages/typescript/tma-js-sdk/about

features:
- icon: 💻
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ visibility state, progress visibility state, text, and its color. It also accept
function to call Telegram Mini Apps methods.

```typescript
import { BackButton, postEvent } from '@tma.js/sdk';
import { MainButton, postEvent } from '@tma.js/sdk';

const mainButton = new MainButton({
backgroundColor: '#aaddfe',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# `SettingsButton`

Implements Telegram Mini Apps [Settings Button](../../../../platform/ui/settings-button.md).

## Initialization

Component constructor accepts visibility state, Telegram Mini Apps version and optional function
to call Telegram Mini Apps methods.

```typescript
import { SettingsButton, postEvent } from '@tma.js/sdk';

const settingsButton = new SettingsButton(false, '6.3', postEvent);
```

## Showing and hiding

To show and hide the `SettingsButton`, it is required to use `show()` and `hide()` methods. These
methods update the button's `isVisible` property:

```typescript
settingsButton.show();
console.log(settingsButton.isVisible); // true

settingsButton.hide();
console.log(settingsButton.isVisible); // false
```

## Events

List of events, which could be used in `on` and `off` component instance methods:

| Event | Listener | Triggered when |
|------------------|----------------------------|--------------------------------|
| click | `() => void` | Settings Button was clicked |
| change | `() => void` | Something in component changed |
| change:isVisible | `(value: boolean) => void` | `isVisible` property changed |

## Methods support

List of methods, which could be used in `supports` component instance method:

- `show`
- `hide`

```typescript
import { SettingsButton } from '@tma.js/sdk';

const settingsButton = new SettingsButton(...);
settingsButton.supports('show');
settingsButton.supports('hide');
```
150 changes: 145 additions & 5 deletions apps/docs/packages/typescript/tma-js-sdk/methods-and-events.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Methods and events
# Methods and Events

This section of SDK covers the topic related
to [apps communication](../../../platform/apps-communication/flow-definition.md).

## Calling methods
## Calling Methods

To call the Telegram Mini Apps methods, developer should use `postEvent` function:

Expand All @@ -17,7 +17,147 @@ This function automatically finds the correct way to send this event based on th
environment features. For greater accuracy, it determines the current Telegram application type and
selects the appropriate flow.

## Listening to events
### `request`

`request` function should be used in case, it is required to call some Telegram Mini Apps method
and receive specified event. For example, developer would like to
call [web_app_request_viewport](../../../platform/apps-communication/methods.md#web-app-request-viewport)
method and catch [viewport_changed](../../../platform/apps-communication/events.md#viewport-changed)
event, to receive actual viewport data.

```typescript
import { request } from '@tma.js/sdk';

const viewport = await request('web_app_request_viewport', 'viewport_changed');

console.log(viewport);
// Output:
// {
// is_state_stable: true,
// is_expanded: false,
// height: 320
// };
```

In case, Telegram Mini Apps accepts parameters, you should pass them as the second argument:

```typescript
import { request } from '@tma.js/sdk';

const viewport = await request(
'web_app_invoke_custom_method',
{
req_id: 'abc',
method: 'getStorageValues',
params: { keys: ['a'] }
},
'custom_method_invoked',
);
```

This function allows passing additional options, such as `postEvent`, `timeout` and `capture`.

#### `postEvent`

We use `postEvent` option to override the method, which is used to call the Telegram Mini Apps
method.

```typescript
import { request, createPostEvent } from '@tma.js/sdk';

request('web_app_request_viewport', 'viewport_changed', {
postEvent: createPostEvent('6.5'),
});
```

#### `timeout`

`timeout` option is responsible for assigning the request timeout. In case, timeout was reached,
an error will be thrown.

```typescript
import { request, isTimeoutError } from '@tma.js/sdk';

try {
await request(
'web_app_invoke_custom_method',
{
req_id: '1',
method: 'deleteStorageValues',
params: { keys: ['a'] },
},
'custom_method_invoked',
{ timeout: 5000 },
);
} catch (e) {
if (isTimeoutError(e)) {
console.error('Timeout error:', e);
return;
}
console.error('Some different error', e);
}
```

#### `capture`

`capture` property is a function, that allows developer to determine if occurred Telegram Mini Apps
event should be captured and returned from the `request` function:

```typescript
request(
'web_app_open_invoice',
{ slug: 'jjKSJnm1k23lodd' },
'invoice_closed',
{
postEvent: this.postEvent,
capture(data) {
return slug === data.slug;
},
},
)
```

In this case, `request` function will capture the event only in case, it has the expected slug.

## Invoking Custom Methods

Custom methods are methods, which could be used by Telegram Mini Apps
`web_app_invoke_custom_method` method. It only simplifies usage of such methods and reuses the
`request` function.

Here is the code example without using this function:

```typescript
import { request } from '@tma.js/sdk';

request(
'web_app_invoke_custom_method',
{
req_id: 'request_id_1',
method: 'deleteStorageValues',
params: { keys: ['a'] },
},
'custom_method_invoked',
)
```

And that is how we could rewrite it using the `invokeCustomMethod` function:

```typescript
import { invokeCustomMethod } from '@tma.js/sdk';

invokeCustomMethod(
'deleteStorageValues',
{ keys: ['a'] },
'request_id_1',
);
```

In contrary to the `request` function, the `invokeCustomMethod` function parses the result and
checks if contains the `error` property. In case it does, the function will throw the according
error. Otherwise, the `result` property will be returned.

## Listening to Events

### `on` and `off`

Expand Down Expand Up @@ -76,7 +216,7 @@ subscribe(listener);
unsubscribe(listener);
```

## Checking method support
## Checking Method Support

`postEvent` function itself is not checking if specified method supported by current native Telegram
application. To do this, developer could use `supports` function which accepts Telegram Mini Apps
Expand Down Expand Up @@ -136,7 +276,7 @@ import { setDebug } from '@tma.js/sdk';
setDebug(true);
```

## Target origin
## Target Origin

If the package is being used in a browser environment (iframe), packages employs the
function `window.parent.postMessage`. This function requires specifying the target origin to ensure
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/bridge/events/parsers/phoneRequested.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { json, string } from '~/parsing/index.js';

export type PhoneRequestedStatus = 'sent' | string;
export type PhoneRequestedStatus = 'sent' | 'cancelled' | string;

export interface PhoneRequestedPayload {
/**
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/src/bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './env/index.js';
export * from './errors/index.js';
export * from './events/index.js';
export * from './methods/index.js';
export * from './invoke-custom-method.js';
export * from './request.js';
56 changes: 56 additions & 0 deletions packages/sdk/src/bridge/invoke-custom-method.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { ExecuteWithOptions } from '~/types/index.js';

import type { CustomMethodName, CustomMethodParams } from './methods/index.js';
import { request } from './request.js';

/**
* Invokes known custom method. Returns method execution result.
* @param method - method name.
* @param params - method parameters.
* @param requestId - request identifier.
* @param options - additional options.
*/
export async function invokeCustomMethod<M extends CustomMethodName>(
method: M,
params: CustomMethodParams<M>,
requestId: string,
options?: ExecuteWithOptions,
): Promise<unknown>;

/**
* Invokes unknown custom method. Returns method execution result.
* @param method - method name.
* @param params - method parameters.
* @param requestId - request identifier.
* @param options - additional options.
*/
export function invokeCustomMethod(
method: string,
params: object,
requestId: string,
options?: ExecuteWithOptions,
): Promise<unknown>;

export async function invokeCustomMethod(
method: string,
params: object,
requestId: string,
options: ExecuteWithOptions = {},
): Promise<unknown> {
const { result, error } = await request(
'web_app_invoke_custom_method',
{
method,
params,
req_id: requestId,
},
'custom_method_invoked',
options,
);

if (error) {
throw new Error(error);
}

return result;
}
Loading

0 comments on commit 5da4529

Please sign in to comment.