2022-04-13 17:11:59 +02:00
// WebView
2022-04-07 08:19:13 +02:00
( function ( ) {
var eventHandlers = { } ;
var locationHash = '' ;
try {
locationHash = location . hash . toString ( ) ;
} catch ( e ) { }
var initParams = urlParseHashParams ( locationHash ) ;
2022-06-03 15:46:09 +02:00
var storedParams = sessionStorageGet ( 'initParams' ) ;
if ( storedParams ) {
for ( var key in storedParams ) {
if ( typeof initParams [ key ] === 'undefined' ) {
initParams [ key ] = storedParams [ key ] ;
}
}
}
sessionStorageSet ( 'initParams' , initParams ) ;
2022-04-07 08:19:13 +02:00
2022-04-21 17:35:07 +02:00
var isIframe = false , iFrameStyle ;
2022-04-07 08:19:13 +02:00
try {
isIframe = ( window . parent != null && window != window . parent ) ;
if ( isIframe ) {
window . addEventListener ( 'message' , function ( event ) {
if ( event . source !== window . parent ) return ;
try {
var dataParsed = JSON . parse ( event . data ) ;
} catch ( e ) {
return ;
}
if ( ! dataParsed || ! dataParsed . eventType ) {
return ;
}
2022-04-21 17:35:07 +02:00
if ( dataParsed . eventType == 'set_custom_style' ) {
iFrameStyle . innerHTML = dataParsed . eventData ;
} else {
receiveEvent ( dataParsed . eventType , dataParsed . eventData ) ;
}
2022-04-07 08:19:13 +02:00
} ) ;
2022-04-21 17:35:07 +02:00
iFrameStyle = document . createElement ( 'style' ) ;
document . head . appendChild ( iFrameStyle ) ;
try {
window . parent . postMessage ( JSON . stringify ( { eventType : 'iframe_ready' } ) , '*' ) ;
} catch ( e ) { }
2022-04-07 08:19:13 +02:00
}
} catch ( e ) { }
function urlSafeDecode ( urlencoded ) {
try {
urlencoded = urlencoded . replace ( /\+/g , '%20' ) ;
return decodeURIComponent ( urlencoded ) ;
} catch ( e ) {
return urlencoded ;
}
}
function urlParseHashParams ( locationHash ) {
locationHash = locationHash . replace ( /^#/ , '' ) ;
var params = { } ;
if ( ! locationHash . length ) {
return params ;
}
if ( locationHash . indexOf ( '=' ) < 0 && locationHash . indexOf ( '?' ) < 0 ) {
params . _path = urlSafeDecode ( locationHash ) ;
return params ;
}
var qIndex = locationHash . indexOf ( '?' ) ;
if ( qIndex >= 0 ) {
var pathParam = locationHash . substr ( 0 , qIndex ) ;
params . _path = urlSafeDecode ( pathParam ) ;
locationHash = locationHash . substr ( qIndex + 1 ) ;
}
2022-04-13 17:11:59 +02:00
var query _params = urlParseQueryString ( locationHash ) ;
for ( var k in query _params ) {
params [ k ] = query _params [ k ] ;
}
return params ;
}
function urlParseQueryString ( queryString ) {
var params = { } ;
if ( ! queryString . length ) {
return params ;
}
var queryStringParams = queryString . split ( '&' ) ;
2022-04-07 08:19:13 +02:00
var i , param , paramName , paramValue ;
2022-04-13 17:11:59 +02:00
for ( i = 0 ; i < queryStringParams . length ; i ++ ) {
param = queryStringParams [ i ] . split ( '=' ) ;
2022-04-07 08:19:13 +02:00
paramName = urlSafeDecode ( param [ 0 ] ) ;
paramValue = param [ 1 ] == null ? null : urlSafeDecode ( param [ 1 ] ) ;
params [ paramName ] = paramValue ;
}
return params ;
}
// Telegram apps will implement this logic to add service params (e.g. tgShareScoreUrl) to game URL
function urlAppendHashParams ( url , addHash ) {
// url looks like 'https://game.com/path?query=1#hash'
// addHash looks like 'tgShareScoreUrl=' + encodeURIComponent('tgb://share_game_score?hash=telegram-crawler_long_hash123')
var ind = url . indexOf ( '#' ) ;
if ( ind < 0 ) {
// https://game.com/path -> https://game.com/path#tgShareScoreUrl=etc
return url + '#' + addHash ;
}
var curHash = url . substr ( ind + 1 ) ;
if ( curHash . indexOf ( '=' ) >= 0 || curHash . indexOf ( '?' ) >= 0 ) {
// https://game.com/#hash=1 -> https://game.com/#hash=1&tgShareScoreUrl=etc
// https://game.com/#path?query -> https://game.com/#path?query&tgShareScoreUrl=etc
return url + '&' + addHash ;
}
// https://game.com/#hash -> https://game.com/#hash?tgShareScoreUrl=etc
if ( curHash . length > 0 ) {
return url + '?' + addHash ;
}
// https://game.com/# -> https://game.com/#tgShareScoreUrl=etc
return url + addHash ;
}
function postEvent ( eventType , callback , eventData ) {
if ( ! callback ) {
callback = function ( ) { } ;
}
if ( eventData === undefined ) {
eventData = '' ;
}
2023-08-26 15:42:46 +02:00
console . log ( '[Telegram.WebView] > postEvent' , eventType , eventData ) ;
2022-04-07 08:19:13 +02:00
if ( window . TelegramWebviewProxy !== undefined ) {
TelegramWebviewProxy . postEvent ( eventType , JSON . stringify ( eventData ) ) ;
callback ( ) ;
}
else if ( window . external && 'notify' in window . external ) {
window . external . notify ( JSON . stringify ( { eventType : eventType , eventData : eventData } ) ) ;
callback ( ) ;
}
else if ( isIframe ) {
try {
var trustedTarget = 'https://web.telegram.org' ;
// For now we don't restrict target, for testing purposes
trustedTarget = '*' ;
window . parent . postMessage ( JSON . stringify ( { eventType : eventType , eventData : eventData } ) , trustedTarget ) ;
callback ( ) ;
} catch ( e ) {
callback ( e ) ;
}
}
else {
callback ( { notAvailable : true } ) ;
}
} ;
function receiveEvent ( eventType , eventData ) {
2023-08-26 15:42:46 +02:00
console . log ( '[Telegram.WebView] < receiveEvent' , eventType , eventData ) ;
2022-04-11 03:58:11 +02:00
callEventCallbacks ( eventType , function ( callback ) {
callback ( eventType , eventData ) ;
} ) ;
}
function callEventCallbacks ( eventType , func ) {
2022-04-07 08:19:13 +02:00
var curEventHandlers = eventHandlers [ eventType ] ;
if ( curEventHandlers === undefined ||
! curEventHandlers . length ) {
return ;
}
for ( var i = 0 ; i < curEventHandlers . length ; i ++ ) {
try {
2022-04-11 03:58:11 +02:00
func ( curEventHandlers [ i ] ) ;
2022-04-07 08:19:13 +02:00
} catch ( e ) { }
}
}
function onEvent ( eventType , callback ) {
if ( eventHandlers [ eventType ] === undefined ) {
eventHandlers [ eventType ] = [ ] ;
}
var index = eventHandlers [ eventType ] . indexOf ( callback ) ;
if ( index === - 1 ) {
eventHandlers [ eventType ] . push ( callback ) ;
}
} ;
function offEvent ( eventType , callback ) {
if ( eventHandlers [ eventType ] === undefined ) {
return ;
}
var index = eventHandlers [ eventType ] . indexOf ( callback ) ;
if ( index === - 1 ) {
return ;
}
eventHandlers [ eventType ] . splice ( index , 1 ) ;
} ;
2022-04-13 17:11:59 +02:00
function openProtoUrl ( url ) {
if ( ! url . match ( /^(web\+)?tgb?:\/\/./ ) ) {
return false ;
}
var useIframe = navigator . userAgent . match ( /iOS|iPhone OS|iPhone|iPod|iPad/i ) ? true : false ;
if ( useIframe ) {
var iframeContEl = document . getElementById ( 'tgme_frame_cont' ) || document . body ;
var iframeEl = document . createElement ( 'iframe' ) ;
iframeContEl . appendChild ( iframeEl ) ;
var pageHidden = false ;
var enableHidden = function ( ) {
pageHidden = true ;
} ;
window . addEventListener ( 'pagehide' , enableHidden , false ) ;
window . addEventListener ( 'blur' , enableHidden , false ) ;
if ( iframeEl !== null ) {
iframeEl . src = url ;
}
setTimeout ( function ( ) {
if ( ! pageHidden ) {
window . location = url ;
}
window . removeEventListener ( 'pagehide' , enableHidden , false ) ;
window . removeEventListener ( 'blur' , enableHidden , false ) ;
} , 2000 ) ;
}
else {
window . location = url ;
}
return true ;
}
2022-06-03 15:46:09 +02:00
function sessionStorageSet ( key , value ) {
try {
window . sessionStorage . setItem ( '__telegram__' + key , JSON . stringify ( value ) ) ;
return true ;
} catch ( e ) { }
return false ;
}
function sessionStorageGet ( key ) {
try {
return JSON . parse ( window . sessionStorage . getItem ( '__telegram__' + key ) ) ;
} catch ( e ) { }
return null ;
}
2022-04-13 17:11:59 +02:00
if ( ! window . Telegram ) {
window . Telegram = { } ;
}
window . Telegram . WebView = {
initParams : initParams ,
2022-04-26 17:42:18 +02:00
isIframe : isIframe ,
2022-04-13 17:11:59 +02:00
onEvent : onEvent ,
offEvent : offEvent ,
postEvent : postEvent ,
receiveEvent : receiveEvent ,
callEventCallbacks : callEventCallbacks
} ;
window . Telegram . Utils = {
urlSafeDecode : urlSafeDecode ,
urlParseQueryString : urlParseQueryString ,
urlParseHashParams : urlParseHashParams ,
2022-06-03 15:46:09 +02:00
urlAppendHashParams : urlAppendHashParams ,
sessionStorageSet : sessionStorageSet ,
sessionStorageGet : sessionStorageGet
2022-04-13 17:11:59 +02:00
} ;
// For Windows Phone app
window . TelegramGameProxy _receiveEvent = receiveEvent ;
// App backward compatibility
window . TelegramGameProxy = {
receiveEvent : receiveEvent
} ;
} ) ( ) ;
// WebApp
( function ( ) {
var Utils = window . Telegram . Utils ;
var WebView = window . Telegram . WebView ;
var initParams = WebView . initParams ;
2022-04-26 17:42:18 +02:00
var isIframe = WebView . isIframe ;
2022-04-13 17:11:59 +02:00
var WebApp = { } ;
var webAppInitData = '' , webAppInitDataUnsafe = { } ;
var themeParams = { } , colorScheme = 'light' ;
2022-05-13 20:59:19 +02:00
var webAppVersion = '6.0' ;
2022-08-24 16:31:30 +02:00
var webAppPlatform = 'unknown' ;
2022-04-13 17:11:59 +02:00
if ( initParams . tgWebAppData && initParams . tgWebAppData . length ) {
webAppInitData = initParams . tgWebAppData ;
webAppInitDataUnsafe = Utils . urlParseQueryString ( webAppInitData ) ;
for ( var key in webAppInitDataUnsafe ) {
var val = webAppInitDataUnsafe [ key ] ;
try {
if ( val . substr ( 0 , 1 ) == '{' && val . substr ( - 1 ) == '}' ||
val . substr ( 0 , 1 ) == '[' && val . substr ( - 1 ) == ']' ) {
webAppInitDataUnsafe [ key ] = JSON . parse ( val ) ;
}
} catch ( e ) { }
}
}
if ( initParams . tgWebAppThemeParams && initParams . tgWebAppThemeParams . length ) {
var themeParamsRaw = initParams . tgWebAppThemeParams ;
try {
var theme _params = JSON . parse ( themeParamsRaw ) ;
2022-06-03 15:46:09 +02:00
if ( theme _params ) {
setThemeParams ( theme _params ) ;
}
2022-04-13 17:11:59 +02:00
} catch ( e ) { }
}
2022-06-03 15:46:09 +02:00
var theme _params = Utils . sessionStorageGet ( 'themeParams' ) ;
if ( theme _params ) {
setThemeParams ( theme _params ) ;
}
2022-04-26 17:42:18 +02:00
if ( initParams . tgWebAppVersion ) {
webAppVersion = initParams . tgWebAppVersion ;
}
2022-08-24 16:31:30 +02:00
if ( initParams . tgWebAppPlatform ) {
webAppPlatform = initParams . tgWebAppPlatform ;
}
2022-04-13 17:11:59 +02:00
function onThemeChanged ( eventType , eventData ) {
if ( eventData . theme _params ) {
setThemeParams ( eventData . theme _params ) ;
2022-06-14 21:45:40 +02:00
window . Telegram . WebApp . MainButton . setParams ( { } ) ;
updateBackgroundColor ( ) ;
2022-04-13 17:11:59 +02:00
receiveWebViewEvent ( 'themeChanged' ) ;
}
}
var lastWindowHeight = window . innerHeight ;
function onViewportChanged ( eventType , eventData ) {
if ( eventData . height ) {
window . removeEventListener ( 'resize' , onWindowResize ) ;
setViewportHeight ( eventData ) ;
}
}
function onWindowResize ( e ) {
if ( lastWindowHeight != window . innerHeight ) {
lastWindowHeight = window . innerHeight ;
receiveWebViewEvent ( 'viewportChanged' , {
isStateStable : true
} ) ;
}
}
2022-04-26 17:42:18 +02:00
function linkHandler ( e ) {
if ( e . metaKey || e . ctrlKey ) return ;
var el = e . target ;
while ( el . tagName != 'A' && el . parentNode ) {
el = el . parentNode ;
}
if ( el . tagName == 'A' &&
el . target != '_blank' &&
( el . protocol == 'http:' || el . protocol == 'https:' ) &&
el . hostname == 't.me' ) {
WebApp . openTgLink ( el . href ) ;
2022-04-26 18:20:22 +02:00
e . preventDefault ( ) ;
2022-04-26 17:42:18 +02:00
}
}
2022-07-01 17:16:45 +02:00
function strTrim ( str ) {
return str . toString ( ) . replace ( /^\s+|\s+$/g , '' ) ;
}
2022-04-11 03:58:11 +02:00
function receiveWebViewEvent ( eventType ) {
var args = Array . prototype . slice . call ( arguments ) ;
eventType = args . shift ( ) ;
2022-04-13 17:11:59 +02:00
WebView . callEventCallbacks ( 'webview:' + eventType , function ( callback ) {
callback . apply ( WebApp , args ) ;
2022-04-11 03:58:11 +02:00
} ) ;
}
function onWebViewEvent ( eventType , callback ) {
2022-04-13 17:11:59 +02:00
WebView . onEvent ( 'webview:' + eventType , callback ) ;
2022-04-11 03:58:11 +02:00
} ;
function offWebViewEvent ( eventType , callback ) {
2022-04-13 17:11:59 +02:00
WebView . offEvent ( 'webview:' + eventType , callback ) ;
2022-04-11 03:58:11 +02:00
} ;
2022-04-09 14:27:34 +02:00
function setCssProperty ( name , value ) {
var root = document . documentElement ;
if ( root && root . style && root . style . setProperty ) {
root . style . setProperty ( '--tg-' + name , value ) ;
}
}
2022-04-07 08:19:13 +02:00
function setThemeParams ( theme _params ) {
2022-06-16 17:00:05 +02:00
// temp iOS fix
if ( theme _params . bg _color == '#1c1c1d' &&
theme _params . bg _color == theme _params . secondary _bg _color ) {
theme _params . secondary _bg _color = '#2c2c2e' ;
}
2022-04-09 14:27:34 +02:00
var color ;
for ( var key in theme _params ) {
if ( color = parseColorToHex ( theme _params [ key ] ) ) {
themeParams [ key ] = color ;
if ( key == 'bg_color' ) {
2022-04-09 23:57:53 +02:00
colorScheme = isColorDark ( color ) ? 'dark' : 'light'
setCssProperty ( 'color-scheme' , colorScheme ) ;
2022-04-07 08:19:13 +02:00
}
2022-04-09 14:27:34 +02:00
key = 'theme-' + key . split ( '_' ) . join ( '-' ) ;
setCssProperty ( key , color ) ;
2022-04-07 08:19:13 +02:00
}
}
2022-06-03 15:46:09 +02:00
Utils . sessionStorageSet ( 'themeParams' , themeParams ) ;
2022-04-07 08:19:13 +02:00
}
2023-08-25 14:44:38 +02:00
var webAppCallbacks = { } ;
function generateCallbackId ( len ) {
var tries = 100 ;
while ( -- tries ) {
var id = '' , chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' , chars _len = chars . length ;
for ( var i = 0 ; i < len ; i ++ ) {
id += chars [ Math . floor ( Math . random ( ) * chars _len ) ] ;
}
if ( ! webAppCallbacks [ id ] ) {
webAppCallbacks [ id ] = { } ;
return id ;
}
2022-12-13 15:46:38 +01:00
}
2023-08-25 14:44:38 +02:00
throw Error ( 'WebAppCallbackIdGenerateFailed' ) ;
2022-12-13 15:46:38 +01:00
}
2022-04-11 03:58:11 +02:00
var viewportHeight = false , viewportStableHeight = false , isExpanded = true ;
function setViewportHeight ( data ) {
if ( typeof data !== 'undefined' ) {
isExpanded = ! ! data . is _expanded ;
viewportHeight = data . height ;
if ( data . is _state _stable ) {
viewportStableHeight = data . height ;
}
receiveWebViewEvent ( 'viewportChanged' , {
isStateStable : ! ! data . is _state _stable
} ) ;
2022-04-09 14:27:34 +02:00
}
2022-04-11 03:58:11 +02:00
var height , stable _height ;
2022-04-09 14:27:34 +02:00
if ( viewportHeight !== false ) {
2022-04-11 03:58:11 +02:00
height = ( viewportHeight - mainButtonHeight ) + 'px' ;
2022-04-09 14:27:34 +02:00
} else {
2022-04-11 03:58:11 +02:00
height = mainButtonHeight ? 'calc(100vh - ' + mainButtonHeight + 'px)' : '100vh' ;
2022-04-09 14:27:34 +02:00
}
2022-04-11 03:58:11 +02:00
if ( viewportStableHeight !== false ) {
stable _height = ( viewportStableHeight - mainButtonHeight ) + 'px' ;
} else {
stable _height = mainButtonHeight ? 'calc(100vh - ' + mainButtonHeight + 'px)' : '100vh' ;
}
setCssProperty ( 'viewport-height' , height ) ;
setCssProperty ( 'viewport-stable-height' , stable _height ) ;
2022-04-09 14:27:34 +02:00
}
2022-07-29 11:39:25 +02:00
var isClosingConfirmationEnabled = false ;
2022-07-01 17:16:45 +02:00
function setClosingConfirmation ( need _confirmation ) {
if ( ! versionAtLeast ( '6.2' ) ) {
2022-07-29 11:39:25 +02:00
console . warn ( '[Telegram.WebApp] Closing confirmation is not supported in version ' + webAppVersion ) ;
2022-07-01 17:16:45 +02:00
return ;
}
2022-07-29 11:39:25 +02:00
isClosingConfirmationEnabled = ! ! need _confirmation ;
WebView . postEvent ( 'web_app_setup_closing_behavior' , false , { need _confirmation : isClosingConfirmationEnabled } ) ;
2022-07-01 17:16:45 +02:00
}
2022-05-31 18:08:03 +02:00
var headerColorKey = 'bg_color' ;
2022-06-14 21:45:40 +02:00
function getHeaderColor ( ) {
return themeParams [ headerColorKey ] || null ;
}
2022-05-31 18:08:03 +02:00
function setHeaderColor ( color ) {
if ( ! versionAtLeast ( '6.1' ) ) {
console . warn ( '[Telegram.WebApp] Header color is not supported in version ' + webAppVersion ) ;
return ;
}
var color _key ;
if ( color == 'bg_color' || color == 'secondary_bg_color' ) {
color _key = color ;
} else {
color _key = parseColorToHex ( color ) ;
if ( themeParams . bg _color &&
themeParams . bg _color == color _key ) {
color _key = 'bg_color' ;
} else if ( themeParams . secondary _bg _color &&
themeParams . secondary _bg _color == color _key ) {
color _key = 'secondary_bg_color' ;
} else {
color _key = false ;
}
}
2022-05-26 23:00:05 +02:00
if ( color _key != 'bg_color' &&
color _key != 'secondary_bg_color' ) {
2022-05-31 18:08:03 +02:00
console . error ( '[Telegram.WebApp] Header color key should be one of Telegram.WebApp.themeParams.bg_color, Telegram.WebApp.themeParams.secondary_bg_color, \'bg_color\', \'secondary_bg_color\'' , color ) ;
2022-05-26 23:00:05 +02:00
throw Error ( 'WebAppHeaderColorKeyInvalid' ) ;
}
2022-05-31 18:08:03 +02:00
headerColorKey = color _key ;
2022-05-26 23:00:05 +02:00
WebView . postEvent ( 'web_app_set_header_color' , false , { color _key : color _key } ) ;
2022-06-14 21:45:40 +02:00
}
2022-05-26 23:00:05 +02:00
2022-06-14 21:45:40 +02:00
var backgroundColor = 'bg_color' ;
function getBackgroundColor ( ) {
if ( backgroundColor == 'secondary_bg_color' ) {
return themeParams . secondary _bg _color ;
} else if ( backgroundColor == 'bg_color' ) {
return themeParams . bg _color ;
}
return backgroundColor ;
}
2022-05-26 23:00:05 +02:00
function setBackgroundColor ( color ) {
2022-05-31 18:08:03 +02:00
if ( ! versionAtLeast ( '6.1' ) ) {
console . warn ( '[Telegram.WebApp] Background color is not supported in version ' + webAppVersion ) ;
return ;
}
2022-06-14 21:45:40 +02:00
var bg _color ;
if ( color == 'bg_color' || color == 'secondary_bg_color' ) {
bg _color = color ;
} else {
bg _color = parseColorToHex ( color ) ;
if ( ! bg _color ) {
console . error ( '[Telegram.WebApp] Background color format is invalid' , color ) ;
throw Error ( 'WebAppBackgroundColorInvalid' ) ;
}
2022-05-26 23:00:05 +02:00
}
2022-06-14 21:45:40 +02:00
backgroundColor = bg _color ;
updateBackgroundColor ( ) ;
}
var appBackgroundColor = null ;
function updateBackgroundColor ( ) {
var color = getBackgroundColor ( ) ;
if ( appBackgroundColor != color ) {
appBackgroundColor = color ;
WebView . postEvent ( 'web_app_set_background_color' , false , { color : color } ) ;
}
}
2022-05-26 23:00:05 +02:00
2022-04-09 14:27:34 +02:00
2022-04-07 08:19:13 +02:00
function parseColorToHex ( color ) {
color += '' ;
var match ;
2022-05-24 14:50:44 +02:00
if ( match = /^\s*#([0-9a-f]{6})\s*$/i . exec ( color ) ) {
return '#' + match [ 1 ] . toLowerCase ( ) ;
2022-04-07 08:19:13 +02:00
}
2022-05-24 14:50:44 +02:00
else if ( match = /^\s*#([0-9a-f])([0-9a-f])([0-9a-f])\s*$/i . exec ( color ) ) {
2022-04-07 08:19:13 +02:00
return ( '#' + match [ 1 ] + match [ 1 ] + match [ 2 ] + match [ 2 ] + match [ 3 ] + match [ 3 ] ) . toLowerCase ( ) ;
}
2022-05-24 14:50:44 +02:00
else if ( match = /^\s*rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)\s*$/ . exec ( color ) ) {
var r = parseInt ( match [ 1 ] ) , g = parseInt ( match [ 2 ] ) , b = parseInt ( match [ 3 ] ) ;
r = ( r < 16 ? '0' : '' ) + r . toString ( 16 ) ;
g = ( g < 16 ? '0' : '' ) + g . toString ( 16 ) ;
b = ( b < 16 ? '0' : '' ) + b . toString ( 16 ) ;
return '#' + r + g + b ;
}
2022-04-07 08:19:13 +02:00
return false ;
}
function isColorDark ( rgb ) {
rgb = rgb . replace ( /[\s#]/g , '' ) ;
if ( rgb . length == 3 ) {
rgb = rgb [ 0 ] + rgb [ 0 ] + rgb [ 1 ] + rgb [ 1 ] + rgb [ 2 ] + rgb [ 2 ] ;
}
var r = parseInt ( rgb . substr ( 0 , 2 ) , 16 ) ;
var g = parseInt ( rgb . substr ( 2 , 2 ) , 16 ) ;
var b = parseInt ( rgb . substr ( 4 , 2 ) , 16 ) ;
var hsp = Math . sqrt ( 0.299 * ( r * r ) + 0.587 * ( g * g ) + 0.114 * ( b * b ) ) ;
return hsp < 120 ;
}
2022-04-26 17:42:18 +02:00
function versionCompare ( v1 , v2 ) {
if ( typeof v1 !== 'string' ) v1 = '' ;
if ( typeof v2 !== 'string' ) v2 = '' ;
v1 = v1 . replace ( /^\s+|\s+$/g , '' ) . split ( '.' ) ;
v2 = v2 . replace ( /^\s+|\s+$/g , '' ) . split ( '.' ) ;
var a = Math . max ( v1 . length , v2 . length ) , i , p1 , p2 ;
for ( i = 0 ; i < a ; i ++ ) {
p1 = parseInt ( v1 [ i ] ) || 0 ;
p2 = parseInt ( v2 [ i ] ) || 0 ;
if ( p1 == p2 ) continue ;
if ( p1 > p2 ) return 1 ;
return - 1 ;
}
return 0 ;
}
function versionAtLeast ( ver ) {
return versionCompare ( webAppVersion , ver ) >= 0 ;
}
2022-04-07 08:19:13 +02:00
function byteLength ( str ) {
if ( window . Blob ) {
try { return new Blob ( [ str ] ) . size ; } catch ( e ) { }
}
var s = str . length ;
for ( var i = str . length - 1 ; i >= 0 ; i -- ) {
var 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 ;
}
2022-05-20 23:38:29 +02:00
var BackButton = ( function ( ) {
var isVisible = false ;
var backButton = { } ;
Object . defineProperty ( backButton , 'isVisible' , {
set : function ( val ) { setParams ( { is _visible : val } ) ; } ,
get : function ( ) { return isVisible ; } ,
enumerable : true
} ) ;
var curButtonState = null ;
WebView . onEvent ( 'back_button_pressed' , onBackButtonPressed ) ;
function onBackButtonPressed ( ) {
receiveWebViewEvent ( 'backButtonClicked' ) ;
}
function buttonParams ( ) {
return { is _visible : isVisible } ;
}
function buttonState ( btn _params ) {
if ( typeof btn _params === 'undefined' ) {
btn _params = buttonParams ( ) ;
}
return JSON . stringify ( btn _params ) ;
}
function buttonCheckVersion ( ) {
if ( ! versionAtLeast ( '6.1' ) ) {
console . warn ( '[Telegram.WebApp] BackButton is not supported in version ' + webAppVersion ) ;
2022-05-24 14:50:44 +02:00
return false ;
2022-05-20 23:38:29 +02:00
}
2022-05-24 14:50:44 +02:00
return true ;
2022-05-20 23:38:29 +02:00
}
function updateButton ( ) {
var btn _params = buttonParams ( ) ;
var btn _state = buttonState ( btn _params ) ;
if ( curButtonState === btn _state ) {
return ;
}
curButtonState = btn _state ;
WebView . postEvent ( 'web_app_setup_back_button' , false , btn _params ) ;
}
function setParams ( params ) {
2022-05-24 14:50:44 +02:00
if ( ! buttonCheckVersion ( ) ) {
return backButton ;
}
2022-05-20 23:38:29 +02:00
if ( typeof params . is _visible !== 'undefined' ) {
isVisible = ! ! params . is _visible ;
}
updateButton ( ) ;
return backButton ;
}
backButton . onClick = function ( callback ) {
2022-05-24 14:50:44 +02:00
if ( buttonCheckVersion ( ) ) {
onWebViewEvent ( 'backButtonClicked' , callback ) ;
}
2022-05-20 23:38:29 +02:00
return backButton ;
} ;
backButton . offClick = function ( callback ) {
2022-05-24 14:50:44 +02:00
if ( buttonCheckVersion ( ) ) {
offWebViewEvent ( 'backButtonClicked' , callback ) ;
}
2022-05-20 23:38:29 +02:00
return backButton ;
} ;
backButton . show = function ( ) {
return setParams ( { is _visible : true } ) ;
} ;
backButton . hide = function ( ) {
return setParams ( { is _visible : false } ) ;
} ;
return backButton ;
} ) ( ) ;
2022-04-09 14:27:34 +02:00
var mainButtonHeight = 0 ;
2022-04-07 08:19:13 +02:00
var MainButton = ( function ( ) {
var isVisible = false ;
var isActive = true ;
var isProgressVisible = false ;
var buttonText = 'CONTINUE' ;
var buttonColor = false ;
var buttonTextColor = false ;
var mainButton = { } ;
Object . defineProperty ( mainButton , 'text' , {
set : function ( val ) { mainButton . setParams ( { text : val } ) ; } ,
get : function ( ) { return buttonText ; } ,
enumerable : true
} ) ;
Object . defineProperty ( mainButton , 'color' , {
set : function ( val ) { mainButton . setParams ( { color : val } ) ; } ,
get : function ( ) { return buttonColor || themeParams . button _color || '#2481cc' ; } ,
enumerable : true
} ) ;
Object . defineProperty ( mainButton , 'textColor' , {
set : function ( val ) { mainButton . setParams ( { text _color : val } ) ; } ,
get : function ( ) { return buttonTextColor || themeParams . button _text _color || '#ffffff' ; } ,
enumerable : true
} ) ;
Object . defineProperty ( mainButton , 'isVisible' , {
set : function ( val ) { mainButton . setParams ( { is _visible : val } ) ; } ,
get : function ( ) { return isVisible ; } ,
enumerable : true
} ) ;
Object . defineProperty ( mainButton , 'isProgressVisible' , {
get : function ( ) { return isProgressVisible ; } ,
enumerable : true
} ) ;
Object . defineProperty ( mainButton , 'isActive' , {
set : function ( val ) { mainButton . setParams ( { is _active : val } ) ; } ,
get : function ( ) { return isActive ; } ,
enumerable : true
} ) ;
2022-04-26 14:55:46 +02:00
var curButtonState = null ;
2022-04-13 17:11:59 +02:00
WebView . onEvent ( 'main_button_pressed' , onMainButtonPressed ) ;
2022-04-07 08:19:13 +02:00
2022-04-09 14:27:34 +02:00
var debugBtn = null , debugBtnStyle = { } ;
2022-04-08 13:41:32 +02:00
if ( initParams . tgWebAppDebug ) {
2022-04-07 08:19:13 +02:00
debugBtn = document . createElement ( 'tg-main-button' ) ;
debugBtnStyle = {
font : '600 14px/18px sans-serif' ,
display : 'none' ,
width : '100%' ,
height : '48px' ,
borderRadius : '0' ,
background : 'no-repeat right center' ,
position : 'fixed' ,
left : '0' ,
right : '0' ,
bottom : '0' ,
margin : '0' ,
padding : '15px 20px' ,
textAlign : 'center' ,
boxSizing : 'border-box' ,
zIndex : '10000'
} ;
for ( var k in debugBtnStyle ) {
debugBtn . style [ k ] = debugBtnStyle [ k ] ;
}
document . addEventListener ( 'DOMContentLoaded' , function onDomLoaded ( event ) {
document . removeEventListener ( 'DOMContentLoaded' , onDomLoaded ) ;
document . body . appendChild ( debugBtn ) ;
debugBtn . addEventListener ( 'click' , onMainButtonPressed , false ) ;
} ) ;
}
function onMainButtonPressed ( ) {
2022-04-11 03:58:11 +02:00
if ( isActive ) {
receiveWebViewEvent ( 'mainButtonClicked' ) ;
2022-04-07 08:19:13 +02:00
}
}
2022-04-26 14:55:46 +02:00
function buttonParams ( ) {
2022-04-07 08:19:13 +02:00
var color = mainButton . color ;
var text _color = mainButton . textColor ;
2022-04-26 14:55:46 +02:00
return isVisible ? {
2022-04-07 08:19:13 +02:00
is _visible : true ,
is _active : isActive ,
is _progress _visible : isProgressVisible ,
text : buttonText ,
color : color ,
text _color : text _color
2022-04-26 14:55:46 +02:00
} : { is _visible : false } ;
}
function buttonState ( btn _params ) {
if ( typeof btn _params === 'undefined' ) {
btn _params = buttonParams ( ) ;
}
return JSON . stringify ( btn _params ) ;
}
function updateButton ( ) {
var btn _params = buttonParams ( ) ;
var btn _state = buttonState ( btn _params ) ;
if ( curButtonState === btn _state ) {
return ;
}
curButtonState = btn _state ;
WebView . postEvent ( 'web_app_setup_main_button' , false , btn _params ) ;
2022-04-08 13:41:32 +02:00
if ( initParams . tgWebAppDebug ) {
2022-04-26 14:55:46 +02:00
updateDebugButton ( btn _params ) ;
}
}
function updateDebugButton ( btn _params ) {
if ( btn _params . is _visible ) {
debugBtn . style . display = 'block' ;
mainButtonHeight = 48 ;
debugBtn . style . opacity = btn _params . is _active ? '1' : '0.8' ;
debugBtn . style . cursor = btn _params . is _active ? 'pointer' : 'auto' ;
debugBtn . disabled = ! btn _params . is _active ;
debugBtn . innerText = btn _params . text ;
debugBtn . style . backgroundImage = btn _params . is _progress _visible ? "url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20viewport%3D%220%200%2048%2048%22%20width%3D%2248px%22%20height%3D%2248px%22%3E%3Ccircle%20cx%3D%2250%25%22%20cy%3D%2250%25%22%20stroke%3D%22%23fff%22%20stroke-width%3D%222.25%22%20stroke-linecap%3D%22round%22%20fill%3D%22none%22%20stroke-dashoffset%3D%22106%22%20r%3D%229%22%20stroke-dasharray%3D%2256.52%22%20rotate%3D%22-90%22%3E%3Canimate%20attributeName%3D%22stroke-dashoffset%22%20attributeType%3D%22XML%22%20dur%3D%22360s%22%20from%3D%220%22%20to%3D%2212500%22%20repeatCount%3D%22indefinite%22%3E%3C%2Fanimate%3E%3CanimateTransform%20attributeName%3D%22transform%22%20attributeType%3D%22XML%22%20type%3D%22rotate%22%20dur%3D%221s%22%20from%3D%22-90%2024%2024%22%20to%3D%22630%2024%2024%22%20repeatCount%3D%22indefinite%22%3E%3C%2FanimateTransform%3E%3C%2Fcircle%3E%3C%2Fsvg%3E')" : 'none' ;
debugBtn . style . backgroundColor = btn _params . color ;
debugBtn . style . color = btn _params . text _color ;
} else {
debugBtn . style . display = 'none' ;
mainButtonHeight = 0 ;
}
if ( document . documentElement ) {
document . documentElement . style . boxSizing = 'border-box' ;
document . documentElement . style . paddingBottom = mainButtonHeight + 'px' ;
2022-04-07 08:19:13 +02:00
}
2022-04-26 14:55:46 +02:00
setViewportHeight ( ) ;
2022-04-07 08:19:13 +02:00
}
function setParams ( params ) {
if ( typeof params . text !== 'undefined' ) {
2022-07-01 17:16:45 +02:00
var text = strTrim ( params . text ) ;
2022-04-07 08:19:13 +02:00
if ( ! text . length ) {
console . error ( '[Telegram.WebApp] Main button text is required' , params . text ) ;
throw Error ( 'WebAppMainButtonParamInvalid' ) ;
}
if ( text . length > 64 ) {
console . error ( '[Telegram.WebApp] Main button text is too long' , text ) ;
throw Error ( 'WebAppMainButtonParamInvalid' ) ;
}
buttonText = text ;
}
if ( typeof params . color !== 'undefined' ) {
if ( params . color === false ||
params . color === null ) {
buttonColor = false ;
} else {
var color = parseColorToHex ( params . color ) ;
if ( ! color ) {
2022-05-24 14:50:44 +02:00
console . error ( '[Telegram.WebApp] Main button color format is invalid' , params . color ) ;
2022-04-07 08:19:13 +02:00
throw Error ( 'WebAppMainButtonParamInvalid' ) ;
}
buttonColor = color ;
}
}
if ( typeof params . text _color !== 'undefined' ) {
if ( params . text _color === false ||
params . text _color === null ) {
buttonTextColor = false ;
} else {
var text _color = parseColorToHex ( params . text _color ) ;
if ( ! text _color ) {
2022-05-24 14:50:44 +02:00
console . error ( '[Telegram.WebApp] Main button text color format is invalid' , params . text _color ) ;
2022-04-07 08:19:13 +02:00
throw Error ( 'WebAppMainButtonParamInvalid' ) ;
}
buttonTextColor = text _color ;
}
}
if ( typeof params . is _visible !== 'undefined' ) {
if ( params . is _visible &&
! mainButton . text . length ) {
console . error ( '[Telegram.WebApp] Main button text is required' ) ;
throw Error ( 'WebAppMainButtonParamInvalid' ) ;
}
isVisible = ! ! params . is _visible ;
}
if ( typeof params . is _active !== 'undefined' ) {
isActive = ! ! params . is _active ;
}
2022-04-26 14:55:46 +02:00
updateButton ( ) ;
2022-04-07 08:19:13 +02:00
return mainButton ;
}
mainButton . setText = function ( text ) {
2022-04-11 03:58:11 +02:00
return mainButton . setParams ( { text : text } ) ;
2022-04-07 08:19:13 +02:00
} ;
mainButton . onClick = function ( callback ) {
2022-04-11 03:58:11 +02:00
onWebViewEvent ( 'mainButtonClicked' , callback ) ;
return mainButton ;
} ;
mainButton . offClick = function ( callback ) {
offWebViewEvent ( 'mainButtonClicked' , callback ) ;
2022-04-08 13:15:09 +02:00
return mainButton ;
2022-04-07 08:19:13 +02:00
} ;
mainButton . show = function ( ) {
return mainButton . setParams ( { is _visible : true } ) ;
} ;
mainButton . hide = function ( ) {
return mainButton . setParams ( { is _visible : false } ) ;
} ;
mainButton . enable = function ( ) {
return mainButton . setParams ( { is _active : true } ) ;
} ;
mainButton . disable = function ( ) {
return mainButton . setParams ( { is _active : false } ) ;
} ;
mainButton . showProgress = function ( leaveActive ) {
isActive = ! ! leaveActive ;
isProgressVisible = true ;
updateButton ( ) ;
return mainButton ;
} ;
mainButton . hideProgress = function ( ) {
if ( ! mainButton . isActive ) {
isActive = true ;
}
isProgressVisible = false ;
updateButton ( ) ;
return mainButton ;
}
2022-04-11 03:58:11 +02:00
mainButton . setParams = setParams ;
2022-04-07 08:19:13 +02:00
return mainButton ;
} ) ( ) ;
2022-05-31 18:08:03 +02:00
function onSettingsButtonPressed ( ) {
receiveWebViewEvent ( 'settingsButtonClicked' ) ;
}
WebView . onEvent ( 'settings_button_pressed' , onSettingsButtonPressed ) ;
2022-05-20 23:38:29 +02:00
var HapticFeedback = ( function ( ) {
var hapticFeedback = { } ;
function triggerFeedback ( params ) {
2022-05-24 14:50:44 +02:00
if ( ! versionAtLeast ( '6.1' ) ) {
console . warn ( '[Telegram.WebApp] HapticFeedback is not supported in version ' + webAppVersion ) ;
return hapticFeedback ;
}
2022-05-20 23:38:29 +02:00
if ( params . type == 'impact' ) {
if ( params . impact _style != 'light' &&
params . impact _style != 'medium' &&
params . impact _style != 'heavy' &&
params . impact _style != 'rigid' &&
params . impact _style != 'soft' ) {
console . error ( '[Telegram.WebApp] Haptic impact style is invalid' , params . impact _style ) ;
throw Error ( 'WebAppHapticImpactStyleInvalid' ) ;
}
} else if ( params . type == 'notification' ) {
if ( params . notification _type != 'error' &&
params . notification _type != 'success' &&
params . notification _type != 'warning' ) {
console . error ( '[Telegram.WebApp] Haptic notification type is invalid' , params . notification _type ) ;
throw Error ( 'WebAppHapticNotificationTypeInvalid' ) ;
}
} else if ( params . type == 'selection_change' ) {
// no params needed
} else {
console . error ( '[Telegram.WebApp] Haptic feedback type is invalid' , params . type ) ;
throw Error ( 'WebAppHapticFeedbackTypeInvalid' ) ;
}
WebView . postEvent ( 'web_app_trigger_haptic_feedback' , false , params ) ;
return hapticFeedback ;
}
2022-05-24 14:50:44 +02:00
hapticFeedback . impactOccurred = function ( style ) {
2022-05-20 23:38:29 +02:00
return triggerFeedback ( { type : 'impact' , impact _style : style } ) ;
} ;
hapticFeedback . notificationOccurred = function ( type ) {
return triggerFeedback ( { type : 'notification' , notification _type : type } ) ;
} ;
hapticFeedback . selectionChanged = function ( ) {
return triggerFeedback ( { type : 'selection_change' } ) ;
} ;
return hapticFeedback ;
} ) ( ) ;
2023-08-25 14:44:38 +02:00
var CloudStorage = ( function ( ) {
var cloudStorage = { } ;
function invokeStorageMethod ( method , params , callback ) {
if ( ! versionAtLeast ( '6.9' ) ) {
console . error ( '[Telegram.WebApp] CloudStorage is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
invokeCustomMethod ( method , params , callback ) ;
return cloudStorage ;
}
cloudStorage . setItem = function ( key , value , callback ) {
return invokeStorageMethod ( 'saveStorageValue' , { key : key , value : value } , callback ) ;
} ;
cloudStorage . getItem = function ( key , callback ) {
return cloudStorage . getItems ( [ key ] , callback ? function ( err , res ) {
if ( err ) callback ( err ) ;
2023-08-26 14:03:09 +02:00
else callback ( null , res [ key ] ) ;
2023-08-25 14:44:38 +02:00
} : null ) ;
} ;
cloudStorage . getItems = function ( keys , callback ) {
return invokeStorageMethod ( 'getStorageValues' , { keys : keys } , callback ) ;
} ;
cloudStorage . removeItem = function ( key , callback ) {
return cloudStorage . removeItems ( [ key ] , callback ) ;
} ;
cloudStorage . removeItems = function ( keys , callback ) {
return invokeStorageMethod ( 'deleteStorageValues' , { keys : keys } , callback ) ;
} ;
cloudStorage . getKeys = function ( callback ) {
return invokeStorageMethod ( 'getStorageKeys' , { } , callback ) ;
} ;
return cloudStorage ;
} ) ( ) ;
2022-05-10 16:55:52 +02:00
var webAppInvoices = { } ;
function onInvoiceClosed ( eventType , eventData ) {
if ( eventData . slug && webAppInvoices [ eventData . slug ] ) {
var invoiceData = webAppInvoices [ eventData . slug ] ;
delete webAppInvoices [ eventData . slug ] ;
if ( invoiceData . callback ) {
invoiceData . callback ( eventData . status ) ;
}
receiveWebViewEvent ( 'invoiceClosed' , {
url : invoiceData . url ,
status : eventData . status
} ) ;
}
}
2022-07-01 17:16:45 +02:00
var webAppPopupOpened = false ;
function onPopupClosed ( eventType , eventData ) {
if ( webAppPopupOpened ) {
var popupData = webAppPopupOpened ;
webAppPopupOpened = false ;
var button _id = null ;
if ( typeof eventData . button _id !== 'undefined' ) {
button _id = eventData . button _id ;
}
if ( popupData . callback ) {
popupData . callback ( button _id ) ;
}
receiveWebViewEvent ( 'popupClosed' , {
button _id : button _id
} ) ;
}
}
2022-12-13 15:46:38 +01:00
var webAppScanQrPopupOpened = false ;
2022-12-14 14:55:38 +01:00
function onQrTextReceived ( eventType , eventData ) {
2022-12-13 15:46:38 +01:00
if ( webAppScanQrPopupOpened ) {
var popupData = webAppScanQrPopupOpened ;
var data = null ;
if ( typeof eventData . data !== 'undefined' ) {
data = eventData . data ;
}
if ( popupData . callback ) {
2022-12-14 14:55:38 +01:00
if ( popupData . callback ( data ) ) {
webAppScanQrPopupOpened = false ;
WebView . postEvent ( 'web_app_close_scan_qr_popup' , false ) ;
}
2022-12-13 15:46:38 +01:00
}
2022-12-14 14:55:38 +01:00
receiveWebViewEvent ( 'qrTextReceived' , {
2022-12-13 15:46:38 +01:00
data : data
} ) ;
}
}
2022-12-14 14:55:38 +01:00
function onScanQrPopupClosed ( eventType , eventData ) {
webAppScanQrPopupOpened = false ;
}
2022-12-13 15:46:38 +01:00
function onClipboardTextReceived ( eventType , eventData ) {
2023-08-25 14:44:38 +02:00
if ( eventData . req _id && webAppCallbacks [ eventData . req _id ] ) {
var requestData = webAppCallbacks [ eventData . req _id ] ;
delete webAppCallbacks [ eventData . req _id ] ;
2022-12-13 15:46:38 +01:00
var data = null ;
if ( typeof eventData . data !== 'undefined' ) {
data = eventData . data ;
}
if ( requestData . callback ) {
requestData . callback ( data ) ;
}
receiveWebViewEvent ( 'clipboardTextReceived' , {
data : data
} ) ;
}
}
2023-08-25 14:44:38 +02:00
var WebAppWriteAccessRequested = false ;
function onWriteAccessRequested ( eventType , eventData ) {
if ( WebAppWriteAccessRequested ) {
var requestData = WebAppWriteAccessRequested ;
WebAppWriteAccessRequested = false ;
if ( requestData . callback ) {
requestData . callback ( eventData . status == 'allowed' ) ;
}
receiveWebViewEvent ( 'writeAccessRequested' , {
status : eventData . status
} ) ;
}
}
var WebAppContactRequested = false ;
function onPhoneRequested ( eventType , eventData ) {
if ( WebAppContactRequested ) {
var requestData = WebAppContactRequested ;
WebAppContactRequested = false ;
if ( requestData . callback ) {
requestData . callback ( eventData . status == 'sent' ) ;
}
receiveWebViewEvent ( 'contactRequested' , {
status : eventData . status
} ) ;
}
}
function onCustomMethodInvoked ( eventType , eventData ) {
if ( eventData . req _id && webAppCallbacks [ eventData . req _id ] ) {
var requestData = webAppCallbacks [ eventData . req _id ] ;
delete webAppCallbacks [ eventData . req _id ] ;
var res = null , err = null ;
if ( typeof eventData . result !== 'undefined' ) {
res = eventData . result ;
}
if ( typeof eventData . error !== 'undefined' ) {
err = eventData . error ;
}
if ( requestData . callback ) {
requestData . callback ( err , res ) ;
}
}
}
function invokeCustomMethod ( method , params , callback ) {
if ( ! versionAtLeast ( '6.9' ) ) {
console . error ( '[Telegram.WebApp] Method invokeCustomMethod is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
var req _id = generateCallbackId ( 16 ) ;
var req _params = { req _id : req _id , method : method , params : params || { } } ;
webAppCallbacks [ req _id ] = {
callback : callback
} ;
WebView . postEvent ( 'web_app_invoke_custom_method' , false , req _params ) ;
} ;
2022-04-07 08:19:13 +02:00
if ( ! window . Telegram ) {
window . Telegram = { } ;
}
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'initData' , {
get : function ( ) { return webAppInitData ; } ,
2022-04-09 23:57:53 +02:00
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'initDataUnsafe' , {
get : function ( ) { return webAppInitDataUnsafe ; } ,
2022-04-09 23:57:53 +02:00
enumerable : true
} ) ;
2022-04-26 17:42:18 +02:00
Object . defineProperty ( WebApp , 'version' , {
get : function ( ) { return webAppVersion ; } ,
enumerable : true
} ) ;
2022-08-24 16:31:30 +02:00
Object . defineProperty ( WebApp , 'platform' , {
get : function ( ) { return webAppPlatform ; } ,
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'colorScheme' , {
2022-04-09 23:57:53 +02:00
get : function ( ) { return colorScheme ; } ,
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'themeParams' , {
2022-04-11 03:58:11 +02:00
get : function ( ) { return themeParams ; } ,
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'isExpanded' , {
2022-04-11 03:58:11 +02:00
get : function ( ) { return isExpanded ; } ,
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'viewportHeight' , {
2022-04-09 22:21:15 +02:00
get : function ( ) { return ( viewportHeight === false ? window . innerHeight : viewportHeight ) - mainButtonHeight ; } ,
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'viewportStableHeight' , {
2022-04-11 03:58:11 +02:00
get : function ( ) { return ( viewportStableHeight === false ? window . innerHeight : viewportStableHeight ) - mainButtonHeight ; } ,
enumerable : true
} ) ;
2022-07-29 11:39:25 +02:00
Object . defineProperty ( WebApp , 'isClosingConfirmationEnabled' , {
2022-07-01 17:16:45 +02:00
set : function ( val ) { setClosingConfirmation ( val ) ; } ,
2022-07-29 11:39:25 +02:00
get : function ( ) { return isClosingConfirmationEnabled ; } ,
2022-07-01 17:16:45 +02:00
enumerable : true
} ) ;
2022-05-26 23:00:05 +02:00
Object . defineProperty ( WebApp , 'headerColor' , {
set : function ( val ) { setHeaderColor ( val ) ; } ,
2022-06-14 21:45:40 +02:00
get : function ( ) { return getHeaderColor ( ) ; } ,
2022-05-26 23:00:05 +02:00
enumerable : true
} ) ;
Object . defineProperty ( WebApp , 'backgroundColor' , {
set : function ( val ) { setBackgroundColor ( val ) ; } ,
2022-06-14 21:45:40 +02:00
get : function ( ) { return getBackgroundColor ( ) ; } ,
2022-05-26 23:00:05 +02:00
enumerable : true
} ) ;
2022-05-20 23:38:29 +02:00
Object . defineProperty ( WebApp , 'BackButton' , {
value : BackButton ,
enumerable : true
} ) ;
2022-04-13 17:11:59 +02:00
Object . defineProperty ( WebApp , 'MainButton' , {
value : MainButton ,
enumerable : true
} ) ;
2022-05-20 23:38:29 +02:00
Object . defineProperty ( WebApp , 'HapticFeedback' , {
value : HapticFeedback ,
enumerable : true
} ) ;
2023-08-25 14:44:38 +02:00
Object . defineProperty ( WebApp , 'CloudStorage' , {
value : CloudStorage ,
enumerable : true
} ) ;
2022-05-24 14:50:44 +02:00
WebApp . setHeaderColor = function ( color _key ) {
2022-05-26 23:00:05 +02:00
WebApp . headerColor = color _key ;
2022-05-24 14:50:44 +02:00
} ;
WebApp . setBackgroundColor = function ( color ) {
2022-05-26 23:00:05 +02:00
WebApp . backgroundColor = color ;
2022-05-24 14:50:44 +02:00
} ;
2022-07-01 17:16:45 +02:00
WebApp . enableClosingConfirmation = function ( ) {
2022-07-29 11:39:25 +02:00
WebApp . isClosingConfirmationEnabled = true ;
2022-07-01 17:16:45 +02:00
} ;
WebApp . disableClosingConfirmation = function ( ) {
2022-07-29 11:39:25 +02:00
WebApp . isClosingConfirmationEnabled = false ;
2022-07-01 17:16:45 +02:00
} ;
2022-04-26 17:42:18 +02:00
WebApp . isVersionAtLeast = function ( ver ) {
return versionAtLeast ( ver ) ;
} ;
2022-04-13 17:11:59 +02:00
WebApp . onEvent = function ( eventType , callback ) {
onWebViewEvent ( eventType , callback ) ;
} ;
WebApp . offEvent = function ( eventType , callback ) { offWebViewEvent ( eventType , callback ) ;
} ;
WebApp . sendData = function ( data ) {
if ( ! data || ! data . length ) {
console . error ( '[Telegram.WebApp] Data is required' , data ) ;
throw Error ( 'WebAppDataInvalid' ) ;
}
if ( byteLength ( data ) > 4096 ) {
console . error ( '[Telegram.WebApp] Data is too long' , data ) ;
throw Error ( 'WebAppDataInvalid' ) ;
}
WebView . postEvent ( 'web_app_data_send' , false , { data : data } ) ;
} ;
2023-02-21 20:07:49 +01:00
WebApp . switchInlineQuery = function ( query , choose _chat _types ) {
if ( ! versionAtLeast ( '6.6' ) ) {
console . error ( '[Telegram.WebApp] Method switchInlineQuery is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
if ( ! initParams . tgWebAppBotInline ) {
console . error ( '[Telegram.WebApp] Inline mode is disabled for this bot. Read more about inline mode: https://core.telegram.org/bots/inline' ) ;
throw Error ( 'WebAppInlineModeDisabled' ) ;
}
query = query || '' ;
if ( query . length > 256 ) {
console . error ( '[Telegram.WebApp] Inline query is too long' , query ) ;
throw Error ( 'WebAppInlineQueryInvalid' ) ;
}
var chat _types = [ ] ;
if ( choose _chat _types ) {
if ( ! Array . isArray ( choose _chat _types ) ) {
console . error ( '[Telegram.WebApp] Choose chat types should be an array' , choose _chat _types ) ;
throw Error ( 'WebAppInlineChooseChatTypesInvalid' ) ;
}
var good _types = { users : 1 , bots : 1 , groups : 1 , channels : 1 } ;
for ( var i = 0 ; i < choose _chat _types . length ; i ++ ) {
var chat _type = choose _chat _types [ i ] ;
if ( ! good _types [ chat _type ] ) {
console . error ( '[Telegram.WebApp] Choose chat type is invalid' , chat _type ) ;
throw Error ( 'WebAppInlineChooseChatTypeInvalid' ) ;
}
if ( good _types [ chat _type ] != 2 ) {
good _types [ chat _type ] = 2 ;
chat _types . push ( chat _type ) ;
}
}
}
WebView . postEvent ( 'web_app_switch_inline_query' , false , { query : query , chat _types : chat _types } ) ;
} ;
2022-12-13 15:46:38 +01:00
WebApp . openLink = function ( url , options ) {
2022-05-20 23:38:29 +02:00
var a = document . createElement ( 'A' ) ;
a . href = url ;
if ( a . protocol != 'http:' &&
a . protocol != 'https:' ) {
console . error ( '[Telegram.WebApp] Url protocol is not supported' , url ) ;
throw Error ( 'WebAppTgUrlInvalid' ) ;
}
var url = a . href ;
2022-12-13 15:46:38 +01:00
options = options || { } ;
2022-05-20 23:38:29 +02:00
if ( versionAtLeast ( '6.1' ) ) {
2022-12-13 15:46:38 +01:00
WebView . postEvent ( 'web_app_open_link' , false , { url : url , try _instant _view : versionAtLeast ( '6.4' ) && ! ! options . try _instant _view } ) ;
2022-05-20 23:38:29 +02:00
} else {
2022-05-24 14:50:44 +02:00
window . open ( url , '_blank' ) ;
2022-05-20 23:38:29 +02:00
}
} ;
2022-05-10 16:55:52 +02:00
WebApp . openTelegramLink = function ( url ) {
2022-04-26 17:42:18 +02:00
var a = document . createElement ( 'A' ) ;
a . href = url ;
if ( a . protocol != 'http:' &&
a . protocol != 'https:' ) {
console . error ( '[Telegram.WebApp] Url protocol is not supported' , url ) ;
throw Error ( 'WebAppTgUrlInvalid' ) ;
}
if ( a . hostname != 't.me' ) {
console . error ( '[Telegram.WebApp] Url host is not supported' , url ) ;
throw Error ( 'WebAppTgUrlInvalid' ) ;
}
var path _full = a . pathname + a . search ;
2022-05-20 23:38:29 +02:00
if ( isIframe || versionAtLeast ( '6.1' ) ) {
2022-04-26 17:55:34 +02:00
WebView . postEvent ( 'web_app_open_tg_link' , false , { path _full : path _full } ) ;
2022-04-26 17:42:18 +02:00
} else {
location . href = 'https://t.me' + path _full ;
}
} ;
2022-05-10 16:55:52 +02:00
WebApp . openInvoice = function ( url , callback ) {
var a = document . createElement ( 'A' ) , match , slug ;
a . href = url ;
if ( a . protocol != 'http:' &&
a . protocol != 'https:' ||
a . hostname != 't.me' ||
! ( match = a . pathname . match ( /^\/(\$|invoice\/)([A-Za-z0-9\-_=]+)$/ ) ) ||
! ( slug = match [ 2 ] ) ) {
console . error ( '[Telegram.WebApp] Invoice url is invalid' , url ) ;
throw Error ( 'WebAppInvoiceUrlInvalid' ) ;
}
2022-05-20 23:38:29 +02:00
if ( ! versionAtLeast ( '6.1' ) ) {
2022-05-10 16:55:52 +02:00
console . error ( '[Telegram.WebApp] Method openInvoice is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
if ( webAppInvoices [ slug ] ) {
console . error ( '[Telegram.WebApp] Invoice is already opened' ) ;
throw Error ( 'WebAppInvoiceOpened' ) ;
}
webAppInvoices [ slug ] = {
url : url ,
callback : callback
} ;
WebView . postEvent ( 'web_app_open_invoice' , false , { slug : slug } ) ;
} ;
2022-07-01 18:14:00 +02:00
WebApp . showPopup = function ( params , callback ) {
2022-07-01 17:16:45 +02:00
if ( ! versionAtLeast ( '6.2' ) ) {
2022-07-01 18:14:00 +02:00
console . error ( '[Telegram.WebApp] Method showPopup is not supported in version ' + webAppVersion ) ;
2022-07-01 17:16:45 +02:00
throw Error ( 'WebAppMethodUnsupported' ) ;
}
if ( webAppPopupOpened ) {
console . error ( '[Telegram.WebApp] Popup is already opened' ) ;
throw Error ( 'WebAppPopupOpened' ) ;
}
var title = '' ;
var message = '' ;
var buttons = [ ] ;
var popup _buttons = { } ;
var popup _params = { } ;
if ( typeof params . title !== 'undefined' ) {
title = strTrim ( params . title ) ;
if ( title . length > 64 ) {
console . error ( '[Telegram.WebApp] Popup title is too long' , title ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
if ( title . length > 0 ) {
popup _params . title = title ;
}
}
if ( typeof params . message !== 'undefined' ) {
message = strTrim ( params . message ) ;
}
if ( ! message . length ) {
console . error ( '[Telegram.WebApp] Popup message is required' , params . message ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
if ( message . length > 256 ) {
console . error ( '[Telegram.WebApp] Popup message is too long' , message ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
popup _params . message = message ;
if ( typeof params . buttons !== 'undefined' ) {
if ( ! Array . isArray ( params . buttons ) ) {
console . error ( '[Telegram.WebApp] Popup buttons should be an array' , params . buttons ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
for ( var i = 0 ; i < params . buttons . length ; i ++ ) {
var button = params . buttons [ i ] ;
var btn = { } ;
var id = '' ;
if ( typeof button . id !== 'undefined' ) {
id = button . id . toString ( ) ;
if ( id . length > 64 ) {
console . error ( '[Telegram.WebApp] Popup button id is too long' , id ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
}
btn . id = id ;
var button _type = button . type ;
if ( typeof button _type === 'undefined' ) {
button _type = 'default' ;
}
btn . type = button _type ;
if ( button _type == 'ok' ||
button _type == 'close' ||
button _type == 'cancel' ) {
// no params needed
} else if ( button _type == 'default' ||
button _type == 'destructive' ) {
var text = '' ;
if ( typeof button . text !== 'undefined' ) {
text = strTrim ( button . text ) ;
}
if ( ! text . length ) {
console . error ( '[Telegram.WebApp] Popup button text is required for type ' + button _type , button . text ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
if ( text . length > 64 ) {
console . error ( '[Telegram.WebApp] Popup button text is too long' , text ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
btn . text = text ;
} else {
console . error ( '[Telegram.WebApp] Popup button type is invalid' , button _type ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
buttons . push ( btn ) ;
}
} else {
buttons . push ( { id : '' , type : 'close' } ) ;
}
if ( buttons . length < 1 ) {
console . error ( '[Telegram.WebApp] Popup should have at least one button' ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
if ( buttons . length > 3 ) {
console . error ( '[Telegram.WebApp] Popup should not have more than 3 buttons' ) ;
throw Error ( 'WebAppPopupParamInvalid' ) ;
}
popup _params . buttons = buttons ;
webAppPopupOpened = {
callback : callback
} ;
WebView . postEvent ( 'web_app_open_popup' , false , popup _params ) ;
} ;
WebApp . showAlert = function ( message , callback ) {
2022-07-01 18:14:00 +02:00
WebApp . showPopup ( {
2022-07-01 17:16:45 +02:00
message : message
} , callback ? function ( ) { callback ( ) ; } : null ) ;
} ;
WebApp . showConfirm = function ( message , callback ) {
2022-07-01 18:14:00 +02:00
WebApp . showPopup ( {
2022-07-01 17:16:45 +02:00
message : message ,
buttons : [
{ type : 'ok' , id : 'ok' } ,
{ type : 'cancel' }
]
} , callback ? function ( button _id ) {
callback ( button _id == 'ok' ) ;
} : null ) ;
} ;
2022-12-13 15:46:38 +01:00
WebApp . showScanQrPopup = function ( params , callback ) {
if ( ! versionAtLeast ( '6.4' ) ) {
console . error ( '[Telegram.WebApp] Method showScanQrPopup is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
if ( webAppScanQrPopupOpened ) {
console . error ( '[Telegram.WebApp] Popup is already opened' ) ;
throw Error ( 'WebAppScanQrPopupOpened' ) ;
}
var text = '' ;
var popup _params = { } ;
if ( typeof params . text !== 'undefined' ) {
text = strTrim ( params . text ) ;
if ( text . length > 64 ) {
console . error ( '[Telegram.WebApp] Scan QR popup text is too long' , text ) ;
throw Error ( 'WebAppScanQrPopupParamInvalid' ) ;
}
if ( text . length > 0 ) {
popup _params . text = text ;
}
}
webAppScanQrPopupOpened = {
callback : callback
} ;
WebView . postEvent ( 'web_app_open_scan_qr_popup' , false , popup _params ) ;
} ;
2022-12-14 14:55:38 +01:00
WebApp . closeScanQrPopup = function ( ) {
if ( ! versionAtLeast ( '6.4' ) ) {
console . error ( '[Telegram.WebApp] Method closeScanQrPopup is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
webAppScanQrPopupOpened = false ;
WebView . postEvent ( 'web_app_close_scan_qr_popup' , false ) ;
} ;
2022-12-13 19:52:24 +01:00
WebApp . readTextFromClipboard = function ( callback ) {
2022-12-13 15:46:38 +01:00
if ( ! versionAtLeast ( '6.4' ) ) {
console . error ( '[Telegram.WebApp] Method readTextFromClipboard is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
2023-08-25 14:44:38 +02:00
var req _id = generateCallbackId ( 16 ) ;
2022-12-13 15:46:38 +01:00
var req _params = { req _id : req _id } ;
2023-08-25 14:44:38 +02:00
webAppCallbacks [ req _id ] = {
2022-12-13 15:46:38 +01:00
callback : callback
} ;
WebView . postEvent ( 'web_app_read_text_from_clipboard' , false , req _params ) ;
} ;
2023-08-25 14:44:38 +02:00
WebApp . requestWriteAccess = function ( callback ) {
if ( ! versionAtLeast ( '6.9' ) ) {
console . error ( '[Telegram.WebApp] Method requestWriteAccess is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
if ( WebAppWriteAccessRequested ) {
console . error ( '[Telegram.WebApp] Write access is already requested' ) ;
throw Error ( 'WebAppWriteAccessRequested' ) ;
}
WebAppWriteAccessRequested = {
callback : callback
} ;
WebView . postEvent ( 'web_app_request_write_access' ) ;
} ;
WebApp . requestContact = function ( callback ) {
if ( ! versionAtLeast ( '6.9' ) ) {
console . error ( '[Telegram.WebApp] Method requestContact is not supported in version ' + webAppVersion ) ;
throw Error ( 'WebAppMethodUnsupported' ) ;
}
if ( WebAppContactRequested ) {
console . error ( '[Telegram.WebApp] Contact is already requested' ) ;
throw Error ( 'WebAppContactRequested' ) ;
}
WebAppContactRequested = {
callback : callback
} ;
WebView . postEvent ( 'web_app_request_phone' ) ;
} ;
WebApp . invokeCustomMethod = function ( method , params , callback ) {
invokeCustomMethod ( method , params , callback ) ;
} ;
2022-04-13 17:11:59 +02:00
WebApp . ready = function ( ) {
WebView . postEvent ( 'web_app_ready' ) ;
} ;
WebApp . expand = function ( ) {
WebView . postEvent ( 'web_app_expand' ) ;
} ;
WebApp . close = function ( ) {
WebView . postEvent ( 'web_app_close' ) ;
} ;
window . Telegram . WebApp = WebApp ;
2022-04-07 08:19:13 +02:00
2022-06-14 21:45:40 +02:00
updateBackgroundColor ( ) ;
2022-04-09 14:27:34 +02:00
setViewportHeight ( ) ;
2022-04-11 03:58:11 +02:00
window . addEventListener ( 'resize' , onWindowResize ) ;
2022-04-26 17:42:18 +02:00
if ( isIframe ) {
document . addEventListener ( 'click' , linkHandler ) ;
}
2022-04-11 03:58:11 +02:00
2022-04-13 17:11:59 +02:00
WebView . onEvent ( 'theme_changed' , onThemeChanged ) ;
WebView . onEvent ( 'viewport_changed' , onViewportChanged ) ;
2022-05-10 16:55:52 +02:00
WebView . onEvent ( 'invoice_closed' , onInvoiceClosed ) ;
2022-07-01 17:16:45 +02:00
WebView . onEvent ( 'popup_closed' , onPopupClosed ) ;
2022-12-14 14:55:38 +01:00
WebView . onEvent ( 'qr_text_received' , onQrTextReceived ) ;
2022-12-13 15:46:38 +01:00
WebView . onEvent ( 'scan_qr_popup_closed' , onScanQrPopupClosed ) ;
WebView . onEvent ( 'clipboard_text_received' , onClipboardTextReceived ) ;
2023-08-25 14:44:38 +02:00
WebView . onEvent ( 'write_access_requested' , onWriteAccessRequested ) ;
WebView . onEvent ( 'phone_requested' , onPhoneRequested ) ;
WebView . onEvent ( 'custom_method_invoked' , onCustomMethodInvoked ) ;
2022-04-13 17:11:59 +02:00
WebView . postEvent ( 'web_app_request_theme' ) ;
WebView . postEvent ( 'web_app_request_viewport' ) ;
2022-04-07 08:19:13 +02:00
} ) ( ) ;