Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Portuguese

Este arquivo PRW contém o ferramental necessário para customizações ADVPL à partir do CloudBridge, nele você entenderá todo o mecanismo de comunicação entre o Navegador Embedado (JavaScript) e o ADVPL.

As funções mais importantes são:

Function u_CBCustom()
Função principal, deve ser inserida na TAG mainFunction no arquivo .cloud, base do aplicativo, para ser instanciada no momento da abertura.

Function loadFinished()
Função atribuida como bloco de código do oWebEngine:bLoadFinished, ela será disparada ao termino da carga das páginas e como parâmetro recebe a URL carregada.

Function notificationTapped()
Função atribuida como bloco de código do oMobile:bNotificationTapped, ela será disparada quando a notificação for selecionada no dispositivo móvel. Ela recebe o ID inserido na notificação.

Function jsToAdvpl()
Função atribuida como bloco de código do oWebChannel:bJsToAdvpl, ela será disparada durante o recebimento da Função dialog.jsToAdvpl() que será disparada via JavaScript.

Arquivo

Bloco de código
languagecpp
themeEclipse
linenumberstrue
collapsefalse
#include "TOTVS.CH"
#include "FILEIO.CH"
#INCLUDE "TBIConn.ch"

Function u_CBCustom()
    	// ---------------------------------------------------------------
    	local i
    	local oWebChannel
    	local cMultGet := ""
    	local cHost,nPort,lConnected
    	local tempPath := GetTempPath()
    	PRIVATE oWebEngine
    	PRIVATE oMultGet
    	PRIVATE oGetLink
    PRIVATE    oDlg

    	PRIVATE	oDlg
	oDlg := TWindow():New(10, 10, 800, 600, "TOTVS - CloudBridge", NIL, NIL, NIL, NIL, NIL, NIL, NIL,;
    	CLR_BLACK, CLR_WHITE, NIL, NIL, NIL, NIL, NIL, NIL, .T. )
    	oDlg:setCSS("QPushButton{margin: 1px; background-color: "+_colorTOTVS+"; border: none; color: #fff; }")

    	// Android ou iOS
    	if _rmtType == 8 .Or. _rmtType == 9
        		// Libera rotacao do dispositivo
        		PRIVATE oMobile := TMobile():New(oDlg)
        		oMobile:SetScreenOrientation(-1)

        		// Temporario do dispositivo
        		tempPath := oMobile:GetTempPath() + "/"

        		// Prepara bloco de codigo pra callBack de notificacao
        		oMobile:bNotificationTapped := {|id| notificationTapped(id) }
    	endif

    	// Prepara o conector WebSocket, sempre pra LOCALHOST e retorna a PORTA LIVRE
    	oWebChannel := TWebChannel():New()
    	nPort          		:= oWebChannel::connect()
    	cHost         		:= oWebChannel:cHost
    	nPort         		:= oWebChannel:nPort
    	lConnected     	:= oWebChannel:lConnected

    	// Verifica conexão
    	if !lConnected
        		msgStop("Erro na conexão com o WebSocket")
        		return
    	endif

    	// Define o CallBack JavaScript
    	oWebChannel:bJsToAdvpl := {|self,codeType,codeContent| jsToAdvpl(self,codeType,codeContent) }

    	// Monta link GLOBAL
    	if subs(tempPath,1,2) == "C:"
        		tempPath := "file:///" + strTran(tempPath, "\", "/")
    	endif
    	mainHtml := tempPath + mainHtml

    	oWebEngine := TWebEngine():New(oDlg, 0, 0, 100, 100,, nPort)
    	oWebEngine:bLoadFinished := {|self,url| loadFinished(self,url) }
    	oWebEngine:setAsMain() // Define como WebEngine que recebera o KEY_BACK (Android)

    	// Painel superior
    	@ 000, 000 MSPANEL pnTop SIZE 250, 024 OF oDlg COLORS 0, 16777215 RAISED // Mansano: 250, 012
    	pnTop:setCss("QFrame{background-color: #6BB4F1;}")

    	// Alinha componentes
    	pnTop:Align := CONTROL_ALIGN_TOP
    	oWebEngine:Align := CONTROL_ALIGN_ALLCLIENT

    	// CONOUT fake para exibir a mensageria
    	oFont1 := TFont():New("Courier",,018,,.F.,,,,,.F.,.F.)
    	@ 038, 000 MSPANEL ConOut SIZE 250, 16 OF oDlg COLORS 0, 16777215 RAISED
    	oMultGet := TSimpleEditor():New( 0,0,ConOut, 50,50,"",, {| u | if( pCount() > 0, cMultGet := u, cMultGet )}, oFont1, .T.)
    	ConOut:Align := CONTROL_ALIGN_BOTTOM
    	oMultGet:Align := CONTROL_ALIGN_ALLCLIENT

    	CreateFormTop(pnTop)

    	oDlg:Activate("MAXIMIZED")
Return

// Parseia o Json em um Hash
Static Function getJsonHash(jsonData, oHash)
    	// ---------------------------------------------------------------
    	Local oJson := tJsonParser():New()
    	Local jsonfields := {}
    	Local nRetParser := 0

    	if empty(jsonData)
        		return .F.
    	endif

    	// Converte JSON pra Hash
    	return oJson:Json_Hash(jsonData, len(jsonData), @jsonfields, @nRetParser, @oHash)
return

// Retorna valor do campo no Hash
Static Function getHField(oHash, jsonField)
    	// ---------------------------------------------------------------
    	Local xGet := Nil
    	// Recupera valor do campo
    	if HMGet(oHash, jsonField, xGet)
        		return xGet
    	else
        		return ""
    	endif
return

// Bloco de codigo do termino da carga da pagina
static function loadFinished(self,url)
    	// ---------------------------------------------------------------
    	oGetLink:cText := url+space(1000)
return

// CALLBACK das notificacoes
static function notificationTapped(id)
    	conout("createNotification: id: " + cValToChar(id))
return

// CALLBACK JavaScript
static function jsToAdvpl(self,codeType,codeContent)
    // 	// ---------------------------------------------------------------
    	Local i
    	Local oTmpHash := .F.
    	Local xRet, lRet
    , scalesize
	Local xVal, fnCallBack, cFile, aBarResult,;
    	aDevicesResult, sMsg, cPosition, id, title, message,;
    	cQuery, nFields, nRecords, aAccelerometerSensor

    	if valType(codeType) == "C"
        		_conout("jsToAdvpl->codeType: " + codeType + " = " + codeContent)

        		if codeType == "runAdvpl"
            			if getJsonHash(codeContent, @oTmpHash)
                				xVal := &("{|| " + getHField(oTmpHash, "codeBlock") + "}")
                				if valType(xVal) == "B"
				  conout("vou rodar o advpl - {|| " + getHField(oTmpHash, "codeBlock")         + "}")
					xRet := eval(xVal)
                    					xRet := cValToChar(xRet) // Converte pra String

                    // Executa o CallBack
                    fnCallBack = 					// Executa o CallBack
					fnCallBack = getHField(oTmpHash, "callBack")+"('" +xRet+ "')"
					conout("rodei o advpl, agora vou chamar o callback - "           + fnCallBack)
					oWebEngine:runJavaScript(fnCallBack)
					conout("chamei                endif
            else
                o callback")
				endif
			else
				_msgAlert("RunAdvpl command not executed", "CloudBridge")
			endif
			return
		endif
		
		if codeType == "decode64"
		  if       endifgetJsonHash(codeContent, @oTmpHash)
        strDec :=   returngetHField(oTmpHash, "strDecode")
        endif
strFile := getHField(oTmpHash, "strFile")
        //lChangeCase Android Ou iOS:= getHField(oTmpHash, "lChangeCase")
        if _rmtTypevalType(strDec) == 8 .Or. _rmtType == 9
"C"
          Decode64(strDec,oMobile:GetTempPath() + "//" Tira foto+ strFile,lChangeCase)
          // Executa if codeType == "getPicture"o CallBack
          fnCallBack = getHField(oTmpHash, "callBack")+"('" +  cFile:= oMobile:TakePictureGetTempPath()
 + "/" + strFile + "')"
          _conout("[getPicture]rodei o advpl, agora vou chamar o callback - " + cFilefnCallBack)

          oWebEngine:runJavaScript(fnCallBack)
         // Executa conout("chamei o CallBackcallback")
        endif
      else
   fnCallBack    = codeContent+"_msgAlert('" +cFile+ "')"RunAdvpl command not executed", "CloudBridge")
      endif
          oWebEngine:runJavaScript(fnCallBack)
                return
            endif
return
		endif
		// Android Ou iOS
		if _rmtType == 8 .Or. _rmtType == 9
			// Tira foto
			if codeType == "getPicture"
			  if getJsonHash(codeContent, @oTmpHash)
			    scalesize := getHField(oTmpHash, "ScaletoWidth")
          cFile:=  // Codigo de  barras
            if codeType == "barCodeScanner"oMobile:TakePicture(scalesize)
			    fnCallBack = getHField(oTmpHash, "callBack")+"('" +cFile+ "')"
			  else
			    
			  endif
        _conout("[getPicture] - "      aBarResult := oMobile:BarCode(+ cFile)
        // Executa o CallBack
     If aBarResult[1] = "" oWebEngine:runJavaScript(fnCallBack)
        return
      endif
			// Codigo de  barras
			if codeType == "barCodeScanner"
				aBarResult := oMobile:BarCode()
				If aBarResult[1] = ""
					_conout("[barCode] - " + "Nenhum códigocódigo de barras disponíveldisponível.")
                Else
                    				Else
					_conout("[barCode] - " + "CódigoCódigo: " + aBarResult[1] + chr(13) + "Formato: " + aBarResult[2])

                    // Executa o CallBack
                    					// Executa o CallBack
					fnCallBack = codeContent+"('" +aBarResult[1]+ "')"
                    					oWebEngine:runJavaScript(fnCallBack)
				EndIf
				return
			endif
			// Verifica dispositivos pareados
			if codeType == "pairedDevices"
				aDevicesResult:= oMobile:GetPairedBluetoothDevices()
				sMsg := ""
				For i := 1    EndIf

                return
            endif

            // Verifica dispositivos pareados
            to len(aDevicesResult)
					sMsg := sMsg + "Nome: " + aDevicesResult[i][1] + chr(13)
					sMsg := sMsg + "Endereço: " + aDevicesResult[i][2] + chr(13) + chr(13)
				Next i
				If sMsg = ""
					sMsg := "Nenhum dispositivo pareado ou interface Bluetooth desligada."
				Else
					sMsg := "Dispositivos Bluetooth Pareados:" + chr(13) + chr(13) + sMsg
				EndIf
				_conout("[bluetooth] - " + sMsg)
				// Executa o CallBack
				fnCallBack = codeContent+"('" +SubStr(sMsg,1,30)+ "')"
				oWebEngine:runJavaScript(fnCallBack)
				return
			endif
			// Libera orientacao
			if codeType == "pairedDevices"
                aDevicesResult:= oMobile:GetPairedBluetoothDevices()

                sMsg := ""
                For i := 1 to len(aDevicesResult)
                    sMsg := sMsg + "Nome: " + aDevicesResult[i][1] + chr(13)
                    sMsg := sMsg + "Endereço: " + aDevicesResult[i][2] + chr(13) + chr(13)
                Next i

                If sMsg = ""
                    sMsg := "Nenhum dispositivo pareado ou interface Bluetooth desligada."
                Else
                    sMsg := "Dispositivos Bluetooth Pareados:" + chr(13) + chr(13) + sMsg
                EndIf
                _conout("[bluetooth] - " + sMsg)

                // Executa o CallBack
                fnCallBack = codeContent+"('" +SubStr(sMsg,1,30)+ "')"
                oWebEngine:runJavaScript(fnCallBack)
                return
            endif

            // Libera orientacao
            if codeType == "unlockOrientation"
                oMobile:SetScreenOrientation(-1)
                _conout("[unlockOrientation]")
                return
            endif

            // Trava orientacao
            if codeType == "lockOrientation"
                oMobile:SetScreenOrientation(2)
                _conout("[lockOrientation]")
                return
            endif

            // GPS
            if codeType == "getCurrentPosition"
                cPosition := oMobile:getGeoCoordinate(1)

                // PARA LIMPAR O SINAL DE GRAUS CHR(176)
                //cPosition := StrTran(cPosition, chr(176), "")

                _conout("[getCurrentPosition] - " + cPosition)

                // Executa o CallBack
                fnCallBack = codeContent+"('" +cPosition+ "')"
                oWebEngine:runJavaScript(fnCallBack)
                return
            endif

            // Testa perifericos
            if codeType == "testDevice"
                if getJsonHash(codeContent, @oTmpHash)
                    lRet := oMobile:TestDevice(getHField(oTmpHash, "testFeature"))

                    // Executa o CallBack
                    fnCallBack = getHField(oTmpHash, "callBack")+"('" +cValToChar(lRet)+ "')"unlockOrientation"
				oMobile:SetScreenOrientation(-1)
				_conout("[unlockOrientation]")
				return
			endif
			// Trava orientacao
			if codeType == "lockOrientation"
				oMobile:SetScreenOrientation(2)
				_conout("[lockOrientation]")
				return
			endif
			// GPS
			if codeType == "getCurrentPosition"
				cPosition := oMobile:getGeoCoordinate(1)
				_conout("[getCurrentPosition] - " + cPosition)
				// PARA LIMPAR O SINAL DE GRAUS CHR(176)
				cPosition := StrTran(cPosition, chr(176), "")
				// Executa o CallBack
				fnCallBack = codeContent+"('" +cPosition+ "');"
				oWebEngine:runJavaScript(fnCallBack)
				return
			endif
			// Testa perifericos
			if codeType == "testDevice"
				if getJsonHash(codeContent, @oTmpHash)
					lRet := oMobile:TestDevice(getHField(oTmpHash, "testFeature"))
					// Executa o CallBack
					fnCallBack = getHField(oTmpHash, "callBack")+"('" +cValToChar(lRet)+ "')"
					oWebEngine:runJavaScript(fnCallBack)
				else
					_msgAlert("testDevice command not executed", "CloudBridge")
				endif
				return
			endif
			// Cria notificacao
			// O callBack sera disparado pelo bloco de codigo bNotificationTapped
			if codeType == "createNotification"
				if getJsonHash(codeContent, @oTmpHash)
					id := getHField(oTmpHash, "id")
					title := getHField(oTmpHash, "title")
					message := getHField(oTmpHash, "message")
					oMobile:CreateNotification(id, title, message)
				else
					_msgAlert("createNotification command not executed", "CloudBridge")
				endif
				return
			endif
			// Abre configuracoes
			if codeType == "openSettings"
				oWebEngine:runJavaScript("openSettings")
				oMobile:OpenSettings(val(codeContent))
				return
			endif
			
			// Recupera diretorio temporario 
			if codeType == "getTempPath"
				fnCallBack = codeContent + "('" + oMobile:GetTempPath() + "');"
				oWebEngine:runJavaScript(fnCallBack)
			endif
			
			// Aciona o vibracall do dispositivo 
			if codeType == "vibrate"
				oMobile:vibrate(val(codeContent))
			endif
			
			// Efetua uma leitura no sensor de acelerômetro do dispositivo 
			if codeType == "readAccelerometer"
				aAccelerometerSensor:= oMobile:ReadAccelerometer()
				sMsg := "Valores lidos do sensor acelerometro (m/s2):" + "\n"
				sMsg += "x:" + str(aAccelerometerSensor[1]) + "\n"
				sMsg += "y:" + str(aAccelerometerSensor[2]) + "\n"
				sMsg += "z:" + str(aAccelerometerSensor[3])
				_conout("accelerometer - " + sMsg)
				// Executa o CallBack
				fnCallBack = codeContent+"('" +sMsg+ "')"
				oWebEngine:runJavaScript(fnCallBack)
				return
			endif
			
			// Habilita bloco de código bOnPause
			if codeType == "enblOnPause"
			  _msgAlert("Conferir resultado na barra de status.", "CloudBridge")
			  _conout("[bOnPause] - Cada evento OnPause sera exibido aqui com o horario.")
			  oMobile:bOnPause := { || _conout("bOnPause >> Aplicativo entrou em background as " + TIME()) }
			  return
			endif
			// Habilita bloco de código bOnResume
			if codeType == "enblOnResume"
			  _msgAlert("Conferir resultado na barra de status.", "CloudBridge")
			  _conout("[bOnResume] - Cada evento OnResume sera exibido aqui com o horario.")
			  oMobile:bOnResume := { || _conout("bOnResume >> Aplicativo voltou em primeiro plano as " + TIME()) }
			  return
			endif
			// Pre-insere um contato da agenda do dispositivo 
			if codeType == "addContact"
				if getJsonHash(codeContent, @oTmpHash)
					aEmails := {}
					aPhones := {}
					aPostals := {}
					oTMobCont := TMobileContact():New()
					oTMobCont:cName := getHField(oTmpHash, "name")
					oTMobCont:cCompany := getHField(oTmpHash, "company")
					oTMobCont:cJobTitle := getHField(oTmpHash, "jobTitle")
					oTMobCont:cNote := getHField(oTmpHash, "note")
					cEmail1 := getHField(oTmpHash, "email1")
					nEmailType1 := getHField(oTmpHash, "emailType1")
					aAdd( aEmails, TMobileContactEmail():New2( nEmailType1, cEmail1 ) )
					cPhone1 := getHField(oTmpHash, "phone1")
					nPhoneType1 := getHField(oTmpHash, "phoneType1")
					aAdd( aPhones, TMobileContactPhone():New2( nPhoneType1, cPhone1 ) )
					aAdd( aPostals, TMobileContactPostal():New2( 2, getHField(oTmpHash, "postal") ) )
					oTMobCont:aEmails := aEmails
					oTMobCont:aPhones := aPhones
					oTMobCont:aPostals := aPostals
					oMobile:AddContact( oTMobCont )
				else
					_msgAlert("addContact command not executed", "CloudBridge")
				endif
				return
			endif
			
			// Procura contatos no dispositivo
			if codeType == "findContact"
				if getJsonHash(codeContent, @oTmpHash)
					aContacts := {}
					aContacts := oMobile:FindContact( getHField( oTmpHash, "filter" ) )
					//VarInfo( "Contatos encontrados", aContacts )
					sMsg := "Resultado da busca por contatos:"
					For i := 1 to len( aContacts )
					  sMsg += "\n\n"
					  If len( aContacts[i]:cName ) > 0
					    sMsg += "Nome: " + aContacts[i]:cName + "\n"
					  EndIf
					  If len( aContacts[i]:aPhones ) > 0
					    sMsg += "Fone: " + aContacts[i]:aPhones[1]:cNumber + "\n"
					  EndIf
					  If len( aContacts[i]:aEmails ) > 0
					    sMsg += "E-mail: " + aContacts[i]:aEmails[1]:cAddress + "\n"
					  EndIf
					Next i
					fnCallBack = getHField(oTmpHash, "callBack")+"('" + sMsg + "')"
					oWebEngine:runJavaScript(fnCallBack)
				else
					_msgAlert("findContact command not executed", "CloudBridge")
				endif
				return
			endif
			// Pre-insere um evento de calendario do dispositivo 
      if codeType == "addCalendar"
        if getJsonHash(codeContent, @oTmpHash)
          datai := getHField(oTmpHash, "startdate")
          datae :=         oWebEngine:runJavaScript(fnCallBackgetHField(oTmpHash, "enddate")
          dataictod := right(datai,2) + "/"  else
    + substr(datai,6,2) + "/" + left(datai,4)
          dataectod := right(datae,2) + "/" + _msgAlert("testDevice command not executed", "CloudBridge"substr(datae,6,2) + "/" + left(datae,4)
          oTmpCalEv := TCalendarEvent():New()
    endif
      oTmpCalEv:cTitle := getHField(oTmpHash, "title")
       return
   oTmpCalEv:cDescription := getHField(oTmpHash, "descr")
      endif

    oTmpCalEv:cLocation := getHField(oTmpHash, "addr")
     // Cria notificacao
   oTmpCalEv:dStartDate := ctod(dataictod,"ddmmyyyy")
       // O callBack sera disparado pelo bloco de codigo bNotificationTappedoTmpCalEv:cStartTime := getHField(oTmpHash, "starttime")
            if codeType == "createNotification"oTmpCalEv:dEndDate := ctod(dataectod,"ddmmyyyy")
          oTmpCalEv:cEndTime := getHField(oTmpHash, "endtime")
    if getJsonHash(codeContent, @oTmpHash)
    if getHField(oTmpHash, "allday") == "True"
            idoTmpCalEv:lAllDay := getHField(oTmpHash, "id")
.T.
          else
            titleoTmpCalEv:lAllDay := getHField(oTmpHash, "title").F.
          endif
          messageiRet := getHField(oTmpHash, "message"oMobile:addCalendarEvent(oTmpCalEv)
          fnCallBack = getHField(oTmpHash, "callBack")+"('" +cValToChar(iRet)+ "')"
          oMobileoWebEngine:CreateNotification(id, title, messagerunJavaScript(fnCallBack)
        endif
      endif
   else
   
      // Procura eventos de calendario no dispositivo
     _msgAlert("createNotification commandif not executed",codeType == "CloudBridgefindCalendar")
        if getJsonHash(codeContent, @oTmpHash)
      endif
    datai := getHField(oTmpHash, "startdate")
         return
 datae := getHField(oTmpHash, "enddate")
        endif

  dataictod := right(datai,2) + "/" + substr(datai,6,2) +   "//" Abre configuracoes+ left(datai,4)
          dataectod  if codeType == "openSettings"
                oWebEngine:runJavaScript("openSettings")

:= right(datae,2) + "/" + substr(datae,6,2) + "/" + left(datae,4)
          aCalIds  :=    oMobile:OpenSettings(val(codeContentfindCalendarEvent(ctod(dataictod,"ddmmyyyy"), ctod(dataectod,"ddmmyyyy"))
          cIds :=   '{"ids": ['
  return
        if Len(aCalIds) >  endif0
            
for i := 1 to len(aCalIds)
       // Recupera diretorio temporario 
   cIds += '"' + cvaltochar(aCalIds[i]) + '",'
   if codeType == "getTempPath"
      next
          fnCallBack = codeContentcIds +:= "('" + oMobile:GetTempPath() + "');"left(cIds,Len(cIds)-1)
          endif
      oWebEngine:runJavaScript(fnCallBack)
    cIds += "]}"
      endif
    fnCallBack = getHField(oTmpHash, "callBack")+"('" +cIds+ "')"
   
       oWebEngine:runJavaScript(fnCallBack)
     // Aciona o vibracallendif
    do dispositivo endif
      
      // Visualiza evento ifdo codeTypecalendario == "vibrate"do dispositivo
      if codeType == "viewCalendar"
        oMobile:vibrateviewCalendarEvent(val(codeContentcodecontent))
      endif
      endif
      // Retorna informações do evento  informado
      if codeType == "getCalendar"
   // Efetua uma leitura no sensor de acelerômetro do dispositivo if getJsonHash(codeContent, @oTmpHash)
          id  if codeType == "readAccelerometer":= getHField(oTmpHash, "id")
          oCalEv      aAccelerometerSensor:= oMobile:ReadAccelerometer()
:= oMobile:getCalendarEvent(id)
          
      sMsg := "Valores lidos dodateic sensor:= acelerometro (m/s2):" + "\n"
dtos(oCalEv:dStartDate)
          dateec := dtos(oCalEv:dEndDate)
      sMsg += "x:" + str(aAccelerometerSensor[1]) + "\n dateijs := ""
                sMsg += "y:" + str(aAccelerometerSensor[2]) + "\ndateejs := ""
          if Len(dateic) == 8 .AND.  sMsg += "z:" + str(aAccelerometerSensor[3])

Len(dateec) == 8
            dateijs := left(dateic,4) + "-" + _conout("accelerometer - substr(dateic,5,2) + "-" + sMsgright(dateic,2)

            dateejs := left(dateec,4) + // Executa o CallBack
    "-" + substr(dateec,5,2) + "-" + right(dateec,2)
          endif
  fnCallBack = codeContent+"('" +sMsg+ "')"
    if oCalEv:lAllDay
           oWebEngine:runJavaScript(fnCallBack)
 cAllday := "True"
          else
   return
         cAllDay   endif

:= "False"
          endif 
 //  Pre-insere um contato da agenda do dispositivo 
            if codeType =cCalEv := "addContact{"
          cCalEv += '"title":"'    if getJsonHash(codeContent, @oTmpHash)
+ oCalEv:cTitle           + '",'
        aEmails := {}
cCalEv += '"descr":"'     + oCalEv:cDescription     + '",'
      aPhones := {}
  cCalEv += '"addr":"'      + oCalEv:cLocation        + aPostals := {}

'",'
          cCalEv += '"startdate":"'  + dateijs       oTMobCont := TMobileContact():New()
         + '",'
          oTMobCont:cNamecCalEv :+= getHField(oTmpHash, "name")
  '"starttime":"'  + oCalEv:cStartTime       + '",'
          oTMobCont:cCompanycCalEv :+= getHField(oTmpHash, "company")
'"enddate":"'   + dateejs                oTMobCont:cJobTitle := getHField(oTmpHash, "jobTitle")
+ '",'
          cCalEv += '"endtime":"'   + oCalEv:cEndTime       oTMobCont:cNote := getHField(oTmpHash, "note")
 + '",'
          cCalEv += '"allday":"'    + cAllDay   cEmail1 := getHField(oTmpHash, "email1")
            + '"}'
       nEmailType1 := getHField(oTmpHash, "emailType1")
          fnCallBack          aAdd( aEmails, TMobileContactEmail():New2( nEmailType1, cEmail1 ) )

= getHField(oTmpHash, "callBack")+"('" +cCalEv+ "')"
                    cPhone1 := getHField(oTmpHash, "phone1"oWebEngine:runJavaScript(fnCallBack)
        endif
      endif
      nPhoneType1 := getHField(oTmpHash, "phoneType1")
                    aAdd( aPhones, TMobileContactPhone():New2( nPhoneType1, cPhone1 ) )

                    aAdd( aPostals, TMobileContactPostal():New2( 2, getHField(oTmpHash, "postal") ) )

                    oTMobCont:aEmails := aEmails
                    oTMobCont:aPhones := aPhones
                    oTMobCont:aPostals := aPostals

                    oMobile:AddContact( oTMobCont )
                else
                    _msgAlert("addContact command not executed", "CloudBridge")
                endif
                return
            endif
            
            // Procura contatos no dispositivo
            if codeType == "findContact"
                if getJsonHash(codeContent, @oTmpHash)
                    aContacts := {}

                    oTMobCont := TMobileContact():New()
                    aContacts := oTMobCont:FindContact( getHField( oTmpHash, "filter" ) )
                    VarInfo( "Contatos encontrados", aContacts )
                else
                    _msgAlert("findContact command not executed", "CloudBridge")
                endif
                return
            endif

        endif

        if codeType == "change_link"
            oGetLink:cText := codeContent+space(1000)
            return
        endif

        // SQLITE - BEGIN -----------------------------------------------------------------------------

        // SQLITE - Begin transction
        if codeType == "dbBegin" .and. getJsonHash(codeContent, @oTmpHash)
            if TCSQLExec("BEGIN") < 0
                // Executa o CallBack de ERRO
                fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
                oWebEngine:runJavaScript(fnCallBack)
            else
                // Executa o CallBack de SUCESSO
                fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
                oWebEngine:runJavaScript(fnCallBack)
            endif
        endif

        // SQLITE - Commit
        if codeType == "dbCommit" .and. getJsonHash(codeContent, @oTmpHash)
            if TCSQLExec("COMMIT") < 0
                // Executa o CallBack de ERRO
                fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
                oWebEngine:runJavaScript(fnCallBack)
            else
                // Executa o CallBack de SUCESSO
                fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
                oWebEngine:runJavaScript(fnCallBack)
            endif
        endif

        // SQLITE - RollBack
        
		endif
		
		
		if codeType == "change_link"
			oGetLink:cText := codeContent+space(1000)
			return
		endif
		// SQLITE - BEGIN -----------------------------------------------------------------------------
		// SQLITE - Begin transction
		if codeType == "dbRollbackdbBegin" .and. getJsonHash(codeContent, @oTmpHash)
            			if TCSQLExec("ROLLBACKBEGIN") < 0
                				// Executa o CallBack de ERRO
                				fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
                				oWebEngine:runJavaScript(fnCallBack)
            else
                			else
				// Executa o CallBack de SUCESSO
                				fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
                				oWebEngine:runJavaScript(fnCallBack)
            endif
        endif

        // SQLITE - Executa query
        			endif
		endif
		// SQLITE - Commit
		if codeType == "dbExecdbCommit"
 .and. getJsonHash(codeContent, @oTmpHash)
			if TCSQLExec("COMMIT") < 0
				// Executa o CallBack de  if getJsonHash(codeContent, @oTmpHash)
                cQuery :ERRO
				fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
				oWebEngine:runJavaScript(fnCallBack)
			else
				// Executa o CallBack de SUCESSO
				fnCallBack = getHField(oTmpHash, "query")

                // Testa query
                if TCSQLExec(cQuery) < 0
                    callBackSuccess") + "();"
				oWebEngine:runJavaScript(fnCallBack)
			endif
		endif
		// SQLITE - RollBack
		if codeType == "dbRollback" .and. getJsonHash(codeContent, @oTmpHash)
			if TCSQLExec("ROLLBACK") < 0
				// Executa o CallBack de ERRO
                    				fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
				oWebEngine:runJavaScript(fnCallBack)
			else
				// Executa o CallBack de SUCESSO
				fnCallBack = getHField(oTmpHash, "callBackSuccess")            + "();"
				oWebEngine:runJavaScript(fnCallBack)
			endif
		endif
		// SQLITE - Executa query
		if codeType == "dbExec"
			if getJsonHash(codeContent, @oTmpHash)
				cQuery := getHField(oTmpHash, "query")
				// Testa   else
                    query
				if TCSQLExec(cQuery) < 0
					// Executa o CallBack de SUCESSO
                    ERRO
					fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
					oWebEngine:runJavaScript(fnCallBack)
				else
					// Executa o CallBack de SUCESSO
					fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
                    					oWebEngine:runJavaScript(fnCallBack)
                endif
            else
                				endif
			else
				_msgAlert("dbExec command not executed", "CloudBridge")
            endif
        endif

        			endif
		endif
		// SQLITE - Recupera dados da query
         da query
		if codeType == "dbGet"
            			if getJsonHash(codeContent, @oTmpHash)
                				cQuery := getHField(oTmpHash, "query")

                				// Testa query
                				if TCSQLExec(cQuery) < 0
                    ) < 0
					// Executa o CallBack de ERRO
                    					fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
                    					oWebEngine:runJavaScript(fnCallBack)

                    return
                endif

                					return
				endif
				// Recupera os dados
                				dbUseArea(.T., 'TOPCONN', TCGenQry(,,cQuery),'TRB', .F., .T.)

                				nFields := TRB->(fCount())
                				nRecords := TRB->(recCount())
                				xRet := "["
                				while !TRB->(eof())
                    xRet += '{'

                    for i :=  1 to nFields
                        					xRet += '{'
					for i :=  1 to nFields
						xRet += quotedStr( fieldName(i) )+":"
                        						xRet += quotedStr( fieldGet(i) ) + iif(i < nFields, ",", "")
                    next i

                     "")
					next i
					xRet += '}' + iif(TRB->(recno()) < nRecords, ",", "")
                    					TRB->(DbSkip())
                end
                xRet += "]"
                				end
				xRet += "]"
				TRB->(dbCloseArea())

                				// Executa o CallBack
                				fnCallBack = getHField(oTmpHash, "callBackSuccess") + "(" +xRet+ ");"
                				oWebEngine:runJavaScript(fnCallBack)
            else
                			else
				_msgAlert("dbGet command not executed", "CloudBridge")
            endif
        endif
        			endif
		endif
		// SQLITE - END -----------------------------------------------------------------------------

        		if codeType == "page_started"
            			//form:loadForm()
        endif

    endif

return

		endif
	endif
return
// Cria componentes superiores
static function CreateFormTop(pnTop)
    	// ---------------------------------------------------------------
    	Local oButton1
    	Local cLink := mainHtml + space(1000)
    	Local oFontBtn := TFont():New("Arial Narrow",,022,,.F.,,,,,.F.,.F.)
    	Local oFontGet := TFont():New("Arial",,022,,.F.,,,,,.F.,.F.)

    	oWebEngine:navigate(mainHtml)

    	@ 000, 221 BUTTON oButtonL1 PROMPT "<" SIZE 028, 011 OF pnTop ACTION {|| oWebEngine:goBack() } FONT oFontBtn PIXEL
    	@ 000, 221 BUTTON oButtonL2 PROMPT ">" SIZE 028, 011 OF pnTop ACTION {|| oWebEngine:goForward() } FONT oFontBtn PIXEL

    	oGetLink := TGet():New( 000, 000, { | u | If( PCount() == 0, cLink, cLink := u ) },pnTop, 220, 011,,, 0, 16777215,,.F.,,.T.,,.F.,,.F.,.F.,,.F.,.F. ,,"cLink",,,, )
    	oGetLink:setFont(oFontGet)

    	@ 000, 221 BUTTON oButton1 PROMPT "Go" SIZE 028, 011 OF pnTop ACTION {|| oWebEngine:navigate(cLink) } FONT oFontBtn PIXEL
    	@ 000, 221 BUTTON oButton2 PROMPT "Menu" SIZE 028, 011 OF pnTop ACTION {|| oGetLink:cText:=mainHtml, oMultGet:Load(""), oWebEngine:Navigate(mainHtml) } FONT oFontBtn PIXEL

    	@ 000, 221 BUTTON oButtonClose PROMPT "X" SIZE 028, 011 OF pnTop ACTION {|| oDlg:end() } FONT oFontBtn PIXEL
    	oButtonClose:setCSS("QPushButton{margin: 1px; background-color: #C75050; border: none; color: #fff; }")

    	oGetLink:setCSS("QLineEdit{margin: 1px; border: 1px solid "+_colorTOTVS)

    	oButtonL1:Align     	:= CONTROL_ALIGN_LEFT
    	oButtonL2:Align     	:= CONTROL_ALIGN_LEFT
    	oButtonClose:Align     	:= CONTROL_ALIGN_RIGHT
    oButton2:Align         	oButton2:Align 		:= CONTROL_ALIGN_RIGHT
    	oButton1:Align         		:= CONTROL_ALIGN_RIGHT
    	oGetLink:Align         		:= CONTROL_ALIGN_ALLCLIENT

return

// ---------------------------------------------------------------
// Funcoes de apoio
// ---------------------------------------------------------------
static function _conout(cText)
    	conOut(cText)
    	oMultGet:Load(cText)
Return

Static function _msgAlert(cText)
    	// Android Ou iOS
    	if _rmtType == 8 .Or. _rmtType == 9
        		oMobile:CreateNotification(999, "CloudBridge", cText)
    	else
        		msgAlert(cText,"")
        		conout(cText)
    	endif
Return

static function quotedStr(xText)
return ('"'+ cValToChar(xText) +'"')