/
kaws
/
MiniAppExample
Обзор
Документация
Войти
/
kaws
/
MiniAppExample
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
index.html
1 834 строки
75 KB
Oleg Koval (revenkroz)
Up to Bot API 8.0
23 ноя 2024, 19:57
23 ноя 2024, 19:57
7a59b44
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="format-detection" content="telephone=no" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="MobileOptimized" content="176" /> <meta name="HandheldFriendly" content="True" /> <meta name="robots" content="noindex,nofollow" /> <script src="https://telegram.org/js/telegram-web-app.js?2"></script> <script> function setThemeClass() { document.documentElement.className = Telegram.WebApp.colorScheme; } Telegram.WebApp.onEvent('themeChanged', setThemeClass); setThemeClass(); </script> <title></title> <style> body { --bg-color: var(--tg-theme-bg-color, #fff); font-family: sans-serif; background-color: var(--bg-color); color: var(--tg-theme-text-color, #222); font-size: 14px; margin: 0; padding: 0; color-scheme: var(--tg-color-scheme); } body.gray { background-color: var(--tg-theme-secondary-bg-color, #efefef); } a { color: var(--tg-theme-link-color, #2678b6); } .btn { font-size: 14px; padding: 10px 17px; } .btn-primary { background-color: var(--tg-theme-button-color, #50a8eb); color: var(--tg-theme-button-text-color, #fff); border: none; } button { display: block; width: 100%; font-size: 14px; margin: 15px 0; padding: 12px 20px; border: none; border-radius: 4px; background-color: var(--tg-theme-button-color, #50a8eb); color: var(--tg-theme-button-text-color, #ffffff); cursor: pointer; } .main-container { padding: 15px; } .list-header { text-transform: uppercase; font-size: .92em; color: var(--tg-theme-hint-color, #ccc); margin: 0 0 10px; } a.list-group-item, button.list-group-item { color: var(--tg-theme-text-color, #222); } .main-container p { margin: 0 0 10px; } .main-container pre, .main-container > .btn { margin: 0 0 7px; } .main-container pre + .hint, .main-container > .btn + .hint { text-align: center; margin: 0 0 15px; } button[disabled] { opacity: 0.6; cursor: auto; pointer-events: none; } button.close_btn { /*position: fixed;*/ position: absolute; left: 0; right: 0; bottom: 0; border-radius: 0; margin: 0; padding: 16px 20px; text-transform: uppercase; } input[type="text"], .input[contenteditable] { display: block; box-sizing: border-box; font-size: 14px; width: 100%; padding: 12px 20px; margin: 15px 0; border: 1px solid var(--tg-theme-link-color, #000); background-color: var(--tg-theme-bg-color, #ffffff); border-radius: 4px; color: var(--tg-theme-text-color, #222222); text-align: start; } input[type="text"]::-webkit-input-placeholder { color: var(--tg-theme-hint-color, #ccc); } input[type="text"]::-moz-placeholder { color: var(--tg-theme-hint-color, #ccc); } input[type="text"]:-ms-input-placeholder { color: var(--tg-theme-hint-color, #ccc); } .input[data-placeholder] { position: relative; } .input[data-placeholder]:empty:before { position: absolute; left: 0; right: 0; content: attr(data-placeholder); color: var(--tg-theme-hint-color, #ccc); padding: 0 20px; font-weight: normal; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; pointer-events: none; z-index: -1; } section { padding: 15px; text-align: center; background-color: var(--bg-color, #ffffff); } section#top_sect { background-color: var(--tg-theme-bg-color, #ffffff); } section#top_sect.second { background-color: var(--tg-theme-secondary-bg-color, #efefef); } section .sect_row { margin: 10px 0; } section + section { padding: 0 15px 65px; } p { margin: 40px 0 15px; } ul { text-align: left; } li { color: var(--tg-theme-hint-color, #a8a8a8); } textarea { width: 100%; box-sizing: border-box; padding: 7px; } pre { background: rgba(0, 0, 0, .07); color: var(--tg-theme-text-color, #222); font-size: 12px; border: none; border-radius: 4px; padding: 8px; margin: 7px 0; word-break: break-word; white-space: pre-wrap; text-align: left; } .dark pre { background: rgba(255, 255, 255, .15); } .chat_img { width: 30px; border-radius: 15px; margin-right: 10px; } .columns { display: flex; } .columns > * { flex-grow: 1; } .hint { font-size: .8em; color: var(--tg-theme-hint-color, #a8a8a8); } .ok { color: green; } .err { color: red; } .status_need { display: none; } #fixed_wrap { position: fixed; left: 0; right: 0; top: 0; transform: translateY(100vh); } .viewport-container { position: fixed; left: 0; right: 0; top: 0; height: var(--tg-viewport-stable-height, 100vh); transition: height .2s ease; } .viewport-container .main-container { position: absolute; left: 0; right: 0; top: 0; bottom: 0; display: flex; justify-content: center; align-items: center; } .viewport-container .main-container button { width: auto; } .viewport-border, .viewport-stable_border { position: fixed; left: 0; right: 0; top: 0; height: var(--tg-viewport-height, 100vh); pointer-events: none; } .viewport-stable_border { height: var(--tg-viewport-stable-height, 100vh); } .viewport-border:before, .viewport-stable_border:before { content: attr(text); display: inline-block; position: absolute; background: gray; right: 0; top: 0; font-size: 7px; padding: 2px 4px; vertical-align: top; } .viewport-stable_border:before { background: green; left: 0; right: auto; } .viewport-border:after, .viewport-stable_border:after { content: ''; display: block; position: absolute; left: 0; right: 0; top: 0; bottom: 0; border: 2px dashed gray; } .viewport-stable_border:after { border-color: green; } small { font-size: 12px; } .small { font-size: 12px; } .table { width: 100%; border-collapse: collapse; } .table td { padding: 2px; } .table-bordered { border: 1px solid var(--tg-theme-hint-color, #ccc); } .table-bordered th, .table-bordered td { border: 1px solid var(--tg-theme-hint-color, #ccc); padding: 4px; } .table.small button { padding: 3px 6px; font-size: 12px; margin: 4px 0; } .table.small input { padding: 3px 6px; font-size: 12px; margin: 4px 0; } </style> </head> <body class="" style="visibility: hidden;"> <section id="top_sect" class="second"> <button id="main_btn" onclick="DemoApp.sendMessage('');">Send «Hello, World!»</button> <button id="with_webview_btn" onclick="DemoApp.sendMessage('', true);">Send «Hello, World!» with inline webview button</button> <button id="share_btn" onclick="DemoApp.sendMessage('', false, true);">Share «Hello, World!»</button> <button id="share_ww_btn" onclick="DemoApp.sendMessage('', true, true);">Share «Hello, World!» with inline button</button> <button id="data_btn" onclick="DemoApp.sendTime(true);">Send current time to bot (x10)</button> <button onclick="DemoApp.expand();">Expand Webview</button> <button onclick="DemoApp.toggleBackButton(this);">Show Back Button</button> <button onclick="DemoApp.toggleSettingsButton(this);">Show Settings Button</button> <button onclick="DemoApp.toggleMainButton(this);">Hide Main Button</button> <button onclick="DemoApp.toggleSecondaryButton(this);">Hide Secondary Button</button> <button onclick="DemoApp.toggleButtonsProgress(this);">Show Progress</button> <button onclick="DemoApp.toggleSwipeBehavior(this);">Disable Vertical Swypes</button> <button id="fullscreen_btn" onclick="DemoApp.toggleFullscreen(this);">Request Fullscreen</button> <button id="orient_btn" onclick="DemoApp.toggleOrientationLock(this);">Lock Orientation</button> <input type="text" placeholder="Input text in regular input..." id="regular_field" /> <div class="input" contenteditable="true" data-placeholder="Input text in contenteditable field..." id="text_field" ></div> <div id="peer_wrap" style="display:none"> <img id="peer_photo" class="chat_img" src=""> <span id="peer_name"></span> </div> <div class="sect_row">Header: <input type="color" id="header_color_input" /> <select id="header_color_sel"> <option value="bg_color" selected>bg_color</option> <option value="secondary_bg_color">secondary_bg_color</option> <option value="custom" id="header_color_val">custom...</option> </select> </div> <div class="sect_row">Background: <input type="color" id="bg_color_input" /> <select id="bg_color_sel"> <option value="bg_color" selected>bg_color</option> <option value="secondary_bg_color">secondary_bg_color</option> <option value="custom" id="bg_color_val">custom...</option> </select> </div> <div class="sect_row">Bottom Bar: <input type="color" id="bbar_color_input" /> <select id="bbar_color_sel"> <option value="bg_color">bg_color</option> <option value="secondary_bg_color">secondary_bg_color</option> <option value="bottom_bar_bg_color" selected>bottom_bar_bg_color</option> <option value="custom" id="bbar_color_val">custom...</option> </select> </div> </section> <section> <div id="btn_status" class="hint" style="display: none;"></div> <p>Test links:</p> <ul> <li><a id="regular_link" href="?nextpage=1">Regular link #1</a> (opens inside webview)</li> <li><a href="https://telegram.org/" target="_blank">target="_blank" link</a> (opens outside webview)</li> <li><a href="javascript:window.open('https://telegram.org/');">window.open() link</a> (opens outside webview)</li> <li><a href="https://t.me/like">LikeBot t.me link</a> (opens inside Telegram app)</li> <li><a href="javascript:Telegram.WebApp.openTelegramLink('https://t.me/vote');">web_app_open_tg_link()</a> (opens inside Telegram app)</li> <li><a href="javascript:Telegram.WebApp.openLink('https://google.com/');">web_app_open_link()</a> (opens outside webview)</li> <li><a href="tg://resolve?domain=vote">VoteBot tg:// link</a> (does not open)</li> <li><a href="javascript:Telegram.WebApp.openLink('https://telegra.ph/api',{try_instant_view:true});">web_app_open_link({try_instant_view:true})</a> (opens IV inside Telegram app)</li> <li><a href="javascript:Telegram.WebApp.openTelegramLink('https://t.me/DurgerKingBot/menu');">web_app_open_tg_link(webapp_direct_link)</a> (opens with confirm for the first time, then without)</li> </ul> <ul> <li><a href="javascript:Telegram.WebApp.openLink('https://telegram.org',{try_browser:'chrome'});">telegram.org</a> (opens in Chrome)</li> <li><a href="javascript:Telegram.WebApp.openLink('https://telegram.org',{try_browser:'firefox'});">telegram.org</a> (opens in Firefox)</li> <li><a href="javascript:Telegram.WebApp.openLink('https://telegram.org',{try_browser:'safari'});">telegram.org</a> (opens in Safari)</li> <li><a href="javascript:Telegram.WebApp.openLink('https://telegram.org',{try_browser:'opera'});">telegram.org</a> (opens in Opera)</li> <li><a href="javascript:Telegram.WebApp.close({return_back:true});">Return back</a> (Android only)</li> </ul> <ul> <li><a href="javascript:Telegram.WebApp.shareToStory('https://telegra.ph/file/5583ac37c90979f052b7b.png');">Share picture to story</a></li> <li><a href="javascript:Telegram.WebApp.shareToStory('https://telegra.ph/file/5583ac37c90979f052b7b.png',{text:'Test caption'});">Share picture to story</a> (with caption)</li> <li><a href="javascript:Telegram.WebApp.shareToStory('https://telegra.ph/file/5583ac37c90979f052b7b.png',{widget_link:{url:'https://telegra.ph/Almost-done-07-23'}});">Share picture to story</a> (with link widget)</li> <li><a href="javascript:Telegram.WebApp.shareToStory('https://telegra.ph/file/61f1dac694c3131a7b4ac.mp4',{text:'Test caption',widget_link:{url:'https://telegra.ph/Almost-done-07-23',name:'Link'}});">Share video to story</a> (with caption and link widget)</li> </ul> <ul> <li><a href="javascript:DemoApp.downloadFile(this, 'https://telegra.ph/file/5583ac37c90979f052b7b.png', 'Photo.png');">Download picture</a> <span></span></li> <li><a href="javascript:DemoApp.downloadFile(this, 'https://telegra.ph/file/61f1dac694c3131a7b4ac.mp4', 'Video.mp4');">Download video</a> <span></span></li> <li><a href="javascript:DemoApp.downloadFile(this, 'https://pdfobject.com/pdf/sample.pdf', 'Sample.pdf');">Download PDF</a> <span></span></li> </ul> <ul> <li><a href="javascript:Telegram.WebApp.openTelegramLink('https://t.me/addstickers/fltmp');">Stickerpack</a></li> <li><a href="javascript:Telegram.WebApp.openTelegramLink('https://t.me/addstickers/fltmp', {force_request:true});">Stickerpack</a> (nocache)</li> </ul> <ul> <li><a href="javascript:;" onclick="return DemoApp.checkHomeScreenStatus(this);">Check Home Screen Status</a> <span></span></li> <li><a id="add_to_home_btn" href="javascript:;" onclick="return DemoApp.addToHomeScreen(this);">Add to Home Screen</a></li> </ul> <ul> <li><a href="javascript:DemoApp.setEmojiStatus(this, '5213305508034783384');">Set emoji status</a> <span></span></li> <li><a href="javascript:DemoApp.setEmojiStatus(this, '5213305508034783384', 300);">Set emoji status</a> for 5 min <span></span></li> <li><a href="javascript:DemoApp.setEmojiStatus(this, '123');">Set emoji status</a> (invalid id) <span></span></li> </ul> <p>Test permissions:</p> <div class="columns"> <ul> <li><a href="javascript:;" onclick="return DemoApp.requestLocation(this);">Request Location</a> <span></span></li> <li><a href="javascript:;" onclick="return DemoApp.requestVideo(this);">Request Video</a> <span></span></li> <li><a href="javascript:;" onclick="return DemoApp.requestAudio(this);">Request Audio</a> <span></span></li> <li><a href="javascript:;" onclick="return DemoApp.requestAudioVideo(this);">Request Audio+Video</a> <span></span></li> <li><a href="javascript:;" onclick="return DemoApp.testClipboard(this);" id="clipboard_test">Read from clipboard</a> <span></span></li> </ul> <ul> <li><a href="javascript:;" onclick="return DemoApp.requestWriteAccess(this);">Request write access</a> <span></span></li> <li><a href="javascript:;" onclick="return DemoApp.requestPhoneNumber(this);">Request phone number</a> <span></span><br><br></li> <li><a href="javascript:;" onclick="return DemoApp.requestServerTime(this);">Request server time</a> (invokes custom method) <span></span></li> </ul> </div> <p>Sensors:</p> <div class="columns"> <ul> <li><a id="accelerometer_btn" href="javascript:;" onclick="return DemoApp.toggleAccelerometer(this);">Start Accelerometer</a> <span></span></li> <li><a id="device_orientation_btn" href="javascript:;" onclick="return DemoApp.toggleDeviceOrientation(this);">Start DeviceOrientation(need_absolute=false)</a> <span></span></li> <li id="device_orientation_abs_item"><a href="javascript:;" onclick="return DemoApp.toggleDeviceOrientation(this, true);">Start DeviceOrientation(need_absolute=true)</a> <span></span></li> <li><a id="gyroscope_btn" href="javascript:;" onclick="return DemoApp.toggleGyroscope(this);">Start Gyroscope</a> <span></span></li> </ul> </div> <p>Test alerts:</p> <div class="columns"> <ul> <li><a href="javascript:;" onclick="alert('Hello!');">alert</a></li> <li><a href="javascript:;" onclick="confirm('Are you sure?');">confirm</a></li> <li><a href="javascript:;" onclick="prompt('How old are you?');">prompt</a></li> </ul> <ul> <li><a href="javascript:;" onclick="DemoApp.showAlert('Hello!');">showAlert</a></li> <li><a href="javascript:;" onclick="DemoApp.showConfirm('Are you sure?');">showConfirm</a></li> <li><a href="javascript:;" onclick="DemoApp.requestWriteAccess();">requestWriteAccess</a></li> <li><a href="javascript:;" onclick="DemoApp.requestContact();">requestContact</a></li> <li><a href="javascript:;" onclick="DemoApp.showPopup();">showPopup</a></li> <li><a href="javascript:;" onclick="DemoApp.showScanQrPopup();">showScanQrPopup</a></li> <li><a href="javascript:;" onclick="DemoApp.showScanQrPopup(true);">showScanQrPopup (links only)</a></li> </ul> </div> <p>Haptics:</p> <ul> <li>Impact: <a href="javascript:Telegram.WebApp.HapticFeedback.impactOccurred('heavy');">heavy</a>, <a href="javascript:Telegram.WebApp.HapticFeedback.impactOccurred('light');">light</a>, <a href="javascript:Telegram.WebApp.HapticFeedback.impactOccurred('medium');">medium</a>, <a href="javascript:Telegram.WebApp.HapticFeedback.impactOccurred('rigid');">rigid</a>, <a href="javascript:Telegram.WebApp.HapticFeedback.impactOccurred('soft');">soft</a><br><br></li> <li>Notification: <a href="javascript:Telegram.WebApp.HapticFeedback.notificationOccurred('error');">error</a>, <a href="javascript:Telegram.WebApp.HapticFeedback.notificationOccurred('success');">success</a>, <a href="javascript:Telegram.WebApp.HapticFeedback.notificationOccurred('warning');">warning</a><br><br></li> <li>Selection: <a href="javascript:Telegram.WebApp.HapticFeedback.selectionChanged();">changed</a><br><br></li> </ul> <p>Cloud storage:</p> <form onsubmit="DemoApp.saveCloudForm(this, event);"> <table class="table table-bordered small"> <thead> <tr> <th width="20%">Key</th> <th width="70%">Value</th> <th width="10%"></th> </tr> </thead> <tbody id="cloud_rows"></tbody> <tfoot> <tr> <td><input type="text" name="key" /></td> <td><input type="text" name="value" /></td> <td> <button type="submit">Save</button> <button type="reset">Clear</button> </td> </tr> </tfoot> </table> </form> <p>Biometrics:</p> <div class="columns"> <ul> <li>isInited: <span class="txt" id="bm_inited">false</span></li> <li>available: <span class="txt" id="bm_available">false</span></li> <li>type: <span class="txt" id="bm_type"></span></li> <li>access_requested: <span class="txt" id="bm_access_requested">false</span> (<a href="javascript:;" onclick="return DemoApp.biometricRequestAccess(this);">Request access</a>) <span></span></li> <li>access_granted: <span class="txt" id="bm_access_granted">false</span> <span id="bm_settings" style="display:none;">(<a href="javascript:;" onclick="return DemoApp.biometricOpenSettings(this);">Open settings</a>)</span></li> <li>token_saved: <span class="txt" id="bm_token_saved">false</span> (<a href="javascript:;" onclick="return DemoApp.biometricSetToken(this);">Set token</a>, <a href="javascript:;" onclick="return DemoApp.biometricRemoveToken(this);">Remove token</a>) <span></span></li> <li>device_id: <span class="txt" id="bm_device_id"></span></li> <li><a href="javascript:;" onclick="return DemoApp.biometricRequestAuth(this);">Request auth</a> <span></span></li> </ul> </div> <p>Location:</p> <div class="columns"> <ul> <li>isInited: <span class="txt" id="loc_inited">false</span></li> <li>available: <span class="txt" id="loc_available">false</span></li> <li>access_requested: <span class="txt" id="loc_access_requested">false</span> (<a href="javascript:;" onclick="return DemoApp.locationGet(this);">Request location</a>) <span></span></li> <li>access_granted: <span class="txt" id="loc_access_granted">false</span> <span id="loc_settings" style="display:none;">(<a href="javascript:;" onclick="return DemoApp.locationOpenSettings(this);">Open settings</a>)</span> </li> </ul> </div> <pre><code id="webview_data"></code></pre> <div class="hint"> Data passed to webview. <span id="webview_data_status" class="status_need">Checking hash...</span>, <span id="webview_data_sign_status">checking signature...</span> </div> <pre><code id="theme_data"></code></pre> <div class="hint"> Theme params </div> <div class="hint"> Version: <span id="ver"></span>, platform: <span id="platform"></span> </div> <div class="hint"> <span id="cur_activity"></span><span id="prev_activity"></span> </div> </section> <div class="safe-area-border"></div> <div class="tg-safe-area-border"> <div class="tg-content-safe-area-border"></div> </div> <div class="viewport-border"></div> <div class="viewport-stable_border"></div> <script type="application/javascript"> /* * This is a demo code for Telegram WebApp for Bots * It contains basic examples of how to use the API * Note: all requests to backend are disabled in this demo, you should use your own backend */ const DemoApp = { initData : Telegram.WebApp.initData || '', initDataUnsafe: Telegram.WebApp.initDataUnsafe || {}, MainButton: Telegram.WebApp.MainButton, SecondaryButton: Telegram.WebApp.SecondaryButton, BackButton: Telegram.WebApp.BackButton, SettingsButton: Telegram.WebApp.SettingsButton, init: function(options) { document.body.style.visibility = ''; Telegram.WebApp.ready(); Telegram.WebApp.MainButton.setParams({ text: 'Close Webview', has_shine_effect: true, is_visible: true }).onClick(DemoApp.close); Telegram.WebApp.SecondaryButton.setParams({ text: 'Do Something', is_visible: true }).onClick(DemoApp.moveSecondaryButton); Telegram.WebApp.BackButton.onClick(function() { DemoApp.showAlert('Back button pressed'); }); Telegram.WebApp.SettingsButton.onClick(function() { DemoApp.showAlert('Settings opened!'); }); }, expand() { Telegram.WebApp.expand(); }, close() { Telegram.WebApp.close(); }, toggleMainButton(el) { const mainButton = Telegram.WebApp.MainButton if (mainButton.isVisible) { mainButton.hide() el.innerHTML = 'Show Main Button' } else { mainButton.show() el.innerHTML = 'Hide Main Button' } }, toggleSecondaryButton(el) { if (DemoApp.SecondaryButton.isVisible) { DemoApp.SecondaryButton.hide() el.innerHTML = 'Show Secondary Button' } else { DemoApp.SecondaryButton.show(); el.innerHTML = 'Hide Secondary Button' } }, toggleButtonsProgress(el) { if (DemoApp.MainButton.isProgressVisible) { DemoApp.MainButton.hideProgress() DemoApp.SecondaryButton.hideProgress() el.innerHTML = 'Show Progress' } else { DemoApp.MainButton.showProgress() DemoApp.SecondaryButton.showProgress() el.innerHTML = 'Hide Progress' } }, moveSecondaryButton(el) { const sButton = DemoApp.SecondaryButton if (sButton.position === 'left') { sButton.position = 'top' } else if (sButton.position === 'top') { sButton.position = 'right' } else if (sButton.position === 'right') { sButton.position = 'bottom' } else if (sButton.position === 'bottom') { sButton.position = 'left' } }, toggleBackButton(el) { if (DemoApp.BackButton.isVisible) { DemoApp.BackButton.hide() el.innerHTML = 'Show Back Button' } else { DemoApp.BackButton.show() el.innerHTML = 'Hide Back Button' } }, toggleSettingsButton(el) { if (DemoApp.SettingsButton.isVisible) { DemoApp.SettingsButton.hide() el.innerHTML = 'Show Settings Button' } else { DemoApp.SettingsButton.show() el.innerHTML = 'Hide Settings Button' } }, toggleSwipeBehavior(el) { if (Telegram.WebApp.isVerticalSwipesEnabled) { Telegram.WebApp.disableVerticalSwipes() el.innerHTML = 'Enable Vertical Swypes' } else { Telegram.WebApp.enableVerticalSwipes() el.innerHTML = 'Disable Vertical Swypes' } }, toggleOrientationLock(el) { if (Telegram.WebApp.isOrientationLocked) { Telegram.WebApp.unlockOrientation() el.innerHTML = 'Lock Orientation' } else { Telegram.WebApp.lockOrientation() el.innerHTML = 'Unlock Orientation' } }, fullscreenInit() { Telegram.WebApp.onEvent('fullscreenChanged', function() { DemoApp.updateFullscreenButton() }) Telegram.WebApp.onEvent('fullscreenFailed', function(params) { DemoApp.showAlert('fullscreenFailed: ' + params.error) }) DemoApp.updateFullscreenButton() }, toggleFullscreen(el) { if (Telegram.WebApp.isFullscreen) { Telegram.WebApp.exitFullscreen() } else { Telegram.WebApp.requestFullscreen() } }, updateFullscreenButton() { const fullscreenBtn = document.getElementById('fullscreen_btn') if (Telegram.WebApp.isFullscreen) { fullscreenBtn.innerHTML = 'Exit Fullscreen' } else { fullscreenBtn.innerHTML = 'Request Fullscreen' } }, // accelerometer accelerometerInit() { Telegram.WebApp.onEvent('accelerometerStarted', function() { const span = document.getElementById('accelerometer_btn').nextElementSibling; span.textContent = ''; span.className = ''; DemoApp.updateAccelerometerLink(); }) Telegram.WebApp.onEvent('accelerometerStopped', function() { const span = document.getElementById('accelerometer_btn').nextElementSibling; span.textContent = ''; span.className = ''; DemoApp.updateAccelerometerLink(); }) Telegram.WebApp.onEvent('accelerometerChanged', function() { const span = document.getElementById('accelerometer_btn').nextElementSibling; span.textContent = '(x: ' + this.Accelerometer.x + '; y: ' + this.Accelerometer.y + '; z: ' + this.Accelerometer.z + ')'; span.className = 'ok'; }) Telegram.WebApp.onEvent('accelerometerFailed', function(params) { const span = document.getElementById('accelerometer_btn').nextElementSibling; span.textContent = '(ERR: ' + params.error + ')'; span.className = 'err'; }) DemoApp.updateAccelerometerLink() }, toggleAccelerometer: function(el) { if (Telegram.WebApp.Accelerometer.isStarted) { Telegram.WebApp.Accelerometer.stop(); } else { Telegram.WebApp.Accelerometer.start({ refresh_rate: 100 }); } }, updateAccelerometerLink() { var accelerometerBtn = document.getElementById('accelerometer_btn'); if (Telegram.WebApp.Accelerometer.isStarted) { accelerometerBtn.innerHTML = 'Stop Accelerometer'; } else { accelerometerBtn.innerHTML = 'Start Accelerometer'; } }, // device orientation deviceOrientationInit() { Telegram.WebApp.onEvent('deviceOrientationStarted', function() { var span = document.getElementById('device_orientation_btn').nextElementSibling; span.textContent = ''; span.className = ''; DemoApp.updateDeviceOrientationLink(); }) Telegram.WebApp.onEvent('deviceOrientationStopped', function() { var span = document.getElementById('device_orientation_btn').nextElementSibling; span.textContent = ''; span.className = ''; DemoApp.updateDeviceOrientationLink(); }) Telegram.WebApp.onEvent('deviceOrientationChanged', function() { var span = document.getElementById('device_orientation_btn').nextElementSibling; span.textContent = '(alpha: ' + this.DeviceOrientation.alpha + '; beta: ' + this.DeviceOrientation.beta + '; gamma: ' + this.DeviceOrientation.gamma + '; absolute: ' + (this.DeviceOrientation.absolute ? 'true' : 'false') + ')'; span.className = 'ok'; }) Telegram.WebApp.onEvent('deviceOrientationFailed', function(params) { var span = document.getElementById('device_orientation_btn').nextElementSibling; span.textContent = '(ERR: ' + params.error + ')'; span.className = 'err'; }) DemoApp.updateDeviceOrientationLink() }, toggleDeviceOrientation(el, need_absolute) { if (Telegram.WebApp.DeviceOrientation.isStarted) { Telegram.WebApp.DeviceOrientation.stop(); } else { Telegram.WebApp.DeviceOrientation.start({ refresh_rate: 100, need_absolute: need_absolute }); } }, updateDeviceOrientationLink() { var deviceOrientationBtn = document.getElementById('device_orientation_btn'); var absItem = document.getElementById('device_orientation_abs_item'); if (Telegram.WebApp.DeviceOrientation.isStarted) { deviceOrientationBtn.innerHTML = 'Stop DeviceOrientation'; absItem.style.display = 'none'; } else { deviceOrientationBtn.innerHTML = 'Start DeviceOrientation(need_absolute=false)'; absItem.style.display = 'block'; } }, // gyroscope gyroscopeInit() { Telegram.WebApp.onEvent('gyroscopeStarted', function() { var span = document.getElementById('gyroscope_btn').nextElementSibling; span.textContent = ''; span.className = ''; DemoApp.updateGyroscopeLink(); }) Telegram.WebApp.onEvent('gyroscopeStopped', function() { var span = document.getElementById('gyroscope_btn').nextElementSibling; span.textContent = ''; span.className = ''; DemoApp.updateGyroscopeLink(); }) Telegram.WebApp.onEvent('gyroscopeChanged', function() { var span = document.getElementById('gyroscope_btn').nextElementSibling; span.textContent = '(x: ' + this.Gyroscope.x + '; y: ' + this.Gyroscope.y + '; z: ' + this.Gyroscope.z + ')'; span.className = 'ok'; }) Telegram.WebApp.onEvent('gyroscopeFailed', function(params) { var span = document.getElementById('gyroscope_btn').nextElementSibling; span.textContent = '(ERR: ' + params.error + ')'; span.className = 'err'; }) DemoApp.updateGyroscopeLink() }, toggleGyroscope(el) { if (Telegram.WebApp.Gyroscope.isStarted) { Telegram.WebApp.Gyroscope.stop(); } else { Telegram.WebApp.Gyroscope.start({ refresh_rate: 100 }); } }, updateGyroscopeLink() { var gyroscopeBtn = document.getElementById('gyroscope_btn'); if (Telegram.WebApp.Gyroscope.isStarted) { gyroscopeBtn.innerHTML = 'Stop Gyroscope'; } else { gyroscopeBtn.innerHTML = 'Start Gyroscope'; } }, // location locationInit(el) { const locationManager = Telegram.WebApp.LocationManager; if (!DemoApp.locationInited) { DemoApp.locationInited = true; Telegram.WebApp.onEvent('locationManagerUpdated', function() { document.getElementById('loc_inited').textContent = locationManager.isInited ? 'true' : 'false'; document.getElementById('loc_available').textContent = locationManager.isLocationAvailable ? 'true' : 'false'; document.getElementById('loc_access_requested').textContent = locationManager.isAccessRequested ? 'true' : 'false'; document.getElementById('loc_access_granted').textContent = locationManager.isAccessGranted ? 'true' : 'false'; document.getElementById('loc_settings').style.display = (locationManager.isLocationAvailable && locationManager.isAccessRequested && !locationManager.isAccessGranted) ? 'block' : 'none'; }); } locationManager.init(); }, locationGet(el) { const locationManager = Telegram.WebApp.LocationManager; if (!locationManager.isInited) { return DemoApp.showAlert('Location not inited yet!'); } locationManager.getLocation(function(location_data) { const span = el.nextElementSibling; if (location_data) { span.textContent = '(' + JSON.stringify(location_data) + ')'; span.className = 'ok'; } else { span.textContent = '(Request declined)'; span.className = 'err'; } }) }, locationOpenSettings(el) { const locationManager = Telegram.WebApp.LocationManager; if (!locationManager.isInited) { return DemoApp.showAlert('Location not inited yet!'); } if (!locationManager.isLocationAvailable || !locationManager.isAccessRequested || locationManager.isAccessGranted) { return false; } locationManager.openSettings(); }, // version to string Example: '6.9' doesntSupport(version) { // console.log("version: " + version); // console.log("realVersion: " + this.version()); // console.log("doesntSupport: " + this.isVersionAtLeast(version)); if (!this.isVersionAtLeast(version)) { Telegram.WebApp.showAlert('This feature is not supported in this version of Telegram', function () { Telegram.WebApp.close(); }); throw new Error('This feature is not supported in this version of Telegram'); } }, // actions sendMessage(msg_id, with_webview) { if (!DemoApp.initDataUnsafe.query_id) { alert('WebViewQueryId not defined'); return; } document.querySelectorAll('button').forEach((btn) => btn.disabled = true); const btn = document.querySelector('#btn_status'); btn.textContent = 'Sending...'; DemoApp.apiRequest('sendMessage', { msg_id : msg_id || '', with_webview: !DemoApp.initDataUnsafe.receiver && with_webview ? 1 : 0 }, function (result) { document.querySelectorAll('button').forEach((btn) => btn.disabled = false); if (result.response) { if (result.response.ok) { btn.textContent = 'Message sent successfully!'; btn.className = 'ok'; btn.style.display = 'block'; } else { btn.textContent = result.response.description; btn.className = 'err'; btn.style.display = 'block'; alert(result.response.description); } } else if (result.error) { btn.textContent = result.error; btn.className = 'err'; btn.style.display = 'block'; alert(result.error); } else { btn.textContent = 'Unknown error'; btn.className = 'err'; btn.style.display = 'block'; alert('Unknown error'); } }); }, changeMenuButton(close) { document.querySelectorAll('button').forEach((btn) => btn.disabled = true); const btnStatus = document.querySelector('#btn_status'); btnStatus.textContent = 'Changing button...'; DemoApp.apiRequest('changeMenuButton', {}, function (result) { document.querySelectorAll('button').forEach((btn) => btn.disabled = false); if (result.response) { if (result.response.ok) { btnStatus.textContent = 'Button changed!'; btnStatus.className = 'ok'; btnStatus.style.display = 'block'; Telegram.WebApp.close(); } else { btnStatus.textContent = result.response.description; btnStatus.className = 'err'; btnStatus.style.display = 'block'; alert(result.response.description); } } else if (result.error) { btnStatus.textContent = result.error; btnStatus.className = 'err'; btnStatus.style.display = 'block'; alert(result.error); } else { btnStatus.textContent = 'Unknown error'; btnStatus.className = 'err'; btnStatus.style.display = 'block'; alert('Unknown error'); } }); if (close) { setTimeout(function () { Telegram.WebApp.close(); }, 50); } }, checkInitData() { const webViewStatus = document.querySelector('#webview_data_status'); if (DemoApp.initDataUnsafe.query_id && DemoApp.initData && webViewStatus.classList.contains('status_need') ) { webViewStatus.classList.remove('status_need'); DemoApp.apiRequest('checkInitData', {}, function (result) { if (result.ok) { webViewStatus.textContent = 'Hash is correct (async)'; webViewStatus.className = 'ok'; } else { webViewStatus.textContent = result.error + ' (async)'; webViewStatus.className = 'err'; } }); } }, sendText(spam) { const textField = document.querySelector('#text_field'); const text = textField.value; if (!text.length) { return textField.focus(); } if (byteLength(text) > 4096) { return alert('Text is too long'); } const repeat = spam ? 10 : 1; for (let i = 0; i < repeat; i++) { Telegram.WebApp.sendData(text); } }, sendTime(spam) { const repeat = spam ? 10 : 1; for (let i = 0; i < repeat; i++) { Telegram.WebApp.sendData(new Date().toString()); } }, switchInlineQuery(query, chooseChat) { if (chooseChat) { const chatTypes = [] const types = ['users', 'bots', 'groups', 'channels']; for (let i = 0; i < types.length; i++) { const el = document.getElementById('select-' + types[i]); if (el.checked) { chatTypes.push(types[i]); } } if (!chooseChatTypes.length) { return DemoApp.showAlert('Select chat types!'); } Telegram.WebApp.switchInlineQuery(query, chatTypes) } Telegram.WebApp.switchInlineQuery(query, false) }, // Alerts showAlert(message) { Telegram.WebApp.showAlert(message); }, showConfirm(message) { Telegram.WebApp.showConfirm(message); }, requestContact() { Telegram.WebApp.requestContact(function (result) { if (result) { DemoApp.showAlert('Contact granted'); } else { DemoApp.showAlert('Contact denied'); } }); }, isVersionAtLeast(version) { return Telegram.WebApp.isVersionAtLeast(version); }, showPopup() { Telegram.WebApp.showPopup({ title : 'Popup title', message: 'Popup message', buttons: [ {id: 'delete', type: 'destructive', text: 'Delete all'}, {id: 'faq', type: 'default', text: 'Open FAQ'}, {type: 'cancel'}, ] }, function (buttonId) { if (buttonId === 'delete') { DemoApp.showAlert("'Delete all' selected"); } else if (buttonId === 'faq') { Telegram.WebApp.openLink('https://telegram.org/faq'); } }); }, showScanQrPopup: function (linksOnly) { Telegram.WebApp.showScanQrPopup({ text: linksOnly ? 'with any link' : 'for test purposes' }, function (text) { if (linksOnly) { const lowerText = text.toString().toLowerCase(); if (lowerText.substring(0, 7) === 'http://' || lowerText.substring(0, 8) === 'https://' ) { setTimeout(function () { Telegram.WebApp.openLink(text); }, 50); return true; } } else { DemoApp.showAlert(text); return true; } }); }, // Permissions requestLocation(el) { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function (position) { el.nextElementSibling.innerHTML = '(' + position.coords.latitude + ', ' + position.coords.longitude + ')'; el.nextElementSibling.className = 'ok'; }); } else { el.nextElementSibling.innerHTML = 'Geolocation is not supported in this browser.'; el.nextElementSibling.className = 'err'; } return false; }, requestVideo(el) { if (navigator.mediaDevices) { navigator.mediaDevices.getUserMedia({audio: false, video: true}).then(function (stream) { el.nextElementSibling.innerHTML = '(Access granted)'; }); } else { el.nextElementSibling.innerHTML = 'Media devices is not supported in this browser.'; el.nextElementSibling.className = 'err'; } return false; }, requestAudio(el) { if (navigator.mediaDevices) { navigator.mediaDevices.getUserMedia({audio: true, video: false}).then(function (stream) { el.nextElementSibling.innerHTML = '(Access granted)'; el.nextElementSibling.className = 'ok'; }); } else { el.nextElementSibling.innerHTML = 'Media devices is not supported in this browser.'; el.nextElementSibling.className = 'err'; } return false; }, requestAudioVideo(el) { if (navigator.mediaDevices) { navigator.mediaDevices.getUserMedia({audio: true, video: true}).then(function (stream) { el.nextElementSibling.innerHTML = '(Access granted)'; el.nextElementSibling.className = 'ok'; }); } else { el.nextElementSibling.innerHTML = 'Media devices is not supported in this browser.'; el.nextElementSibling.className = 'err'; } return false; }, testClipboard(el) { Telegram.WebApp.readTextFromClipboard(function (clipText) { if (clipText === null) { el.nextElementSibling.innerHTML = 'Clipboard text unavailable.'; el.nextElementSibling.className = 'err'; } else { el.nextElementSibling.innerHTML = '(Read from clipboard: «' + clipText + '»)'; el.nextElementSibling.className = 'ok'; } }); return false; }, requestWriteAccess(el) { Telegram.WebApp.requestWriteAccess(function(allowed) { if (allowed) { el.nextElementSibling.innerHTML = '(Access granted)' el.nextElementSibling.className = 'ok' } else { el.nextElementSibling.innerHTML = '(User declined this request)' el.nextElementSibling.className = 'err' } }) }, requestPhoneNumber(el) { Telegram.WebApp.requestContact(function(sent, event) { if (sent) { el.nextElementSibling.innerHTML = '(Phone number sent to the bot' + (event && event.responseUnsafe && event.responseUnsafe.contact && event.responseUnsafe.contact.phone_number ? ': +' + event.responseUnsafe.contact.phone_number : '') + ')' el.nextElementSibling.className = 'ok' } else { el.nextElementSibling.innerHTML = '(User declined this request)' el.nextElementSibling.className = 'err' } }) }, requestServerTime(el) { Telegram.WebApp.invokeCustomMethod('getCurrentTime', {}, function(err, time) { if (err) { el.nextElementSibling.innerHTML = '(' + err + ')' el.nextElementSibling.className = 'err' } else { el.nextElementSibling.innerHTML = '(' + (new Date(time * 1000)).toString() + ')' el.nextElementSibling.className = 'ok' } }); }, // cloud storage cloudStorageKeys: {}, cloudStorageItems: {}, editCloudRow(el, event) { event.preventDefault(); const values = DemoApp.cloudStorageItems const key = el.closest('tr').getAttribute('data-key') el.form.reset(); el.form.key.value = key; el.form.value.value = values[key]; }, deleteCloudRow(el, event) { event.preventDefault(); const key = el.closest('tr').getAttribute('data-key') Telegram.WebApp.CloudStorage.removeItem(key, function(err, deleted) { if (err) { DemoApp.showAlert('Error: ' + err); } else { if (deleted) { const index = DemoApp.cloudStorageKeys.indexOf(key); if (index >= 0) { DemoApp.cloudStorageKeys.splice(index, 1); } delete DemoApp.cloudStorageItems[key]; } el.form.reset(); DemoApp.updateCloudRows(); } }); }, saveCloudForm(form, event) { event.preventDefault(); const key = form.key.value const value = form.value.value Telegram.WebApp.CloudStorage.setItem(key, value, function(err, saved) { if (err) { DemoApp.showAlert('Error: ' + err); } else { if (saved) { if (typeof DemoApp.cloudStorageItems[key] === 'undefined') { DemoApp.cloudStorageKeys.push(key); } DemoApp.cloudStorageItems[key] = value; } form.reset(); DemoApp.updateCloudRows(); } }); }, updateCloudRows() { let html = ''; const keys = DemoApp.cloudStorageKeys; const values = DemoApp.cloudStorageItems; for (let i = 0; i < keys.length; i++) { const key = keys[i]; html += '<tr data-key="'+cleanHTML(key)+'"><td>'+cleanHTML(key)+'</td><td>'+cleanHTML(values[key])+'</td><td><button onclick="DemoApp.editCloudRow(this, event);">Edit</button><button onclick="DemoApp.deleteCloudRow(this, event);">Delete</button></td></tr>'; } document.getElementById('cloud_rows').innerHTML = html }, loadCloudKeys(el) { Telegram.WebApp.CloudStorage.getKeys(function(err, keys) { if (err) { DemoApp.showAlert('Error: ' + err); } else { if (keys.length > 0) { Telegram.WebApp.CloudStorage.getItems(keys, function(err, values) { if (err) { DemoApp.showAlert('Error: ' + err); } else { DemoApp.cloudStorageKeys = keys; DemoApp.cloudStorageItems = {}; for (let i = 0; i < keys.length; i++) { const key = keys[i]; DemoApp.cloudStorageItems[key] = values[key]; } DemoApp.updateCloudRows(); } }); } } }); }, // biometrics biometricInit(el) { const biometricManager = Telegram.WebApp.BiometricManager; if (!DemoApp.biometricInited) { DemoApp.biometricInited = true; Telegram.WebApp.onEvent('biometricManagerUpdated', function() { document.getElementById('bm_inited').textContent = biometricManager.isInited ? 'true' : 'false' document.getElementById('bm_available').textContent = biometricManager.isBiometricAvailable ? 'true' : 'false' document.getElementById('bm_type').textContent = biometricManager.biometricType || '' document.getElementById('bm_access_requested').textContent = biometricManager.isAccessRequested ? 'true' : 'false' document.getElementById('bm_access_granted').textContent = biometricManager.isAccessGranted ? 'true' : 'false' document.getElementById('bm_token_saved').textContent = biometricManager.isBiometricTokenSaved ? 'true' : 'false' document.getElementById('bm_device_id').textContent = biometricManager.deviceId || '' document.getElementById('bm_settings').style.display = biometricManager.isBiometricAvailable && biometricManager.isAccessRequested && !biometricManager.isAccessGranted ? 'block' : 'none' }); } biometricManager.init(); }, biometricRequestAccess(el) { const biometricManager = Telegram.WebApp.BiometricManager; if (!biometricManager.isInited) { return DemoApp.showAlert('Biometric not inited yet!'); } biometricManager.requestAccess({reason: 'The bot uses biometrics for testing purposes.'}, function(access_granted) { if (access_granted) { el.nextElementSibling.innerHTML = '(Access granted)'; el.nextElementSibling.className = 'ok'; } else { el.nextElementSibling.innerHTML = '(Request declined)'; el.nextElementSibling.className = 'err'; } }); }, biometricRequestAuth(el) { const biometricManager = Telegram.WebApp.BiometricManager; if (!biometricManager.isInited) { return DemoApp.showAlert('Biometric not inited yet!'); } el.nextElementSibling.innerHTML = ''; el.nextElementSibling.classList.remove('ok', 'err') biometricManager.authenticate({reason: 'The bot requests biometrics for testing purposes.'}, function(success, token) { if (success) { el.nextElementSibling.innerHTML = '(Success, token: ' + token + ')'; el.nextElementSibling.className = 'ok'; } else { el.nextElementSibling.innerHTML = '(Failed)'; el.nextElementSibling.className = 'err'; } }); }, biometricOpenSettings(el) { const biometricManager = Telegram.WebApp.BiometricManager; if (!biometricManager.isInited) { return DemoApp.showAlert('Biometric not inited yet!'); } if (!biometricManager.isBiometricAvailable || !biometricManager.isAccessRequested || biometricManager.isAccessGranted) { return false; } biometricManager.openSettings(); }, biometricSetToken(el) { const biometricManager = Telegram.WebApp.BiometricManager; if (!biometricManager.isInited) { return DemoApp.showAlert('Biometric not inited yet!'); } const token = parseInt(Math.random().toString().substring(2)).toString(16); biometricManager.updateBiometricToken(token, function(updated) { if (updated) { document.getElementById('bm_token_saved').textContent = biometricManager.isBiometricTokenSaved ? 'true' : 'false' el.nextElementSibling.innerHTML = '(Updated: ' + token + ')' el.nextElementSibling.className = 'ok' } else { el.nextElementSibling.innerHTML = '(Failed)' el.nextElementSibling.className = 'err' } }); }, biometricRemoveToken(el) { const biometricManager = Telegram.WebApp.BiometricManager; if (!biometricManager.isInited) { return DemoApp.showAlert('Biometric not inited yet!'); } biometricManager.updateBiometricToken('', function(updated) { if (updated) { document.getElementById('bm_token_saved').textContent = biometricManager.isBiometricTokenSaved ? 'true' : 'false' el.nextElementSibling.innerHTML = '(Removed)' el.nextElementSibling.className = 'ok' } else { el.nextElementSibling.innerHTML = '(Failed)' el.nextElementSibling.className = 'err' } }); }, // home screen homeScreenInit() { Telegram.WebApp.onEvent('homeScreenAdded', function(params) { const span = document.getElementById('add_to_home_btn').nextElementSibling; span.textContent = '(added!)'; span.className = 'ok'; }) }, addToHomeScreen(el) { Telegram.WebApp.addToHomeScreen() }, checkHomeScreenStatus(el) { Telegram.WebApp.checkHomeScreenStatus(function(status) { const span = el.nextElementSibling; span.textContent = '(status: ' + status + ')'; span.className = 'ok'; }) }, // emoji status emojiStatusInit: function() { Telegram.WebApp.onEvent('emojiStatusFailed', function(params) { DemoApp.showAlert('emojiStatusFailed: ' + params.error); }) }, setEmojiStatus: function(el, custom_emoji_id, duration) { Telegram.WebApp.setEmojiStatus(custom_emoji_id, duration ? {duration: duration} : {}, function(result) { const span = el.nextElementSibling; if (result) { span.textContent = '(status set!)'; span.className = 'ok'; } else { span.textContent = '(status NOT set)'; span.className = 'err'; } }); }, requestEmojiStatusAccess: function(el) { Telegram.WebApp.requestEmojiStatusAccess(function(allowed) { const span = el.nextElementSibling; if (allowed) { span.textContent = '(Access granted)'; span.className = 'ok'; } else { span.textContent = '(User declined this request)'; span.className = 'err'; } }) }, // activity activityStartTime: new Date(), activityPrevDuration: false, activityTo: null, activityInit: function() { Telegram.WebApp.onEvent('activated', function(params) { DemoApp.activityStartTime = new Date(); DemoApp.activityUpdate(); }); Telegram.WebApp.onEvent('deactivated', function(params) { DemoApp.activityPrevDuration = new Date() - DemoApp.activityStartTime; DemoApp.activityStartTime = false; clearTimeout(DemoApp.activityTo); DemoApp.activityUpdate(); }); DemoApp.activityUpdate(); }, activityUpdate: function() { const curActivityElement = document.getElementById('cur_activity'); const prevActivityElement = document.getElementById('prev_activity'); if (Telegram.WebApp.isActive) { const nowDuration = new Date() - DemoApp.activityStartTime; curActivityElement.innerHTML = 'Mini App is active for <b>' + Math.round(nowDuration / 1000) + '</b> sec'; DemoApp.activityTo = setTimeout(DemoApp.activityUpdate, 100); } else { curActivityElement.innerHTML = 'Mini App is <b>inactive</b>'; } if (DemoApp.activityPrevDuration !== false) { const prevDuration = DemoApp.activityPrevDuration; prevActivityElement.innerHTML = ', <br>previously was active for <b>' + Math.round(prevDuration / 1000) + '</b> sec'; } }, // Other apiRequest(method, data, onCallback) { // DISABLE BACKEND FOR FRONTEND DEMO // YOU CAN USE YOUR OWN REQUESTS TO YOUR OWN BACKEND // CHANGE THIS CODE TO YOUR OWN return onCallback && onCallback({error: 'This function (' + method + ') should send requests to your backend. Please, change this code to your own.'}); const authData = DemoApp.initData || ''; fetch('/demo/api', { method : 'POST', body : JSON.stringify(Object.assign(data, { _auth : authData, method: method, })), credentials: 'include', headers : { 'Content-Type': 'application/json' } }).then(function (response) { return response.json(); }).then(function (result) { onCallback && onCallback(result); }).catch(function (error) { onCallback && onCallback({error: 'Server error'}); }); }, downloadFile: function(el, url, file_name) { Telegram.WebApp.downloadFile({url: url, file_name: file_name}, function(result) { const span = el.nextElementSibling; if (result) { span.textContent = '(downloading...)'; span.className = 'ok'; } else { span.textContent = '(declined)'; span.className = 'err'; } }); }, } const DemoAppMenu = { init() { DemoApp.init(); document.body.classList.add('gray'); Telegram.WebApp.setHeaderColor('secondary_bg_color'); } }; const DemoAppInitData = { init() { DemoApp.init(); Telegram.WebApp.onEvent('themeChanged', function () { document.getElementById('theme_data').innerHTML = JSON.stringify(Telegram.WebApp.themeParams, null, 2); }); document.getElementById('webview_data').innerHTML = JSON.stringify(DemoApp.initDataUnsafe, null, 2); document.getElementById('theme_data').innerHTML = JSON.stringify(Telegram.WebApp.themeParams, null, 2); DemoApp.checkInitData(); } }; const DemoAppViewport = { init() { DemoApp.init(); Telegram.WebApp.onEvent('viewportChanged', DemoAppViewport.setData); DemoAppViewport.setData(); }, setData() { document.querySelector('.viewport-border').setAttribute('text', window.innerWidth + ' x ' + round(Telegram.WebApp.viewportHeight, 2)) document.querySelector('.viewport-stable_border').setAttribute('text', window.innerWidth + ' x ' + round(Telegram.WebApp.viewportStableHeight, 2) + ' | is_expanded: ' + (Telegram.WebApp.isExpanded ? 'true' : 'false')); } } function cleanHTML(value) { return value .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/\n/g, '<br/>') } function byteLength(str) { if (window.Blob) { try { return new Blob([str]).size; } catch (e) { } } let s = str.length; for (let i = str.length - 1; i >= 0; i--) { const code = str.charCodeAt(i); if (code > 0x7f && code <= 0x7ff) { s++; } else if (code > 0x7ff && code <= 0xffff) { s += 2; } if (code >= 0xDC00 && code <= 0xDFFF) { i--; } } return s; } function round(val, d) { const k = Math.pow(10, d || 0); return Math.round(val * k) / k; } </script> <script type="application/javascript"> /* * This part of code is used to initialize the demo app and set up the event handlers we need. */ Telegram.WebApp.onEvent('themeChanged', function () { document.getElementById('theme_data').innerHTML = JSON.stringify(Telegram.WebApp.themeParams, null, 2); }); if (DemoApp.initDataUnsafe.query_id) { document.getElementById('main_btn').style.display = 'block'; } document.getElementById('with_webview_btn').style.display = !!DemoApp.initDataUnsafe.query_id && !DemoApp.initDataUnsafe.receiver ? 'block' : 'none'; document.getElementById('webview_data').innerHTML = JSON.stringify(DemoApp.initDataUnsafe, null, 2); document.getElementById('theme_data').innerHTML = JSON.stringify(Telegram.WebApp.themeParams, null, 2); document.getElementById('regular_link').setAttribute('href', document.getElementById('regular_link').getAttribute('href') + location.hash); document.getElementById('text_field').focus(); document.getElementById('regular_field').addEventListener('input', function (e) { const val = this.value.toLowerCase(); if (val.indexOf('progress') >= 0) { Telegram.WebApp.MainButton.showProgress(); } else { Telegram.WebApp.MainButton.hideProgress(); } }); document.getElementById('ver').innerHTML = Telegram.WebApp.version; document.getElementById('platform').innerHTML = Telegram.WebApp.platform; if (DemoApp.initDataUnsafe.receiver) { document.getElementById('peer_wrap').style.display = 'block'; document.getElementById('peer_name').innerHTML = DemoApp.initDataUnsafe.receiver.first_name + ' ' + DemoApp.initDataUnsafe.receiver.last_name; if (DemoApp.initDataUnsafe.receiver.photo_url) { document.getElementById('peer_photo').setAttribute('src', DemoApp.initDataUnsafe.receiver.photo_url); } else { document.getElementById('peer_photo').style.display = 'none'; } } else if (DemoApp.initDataUnsafe.chat) { document.getElementById('peer_wrap').style.display = 'block'; document.getElementById('peer_name').innerHTML = DemoApp.initDataUnsafe.chat.title; if (DemoApp.initDataUnsafe.chat.photo_url) { document.getElementById('peer_photo').setAttribute('src', DemoApp.initDataUnsafe.chat.photo_url); } else { document.getElementById('peer_photo').style.display = 'none'; } } DemoApp.checkInitData(); DemoApp.init(); function setViewportData() { document.querySelector('.viewport-border').setAttribute('text', window.innerWidth + ' x ' + round(Telegram.WebApp.viewportHeight, 2)) document.querySelector('.viewport-stable_border').setAttribute('text', window.innerWidth + ' x ' + round(Telegram.WebApp.viewportStableHeight, 2) + ' | is_expanded: ' + (Telegram.WebApp.isExpanded ? 'true' : 'false')); } Telegram.WebApp.setHeaderColor('secondary_bg_color'); Telegram.WebApp.onEvent('viewportChanged', setViewportData); setViewportData(); // bg color picker const bgColorSel = document.getElementById('bg_color_sel') const bgColorInput = document.getElementById('bg_color_input') let prevBgColorValue = bgColorSel.value bgColorInput.value = Telegram.WebApp.backgroundColor document.body.style.setProperty('--bg-color', Telegram.WebApp.backgroundColor) bgColorInput.addEventListener('change', function(e) { const color = e.target.value; document.getElementById('bg_color_val').textContent = color; bgColorSel.value = 'custom'; prevBgColorValue = bgColorSel.value; Telegram.WebApp.setBackgroundColor(color); document.body.style.setProperty('--bg-color', Telegram.WebApp.backgroundColor); }) bgColorSel.addEventListener('change', function(e) { const color = e.target.value; if (color === 'custom') { bgColorSel.value = prevBgColorValue; const input = bgColorInput; input.focus(); input.click(); } else { document.getElementById('bg_color_val').textContent = 'custom...'; Telegram.WebApp.setBackgroundColor(color); document.body.style.setProperty('--bg-color', Telegram.WebApp.backgroundColor); bgColorInput.value = Telegram.WebApp.backgroundColor; prevBgColorValue = bgColorSel.value; } }) // header color picker const headerColorSel = document.getElementById('header_color_sel') const headerColorInput = document.getElementById('header_color_input') let prevHeaderColorValue = headerColorSel.value headerColorInput.value = Telegram.WebApp.headerColor document.body.style.setProperty('--header-color', Telegram.WebApp.headerColor) headerColorSel.value = 'secondary_bg_color' headerColorInput.addEventListener('change', function(e) { const color = e.target.value; document.getElementById('header_color_val').textContent = color; headerColorSel.value = 'custom'; prevHeaderColorValue = headerColorSel.value; Telegram.WebApp.setHeaderColor(color); document.body.style.setProperty('--header-color', Telegram.WebApp.headerColor); }) headerColorSel.addEventListener('change', function(e) { const color = e.target.value; if (color === 'custom') { headerColorSel.value = prevHeaderColorValue; const input = headerColorInput; input.focus(); input.click(); } else { document.getElementById('header_color_val').textContent = 'custom...'; Telegram.WebApp.setHeaderColor(color); document.getElementById('top_sect').classList.toggle('second', color === 'secondary_bg_color'); document.body.style.setProperty('--header-color', Telegram.WebApp.headerColor); headerColorInput.value = Telegram.WebApp.headerColor; prevHeaderColorValue = headerColorSel.value; } }) // bottom bar color picker const bbarColorSel = document.getElementById('bbar_color_sel') const bbarColorInput = document.getElementById('bbar_color_input') let prevBbarColorValue = bbarColorSel.value; bbarColorInput.value = Telegram.WebApp.bottomBarColor; document.body.style.setProperty('--bottom-bar-color', Telegram.WebApp.bottomBarColor); bbarColorInput.addEventListener('change', function(e) { const color = e.target.value; document.getElementById('bbar_color_val').textContent = color; bbarColorSel.value = 'custom'; prevBbarColorValue = bbarColorSel.value; Telegram.WebApp.setBottomBarColor(color); document.body.style.setProperty('--bottom-bar-color', Telegram.WebApp.bottomBarColor); }) bbarColorSel.addEventListener('change', function(e) { const color = e.target.value; if (color === 'custom') { bbarColorSel.value = prevBbarColorValue; const input = bbarColorInput; input.focus(); input.click(); } else { document.getElementById('bbar_color_val').textContent = 'custom...'; Telegram.WebApp.setBottomBarColor(color); document.body.style.setProperty('--bottom-bar-color', Telegram.WebApp.bottomBarColor); bbarColorInput.value = Telegram.WebApp.bottomBarColor; prevBbarColorValue = bbarColorSel.value; } }) // theme Telegram.WebApp.onEvent('themeChanged', function () { bgColorInput.value = Telegram.WebApp.backgroundColor document.body.setAttribute('style', '--bg-color:' + Telegram.WebApp.backgroundColor) }) const orientBtn = document.getElementById('orient_btn') if (Telegram.WebApp.isOrientationLocked) { orientBtn.innerHTML = 'Unlock Orientation' } else { orientBtn.innerHTML = 'Lock Orientation' } // permissions try { DemoApp.testClipboard(document.getElementById('clipboard_test')); } catch(e) {} try { DemoApp.loadCloudKeys(); } catch(e) {} try { DemoApp.biometricInit(); } catch(e) {} try { DemoApp.fullscreenInit(); } catch(e) {} try { DemoApp.accelerometerInit(); } catch(e) {} try { DemoApp.deviceOrientationInit(); } catch(e) {} try { DemoApp.gyroscopeInit(); } catch(e) {} try { DemoApp.locationInit(); } catch(e) {} try { DemoApp.homeScreenInit(); } catch(e) {} try { DemoApp.emojiStatusInit(); } catch(e) {} try { DemoApp.activityInit(); } catch(e) {} </script> </body> </html>