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 = '' ;
}
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 ) ;
2022-04-09 23:15:24 +02:00
if ( initParams . tgWebAppDebug ) {
console . log ( '[Telegram.WebView] postEvent via postMessage' , eventType , eventData ) ;
}
2022-04-07 08:19:13 +02:00
callback ( ) ;
} catch ( e ) {
callback ( e ) ;
}
}
else {
2022-04-09 23:15:24 +02:00
if ( initParams . tgWebAppDebug ) {
console . log ( '[Telegram.WebView] postEvent' , eventType , eventData ) ;
}
2022-04-07 08:19:13 +02:00
callback ( { notAvailable : true } ) ;
}
} ;
function 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-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-04-13 17:11:59 +02:00
function onThemeChanged ( eventType , eventData ) {
if ( eventData . theme _params ) {
setThemeParams ( eventData . theme _params ) ;
window . Telegram . WebApp . MainButton . setParams ( {
force _update : true
} ) ;
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-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-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
}
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-05-31 18:08:03 +02:00
var headerColorKey = 'bg_color' ;
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 } ) ;
} ;
var backgroundColor = null ;
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-05-26 23:00:05 +02:00
var bg _color = parseColorToHex ( color ) ;
if ( ! bg _color ) {
console . error ( '[Telegram.WebApp] Background color format is invalid' , color ) ;
throw Error ( 'WebAppBackgroundColorInvalid' ) ;
}
backgroundColor = color ;
WebView . postEvent ( 'web_app_set_background_color' , false , { color : color } ) ;
} ;
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' ) {
var text = params . text . toString ( ) . replace ( /^\s+|\s+$/g , '' ) ;
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 ;
} ) ( ) ;
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-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-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-05-26 23:00:05 +02:00
Object . defineProperty ( WebApp , 'headerColor' , {
set : function ( val ) { setHeaderColor ( val ) ; } ,
2022-05-31 18:08:03 +02:00
get : function ( ) { return themeParams [ headerColorKey ] || null ; } ,
2022-05-26 23:00:05 +02:00
enumerable : true
} ) ;
Object . defineProperty ( WebApp , 'backgroundColor' , {
set : function ( val ) { setBackgroundColor ( val ) ; } ,
get : function ( ) { return backgroundColor ; } ,
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
} ) ;
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-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 } ) ;
} ;
2022-05-20 23:38:29 +02:00
WebApp . openLink = function ( url ) {
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 ;
if ( versionAtLeast ( '6.1' ) ) {
WebView . postEvent ( 'web_app_open_link' , false , { url : url } ) ;
} 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-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-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-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
} ) ( ) ;