feat(account): add QR invitation poster and 8-character invitation codes

- Invite opens an appearance-matched poster with the app icon, inviter name,
  QR code, and short code; tap for a full-brightness QR view; save (add-only
  Photos access), share, or copy the link. Mac shows the poster in a popover
  and can save it as PNG.
- Accounts get look-alike-free 8-character codes. "I have a code" accepts a
  code, link, or pasted message during the server-defined binding window.
- Permanently rejected redemptions show a specific message and drop the
  stored code instead of retrying on every sign-in.
This commit is contained in:
2026-10-20 20:06:36 +02:00
parent eaacc35cf7
commit 03bfbbe08b
26 changed files with 2269 additions and 86 deletions
+15
View File
@@ -498,6 +498,16 @@
"mac.account.invite.rewarded" = "Rewarded invites";
"mac.account.invite.pending" = "Pending invites";
"mac.account.invite.footnote" = "Both of you get credits once an invited friend qualifies.";
"mac.account.invite.qr" = "QR Code";
"mac.account.invite.qrHint" = "Scan with a phone, or save the poster and send it to a friend.";
"mac.account.invite.savePoster" = "Save Poster…";
"mac.account.invite.saveFailed" = "Couldn’t save the poster.";
"invite.poster.slogan" = "Your AI voice double";
"invite.poster.hint" = "Scan to try it and earn credits";
"invite.poster.defaultInviter" = "OSG User";
"invite.poster.inviter" = "%@ invites you to try\nOSG AI Keyboard";
"invite.poster.scan" = "Scan to download and enter the code to earn credits";
"invite.poster.code" = "Invitation code: %@";
"mac.account.delete.title" = "Delete Account";
"mac.account.delete.body" = "Deleting removes your account and any remaining credits. This cannot be undone.";
"mac.account.delete.action" = "Delete Account…";
@@ -523,6 +533,11 @@
"account.referral.error.notFound" = "Your invitation link isn’t available yet.";
"account.referral.error.session" = "Sign in again to load your invitation link.";
"account.referral.error.unavailable" = "The invitation service is temporarily unavailable.";
"account.referral.redeem.error.invalid" = "This invitation link is invalid, or the campaign has ended.";
"account.referral.redeem.error.expired" = "The time to add an invitation to this account has passed.";
"account.referral.redeem.error.self" = "You can’t use your own invitation.";
"account.referral.redeem.error.alreadyBound" = "This account has already accepted another invitation.";
"account.referral.redeem.error.ineligible" = "This account can’t accept this invitation.";
/* Rime / typing engine errors */
"error.rime.appGroupUnavailable" = "App Group unavailable.";