Skip to content
This repository was archived by the owner on Jan 7, 2025. It is now read-only.

Commit 29b7792

Browse files
committed
Migrate to Telegram SDK
1 parent b777d51 commit 29b7792

12 files changed

+87
-268
lines changed

README.md

+3-72
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Vanilla JS example
22

33
> ⚠️ Please, avoid using vanilla JavaScript if possible on Telegram Mini Apps
4-
> platform. It is better to use ES modules at least. [Learn more](#about-iife).
4+
> platform. It is better to use ES modules at least.
55
66
This example shows how developer could use Vanilla JavaScript to start developing at
77
Telegram Mini Apps platform.
@@ -10,7 +10,7 @@ This template demonstrates how developers can implement an application on the Te
1010
Mini Apps platform using the following technologies and libraries
1111

1212
- [TON Connect](https://docs.ton.org/develop/dapps/ton-connect/overview)
13-
- [@telegram-apps SDK](https://docs.telegram-mini-apps.com/packages/telegram-apps-sdk)
13+
- [Telegram SDK](https://core.telegram.org/bots/webapps#initializing-mini-apps)
1414

1515
> This boilerplate was created using [pnpm](https://pnpm.io/). Therefore, it is required to use
1616
> it for this project as well.
@@ -73,15 +73,9 @@ devices in the same network with the current device.
7373
To view the application, you need to open the `Local`
7474
link (`http://localhost:3000` in this example) in your browser.
7575

76-
It is important to note that some libraries in this template, such as `@telegram-apps/sdk`, are not
76+
It is important to note that some libraries in this template, such as Telegram SDK, are not
7777
intended for use outside of Telegram.
7878

79-
Nevertheless, they appear to function properly. This is because the `dist/js/mockEnv.ts` file, which is
80-
imported in the application's entry point (`dist/index.html`), employs the `mockTelegramEnv` function
81-
to simulate the Telegram environment. This trick convinces the application that it is running in a
82-
Telegram-based environment. Therefore, be cautious not to use this function in production mode
83-
unless you fully understand its implications.
84-
8579
### Run Inside Telegram
8680

8781
Although it is possible to run the application outside of Telegram, it is recommended to develop it
@@ -108,69 +102,6 @@ to [@BotFather](https://t.me/botfather). Then, navigate
108102
to [https://web.telegram.org/k/](https://web.telegram.org/k/), find your bot, and launch the
109103
Telegram Mini App. This approach provides the full development experience.
110104

111-
## About IIFE
112-
113-
### Dependencies
114-
115-
Some of the packages use other `@tma.js` packages as dependencies. In this case there are 2
116-
ways of importing them:
117-
118-
1. **By inserting another `script` tag which loads the dependency**.
119-
This way makes usage of package with a lot of dependencies almost unreal.
120-
2. **By inlining these packages**.
121-
This way leads to code duplication between several packages using the same package as dependency.
122-
123-
As you can see, there is no optimal solution between both of them. As the additional problem
124-
developer gets here, is bundler is unable to
125-
use [tree shaking](https://stackoverflow.com/questions/45884414/what-is-tree-shaking-and-why-would-i-need-it),
126-
making browser to load the code not used in the application. Imagine using the only 1 function from
127-
some library like `lodash`, but fully load it.
128-
129-
### Unknown target
130-
131-
The other problem developer can face is IIFE packages are built for the specific browser of specific
132-
version. So, the package author does not know which target he should choose as long as he doesn't
133-
know it when creating such package. That's why the the package target should be lowered to support
134-
most part of browsers, but this also make final bunlde bigger.
135-
136-
### Conclusion
137-
138-
Unfortunately, developer is unable to avoid these problems when using IIFE format. This is the
139-
reason why it is recommended to use modern technologies along with ESM format.
140-
141-
### When there is no other choice
142-
143-
First of all, it is required to load the package. Developer could use [JSDelivr](https://www.jsdelivr.com/)
144-
to do it:
145-
146-
```html
147-
148-
<head>
149-
<script src="https://cdn.jsdelivr.net/npm/@telegram-apps/sdk/dist/index.iife.js"></script>
150-
</head>
151-
```
152-
153-
Loaded packages of `@telegram-apps` in IIFE format are accessible by path `window.telegramApps.*`:
154-
155-
```html
156-
157-
<head>
158-
<script src="https://cdn.jsdelivr.net/npm/@telegram-apps/sdk/dist/index.iife.js"></script>
159-
</head>
160-
<body>
161-
<script>
162-
var sdk = window.telegramApps.sdk;
163-
console.log(sdk.retrieveLaunchData());
164-
</script>
165-
</body>
166-
```
167-
168-
> ⚠️ In this example we did not specify the exact version of required package. In this case,
169-
> JSDelivr CDN will return the latest version of the package which in some cases may lead to
170-
> unexpected behavior. To prevent such case, specify the exact version.
171-
172-
173-
174105
## Deploy
175106

176107
This boilerplate uses GitHub Pages as the way to host the application externally. GitHub Pages

dist/index.html

+1-5
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,14 @@
2424
<link href="css/link.css" rel="stylesheet">
2525
<link href="css/displayData.css" rel="stylesheet">
2626

27-
<script src="https://cdn.jsdelivr.net/npm/@telegram-apps/[email protected]/dist/index.iife.js"></script>
27+
<script src="https://telegram.org/js/telegram-web-app.js"></script>
2828
<script src="https://unpkg.com/@tonconnect/[email protected]/dist/tonconnect-ui.min.js"></script>
2929
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
3030
</head>
3131
<body>
3232
<noscript>You need to enable JavaScript to run this app.</noscript>
3333
<div id="root"></div>
3434
<script src="js/utils.js"></script>
35-
<!-- Uncomment next line for local development outside Telegram Mini App -->
36-
<!-- <script src="js/mockEnv.js"></script> -->
37-
<script src="js/initNavigrator.js"></script>
38-
<script src="js/initComponents.js"></script>
3935
<script src="js/initTonConnect.js"></script>
4036

4137
<script src="js/components/DisplayData.js"></script>

dist/js/components/DisplayData.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
function isRGB(value) {
2+
return /^#[a-f0-9]{3,6}$/i.test(value);
3+
}
4+
15
class DisplayData {
26
constructor({ rows }) {
37
this.el = $('<div/>');
@@ -15,7 +19,7 @@ class DisplayData {
1519
this.el.empty().append(
1620
...rows.map(row => {
1721
const lineValue = $('<span class="display-data__line-value"/>');
18-
if (typeof row.value === 'string' && window.telegramApps.sdk.isRGB(row.value)) {
22+
if (typeof row.value === 'string' && isRGB(row.value)) {
1923
lineValue.append(new RGB({ color: row.value }).element());
2024
} else if (row.value === false) {
2125
lineValue.text('❌');

dist/js/components/Link.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ class Link {
88
this.el = $('<a/>')
99
.attr('class', 'link')
1010
.addClass(className ?? '')
11-
.attr('href', isExternal ? href : context.navigator.renderPath(href));
11+
.attr('href', isExternal ? href : `#${href}`);
1212

1313
if (isExternal) {
1414
this.el.on('click', (e) => {
1515
e.preventDefault();
16-
context.utils.openLink(targetUrl.toString());
16+
context.getWebApp().openLink(targetUrl.toString());
1717
});
1818
}
1919
}

dist/js/index.js

+57-68
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,59 @@
1-
(async () => {
2-
// Uncomment next line for local development outside Telegram Mini App
3-
// mockEnv();
4-
5-
const launchParams = window.telegramApps.sdk.retrieveLaunchParams();
6-
7-
// Launch eruda and enable SDK debug mode, if debug mode was requested outside.
8-
const debug = launchParams.startParam === 'debug';
9-
if (debug) {
10-
window.telegramApps.sdk.setDebug(debug);
1+
const tonConnectUI = initTonConnectUI();
2+
3+
const routes = [
4+
{ pathname: '/', Page: HomePage },
5+
{ pathname: '/init-data', Page: InitDataPage, title: 'Init Data' },
6+
{ pathname: '/theme-params', Page: ThemeParamsPage, title: 'Theme Params' },
7+
{ pathname: '/launch-params', Page: LaunchParamsPage, title: 'Launch Params' },
8+
{
9+
pathname: '/ton-connect',
10+
Page: TonConnectPage,
11+
title: 'TON Connect',
12+
icon: `${window.location.origin}${window.location.pathname}ton.svg`,
13+
},
14+
];
15+
16+
const root = document.getElementById('root');
17+
const appContext = {
18+
getWebApp() {
19+
return window.Telegram.WebApp;
20+
},
21+
tonConnectUI,
22+
routes,
23+
};
24+
let prevPage;
25+
26+
27+
appContext.getWebApp().BackButton.onClick(goBack);
28+
29+
window.addEventListener('hashchange', () => {
30+
const path = window.location.hash.slice(1);
31+
renderCurrentRoute(path);
32+
updateBackButton(path)
33+
})
34+
35+
renderCurrentRoute(window.location.hash.slice(1));
36+
37+
function renderCurrentRoute(path) {
38+
const route = routes.find(r => r.pathname === path);
39+
if (!route) {
40+
window.location.hash = '#/';
41+
return;
1142
}
12-
13-
// The web version of Telegram is capable of sending some specific CSS styles we would
14-
// like to catch.
15-
if (window.telegramApps.sdk.isIframe()) {
16-
window.telegramApps.sdk.initWeb(true);
43+
prevPage && prevPage.destroy && prevPage.destroy();
44+
prevPage = new route.Page(appContext);
45+
prevPage.init && prevPage.init();
46+
prevPage.render(root);
47+
}
48+
49+
function goBack() {
50+
window.history.go(-1);
51+
}
52+
53+
function updateBackButton(path) {
54+
if (path === '/') {
55+
appContext.getWebApp().BackButton.isVisible && appContext.getWebApp().BackButton.hide();
56+
} else {
57+
!appContext.getWebApp().BackButton.isVisible && appContext.getWebApp().BackButton.show();
1758
}
18-
19-
const {
20-
miniApp,
21-
viewport,
22-
utils,
23-
themeParams,
24-
initData,
25-
} = await initComponents();
26-
const navigator = await initNavigator();
27-
const tonConnectUI = initTonConnectUI();
28-
29-
const routes = [
30-
{ pathname: '/', Page: HomePage },
31-
{ pathname: '/init-data', Page: InitDataPage, title: 'Init Data' },
32-
{ pathname: '/theme-params', Page: ThemeParamsPage, title: 'Theme Params' },
33-
{ pathname: '/launch-params', Page: LaunchParamsPage, title: 'Launch Params' },
34-
{
35-
pathname: '/ton-connect',
36-
Page: TonConnectPage,
37-
title: 'TON Connect',
38-
icon: `${window.location.origin}${window.location.pathname}ton.svg`,
39-
},
40-
];
41-
42-
const root = document.getElementById('root');
43-
const appContext = {
44-
initData,
45-
launchParams,
46-
miniApp,
47-
navigator,
48-
themeParams,
49-
utils,
50-
viewport,
51-
tonConnectUI,
52-
routes,
53-
};
54-
let prevPage;
55-
56-
function renderCurrentRoute() {
57-
const route = routes.find(r => r.pathname === navigator.pathname);
58-
if (!route) {
59-
navigator.replace('/');
60-
return;
61-
}
62-
prevPage && prevPage.destroy && prevPage.destroy();
63-
prevPage = new route.Page(appContext);
64-
prevPage.init && prevPage.init();
65-
prevPage.render(root);
66-
}
67-
68-
navigator.on('change', renderCurrentRoute);
69-
renderCurrentRoute();
70-
})();
59+
}

dist/js/initComponents.js

-22
This file was deleted.

dist/js/initNavigrator.js

-8
This file was deleted.

dist/js/mockEnv.js

-63
This file was deleted.

0 commit comments

Comments
 (0)