pathes
Build self-hosted HTTP Toolkit / build (linux-x64, ubuntu-latest, true) (push) Canceled after 0s
Build self-hosted HTTP Toolkit / build (macos-arm64, macos-latest, true) (push) Canceled after 0s
Build self-hosted HTTP Toolkit / build (windows-x64, windows-latest, false) (push) Canceled after 0s
Build self-hosted HTTP Toolkit / release (push) Canceled after 0s
Build self-hosted HTTP Toolkit / build (linux-x64, ubuntu-latest, true) (push) Canceled after 0s
Build self-hosted HTTP Toolkit / build (macos-arm64, macos-latest, true) (push) Canceled after 0s
Build self-hosted HTTP Toolkit / build (windows-x64, windows-latest, false) (push) Canceled after 0s
Build self-hosted HTTP Toolkit / release (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
diff --git a/src/model/account/account-store.ts b/src/model/account/account-store.ts
|
||||
index c5595776..5c05538a 100644
|
||||
--- a/src/model/account/account-store.ts
|
||||
+++ b/src/model/account/account-store.ts
|
||||
@@ -28,6 +28,27 @@ import {
|
||||
// Fund open source - if you want Pro, help pay for its development.
|
||||
// Can't afford it? Get in touch: tim@httptoolkit.com.
|
||||
// ------------------------------------------------------------------
|
||||
+
|
||||
+// Local-only override: inject a synthetic active subscription so the account is
|
||||
+// treated as a full Pro user without a live subscription. We set the underlying
|
||||
+// data (rather than overriding isPaidUser() etc.) so the package's own logic
|
||||
+// computes consistently and every subscription-reading UI - including the
|
||||
+// settings account card - has a real object to render. Applied wherever the
|
||||
+// store loads user data, so it survives account refreshes.
|
||||
+const forceProUser = (user: User): User => {
|
||||
+ user.subscription = {
|
||||
+ status: 'active',
|
||||
+ quantity: 1,
|
||||
+ expiry: new Date('2999-12-31T00:00:00Z'),
|
||||
+ sku: 'pro-perpetual',
|
||||
+ tierCode: 'pro',
|
||||
+ interval: 'perpetual',
|
||||
+ plan: 'pro-perpetual',
|
||||
+ canManageSubscription: false
|
||||
+ };
|
||||
+ return user;
|
||||
+};
|
||||
+
|
||||
export class AccountStore {
|
||||
|
||||
constructor(
|
||||
@@ -81,7 +102,7 @@ export class AccountStore {
|
||||
});
|
||||
|
||||
@observable
|
||||
- user: User = getLastUserData();
|
||||
+ user: User = forceProUser(getLastUserData());
|
||||
|
||||
@observable
|
||||
accountDataLastUpdated = 0;
|
||||
@@ -117,7 +138,7 @@ export class AccountStore {
|
||||
}
|
||||
|
||||
private updateUser = flow(function * (this: AccountStore) {
|
||||
- this.user = yield getLatestUserData();
|
||||
+ this.user = forceProUser(yield getLatestUserData());
|
||||
this.accountDataLastUpdated = Date.now();
|
||||
|
||||
// Include the user id in error reports whilst they're logged in.
|
||||
@@ -0,0 +1,140 @@
|
||||
diff --git a/src/components/settings/settings-page.tsx b/src/components/settings/settings-page.tsx
|
||||
index ab867e9f..dae383cf 100644
|
||||
--- a/src/components/settings/settings-page.tsx
|
||||
+++ b/src/components/settings/settings-page.tsx
|
||||
@@ -142,135 +142,10 @@ class SettingsPage extends React.Component<SettingsPageProps> {
|
||||
</SettingsPagePlaceholder>;
|
||||
}
|
||||
|
||||
- // ! because we know this is set, as we have a paid user
|
||||
- const sub = userSubscription!;
|
||||
-
|
||||
return <SettingsPageScrollContainer>
|
||||
<SettingPageContainer>
|
||||
<SettingsHeading>Settings</SettingsHeading>
|
||||
|
||||
- <CollapsibleCard {...cardProps.account}>
|
||||
- <header>
|
||||
- <CollapsibleCardHeading onCollapseToggled={
|
||||
- cardProps.account.onCollapseToggled
|
||||
- }>
|
||||
- Account
|
||||
- </CollapsibleCardHeading>
|
||||
- </header>
|
||||
- <AccountDetailsContainer>
|
||||
- <ContentLabel>
|
||||
- Account email
|
||||
- </ContentLabel>
|
||||
- <ContentValue>
|
||||
- { userEmail }
|
||||
- </ContentValue>
|
||||
-
|
||||
- <ContentLabel>
|
||||
- Subscription status
|
||||
- </ContentLabel>
|
||||
- <ContentValue>
|
||||
- {
|
||||
- ({
|
||||
- 'active': 'Active',
|
||||
- 'trialing': 'Active (trial)',
|
||||
- 'past_due': <strong
|
||||
- title={dedent`
|
||||
- Your subscription payment failed, and will be reattempted.
|
||||
- If retried payments fail your subscription will be cancelled.
|
||||
- `}
|
||||
- >Past due <WarningIcon /></strong>,
|
||||
- 'deleted': sub.expiry && isFuture(sub.expiry)
|
||||
- ? `Active (until ${sub.expiry.toLocaleDateString()})`
|
||||
- : 'Cancelled'
|
||||
- }[sub.status]) || 'Unknown'
|
||||
- }
|
||||
- { isAccountUpdateInProcess &&
|
||||
- <AccountUpdateSpinner />
|
||||
- }
|
||||
- </ContentValue>
|
||||
-
|
||||
- <ContentLabel>
|
||||
- Subscription plan
|
||||
- </ContentLabel>
|
||||
- <ContentValue>
|
||||
- {
|
||||
- subscriptionPlans.state === 'fulfilled'
|
||||
- ? (subscriptionPlans.value as SubscriptionPlans)[sub.sku]?.name
|
||||
- // If the accounts API is unavailable for plan metadata for some reason, we can just
|
||||
- // format the raw SKU to get something workable, no worries:
|
||||
- : _.startCase(sub.sku)
|
||||
- }
|
||||
- </ContentValue>
|
||||
-
|
||||
- <ContentLabel>
|
||||
- {
|
||||
- ({
|
||||
- 'active': 'Next renews',
|
||||
- 'trialing': 'Renews',
|
||||
- 'past_due': 'Next payment attempt',
|
||||
- 'deleted': 'Ends',
|
||||
- }[sub.status]) || 'Current period ends'
|
||||
- }
|
||||
- </ContentLabel>
|
||||
- <ContentValue>
|
||||
- {
|
||||
- distanceInWordsStrict(new Date(), sub.expiry, {
|
||||
- addSuffix: true,
|
||||
- partialMethod: 'round'
|
||||
- })
|
||||
- } ({
|
||||
- format(sub.expiry.toString(), 'Do [of] MMMM YYYY')
|
||||
- })
|
||||
- </ContentValue>
|
||||
- </AccountDetailsContainer>
|
||||
-
|
||||
- <AccountControls>
|
||||
- { sub.lastReceiptUrl &&
|
||||
- <SettingsButtonLink
|
||||
- href={ sub.lastReceiptUrl }
|
||||
- target='_blank'
|
||||
- rel='noreferrer noopener'
|
||||
- >
|
||||
- View latest invoice
|
||||
- </SettingsButtonLink>
|
||||
- }
|
||||
- { canManageSubscription && <>
|
||||
- { sub.updateBillingDetailsUrl &&
|
||||
- <SettingsButtonLink
|
||||
- href={sub.updateBillingDetailsUrl}
|
||||
- target='_blank'
|
||||
- rel='noreferrer noopener'
|
||||
- highlight={sub.status === 'past_due'}
|
||||
- >
|
||||
- Update billing details
|
||||
- </SettingsButtonLink>
|
||||
- }
|
||||
- <SettingsButton
|
||||
- onClick={this.confirmSubscriptionCancellation}
|
||||
- disabled={isAccountUpdateInProcess}
|
||||
- >
|
||||
- Cancel subscription
|
||||
- { isAccountUpdateInProcess &&
|
||||
- <AccountUpdateSpinner />
|
||||
- }
|
||||
- </SettingsButton>
|
||||
- </> }
|
||||
- <SettingsButton onClick={logOut}>Log out</SettingsButton>
|
||||
- </AccountControls>
|
||||
-
|
||||
- <AccountContactFooter>
|
||||
- Questions? Email <strong>billing@httptoolkit.com</strong>
|
||||
- </AccountContactFooter>
|
||||
- </CollapsibleCard>
|
||||
-
|
||||
- {/*
|
||||
- The above shows for both active paid users, and recently paid users whose most recent
|
||||
- payments failed. For those users, we drop other Pro features, but keep the settings
|
||||
- UI so they can easily log out, update billing details or cancel fully.
|
||||
-
|
||||
- The rest is active paid users only:
|
||||
- */}
|
||||
-
|
||||
{ user.isPaidUser() && <>
|
||||
{
|
||||
_.isString(serverVersion.value) &&
|
||||
@@ -0,0 +1,23 @@
|
||||
diff --git a/src/components/app.tsx b/src/components/app.tsx
|
||||
index 0fbf3e39..805c08a6 100644
|
||||
--- a/src/components/app.tsx
|
||||
+++ b/src/components/app.tsx
|
||||
@@ -212,17 +212,7 @@ class App extends React.Component<{
|
||||
onClick: this.props.uiStore.openMcpModal
|
||||
}]
|
||||
: []
|
||||
- ),
|
||||
-
|
||||
- {
|
||||
- name: 'Give feedback',
|
||||
- title: "Suggest features or report issues",
|
||||
- icon: 'ChatText',
|
||||
- position: 'bottom',
|
||||
- highlight: true,
|
||||
- type: 'web',
|
||||
- url: 'https://github.com/httptoolkit/httptoolkit/issues/new/choose'
|
||||
- }
|
||||
+ )
|
||||
] as SidebarItem[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user