Files
Leon.Schmidt 30559048fd FIX - complete LB custom app compatibility (#11)
* FIX - preserve LB custom app lifecycle

* FIX - reset LB export aliases before startup

* FIX - report competing custom app providers

* FIX - identify LB app frames as live NUI

* FIX - complete LB custom app compatibility

* FIX - provide LB PicChat runtime exports

* FIX - route LB PicChat through Sky Phone

* FIX - return cached LB equipped phone number

* FIX - harden PicChat compatibility migration

* ENH - complete modular phone provider and Creator APIs

* DOC - document the Sky Phone Creator API

---------

Co-authored-by: DerEchteAlec <bycraky@gmail.com>
Co-authored-by: DerEchteAlec <alec.schitzkat@luwan.io>
2026-08-20 18:19:16 +02:00

168 lines
5.0 KiB
Lua

local net_events = {}
local nui_messages = {}
local registered_apps = {
["custom-chat"] = true,
messages = true,
}
Config = {
Bridge = {
Locale = "en",
},
}
SkyPhoneApps = {
CanReceiveNotification = function(app_id)
return registered_apps[app_id] == true
end,
ValidateAppId = function(app_id)
return type(app_id) == "string"
and #app_id <= 64
and app_id:match("^[a-z0-9][a-z0-9._-]+$") ~= nil
end,
}
SkyPhoneLocales = {
Resolve = function()
return {
Nui = {
Apps = {},
},
}
end,
}
SkyPhoneNavigation = nil
Bridge = {
Callbacks = {
Trigger = function(name, notification)
assert(name == "sky_phone:notifications:self")
assert(notification.device == nil, "self notifications must not carry caller device data")
return { success = true, data = { delivered = 1 } }
end,
},
Debug = function() end,
Framework = {
Notify = function() end,
},
}
function RegisterNetEvent(name, callback)
net_events[name] = callback
end
function SendNUIMessage(message)
nui_messages[#nui_messages + 1] = message
end
function TriggerEvent()
end
assert(loadfile("sky_phone/source/shared/imei.lua"))()
assert(loadfile("sky_phone/source/client/notifications.lua"))()
local success, error_code = SkyPhoneNotifications.Show(nil)
assert(not success and error_code == "invalid_notification", "non-table notifications must be rejected")
success, error_code = SkyPhoneNotifications.Show({
appId = "messages",
app_id = "mail",
title = "Title",
text = "Text",
})
assert(not success and error_code == "invalid_app_id", "conflicting app aliases must be rejected")
success, error_code = SkyPhoneNotifications.Show({
appId = "missing-app",
title = "Title",
text = "Text",
})
assert(not success and error_code == "invalid_app_id", "unknown apps must not receive notifications")
success, error_code = SkyPhoneNotifications.Show({
appId = "messages",
title = string.rep("x", 161),
text = "Text",
})
assert(not success and error_code == "invalid_title", "notification titles must be bounded")
success, error_code = SkyPhoneNotifications.Show({
app_id = "custom-chat",
body = " Custom body ",
device = {
imei = "123456789012347",
name = "Spoofed",
},
title = " Custom title ",
url = "https://invalid.example",
})
assert(success, error_code)
assert(#nui_messages == 1, "valid local notifications must reach NUI while the phone is closed")
assert(nui_messages[1].type == "notification:show", "notification NUI route changed")
assert(nui_messages[1].data.appId == "custom-chat", "app_id alias was not normalized")
assert(nui_messages[1].data.route == "/apps/custom-chat", "safe app route was not generated")
assert(nui_messages[1].data.title == "Custom title", "title was not normalized")
assert(nui_messages[1].data.text == "Custom body", "body alias was not normalized")
assert(nui_messages[1].data.device == nil, "local callers must not inject a device context")
assert(nui_messages[1].data.url == nil, "arbitrary URLs must not cross the notification boundary")
local send_result
success, send_result = SkyPhoneNotifications.Send({
appId = "messages",
title = "Server-routed",
text = "Authoritative device",
})
assert(success and send_result.delivered == 1, "self notifications must use the server router")
assert(#nui_messages == 1, "self notifications must wait for authoritative server delivery")
source = 42
net_events["sky_phone:notifications:show"]({
appId = "messages",
device = {
imei = "123456789012347",
name = "Phone",
},
title = "Spoofed",
text = "Spoofed",
})
assert(#nui_messages == 1, "client-triggered delivery events must be rejected")
source = 65535
net_events["sky_phone:notifications:show"]({
appId = "messages",
title = "Missing device",
text = "Rejected",
})
assert(#nui_messages == 1, "server deliveries without a device must be rejected")
net_events["sky_phone:notifications:show"]({
appId = "messages",
device = {
imei = "123456789012347",
name = " Work Phone ",
settings = [[{"version":1}]],
},
title = "Server",
text = "Delivered",
})
assert(#nui_messages == 2, "server-originated delivery must reach NUI while navigation is empty")
local delivered = nui_messages[2].data
assert(delivered.device.imei == "123456789012347", "server IMEI context was dropped")
assert(delivered.device.name == "Work Phone", "server device name was not normalized")
assert(delivered.device.settings == [[{"version":1}]], "server device settings were dropped")
assert(delivered.route == "/apps/messages", "server notification route changed")
net_events["sky_phone:notifications:show"]({
appId = "messages",
device = {
imei = "invalid",
name = "Phone",
},
title = "Invalid",
text = "Rejected",
})
assert(#nui_messages == 2, "invalid server device contexts must be rejected")
print("Client notification router tests passed")