mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-28 17:01:18 +00:00
30559048fd
* 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>
168 lines
5.0 KiB
Lua
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")
|