diff --git a/apps/mobile/src/components/Announcements/announcement.js b/apps/mobile/src/components/Announcements/announcement.js
new file mode 100644
index 000000000..9ecfcb06d
--- /dev/null
+++ b/apps/mobile/src/components/Announcements/announcement.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import {FlatList, View} from 'react-native';
+import {useTracked} from '../../provider';
+import {useMessageStore, useSelectionStore} from '../../provider/stores';
+import {Button} from '../Button';
+import {allowedOnPlatform, renderItem} from './functions';
+
+export const Announcement = ({color}) => {
+ const [state] = useTracked();
+ const colors = state.colors;
+ const announcements = useMessageStore(state => state.announcements);
+ const remove = useMessageStore(state => state.remove);
+ let announcement = announcements.length > 0 ? announcements[0] : null;
+ const selectionMode = useSelectionStore(state => state.selectionMode);
+
+ return !announcement || selectionMode ? null : (
+
+
+
+
+
+
+
+
+ allowedOnPlatform(item.platform)
+ )}
+ renderItem={({item, index}) =>
+ renderItem({item: item, index: index, color: colors[color]})
+ }
+ />
+
+
+
+ );
+};
diff --git a/apps/mobile/src/components/Announcements/cta.js b/apps/mobile/src/components/Announcements/cta.js
index 599bb8f0e..80a00d689 100644
--- a/apps/mobile/src/components/Announcements/cta.js
+++ b/apps/mobile/src/components/Announcements/cta.js
@@ -1,31 +1,89 @@
import React from 'react';
import { View } from 'react-native';
import { useTracked } from '../../provider';
+import { eSendEvent, presentSheet } from '../../services/EventManager';
+import { eCloseAnnouncementDialog, eOpenPremiumDialog } from '../../utils/Events';
+import { openLinkInBrowser } from '../../utils/functions';
+import { SIZE } from '../../utils/SizeUtils';
+import { sleep } from '../../utils/TimeUtils';
+import { SettingsBackupAndRestore } from '../../views/Settings';
import { Button } from '../Button';
-import { getStyle } from './functions';
+import { allowedOnPlatform, getStyle } from './functions';
-export const Cta = ({actions, style = {}}) => {
+export const Cta = ({actions, style = {}, color}) => {
const [state] = useTracked();
const colors = state.colors;
+ let buttons =
+ actions.filter(item =>
+ allowedOnPlatform(item.platforms)
+ ) || [];
+
+ const onPress = async item => {
+ eSendEvent(eCloseAnnouncementDialog);
+ await sleep(500);
+ if (item.type === 'link') {
+ try {
+ await openLinkInBrowser(item.data, colors);
+ } catch (e) {}
+ } else if (item.type === 'promo') {
+ eSendEvent(eOpenPremiumDialog, {
+ promoCode: item.data,
+ text: item.title
+ });
+ } else if (item.type === 'backup') {
+ presentSheet({
+ title: 'Backup & restore',
+ paragraph: 'Please enable automatic backups to keep your data safe',
+ noProgress: true,
+ noIcon: true,
+ component:
+ });
+ }
+ };
return (
- {actions.map((item, index) => (
-
);
};
diff --git a/apps/mobile/src/components/Announcements/functions.js b/apps/mobile/src/components/Announcements/functions.js
index 59d80b5b8..b8f91da8b 100644
--- a/apps/mobile/src/components/Announcements/functions.js
+++ b/apps/mobile/src/components/Announcements/functions.js
@@ -1,3 +1,19 @@
+import React from 'react';
+import {View} from 'react-native';
+import {allowedPlatforms} from '../../provider/stores';
+import {ProFeatures} from '../ResultDialog/pro-features';
+import {Body} from './body';
+import {Cta} from './cta';
+import {Description} from './description';
+import {List} from './list';
+import {Photo} from './photo';
+import {SubHeading} from './subheading';
+import {Title} from './title';
+
+export function allowedOnPlatform(platforms) {
+ return platforms.some(platform => allowedPlatforms.indexOf(platform) > -1);
+}
+
export const margins = {
0: 0,
1: 12,
@@ -12,3 +28,34 @@ export const getStyle = style => {
textAlign: style.textAlign || 'left'
};
};
+
+const Features = () => {
+ return (
+
+
+
+ );
+};
+
+const renderItems = {
+ title: Title,
+ description: Description,
+ body: Body,
+ cta: Cta,
+ image: Photo,
+ list: List,
+ subheading: SubHeading,
+ features: Features,
+ callToActions: Cta
+};
+
+export const renderItem = ({item, index, color}) => {
+ const Item = renderItems[item.type];
+
+ return ;
+};
diff --git a/apps/mobile/src/components/Announcements/index.js b/apps/mobile/src/components/Announcements/index.js
index 3eb42c37c..301401063 100644
--- a/apps/mobile/src/components/Announcements/index.js
+++ b/apps/mobile/src/components/Announcements/index.js
@@ -1,112 +1,21 @@
import React, {useEffect, useState} from 'react';
import {FlatList, View} from 'react-native';
import {useTracked} from '../../provider';
+import {useMessageStore} from '../../provider/stores';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {
eCloseAnnouncementDialog,
eOpenAnnouncementDialog
} from '../../utils/Events';
import BaseDialog from '../Dialog/base-dialog';
-import {Body} from './body';
-import {Description} from './description';
-import {Photo} from './photo';
-import {SubHeading} from './subheading';
-import {List} from './list';
-import {Title} from './title';
-import {Cta} from './cta';
-import {allowedPlatforms} from '../../provider/stores';
-import {ProFeatures} from '../ResultDialog/pro-features';
+import {renderItem} from "./functions";
-const announcement_dialog_info = {
- body: [
- {
- type: 'image',
- src: 'https://media.istockphoto.com/vectors/flash-sale-promotional-labels-templates-set-special-offer-text-design-vector-id1195558677?s=170667a',
- caption: 'an image of a bear',
- style: {}
- },
- {
- type: 'title',
- text: "Don't miss out on this one!",
- style: {
- textAlign: 'center',
- marginTop: 1
- }
- },
- {
- type: 'description',
- text: "It's 50% off on Notesnook Pro today. Grab the offer now before it's too late.",
- style: {
- textAlign: 'center',
- marginBottom: 1
- }
- },
- {
- type: 'features'
- }
- // {
- // type: 'subheading',
- // text: 'New image tool'
- // },
- // {
- // type: 'body',
- // text: 'But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer.'
- // },
- // {
- // type: 'list',
- // items: [
- // {
- // text: 'Lorem ipsum dolor sit amet'
- // },
- // {
- // text: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium'
- // }
- // ]
- // }
- ],
- callToActions: [
- {
- text: 'Get 50% Off for One Year',
- action: 'none',
- platforms: ['mobile']
- }
- ]
-};
-
-const Features = () => {
- return (
-
-
-
- );
-};
-
-const renderItems = {
- title: Title,
- description: Description,
- body: Body,
- cta: Cta,
- image: Photo,
- list: List,
- subheading: SubHeading,
- features: Features
-};
-
-const renderItem = ({item, index}) => {
- const Item = renderItems[item.type];
-
- return ;
-};
-
-export const Announcement = () => {
+export const AnnouncementDialog = () => {
const [state] = useTracked();
const colors = state.colors;
- const [visible, setVisible] = useState(true);
+ const [visible, setVisible] = useState(false);
+ const [info, setInfo] = useState(null);
+ const remove = useMessageStore(state => state.remove);
useEffect(() => {
eSubscribeEvent(eOpenAnnouncementDialog, open);
@@ -117,11 +26,15 @@ export const Announcement = () => {
};
}, [visible]);
- const open = () => {
+ const open = data => {
+ setInfo(data);
+ console.log(info);
setVisible(true);
};
const close = () => {
+ //remove(info.id);
+ setInfo(null);
setVisible(false);
};
@@ -130,6 +43,7 @@ export const Announcement = () => {
animated={false}
centered={false}
bottom={true}
+ onRequestClose={close}
visible={visible}>
{
style={{
width: '100%'
}}
- data={announcement_dialog_info.body}
+ data={info?.body}
renderItem={renderItem}
/>
-
- item.platforms.some(
- platform => allowedPlatforms.indexOf(platform) > -1
- )
- )}
- />
-
+
>
);
}
diff --git a/apps/mobile/src/components/Shapes/index.js b/apps/mobile/src/components/Shapes/index.js
new file mode 100644
index 000000000..9af473863
--- /dev/null
+++ b/apps/mobile/src/components/Shapes/index.js
@@ -0,0 +1,287 @@
+import React from 'react';
+import { Dimensions, StyleSheet, View } from 'react-native';
+
+const Circle = ({size, color, position}) => {
+ let style = {
+ wrapper: {
+ flexDirection: 'row',
+ ...position
+ },
+ circle: {
+ width: size,
+ height: size,
+ borderRadius: size / 2,
+ backgroundColor: color
+ }
+ };
+ return (
+
+
+
+ );
+};
+
+const Donut = ({size, color, position}) => {
+ let style = {
+ wrapper: {
+ flexDirection: 'row',
+ ...position
+ },
+ donut: {
+ width: size,
+ height: size,
+ borderRadius: size / 2,
+ borderWidth: size / 4,
+ borderColor: color
+ }
+ };
+ return (
+
+
+
+ );
+};
+
+const Triangle = ({size, color, position}) => {
+ let style = {
+ wrapper: {
+ flexDirection: 'row',
+ ...position
+ },
+ triangle: {
+ width: 0,
+ height: 0,
+ backgroundColor: 'transparent',
+ borderStyle: 'solid',
+ borderLeftWidth: size / 2,
+ borderRightWidth: size / 2,
+ borderBottomWidth: size,
+ borderLeftColor: 'transparent',
+ borderRightColor: 'transparent',
+ borderBottomColor: color,
+ transform: [{rotate: '180deg'}]
+ }
+ };
+ return (
+
+
+
+ );
+};
+
+const DiamondNarrow = ({size, color, position}) => {
+ let style = {
+ wrapper: {
+ flexDirection: 'row',
+ ...position
+ },
+ diamondNarrow: {},
+ diamondNarrowTop: {
+ width: 0,
+ height: 0,
+ borderTopWidth: 0,
+ borderTopColor: 'transparent',
+ borderLeftColor: 'transparent',
+ borderLeftWidth: size / 2,
+ borderRightColor: 'transparent',
+ borderRightWidth: size / 2,
+ borderBottomColor: color,
+ borderBottomWidth: size / 1.42
+ },
+ diamondNarrowBottom: {
+ width: 0,
+ height: 0,
+ borderTopWidth: size / 1.42,
+ borderTopColor: color,
+ borderLeftColor: 'transparent',
+ borderLeftWidth: size / 2,
+ borderRightColor: 'transparent',
+ borderRightWidth: size / 2,
+ borderBottomColor: 'transparent',
+ borderBottomWidth: 0
+ }
+ };
+ return (
+
+
+
+
+
+
+ );
+};
+
+const CutDiamond = ({size, color, position}) => {
+ let style = {
+ wrapper: {
+ flexDirection: 'row',
+ ...position
+ },
+ cutDiamond: {},
+ cutDiamondTop: {
+ width: size,
+ height: 0,
+ borderTopWidth: 0,
+ borderTopColor: 'transparent',
+ borderLeftColor: 'transparent',
+ borderLeftWidth: size / 4,
+ borderRightColor: 'transparent',
+ borderRightWidth: size / 4,
+ borderBottomColor: color,
+ borderBottomWidth: size / 4
+ },
+ cutDiamondBottom: {
+ width: 0,
+ height: 0,
+ borderTopWidth: size / 1.42,
+ borderTopColor: color,
+ borderLeftColor: 'transparent',
+ borderLeftWidth: size / 2,
+ borderRightColor: 'transparent',
+ borderRightWidth: size / 2,
+ borderBottomColor: 'transparent',
+ borderBottomWidth: 0
+ }
+ };
+ return (
+
+
+
+
+
+
+ );
+};
+
+
+
+const Shapes = ({
+ primaryColor,
+ secondaryColor,
+ height,
+ figures,
+ borderRadius,
+ style
+}) => {
+ const config = {
+ primaryColor: primaryColor || '#416DF8',
+ secondaryColor: secondaryColor || '#2F53D5',
+ height: Dimensions.get('window').height / (height || 3.5),
+ sizefigure: 100,
+ figures: figures || [
+ {name: 'circle', position: 'center', size: 60},
+ {name: 'donut', position: 'flex-start', axis: 'top', size: 80},
+ {name: 'circle', position: 'center', axis: 'right', size: 100}
+ ],
+ borderRadius: borderRadius !== undefined ? borderRadius : 30
+ };
+
+ const arrFigures = [];
+ const buildFigures = () => {
+ config.figures.forEach((e, i) => {
+ let position = {
+ alignItems: e.position
+ };
+
+ const sizefigure = e.size || config.sizefigure;
+
+ switch (e.axis) {
+ case 'left':
+ position.left = -sizefigure / 2;
+ break;
+ case 'right':
+ position.right = -sizefigure / 2;
+ break;
+ case 'top':
+ position.top = -sizefigure / 2;
+ break;
+ case 'bottom':
+ position.bottom = -sizefigure / 2;
+ break;
+ default:
+ break;
+ }
+
+ if (e.name === 'circle') {
+ arrFigures.push(
+
+ );
+ }
+ if (e.name === 'donut') {
+ arrFigures.push(
+
+ );
+ }
+ if (e.name === 'triangle') {
+ arrFigures.push(
+
+ );
+ }
+ if (e.name === 'diamondNarrow') {
+ arrFigures.push(
+
+ );
+ }
+ if (e.name === 'cutDiamond') {
+ arrFigures.push(
+
+ );
+ }
+ });
+
+ return arrFigures;
+ };
+
+ return (
+
+ <>{buildFigures()}>
+
+ );
+};
+
+const styles = StyleSheet.create({
+ wrapper: {
+ position: 'absolute',
+ height: '100%',
+ left: 0,
+ right: 0,
+ flexDirection: 'row',
+ justifyContent: 'space-between'
+ }
+});
+
+export { Shapes };
+
diff --git a/apps/mobile/src/components/SimpleList/announcement.js b/apps/mobile/src/components/SimpleList/announcement.js
deleted file mode 100644
index a20b1b6b2..000000000
--- a/apps/mobile/src/components/SimpleList/announcement.js
+++ /dev/null
@@ -1,195 +0,0 @@
-import React from 'react';
-import { View } from 'react-native';
-import { useTracked } from '../../provider';
-import {
- allowedPlatforms,
- useMessageStore,
- useSelectionStore
-} from '../../provider/stores';
-import { eSendEvent, presentSheet } from '../../services/EventManager';
-import { hexToRGBA, RGB_Linear_Shade } from '../../utils/ColorUtils';
-import { eOpenPremiumDialog } from '../../utils/Events';
-import { openLinkInBrowser } from '../../utils/functions';
-import { SIZE } from '../../utils/SizeUtils';
-import { SettingsBackupAndRestore } from '../../views/Settings';
-import { Button } from '../Button';
-import Seperator from '../Seperator';
-import Heading from '../Typography/Heading';
-import Paragraph from '../Typography/Paragraph';
-
-export const Announcement = ({color}) => {
- const [state] = useTracked();
- const colors = state.colors;
- const announcements = useMessageStore(state => state.announcements);
- const remove = useMessageStore(state => state.remove);
- let announcement = announcements.length > 0 ? announcements[0] : null;
- const selectionMode = useSelectionStore(state => state.selectionMode);
-
- return !announcement || selectionMode ? null : (
-
-
-
-
-
-
- {announcements.length}
-
-
-
-
-
- {
- remove(announcement.id);
- }}
- style={{
- paddingVertical: 4
- }}
- />
-
-
-
- {announcement?.title && (
-
- {announcement.title}
-
- )}
-
-
- {announcement?.description && (
- {announcement.description}
- )}
-
-
- {announcement?.callToActions &&
- announcement.callToActions.map((item, index) =>
- item.platforms.some(
- platform => allowedPlatforms.indexOf(platform) > -1
- ) ? (
- <>
- {
- if (item.type === 'link') {
- try {
- await openLinkInBrowser(item.data, state.colors);
- } catch (e) {}
- } else if (item.type === 'promo') {
- eSendEvent(eOpenPremiumDialog, {
- promoCode: item.data,
- text: item.title
- });
- } else if (item.type === 'backup') {
- presentSheet({
- title: 'Backup & restore',
- paragraph:
- 'Please enable automatic backups to keep your data safe',
- noProgress: true,
- noIcon: true,
- component:
- });
- }
- }}
- width={'100%'}
- style={{
- marginBottom: 10
- }}
- />
- >
- ) : null
- )}
-
-
-
- );
-};
diff --git a/apps/mobile/src/components/SimpleList/header.js b/apps/mobile/src/components/SimpleList/header.js
index bb1818f12..e47047cea 100644
--- a/apps/mobile/src/components/SimpleList/header.js
+++ b/apps/mobile/src/components/SimpleList/header.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {useMessageStore} from '../../provider/stores';
@@ -8,8 +8,10 @@ import {normalize, SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import {Placeholder} from '../ListPlaceholders';
import Heading from '../Typography/Heading';
-import {Announcement} from './announcement';
+import {Announcement} from '../Announcements/announcement';
import {Card} from './card';
+import { eSendEvent } from '../../services/EventManager';
+import { eOpenAnnouncementDialog } from '../../utils/Events';
export const Header = React.memo(
({
@@ -28,8 +30,14 @@ export const Header = React.memo(
const [state] = useTracked();
const {colors} = state;
const announcements = useMessageStore(state => state.announcements);
+ const dialogs = useMessageStore(state => state.dialogs);
- return announcements.length > 0 && !noAnnouncement ? (
+ useEffect(() => {
+ if (dialogs.length > 0) {
+ eSendEvent(eOpenAnnouncementDialog,dialogs[0]);
+ }
+ },[dialogs])
+ return announcements.length !== 0 && !noAnnouncement ? (
) : type === 'search' ? null : !shouldShow ? (
)}
-
) : (
void,
setDeviceMode: (mode: string) => void,
setDimensions: (dimensions: Dimensions) => void
- appLoading:boolean
- setAppLoading:(appLoading:boolean) => void
- isIntroCompleted:boolean
- setIntroCompleted:(isIntroCompleted:boolean) => void
+ appLoading: boolean
+ setAppLoading: (appLoading: boolean) => void
+ isIntroCompleted: boolean
+ setIntroCompleted: (isIntroCompleted: boolean) => void
}
export interface MenuStore extends State {
@@ -149,10 +149,25 @@ export type Action = {
title: string
data: string
}
+export type Style = {
+ marginTop?: number,
+ marginBottom?: number,
+ textAlign?: "center" | "left" | "right"
+}
+export type BodyItem = {
+ type: "image" | "title" | "description" | "body" | "list" | "features" | "poll" | "subheading" | "shapes"
+ src?: string
+ caption?: string
+ text?: string
+ style?: Style,
+ items?: Array<{
+ text?: string
+ }>
+}
export type Announcement = {
- title: string
- description: string
+ type: "dialog" | "inline"
+ body: BodyItem[]
id: string
callToActions: Action[]
timestamp: number
@@ -166,6 +181,7 @@ export interface MessageStore extends State {
setMessage: (message: Message) => void
announcements: Announcement[],
setAnnouncement: () => Promise
+ dialogs: Announcement[]
remove: (id: string) => void
}
diff --git a/apps/mobile/src/provider/stores.ts b/apps/mobile/src/provider/stores.ts
index 116cc8ad7..7380d8441 100644
--- a/apps/mobile/src/provider/stores.ts
+++ b/apps/mobile/src/provider/stores.ts
@@ -332,6 +332,7 @@ export const useMessageStore = create((set, get) => ({
}
set({ announcements: copy });
},
+ dialogs:[],
setAnnouncement: async function () {
let announcements: Announcement[] = [];
try {
@@ -342,14 +343,15 @@ export const useMessageStore = create((set, get) => ({
} catch (e) {
set({ announcements: [] })
} finally {
- set({ announcements: await getFiltered(announcements) })
+ let all = await getFiltered(announcements);
+ set({ announcements: all.filter(a => a.type === "inline"),dialogs:all.filter(a => a.type === "dialog") })
}
}
}));
-const getFiltered = async (announcements) => {
+const getFiltered = async (announcements:Announcement[]) => {
if (!announcements) return [];
- let filtered = [];
+ let filtered:Announcement[] = [];
for (var announcement of announcements) {
if (await shouldShowAnnouncement(announcement)) {
filtered.push(announcement);