Árvore de páginas

Você está vendo a versão antiga da página. Ver a versão atual.

Comparar com o atual Ver Histórico da Página

« Anterior Versão 5 Próxima »

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

#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

    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
    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"
                    xRet := eval(xVal)
                    xRet := cValToChar(xRet) // Converte pra String

                    // Executa o CallBack
                    fnCallBack = getHField(oTmpHash, "callBack")+"('" +xRet+ "')"
                    oWebEngine:runJavaScript(fnCallBack)
                endif
            else
                _msgAlert("RunAdvpl command not executed", "CloudBridge")
            endif
            return
        endif

        // Android Ou iOS
        if _rmtType == 8 .Or. _rmtType == 9

            // Tira foto
            if codeType == "getPicture"
                cFile:= oMobile:TakePicture()
                _conout("[getPicture] - " + cFile)

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

            // Codigo de  barras
            if codeType == "barCodeScanner"
                aBarResult := oMobile:BarCode()
                If aBarResult[1] = ""
                    _conout("[barCode] - " + "Nenhum código de barras disponível.")
                Else
                    _conout("[barCode] - " + "Código: " + aBarResult[1] + chr(13) + "Formato: " + aBarResult[2])

                    // 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 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)+ "')"
                    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

            // 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 := {}

                    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
        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 query
                if TCSQLExec(cQuery) < 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
            else
                _msgAlert("dbExec command not executed", "CloudBridge")
            endif
        endif

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

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

                    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 += quotedStr( fieldName(i) )+":"
                        xRet += quotedStr( fieldGet(i) ) + iif(i < nFields, ",", "")
                    next i

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

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

        if codeType == "page_started"
            //form:loadForm()
        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         := 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) +'"')

  • Sem rótulos