Custom apps

Custom Apps

LB Phone allows you to add apps that either have a UI or simply trigger functions when opening the app. To add an app that triggers a function upon opening it, go to lb-phone/config/config.lua and add the app to the Config.CustomApps table, like this:

lb-phone/config/config.lua
Config.CustomApps = {
    ["app_identifier"] = { -- A unique identifier for the app, not shown to the user
        name = "App Name", -- The name of the app, shown to the user
        description = "App Description", -- The description of the app, shown to the user
        developer = "LB Phone", -- OPTIONAL the developer of the app
        defaultApp = true, -- OPTIONAL if set to true, app should be added without having to download it,
        game = false -- OPTIONAL if set to true, app will be added to the game section
        size = 59812, -- OPTIONAL in kB
        images = { "https://example.com/photo.jpg" }, -- OPTIONAL array of images for the app on the app store
        ui = "resource-name/ui/index.html", -- OPTIONAL
        icon = "https://cfx-nui-" .. GetCurrentResourceName() .. "/ui/icon.png", -- OPTIONAL app icon
        price = 0, -- OPTIONAL, Make players pay with in-game money to download the app
        landscape = false, -- OPTIONAL, if set to true, the app will be displayed in landscape mode
        keepOpen = true, -- OPTIONAL, if set to true, the app will not close when the player opens the app (only works if ui is not defined)
        onUse = function() -- OPTIONAL function to be called when the app is opened
            -- do something
        end,
        onServerUse = function(source) -- OPTIONAL server side function to be called when the app is opened
            -- do something
        end
    }
}

Custom app using UI

If you want to use a custom UI for your app, you need to create a seperate script and provide the path of the HTML file and send it as ui.

The recommended way to create an app with UI is to create it using exports. We have template apps (opens in a new tab) that you can use for reference.

Adding the app

To add the app, use the following export:

client.lua
local added, errorMessage = exports["lb-phone"]:AddCustomApp({
    identifier = "test-app",
    name = "Test App",
    description = "This is a test app",
    ui = GetCurrentResourceName() .. "/ui/index.html" -- this is the path to the HTML file,
})
 
if not added then
    print("Could not add app:", errorMessage)
end

Removing the app

To remove the app, use the following export:

client.lua
local removed, errorMessage = exports["lb-phone"]:RemoveCustomApp("test-app")
 
if not removed then
    print("Could not remove app:", errorMessage)
end

Sending a message to the UI

To send a message to the UI, you need to use the SendCustomAppMessage export instead of using SendNUIMessage. You would listen for it the same way in the frontend. Here's how to use it:

client.lua
exports["lb-phone"]:SendCustomAppMessage("test-app", {
    message = "Hello world!"
})

Imported JS functions

When the app gets loaded on the phone, a few functions are imported into the globalThis object. These functions are:

fetchNui(event, data?, scriptName?)

fetchNui('getDirection').then((direction) => {
    console.log(direction)
})

setPopUp(data)

setPopUp({
    title: 'Popup Menu',
    description: 'Confirm your choice',
    input: {
        type: 'text', //Any HTML input type
        placeholder: 'Enter your name',
        value: 'John Doe',
        minCharacters: 3,
        maxCharacters: 20,
        onChange: (value) => {
            console.log(value)
        }
        // Any other input attributes
    },
    buttons: [
        {
            title: 'Cancel',
            color: 'red',
            cb: () => {
                console.log('Cancel')
            }
        },
        {
            title: 'Confirm',
            color: 'blue',
            cb: () => {
                console.log('Confirm')
            }
        }
    ]
})

setContextMenu(data)

setContextMenu({
    title: 'Context menu',
    buttons: [
        {
            title: 'Phone Notification',
            color: 'blue',
            cb: () => {
                sendNotification({ title: notificationText })
            }
        },
        {
            title: 'GTA Notification',
            color: 'red',
            cb: () => {
                fetchNui('drawNotification', { message: notificationText })
            }
        }
    ]
})

setContactModal(phoneNumber)

setContactModal('1234567890')

selectGallery(data)

selectGallery({
    includeVideos: true,
    includeImages: true,
    cb: (data) => {
        setPopUp({
            title: 'Selected media',
            attachment: data,
            buttons: [
                {
                    title: 'OK'
                }
            ]
        })
    }
})

selectGIF(cb)

selectGIF((gif) => {
    console.log(gif)
})

selectEmoji(cb)

selectEmoji((emoji) => {
    console.log(emoji)
})

getSettings()

getSettings().then((settings) => {
    let theme = settings.display.theme
    console.log(theme)
})

getLocale(path, format?)

getLocale('BACKEND.CAMERA.TAKE_PHOTO', { key: 'Enter' }).then((locale) => {
    console.log(locale)
})

sendNotification(data)

See SendNotification for more information.

sendNotification({ title: 'Notification Text' })

onSettingsChange(cb)

onSettingsChange((settings) => {
    let theme = settings.display.theme
    console.log(theme)
})

useCamera(cb, options?)

useCamera(
    (url) => {
        console.log(url)
    },
    {
        default: {
            type: 'Photo', // 'Photo' | 'Video' | 'Landscape'
            flash: false,
            camera: 'rear' // 'rear' | 'front'
        },
        permissions: {
            toggleFlash: true,
            flipCamera: true,
            takePhoto: true,
            takeVideo: true,
            takeLandscapePhoto: true
        }
    }
)

createCall(options)

See CreateCall for more information.

createCall({
    number: '1234567890',
    company: 'police', // if you want to call a company, don't provide a number
 
    videoCall: false,
    hideNumber: false
})

setApp(app | options)

Opens an app, optionally with metadata

setApp({
    name: 'Mail',
    data: {
        view: 'newMail',
        recipient: '[email protected]'
    }
})

formatPhoneNumber(phoneNumber)

Formats a phone number using the format provided in the lb-phone config.

let formattedNumber = formatPhoneNumber('1234567890')