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 apps 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.

If the user has dark mode enabled, data-theme will be set to dark. Otherwise, it will be set to light.

Adding the app

To add the app, use the AddCustomApp export.

Removing the app

To remove the app, use the RemoveCustomApp export.

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.

Imported components & functions

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

Data

NameTypeDescription
resourceNamestringThe name of the resource that added the custom app
appNamestringThe app name
settingsobjectThe settings of the phone
componentsobjectUseful components for the app

Components

createGameRender

Creates a game render, which renders the game to a canvas. This is used to create a camera in your app, and should be used with the camera exports.

const gameRender = new GameRender(canvas)
 
// Set the aspect ratio
gameRender.resizeByAspect(9 / 16)
 
// pause the rendering
gameRender.pause()
 
// unpause the rendering
gameRender.resume()
 
// take a photo
const blob: Blob = await gameRender.takePhoto()
 
// take a video
const recorder = gameRender.startRecording((blob: Blob) => {
    console.log('Video recorder')
})
 
setTimeout(() => {
    recorder.stop()
}, 5000)
 
// Destroy the game render
gameRender.destroy()

uploadMedia

Uploads media and returns a promise with the URL.

// Upload type can be 'Video' | 'Image' | 'Audio'
const url = await components.uploadMedia('Video', blob)

saveToGallery

Saves a URL to the gallery and returns a promise with the ID

const id = await components.saveToGallery(url)

setColorPicker

components.setColorPicker({
    onSelect(color) {},
    onClose(color) {}
})

setPopUp

components.setPopUp({
    title: 'Popup Menu',
    description: 'Confirm your choice',
    buttons: [
        {
            title: 'Cancel',
            color: 'red',
            cb: () => {
                console.log('Cancel')
            }
        },
        {
            title: 'Confirm',
            color: 'blue',
            cb: () => {
                console.log('Confirm')
            }
        }
    ]
})

setContextMenu

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

setEmojiPickerVisible

components.setEmojiPickerVisible({
    onSelect: (emoji) => {
        components.setEmojiPickerVisible(false)
        components.setPopUp({
            title: 'Selected emoji',
            description: emoji.emoji,
            buttons: [
                {
                    title: 'OK'
                }
            ]
        })
    }
})

setGifPickerVisible

components.setGifPickerVisible({
    onSelect(gif) {
        components.setPopUp({
            title: 'Selected GIF',
            attachment: { src: gif },
            buttons: [
                {
                    title: 'OK'
                }
            ]
        })
    }
})

setGallery

components.setGallery({
    includeVideos: true,
    includeImages: true,
    allowExternal: true,
    multiSelect: false,
 
    onSelect(data) {
        components.setPopUp({
            title: 'Selected media',
            attachment: { src: Array.isArray(data) ? data[0].src : data.src },
            buttons: [
                {
                    title: 'OK'
                }
            ]
        })
    }
})

setFullscreenImage

components.setFullscreenImage('https://docs.lbscripts.com/images/icons/icon.png')

setHomeIndicatorVisible

components.setHomeIndicatorVisible(true)

Functions

fetchNui(event, data, scriptName?)

fetchNui('test', {
    foo: 'bar'
})

useNuiEvent(event, cb)

Listen for NUI messages sent via SendCustomAppMessage

useNuiEvent('test', (data) => {
    console.log(data)
})

onSettingsChange(cb)

Listen for settings changes

onSettingsChange((newSettings) => {
    console.log(newSettings)
})

createCall(data)

createCall({
    number: '1234567890', // you can send `company` instead of `number` to call a company
    videoCAll: false,
    hideNumber: false
})