Skip to content

Commit 07f60e2

Browse files
authored
Merge pull request #670 from Telegram-Mini-Apps/feature/download-file-and-copy-to-clipboard
Feature/download file and copy to clipboard
2 parents 26633de + c25520f commit 07f60e2

File tree

7 files changed

+120
-3
lines changed

7 files changed

+120
-3
lines changed

.changeset/hip-balloons-bathe.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@telegram-apps/sdk": minor
3+
---
4+
5+
Implement `copyTextToClipboard` and `downloadFile`.

apps/docs/packages/telegram-apps-sdk/3-x/utils/uncategorized.md

+38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
# Uncategorized
22

3+
## `copyTextToClipboard`
4+
5+
Copies specified text to the clipboard using all known methods.
6+
7+
```ts
8+
import { copyTextToClipboard } from '@telegram-apps/sdk';
9+
10+
await copyTextToClipboard('My text goes here');
11+
```
12+
13+
## `downloadFile`
14+
15+
To request file download, use the `downloadFile` function. It accepts a file URL and its proposed saved name.
16+
17+
::: code-group
18+
19+
```ts [Using isAvailable]
20+
import { downloadFile } from '@telegram-apps/sdk';
21+
22+
if (downloadFile.isAvailable()) {
23+
await downloadFile(
24+
'https://telegram.org/js/telegram-web-app.js',
25+
'telegram-sdk.js',
26+
);
27+
}
28+
```
29+
30+
```ts [Using ifAvailable]
31+
import { downloadFile } from '@telegram-apps/sdk';
32+
33+
await downloadFile.ifAvailable(
34+
'https://telegram.org/js/telegram-web-app.js',
35+
'telegram-sdk.js',
36+
);
37+
```
38+
39+
:::
40+
341
## `getCurrentTime`
442

543
To retrieve the current Telegram server time, use the `getCurrentTime` function. It returns

apps/docs/platform/events.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,9 @@ Custom emoji status set.
290290

291291
Available since: **v8.0**
292292

293-
| Field | Type | Description |
294-
|--------|----------|------------------------------------------------------------------|
295-
| status | `string` | Request status. Set to `downloading` if the is being downloaded. |
293+
| Field | Type | Description |
294+
|--------|----------|-----------------------------------------------------------------|
295+
| status | `string` | Request status. Set to `downloading` if a file is being loaded. |
296296

297297
### `fullscreen_changed`
298298

apps/docs/platform/methods.md

+2
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,8 @@ Available since: **v8.0**
432432

433433
Displays a native popup prompting the user to download a file.
434434

435+
In turn, the Telegram client emits the [file_download_requested](./events.md#file_download_requested) event.
436+
435437
| Field | Type | Description |
436438
|-----------|----------|---------------------------------------------|
437439
| url | `string` | The HTTPS URL of the file to be downloaded. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
function fallback(text: string) {
2+
const textArea = document.createElement('textarea');
3+
textArea.value = text;
4+
5+
// Avoid scrolling to bottom
6+
textArea.style.top = '0';
7+
textArea.style.left = '0';
8+
textArea.style.position = 'fixed';
9+
10+
document.body.appendChild(textArea);
11+
textArea.focus();
12+
textArea.select();
13+
14+
try {
15+
document.execCommand('copy');
16+
} finally {
17+
document.body.removeChild(textArea);
18+
}
19+
}
20+
21+
/**
22+
* Copies specified text to the clipboard.
23+
* @param text - text to copy.
24+
*/
25+
export async function copyTextToClipboard(text: string): Promise<void> {
26+
try {
27+
const { clipboard } = navigator;
28+
if (clipboard) {
29+
return await clipboard.writeText(text);
30+
}
31+
} catch {
32+
}
33+
fallback(text);
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { request } from '@/globals.js';
2+
import { wrapSafe } from '@/scopes/wrappers/wrapSafe.js';
3+
import { AccessDeniedError } from '@/errors.js';
4+
import type { RequestOptionsNoCapture } from '@/types.js';
5+
6+
const METHOD_NAME = 'web_app_request_file_download';
7+
8+
/**
9+
* Displays a native popup prompting the user to download a file.
10+
* @param url - the HTTPS URL of the file to be downloaded.
11+
* @param file - the suggested name for the downloaded file.
12+
* @param options - additional request execution options.
13+
* @since Mini Apps v8.0
14+
* @throws {FunctionNotAvailableError} The environment is unknown
15+
* @throws {FunctionNotAvailableError} The SDK is not initialized
16+
* @throws {FunctionNotAvailableError} The function is not supported
17+
* @throws {AccessDeniedError} User denied the action
18+
* @example
19+
* if (downloadFile.isAvailable()) {
20+
* await downloadFile('https://telegram.org/js/telegram-web-app.js', 'telegram-sdk.js');
21+
* }
22+
*/
23+
export const downloadFile = wrapSafe(
24+
'downloadFile',
25+
(url: string, fileName: string, options?: RequestOptionsNoCapture) => {
26+
return request(
27+
METHOD_NAME,
28+
'file_download_requested',
29+
{ ...options, params: { url, file_name: fileName } },
30+
).then(response => {
31+
if (response.status !== 'downloading') {
32+
throw new AccessDeniedError('User denied the action');
33+
}
34+
});
35+
}, { isSupported: METHOD_NAME },
36+
);

packages/sdk/src/scopes/utilities/uncategorized/exports.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
export { copyTextToClipboard } from './copyTextToClipboard.js';
2+
export { downloadFile } from './downloadFile.js';
13
export { getCurrentTime } from './getCurrentTime.js';
24
export { readTextFromClipboard } from './readTextFromClipboard.js';
35
export { sendData } from './sendData.js';

0 commit comments

Comments
 (0)