diff --git a/models/Invoice.ts b/models/Invoice.ts index 5b2558f49..ac627c604 100644 --- a/models/Invoice.ts +++ b/models/Invoice.ts @@ -380,4 +380,8 @@ export default class Invoice extends BaseModel { .replace(/([^,]) (\d)/g, '$2 $1') // RTL ); } + + @computed public get getNoteKey(): string { + return `note-${this.payment_hash || this.getRPreimage}`; + } } diff --git a/models/Payment.ts b/models/Payment.ts index 9d95bc201..94da08d31 100644 --- a/models/Payment.ts +++ b/models/Payment.ts @@ -310,7 +310,7 @@ export default class Payment extends BaseModel { .replace(/ (\d+)/g, ' $1'); } - @computed public get noteKey(): string { - return this.paymentHash || this.getPreimage; + @computed public get getNoteKey(): string { + return `note-${this.paymentHash || this.getPreimage}`; } } diff --git a/models/Transaction.ts b/models/Transaction.ts index 0b8e9294d..77d19594d 100644 --- a/models/Transaction.ts +++ b/models/Transaction.ts @@ -129,4 +129,8 @@ export default class Transaction extends BaseModel { }); return outpoint; } + + @computed public get getNoteKey(): string { + return `note-${this.tx}`; + } } diff --git a/stores/NotesStore.ts b/stores/NotesStore.ts index 930fc7f18..f88236050 100644 --- a/stores/NotesStore.ts +++ b/stores/NotesStore.ts @@ -5,9 +5,16 @@ const NOTES_KEY = 'note-Keys'; export default class NotesStore { @observable public noteKeys: string[] = []; + @observable public notes: { [key: string]: string } = {}; + + constructor() { + this.loadNoteKeys(); + } @action public storeNoteKeys = async (key: string, notes: string) => { + this.notes[key] = notes; + if (!this.noteKeys.includes(key)) { if (notes) { this.noteKeys.push(key); @@ -21,11 +28,36 @@ export default class NotesStore { const index = this.noteKeys.indexOf(key); if (index !== -1) { this.noteKeys.splice(index, 1); - // write updated keys to storage + delete this.notes[key]; await this.writeNoteKeysToLocalStorage(); } }; + @action + public async loadNoteKeys() { + console.log('Loading notes...'); + try { + const storedKeys = await EncryptedStorage.getItem(NOTES_KEY); + if (storedKeys) { + this.noteKeys = JSON.parse(storedKeys); + // Load all notes + await Promise.all( + this.noteKeys.map(async (key) => { + const note = await EncryptedStorage.getItem(key); + if (note) { + this.notes[key] = note; + } + }) + ); + } + } catch (error) { + console.error( + 'Error loading note keys from encrypted storage', + error + ); + } + } + writeNoteKeysToLocalStorage = async () => { try { await EncryptedStorage.setItem( diff --git a/stores/TransactionsStore.ts b/stores/TransactionsStore.ts index 6c2cd0da6..e5f8cbfc6 100644 --- a/stores/TransactionsStore.ts +++ b/stores/TransactionsStore.ts @@ -55,6 +55,8 @@ export default class TransactionsStore { @observable onchain_address: string; @observable txid: string | null; @observable status: string | number | null; + @observable noteKey: string; + // in lieu of receiving txid on LND's publishTransaction @observable publishSuccess = false; @observable broadcast_txid: string; @@ -487,6 +489,7 @@ export default class TransactionsStore { this.payment_route = result.payment_route; const payment = new Payment(result); + this.noteKey = payment.getNoteKey; this.payment_preimage = payment.getPreimage; this.payment_hash = payment.paymentHash; this.isIncomplete = payment.isIncomplete; diff --git a/views/Activity/Activity.tsx b/views/Activity/Activity.tsx index 61f8d9c05..d0ba9ca99 100644 --- a/views/Activity/Activity.tsx +++ b/views/Activity/Activity.tsx @@ -27,6 +27,7 @@ import ActivityStore from '../../stores/ActivityStore'; import FiatStore from '../../stores/FiatStore'; import PosStore from '../../stores/PosStore'; import SettingsStore from '../../stores/SettingsStore'; +import NotesStore from '../../stores/NotesStore'; import { SATS_PER_BTC } from '../../stores/UnitsStore'; import Filter from '../../assets/images/SVG/Filter On.svg'; @@ -38,6 +39,7 @@ interface ActivityProps { FiatStore: FiatStore; PosStore: PosStore; SettingsStore: SettingsStore; + NotesStore: NotesStore; route: Route<'Activity', { order: any }>; } @@ -45,7 +47,7 @@ interface ActivityState { selectedPaymentForOrder: any; } -@inject('ActivityStore', 'FiatStore', 'PosStore', 'SettingsStore') +@inject('ActivityStore', 'FiatStore', 'PosStore', 'SettingsStore', 'NotesStore') @observer export default class Activity extends React.PureComponent< ActivityProps, @@ -225,6 +227,20 @@ export default class Activity extends React.PureComponent< ); + const getMatchingNote = (item: any) => { + const { NotesStore } = this.props; + const notes = NotesStore.notes; + + // Use the getNoteKey from the model + const noteKey = item.getNoteKey; + + if (noteKey && notes[noteKey]) { + return notes[noteKey]; + } + + return null; + }; + return (
{ + const note = getMatchingNote(item); + let displayName = item.model; let subTitle = item.model; @@ -563,6 +581,50 @@ export default class Activity extends React.PureComponent< )} + {note && ( + + + {localeString( + 'general.note' + )} + + + + {note.length > 150 + ? `${note.substring( + 0, + 150 + )}...` + : note} + + + )} diff --git a/views/AddNotes.tsx b/views/AddNotes.tsx index b91cffe70..2d87e0d19 100644 --- a/views/AddNotes.tsx +++ b/views/AddNotes.tsx @@ -20,16 +20,11 @@ import SaveIcon from '../assets/images/SVG/Save.svg'; interface AddNotesProps { navigation: StackNavigationProp; NotesStore: NotesStore; - route: Route< - 'AddNotes', - { payment_hash: string; txid: string; getRPreimage: string } - >; + route: Route<'AddNotes', { noteKey: string }>; } interface AddNotesState { notes?: string; - payment_hash?: string; - txid?: string; - getRPreimage?: string; + noteKey?: string; isNoteStored?: boolean; } @@ -41,24 +36,17 @@ export default class AddNotes extends React.Component< > { constructor(props: any) { super(props); - const { payment_hash, txid, getRPreimage } = - this.props.route.params ?? {}; + const { noteKey } = this.props.route.params ?? {}; this.state = { notes: '', - payment_hash, - txid, - getRPreimage, + noteKey, isNoteStored: false }; } async componentDidMount() { - const key: string = - 'note-' + - (this.state.txid || - this.state.payment_hash || - this.state.getRPreimage); - const storedNotes = await EncryptedStorage.getItem(key); + const { noteKey } = this.state; + const storedNotes = await EncryptedStorage.getItem(noteKey); if (storedNotes) { this.setState({ notes: storedNotes, isNoteStored: true }); } @@ -67,14 +55,12 @@ export default class AddNotes extends React.Component< render() { const { navigation, NotesStore } = this.props; const { storeNoteKeys, removeNoteKeys } = NotesStore; - const { payment_hash, txid, getRPreimage, isNoteStored } = this.state; + const { noteKey, isNoteStored } = this.state; const { notes } = this.state; const saveNote = async () => { - const key: string = - 'note-' + (payment_hash || txid || getRPreimage); - EncryptedStorage.setItem(key, notes); - await storeNoteKeys(key, notes); + EncryptedStorage.setItem(noteKey, notes); + await storeNoteKeys(noteKey, notes); navigation.goBack(); }; @@ -119,10 +105,7 @@ export default class AddNotes extends React.Component< onChangeText={(text: string) => { this.setState({ notes: text }); if (!text) { - const key: string = - 'note-' + - (payment_hash || txid || getRPreimage); - removeNoteKeys(key); + removeNoteKeys(noteKey); } }} multiline diff --git a/views/Invoice.tsx b/views/Invoice.tsx index b5734b34d..505a7411a 100644 --- a/views/Invoice.tsx +++ b/views/Invoice.tsx @@ -38,8 +38,8 @@ export default class InvoiceView extends React.Component { const { navigation, route } = this.props; const invoice = route.params?.invoice; navigation.addListener('focus', () => { - const noteKey = invoice.getRPreimage || invoice.payment_hash; - EncryptedStorage.getItem('note-' + noteKey) + const noteKey = invoice.getNoteKey; + EncryptedStorage.getItem(noteKey) .then((storedNotes) => { this.setState({ storedNotes }); }) @@ -72,10 +72,10 @@ export default class InvoiceView extends React.Component { getPaymentRequest, getKeysendMessage, is_amp, - value + value, + getNoteKey } = invoice; const privateInvoice = invoice.private; - const noteKey = getRPreimage || payment_hash; const QRButton = () => ( { const EditNotesButton = () => ( - navigation.navigate('AddNotes', { getRPreimage: noteKey }) + navigation.navigate('AddNotes', { + noteKey: getNoteKey + }) } style={{ marginRight: 15 }} > @@ -295,7 +297,7 @@ export default class InvoiceView extends React.Component { sensitive mempoolLink={() => navigation.navigate('AddNotes', { - getRPreimage: noteKey + noteKey: getNoteKey }) } /> @@ -303,7 +305,7 @@ export default class InvoiceView extends React.Component { - {noteKey && ( + {getNoteKey && (