Skip to content

bug: a canceled subscription reads expired while its paid period runs #845

Description

@ovitrif

Twin: synonymdev/bitkit-android#1413

What happened?

Right after Swipe To Cancel, a subscription reads as expired while the period already paid for is still running. STATUS reads "Expired", the timing cell reads "EXPIRED " with the end of that paid period, and the list row's subtitle reads "Expired". Nothing says it was canceled.

Bitkit Android showed exactly this on 25 Sep: "Expired" and "EXPIRED November 25" on both sides, while the paid period ran until 25 Nov. The iOS code maps it the same way: on master, a canceled subscription with a paid period that ends on Oct 1 renders STATUS "Expired", the timing cell "EXPIRED October 1" and the row subtitle "Expired" (checked on a simulator with a canceled fixture subscription).

Where, on master (c5a2a05):

  • Bitkit/Services/PaykitSubscription.swift:489 isActive(at:) requires .activeRecurring, and :509-510 isExpired(at:) counts .canceled as expired.
  • Bitkit/Views/Subscriptions/SubscriptionsView.swift maps every inactive subscription to "Expired":
    • :1052-1056 statusLabel(at:): return isActive(at: now) ? t("subscriptions__active") : t("subscriptions__expired")
    • :517-519 timingTitle(_:): guard subscription.isActive(at: now) else { return t("subscriptions__expired") }
    • :509-512 renewalText(_:) with :263-264 subscriptionEndDate: the timing value is the end of the last paid period.
    • :1076-1077 rowSubtitle(at:): a canceled subscription with no end date reads "Expired".

Expected behavior

Per the Figma v3 Subscription Details Renew frame (48063:282720: "a subscription has been canceled but has not expired yet") and the Overview list (48063:282432):

  • A canceled subscription whose paid period has not ended looks like an active one with an end date: STATUS "Active", row subtitle "Expires ", listed under ACTIVE, timing cell "EXPIRES ".
  • When the paid period ends it is listed under EXPIRED with the timing cell "EXPIRED ".
  • A canceled subscription with no end date has no timing cell.
  • The footer offers More Info and no Cancel.
  • Active subscriptions keep "Renews" or "Expires".

Steps to Reproduce

  1. Subscribe to a monthly subscription and pay the first period.
  2. Open it and Swipe To Cancel.
  3. See STATUS "Expired" and "EXPIRED " while that date is still ahead; the list row reads "Expired".

Logs / Screenshots / Recordings

The code quotes above. Android on 25 Sep, right after Swipe To Cancel: "Expired" and "EXPIRED November 25".

iOS on master, canceled fixture subscription:

Bitkit Version

master c5a2a05

Device / OS

iPhone 17 simulator, iOS 26.5, with a canceled fixture subscription; not checked with a real Swipe To Cancel on a device.

Reproducibility

Always

Additional context

Android has the same defect and gets the same fix in its own PR.

Proposal:

  • Treat a canceled subscription with a paid period still ahead like an active one with an end date, with one shared predicate for status, row subtitle, section, timing cell and the refresh timers.
  • Test the status, subtitle, section grouping, timing title and timer date for a canceled subscription before and after the end of its paid period.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions