Releases: Samuels-Development/sd-phone
Release list
v0.9.4
Calls
The in-call screen stopped being decorative — every control on it now does something.
- Mute and speakerphone actually work, wired through to the voice backend rather than just lighting up
- An in-call keypad with real DTMF tones, so phone trees and automated lines can be navigated mid-call
- A contacts overlay during a call, to look someone up without dropping the line
- Calls now surface as an island with a peek — the ongoing call stays visible and one-tap returnable while you use the rest of the phone
- Saved emails: addresses you send to can be saved and reused, with compose autofill, a picker sheet, and a prompt offering to save the address the first time you mail it (#105)
- Document attachments: attach a document from Files to an email. The attachment is snapshotted server-side at send time, so it stays exactly what you sent even if the original changes later, and the recipient can download it straight into their own Files
- The detail action bar no longer disappears while the page slides in (#103)
Files & documents
The signature system grew a second half: originals that come back countersigned.
- Signature requests — hand your document to a nearby player through AirShare and get it back with their signature on your original, rather than on a copy
- Counter-signing gates on the viewer's own signature, so a document you have already signed asks the other party, not you
- An inline-image block editor for player-authored documents, so a document can be written with pictures in place instead of raw URLs
- Owners can now delete any file they hold, with a
deletable = falseopt-out for issuing resources that need a document to stick - A visual pass: grey document view, badge pills, a larger signature counter and sign button, and the create dialog now blurs the tab bar behind it
- Fixed: documents created with a numeric
locked = 0were stored as locked, because 0 is truthy in Lua. Affected rows unlock themselves on first boot
Birdy
- The hand-drawn Birdy mark replaces the borrowed Lucide feather across every brand surface — icon, splash, empty states (#102)
- Real trending hashtags, computed server-side from recent posts, plus hashtag search that actually returns posts (#104)
- Photo and GIF replies, with a GIF picker in the reply composer
- A legibility pass: larger avatars, post text and action icons, so the feed no longer reads smaller than the rest of the phone. Edit Profile was rebuilt to match the iOS forms elsewhere, and New Message now pushes in like every other drill-in (#120)
- Notification rows put the avatar and text on one line (#114)
AirShare
- The share prompt now expands out of the dynamic island the way iOS does, and the nearby-player picker resolves names through your contacts instead of showing raw identifiers
Security
Two ways to mint money were found and closed (#115). Both were reachable by a modified client, and both ended in real bank funds:
- The stock market filled buy and sell orders at the price quoted before the order's own market impact was applied, so a round trip could pocket the difference
- Blackjack credited a winning hand's payout before clearing the hand, so a hand could be settled more than once against a single wager
Updating is recommended for any server running the Stocks or Casino apps.
Performance
A full audit of the Lua side, with the fixes landing across five changes. Nothing here changes behaviour — it changes how much the server does to produce it.
- Player identity resolution is now O(1) (#119). Resolving a citizenid to a connected player used to scan every player on the server and ask the framework for each one; it is now an indexed lookup, invalidated on connect, disconnect and character switch. On a 200-slot server this takes a busy second from ~5,000 framework calls and 12,000 list iterations to none
- Notification fan-outs resolve recipients once instead of once per recipient, and Birdy writes its follower notifications in a single statement rather than one per follower (#117)
- Badge pushes carry only the app that changed (#118). A new post used to recompute all seven unread counts for every recipient, including an unindexable scan of the mail table that a post cannot affect
- Pages and Marketplace feed updates go only to players with the app open (#122). Every classified post previously pushed a message to every connected player, which the vast majority received and discarded
- Eleven smaller wins (#116): stock price broadcasts scoped to open apps, the settings screen built from one query instead of sixteen, the friends live-location loop no longer re-reading the roster every tick, missing indexes on the game leaderboards and Cherry matches, phone-number lookups made index-seekable, and a boot-time full-table update that ran on every start now running once
Settings
- Screen brightness persists across restarts and reconnects — it had never been saved, and reset to full every time the phone reloaded (#121)
Configuration
configs/homescreen.lua is now configs/apps.lua, and every app carries explicit flags:
base = true— ships installed and cannot be removed; never appears in the App Storeenabled = false— the app does not exist on this server: hidden from the home screen and the App Store, uninstallable, and removed from phones that already had it. Server modules keep running; only the app's presence on the phone is gated
Upgrading
If you customized configs/homescreen.lua, copy your changes over before restarting. That file is gone in this release, replaced by configs/apps.lua — your dock, wallpaper and app list will fall back to the defaults otherwise. It is the only manual step.
Everything else is drop-in. New columns, indexes and the two one-time data repairs create and run themselves on first boot; the repairs record themselves in phone_migrations so they never run twice. The first start after updating may take slightly longer than usual while indexes build.
As always, the attached sd-phone.zip ships the built UI.
v0.9.3
Files
A full file manager joins the phone as a base app — preinstalled for everyone, with Browse and Recents tabs, nested folders, text documents with a built-in editor, imported images and external files, AirShare to nearby phones, and per-character persistence that follows your phone across sessions and SIM restores.
Files is also the phone's new paperwork layer for other scripts: an exports API lets any resource put documents on a player's phone — citations from an MDT, contracts from a dealership, licenses from city hall.
createDocument/createDocumentForNumbercreate documents with named folders (auto-created), live delivery into an open phone, and optional notification banners- Documents marked
lockedare read-only for the player — no editing, renaming, or deleting — while the issuing resource can still revoke them withdeleteDocumentById getPlayerDocumentsandgetDocumentContentread a player's library back- Illustrated documents: in the read-only view, any content line that is exactly one URL renders as an inline image — dossiers with surveillance stills, deeds with property photos, inspection reports with a picture per finding, all in a single document
- Full API reference with worked examples at docs.samueldev.shop
Document signatures
Documents can now be signed — and the signatures are real, not decoration (suggested by the community, thank you!).
- Draw your signature once on a signature pad, or type your name and pick one of four signature styles (Elegant script, Script, Formal italic, Typewriter); after that, signing any document is one tap with a confirmation dialog
- Signatures are server-verified: each records the signer's identity, their display name frozen at signing time, an image snapshot, and the timestamp. The verified badge renders from server rows, never from document text — a signature cannot be forged by typing a name
- Signing freezes the document's content and name; delete, move, duplicate and AirShare stay available, and shared copies carry their signatures verifiably
- Script-issued locked documents are signable by design — issue a locked agreement, then check for the player's signature before releasing keys or titles
- New
getDocumentSignaturesandisDocumentSignedexports for that verification, documented with dealership and court examples
Unique phones & SIM setups
The unique-phones system grew into a family of setups, with a pick-your-setup guide in configs/uniqueandsim.lua (#81).
- Device-owns-data mode: the phone item owns the data — swap phones and your world moves with the handset, exactly like real hardware
- Built-in numbers mode: unique phones without SIM cards; every handset carries its own number
- Character data mode: the stock per-character data model with SIM-card numbers layered on top
- Blank SIM cards now self-activate on first use
- Phones open instantly: the SIM resolve moved off the reveal path (#79)
Wallpapers, like a real iPhone
- Separate Lock Screen and Home Screen wallpapers — tap either preview on the Wallpaper page to set that screen individually, or choose one wallpaper for both (#91)
- A blur toggle per screen, both persisted — blur previously reset on every reconnect
- The previews are now true-to-phone miniatures of your actual screens: your customized lock clock, the real icon grid and dock, and live blur that matches the in-game effect exactly
Settings
- Phone scale and phone position finally persist across restarts and reconnects (#84 — thanks for the report!), and they ride SIM backups too (#85, #87)
- Software Update now shows the real installed version and checks the latest GitHub release — when a new release is out, the page tells you (#89)
- Slider changes now write once per drag instead of once per tick (#88)
- A polish pass across the settings sub-pages: list dividers run full-bleed, hero cards sit on the house card grey, and the battery percentage is finally legible in light mode (#89, #90)
- The Files icon joined the dark-tile family — no more bright white glare in the icon set (#92)
Input & controls
- Scroll lock: with the phone open, the mouse wheel belongs to the phone — no more changing radio stations while scrolling a list in a car, no weapon cycling on foot (#95)
- Number pads don't freeze you anymore: entering your lockscreen PIN or dialing keeps WASD movement alive, while proper text typing still locks input to the field as before (#96)
- Physical keyboard support for every digit keypad — lockscreen, dialer, payphone, Face Unlock (#83)
Apps round-up
- Birdy: a frontend polish pass with new feather branding, and post timestamps now follow the app's locale (#68)
- Dark Chat: a per-room notifications toggle, and room creators can remove members (#73)
- Services: per-job commission on paid business invoices (#80)
Localization
- Turkish (tr) catalog — teşekkürler! (#77)
- The English catalog topped up with 256 keys that were missing from the scan
Upgrading
Drop-in: all new database columns and tables (settings persistence, per-screen wallpapers, signatures) create and backfill themselves on first boot — no manual migration. As always, the attached sd-phone.zip ships the built UI.
v0.9.2
Vibez
Vibez has been on the phone for a while as a frontend-only mock; this release gives it a real server backend (#55). The frontend still needs a proper round of work, so expect rough edges there while that lands in a coming release.
- The feed, likes, comments, Discover and profiles are now backed by the server, with editing and uploads through the shared media pipeline
- Accounts run on the shared accounts engine: register, sign in, password resets by text from the app's short code
- Go live: real live streaming with a host view, a viewer with live comments, and late-join support
- Admin moderation tooling wired into the phone's admin panel
- Inbox notifications with a proper home-screen badge, server-authoritative like the other social apps
Payphones (beta)
Street payphones landed (#56) and got a full follow-up round. Treat them as a beta for now: they work, but there is more to do before they're considered finished.
- Working payphone booths across the map with static numbers; call out from a booth, or answer one that's ringing
- Booths play a proper handset scene: the world prop swaps for an animated one and the ped grabs the handset
- Coin-operated calling (optional,
configs/payphone.lua): the LCD reads INSERT COIN, feeding the slot charges the configured cost and unlocks the keypad, a failed dial keeps your credit, answering is always free - A fully redrawn machine UI: brushed-steel enclosure, hanging handset that lifts during calls, green LCD, riveted placard and taped-on notes
- ox_lib menu mode for servers that prefer context menus over the machine UI; the menu flow charges the coin toll on dial
- Ring matching is tight enough for payphone banks, so the booth next to a ringing one no longer offers Answer Phone
Invoicing
Invoicing arrived in two layers this release: businesses first, then everyone.
Business invoicing (Services)
- On-duty employees send invoices from their business (suggested in #62): recipient by phone number or server ID, amount and note, with server-side validation and configurable bounds (
configs/services.lua) - Payments land in the business society account where society banking exists, with a personal-bank fallback and an automatic refund if crediting fails; the sender gets a paid notification
- The Actions tab now has two clean entries: Send Invoice opens a full slide-in composer page, View Invoices opens the business ledger with pending and settled invoices, status chips and cancelling
Personal invoicing (Wallet)
- The Wallet grew a tab bar: Home is the familiar wallet, and a new Invoices tab (with a pending-count badge and swipe transitions) holds everything invoice-shaped (#75)
- Anyone can invoice anyone: full-page composer with a contact picker, drafts that survive closing the phone, and recipients by phone number or server ID
- Received shows business and personal invoices together, pending pinned on top, with settled history kept as Paid/Cancelled chips so a cancelled invoice explains itself instead of vanishing
- Sent tracks your own invoices with live status and cancelling
- Anti-spam guard rails in
configs/banking.lua: amount bounds plus a cap on outstanding unpaid invoices per sender - Identity follows your contact book everywhere: saved contacts show their name and avatar, strangers show their number, in rows, dialogs and even the notification banners, and adding or deleting a contact updates open lists on the spot
Wallet
- Every invoice payment carries a short reference code, printed on both parties' transactions (
Invoice Paid · 4F09AC) and beside every invoice title, so payments and invoices match up from either side; invoice transactions have their own category and receipt icon - The balance now updates live when money moves from anywhere, not just phone features: the phone listens to the framework money broadcasts, so a paycheck or a shop purchase ticks the balance while the Wallet is open
- Every bank movement from any script now lands in the transaction list as a labelled row (qb/qbox), with phone-driven movements deduplicated so transfers and invoices keep their single richer entry
- The Wallet and the Services company balance both re-sync the moment the app is foregrounded, closing the stale-balance-until-reopen gap
Phone shell
- The phone can reopen straight into the app you were using, now a per-player toggle in Settings (Reopen Last App)
- iOS-style reveal animations across the shell, plus settings row polish
- The phone opens noticeably faster: the hold animation and the installed-app list moved off the critical path, so the UI reveals instantly and reconciles in the background (#57)
/wipemyphoneno longer strands NUI focus, and a wipe mid-payphone-call now tears the booth session down properly
Messages and contacts
- Save a number from a conversation: unknown-number threads offer Add Contact in the header, opening the contact form prefilled in a standard sheet; automated senders like password-reset short codes are excluded (#60)
- Conversation names resolve live against your contacts: deleting a contact reverts their threads to the number, renames propagate instantly (#58)
- Unknown numbers show a proper person silhouette instead of number-derived initials, across the messages list, conversation headers, recents, No Caller ID calls, call screens and the Add Contact photo placeholder (#59)
- The call detail page updates in place after Add to Contacts: saved name, avatar, and the add button gone
Fixes
- Garage status labels no longer surface in the wrong language: they resolve against the active locale on every render instead of freezing at first load (#65)
- The Health app's Time Awake starts counting from character load, not from the first time you open the app; steps and heart rate were always session-tracked (#64)
- Mark All Read in Mail now clears the home-screen badge, and the underlying write race that silently lost read flags on restart is gone (#61)
- Birdy got a full round of reported fixes: feed, follows, comments, reposts, notifications, privacy, DMs and avatars (#37)
- Picking dark mode during setup (or any setting, on a slow first join) no longer reverts to defaults after a relog: the character-load rehydrate was silently lost in the Vibez merge and is restored, so theme, wallpaper, tones and language apply the moment the character loads
Under the hood
- The project is now licensed under GPLv3, same as the frameworks it runs beside
- Adding a language is now a one-file job: drop a
locales/<code>.jsonin and it appears in the Setup and Settings language pickers automatically with its native name (a UI rebuild is still required, since catalogs are bundled as lazy chunks) - New
phone_service_invoicestable with an idempotent boot migration; existing installs upgrade in place - The
/mailseedtest command is gone (again)
Contributors
Thanks to everyone who contributed to this release:
- @Epixx1337: Vibez, street payphones, and the Birdy fix round
- @ihyajb: faster phone opening and the wipe focus cleanup (#57)
- @boppescripting: reported #58, #61 and #64, and suggested contact saving (#60), silhouette avatars (#59) and business invoicing (#62)
- @OhNoItsOri: reported the garage locale bug (#65)
Full changelog: v0.9.1...v0.9.2
v0.9.1
The Mail app got a major round of upgrades this release.
Attachments
- Attach photos, voice memos and notes to emails (up to 5 per mail) via the paperclip in the composer
- Multi-select pickers in the same style as the shared media picker, with full previews before sending: play memos, read notes, view photos in the lightbox
- Recipients can play memos and read notes inline, open photos fullscreen, and save any attachment into their own Photos, Voice Memos or Notes apps. Saves are duplicate-safe and the saved state is remembered across sessions; senders viewing their own mail see no save buttons
- Attachments survive the full draft cycle: save as draft, resume, edit, re-send
- Script integration:
exports['sd-phone']:sendMailnow accepts attachments (plain URL strings or taggedphoto/audio/notetables), and the lb-phoneSendMailcompat delivers itsattachmentsfield as real photo attachments instead of URLs appended to the body
Mailbox management
- Edit mode in every folder: select multiple emails, batch delete (to the Bin first, permanently from inside the Bin), Mark Read for a selection, or Mark All Read with nothing selected (suggested in #49)
- New mail now fires a proper phone banner notification (#10)
- Drafts reopen in the composer for editing instead of the read-only viewer, and re-sending or re-saving replaces the old draft instead of duplicating it (#10)
- Smarter compose cancel: an untouched draft or reply closes silently; real edits get honest "Discard Changes / Save Changes" options
- Folder reordering in the mailbox list is no longer glitchy in-game, and displaced folders now slide smoothly into place
- Reading view polish: consistent background shade, a standard bottom action bar, a larger sender header, and working previous/next arrows with a directional transition
- Changing your mail password now offers to save the new login to the Passwords app when it was never stored there (#10)
- Removed the stray extra @ in front of the address in the mailbox account header (#10)
Photos and wallpaper
- Batch favourite photos straight from the selection bar, plus a redesigned album picker grid
- Set your own photos as wallpaper, and import custom wallpapers via link
Games
- Blackjack dealing is now server-authoritative, with client-side chip settling retired
- Game chips: solo and co-op settle payouts are now backed by a per-character escrow, closing an infinite-money mint exploit across the casino games (#52)
- Battleship: no shots until both fleets are deployed (#33), and shot hits/misses show immediately
Fixes
- Wallpaper and language no longer reset to defaults after a slow join or a character switch; settings hydrate the moment the character loads
- The Passwords app refreshes when brought back to the foreground, so password changes show without fully closing it; saved dates also follow the phone locale (#31)
- Uninstalled apps can no longer be opened through the back door: notifications, deeplinks, server-triggered launches and Control Center all respect the installed list now and route to the App Store instead (#46)
- Groups (#46):
- Going offline now reaches co-members: the server tracks lifecycle events and nudges every online co-member's app when someone disconnects, so online dots no longer stay green until a manual refresh. Create/accept responses also carry real online states right away
- Uninstalling Groups now cleans up properly: led groups disband with members notified, plain memberships are removed with the leader notified, pending invites are dropped. This ships as a first-party
sd-phone:server:apps:uninstalledevent any stateful app can hook
- Cherry (#48):
- The signup age field no longer accepts
e/+/-: number fields in the shared auth form are digit-only now - Profile changes reach your matches live: saving your profile pushes the fresh card to every online matched partner, and the app also refetches when brought back to the foreground
- The unread dot was cherry-pink on a cherry-pink placeholder avatar, literally invisible; it now carries a white ring so it reads everywhere
- The signup age field no longer accepts
- Photo uploads: one capture upload per player at a time, and a shared per-character upload budget across all Fivemanage paths
Under the hood
- The compiled UI (
web/build) is no longer tracked in the repository. Use the release asset below, or build it yourself withnpm run buildinweb/ - Repo housekeeping: internal design documents no longer live in the source tree
Contributors
Thanks to everyone who contributed to this release:
- @Epixx1337: mail notifications, draft editing and vault offer, battleship deploy gate, passwords date locale, groups and Cherry fixes
- @LouayeG: blackjack chips escrow fix
- @boppescripting: suggested Mark All Read (#49)
Full changelog: v0.9.0...v0.9.1
v0.9.0
First packaged release, nearing a 1.0.0 full release.
Install
Download sd-phone-v0.9.0.zip below (the packaged release). Drop the sd-phone folder into your resources and ensure it after ox_lib and oxmysql. Full guide in the README and the docs.
The zip is built from source and attached automatically by CI.