Skip to content

Commit

Permalink
Add the upgrade modal to the popup
Browse files Browse the repository at this point in the history
  • Loading branch information
blackforestboi committed May 11, 2024
1 parent 6a48caf commit 301068a
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 23 deletions.
22 changes: 19 additions & 3 deletions src/custom-lists/ui/CollectionPicker/logic.ts
Expand Up @@ -710,7 +710,7 @@ export default class SpacePickerLogic extends UILogic<

await executeUITask(this, 'spaceAddRemoveState', async () => {
try {
let entrySelectPromise: Promise<void>
let entrySelectPromise: Promise<void> | Promise<boolean>
// If we're going to unselect it
if (previousState.selectedListIds.includes(entry.localId)) {
this.selectedListIds = previousState.selectedListIds.filter(
Expand Down Expand Up @@ -748,7 +748,20 @@ export default class SpacePickerLogic extends UILogic<
)
}

await entrySelectPromise
let entrySelectResult = null
if (entrySelectPromise instanceof Promise) {
entrySelectResult = await entrySelectPromise
} else {
entrySelectPromise = entrySelectPromise
}

if (entrySelectResult === false) {
nextState = this.applyAndEmitMutation(previousState, {
selectedListIds: {
$set: previousState.selectedListIds,
},
})
}
} catch (e) {
this.selectedListIds = previousState.selectedListIds
nextState = this.applyAndEmitMutation(previousState, {
Expand Down Expand Up @@ -900,7 +913,10 @@ export default class SpacePickerLogic extends UILogic<
entry,
previousState,
)
await this.dependencies.selectEntry(listId)
const isSuccessful = await this.dependencies.selectEntry(listId)
if (!isSuccessful) {
throw new Error('Failed to select the newly created list')
}
} catch (err) {
this.emitMutation({ spaceWriteError: { $set: err.message } })
throw err
Expand Down
2 changes: 1 addition & 1 deletion src/custom-lists/ui/CollectionPicker/types.ts
Expand Up @@ -89,7 +89,7 @@ export interface SpacePickerDependencies {
selectEntry: (
listId: number,
options?: { protectAnnotation?: boolean },
) => Promise<void>
) => Promise<void> | Promise<boolean>
unselectEntry: (listId: number) => Promise<void>
actOnAllTabs?: (listId: number) => Promise<void>
/** Called when user keys Enter+Cmd/Ctrl in main text input */
Expand Down
9 changes: 7 additions & 2 deletions src/popup/bookmark-button/components/BookmarkButton.tsx
Expand Up @@ -11,6 +11,9 @@ import styled from 'styled-components'
import * as icons from 'src/common-ui/components/design-library/icons'
import Icon from '@worldbrain/memex-common/lib/common-ui/components/icon'
import KeyboardShortcuts from '@worldbrain/memex-common/lib/common-ui/components/keyboard-shortcuts'
import { pageActionAllowed } from '@worldbrain/memex-common/lib/subscriptions/storage'
import { Browser } from 'webextension-polyfill'
import { RemoteCollectionsInterface } from 'src/custom-lists/background/types'

const styles = require('./BookmarkButton.css')
const buttonStyles = require('../../components/Button.css')
Expand All @@ -20,6 +23,9 @@ export interface OwnProps {
pageUrl: string
isSavedPage: boolean
getRootElement: () => HTMLElement
browserAPIs: Browser
collectionsBG: RemoteCollectionsInterface
saveBookmark: () => Promise<boolean>
}

interface StateProps {
Expand Down Expand Up @@ -142,8 +148,7 @@ const mapDispatch: (dispatch, props: OwnProps) => DispatchProps = (
props,
) => ({
toggleBookmark: async (element: HTMLElement) => {
const allowed = true
// await pageActionAllowed(analyticsBG)
const allowed = await props.saveBookmark()

if (allowed) {
await dispatch(acts.toggleBookmark())
Expand Down
114 changes: 97 additions & 17 deletions src/popup/container.tsx
Expand Up @@ -41,10 +41,13 @@ import * as icons from 'src/common-ui/components/design-library/icons'
import Icon from '@worldbrain/memex-common/lib/common-ui/components/icon'
import { getTelegramUserDisplayName } from '@worldbrain/memex-common/lib/telegram/utils'
import { AnalyticsCoreInterface } from '@worldbrain/memex-common/lib/analytics/types'
import { pageActionAllowed } from '@worldbrain/memex-common/lib/subscriptions/storage'
import { AnnotationsSidebarInPageEventEmitter } from 'src/sidebar/annotations-sidebar/types'

export interface OwnProps {
analyticsBG: AnalyticsCoreInterface
getRootElement: () => HTMLElement
sidebarEvents: AnnotationsSidebarInPageEventEmitter
}

interface StateProps {
Expand Down Expand Up @@ -83,6 +86,7 @@ class PopupContainer extends StatefulUIElement<Props, State, Event> {
syncSettings: createSyncSettingsStore({
syncSettingsBG: runInBackground(),
}),
sidebarEvents: runInBackground(),
}),
)
}
Expand Down Expand Up @@ -186,6 +190,42 @@ class PopupContainer extends StatefulUIElement<Props, State, Event> {
}
}

private renderUpgradeNotif() {
if (this.state.showUpgradeNotif) {
return (
<BlurredNotice browser={this.browserName}>
<NoticeTitle>
You've reached the limit of
<br /> 25 saved pages per month
</NoticeTitle>
<NoticeSubTitle>
Upgrade to continue to save, annotate and organise.
Search & AI features are not affected.
</NoticeSubTitle>
<PrimaryAction
label="Upgrade"
onClick={() => {
browser.tabs.create({
url: `chrome-extension://${browser.runtime.id}/options.html#/account`,
})
this.processEvent('showUpgradeNotif', false)
}}
size={'medium'}
type={'primary'}
/>
<PrimaryAction
label="Go Back"
onClick={() => {
this.processEvent('showUpgradeNotif', false)
}}
size={'medium'}
type={'tertiary'}
/>
</BlurredNotice>
)
}
return null
}
private maybeRenderBlurredNotice() {
if (!this.isCurrentPagePDF) {
return null
Expand Down Expand Up @@ -270,19 +310,34 @@ class PopupContainer extends StatefulUIElement<Props, State, Event> {
if (this.props.showCollectionsPicker) {
return (
<SpacePickerContainer>
{this.renderUpgradeNotif()}
<BackContainer
onClick={this.props.toggleShowCollectionsPicker}
header={'Add Page to Spaces'}
showAutoSaved={this.state.showAutoSaved}
/>
<CollectionPicker
selectEntry={(listId) =>
this.handleListUpdate({
added: listId,
deleted: null,
pageTitle: title,
})
}
selectEntry={async (listId) => {
const isAllowed = await pageActionAllowed(
browser,
null,
collections,
this.props.url,
false,
)

if (!isAllowed) {
this.processEvent('showUpgradeNotif', true)
return false
} else {
this.handleListUpdate({
added: listId,
deleted: null,
pageTitle: title,
})
return true
}
}}
unselectEntry={(listId) =>
this.handleListUpdate({
added: null,
Expand All @@ -307,6 +362,7 @@ class PopupContainer extends StatefulUIElement<Props, State, Event> {
return (
<PopupContainerContainer>
{this.maybeRenderBlurredNotice()}
{this.renderUpgradeNotif()}
<FeedActivitySection
onClick={async () => {
await this.activityIndicatorBG.markActivitiesAsSeen()
Expand All @@ -331,6 +387,26 @@ class PopupContainer extends StatefulUIElement<Props, State, Event> {
closePopup={this.closePopup}
isSavedPage={this.state.isSavedPage}
getRootElement={this.props.getRootElement}
browserAPIs={browser}
collectionsBG={collections}
saveBookmark={async () => {
const isAllowed = await pageActionAllowed(
browser,
null,
collections,
this.props.url,
false,
)

console.log('isAllowed', isAllowed)

if (!isAllowed) {
this.processEvent('showUpgradeNotif', true)
return false
} else {
return true
}
}}
/>
<CollectionsButton
getRootElement={this.props.getRootElement}
Expand Down Expand Up @@ -495,11 +571,15 @@ const FeedActivitySectionInnerContainer = styled.div`
`

const NoticeTitle = styled.div`
font-size: 16px;
color: ${(props) => props.theme.colors.white};
font-size: 18px;
font-weight: bold;
text-align: center;
margin-bottom: 20px;
background: ${(props) => props.theme.colors.headerGradient};
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 700;
`

const LoadingBox = styled.div`
Expand All @@ -511,37 +591,37 @@ const LoadingBox = styled.div`
`

const NoticeSubTitle = styled.div`
font-size: 14px;
color: ${(props) => props.theme.colors.greyScale5};
font-size: 16px;
color: ${(props) => props.theme.colors.greyScale6};
font-weight: 300;
padding-bottom: 15px;
text-align: center;
padding: 0 10px;
margin-bottom: 20px;
margin-bottom: 30px;
`

const BlurredNotice = styled.div<{
browser: string
location: string
browser?: string
location?: string
}>`
position: absolute;
height: 100%;
width: 100%;
width: fill-available;
width: -moz-available;
height: 100%;
z-index: 30;
z-index: 11111;
overflow-y: ${(props) =>
props.browser === 'firefox' && props.location === 'local'
? 'hidden'
: 'scroll'};
background: ${(props) =>
props.browser === 'firefox' ? props.theme.colors.black + 90 : 'none'};
props.browser === 'firefox' ? props.theme.colors.black1 + 99 : 'none'};
backdrop-filter: blur(10px);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 20px;
scrollbar-width: none;
Expand Down
6 changes: 6 additions & 0 deletions src/popup/index.tsx
Expand Up @@ -13,6 +13,8 @@ import Popup from './container'
import configureStore from './store'
import { setupRpcConnection } from 'src/util/webextensionRPC'
import { MemexThemeVariant } from '@worldbrain/memex-common/lib/common-ui/styles/types'
import { AnnotationsSidebarInPageEventEmitter } from 'src/sidebar/annotations-sidebar/types'
import { EventEmitter } from 'events'

interface RootProps {
store: ReturnType<typeof configureStore>
Expand All @@ -25,25 +27,29 @@ interface RootState {

class Root extends React.Component<RootProps, RootState> {
state: RootState = {}
sidebarEvents: AnnotationsSidebarInPageEventEmitter

async componentDidMount() {
this.setState({
themeVariant: await loadThemeVariant(),
})
this.sidebarEvents = new EventEmitter() as AnnotationsSidebarInPageEventEmitter
}

render() {
const { themeVariant } = this.state
if (!themeVariant) {
return null
}
console.log('this sidebarEvents', this.sidebarEvents)
return (
<Provider store={this.props.store}>
<ThemeProvider theme={theme({ variant: themeVariant })}>
<ErrorBoundary component={RuntimeError}>
<Popup
getRootElement={this.props.getRootElement}
analyticsBG={null}
sidebarEvents={this.sidebarEvents}
/>
</ErrorBoundary>
</ThemeProvider>
Expand Down
11 changes: 11 additions & 0 deletions src/popup/logic.ts
Expand Up @@ -15,6 +15,7 @@ import type { AnalyticsCoreInterface } from '@worldbrain/memex-common/lib/analyt
import type { AnnotationInterface } from 'src/annotations/background/types'
import type { AuthRemoteFunctionsInterface } from 'src/authentication/background/types'
import { setUserContext as setSentryUserContext } from 'src/util/raven'
import { AnnotationsSidebarInPageEventEmitter } from 'src/sidebar/annotations-sidebar/types'

export interface Dependencies {
extensionAPI: Pick<Extension.Static, 'isAllowedFileSchemeAccess'>
Expand All @@ -27,13 +28,15 @@ export interface Dependencies {
analyticsBG: AnalyticsCoreInterface
annotationsBG: AnnotationInterface<'provider'>
authBG: AuthRemoteFunctionsInterface
sidebarEvents: AnnotationsSidebarInPageEventEmitter
}

export interface Event {
togglePDFReader: null
togglePDFReaderEnabled: null
addPageList: { listId: number }
delPageList: { listId: number }
showUpgradeNotif: boolean
}

export interface State {
Expand All @@ -50,6 +53,7 @@ export interface State {
showAutoSaved: boolean
analyticsBG: AnalyticsCoreInterface
isSavedPage: boolean
showUpgradeNotif: boolean
}

type EventHandler<EventName extends keyof Event> = UIEventHandler<
Expand All @@ -76,6 +80,7 @@ export default class PopupLogic extends UILogic<State, Event> {
showAutoSaved: false,
analyticsBG: null,
isSavedPage: false,
showUpgradeNotif: false,
})

async init() {
Expand Down Expand Up @@ -186,6 +191,12 @@ export default class PopupLogic extends UILogic<State, Event> {
this.emitMutation({ currentTabFullUrl: { $set: nextPageUrl } })
}

showUpgradeNotif: EventHandler<'showUpgradeNotif'> = async ({
event,
previousState,
}) => {
this.emitMutation({ showUpgradeNotif: { $set: event } })
}
addPageList: EventHandler<'addPageList'> = async ({
event,
previousState,
Expand Down

0 comments on commit 301068a

Please sign in to comment.