diff --git a/src/app/chat/__tests__/chat-screen.helpers.test.ts b/src/app/chat/__tests__/chat-screen.helpers.test.ts
new file mode 100644
index 00000000..690afada
--- /dev/null
+++ b/src/app/chat/__tests__/chat-screen.helpers.test.ts
@@ -0,0 +1,35 @@
+import { describe, expect, it } from "vitest";
+
+import { getInsufficientCreditsMessageLimitView } from "../chat-screen.helpers";
+
+describe("getInsufficientCreditsMessageLimitView", () => {
+ it("asks guests to log in for more free chats", () => {
+ expect(getInsufficientCreditsMessageLimitView("guest")).toEqual({
+ title: "Log in to get more free chats",
+ description: "Free chats refresh every day. Log in to get more chances.",
+ ctaLabel: "Log in to continue",
+ action: "auth",
+ });
+ });
+
+ it("treats the transient not logged in state like guest", () => {
+ expect(getInsufficientCreditsMessageLimitView("notLoggedIn")).toEqual({
+ title: "Log in to get more free chats",
+ description: "Free chats refresh every day. Log in to get more chances.",
+ ctaLabel: "Log in to continue",
+ action: "auth",
+ });
+ });
+
+ it.each(["email", "facebook", "google", "apple"] as const)(
+ "asks %s users to top up credits",
+ (loginStatus) => {
+ expect(getInsufficientCreditsMessageLimitView(loginStatus)).toEqual({
+ title: "Insufficient credits\nTop up to continue chatting",
+ description: "Free chats refresh every day. You can also top up credits now.",
+ ctaLabel: "Top up credits to continue",
+ action: "topup",
+ });
+ },
+ );
+});
diff --git a/src/app/chat/chat-screen.helpers.ts b/src/app/chat/chat-screen.helpers.ts
index dbb4e122..f01025c1 100644
--- a/src/app/chat/chat-screen.helpers.ts
+++ b/src/app/chat/chat-screen.helpers.ts
@@ -9,10 +9,39 @@ export interface ExternalBrowserPromptState {
loginStatus: LoginStatus;
}
+export type InsufficientCreditsAction = "auth" | "topup";
+
+export interface InsufficientCreditsMessageLimitView {
+ title: string;
+ description: string;
+ ctaLabel: string;
+ action: InsufficientCreditsAction;
+}
+
export function deriveIsGuest(loginStatus: LoginStatus): boolean {
return loginStatus === "guest";
}
+export function getInsufficientCreditsMessageLimitView(
+ loginStatus: LoginStatus,
+): InsufficientCreditsMessageLimitView {
+ if (loginStatus === "guest" || loginStatus === "notLoggedIn") {
+ return {
+ title: "Log in to get more free chats",
+ description: "Free chats refresh every day. Log in to get more chances.",
+ ctaLabel: "Log in to continue",
+ action: "auth",
+ };
+ }
+
+ return {
+ title: "Insufficient credits",
+ description: "Free chats refresh every day. You can also top up credits now.",
+ ctaLabel: "Top up credits to continue",
+ action: "topup",
+ };
+}
+
export function isChatDevelopmentEnvironment(): boolean {
return AppEnvUtil.isDevelopment();
}
diff --git a/src/app/chat/chat-screen.tsx b/src/app/chat/chat-screen.tsx
index 94a6d8e9..4cb4a918 100644
--- a/src/app/chat/chat-screen.tsx
+++ b/src/app/chat/chat-screen.tsx
@@ -30,6 +30,7 @@ import {
} from "./components";
import {
deriveIsGuest,
+ getInsufficientCreditsMessageLimitView,
getInsufficientCreditsSubscriptionType,
isChatDevelopmentEnvironment,
shouldStartExternalBrowserPrompt,
@@ -61,9 +62,9 @@ export function ChatScreen() {
const showMessageLimitBanner =
state.upgradePromptVisible &&
state.upgradeReason === "insufficient_credits";
- const messageLimitTitle =
- "Insufficient credits\nTop up to continue chatting";
- const messageLimitCtaLabel = "Top up credits to continue";
+ const messageLimitView = getInsufficientCreditsMessageLimitView(
+ authState.loginStatus,
+ );
const firstRechargeOfferBanner = useFirstRechargeOfferBanner({
historyLoaded: state.historyLoaded,
loginStatus: authState.loginStatus,
@@ -141,6 +142,11 @@ export function ChatScreen() {
}
function handleMessageLimitUnlock(): void {
+ if (messageLimitView.action === "auth") {
+ navigator.openAuth(ROUTES.chat);
+ return;
+ }
+
navigator.openSubscription({
type: getInsufficientCreditsSubscriptionType(userState.isVip),
returnTo: "chat",
@@ -190,8 +196,9 @@ export function ChatScreen() {
{showMessageLimitBanner ? (
{description}
+ ) : null}