Skip to Content

Custom Apps

See the custom apps exports for adding the app to the tablet. We recommend using our custom app template  to get started with creating custom apps.

Imported data

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

resourceName

The resource name of the app

appName

The name of the app

settings

The tablet settings

onNuiEvent

A function to listen for NUI events sent via SendCustomAppMessage

globalThis.onNuiEvent(event: string, callback: (data: any) => void): void

onSettingsChange

Listen for settings changes

globalThis.onSettingsChange(callback: (settings: any) => void): void

fetchNui

Fetch data from the script

globalThis.fetchNui(event: string, data?: any, scriptName?: string): Promise<any>

setApp

Open another app

globalThis.setApp(app: string): void

closeApp

Close the app

globalThis.closeApp(): void

setPopUp

Show a popup

type PopUp = { id?: number; title: string; description: string; vertical?: boolean; inputs?: PopUpInput[]; input?: PopUpInput; textareas?: PopUpTextarea[]; textarea?: PopUpTextarea; attachment?: { src: string; }; buttons: { title: string; cb?: () => void; disabled?: boolean; bold?: boolean; color?: 'red' | 'blue'; }[]; }; globalThis.setPopUp(data: PopUp): void

setFullScreenImage

Show a full screen image

globalThis.setFullScreenImage(src: string): void

setContextMenu

Show a context menu

type Contextmenu = { id?: number; title?: string; buttons: { title: string; color?: 'red' | 'blue'; disabled?: boolean; cb?: () => void; }[]; }; globalThis.setContextMenu(data: Contextmenu): void

setControlCentreVisible

Show or hide the control centre

globalThis.setControlCentreVisible(visible: boolean): void

setGallery

Select an image or video from the gallery

type GalleryData = { id?: number; includeVideos?: boolean; includeImages?: boolean; allowExternal?: boolean; multiSelect?: boolean; onSelect: (data: PhotoData) => void; }; type PhotoData = { id: number; src: string; timestamp?: number; type?: 'string'; favourite?: boolean; isVideo?: boolean; size?: number; duration?: number; }; globalThis.setGallery(data: GalleryData): void

setColorPicker

Select a color

type ColorPickerData = { id?: number; defaultColor?: string; onSelect: (color: string) => void; onClose?: (color: string) => void; }; globalThis.setColorPicker(data: ColorPickerData): void

setIndicatorVisible

Show or hide the indicator

globalThis.setIndicatorVisible(visible: boolean): void

saveToGallery

saveToGallery: (url: string, size?: number, type?: 'screenshot' | 'selfie' | 'import', shouldLog?: boolean) => Promise<number | false>

uploadMedia

uploadMedia: (uploadType: 'Video' | 'Image' | 'Audio', blob: Blob) => Promise<string>

createGameRender

GameRender

interface GameRender { quality: number xOffset: number yOffset: number recorder: MediaRecorder | undefined recording: boolean destroyed: boolean canvas: HTMLCanvasElement | null gl: WebGLRenderingContext | null program: WebGLProgram | null paused: boolean viewport: { x: number y: number width: number height: number } canvasSize: { width: number height: number } animationFrame: number | null mainTexture: WebGLTexture | null hasPrevFrame: boolean prevTextures: WebGLTexture[] prevBuffers: WebGLFramebuffer[] pause(): void resume(): void resize(width: number, height: number): void resizeByAspect(ratio: number): void setQuality(quality: number): void setXOffset(offset: number): void setYOffset(offset: number): void destroy(keepCanvas?: boolean): void takePhoto(): Promise<Blob> startRecording(cb: (blob: Blob) => void): MediaRecorder | undefined render(): void }
createGameRender: (canvas: HTMLCanvasElement) => GameRender | undefined

getMicrophoneStream

getMicrophoneStream: () => Promise<MediaStream | undefined>

releaseMicrophoneStream

releaseMicrophoneStream: () => void

listenToNearbyVoices

listenToNearbyVoices: (audioCtx: AudioContext, destination: MediaStreamAudioDestinationNode) => void

stopListeningToNearbyVoices

stopListeningToNearbyVoices: () => void