mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 06:59:31 +01:00
add a new premium dialog
This commit is contained in:
@@ -4,15 +4,18 @@ import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
|||||||
import {useTracked} from '../../provider';
|
import {useTracked} from '../../provider';
|
||||||
import {Actions} from '../../provider/Actions';
|
import {Actions} from '../../provider/Actions';
|
||||||
import {DDS} from '../../services/DeviceDetection';
|
import {DDS} from '../../services/DeviceDetection';
|
||||||
import {sendNoteEditedEvent} from '../../services/EventManager';
|
import {eSendEvent, sendNoteEditedEvent} from '../../services/EventManager';
|
||||||
import { dWidth } from '../../utils';
|
import PremiumService from '../../services/PremiumService';
|
||||||
|
import {dWidth} from '../../utils';
|
||||||
import {COLORS_NOTE} from '../../utils/Colors';
|
import {COLORS_NOTE} from '../../utils/Colors';
|
||||||
import {hexToRGBA, RGB_Linear_Shade} from '../../utils/ColorUtils';
|
import {hexToRGBA, RGB_Linear_Shade} from '../../utils/ColorUtils';
|
||||||
import {db} from '../../utils/DB';
|
import {db} from '../../utils/DB';
|
||||||
|
import { eShowGetPremium } from '../../utils/Events';
|
||||||
import {SIZE} from '../../utils/SizeUtils';
|
import {SIZE} from '../../utils/SizeUtils';
|
||||||
|
import { sleep } from '../../utils/TimeUtils';
|
||||||
import {PressableButton} from '../PressableButton';
|
import {PressableButton} from '../PressableButton';
|
||||||
|
|
||||||
export const ActionSheetColorsSection = ({item}) => {
|
export const ActionSheetColorsSection = ({item,close}) => {
|
||||||
const [state, dispatch] = useTracked();
|
const [state, dispatch] = useTracked();
|
||||||
const {colors} = state;
|
const {colors} = state;
|
||||||
const [note, setNote] = useState(item);
|
const [note, setNote] = useState(item);
|
||||||
@@ -49,16 +52,23 @@ export const ActionSheetColorsSection = ({item}) => {
|
|||||||
opacity={1}
|
opacity={1}
|
||||||
key={color.value}
|
key={color.value}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
let noteColors = note.colors;
|
await PremiumService.verify(async () => {
|
||||||
|
let noteColors = note.colors;
|
||||||
if (noteColors.includes(color.name)) {
|
if (noteColors.includes(color.name)) {
|
||||||
await db.notes.note(note.id).uncolor(color.name);
|
await db.notes.note(note.id).uncolor(color.name);
|
||||||
} else {
|
} else {
|
||||||
await db.notes.note(note.id).color(color.name);
|
await db.notes.note(note.id).color(color.name);
|
||||||
}
|
}
|
||||||
dispatch({type: Actions.COLORS});
|
dispatch({type: Actions.COLORS});
|
||||||
sendNoteEditedEvent(note.id, false, true);
|
sendNoteEditedEvent(note.id, false, true);
|
||||||
localRefresh();
|
localRefresh();
|
||||||
|
},() => {
|
||||||
|
eSendEvent(eShowGetPremium,{
|
||||||
|
context:'sheet',
|
||||||
|
title:'Get Notesnook Pro',
|
||||||
|
desc:'To assign color to a note get Notesnook Pro today.'
|
||||||
|
})
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
customStyle={{
|
customStyle={{
|
||||||
width: DDS.isTab ? 400 / 10 : dWidth / 10,
|
width: DDS.isTab ? 400 / 10 : dWidth / 10,
|
||||||
|
|||||||
@@ -2,16 +2,19 @@ import React, {createRef, useCallback, useEffect, useState} from 'react';
|
|||||||
import {Text, TextInput, TouchableOpacity, View} from 'react-native';
|
import {Text, TextInput, TouchableOpacity, View} from 'react-native';
|
||||||
import {useTracked} from '../../provider';
|
import {useTracked} from '../../provider';
|
||||||
import {Actions} from '../../provider/Actions';
|
import {Actions} from '../../provider/Actions';
|
||||||
import {sendNoteEditedEvent, ToastEvent} from '../../services/EventManager';
|
import {eSendEvent, sendNoteEditedEvent, ToastEvent} from '../../services/EventManager';
|
||||||
|
import PremiumService from '../../services/PremiumService';
|
||||||
import {db} from '../../utils/DB';
|
import {db} from '../../utils/DB';
|
||||||
|
import { eShowGetPremium } from '../../utils/Events';
|
||||||
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
|
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
|
||||||
|
import {sleep} from '../../utils/TimeUtils';
|
||||||
|
|
||||||
const tagsInputRef = createRef();
|
const tagsInputRef = createRef();
|
||||||
let prevQuery = null;
|
let prevQuery = null;
|
||||||
let tagToAdd = '';
|
let tagToAdd = '';
|
||||||
let backPressCount = 0;
|
let backPressCount = 0;
|
||||||
|
|
||||||
export const ActionSheetTagsSection = ({item}) => {
|
export const ActionSheetTagsSection = ({item, close}) => {
|
||||||
const [state, dispatch] = useTracked();
|
const [state, dispatch] = useTracked();
|
||||||
const {colors, tags, premiumUser} = state;
|
const {colors, tags, premiumUser} = state;
|
||||||
const [suggestions, setSuggestions] = useState([]);
|
const [suggestions, setSuggestions] = useState([]);
|
||||||
@@ -42,22 +45,45 @@ export const ActionSheetTagsSection = ({item}) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tag = tagToAdd;
|
async function add() {
|
||||||
tag = tag.trim();
|
let tag = tagToAdd;
|
||||||
if (tag.includes(' ')) {
|
tag = tag.trim();
|
||||||
tag = tag.replace(' ', '_');
|
if (tag.includes(' ')) {
|
||||||
}
|
tag = tag.replace(' ', '_');
|
||||||
if (tag.includes(',')) {
|
}
|
||||||
tag = tag.replace(',', '');
|
if (tag.includes(',')) {
|
||||||
|
tag = tag.replace(',', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.notes.note(note.id).tag(tag);
|
||||||
|
localRefresh(note.type);
|
||||||
|
dispatch({type: Actions.TAGS});
|
||||||
|
tagsInputRef.current?.setNativeProps({
|
||||||
|
text: '',
|
||||||
|
});
|
||||||
|
tagToAdd = '';
|
||||||
|
} catch (e) {
|
||||||
|
ToastEvent.show(e.message, 'error', 'local');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.notes.note(note.id).tag(tag);
|
if (
|
||||||
localRefresh(note.type);
|
tags.length >= 5 &&
|
||||||
dispatch({type: Actions.TAGS});
|
tags.findIndex((t) => t.title === tagToAdd) === -1
|
||||||
tagsInputRef.current?.setNativeProps({
|
) {
|
||||||
text: '',
|
await PremiumService.verify(add, () => {
|
||||||
});
|
eSendEvent(eShowGetPremium, {
|
||||||
tagToAdd = '';
|
context: 'sheet',
|
||||||
|
title: 'Get Notesnook Pro',
|
||||||
|
desc: 'To create more tags for your notes become a Pro user today.',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await add();
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -171,7 +197,7 @@ export const ActionSheetTagsSection = ({item}) => {
|
|||||||
fontSize: SIZE.xs,
|
fontSize: SIZE.xs,
|
||||||
color: colors.pri,
|
color: colors.pri,
|
||||||
}}>
|
}}>
|
||||||
{"Suggested: "}
|
{'Suggested: '}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import Animated, {Easing} from 'react-native-reanimated';
|
||||||
|
import {useTracked} from '../../provider';
|
||||||
|
import {
|
||||||
|
eSendEvent,
|
||||||
|
eSubscribeEvent,
|
||||||
|
eUnSubscribeEvent,
|
||||||
|
} from '../../services/EventManager';
|
||||||
|
import {getElevation} from '../../utils';
|
||||||
|
import {eOpenPremiumDialog, eShowGetPremium} from '../../utils/Events';
|
||||||
|
import { SIZE } from '../../utils/SizeUtils';
|
||||||
|
import {sleep} from '../../utils/TimeUtils';
|
||||||
|
import {Button} from '../Button';
|
||||||
|
import Heading from '../Typography/Heading';
|
||||||
|
import Paragraph from '../Typography/Paragraph';
|
||||||
|
|
||||||
|
const translate = new Animated.Value(-800);
|
||||||
|
|
||||||
|
export const GetPremium = ({close, context = 'global',offset=0}) => {
|
||||||
|
const [state, dispatch] = useTracked();
|
||||||
|
const {colors} = state;
|
||||||
|
const [msg, setMsg] = useState({
|
||||||
|
title: '',
|
||||||
|
desc: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const open = (event) => {
|
||||||
|
if (event.context === context) {
|
||||||
|
setMsg({
|
||||||
|
title: event.title,
|
||||||
|
desc: event.desc,
|
||||||
|
});
|
||||||
|
Animated.timing(translate, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 300,
|
||||||
|
easing: Easing.inOut(Easing.ease),
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
setTimeout(async () => {
|
||||||
|
Animated.timing(translate, {
|
||||||
|
toValue: +800,
|
||||||
|
duration: 150,
|
||||||
|
easing: Easing.inOut(Easing.ease),
|
||||||
|
}).start();
|
||||||
|
await sleep(200);
|
||||||
|
translate.setValue(-800);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
eSubscribeEvent(eShowGetPremium, open);
|
||||||
|
return () => {
|
||||||
|
eUnSubscribeEvent(eShowGetPremium, open);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
backgroundColor: colors.accent,
|
||||||
|
zIndex: 999,
|
||||||
|
...getElevation(10),
|
||||||
|
padding: 12,
|
||||||
|
borderRadius: 5,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignSelf: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
top:offset,
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
translateX: translate,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}>
|
||||||
|
<Heading size={SIZE.md} color="white" style={{maxWidth: '75%', paddingRight: 6}}>
|
||||||
|
{msg.title}
|
||||||
|
{'\n'}
|
||||||
|
<Paragraph color="white">{msg.desc}</Paragraph>
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onPress={async () => {
|
||||||
|
close();
|
||||||
|
await sleep(300);
|
||||||
|
eSendEvent(eOpenPremiumDialog);
|
||||||
|
}}
|
||||||
|
width={80}
|
||||||
|
title="Get Now"
|
||||||
|
type="inverted"
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
sendNoteEditedEvent,
|
sendNoteEditedEvent,
|
||||||
ToastEvent,
|
ToastEvent,
|
||||||
} from '../../services/EventManager';
|
} from '../../services/EventManager';
|
||||||
|
import PremiumService from '../../services/PremiumService';
|
||||||
import {
|
import {
|
||||||
ACCENT,
|
ACCENT,
|
||||||
COLOR_SCHEME,
|
COLOR_SCHEME,
|
||||||
@@ -27,11 +28,15 @@ import {
|
|||||||
setColorScheme,
|
setColorScheme,
|
||||||
} from '../../utils/Colors';
|
} from '../../utils/Colors';
|
||||||
import {db} from '../../utils/DB';
|
import {db} from '../../utils/DB';
|
||||||
import {eOpenLoginDialog, eOpenMoveNoteDialog} from '../../utils/Events';
|
import {
|
||||||
import { deleteItems } from '../../utils/functions';
|
eOpenLoginDialog,
|
||||||
|
eOpenMoveNoteDialog,
|
||||||
|
eShowGetPremium,
|
||||||
|
} from '../../utils/Events';
|
||||||
|
import {deleteItems} from '../../utils/functions';
|
||||||
import {MMKV} from '../../utils/mmkv';
|
import {MMKV} from '../../utils/mmkv';
|
||||||
import {opacity, ph, pv, SIZE, WEIGHT} from '../../utils/SizeUtils';
|
import {opacity, ph, pv, SIZE, WEIGHT} from '../../utils/SizeUtils';
|
||||||
import {timeConverter} from '../../utils/TimeUtils';
|
import {sleep, timeConverter} from '../../utils/TimeUtils';
|
||||||
import {Button} from '../Button';
|
import {Button} from '../Button';
|
||||||
import {PremiumTag} from '../Premium/PremiumTag';
|
import {PremiumTag} from '../Premium/PremiumTag';
|
||||||
import {PressableButton} from '../PressableButton';
|
import {PressableButton} from '../PressableButton';
|
||||||
@@ -40,6 +45,7 @@ import Heading from '../Typography/Heading';
|
|||||||
import Paragraph from '../Typography/Paragraph';
|
import Paragraph from '../Typography/Paragraph';
|
||||||
import {ActionSheetColorsSection} from './ActionSheetColorsSection';
|
import {ActionSheetColorsSection} from './ActionSheetColorsSection';
|
||||||
import {ActionSheetTagsSection} from './ActionSheetTagsSection';
|
import {ActionSheetTagsSection} from './ActionSheetTagsSection';
|
||||||
|
import {GetPremium} from './GetPremium';
|
||||||
const w = Dimensions.get('window').width;
|
const w = Dimensions.get('window').width;
|
||||||
|
|
||||||
export const ActionSheetComponent = ({
|
export const ActionSheetComponent = ({
|
||||||
@@ -174,11 +180,10 @@ export const ActionSheetComponent = ({
|
|||||||
func: async () => {
|
func: async () => {
|
||||||
close();
|
close();
|
||||||
try {
|
try {
|
||||||
await deleteItems(note)
|
await deleteItems(note);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -423,36 +428,44 @@ export const ActionSheetComponent = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPressVaultButton = () => {
|
const onPressVaultButton = async () => {
|
||||||
if (!premiumUser) {
|
await PremiumService.verify(
|
||||||
close('premium');
|
() => {
|
||||||
return;
|
if (!note.id) return;
|
||||||
}
|
|
||||||
if (!note.id) return;
|
|
||||||
|
|
||||||
if (note.locked) {
|
if (note.locked) {
|
||||||
close('unlock');
|
close('unlock');
|
||||||
} else {
|
} else {
|
||||||
db.vault
|
db.vault
|
||||||
.add(note.id)
|
.add(note.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
sendNoteEditedEvent(note.id, false, true);
|
sendNoteEditedEvent(note.id, false, true);
|
||||||
close();
|
|
||||||
})
|
|
||||||
.catch(async (e) => {
|
|
||||||
switch (e.message) {
|
|
||||||
case db.vault.ERRORS.noVault:
|
|
||||||
close('novault');
|
|
||||||
break;
|
|
||||||
case db.vault.ERRORS.vaultLocked:
|
|
||||||
close('locked');
|
|
||||||
break;
|
|
||||||
case db.vault.ERRORS.wrongPassword:
|
|
||||||
close();
|
close();
|
||||||
break;
|
})
|
||||||
}
|
.catch(async (e) => {
|
||||||
|
switch (e.message) {
|
||||||
|
case db.vault.ERRORS.noVault:
|
||||||
|
close('novault');
|
||||||
|
break;
|
||||||
|
case db.vault.ERRORS.vaultLocked:
|
||||||
|
close('locked');
|
||||||
|
break;
|
||||||
|
case db.vault.ERRORS.wrongPassword:
|
||||||
|
close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
eSendEvent(eShowGetPremium, {
|
||||||
|
context: 'sheet',
|
||||||
|
title: 'Get Notesnook Pro',
|
||||||
|
desc:
|
||||||
|
'With Notesnook Pro you can add notes to your vault and do so much more! Get it now.',
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -467,6 +480,7 @@ export const ActionSheetComponent = ({
|
|||||||
backgroundColor: colors.bg,
|
backgroundColor: colors.bg,
|
||||||
paddingHorizontal: 0,
|
paddingHorizontal: 0,
|
||||||
}}>
|
}}>
|
||||||
|
<GetPremium context="sheet" close={close} offset={-110} />
|
||||||
{!note.id && !note.dateCreated ? (
|
{!note.id && !note.dateCreated ? (
|
||||||
<Paragraph style={{marginVertical: 10}}>
|
<Paragraph style={{marginVertical: 10}}>
|
||||||
Start writing to save your note.
|
Start writing to save your note.
|
||||||
@@ -635,10 +649,16 @@ export const ActionSheetComponent = ({
|
|||||||
</PressableButton>
|
</PressableButton>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{hasColors && note.id ? <ActionSheetColorsSection item={note} /> : null}
|
{hasColors && note.id ? (
|
||||||
|
<ActionSheetColorsSection close={close} item={note} />
|
||||||
|
) : null}
|
||||||
|
|
||||||
{hasTags ? (
|
{hasTags ? (
|
||||||
<ActionSheetTagsSection item={note} localRefresh={localRefresh} />
|
<ActionSheetTagsSection
|
||||||
|
close={close}
|
||||||
|
item={note}
|
||||||
|
localRefresh={localRefresh}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{columnItems.length > 0 ? (
|
{columnItems.length > 0 ? (
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ const BUTTON_TYPES = {
|
|||||||
text: 'white',
|
text: 'white',
|
||||||
selected: 'accent',
|
selected: 'accent',
|
||||||
},
|
},
|
||||||
|
inverted: {
|
||||||
|
primary: 'bg',
|
||||||
|
text: 'accent',
|
||||||
|
selected: 'bg',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Button = ({
|
export const Button = ({
|
||||||
@@ -61,7 +66,7 @@ export const Button = ({
|
|||||||
style={{
|
style={{
|
||||||
marginRight: 0,
|
marginRight: 0,
|
||||||
}}
|
}}
|
||||||
color={color[BUTTON_TYPES[type].text]}
|
color={colors[BUTTON_TYPES[type].text]}
|
||||||
size={SIZE.md}
|
size={SIZE.md}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ const SimpleList = ({
|
|||||||
onPress={placeholderData.action}
|
onPress={placeholderData.action}
|
||||||
title={placeholderData.button}
|
title={placeholderData.button}
|
||||||
icon="plus"
|
icon="plus"
|
||||||
|
type="transparent"
|
||||||
fontSize={SIZE.md}
|
fontSize={SIZE.md}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { eSendEvent } from "./EventManager";
|
|||||||
|
|
||||||
let premiumStatus = null;
|
let premiumStatus = null;
|
||||||
|
|
||||||
function setPremiumStatus(status) {
|
async function setPremiumStatus(status) {
|
||||||
try {
|
try {
|
||||||
let user = await db.user.get();
|
let user = await db.user.get();
|
||||||
if (!user || !user.id) {
|
if (!user || !user.id) {
|
||||||
@@ -17,12 +17,17 @@ function setPremiumStatus(status) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function verify(callback) {
|
async function verify(callback,error) {
|
||||||
try {
|
try {
|
||||||
let user = await db.user.get();
|
let user = await db.user.get();
|
||||||
|
|
||||||
if (!user || !user.id) {
|
if (!user || !user.id) {
|
||||||
eSendEvent(eOpenPremiumDialog);
|
if (error) {
|
||||||
|
error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eSendEvent( eOpenPremiumDialog);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!callback) console.warn('You must provide a callback function');
|
if (!callback) console.warn('You must provide a callback function');
|
||||||
|
|||||||
@@ -120,3 +120,5 @@ export const eCloseSortDialog = '560';
|
|||||||
|
|
||||||
export const eOpenJumpToDialog = '561';
|
export const eOpenJumpToDialog = '561';
|
||||||
export const eCloseJumpToDialog = '562';
|
export const eCloseJumpToDialog = '562';
|
||||||
|
|
||||||
|
export const eShowGetPremium = '563';
|
||||||
Reference in New Issue
Block a user