fix linting issues

This commit is contained in:
ammarahm-ed
2022-01-22 12:57:05 +05:00
parent e907a16a54
commit e663bb66f5
209 changed files with 5211 additions and 5974 deletions

View File

@@ -1,4 +1,41 @@
module.exports = {
root: true,
extends: '@react-native-community',
parser: '@babel/eslint-parser',
env: {
browser: true,
es2021: true,
'react-native/react-native': true
},
extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:prettier/recommended'],
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 12,
es6: true,
sourceType: 'module'
},
plugins: ['react', 'react-native', 'prettier', 'unused-imports'],
rules: {
'react/display-name': 0,
'no-unused-vars': 'off',
'unused-imports/no-unused-vars': [
'warn',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_'
}
],
'no-empty': 'off',
'react/prop-types': 0,
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
'prettier/prettier': [
'error',
{},
{
usePrettierrc: true
}
]
}
};

View File

@@ -1,7 +1,13 @@
module.exports = {
bracketSpacing: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'none',
arrowParens: 'avoid',
bracketSpacing: true,
jsxBracketSameLine: false,
jsxSingleQuote: false,
quoteProps: 'as-needed',
singleQuote: true,
semi: true,
printWidth: 100,
useTabs: false,
tabWidth: 2,
trailingComma: 'none'
};

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
import React from 'react';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {PressableButton} from '../PressableButton';
import {SIZE} from '../../utils/SizeUtils';
import {hexToRGBA, RGB_Linear_Shade} from '../../utils/ColorUtils';
import { useTracked } from '../../provider';
import { PressableButton } from '../PressableButton';
import { SIZE } from '../../utils/SizeUtils';
import { hexToRGBA, RGB_Linear_Shade } from '../../utils/ColorUtils';
import { showTooltip } from '../../utils';
export const ActionIcon = ({
@@ -21,17 +21,17 @@ export const ActionIcon = ({
disabled,
onLongPress,
tooltipText,
type="gray"
type = 'gray'
}) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
return (
<PressableButton
testID={testID}
onPress={onPress}
hitSlop={{top: top, left: left, right: right, bottom: bottom}}
onLongPress={(event) => {
hitSlop={{ top: top, left: left, right: right, bottom: bottom }}
onLongPress={event => {
if (onLongPress) {
onLongPress();
return;
@@ -48,14 +48,13 @@ export const ActionIcon = ({
justifyContent: 'center',
alignItems: 'center',
borderRadius: 100,
...customStyle,
}}>
...customStyle
}}
>
<Icon
name={name}
style={iconStyle}
color={
disabled ? RGB_Linear_Shade(-0.05, hexToRGBA(colors.nav)) : color
}
color={disabled ? RGB_Linear_Shade(-0.05, hexToRGBA(colors.nav)) : color}
size={size}
/>
</PressableButton>

View File

@@ -1,24 +1,13 @@
import React, { createRef } from 'react';
import {
Keyboard,
StyleSheet, TextInput, TouchableOpacity,
View
} from 'react-native';
import { Keyboard, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import { notesnook } from '../../../e2e/test.ids';
import { useMenuStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import {
eSubscribeEvent,
eUnSubscribeEvent,
ToastEvent
} from '../../services/EventManager';
import { eSubscribeEvent, eUnSubscribeEvent, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import { db } from '../../utils/database';
import {
eCloseAddNotebookDialog,
eOpenAddNotebookDialog
} from '../../utils/Events';
import { eCloseAddNotebookDialog, eOpenAddNotebookDialog } from '../../utils/Events';
import { ph, pv, SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import { ActionIcon } from '../ActionIcon';
@@ -94,7 +83,7 @@ export class AddNotebookDialog extends React.Component {
} else {
this.setState({
visible: true,
notebook:null
notebook: null
});
}
sleep(100).then(r => {
@@ -115,7 +104,7 @@ export class AddNotebookDialog extends React.Component {
};
onDelete = index => {
let {topics} = this.state;
let { topics } = this.state;
let prevTopics = topics;
refs = [];
prevTopics.splice(index, 1);
@@ -145,7 +134,7 @@ export class AddNotebookDialog extends React.Component {
this.setState({
loading: true
});
let {topics, notebook} = this.state;
let { topics, notebook } = this.state;
if (!this.title || this.title?.trim().length === 0) {
ToastEvent.show({
@@ -176,9 +165,7 @@ export class AddNotebookDialog extends React.Component {
if (notebook) {
if (this.topicsToDelete?.length > 0) {
await db.notebooks
.notebook(toEdit.id)
.topics.delete(...this.topicsToDelete);
await db.notebooks.notebook(toEdit.id).topics.delete(...this.topicsToDelete);
toEdit = db.notebooks.notebook(toEdit.id).data;
}
@@ -189,7 +176,7 @@ export class AddNotebookDialog extends React.Component {
});
let nextTopics = toEdit.topics.map((topic, index) => {
let copy = {...topic};
let copy = { ...topic };
copy.title = prevTopics[index];
return copy;
});
@@ -206,7 +193,7 @@ export class AddNotebookDialog extends React.Component {
title: this.title,
description: this.description,
topics: prevTopics,
id:null
id: null
});
}
useMenuStore.getState().setMenuPins();
@@ -224,9 +211,8 @@ export class AddNotebookDialog extends React.Component {
onSubmit = (forward = true) => {
this.hiddenInput.current?.focus();
let willFocus = true;
let {topics} = this.state;
if (!this.currentInputValue || this.currentInputValue?.trim().length === 0)
return;
let { topics } = this.state;
if (!this.currentInputValue || this.currentInputValue?.trim().length === 0) return;
let prevTopics = [...topics];
if (this.prevItem === null) {
@@ -235,7 +221,7 @@ export class AddNotebookDialog extends React.Component {
topics: prevTopics
});
setTimeout(() => {
this.listRef.scrollToEnd({animated: true});
this.listRef.scrollToEnd({ animated: true });
}, 30);
this.currentInputValue = null;
} else {
@@ -259,7 +245,7 @@ export class AddNotebookDialog extends React.Component {
if (forward) {
setTimeout(() => {
this.listRef.scrollToEnd({animated: true});
this.listRef.scrollToEnd({ animated: true });
}, 30);
}
}
@@ -270,8 +256,8 @@ export class AddNotebookDialog extends React.Component {
};
render() {
const {colors} = this.props;
const {topics, visible, topicInputFocused, notebook} = this.state;
const { colors } = this.props;
const { topics, visible, topicInputFocused, notebook } = this.state;
if (!visible) return null;
return (
<SheetWrapper
@@ -293,13 +279,15 @@ export class AddNotebookDialog extends React.Component {
});
}}
statusBarTranslucent={false}
onRequestClose={this.close}>
onRequestClose={this.close}
>
<View
style={{
maxHeight: DDS.isTab ? '90%' : '100%',
borderRadius: DDS.isTab ? 5 : 0,
paddingHorizontal: 12
}}>
}}
>
<TextInput
ref={this.hiddenInput}
style={{
@@ -311,11 +299,7 @@ export class AddNotebookDialog extends React.Component {
blurOnSubmit={false}
/>
<DialogHeader
title={
notebook && notebook.dateCreated
? 'Edit Notebook'
: 'New Notebook'
}
title={notebook && notebook.dateCreated ? 'Edit Notebook' : 'New Notebook'}
paragraph={
notebook && notebook.dateCreated
? 'You are editing ' + this.title + ' notebook.'
@@ -392,8 +376,8 @@ export class AddNotebookDialog extends React.Component {
}}
keyboardShouldPersistTaps="always"
keyboardDismissMode="interactive"
ListFooterComponent={<View style={{height: 50}} />}
renderItem={({item, index}) => (
ListFooterComponent={<View style={{ height: 50 }} />}
renderItem={({ item, index }) => (
<TopicItem
item={item}
onPress={(item, index) => {
@@ -419,11 +403,7 @@ export class AddNotebookDialog extends React.Component {
width="100%"
height={50}
fontSize={SIZE.md}
title={
notebook && notebook.dateCreated
? 'Save changes'
: 'Create notebook'
}
title={notebook && notebook.dateCreated ? 'Save changes' : 'Create notebook'}
type="accent"
onPress={this.addNewNotebook}
/>
@@ -443,7 +423,7 @@ export class AddNotebookDialog extends React.Component {
}
}
const TopicItem = ({item, index, colors, onPress, onDelete}) => {
const TopicItem = ({ item, index, colors, onPress, onDelete }) => {
const topicRef = ref => (refs[index] = ref);
return (
@@ -455,7 +435,8 @@ const TopicItem = ({item, index, colors, onPress, onDelete}) => {
backgroundColor: colors.nav,
borderRadius: 5,
marginVertical: 5
}}>
}}
>
<TouchableOpacity
style={{
width: '80%',
@@ -489,7 +470,8 @@ const TopicItem = ({item, index, colors, onPress, onDelete}) => {
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'flex-end'
}}>
}}
>
<ActionIcon
onPress={() => {
onPress(item, index);

View File

@@ -1,27 +1,19 @@
import React, {createRef} from 'react';
import {Keyboard, LayoutAnimation, UIManager, View} from 'react-native';
import {
Transition,
Transitioning,
TransitioningView
} from 'react-native-reanimated';
import {useMenuStore} from '../../provider/stores';
import {
eSubscribeEvent,
eUnSubscribeEvent,
ToastEvent
} from '../../services/EventManager';
import React, { createRef } from 'react';
import { Keyboard, LayoutAnimation, UIManager, View } from 'react-native';
import { Transition, Transitioning, TransitioningView } from 'react-native-reanimated';
import { useMenuStore } from '../../provider/stores';
import { eSubscribeEvent, eUnSubscribeEvent, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {db} from '../../utils/database';
import {eCloseAddTopicDialog, eOpenAddTopicDialog} from '../../utils/Events';
import {sleep} from '../../utils/TimeUtils';
import { db } from '../../utils/database';
import { eCloseAddTopicDialog, eOpenAddTopicDialog } from '../../utils/Events';
import { sleep } from '../../utils/TimeUtils';
import BaseDialog from '../Dialog/base-dialog';
import DialogButtons from '../Dialog/dialog-buttons';
import DialogContainer from '../Dialog/dialog-container';
import DialogHeader from '../Dialog/dialog-header';
import Input from '../Input';
import Seperator from '../Seperator';
import {Toast} from '../Toast';
import { Toast } from '../Toast';
export class AddTopicDialog extends React.Component {
constructor(props) {
@@ -41,14 +33,14 @@ export class AddTopicDialog extends React.Component {
addNewTopic = async () => {
try {
this.setState({loading: true});
this.setState({ loading: true });
if (!this.title || this.title?.trim() === '') {
ToastEvent.show({
heading: 'Topic title is required',
type: 'error',
context: 'local'
});
this.setState({loading: false});
this.setState({ loading: false });
return;
}
@@ -60,7 +52,7 @@ export class AddTopicDialog extends React.Component {
await db.notebooks.notebook(topic.notebookId).topics.add(topic);
}
this.setState({loading: false});
this.setState({ loading: false });
this.close();
Navigation.setRoutesToUpdate([
Navigation.routeNames.Notebooks,
@@ -80,7 +72,7 @@ export class AddTopicDialog extends React.Component {
eUnSubscribeEvent(eCloseAddTopicDialog, this.close);
}
open = async ({notebookId, toEdit}) => {
open = async ({ notebookId, toEdit }) => {
let id = notebookId;
if (id) {
this.notebook = await db.notebooks.notebook(id).data;
@@ -105,7 +97,7 @@ export class AddTopicDialog extends React.Component {
};
render() {
const {visible} = this.state;
const { visible } = this.state;
if (!visible) return null;
return (
<BaseDialog
@@ -123,15 +115,14 @@ export class AddTopicDialog extends React.Component {
bounce={false}
statusBarTranslucent={false}
visible={true}
onRequestClose={this.close}>
onRequestClose={this.close}
>
<DialogContainer>
<DialogHeader
icon="book-outline"
title={this.toEdit ? 'Edit topic' : 'New topic'}
paragraph={
this.toEdit
? 'Edit title of the topic'
: 'Add a new topic in ' + this.notebook.title
this.toEdit ? 'Edit title of the topic' : 'Add a new topic in ' + this.notebook.title
}
padding={12}
/>
@@ -139,7 +130,8 @@ export class AddTopicDialog extends React.Component {
<View
style={{
paddingHorizontal: 12
}}>
}}
>
<Input
fwdRef={this.titleRef}
onChangeText={value => {

View File

@@ -1,11 +1,11 @@
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';
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}) => {
export const Announcement = ({ color }) => {
const [state] = useTracked();
const colors = state.colors;
const announcements = useMessageStore(state => state.announcements);
@@ -18,14 +18,16 @@ export const Announcement = ({color}) => {
style={{
backgroundColor: colors.bg,
width: '100%'
}}>
}}
>
<View
style={{
paddingVertical: 12,
width: '100%',
borderRadius: 10,
overflow: 'hidden'
}}>
}}
>
<Button
type="errorShade"
icon="close"
@@ -48,11 +50,9 @@ export const Announcement = ({color}) => {
width: '100%',
marginTop: 15
}}
data={announcement?.body.filter(item =>
allowedOnPlatform(item.platforms)
)}
renderItem={({item, index}) =>
renderItem({item: item, index: index, color: colors[color],inline:true})
data={announcement?.body.filter(item => allowedOnPlatform(item.platforms))}
renderItem={({ item, index }) =>
renderItem({ item: item, index: index, color: colors[color], inline: true })
}
/>
</View>

View File

@@ -3,8 +3,7 @@ import { useTracked } from '../../provider';
import Paragraph from '../Typography/Paragraph';
import { getStyle } from './functions';
export const Body = ({text, style = {}}) => {
export const Body = ({ text, style = {} }) => {
const [state] = useTracked();
const colors = state.colors;
@@ -13,8 +12,9 @@ export const Body = ({text, style = {}}) => {
style={{
paddingHorizontal: 12,
...getStyle(style)
}}>
}}
>
{text}
</Paragraph>
);
};
};

View File

@@ -1,18 +1,18 @@
import React from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {eSendEvent, presentSheet} from '../../services/EventManager';
import {eCloseAnnouncementDialog} from '../../utils/Events';
import {openLinkInBrowser} from '../../utils/functions';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { eSendEvent, presentSheet } from '../../services/EventManager';
import { eCloseAnnouncementDialog } from '../../utils/Events';
import { openLinkInBrowser } from '../../utils/functions';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import SettingsBackupAndRestore from '../../views/Settings/backup-restore';
import {Button} from '../Button';
import { Button } from '../Button';
import GeneralSheet from '../GeneralSheet';
import {PricingPlans} from '../Premium/pricing-plans';
import {allowedOnPlatform, getStyle} from './functions';
import { PricingPlans } from '../Premium/pricing-plans';
import { allowedOnPlatform, getStyle } from './functions';
export const Cta = ({actions, style = {}, color, inline}) => {
export const Cta = ({ actions, style = {}, color, inline }) => {
const [state] = useTracked();
const colors = state.colors;
let buttons = actions.filter(item => allowedOnPlatform(item.platforms)) || [];
@@ -51,7 +51,8 @@ export const Cta = ({actions, style = {}, color, inline}) => {
style={{
paddingHorizontal: 12,
...getStyle(style)
}}>
}}
>
<GeneralSheet context="premium_cta" />
{buttons.length > 0 &&
buttons.slice(0, 1).map(item => (

View File

@@ -4,8 +4,7 @@ import { SIZE } from '../../utils/SizeUtils';
import Paragraph from '../Typography/Paragraph';
import { getStyle } from './functions';
export const Description = ({text, style = {}}) => {
export const Description = ({ text, style = {} }) => {
const [state] = useTracked();
const colors = state.colors;
return (
@@ -14,7 +13,8 @@ export const Description = ({text, style = {}}) => {
style={{
marginHorizontal: 12,
...getStyle(style)
}}>
}}
>
{text}
</Paragraph>
);

View File

@@ -1,14 +1,14 @@
import React, { Fragment } 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';
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) {
if (!platforms) return true;
@@ -37,7 +37,8 @@ const Features = () => {
paddingHorizontal: 12,
alignItems: 'center',
width: '100%'
}}>
}}
>
<ProFeatures />
</View>
);
@@ -47,7 +48,7 @@ const renderItems = {
title: Title,
description: Description,
body: Body,
text:Body,
text: Body,
image: Photo,
list: List,
subheading: SubHeading,
@@ -55,8 +56,16 @@ const renderItems = {
callToActions: Cta
};
export const renderItem = ({item, index, color,inline}) => {
const Item = renderItems[item.type] || Fragment
export const renderItem = ({ item, index, color, inline }) => {
const Item = renderItems[item.type] || Fragment;
return <Item key={item.text || item.src || item.type} {...item} index={index} color={color} inline={inline} />;
return (
<Item
key={item.text || item.src || item.type}
{...item}
index={index}
color={color}
inline={inline}
/>
);
};

View File

@@ -1,15 +1,12 @@
import React, {useEffect, useState} from 'react';
import {FlatList, View} from 'react-native';
import {useTracked} from '../../provider';
import {useMessageStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {
eCloseAnnouncementDialog,
eOpenAnnouncementDialog
} from '../../utils/Events';
import React, { useEffect, useState } from 'react';
import { FlatList, View } from 'react-native';
import { useTracked } from '../../provider';
import { useMessageStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import { eCloseAnnouncementDialog, eOpenAnnouncementDialog } from '../../utils/Events';
import BaseDialog from '../Dialog/base-dialog';
import {allowedOnPlatform, renderItem} from './functions';
import { allowedOnPlatform, renderItem } from './functions';
export const AnnouncementDialog = () => {
const [state] = useTracked();
@@ -46,7 +43,8 @@ export const AnnouncementDialog = () => {
centered={false}
bottom={true}
onRequestClose={close}
visible={visible}>
visible={visible}
>
<View
style={{
width: DDS.isTab ? 600 : '100%',
@@ -55,7 +53,8 @@ export const AnnouncementDialog = () => {
borderRadius: DDS.isTab ? 10 : 0,
overflow: 'hidden',
marginBottom: DDS.isTab ? 20 : 0
}}>
}}
>
<FlatList
style={{
width: '100%'

View File

@@ -5,28 +5,32 @@ import { useTracked } from '../../provider';
import Paragraph from '../Typography/Paragraph';
import { getStyle } from './functions';
export const List = ({items, listType, style = {}}) => {
export const List = ({ items, listType, style = {} }) => {
const [state] = useTracked();
const colors = state.colors;
return (
<View
style={{
paddingHorizontal: 12,
paddingLeft: listType === 'ordered' ? 25 : 25,
...getStyle(style)
}}>
}}
>
{items.map((item, index) => (
<View
key={item.text}
style={{
paddingVertical: 6,
flexDirection: 'row'
}}>
}}
>
{listType === 'ordered' ? (
<Paragraph
style={{
marginRight: 5
}}>
}}
>
{index + 1}.
</Paragraph>
) : (

View File

@@ -2,11 +2,10 @@ import React from 'react';
import { Image } from 'react-native';
import { getStyle } from './functions';
export const Photo = ({src, style = {}}) => {
return src ?(
export const Photo = ({ src, style = {} }) => {
return src ? (
<Image
source={{uri: src}}
source={{ uri: src }}
resizeMode="cover"
style={{
width: '100%',
@@ -15,5 +14,5 @@ export const Photo = ({src, style = {}}) => {
...getStyle(style)
}}
/>
) : null
};
) : null;
};

View File

@@ -4,8 +4,7 @@ import { SIZE } from '../../utils/SizeUtils';
import Heading from '../Typography/Heading';
import { getStyle } from './functions';
export const SubHeading = ({text, style = {}}) => {
export const SubHeading = ({ text, style = {} }) => {
const [state] = useTracked();
const colors = state.colors;
@@ -16,7 +15,8 @@ export const SubHeading = ({text, style = {}}) => {
marginHorizontal: 12,
marginTop: 12,
...getStyle(style)
}}>
}}
>
{text}
</Heading>
);

View File

@@ -1,21 +1,21 @@
import React from 'react';
import { useTracked } from '../../provider';
import Heading from '../Typography/Heading';
import { getStyle } from './functions';
export const Title = ({text, style = {}}) => {
const [state] = useTracked();
const colors = state.colors;
return (
<Heading
style={{
marginHorizontal: 12,
marginTop: 12,
...getStyle(style)
}}>
{text}
</Heading>
);
};
export const Title = ({ text, style = {} }) => {
const [state] = useTracked();
const colors = state.colors;
return (
<Heading
style={{
marginHorizontal: 12,
marginTop: 12,
...getStyle(style)
}}
>
{text}
</Heading>
);
};

View File

@@ -1,8 +1,8 @@
import React, {useEffect, useRef, useState} from 'react';
import {Appearance, Linking, Platform, SafeAreaView, View} from 'react-native';
import Animated, {Easing} from 'react-native-reanimated';
import React, { useEffect, useRef, useState } from 'react';
import { Appearance, Linking, Platform, SafeAreaView, View } from 'react-native';
import Animated, { Easing } from 'react-native-reanimated';
import AnimatedProgress from 'react-native-reanimated-progress-bar';
import {useTracked} from '../../provider';
import { useTracked } from '../../provider';
import {
useFavoriteStore,
useMessageStore,
@@ -12,7 +12,7 @@ import {
} from '../../provider/stores';
import Backup from '../../services/Backup';
import BiometricService from '../../services/BiometricService';
import {DDS} from '../../services/DeviceDetection';
import { DDS } from '../../services/DeviceDetection';
import {
eSendEvent,
eSubscribeEvent,
@@ -21,34 +21,30 @@ import {
ToastEvent
} from '../../services/EventManager';
import PremiumService from '../../services/PremiumService';
import {editing, STORE_LINK} from '../../utils';
import {COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT} from '../../utils/Colors';
import {db} from '../../utils/database';
import {
eOpenAnnouncementDialog,
eOpenLoginDialog,
eOpenRateDialog
} from '../../utils/Events';
import {MMKV} from '../../utils/mmkv';
import {tabBarRef} from '../../utils/Refs';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import { editing, STORE_LINK } from '../../utils';
import { COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT } from '../../utils/Colors';
import { db } from '../../utils/database';
import { eOpenAnnouncementDialog, eOpenLoginDialog, eOpenRateDialog } from '../../utils/Events';
import { MMKV } from '../../utils/mmkv';
import { tabBarRef } from '../../utils/Refs';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import SettingsBackupAndRestore from '../../views/Settings/backup-restore';
import {Button} from '../Button';
import { Button } from '../Button';
import Input from '../Input';
import Seperator from '../Seperator';
import SplashScreen from '../SplashScreen';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {checkVersion} from 'react-native-check-version';
import {Placeholder, SvgToPngView} from '../ListPlaceholders';
import {Update} from '../Update';
import {setRateAppMessage} from '../../services/Message';
import { checkVersion } from 'react-native-check-version';
import { Placeholder, SvgToPngView } from '../ListPlaceholders';
import { Update } from '../Update';
import { setRateAppMessage } from '../../services/Message';
let passwordValue = null;
let didVerifyUser = false;
const opacityV = new Animated.Value(1);
const AppLoader = ({onLoad}) => {
const AppLoader = ({ onLoad }) => {
const [state] = useTracked();
const colors = state.colors;
const [loading, setLoading] = useState(true);
@@ -172,10 +168,7 @@ const AppLoader = ({onLoad}) => {
const checkNeedsBackup = async () => {
let settingsStore = useSettingStore.getState();
let askForBackup = await MMKV.getItem('askForBackup');
if (
settingsStore.settings.reminder === 'off' ||
!settingsStore.settings.reminder
) {
if (settingsStore.settings.reminder === 'off' || !settingsStore.settings.reminder) {
askForBackup = JSON.parse(askForBackup);
if (askForBackup?.timestamp < Date.now()) {
presentSheet({
@@ -215,10 +208,7 @@ const AppLoader = ({onLoad}) => {
});
return;
}
let verified = await BiometricService.validateUser(
'Unlock to access your notes',
''
);
let verified = await BiometricService.validateUser('Unlock to access your notes', '');
if (verified) {
didVerifyUser = true;
setVerifyUser(false);
@@ -241,46 +231,40 @@ const AppLoader = ({onLoad}) => {
return loading ? (
<Animated.View
style={{
backgroundColor:
Appearance.getColorScheme() === 'dark'
? COLOR_SCHEME_DARK.bg
: colors.bg,
backgroundColor: Appearance.getColorScheme() === 'dark' ? COLOR_SCHEME_DARK.bg : colors.bg,
width: '100%',
height: '100%',
position: 'absolute',
zIndex: 999,
borderRadius: 10
}}>
}}
>
<Animated.View
style={{
backgroundColor:
Appearance.getColorScheme() === 'dark'
? COLOR_SCHEME_DARK.bg
: colors.bg,
Appearance.getColorScheme() === 'dark' ? COLOR_SCHEME_DARK.bg : colors.bg,
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 10,
opacity: opacityV
}}>
}}
>
{verifyUser ? (
<SafeAreaView
style={{
flex: 1,
justifyContent: 'center',
width:
deviceMode !== 'mobile'
? '50%'
: Platform.OS == 'ios'
? '95%'
: '100%',
width: deviceMode !== 'mobile' ? '50%' : Platform.OS == 'ios' ? '95%' : '100%',
paddingHorizontal: 12
}}>
}}
>
<Heading
style={{
alignSelf: 'center'
}}>
}}
>
Verify your identity
</Heading>
@@ -289,9 +273,10 @@ const AppLoader = ({onLoad}) => {
<Paragraph
style={{
alignSelf: 'center'
}}>
To keep your notes secure, please enter password of the
account you are logged in to.
}}
>
To keep your notes secure, please enter password of the account you are logged in
to.
</Paragraph>
<Seperator />
<Input
@@ -317,9 +302,9 @@ const AppLoader = ({onLoad}) => {
<Paragraph
style={{
alignSelf: 'center'
}}>
To keep your notes secure, please unlock app the with
biometrics.
}}
>
To keep your notes secure, please unlock app the with biometrics.
</Paragraph>
<Seperator />
</>
@@ -341,7 +326,8 @@ const AppLoader = ({onLoad}) => {
height: 10,
flexDirection: 'row',
width: 100
}}>
}}
>
<AnimatedProgress
style={{
backgroundColor:

View File

@@ -5,15 +5,9 @@ import * as Progress from 'react-native-progress';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { useTracked } from '../../provider';
import { useAttachmentStore } from '../../provider/stores';
import {
eSubscribeEvent,
eUnSubscribeEvent
} from '../../services/EventManager';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import { db } from '../../utils/database';
import {
eCloseAttachmentDialog,
eOpenAttachmentsDialog
} from '../../utils/Events';
import { eCloseAttachmentDialog, eOpenAttachmentsDialog } from '../../utils/Events';
import filesystem from '../../utils/filesystem';
import { SIZE } from '../../utils/SizeUtils';
import { ActionIcon } from '../ActionIcon';
@@ -41,7 +35,7 @@ export const AttachmentDialog = () => {
const open = item => {
setNote(item);
setVisible(true);
let _attachments = db.attachments.ofNote(item.id, "all");
let _attachments = db.attachments.ofNote(item.id, 'all');
setAttachments(_attachments);
};
@@ -62,13 +56,15 @@ export const AttachmentDialog = () => {
fwdRef={actionSheetRef}
onClose={async () => {
setVisible(false);
}}>
}}
>
<View
style={{
width: '100%',
alignSelf: 'center',
paddingHorizontal: 12
}}>
}}
>
<DialogHeader title="Attachments" />
<FlatList
nestedScrollEnabled
@@ -85,13 +81,14 @@ export const AttachmentDialog = () => {
height: 150,
justifyContent: 'center',
alignItems: 'center'
}}>
}}
>
<Icon name="attachment" size={60} color={colors.icon} />
<Paragraph>No attachments on this note</Paragraph>
</View>
}
data={attachments}
renderItem={({item, index}) => (
renderItem={({ item, index }) => (
<Attachment attachment={item} note={note} setNote={setNote} />
)}
/>
@@ -102,7 +99,8 @@ export const AttachmentDialog = () => {
style={{
textAlign: 'center',
marginTop: 10
}}>
}}
>
<Icon name="shield-key-outline" size={SIZE.xs} color={colors.icon} />
{' '}All attachments are end-to-end encrypted.
</Paragraph>
@@ -128,7 +126,7 @@ function getFileExtension(filename) {
return ext == null ? '' : ext[1];
}
export const Attachment = ({attachment, encryption}) => {
export const Attachment = ({ attachment, encryption }) => {
const [state] = useTracked();
const colors = state.colors;
const progress = useAttachmentStore(state => state.progress);
@@ -149,7 +147,7 @@ export const Attachment = ({attachment, encryption}) => {
useAttachmentStore.getState().remove(attachment.metadata.hash);
return;
}
filesystem.downloadAttachment(attachment.metadata.hash,false);
filesystem.downloadAttachment(attachment.metadata.hash, false);
};
useEffect(() => {
@@ -182,20 +180,23 @@ export const Attachment = ({attachment, encryption}) => {
borderRadius: 5,
backgroundColor: colors.nav
}}
type="grayBg">
type="grayBg"
>
<GeneralSheet context={attachment.metadata.hash} />
<View
style={{
flexShrink: 1,
flexDirection: 'row',
alignItems: 'center'
}}>
}}
>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
marginLeft: -5
}}>
}}
>
<Icon name="file" size={SIZE.xxxl} color={colors.icon} />
<Paragraph
@@ -204,7 +205,8 @@ export const Attachment = ({attachment, encryption}) => {
color={colors.light}
style={{
position: 'absolute'
}}>
}}
>
{getFileExtension(attachment.metadata.filename).toUpperCase()}
</Paragraph>
</View>
@@ -213,7 +215,8 @@ export const Attachment = ({attachment, encryption}) => {
style={{
flexShrink: 1,
marginLeft: 10
}}>
}}
>
<Paragraph
size={SIZE.sm - 1}
style={{
@@ -222,18 +225,15 @@ export const Attachment = ({attachment, encryption}) => {
}}
numberOfLines={1}
lineBreakMode="middle"
color={colors.pri}>
color={colors.pri}
>
{attachment.metadata.filename}
</Paragraph>
<Paragraph color={colors.icon} size={SIZE.xs}>
{formatBytes(attachment.length)}{' '}
{currentProgress?.type
? '(' + currentProgress.type + 'ing - tap to cancel)'
: ''}
{currentProgress?.type ? '(' + currentProgress.type + 'ing - tap to cancel)' : ''}
</Paragraph>
</View>
</View>
@@ -250,7 +250,8 @@ export const Attachment = ({attachment, encryption}) => {
marginLeft: 5,
marginTop: 5,
marginRight: -5
}}>
}}
>
<Progress.Circle
size={SIZE.xxl}
progress={

View File

@@ -1,10 +1,10 @@
import React from 'react';
import {ActivityIndicator} from 'react-native';
import { ActivityIndicator } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {BUTTON_TYPES, showTooltip} from '../../utils';
import {ph, SIZE} from '../../utils/SizeUtils';
import {PressableButton} from '../PressableButton';
import { useTracked } from '../../provider';
import { BUTTON_TYPES, showTooltip } from '../../utils';
import { ph, SIZE } from '../../utils/SizeUtils';
import { PressableButton } from '../PressableButton';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
@@ -36,7 +36,7 @@ export const Button = ({
iconColor
}) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const textColor = buttonType.text
? buttonType.text
@@ -45,8 +45,7 @@ export const Button = ({
? BUTTON_TYPES[type](accentColor, accentText).text
: BUTTON_TYPES[type].text
];
const Component = bold ? Heading : Paragraph
const Component = bold ? Heading : Paragraph;
return (
<PressableButton
@@ -80,7 +79,8 @@ export const Button = ({
alignItems: 'center',
flexDirection: 'row',
...style
}}>
}}
>
{loading ? <ActivityIndicator color={textColor} size={fontSize + 4} /> : null}
{icon && !loading && iconPosition === 'left' ? (
<Icon
@@ -88,7 +88,6 @@ export const Button = ({
style={{
marginRight: 0
}}
color={iconColor || buttonType.text || textColor}
size={iconSize}
/>
@@ -105,7 +104,8 @@ export const Button = ({
marginRight: icon || (loading && iconPosition === 'right') ? 5 : 0
},
textStyle
]}>
]}
>
{title}
</Component>
)}

View File

@@ -1,26 +1,16 @@
import React, {useEffect} from 'react';
import {Keyboard, Platform, View} from 'react-native';
import Animated, {Easing, sub} from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import React, { useEffect } from 'react';
import { Keyboard, Platform, View } from 'react-native';
import Animated, { Easing, sub } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
import {useSettingStore} from '../../provider/stores';
import {
editing,
getElevation,
showTooltip,
TOOLTIP_POSITIONS,
} from '../../utils';
import {normalize, SIZE} from '../../utils/SizeUtils';
import {PressableButton} from '../PressableButton';
import { notesnook } from '../../../e2e/test.ids';
import { useSettingStore } from '../../provider/stores';
import { editing, getElevation, showTooltip, TOOLTIP_POSITIONS } from '../../utils';
import { normalize, SIZE } from '../../utils/SizeUtils';
import { PressableButton } from '../PressableButton';
const translateY = new Animated.Value(0);
export const ContainerBottomButton = ({
title,
onPress,
color = 'accent',
shouldShow = false,
}) => {
export const ContainerBottomButton = ({ title, onPress, color = 'accent', shouldShow = false }) => {
const insets = useSafeAreaInsets();
const deviceMode = useSettingStore(state => state.deviceMode);
@@ -28,7 +18,7 @@ export const ContainerBottomButton = ({
Animated.timing(translateY, {
toValue: translate,
duration: 250,
easing: Easing.elastic(1),
easing: Easing.elastic(1)
}).start();
}
@@ -45,8 +35,8 @@ export const ContainerBottomButton = ({
};
useEffect(() => {
let sub1 = Keyboard.addListener('keyboardDidShow', onKeyboardShow);
let sub2 = Keyboard.addListener('keyboardDidHide', onKeyboardHide);
let sub1 = Keyboard.addListener('keyboardDidShow', onKeyboardShow);
let sub2 = Keyboard.addListener('keyboardDidHide', onKeyboardHide);
return () => {
sub1?.remove();
sub2?.remove();
@@ -67,13 +57,14 @@ export const ContainerBottomButton = ({
zIndex: 10,
transform: [
{
translateY: translateY,
translateY: translateY
},
{
translateX: translateY,
},
],
}}>
translateX: translateY
}
]
}}
>
<PressableButton
testID={notesnook.buttons.add}
type="accent"
@@ -81,20 +72,21 @@ export const ContainerBottomButton = ({
accentText="light"
customStyle={{
...getElevation(5),
borderRadius: 100,
borderRadius: 100
}}
onLongPress={event => {
showTooltip(event, title, TOOLTIP_POSITIONS.LEFT);
}}
onPress={onPress}>
onPress={onPress}
>
<View
style={{
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: normalize(60),
width: normalize(60),
}}>
width: normalize(60)
}}
>
<Icon
name={title === 'Clear all trash' ? 'delete' : 'plus'}
color="white"

View File

@@ -3,9 +3,9 @@ import { View } from 'react-native';
import { useTracked } from '../../provider';
import { useSelectionStore } from '../../provider/stores';
export const ContainerTopSection = ({children}) => {
export const ContainerTopSection = ({ children }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const selectionMode = useSelectionStore(state => state.selectionMode);
return !selectionMode ? (
@@ -13,9 +13,10 @@ export const ContainerTopSection = ({children}) => {
style={{
backgroundColor: colors.bg,
width: '100%',
overflow: 'hidden',
}}>
overflow: 'hidden'
}}
>
{children}
</View>
) : null
) : null;
};

View File

@@ -2,25 +2,27 @@ import React from 'react';
import { KeyboardAvoidingView, Platform, SafeAreaView } from 'react-native';
import { useTracked } from '../../provider';
import useIsFloatingKeyboard from '../../utils/use-is-floating-keyboard';
export const Container = ({children}) => {
export const Container = ({ children }) => {
const [state] = useTracked();
const {colors, } = state;
const { colors } = state;
const floating = useIsFloatingKeyboard();
return (
<KeyboardAvoidingView behavior="padding" enabled={Platform.OS === 'ios' && !floating }
<KeyboardAvoidingView
behavior="padding"
enabled={Platform.OS === 'ios' && !floating}
style={{
backgroundColor:colors.bg,
width:"100%",
height:"100%"
backgroundColor: colors.bg,
width: '100%',
height: '100%'
}}
>
<SafeAreaView
style={{
height: '100%',
backgroundColor:colors.bg,
overflow:"hidden",
}}>
backgroundColor: colors.bg,
overflow: 'hidden'
}}
>
{children}
</SafeAreaView>
</KeyboardAvoidingView>

View File

@@ -1,9 +1,9 @@
import React, {Component, createRef} from 'react';
import {Platform} from 'react-native';
import {Keyboard} from 'react-native';
import {FlatList, TextInput, View} from 'react-native';
import {DDS} from '../../services/DeviceDetection';
import {editing} from '../../utils';
import React, { Component, createRef } from 'react';
import { Platform } from 'react-native';
import { Keyboard } from 'react-native';
import { FlatList, TextInput, View } from 'react-native';
import { DDS } from '../../services/DeviceDetection';
import { editing } from '../../utils';
export default class CustomTabs extends Component {
constructor(props) {
@@ -22,7 +22,7 @@ export default class CustomTabs extends Component {
this.lastOffset = this.props.offsets.a;
}
renderItem = ({item, index}) => this.props.items[index];
renderItem = ({ item, index }) => this.props.items[index];
onMoveShouldSetResponder = event => {
if (this.responderAllowedScroll) return;
@@ -69,8 +69,7 @@ export default class CustomTabs extends Component {
this.currentDrawerState = true;
this.goToIndex(0);
}
this.props.onDrawerStateChange &&
this.props.onDrawerStateChange(this.currentDrawerState);
this.props.onDrawerStateChange && this.props.onDrawerStateChange(this.currentDrawerState);
}
};
@@ -78,8 +77,7 @@ export default class CustomTabs extends Component {
if (this.page === 0) {
this.goToIndex(1);
this.currentDrawerState = false;
this.props.onDrawerStateChange &&
this.props.onDrawerStateChange(this.currentDrawerState);
this.props.onDrawerStateChange && this.props.onDrawerStateChange(this.currentDrawerState);
}
};
@@ -151,11 +149,7 @@ export default class CustomTabs extends Component {
this.scrollTimeout = null;
}
this.scrollTimeout = setTimeout(() => {
if (
this.scrollOffset !== this.props.offsets.a &&
this.page === 1 &&
!this.scrollEnabled
) {
if (this.scrollOffset !== this.props.offsets.a && this.page === 1 && !this.scrollEnabled) {
this.goToIndex(2, false);
}
}, 300);
@@ -174,7 +168,7 @@ export default class CustomTabs extends Component {
this.goToIndex(2);
}
if (this.page !== page) {
this.props.onChangeTab({i: page, from: this.page});
this.props.onChangeTab({ i: page, from: this.page });
this.page = page;
}
};
@@ -202,17 +196,14 @@ export default class CustomTabs extends Component {
let drawerState = page === 0 && this.scrollOffset < 150;
if (drawerState !== this.currentDrawerState) {
this.currentDrawerState = drawerState;
this.props.onDrawerStateChange &&
this.props.onDrawerStateChange(this.currentDrawerState);
this.props.onDrawerStateChange && this.props.onDrawerStateChange(this.currentDrawerState);
}
this.props.toggleOverlay(
Math.floor(this.scrollOffset) < Math.floor(this.props.offsets.a - 10)
? true
: false
Math.floor(this.scrollOffset) < Math.floor(this.props.offsets.a - 10) ? true : false
);
if (this.page !== page) {
this.scrollEndTimeout = setTimeout(() => {
this.props.onChangeTab({i: page, from: this.page});
this.props.onChangeTab({ i: page, from: this.page });
this.page = page;
}, 50);
}
@@ -225,8 +216,7 @@ export default class CustomTabs extends Component {
if (px > width * 0.75 || (DDS.isSmallTab && px > this.props.widths.a)) {
this.goToIndex(1);
this.currentDrawerState = false;
this.props.onDrawerStateChange &&
this.props.onDrawerStateChange(this.currentDrawerState);
this.props.onDrawerStateChange && this.props.onDrawerStateChange(this.currentDrawerState);
}
}
};
@@ -239,10 +229,11 @@ export default class CustomTabs extends Component {
onStartShouldSetResponderCapture={this.onMoveShouldSetResponder}
style={{
flex: 1
}}>
}}
>
<TextInput
ref={this.inputElement}
style={{height: 1, padding: 0, width: 1, position: 'absolute'}}
style={{ height: 1, padding: 0, width: 1, position: 'absolute' }}
blurOnSubmit={false}
/>
<FlatList
@@ -270,11 +261,7 @@ export default class CustomTabs extends Component {
disableIntervalMomentum={true}
decelerationRate="fast"
snapToAlignment="start"
snapToOffsets={[
this.props.offsets.a,
this.props.offsets.b,
this.props.offsets.c
]}
snapToOffsets={[this.props.offsets.a, this.props.offsets.b, this.props.offsets.c]}
contentOffset={{
x: editing.movedAway ? this.props.offsets.a : this.props.offsets.b
}}

View File

@@ -1,4 +1,4 @@
import React, {useEffect} from 'react';
import React, { useEffect } from 'react';
import {
Keyboard,
KeyboardAvoidingView,
@@ -8,9 +8,9 @@ import {
StyleSheet,
TouchableOpacity
} from 'react-native';
import {useSettingStore} from '../../provider/stores';
import { useSettingStore } from '../../provider/stores';
import useIsFloatingKeyboard from '../../utils/use-is-floating-keyboard';
import {BouncingView} from '../Transitions/bouncing-view';
import { BouncingView } from '../Transitions/bouncing-view';
const BaseDialog = ({
visible,
@@ -60,18 +60,14 @@ const BaseDialog = ({
if (!closeOnTouch) return null;
useSettingStore.getState().setSheetKeyboardHandler(true);
onRequestClose && onRequestClose();
}}>
}}
>
<SafeAreaView
style={{
backgroundColor: background
? background
: transparent
? 'transparent'
: 'rgba(0,0,0,0.3)'
}}>
<KeyboardAvoidingView
enabled={!floating && Platform.OS === 'ios'}
behavior="padding">
backgroundColor: background ? background : transparent ? 'transparent' : 'rgba(0,0,0,0.3)'
}}
>
<KeyboardAvoidingView enabled={!floating && Platform.OS === 'ios'} behavior="padding">
<BouncingView
duration={400}
animated={animated}
@@ -79,13 +75,10 @@ const BaseDialog = ({
style={[
styles.backdrop,
{
justifyContent: centered
? 'center'
: bottom
? 'flex-end'
: 'flex-start'
justifyContent: centered ? 'center' : bottom ? 'flex-end' : 'flex-start'
}
]}>
]}
>
<TouchableOpacity
onPress={closeOnTouch ? onRequestClose : null}
style={styles.overlayButton}

View File

@@ -1,11 +1,11 @@
import React from 'react';
import {ActivityIndicator, StyleSheet, View} from 'react-native';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import { useTracked } from '../../provider';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import Paragraph from '../Typography/Paragraph';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
import { notesnook } from '../../../e2e/test.ids';
const DialogButtons = ({
onPressPositive,
@@ -17,29 +17,31 @@ const DialogButtons = ({
positiveType
}) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
return (
<View style={[styles.container,{
backgroundColor:colors.nav,
height:60,
borderBottomRightRadius:10,
borderBottomLeftRadius:10,
paddingHorizontal:12
}]}>
<View
style={[
styles.container,
{
backgroundColor: colors.nav,
height: 60,
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10,
paddingHorizontal: 12
}
]}
>
{loading ? (
<ActivityIndicator color={colors.accent} size={SIZE.lg} />
) : doneText ? (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
<Icon
color={colors.accent}
name="check-circle-outline"
size={SIZE.md}
/>
alignItems: 'center'
}}
>
<Icon color={colors.accent} name="check-circle-outline" size={SIZE.md} />
<Paragraph color={colors.accent}>{' ' + doneText}</Paragraph>
</View>
) : (
@@ -49,8 +51,9 @@ const DialogButtons = ({
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
alignItems: 'center'
}}
>
<Button
onPress={onPressNegative}
fontSize={SIZE.md}
@@ -65,10 +68,10 @@ const DialogButtons = ({
fontSize={SIZE.md}
testID={notesnook.ids.default.dialog.yes}
style={{
marginLeft: 10,
marginLeft: 10
}}
bold
type={positiveType || "transparent"}
type={positiveType || 'transparent'}
title={positiveTitle}
/>
) : null}
@@ -84,6 +87,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
marginTop: 10,
},
marginTop: 10
}
});

View File

@@ -4,8 +4,8 @@ import { useTracked } from '../../provider';
import { DDS } from '../../services/DeviceDetection';
import { getElevation } from '../../utils';
const DialogContainer = ({width, height, ...restProps}) => {
const [state,] = useTracked();
const DialogContainer = ({ width, height, ...restProps }) => {
const [state] = useTracked();
const colors = state.colors;
return (
@@ -17,7 +17,7 @@ const DialogContainer = ({width, height, ...restProps}) => {
maxHeight: height || 450,
borderRadius: 10,
backgroundColor: colors.bg,
paddingTop: 12,
paddingTop: 12
}}
/>
);

View File

@@ -1,9 +1,9 @@
import React from 'react';
import {Text} from 'react-native';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import { Text } from 'react-native';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
@@ -29,22 +29,22 @@ const DialogHeader = ({
justifyContent: 'space-between',
minHeight: 50,
paddingHorizontal: padding
}}>
}}
>
<View
style={{
width: '100%'
}}>
}}
>
<View
style={{
flexDirection: 'row',
justifyContent: centered ? 'center' : 'space-between',
alignItems: 'center'
}}>
}}
>
<Heading size={SIZE.xl}>
{title}{' '}
{titlePart ? (
<Text style={{color: colors.accent}}>{titlePart}</Text>
) : null}
{title} {titlePart ? <Text style={{ color: colors.accent }}>{titlePart}</Text> : null}
</Heading>
{button ? (
@@ -69,7 +69,8 @@ const DialogHeader = ({
maxWidth: centered ? '90%' : '100%',
alignSelf: centered ? 'center' : 'flex-start'
}}
color={paragraphColor || colors.icon}>
color={paragraphColor || colors.icon}
>
{paragraph}
</Paragraph>
) : null}

View File

@@ -1,28 +1,34 @@
import { eSendEvent } from "../../services/EventManager";
import { eCloseSimpleDialog, eOpenSimpleDialog } from "../../utils/Events";
import { eSendEvent } from '../../services/EventManager';
import { eCloseSimpleDialog, eOpenSimpleDialog } from '../../utils/Events';
type DialogInfo = {
title?: string,
paragraph?: string,
positiveText?: string,
negativeText?: string,
positivePress?: (value:any) => void,
onClose?: () => void,
positiveType?: "transparent" | "gray" | "grayBg" | "accent" | "inverted" | "shade" | "error" | "errorShade",
icon?: string,
paragraphColor: string,
input:boolean,
inputPlaceholder:string,
defaultValue:string,
context:"global" | "local"
}
title?: string;
paragraph?: string;
positiveText?: string;
negativeText?: string;
positivePress?: (value: any) => void;
onClose?: () => void;
positiveType?:
| 'transparent'
| 'gray'
| 'grayBg'
| 'accent'
| 'inverted'
| 'shade'
| 'error'
| 'errorShade';
icon?: string;
paragraphColor: string;
input: boolean;
inputPlaceholder: string;
defaultValue: string;
context: 'global' | 'local';
};
export function presentDialog(data: DialogInfo): void {
eSendEvent(eOpenSimpleDialog, data);
}
export function hideDialog(): void {
eSendEvent(eCloseSimpleDialog);
}
}

View File

@@ -13,7 +13,7 @@ import BaseDialog from './base-dialog';
import DialogButtons from './dialog-buttons';
import DialogHeader from './dialog-header';
export const Dialog = ({context = 'global'}) => {
export const Dialog = ({ context = 'global' }) => {
const [state] = useTracked();
const colors = state.colors;
const [visible, setVisible] = useState(false);
@@ -32,7 +32,7 @@ export const Dialog = ({context = 'global'}) => {
input: false,
inputPlaceholder: 'Enter some text',
defaultValue: '',
disableBackdropClosing:false
disableBackdropClosing: false
});
useEffect(() => {
@@ -48,9 +48,7 @@ export const Dialog = ({context = 'global'}) => {
const onPressPositive = async () => {
if (dialogInfo.positivePress) {
inputRef.current?.blur();
let result = await dialogInfo.positivePress(
inputValue || dialogInfo.defaultValue
);
let result = await dialogInfo.positivePress(inputValue || dialogInfo.defaultValue);
if (result === false) {
return;
}
@@ -93,16 +91,16 @@ export const Dialog = ({context = 'global'}) => {
closeOnTouch={!dialogInfo.disableBackdropClosing}
onShow={async () => {
if (dialogInfo.input) {
inputRef.current?.setNativeProps({
text:dialogInfo.defaultValue
text: dialogInfo.defaultValue
});
await sleep(300);
inputRef.current?.focus();
}
}}
visible={true}
onRequestClose={hide}>
onRequestClose={hide}
>
<View style={style}>
<DialogHeader
title={dialogInfo.title}
@@ -117,7 +115,8 @@ export const Dialog = ({context = 'global'}) => {
<View
style={{
paddingHorizontal: 12
}}>
}}
>
<Input
fwdRef={inputRef}
autoCapitalize="none"

View File

@@ -1,4 +1,4 @@
import {eSendEvent} from '../../services/EventManager';
import { eSendEvent } from '../../services/EventManager';
import {
eCloseActionSheet,
eCloseAddNotebookDialog,

View File

@@ -33,10 +33,7 @@ export class DialogManager extends Component {
}
shouldComponentUpdate(nextProps, nextState) {
return (
JSON.stringify(nextProps) !== JSON.stringify(this.props) ||
nextState !== this.state
);
return JSON.stringify(nextProps) !== JSON.stringify(this.props) || nextState !== this.state;
}
onThemeChange = () => {
@@ -54,7 +51,7 @@ export class DialogManager extends Component {
}
render() {
let {colors} = this.state;
let { colors } = this.state;
return (
<>
<Dialog context="global" />

View File

@@ -18,18 +18,12 @@ import Seperator from '../Seperator';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
const {
eSubscribeEvent,
eUnSubscribeEvent
} = require('../../services/EventManager');
const {
eOpenExportDialog,
eCloseExportDialog,
} = require('../../utils/Events');
const { eSubscribeEvent, eUnSubscribeEvent } = require('../../services/EventManager');
const { eOpenExportDialog, eCloseExportDialog } = require('../../utils/Events');
const ExportDialog = () => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const [visible, setVisible] = useState(false);
const actionSheetRef = useRef();
@@ -75,9 +69,7 @@ const ExportDialog = () => {
}
setDoneText(
`Note exported successfully! You can find the exported note in ${
Platform.OS === 'ios'
? 'Files Manager/Notesnook'
: `Storage/Notesnook/exported/${name}`
Platform.OS === 'ios' ? 'Files Manager/Notesnook' : `Storage/Notesnook/exported/${name}`
}.`
);
@@ -137,13 +129,12 @@ const ExportDialog = () => {
<View
style={{
paddingHorizontal: 12
}}>
}}
>
<DialogHeader
icon="export"
title="Export Note"
paragraph={
'All exports are saved in Notesnook/exported folder in phone storage'
}
paragraph={'All exports are saved in Notesnook/exported folder in phone storage'}
/>
</View>
@@ -163,7 +154,8 @@ const ExportDialog = () => {
justifyContent: 'flex-start',
borderRadius: 0,
paddingHorizontal: 12
}}>
}}
>
<View
style={{
backgroundColor: colors.shade,
@@ -172,24 +164,19 @@ const ExportDialog = () => {
width: 60,
justifyContent: 'center',
alignItems: 'center'
}}>
<Icon
name={item.icon}
color={colors.accent}
size={SIZE.xxxl + 10}
/>
}}
>
<Icon name={item.icon} color={colors.accent} size={SIZE.xxxl + 10} />
</View>
<View
style={{
flexShrink: 1
}}>
<Heading style={{marginLeft: 10}} size={SIZE.md}>
}}
>
<Heading style={{ marginLeft: 10 }} size={SIZE.md}>
{item.title}
</Heading>
<Paragraph
style={{marginLeft: 10}}
size={SIZE.sm}
color={colors.icon}>
<Paragraph style={{ marginLeft: 10 }} size={SIZE.sm} color={colors.icon}>
{item.desc}
</Paragraph>
</View>
@@ -202,7 +189,8 @@ const ExportDialog = () => {
width: '100%',
paddingHorizontal: 12,
marginTop: 10
}}>
}}
>
{complete && (
<>
<Button
@@ -259,13 +247,12 @@ const ExportDialog = () => {
marginTop: 5
}}
color={colors.icon}
size={SIZE.xs}>
size={SIZE.xs}
>
{'Note exported as ' + result.fileName}
</Paragraph>
)}
{exporting && !complete && (
<Button loading={true} height={50} width="100%" />
)}
{exporting && !complete && <Button loading={true} height={50} width="100%" />}
</View>
</View>
</View>

View File

@@ -1,17 +1,18 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
import FileViewer from 'react-native-file-viewer';
import Share from 'react-native-share';
import {ToastEvent} from '../../services/EventManager';
import {SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import { ToastEvent } from '../../services/EventManager';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
export const ShareComponent = ({uri, name, padding}) => {
export const ShareComponent = ({ uri, name, padding }) => {
return (
<View
style={{
paddingHorizontal: padding
}}>
}}
>
<Button
title="Open"
type="accent"

View File

@@ -15,9 +15,9 @@ import SheetWrapper from '../Sheet';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
const GeneralSheet = ({context}) => {
const GeneralSheet = ({ context }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const [visible, setVisible] = useState(false);
const [dialogData, setDialogData] = useState(null);
const actionSheetRef = useRef();
@@ -35,10 +35,7 @@ const GeneralSheet = ({context}) => {
}, [visible]);
const open = async data => {
if (
(data.context && !context) ||
(data.context && data.context !== context)
) {
if ((data.context && !context) || (data.context && data.context !== context)) {
return;
}
if (visible || dialogData) {
@@ -92,20 +89,19 @@ const GeneralSheet = ({context}) => {
dialogData.onClose && dialogData.onClose();
setVisible(false);
setDialogData(null);
}}>
}}
>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
marginBottom:
!dialogData.progress &&
!dialogData.icon &&
!dialogData.title &&
!dialogData.paragraph
!dialogData.progress && !dialogData.icon && !dialogData.title && !dialogData.paragraph
? 0
: 10,
paddingHorizontal: 12
}}>
}}
>
{dialogData?.progress ? (
<ActivityIndicator
style={{
@@ -127,9 +123,7 @@ const GeneralSheet = ({context}) => {
{dialogData?.title ? <Heading> {dialogData?.title}</Heading> : null}
{dialogData?.paragraph ? (
<Paragraph style={{textAlign: 'center'}}>
{dialogData?.paragraph}
</Paragraph>
<Paragraph style={{ textAlign: 'center' }}>{dialogData?.paragraph}</Paragraph>
) : null}
</View>
@@ -141,14 +135,15 @@ const GeneralSheet = ({context}) => {
style={{
paddingHorizontal: 12,
marginBottom: dialogData.valueArray ? 12 : 0
}}>
}}
>
{dialogData.valueArray &&
dialogData.valueArray.map(v => (
<Button
title={v}
type="gray"
key={v}
textStyle={{fontWeight: 'normal'}}
textStyle={{ fontWeight: 'normal' }}
fontSize={SIZE.sm}
icon="check"
width="100%"
@@ -163,7 +158,8 @@ const GeneralSheet = ({context}) => {
<View
style={{
paddingHorizontal: 12
}}>
}}
>
{dialogData?.action ? (
<Button
onPress={dialogData.action}
@@ -171,7 +167,6 @@ const GeneralSheet = ({context}) => {
title={dialogData.actionText}
accentColor={dialogData.iconColor || 'accent'}
accentText="light"
fontSize={SIZE.lg}
type="accent"
height={50}
width="100%"
@@ -205,12 +200,9 @@ const GeneralSheet = ({context}) => {
}}
size={SIZE.xs}
onPress={dialogData.learnMorePress}
color={colors.icon}>
<Icon
color={colors.icon}
name="information-outline"
size={SIZE.xs}
/>{' '}
color={colors.icon}
>
<Icon color={colors.icon} name="information-outline" size={SIZE.xs} />{' '}
{dialogData.learnMore}
</Paragraph>
) : null}

View File

@@ -5,7 +5,7 @@ import { useTracked } from '../../provider';
import { useUserStore } from '../../provider/stores';
import { eSendEvent, ToastEvent } from '../../services/EventManager';
import PremiumService from '../../services/PremiumService';
import { APP_VERSION } from "../../../version";
import { APP_VERSION } from '../../../version';
import { db } from '../../utils/database';
import { eCloseProgressDialog } from '../../utils/Events';
import { openLinkInBrowser } from '../../utils/functions';
@@ -29,9 +29,8 @@ export const Issue = () => {
const onPress = async () => {
if (loading) return;
if (!title.current || !body.current) return;
if (title.current?.trim() === '' || body.current?.trim().length === 0)
return;
if (title.current?.trim() === '' || body.current?.trim().length === 0) return;
try {
setLoading(true);
@@ -43,8 +42,8 @@ export const Issue = () => {
**Device information:**
App version: ${APP_VERSION}
Platform: ${Platform.OS}
Model: ${Platform.constants.Brand || ""}-${Platform.constants.Model|| ""}-${
Platform.constants.Version || ""
Model: ${Platform.constants.Brand || ''}-${Platform.constants.Model || ''}-${
Platform.constants.Version || ''
}
Pro: ${PremiumService.get()}
Logged in: ${user ? 'yes' : 'no'}`,
@@ -65,11 +64,12 @@ Logged in: ${user ? 'yes' : 'no'}`,
}}
onPress={() => {
Linking.openURL(issue_url);
}}>
}}
>
{issue_url}.
</Text>{' '}
Please note that we will respond to your issue on the given link. We
recommend that you save it.
Please note that we will respond to your issue on the given link. We recommend that you
save it.
</Text>
),
positiveText: 'Copy link',
@@ -97,7 +97,8 @@ Logged in: ${user ? 'yes' : 'no'}`,
<View
style={{
paddingHorizontal: 12
}}>
}}
>
<DialogHeader
title="Report issue"
paragraph="Let us know if you have faced any issue/bug while using Notesnook."
@@ -116,7 +117,7 @@ Logged in: ${user ? 'yes' : 'no'}`,
fontFamily: 'OpenSans-Regular',
marginBottom: 10,
fontSize: SIZE.md,
color:colors.heading,
color: colors.heading
}}
placeholderTextColor={colors.placeholder}
/>
@@ -140,15 +141,14 @@ For example:
maxHeight: 200,
fontSize: SIZE.sm,
marginBottom: 2.5,
color:colors.pri
color: colors.pri
}}
placeholderTextColor={colors.placeholder}
/>
<Paragraph
size={SIZE.xs}
color={
colors.icon
}>{`App version: ${APP_VERSION} Platform: ${Platform.OS} Model: ${Platform.constants.Brand}-${Platform.constants.Model}-${Platform.constants.Version}`}</Paragraph>
color={colors.icon}
>{`App version: ${APP_VERSION} Platform: ${Platform.OS} Model: ${Platform.constants.Brand}-${Platform.constants.Model}-${Platform.constants.Version}`}</Paragraph>
<Seperator />
<Button
@@ -166,7 +166,8 @@ For example:
style={{
marginTop: 10,
textAlign: 'center'
}}>
}}
>
The information above will be publically available at{' '}
<Text
onPress={() => {
@@ -175,11 +176,11 @@ For example:
style={{
textDecorationLine: 'underline',
color: colors.accent
}}>
}}
>
github.com/streetwriters/notesnook.
</Text>{' '}
If you want to ask something in general or need some assistance, we
would suggest that you{' '}
If you want to ask something in general or need some assistance, we would suggest that you{' '}
<Text
style={{
textDecorationLine: 'underline',
@@ -189,7 +190,8 @@ For example:
try {
await openLinkInBrowser('https://discord.gg/zQBK97EE22', colors);
} catch (e) {}
}}>
}}
>
join our community on Discord.
</Text>
</Paragraph>

View File

@@ -7,9 +7,9 @@ import Navigation from '../../services/Navigation';
import { SIZE } from '../../utils/SizeUtils';
import { ActionIcon } from '../ActionIcon';
export const HeaderLeftMenu = ({currentScreen,headerMenuState}) => {
export const HeaderLeftMenu = ({ currentScreen, headerMenuState }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const deviceMode = useSettingStore(state => state.deviceMode);
const onLeftButtonPress = () => {
@@ -20,12 +20,9 @@ export const HeaderLeftMenu = ({currentScreen,headerMenuState}) => {
Navigation.goBack();
};
return (
<>
{deviceMode !== "tablet" ||
currentScreen === 'Search' ||
!headerMenuState ? (
{deviceMode !== 'tablet' || currentScreen === 'Search' || !headerMenuState ? (
<ActionIcon
testID={notesnook.ids.default.header.buttons.left}
customStyle={{
@@ -35,11 +32,11 @@ export const HeaderLeftMenu = ({currentScreen,headerMenuState}) => {
width: 40,
borderRadius: 100,
marginLeft: -5,
marginRight:DDS.isLargeTablet()? 10 : 25,
marginRight: DDS.isLargeTablet() ? 10 : 25
}}
left={40}
top={40}
right={DDS.isLargeTablet()? 10 : 25}
right={DDS.isLargeTablet() ? 10 : 25}
onPress={onLeftButtonPress}
onLongPress={() => {
Navigation.popToTop();
@@ -47,7 +44,7 @@ export const HeaderLeftMenu = ({currentScreen,headerMenuState}) => {
name={!headerMenuState ? 'arrow-left' : 'menu'}
color={colors.pri}
iconStyle={{
marginLeft: !headerMenuState ? -5 : 0,
marginLeft: !headerMenuState ? -5 : 0
}}
/>
) : undefined}

View File

@@ -11,9 +11,9 @@ import { sleep } from '../../utils/TimeUtils';
import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
export const HeaderRightMenu = ({currentScreen, action, rightButtons}) => {
export const HeaderRightMenu = ({ currentScreen, action, rightButtons }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const deviceMode = useSettingStore(state => state.deviceMode);
const menuRef = useRef();
return (
@@ -25,7 +25,6 @@ export const HeaderRightMenu = ({currentScreen, action, rightButtons}) => {
menu: false
});
}}
name="magnify"
color={colors.pri}
customStyle={styles.rightBtn}
@@ -40,10 +39,10 @@ export const HeaderRightMenu = ({currentScreen, action, rightButtons}) => {
iconSize={SIZE.xl}
type="shade"
hitSlop={{
top:10,
right:10,
bottom:10,
left:0
top: 10,
right: 10,
bottom: 10,
left: 0
}}
style={{
marginLeft: 10,
@@ -51,8 +50,8 @@ export const HeaderRightMenu = ({currentScreen, action, rightButtons}) => {
height: 32,
borderRadius: 5,
paddingHorizontal: 0,
borderWidth:1,
borderColor:colors.accent
borderWidth: 1,
borderColor: colors.accent
}}
/>
) : null}
@@ -75,7 +74,8 @@ export const HeaderRightMenu = ({currentScreen, action, rightButtons}) => {
color={colors.pri}
customStyle={styles.rightBtn}
/>
}>
}
>
{rightButtons.map((item, index) => (
<MenuItem
key={item.title}
@@ -87,7 +87,8 @@ export const HeaderRightMenu = ({currentScreen, action, rightButtons}) => {
textStyle={{
fontSize: SIZE.md,
color: colors.pri
}}>
}}
>
<Icon name={item.icon} size={SIZE.md} />
{' ' + item.title}
</MenuItem>

View File

@@ -1,20 +1,20 @@
import React, {useEffect, useState} from 'react';
import {Platform, StyleSheet, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {useTracked} from '../../provider';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import React, { useEffect, useState } from 'react';
import { Platform, StyleSheet, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTracked } from '../../provider';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import SearchService from '../../services/SearchService';
import {eScrollEvent} from '../../utils/Events';
import {ActionIcon} from '../ActionIcon';
import {SearchInput} from '../SearchInput';
import {HeaderLeftMenu} from './HeaderLeftMenu';
import {HeaderRightMenu} from './HeaderRightMenu';
import {Title} from './title';
import { eScrollEvent } from '../../utils/Events';
import { ActionIcon } from '../ActionIcon';
import { SearchInput } from '../SearchInput';
import { HeaderLeftMenu } from './HeaderLeftMenu';
import { HeaderRightMenu } from './HeaderRightMenu';
import { Title } from './title';
export const Header = React.memo(
({root, title, screen, isBack, color, action, rightButtons, notebook}) => {
({ root, title, screen, isBack, color, action, rightButtons, notebook }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const insets = useSafeAreaInsets();
const [hide, setHide] = useState(true);
@@ -44,9 +44,10 @@ export const Header = React.memo(
overflow: 'hidden',
borderBottomWidth: 1,
borderBottomColor: hide ? 'transparent' : colors.nav,
justifyContent: 'space-between',
justifyContent: 'space-between'
}
]}>
]}
>
<View style={styles.leftBtnContainer}>
<HeaderLeftMenu headerMenuState={!isBack} currentScreen={screen} />
@@ -59,11 +60,7 @@ export const Header = React.memo(
/>
</View>
<HeaderRightMenu
rightButtons={rightButtons}
action={action}
currentScreen={screen}
/>
<HeaderRightMenu rightButtons={rightButtons} action={action} currentScreen={screen} />
</View>
);
},

View File

@@ -1,20 +1,16 @@
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent
} from '../../services/EventManager';
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {eOnNewTopicAdded, eScrollEvent} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import { eOnNewTopicAdded, eScrollEvent } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
export const Title = ({heading, headerColor, screen, notebook}) => {
export const Title = ({ heading, headerColor, screen, notebook }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const [hide, setHide] = useState(screen === 'Notebook' ? true : false);
const onScroll = data => {
@@ -59,7 +55,8 @@ export const Title = ({heading, headerColor, screen, notebook}) => {
opacity: 1,
flexShrink: 1,
flexDirection: 'row'
}}>
}}
>
{!hide ? (
<Heading
onPress={navigateToNotebook}
@@ -68,16 +65,15 @@ export const Title = ({heading, headerColor, screen, notebook}) => {
style={{
flexWrap: 'wrap'
}}
color={headerColor}>
color={headerColor}
>
{notebook ? (
<Paragraph numberOfLines={1} size={SIZE.xs + 1}>
{notebook?.title}
{'\n'}
</Paragraph>
) : null}
<Heading color={colors.accent}>
{heading.slice(0, 1) === '#' ? '#' : null}
</Heading>
<Heading color={colors.accent}>{heading.slice(0, 1) === '#' ? '#' : null}</Heading>
{heading.slice(0, 1) === '#' ? heading.slice(1) : heading}
</Heading>
) : null}

View File

@@ -1,14 +1,11 @@
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import ImageViewer from 'react-native-image-zoom-viewer';
import RNFetchBlob from 'rn-fetch-blob';
import Storage from '../../utils/storage';
import {ActionIcon} from '../ActionIcon';
import { ActionIcon } from '../ActionIcon';
import BaseDialog from '../Dialog/base-dialog';
const {
eSubscribeEvent,
eUnSubscribeEvent
} = require('../../services/EventManager');
const { eSubscribeEvent, eUnSubscribeEvent } = require('../../services/EventManager');
const ImagePreview = () => {
const [visible, setVisible] = useState(false);
@@ -40,7 +37,8 @@ const ImagePreview = () => {
width: '100%',
height: '100%',
backgroundColor: 'black'
}}>
}}
>
<ImageViewer
enableImageZoom={true}
renderIndicator={() => <></>}
@@ -62,7 +60,8 @@ const ImagePreview = () => {
zIndex: 999,
backgroundColor: 'rgba(0,0,0,0.3)',
paddingTop: 30
}}>
}}
>
<ActionIcon
name="close"
color="white"
@@ -78,8 +77,6 @@ const ImagePreview = () => {
}
]}
/>
</View>
</BaseDialog>
)

View File

@@ -1,17 +1,17 @@
import React, {useState} from 'react';
import {TouchableOpacity,TextInput} from 'react-native';
import {View} from 'react-native';
import React, { useState } from 'react';
import { TouchableOpacity, TextInput } from 'react-native';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider/index';
import { useTracked } from '../../provider/index';
import {
ERRORS_LIST,
validateEmail,
validatePass,
validateUsername
} from '../../services/Validation';
import {getElevation} from '../../utils';
import {SIZE} from '../../utils/SizeUtils';
import {ActionIcon} from '../ActionIcon';
import { getElevation } from '../../utils';
import { SIZE } from '../../utils/SizeUtils';
import { ActionIcon } from '../ActionIcon';
import Paragraph from '../Typography/Paragraph';
const Input = ({
@@ -43,7 +43,7 @@ const Input = ({
onFocusInput,
buttons,
marginRight,
autoCorrect=true,
autoCorrect = true,
buttonLeft
}) => {
const [state] = useTracked();
@@ -60,11 +60,7 @@ const Input = ({
// SPECIAL: true,
});
const color = error
? colors.red
: focus
? customColor || colors.accent
: colors.nav;
const color = error ? colors.red : focus ? customColor || colors.accent : colors.nav;
const validate = value => {
if (!validationType) return;
@@ -142,7 +138,7 @@ const Input = ({
flexGrow: 1,
height: height || 50,
paddingHorizontal: 12,
paddingRight:buttons || button || secureTextEntry || error ? 6 : 12
paddingRight: buttons || button || secureTextEntry || error ? 6 : 12
};
const textStyle = {
@@ -153,7 +149,7 @@ const Input = ({
paddingBottom: 2.5,
flexGrow: 1,
height: height || 50,
fontFamily:"OpenSans-Regular"
fontFamily: 'OpenSans-Regular'
};
return (
@@ -165,16 +161,11 @@ const Input = ({
marginBottom: marginBottom,
flexGrow: 1,
maxHeight: height,
marginRight:marginRight
}}>
<TouchableOpacity
disabled={!loading}
onPress={onPress}
activeOpacity={1}
style={style}>
{
buttonLeft && buttonLeft
}
marginRight: marginRight
}}
>
<TouchableOpacity disabled={!loading} onPress={onPress} activeOpacity={1} style={style}>
{buttonLeft && buttonLeft}
<TextInput
ref={fwdRef}
@@ -185,9 +176,7 @@ const Input = ({
onChangeText={onChange}
autoCorrect={autoCorrect}
onBlur={onBlur}
keyboardType={
validationType === 'email' ? 'email-address' : 'default'
}
keyboardType={validationType === 'email' ? 'email-address' : 'default'}
importantForAutofill="yes"
importantForAccessibility="yes"
returnKeyLabel={returnKeyLabel}
@@ -209,7 +198,8 @@ const Input = ({
justifyContent: 'center',
height: 35 > height ? height : 35,
alignItems: 'center'
}}>
}}
>
{secureTextEntry && (
<ActionIcon
name="eye"
@@ -269,18 +259,16 @@ const Input = ({
borderRadius: 2.5,
...getElevation(2),
top: 0
}}>
}}
>
<Paragraph
size={SIZE.xs}
style={{
textAlign: 'right',
textAlignVertical: 'bottom'
}}>
<Icon
name="alert-circle-outline"
size={SIZE.xs}
color={colors.errorText}
/>{' '}
}}
>
<Icon name="alert-circle-outline" size={SIZE.xs} color={colors.errorText} />{' '}
{errorMessage}
</Paragraph>
</View>
@@ -292,22 +280,23 @@ const Input = ({
<View
style={{
paddingTop: 5
}}>
{Object.keys(errorList).filter(k => errorList[k] === true).length !==
0 ? (
}}
>
{Object.keys(errorList).filter(k => errorList[k] === true).length !== 0 ? (
Object.keys(ERRORS_LIST).map(error => (
<View
key={ERRORS_LIST[error]}
style={{
flexDirection: 'row',
alignItems: 'center'
}}>
}}
>
<Icon
name={errorList[error] ? 'close' : 'check'}
color={errorList[error] ? 'red' : 'green'}
/>
<Paragraph style={{marginLeft: 5}} size={SIZE.xs}>
<Paragraph style={{ marginLeft: 5 }} size={SIZE.xs}>
{ERRORS_LIST[error]}
</Paragraph>
</View>

View File

@@ -1,35 +1,29 @@
import React, {useEffect, useState} from 'react';
import {ScrollView, View} from 'react-native';
import React, { useEffect, useState } from 'react';
import { ScrollView, View } from 'react-native';
import BaseDialog from '../../components/Dialog/base-dialog';
import {PressableButton} from '../../components/PressableButton';
import { PressableButton } from '../../components/PressableButton';
import Seperator from '../../components/Seperator';
import {useTracked} from '../../provider';
import {useMessageStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {getElevation} from '../../utils';
import {
eCloseJumpToDialog,
eOpenJumpToDialog,
eScrollEvent
} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import { useTracked } from '../../provider';
import { useMessageStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import { getElevation } from '../../utils';
import { eCloseJumpToDialog, eOpenJumpToDialog, eScrollEvent } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
const offsets = [];
let timeout = null;
const JumpToDialog = ({scrollRef, data, type, screen}) => {
const JumpToDialog = ({ scrollRef, data, type, screen }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const notes = data;
const [visible, setVisible] = useState(false);
const [currentIndex, setCurrentIndex] = useState(null);
const onPress = (item, index) => {
let ind = notes.findIndex(
i => i.title === item.title && i.type === 'header'
);
let ind = notes.findIndex(i => i.title === item.title && i.type === 'header');
console.log(ind);
scrollRef.current?.scrollToIndex({
index: ind,
@@ -80,9 +74,7 @@ const JumpToDialog = ({scrollRef, data, type, screen}) => {
.filter(i => i.type === 'header')
.map((item, index) => {
let offset = 35 * index;
let ind = notes.findIndex(
i => i.title === item.title && i.type === 'header'
);
let ind = notes.findIndex(i => i.title === item.title && i.type === 'header');
let messageState = useMessageStore.getState().message;
let msgOffset = messageState?.visible ? 60 : 10;
ind = ind + 1;
@@ -98,7 +90,8 @@ const JumpToDialog = ({scrollRef, data, type, screen}) => {
loadOffsets();
}}
onRequestClose={close}
visible={true}>
visible={true}
>
<View
style={{
...getElevation(5),
@@ -111,11 +104,13 @@ const JumpToDialog = ({scrollRef, data, type, screen}) => {
alignSelf: 'center',
padding: 10,
paddingTop: 30
}}>
}}
>
<ScrollView
style={{
maxHeight: '100%'
}}>
}}
>
<View
style={{
flexDirection: 'row',
@@ -123,7 +118,8 @@ const JumpToDialog = ({scrollRef, data, type, screen}) => {
alignSelf: 'center',
justifyContent: 'center',
paddingBottom: 20
}}>
}}
>
{notes
.filter(i => i.type === 'header')
.map((item, index) => {
@@ -140,15 +136,15 @@ const JumpToDialog = ({scrollRef, data, type, screen}) => {
borderRadius: 100,
height: 25,
marginVertical: 10
}}>
}}
>
<Paragraph
size={SIZE.sm}
color={
currentIndex === index ? colors.light : colors.accent
}
color={currentIndex === index ? colors.light : colors.accent}
style={{
textAlign: 'center'
}}>
}}
>
{item.title}
</Paragraph>
</PressableButton>

View File

@@ -14,54 +14,55 @@ import {
TRASH_SVG
} from '../../assets/images/assets';
import { useTracked } from '../../provider';
export const Placeholder = ({type, w, h, color}) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const getSVG = () => {
switch (type) {
case 'notes':
return NOTE_SVG(color || colors.accent);
case 'notebooks':
return NOTEBOOK_SVG(colors.accent);
case 'topics':
return TOPIC_SVG(colors.accent);
case 'tags':
return TAG_SVG(colors.accent);
case 'favorites':
return FAV_SVG(colors.accent);
case 'trash':
return TRASH_SVG(colors.accent);
case 'settings':
return SETTINGS_SVG(colors.accent);
case 'search':
return SEARCH_SVG(colors.accent);
case 'login':
return LOGIN_SVG(colors.accent);
case 'signup':
return LOGO_SVG;
}
};
export const Placeholder = ({ type, w, h, color }) => {
const [state, dispatch] = useTracked();
const { colors } = state;
const getSVG = () => {
switch (type) {
case 'notes':
return NOTE_SVG(color || colors.accent);
case 'notebooks':
return NOTEBOOK_SVG(colors.accent);
case 'topics':
return TOPIC_SVG(colors.accent);
case 'tags':
return TAG_SVG(colors.accent);
case 'favorites':
return FAV_SVG(colors.accent);
case 'trash':
return TRASH_SVG(colors.accent);
case 'settings':
return SETTINGS_SVG(colors.accent);
case 'search':
return SEARCH_SVG(colors.accent);
case 'login':
return LOGIN_SVG(colors.accent);
case 'signup':
return LOGO_SVG;
}
};
return (
<SvgToPngView
color={type === 'notes' ? color || colors.accent : colors.accent}
src={getSVG()}
img={type}
width={w}
height={h}
/>
)
}
return (
<SvgToPngView
color={type === 'notes' ? color || colors.accent : colors.accent}
src={getSVG()}
img={type}
width={w}
height={h}
/>
);
};
export const SvgToPngView = ({width, height, src, color, img}) => {
export const SvgToPngView = ({ width, height, src, color, img }) => {
const [error, setError] = useState(false);
return (
<View
style={{
height: width || 250,
width: height || 250,
}}>
width: height || 250
}}
>
<SvgXml xml={src} width="100%" height="100%" />
</View>
);

View File

@@ -1,8 +1,8 @@
import React from 'react';
import {ActivityIndicator, StyleSheet, View} from 'react-native';
import {useTracked} from '../../provider';
import {ph, pv, SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import { useTracked } from '../../provider';
import { ph, pv, SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import Paragraph from '../Typography/Paragraph';
export const Loading = ({
@@ -11,24 +11,22 @@ export const Loading = ({
done = false,
doneText = 'Action completed successfully!',
onDone = () => {},
customStyle = {},
customStyle = {}
}) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
return (
<View
style={[
{height: height, backgroundColor: colors.bg},
{ height: height, backgroundColor: colors.bg },
styles.activityContainer,
customStyle,
]}>
customStyle
]}
>
{done ? (
<>
<Paragraph
color={colors.icon}
size={SIZE.xs}
style={styles.activityText}>
<Paragraph color={colors.icon} size={SIZE.xs} style={styles.activityText}>
{doneText}
</Paragraph>
@@ -40,9 +38,10 @@ export const Loading = ({
<Paragraph
size={SIZE.md}
style={{
marginTop:10
marginTop: 10
}}
color={colors.pri}>
color={colors.pri}
>
{tagline}
</Paragraph>
</>
@@ -55,11 +54,11 @@ const styles = StyleSheet.create({
activityText: {
fontSize: SIZE.sm,
textAlign: 'center',
marginBottom: 10,
marginBottom: 10
},
activityContainer: {
alignItems: 'center',
justifyContent: 'center',
justifyContent: 'center'
},
button: {
paddingVertical: pv,
@@ -71,11 +70,11 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
flexDirection: 'row',
flexDirection: 'row'
},
buttonText: {
//fontFamily: "sans-serif",
color: 'white',
fontSize: SIZE.sm,
},
fontSize: SIZE.sm
}
});

View File

@@ -1,12 +1,12 @@
import React, {useEffect, useRef, useState} from 'react';
import {ScrollView, Text, TouchableOpacity, View} from 'react-native';
import React, { useEffect, useRef, useState } from 'react';
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {Button} from '../../components/Button';
import { Button } from '../../components/Button';
import Seperator from '../../components/Seperator';
import {useTracked} from '../../provider/index';
import {useUserStore} from '../../provider/stores';
import { useTracked } from '../../provider/index';
import { useUserStore } from '../../provider/stores';
import BiometricService from '../../services/BiometricService';
import {DDS} from '../../services/DeviceDetection';
import { DDS } from '../../services/DeviceDetection';
import {
eSendEvent,
eSubscribeEvent,
@@ -14,26 +14,26 @@ import {
presentSheet,
ToastEvent
} from '../../services/EventManager';
import {clearMessage, setEmailVerifyMessage} from '../../services/Message';
import { clearMessage, setEmailVerifyMessage } from '../../services/Message';
import PremiumService from '../../services/PremiumService';
import Sync from '../../services/Sync';
import {hexToRGBA} from '../../utils/ColorUtils';
import {db} from '../../utils/database';
import {eOpenLoginDialog, eOpenResultDialog} from '../../utils/Events';
import {openLinkInBrowser} from '../../utils/functions';
import {MMKV} from '../../utils/mmkv';
import {SIZE} from '../../utils/SizeUtils';
import { hexToRGBA } from '../../utils/ColorUtils';
import { db } from '../../utils/database';
import { eOpenLoginDialog, eOpenResultDialog } from '../../utils/Events';
import { openLinkInBrowser } from '../../utils/functions';
import { MMKV } from '../../utils/mmkv';
import { SIZE } from '../../utils/SizeUtils';
import Storage from '../../utils/storage';
import {sleep} from '../../utils/TimeUtils';
import { sleep } from '../../utils/TimeUtils';
import SheetWrapper from '../Sheet';
import BaseDialog from '../Dialog/base-dialog';
import DialogButtons from '../Dialog/dialog-buttons';
import DialogContainer from '../Dialog/dialog-container';
import DialogHeader from '../Dialog/dialog-header';
import Input from '../Input';
import {Header} from '../SimpleList/header';
import { Header } from '../SimpleList/header';
import Paragraph from '../Typography/Paragraph';
import {ActionIcon} from '../ActionIcon';
import { ActionIcon } from '../ActionIcon';
import umami from '../../utils/umami';
const MODES = {
@@ -145,8 +145,7 @@ const LoginDialog = () => {
buttonFunc: () => changePassword(),
headerParagraph: 'login to your account',
showForgotButton: false,
loading:
'Please wait while we change your password and encrypt your data.',
loading: 'Please wait while we change your password and encrypt your data.',
showLoader: true,
buttonAlt: null
},
@@ -182,8 +181,7 @@ const LoginDialog = () => {
console.log('REQUESTING NEW TOKEN');
let res = await db.user.tokenManager.getToken();
if (!res) throw new Error('no token found');
if (db.user.tokenManager._isTokenExpired(res))
throw new Error('token expired');
if (db.user.tokenManager._isTokenExpired(res)) throw new Error('token expired');
if (!(await Sync.run())) throw new Error('e');
await MMKV.removeItem('loginSessionHasExpired');
return;
@@ -279,8 +277,7 @@ const LoginDialog = () => {
if (error) {
ToastEvent.show({
heading: 'Invalid signup information',
message:
'Some or all information provided is invalid. Resolve all errors and try again.',
message: 'Some or all information provided is invalid. Resolve all errors and try again.',
type: 'error',
context: 'local'
});
@@ -346,10 +343,7 @@ const LoginDialog = () => {
}
try {
let lastRecoveryEmailTime = await MMKV.getItem('lastRecoveryEmailTime');
if (
lastRecoveryEmailTime &&
Date.now() - JSON.parse(lastRecoveryEmailTime) < 60000 * 3
) {
if (lastRecoveryEmailTime && Date.now() - JSON.parse(lastRecoveryEmailTime) < 60000 * 3) {
throw new Error('Please wait before requesting another email');
}
!nostatus && setStatus('Password Recovery Email Sent!');
@@ -435,13 +429,15 @@ const LoginDialog = () => {
}, 500);
}}
background={!DDS.isTab ? colors.bg : null}
transparent={true}>
transparent={true}
>
{confirm && (
<BaseDialog
onRequestClose={() => {
setConfirm(false);
}}
visible>
visible
>
<DialogContainer>
<DialogHeader
title="Logout"
@@ -506,7 +502,8 @@ const LoginDialog = () => {
backgroundColor: colors.bg,
zIndex: 10,
minHeight: DDS.isTab ? '50%' : '85%'
}}>
}}
>
<Header
color="transparent"
type="login"
@@ -526,16 +523,16 @@ const LoginDialog = () => {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: hexToRGBA(colors.red, 0.2)
}}>
}}
>
<Icon
size={20}
style={{marginRight: 10}}
style={{ marginRight: 10 }}
name="information"
color={colors.errorText}
/>
<Paragraph style={{maxWidth: '90%'}} color={colors.errorText}>
Please log in to your account to access your notes on this device
and sync them.
<Paragraph style={{ maxWidth: '90%' }} color={colors.errorText}>
Please log in to your account to access your notes on this device and sync them.
</Paragraph>
</View>
)}
@@ -550,19 +547,13 @@ const LoginDialog = () => {
marginTop: 10,
flexDirection: 'row',
alignItems: 'center'
}}>
<Icon
size={20}
style={{marginRight: 10}}
name="information"
color={colors.accent}
/>
<Paragraph style={{maxWidth: '90%'}} color={colors.accent}>
}}
>
<Icon size={20} style={{ marginRight: 10 }} name="information" color={colors.accent} />
<Paragraph style={{ maxWidth: '90%' }} color={colors.accent}>
When you sign up, your{' '}
<Text style={{fontWeight: 'bold'}}>
14 day free trial of Notesnook Pro
</Text>{' '}
will be activated.
<Text style={{ fontWeight: 'bold' }}>14 day free trial of Notesnook Pro</Text> will be
activated.
</Paragraph>
</View>
)}
@@ -572,7 +563,8 @@ const LoginDialog = () => {
paddingHorizontal: 12,
paddingTop: 12,
width: focused ? '100%' : '99.9%'
}}>
}}
>
{mode === MODES.changePassword ? null : (
<Input
fwdRef={_email}
@@ -710,12 +702,14 @@ const LoginDialog = () => {
flexDirection: 'row',
width: '100%',
alignItems: 'center'
}}>
}}
>
<Paragraph
size={11}
style={{
maxWidth: '90%'
}}>
}}
>
By signing up you agree to our{' '}
<Paragraph
size={11}
@@ -724,7 +718,8 @@ const LoginDialog = () => {
.catch(e => {})
.then(r => {});
}}
color={colors.accent}>
color={colors.accent}
>
terms of service{' '}
</Paragraph>
and{' '}
@@ -735,7 +730,8 @@ const LoginDialog = () => {
.catch(e => {})
.then(r => {});
}}
color={colors.accent}>
color={colors.accent}
>
privacy policy.
</Paragraph>
</Paragraph>
@@ -780,16 +776,17 @@ const LoginDialog = () => {
flexDirection: 'row',
alignItems: 'center',
flexShrink: 1
}}>
}}
>
<ActionIcon name="alert" color={colors.warningText} />
<Paragraph
style={{
flexShrink: 1,
marginLeft: 5
}}
color={colors.warningText}>
Do not close the app or move it to background while we change
your password.
color={colors.warningText}
>
Do not close the app or move it to background while we change your password.
</Paragraph>
</View>
) : null}

View File

@@ -1,19 +1,15 @@
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {useMenuStore, useNoteStore} from '../../provider/stores';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent
} from '../../services/EventManager';
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { useMenuStore, useNoteStore } from '../../provider/stores';
import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {COLORS_NOTE} from '../../utils/Colors';
import {db} from '../../utils/database';
import {refreshNotesPage} from '../../utils/Events';
import {normalize, SIZE} from '../../utils/SizeUtils';
import {presentDialog} from '../Dialog/functions';
import {PressableButton} from '../PressableButton';
import { COLORS_NOTE } from '../../utils/Colors';
import { db } from '../../utils/database';
import { refreshNotesPage } from '../../utils/Events';
import { normalize, SIZE } from '../../utils/SizeUtils';
import { presentDialog } from '../Dialog/functions';
import { PressableButton } from '../PressableButton';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
@@ -28,14 +24,12 @@ export const ColorSection = () => {
}
}, [loading]);
return colorNotes.map((item, index) => (
<ColorItem key={item.id} item={item} index={index} />
));
return colorNotes.map((item, index) => <ColorItem key={item.id} item={item} index={index} />);
};
const ColorItem = ({item, index}) => {
const ColorItem = ({ item, index }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const setColorNotes = useMenuStore(state => state.setColorNotes);
const [headerTextState, setHeaderTextState] = useState(null);
const alias = db.colors.alias(item.id);
@@ -83,17 +77,15 @@ const ColorItem = ({item, index}) => {
if (!value || value.trim().length === 0) return;
await db.colors.rename(item.id, value);
setColorNotes();
console.log('color updated')
console.log('color updated');
},
positiveText:"Rename"
positiveText: 'Rename'
});
};
return (
<PressableButton
customColor={
headerTextState?.id === item.id ? 'rgba(0,0,0,0.04)' : 'transparent'
}
customColor={headerTextState?.id === item.id ? 'rgba(0,0,0,0.04)' : 'transparent'}
onLongPress={onLongPress}
customSelectedColor={COLORS_NOTE[item.title.toLowerCase()]}
customAlpha={!colors.night ? -0.02 : 0.02}
@@ -109,18 +101,21 @@ const ColorItem = ({item, index}) => {
alignItems: 'center',
height: normalize(50),
marginBottom: 5
}}>
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center'
}}>
}}
>
<View
style={{
width: 30,
justifyContent: 'center',
alignItems: 'flex-start'
}}>
}}
>
<View
style={{
width: SIZE.lg - 2,

View File

@@ -1,23 +1,22 @@
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import { useTracked } from '../../provider';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {getElevation} from '../../utils';
import {normalize, SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import {PressableButton} from '../PressableButton';
import { getElevation } from '../../utils';
import { normalize, SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import { PressableButton } from '../PressableButton';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import ToggleSwitch from 'toggle-switch-react-native';
export const MenuListItem = ({item, index, noTextMode, testID, rightBtn}) => {
export const MenuListItem = ({ item, index, noTextMode, testID, rightBtn }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [headerTextState, setHeaderTextState] = useState(null);
let isFocused =
headerTextState?.id === item.name.toLowerCase() + '_navigation';
let isFocused = headerTextState?.id === item.name.toLowerCase() + '_navigation';
const _onPress = event => {
if (item.func) {
@@ -70,12 +69,14 @@ export const MenuListItem = ({item, index, noTextMode, testID, rightBtn}) => {
alignItems: 'center',
height: normalize(50),
marginBottom: 5
}}>
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center'
}}>
}}
>
<Icon
style={{
width: 30,
@@ -83,13 +84,7 @@ export const MenuListItem = ({item, index, noTextMode, testID, rightBtn}) => {
textAlign: 'left'
}}
name={item.icon}
color={
item.icon === 'crown'
? colors.yellow
: isFocused
? colors.accent
: colors.pri
}
color={item.icon === 'crown' ? colors.yellow : isFocused ? colors.accent : colors.pri}
size={SIZE.lg - 2}
/>
{isFocused ? (

View File

@@ -1,21 +1,17 @@
import React, {useEffect, useRef, useState} from 'react';
import {FlatList, View} from 'react-native';
import React, { useEffect, useRef, useState } from 'react';
import { FlatList, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {useMenuStore, useNoteStore} from '../../provider/stores';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent
} from '../../services/EventManager';
import { useTracked } from '../../provider';
import { useMenuStore, useNoteStore } from '../../provider/stores';
import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {db} from '../../utils/database';
import {eOnNewTopicAdded, refreshNotesPage} from '../../utils/Events';
import {normalize, SIZE} from '../../utils/SizeUtils';
import { db } from '../../utils/database';
import { eOnNewTopicAdded, refreshNotesPage } from '../../utils/Events';
import { normalize, SIZE } from '../../utils/SizeUtils';
import SheetWrapper from '../Sheet';
import {Button} from '../Button';
import {ActionSheetEvent} from '../DialogManager/recievers';
import {PressableButton} from '../PressableButton';
import { Button } from '../Button';
import { ActionSheetEvent } from '../DialogManager/recievers';
import { PressableButton } from '../PressableButton';
import Seperator from '../Seperator';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
@@ -60,7 +56,7 @@ export const TagsSection = () => {
type: item.type
});
} else {
params = {...item, menu: true, get: 'topics'};
params = { ...item, menu: true, get: 'topics' };
eSendEvent(refreshNotesPage, params);
Navigation.navigate('NotesPage', params, {
heading: item.title,
@@ -75,7 +71,8 @@ export const TagsSection = () => {
<View
style={{
flexGrow: 1
}}>
}}
>
<FlatList
data={menuPins}
style={{
@@ -85,17 +82,15 @@ export const TagsSection = () => {
flexGrow: 1
}}
keyExtractor={(item, index) => item.id}
renderItem={({item, index}) => (
<PinItem item={item} index={index} onPress={onPress} />
)}
renderItem={({ item, index }) => <PinItem item={item} index={index} onPress={onPress} />}
/>
</View>
);
};
const PinItem = ({item, index, onPress}) => {
const PinItem = ({ item, index, onPress }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const setMenuPins = useMenuStore(state => state.setMenuPins);
const alias = item.type === 'tag' ? db.tags.alias(item.title) : item.title;
const [visible, setVisible] = useState(false);
@@ -133,7 +128,8 @@ const PinItem = ({item, index, onPress}) => {
}}
gestureEnabled={false}
fwdRef={fwdRef}
visible={true}>
visible={true}
>
<Seperator />
<Button
title="Remove Shortcut"
@@ -168,19 +164,22 @@ const PinItem = ({item, index, onPress}) => {
alignItems: 'center',
height: normalize(50),
marginBottom: 5
}}>
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
flexGrow: 1,
flex: 1
}}>
}}
>
<View
style={{
width: 30,
justifyContent: 'center'
}}>
}}
>
<Icon color={color} size={SIZE.lg - 2} name={icons[item.type]} />
<Icon
style={{
@@ -198,14 +197,16 @@ const PinItem = ({item, index, onPress}) => {
alignItems: 'flex-start',
flexGrow: 1,
flex: 1
}}>
}}
>
{headerTextState?.id === item.id ? (
<Heading
style={{
flexWrap: 'wrap'
}}
color={colors.heading}
size={SIZE.md}>
size={SIZE.md}
>
{alias}
</Heading>
) : (

View File

@@ -1,12 +1,11 @@
import React, {useEffect, useState} from 'react';
import {timeSince} from '../../utils/TimeUtils';
import React, { useEffect, useState } from 'react';
import { timeSince } from '../../utils/TimeUtils';
import Paragraph from '../Typography/Paragraph';
export const TimeSince = ({time, style,updateFrequency=30000}) => {
export const TimeSince = ({ time, style, updateFrequency = 30000 }) => {
const [timeAgo, setTimeAgo] = useState(null);
useEffect(() => {
let t = timeSince(time || Date.now());
setTimeAgo(t);
let interval = setInterval(() => {
@@ -17,7 +16,7 @@ export const TimeSince = ({time, style,updateFrequency=30000}) => {
clearInterval(interval);
interval = null;
};
}, [time,updateFrequency]);
}, [time, updateFrequency]);
return <Paragraph style={style}>{timeAgo}</Paragraph>;
};

View File

@@ -1,8 +1,5 @@
import React from 'react';
import {
ActivityIndicator,
Platform, View
} from 'react-native';
import { ActivityIndicator, Platform, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { useTracked } from '../../provider';
@@ -18,7 +15,7 @@ import { TimeSince } from './TimeSince';
export const UserSection = () => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const user = useUserStore(state => state.user);
const syncing = useUserStore(state => state.syncing);
const lastSynced = useUserStore(state => state.lastSynced);
@@ -32,13 +29,15 @@ export const UserSection = () => {
paddingBottom: Platform.OS === 'ios' ? insets.bottom / 2 : null,
borderTopWidth: 1,
borderTopColor: colors.nav
}}>
}}
>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
}}>
}}
>
<PressableButton
onPress={async () => {
if (user) {
@@ -54,18 +53,21 @@ export const UserSection = () => {
padding: 12,
paddingHorizontal: 20,
borderRadius: 0
}}>
}}
>
<View
style={{
flexShrink: 1,
flexGrow: 1
}}>
}}
>
<Heading
style={{
flexWrap: 'wrap'
}}
size={SIZE.xs}
color={colors.icon}>
color={colors.icon}
>
{!user ? (
'You are not logged in'
) : !syncing ? (
@@ -73,7 +75,7 @@ export const UserSection = () => {
<>
Last synced{' '}
<TimeSince
style={{fontSize: SIZE.xs, color: colors.icon}}
style={{ fontSize: SIZE.xs, color: colors.icon }}
time={lastSynced}
/>
</>
@@ -94,10 +96,9 @@ export const UserSection = () => {
style={{
flexWrap: 'wrap'
}}
color={colors.heading}>
{!user
? 'Login to sync your notes.'
: 'Tap here to sync your notes.'}
color={colors.heading}
>
{!user ? 'Login to sync your notes.' : 'Tap here to sync your notes.'}
</Paragraph>
</View>

View File

@@ -1,14 +1,14 @@
import React from 'react';
import {FlatList, View} from 'react-native';
import { FlatList, View } from 'react-native';
import Animated from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
import {useSettingStore, useUserStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {eSendEvent} from '../../services/EventManager';
import {DrawerScale} from '../../utils/Animations';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { Actions } from '../../provider/Actions';
import { useSettingStore, useUserStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { eSendEvent } from '../../services/EventManager';
import { DrawerScale } from '../../utils/Animations';
import {
ACCENT,
COLOR_SCHEME,
@@ -16,26 +16,26 @@ import {
COLOR_SCHEME_LIGHT,
setColorScheme
} from '../../utils/Colors';
import {eOpenPremiumDialog} from '../../utils/Events';
import {MenuItemsList, SUBSCRIPTION_STATUS} from '../../utils/index';
import {MMKV} from '../../utils/mmkv';
import { eOpenPremiumDialog } from '../../utils/Events';
import { MenuItemsList, SUBSCRIPTION_STATUS } from '../../utils/index';
import { MMKV } from '../../utils/mmkv';
import umami from '../../utils/umami';
import {ColorSection} from './ColorSection';
import {MenuListItem} from './MenuListItem';
import {TagsSection} from './TagsSection';
import {UserSection} from './UserSection';
import { ColorSection } from './ColorSection';
import { MenuListItem } from './MenuListItem';
import { TagsSection } from './TagsSection';
import { UserSection } from './UserSection';
export const Menu = React.memo(
() => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const deviceMode = useSettingStore(state => state.deviceMode);
const insets = useSafeAreaInsets();
const user = useUserStore(state => state.user);
const noTextMode = false;
function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
let newColors = setColorScheme(colors, accent);
dispatch({type: Actions.THEME, colors: newColors});
dispatch({ type: Actions.THEME, colors: newColors });
}
const BottomItemsList = [
@@ -44,10 +44,10 @@ export const Menu = React.memo(
icon: 'theme-light-dark',
func: () => {
if (!colors.night) {
MMKV.setStringAsync('theme', JSON.stringify({night: true}));
MMKV.setStringAsync('theme', JSON.stringify({ night: true }));
changeColorScheme(COLOR_SCHEME_DARK);
} else {
MMKV.setStringAsync('theme', JSON.stringify({night: false}));
MMKV.setStringAsync('theme', JSON.stringify({ night: false }));
changeColorScheme(COLOR_SCHEME_LIGHT);
}
},
@@ -66,7 +66,7 @@ export const Menu = React.memo(
name: 'Notesnook Pro',
icon: 'crown',
func: () => {
umami.pageView("/pro-screen","/sidemenu");
umami.pageView('/pro-screen', '/sidemenu');
eSendEvent(eOpenPremiumDialog);
}
};
@@ -77,7 +77,8 @@ export const Menu = React.memo(
height: '100%',
width: '100%',
backgroundColor: colors.nav
}}>
}}
>
<Animated.View
style={{
height: '100%',
@@ -91,7 +92,8 @@ export const Menu = React.memo(
scale: deviceMode !== 'mobile' ? 1 : DrawerScale
}
]
}}>
}}
>
<FlatList
alwaysBounceVertical={false}
contentContainerStyle={{
@@ -108,12 +110,7 @@ export const Menu = React.memo(
renderItem={() => (
<>
{MenuItemsList.map((item, index) => (
<MenuListItem
key={item.name}
item={item}
testID={item.name}
index={index}
/>
<MenuListItem key={item.name} item={item} testID={item.name} index={index} />
))}
<ColorSection noTextMode={noTextMode} />
<TagsSection />
@@ -123,45 +120,34 @@ export const Menu = React.memo(
<View
style={{
paddingHorizontal: 12
}}>
{!user || user?.subscription?.type === SUBSCRIPTION_STATUS.TRIAL ||
}}
>
{!user ||
user?.subscription?.type === SUBSCRIPTION_STATUS.TRIAL ||
user?.subscription?.type === SUBSCRIPTION_STATUS.BASIC ? (
<MenuListItem
testID={pro.name}
key={pro.name}
item={pro}
index={0}
ignore={true}
/>
<MenuListItem testID={pro.name} key={pro.name} item={pro} index={0} ignore={true} />
) : null}
{BottomItemsList.slice(DDS.isLargeTablet() ? 0 : 1, 3).map(
(item, index) => (
<MenuListItem
testID={
item.name == 'Night mode'
? notesnook.ids.menu.nightmode
: item.name
}
key={item.name}
item={item}
index={index}
ignore={true}
rightBtn={
DDS.isLargeTablet() || item.name === 'Notesnook Pro'
? null
: BottomItemsList[0]
}
/>
)
)}
{BottomItemsList.slice(DDS.isLargeTablet() ? 0 : 1, 3).map((item, index) => (
<MenuListItem
testID={item.name == 'Night mode' ? notesnook.ids.menu.nightmode : item.name}
key={item.name}
item={item}
index={index}
ignore={true}
rightBtn={
DDS.isLargeTablet() || item.name === 'Notesnook Pro' ? null : BottomItemsList[0]
}
/>
))}
</View>
<View
style={{
width: '100%',
paddingHorizontal: 0
}}>
}}
>
<UserSection noTextMode={noTextMode} />
</View>
</Animated.View>

View File

@@ -1,36 +1,29 @@
import KeepAwake from '@sayem314/react-native-keep-awake';
import {EV, EVENTS} from 'notes-core/common';
import React, {createRef, useEffect, useState} from 'react';
import {Modal, SafeAreaView, Text, View} from 'react-native';
import { EV, EVENTS } from 'notes-core/common';
import React, { createRef, useEffect, useState } from 'react';
import { Modal, Platform, SafeAreaView, Text, View } from 'react-native';
import Animated from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import WebView from 'react-native-webview';
import {useTracked} from '../../provider';
import {DDS} from '../../services/DeviceDetection';
import { useTracked } from '../../provider';
import { DDS } from '../../services/DeviceDetection';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent
eUnSubscribeEvent,
ToastEvent
} from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import Sync from '../../services/Sync';
import {dHeight} from '../../utils';
import {db} from '../../utils/database';
import {
eApplyChanges,
eShowMergeDialog,
refreshNotesPage
} from '../../utils/Events';
import {openLinkInBrowser} from '../../utils/functions';
import {normalize, SIZE} from '../../utils/SizeUtils';
import {timeConverter} from '../../utils/TimeUtils';
import {
getNote,
sourceUri,
updateNoteInEditor
} from '../../views/Editor/Functions';
import {ActionIcon} from '../ActionIcon';
import {Button} from '../Button';
import { dHeight } from '../../utils';
import { db } from '../../utils/database';
import { eApplyChanges, eShowMergeDialog, refreshNotesPage } from '../../utils/Events';
import { openLinkInBrowser } from '../../utils/functions';
import { normalize, SIZE } from '../../utils/SizeUtils';
import { timeConverter } from '../../utils/TimeUtils';
import { getNote, sourceUri, updateNoteInEditor } from '../../views/Editor/Functions';
import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
import BaseDialog from '../Dialog/base-dialog';
import DialogButtons from '../Dialog/dialog-buttons';
import DialogContainer from '../Dialog/dialog-container';
@@ -44,7 +37,7 @@ let note = null;
let primaryData = null;
let secondaryData = null;
function onMediaLoaded({hash, src}) {
function onMediaLoaded({ hash, src }) {
console.log('on media download complete');
let inject = `
(function(){
@@ -58,7 +51,7 @@ function onMediaLoaded({hash, src}) {
const MergeEditor = () => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [visible, setVisible] = useState(false);
const [primary, setPrimary] = useState(true);
const [secondary, setSecondary] = useState(true);
@@ -70,12 +63,9 @@ const MergeEditor = () => {
const insets = useSafeAreaInsets();
const onPrimaryWebViewLoad = async () => {
let content = await db.content.insertPlaceholders(
primaryData,
'placeholder.svg'
);
let content = await db.content.insertPlaceholders(primaryData, 'placeholder.svg');
postMessage(primaryWebView, 'htmldiff', content.data);
let theme = {...colors};
let theme = { ...colors };
theme.factor = normalize(1);
primaryWebView.current?.injectJavaScript(`
@@ -93,12 +83,9 @@ const MergeEditor = () => {
const onSecondaryWebViewLoad = async () => {
if (!secondaryData) return;
let content = await db.content.insertPlaceholders(
secondaryData,
'placeholder.svg'
);
let content = await db.content.insertPlaceholders(secondaryData, 'placeholder.svg');
postMessage(secondaryWebView, 'htmldiff', content?.data);
let theme = {...colors};
let theme = { ...colors };
theme.factor = normalize(1);
secondaryWebView.current?.injectJavaScript(`
(function() {
@@ -143,11 +130,7 @@ const MergeEditor = () => {
const applyChanges = async () => {
let content = keepContentFrom === 'primary' ? primaryData : secondaryData;
let keepCopy =
copyToSave === 'primary'
? primaryData
: copyToSave === 'secondary'
? secondaryData
: null;
copyToSave === 'primary' ? primaryData : copyToSave === 'secondary' ? secondaryData : null;
await db.notes.add({
id: note.id,
@@ -255,8 +238,6 @@ const MergeEditor = () => {
setDialogVisible(false);
primaryData = null;
secondaryData = null;
primaryText = null;
secondaryText = null;
note = null;
};
@@ -289,12 +270,14 @@ const MergeEditor = () => {
'landscape-left',
'landscape-right'
]}
visible={true}>
visible={true}
>
<SafeAreaView
style={{
backgroundColor: colors.bg,
paddingTop: insets.top
}}>
}}
>
<KeepAwake />
{dialogVisible && (
<BaseDialog visible={true}>
@@ -320,7 +303,8 @@ const MergeEditor = () => {
height: '100%',
width: '100%',
backgroundColor: DDS.isLargeTablet() ? 'rgba(0,0,0,0.3)' : null
}}>
}}
>
<View
style={{
width: '100%',
@@ -330,26 +314,19 @@ const MergeEditor = () => {
alignItems: 'center',
paddingHorizontal: 12,
paddingLeft: 6
}}>
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
flexShrink: 1
}}>
<ActionIcon
onPress={close}
color={colors.pri}
name="arrow-left"
/>
<Paragraph
style={{flexWrap: 'wrap'}}
color={colors.icon}
size={SIZE.xs}>
<Text style={{color: colors.accent, fontWeight: 'bold'}}>
(This Device)
</Text>
}}
>
<ActionIcon onPress={close} color={colors.pri} name="arrow-left" />
<Paragraph style={{ flexWrap: 'wrap' }} color={colors.icon} size={SIZE.xs}>
<Text style={{ color: colors.accent, fontWeight: 'bold' }}>(This Device)</Text>
{'\n'}
{timeConverter(primaryData?.dateEdited)}
</Paragraph>
@@ -360,7 +337,8 @@ const MergeEditor = () => {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end'
}}>
}}
>
{keepContentFrom === 'secondary' ? (
<Button
onPress={onPressSaveCopyFromPrimaryWebView}
@@ -374,7 +352,7 @@ const MergeEditor = () => {
fontSize={SIZE.xs}
/>
) : null}
<View style={{width: 10}} />
<View style={{ width: 10 }} />
{keepContentFrom === 'secondary' ? (
<Button
title="Discard"
@@ -431,7 +409,8 @@ const MergeEditor = () => {
backgroundColor: colors.bg,
borderBottomWidth: 1,
borderBottomColor: colors.nav
}}>
}}
>
<WebView
onLoad={onPrimaryWebViewLoad}
ref={primaryWebView}
@@ -467,21 +446,18 @@ const MergeEditor = () => {
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 12
}}>
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
flexShrink: 1
}}>
<Paragraph
style={{flexWrap: 'wrap'}}
color={colors.icon}
size={SIZE.xs}>
<Text style={{color: 'red', fontWeight: 'bold'}}>
(Incoming)
</Text>
}}
>
<Paragraph style={{ flexWrap: 'wrap' }} color={colors.icon} size={SIZE.xs}>
<Text style={{ color: 'red', fontWeight: 'bold' }}>(Incoming)</Text>
{'\n'}
{timeConverter(secondaryData?.dateEdited)}
</Paragraph>
@@ -492,7 +468,8 @@ const MergeEditor = () => {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end'
}}>
}}
>
{keepContentFrom === 'primary' ? (
<Button
height={30}
@@ -507,7 +484,7 @@ const MergeEditor = () => {
title="Save a copy"
/>
) : null}
<View style={{width: 10}} />
<View style={{ width: 10 }} />
{keepContentFrom === 'primary' ? (
<Button
title="Discard"
@@ -563,7 +540,8 @@ const MergeEditor = () => {
height: dHeight / 2 - (50 + insets.top / 2),
backgroundColor: colors.bg,
borderRadius: 10
}}>
}}
>
<WebView
onLoad={onSecondaryWebViewLoad}
ref={secondaryWebView}

View File

@@ -1,15 +1,11 @@
import React, {createRef, useEffect, useState} from 'react';
import {Keyboard, TextInput, TouchableOpacity, View} from 'react-native';
import {FlatList} from 'react-native-gesture-handler';
import React, { createRef, useEffect, useState } from 'react';
import { Keyboard, TextInput, TouchableOpacity, View } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
import {
useNotebookStore,
useSelectionStore,
useSettingStore
} from '../../provider/stores';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { Actions } from '../../provider/Actions';
import { useNotebookStore, useSelectionStore, useSettingStore } from '../../provider/stores';
import {
eSubscribeEvent,
eUnSubscribeEvent,
@@ -17,20 +13,20 @@ import {
ToastEvent
} from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {getTotalNotes, InteractionManager} from '../../utils';
import {db} from '../../utils/database';
import {eOpenMoveNoteDialog} from '../../utils/Events';
import {pv, SIZE} from '../../utils/SizeUtils';
import { getTotalNotes, InteractionManager } from '../../utils';
import { db } from '../../utils/database';
import { eOpenMoveNoteDialog } from '../../utils/Events';
import { pv, SIZE } from '../../utils/SizeUtils';
import SheetWrapper from '../Sheet';
import {Button} from '../Button';
import { Button } from '../Button';
import DialogHeader from '../Dialog/dialog-header';
import {PressableButton} from '../PressableButton';
import { PressableButton } from '../PressableButton';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import Input from '../Input';
import {ActionIcon} from '../ActionIcon';
import {Dialog} from '../Dialog';
import {presentDialog} from '../Dialog/functions';
import { ActionIcon } from '../ActionIcon';
import { Dialog } from '../Dialog';
import { presentDialog } from '../Dialog/functions';
import layoutmanager from '../../utils/layout-manager';
let newNotebookTitle = null;
@@ -85,13 +81,11 @@ const MoveNoteDialog = () => {
export default MoveNoteDialog;
const MoveNoteComponent = ({close, note, setNote}) => {
const MoveNoteComponent = ({ close, note, setNote }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const nbs = useNotebookStore(state =>
state.notebooks.filter(n => n?.type === 'notebook')
);
const nbs = useNotebookStore(state => state.notebooks.filter(n => n?.type === 'notebook'));
let notebooks = [...db.notebooks.all];
const selectedItemsList = useSelectionStore(state => state.selectedItemsList);
@@ -140,13 +134,10 @@ const MoveNoteComponent = ({close, note, setNote}) => {
const handlePress = async (item, index) => {
if (note && item.notes.indexOf(note.id) > -1) {
await db.notebooks
.notebook(item.notebookId)
.topics.topic(item.id)
.delete(note.id);
await db.notebooks.notebook(item.notebookId).topics.topic(item.id).delete(note.id);
if (note && note.id) {
setNote({...db.notes.note(note.id).data});
setNote({ ...db.notes.note(note.id).data });
requestAnimationFrame(() => {
//layoutmanager.withSpringAnimation(500);
Navigation.setRoutesToUpdate([
@@ -173,7 +164,7 @@ const MoveNoteComponent = ({close, note, setNote}) => {
...noteIds
);
if (note && note.id) {
setNote({...db.notes.note(note.id).data});
setNote({ ...db.notes.note(note.id).data });
requestAnimationFrame(() => {
//layoutmanager.withSpringAnimation(500);
Navigation.setRoutesToUpdate([
@@ -240,7 +231,8 @@ const MoveNoteComponent = ({close, note, setNote}) => {
paddingHorizontal: 12,
flexDirection: 'row',
justifyContent: 'space-between'
}}>
}}
>
<DialogHeader
title="Add to notebook"
paragraph={`Add your notes to notebooks to find them easily.`}
@@ -273,7 +265,8 @@ const MoveNoteComponent = ({close, note, setNote}) => {
style={{
width: '100%',
marginTop: 10
}}>
}}
>
<Input
fwdRef={notebookInput}
onChangeText={value => {
@@ -290,7 +283,7 @@ const MoveNoteComponent = ({close, note, setNote}) => {
button={{
icon: 'check',
color: notebookInputFocused ? colors.accent : colors.icon,
onPress:addNewNotebook
onPress: addNewNotebook
}}
onSubmit={addNewNotebook}
placeholder="Create a new notebook"
@@ -300,7 +293,7 @@ const MoveNoteComponent = ({close, note, setNote}) => {
style={{
paddingHorizontal: 12
}}
renderItem={({item, index}) => (
renderItem={({ item, index }) => (
<View
style={{
borderWidth: 1,
@@ -308,7 +301,8 @@ const MoveNoteComponent = ({close, note, setNote}) => {
borderRadius: 6,
overflow: 'hidden',
marginBottom: 10
}}>
}}
>
<PressableButton
onPress={() => {
if (!item.topics || item.topics.length === 0) {
@@ -326,7 +320,8 @@ const MoveNoteComponent = ({close, note, setNote}) => {
width: '100%',
borderRadius: 5,
alignItems: 'flex-start'
}}>
}}
>
<View
style={{
width: '100%',
@@ -335,13 +330,13 @@ const MoveNoteComponent = ({close, note, setNote}) => {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 12
}}>
}}
>
<View>
<Heading
color={
noteExists.indexOf(item.id) > -1 ? colors.accent : null
}
size={SIZE.md}>
color={noteExists.indexOf(item.id) > -1 ? colors.accent : null}
size={SIZE.md}
>
{item.title}
</Heading>
{item.topics?.length > 0 ? (
@@ -391,7 +386,7 @@ const MoveNoteComponent = ({close, note, setNote}) => {
alignSelf: 'flex-end',
maxHeight: 500
}}
renderItem={({item, index}) => (
renderItem={({ item, index }) => (
<PressableButton
onPress={() => handlePress(item, index)}
type="gray"
@@ -405,11 +400,10 @@ const MoveNoteComponent = ({close, note, setNote}) => {
flexDirection: 'row',
paddingHorizontal: 12,
justifyContent: 'space-between'
}}>
}}
>
<View>
<Paragraph color={colors.heading}>
{item.title}
</Paragraph>
<Paragraph color={colors.heading}>{item.title}</Paragraph>
<Paragraph color={colors.icon} size={SIZE.xs}>
{item.notes.length + ' notes'}
</Paragraph>

View File

@@ -1,25 +1,25 @@
import React, {useCallback, useEffect, useState} from 'react';
import {Text, View} from 'react-native';
import {FlatList} from 'react-native-gesture-handler';
import React, { useCallback, useEffect, useState } from 'react';
import { Text, View } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {presentSheet} from '../../services/EventManager';
import {db} from '../../utils/database';
import { useTracked } from '../../provider';
import { presentSheet } from '../../services/EventManager';
import { db } from '../../utils/database';
import { openLinkInBrowser } from '../../utils/functions';
import {SIZE} from '../../utils/SizeUtils';
import {timeConverter, timeSince} from '../../utils/TimeUtils';
import { SIZE } from '../../utils/SizeUtils';
import { timeConverter, timeSince } from '../../utils/TimeUtils';
import DialogHeader from '../Dialog/dialog-header';
import GeneralSheet from '../GeneralSheet';
import {PressableButton} from '../PressableButton';
import { PressableButton } from '../PressableButton';
import Seperator from '../Seperator';
import Paragraph from '../Typography/Paragraph';
import NotePreview from './preview';
export default function NoteHistory({note, ref}) {
export default function NoteHistory({ note, ref }) {
const [history, setHistory] = useState([]);
const [loading, setLoading] = useState(true);
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
useEffect(() => {
(async () => {
@@ -41,7 +41,7 @@ export default function NoteHistory({note, ref}) {
content={content}
/>
),
context: 'note_history',
context: 'note_history'
});
}
@@ -58,7 +58,7 @@ export default function NoteHistory({note, ref}) {
};
const renderItem = useCallback(
({item, index}) => (
({ item, index }) => (
<PressableButton
type="grayBg"
onPress={() => preview(item)}
@@ -69,7 +69,8 @@ export default function NoteHistory({note, ref}) {
height: 45,
marginBottom: 10,
flexDirection: 'row'
}}>
}}
>
<Paragraph>{getDate(item.dateCreated, item.dateModified)}</Paragraph>
<Paragraph color={colors.icon} size={SIZE.xs}>
{timeSince(item.dateModified)}
@@ -106,11 +107,10 @@ export default function NoteHistory({note, ref}) {
justifyContent: 'center',
alignItems: 'center',
height: 200
}}>
}}
>
<Icon name="history" size={60} color={colors.icon} />
<Paragraph color={colors.icon}>
No note history found on this device.
</Paragraph>
<Paragraph color={colors.icon}>No note history found on this device.</Paragraph>
</View>
}
renderItem={renderItem}
@@ -120,13 +120,15 @@ export default function NoteHistory({note, ref}) {
color={colors.icon}
style={{
alignSelf: 'center'
}}>
Note version history is local only.{' '}
<Text
onPress={() => {
openLinkInBrowser("https://docs.notesnook.com/versionhistory",colors);
}}
style={{color: colors.accent, textDecorationLine: 'underline'}}>
>
Note version history is local only.{' '}
<Text
onPress={() => {
openLinkInBrowser('https://docs.notesnook.com/versionhistory', colors);
}}
style={{ color: colors.accent, textDecorationLine: 'underline' }}
>
Learn how this works.
</Text>
</Paragraph>

View File

@@ -1,33 +1,30 @@
import React, {useRef} from 'react';
import {Alert, Platform, View} from 'react-native';
import React, { useRef } from 'react';
import { Alert, Platform, View } from 'react-native';
import WebView from 'react-native-webview';
import {useTracked} from '../../provider';
import {useEditorStore} from '../../provider/stores';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import { useTracked } from '../../provider';
import { useEditorStore } from '../../provider/stores';
import { eSendEvent, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {db} from '../../utils/database';
import {eCloseProgressDialog, eOnLoadNote} from '../../utils/Events';
import {openLinkInBrowser} from '../../utils/functions';
import {normalize} from '../../utils/SizeUtils';
import {getNote, sourceUri} from '../../views/Editor/Functions';
import { db } from '../../utils/database';
import { eCloseProgressDialog, eOnLoadNote } from '../../utils/Events';
import { openLinkInBrowser } from '../../utils/functions';
import { normalize } from '../../utils/SizeUtils';
import { getNote, sourceUri } from '../../views/Editor/Functions';
import tiny from '../../views/Editor/tiny/tiny';
import {ActionIcon} from '../ActionIcon';
import {Button} from '../Button';
import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
import DialogHeader from '../Dialog/dialog-header';
import Paragraph from '../Typography/Paragraph';
export default function NotePreview({session, content}) {
export default function NotePreview({ session, content }) {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const webviewRef = useRef();
const onLoad = async () => {
let preview = await db.content.insertPlaceholders(
content,
'placeholder.svg'
);
let preview = await db.content.insertPlaceholders(content, 'placeholder.svg');
let theme = {...colors};
let theme = { ...colors };
theme.factor = normalize(1);
webviewRef.current?.injectJavaScript(`
@@ -77,7 +74,7 @@ export default function NotePreview({session, content}) {
await db.noteHistory.restore(session.id);
if (useEditorStore.getState()?.currentEditingNote === session?.noteId) {
if (getNote()) {
eSendEvent(eOnLoadNote, {...getNote(), forced: true});
eSendEvent(eOnLoadNote, { ...getNote(), forced: true });
}
}
eSendEvent(eCloseProgressDialog, 'note_history');
@@ -99,7 +96,8 @@ export default function NotePreview({session, content}) {
style={{
height: session.locked ? null : 600,
width: '100%'
}}>
}}
>
<DialogHeader padding={12} title={session.session} />
{!session.locked ? (
<WebView
@@ -138,23 +136,18 @@ export default function NotePreview({session, content}) {
height: 100,
justifyContent: 'center',
alignItems: 'center'
}}>
<Paragraph color={colors.icon}>
Preview not available, content is encrypted.
</Paragraph>
}}
>
<Paragraph color={colors.icon}>Preview not available, content is encrypted.</Paragraph>
</View>
)}
<View
style={{
paddingHorizontal: 12
}}>
<Button
onPress={restore}
title="Restore this version"
type="accent"
width="100%"
/>
}}
>
<Button onPress={restore} title="Restore this version" type="accent" width="100%" />
</View>
</View>
);

View File

@@ -1,27 +1,27 @@
import {decode, EntityLevel} from 'entities';
import React, {useEffect} from 'react';
import {Platform, View} from 'react-native';
import { decode, EntityLevel } from 'entities';
import React, { useEffect } from 'react';
import { Platform, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider';
import {useSettingStore, useTagStore} from '../../provider/stores';
import {eSendEvent} from '../../services/EventManager';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { useSettingStore, useTagStore } from '../../provider/stores';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {COLORS_NOTE} from '../../utils/Colors';
import {db} from '../../utils/database';
import {refreshNotesPage} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {ActionIcon} from '../ActionIcon';
import {Button} from '../Button';
import {ActionSheetEvent} from '../DialogManager/recievers';
import {TimeSince} from '../Menu/TimeSince';
import {Properties} from '../Properties';
import { COLORS_NOTE } from '../../utils/Colors';
import { db } from '../../utils/database';
import { refreshNotesPage } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
import { ActionSheetEvent } from '../DialogManager/recievers';
import { TimeSince } from '../Menu/TimeSince';
import { Properties } from '../Properties';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
const navigateToTopic = topic => {
let routeName = 'NotesPage';
let params = {...topic, menu: false, get: 'topics'};
let params = { ...topic, menu: false, get: 'topics' };
let headerState = {
heading: topic.title,
id: topic.id,
@@ -52,15 +52,9 @@ const showActionSheet = item => {
Properties.present(item);
};
const NoteItem = ({
item,
isTrash,
tags,
dateBy = 'dateCreated',
noOpen = false
}) => {
const NoteItem = ({ item, isTrash, tags, dateBy = 'dateCreated', noOpen = false }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const settings = useSettingStore(state => state.settings);
const compactMode = settings.notesListMode === 'compact';
const attachmentCount = db.attachments?.ofNote(item.id, 'all')?.length || 0;
@@ -68,7 +62,7 @@ const NoteItem = ({
function getNotebook() {
if (isTrash || !item.notebooks || item.notebooks.length < 1) return [];
let item_notebook = item.notebooks?.slice(0, 1)[0];
notebook = db.notebooks.notebook(item_notebook.id);
let notebook = db.notebooks.notebook(item_notebook.id);
if (!notebook) return [];
let topic = notebook.topics.topic(item_notebook.topics[0])?._topic;
@@ -92,7 +86,8 @@ const NoteItem = ({
style={{
flexGrow: 1,
flexShrink: 1
}}>
}}
>
{!compactMode ? (
<View
style={{
@@ -101,7 +96,8 @@ const NoteItem = ({
zIndex: 10,
elevation: 10,
marginBottom: 2.5
}}>
}}
>
{getNotebook().map(_item => (
<Button
title={_item.title}
@@ -133,7 +129,8 @@ const NoteItem = ({
style={{
flexWrap: 'wrap'
}}
size={SIZE.md}>
size={SIZE.md}
>
{item.title}
</Heading>
@@ -142,7 +139,8 @@ const NoteItem = ({
style={{
flexWrap: 'wrap'
}}
numberOfLines={2}>
numberOfLines={2}
>
{decode(item.headline, {
level: EntityLevel.HTML
})}
@@ -157,7 +155,8 @@ const NoteItem = ({
width: '100%',
marginTop: 5,
height: SIZE.md + 2
}}>
}}
>
{!isTrash ? (
<>
{item.conflicted ? (
@@ -177,9 +176,7 @@ const NoteItem = ({
marginRight: 6
}}
time={item[dateBy]}
updateFrequency={
Date.now() - item[dateBy] < 60000 ? 2000 : 60000
}
updateFrequency={Date.now() - item[dateBy] < 60000 ? 2000 : 60000}
/>
{attachmentCount > 0 ? (
@@ -188,7 +185,8 @@ const NoteItem = ({
flexDirection: 'row',
alignItems: 'center',
marginRight: 6
}}>
}}
>
<Icon name="attachment" size={SIZE.md} color={colors.icon} />
<Paragraph color={colors.icon} size={SIZE.xs}>
{attachmentCount}
@@ -204,9 +202,7 @@ const NoteItem = ({
style={{
marginRight: 6
}}
color={
COLORS_NOTE[item.color?.toLowerCase()] || colors.accent
}
color={COLORS_NOTE[item.color?.toLowerCase()] || colors.accent}
/>
) : null}
@@ -244,7 +240,7 @@ const NoteItem = ({
textStyle={{
textDecorationLine: 'underline'
}}
hitSlop={{top: 8, bottom: 12, left: 0, right: 0}}
hitSlop={{ top: 8, bottom: 12, left: 0, right: 0 }}
fontSize={SIZE.xs}
style={{
borderRadius: 5,
@@ -266,7 +262,8 @@ const NoteItem = ({
size={SIZE.xs}
style={{
marginRight: 6
}}>
}}
>
Deleted on{' '}
{item && item.dateDeleted
? new Date(item.dateDeleted).toISOString().slice(0, 10)
@@ -278,7 +275,8 @@ const NoteItem = ({
size={SIZE.xs}
style={{
marginRight: 6
}}>
}}
>
{item.itemType[0].toUpperCase() + item.itemType.slice(1)}
</Paragraph>
</>

View File

@@ -1,19 +1,19 @@
import React from 'react';
import NoteItem from '.';
import {notesnook} from '../../../e2e/test.ids';
import {useSelectionStore, useTrashStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {eSendEvent, openVault, ToastEvent} from '../../services/EventManager';
import { notesnook } from '../../../e2e/test.ids';
import { useSelectionStore, useTrashStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { eSendEvent, openVault, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {history} from '../../utils';
import {db} from '../../utils/database';
import {eOnLoadNote, eShowMergeDialog} from '../../utils/Events';
import {tabBarRef} from '../../utils/Refs';
import {presentDialog} from '../Dialog/functions';
import { history } from '../../utils';
import { db } from '../../utils/database';
import { eOnLoadNote, eShowMergeDialog } from '../../utils/Events';
import { tabBarRef } from '../../utils/Refs';
import { presentDialog } from '../Dialog/functions';
import SelectionWrapper from '../SelectionWrapper';
export const NoteWrapper = React.memo(
({item, index, tags, compactMode, dateBy}) => {
({ item, index, tags, dateBy }) => {
const isTrash = item.type === 'trash';
const setSelectedItem = useSelectionStore(state => state.setSelectedItem);
const onPress = async () => {
@@ -92,13 +92,14 @@ export const NoteWrapper = React.memo(
height={100}
testID={notesnook.ids.note.get(index)}
onPress={onPress}
item={item}>
item={item}
>
<NoteItem item={item} dateBy={dateBy} tags={tags} isTrash={isTrash} />
</SelectionWrapper>
);
},
(prev, next) => {
if (prev.dateBy !== next.dateBy ) {
if (prev.dateBy !== next.dateBy) {
return false;
}
if (prev.item?.dateEdited !== next.item?.dateEdited) {

View File

@@ -1,30 +1,24 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider';
import {useSettingStore} from '../../provider/stores';
import {eSendEvent} from '../../services/EventManager';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { useSettingStore } from '../../provider/stores';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {getTotalNotes, history} from '../../utils';
import {refreshNotesPage} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {ActionIcon} from '../ActionIcon';
import {Button} from '../Button';
import {ActionSheetEvent} from '../DialogManager/recievers';
import { getTotalNotes, history } from '../../utils';
import { refreshNotesPage } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
import { ActionSheetEvent } from '../DialogManager/recievers';
import { Properties } from '../Properties';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
export const NotebookItem = ({
item,
isTopic = false,
notebookID,
isTrash,
dateBy
}) => {
export const NotebookItem = ({ item, isTopic = false, notebookID, isTrash, dateBy }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const settings = useSettingStore(state => state.settings);
const compactMode = settings.notebooksListMode === 'compact';
const topics = item.topics?.slice(0, 3) || [];
@@ -36,7 +30,7 @@ export const NotebookItem = ({
const navigateToTopic = topic => {
if (history.selectedItemsList.length > 0) return;
let routeName = 'NotesPage';
let params = {...topic, menu: false, get: 'topics'};
let params = { ...topic, menu: false, get: 'topics' };
let headerState = {
heading: topic.title,
id: topic.id,
@@ -52,13 +46,15 @@ export const NotebookItem = ({
style={{
flexGrow: 1,
flexShrink: 1
}}>
}}
>
<Heading
size={SIZE.md}
numberOfLines={1}
style={{
flexWrap: 'wrap'
}}>
}}
>
{item.title}
</Heading>
{isTopic || !item.description || compactMode ? null : (
@@ -67,7 +63,8 @@ export const NotebookItem = ({
numberOfLines={2}
style={{
flexWrap: 'wrap'
}}>
}}
>
{item.description}
</Paragraph>
)}
@@ -78,7 +75,8 @@ export const NotebookItem = ({
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap'
}}>
}}
>
{topics.map(topic => (
<Button
title={topic.title}
@@ -86,14 +84,12 @@ export const NotebookItem = ({
height={null}
textStyle={{
fontWeight: 'normal',
fontFamily: null
fontFamily: null,
marginRight: 0
}}
type="grayBg"
fontSize={SIZE.xs}
icon="bookmark-outline"
textStyle={{
marginRight: 0
}}
iconSize={SIZE.sm}
style={{
borderRadius: 5,
@@ -118,13 +114,15 @@ export const NotebookItem = ({
alignItems: 'center',
marginTop: 5,
height: SIZE.md + 2
}}>
}}
>
<Paragraph
color={colors.accent}
size={SIZE.xs}
style={{
marginRight: 6
}}>
}}
>
{isTopic ? 'Topic' : 'Notebook'}
</Paragraph>
@@ -136,9 +134,9 @@ export const NotebookItem = ({
style={{
textAlignVertical: 'center',
marginRight: 6
}}>
{'Deleted on ' +
new Date(item.dateDeleted).toISOString().slice(0, 10)}
}}
>
{'Deleted on ' + new Date(item.dateDeleted).toISOString().slice(0, 10)}
</Paragraph>
<Paragraph
color={colors.accent}
@@ -146,7 +144,8 @@ export const NotebookItem = ({
style={{
textAlignVertical: 'center',
marginRight: 6
}}>
}}
>
{item.itemType[0].toUpperCase() + item.itemType.slice(1)}
</Paragraph>
</>
@@ -156,7 +155,8 @@ export const NotebookItem = ({
size={SIZE.xs}
style={{
marginRight: 6
}}>
}}
>
{new Date(item[dateBy]).toDateString().substring(4)}
</Paragraph>
)}
@@ -165,7 +165,8 @@ export const NotebookItem = ({
size={SIZE.xs}
style={{
marginRight: 6
}}>
}}
>
{item && totalNotes > 1
? totalNotes + ' notes'
: totalNotes === 1
@@ -175,7 +176,6 @@ export const NotebookItem = ({
{item.pinned ? (
<Icon
style={{marginRight: 6}}
name="pin-outline"
size={SIZE.sm}
style={{

View File

@@ -1,14 +1,14 @@
import React from 'react';
import {NotebookItem} from '.';
import {useSelectionStore} from '../../provider/stores';
import {eSendEvent} from '../../services/EventManager';
import { NotebookItem } from '.';
import { useSelectionStore } from '../../provider/stores';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {history} from '../../utils';
import {eOnNewTopicAdded, refreshNotesPage} from '../../utils/Events';
import { history } from '../../utils';
import { eOnNewTopicAdded, refreshNotesPage } from '../../utils/Events';
import SelectionWrapper from '../SelectionWrapper';
export const NotebookWrapper = React.memo(
({item, index,dateBy}) => {
({ item, index, dateBy }) => {
const isTrash = item.type === 'trash';
const setSelectedItem = useSelectionStore(state => state.setSelectedItem);
@@ -23,7 +23,7 @@ export const NotebookWrapper = React.memo(
let params =
item.type === 'topic'
? {...item, menu: false}
? { ...item, menu: false }
: {
menu: false,
notebook: item,
@@ -47,7 +47,8 @@ export const NotebookWrapper = React.memo(
index={index}
onPress={onPress}
height={item.type === 'topic' ? 80 : 110}
item={item}>
item={item}
>
<NotebookItem
isTopic={item.type === 'topic'}
item={item}
@@ -59,7 +60,7 @@ export const NotebookWrapper = React.memo(
);
},
(prev, next) => {
if (prev.dateBy !== next.dateBy ) {
if (prev.dateBy !== next.dateBy) {
return false;
}

View File

@@ -1,68 +1,68 @@
import React from 'react';
import {ScrollView} from 'react-native';
import {useTracked} from '../../provider';
import {FeatureBlock} from './feature';
import { ScrollView } from 'react-native';
import { FeatureBlock } from './feature';
export const CompactFeatures = ({vertical,features = [],maxHeight=500,scrollRef}) => {
const [state, dispatch] = useTracked();
const {colors} = state;
let data = vertical ? features : [
{
highlight: 'Everything',
content: 'in basic',
icon: 'emoticon-wink'
},
{
highlight: 'Unlimited',
content: 'notebooks',
icon: 'notebook'
},
{
highlight: 'File & image',
content: 'attachments',
icon: 'attachment'
},
{
highlight: 'Instant',
content: 'syncing',
icon: 'sync'
},
{
highlight: 'Private',
content: 'vault',
icon: 'shield'
},
{
highlight: 'Rich text',
content: 'editing',
icon: 'square-edit-outline'
},
{
highlight: 'PDF & markdown',
content: 'exports',
icon: 'file'
},
{
highlight: 'Encrypted',
content: 'backups',
icon: 'backup-restore'
}
]
export const CompactFeatures = ({ vertical, features = [], maxHeight = 500, scrollRef }) => {
let data = vertical
? features
: [
{
highlight: 'Everything',
content: 'in basic',
icon: 'emoticon-wink'
},
{
highlight: 'Unlimited',
content: 'notebooks',
icon: 'notebook'
},
{
highlight: 'File & image',
content: 'attachments',
icon: 'attachment'
},
{
highlight: 'Instant',
content: 'syncing',
icon: 'sync'
},
{
highlight: 'Private',
content: 'vault',
icon: 'shield'
},
{
highlight: 'Rich text',
content: 'editing',
icon: 'square-edit-outline'
},
{
highlight: 'PDF & markdown',
content: 'exports',
icon: 'file'
},
{
highlight: 'Encrypted',
content: 'backups',
icon: 'backup-restore'
}
];
return (
<ScrollView
horizontal={!vertical}
nestedScrollEnabled
onMomentumScrollEnd={() => {
scrollRef?.current?.handleChildScrollEnd();
}}
nestedScrollEnabled
onMomentumScrollEnd={() => {
scrollRef?.current?.handleChildScrollEnd();
}}
showsHorizontalScrollIndicator={false}
style={{
width: '100%',
maxHeight:maxHeight
}}>
maxHeight: maxHeight
}}
>
{data.map(item => (
<FeatureBlock vertical={vertical} {...item} />
<FeatureBlock key={item.highlight} vertical={vertical} {...item} />
))}
</ScrollView>
);

View File

@@ -1,27 +1,27 @@
import React, {useState} from 'react';
import {ScrollView, View} from 'react-native';
import {LAUNCH_ROCKET} from '../../assets/images/assets';
import {useTracked} from '../../provider';
import {useUserStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {eSendEvent, presentSheet} from '../../services/EventManager';
import {getElevation} from '../../utils';
import {eOpenLoginDialog} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import React, { useState } from 'react';
import { ScrollView, View } from 'react-native';
import { LAUNCH_ROCKET } from '../../assets/images/assets';
import { useTracked } from '../../provider';
import { useUserStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { eSendEvent, presentSheet } from '../../services/EventManager';
import { getElevation } from '../../utils';
import { eOpenLoginDialog } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import umami from '../../utils/umami';
import {ActionIcon} from '../ActionIcon';
import {Button} from '../Button';
import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
import GeneralSheet from '../GeneralSheet';
import {SvgToPngView} from '../ListPlaceholders';
import { SvgToPngView } from '../ListPlaceholders';
import Seperator from '../Seperator';
import {Toast} from '../Toast';
import { Toast } from '../Toast';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {features} from './features';
import {Group} from './group';
import {PricingPlans} from './pricing-plans';
import { features } from './features';
import { Group } from './group';
import { PricingPlans } from './pricing-plans';
export const Component = ({close, promo, getRef}) => {
export const Component = ({ close, promo, getRef }) => {
const [state, dispatch] = useTracked();
const colors = state.colors;
const user = useUserStore(state => state.user);
@@ -63,7 +63,8 @@ export const Component = ({close, promo, getRef}) => {
justifyContent: 'space-between',
borderRadius: 10,
maxHeight: '100%'
}}>
}}
>
<GeneralSheet context="pricing_plans" />
<ActionIcon
onPress={() => {
@@ -87,7 +88,8 @@ export const Component = ({close, promo, getRef}) => {
}}
keyboardDismissMode="none"
keyboardShouldPersistTaps="always"
onScroll={onScroll}>
onScroll={onScroll}
>
<View
key="top-banner"
style={{
@@ -95,12 +97,9 @@ export const Component = ({close, promo, getRef}) => {
alignItems: 'center',
height: 400,
justifyContent: 'center'
}}>
<SvgToPngView
width={350}
height={350}
src={LAUNCH_ROCKET(colors.accent)}
/>
}}
>
<SvgToPngView width={350} height={350} src={LAUNCH_ROCKET(colors.accent)} />
</View>
<Heading
@@ -109,7 +108,8 @@ export const Component = ({close, promo, getRef}) => {
style={{
alignSelf: 'center',
paddingTop: 20
}}>
}}
>
Notesnook{' '}
<Heading size={SIZE.lg} color={colors.accent}>
Pro
@@ -124,16 +124,15 @@ export const Component = ({close, promo, getRef}) => {
alignSelf: 'center',
paddingBottom: 20,
width: '90%'
}}>
}}
>
Ready to take the next step on your private note taking journey?
</Paragraph>
<Button
key="calltoaction"
onPress={onPress}
title={
promo ? promo.text : user ? `See all plans` : 'Try free for 14 days'
}
title={promo ? promo.text : user ? `See all plans` : 'Try free for 14 days'}
type="accent"
style={{
paddingHorizontal: 24,
@@ -151,7 +150,8 @@ export const Component = ({close, promo, getRef}) => {
key="plans"
style={{
paddingHorizontal: 12
}}>
}}
>
<PricingPlans promo={promo} />
</View>
</ScrollView>
@@ -159,9 +159,7 @@ export const Component = ({close, promo, getRef}) => {
{floatingButton ? (
<Button
onPress={onPress}
title={
promo ? promo.text : user ? `See all plans` : 'Try free for 14 days'
}
title={promo ? promo.text : user ? `See all plans` : 'Try free for 14 days'}
type="accent"
style={{
paddingHorizontal: 24,

View File

@@ -1,17 +1,9 @@
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent
} from '../../services/EventManager';
import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import PremiumService from '../../services/PremiumService';
import {
eOpenPremiumDialog,
eOpenResultDialog,
eOpenTrialEndingDialog
} from '../../utils/Events';
import { eOpenPremiumDialog, eOpenResultDialog, eOpenTrialEndingDialog } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import { Button } from '../Button';
@@ -25,17 +17,19 @@ import { Offer } from './offer';
export const Expiring = () => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [visible, setVisible] = useState(false);
const [status, setStatus] = useState({
title: 'Your trial is ending soon',
offer: null,
extend: true
});
const promo = status.offer ? {
promoCode:"com.streetwriters.notesnook.sub.yr.trialoffer",
text:"GET 30% OFF on yearly"
}: null
const promo = status.offer
? {
promoCode: 'com.streetwriters.notesnook.sub.yr.trialoffer',
text: 'GET 30% OFF on yearly'
}
: null;
useEffect(() => {
eSubscribeEvent(eOpenTrialEndingDialog, open);
@@ -54,24 +48,28 @@ export const Expiring = () => {
<BaseDialog
onRequestClose={() => {
setVisible(false);
}}>
}}
>
<DialogContainer>
<View
style={{
width: '100%',
alignItems: 'center'
}}>
}}
>
<View
style={{
paddingHorizontal: 12,
width: '100%'
}}>
}}
>
<Heading
textBreakStrategy="balanced"
style={{
textAlign: 'center',
paddingTop: 18
}}>
}}
>
{status.title}
</Heading>
<Seperator />
@@ -79,7 +77,8 @@ export const Expiring = () => {
style={{
width: '100%',
alignItems: 'center'
}}>
}}
>
{status.offer ? (
<>
<Offer padding={20} off={status.offer} />
@@ -93,14 +92,14 @@ export const Expiring = () => {
paddingTop: 0,
paddingBottom: 20
}}
size={SIZE.md + 2}>
Upgrade now to continue using all the pro features after
your trial ends
size={SIZE.md + 2}
>
Upgrade now to continue using all the pro features after your trial ends
</Paragraph>
</>
)}
<CompactFeatures/>
<CompactFeatures />
<Paragraph
onPress={async () => {
@@ -113,7 +112,8 @@ export const Expiring = () => {
textDecorationLine: 'underline',
color: colors.icon,
marginTop: 10
}}>
}}
>
See what's included in Basic & Pro plans
</Paragraph>
@@ -127,14 +127,15 @@ export const Expiring = () => {
width: '100%',
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10
}}>
}}
>
<Button
type="transparent"
title="Subscribe now"
onPress={async () => {
setVisible(false);
await sleep(300);
PremiumService.sheet(null,promo)
PremiumService.sheet(null, promo);
}}
fontSize={SIZE.md + 2}
style={{

View File

@@ -1,23 +1,14 @@
import React from 'react';
import {Text, View} from 'react-native';
import {color} from 'react-native-reanimated';
import { Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import Seperator from '../Seperator';
import { useTracked } from '../../provider';
import { SIZE } from '../../utils/SizeUtils';
import Paragraph from '../Typography/Paragraph';
import {ProTag} from './pro-tag';
import { ProTag } from './pro-tag';
export const FeatureBlock = ({
vertical,
highlight,
content,
icon,
pro,
proTagBg
}) => {
const [state, dispatch] = useTracked();
const {colors} = state;
export const FeatureBlock = ({ vertical, highlight, content, icon, pro, proTagBg }) => {
const [state] = useTracked();
const { colors } = state;
return vertical ? (
<View
@@ -25,8 +16,9 @@ export const FeatureBlock = ({
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 12,
marginBottom: 10,
}}>
marginBottom: 10
}}
>
<Icon color={colors.accent} name="check" size={SIZE.lg} />
<Paragraph
@@ -35,7 +27,8 @@ export const FeatureBlock = ({
marginLeft: 5,
flexShrink: 1
}}
size={SIZE.md}>
size={SIZE.md}
>
{content}
</Paragraph>
</View>
@@ -48,17 +41,18 @@ export const FeatureBlock = ({
marginRight: 10,
borderRadius: 5,
minWidth: 100
}}>
}}
>
<Icon color={colors.icon} name={icon} size={SIZE.xl} />
<Paragraph size={SIZE.md}>
<Text style={{color: colors.accent}}>{highlight}</Text>
<Text style={{ color: colors.accent }}>{highlight}</Text>
{'\n'}
{content}
</Paragraph>
{pro ? (
<>
<View style={{height: 5}} />
<View style={{ height: 5 }} />
<ProTag width={50} size={SIZE.xs} background={proTagBg} />
</>
) : (

View File

@@ -39,8 +39,7 @@ export const features = [
},
{
title: 'Attach files & images',
detail:
'Add your documents, PDFs, images and videos, and keep them safe and organized.',
detail: 'Add your documents, PDFs, images and videos, and keep them safe and organized.',
pro: true,
features: [
{
@@ -78,8 +77,7 @@ export const features = [
},
{
title: 'Organize yourself in the best way',
detail:
'We offer multiple ways to keep you organized. The only limit is your imagination.',
detail: 'We offer multiple ways to keep you organized. The only limit is your imagination.',
features: [
{
highlight: 'Unlimited',
@@ -208,8 +206,7 @@ export const features = [
},
{
title: 'Personalize & make Notesnook your own',
detail:
'Change app themes to match your style. Custom themes are coming soon.',
detail: 'Change app themes to match your style. Custom themes are coming soon.',
pro: true,
features: [
{

View File

@@ -1,13 +1,13 @@
import React from 'react';
import {ScrollView, View} from 'react-native';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import { ScrollView, View } from 'react-native';
import { useTracked } from '../../provider';
import { SIZE } from '../../utils/SizeUtils';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {FeatureBlock} from './feature';
import {ProTag} from './pro-tag';
import { FeatureBlock } from './feature';
import { ProTag } from './pro-tag';
export const Group = ({item, index}) => {
export const Group = ({ item, index }) => {
const [state] = useTracked();
const colors = state.colors;
@@ -15,15 +15,12 @@ export const Group = ({item, index}) => {
<View
style={{
paddingHorizontal: 12,
paddingVertical: 8,
backgroundColor: index % 2 !== 0 ? colors.bg : colors.nav,
paddingVertical: 40
}}>
}}
>
{item?.pro ? (
<ProTag
size={SIZE.sm}
background={index % 2 === 0 ? colors.bg : colors.nav}
/>
<ProTag size={SIZE.sm} background={index % 2 === 0 ? colors.bg : colors.nav} />
) : null}
<Heading>{item.title}</Heading>
<Paragraph size={SIZE.md}>{item.detail}</Paragraph>
@@ -34,9 +31,11 @@ export const Group = ({item, index}) => {
marginTop: 20
}}
horizontal
showsHorizontalScrollIndicator={false}>
showsHorizontalScrollIndicator={false}
>
{item.features?.map(item => (
<FeatureBlock
key={item.detail}
{...item}
detail={item.detail}
pro={item.pro}
@@ -51,7 +50,8 @@ export const Group = ({item, index}) => {
marginTop: 10
}}
size={SIZE.xs}
color={colors.icon}>
color={colors.icon}
>
{item.info}
</Paragraph>
) : null}

View File

@@ -1,8 +1,8 @@
import React, {createRef} from 'react';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {eClosePremiumDialog, eOpenPremiumDialog} from '../../utils/Events';
import React, { createRef } from 'react';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import { eClosePremiumDialog, eOpenPremiumDialog } from '../../utils/Events';
import BaseDialog from '../Dialog/base-dialog';
import {Component} from './component';
import { Component } from './component';
class PremiumDialog extends React.Component {
constructor(props) {
@@ -46,15 +46,8 @@ class PremiumDialog extends React.Component {
render() {
return !this.state.visible ? null : (
<BaseDialog
bounce
background={this.props.colors.bg}
onRequestClose={this.onClose}>
<Component
getRef={() => this.actionSheetRef}
promo={this.state.promo}
close={this.close}
/>
<BaseDialog bounce background={this.props.colors.bg} onRequestClose={this.onClose}>
<Component getRef={() => this.actionSheetRef} promo={this.state.promo} close={this.close} />
</BaseDialog>
);
}

View File

@@ -1,16 +1,12 @@
import React from 'react';
import {Text} from 'react-native';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import { Text } from 'react-native';
import { useTracked } from '../../provider';
import { SIZE } from '../../utils/SizeUtils';
import Paragraph from '../Typography/Paragraph';
export const Offer = ({
off = '30',
text = 'on yearly plan, offer ends soon',
padding = 0
}) => {
export const Offer = ({ off = '30', text = 'on yearly plan, offer ends soon', padding = 0 }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
return (
<Paragraph
@@ -18,9 +14,10 @@ export const Offer = ({
textAlign: 'center',
paddingVertical: padding
}}
size={SIZE.xxxl}>
size={SIZE.xxxl}
>
GET {off}
<Text style={{color: colors.accent}}>%</Text> OFF!{'\n'}
<Text style={{ color: colors.accent }}>%</Text> OFF!{'\n'}
<Paragraph color={colors.icon}>{text}</Paragraph>
</Paragraph>
);

View File

@@ -1,24 +1,16 @@
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import Animated, {Easing} from 'react-native-reanimated';
import {useTracked} from '../../provider';
import {DDS} from '../../services/DeviceDetection';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent
} from '../../services/EventManager';
import {dWidth, editing, getElevation} from '../../utils';
import {
eCloseActionSheet,
eOpenPremiumDialog,
eShowGetPremium
} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import {EditorWebView} from '../../views/Editor/Functions';
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import Animated, { Easing } from 'react-native-reanimated';
import { useTracked } from '../../provider';
import { DDS } from '../../services/DeviceDetection';
import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import { dWidth, editing, getElevation } from '../../utils';
import { eCloseActionSheet, eOpenPremiumDialog, eShowGetPremium } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import { EditorWebView } from '../../views/Editor/Functions';
import tiny from '../../views/Editor/tiny/tiny';
import {Button} from '../Button';
import { Button } from '../Button';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
@@ -29,9 +21,9 @@ let currentMsg = {
title: '',
desc: ''
};
export const PremiumToast = ({close, context = 'global', offset = 0}) => {
export const PremiumToast = ({ close, context = 'global', offset = 0 }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [msg, setMsg] = useState(currentMsg);
const open = event => {
@@ -130,19 +122,22 @@ export const PremiumToast = ({close, context = 'global', offset = 0}) => {
translateY: translatePrem
}
]
}}>
}}
>
<View
style={{
flexShrink: 1,
flexGrow: 1,
paddingRight: 6
}}>
}}
>
<Heading
style={{
flexWrap: 'wrap'
}}
color={colors.accent}
size={SIZE.md}>
size={SIZE.md}
>
{msg.title}
</Heading>
@@ -151,7 +146,8 @@ export const PremiumToast = ({close, context = 'global', offset = 0}) => {
flexWrap: 'wrap'
}}
size={SIZE.sm}
color={colors.pri}>
color={colors.pri}
>
{msg.desc}
</Paragraph>
</View>

View File

@@ -1,13 +1,13 @@
import React from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { getElevation } from '../../utils';
import {SIZE} from '../../utils/SizeUtils';
import {PressableButton} from '../PressableButton';
import { SIZE } from '../../utils/SizeUtils';
import { PressableButton } from '../PressableButton';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
export const PricingItem = ({product, onPress, compact}) => {
export const PricingItem = ({ product, onPress, compact }) => {
const [state, dispatch] = useTracked();
const colors = state.colors;
@@ -22,27 +22,22 @@ export const PricingItem = ({product, onPress, compact}) => {
paddingHorizontal: 12,
paddingVertical: compact ? 15 : 10,
width: compact ? null : '100%',
minWidth: 150,
}}>
minWidth: 150
}}
>
{!compact && (
<View>
<Heading size={SIZE.lg - 2}>
{product?.type === 'yearly' || product?.offerType === 'yearly'
? 'Yearly'
: 'Monthly'}
{product?.type === 'yearly' || product?.offerType === 'yearly' ? 'Yearly' : 'Monthly'}
</Heading>
{product?.info && (
<Paragraph size={SIZE.xs}>{product.info}</Paragraph>
)}
{product?.info && <Paragraph size={SIZE.xs}>{product.info}</Paragraph>}
</View>
)}
<View>
<Paragraph size={SIZE.sm}>
<Heading size={SIZE.lg - 2}>{product?.data?.localizedPrice}/</Heading>
{product?.type === 'yearly' || product?.offerType === 'yearly'
? '/year'
: '/month'}
{product?.type === 'yearly' || product?.offerType === 'yearly' ? '/year' : '/month'}
</Paragraph>
</View>
</PressableButton>

View File

@@ -1,32 +1,28 @@
import React, {useEffect, useState} from 'react';
import {ActivityIndicator, Platform, Text, View} from 'react-native';
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, Platform, Text, View } from 'react-native';
import * as RNIap from 'react-native-iap';
import {useTracked} from '../../provider';
import {useUserStore} from '../../provider/stores';
import {
eSendEvent,
presentSheet,
ToastEvent
} from '../../services/EventManager';
import { useTracked } from '../../provider';
import { useUserStore } from '../../provider/stores';
import { eSendEvent, presentSheet, ToastEvent } from '../../services/EventManager';
import PremiumService from '../../services/PremiumService';
import {db} from '../../utils/database';
import { db } from '../../utils/database';
import {
eClosePremiumDialog,
eCloseProgressDialog,
eCloseSimpleDialog,
eOpenLoginDialog
} from '../../utils/Events';
import {openLinkInBrowser} from '../../utils/functions';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import { openLinkInBrowser } from '../../utils/functions';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import umami from '../../utils/umami';
import {Button} from '../Button';
import {Dialog} from '../Dialog';
import { Button } from '../Button';
import { Dialog } from '../Dialog';
import BaseDialog from '../Dialog/base-dialog';
import {presentDialog} from '../Dialog/functions';
import { presentDialog } from '../Dialog/functions';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {PricingItem} from './pricing-item';
import { PricingItem } from './pricing-item';
const promoCyclesMonthly = {
1: 'first month',
@@ -40,12 +36,7 @@ const promoCyclesYearly = {
3: 'first 3 years'
};
export const PricingPlans = ({
promo,
marginTop,
heading = true,
compact = false
}) => {
export const PricingPlans = ({ promo, marginTop, heading = true, compact = false }) => {
const [state, dispatch] = useTracked();
const colors = state.colors;
const user = useUserStore(state => state.user);
@@ -61,12 +52,8 @@ export const PricingPlans = ({
let products = await PremiumService.getProducts();
if (products.length > 0) {
let offers = {
monthly: products.find(
p => p.productId === 'com.streetwriters.notesnook.sub.mo'
),
yearly: products.find(
p => p.productId === 'com.streetwriters.notesnook.sub.yr'
)
monthly: products.find(p => p.productId === 'com.streetwriters.notesnook.sub.mo'),
yearly: products.find(p => p.productId === 'com.streetwriters.notesnook.sub.yr')
};
setOffers(offers);
@@ -98,12 +85,10 @@ export const PricingPlans = ({
let isMonthly = product.productId.indexOf('.mo') > -1;
let cycleText = isMonthly
? promoCyclesMonthly[
product.introductoryPriceCyclesAndroid ||
product.introductoryPriceNumberOfPeriodsIOS
product.introductoryPriceCyclesAndroid || product.introductoryPriceNumberOfPeriodsIOS
]
: promoCyclesYearly[
product.introductoryPriceCyclesAndroid ||
product.introductoryPriceNumberOfPeriodsIOS
product.introductoryPriceCyclesAndroid || product.introductoryPriceNumberOfPeriodsIOS
];
setProduct({
@@ -132,18 +117,8 @@ export const PricingPlans = ({
setBuying(false);
return;
}
umami.pageView(
'/iap-native',
`${compact ? 'pro-sheet' : 'pro-screen'}/pro-plans`
);
await RNIap.requestSubscription(
product?.productId,
false,
null,
null,
null,
user.id
);
umami.pageView('/iap-native', `${compact ? 'pro-sheet' : 'pro-screen'}/pro-plans`);
await RNIap.requestSubscription(product?.productId, false, null, null, null, user.id);
setBuying(false);
eSendEvent(eCloseProgressDialog);
eSendEvent(eClosePremiumDialog);
@@ -170,14 +145,16 @@ export const PricingPlans = ({
justifyContent: 'center',
alignItems: 'center',
height: 100
}}>
}}
>
<ActivityIndicator color={colors.accent} size={25} />
</View>
) : (
<View
style={{
paddingHorizontal: 12
}}>
}}
>
{buying ? (
<BaseDialog statusBarTranslucent centered>
<ActivityIndicator size={50} color="white" />
@@ -190,14 +167,16 @@ export const PricingPlans = ({
alignSelf: 'center',
textAlign: 'center'
}}
size={SIZE.lg - 4}>
size={SIZE.lg - 4}
>
{product.data.introductoryPrice}
<Paragraph
style={{
textDecorationLine: 'line-through',
color: colors.icon
}}
size={SIZE.sm}>
size={SIZE.sm}
>
({product.data.localizedPrice})
</Paragraph>{' '}
for {product.cycleText}
@@ -212,7 +191,8 @@ export const PricingPlans = ({
alignSelf: 'center',
marginTop: marginTop || 20,
marginBottom: 20
}}>
}}
>
Choose a plan
</Heading>
) : null}
@@ -222,7 +202,8 @@ export const PricingPlans = ({
flexDirection: !compact ? 'column' : 'row',
flexWrap: 'wrap',
justifyContent: 'space-around'
}}>
}}
>
<PricingItem
onPress={() => buySubscription(offers?.monthly)}
compact={compact}
@@ -271,8 +252,7 @@ export const PricingPlans = ({
eSendEvent(eCloseSimpleDialog);
setBuying(true);
try {
if (!(await getPromo(value)))
throw new Error('Error applying promo code');
if (!(await getPromo(value))) throw new Error('Error applying promo code');
ToastEvent.show({
heading: 'Discount applied!',
type: 'success',
@@ -333,12 +313,14 @@ export const PricingPlans = ({
alignSelf: 'center',
justifyContent: 'center',
textAlign: 'center'
}}>
}}
>
Use promo code{' '}
<Text
style={{
fontFamily: 'OpenSans-SemiBold'
}}>
}}
>
{promo.promoCode}
</Text>{' '}
at checkout
@@ -380,14 +362,13 @@ export const PricingPlans = ({
alignSelf: 'center',
textAlign: 'center',
marginTop: 10
}}>
Upon signing up, your 14 day free trial of Notesnook Pro will be
activated automatically.{' '}
<Paragraph size={SIZE.xs} style={{fontWeight: 'bold'}}>
}}
>
Upon signing up, your 14 day free trial of Notesnook Pro will be activated automatically.{' '}
<Paragraph size={SIZE.xs} style={{ fontWeight: 'bold' }}>
No credit card information is required.
</Paragraph>{' '}
Once the free trial period ends, your account will be downgraded to
basic free account.{' '}
Once the free trial period ends, your account will be downgraded to basic free account.{' '}
<Paragraph
size={SIZE.xs}
onPress={() => {
@@ -398,9 +379,9 @@ export const PricingPlans = ({
});
}}
color={colors.accent}
style={{fontWeight: 'bold', textDecorationLine: 'underline'}}>
Visit our website to learn what is included in the basic free
account.
style={{ fontWeight: 'bold', textDecorationLine: 'underline' }}
>
Visit our website to learn what is included in the basic free account.
</Paragraph>
</Paragraph>
) : null}
@@ -416,10 +397,11 @@ export const PricingPlans = ({
alignSelf: 'center',
marginTop: 10,
textAlign: 'center'
}}>
By subscribing, you will be charged to your iTunes Account for the
selected plan. Subscriptions will automatically renew unless
cancelled within 24-hours before the end of the current period.
}}
>
By subscribing, you will be charged to your iTunes Account for the selected plan.
Subscriptions will automatically renew unless cancelled within 24-hours before the end
of the current period.
</Paragraph>
) : (
<Paragraph
@@ -429,24 +411,26 @@ export const PricingPlans = ({
alignSelf: 'center',
marginTop: 10,
textAlign: 'center'
}}>
By subscribing, your will be charged on your Google Account, and
your subscription will automatically renew until you cancel prior
to the end of the then current period.
}}
>
By subscribing, your will be charged on your Google Account, and your subscription
will automatically renew until you cancel prior to the end of the then current period.
</Paragraph>
)}
<View
style={{
width: '100%'
}}>
}}
>
<Paragraph
size={SIZE.xs}
color={colors.icon}
style={{
maxWidth: '100%',
textAlign: 'center'
}}>
}}
>
By subscribing, you agree to our{' '}
<Paragraph
size={SIZE.xs}
@@ -460,7 +444,8 @@ export const PricingPlans = ({
style={{
textDecorationLine: 'underline'
}}
color={colors.accent}>
color={colors.accent}
>
Terms of Service{' '}
</Paragraph>
and{' '}
@@ -476,7 +461,8 @@ export const PricingPlans = ({
style={{
textDecorationLine: 'underline'
}}
color={colors.accent}>
color={colors.accent}
>
Privacy Policy.
</Paragraph>
</Paragraph>

View File

@@ -1,10 +1,10 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import { useTracked } from '../../provider';
import Paragraph from '../Typography/Paragraph';
export const ProTag = ({width, size, background}) => {
export const ProTag = ({ width, size, background }) => {
const [state] = useTracked();
const colors = state.colors;
@@ -13,12 +13,13 @@ export const ProTag = ({width, size, background}) => {
style={{
backgroundColor: background || colors.bg,
borderRadius: 100,
width:width || 60,
width: width || 60,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 2.5,
flexDirection: 'row'
}}>
}}
>
<Icon
style={{
marginRight: 3

View File

@@ -32,25 +32,31 @@ export const PressableButton = ({
customOpacity
}) => {
const [state] = useTracked();
const {colors} = state;
const selectedColor = customSelectedColor ||
const { colors } = state;
const selectedColor =
customSelectedColor ||
colors[
type === 'accent'
? BUTTON_TYPES[type](accentColor, accentText).selected
: BUTTON_TYPES[type].selected
];
const primaryColor = customColor ||
const primaryColor =
customColor ||
colors[
type === 'accent'
? BUTTON_TYPES[type](accentColor, accentText).primary
: BUTTON_TYPES[type].primary
];
const opacity = customOpacity ? customOpacity : type === 'accent' ? 1 : BUTTON_TYPES[type].opacity;
const alpha = customAlpha? customAlpha : colors.night ? 0.04 : -0.04;
const opacity = customOpacity
? customOpacity
: type === 'accent'
? 1
: BUTTON_TYPES[type].opacity;
const alpha = customAlpha ? customAlpha : colors.night ? 0.04 : -0.04;
const getStyle = useCallback(
({pressed}) => [
({ pressed }) => [
{
backgroundColor: pressed
? RGB_Linear_Shade(alpha, hexToRGBA(selectedColor, opacity || 1))
@@ -60,11 +66,11 @@ export const PressableButton = ({
borderRadius: noborder ? 0 : br,
justifyContent: 'center',
alignItems: 'center',
marginBottom: 0,
marginBottom: 0
},
customStyle,
customStyle
],
[customStyle, noborder, type,colors],
[customStyle, noborder, type, colors]
);
return (
@@ -74,7 +80,8 @@ export const PressableButton = ({
hitSlop={hitSlop}
onPress={onPress}
onLongPress={onLongPress}
style={getStyle}>
style={getStyle}
>
{children}
</Pressable>
);

View File

@@ -1,20 +1,20 @@
import React, {useState} from 'react';
import {View} from 'react-native';
import React, { useState } from 'react';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
import {useMenuStore, useSettingStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {eSendEvent} from '../../services/EventManager';
import { notesnook } from '../../../e2e/test.ids';
import { useMenuStore, useSettingStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {dWidth} from '../../utils';
import {COLORS_NOTE} from '../../utils/Colors';
import {db} from '../../utils/database';
import {refreshNotesPage} from '../../utils/Events';
import { dWidth } from '../../utils';
import { COLORS_NOTE } from '../../utils/Colors';
import { db } from '../../utils/database';
import { refreshNotesPage } from '../../utils/Events';
import layoutmanager from '../../utils/layout-manager';
import {SIZE} from '../../utils/SizeUtils';
import {PressableButton} from '../PressableButton';
import { SIZE } from '../../utils/SizeUtils';
import { PressableButton } from '../PressableButton';
export const ColorTags = ({item, close}) => {
export const ColorTags = ({ item, close }) => {
const [note, setNote] = useState(item);
const setColorNotes = useMenuStore(state => state.setColorNotes);
const dimensions = useSettingStore(state => state.dimensions);
@@ -27,7 +27,7 @@ export const ColorTags = ({item, close}) => {
await db.notes.note(note.id).color(color.name);
}
let _note = db.notes.note(note.id).data;
setNote({..._note});
setNote({ ..._note });
setColorNotes();
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
@@ -56,7 +56,8 @@ export const ColorTags = ({item, close}) => {
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center'
}}>
}}
>
{note.color?.toLowerCase() === color.name ? (
<Icon name="check" color="white" size={SIZE.lg} />
) : null}
@@ -75,7 +76,8 @@ export const ColorTags = ({item, close}) => {
marginTop: 20,
alignItems: 'center',
justifyContent: 'space-between'
}}>
}}
>
{Object.keys(COLORS_NOTE).map(_renderColor)}
</View>
);

View File

@@ -1,13 +1,13 @@
import React from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { SIZE } from '../../utils/SizeUtils';
import { timeConverter } from '../../utils/TimeUtils';
import Paragraph from '../Typography/Paragraph';
export const DateMeta = ({item}) => {
export const DateMeta = ({ item }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const getNameFromKey = key => {
switch (key) {
@@ -30,7 +30,8 @@ export const DateMeta = ({item}) => {
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: 3
}}>
}}
>
<Paragraph size={SIZE.xs} color={colors.icon}>
{getNameFromKey(key)}
</Paragraph>
@@ -48,7 +49,8 @@ export const DateMeta = ({item}) => {
borderTopWidth: 1,
borderTopColor: colors.nav,
paddingHorizontal: 12
}}>
}}
>
{Object.keys(item).map(renderItem)}
</View>
);

View File

@@ -7,7 +7,7 @@ import { db } from '../../utils/database';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
export const DevMode = ({item}) => {
export const DevMode = ({ item }) => {
const settings = useSettingStore(state => state.settings);
return settings.devMode ? (
@@ -16,7 +16,8 @@ export const DevMode = ({item}) => {
width: '100%',
paddingHorizontal: 12,
marginTop: 10
}}>
}}
>
<Button
onPress={async () => {
let additionalData = {};
@@ -28,7 +29,7 @@ export const DevMode = ({item}) => {
}
}
additionalData.lastSynced = await db.lastSynced();
let _note = {...item};
let _note = { ...item };
_note.additionalData = additionalData;
Clipboard.setString(db.debug.strip(_note));

View File

@@ -1,24 +1,24 @@
import React from 'react';
import {ScrollView, View} from 'react-native';
import {useTracked} from '../../provider';
import {DDS} from '../../services/DeviceDetection';
import {presentSheet} from '../../services/EventManager';
import {db} from '../../utils/database';
import {SIZE} from '../../utils/SizeUtils';
import { Platform, ScrollView, View } from 'react-native';
import { useTracked } from '../../provider';
import { DDS } from '../../services/DeviceDetection';
import { presentSheet } from '../../services/EventManager';
import { db } from '../../utils/database';
import { SIZE } from '../../utils/SizeUtils';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {ColorTags} from './color-tags';
import {DateMeta} from './date-meta';
import {DevMode} from './dev-mode';
import {Items} from './items';
import { ColorTags } from './color-tags';
import { DateMeta } from './date-meta';
import { DevMode } from './dev-mode';
import { Items } from './items';
import Notebooks from './notebooks';
import {Synced} from './synced';
import {Tags} from './tags';
import {Topics} from './topics';
import { Synced } from './synced';
import { Tags } from './tags';
import { Topics } from './topics';
export const Properties = ({close = () => {}, item, buttons = [], getRef}) => {
export const Properties = ({ close = () => {}, item, buttons = [], getRef }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const alias = item
? item.type === 'tag'
@@ -43,9 +43,10 @@ export const Properties = ({close = () => {}, item, buttons = [], getRef}) => {
paddingHorizontal: 0,
borderBottomRightRadius: DDS.isLargeTablet() ? 10 : 1,
borderBottomLeftRadius: DDS.isLargeTablet() ? 10 : 1
}}>
}}
>
{!item || !item.id ? (
<Paragraph style={{marginVertical: 10, alignSelf: 'center'}}>
<Paragraph style={{ marginVertical: 10, alignSelf: 'center' }}>
Start writing to save your note.
</Paragraph>
) : (
@@ -53,11 +54,13 @@ export const Properties = ({close = () => {}, item, buttons = [], getRef}) => {
style={{
marginTop: 5,
zIndex: 10
}}>
}}
>
<View
style={{
paddingHorizontal: 12
}}>
}}
>
<Heading size={SIZE.lg}>
{item.type === 'tag' ? '#' : null}
{alias}
@@ -65,12 +68,10 @@ export const Properties = ({close = () => {}, item, buttons = [], getRef}) => {
{item.headline || item.description ? (
<Paragraph numberOfLines={2} color={colors.icon}>
{(item.type === 'notebook' || item.itemType === 'notebook') &&
item?.description
{(item.type === 'notebook' || item.itemType === 'notebook') && item?.description
? item.description
: null}
{(item.type === 'note' || item.itemType === 'note') &&
item?.headline
{(item.type === 'note' || item.itemType === 'note') && item?.headline
? item.headline
: null}
</Paragraph>
@@ -81,9 +82,7 @@ export const Properties = ({close = () => {}, item, buttons = [], getRef}) => {
<Topics item={item} close={close} />
</View>
{item.type === 'note' ? (
<Notebooks note={item} close={close} />
) : null}
{item.type === 'note' ? <Notebooks note={item} close={close} /> : null}
<DateMeta item={item} />
</View>
@@ -117,13 +116,13 @@ Properties.present = (item, buttons = []) => {
if (!item) return;
let type = item?.type;
let props = [item];
let android = [];
switch (type) {
case 'trash':
props.push(['PermDelete', 'Restore']);
break;
case 'note':
let android = Platform.OS === 'android' ? ['PinToNotif'] : [];
android = Platform.OS === 'android' ? ['PinToNotif'] : [];
props.push([
'Add to notebook',
'Share',

View File

@@ -1,21 +1,21 @@
import React from 'react';
import {View} from 'react-native';
import {FlatList} from 'react-native-gesture-handler';
import { View } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {useSettingStore} from '../../provider/stores';
import {DDS} from '../../services/DeviceDetection';
import {SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import {PressableButton} from '../PressableButton';
import { useTracked } from '../../provider';
import { useSettingStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import { PressableButton } from '../PressableButton';
import Paragraph from '../Typography/Paragraph';
import {useActions} from './use-actions';
import { useActions } from './use-actions';
export const Items = ({item, buttons, close}) => {
export const Items = ({ item, buttons, close }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const dimensions = useSettingStore(state => state.dimensions);
const actions = useActions({item, close});
const actions = useActions({ item, close });
const data = actions.filter(i => buttons.indexOf(i.name) > -1 && !i.hidden);
let width = dimensions.width > 600 ? 600 : dimensions.width;
@@ -24,7 +24,7 @@ export const Items = ({item, buttons, close}) => {
? (width - 24) / columnItemsCount
: (width - 24) / columnItemsCount;
const _renderRowItem = ({item, index}) => (
const _renderRowItem = ({ item, index }) => (
<View
onPress={item.func}
key={item.name}
@@ -33,7 +33,8 @@ export const Items = ({item, buttons, close}) => {
alignItems: 'center',
width: columnItemWidth,
marginBottom: 10
}}>
}}
>
<PressableButton
onPress={item.func}
type={item.on ? 'shade' : 'grayBg'}
@@ -46,7 +47,8 @@ export const Items = ({item, buttons, close}) => {
textAlign: 'center',
textAlignVertical: 'center',
marginBottom: DDS.isTab ? 7 : 3.5
}}>
}}
>
<Icon
name={item.icon}
size={DDS.isTab ? SIZE.xxl : SIZE.lg}
@@ -60,13 +62,13 @@ export const Items = ({item, buttons, close}) => {
/>
</PressableButton>
<Paragraph size={SIZE.xs + 1} style={{textAlign: 'center'}}>
<Paragraph size={SIZE.xs + 1} style={{ textAlign: 'center' }}>
{item.title}
</Paragraph>
</View>
);
const renderColumnItem = ({item, index}) => (
const renderColumnItem = ({ item, index }) => (
<Button
buttonType={{
text: item.on
@@ -109,10 +111,6 @@ export const Items = ({item, buttons, close}) => {
renderItem={_renderRowItem}
/>
) : (
<FlatList
data={data}
keyExtractor={item => item.title}
renderItem={renderColumnItem}
/>
<FlatList data={data} keyExtractor={item => item.title} renderItem={renderColumnItem} />
);
};

View File

@@ -1,19 +1,19 @@
import React from 'react';
import {ScrollView, View} from 'react-native';
import { ScrollView, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {eSendEvent} from '../../services/EventManager';
import { useTracked } from '../../provider';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {db} from '../../utils/database';
import {eOnNewTopicAdded, refreshNotesPage} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import {PressableButton} from '../PressableButton';
import { db } from '../../utils/database';
import { eOnNewTopicAdded, refreshNotesPage } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import { PressableButton } from '../PressableButton';
import Heading from '../Typography/Heading';
export default function Notebooks({note, close}) {
const [state, dispatch] = useTracked();
const {colors} = state;
export default function Notebooks({ note, close }) {
const [state] = useTracked();
const { colors } = state;
function getNotebooks(item) {
if (!item.notebooks || item.notebooks.length < 1) return [];
@@ -63,7 +63,7 @@ export default function Notebooks({note, close}) {
let routeName = 'NotesPage';
let item = db.notebooks.notebook(notebookId).topics.topic(id)._topic;
let params = {...item, menu: false};
let params = { ...item, menu: false };
let headerState = {
heading: item.title,
id: item.id,
@@ -79,9 +79,11 @@ export default function Notebooks({note, close}) {
width: '100%',
borderTopWidth: 1,
borderTopColor: colors.nav
}}>
}}
>
{getNotebooks(note).map(item => (
<PressableButton
key={item.id}
onPress={() => {
navigateNotebook(item.id);
close();
@@ -95,7 +97,8 @@ export default function Notebooks({note, close}) {
flexGrow: 1,
marginTop: 5,
paddingVertical: 6
}}>
}}
>
<Icon
name="book-outline"
color={colors.accent}
@@ -109,7 +112,8 @@ export default function Notebooks({note, close}) {
style={{
maxWidth: '50%'
}}
size={SIZE.sm}>
size={SIZE.sm}
>
{item.title}
</Heading>
@@ -122,9 +126,11 @@ export default function Notebooks({note, close}) {
borderLeftColor: colors.nav,
borderLeftWidth: 1,
paddingLeft: 8
}}>
}}
>
{item.topics.map(topic => (
<Button
key={topic.id}
onPress={() => {
navigateTopic(topic.id, item.id);
close();
@@ -141,7 +147,7 @@ export default function Notebooks({note, close}) {
}}
/>
))}
<View style={{width: 10}} />
<View style={{ width: 10 }} />
</ScrollView>
</PressableButton>
))}

View File

@@ -1,18 +1,18 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {useUserStore} from '../../provider/stores';
import {openLinkInBrowser} from '../../utils/functions';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import {Button} from '../Button';
import { useTracked } from '../../provider';
import { useUserStore } from '../../provider/stores';
import { openLinkInBrowser } from '../../utils/functions';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import { Button } from '../Button';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
export const Synced = ({item, close}) => {
export const Synced = ({ item, close }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const user = useUserStore(state => state.user);
const lastSynced = useUserStore(state => state.lastSynced);
@@ -30,7 +30,8 @@ export const Synced = ({item, close}) => {
marginTop: 10,
borderTopWidth: 1,
borderTopColor: colors.nav
}}>
}}
>
<Icon name="shield-key-outline" color={colors.accent} size={SIZE.xxxl} />
<View
@@ -38,13 +39,15 @@ export const Synced = ({item, close}) => {
flex: 1,
marginLeft: 5,
flexShrink: 1
}}>
}}
>
<Heading
color={colors.heading}
size={SIZE.xs}
style={{
flexWrap: 'wrap'
}}>
}}
>
Encrypted and synced
</Heading>
<Paragraph
@@ -52,7 +55,8 @@ export const Synced = ({item, close}) => {
flexWrap: 'wrap'
}}
size={SIZE.xs}
color={colors.pri}>
color={colors.pri}
>
No one can view this {item.itemType || item.type} except you.
</Paragraph>
</View>
@@ -62,10 +66,7 @@ export const Synced = ({item, close}) => {
try {
close();
await sleep(300);
await openLinkInBrowser(
'https://docs.notesnook.com/how-is-my-data-encrypted/',
colors
);
await openLinkInBrowser('https://docs.notesnook.com/how-is-my-data-encrypted/', colors);
} catch (e) {}
}}
fontSize={SIZE.xs + 1}

View File

@@ -1,30 +1,32 @@
import React, {useState} from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {eSendEvent} from '../../services/EventManager';
import React, { useState } from 'react';
import { View } from 'react-native';
import { useTracked } from '../../provider';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {db} from '../../utils/database';
import {eOpenTagsDialog, refreshNotesPage} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import {Button} from '../Button';
import { db } from '../../utils/database';
import { eOpenTagsDialog, refreshNotesPage } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import { Button } from '../Button';
export const Tags = ({item, close}) => {
export const Tags = ({ item, close }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
return item.id ? (
<View
style={{
marginTop: 5,
marginBottom: 5
}}>
}}
>
<View
style={{
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center'
}}>
}}
>
<Button
onPress={async () => {
close();
@@ -41,8 +43,7 @@ export const Tags = ({item, close}) => {
height={25}
fontSize={SIZE.xs + 1}
style={{
marginRight:5,
paddingHorizontal: 0,
marginRight: 5,
borderRadius: 100,
paddingHorizontal: 8
}}
@@ -55,7 +56,7 @@ export const Tags = ({item, close}) => {
) : null;
};
const TagItem = ({tag, close}) => {
const TagItem = ({ tag, close }) => {
const onPress = async () => {
let tags = db.tags.all;
let _tag = tags.find(t => t.title === tag);
@@ -76,7 +77,6 @@ const TagItem = ({tag, close}) => {
};
const style = {
paddingHorizontal: 0,
paddingHorizontal: 8,
marginVertical: 5,
borderRadius: 100,

View File

@@ -1,21 +1,17 @@
import React from 'react';
import {View} from 'react-native';
import {useTracked} from '../../provider';
import {eSendEvent} from '../../services/EventManager';
import { View } from 'react-native';
import { eSendEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {refreshNotesPage} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import { refreshNotesPage } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
export const Topics = ({item, close}) => {
const [state] = useTracked();
const {colors} = state;
const open = (topic) => {
export const Topics = ({ item, close }) => {
const open = topic => {
close();
let routeName = 'NotesPage';
let params = {...topic, menu: false, get: 'topics'};
let params = { ...topic, menu: false, get: 'topics' };
let headerState = {
heading: topic.title,
id: topic.id,
@@ -39,7 +35,6 @@ export const Topics = ({item, close}) => {
fontSize={SIZE.xs + 1}
style={{
marginRight: 5,
paddingHorizontal: 0,
paddingHorizontal: 8,
borderRadius: 100,
marginVertical: 5
@@ -47,17 +42,15 @@ export const Topics = ({item, close}) => {
/>
);
return item &&
item.type === 'notebook' &&
item.topics &&
item.topics.length > 0 ? (
return item && item.type === 'notebook' && item.topics && item.topics.length > 0 ? (
<View
style={{
flexDirection: 'row',
marginTop: 5,
width: '100%',
flexWrap: 'wrap'
}}>
}}
>
{item.topics
.sort((a, b) => a.dateEdited - b.dateEdited)
.slice(0, 6)

View File

@@ -1,16 +1,11 @@
import Clipboard from '@react-native-clipboard/clipboard';
import React, {useEffect, useState} from 'react';
import {Platform} from 'react-native';
import React, { useEffect, useState } from 'react';
import { Platform } from 'react-native';
import Share from 'react-native-share';
import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
import {
useMenuStore,
useSelectionStore,
useTagStore,
useUserStore
} from '../../provider/stores';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { Actions } from '../../provider/Actions';
import { useMenuStore, useSelectionStore, useTagStore, useUserStore } from '../../provider/stores';
import {
eSendEvent,
eSubscribeEvent,
@@ -22,7 +17,7 @@ import {
import Navigation from '../../services/Navigation';
import Notifications from '../../services/Notifications';
import SettingsService from '../../services/SettingsService';
import {editing, toTXT} from '../../utils';
import { editing, toTXT } from '../../utils';
import {
ACCENT,
COLOR_SCHEME,
@@ -31,7 +26,7 @@ import {
COLOR_SCHEME_PITCH_BLACK,
setColorScheme
} from '../../utils/Colors';
import {db} from '../../utils/database';
import { db } from '../../utils/database';
import {
eOpenAddNotebookDialog,
eOpenAddTopicDialog,
@@ -41,21 +36,19 @@ import {
eOpenMoveNoteDialog,
eOpenPublishNoteDialog
} from '../../utils/Events';
import {deleteItems} from '../../utils/functions';
import {MMKV} from '../../utils/mmkv';
import {sleep} from '../../utils/TimeUtils';
import {presentDialog} from '../Dialog/functions';
import { deleteItems } from '../../utils/functions';
import { MMKV } from '../../utils/mmkv';
import { sleep } from '../../utils/TimeUtils';
import { presentDialog } from '../Dialog/functions';
import NoteHistory from '../NoteHistory';
export const useActions = ({close = () => {}, item}) => {
export const useActions = ({ close = () => {}, item }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const clearSelection = useSelectionStore(state => state.clearSelection);
const setSelectedItem = useSelectionStore(state => state.setSelectedItem);
const setMenuPins = useMenuStore(state => state.setMenuPins);
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
db.settings.isPinned(item.id)
);
const [isPinnedToMenu, setIsPinnedToMenu] = useState(db.settings.isPinned(item.id));
const user = useUserStore(state => state.user);
const [notifPinned, setNotifPinned] = useState(null);
@@ -66,8 +59,7 @@ export const useActions = ({close = () => {}, item}) => {
? db.colors.alias(item.id)
: item.title;
const isPublished =
item.type === 'note' && db.monographs.isPublished(item.id);
const isPublished = item.type === 'note' && db.monographs.isPublished(item.id);
const noteInTopic =
item.type === 'note' &&
editing.actionAfterFirstSave.type === 'topic' &&
@@ -117,19 +109,19 @@ export const useActions = ({close = () => {}, item}) => {
function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
let newColors = setColorScheme(colors, accent);
dispatch({type: Actions.THEME, colors: newColors});
dispatch({ type: Actions.THEME, colors: newColors });
}
function switchTheme() {
if (!colors.night) {
MMKV.setStringAsync('theme', JSON.stringify({night: true}));
MMKV.setStringAsync('theme', JSON.stringify({ night: true }));
let nextTheme = SettingsService.get().pitchBlack
? COLOR_SCHEME_PITCH_BLACK
: COLOR_SCHEME_DARK;
changeColorScheme(nextTheme);
return;
}
MMKV.setStringAsync('theme', JSON.stringify({night: false}));
MMKV.setStringAsync('theme', JSON.stringify({ night: false }));
changeColorScheme(COLOR_SCHEME_LIGHT);
}
@@ -165,10 +157,7 @@ export const useActions = ({close = () => {}, item}) => {
return;
}
await db[`${type}s`][type](item.id).pin();
Navigation.setRoutesToUpdate([
Navigation.routeNames.Notebooks,
Navigation.routeNames.Notes
]);
Navigation.setRoutesToUpdate([Navigation.routeNames.Notebooks, Navigation.routeNames.Notes]);
}
async function pinToNotifications() {
@@ -206,12 +195,9 @@ export const useActions = ({close = () => {}, item}) => {
Navigation.routeNames.Favorites,
Navigation.routeNames.Trash
]);
type = item.type === 'trash' ? item.itemType : item.type;
let type = item.type === 'trash' ? item.itemType : item.type;
ToastEvent.show({
heading:
type === 'note'
? 'Note restored from trash'
: 'Notebook restored from trash',
heading: type === 'note' ? 'Note restored from trash' : 'Notebook restored from trash',
type: 'success'
});
}
@@ -337,7 +323,7 @@ export const useActions = ({close = () => {}, item}) => {
notebookId: item.notebookId
});
} else {
await db.settings.pin(item.type, {id: item.id});
await db.settings.pin(item.type, { id: item.id });
}
}
setIsPinnedToMenu(db.settings.isPinned(item.id));
@@ -526,10 +512,7 @@ export const useActions = ({close = () => {}, item}) => {
},
{
name: 'PinToNotif',
title:
notifPinned !== null
? 'Unpin from Notifications'
: 'Pin to Notifications',
title: notifPinned !== null ? 'Unpin from Notifications' : 'Pin to Notifications',
icon: 'bell',
on: notifPinned !== null,
func: pinToNotifications
@@ -631,9 +614,7 @@ export const useActions = ({close = () => {}, item}) => {
{
name: 'Delete',
title:
item.type !== 'notebook' && item.type !== 'note'
? 'Delete ' + item.type
: 'Move to trash',
item.type !== 'notebook' && item.type !== 'note' ? 'Delete ' + item.type : 'Move to trash',
icon: 'delete-outline',
type: 'error',
func: deleteItem

View File

@@ -1,31 +1,24 @@
import React, {useEffect, useRef, useState} from 'react';
import {ActivityIndicator, TouchableOpacity, View} from 'react-native';
import React, { useEffect, useRef, useState } from 'react';
import { ActivityIndicator, TouchableOpacity, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import Clipboard from '@react-native-clipboard/clipboard';
import {useTracked} from '../../provider';
import {
eSubscribeEvent,
eUnSubscribeEvent,
ToastEvent
} from '../../services/EventManager';
import { useTracked } from '../../provider';
import { eSubscribeEvent, eUnSubscribeEvent, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {db} from '../../utils/database';
import {
eClosePublishNoteDialog,
eOpenPublishNoteDialog
} from '../../utils/Events';
import {openLinkInBrowser} from '../../utils/functions';
import {SIZE} from '../../utils/SizeUtils';
import {ActionIcon} from '../ActionIcon';
import { db } from '../../utils/database';
import { eClosePublishNoteDialog, eOpenPublishNoteDialog } from '../../utils/Events';
import { openLinkInBrowser } from '../../utils/functions';
import { SIZE } from '../../utils/SizeUtils';
import { ActionIcon } from '../ActionIcon';
import SheetWrapper from '../Sheet';
import {Button} from '../Button';
import { Button } from '../Button';
import DialogHeader from '../Dialog/dialog-header';
import Input from '../Input';
import Seperator from '../Seperator';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {useAttachmentStore} from '../../provider/stores';
import {editing} from '../../utils';
import { useAttachmentStore } from '../../provider/stores';
import { editing } from '../../utils';
let passwordValue = null;
const PublishNoteDialog = () => {
@@ -39,8 +32,7 @@ const PublishNoteDialog = () => {
const [note, setNote] = useState(null);
const [publishing, setPublishing] = useState(false);
const publishUrl =
note &&
`https://monograph.notesnook.com/${db?.monographs.monograph(note?.id)}`;
note && `https://monograph.notesnook.com/${db?.monographs.monograph(note?.id)}`;
const isPublished = note && db?.monographs.isPublished(note?.id);
const pwdInput = useRef();
@@ -137,13 +129,15 @@ const PublishNoteDialog = () => {
onClose={async () => {
passwordValue = null;
setVisible(false);
}}>
}}
>
<View
style={{
width: '100%',
alignSelf: 'center',
paddingHorizontal: 12
}}>
}}
>
<DialogHeader
title={note.title}
paragraph={`Anyone with the link${
@@ -158,17 +152,16 @@ const PublishNoteDialog = () => {
alignContent: 'center',
height: 150,
width: '100%'
}}>
}}
>
<ActivityIndicator size={25} color={colors.accent} />
<Paragraph
style={{
textAlign: 'center'
}}>
}}
>
Please wait...
{loading &&
`\nDownloading attachments (${
loading?.current / loading?.total
})`}
{loading && `\nDownloading attachments (${loading?.current / loading?.total})`}
</Paragraph>
</View>
) : (
@@ -182,12 +175,14 @@ const PublishNoteDialog = () => {
backgroundColor: colors.nav,
padding: 12,
borderRadius: 5
}}>
}}
>
<View
style={{
width: '100%',
flexShrink: 1
}}>
}}
>
<Heading size={SIZE.sm}>Published at:</Heading>
<Paragraph size={SIZE.xs} numberOfLines={1}>
{publishUrl}
@@ -202,9 +197,9 @@ const PublishNoteDialog = () => {
style={{
marginTop: 5,
color: colors.pri
}}>
<Icon color={colors.accent} name="open-in-new" /> Open in
browser
}}
>
<Icon color={colors.accent} name="open-in-new" /> Open in browser
</Paragraph>
</View>
@@ -235,7 +230,8 @@ const PublishNoteDialog = () => {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10
}}>
}}
>
<ActionIcon
onPress={() => {
if (publishing) return;
@@ -243,22 +239,18 @@ const PublishNoteDialog = () => {
}}
color={isLocked ? colors.accent : colors.icon}
size={SIZE.lg}
name={
isLocked
? 'check-circle-outline'
: 'checkbox-blank-circle-outline'
}
name={isLocked ? 'check-circle-outline' : 'checkbox-blank-circle-outline'}
/>
<View
style={{
width: '100%',
flexShrink: 1
}}>
}}
>
<Heading size={SIZE.md}>Password protection</Heading>
<Paragraph>
Published note can only be viewed by someone with the
password.
Published note can only be viewed by someone with the password.
</Paragraph>
</View>
</TouchableOpacity>
@@ -271,29 +263,26 @@ const PublishNoteDialog = () => {
style={{
flexDirection: 'row',
alignItems: 'center'
}}>
}}
>
<ActionIcon
onPress={() => {
setSelfDestruct(!selfDestruct);
}}
color={selfDestruct ? colors.accent : colors.icon}
size={SIZE.lg}
name={
selfDestruct
? 'check-circle-outline'
: 'checkbox-blank-circle-outline'
}
name={selfDestruct ? 'check-circle-outline' : 'checkbox-blank-circle-outline'}
/>
<View
style={{
width: '100%',
flexShrink: 1
}}>
}}
>
<Heading size={SIZE.md}>Self destruct</Heading>
<Paragraph>
Published note link will be automatically deleted once it is
viewed by someone.
Published note link will be automatically deleted once it is viewed by someone.
</Paragraph>
</View>
</TouchableOpacity>
@@ -303,7 +292,8 @@ const PublishNoteDialog = () => {
width: '100%',
alignSelf: 'center',
marginTop: 10
}}>
}}
>
{isLocked ? (
<>
<Input
@@ -357,12 +347,10 @@ const PublishNoteDialog = () => {
}}
onPress={async () => {
try {
await openLinkInBrowser(
'https://docs.notesnook.com/monographs/',
colors.accent
);
await openLinkInBrowser('https://docs.notesnook.com/monographs/', colors.accent);
} catch (e) {}
}}>
}}
>
Learn more about Notesnook Monograph
</Paragraph>
</View>

View File

@@ -1,16 +1,16 @@
import React, {useEffect, useRef, useState} from 'react';
import {Linking, Platform, View} from 'react-native';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {eCloseRateDialog, eOpenRateDialog} from '../../utils/Events';
import {MMKV} from '../../utils/mmkv';
import {SIZE} from '../../utils/SizeUtils';
import React, { useEffect, useRef, useState } from 'react';
import { Linking, Platform, View } from 'react-native';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
import { eCloseRateDialog, eOpenRateDialog } from '../../utils/Events';
import { MMKV } from '../../utils/mmkv';
import { SIZE } from '../../utils/SizeUtils';
import SheetWrapper from '../Sheet';
import {Button} from '../Button';
import { Button } from '../Button';
import Seperator from '../Seperator';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {STORE_LINK} from '../../utils';
import {clearMessage} from '../../services/Message';
import { STORE_LINK } from '../../utils';
import { clearMessage } from '../../services/Message';
const RateDialog = () => {
const [visible, setVisible] = useState(false);
@@ -51,17 +51,19 @@ const RateDialog = () => {
);
setVisible(false);
clearMessage();
}}>
}}
>
<View
style={{
width: '100%',
alignSelf: 'center',
paddingHorizontal: 12
}}>
}}
>
<Heading>Do you enjoy using Notesnook?</Heading>
<Paragraph size={SIZE.md}>
It took us a year to bring Notesnook to life. Share your experience
and suggestions to help us improve it.
It took us a year to bring Notesnook to life. Share your experience and suggestions to
help us improve it.
</Paragraph>
<Seperator half />
@@ -86,7 +88,8 @@ const RateDialog = () => {
paddingTop: 12,
width: '100%',
alignSelf: 'center'
}}>
}}
>
<Button
onPress={async () => {
await MMKV.setItem('askForRating', 'never');

View File

@@ -1,8 +1,8 @@
import React, {createRef} from 'react';
import {Platform, View} from 'react-native';
import React, { createRef } from 'react';
import { Platform, View } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import Share from 'react-native-share';
import {LOGO_BASE64} from '../../assets/images/assets';
import { LOGO_BASE64 } from '../../assets/images/assets';
import Clipboard from '@react-native-clipboard/clipboard';
import {
eSendEvent,
@@ -10,22 +10,22 @@ import {
eUnSubscribeEvent,
ToastEvent
} from '../../services/EventManager';
import {db} from '../../utils/database';
import {eOpenRecoveryKeyDialog, eOpenResultDialog} from '../../utils/Events';
import {sanitizeFilename} from '../../utils/filename';
import {SIZE} from '../../utils/SizeUtils';
import { db } from '../../utils/database';
import { eOpenRecoveryKeyDialog, eOpenResultDialog } from '../../utils/Events';
import { sanitizeFilename } from '../../utils/filename';
import { SIZE } from '../../utils/SizeUtils';
import Storage from '../../utils/storage';
import {sleep} from '../../utils/TimeUtils';
import { sleep } from '../../utils/TimeUtils';
import SheetWrapper from '../Sheet';
import {Button} from '../Button';
import { Button } from '../Button';
import DialogHeader from '../Dialog/dialog-header';
import Seperator from '../Seperator';
import Paragraph from '../Typography/Paragraph';
import FileViewer from 'react-native-file-viewer';
import * as ScopedStorage from 'react-native-scoped-storage';
import {MMKV} from '../../utils/mmkv';
import {clearMessage} from '../../services/Message';
import { MMKV } from '../../utils/mmkv';
import { clearMessage } from '../../services/Message';
let RNFetchBlob;
@@ -98,24 +98,18 @@ class RecoveryKeyDialog extends React.Component {
let path;
RNFetchBlob = require('rn-fetch-blob').default;
let fileName = 'nn_' + this.user.email + '_recovery_key_qrcode';
fileName = sanitizeFilename(fileName, {replacement: '_'});
fileName = sanitizeFilename(fileName, { replacement: '_' });
fileName = fileName + '.png';
if (Platform.OS === 'android') {
await ScopedStorage.createDocument(
fileName,
'image/png',
data,
'base64'
);
await ScopedStorage.createDocument(fileName, 'image/png', data, 'base64');
} else {
path = await Storage.checkAndCreateDir('/');
await RNFetchBlob.fs.writeFile(path + fileName, data, 'base64');
}
ToastEvent.show({
heading: 'Recovery key QR-Code saved',
message:
'QR-Code image has been saved to Gallery at ' + path + fileName,
message: 'QR-Code image has been saved to Gallery at ' + path + fileName,
type: 'success',
context: 'local'
});
@@ -127,7 +121,7 @@ class RecoveryKeyDialog extends React.Component {
try {
let path;
let fileName = 'nn_' + this.user?.email + '_recovery_key';
fileName = sanitizeFilename(fileName, {replacement: '_'});
fileName = sanitizeFilename(fileName, { replacement: '_' });
fileName = fileName + '.txt';
RNFetchBlob = require('rn-fetch-blob').default;
@@ -174,7 +168,7 @@ class RecoveryKeyDialog extends React.Component {
try {
if (Platform.OS === 'ios') {
Share.open({
url: 'file:/' + result.filePath,
url: 'file:/' + path,
failOnCancel: false
}).catch(console.log);
} else {
@@ -188,14 +182,15 @@ class RecoveryKeyDialog extends React.Component {
};
render() {
const {colors} = this.props;
const { colors } = this.props;
if (!this.state.visible) return null;
return (
<SheetWrapper
closeOnTouchBackdrop={false}
gestureEnabled={false}
onOpen={this.onOpen}
fwdRef={this.actionSheetRef}>
fwdRef={this.actionSheetRef}
>
<View
style={{
width: '100%',
@@ -204,7 +199,8 @@ class RecoveryKeyDialog extends React.Component {
paddingHorizontal: 12,
borderRadius: 10,
paddingTop: 10
}}>
}}
>
<DialogHeader
title="Save account recovery key"
paragraph="If you forget your password, you can recover your
@@ -216,7 +212,8 @@ class RecoveryKeyDialog extends React.Component {
borderRadius: 5,
padding: 12,
marginTop: 10
}}>
}}
>
<Paragraph
color={colors.pri}
size={SIZE.sm}
@@ -228,7 +225,8 @@ class RecoveryKeyDialog extends React.Component {
paddingRight: 10,
textAlign: 'center',
textDecorationLine: 'underline'
}}>
}}
>
{this.state.key}
</Paragraph>
</View>
@@ -244,13 +242,14 @@ class RecoveryKeyDialog extends React.Component {
position: 'absolute',
opacity: 0,
zIndex: -1
}}>
}}
>
{this.state.key ? (
<QRCode
getRef={this.svg}
size={500}
value={this.state.key}
logo={{uri: LOGO_BASE64}}
logo={{ uri: LOGO_BASE64 }}
logoBorderRadius={10}
/>
) : null}
@@ -314,7 +313,8 @@ class RecoveryKeyDialog extends React.Component {
maxWidth: '100%',
marginBottom: 5,
textAlign: 'center'
}}>
}}
>
Tap twice to confirm you have saved the recovery key.
</Paragraph>
<Button

View File

@@ -1,30 +1,26 @@
import React, {createRef, useEffect, useState} from 'react';
import {ActivityIndicator, Platform, View} from 'react-native';
import React, { createRef, useEffect, useState } from 'react';
import { ActivityIndicator, Platform, View } from 'react-native';
import DocumentPicker from 'react-native-document-picker';
import {FlatList} from 'react-native-gesture-handler';
import {useTracked} from '../../provider';
import {initialize} from '../../provider/stores';
import {
eSubscribeEvent,
eUnSubscribeEvent,
ToastEvent
} from '../../services/EventManager';
import {db} from '../../utils/database';
import {eCloseRestoreDialog, eOpenRestoreDialog} from '../../utils/Events';
import {MMKV} from '../../utils/mmkv';
import {SIZE} from '../../utils/SizeUtils';
import { FlatList } from 'react-native-gesture-handler';
import { useTracked } from '../../provider';
import { initialize } from '../../provider/stores';
import { eSubscribeEvent, eUnSubscribeEvent, ToastEvent } from '../../services/EventManager';
import { db } from '../../utils/database';
import { eCloseRestoreDialog, eOpenRestoreDialog } from '../../utils/Events';
import { MMKV } from '../../utils/mmkv';
import { SIZE } from '../../utils/SizeUtils';
import storage from '../../utils/storage';
import {sleep, timeConverter} from '../../utils/TimeUtils';
import { sleep, timeConverter } from '../../utils/TimeUtils';
import SheetWrapper from '../Sheet';
import {Button} from '../Button';
import { Button } from '../Button';
import DialogHeader from '../Dialog/dialog-header';
import Seperator from '../Seperator';
import Paragraph from '../Typography/Paragraph';
import * as ScopedStorage from 'react-native-scoped-storage';
import {Dialog} from '../Dialog';
import {verifyUser} from '../../views/Settings/functions';
import {presentDialog} from '../Dialog/functions';
import {Toast} from '../Toast';
import { Dialog } from '../Dialog';
import { verifyUser } from '../../views/Settings/functions';
import { presentDialog } from '../Dialog/functions';
import { Toast } from '../Toast';
const actionSheetRef = createRef();
let RNFetchBlob;
@@ -71,12 +67,9 @@ const RestoreDialog = () => {
fwdRef={actionSheetRef}
gestureEnabled={!restoring}
closeOnTouchBackdrop={!restoring}
onClose={close}>
<RestoreDataComponent
close={close}
restoring={restoring}
setRestoring={setRestoring}
/>
onClose={close}
>
<RestoreDataComponent close={close} restoring={restoring} setRestoring={setRestoring} />
<Toast context="local" />
</SheetWrapper>
);
@@ -84,9 +77,9 @@ const RestoreDialog = () => {
export default RestoreDialog;
const RestoreDataComponent = ({close, setRestoring, restoring}) => {
const RestoreDataComponent = ({ close, setRestoring, restoring }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [files, setFiles] = useState([]);
const [loading, setLoading] = useState(true);
const [backupDirectoryAndroid, setBackupDirectoryAndroid] = useState(false);
@@ -187,8 +180,8 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
files = await RNFetchBlob.fs.lstat(path);
}
files = files.sort(function (a, b) {
timeA = a.lastModified;
timeB = b.lastModified;
let timeA = a.lastModified;
let timeB = b.lastModified;
return timeB - timeA;
});
setFiles(files);
@@ -201,7 +194,7 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
}
};
const renderItem = ({item, index}) => (
const renderItem = ({ item, index }) => (
<View
style={{
minHeight: 50,
@@ -212,12 +205,14 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
flexDirection: 'row',
borderBottomWidth: 0.5,
borderBottomColor: colors.nav
}}>
}}
>
<View
style={{
maxWidth: '75%'
}}>
<Paragraph size={SIZE.sm} style={{width: '100%', maxWidth: '100%'}}>
}}
>
<Paragraph size={SIZE.sm} style={{ width: '100%', maxWidth: '100%' }}>
{timeConverter(item?.lastModified * 1)}
</Paragraph>
<Paragraph size={SIZE.xs}>
@@ -276,10 +271,7 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
.then(async r => {
try {
let backup = await r.json();
console.log(
'backup encrypted:',
backup.data.iv && backup.data.salt
);
console.log('backup encrypted:', backup.data.iv && backup.data.salt);
if (backup.data.iv && backup.data.salt) {
withPassword(
async value => {
@@ -326,13 +318,12 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
paddingRight: 8,
alignItems: 'center',
paddingTop: restoring ? 8 : 0
}}>
}}
>
<DialogHeader
title="Backups"
paragraph={`All the backups are stored in ${
Platform.OS === 'ios'
? 'File Manager/Notesnook/Backups'
: 'selected backups folder.'
Platform.OS === 'ios' ? 'File Manager/Notesnook/Backups' : 'selected backups folder.'
}`}
button={button}
/>
@@ -351,7 +342,8 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
justifyContent: 'center',
alignItems: 'center',
height: 100
}}>
}}
>
<ActivityIndicator color={colors.accent} size={SIZE.lg} />
</View>
) : (
@@ -360,16 +352,15 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
justifyContent: 'center',
alignItems: 'center',
height: 100
}}>
}}
>
{Platform.OS === 'android' && !backupDirectoryAndroid ? (
<>
<Button
title="Select backups folder"
icon="folder"
onPress={async () => {
let folder = await ScopedStorage.openDocumentTree(
true
);
let folder = await ScopedStorage.openDocumentTree(true);
let subfolder;
if (folder.name !== 'Notesnook backups') {
subfolder = await ScopedStorage.createDirectory(
@@ -380,10 +371,7 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
subfolder = folder;
}
console.log(subfolder, folder);
MMKV.setItem(
'backupStorageDir',
JSON.stringify(subfolder)
);
MMKV.setItem('backupStorageDir', JSON.stringify(subfolder));
setBackupDirectoryAndroid(subfolder);
setLoading(true);
checkBackups();
@@ -403,9 +391,9 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
}}
size={SIZE.xs}
textBreakStrategy="balanced"
color={colors.icon}>
Select the folder that includes your backup files to
list them here.
color={colors.icon}
>
Select the folder that includes your backup files to list them here.
</Paragraph>
</>
) : (
@@ -419,11 +407,10 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
justifyContent: 'center',
alignItems: 'center',
height: 200
}}>
}}
>
<ActivityIndicator color={colors.accent} />
<Paragraph color={colors.icon}>
Restoring backup. Please wait.
</Paragraph>
<Paragraph color={colors.icon}>Restoring backup. Please wait.</Paragraph>
</View>
)
}

View File

@@ -1,30 +1,24 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {eSendEvent} from '../../services/EventManager';
import {
eCloseProgressDialog,
eCloseResultDialog,
eOpenPremiumDialog
} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import { useTracked } from '../../provider';
import { eSendEvent } from '../../services/EventManager';
import { eCloseProgressDialog, eCloseResultDialog, eOpenPremiumDialog } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import Paragraph from '../Typography/Paragraph';
export const ProFeatures = ({count = 6}) => {
export const ProFeatures = ({ count = 6 }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
return (
<>
{[
{
content:
'Unlock unlimited notebooks, tags, colors. Organize like a pro'
content: 'Unlock unlimited notebooks, tags, colors. Organize like a pro'
},
{
content:
'Attach files upto 500MB, upload 4K images with unlimited storage'
content: 'Attach files upto 500MB, upload 4K images with unlimited storage'
},
{
content: 'Instantly sync to unlimited devices'
@@ -33,8 +27,7 @@ export const ProFeatures = ({count = 6}) => {
content: 'A private vault to keep everything imporant always locked'
},
{
content:
'Rich note editing experience with markdown, tables, checklists and more'
content: 'Rich note editing experience with markdown, tables, checklists and more'
},
{
content: 'Export your notes in Pdf, markdown and html formats'
@@ -43,6 +36,7 @@ export const ProFeatures = ({count = 6}) => {
.slice(0, count)
.map(item => (
<View
key={item.content}
style={{
flexDirection: 'row',
width: '100%',
@@ -52,11 +46,10 @@ export const ProFeatures = ({count = 6}) => {
alignItems: 'center',
borderRadius: 5,
justifyContent: 'flex-start'
}}>
}}
>
<Icon size={SIZE.lg} color={colors.accent} name="check" />
<Paragraph style={{marginLeft: 5, flexShrink: 1}}>
{item.content}
</Paragraph>
<Paragraph style={{ marginLeft: 5, flexShrink: 1 }}>{item.content}</Paragraph>
</View>
))}
<Paragraph
@@ -70,7 +63,8 @@ export const ProFeatures = ({count = 6}) => {
style={{
textDecorationLine: 'underline',
color: colors.icon
}}>
}}
>
See all features included in Notesnook Pro
</Paragraph>
</>

View File

@@ -15,16 +15,14 @@ import { ProFeatures } from './pro-features';
const ResultDialog = () => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [visible, setVisible] = useState(false);
const [dialogData, setDialogData] = useState({
title: 'Thank you for signing up!',
paragraph:
'Try out all features of Notesnook free for 7 days. No limitations. No commitments.',
paragraph: 'Try out all features of Notesnook free for 7 days. No limitations. No commitments.',
button: 'Start taking notes'
});
useEffect(() => {
eSubscribeEvent(eOpenResultDialog, open);
eSubscribeEvent(eCloseResultDialog, close);
return () => {
@@ -56,7 +54,8 @@ const ResultDialog = () => {
paddingTop: 20,
justifyContent: 'center',
alignItems: 'center'
}}>
}}
>
<Heading
size={SIZE.lg}
textBreakStrategy="balanced"
@@ -67,7 +66,8 @@ const ResultDialog = () => {
maxWidth: '100%',
marginBottom: 10,
paddingHorizontal: 12
}}>
}}
>
{dialogData.title}
</Heading>
@@ -79,7 +79,8 @@ const ResultDialog = () => {
textAlign: 'center',
maxWidth: '80%',
lineHeight: SIZE.sm + 5
}}>
}}
>
{dialogData.paragraph}
</Paragraph>
@@ -90,7 +91,8 @@ const ResultDialog = () => {
paddingHorizontal: 12,
alignItems: 'center',
width: '100%'
}}>
}}
>
<ProFeatures count={4} />
</View>
@@ -102,7 +104,8 @@ const ResultDialog = () => {
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10,
paddingVertical: 10
}}>
}}
>
<Button
title={dialogData.button}
width={null}

View File

@@ -1,24 +1,24 @@
import React, {useEffect} from 'react';
import {BackHandler, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {useTracked} from '../../provider';
import {useSelectionStore} from '../../provider/stores';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import React, { useEffect } from 'react';
import { BackHandler, Platform, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTracked } from '../../provider';
import { useSelectionStore } from '../../provider/stores';
import { eSendEvent, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import SearchService from '../../services/SearchService';
import {db} from '../../utils/database';
import {eOpenMoveNoteDialog, refreshNotesPage} from '../../utils/Events';
import {deleteItems} from '../../utils/functions';
import { db } from '../../utils/database';
import { eOpenMoveNoteDialog, refreshNotesPage } from '../../utils/Events';
import { deleteItems } from '../../utils/functions';
import layoutmanager from '../../utils/layout-manager';
import {SIZE} from '../../utils/SizeUtils';
import {sleep} from '../../utils/TimeUtils';
import {ActionIcon} from '../ActionIcon';
import {presentDialog} from '../Dialog/functions';
import { SIZE } from '../../utils/SizeUtils';
import { sleep } from '../../utils/TimeUtils';
import { ActionIcon } from '../ActionIcon';
import { presentDialog } from '../Dialog/functions';
import Heading from '../Typography/Heading';
export const SelectionHeader = React.memo(({screen, type, extras}) => {
export const SelectionHeader = React.memo(({ screen, type, extras }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const selectionMode = useSelectionStore(state => state.selectionMode);
const selectedItemsList = useSelectionStore(state => state.selectedItemsList);
@@ -90,14 +90,16 @@ export const SelectionHeader = React.memo(({screen, type, extras}) => {
flexDirection: 'row',
zIndex: 999,
paddingHorizontal: 12
}}>
}}
>
<View
style={{
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
borderRadius: 100
}}>
}}
>
<ActionIcon
customStyle={{
justifyContent: 'center',
@@ -125,7 +127,8 @@ export const SelectionHeader = React.memo(({screen, type, extras}) => {
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center'
}}>
}}
>
<Heading size={SIZE.md} color={colors.accent}>
{selectedItemsList.length + ' Selected'}
</Heading>
@@ -136,7 +139,8 @@ export const SelectionHeader = React.memo(({screen, type, extras}) => {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center'
}}>
}}
>
{/* <ActionIcon
onPress={async () => {
// await sleep(100);
@@ -219,9 +223,7 @@ export const SelectionHeader = React.memo(({screen, type, extras}) => {
}}
onPress={async () => {
presentDialog({
title: `Delete ${
selectedItemsList.length > 1 ? 'items' : 'item'
}`,
title: `Delete ${selectedItemsList.length > 1 ? 'items' : 'item'}`,
paragraph: `Are you sure you want to delete ${
selectedItemsList.length > 1 ? 'these items?' : 'this item?'
}`,
@@ -257,4 +259,6 @@ export const SelectionHeader = React.memo(({screen, type, extras}) => {
);
});
SelectionHeader.displayName = 'SelectionHeader';
export default SelectionHeader;

View File

@@ -1,12 +1,13 @@
import React, { useEffect, useState } from 'react';
import {View } from 'react-native';
import Clipboard from "@react-native-clipboard/clipboard"
import { View } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import Animated, { useValue } from 'react-native-reanimated';
import { useTracked } from '../../provider';
import {
useMenuStore,
useNotebookStore,
useSelectionStore
useSelectionStore,
useTrashStore
} from '../../provider/stores';
import { openVault, ToastEvent } from '../../services/EventManager';
import Navigation from '../../services/Navigation';
@@ -17,9 +18,9 @@ import { ActionIcon } from '../ActionIcon';
import { Button } from '../Button';
import { presentDialog } from '../Dialog/functions';
export const ActionStrip = ({note, setActionStrip}) => {
export const ActionStrip = ({ note, setActionStrip }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const selectionMode = useSelectionStore(state => state.selectionMode);
const setNotebooks = useNotebookStore(state => state.setNotebooks);
const setMenuPins = useMenuStore(state => state.setMenuPins);
@@ -38,7 +39,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Notes,
Navigation.routeNames.Notes
]);
};
@@ -63,7 +64,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
if (db.notes.pinned.length === 3 && !note.pinned) {
ToastEvent.show({
heading: 'Cannot pin more than 3 notes',
type: 'error',
type: 'error'
});
return;
}
@@ -72,7 +73,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
if (db.notebooks.pinned.length === 3 && !note.pinned) {
ToastEvent.show({
heading: 'Cannot pin more than 3 notebooks',
type: 'error',
type: 'error'
});
return;
}
@@ -81,7 +82,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
}
updateNotes();
setActionStrip(false);
},
}
},
{
title: 'Add to favorites',
@@ -97,13 +98,11 @@ export const ActionStrip = ({note, setActionStrip}) => {
setActionStrip(false);
},
visible: note.type === 'note',
color: !note.favorite ? 'orange' : null,
color: !note.favorite ? 'orange' : null
},
{
title: isPinnedToMenu
? 'Remove Shortcut from Menu'
: 'Add Shortcut to Menu',
title: isPinnedToMenu ? 'Remove Shortcut from Menu' : 'Add Shortcut to Menu',
icon: isPinnedToMenu ? 'link-variant-remove' : 'link-variant',
onPress: async () => {
try {
@@ -111,20 +110,20 @@ export const ActionStrip = ({note, setActionStrip}) => {
await db.settings.unpin(note.id);
ToastEvent.show({
heading: 'Shortcut removed from menu',
type: 'success',
type: 'success'
});
} else {
if (note.type === 'topic') {
await db.settings.pin(note.type, {
id: note.id,
notebookId: note.notebookId,
notebookId: note.notebookId
});
} else {
await db.settings.pin(note.type, {id: note.id});
await db.settings.pin(note.type, { id: note.id });
}
ToastEvent.show({
heading: 'Shortcut added to menu',
type: 'success',
type: 'success'
});
}
setIsPinnedToMenu(db.settings.isPinned(note.id));
@@ -133,7 +132,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
setActionStrip(false);
} catch (e) {}
},
visible: note.type !== 'note',
visible: note.type !== 'note'
},
{
title: 'Copy Note',
@@ -147,7 +146,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
locked: true,
item: note,
title: 'Copy note',
description: 'Unlock note to copy to clipboard.',
description: 'Unlock note to copy to clipboard.'
});
} else {
let delta = await db.notes.note(note.id).content();
@@ -156,11 +155,11 @@ export const ActionStrip = ({note, setActionStrip}) => {
Clipboard.setString(text);
ToastEvent.show({
heading: 'Note copied to clipboard',
type: 'success',
type: 'success'
});
}
setActionStrip(false);
},
}
},
{
title: 'Restore ' + note.itemType,
@@ -172,20 +171,18 @@ export const ActionStrip = ({note, setActionStrip}) => {
Navigation.routeNames.Notebooks,
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Trash,
Navigation.routeNames.Trash
]);
ToastEvent.show({
heading:
item.type === 'note'
? 'Note restored from trash'
: 'Notebook restored from trash',
type: 'success',
note.type === 'note' ? 'Note restored from trash' : 'Notebook restored from trash',
type: 'success'
});
setActionStrip(false);
},
visible: note.type === 'trash',
visible: note.type === 'trash'
},
{
title: 'Delete' + note.itemType,
@@ -204,13 +201,13 @@ export const ActionStrip = ({note, setActionStrip}) => {
ToastEvent.show({
heading: 'Permanantly deleted items',
type: 'success',
context: 'local',
context: 'local'
});
},
positiveType: 'errorShade',
positiveType: 'errorShade'
});
setActionStrip(false);
},
}
},
{
title: 'Delete' + note.type,
@@ -221,7 +218,7 @@ export const ActionStrip = ({note, setActionStrip}) => {
await deleteItems(note);
} catch (e) {}
setActionStrip(false);
},
}
},
{
title: 'Close',
@@ -229,8 +226,8 @@ export const ActionStrip = ({note, setActionStrip}) => {
onPress: () => setActionStrip(false),
color: colors.light,
bg: colors.red,
visible: true,
},
visible: true
}
];
return (
@@ -246,8 +243,9 @@ export const ActionStrip = ({note, setActionStrip}) => {
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
opacity: opacity,
}}>
opacity: opacity
}}
>
<Button
type="accent"
title="Select"
@@ -263,36 +261,36 @@ export const ActionStrip = ({note, setActionStrip}) => {
style={{
borderRadius: 100,
paddingHorizontal: 12,
...getElevation(5),
...getElevation(5)
}}
height={30}
/>
{actions.map(
item =>
item.visible ? (
<View
key={item.icon}
style={{
width: width / 1.4 / actions.length,
height: width / 1.4 / actions.length,
backgroundColor: item.bg || colors.nav,
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center',
...getElevation(5),
marginLeft: 15,
}}>
<ActionIcon
color={item.color || colors.heading}
onPress={item.onPress}
tooltipText={item.title}
top={60}
bottom={60}
name={item.icon}
size={width / 2.8 / actions.length}
/>
</View>
) : null,
{actions.map(item =>
item.visible ? (
<View
key={item.icon}
style={{
width: width / 1.4 / actions.length,
height: width / 1.4 / actions.length,
backgroundColor: item.bg || colors.nav,
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center',
...getElevation(5),
marginLeft: 15
}}
>
<ActionIcon
color={item.color || colors.heading}
onPress={item.onPress}
tooltipText={item.title}
top={60}
bottom={60}
name={item.icon}
size={width / 2.8 / actions.length}
/>
</View>
) : null
)}
</Animated.View>
);

View File

@@ -4,10 +4,10 @@ import { useTracked } from '../../provider';
import { useEditorStore } from '../../provider/stores';
import { hexToRGBA } from '../../utils/ColorUtils';
export const Filler = ({item, background}) => {
export const Filler = ({ item, background }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const currentEditingNote = useEditorStore(state => state.currentEditingNote);
const color = 'gray';
@@ -18,12 +18,11 @@ export const Filler = ({item, background}) => {
position: 'absolute',
width: '110%',
height: '150%',
backgroundColor:currentEditingNote === item.id ? hexToRGBA(colors[color], 0.12) : null,
borderLeftWidth:5,
borderLeftColor:currentEditingNote === item.id ? colors[item.color || 'accent'] : 'transparent'
}}>
</View>
) : null
backgroundColor: currentEditingNote === item.id ? hexToRGBA(colors[color], 0.12) : null,
borderLeftWidth: 5,
borderLeftColor:
currentEditingNote === item.id ? colors[item.color || 'accent'] : 'transparent'
}}
></View>
) : null;
};

View File

@@ -8,20 +8,13 @@ import { ActionStrip } from './action-strip';
import { Filler } from './back-fill';
import { SelectionIcon } from './selection';
const SelectionWrapper = ({
children,
item,
background,
onLongPress,
onPress,
testID,
}) => {
const SelectionWrapper = ({ children, item, background, onLongPress, onPress, testID }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const [actionStrip, setActionStrip] = useState(false);
const settings = useSettingStore(state => state.settings);
const listMode = item.type === "notebook" ? settings.notebooksListMode : settings.notesListMode
const compactMode = (item.type === 'notebook' || item.type === 'note') && listMode === "compact"
const listMode = item.type === 'notebook' ? settings.notebooksListMode : settings.notesListMode;
const compactMode = (item.type === 'notebook' || item.type === 'note') && listMode === 'compact';
const _onLongPress = () => {
if (history.selectedItemsList.length > 0) return;
@@ -65,11 +58,10 @@ const SelectionWrapper = ({
borderRadius: 0,
overflow: 'hidden',
paddingHorizontal: 12,
paddingVertical:compactMode ? 8 : 12,
}}>
{actionStrip ? (
<ActionStrip note={item} setActionStrip={setActionStrip} />
) : null}
paddingVertical: compactMode ? 8 : 12
}}
>
{actionStrip ? <ActionStrip note={item} setActionStrip={setActionStrip} /> : null}
{item.type === 'note' ? <Filler background={background} item={item} /> : null}
<SelectionIcon

View File

@@ -1,14 +1,14 @@
import React, {useEffect, useState} from 'react';
import {TouchableOpacity, View} from 'react-native';
import React, { useEffect, useState } from 'react';
import { TouchableOpacity, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
import {useSelectionStore} from '../../provider/stores';
import {SIZE} from '../../utils/SizeUtils';
import { useTracked } from '../../provider';
import { Actions } from '../../provider/Actions';
import { useSelectionStore } from '../../provider/stores';
import { SIZE } from '../../utils/SizeUtils';
export const SelectionIcon = ({setActionStrip, item,compactMode}) => {
export const SelectionIcon = ({ setActionStrip, item, compactMode }) => {
const [state, dispatch] = useTracked();
const {colors} = state;
const { colors } = state;
const selectionMode = useSelectionStore(state => state.selectionMode);
const selectedItemsList = useSelectionStore(state => state.selectedItemsList);
@@ -18,9 +18,7 @@ export const SelectionIcon = ({setActionStrip, item,compactMode}) => {
useEffect(() => {
if (selectionMode) {
setActionStrip(false);
let exists = selectedItemsList.filter(
o => o.dateCreated === item.dateCreated
);
let exists = selectedItemsList.filter(o => o.dateCreated === item.dateCreated);
if (exists[0]) {
if (!selected) {
@@ -34,7 +32,7 @@ export const SelectionIcon = ({setActionStrip, item,compactMode}) => {
}
}, [selectedItemsList, item.id]);
onPress = () => {
const onPress = () => {
setSelectedItem(item);
};
@@ -44,7 +42,7 @@ export const SelectionIcon = ({setActionStrip, item,compactMode}) => {
display: 'flex',
opacity: 1,
width: '10%',
height:compactMode ? 40 : 70,
height: compactMode ? 40 : 70,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.bg,
@@ -52,7 +50,8 @@ export const SelectionIcon = ({setActionStrip, item,compactMode}) => {
marginRight: 10,
borderWidth: 1,
borderColor: selected ? colors.accent : colors.border
}}>
}}
>
<TouchableOpacity
activeOpacity={1}
onPress={onPress}
@@ -60,13 +59,10 @@ export const SelectionIcon = ({setActionStrip, item,compactMode}) => {
justifyContent: 'center',
alignItems: 'center',
height: 70
}}>
}}
>
{selected && (
<Icon
size={SIZE.xl}
color={selected ? colors.accent : colors.icon}
name="check"
/>
<Icon size={SIZE.xl} color={selected ? colors.accent : colors.icon} name="check" />
)}
</TouchableOpacity>
</View>

View File

@@ -1,15 +1,15 @@
import React from 'react';
import { View} from 'react-native';
import { View } from 'react-native';
const Seperator = ({half = false}) => {
const Seperator = ({ half = false }) => {
return (
<View
style={{
width: half ? 7.5 :15,
height: half ? 7.5 : 15,
width: half ? 7.5 : 15,
height: half ? 7.5 : 15
}}
/>
);
};
export default Seperator
export default Seperator;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Dimensions, StyleSheet, View } from 'react-native';
const Circle = ({size, color, position}) => {
const Circle = ({ size, color, position }) => {
let style = {
wrapper: {
flexDirection: 'row',
@@ -21,7 +21,7 @@ const Circle = ({size, color, position}) => {
);
};
const Donut = ({size, color, position}) => {
const Donut = ({ size, color, position }) => {
let style = {
wrapper: {
flexDirection: 'row',
@@ -42,7 +42,7 @@ const Donut = ({size, color, position}) => {
);
};
const Triangle = ({size, color, position}) => {
const Triangle = ({ size, color, position }) => {
let style = {
wrapper: {
flexDirection: 'row',
@@ -59,7 +59,7 @@ const Triangle = ({size, color, position}) => {
borderLeftColor: 'transparent',
borderRightColor: 'transparent',
borderBottomColor: color,
transform: [{rotate: '180deg'}]
transform: [{ rotate: '180deg' }]
}
};
return (
@@ -69,7 +69,7 @@ const Triangle = ({size, color, position}) => {
);
};
const DiamondNarrow = ({size, color, position}) => {
const DiamondNarrow = ({ size, color, position }) => {
let style = {
wrapper: {
flexDirection: 'row',
@@ -111,7 +111,7 @@ const DiamondNarrow = ({size, color, position}) => {
);
};
const CutDiamond = ({size, color, position}) => {
const CutDiamond = ({ size, color, position }) => {
let style = {
wrapper: {
flexDirection: 'row',
@@ -153,25 +153,16 @@ const CutDiamond = ({size, color, position}) => {
);
};
const Shapes = ({
primaryColor,
secondaryColor,
height,
figures,
borderRadius,
style
}) => {
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}
{ 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
};
@@ -204,32 +195,17 @@ const Shapes = ({
if (e.name === 'circle') {
arrFigures.push(
<Circle
key={i}
size={sizefigure}
color={config.secondaryColor}
position={position}
/>
<Circle key={i} size={sizefigure} color={config.secondaryColor} position={position} />
);
}
if (e.name === 'donut') {
arrFigures.push(
<Donut
key={i}
size={sizefigure}
color={config.secondaryColor}
position={position}
/>
<Donut key={i} size={sizefigure} color={config.secondaryColor} position={position} />
);
}
if (e.name === 'triangle') {
arrFigures.push(
<Triangle
key={i}
size={sizefigure}
color={config.secondaryColor}
position={position}
/>
<Triangle key={i} size={sizefigure} color={config.secondaryColor} position={position} />
);
}
if (e.name === 'diamondNarrow') {
@@ -244,12 +220,7 @@ const Shapes = ({
}
if (e.name === 'cutDiamond') {
arrFigures.push(
<CutDiamond
key={i}
size={sizefigure}
color={config.secondaryColor}
position={position}
/>
<CutDiamond key={i} size={sizefigure} color={config.secondaryColor} position={position} />
);
}
});
@@ -266,7 +237,8 @@ const Shapes = ({
borderBottomLeftRadius: config.borderRadius,
borderBottomRightRadius: config.borderRadius,
...style
}}>
}}
>
<>{buildFigures()}</>
</View>
);
@@ -284,4 +256,3 @@ const styles = StyleSheet.create({
});
export { Shapes };

View File

@@ -1,13 +1,13 @@
import React from 'react';
import {Platform, View} from 'react-native';
import { Platform, View } from 'react-native';
import ActionSheet from 'react-native-actions-sheet';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {useTracked} from '../../provider';
import {useSettingStore} from '../../provider/stores';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTracked } from '../../provider';
import { useSettingStore } from '../../provider/stores';
import layoutmanager from '../../utils/layout-manager';
import {PremiumToast} from '../Premium/premium-toast';
import {Toast} from '../Toast';
import {BouncingView} from '../Transitions/bouncing-view';
import { PremiumToast } from '../Premium/premium-toast';
import { Toast } from '../Toast';
import { BouncingView } from '../Transitions/bouncing-view';
const SheetWrapper = ({
children,
@@ -20,7 +20,7 @@ const SheetWrapper = ({
keyboardMode
}) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const deviceMode = useSettingStore(state => state.deviceMode);
const sheetKeyboardHandler = useSettingStore(state => state.sheetKeyboardHandler);
const largeTablet = deviceMode === 'tablet';
@@ -57,7 +57,7 @@ const SheetWrapper = ({
}
};
console.log('Sheet keyboard handler',sheetKeyboardHandler)
console.log('Sheet keyboard handler', sheetKeyboardHandler);
return (
<ActionSheet
@@ -74,27 +74,21 @@ const SheetWrapper = ({
indicatorColor={colors.nav}
onOpen={_onOpen}
keyboardDismissMode="none"
overlayColor={pitchBlack? '#585858' : "#000000"}
overlayColor={pitchBlack ? '#585858' : '#000000'}
keyboardShouldPersistTaps="always"
ExtraOverlayComponent={
<>
<Toast context="local" />
<PremiumToast
context="sheet"
close={() => fwdRef?.current?.hide()}
offset={50}
/>
<PremiumToast context="sheet" close={() => fwdRef?.current?.hide()} offset={50} />
</>
}
onClose={_onClose}>
onClose={_onClose}
>
<BouncingView>
{children}
<View
style={{
height:
Platform.OS === 'ios' && insets.bottom !== 0
? insets.bottom + 5
: 20
height: Platform.OS === 'ios' && insets.bottom !== 0 ? insets.bottom + 5 : 20
}}
/>
</BouncingView>

View File

@@ -1,15 +1,15 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {useMessageStore, useSelectionStore} from '../../provider/stores';
import {hexToRGBA} from '../../utils/ColorUtils';
import {SIZE} from '../../utils/SizeUtils';
import {PressableButton} from '../PressableButton';
import { useTracked } from '../../provider';
import { useMessageStore, useSelectionStore } from '../../provider/stores';
import { hexToRGBA } from '../../utils/ColorUtils';
import { SIZE } from '../../utils/SizeUtils';
import { PressableButton } from '../PressableButton';
import Paragraph from '../Typography/Paragraph';
export const Card = ({color}) => {
const [state,] = useTracked();
export const Card = ({ color }) => {
const [state] = useTracked();
const colors = state.colors;
color = color ? color : colors.accent;
@@ -27,8 +27,9 @@ export const Card = ({color}) => {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
paddingHorizontal: 0,
}}>
paddingHorizontal: 0
}}
>
<View
style={{
width: 40,
@@ -41,7 +42,8 @@ export const Card = ({color}) => {
borderRadius: 100,
alignItems: 'center',
justifyContent: 'center'
}}>
}}
>
<Icon
size={SIZE.lg}
color={messageBoardState.type === 'error' ? colors.errorText : color}
@@ -53,7 +55,8 @@ export const Card = ({color}) => {
style={{
marginLeft: 10,
maxWidth: '70%'
}}>
}}
>
<Paragraph color={colors.icon} size={SIZE.xs}>
{messageBoardState.message}
</Paragraph>
@@ -61,7 +64,8 @@ export const Card = ({color}) => {
style={{
maxWidth: '100%'
}}
color={colors.heading}>
color={colors.heading}
>
{messageBoardState.actionText}
</Paragraph>
</View>
@@ -74,7 +78,8 @@ export const Card = ({color}) => {
alignItems: 'center',
position: 'absolute',
right: 6
}}>
}}
>
<Icon
name="chevron-right"
color={messageBoardState.type === 'error' ? colors.red : color}

View File

@@ -1,28 +1,21 @@
import React from 'react';
import {ActivityIndicator, useWindowDimensions, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider';
import {COLORS_NOTE} from '../../utils/Colors';
import {normalize, SIZE} from '../../utils/SizeUtils';
import {Button} from '../Button';
import {Placeholder} from '../ListPlaceholders';
import { ActivityIndicator, useWindowDimensions, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { COLORS_NOTE } from '../../utils/Colors';
import { normalize, SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import { Placeholder } from '../ListPlaceholders';
import Seperator from '../Seperator';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
export const Empty = ({
loading = true,
placeholderData,
absolute,
headerProps,
type,
screen
}) => {
export const Empty = ({ loading = true, placeholderData, absolute, headerProps, type, screen }) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const insets = useSafeAreaInsets();
const {height} = useWindowDimensions();
const { height } = useWindowDimensions();
return (
<View
@@ -34,13 +27,15 @@ export const Empty = ({
height: height - 250 - insets.top,
width: '100%'
}
]}>
]}
>
<View
style={{
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center'
}}>
}}
>
<Placeholder
color={COLORS_NOTE[headerProps.color?.toLowerCase()] || colors.accent}
w={normalize(150)}
@@ -54,7 +49,8 @@ export const Empty = ({
textAlign: 'center',
width: '80%'
}}
color={colors.icon}>
color={colors.icon}
>
{loading ? placeholderData.loading : placeholderData.paragraph}
</Paragraph>
<Seperator />
@@ -68,9 +64,7 @@ export const Empty = ({
fontSize={SIZE.md}
accentColor="bg"
accentText={
COLORS_NOTE[headerProps.color?.toLowerCase()]
? headerProps.color
: 'accent'
COLORS_NOTE[headerProps.color?.toLowerCase()] ? headerProps.color : 'accent'
}
/>
) : loading ? (
@@ -78,9 +72,7 @@ export const Empty = ({
style={{
height: 35
}}
color={
COLORS_NOTE[headerProps.color?.toLowerCase()] || colors.accent
}
color={COLORS_NOTE[headerProps.color?.toLowerCase()] || colors.accent}
/>
) : (
<View

View File

@@ -1,6 +1,6 @@
import React from 'react';
import {View} from 'react-native';
import { View } from 'react-native';
export const Footer = () => {
return <View style={{height: 150}} />;
return <View style={{ height: 150 }} />;
};

View File

@@ -26,7 +26,7 @@ export const Header = React.memo(
height
}) => {
const [state] = useTracked();
const {colors} = state;
const { colors } = state;
const announcements = useMessageStore(state => state.announcements);
return announcements.length !== 0 && !noAnnouncement ? (
@@ -39,16 +39,16 @@ export const Header = React.memo(
width: '100%',
justifyContent: 'center',
alignItems: 'center'
}}>
{messageCard ? (
<Card color={COLORS_NOTE[color?.toLowerCase()] || colors.accent} />
) : null}
}}
>
{messageCard ? <Card color={COLORS_NOTE[color?.toLowerCase()] || colors.accent} /> : null}
</View>
) : (
<View
style={{
width: '100%'
}}>
}}
>
<View
style={{
minHeight: height || 195,
@@ -59,14 +59,16 @@ export const Header = React.memo(
backgroundColor: COLORS_NOTE[color?.toLowerCase()]
? hexToRGBA(COLORS_NOTE[color?.toLowerCase()], 0.15)
: color || colors.shade
}}>
}}
>
<View
style={{
right: 0,
paddingRight: 12,
bottom: 0,
position: 'absolute'
}}>
}}
>
<Placeholder
color={COLORS_NOTE[color?.toLowerCase()] || colors.accent}
w={normalize(150)}
@@ -78,10 +80,9 @@ export const Header = React.memo(
<View
style={{
marginTop: 15
}}>
<Heading
style={{marginBottom: paragraph ? 0 : 0}}
size={SIZE.xxxl * 1.2}>
}}
>
<Heading style={{ marginBottom: paragraph ? 0 : 0 }} size={SIZE.xxxl * 1.2}>
<Heading size={SIZE.xxxl * 1.2} color={colors.accent}>
{title.slice(0, 1) === '#' ? '#' : null}
</Heading>
@@ -112,3 +113,5 @@ export const Header = React.memo(
);
}
);
Header.displayName = 'Header';

Some files were not shown because too many files have changed in this diff Show More