diff --git a/README.md b/README.md index 22f9e6a..836763f 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ An iFruit account is optional. Unlinked devices retain local settings, alarms, m - A FiveManage V3 Media API token for Camera photo/video uploads and Gallery deletion. Set the server-only `Config.Media.FiveManage.ApiKey` in `sky_phone/config/media.lua`; the token is never sent to NUI because clients receive temporary presigned upload URLs instead. +- `yaca-voice`, `pma-voice`, or `saltychat` when the Radio app is enabled. `Config.Radio.VoiceProvider = "auto"` selects the first running provider in that order. ## Messages GIF provider @@ -77,6 +78,14 @@ For a fresh manual database installation, import `sky_phone/sql/install.sql`. It Framework, inventory, callback, notification, and database integrations live under `sky_phone/source/bridge`. The resource has no dependency on any other Sky resource. +## Radio app + +The built-in Radio app supports a primary frequency, volume, recent channels, participant lists, automatic rejoin, join/leave notifications, and an optional service number. YACA and SaltyChat support the configured secondary frequency; PMA Voice exposes one radio channel, so the secondary input is hidden automatically. + +Configure frequency bounds and precision, restricted channel ranges and allowed jobs, history length, defaults, badge validation, radio display-name permissions, and the built-in speaker HUD under `Config.Radio`. `Config.Radio.DisplayName.AllowedJobs` maps authoritative framework job names to their minimum grade. Unlisted jobs cannot change the name; an empty name restores the normal player or character name. Channel and display-name access are always checked server-side. `Config.Radio.Hud` controls the phone-owned overlay, its screen edge, offsets, and recent-speaker duration without depending on another HUD resource. Active-speaker highlighting uses the YACA radio events; the Radio app itself continues to support every configured voice provider. + +Radio profiles are stored in `sky_phone_radio_profiles`. Runtime migration creates the table automatically; fresh installations receive it through `sky_phone/sql/install.sql`. + Inventory metadata has no framework-wide standard: providers differ in export names, callback payloads, slot handling, and whether metadata is called `metadata` or `info`. For that reason, `sky_phone` uses explicit provider adapters instead of guessing exports at runtime. Every supported adapter implements slot lookup, item lookup, metadata replacement, capacity handling, add/remove operations, and usable-item registration. Providers without a separate capacity export use their authoritative add operation as the final capacity gate. When a SIM is ejected or replaced, the returned inventory item is rebuilt from the authoritative `sky_phone_sims` row. Its metadata contains `sim_metadata_version`, `sim_id`, `phone_number`, `formatted_number`, and `sim_type`. Registered SIMs additionally contain `firstname`, `lastname`, `birthdate`, and `registered_at`. The internal framework owner identifier remains database-only. Inserting the item again resolves the SIM by `sim_id`; contacts and device/cloud data remain attached to their existing phone-owned persistence instead of being copied into inventory metadata. diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 9c40798..a21e397 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -18,6 +18,7 @@ import PhonePasscode from '@/components/PhonePasscode.vue' import PhoneNotifications from '@/components/PhoneNotifications.vue' import NotificationPhonePreview from '@/components/NotificationPhonePreview.vue' import PhoneStatusBar from '@/components/PhoneStatusBar.vue' +import RadioHud from '@/components/RadioHud.vue' import SimPhonePicker, { type SimPhoneChoice, } from '@/components/SimPhonePicker.vue' @@ -364,6 +365,7 @@ function onMessage(event: MessageEvent): void { appId: 'calendar', subtitle: new Intl.DateTimeFormat(phone.lang, { hour: '2-digit', + hourCycle: 'h23', minute: '2-digit', }).format(startsAt), text: @@ -757,6 +759,7 @@ onBeforeUnmount(() => {