From e83d71aa3c03d446523ce428abca250567ef467b Mon Sep 17 00:00:00 2001
From: DanSnow
Date: Thu, 29 Feb 2024 14:44:04 +0800
Subject: [PATCH] fix: simplify signin
---
src/components/EmailForm.vue | 18 +++-----
src/components/LeakyPaywall.vue | 24 +---------
src/composables/paywall-mode.ts | 26 -----------
src/composables/subscribe.ts | 78 +++++++--------------------------
src/gql/gql.ts | 9 +---
src/gql/graphql.ts | 58 +++++++++++++++++-------
6 files changed, 67 insertions(+), 146 deletions(-)
delete mode 100644 src/composables/paywall-mode.ts
diff --git a/src/components/EmailForm.vue b/src/components/EmailForm.vue
index 9700b82a..e9ac6e60 100644
--- a/src/components/EmailForm.vue
+++ b/src/components/EmailForm.vue
@@ -4,12 +4,9 @@ import { Field as FormField, useForm } from 'vee-validate'
import { useAutoAnimate } from '@formkit/auto-animate/vue'
import * as z from 'zod'
import { useModel } from 'vue'
-import type { Mode } from '~/composables/paywall-mode'
const props = defineProps<{
- mode: Mode
email: string
- buttonText: string
}>()
defineEmits<{
@@ -34,15 +31,14 @@ const form = useForm({
})
const emailInput = useModel(props, 'email')
-const { subscribe } = useSubscribe(toRef(props, 'mode'))
-
-const showLoginDialog = ref(false)
+const { subscribe } = useSubscribe()
const onSubmit = form.handleSubmit(async (values) => {
const res = await subscribe(values)
- if (res.ok && !res.token) {
- showLoginDialog.value = true
+ if (res.ok && res.token) {
+ $paywall.setKey('token', res.token)
}
+ // TODO: error handling
})
const [formItem, setAnimate] = useAutoAnimate({ duration: 200 })
@@ -75,10 +71,6 @@ onMounted(async () => {
-
-
-
+
diff --git a/src/components/LeakyPaywall.vue b/src/components/LeakyPaywall.vue
index c23eaa37..596b9d8b 100644
--- a/src/components/LeakyPaywall.vue
+++ b/src/components/LeakyPaywall.vue
@@ -10,8 +10,6 @@ initConfig()
const config = useStore($config)
const paywall = useStore($paywall)
-const { mode, primaryButton, reset, secondaryButton, toggleMode } = usePaywallMode()
-
const themeConfig = computed(() => ({
'--sp-primary': config.value.primaryColor,
}))
@@ -95,11 +93,6 @@ onMounted(async () => {
const emailInput = ref('')
-function switchMode() {
- // After this step, the form will be reset
- toggleMode()
-}
-
// Unlock scroll if user scroll up
useEventListener(window, 'wheel', (event) => {
if (event.deltaY <= -5) {
@@ -155,15 +148,6 @@ whenever(
},
{ immediate: true },
)
-
-// reset form content after close
-whenever(
- logicNot(show),
- () => {
- reset()
- },
- { flush: 'post' },
-)
@@ -193,13 +177,7 @@ whenever(
-
-
-
-
-
+
diff --git a/src/composables/paywall-mode.ts b/src/composables/paywall-mode.ts
deleted file mode 100644
index 3fbce13c..00000000
--- a/src/composables/paywall-mode.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export type Mode = 'subscribe' | 'login'
-
-export interface UsePaywallModeReturn {
- mode: Ref
- toggleMode: () => void
- reset: () => void
-
- primaryButton: Ref
- secondaryButton: Ref
-}
-
-export function usePaywallMode(): UsePaywallModeReturn {
- const [state, setState] = useToggle()
- const mode = computed(() => (state.value ? 'login' : 'subscribe'))
-
- const primaryButton = computed(() => (mode.value === 'subscribe' ? 'Subscribe' : 'Sign in'))
- const secondaryButton = computed(() => (mode.value === 'subscribe' ? 'Sign in' : 'Subscribe'))
- return {
- mode,
- toggleMode: () => setState(),
- reset: () => setState(false),
-
- primaryButton,
- secondaryButton,
- }
-}
diff --git a/src/composables/subscribe.ts b/src/composables/subscribe.ts
index ebb5ead9..c9b956e4 100644
--- a/src/composables/subscribe.ts
+++ b/src/composables/subscribe.ts
@@ -16,7 +16,6 @@ interface SubscribeInput {
interface SuccessSubscribeReturn {
ok: true
- // Sign in require to check the email
token?: string
}
@@ -28,88 +27,43 @@ interface FailSubscribeReturn {
type SubscribeReturn = SuccessSubscribeReturn | FailSubscribeReturn
-export function useSubscribe(mode: Ref<'subscribe' | 'login'>) {
- const { executeMutation: requestSignInSubscriberMutate } = useMutation(
+export function useSubscribe() {
+ const { executeMutation: signInPaywall } = useMutation(
graphql(`
- mutation RequestSignInSubscriber($email: EmailString!, $referer: String!, $from: String!) {
- requestSignInSubscriber(input: { email: $email, referer: $referer, from: $from })
+ mutation SignInPaywall($email: EmailString!) {
+ signInLeakySubscriber(input: { email: $email })
}
`),
)
- const { executeMutation: signUpSubscriberMutate } = useMutation(
- graphql(`
- mutation SignUpSubscriber($email: EmailString!, $referer: String!, $from: String!) {
- signUpSubscriber(input: { email: $email, referer: $referer, from: $from })
- }
- `),
- )
-
- function collectReferer() {
- return {
- referer: document.referrer || location.origin,
- from: location.href,
- }
- }
-
async function doLogin(input: SubscribeInput): Promise {
- const res = await requestSignInSubscriberMutate({
- email: input.email,
- ...collectReferer(),
- })
-
- if (res.error) {
- return {
- ok: false,
- isBadRequest: isBadRequest(res.error.graphQLErrors?.[0]),
- error: res.error,
- }
- }
-
- return {
- ok: true,
- }
- }
-
- async function doSignup(input: SubscribeInput): Promise {
- const res = await signUpSubscriberMutate({
+ const res = await signInPaywall({
email: input.email,
- ...collectReferer(),
})
- if (res.error) {
+ if (res.error || !res.data?.signInLeakySubscriber) {
return {
ok: false,
- isBadRequest: isBadRequest(res.error.graphQLErrors?.[0]),
- error: res.error,
+ isBadRequest: isBadRequest(res.error?.graphQLErrors?.[0]),
+ error: res.error ?? createUnknownError(),
}
}
return {
ok: true,
- token: res.data?.signUpSubscriber,
+ token: res.data.signInLeakySubscriber,
}
}
return {
async subscribe(input: SubscribeInput): Promise {
- const actions = mode.value === 'login' ? [doLogin, doSignup] : [doSignup, doLogin]
- for (const action of actions) {
- const result = await action(input)
- if (!result.ok && !result.isBadRequest) {
- return result
- }
- if (result.ok) {
- return result
- }
- }
- return {
- ok: false,
- isBadRequest: false,
- error: new CombinedError({
- networkError: new Error('Unknown error'),
- }),
- }
+ return doLogin(input)
},
}
}
+
+function createUnknownError() {
+ return new CombinedError({
+ networkError: new Error('Unknown error'),
+ })
+}
diff --git a/src/gql/gql.ts b/src/gql/gql.ts
index 99bdacee..df71523e 100644
--- a/src/gql/gql.ts
+++ b/src/gql/gql.ts
@@ -15,8 +15,7 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-
const documents = {
"\n mutation VerifySubscriberEmail($token: String!) {\n verifySubscriberEmail(token: $token)\n }\n ": types.VerifySubscriberEmailDocument,
"\n mutation SignInSubscriber($token: String!) {\n signInSubscriber(token: $token)\n }\n ": types.SignInSubscriberDocument,
- "\n mutation RequestSignInSubscriber($email: EmailString!, $referer: String!, $from: String!) {\n requestSignInSubscriber(input: { email: $email, referer: $referer, from: $from })\n }\n ": types.RequestSignInSubscriberDocument,
- "\n mutation SignUpSubscriber($email: EmailString!, $referer: String!, $from: String!) {\n signUpSubscriber(input: { email: $email, referer: $referer, from: $from })\n }\n ": types.SignUpSubscriberDocument,
+ "\n mutation SignInPaywall($email: EmailString!) {\n signInLeakySubscriber(input: { email: $email })\n }\n ": types.SignInPaywallDocument,
"\n mutation TrackSubscriberActivity($input: TrackSubscriberActivityInput!) {\n trackSubscriberActivity(input: $input)\n }\n ": types.TrackSubscriberActivityDocument,
};
@@ -45,11 +44,7 @@ export function graphql(source: "\n mutation SignInSubscriber($token: Strin
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
-export function graphql(source: "\n mutation RequestSignInSubscriber($email: EmailString!, $referer: String!, $from: String!) {\n requestSignInSubscriber(input: { email: $email, referer: $referer, from: $from })\n }\n "): (typeof documents)["\n mutation RequestSignInSubscriber($email: EmailString!, $referer: String!, $from: String!) {\n requestSignInSubscriber(input: { email: $email, referer: $referer, from: $from })\n }\n "];
-/**
- * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
- */
-export function graphql(source: "\n mutation SignUpSubscriber($email: EmailString!, $referer: String!, $from: String!) {\n signUpSubscriber(input: { email: $email, referer: $referer, from: $from })\n }\n "): (typeof documents)["\n mutation SignUpSubscriber($email: EmailString!, $referer: String!, $from: String!) {\n signUpSubscriber(input: { email: $email, referer: $referer, from: $from })\n }\n "];
+export function graphql(source: "\n mutation SignInPaywall($email: EmailString!) {\n signInLeakySubscriber(input: { email: $email })\n }\n "): (typeof documents)["\n mutation SignInPaywall($email: EmailString!) {\n signInLeakySubscriber(input: { email: $email })\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/src/gql/graphql.ts b/src/gql/graphql.ts
index 5ac08a6c..37a8726c 100644
--- a/src/gql/graphql.ts
+++ b/src/gql/graphql.ts
@@ -1248,6 +1248,12 @@ export type FacebookSearchPage = {
name: Scalars['String']['output'];
};
+export type HubSpotInfo = {
+ __typename?: 'HubSpotInfo';
+ /** whether the integration is activated or not */
+ activated_at?: Maybe;
+};
+
export type IframelyIframelyInput = {
/**
* iframely params,
@@ -1627,6 +1633,8 @@ export type Mutation = {
confirmCustomDomain: Scalars['Boolean']['output'];
/** confirm account email */
confirmEmail: Scalars['Boolean']['output'];
+ /** initiate OAuth for HubSpot and return the redirect URL */
+ connectHubSpot: Scalars['String']['output'];
/** initiate OAuth for Webflow and return the redirect URL */
connectWebflow: Scalars['String']['output'];
createAppSubscription: Scalars['Boolean']['output'];
@@ -1733,6 +1741,8 @@ export type Mutation = {
* @deprecated No longer supported
*/
disableSubscription: Site;
+ /** disconnect HubSpot integration */
+ disconnectHubSpot: Scalars['Boolean']['output'];
/** disconnect specific integration */
disconnectIntegration: Integration;
/** disconnect stripe connect */
@@ -1864,6 +1874,8 @@ export type Mutation = {
signIframelySignature: Scalars['String']['output'];
/** sign in to the app */
signIn: AuthToken;
+ /** sign up/in to customer site */
+ signInLeakySubscriber: Scalars['String']['output'];
/** sign in to customer site */
signInSubscriber: Scalars['String']['output'];
/** sign out of the app */
@@ -2539,6 +2551,11 @@ export type MutationSignInArgs = {
};
+export type MutationSignInLeakySubscriberArgs = {
+ input: SignInLeakySubscriberInput;
+};
+
+
export type MutationSignInSubscriberArgs = {
token: Scalars['String']['input'];
};
@@ -2843,6 +2860,18 @@ export type MutationVerifySubscriberEmailArgs = {
token: Scalars['String']['input'];
};
+export type Notification = {
+ __typename?: 'Notification';
+ /** notification meta data */
+ data?: Maybe;
+ /** notification id */
+ id: Scalars['ID']['output'];
+ /** notification create time */
+ occurred_at: Scalars['DateTime']['output'];
+ /** notification state */
+ type: Scalars['String']['output'];
+};
+
export type OptInWordPressFeatureInput = {
/** feature Type */
key: WordPressOptionalFeatureType;
@@ -3039,6 +3068,10 @@ export type Query = {
/** get specific email */
email?: Maybe;
facebookPages: Array;
+ /** whether the HubSpot OAuth has been completed or not */
+ hubSpotAuthorized: Scalars['Boolean']['output'];
+ /** get HubSpot information */
+ hubSpotInfo: HubSpotInfo;
/**
* make a iframely request for specific url
* @deprecated use signIframelySignature mutation
@@ -3061,6 +3094,8 @@ export type Query = {
me: User;
/** media info */
media: Media;
+ /** fetch notifications */
+ notifications: Array;
/** get specific page */
page?: Maybe;
/** fetch pages */
@@ -3760,6 +3795,11 @@ export type ShopifyProductVariant = {
title: Scalars['String']['output'];
};
+export type SignInLeakySubscriberInput = {
+ /** subscriber email */
+ email: Scalars['EmailString']['input'];
+};
+
export type SignUpInput = {
appsumo_code?: InputMaybe;
campaign?: InputMaybe;
@@ -5233,23 +5273,12 @@ export type SignInSubscriberMutationVariables = Exact<{
export type SignInSubscriberMutation = { __typename?: 'Mutation', signInSubscriber: string };
-export type RequestSignInSubscriberMutationVariables = Exact<{
+export type SignInPaywallMutationVariables = Exact<{
email: Scalars['EmailString']['input'];
- referer: Scalars['String']['input'];
- from: Scalars['String']['input'];
-}>;
-
-
-export type RequestSignInSubscriberMutation = { __typename?: 'Mutation', requestSignInSubscriber: boolean };
-
-export type SignUpSubscriberMutationVariables = Exact<{
- email: Scalars['EmailString']['input'];
- referer: Scalars['String']['input'];
- from: Scalars['String']['input'];
}>;
-export type SignUpSubscriberMutation = { __typename?: 'Mutation', signUpSubscriber: string };
+export type SignInPaywallMutation = { __typename?: 'Mutation', signInLeakySubscriber: string };
export type TrackSubscriberActivityMutationVariables = Exact<{
input: TrackSubscriberActivityInput;
@@ -5261,6 +5290,5 @@ export type TrackSubscriberActivityMutation = { __typename?: 'Mutation', trackSu
export const VerifySubscriberEmailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"VerifySubscriberEmail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"verifySubscriberEmail"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}]}]}}]} as unknown as DocumentNode;
export const SignInSubscriberDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SignInSubscriber"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"signInSubscriber"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}]}]}}]} as unknown as DocumentNode;
-export const RequestSignInSubscriberDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RequestSignInSubscriber"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EmailString"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"referer"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"from"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestSignInSubscriber"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"referer"},"value":{"kind":"Variable","name":{"kind":"Name","value":"referer"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"from"},"value":{"kind":"Variable","name":{"kind":"Name","value":"from"}}}]}}]}]}}]} as unknown as DocumentNode;
-export const SignUpSubscriberDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SignUpSubscriber"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EmailString"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"referer"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"from"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"signUpSubscriber"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"referer"},"value":{"kind":"Variable","name":{"kind":"Name","value":"referer"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"from"},"value":{"kind":"Variable","name":{"kind":"Name","value":"from"}}}]}}]}]}}]} as unknown as DocumentNode;
+export const SignInPaywallDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SignInPaywall"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EmailString"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"signInLeakySubscriber"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}}]}}]}]}}]} as unknown as DocumentNode;
export const TrackSubscriberActivityDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"TrackSubscriberActivity"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"TrackSubscriberActivityInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"trackSubscriberActivity"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode;
\ No newline at end of file