mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 06:59:31 +01:00
add support to show promo
This commit is contained in:
@@ -322,6 +322,8 @@ export const AppRootEvents = React.memo(
|
|||||||
await PremiumService.setPremiumStatus();
|
await PremiumService.setPremiumStatus();
|
||||||
setLoginMessage(dispatch);
|
setLoginMessage(dispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let user = await db.user.getUser();
|
let user = await db.user.getUser();
|
||||||
if (user && !user.isEmailConfirmed) {
|
if (user && !user.isEmailConfirmed) {
|
||||||
@@ -336,6 +338,9 @@ export const AppRootEvents = React.memo(
|
|||||||
if (login) {
|
if (login) {
|
||||||
eSendEvent(eCloseProgressDialog);
|
eSendEvent(eCloseProgressDialog);
|
||||||
}
|
}
|
||||||
|
let announcement = await db.announcement();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -185,8 +185,8 @@ export class DialogManager extends Component {
|
|||||||
eUnSubscribeEvent(eClosePremiumDialog, this.hidePremiumDialog);
|
eUnSubscribeEvent(eClosePremiumDialog, this.hidePremiumDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
showPremiumDialog = () => {
|
showPremiumDialog = (prompoInfo) => {
|
||||||
this.premiumDialog.open();
|
this.premiumDialog.open(prompoInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
hidePremiumDialog = () => {
|
hidePremiumDialog = () => {
|
||||||
|
|||||||
@@ -7,14 +7,17 @@ class PremiumDialog extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
visible: false,
|
visible: false,
|
||||||
|
promo:null
|
||||||
};
|
};
|
||||||
this.actionSheetRef = createRef();
|
this.actionSheetRef = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
open() {
|
open(promoInfo) {
|
||||||
|
console.log(promoInfo)
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
visible: true,
|
visible: true,
|
||||||
|
promo:promoInfo
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.actionSheetRef.current?.setModalVisible(true);
|
this.actionSheetRef.current?.setModalVisible(true);
|
||||||
@@ -35,7 +38,7 @@ class PremiumDialog extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return !this.state.visible ? null : (
|
return !this.state.visible ? null : (
|
||||||
<ActionSheetWrapper onClose={this.onClose} fwdRef={this.actionSheetRef}>
|
<ActionSheetWrapper onClose={this.onClose} fwdRef={this.actionSheetRef}>
|
||||||
<PremiumComponent close={this.close} />
|
<PremiumComponent promo={this.state.promo} close={this.close} />
|
||||||
</ActionSheetWrapper>
|
</ActionSheetWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {eCloseResultDialog, eOpenResultDialog} from '../../utils/Events';
|
|||||||
import {ph, SIZE} from '../../utils/SizeUtils';
|
import {ph, SIZE} from '../../utils/SizeUtils';
|
||||||
import {Button} from '../Button';
|
import {Button} from '../Button';
|
||||||
import BaseDialog from '../Dialog/base-dialog';
|
import BaseDialog from '../Dialog/base-dialog';
|
||||||
|
import {SvgToPngView} from '../ListPlaceholders';
|
||||||
import Seperator from '../Seperator';
|
import Seperator from '../Seperator';
|
||||||
import Heading from '../Typography/Heading';
|
import Heading from '../Typography/Heading';
|
||||||
import Paragraph from '../Typography/Paragraph';
|
import Paragraph from '../Typography/Paragraph';
|
||||||
@@ -33,7 +34,7 @@ const ResultDialog = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const open = (data) => {
|
const open = data => {
|
||||||
setDialogData(data);
|
setDialogData(data);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
@@ -56,7 +57,13 @@ const ResultDialog = () => {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}>
|
}}>
|
||||||
<SvgXml xml={WELCOME_SVG(colors.accent)} width={170} height={170} />
|
<SvgToPngView
|
||||||
|
src={WELCOME_SVG(colors.accent)}
|
||||||
|
color={colors.accent}
|
||||||
|
img="welcome"
|
||||||
|
width={170}
|
||||||
|
height={170}
|
||||||
|
/>
|
||||||
|
|
||||||
<Heading
|
<Heading
|
||||||
size={SIZE.lg}
|
size={SIZE.lg}
|
||||||
|
|||||||
83
apps/mobile/src/components/SimpleList/announcement.js
Normal file
83
apps/mobile/src/components/SimpleList/announcement.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import React, {useEffect} from 'react';
|
||||||
|
import {View} from 'react-native';
|
||||||
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
import {useTracked} from '../../provider';
|
||||||
|
import {eSendEvent} from '../../services/EventManager';
|
||||||
|
import {eOpenPremiumDialog} from '../../utils/Events';
|
||||||
|
import {openLinkInBrowser} from '../../utils/functions';
|
||||||
|
import {SIZE} from '../../utils/SizeUtils';
|
||||||
|
import useAnnouncement from '../../utils/useAnnouncement';
|
||||||
|
import {Button} from '../Button';
|
||||||
|
import Seperator from '../Seperator';
|
||||||
|
import Heading from '../Typography/Heading';
|
||||||
|
import Paragraph from '../Typography/Paragraph';
|
||||||
|
|
||||||
|
export const Announcement = ({data, color}) => {
|
||||||
|
const [state] = useTracked();
|
||||||
|
const {selectionMode} = state;
|
||||||
|
const [announcement, remove] = useAnnouncement();
|
||||||
|
|
||||||
|
return !announcement || selectionMode ? null : (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: color,
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
paddingVertical: 12,
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
}}>
|
||||||
|
{announcement?.title && (
|
||||||
|
<Heading
|
||||||
|
style={{
|
||||||
|
width: '90%',
|
||||||
|
}}
|
||||||
|
size={SIZE.lg}
|
||||||
|
color="white">
|
||||||
|
{announcement.title}
|
||||||
|
</Heading>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Icon onPress={remove} name="close" size={SIZE.xl} color="white" />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{announcement?.description && (
|
||||||
|
<Paragraph color="white">{announcement.description}</Paragraph>
|
||||||
|
)}
|
||||||
|
<Seperator />
|
||||||
|
|
||||||
|
{announcement?.cta && (
|
||||||
|
<Button
|
||||||
|
type="inverted"
|
||||||
|
title={announcement.cta.text}
|
||||||
|
fontSize={SIZE.md}
|
||||||
|
onPress={async () => {
|
||||||
|
if (announcement.cta.type === 'link') {
|
||||||
|
try {
|
||||||
|
await openLinkInBrowser(
|
||||||
|
announcement.cta.action,
|
||||||
|
state.colors,
|
||||||
|
);
|
||||||
|
} catch (e) {}
|
||||||
|
} else if (announcement.cta.type === 'promo') {
|
||||||
|
eSendEvent(eOpenPremiumDialog, {
|
||||||
|
promoCode: announcement.cta.action,
|
||||||
|
text: announcement.cta.text,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
width="100%"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -12,6 +12,8 @@ export const Card = ({data, color}) => {
|
|||||||
const [state] = useTracked();
|
const [state] = useTracked();
|
||||||
const {selectionMode, messageBoardState} = state;
|
const {selectionMode, messageBoardState} = state;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return !messageBoardState.visible || selectionMode ? null : (
|
return !messageBoardState.visible || selectionMode ? null : (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
activeOpacity={0.8}
|
activeOpacity={0.8}
|
||||||
@@ -24,7 +26,7 @@ export const Card = ({data, color}) => {
|
|||||||
position: DDS.isLargeTablet() ? 'relative' : 'absolute',
|
position: DDS.isLargeTablet() ? 'relative' : 'absolute',
|
||||||
right: 0,
|
right: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
zIndex: 999,
|
zIndex: 100,
|
||||||
backgroundColor: messageBoardState.type === 'error' ? 'red' : color,
|
backgroundColor: messageBoardState.type === 'error' ? 'red' : color,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
}}>
|
}}>
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import {View} from 'react-native';
|
||||||
import { useTracked } from '../../provider';
|
import {useTracked} from '../../provider';
|
||||||
import { DDS } from '../../services/DeviceDetection';
|
import {DDS} from '../../services/DeviceDetection';
|
||||||
import { COLORS_NOTE } from '../../utils/Colors';
|
import {COLORS_NOTE} from '../../utils/Colors';
|
||||||
import { hexToRGBA } from '../../utils/ColorUtils';
|
import {hexToRGBA} from '../../utils/ColorUtils';
|
||||||
import { normalize, SIZE } from '../../utils/SizeUtils';
|
import {normalize, SIZE} from '../../utils/SizeUtils';
|
||||||
import { Button } from '../Button';
|
import {Button} from '../Button';
|
||||||
import { Placeholder } from '../ListPlaceholders';
|
import {Placeholder} from '../ListPlaceholders';
|
||||||
import Heading from '../Typography/Heading';
|
import Heading from '../Typography/Heading';
|
||||||
import { Card } from './card';
|
import {Announcement} from './announcement';
|
||||||
|
import {Card} from './card';
|
||||||
|
|
||||||
export const Header = ({
|
export const Header = ({
|
||||||
type,
|
type,
|
||||||
@@ -103,7 +104,7 @@ export const Header = ({
|
|||||||
fontSize={SIZE.sm}
|
fontSize={SIZE.sm}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
): null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ import Navigation from '../../services/Navigation';
|
|||||||
import SettingsService from '../../services/SettingsService';
|
import SettingsService from '../../services/SettingsService';
|
||||||
import Sync from '../../services/Sync';
|
import Sync from '../../services/Sync';
|
||||||
import {dHeight} from '../../utils';
|
import {dHeight} from '../../utils';
|
||||||
|
import {COLORS_NOTE} from '../../utils/Colors';
|
||||||
import {eScrollEvent} from '../../utils/Events';
|
import {eScrollEvent} from '../../utils/Events';
|
||||||
import {sleep} from '../../utils/TimeUtils';
|
import {sleep} from '../../utils/TimeUtils';
|
||||||
import {NotebookWrapper} from '../NotebookItem/wrapper';
|
import {NotebookWrapper} from '../NotebookItem/wrapper';
|
||||||
import {NoteWrapper} from '../NoteItem/wrapper';
|
import {NoteWrapper} from '../NoteItem/wrapper';
|
||||||
import TagItem from '../TagItem';
|
import TagItem from '../TagItem';
|
||||||
|
import {Announcement} from './announcement';
|
||||||
import {Empty} from './empty';
|
import {Empty} from './empty';
|
||||||
import {Footer} from './footer';
|
import {Footer} from './footer';
|
||||||
import {Header} from './header';
|
import {Header} from './header';
|
||||||
@@ -69,9 +71,14 @@ const SimpleList = ({
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setTimeout(() => {
|
setTimeout(
|
||||||
setLoaded(true)
|
() => {
|
||||||
},Navigation.getCurrentScreen() === SettingsService.get().homepage ? 1000 : 150);
|
setLoaded(true);
|
||||||
|
},
|
||||||
|
Navigation.getCurrentScreen() === SettingsService.get().homepage
|
||||||
|
? 1000
|
||||||
|
: 150,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [listData, deviceMode, loading]);
|
}, [listData, deviceMode, loading]);
|
||||||
|
|
||||||
@@ -82,14 +89,14 @@ const SimpleList = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _onScroll = (event) => {
|
const _onScroll = event => {
|
||||||
if (!event) return;
|
if (!event) return;
|
||||||
let y = event.nativeEvent.contentOffset.y;
|
let y = event.nativeEvent.contentOffset.y;
|
||||||
eSendEvent(eScrollEvent, y);
|
eSendEvent(eScrollEvent, y);
|
||||||
};
|
};
|
||||||
|
|
||||||
const _layoutProvider = new LayoutProvider(
|
const _layoutProvider = new LayoutProvider(
|
||||||
(index) => {
|
index => {
|
||||||
return dataProvider.getDataForIndex(index).type;
|
return dataProvider.getDataForIndex(index).type;
|
||||||
},
|
},
|
||||||
(type, dim) => {
|
(type, dim) => {
|
||||||
@@ -230,6 +237,9 @@ const SimpleList = ({
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Announcement
|
||||||
|
color={COLORS_NOTE[headerProps.heading?.toLowerCase()] || colors.accent}
|
||||||
|
/>
|
||||||
{loaded && !loading ? null : (
|
{loaded && !loading ? null : (
|
||||||
<>
|
<>
|
||||||
<View
|
<View
|
||||||
@@ -240,6 +250,11 @@ const SimpleList = ({
|
|||||||
backgroundColor: colors.bg,
|
backgroundColor: colors.bg,
|
||||||
zIndex: 999,
|
zIndex: 999,
|
||||||
}}>
|
}}>
|
||||||
|
<Announcement
|
||||||
|
color={
|
||||||
|
COLORS_NOTE[headerProps.heading?.toLowerCase()] || colors.accent
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Header
|
<Header
|
||||||
title={headerProps.heading}
|
title={headerProps.heading}
|
||||||
paragraph={headerProps.paragraph}
|
paragraph={headerProps.paragraph}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
|||||||
import {DDS} from '../../services/DeviceDetection';
|
import {DDS} from '../../services/DeviceDetection';
|
||||||
import {openLinkInBrowser} from '../../utils/functions';
|
import {openLinkInBrowser} from '../../utils/functions';
|
||||||
import {Modal} from 'react-native';
|
import {Modal} from 'react-native';
|
||||||
|
import {SafeAreaView} from 'react-native';
|
||||||
|
import {SvgToPngView} from '../ListPlaceholders';
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
@@ -39,6 +41,7 @@ const features = [
|
|||||||
'Your data is encrypted on your device. No one but you can read your notes.',
|
'Your data is encrypted on your device. No one but you can read your notes.',
|
||||||
icon: PRIVACY_SVG,
|
icon: PRIVACY_SVG,
|
||||||
link: 'https://notesnook.com',
|
link: 'https://notesnook.com',
|
||||||
|
img:"privacy"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: SYNC_SVG,
|
icon: SYNC_SVG,
|
||||||
@@ -46,6 +49,7 @@ const features = [
|
|||||||
description:
|
description:
|
||||||
'Everything is automatically synced to all your devices in a safe and secure way. Notesnook is available on all major platforms.',
|
'Everything is automatically synced to all your devices in a safe and secure way. Notesnook is available on all major platforms.',
|
||||||
link: 'https://notesnook.com',
|
link: 'https://notesnook.com',
|
||||||
|
img:'sync'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: ORGANIZE_SVG,
|
icon: ORGANIZE_SVG,
|
||||||
@@ -53,6 +57,7 @@ const features = [
|
|||||||
description:
|
description:
|
||||||
'Add your notes in notebooks and topics or simply assign tags or colors to find them easily.',
|
'Add your notes in notebooks and topics or simply assign tags or colors to find them easily.',
|
||||||
link: 'https://notesnook.com',
|
link: 'https://notesnook.com',
|
||||||
|
img:"sync"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: COMMUNITY_SVG,
|
icon: COMMUNITY_SVG,
|
||||||
@@ -60,6 +65,7 @@ const features = [
|
|||||||
description:
|
description:
|
||||||
'We are not ghosts, chat with us and share your experience. Give suggestions, report issues and meet other people using Notesnook',
|
'We are not ghosts, chat with us and share your experience. Give suggestions, report issues and meet other people using Notesnook',
|
||||||
link: 'https://discord.gg/zQBK97EE22',
|
link: 'https://discord.gg/zQBK97EE22',
|
||||||
|
img:'community'
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
@@ -75,7 +81,7 @@ const SplashScreen = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Storage.read('introCompleted').then(async r => {
|
Storage.read('introCompleted').then(async r => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
if (!r) {
|
if (r) {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
timing(opacity, {
|
timing(opacity, {
|
||||||
toValue: 1,
|
toValue: 1,
|
||||||
@@ -94,7 +100,7 @@ const SplashScreen = () => {
|
|||||||
return (
|
return (
|
||||||
visible && (
|
visible && (
|
||||||
<Modal animationType="slide" statusBarTranslucent visible>
|
<Modal animationType="slide" statusBarTranslucent visible>
|
||||||
<Animated.View
|
<SafeAreaView
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@@ -119,8 +125,7 @@ const SplashScreen = () => {
|
|||||||
onSnapToItem={i => {
|
onSnapToItem={i => {
|
||||||
currentIndex = i;
|
currentIndex = i;
|
||||||
}}
|
}}
|
||||||
activeAnimationType="timing"
|
maxToRenderPerBatch={10}
|
||||||
shouldOptimizeUpdates
|
|
||||||
renderItem={({item, index}) => (
|
renderItem={({item, index}) => (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@@ -155,12 +160,14 @@ const SplashScreen = () => {
|
|||||||
size={170}
|
size={170}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SvgXml
|
<SvgToPngView
|
||||||
xml={
|
src={
|
||||||
item.icon
|
item.icon
|
||||||
? item.icon(colors.accent)
|
? item.icon(colors.accent)
|
||||||
: NOTE_SVG(colors.accent)
|
: NOTE_SVG(colors.accent)
|
||||||
}
|
}
|
||||||
|
img={item.img}
|
||||||
|
color={colors.accent}
|
||||||
width={250}
|
width={250}
|
||||||
height={250}
|
height={250}
|
||||||
/>
|
/>
|
||||||
@@ -249,7 +256,7 @@ const SplashScreen = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</Animated.View>
|
</SafeAreaView>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const UpdateDialog = () => {
|
|||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [version, setVersion] = useState(null);
|
const [version, setVersion] = useState(null);
|
||||||
|
|
||||||
const open = (version) => {
|
const open = version => {
|
||||||
setVersion(version);
|
setVersion(version);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
@@ -31,10 +31,10 @@ export const UpdateDialog = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent('updateDialog', open);
|
eUnSubscribeEvent('updateDialog', open);
|
||||||
};
|
};
|
||||||
},[]);
|
}, []);
|
||||||
|
|
||||||
const format = (ver) => {
|
const format = ver => {
|
||||||
if (!ver) return ""
|
if (!ver) return '';
|
||||||
let parts = ver.toString().split('');
|
let parts = ver.toString().split('');
|
||||||
return `v${parts[0]}.${parts[1]}.${parts[2]}${
|
return `v${parts[0]}.${parts[1]}.${parts[2]}${
|
||||||
parts[3] === '0' ? '' : parts[3]
|
parts[3] === '0' ? '' : parts[3]
|
||||||
@@ -45,7 +45,7 @@ export const UpdateDialog = () => {
|
|||||||
visible && (
|
visible && (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
onRequestClose={() => {
|
onRequestClose={() => {
|
||||||
setVisible(false);
|
version.severity !== 2 && setVisible(false);
|
||||||
}}
|
}}
|
||||||
visible={true}>
|
visible={true}>
|
||||||
<DialogContainer>
|
<DialogContainer>
|
||||||
@@ -114,9 +114,7 @@ export const UpdateDialog = () => {
|
|||||||
let url_android =
|
let url_android =
|
||||||
'https://play.google.com/store/apps/details?id=com.streetwriters.notesnook';
|
'https://play.google.com/store/apps/details?id=com.streetwriters.notesnook';
|
||||||
let url_ios = 'itms-apps://itunes.apple.com/app/id1544027013';
|
let url_ios = 'itms-apps://itunes.apple.com/app/id1544027013';
|
||||||
setVisible(false);
|
version.severity !== 2 && setVisible(false);
|
||||||
|
|
||||||
|
|
||||||
await Linking.openURL(
|
await Linking.openURL(
|
||||||
Platform.OS === 'android' ? url_android : url_ios,
|
Platform.OS === 'android' ? url_android : url_ios,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,15 +14,18 @@ import {itemSkus} from '../utils';
|
|||||||
|
|
||||||
let premiumStatus = 0;
|
let premiumStatus = 0;
|
||||||
let products = [];
|
let products = [];
|
||||||
|
let user = null
|
||||||
|
|
||||||
|
function getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
async function setPremiumStatus() {
|
async function setPremiumStatus() {
|
||||||
try {
|
try {
|
||||||
let user = await db.user.getUser();
|
user = await db.user.getUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
premiumStatus = null;
|
premiumStatus = null;
|
||||||
updateEvent({type: Actions.PREMIUM, state: get()});
|
updateEvent({type: Actions.PREMIUM, state: get()});
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
premiumStatus = user.subscription.type;
|
premiumStatus = user.subscription.type;
|
||||||
updateEvent({type: Actions.PREMIUM, state: get()});
|
updateEvent({type: Actions.PREMIUM, state: get()});
|
||||||
@@ -172,5 +175,6 @@ export default {
|
|||||||
get,
|
get,
|
||||||
onUserStatusCheck,
|
onUserStatusCheck,
|
||||||
showVerifyEmailDialog,
|
showVerifyEmailDialog,
|
||||||
getProducts
|
getProducts,
|
||||||
|
getUser
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export async function setSetting(settings, name, value) {
|
|||||||
export const scrollRef = createRef();
|
export const scrollRef = createRef();
|
||||||
export const AndroidModule = NativeModules.NNativeModule;
|
export const AndroidModule = NativeModules.NNativeModule;
|
||||||
|
|
||||||
export const getElevation = (elevation) => {
|
export const getElevation = elevation => {
|
||||||
return {
|
return {
|
||||||
elevation,
|
elevation,
|
||||||
shadowColor: 'black',
|
shadowColor: 'black',
|
||||||
@@ -154,8 +154,9 @@ export const SUBSCRIPTION_STATUS = {
|
|||||||
BASIC: 0,
|
BASIC: 0,
|
||||||
TRIAL: 1,
|
TRIAL: 1,
|
||||||
BETA: 2,
|
BETA: 2,
|
||||||
TRIAL_EXPIRED: 3,
|
PREMIUM: 5,
|
||||||
BETA_EXPIRED: 4,
|
PREMIUM_EXPIRED: 6,
|
||||||
|
PREMIUM_CANCELLED: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SUBSCRIPTION_STATUS_STRINGS = {
|
export const SUBSCRIPTION_STATUS_STRINGS = {
|
||||||
|
|||||||
75
apps/mobile/src/utils/useAnnouncement.js
Normal file
75
apps/mobile/src/utils/useAnnouncement.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import {useCallback, useEffect, useState} from 'react';
|
||||||
|
import {Platform} from 'react-native';
|
||||||
|
import {SUBSCRIPTION_STATUS} from '.';
|
||||||
|
import PremiumService from '../services/PremiumService';
|
||||||
|
import { db } from './DB';
|
||||||
|
import Storage from './storage';
|
||||||
|
|
||||||
|
var CACHED_ANNOUNCEMENT;
|
||||||
|
export default function useAnnouncement() {
|
||||||
|
const [announcement, setAnnouncement] = useState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async function () {
|
||||||
|
try {
|
||||||
|
CACHED_ANNOUNCEMENT = CACHED_ANNOUNCEMENT || (await db.announcement());
|
||||||
|
|
||||||
|
if (
|
||||||
|
!CACHED_ANNOUNCEMENT ||
|
||||||
|
await Storage.read('removedAnnouncement') === CACHED_ANNOUNCEMENT.id ||
|
||||||
|
!shouldShowAnnouncement(CACHED_ANNOUNCEMENT)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setAnnouncement(CACHED_ANNOUNCEMENT);
|
||||||
|
} catch(e) {
|
||||||
|
setAnnouncement()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const remove = useCallback(async () => {
|
||||||
|
await Storage.write('removedAnnouncement', CACHED_ANNOUNCEMENT.id);
|
||||||
|
setAnnouncement();
|
||||||
|
}, [announcement]);
|
||||||
|
return [announcement, remove];
|
||||||
|
}
|
||||||
|
|
||||||
|
const allowedPlatforms = ['all', 'mobile', Platform.OS];
|
||||||
|
function shouldShowAnnouncement(announcement) {
|
||||||
|
let show = allowedPlatforms.indexOf(announcement.platform) > -1;
|
||||||
|
console.log(show)
|
||||||
|
if (!show) return;
|
||||||
|
|
||||||
|
const subStatus = PremiumService.getUser()?.subscription?.type;
|
||||||
|
|
||||||
|
switch (announcement.userType) {
|
||||||
|
case 'pro':
|
||||||
|
show = isUserPremium();
|
||||||
|
break;
|
||||||
|
case 'trial':
|
||||||
|
show = subStatus === SUBSCRIPTION_STATUS.TRIAL;
|
||||||
|
break;
|
||||||
|
case 'trialExpired':
|
||||||
|
show = subStatus === SUBSCRIPTION_STATUS.BASIC;
|
||||||
|
break;
|
||||||
|
case 'loggedOut':
|
||||||
|
show = !PremiumService.getUser();
|
||||||
|
break;
|
||||||
|
case 'unverified':
|
||||||
|
show = !PremiumService.getUser()?.isEmailVerified;
|
||||||
|
break;
|
||||||
|
case 'proExpired':
|
||||||
|
show =
|
||||||
|
subStatus === SUBSCRIPTION_STATUS.PREMIUM_EXPIRED ||
|
||||||
|
subStatus === SUBSCRIPTION_STATUS.PREMIUM_CANCELED;
|
||||||
|
break;
|
||||||
|
case 'any':
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return show;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user