mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-02 20:21:19 +02:00
Merge branch 'develop'
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
- Added issue reporting from within the app. Click on "Report an issue" in settings.
|
||||
- Fixed undo manager not updated on cut.
|
||||
- Fixed note is not saved when content is directly pasted
|
||||
- Fixed editor is empty sometimes when note is opened
|
||||
- Other minor performance improvements
|
||||
- Add new header for notebook screen & topic
|
||||
- Ensure that products are loaded before showing pricing
|
||||
- Show notebook & topic on note items
|
||||
- Fixed sorting on items in groups
|
||||
- Fixed editor losing focus in checklists
|
||||
- Fixed cursor jump to end of paragraph on removing new line
|
||||
- Minor bug fixes and performance improvements.
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -224,8 +224,16 @@ function setTheme() {
|
||||
.tox .tox-toolbar__primary {
|
||||
background: none !important;
|
||||
border-bottom: 1px solid ${pageTheme.colors.nav} !important;
|
||||
}`;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: white !important;
|
||||
background: ${pageTheme.colors.accent} !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
`;
|
||||
|
||||
let node2 = `
|
||||
.mce-content-body table[data-mce-selected], {
|
||||
@@ -254,6 +262,24 @@ function setTheme() {
|
||||
opacity:0.5;
|
||||
}
|
||||
|
||||
.mce-content-body a {
|
||||
color: ${pageTheme.colors.accent} !important;
|
||||
}
|
||||
|
||||
.mce-content-body [data-mce-selected="inline-boundary"] {
|
||||
background-color: ${pageTheme.colors.shade} !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: white !important;
|
||||
background: ${pageTheme.colors.accent} !important;
|
||||
}
|
||||
|
||||
|
||||
.mce-content-body a[data-mce-selected] {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
span.attachment {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
@@ -4,70 +4,75 @@ body {
|
||||
font-family:"Open Sans";
|
||||
}
|
||||
|
||||
#formBox textarea {
|
||||
font-family: "Open Sans";
|
||||
font-weight: 600 !important;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
resize: none;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
#formBox {
|
||||
margin-block-end: 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#titlebar {
|
||||
background-color: transparent;
|
||||
padding-left: 0px;
|
||||
padding-right: 12px;
|
||||
min-height: 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
#formBox > div,
|
||||
#formBox > textarea {
|
||||
word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#formBox > textarea {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
.app-main {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
padding-top: 4px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#textCopy {
|
||||
font-family: "Open Sans";
|
||||
font-weight: 600 !important;
|
||||
font-size: 32px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 5px;
|
||||
padding-right: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
#formBox > div {
|
||||
min-height: 45px;
|
||||
}
|
||||
|
||||
.info-bar {
|
||||
font-family: "Open Sans";
|
||||
color: gray;
|
||||
font-size: 11px;
|
||||
height: 15px;
|
||||
display: flex;
|
||||
padding-left: 14px !important;
|
||||
justify-content: space-between;
|
||||
}
|
||||
#formBox input {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 600 !important;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
resize: none;
|
||||
font-size: 25px;
|
||||
height: 45x;
|
||||
padding-top:0px;
|
||||
padding-bottom:0px;
|
||||
}
|
||||
|
||||
#formBox {
|
||||
margin-block-end: 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#titlebar {
|
||||
background-color: transparent;
|
||||
padding-left: 0px;
|
||||
padding-right: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
#formBox > div,
|
||||
#formBox > input {
|
||||
word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#titlebar input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.info-bar {
|
||||
font-family: 'Open Sans';
|
||||
color: gray;
|
||||
font-size: 11.5px;
|
||||
height: 13px;
|
||||
display: flex;
|
||||
padding-left: 14px !important;
|
||||
justify-content: space-between;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.info-bar a {
|
||||
text-decoration: none;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
#infowords,
|
||||
#infodate,
|
||||
#infosaved {
|
||||
font-family: 'Open Sans';
|
||||
margin-right: 5px;
|
||||
margin-left: 0px;
|
||||
border-radius: 5px;
|
||||
margin-top: 0;
|
||||
height: 16px;
|
||||
padding-top: 2.5px;
|
||||
}
|
||||
|
||||
.info-bar a {
|
||||
text-decoration: none;
|
||||
|
||||
@@ -136,6 +136,7 @@ function init_tiny(size) {
|
||||
'media imagetools table paste wordcount autoresize directionality blockescape contenthandler'
|
||||
],
|
||||
toolbar: false,
|
||||
keep_styles:false,
|
||||
paste_data_images: true,
|
||||
statusbar: false,
|
||||
textpattern_patterns: markdownPatterns,
|
||||
@@ -263,6 +264,104 @@ function init_tiny(size) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
init_instance_callback: function (_editor) {
|
||||
editor = _editor;
|
||||
setTheme();
|
||||
|
||||
editor.on('SelectionChange', function (e) {
|
||||
selectchange();
|
||||
});
|
||||
|
||||
editor.on('ClearUndos', onUndoChange);
|
||||
editor.on('Undo', onUndoChange);
|
||||
editor.on('Redo', onUndoChange);
|
||||
editor.on('TypingUndos', onUndoChange);
|
||||
editor.on('BeforeAddUndo', onUndoChange);
|
||||
editor.on('AddUndo', onUndoChange);
|
||||
editor.on('cut', function () {
|
||||
onChange({type: 'cut'});
|
||||
onUndoChange();
|
||||
});
|
||||
editor.on('copy', onUndoChange);
|
||||
editor.on('paste', function () {
|
||||
onChange({type: 'paste'});
|
||||
});
|
||||
|
||||
editor.on('focus', function () {
|
||||
reactNativeEventHandler('focus', 'editor');
|
||||
});
|
||||
|
||||
editor.on('SetContent', function (event) {
|
||||
if (globalThis.isClearingNoteData) {
|
||||
globalThis.isClearingNoteData = false;
|
||||
return;
|
||||
}
|
||||
setTimeout(function () {
|
||||
editor.undoManager.transact(function () {});
|
||||
}, 1000);
|
||||
if (!event.paste) {
|
||||
reactNativeEventHandler('noteLoaded', true);
|
||||
}
|
||||
});
|
||||
|
||||
editor.on('NewBlock', function (e) {
|
||||
console.log('New Block');
|
||||
const {newBlock} = e;
|
||||
let target;
|
||||
if (newBlock) {
|
||||
target = newBlock.previousElementSibling;
|
||||
}
|
||||
if (target && target.classList.contains(COLLAPSED_KEY)) {
|
||||
target.classList.remove(COLLAPSED_KEY);
|
||||
collapseElement(target);
|
||||
}
|
||||
});
|
||||
|
||||
editor.on('touchstart mousedown', function (e) {
|
||||
const {target} = e;
|
||||
if (
|
||||
e.offsetX < 6 &&
|
||||
collapsibleTags[target.tagName] &&
|
||||
target.parentElement &&
|
||||
target.parentElement.tagName === 'BODY'
|
||||
) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
editor.undoManager.transact(function () {
|
||||
if (target.classList.contains(COLLAPSED_KEY)) {
|
||||
target.classList.remove(COLLAPSED_KEY);
|
||||
} else {
|
||||
target.classList.add(COLLAPSED_KEY);
|
||||
}
|
||||
collapseElement(target);
|
||||
editor.getHTML().then(function (html) {
|
||||
reactNativeEventHandler('tiny', html);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
editor.on('tap', function (e) {
|
||||
if (
|
||||
e.target.classList.contains('mce-content-body') &&
|
||||
!e.target.innerText.length > 0
|
||||
) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
editor.on('ScrollIntoView', function (e) {
|
||||
e.preventDefault();
|
||||
e.elm.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest'
|
||||
});
|
||||
});
|
||||
editor.on('input', onChange);
|
||||
editor.on('keyup', onChange);
|
||||
editor.on('NodeChange', onChange);
|
||||
editor.on('compositionend', onChange);
|
||||
},
|
||||
setup: function (_editor) {
|
||||
editor = _editor;
|
||||
editor.ui.registry.addButton('deleteimage', {
|
||||
|
||||
@@ -1118,7 +1118,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1670;
|
||||
CURRENT_PROJECT_VERSION = 1680;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
@@ -1191,7 +1191,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.6.70;
|
||||
MARKETING_VERSION = 1.6.80;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1219,7 +1219,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Notesnook/Notesnook.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1670;
|
||||
CURRENT_PROJECT_VERSION = 1680;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@@ -1291,7 +1291,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.6.70;
|
||||
MARKETING_VERSION = 1.6.80;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
@@ -1449,7 +1449,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1670;
|
||||
CURRENT_PROJECT_VERSION = 1680;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@@ -1460,7 +1460,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.6.70;
|
||||
MARKETING_VERSION = 1.6.80;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
@@ -1490,7 +1490,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1670;
|
||||
CURRENT_PROJECT_VERSION = 1680;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@@ -1501,7 +1501,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.6.70;
|
||||
MARKETING_VERSION = 1.6.80;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1530,7 +1530,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1670;
|
||||
CURRENT_PROJECT_VERSION = 1680;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@@ -1603,7 +1603,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.6.70;
|
||||
MARKETING_VERSION = 1.6.80;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
@@ -1633,7 +1633,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1670;
|
||||
CURRENT_PROJECT_VERSION = 1680;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@@ -1706,7 +1706,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.6.70;
|
||||
MARKETING_VERSION = 1.6.80;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
- Added issue reporting from within the app. Click on "Report an issue" in settings.
|
||||
- Fixed undo manager not updated on cut.
|
||||
- Fixed note is not saved when content is directly pasted
|
||||
- Fixed editor is empty sometimes when note is opened
|
||||
- Other minor performance improvements
|
||||
- Add new header for notebook screen & topic
|
||||
- Ensure that products are loaded before showing pricing
|
||||
- Show notebook & topic on note items
|
||||
- Fixed sorting on items in groups
|
||||
- Fixed editor losing focus in checklists
|
||||
- Fixed cursor jump to end of paragraph on removing new line
|
||||
- Minor bug fixes and performance improvements.
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -1,17 +1,19 @@
|
||||
import React, {useRef, useState} from 'react';
|
||||
import {Linking, Platform, Text, TextInput, View} from 'react-native';
|
||||
import deviceInfoModule from 'react-native-device-info';
|
||||
import {useTracked} from '../../provider';
|
||||
import {eSendEvent, ToastEvent} from '../../services/EventManager';
|
||||
import {APP_VERSION} from '../../utils';
|
||||
import {db} from '../../utils/database';
|
||||
import {eCloseProgressDialog} from '../../utils/Events';
|
||||
import {openLinkInBrowser} from '../../utils/functions';
|
||||
import {SIZE} from '../../utils/SizeUtils';
|
||||
import {sleep} from '../../utils/TimeUtils';
|
||||
import {Button} from '../Button';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Linking, Platform, Text, TextInput, View } from 'react-native';
|
||||
import { useTracked } from '../../provider';
|
||||
import { useUserStore } from '../../provider/stores';
|
||||
import { eSendEvent, ToastEvent } from '../../services/EventManager';
|
||||
import PremiumService from '../../services/PremiumService';
|
||||
import { APP_VERSION } from '../../utils';
|
||||
import { db } from '../../utils/database';
|
||||
import { eCloseProgressDialog } from '../../utils/Events';
|
||||
import { openLinkInBrowser } from '../../utils/functions';
|
||||
import { SIZE } from '../../utils/SizeUtils';
|
||||
import { sleep } from '../../utils/TimeUtils';
|
||||
import { Button } from '../Button';
|
||||
import DialogHeader from '../Dialog/dialog-header';
|
||||
import {presentDialog} from '../Dialog/functions';
|
||||
import { presentDialog } from '../Dialog/functions';
|
||||
import Seperator from '../Seperator';
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
|
||||
@@ -20,6 +22,7 @@ export const Issue = () => {
|
||||
const colors = state.colors;
|
||||
const body = useRef(null);
|
||||
const title = useRef(null);
|
||||
const user = useUserStore(state => state.user);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const onPress = async () => {
|
||||
@@ -30,15 +33,21 @@ export const Issue = () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
let issue_url = await db.debug.report(
|
||||
title.current,
|
||||
body.current +
|
||||
let issue_url = await db.debug.report({
|
||||
title: title.current,
|
||||
body:
|
||||
body.current +
|
||||
`\n_______________
|
||||
**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'}`,
|
||||
userId: user?.id
|
||||
});
|
||||
setLoading(false);
|
||||
eSendEvent(eCloseProgressDialog);
|
||||
await sleep(300);
|
||||
@@ -55,10 +64,21 @@ Model: ${Platform.constants.Brand}-${Platform.constants.Model}-${Platform.consta
|
||||
onPress={() => {
|
||||
Linking.openURL(issue_url);
|
||||
}}>
|
||||
{issue_url}
|
||||
</Text>
|
||||
{issue_url}.
|
||||
</Text>{' '}
|
||||
Please note that we will respond to your issue on the given link. We
|
||||
recommend that you save it.
|
||||
</Text>
|
||||
),
|
||||
positiveText: 'Copy link',
|
||||
positivePress: () => {
|
||||
Clipboard.setString(issue_url);
|
||||
ToastEvent.show({
|
||||
heading: 'Issue url copied!',
|
||||
type: 'success',
|
||||
context: 'global'
|
||||
});
|
||||
},
|
||||
negativeText: 'Close'
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -141,7 +161,7 @@ For example:
|
||||
marginTop: 10,
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
The information above will be is publically available on{' '}
|
||||
The information above will be publically available at{' '}
|
||||
<Text
|
||||
onPress={() => {
|
||||
Linking.openURL('https://github.com/streetwriters/notesnook');
|
||||
@@ -152,8 +172,8 @@ For example:
|
||||
}}>
|
||||
github.com/streetwriters/notesnook.
|
||||
</Text>{' '}
|
||||
If you want to ask something 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',
|
||||
|
||||
@@ -97,64 +97,31 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
zIndex: 10,
|
||||
elevation: 10
|
||||
elevation: 10,
|
||||
marginBottom:2.5
|
||||
}}>
|
||||
{!isTrash && item.notebooks
|
||||
? item.notebooks?.slice(0, 1)?.map(_item => {
|
||||
let notebook = db.notebooks.notebook(_item.id);
|
||||
notebook = notebook?.data;
|
||||
|
||||
return notebook ? (
|
||||
<Button
|
||||
title={notebook.title}
|
||||
key={_item}
|
||||
height={20}
|
||||
icon="book-outline"
|
||||
type="grayBg"
|
||||
fontSize={SIZE.xs + 1}
|
||||
iconSize={SIZE.sm}
|
||||
textStyle={{
|
||||
marginRight: 0,
|
||||
fontWeight: 'normal',
|
||||
fontFamily: null
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
marginRight: 5,
|
||||
borderWidth: 0.5,
|
||||
borderColor: colors.icon,
|
||||
paddingHorizontal: 6
|
||||
}}
|
||||
onPress={() => navigateToNotebook(notebook)}
|
||||
/>
|
||||
) : null;
|
||||
})
|
||||
: null}
|
||||
{!isTrash && tags
|
||||
? tags.slice(0, 2)?.map(item => (
|
||||
<Button
|
||||
title={'#' + db.tags.alias(item)}
|
||||
key={item}
|
||||
height={20}
|
||||
textStyle={{
|
||||
marginRight: 0,
|
||||
fontWeight: 'normal',
|
||||
fontFamily: null
|
||||
}}
|
||||
type="grayBg"
|
||||
fontSize={SIZE.xs + 1}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
marginRight: 5,
|
||||
borderWidth: 0.5,
|
||||
borderColor: colors.icon,
|
||||
paddingHorizontal: 6,
|
||||
zIndex: 10
|
||||
}}
|
||||
onPress={() => navigateToTag(item)}
|
||||
/>
|
||||
))
|
||||
: null}
|
||||
{getNotebook().map(_item => (
|
||||
<Button
|
||||
title={_item.title}
|
||||
key={_item}
|
||||
height={20}
|
||||
icon="book-outline"
|
||||
type="grayBg"
|
||||
fontSize={SIZE.xs + 1}
|
||||
iconSize={SIZE.sm}
|
||||
textStyle={{
|
||||
marginRight: 0
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
marginRight: 5,
|
||||
borderWidth: 0.5,
|
||||
borderColor: colors.icon,
|
||||
paddingHorizontal: 6
|
||||
}}
|
||||
onPress={() => navigateToTopic(_item.topic)}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -189,11 +156,21 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
}}>
|
||||
{!isTrash ? (
|
||||
<>
|
||||
{item.conflicted ? (
|
||||
<Icon
|
||||
name="alert-circle"
|
||||
style={{
|
||||
marginRight: 6
|
||||
}}
|
||||
size={SIZE.sm}
|
||||
color={colors.red}
|
||||
/>
|
||||
) : null}
|
||||
<TimeSince
|
||||
style={{
|
||||
fontSize: SIZE.xs + 1,
|
||||
color: colors.icon,
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}
|
||||
time={item.dateCreated}
|
||||
updateFrequency={
|
||||
@@ -201,27 +178,26 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
}
|
||||
/>
|
||||
|
||||
{item.color ? (
|
||||
{/* {db.attachments?.ofNote(item.id)?.length === 0 ? (
|
||||
<View
|
||||
key={item}
|
||||
style={{
|
||||
width: SIZE.xs,
|
||||
height: SIZE.xs,
|
||||
borderRadius: 100,
|
||||
backgroundColor: COLORS_NOTE[item.color.toLowerCase()],
|
||||
marginRight: -4.5,
|
||||
marginRight: 10
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginRight: 6
|
||||
}}>
|
||||
<Icon name="attachment" size={SIZE.md} color={colors.icon} />
|
||||
<Paragraph color={colors.icon} size={SIZE.xs + 1}>
|
||||
10
|
||||
</Paragraph>
|
||||
</View>
|
||||
) : null} */}
|
||||
|
||||
{item.pinned ? (
|
||||
<Icon
|
||||
style={{marginRight: 10}}
|
||||
name="pin"
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
marginRight: 5
|
||||
marginRight: 6
|
||||
}}
|
||||
color={
|
||||
COLORS_NOTE[item.color?.toLowerCase()] || colors.accent
|
||||
@@ -231,11 +207,10 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
|
||||
{item.locked ? (
|
||||
<Icon
|
||||
style={{marginRight: 10}}
|
||||
name="lock"
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}
|
||||
color={colors.icon}
|
||||
/>
|
||||
@@ -246,35 +221,35 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
name="star"
|
||||
size={SIZE.md}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}
|
||||
color="orange"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.conflicted ? (
|
||||
<View
|
||||
style={{
|
||||
marginRight: 10,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}}>
|
||||
<Icon
|
||||
name="alert-circle"
|
||||
size={SIZE.xs + 1}
|
||||
color={colors.red}
|
||||
/>
|
||||
<Heading
|
||||
size={SIZE.xs}
|
||||
style={{
|
||||
color: colors.red,
|
||||
marginLeft: 2
|
||||
}}>
|
||||
CONFLICTS
|
||||
</Heading>
|
||||
</View>
|
||||
) : null}
|
||||
{!isTrash && !compactMode && tags
|
||||
? tags.slice(0, 3)?.map(item => (
|
||||
<Button
|
||||
title={'#' + db.tags.alias(item)}
|
||||
key={item}
|
||||
height={20}
|
||||
type="gray"
|
||||
textStyle={{
|
||||
textDecorationLine: 'underline'
|
||||
}}
|
||||
hitSlop={{top: 8, bottom: 12, left: 0, right: 0}}
|
||||
fontSize={SIZE.xs + 1}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: 2,
|
||||
marginRight: 4,
|
||||
zIndex: 10,
|
||||
maxWidth: tags?.slice(0, 3)?.length > 1 ? 130 : null
|
||||
}}
|
||||
onPress={() => navigateToTag(item)}
|
||||
/>
|
||||
))
|
||||
: null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
@@ -282,7 +257,7 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
color={colors.icon}
|
||||
size={SIZE.xs}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
Deleted on{' '}
|
||||
{item && item.dateDeleted
|
||||
@@ -294,7 +269,7 @@ const NoteItem = ({item, isTrash, tags}) => {
|
||||
color={colors.accent}
|
||||
size={SIZE.xs}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
{item.itemType[0].toUpperCase() + item.itemType.slice(1)}
|
||||
</Paragraph>
|
||||
|
||||
@@ -124,9 +124,9 @@ export const NotebookItem = ({item, isTopic = false, notebookID, isTrash}) => {
|
||||
}}>
|
||||
<Paragraph
|
||||
color={colors.accent}
|
||||
size={SIZE.xs}
|
||||
size={SIZE.xs + 1}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
{isTopic ? 'Topic' : 'Notebook'}
|
||||
</Paragraph>
|
||||
@@ -135,20 +135,20 @@ export const NotebookItem = ({item, isTopic = false, notebookID, isTrash}) => {
|
||||
<>
|
||||
<Paragraph
|
||||
color={colors.icon}
|
||||
size={SIZE.xs}
|
||||
size={SIZE.xs + 1}
|
||||
style={{
|
||||
textAlignVertical: 'center',
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
{'Deleted on ' +
|
||||
new Date(item.dateDeleted).toISOString().slice(0, 10)}
|
||||
</Paragraph>
|
||||
<Paragraph
|
||||
color={colors.accent}
|
||||
size={SIZE.xs}
|
||||
size={SIZE.xs + 1}
|
||||
style={{
|
||||
textAlignVertical: 'center',
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
{item.itemType[0].toUpperCase() + item.itemType.slice(1)}
|
||||
</Paragraph>
|
||||
@@ -156,18 +156,18 @@ export const NotebookItem = ({item, isTopic = false, notebookID, isTrash}) => {
|
||||
) : (
|
||||
<Paragraph
|
||||
color={colors.icon}
|
||||
size={SIZE.xs}
|
||||
size={SIZE.xs + 1}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
{new Date(item.dateCreated).toDateString().substring(4)}
|
||||
</Paragraph>
|
||||
)}
|
||||
<Paragraph
|
||||
color={colors.icon}
|
||||
size={SIZE.xs}
|
||||
size={SIZE.xs + 1}
|
||||
style={{
|
||||
marginRight: 10
|
||||
marginRight: 6
|
||||
}}>
|
||||
{item && totalNotes > 1
|
||||
? totalNotes + ' notes'
|
||||
@@ -178,7 +178,7 @@ export const NotebookItem = ({item, isTopic = false, notebookID, isTrash}) => {
|
||||
|
||||
{item.pinned ? (
|
||||
<Icon
|
||||
style={{marginRight: 10}}
|
||||
style={{marginRight: 6}}
|
||||
name="pin"
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
|
||||
116
apps/mobile/src/components/SimpleList/notebookheader.js
Normal file
116
apps/mobile/src/components/SimpleList/notebookheader.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import React, {useState} from 'react';
|
||||
import {Platform, View} from 'react-native';
|
||||
import {useTracked} from '../../provider';
|
||||
import {useMenuStore} from '../../provider/stores';
|
||||
import {ToastEvent} from '../../services/EventManager';
|
||||
import {getTotalNotes} from '../../utils';
|
||||
import {db} from '../../utils/database';
|
||||
import {SIZE} from '../../utils/SizeUtils';
|
||||
import {ActionIcon} from '../ActionIcon';
|
||||
import {Button} from '../Button';
|
||||
import Heading from '../Typography/Heading';
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
|
||||
export const NotebookHeader = ({notebook, onPress, onEditNotebook}) => {
|
||||
const [state] = useTracked();
|
||||
const {colors} = state;
|
||||
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
|
||||
db.settings.isPinned(notebook.id)
|
||||
);
|
||||
const setMenuPins = useMenuStore(state => state.setMenuPins);
|
||||
const totalNotes = getTotalNotes(notebook);
|
||||
|
||||
const onPinNotebook = async () => {
|
||||
try {
|
||||
if (isPinnedToMenu) {
|
||||
await db.settings.unpin(notebook.id);
|
||||
} else {
|
||||
await db.settings.pin(notebook.type, {id: notebook.id});
|
||||
ToastEvent.show({
|
||||
heading: 'Shortcut created',
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
setIsPinnedToMenu(db.settings.isPinned(notebook.id));
|
||||
setMenuPins();
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
marginBottom: 5,
|
||||
padding: 0,
|
||||
width: '100%',
|
||||
paddingVertical: 15,
|
||||
paddingHorizontal: 12,
|
||||
alignSelf: 'center',
|
||||
borderRadius: 10,
|
||||
paddingTop: 25
|
||||
}}>
|
||||
<Paragraph color={colors.icon} size={SIZE.xs + 1}>
|
||||
{new Date(notebook.dateEdited).toLocaleString()}
|
||||
</Paragraph>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<Heading size={SIZE.xxl}>{notebook.title}</Heading>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row'
|
||||
}}>
|
||||
<ActionIcon
|
||||
name={isPinnedToMenu ? 'link-variant-off' : 'link-variant'}
|
||||
onPress={onPinNotebook}
|
||||
customStyle={{
|
||||
marginRight: 15,
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
type={isPinnedToMenu ? 'grayBg' : 'grayBg'}
|
||||
color={isPinnedToMenu ? colors.accent : colors.icon}
|
||||
size={SIZE.lg}
|
||||
/>
|
||||
<ActionIcon
|
||||
size={SIZE.lg}
|
||||
onPress={onEditNotebook}
|
||||
name="pencil"
|
||||
type="grayBg"
|
||||
color={colors.icon}
|
||||
customStyle={{
|
||||
width: 40,
|
||||
height: 40
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{notebook.description && (
|
||||
<Paragraph size={SIZE.md} color={colors.pri}>
|
||||
{notebook.description}
|
||||
</Paragraph>
|
||||
)}
|
||||
|
||||
<Paragraph
|
||||
style={{
|
||||
marginTop: 10,
|
||||
fontStyle: 'italic',
|
||||
fontFamily: null
|
||||
}}
|
||||
size={SIZE.xs + 1}
|
||||
color={colors.icon}>
|
||||
{notebook.topics.length === 1
|
||||
? '1 topic'
|
||||
: `${notebook.topics.length} topics`}, {notebook && totalNotes > 1
|
||||
? totalNotes + ' notes'
|
||||
: totalNotes === 1
|
||||
? totalNotes + ' note'
|
||||
: '0 notes'}
|
||||
</Paragraph>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -66,8 +66,10 @@ class SortDialog extends React.Component {
|
||||
this.setState({
|
||||
groupOptions: _groupOptions
|
||||
});
|
||||
Navigation.setRoutesToUpdate([this.props.screen]);
|
||||
eSendEvent('groupOptionsUpdate');
|
||||
setTimeout(() => {
|
||||
Navigation.setRoutesToUpdate([this.props.screen]);
|
||||
eSendEvent('groupOptionsUpdate');
|
||||
}, 1);
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -145,7 +147,11 @@ class SortDialog extends React.Component {
|
||||
paddingHorizontal: 12
|
||||
}}>
|
||||
{this.state.groupOptions.groupBy === 'abc' ? (
|
||||
<Paragraph color={colors.icon}>
|
||||
<Paragraph
|
||||
style={{
|
||||
height: 40
|
||||
}}
|
||||
color={colors.icon}>
|
||||
No sort options available.
|
||||
</Paragraph>
|
||||
) : (
|
||||
@@ -162,7 +168,6 @@ class SortDialog extends React.Component {
|
||||
: 'checkbox-blank-circle-outline'
|
||||
}
|
||||
textStyle={{
|
||||
fontWeight: 'normal',
|
||||
color: colors.pri
|
||||
}}
|
||||
fontSize={SIZE.sm}
|
||||
@@ -183,13 +188,16 @@ class SortDialog extends React.Component {
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12
|
||||
paddingHorizontal: 0,
|
||||
borderRadius: 0
|
||||
}}>
|
||||
{Object.keys(GROUP).map((item, index) => (
|
||||
<PressableButton
|
||||
key={item}
|
||||
testID={'btn-' + item}
|
||||
type={groupOptions.groupBy === GROUP[item] ? 'shade' : 'gray'}
|
||||
type={
|
||||
groupOptions.groupBy === GROUP[item] ? 'transparent' : 'gray'
|
||||
}
|
||||
onPress={async () => {
|
||||
let _groupOptions = {
|
||||
...groupOptions,
|
||||
@@ -198,6 +206,7 @@ class SortDialog extends React.Component {
|
||||
|
||||
if (item === 'alphabetical') {
|
||||
_groupOptions.sortBy = 'title';
|
||||
_groupOptions.sortDirection = 'asc';
|
||||
} else {
|
||||
if (this.state.groupOptions.sortBy === 'title') {
|
||||
_groupOptions.sortBy = 'dateEdited';
|
||||
@@ -219,8 +228,10 @@ class SortDialog extends React.Component {
|
||||
<Paragraph
|
||||
size={SIZE.sm}
|
||||
style={{
|
||||
fontWeight:
|
||||
groupOptions.groupBy === GROUP[item] ? 'bold' : 'normal'
|
||||
fontFamily:
|
||||
groupOptions.groupBy === GROUP[item]
|
||||
? 'OpenSans-SemiBold'
|
||||
: 'OpenSans-Regular'
|
||||
}}
|
||||
color={
|
||||
groupOptions.groupBy === GROUP[item]
|
||||
@@ -229,6 +240,7 @@ class SortDialog extends React.Component {
|
||||
}>
|
||||
{item.slice(0, 1).toUpperCase() + item.slice(1, item.length)}
|
||||
</Paragraph>
|
||||
|
||||
{groupOptions.groupBy === GROUP[item] ? (
|
||||
<Icon color={colors.accent} name="check" size={SIZE.lg} />
|
||||
) : null}
|
||||
|
||||
@@ -65,7 +65,7 @@ const TagItem = ({item, index}) => {
|
||||
</Heading>
|
||||
<Paragraph
|
||||
color={colors.icon}
|
||||
size={SIZE.xs}
|
||||
size={SIZE.xs + 1}
|
||||
style={{
|
||||
marginTop: 5
|
||||
}}>
|
||||
|
||||
@@ -2,7 +2,7 @@ import {Platform} from 'react-native';
|
||||
import {Dimensions} from 'react-native';
|
||||
import create from 'zustand';
|
||||
import PremiumService from '../services/PremiumService';
|
||||
import {history, SUBSCRIPTION_STATUS} from '../utils';
|
||||
import {APP_VERSION, history, SUBSCRIPTION_STATUS} from '../utils';
|
||||
import {db} from '../utils/database';
|
||||
import {MMKV} from '../utils/mmkv';
|
||||
import {
|
||||
@@ -416,6 +416,10 @@ async function shouldShowAnnouncement(announcement) {
|
||||
platform => allowedPlatforms.indexOf(platform) > -1
|
||||
);
|
||||
|
||||
if (announcement.appVersion) {
|
||||
return announcement.appVersion === APP_VERSION;
|
||||
}
|
||||
|
||||
if (!show) return false;
|
||||
|
||||
const subStatus = PremiumService.getUser()?.subscription?.type;
|
||||
|
||||
@@ -1,33 +1,41 @@
|
||||
|
||||
export const sleep = (duration) =>
|
||||
new Promise((resolve) => setTimeout(() => resolve(), duration));
|
||||
|
||||
export function timeSince(date) {
|
||||
let seconds = Math.floor((new Date() - date) / 1000);
|
||||
|
||||
seconds = seconds + (86400 * 7 * 4);
|
||||
let interval = Math.floor(seconds / 31536000);
|
||||
|
||||
if (interval > 0.9) {
|
||||
return interval < 2 ? interval + ' year ago' : interval + ' years ago';
|
||||
return interval < 2 ? interval + 'yr ago' : interval + 'yr ago';
|
||||
}
|
||||
interval = Math.floor(seconds / 2592000);
|
||||
if (interval > 0.9) {
|
||||
return interval < 2 ? interval + ' month ago' : interval + ' months ago';
|
||||
return interval < 2 ? interval + 'mo ago' : interval + 'mo ago';
|
||||
}
|
||||
|
||||
interval = Math.floor(seconds / (86400 * 7));
|
||||
if (interval > 0.9) {
|
||||
if (interval === 4) return "1mo ago";
|
||||
return interval < 2 ? interval + 'w ago' : interval + 'w ago';
|
||||
}
|
||||
|
||||
interval = Math.floor(seconds / 86400);
|
||||
if (interval > 0.9) {
|
||||
return interval < 2 ? interval + ' day ago' : interval + ' days ago';
|
||||
return interval < 2 ? interval + 'd ago' : interval + 'd ago';
|
||||
}
|
||||
interval = Math.floor(seconds / 3600);
|
||||
if (interval > 0.9) {
|
||||
return interval < 2 ? interval + ' hour ago' : interval + ' hours ago';
|
||||
return interval < 2 ? interval + 'h ago' : interval + 'h ago';
|
||||
}
|
||||
interval = Math.floor(seconds / 60);
|
||||
if (interval > 0.9) {
|
||||
return interval < 2 ? interval + ' min ago' : interval + ' min ago';
|
||||
return interval < 2 ? interval + 'm ago' : interval + 'm ago';
|
||||
}
|
||||
return Math.floor(seconds) < 0
|
||||
? '0 secs ago'
|
||||
: Math.floor(seconds) + ' secs ago';
|
||||
? '0s ago'
|
||||
: Math.floor(seconds) + 's ago';
|
||||
}
|
||||
|
||||
export const timeConverter = (timestamp) => {
|
||||
|
||||
@@ -16,7 +16,7 @@ import {MMKV} from './mmkv';
|
||||
import {tabBarRef} from './Refs';
|
||||
import {SIZE} from './SizeUtils';
|
||||
|
||||
export const APP_VERSION = 1670;
|
||||
export const APP_VERSION = 1680;
|
||||
|
||||
export const Tracker = ackeeTracker.create('https://sa.streetwriters.co', {
|
||||
ignoreLocalhost: true
|
||||
|
||||
@@ -27,7 +27,6 @@ import {normalize} from '../../utils/SizeUtils';
|
||||
import {sleep, timeConverter} from '../../utils/TimeUtils';
|
||||
import tiny from './tiny/tiny';
|
||||
import {IMAGE_TOOLTIP_CONFIG} from './tiny/toolbar/config';
|
||||
import {parse} from 'node-html-parser';
|
||||
|
||||
export let EditorWebView = createRef();
|
||||
export const editorTitleInput = createRef();
|
||||
@@ -136,14 +135,11 @@ export async function clearTimer(clear) {
|
||||
}
|
||||
|
||||
export const CHECK_STATUS = `(function() {
|
||||
setTimeout(() => {
|
||||
let msg = JSON.stringify({
|
||||
data: true,
|
||||
type: 'running',
|
||||
});
|
||||
window.ReactNativeWebView.postMessage(msg)
|
||||
|
||||
},${Platform.OS === 'ios' ? '300' : '1'})
|
||||
})();`;
|
||||
|
||||
const request_content = `(function() {
|
||||
@@ -285,27 +281,29 @@ export const loadNote = async item => {
|
||||
checkStatus();
|
||||
} else {
|
||||
if (id === item.id && !item.forced) {
|
||||
console.log('return from here duhh.');
|
||||
return;
|
||||
}
|
||||
eSendEvent('loadingNote', item);
|
||||
if (getNote()) {
|
||||
console.log('clearing');
|
||||
await clearEditor(true, false, true);
|
||||
}
|
||||
console.log('done clearing');
|
||||
closingSession = false;
|
||||
disableSaving = false;
|
||||
noteEdited = false;
|
||||
await setNote(item);
|
||||
webviewInit = false;
|
||||
editing.isFocused = false;
|
||||
console.log('opening note');
|
||||
setTimeout(async () => {
|
||||
if (await checkStatus(true)) {
|
||||
requestedReload = true;
|
||||
EditorWebView.current?.reload();
|
||||
} else {
|
||||
eSendEvent('webviewreset');
|
||||
}
|
||||
requestedReload = true;
|
||||
EditorWebView.current?.reload();
|
||||
}, 1);
|
||||
useEditorStore.getState().setCurrentlyEditingNote(item.id);
|
||||
setTimeout(() => {
|
||||
useEditorStore.getState().setCurrentlyEditingNote(item.id);
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -323,9 +321,15 @@ const checkStatus = async noreset => {
|
||||
eUnSubscribeEvent('webviewOk', onWebviewOk);
|
||||
};
|
||||
eSubscribeEvent('webviewOk', onWebviewOk);
|
||||
EditorWebView.current?.injectJavaScript(CHECK_STATUS);
|
||||
setTimeout(
|
||||
() => {
|
||||
EditorWebView.current?.injectJavaScript(CHECK_STATUS);
|
||||
},
|
||||
Platform.OS === 'ios' ? 300 : 1
|
||||
);
|
||||
|
||||
webviewTimer = setTimeout(() => {
|
||||
console.log('timeout has ended');
|
||||
if (!webviewOK && !noreset) {
|
||||
console.log('webview not ok', 'ERROR');
|
||||
webviewInit = false;
|
||||
@@ -411,6 +415,7 @@ export const _onMessage = async evt => {
|
||||
if (!requestedReload && getNote()) return;
|
||||
requestedReload = false;
|
||||
setColors(COLOR_SCHEME);
|
||||
eSendEvent('webviewOk');
|
||||
webviewInit = true;
|
||||
webviewOK = true;
|
||||
if (PremiumService.get()) {
|
||||
@@ -715,6 +720,18 @@ const loadNoteInEditor = async (keepHistory = true) => {
|
||||
}),
|
||||
);
|
||||
`
|
||||
);
|
||||
} else {
|
||||
post('html', content.data);
|
||||
}
|
||||
if (id) {
|
||||
db.attachments.downloadImages(id);
|
||||
}
|
||||
|
||||
setColors();
|
||||
tiny.call(
|
||||
EditorWebView,
|
||||
tiny.updateDateEdited(timeConverter(note.dateEdited))
|
||||
);
|
||||
} else {
|
||||
console.log('opening in editor');
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, {useEffect, useRef, useState} from 'react';
|
||||
import {TextInput, View} from 'react-native';
|
||||
import {Button} from '../../../../components/Button';
|
||||
import {useTracked} from '../../../../provider';
|
||||
import {eSendEvent} from '../../../../services/EventManager';
|
||||
import {eSendEvent, ToastEvent} from '../../../../services/EventManager';
|
||||
import {editing} from '../../../../utils';
|
||||
import {normalize, SIZE} from '../../../../utils/SizeUtils';
|
||||
import {EditorWebView} from '../../Functions';
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
properties
|
||||
} from './constants';
|
||||
import LinkPreview from './linkpreview';
|
||||
import validator from 'validator';
|
||||
|
||||
let inputValue = null;
|
||||
|
||||
@@ -36,11 +37,6 @@ const ToolbarLinkInput = ({format, value, setVisible}) => {
|
||||
properties.inputMode = value ? INPUT_MODE.NO_EDIT : INPUT_MODE.EDITING;
|
||||
editing.tooltip = format;
|
||||
properties.userBlur = false;
|
||||
if (properties.pauseSelectionChange) {
|
||||
setTimeout(() => {
|
||||
properties.pauseSelectionChange = false;
|
||||
}, 100);
|
||||
}
|
||||
return () => {
|
||||
properties.inputMode = null;
|
||||
editing.tooltip = null;
|
||||
@@ -53,10 +49,16 @@ const ToolbarLinkInput = ({format, value, setVisible}) => {
|
||||
if (properties.pauseSelectionChange) {
|
||||
setTimeout(() => {
|
||||
properties.pauseSelectionChange = false;
|
||||
}, 100);
|
||||
}, 1000);
|
||||
}
|
||||
inputRef.current?.focus();
|
||||
return;
|
||||
} else {
|
||||
if (properties.pauseSelectionChange) {
|
||||
setTimeout(() => {
|
||||
properties.pauseSelectionChange = false;
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}, [mode]);
|
||||
|
||||
@@ -68,11 +70,21 @@ const ToolbarLinkInput = ({format, value, setVisible}) => {
|
||||
if (value === 'clear') {
|
||||
inputValue = null;
|
||||
}
|
||||
properties.userBlur = true;
|
||||
if (inputValue === '' || !inputValue) {
|
||||
properties.userBlur = true;
|
||||
formatSelection(execCommands.unlink);
|
||||
setVisible(false);
|
||||
} else {
|
||||
if (!inputValue.includes('://')) inputValue = 'https://' + inputValue;
|
||||
if (!validator.isURL(inputValue)) {
|
||||
ToastEvent.show({
|
||||
heading: 'Invalid url',
|
||||
message: 'Please enter a valid url',
|
||||
type: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
properties.userBlur = true;
|
||||
formatSelection(execCommands[format](inputValue));
|
||||
}
|
||||
|
||||
@@ -115,8 +127,8 @@ const ToolbarLinkInput = ({format, value, setVisible}) => {
|
||||
flexWrap: 'wrap',
|
||||
fontSize: SIZE.sm,
|
||||
flexShrink: 1,
|
||||
minWidth:'80%',
|
||||
fontFamily:"OpenSans-Regular"
|
||||
minWidth: '80%',
|
||||
fontFamily: 'OpenSans-Regular'
|
||||
}}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { getLinkPreview } from 'link-preview-js';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Image, ScrollView, TouchableOpacity, View } from 'react-native';
|
||||
import {getLinkPreview} from 'link-preview-js';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import {Image, ScrollView, TouchableOpacity, View} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { ActionIcon } from '../../../../components/ActionIcon';
|
||||
import {ActionIcon} from '../../../../components/ActionIcon';
|
||||
import Heading from '../../../../components/Typography/Heading';
|
||||
import Paragraph from '../../../../components/Typography/Paragraph';
|
||||
import { useTracked } from '../../../../provider';
|
||||
import { openLinkInBrowser } from '../../../../utils/functions';
|
||||
import { SIZE } from '../../../../utils/SizeUtils';
|
||||
import { INPUT_MODE, properties, reFocusEditor } from './constants';
|
||||
import {useTracked} from '../../../../provider';
|
||||
import {openLinkInBrowser} from '../../../../utils/functions';
|
||||
import {SIZE} from '../../../../utils/SizeUtils';
|
||||
import {INPUT_MODE, properties, reFocusEditor} from './constants';
|
||||
|
||||
let prevLink = {};
|
||||
let prevHeight = 50;
|
||||
@@ -21,9 +21,8 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
useEffect(() => {
|
||||
console.log('previewing', value);
|
||||
if (value && prevLink.value !== value) {
|
||||
|
||||
getLinkPreview(value)
|
||||
.then((r) => {
|
||||
.then(r => {
|
||||
if (r.contentType?.includes('text/html')) {
|
||||
prevLink = {
|
||||
value: value,
|
||||
@@ -31,12 +30,12 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
title: r.title,
|
||||
description: r.description,
|
||||
image: r.images[0],
|
||||
favicon: r.favicons[0],
|
||||
favicon: r.favicons[0]
|
||||
};
|
||||
setLink(prevLink);
|
||||
}
|
||||
})
|
||||
.catch((e) => console.log);
|
||||
.catch(e => console.log);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
@@ -50,9 +49,9 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
marginVertical: 5,
|
||||
borderWidth: 1,
|
||||
borderColor: colors.nav,
|
||||
backgroundColor: colors.nav,
|
||||
backgroundColor: colors.nav
|
||||
}}
|
||||
resizeMode="center"
|
||||
resizeMode="contain"
|
||||
source={{uri: imageLink}}
|
||||
/>
|
||||
) : faviconLink ? (
|
||||
@@ -62,12 +61,12 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
backgroundColor: colors.nav,
|
||||
borderWidth: 1,
|
||||
marginVertical: 5,
|
||||
borderRadius: 5,
|
||||
borderRadius: 5
|
||||
}}>
|
||||
<Image
|
||||
style={{
|
||||
width: height,
|
||||
height: height,
|
||||
height: height
|
||||
}}
|
||||
resizeMode="center"
|
||||
source={{uri: faviconLink}}
|
||||
@@ -82,7 +81,7 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: colors.shade,
|
||||
borderRadius: 5,
|
||||
borderRadius: 5
|
||||
}}>
|
||||
<Icon size={height - 4} color={colors.accent} name="web" />
|
||||
</View>
|
||||
@@ -91,8 +90,8 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
|
||||
const openLink = () => {
|
||||
openLinkInBrowser(value, colors)
|
||||
.catch((e) => {})
|
||||
.then(async (r) => {
|
||||
.catch(e => {})
|
||||
.then(async r => {
|
||||
console.log('closed browser now');
|
||||
await reFocusEditor();
|
||||
});
|
||||
@@ -101,17 +100,17 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
const renderText = (name, title, description) => {
|
||||
return (
|
||||
<View
|
||||
onLayout={(e) => {
|
||||
onLayout={e => {
|
||||
prevHeight = e.nativeEvent.layout.height;
|
||||
e.nativeEvent && setHeight(prevHeight);
|
||||
}}
|
||||
style={{
|
||||
flex: 1,
|
||||
flex: 1
|
||||
}}>
|
||||
<TouchableOpacity onPress={openLink} activeOpacity={1}>
|
||||
<ScrollView
|
||||
style={{
|
||||
marginRight: 10,
|
||||
marginRight: 10
|
||||
}}
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}>
|
||||
@@ -142,7 +141,7 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<ActionIcon
|
||||
onPress={() => {
|
||||
@@ -150,10 +149,10 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
}}
|
||||
customStyle={{
|
||||
width: 40,
|
||||
marginHorizontal: 10,
|
||||
height: 40,
|
||||
marginRight: 10,
|
||||
height: 40
|
||||
}}
|
||||
name="delete"
|
||||
name="link-off"
|
||||
size={SIZE.xl}
|
||||
color={colors.pri}
|
||||
/>
|
||||
@@ -165,8 +164,7 @@ const LinkPreview = ({setMode, value, onSubmit}) => {
|
||||
}}
|
||||
customStyle={{
|
||||
width: 40,
|
||||
marginHorizontal: 10,
|
||||
height: 40,
|
||||
height: 40
|
||||
}}
|
||||
name="pencil"
|
||||
size={SIZE.xl}
|
||||
|
||||
Reference in New Issue
Block a user