Skip to content
Snippets Groups Projects
Commit 1e1a0089 authored by Alexey Lunin's avatar Alexey Lunin
Browse files

Implement autosave

parent 4a93f9e3
No related branches found
No related tags found
1 merge request!12Hin messaging
MEDIATOR_URL=https://ssi-dev.vereign.com/hin/afj-mediator/invite?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiJmOGFkYzVjZC01ZmU1LTQ5MjktODJjOC00MDdhZDY0N2I0MzQiLCJsYWJlbCI6IlZlcmVpZ24tTWVkaWF0b3IiLCJhY2NlcHQiOlsiZGlkY29tbS9haXAxIiwiZGlkY29tbS9haXAyO2Vudj1yZmMxOSJdLCJoYW5kc2hha2VfcHJvdG9jb2xzIjpbImh0dHBzOi8vZGlkY29tbS5vcmcvZGlkZXhjaGFuZ2UvMS4wIiwiaHR0cHM6Ly9kaWRjb21tLm9yZy9jb25uZWN0aW9ucy8xLjAiXSwic2VydmljZXMiOlt7ImlkIjoiI2lubGluZS0wIiwic2VydmljZUVuZHBvaW50IjoiaHR0cHM6Ly9zc2ktZGV2LnZlcmVpZ24uY29tL2hpbi9hZmotbWVkaWF0b3IiLCJ0eXBlIjoiZGlkLWNvbW11bmljYXRpb24iLCJyZWNpcGllbnRLZXlzIjpbImRpZDprZXk6ejZNa2o5TVI5dVdyZjhvWU00WXNla2VpZjNvbTJTaHY2VUpuc3hWQXdkNkdKbk1tIl0sInJvdXRpbmdLZXlzIjpbXX0seyJpZCI6IiNpbmxpbmUtMSIsInNlcnZpY2VFbmRwb2ludCI6IndzOi8vc3NpLWRldi52ZXJlaWduLmNvbS9oaW4vYWZqLW1lZGlhdG9yIiwidHlwZSI6ImRpZC1jb21tdW5pY2F0aW9uIiwicmVjaXBpZW50S2V5cyI6WyJkaWQ6a2V5Ono2TWtqOU1SOXVXcmY4b1lNNFlzZWtlaWYzb20yU2h2NlVKbnN4VkF3ZDZHSm5NbSJdLCJyb3V0aW5nS2V5cyI6W119XX0
SVDX_BASE_URL=https://did.svdx.pr
\ No newline at end of file
SVDX_BASE_URL=https://did.svdx.pro
\ No newline at end of file
MEDIATOR_URL=https://gaiax.vereign.com/mediator?c_i=eyJAdHlwZSI6ICJkaWQ6c292OkJ6Q2JzTlloTXJqSGlxWkRUVUFTSGc7c3BlYy9jb25uZWN0aW9ucy8xLjAvaW52aXRhdGlvbiIsICJAaWQiOiAiZDU0Mjc2ZDUtMDUwYy00MDI1LWExYWUtNGYzMzE4MWQyM2U3IiwgImxhYmVsIjogIk1lZGlhdG9yIiwgInJlY2lwaWVudEtleXMiOiBbIkJjdGoyQllHUWN5dVRTaVlEV0tjTWNjRDNvR3Q3ZkNDellaV0trbkVNdFA5Il0sICJzZXJ2aWNlRW5kcG9pbnQiOiAiaHR0cHM6Ly9nYWlheC52ZXJlaWduLmNvbS9tZWRpYXRvciJ9
SVDX_BASE_URL=https://did.svdx.pr
SVDX_BASE_URL=https://did.svdx.pro
# MEDIATOR_URL=https://mediator.dev.animo.id/invite?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiIyMDc1MDM4YS05ZGU3LTRiODItYWUxYi1jNzBmNDg4MjYzYTciLCJsYWJlbCI6IkFuaW1vIE1lZGlhdG9yIiwiYWNjZXB0IjpbImRpZGNvbW0vYWlwMSIsImRpZGNvbW0vYWlwMjtlbnY9cmZjMTkiXSwiaGFuZHNoYWtlX3Byb3RvY29scyI6WyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCIsImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sInNlcnZpY2VzIjpbeyJpZCI6IiNpbmxpbmUtMCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHBzOi8vbWVkaWF0b3IuZGV2LmFuaW1vLmlkIiwidHlwZSI6ImRpZC1jb21tdW5pY2F0aW9uIiwicmVjaXBpZW50S2V5cyI6WyJkaWQ6a2V5Ono2TWtvSG9RTUphdU5VUE5OV1pQcEw3RGs1SzNtQ0NDMlBpNDJGY3FwR25iampMcSJdLCJyb3V0aW5nS2V5cyI6W119LHsiaWQiOiIjaW5saW5lLTEiLCJzZXJ2aWNlRW5kcG9pbnQiOiJ3c3M6Ly9tZWRpYXRvci5kZXYuYW5pbW8uaWQiLCJ0eXBlIjoiZGlkLWNvbW11bmljYXRpb24iLCJyZWNpcGllbnRLZXlzIjpbImRpZDprZXk6ejZNa29Ib1FNSmF1TlVQTk5XWlBwTDdEazVLM21DQ0MyUGk0MkZjcXBHbmJqakxxIl0sInJvdXRpbmdLZXlzIjpbXX1dfQ
# MEDIATOR_URL=https://ssi-dev.vereign.com/hin/afj-mediator/invite?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI1OTRkMTk3YS0yMzgxLTRkNmUtOTk1ZC0xODBjMzNiY2M1MGYiLCJsYWJlbCI6ImFmai12ZXJlaWduLW1lZGlhdG9yIiwiYWNjZXB0IjpbImRpZGNvbW0vYWlwMSIsImRpZGNvbW0vYWlwMjtlbnY9cmZjMTkiXSwiaGFuZHNoYWtlX3Byb3RvY29scyI6WyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCIsImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sInNlcnZpY2VzIjpbeyJpZCI6IiNpbmxpbmUtMCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHBzOi8vc3NpLWRldi52ZXJlaWduLmNvbS9oaW4vYWZqLW1lZGlhdG9yIiwidHlwZSI6ImRpZC1jb21tdW5pY2F0aW9uIiwicmVjaXBpZW50S2V5cyI6WyJkaWQ6a2V5Ono2TWtvM0g0YWNvZ05mSHFaeUtHVERpdWRCd3o4TTU0dXRoR1ZBWFhnQzE3eHZFTCJdLCJyb3V0aW5nS2V5cyI6W119LHsiaWQiOiIjaW5saW5lLTEiLCJzZXJ2aWNlRW5kcG9pbnQiOiJ3czovL3NzaS1kZXYudmVyZWlnbi5jb20vaGluL2Fmai1tZWRpYXRvciIsInR5cGUiOiJkaWQtY29tbXVuaWNhdGlvbiIsInJlY2lwaWVudEtleXMiOlsiZGlkOmtleTp6Nk1rbzNINGFjb2dOZkhxWnlLR1REaXVkQnd6OE01NHV0aEdWQVhYZ0MxN3h2RUwiXSwicm91dGluZ0tleXMiOltdfV19
......
import React from 'react';
import { format } from 'date-fns';
import {StyleSheet, Text, View} from 'react-native';
import { ColorPallet, TextTheme } from 'src/theme/theme';
import {ColorPallet, TextTheme} from 'src/theme/theme';
import Card from 'src/components/EmailCard';
import { DATE_TIME_FORMAT } from "src/constants/constants";
import {parseAddress} from "src/utils/email";
import Button, {ButtonType} from "../../components/Button";
interface Props {
configInvalid: boolean;
saving: boolean;
saved: boolean;
userEmail: string | undefined;
onSavePress: () => void;
onSettingsPress: () => void;
}
const SaveSection = ({ configInvalid, saving, saved, userEmail, onSavePress }: Props) => {
const SaveSection = ({ configInvalid, onSettingsPress }: Props) => {
if (!configInvalid) return null;
return (
<Card background="white">
<View style={styles.saveWrapper}>
<Text style={styles.warn}>
IMAP Configuration Missing!
</Text>
<Text style={styles.text}>
In order to save your messages securely, you need to set up your IMAP configuration correctly. Currently, the provided IMAP settings are not valid. Please review and update the IMAP configuration in the settings to ensure your messages are saved and accessible.
</Text>
<View>
<Button
title="Save using IMAP"
disabled={configInvalid || saving || saved}
buttonType={ButtonType.Primary}
onPress={onSavePress}
title="Configure IMAP Settings"
buttonStyle={styles.goToImapButton}
onPress={onSettingsPress}
/>
</View>
{!saving && !saved && !configInvalid && (
<Text style={styles.text}>
Press the button to save to {userEmail}
</Text>
)}
{saving && (
<Text style={styles.text}>
Saving to {userEmail}
</Text>
)}
{saved && (
<Text style={styles.text}>
Message saved to {userEmail}
</Text>
)}
{configInvalid && (
<Text style={styles.warn}>
The IMAP config is not valid. Please check the IMAP configuration in the settings.
</Text>
)}
</Card>
);
};
......@@ -55,17 +34,15 @@ const SaveSection = ({ configInvalid, saving, saved, userEmail, onSavePress }: P
export default SaveSection;
const styles = StyleSheet.create({
saveWrapper: {
},
warn: {
...TextTheme.normal,
color: ColorPallet.baseColors.red,
paddingTop: 12,
marginBottom: 6
},
text: {
color: ColorPallet.baseColors.black,
fontWeight: 'bold',
fontSize: 16,
paddingTop: 12,
...TextTheme.normal,
},
goToImapButton: {
marginTop: 16
}
});
......@@ -2,21 +2,16 @@ import React, { useEffect, useState } from 'react';
import { StackScreenProps } from '@react-navigation/stack';
import {
StyleSheet,
Text,
View,
StatusBar,
ScrollView,
NativeModules,
} from 'react-native';
import {observer} from "mobx-react";
import {EmailStackParams, Screens} from 'src/type/navigators';
import { ColorPallet, TextTheme } from 'src/theme/theme';
import {EmailStackParams, Screens, Stacks} from 'src/type/navigators';
import MimeParser from "@vereign/lib-mime";
import {getImapConfig} from "src/utils/keychain";
import {successToast, warningToast} from "src/utils/toast";
import Button, {ButtonType} from "src/components/Button";
import Config from "react-native-config";
import axios from "axios";
import {warningToast} from "src/utils/toast";
import { useObject, useRealm } from '@realm/react';
import {useNavigation} from "@react-navigation/native";
import Email from 'src/db-models/Email';
......@@ -25,8 +20,6 @@ import Subject from './Subject';
import ContentCard from './ContentCard';
import SaveSection from "./SaveSection";
const {VereignImapModule} = NativeModules;
type EmailDetailsProps = StackScreenProps<
EmailStackParams,
Screens.EmailDetails
......@@ -48,8 +41,6 @@ const EmailDetails: React.FC<EmailDetailsProps> = observer(({
}
const [configValid, setConfigValid] = useState(true);
const [savingToEmailBox, setSavingToEmailBox] = useState(false);
const [userEmail, setUserEmail] = useState('');
const [html, setHtml] = useState('');
const [plainText, setPlainText] = useState('');
......@@ -59,7 +50,6 @@ const EmailDetails: React.FC<EmailDetailsProps> = observer(({
setConfigValid(false);
return;
}
setUserEmail(config.username);
}
const parseMime = async () => {
try {
......@@ -86,44 +76,6 @@ const EmailDetails: React.FC<EmailDetailsProps> = observer(({
parseMime();
}, [realmId]);
const saveEmail = async () => {
setSavingToEmailBox(true);
try {
const config = await getImapConfig();
if (config) {
VereignImapModule.saveMessage(config!.host, config!.username, config!.password, email.svdxMime, (success: boolean, error: any) => {
if (success) {
successToast("Email is saved");
realm.write(() => {
email.svdxImapSaved = true;
});
notifySVDXServer();
}
if (error) {
warningToast("Something went wrong " + error);
}
setSavingToEmailBox(false);
});
}
} catch (e: any) {
warningToast(e.message);
setSavingToEmailBox(false);
}
}
const notifySVDXServer = async () => {
const response = await axios({
url: `${Config.SVDX_BASE_URL}/v1/message/read`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: {
messageId: email.svdxMessageId
},
});
}
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
......@@ -132,10 +84,11 @@ const EmailDetails: React.FC<EmailDetailsProps> = observer(({
<View style={styles.content}>
<SaveSection
configInvalid={!configValid}
saving={savingToEmailBox}
saved={email.svdxImapSaved || false}
userEmail={userEmail}
onSavePress={() => saveEmail()}
onSettingsPress={() => {
navigation.getParent().navigate(Stacks.SettingsStack, {
screen: Screens.ImapConfiguration
});
}}
/>
<SentBy
......
......@@ -65,12 +65,16 @@ import {WalletConfig, WalletExportImportConfig} from "@aries-framework/core/buil
import {
LegacyIndyCredentialFormatService
} from "@aries-framework/anoncreds/build/formats/LegacyIndyCredentialFormatService";
import {infoToast, warningToast} from 'src/utils/toast';
import {infoToast, successToast, warningToast} from 'src/utils/toast';
import {Buffer} from "buffer";
import Realm from "realm";
import MimeParser from "@vereign/lib-mime";
import notifee, {AndroidImportance, AuthorizationStatus} from '@notifee/react-native';
import Email from "../db-models/Email";
import axios from "axios";
import {NativeModules} from "react-native";
const {VereignImapModule} = NativeModules;
class AgentStore {
private _rootStore: RootStore;
......@@ -302,6 +306,8 @@ class AgentStore {
infoToast("Received new message");
await this._saveEmail(svdxId, realmRecordId, emailContent);
this._displayNewEmailReceived(from, subject, realmRecordId.toString());
} catch (e) {
warningToast("Email is received but it can not be decoded");
......@@ -310,6 +316,84 @@ class AgentStore {
}
}
private _saveEmail = async (svdxMessageId: string, realmId: Realm.BSON.ObjectId, mime: string) => {
try {
const config = await getImapConfig();
if (config) {
if (!(await this._checkCanSaveEmail(svdxMessageId))) return;
VereignImapModule.saveMessage(config!.host, config!.username, config!.password, mime, (success: boolean, error: any) => {
if (success) {
successToast("Email is saved");
const email = this._realm.objectForPrimaryKey('Email', realmId);
if (email) {
this._realm.write(() => {
email.svdxImapSaved = true;
});
this._notifySVDXServer(svdxMessageId);
}
}
if (error) {
warningToast("Something went wrong " + error);
}
});
}
} catch (e: any) {
warningToast(e.message);
}
}
private _checkCanSaveEmail = async (svdxMessageId: string) => {
return true; // TODO Once https://code.vereign.com/ssi/didcomm-mail/svdx/-/merge_requests/33 merged and deployed, remove this line
try {
const response = await axios({
url: `${Config.SVDX_BASE_URL}/v1/message/status`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: {
messageId: svdxMessageId
},
});
// Check for HTTP 200 status
if (response.status === 200) {
return true;
}
return false
} catch (error: any) {
if (error.response && error.response.status === 404) {
// Handle the case where the message has been delivered already in another way
console.log('Message has been delivered already in another way');
} else {
// Handle other errors
console.error('An error occurred:', error.message);
}
}
return false;
}
private _notifySVDXServer = async (svdxMessageId: string) => {
try {
await axios({
url: `${Config.SVDX_BASE_URL}/v1/message/read`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: {
messageId: svdxMessageId
},
});
console.log('Message has been marked as read');
} catch (e: any) {
console.error('Something wen wrong during notifying SVDX server about read message', e.message);
}
}
private _displayNewEmailReceived = async (from: string, subject: string, realmId: string) => {
const authResult = await notifee.requestPermission()
if (authResult.authorizationStatus !== AuthorizationStatus.AUTHORIZED) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment