fix: hide subscription marketing on iOS (#1929)

This commit is contained in:
Mo
2022-11-02 12:07:26 -05:00
committed by GitHub
parent f3e2d80b44
commit 35b21b21ce
13 changed files with 100 additions and 42 deletions

View File

@@ -203,6 +203,14 @@ export class WebApplication extends SNApplication implements WebApplicationInter
return undefined return undefined
} }
isNativeIOS() {
return this.isNativeMobileWeb() && this.platform === Platform.Ios
}
get hideSubscriptionMarketing() {
return this.isNativeIOS()
}
mobileDevice(): MobileDeviceInterface { mobileDevice(): MobileDeviceInterface {
if (!this.isNativeMobileWeb()) { if (!this.isNativeMobileWeb()) {
throw Error('Attempting to access device as mobile device on non mobile platform') throw Error('Attempting to access device as mobile device on non mobile platform')

View File

@@ -110,6 +110,7 @@ const ContentListView: FunctionComponent<Props> = ({
renderedItems, renderedItems,
items, items,
searchBarElement, searchBarElement,
isCurrentNoteTemplate,
} = itemListController } = itemListController
const { selectedUuids, selectNextItem, selectPreviousItem } = selectionController const { selectedUuids, selectNextItem, selectPreviousItem } = selectionController
@@ -245,13 +246,13 @@ const ContentListView: FunctionComponent<Props> = ({
) )
useEffect(() => { useEffect(() => {
const hasEditorPane = selectedUuids.size > 0 const hasEditorPane = selectedUuids.size > 0 || renderedItems.length === 0 || isCurrentNoteTemplate
if (!hasEditorPane) { if (!hasEditorPane) {
itemsViewPanelRef.current?.style.removeProperty('width') itemsViewPanelRef.current?.style.removeProperty('width')
} }
}, [selectedUuids, itemsViewPanelRef]) }, [selectedUuids, itemsViewPanelRef, isCurrentNoteTemplate, renderedItems])
const hasEditorPane = selectedUuids.size > 0 || renderedItems.length === 0 const hasEditorPane = selectedUuids.size > 0 || renderedItems.length === 0 || isCurrentNoteTemplate
return ( return (
<div <div

View File

@@ -212,14 +212,17 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
{!DailyEntryModeEnabled && {!DailyEntryModeEnabled &&
'Create powerful workflows and organizational layouts with per-tag display preferences.'} 'Create powerful workflows and organizational layouts with per-tag display preferences.'}
</p> </p>
<Button
primary {!application.hideSubscriptionMarketing && (
small <Button
className="col-start-1 col-end-3 mt-3 justify-self-start uppercase" primary
onClick={() => application.openPurchaseFlow()} small
> className="col-start-1 col-end-3 mt-3 justify-self-start uppercase"
Upgrade Features onClick={() => application.openPurchaseFlow()}
</Button> >
Upgrade Features
</Button>
)}
</div> </div>
) )

View File

@@ -12,6 +12,10 @@ const UpgradeNow = ({ application, featuresController }: Props) => {
const shouldShowCTA = !featuresController.hasFolders const shouldShowCTA = !featuresController.hasFolders
const hasAccount = application.hasAccount() const hasAccount = application.hasAccount()
if (hasAccount && application.hideSubscriptionMarketing) {
return null
}
return shouldShowCTA ? ( return shouldShowCTA ? (
<div className="flex h-full items-center px-2"> <div className="flex h-full items-center px-2">
<button <button

View File

@@ -286,11 +286,13 @@ const NotesOptions = ({
const switchClassNames = classNames(textClassNames, defaultClassNames, 'justify-between') const switchClassNames = classNames(textClassNames, defaultClassNames, 'justify-between')
const firstItemClass = 'pt-4'
return ( return (
<> <>
{notes.length === 1 && ( {notes.length === 1 && (
<> <>
<button className={defaultClassNames} onClick={openRevisionHistoryModal}> <button className={classNames(defaultClassNames, firstItemClass)} onClick={openRevisionHistoryModal}>
<Icon type="history" className={iconClass} /> <Icon type="history" className={iconClass} />
Note history Note history
</button> </button>

View File

@@ -31,12 +31,14 @@ const NoSubscription: FunctionComponent<Props> = ({ application }) => {
<Text>You don't have a Standard Notes subscription yet.</Text> <Text>You don't have a Standard Notes subscription yet.</Text>
{isLoadingPurchaseFlow && <Text>Redirecting you to the subscription page...</Text>} {isLoadingPurchaseFlow && <Text>Redirecting you to the subscription page...</Text>}
{purchaseFlowError && <Text className="text-danger">{purchaseFlowError}</Text>} {purchaseFlowError && <Text className="text-danger">{purchaseFlowError}</Text>}
<div className="flex"> {!application.hideSubscriptionMarketing && (
<LinkButton className="mt-3 mr-3 min-w-20" label="Learn More" link={window.plansUrl as string} /> <div className="flex">
{application.hasAccount() && ( <LinkButton className="mt-3 mr-3 min-w-20" label="Learn More" link={window.plansUrl as string} />
<Button className="mt-3 min-w-20" primary label="Subscribe" onClick={onPurchaseClick} /> {application.hasAccount() && (
)} <Button className="mt-3 min-w-20" primary label="Subscribe" onClick={onPurchaseClick} />
</div> )}
</div>
)}
</> </>
) )
} }

View File

@@ -34,12 +34,15 @@ const NoProSubscription: FunctionComponent<Props> = ({ application }) => {
</Text> </Text>
{isLoadingPurchaseFlow && <Text>Redirecting you to the subscription page...</Text>} {isLoadingPurchaseFlow && <Text>Redirecting you to the subscription page...</Text>}
{purchaseFlowError && <Text className="text-danger">{purchaseFlowError}</Text>} {purchaseFlowError && <Text className="text-danger">{purchaseFlowError}</Text>}
<div className="flex">
<LinkButton className="mt-3 mr-3 min-w-20" label="Learn More" link={window.plansUrl as string} /> {!application.hideSubscriptionMarketing && (
{application.hasAccount() && ( <div className="flex">
<Button className="mt-3 min-w-20" primary label="Upgrade" onClick={onPurchaseClick} /> <LinkButton className="mt-3 mr-3 min-w-20" label="Learn More" link={window.plansUrl as string} />
)} {application.hasAccount() && (
</div> <Button className="mt-3 min-w-20" primary label="Upgrade" onClick={onPurchaseClick} />
)}
</div>
)}
</> </>
) )
} }

View File

@@ -61,15 +61,17 @@ const PremiumFeaturesModal: FunctionComponent<Props> = ({
To take advantage of <span className="font-semibold">{featureName}</span> and other advanced features, To take advantage of <span className="font-semibold">{featureName}</span> and other advanced features,
upgrade your current plan. upgrade your current plan.
</AlertDialogDescription> </AlertDialogDescription>
<div className="p-4"> {!application.hideSubscriptionMarketing && (
<button <div className="p-4">
onClick={handleClick} <button
className="no-border w-full cursor-pointer rounded bg-info py-2 font-bold text-info-contrast hover:brightness-125 focus:brightness-125" onClick={handleClick}
ref={plansButtonRef} className="no-border w-full cursor-pointer rounded bg-info py-2 font-bold text-info-contrast hover:brightness-125 focus:brightness-125"
> ref={plansButtonRef}
Upgrade >
</button> Upgrade
</div> </button>
</div>
)}
</div> </div>
</div> </div>
</AlertDialog> </AlertDialog>

View File

@@ -2,6 +2,7 @@ import { WebApplication } from '@/Application/Application'
import { FunctionComponent, MouseEventHandler, useCallback } from 'react' import { FunctionComponent, MouseEventHandler, useCallback } from 'react'
import Switch from '@/Components/Switch/Switch' import Switch from '@/Components/Switch/Switch'
import { isMobileScreen } from '@/Utils' import { isMobileScreen } from '@/Utils'
import { classNames } from '@/Utils/ConcatenateClassNames'
type Props = { type Props = {
application: WebApplication application: WebApplication
@@ -29,7 +30,11 @@ const FocusModeSwitch: FunctionComponent<Props> = ({ application, onToggle, onCl
return ( return (
<button <button
className="group flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none disabled:bg-default disabled:text-passive-2" className={classNames(
'group flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left',
'text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none disabled:bg-default disabled:text-passive-2',
'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item',
)}
onClick={toggle} onClick={toggle}
> >
<div className="flex items-center">Focused Writing</div> <div className="flex items-center">Focused Writing</div>

View File

@@ -53,7 +53,7 @@ const PanelSettingsSection = ({ application }: Props) => {
}, [application]) }, [application])
return ( return (
<div className="hidden text-sm md:block pointer-coarse:md-only:hidden pointer-coarse:lg-only:hidden"> <div className="hidden md:block pointer-coarse:md-only:hidden pointer-coarse:lg-only:hidden">
<MenuItem <MenuItem
type={MenuItemType.SwitchButton} type={MenuItemType.SwitchButton}
className="py-1 hover:bg-contrast focus:bg-info-backdrop" className="py-1 hover:bg-contrast focus:bg-info-backdrop"

View File

@@ -21,6 +21,7 @@ import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { QuickSettingsController } from '@/Controllers/QuickSettingsController' import { QuickSettingsController } from '@/Controllers/QuickSettingsController'
import PanelSettingsSection from './PanelSettingsSection' import PanelSettingsSection from './PanelSettingsSection'
import { PrefDefaults } from '@/Constants/PrefDefaults' import { PrefDefaults } from '@/Constants/PrefDefaults'
import { classNames } from '@/Utils/ConcatenateClassNames'
const focusModeAnimationDuration = 1255 const focusModeAnimationDuration = 1255
@@ -173,7 +174,11 @@ const QuickSettingsMenu: FunctionComponent<MenuProps> = ({ application, quickSet
<div className="my-1 px-3 text-sm font-semibold uppercase text-text">Tools</div> <div className="my-1 px-3 text-sm font-semibold uppercase text-text">Tools</div>
{toggleableComponents.map((component) => ( {toggleableComponents.map((component) => (
<button <button
className="flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-mobile-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none md:text-sm" className={classNames(
'flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left',
'text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none',
'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item',
)}
onClick={() => { onClick={() => {
toggleComponent(component) toggleComponent(component)
}} }}
@@ -191,7 +196,11 @@ const QuickSettingsMenu: FunctionComponent<MenuProps> = ({ application, quickSet
)} )}
<div className="my-1 px-3 text-sm font-semibold uppercase text-text">Appearance</div> <div className="my-1 px-3 text-sm font-semibold uppercase text-text">Appearance</div>
<button <button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-mobile-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none md:text-sm" className={classNames(
'flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left',
'text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none',
'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item',
)}
onClick={toggleDefaultTheme} onClick={toggleDefaultTheme}
ref={defaultThemeButtonRef} ref={defaultThemeButtonRef}
> >

View File

@@ -8,6 +8,7 @@ import { ThemeItem } from './ThemeItem'
import RadioIndicator from '../Radio/RadioIndicator' import RadioIndicator from '../Radio/RadioIndicator'
import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/PremiumFeatureIcon' import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/PremiumFeatureIcon'
import { isMobileScreen } from '@/Utils' import { isMobileScreen } from '@/Utils'
import { classNames } from '@/Utils/ConcatenateClassNames'
type Props = { type Props = {
item: ThemeItem item: ThemeItem
@@ -54,9 +55,11 @@ const ThemesMenuButton: FunctionComponent<Props> = ({ application, item }) => {
return ( return (
<button <button
className={ className={classNames(
'group flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-mobile-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none disabled:bg-default disabled:text-passive-2 md:text-sm' 'group flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5',
} 'text-left text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none disabled:bg-default disabled:text-passive-2',
'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item',
)}
onClick={toggleTheme} onClick={toggleTheme}
> >
{item.component?.isLayerable() ? ( {item.component?.isLayerable() ? (

View File

@@ -386,7 +386,12 @@ export class ItemListController
* In some cases we want to keep the selected item open even if it doesn't appear in results, * In some cases we want to keep the selected item open even if it doesn't appear in results,
* for example if you are inside tag Foo and remove tag Foo from the note, we want to keep the note open. * for example if you are inside tag Foo and remove tag Foo from the note, we want to keep the note open.
*/ */
private shouldCloseActiveItem = (activeItem: SNNote | FileItem | undefined) => { private shouldCloseActiveItem = (activeItem: SNNote | FileItem | undefined, source?: ItemsReloadSource) => {
if (source === ItemsReloadSource.UserTriggeredTagChange) {
log(LoggingDomain.Selection, 'shouldCloseActiveItem true due to ItemsReloadSource.UserTriggeredTagChange')
return true
}
const activeItemExistsInUpdatedResults = this.items.find((item) => item.uuid === activeItem?.uuid) const activeItemExistsInUpdatedResults = this.items.find((item) => item.uuid === activeItem?.uuid)
const closeBecauseActiveItemIsFileAndDoesntExistInUpdatedResults = const closeBecauseActiveItemIsFileAndDoesntExistInUpdatedResults =
@@ -417,6 +422,7 @@ export class ItemListController
return true return true
} }
log(LoggingDomain.Selection, 'shouldCloseActiveItem false')
return false return false
} }
@@ -462,7 +468,7 @@ export class ItemListController
const activeItem = activeController?.item const activeItem = activeController?.item
if (activeController && activeItem && this.shouldCloseActiveItem(activeItem)) { if (activeController && activeItem && this.shouldCloseActiveItem(activeItem, itemsReloadSource)) {
this.closeItemController(activeController) this.closeItemController(activeController)
this.selectionController.deselectItem(activeItem) this.selectionController.deselectItem(activeItem)
@@ -835,6 +841,16 @@ export class ItemListController
this.application.getDesktopService()?.searchText(this.noteFilterText) this.application.getDesktopService()?.searchText(this.noteFilterText)
} }
get isCurrentNoteTemplate(): boolean {
const controller = this.getActiveItemController()
if (!controller) {
return false
}
return controller instanceof NoteViewController && controller.isTemplateNote
}
public async insertCurrentIfTemplate(): Promise<void> { public async insertCurrentIfTemplate(): Promise<void> {
const controller = this.getActiveItemController() const controller = this.getActiveItemController()