Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display Notes on Activity view #2292

Merged
merged 6 commits into from
Sep 16, 2024
Merged
4 changes: 4 additions & 0 deletions models/Invoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
}
}
4 changes: 2 additions & 2 deletions models/Payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
}
}
4 changes: 4 additions & 0 deletions models/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,8 @@ export default class Transaction extends BaseModel {
});
return outpoint;
}

@computed public get getNoteKey(): string {
return `note-${this.tx}`;
}
}
34 changes: 33 additions & 1 deletion stores/NotesStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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(
Expand Down
3 changes: 3 additions & 0 deletions stores/TransactionsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
64 changes: 63 additions & 1 deletion views/Activity/Activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -38,14 +39,15 @@ interface ActivityProps {
FiatStore: FiatStore;
PosStore: PosStore;
SettingsStore: SettingsStore;
NotesStore: NotesStore;
route: Route<'Activity', { order: any }>;
}

interface ActivityState {
selectedPaymentForOrder: any;
}

@inject('ActivityStore', 'FiatStore', 'PosStore', 'SettingsStore')
@inject('ActivityStore', 'FiatStore', 'PosStore', 'SettingsStore', 'NotesStore')
@observer
export default class Activity extends React.PureComponent<
ActivityProps,
Expand Down Expand Up @@ -225,6 +227,20 @@ export default class Activity extends React.PureComponent<
</TouchableOpacity>
);

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 (
<Screen>
<Header
Expand Down Expand Up @@ -255,6 +271,8 @@ export default class Activity extends React.PureComponent<
<FlatList
data={filteredActivity}
renderItem={({ item }: { item: any }) => {
const note = getMatchingNote(item);

let displayName = item.model;
let subTitle = item.model;

Expand Down Expand Up @@ -563,6 +581,50 @@ export default class Activity extends React.PureComponent<
</ListItem.Subtitle>
</View>
)}
{note && (
<View style={styles.row}>
<ListItem.Subtitle
style={{
...styles.leftCell,
color: themeColor(
'text'
),
fontFamily:
'Lato-Regular',
flexShrink: 0,
flex: 0,
width: 'auto',
overflow: 'hidden'
}}
numberOfLines={1}
>
{localeString(
'general.note'
)}
</ListItem.Subtitle>

<ListItem.Subtitle
style={{
...styles.rightCell,
color: themeColor(
'secondaryText'
),
fontFamily:
'Lato-Regular',
flexWrap: 'wrap',
flexShrink: 1
}}
ellipsizeMode="tail"
>
{note.length > 150
? `${note.substring(
0,
150
)}...`
: note}
</ListItem.Subtitle>
</View>
)}
</ListItem.Content>
</ListItem>
</React.Fragment>
Expand Down
37 changes: 10 additions & 27 deletions views/AddNotes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,11 @@ import SaveIcon from '../assets/images/SVG/Save.svg';
interface AddNotesProps {
navigation: StackNavigationProp<any, any>;
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;
}

Expand All @@ -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 });
}
Expand All @@ -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();
};

Expand Down Expand Up @@ -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
Expand Down
18 changes: 10 additions & 8 deletions views/Invoice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export default class InvoiceView extends React.Component<InvoiceProps> {
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 });
})
Expand Down Expand Up @@ -72,10 +72,10 @@ export default class InvoiceView extends React.Component<InvoiceProps> {
getPaymentRequest,
getKeysendMessage,
is_amp,
value
value,
getNoteKey
} = invoice;
const privateInvoice = invoice.private;
const noteKey = getRPreimage || payment_hash;

const QRButton = () => (
<TouchableOpacity
Expand All @@ -91,7 +91,9 @@ export default class InvoiceView extends React.Component<InvoiceProps> {
const EditNotesButton = () => (
<TouchableOpacity
onPress={() =>
navigation.navigate('AddNotes', { getRPreimage: noteKey })
navigation.navigate('AddNotes', {
noteKey: getNoteKey
})
}
style={{ marginRight: 15 }}
>
Expand Down Expand Up @@ -295,15 +297,15 @@ export default class InvoiceView extends React.Component<InvoiceProps> {
sensitive
mempoolLink={() =>
navigation.navigate('AddNotes', {
getRPreimage: noteKey
noteKey: getNoteKey
})
}
/>
)}
</View>
</ScrollView>
<View style={{ bottom: 15 }}>
{noteKey && (
{getNoteKey && (
<Button
title={
storedNotes
Expand All @@ -316,7 +318,7 @@ export default class InvoiceView extends React.Component<InvoiceProps> {
}
onPress={() =>
navigation.navigate('AddNotes', {
getRPreimage: noteKey
noteKey: getNoteKey
})
}
containerStyle={{ marginTop: 15 }}
Expand Down
Loading
Loading