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:
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
Name | Type | Description |
---|---|---|
resourceName | string | The name of the resource that added the custom app |
appName | string | The app name |
settings | object | The settings of the phone |
components | object | Useful 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
})