From 9afeb5b44c060041ac8323da4c6c1e4885f49e98 Mon Sep 17 00:00:00 2001 From: BFlat Date: Mon, 31 Oct 2022 13:35:08 +0700 Subject: [PATCH 01/11] pricing plans --- packages/fakeyou/src/data/PriceTiers.js | 112 ++++---- packages/fakeyou/src/scss/site-refresh.scss | 3 +- .../src/v2/view/NewVocodesContainer.tsx | 5 +- .../fakeyou/src/v2/view/pricing/Pricing.tsx | 264 ------------------ .../src/v2/view/pricing/PricingPage.tsx | 259 +++++++++++++++++ 5 files changed, 324 insertions(+), 319 deletions(-) delete mode 100644 packages/fakeyou/src/v2/view/pricing/Pricing.tsx create mode 100644 packages/fakeyou/src/v2/view/pricing/PricingPage.tsx diff --git a/packages/fakeyou/src/data/PriceTiers.js b/packages/fakeyou/src/data/PriceTiers.js index 4872e10218..6ec704ada7 100644 --- a/packages/fakeyou/src/data/PriceTiers.js +++ b/packages/fakeyou/src/data/PriceTiers.js @@ -1,61 +1,71 @@ const FAKEYOU_PRICES = { - 'free': { - tier: 'free', + free: { + tier: "free", price: 0, features: { - 'Extended Audio': false, - 'mp3': false, - 'Priority Processing': false, - 'Commercial Voices': false - } + "Extended Audio": false, + mp3: false, + "Priority Processing": false, + "Commercial Voices": false, + }, }, - 'basic': { - tier: 'basic', - price: 5, + plus: { + tier: "plus", + price: 7, features: { - 'Extended Audio': true, - 'mp3': false, - 'Priority Processing': false, - 'Commercial Voices': false - } - }, - 'pro': { - tier: 'pro', - price: 30, - features: { - 'Extended Audio': true, - 'mp3': true, - 'Priority Processing': true, - 'Commercial Voices': true - } - } -} - -const STORYTELLER_PRICES = { - 'free': { - tier: 'free', - price: 0, - features: { - 'Priority Processing': false, - 'Stream Labs': false - } - }, - basic: { - tier: 'basic', - price: 5, - features: { - 'Priority Processing': false, - 'Stream Labs': false - } + "Extended Audio": true, + mp3: false, + "Priority Processing": false, + "Commercial Voices": false, + }, }, pro: { - tier: 'premium', + tier: "pro", + price: 15, + features: { + "Extended Audio": true, + mp3: true, + "Priority Processing": true, + "Commercial Voices": true, + }, + }, + elite: { + tier: "elite", + price: 25, + features: { + "Extended Audio": true, + mp3: true, + "Priority Processing": true, + "Commercial Voices": true, + }, + }, +}; + +const STORYTELLER_PRICES = { + free: { + tier: "free", + price: 0, + features: { + "Priority Processing": false, + "Stream Labs": false, + }, + }, + basic: { + tier: "basic", + price: 5, + features: { + "Priority Processing": false, + "Stream Labs": false, + }, + }, + pro: { + tier: "premium", price: 50, features: { - 'Priority Processing': true, - "Stream Labs": true - } - } -} + "Priority Processing": true, + "Stream Labs": true, + }, + }, +}; -export { FAKEYOU_PRICES, STORYTELLER_PRICES } \ No newline at end of file +export { FAKEYOU_PRICES, STORYTELLER_PRICES }; diff --git a/packages/fakeyou/src/scss/site-refresh.scss b/packages/fakeyou/src/scss/site-refresh.scss index 8abb68f445..5b8da0c810 100644 --- a/packages/fakeyou/src/scss/site-refresh.scss +++ b/packages/fakeyou/src/scss/site-refresh.scss @@ -390,11 +390,12 @@ styles with important tags: .panel-border { box-sizing: border-box; - box-shadow: inset 0px 0px 0px 4px lighten($primary, 5%); + box-shadow: inset 0px 0px 0px 3px $primary; } ul.pricing-list { list-style: none; + padding: 0; } ul li { diff --git a/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx b/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx index c8113b8a61..899cedb7ad 100644 --- a/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx +++ b/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx @@ -56,6 +56,7 @@ import { Language } from "@storyteller/components/src/i18n/Language"; import { VoiceCloneRequestPage } from "./clone_voice_requests/VoiceCloneRequestPage"; import { VocodesPage } from "./vocodes/VocodesPage"; import { UploadVocoderPage } from "./upload/UploadVocoderPage"; +import { PricingPage } from "./pricing/PricingPage"; interface Props { sessionWrapper: SessionWrapper; @@ -174,14 +175,12 @@ class NewVocodesContainer extends React.Component { /> - {/* { }} + querySessionCallback={() => {}} sessionWrapper={this.props.sessionWrapper} /> - */} diff --git a/packages/fakeyou/src/v2/view/pricing/Pricing.tsx b/packages/fakeyou/src/v2/view/pricing/Pricing.tsx deleted file mode 100644 index 62f8125b3a..0000000000 --- a/packages/fakeyou/src/v2/view/pricing/Pricing.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import React from "react"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Link } from "react-router-dom"; -import { - faCheckCircle as TRUE, - faTimesCircle as FALSE, - faCheck, -} from "@fortawesome/free-solid-svg-icons"; -import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; -import { - FAKEYOU_PRICES as FYP, - STORYTELLER_PRICES as STP, -} from "@storyteller/fakeyou/src/data/PriceTiers"; -import { - distance, - pricing1, - pricing2, - pricing3, - delay2, - duration, -} from "../../../data/animation"; - -const Fade = require("react-reveal/Fade"); - -interface Props { - sessionWrapper: SessionWrapper; - querySessionCallback: () => void; -} - -function PricingPage(props: Props) { - function capitalize(word: string) { - return word.charAt(0).toUpperCase() + word.slice(1); - } - - const [FY_TIERS, ST_TIERS] = [Object.keys(FYP), Object.keys(STP)]; - - const [FY_FEATURES, ST_FEATURES] = [ - Object.keys(FYP.free.features), - Object.keys(STP.free.features), - ]; - - let current_tiers: string[], current_features: string[], current_list: any; - - const site = window.location.hostname; - - switch (site) { - case "fakeyou": - [current_tiers, current_features, current_list] = [ - FY_TIERS, - FY_FEATURES, - FYP, - ]; - break; - case "storyteller": - [current_tiers, current_features, current_list] = [ - ST_TIERS, - ST_FEATURES, - STP, - ]; - break; - default: - [current_tiers, current_features, current_list] = [ - FY_TIERS, - FY_FEATURES, - FYP, - ]; - break; - } - - return ( -
- -
-

FakeYou Pricing

-
-
- -
-
-
- -
-

Free

-

Great for hobbyists

- - Create free TTS - -

- ${current_list.free.price} - /month -

-
    -
  • - - Unlimited TTS Generation -
  • -
  • - - Up to 10 seconds audio -
  • -
-
-
-
-
- -
-

Basic

-

Great for hobbyists

- - Buy Basic - -

- ${current_list.basic.price} - /month -

-
    -
  • - - Unlimited TTS Generation -
  • -
  • - - Up to 30 seconds audio -
  • -
  • - - Priority processing -
  • -
-
-
-
-
- -
-

Pro

-

Great for hobbyists

- - Buy Pro - -

- ${current_list.pro.price} - /month -

-
    -
  • - - Unlimited TTS Generation -
  • -
  • - - Up to 1 minute audio -
  • -
  • - - Priority processing -
  • -
  • - - Generate mp3 file -
  • -
  • - - For Commercial Use -
  • -
-
-
-
-
-
- - -
-
- - - - - - {current_tiers.map((e) => { - return ( - - ); - })} - - - - - - - - - - - - {current_features.map((e, i) => { - return ( - - - - - - - - - - ); - })} - -
Feature List - {capitalize(e)} -
Price${current_list.free.price}/month${current_list.basic.price}/month${current_list.pro.price}/month
{e} - - - - - -
-
-
-
-
- ); -} - -export { PricingPage }; diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx new file mode 100644 index 0000000000..f3fcce327e --- /dev/null +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -0,0 +1,259 @@ +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Link } from "react-router-dom"; +import { + faCheckCircle as TRUE, + faTimesCircle as FALSE, + faCheck, +} from "@fortawesome/free-solid-svg-icons"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import { + FAKEYOU_PRICES as FYP, + STORYTELLER_PRICES as STP, +} from "@storyteller/fakeyou/src/data/PriceTiers"; + +interface Props { + sessionWrapper: SessionWrapper; + querySessionCallback: () => void; +} + +function PricingPage(props: Props) { + function capitalize(word: string) { + return word.charAt(0).toUpperCase() + word.slice(1); + } + + const [FY_TIERS, ST_TIERS] = [Object.keys(FYP), Object.keys(STP)]; + + const [FY_FEATURES, ST_FEATURES] = [ + Object.keys(FYP.free.features), + Object.keys(STP.free.features), + ]; + + let current_tiers: string[], current_features: string[], current_list: any; + + const site = window.location.hostname; + + switch (site) { + case "fakeyou": + [current_tiers, current_features, current_list] = [ + FY_TIERS, + FY_FEATURES, + FYP, + ]; + break; + case "storyteller": + [current_tiers, current_features, current_list] = [ + ST_TIERS, + ST_FEATURES, + STP, + ]; + break; + default: + [current_tiers, current_features, current_list] = [ + FY_TIERS, + FY_FEATURES, + FYP, + ]; + break; + } + + return ( +
+
+

Pricing

+
+
+
+
+
+

Free

+ + Use free + +

+ ${current_list.free.price} + /month +

+
    +
  • + + Unlimited TTS Generation +
  • +
  • + + Up to 10 seconds audio +
  • +
+
+
+
+
+

Plus

+ + Buy Plus + +

+ ${current_list.plus.price} + /month +

+
    +
  • + + Unlimited TTS Generation +
  • +
  • + + Up to 30 seconds audio +
  • +
  • + + Priority processing +
  • +
+
+
+
+
+

Pro

+ + Buy Pro + +

+ ${current_list.pro.price} + /month +

+
    +
  • + + Unlimited TTS Generation +
  • +
  • + + Up to 1 minute audio +
  • +
  • + + Priority processing +
  • +
  • + + Generate mp3 file +
  • +
  • + + For Commercial Use +
  • +
+
+
+
+
+

Elite

+ + Buy Elite + +

+ ${current_list.elite.price} + /month +

+
    +
  • + + Unlimited TTS Generation +
  • +
  • + + Up to 1 minute audio +
  • +
  • + + Priority processing +
  • +
  • + + Generate mp3 file +
  • +
  • + + For Commercial Use +
  • +
+
+
+
+
+ +
+
+ + + + + + {current_tiers.map((e) => { + return ( + + ); + })} + + + + + + + + + + + + {current_features.map((e, i) => { + return ( + + + + + + + + + + ); + })} + +
Feature List + {capitalize(e)} +
Price${current_list.free.price}/month${current_list.plus.price}/month${current_list.pro.price}/month
{e} + + + + + +
+
+
+
+ ); +} + +export { PricingPage }; From 0dbdd9f5a8919a49f012a2da49fa03a588dfeeee Mon Sep 17 00:00:00 2001 From: BFlat Date: Mon, 31 Oct 2022 16:00:56 +0700 Subject: [PATCH 02/11] pricing page update --- packages/fakeyou/src/scss/site-refresh.scss | 11 + .../src/v2/view/pricing/PricingPage.tsx | 210 +++++++++++++++--- 2 files changed, 194 insertions(+), 27 deletions(-) diff --git a/packages/fakeyou/src/scss/site-refresh.scss b/packages/fakeyou/src/scss/site-refresh.scss index 5b8da0c810..c05e1f168f 100644 --- a/packages/fakeyou/src/scss/site-refresh.scss +++ b/packages/fakeyou/src/scss/site-refresh.scss @@ -396,6 +396,17 @@ styles with important tags: ul.pricing-list { list-style: none; padding: 0; + + li { + font-size: 14px; + } + + .small-text { + font-size: 12px; + font-weight: 400; + opacity: 0.8; + color: lighten($primary, 10%); + } } ul li { diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index f3fcce327e..292ea7192f 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -61,71 +61,139 @@ function PricingPage(props: Props) {

Pricing

+

+ Some kind of description here, idk haven't thought of it. +

-
+
-

Free

- - Use free +

Starter

+ + Use for free

${current_list.free.price} /month

-
    +
      +
    • TTS
    • - Unlimited TTS Generation + Unlimited generation
    • - Up to 10 seconds audio + Up to 12 seconds audio +
    • +
    • VC Web
    • +
    • + + Up to 12 seconds audio +
    • +
    • + VC App (registered users) +
    • +
    • + 5 + model downloads +
    • +
    • + + Up to 12 secs prerecorded +
    • +
    • + + Up to 2 mins realtime +
    • +
    • Wav2Lip
    • +
    • + + Up to 12 seconds video +
    • +
    • Processing Priority
    • +
    • + + Level 0 +
    • +
    • + + Level 1 (registered users)
-
+

Plus

- + Buy Plus

${current_list.plus.price} /month

-
    +
      +
    • TTS
    • - Unlimited TTS Generation + Unlimited generation
    • Up to 30 seconds audio
    • +
    • VC Web
    • +
    • + + Up to 30 seconds audio +
    • - Priority processing + Push to play +
    • +
    • VC App
    • +
    • + + 10 model downloads +
    • +
    • + + Up to 30 secs prerecorded +
    • +
    • + + Up to 7 mins realtime +
    • +
    • Wav2Lip
    • +
    • + + Up to 1 minute video +
    • +
    • Processing Priority
    • +
    • + + Level 20
-
+

Pro

- + Buy Pro

${current_list.pro.price} /month

-
    +
      +
    • TTS
    • - Unlimited TTS Generation + Unlimited generation
    • @@ -133,49 +201,137 @@ function PricingPage(props: Props) {
    • - Priority processing + Generate MP3 file
    • - Generate mp3 file + Upload private models +
    • +
    • VC Web
    • +
    • + + Up to 2 minutes audio
    • - For Commercial Use + Push to play +
    • +
    • + + Generate MP3 file +
    • +
    • VC App
    • +
    • + + 20 model downloads +
    • +
    • + + Up to 5 mins prerecorded +
    • +
    • + + Up to 15 mins realtime +
    • +
    • Wav2Lip
    • +
    • + + Up to 2 minutes video +
    • +
    • Processing Priority
    • +
    • + + Level 30 +
    • +
    • API Access
    • +
    • + + Full API access
-
+

Elite

- + Buy Elite

${current_list.elite.price} /month

-
    +
      +
    • TTS
    • - Unlimited TTS Generation + Unlimited generation
    • - Up to 1 minute audio + Up to 5 minutes audio
    • - Priority processing + Generate MP3 file
    • - Generate mp3 file + Upload private models
    • - For Commercial Use + Share private models +
    • +
    • VC Web
    • +
    • + + Up to 7 minutes audio +
    • +
    • + + Push to play +
    • +
    • + + Generate MP3 file +
    • +
    • VC App
    • +
    • + + Unlimited models +
    • +
    • + + Unlimited prerecorded +
    • +
    • + + Unlimited realtime +
    • +
    • Wav2Lip
    • +
    • + + Up to 5 minutes video +
    • +
    • + + Turn off watermark +
    • +
    • Processing Priority
    • +
    • + + Level 40 +
    • +
    • API Access
    • +
    • + + Full API access +
    • +
    • Commercial Voices
    • +
    • + + Usable commercial voices
From b3c35e80a1c80ec76951af73dd7134c0882796bb Mon Sep 17 00:00:00 2001 From: BFlat Date: Tue, 1 Nov 2022 11:46:58 +0700 Subject: [PATCH 03/11] minor changes --- packages/fakeyou/src/v2/view/pricing/PricingPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index 292ea7192f..61a9a8f4c1 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -331,7 +331,7 @@ function PricingPage(props: Props) {
  • Commercial Voices
  • - Usable commercial voices + FakeYou commercial voices
  • From 1b7a1143b251bfd968e07e4f205988f05ea31057 Mon Sep 17 00:00:00 2001 From: BFlat Date: Mon, 31 Oct 2022 13:35:08 +0700 Subject: [PATCH 04/11] pricing plans --- packages/fakeyou/src/data/PriceTiers.js | 112 ++++---- packages/fakeyou/src/scss/site-refresh.scss | 3 +- .../src/v2/view/NewVocodesContainer.tsx | 5 +- .../fakeyou/src/v2/view/pricing/Pricing.tsx | 264 ------------------ .../src/v2/view/pricing/PricingPage.tsx | 259 +++++++++++++++++ 5 files changed, 324 insertions(+), 319 deletions(-) delete mode 100644 packages/fakeyou/src/v2/view/pricing/Pricing.tsx create mode 100644 packages/fakeyou/src/v2/view/pricing/PricingPage.tsx diff --git a/packages/fakeyou/src/data/PriceTiers.js b/packages/fakeyou/src/data/PriceTiers.js index 4872e10218..6ec704ada7 100644 --- a/packages/fakeyou/src/data/PriceTiers.js +++ b/packages/fakeyou/src/data/PriceTiers.js @@ -1,61 +1,71 @@ const FAKEYOU_PRICES = { - 'free': { - tier: 'free', + free: { + tier: "free", price: 0, features: { - 'Extended Audio': false, - 'mp3': false, - 'Priority Processing': false, - 'Commercial Voices': false - } + "Extended Audio": false, + mp3: false, + "Priority Processing": false, + "Commercial Voices": false, + }, }, - 'basic': { - tier: 'basic', - price: 5, + plus: { + tier: "plus", + price: 7, features: { - 'Extended Audio': true, - 'mp3': false, - 'Priority Processing': false, - 'Commercial Voices': false - } - }, - 'pro': { - tier: 'pro', - price: 30, - features: { - 'Extended Audio': true, - 'mp3': true, - 'Priority Processing': true, - 'Commercial Voices': true - } - } -} - -const STORYTELLER_PRICES = { - 'free': { - tier: 'free', - price: 0, - features: { - 'Priority Processing': false, - 'Stream Labs': false - } - }, - basic: { - tier: 'basic', - price: 5, - features: { - 'Priority Processing': false, - 'Stream Labs': false - } + "Extended Audio": true, + mp3: false, + "Priority Processing": false, + "Commercial Voices": false, + }, }, pro: { - tier: 'premium', + tier: "pro", + price: 15, + features: { + "Extended Audio": true, + mp3: true, + "Priority Processing": true, + "Commercial Voices": true, + }, + }, + elite: { + tier: "elite", + price: 25, + features: { + "Extended Audio": true, + mp3: true, + "Priority Processing": true, + "Commercial Voices": true, + }, + }, +}; + +const STORYTELLER_PRICES = { + free: { + tier: "free", + price: 0, + features: { + "Priority Processing": false, + "Stream Labs": false, + }, + }, + basic: { + tier: "basic", + price: 5, + features: { + "Priority Processing": false, + "Stream Labs": false, + }, + }, + pro: { + tier: "premium", price: 50, features: { - 'Priority Processing': true, - "Stream Labs": true - } - } -} + "Priority Processing": true, + "Stream Labs": true, + }, + }, +}; -export { FAKEYOU_PRICES, STORYTELLER_PRICES } \ No newline at end of file +export { FAKEYOU_PRICES, STORYTELLER_PRICES }; diff --git a/packages/fakeyou/src/scss/site-refresh.scss b/packages/fakeyou/src/scss/site-refresh.scss index 8abb68f445..5b8da0c810 100644 --- a/packages/fakeyou/src/scss/site-refresh.scss +++ b/packages/fakeyou/src/scss/site-refresh.scss @@ -390,11 +390,12 @@ styles with important tags: .panel-border { box-sizing: border-box; - box-shadow: inset 0px 0px 0px 4px lighten($primary, 5%); + box-shadow: inset 0px 0px 0px 3px $primary; } ul.pricing-list { list-style: none; + padding: 0; } ul li { diff --git a/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx b/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx index c8113b8a61..899cedb7ad 100644 --- a/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx +++ b/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx @@ -56,6 +56,7 @@ import { Language } from "@storyteller/components/src/i18n/Language"; import { VoiceCloneRequestPage } from "./clone_voice_requests/VoiceCloneRequestPage"; import { VocodesPage } from "./vocodes/VocodesPage"; import { UploadVocoderPage } from "./upload/UploadVocoderPage"; +import { PricingPage } from "./pricing/PricingPage"; interface Props { sessionWrapper: SessionWrapper; @@ -174,14 +175,12 @@ class NewVocodesContainer extends React.Component { /> - {/* { }} + querySessionCallback={() => {}} sessionWrapper={this.props.sessionWrapper} /> - */} diff --git a/packages/fakeyou/src/v2/view/pricing/Pricing.tsx b/packages/fakeyou/src/v2/view/pricing/Pricing.tsx deleted file mode 100644 index 62f8125b3a..0000000000 --- a/packages/fakeyou/src/v2/view/pricing/Pricing.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import React from "react"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Link } from "react-router-dom"; -import { - faCheckCircle as TRUE, - faTimesCircle as FALSE, - faCheck, -} from "@fortawesome/free-solid-svg-icons"; -import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; -import { - FAKEYOU_PRICES as FYP, - STORYTELLER_PRICES as STP, -} from "@storyteller/fakeyou/src/data/PriceTiers"; -import { - distance, - pricing1, - pricing2, - pricing3, - delay2, - duration, -} from "../../../data/animation"; - -const Fade = require("react-reveal/Fade"); - -interface Props { - sessionWrapper: SessionWrapper; - querySessionCallback: () => void; -} - -function PricingPage(props: Props) { - function capitalize(word: string) { - return word.charAt(0).toUpperCase() + word.slice(1); - } - - const [FY_TIERS, ST_TIERS] = [Object.keys(FYP), Object.keys(STP)]; - - const [FY_FEATURES, ST_FEATURES] = [ - Object.keys(FYP.free.features), - Object.keys(STP.free.features), - ]; - - let current_tiers: string[], current_features: string[], current_list: any; - - const site = window.location.hostname; - - switch (site) { - case "fakeyou": - [current_tiers, current_features, current_list] = [ - FY_TIERS, - FY_FEATURES, - FYP, - ]; - break; - case "storyteller": - [current_tiers, current_features, current_list] = [ - ST_TIERS, - ST_FEATURES, - STP, - ]; - break; - default: - [current_tiers, current_features, current_list] = [ - FY_TIERS, - FY_FEATURES, - FYP, - ]; - break; - } - - return ( -
    - -
    -

    FakeYou Pricing

    -
    -
    - -
    -
    -
    - -
    -

    Free

    -

    Great for hobbyists

    - - Create free TTS - -

    - ${current_list.free.price} - /month -

    -
      -
    • - - Unlimited TTS Generation -
    • -
    • - - Up to 10 seconds audio -
    • -
    -
    -
    -
    -
    - -
    -

    Basic

    -

    Great for hobbyists

    - - Buy Basic - -

    - ${current_list.basic.price} - /month -

    -
      -
    • - - Unlimited TTS Generation -
    • -
    • - - Up to 30 seconds audio -
    • -
    • - - Priority processing -
    • -
    -
    -
    -
    -
    - -
    -

    Pro

    -

    Great for hobbyists

    - - Buy Pro - -

    - ${current_list.pro.price} - /month -

    -
      -
    • - - Unlimited TTS Generation -
    • -
    • - - Up to 1 minute audio -
    • -
    • - - Priority processing -
    • -
    • - - Generate mp3 file -
    • -
    • - - For Commercial Use -
    • -
    -
    -
    -
    -
    -
    - - -
    -
    - - - - - - {current_tiers.map((e) => { - return ( - - ); - })} - - - - - - - - - - - - {current_features.map((e, i) => { - return ( - - - - - - - - - - ); - })} - -
    Feature List - {capitalize(e)} -
    Price${current_list.free.price}/month${current_list.basic.price}/month${current_list.pro.price}/month
    {e} - - - - - -
    -
    -
    -
    -
    - ); -} - -export { PricingPage }; diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx new file mode 100644 index 0000000000..f3fcce327e --- /dev/null +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -0,0 +1,259 @@ +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Link } from "react-router-dom"; +import { + faCheckCircle as TRUE, + faTimesCircle as FALSE, + faCheck, +} from "@fortawesome/free-solid-svg-icons"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import { + FAKEYOU_PRICES as FYP, + STORYTELLER_PRICES as STP, +} from "@storyteller/fakeyou/src/data/PriceTiers"; + +interface Props { + sessionWrapper: SessionWrapper; + querySessionCallback: () => void; +} + +function PricingPage(props: Props) { + function capitalize(word: string) { + return word.charAt(0).toUpperCase() + word.slice(1); + } + + const [FY_TIERS, ST_TIERS] = [Object.keys(FYP), Object.keys(STP)]; + + const [FY_FEATURES, ST_FEATURES] = [ + Object.keys(FYP.free.features), + Object.keys(STP.free.features), + ]; + + let current_tiers: string[], current_features: string[], current_list: any; + + const site = window.location.hostname; + + switch (site) { + case "fakeyou": + [current_tiers, current_features, current_list] = [ + FY_TIERS, + FY_FEATURES, + FYP, + ]; + break; + case "storyteller": + [current_tiers, current_features, current_list] = [ + ST_TIERS, + ST_FEATURES, + STP, + ]; + break; + default: + [current_tiers, current_features, current_list] = [ + FY_TIERS, + FY_FEATURES, + FYP, + ]; + break; + } + + return ( +
    +
    +

    Pricing

    +
    +
    +
    +
    +
    +

    Free

    + + Use free + +

    + ${current_list.free.price} + /month +

    +
      +
    • + + Unlimited TTS Generation +
    • +
    • + + Up to 10 seconds audio +
    • +
    +
    +
    +
    +
    +

    Plus

    + + Buy Plus + +

    + ${current_list.plus.price} + /month +

    +
      +
    • + + Unlimited TTS Generation +
    • +
    • + + Up to 30 seconds audio +
    • +
    • + + Priority processing +
    • +
    +
    +
    +
    +
    +

    Pro

    + + Buy Pro + +

    + ${current_list.pro.price} + /month +

    +
      +
    • + + Unlimited TTS Generation +
    • +
    • + + Up to 1 minute audio +
    • +
    • + + Priority processing +
    • +
    • + + Generate mp3 file +
    • +
    • + + For Commercial Use +
    • +
    +
    +
    +
    +
    +

    Elite

    + + Buy Elite + +

    + ${current_list.elite.price} + /month +

    +
      +
    • + + Unlimited TTS Generation +
    • +
    • + + Up to 1 minute audio +
    • +
    • + + Priority processing +
    • +
    • + + Generate mp3 file +
    • +
    • + + For Commercial Use +
    • +
    +
    +
    +
    +
    + +
    +
    + + + + + + {current_tiers.map((e) => { + return ( + + ); + })} + + + + + + + + + + + + {current_features.map((e, i) => { + return ( + + + + + + + + + + ); + })} + +
    Feature List + {capitalize(e)} +
    Price${current_list.free.price}/month${current_list.plus.price}/month${current_list.pro.price}/month
    {e} + + + + + +
    +
    +
    +
    + ); +} + +export { PricingPage }; From 72a86858fb7ef6586f1cffab12e16886740218fa Mon Sep 17 00:00:00 2001 From: BFlat Date: Mon, 31 Oct 2022 16:00:56 +0700 Subject: [PATCH 05/11] pricing page update --- packages/fakeyou/src/scss/site-refresh.scss | 11 + .../src/v2/view/pricing/PricingPage.tsx | 210 +++++++++++++++--- 2 files changed, 194 insertions(+), 27 deletions(-) diff --git a/packages/fakeyou/src/scss/site-refresh.scss b/packages/fakeyou/src/scss/site-refresh.scss index 5b8da0c810..c05e1f168f 100644 --- a/packages/fakeyou/src/scss/site-refresh.scss +++ b/packages/fakeyou/src/scss/site-refresh.scss @@ -396,6 +396,17 @@ styles with important tags: ul.pricing-list { list-style: none; padding: 0; + + li { + font-size: 14px; + } + + .small-text { + font-size: 12px; + font-weight: 400; + opacity: 0.8; + color: lighten($primary, 10%); + } } ul li { diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index f3fcce327e..292ea7192f 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -61,71 +61,139 @@ function PricingPage(props: Props) {

    Pricing

    +

    + Some kind of description here, idk haven't thought of it. +

    -
    +
    -

    Free

    - - Use free +

    Starter

    + + Use for free

    ${current_list.free.price} /month

    -
      +
        +
      • TTS
      • - Unlimited TTS Generation + Unlimited generation
      • - Up to 10 seconds audio + Up to 12 seconds audio +
      • +
      • VC Web
      • +
      • + + Up to 12 seconds audio +
      • +
      • + VC App (registered users) +
      • +
      • + 5 + model downloads +
      • +
      • + + Up to 12 secs prerecorded +
      • +
      • + + Up to 2 mins realtime +
      • +
      • Wav2Lip
      • +
      • + + Up to 12 seconds video +
      • +
      • Processing Priority
      • +
      • + + Level 0 +
      • +
      • + + Level 1 (registered users)
    -
    +

    Plus

    - + Buy Plus

    ${current_list.plus.price} /month

    -
      +
        +
      • TTS
      • - Unlimited TTS Generation + Unlimited generation
      • Up to 30 seconds audio
      • +
      • VC Web
      • +
      • + + Up to 30 seconds audio +
      • - Priority processing + Push to play +
      • +
      • VC App
      • +
      • + + 10 model downloads +
      • +
      • + + Up to 30 secs prerecorded +
      • +
      • + + Up to 7 mins realtime +
      • +
      • Wav2Lip
      • +
      • + + Up to 1 minute video +
      • +
      • Processing Priority
      • +
      • + + Level 20
    -
    +

    Pro

    - + Buy Pro

    ${current_list.pro.price} /month

    -
      +
        +
      • TTS
      • - Unlimited TTS Generation + Unlimited generation
      • @@ -133,49 +201,137 @@ function PricingPage(props: Props) {
      • - Priority processing + Generate MP3 file
      • - Generate mp3 file + Upload private models +
      • +
      • VC Web
      • +
      • + + Up to 2 minutes audio
      • - For Commercial Use + Push to play +
      • +
      • + + Generate MP3 file +
      • +
      • VC App
      • +
      • + + 20 model downloads +
      • +
      • + + Up to 5 mins prerecorded +
      • +
      • + + Up to 15 mins realtime +
      • +
      • Wav2Lip
      • +
      • + + Up to 2 minutes video +
      • +
      • Processing Priority
      • +
      • + + Level 30 +
      • +
      • API Access
      • +
      • + + Full API access
    -
    +

    Elite

    - + Buy Elite

    ${current_list.elite.price} /month

    -
      +
        +
      • TTS
      • - Unlimited TTS Generation + Unlimited generation
      • - Up to 1 minute audio + Up to 5 minutes audio
      • - Priority processing + Generate MP3 file
      • - Generate mp3 file + Upload private models
      • - For Commercial Use + Share private models +
      • +
      • VC Web
      • +
      • + + Up to 7 minutes audio +
      • +
      • + + Push to play +
      • +
      • + + Generate MP3 file +
      • +
      • VC App
      • +
      • + + Unlimited models +
      • +
      • + + Unlimited prerecorded +
      • +
      • + + Unlimited realtime +
      • +
      • Wav2Lip
      • +
      • + + Up to 5 minutes video +
      • +
      • + + Turn off watermark +
      • +
      • Processing Priority
      • +
      • + + Level 40 +
      • +
      • API Access
      • +
      • + + Full API access +
      • +
      • Commercial Voices
      • +
      • + + Usable commercial voices
    From 21020e1b1ea8352a8b5c28e3f36763bc3fa73f98 Mon Sep 17 00:00:00 2001 From: BFlat Date: Tue, 1 Nov 2022 11:46:58 +0700 Subject: [PATCH 06/11] minor changes --- packages/fakeyou/src/v2/view/pricing/PricingPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index 292ea7192f..61a9a8f4c1 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -331,7 +331,7 @@ function PricingPage(props: Props) {
  • Commercial Voices
  • - Usable commercial voices + FakeYou commercial voices
  • From 6bcdd7b210db199311fe211140009fa30905ef77 Mon Sep 17 00:00:00 2001 From: BFlat Date: Wed, 2 Nov 2022 15:09:52 +0700 Subject: [PATCH 07/11] pricing update --- packages/fakeyou/src/data/PriceTiers.js | 221 ++++-- .../src/v2/view/pricing/PricingPage.tsx | 697 ++++++++---------- 2 files changed, 490 insertions(+), 428 deletions(-) diff --git a/packages/fakeyou/src/data/PriceTiers.js b/packages/fakeyou/src/data/PriceTiers.js index 6ec704ada7..2dfbf74017 100644 --- a/packages/fakeyou/src/data/PriceTiers.js +++ b/packages/fakeyou/src/data/PriceTiers.js @@ -1,71 +1,176 @@ const FAKEYOU_PRICES = { - free: { - tier: "free", + //Starter Tier + starter: { + tier: "Starter", price: 0, - features: { - "Extended Audio": false, - mp3: false, - "Priority Processing": false, - "Commercial Voices": false, + tts: { + title: "TTS", + features: ["Unlimited generation", "Up to 12 seconds audio"], + }, + vcweb: { + title: "VC Web", + features: ["Up to 12 seconds audio"], + }, + vcapp: { + title: "VC App", + features: [ + "5 model downloads", + "Up to 12 secs prerecorded", + "Up to 2 mins realtime", + ], + }, + w2l: { + title: "Wav2Lip", + features: ["Up to 12 seconds video"], + }, + priority: { + title: "Processing Priority", + features: ["Level 1"], }, }, - plus: { - tier: "plus", - price: 7, - features: { - "Extended Audio": true, - mp3: false, - "Priority Processing": false, - "Commercial Voices": false, - }, - }, - pro: { - tier: "pro", - price: 15, - features: { - "Extended Audio": true, - mp3: true, - "Priority Processing": true, - "Commercial Voices": true, - }, - }, - elite: { - tier: "elite", - price: 25, - features: { - "Extended Audio": true, - mp3: true, - "Priority Processing": true, - "Commercial Voices": true, - }, - }, -}; -const STORYTELLER_PRICES = { - free: { - tier: "free", - price: 0, - features: { - "Priority Processing": false, - "Stream Labs": false, - }, - }, + //Basic Tier basic: { - tier: "basic", - price: 5, - features: { - "Priority Processing": false, - "Stream Labs": false, + tier: "Basic", + price: 3, + tts: { + title: "TTS", + features: ["Unlimited generation", "Up to 20 seconds audio"], + }, + vcweb: { + title: "VC Web", + features: ["Up to 20 seconds audio", "Push to play"], + }, + vcapp: { + title: "VC App", + features: [ + "7 model downloads", + "Up to 20 secs prerecorded", + "Up to 5 mins realtime", + ], + }, + w2l: { + title: "Wav2Lip", + features: ["Up to 30 seconds video"], + }, + priority: { + title: "Processing Priority", + features: ["Level 10"], }, }, + + //Plus Tier + plus: { + tier: "Plus", + price: 7, + tts: { + title: "TTS", + features: ["Unlimited generation", "Up to 30 seconds audio"], + }, + vcweb: { + title: "VC Web", + features: ["Up to 30 seconds audio", "Push to play"], + }, + vcapp: { + title: "VC App", + features: [ + "10 model downloads", + "Up to 30 secs prerecorded", + "Up to 7 mins realtime", + ], + }, + w2l: { + title: "Wav2Lip", + features: ["Up to 1 minute video"], + }, + priority: { + title: "Processing Priority", + features: ["Level 20"], + }, + }, + + //Pro Tier pro: { - tier: "premium", - price: 50, - features: { - "Priority Processing": true, - "Stream Labs": true, + tier: "Pro", + price: 15, + tts: { + title: "TTS", + features: [ + "Unlimited generation", + "Up to 1 minute audio", + "Generate MP3 file", + "Upload private models", + ], + }, + vcweb: { + title: "VC Web", + features: ["Up to 30 seconds audio", "Push to play", "Generate MP3 file"], + }, + vcapp: { + title: "VC App", + features: [ + "20 model downloads", + "Up to 5 mins prerecorded", + "Up to 15 mins realtime", + ], + }, + w2l: { + title: "Wav2Lip", + features: ["Up to 2 minutes video"], + }, + priority: { + title: "Processing Priority", + features: ["Level 30"], + }, + api: { + title: "API Access", + features: ["Full API access"], + }, + }, + + //Elite Tier + elite: { + tier: "Elite", + price: 25, + tts: { + title: "TTS", + features: [ + "Unlimited generation", + "Up to 5 minutes audio", + "Generate MP3 file", + "Upload private models", + "Share private models", + ], + }, + vcweb: { + title: "VC Web", + features: ["Up to 7 minutes audio", "Push to play", "Generate MP3 file"], + }, + vcapp: { + title: "VC App", + features: [ + "Unlimited models", + "Unlimited prerecorded", + "Unlimited realtime", + ], + }, + w2l: { + title: "Wav2Lip", + features: ["Up to 2 minutes video"], + }, + priority: { + title: "Processing Priority", + features: ["Level 40"], + }, + api: { + title: "API Access", + features: ["Full API access"], + }, + commercial: { + title: "Commercial Voices", + features: ["FakeYou commercial voices"], }, }, }; -export { FAKEYOU_PRICES, STORYTELLER_PRICES }; +export { FAKEYOU_PRICES }; diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index 61a9a8f4c1..72afba2032 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -1,16 +1,9 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link } from "react-router-dom"; -import { - faCheckCircle as TRUE, - faTimesCircle as FALSE, - faCheck, -} from "@fortawesome/free-solid-svg-icons"; +import { faCheck } from "@fortawesome/free-solid-svg-icons"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; -import { - FAKEYOU_PRICES as FYP, - STORYTELLER_PRICES as STP, -} from "@storyteller/fakeyou/src/data/PriceTiers"; +import { FAKEYOU_PRICES as FYP } from "@storyteller/fakeyou/src/data/PriceTiers"; interface Props { sessionWrapper: SessionWrapper; @@ -18,45 +11,6 @@ interface Props { } function PricingPage(props: Props) { - function capitalize(word: string) { - return word.charAt(0).toUpperCase() + word.slice(1); - } - - const [FY_TIERS, ST_TIERS] = [Object.keys(FYP), Object.keys(STP)]; - - const [FY_FEATURES, ST_FEATURES] = [ - Object.keys(FYP.free.features), - Object.keys(STP.free.features), - ]; - - let current_tiers: string[], current_features: string[], current_list: any; - - const site = window.location.hostname; - - switch (site) { - case "fakeyou": - [current_tiers, current_features, current_list] = [ - FY_TIERS, - FY_FEATURES, - FYP, - ]; - break; - case "storyteller": - [current_tiers, current_features, current_list] = [ - ST_TIERS, - ST_FEATURES, - STP, - ]; - break; - default: - [current_tiers, current_features, current_list] = [ - FY_TIERS, - FY_FEATURES, - FYP, - ]; - break; - } - return (
    @@ -65,347 +19,350 @@ function PricingPage(props: Props) { Some kind of description here, idk haven't thought of it.

    -
    +
    -

    Starter

    +

    + {FYP.starter.tier} +

    Use for free

    - ${current_list.free.price} + ${FYP.starter.price} /month

      -
    • TTS
    • -
    • - - Unlimited generation -
    • -
    • - - Up to 12 seconds audio -
    • -
    • VC Web
    • -
    • - - Up to 12 seconds audio -
    • -
    • - VC App (registered users) -
    • -
    • - 5 - model downloads -
    • -
    • - - Up to 12 secs prerecorded -
    • -
    • - - Up to 2 mins realtime -
    • -
    • Wav2Lip
    • -
    • - - Up to 12 seconds video -
    • -
    • Processing Priority
    • -
    • - - Level 0 -
    • -
    • - - Level 1 (registered users) -
    • -
    -
    -
    -
    -
    -

    Plus

    - - Buy Plus - -

    - ${current_list.plus.price} - /month -

    -
      -
    • TTS
    • -
    • - - Unlimited generation -
    • -
    • - - Up to 30 seconds audio -
    • -
    • VC Web
    • -
    • - - Up to 30 seconds audio -
    • -
    • - - Push to play -
    • -
    • VC App
    • -
    • - - 10 model downloads -
    • -
    • - - Up to 30 secs prerecorded -
    • -
    • - - Up to 7 mins realtime -
    • -
    • Wav2Lip
    • -
    • - - Up to 1 minute video -
    • -
    • Processing Priority
    • -
    • - - Level 20 -
    • -
    -
    -
    -
    -
    -

    Pro

    - - Buy Pro - -

    - ${current_list.pro.price} - /month -

    -
      -
    • TTS
    • -
    • - - Unlimited generation -
    • -
    • - - Up to 1 minute audio -
    • -
    • - - Generate MP3 file -
    • -
    • - - Upload private models -
    • -
    • VC Web
    • -
    • - - Up to 2 minutes audio -
    • -
    • - - Push to play -
    • -
    • - - Generate MP3 file -
    • -
    • VC App
    • -
    • - - 20 model downloads -
    • -
    • - - Up to 5 mins prerecorded -
    • -
    • - - Up to 15 mins realtime -
    • -
    • Wav2Lip
    • -
    • - - Up to 2 minutes video -
    • -
    • Processing Priority
    • -
    • - - Level 30 -
    • -
    • API Access
    • -
    • - - Full API access -
    • -
    -
    -
    -
    -
    -

    Elite

    - - Buy Elite - -

    - ${current_list.elite.price} - /month -

    -
      -
    • TTS
    • -
    • - - Unlimited generation -
    • -
    • - - Up to 5 minutes audio -
    • -
    • - - Generate MP3 file -
    • -
    • - - Upload private models -
    • -
    • - - Share private models -
    • -
    • VC Web
    • -
    • - - Up to 7 minutes audio -
    • -
    • - - Push to play -
    • -
    • - - Generate MP3 file -
    • -
    • VC App
    • -
    • - - Unlimited models -
    • -
    • - - Unlimited prerecorded -
    • -
    • - - Unlimited realtime -
    • -
    • Wav2Lip
    • -
    • - - Up to 5 minutes video -
    • -
    • - - Turn off watermark -
    • -
    • Processing Priority
    • -
    • - - Level 40 -
    • -
    • API Access
    • -
    • - - Full API access -
    • -
    • Commercial Voices
    • -
    • - - FakeYou commercial voices -
    • -
    -
    -
    -
    -
    - -
    -
    - - - - - - {current_tiers.map((e) => { +
  • {FYP.starter.tts.title}
  • + {FYP.starter.tts.features.map((e: any) => { return ( - +
  • + + {e} +
  • ); })} - - - - - - - - - - - - {current_features.map((e, i) => { - return ( - - - - - - - - - - ); - })} - -
    Feature List - {capitalize(e)} -
    Price${current_list.free.price}/month${current_list.plus.price}/month${current_list.pro.price}/month
    {e} +
  • {FYP.starter.vcweb.title}
  • + {FYP.starter.vcweb.features.map((e: any) => { + return ( +
  • -
  • + {e} + + ); + })} +
  • + {FYP.starter.vcapp.title}{" "} + (registered users) +
  • + {FYP.starter.vcapp.features.map((e: any) => { + return ( +
  • -
  • + {e} + + ); + })} +
  • {FYP.starter.w2l.title}
  • + {FYP.starter.w2l.features.map((e: any) => { + return ( +
  • -
  • + {e} + + ); + })} +
  • + {FYP.starter.priority.title}{" "} + (registered users) +
  • + {FYP.starter.priority.features.map((e: any) => { + return ( +
  • + + {e} +
  • + ); + })} + +
    +
    +
    +
    +

    {FYP.plus.tier}

    + + Buy {FYP.plus.tier} + +

    + ${FYP.plus.price} + /month +

    +
      +
    • {FYP.plus.tts.title}
    • + {FYP.plus.tts.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.plus.vcweb.title}
    • + {FYP.plus.vcweb.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.plus.vcapp.title}
    • + {FYP.plus.vcapp.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.plus.w2l.title}
    • + {FYP.plus.w2l.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.plus.priority.title}
    • + {FYP.plus.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    +
    +
    +
    +

    {FYP.pro.tier}

    + + Buy {FYP.pro.tier} + +

    + ${FYP.pro.price} + /month +

    +
      +
    • {FYP.pro.tts.title}
    • + {FYP.pro.tts.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.pro.vcweb.title}
    • + {FYP.pro.vcweb.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.pro.vcapp.title}
    • + {FYP.pro.vcapp.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.pro.w2l.title}
    • + {FYP.pro.w2l.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.pro.priority.title}
    • + {FYP.pro.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.pro.api.title}
    • + {FYP.pro.api.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    +
    +
    +
    +

    + {FYP.elite.tier} +

    + + Buy {FYP.elite.tier} + +

    + ${FYP.elite.price} + /month +

    +
      +
    • {FYP.elite.tts.title}
    • + {FYP.elite.tts.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.vcweb.title}
    • + {FYP.elite.vcweb.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.vcapp.title}
    • + {FYP.elite.vcapp.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.w2l.title}
    • + {FYP.elite.w2l.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.priority.title}
    • + {FYP.elite.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.api.title}
    • + {FYP.elite.api.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.commercial.title}
    • + {FYP.elite.commercial.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    +
    From b166f54344ccca094288d7b0a5bd3aa613b1fa26 Mon Sep 17 00:00:00 2001 From: BFlat Date: Wed, 2 Nov 2022 15:55:00 +0700 Subject: [PATCH 08/11] latin america basic tier --- .../src/v2/view/pricing/PricingPage.tsx | 191 +++++++++++++++++- 1 file changed, 190 insertions(+), 1 deletion(-) diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index 72afba2032..08c90a1129 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -21,7 +21,8 @@ function PricingPage(props: Props) {
    -
    + {/* Starter Tier */} + {/*

    {FYP.starter.tier} @@ -102,7 +103,87 @@ function PricingPage(props: Props) { })}

    +
    */} + + {/* Basic Tier */} +
    +
    +

    + {FYP.basic.tier} +

    + + Buy {FYP.basic.tier} + +

    + ${FYP.basic.price} + /month +

    +
      +
    • {FYP.basic.tts.title}
    • + {FYP.basic.tts.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.basic.vcweb.title}
    • + {FYP.basic.vcweb.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.basic.vcapp.title}
    • + {FYP.basic.vcapp.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.basic.w2l.title}
    • + {FYP.basic.w2l.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.basic.priority.title}
    • + {FYP.basic.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    + + {/* Plus Tier */}

    {FYP.plus.tier}

    @@ -177,6 +258,8 @@ function PricingPage(props: Props) {
    + + {/* Pro Tier */}

    {FYP.pro.tier}

    @@ -263,6 +346,8 @@ function PricingPage(props: Props) {
    + + {/* Elite Tier */}

    @@ -364,6 +449,110 @@ function PricingPage(props: Props) {

    + +
    +
    +
    +

    + {FYP.starter.tier} +

    + +

    + ${FYP.starter.price} + /month +

    +
    + + + Use for free + + +
    +
    +
      +
    • {FYP.starter.tts.title}
    • + {FYP.starter.tts.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
      +
    • {FYP.starter.vcweb.title}
    • + {FYP.starter.vcweb.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    +
    +
      +
    • + {FYP.starter.vcapp.title}{" "} + (registered users) +
    • + {FYP.starter.vcapp.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    +
    +
      +
    • {FYP.starter.w2l.title}
    • + {FYP.starter.w2l.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
      +
    • + {FYP.starter.priority.title}{" "} + (registered users) +
    • + {FYP.starter.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    +
    +
    +
    +
    ); From f3f3d99bacb140abb49fb24cf8f825f566a0efc7 Mon Sep 17 00:00:00 2001 From: BFlat Date: Wed, 2 Nov 2022 15:56:37 +0700 Subject: [PATCH 09/11] comments --- packages/fakeyou/src/v2/view/pricing/PricingPage.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index 08c90a1129..82ea4cb93e 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -22,7 +22,7 @@ function PricingPage(props: Props) {
    {/* Starter Tier */} - {/*
    +

    {FYP.starter.tier} @@ -103,10 +103,10 @@ function PricingPage(props: Props) { })}

    -
    */} +
    - {/* Basic Tier */} -
    + {/* Basic Tier (For Latin American countries) */} + {/*

    {FYP.basic.tier} @@ -181,7 +181,7 @@ function PricingPage(props: Props) { })}

    -
    +
    */} {/* Plus Tier */}
    @@ -450,6 +450,7 @@ function PricingPage(props: Props) {
    + {/* Starter Tier (to show for Latin American countries) */}
    From 4218f0c37ed782901d7cce0027101025e652fed6 Mon Sep 17 00:00:00 2001 From: BFlat Date: Wed, 2 Nov 2022 15:57:37 +0700 Subject: [PATCH 10/11] commented out bottom starter --- packages/fakeyou/src/v2/view/pricing/PricingPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx index 82ea4cb93e..ae551b18fb 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx @@ -451,7 +451,7 @@ function PricingPage(props: Props) {
    {/* Starter Tier (to show for Latin American countries) */} -
    + {/*

    @@ -553,7 +553,7 @@ function PricingPage(props: Props) {

    -
    +
    */}
    ); From 5b1242d6625c86d028658be34c0a80f691a61fdc Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Tue, 15 Nov 2022 20:31:39 -0500 Subject: [PATCH 11/11] Add checkout and portal related pages --- _redirects | 3 + packages/components/src/api/ApiConfig.ts | 16 ++ .../premium/CreateStripeCheckoutRedirect.ts | 58 +++++ .../api/premium/CreateStripePortalRedirect.ts | 58 +++++ .../api/premium/ListActiveSubscriptions.ts | 55 +++++ .../src/constants/ThirdPartyLinks.ts | 6 +- .../src/elements/EchelonTwitterLink.tsx | 48 ++++ .../session/SessionSubscriptionsWrapper.ts | 38 +++ packages/fakeyou/src/App.tsx | 16 +- packages/fakeyou/src/data/PriceTiers.js | 129 +++++----- .../fakeyou/src/v2/view/NewFooterNavFc.tsx | 3 +- .../src/v2/view/NewVocodesContainer.tsx | 29 ++- .../v2/view/premium/CheckoutCancelPage.tsx | 80 +++++++ .../v2/view/premium/CheckoutSuccessPage.tsx | 73 ++++++ .../src/v2/view/premium/PortalSuccessPage.tsx | 63 +++++ .../view/{pricing => premium}/PricingPage.tsx | 224 ++++++++++++------ 16 files changed, 757 insertions(+), 142 deletions(-) create mode 100644 packages/components/src/api/premium/CreateStripeCheckoutRedirect.ts create mode 100644 packages/components/src/api/premium/CreateStripePortalRedirect.ts create mode 100644 packages/components/src/api/premium/ListActiveSubscriptions.ts create mode 100644 packages/components/src/elements/EchelonTwitterLink.tsx create mode 100644 packages/components/src/session/SessionSubscriptionsWrapper.ts create mode 100644 packages/fakeyou/src/v2/view/premium/CheckoutCancelPage.tsx create mode 100644 packages/fakeyou/src/v2/view/premium/CheckoutSuccessPage.tsx create mode 100644 packages/fakeyou/src/v2/view/premium/PortalSuccessPage.tsx rename packages/fakeyou/src/v2/view/{pricing => premium}/PricingPage.tsx (84%) diff --git a/_redirects b/_redirects index e768dd163a..3d3f888dee 100644 --- a/_redirects +++ b/_redirects @@ -1,6 +1,8 @@ # We can't redirect everything until legacy vocodes is dead /about* /index.html 200 /category* /index.html 200 +/checkout_cancel* /index.html 200 +/checkout_success* /index.html 200 /clone* /index.html 200 /coming-soon* /index.html 200 /contribute* /index.html 200 @@ -14,6 +16,7 @@ /old* /index.html 200 /patrons* /index.html 200 /pending* /index.html 200 +/portal_success* /index.html 200 /profile* /index.html 200 /signup* /index.html 200 /stream* /index.html 200 diff --git a/packages/components/src/api/ApiConfig.ts b/packages/components/src/api/ApiConfig.ts index 141d6dff0c..17261e8d83 100644 --- a/packages/components/src/api/ApiConfig.ts +++ b/packages/components/src/api/ApiConfig.ts @@ -461,6 +461,22 @@ class ApiConfig { //return `wss://obs.storyteller.io/obs/${twitchUsername}`; } + // =============== Premium =============== + + listActiveSubscriptions(): string { + return `${this.getScheme()}://${this.getNewApiHost()}/v1/billing/active_subscriptions`; + } + + createStripeCheckoutRedirect(): string { + return `${this.getScheme()}://${this.getNewApiHost()}/v1/stripe/checkout/create_redirect`; + } + + createStripePortalRedirect(): string { + return `${this.getScheme()}://${this.getNewApiHost()}/v1/stripe/portal/create_redirect`; + } + + // =============== Helper =============== + private getScheme(): string { return this.useSsl ? "https" : "http"; } diff --git a/packages/components/src/api/premium/CreateStripeCheckoutRedirect.ts b/packages/components/src/api/premium/CreateStripeCheckoutRedirect.ts new file mode 100644 index 0000000000..83b67234e3 --- /dev/null +++ b/packages/components/src/api/premium/CreateStripeCheckoutRedirect.ts @@ -0,0 +1,58 @@ +import { ApiConfig } from "@storyteller/components"; + +export interface CreateStripeCheckoutRedirectRequest { + internal_plan_key: string, +} + +export interface CreateStripeCheckoutRedirectSuccessResponse { + success: boolean, + stripe_checkout_redirect_url: string, +} + +export interface CreateStripeCheckoutRedirectErrorResponse { + success: boolean, +} + +type CreateStripeCheckoutRedirectResponse = CreateStripeCheckoutRedirectSuccessResponse | CreateStripeCheckoutRedirectErrorResponse; + +export function CreateStripeCheckoutRedirectIsSuccess(response: CreateStripeCheckoutRedirectResponse): response is CreateStripeCheckoutRedirectSuccessResponse { + return response?.success === true; +} + +export function CreateStripeCheckoutRedirectIsError(response: CreateStripeCheckoutRedirectResponse): response is CreateStripeCheckoutRedirectErrorResponse { + return response?.success === false; +} + +export async function CreateStripeCheckoutRedirect(internal_plan_key: string) : Promise +{ + const endpoint = new ApiConfig().createStripeCheckoutRedirect(); + + const request : CreateStripeCheckoutRedirectRequest = { + internal_plan_key: internal_plan_key, + }; + + return await fetch(endpoint, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + credentials: 'include', + body: JSON.stringify(request), + }) + .then(res => res.json()) + .then(res => { + if (!res) { + return { success : false }; + } + + if (res && 'success' in res) { + return res; + } else { + return { success : false }; + } + }) + .catch(e => { + return { success : false }; + }); +} diff --git a/packages/components/src/api/premium/CreateStripePortalRedirect.ts b/packages/components/src/api/premium/CreateStripePortalRedirect.ts new file mode 100644 index 0000000000..1ff23ce5a9 --- /dev/null +++ b/packages/components/src/api/premium/CreateStripePortalRedirect.ts @@ -0,0 +1,58 @@ +import { ApiConfig } from "@storyteller/components"; + +export interface CreateStripePortalRedirectRequest { + portal_config_id?: string, +} + +export interface CreateStripePortalRedirectSuccessResponse { + success: boolean, + stripe_portal_redirect_url: string, +} + +export interface CreateStripePortalRedirectErrorResponse { + success: boolean, +} + +type CreateStripePortalRedirectResponse = CreateStripePortalRedirectSuccessResponse | CreateStripePortalRedirectErrorResponse; + +export function CreateStripePortalRedirectIsSuccess(response: CreateStripePortalRedirectResponse): response is CreateStripePortalRedirectSuccessResponse { + return response?.success === true; +} + +export function CreateStripePortalRedirectIsError(response: CreateStripePortalRedirectResponse): response is CreateStripePortalRedirectErrorResponse { + return response?.success === false; +} + +export async function CreateStripePortalRedirect(portal_config_id?: string) : Promise +{ + const endpoint = new ApiConfig().createStripePortalRedirect(); + + const request : CreateStripePortalRedirectRequest = { + portal_config_id: portal_config_id, + }; + + return await fetch(endpoint, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + credentials: 'include', + body: JSON.stringify(request), + }) + .then(res => res.json()) + .then(res => { + if (!res) { + return { success : false }; + } + + if (res && 'success' in res) { + return res; + } else { + return { success : false }; + } + }) + .catch(e => { + return { success : false }; + }); +} diff --git a/packages/components/src/api/premium/ListActiveSubscriptions.ts b/packages/components/src/api/premium/ListActiveSubscriptions.ts new file mode 100644 index 0000000000..d39fad91da --- /dev/null +++ b/packages/components/src/api/premium/ListActiveSubscriptions.ts @@ -0,0 +1,55 @@ +import { ApiConfig } from "@storyteller/components"; + +export interface ListActiveSubscriptionsSuccessResponse { + success: boolean, + maybe_loyalty_program?: string, + active_subscriptions: ActiveSubscription[], +} + +export interface ActiveSubscription { + namespace: string, + product_slug: string, +} + +export interface ListActiveSubscriptionsErrorResponse { + success: boolean, +} + +type ListActiveSubscriptionsResponse = ListActiveSubscriptionsSuccessResponse | ListActiveSubscriptionsErrorResponse; + +export function ListActiveSubscriptionsIsSuccess(response: ListActiveSubscriptionsResponse): response is ListActiveSubscriptionsSuccessResponse { + return response?.success === true; +} + +export function ListActiveSubscriptionsIsError(response: ListActiveSubscriptionsResponse): response is ListActiveSubscriptionsErrorResponse { + return response?.success === false; +} + +export async function ListActiveSubscriptions() : Promise +{ + const endpoint = new ApiConfig().listActiveSubscriptions(); + + return await fetch(endpoint, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + credentials: 'include', + }) + .then(res => res.json()) + .then(res => { + if (!res) { + return { success : false }; + } + + if (res && 'success' in res) { + return res; + } else { + return { success : false }; + } + }) + .catch(e => { + return { success : false }; + }); +} diff --git a/packages/components/src/constants/ThirdPartyLinks.ts b/packages/components/src/constants/ThirdPartyLinks.ts index e25de2e5be..49cf770110 100644 --- a/packages/components/src/constants/ThirdPartyLinks.ts +++ b/packages/components/src/constants/ThirdPartyLinks.ts @@ -6,10 +6,14 @@ class ThirdPartyLinks { // Old FakeYou Discord invite link: https://discord.gg/H72KFXm public static readonly FAKEYOU_DISCORD = "https://discord.gg/fakeyou"; - // A link to Twitter that will open a "Follow" prompt + // A link to FakeYou Twitter that will open a "Follow" prompt public static readonly FAKEYOU_TWITTER_WITH_FOLLOW_INTENT = "https://twitter.com/intent/follow?screen_name=FakeYouApp"; public static readonly FAKEYOU_PATREON = "https://www.patreon.com/fakeyou"; + + // A link to echelon's Twitter that will open a "Follow" prompt + // Additional followers may convince VC's that our founder has "clout" (one could hope) + public static readonly ECHELON_TWITTER_WITH_FOLLOW_INTENT = "https://twitter.com/intent/follow?screen_name=echelon"; } export { ThirdPartyLinks } \ No newline at end of file diff --git a/packages/components/src/elements/EchelonTwitterLink.tsx b/packages/components/src/elements/EchelonTwitterLink.tsx new file mode 100644 index 0000000000..a775515ab6 --- /dev/null +++ b/packages/components/src/elements/EchelonTwitterLink.tsx @@ -0,0 +1,48 @@ +import React from "react"; +import { faTwitter } from "@fortawesome/free-brands-svg-icons"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ThirdPartyLinks } from "../constants/ThirdPartyLinks"; + +interface Props { + hideIcon?: boolean; + iconBeforeText?: boolean; + title?: string; + children?: string | Element | Array; // Optional link text, child elements, etc. +} + +function EchelonTwitterLink(props: Props) { + let linkBody = + props.children === undefined ? <>echelon : <>{props.children}; + + const showIcon = !(props.hideIcon ? true : false); + const iconBeforeText = props.iconBeforeText ? true : false; + + const linkTitle = props.title ? props.title : "echelon's Twitter"; + + if (showIcon) { + linkBody = iconBeforeText ? ( + <> + {" "} + {linkBody} + + ) : ( + <> + {linkBody}{" "} + + + ); + } + + return ( + + {linkBody} + + ); +} + +export { EchelonTwitterLink }; diff --git a/packages/components/src/session/SessionSubscriptionsWrapper.ts b/packages/components/src/session/SessionSubscriptionsWrapper.ts new file mode 100644 index 0000000000..a72da017f0 --- /dev/null +++ b/packages/components/src/session/SessionSubscriptionsWrapper.ts @@ -0,0 +1,38 @@ +import { ListActiveSubscriptions, ListActiveSubscriptionsIsSuccess, ListActiveSubscriptionsSuccessResponse } from "../api/premium/ListActiveSubscriptions"; + +export class SessionSubscriptionsWrapper { + listActiveSubscriptionResponse?: ListActiveSubscriptionsSuccessResponse; + + private constructor(listActiveSubscriptionsSuccessResponse?: ListActiveSubscriptionsSuccessResponse) { + if (listActiveSubscriptionsSuccessResponse !== undefined) { + this.listActiveSubscriptionResponse = listActiveSubscriptionsSuccessResponse; + } + } + + public static async lookupActiveSubscriptions() : Promise { + let response = await ListActiveSubscriptions(); + if (ListActiveSubscriptionsIsSuccess(response)) { + return new SessionSubscriptionsWrapper(response); + } else { + return SessionSubscriptionsWrapper.emptySubscriptions(); + } + } + + public static emptySubscriptions() : SessionSubscriptionsWrapper { + return new SessionSubscriptionsWrapper(); + } + + public hasFreeOrPaidPremiumFeatures() : boolean { + return this.hasLoyaltyProgram() || this.hasPaidFeatures(); + } + + + public hasLoyaltyProgram() : boolean { + return !!this.listActiveSubscriptionResponse?.maybe_loyalty_program; + } + + public hasPaidFeatures() : boolean { + const subs = this.listActiveSubscriptionResponse?.active_subscriptions || []; + return subs.length > 0; + } +} \ No newline at end of file diff --git a/packages/fakeyou/src/App.tsx b/packages/fakeyou/src/App.tsx index ebc92ce08c..71c39f7f26 100644 --- a/packages/fakeyou/src/App.tsx +++ b/packages/fakeyou/src/App.tsx @@ -10,6 +10,7 @@ import { Language } from "@storyteller/components/src/i18n/Language"; import { BrowserRouter, Route, Switch } from "react-router-dom"; import { NewVocodesContainer } from "./v2/view/NewVocodesContainer"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper"; import { TtsInferenceJob, TtsInferenceJobStateResponsePayload, @@ -92,6 +93,7 @@ interface State { // Rollout of vocodes 2.0 enableAlpha: boolean; sessionWrapper: SessionWrapper; + sessionSubscriptionsWrapper: SessionSubscriptionsWrapper; // Show flash notice of vocodes name change isShowingVocodesNotice: boolean; @@ -154,7 +156,9 @@ class App extends React.Component { this.state = { enableAlpha: enableAlpha, migrationMode: migrationMode, + sessionWrapper: SessionWrapper.emptySession(), + sessionSubscriptionsWrapper: SessionSubscriptionsWrapper.emptySubscriptions(), isShowingVocodesNotice: props.flashVocodesNotice, @@ -194,11 +198,13 @@ class App extends React.Component { } async componentDidMount() { - await this.querySession(); await this.queryLanguage(); + await this.querySession(); + await this.querySessionSubscriptions(); setInterval(async () => { await this.querySession(); + await this.querySessionSubscriptions(); }, 60000); // TODO: Use websockets, this is dumb setInterval(() => { @@ -213,6 +219,13 @@ class App extends React.Component { }); }; + querySessionSubscriptions = async () => { + const sessionSubscriptionsWrapper = await SessionSubscriptionsWrapper.lookupActiveSubscriptions(); + this.setState({ + sessionSubscriptionsWrapper: sessionSubscriptionsWrapper, + }); + }; + queryLanguage = async () => { let locale = await DetectLocale(); if (DetectLocaleIsOk(locale)) { @@ -645,6 +658,7 @@ class App extends React.Component {
    - Built by echelon in Atlanta. + Built by in Atlanta.
    diff --git a/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx b/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx index 899cedb7ad..a1856ee94f 100644 --- a/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx +++ b/packages/fakeyou/src/v2/view/NewVocodesContainer.tsx @@ -11,6 +11,7 @@ import { NewTopNavFc } from "./NewTopNavFc"; import { ProfileEditFc } from "./profile/profile_edit/ProfileEditFc"; import { ProfileFc } from "./profile/profile_view/ProfileFc"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper"; import { SignupPage } from "./signup/SignupPage"; import { Switch, Route } from "react-router-dom"; import { TermsPage } from "./about/terms_page/TermsPage"; @@ -56,12 +57,17 @@ import { Language } from "@storyteller/components/src/i18n/Language"; import { VoiceCloneRequestPage } from "./clone_voice_requests/VoiceCloneRequestPage"; import { VocodesPage } from "./vocodes/VocodesPage"; import { UploadVocoderPage } from "./upload/UploadVocoderPage"; -import { PricingPage } from "./pricing/PricingPage"; +import { PricingPage } from "./premium/PricingPage"; +import { CheckoutSuccessPage } from "./premium/CheckoutSuccessPage"; +import { CheckoutCancelPage } from "./premium/CheckoutCancelPage"; +import { PortalSuccessPage } from "./premium/PortalSuccessPage"; interface Props { sessionWrapper: SessionWrapper; querySessionAction: () => void; + sessionSubscriptionsWrapper: SessionSubscriptionsWrapper; + isShowingVocodesNotice: boolean; clearVocodesNotice: () => void; @@ -175,8 +181,27 @@ class NewVocodesContainer extends React.Component { /> - + + + + + {}} + sessionWrapper={this.props.sessionWrapper} + /> + + + {}} + sessionWrapper={this.props.sessionWrapper} + /> + + + {}} sessionWrapper={this.props.sessionWrapper} /> diff --git a/packages/fakeyou/src/v2/view/premium/CheckoutCancelPage.tsx b/packages/fakeyou/src/v2/view/premium/CheckoutCancelPage.tsx new file mode 100644 index 0000000000..a0156e4f8a --- /dev/null +++ b/packages/fakeyou/src/v2/view/premium/CheckoutCancelPage.tsx @@ -0,0 +1,80 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { motion } from "framer-motion"; +import { container, item, image } from "../../../data/animation"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; + +interface Props { + sessionWrapper: SessionWrapper; + querySessionCallback: () => void; +} + +function CheckoutCancelPage(props: Props) { + return ( + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + Oh no! + +
    +
    + + It's okay if you don't want to support FakeYou right now, but we'd + appreciate it if you reconsider us in the future. + +
    + + Paid plans go directly to helping us afford more GPUs, engineering, + and research talent. + +
    + + We're trying to build a film and music production system that you + can use to make any content you dream up. Please consider supporting + us monetarily. + +
    +
    +
    +
    +
    + + Back to FakeYou + +
    +
    +
    +
    + + + Select a Premium Plan + +
    +
    +
    +
    + +
    + ); +} + +export { CheckoutCancelPage }; diff --git a/packages/fakeyou/src/v2/view/premium/CheckoutSuccessPage.tsx b/packages/fakeyou/src/v2/view/premium/CheckoutSuccessPage.tsx new file mode 100644 index 0000000000..d96a798c80 --- /dev/null +++ b/packages/fakeyou/src/v2/view/premium/CheckoutSuccessPage.tsx @@ -0,0 +1,73 @@ + +import React from "react"; +import { Link } from "react-router-dom"; +import { motion } from "framer-motion"; +import { container, item, image, panel } from "../../../data/animation"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; + +interface Props { + sessionWrapper: SessionWrapper; + querySessionCallback: () => void; +} + +function CheckoutSuccessPage(props: Props) { + return ( + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + Thank you! + +
    +
    +
    + + We're grateful you're helping FakeYou build the future creative + suite. We're building tools for small creators and have an eye + on building a full AI-powered Hollywood and music production + studio. + +
    + + Your support helps us immensely! + +
    + + Please give it a few minutes for your purchase to take effect. + +
    +
    +
    +
    +
    + + Back to FakeYou + +
    +
    +
    +
    + +
    + ); +} + +export { CheckoutSuccessPage }; diff --git a/packages/fakeyou/src/v2/view/premium/PortalSuccessPage.tsx b/packages/fakeyou/src/v2/view/premium/PortalSuccessPage.tsx new file mode 100644 index 0000000000..a212393e5d --- /dev/null +++ b/packages/fakeyou/src/v2/view/premium/PortalSuccessPage.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { motion } from "framer-motion"; +import { container, item, image, panel } from "../../../data/animation"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; + +interface Props { + sessionWrapper: SessionWrapper; + querySessionCallback: () => void; +} + +function PortalSuccessPage(props: Props) { + return ( + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + Thank You! + +
    +
    + + Your support means a lot to us. + + + Please continue to enjoy FakeYou! + +
    +
    +
    +
    +
    + + Back to FakeYou + +
    +
    +
    +
    + +
    + ); +} + +export { PortalSuccessPage }; diff --git a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx b/packages/fakeyou/src/v2/view/premium/PricingPage.tsx similarity index 84% rename from packages/fakeyou/src/v2/view/pricing/PricingPage.tsx rename to packages/fakeyou/src/v2/view/premium/PricingPage.tsx index ae551b18fb..a77171ca4e 100644 --- a/packages/fakeyou/src/v2/view/pricing/PricingPage.tsx +++ b/packages/fakeyou/src/v2/view/premium/PricingPage.tsx @@ -3,20 +3,74 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link } from "react-router-dom"; import { faCheck } from "@fortawesome/free-solid-svg-icons"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper"; import { FAKEYOU_PRICES as FYP } from "@storyteller/fakeyou/src/data/PriceTiers"; +import { + CreateStripeCheckoutRedirect, + CreateStripeCheckoutRedirectIsError, + CreateStripeCheckoutRedirectIsSuccess, +} from "@storyteller/components/src/api/premium/CreateStripeCheckoutRedirect"; +import { + CreateStripePortalRedirect, + CreateStripePortalRedirectIsError, + CreateStripePortalRedirectIsSuccess, +} from "@storyteller/components/src/api/premium/CreateStripePortalRedirect"; interface Props { sessionWrapper: SessionWrapper; - querySessionCallback: () => void; + sessionSubscriptionsWrapper: SessionSubscriptionsWrapper; } function PricingPage(props: Props) { + + const beginStripeCheckoutFlow = async (internal_plan_key: string) : Promise => { + const response = await CreateStripeCheckoutRedirect(internal_plan_key); + if (CreateStripeCheckoutRedirectIsSuccess(response)) { + window.location.href = response.stripe_checkout_redirect_url; + } else if (CreateStripeCheckoutRedirectIsError(response)) { + // TODO + } + return false; + } + + const beginStripePortalFlow = async () : Promise => { + const response = await CreateStripePortalRedirect(); + if (CreateStripePortalRedirectIsSuccess(response)) { + window.location.href = response.stripe_portal_redirect_url; + } else if (CreateStripePortalRedirectIsError(response)) { + // TODO + } + return false; + } + + const beginStripeFlow = async (internal_plan_key: string) : Promise => { + if (props.sessionSubscriptionsWrapper.hasPaidFeatures()) { + return await beginStripePortalFlow(); + } else { + return await beginStripeCheckoutFlow(internal_plan_key); + } + }; + + const hasPaidPremium = props.sessionSubscriptionsWrapper.hasPaidFeatures(); + + let freeButtonText = 'Use for free'; + let plusButtonText = 'Buy Plus'; + let proButtonText = 'Buy Pro'; + let eliteButtonText = 'Buy Elite'; + + if (hasPaidPremium) { + freeButtonText = 'Unsubscribe'; + plusButtonText = 'Switch to Plus'; + proButtonText = 'Switch to Pro'; + eliteButtonText = 'Switch to Elite'; + } + return (

    Pricing

    - Some kind of description here, idk haven't thought of it. + By purchasing FakeYou premium, you help us build more!

    @@ -28,13 +82,31 @@ function PricingPage(props: Props) { {FYP.starter.tier} - Use for free + {freeButtonText}

    ${FYP.starter.price} /month

      + +
    • + {FYP.starter.priority.title} +
    • + {FYP.starter.priority.features.map((e: any) => { + return ( +
    • + + {e} + {" "} + (registered users) +
    • + ); + })} +
    • {FYP.starter.tts.title}
    • {FYP.starter.tts.features.map((e: any) => { return ( @@ -47,7 +119,7 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.starter.vcweb.title}
    • + {/*
    • {FYP.starter.vcweb.title}
    • {FYP.starter.vcweb.features.map((e: any) => { return (
    • @@ -73,7 +145,7 @@ function PricingPage(props: Props) { {e}
    • ); - })} + })}*/}
    • {FYP.starter.w2l.title}
    • {FYP.starter.w2l.features.map((e: any) => { return ( @@ -86,21 +158,6 @@ function PricingPage(props: Props) { ); })} -
    • - {FYP.starter.priority.title}{" "} - (registered users) -
    • - {FYP.starter.priority.features.map((e: any) => { - return ( -
    • - - {e} -
    • - ); - })}
    @@ -187,14 +244,32 @@ function PricingPage(props: Props) {

    {FYP.plus.tier}

    - - Buy {FYP.plus.tier} - +

    ${FYP.plus.price} /month

      + +
    • {FYP.plus.priority.title}
    • + {FYP.plus.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} + +
    • {FYP.plus.tts.title}
    • {FYP.plus.tts.features.map((e: any) => { return ( @@ -207,7 +282,7 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.plus.vcweb.title}
    • + {/*
    • {FYP.plus.vcweb.title}
    • {FYP.plus.vcweb.features.map((e: any) => { return (
    • @@ -230,7 +305,7 @@ function PricingPage(props: Props) { {e}
    • ); - })} + })}*/}
    • {FYP.plus.w2l.title}
    • {FYP.plus.w2l.features.map((e: any) => { return ( @@ -243,18 +318,6 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.plus.priority.title}
    • - {FYP.plus.priority.features.map((e: any) => { - return ( -
    • - - {e} -
    • - ); - })}
    @@ -263,14 +326,32 @@ function PricingPage(props: Props) {

    {FYP.pro.tier}

    - - Buy {FYP.pro.tier} - +

    ${FYP.pro.price} /month

      + +
    • {FYP.pro.priority.title}
    • + {FYP.pro.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} + +
    • {FYP.pro.tts.title}
    • {FYP.pro.tts.features.map((e: any) => { return ( @@ -283,7 +364,7 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.pro.vcweb.title}
    • + {/*
    • {FYP.pro.vcweb.title}
    • {FYP.pro.vcweb.features.map((e: any) => { return (
    • @@ -306,7 +387,7 @@ function PricingPage(props: Props) { {e}
    • ); - })} + })}*/}
    • {FYP.pro.w2l.title}
    • {FYP.pro.w2l.features.map((e: any) => { return ( @@ -319,19 +400,7 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.pro.priority.title}
    • - {FYP.pro.priority.features.map((e: any) => { - return ( -
    • - - {e} -
    • - ); - })} -
    • {FYP.pro.api.title}
    • + {/*
    • {FYP.pro.api.title}
    • {FYP.pro.api.features.map((e: any) => { return (
    • @@ -342,7 +411,7 @@ function PricingPage(props: Props) { {e}
    • ); - })} + })}*/}
    @@ -353,14 +422,31 @@ function PricingPage(props: Props) {

    {FYP.elite.tier}

    - - Buy {FYP.elite.tier} - +

    ${FYP.elite.price} /month

      + +
    • {FYP.elite.priority.title}
    • + {FYP.elite.priority.features.map((e: any) => { + return ( +
    • + + {e} +
    • + ); + })} +
    • {FYP.elite.tts.title}
    • {FYP.elite.tts.features.map((e: any) => { return ( @@ -373,7 +459,7 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.elite.vcweb.title}
    • + {/*
    • {FYP.elite.vcweb.title}
    • {FYP.elite.vcweb.features.map((e: any) => { return (
    • @@ -396,7 +482,7 @@ function PricingPage(props: Props) { {e}
    • ); - })} + })}*/}
    • {FYP.elite.w2l.title}
    • {FYP.elite.w2l.features.map((e: any) => { return ( @@ -409,19 +495,7 @@ function PricingPage(props: Props) { ); })} -
    • {FYP.elite.priority.title}
    • - {FYP.elite.priority.features.map((e: any) => { - return ( -
    • - - {e} -
    • - ); - })} -
    • {FYP.elite.api.title}
    • + {/*
    • {FYP.elite.api.title}
    • {FYP.elite.api.features.map((e: any) => { return (
    • @@ -432,7 +506,7 @@ function PricingPage(props: Props) { {e}
    • ); - })} + })}*/}
    • {FYP.elite.commercial.title}
    • {FYP.elite.commercial.features.map((e: any) => { return (