mirror of
https://github.com/block-core/blockcore-notes.git
synced 2024-09-29 22:40:44 +00:00
Add support for zaps on profile
This commit is contained in:
parent
7451f91051
commit
b04e11dbf7
@ -17,6 +17,7 @@ import { NostrService } from './nostr';
|
||||
import { ArticleService } from './article';
|
||||
import { LoggerService } from './logger';
|
||||
import { BadgeService } from './badge';
|
||||
import { ZapUiService } from './zap-ui';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@ -55,7 +56,8 @@ export class RelayService {
|
||||
private db: StorageService,
|
||||
private options: OptionsService,
|
||||
private eventService: EventService,
|
||||
private appState: ApplicationState
|
||||
private appState: ApplicationState,
|
||||
private zapUi: ZapUiService
|
||||
) {
|
||||
// Whenever the visibility becomes visible, run connect to ensure we're connected to the relays.
|
||||
this.appState.visibility$.subscribe((visible) => {
|
||||
@ -85,6 +87,11 @@ export class RelayService {
|
||||
|
||||
// Then create a new subscription:
|
||||
const kinds = this.options.values.enableReactions ? [Kind.Text, Kind.Reaction, 6] : [Kind.Text, 6];
|
||||
|
||||
if (this.options.values.enableZapping) {
|
||||
kinds.push(Kind.Zap);
|
||||
}
|
||||
|
||||
this.profileEventSubscription = this.subscribe([{ authors: [this.ui.profile!.pubkey], kinds: kinds, until: options.until, limit: 100 }]).id;
|
||||
} else if (options.type == 'feed') {
|
||||
// If there are no subscription yet, just skip load more.
|
||||
@ -108,6 +115,11 @@ export class RelayService {
|
||||
|
||||
// Then create a new subscription:
|
||||
const kinds = this.options.values.enableReactions ? [Kind.Text, Kind.Reaction, 6] : [Kind.Text, 6];
|
||||
|
||||
if (this.options.values.enableZapping) {
|
||||
kinds.push(Kind.Zap);
|
||||
}
|
||||
|
||||
this.circleEventSubscription = this.subscribe([{ authors: pubkeys, kinds: kinds, until: options.until, limit: 100 }], 'feed').id;
|
||||
}
|
||||
});
|
||||
@ -132,6 +144,11 @@ export class RelayService {
|
||||
}
|
||||
|
||||
const kinds = this.options.values.enableReactions ? [Kind.Text, Kind.Reaction, 6] : [Kind.Text, 6];
|
||||
|
||||
if (this.options.values.enableZapping) {
|
||||
kinds.push(Kind.Zap);
|
||||
}
|
||||
|
||||
this.circleEventSubscription = this.subscribe([{ authors: pubkeys, kinds: kinds, limit: 100 }], 'feed').id;
|
||||
});
|
||||
|
||||
@ -153,12 +170,16 @@ export class RelayService {
|
||||
this.ui.setProfile(profile);
|
||||
}
|
||||
|
||||
this.zapUi.reset();
|
||||
|
||||
// else {
|
||||
// this.enque({ type: 'Profile', identifier: id });
|
||||
// }
|
||||
|
||||
// Subscribe to events for the current user profile.
|
||||
this.profileEventSubscription = this.subscribe([{ authors: [id], kinds: [Kind.Text, Kind.Reaction, 6], limit: 100 }]).id;
|
||||
// Subscribe to events and zaps (received) for the current user profile.
|
||||
this.profileEventSubscription = this.subscribe([
|
||||
{ ['#p']: [id], kinds: [Kind.Zap] },
|
||||
{ authors: [id], kinds: [Kind.Text, Kind.Reaction, 6], limit: 100 },
|
||||
]).id;
|
||||
});
|
||||
|
||||
// Whenever the event ID changes, we'll attempt to load the event.
|
||||
@ -396,9 +417,12 @@ export class RelayService {
|
||||
|
||||
this.logger.debug('SAVE EVENT?:', event);
|
||||
|
||||
if (event.kind == Kind.Zap) {
|
||||
this.zapUi.addZap(event);
|
||||
}
|
||||
|
||||
if (response.subscription) {
|
||||
const sub = this.subs.get(response.subscription);
|
||||
|
||||
if (sub) {
|
||||
if (sub.type == 'Event') {
|
||||
const index = sub.events.findIndex((e) => e.id == event.id);
|
||||
|
@ -13,7 +13,7 @@ import { ZapService } from './zap.service';
|
||||
})
|
||||
/** The orchestrator for UI that holds data to be rendered in different views at any given time. */
|
||||
export class UIService {
|
||||
constructor(private eventService: EventService, private options: OptionsService, private zapService: ZapService) { }
|
||||
constructor(private eventService: EventService, private options: OptionsService, private zapService: ZapService) {}
|
||||
|
||||
#lists = {
|
||||
feedEvents: [] as NostrEventDocument[],
|
||||
@ -617,9 +617,9 @@ export class UIService {
|
||||
|
||||
entry.reactionIds.push(event.id!);
|
||||
const parsedZap = this.zapService.parseZap(event);
|
||||
entry.zaps != undefined ? entry.zaps.push(parsedZap) : entry.zaps = [parsedZap];
|
||||
entry.zaps != undefined ? entry.zaps.push(parsedZap) : (entry.zaps = [parsedZap]);
|
||||
|
||||
this.putThreadEntry(entry)
|
||||
this.putThreadEntry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
89
src/app/services/zap-ui.ts
Normal file
89
src/app/services/zap-ui.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NostrEventDocument, Zapper, ParsedZap, NostrEvent } from './interfaces';
|
||||
import { decode } from 'light-bolt11-decoder';
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
import { Utilities } from './utilities';
|
||||
import { ZapService } from './zap.service';
|
||||
import { EventService } from './event';
|
||||
|
||||
interface ZapStatus {
|
||||
ids: string[];
|
||||
amount: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ZapUiService {
|
||||
events = new Map<string, ZapStatus>();
|
||||
profiles = new Map<string, ZapStatus>();
|
||||
|
||||
constructor(private zapService: ZapService, private eventService: EventService) {}
|
||||
|
||||
reset() {
|
||||
this.events.clear();
|
||||
this.profiles.clear();
|
||||
}
|
||||
|
||||
getEventZapAmount(eventId: string) {
|
||||
const zapStatus = this.events.get(eventId);
|
||||
|
||||
if (!zapStatus) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return zapStatus.amount;
|
||||
}
|
||||
|
||||
getProfileZapAmount(pubkey: string) {
|
||||
const zapStatus = this.profiles.get(pubkey);
|
||||
|
||||
if (!zapStatus) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return zapStatus.amount;
|
||||
}
|
||||
|
||||
addZap(event: NostrEvent) {
|
||||
const parsedZap = this.zapService.parseZap(event);
|
||||
|
||||
if (parsedZap.e) {
|
||||
let eventMap = this.events.get(parsedZap.e);
|
||||
|
||||
if (!eventMap) {
|
||||
eventMap = {
|
||||
ids: [parsedZap.id],
|
||||
amount: parsedZap.amount,
|
||||
};
|
||||
} else {
|
||||
if (eventMap.ids.includes(parsedZap.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventMap.ids.push(parsedZap.id);
|
||||
eventMap.amount += parsedZap.amount;
|
||||
}
|
||||
|
||||
this.events.set(parsedZap.e, eventMap);
|
||||
}
|
||||
|
||||
let profileMap = this.profiles.get(parsedZap.p);
|
||||
|
||||
if (!profileMap) {
|
||||
profileMap = {
|
||||
ids: [parsedZap.id],
|
||||
amount: parsedZap.amount,
|
||||
};
|
||||
} else {
|
||||
if (profileMap.ids.includes(parsedZap.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
profileMap.ids.push(parsedZap.id);
|
||||
profileMap.amount += parsedZap.amount;
|
||||
}
|
||||
|
||||
this.profiles.set(parsedZap.p, profileMap);
|
||||
}
|
||||
}
|
@ -13,8 +13,8 @@ export class ZapService {
|
||||
parseZap(zapEvent: NostrEventDocument): ParsedZap {
|
||||
const { amount, hash } = this.getInvoice(zapEvent);
|
||||
const zapper = hash ? this.getZapper(zapEvent, hash) : ({ isValid: false, content: '' } as Zapper);
|
||||
const e = this.zappedAuthor(zapEvent);
|
||||
const p = this.zappedPost(zapEvent);
|
||||
const p = this.zappedAuthor(zapEvent);
|
||||
const e = this.zappedPost(zapEvent);
|
||||
|
||||
return {
|
||||
id: zapEvent.id,
|
||||
|
@ -107,8 +107,9 @@
|
||||
<p class="wrap linebreaks" *ngIf="profile.about">{{ profile.about }}</p>
|
||||
</span>
|
||||
|
||||
<div class="following-counts" *ngIf="profile.following">
|
||||
<a class="following-link" [routerLink]="['/following', profile.pubkey]">{{ profile.following.length }} <span class="dimmed">Following</span></a>
|
||||
<div class="following-counts">
|
||||
<a class="following-link" *ngIf="profile.following" [routerLink]="['/following', profile.pubkey]">{{ profile.following.length }} <span class="dimmed">Following</span></a>
|
||||
⚡️{{ zapUi.getProfileZapAmount(profile.pubkey) }} <span class="dimmed">Sats</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
@ -11,6 +11,7 @@ import { UIService } from 'src/app/services/ui';
|
||||
import { ApplicationState } from 'src/app/services/applicationstate';
|
||||
import { nip05 } from 'nostr-tools';
|
||||
import { ZapDialogComponent } from '../zap-dialog/zap-dialog.component';
|
||||
import { ZapUiService } from 'src/app/services/zap-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile-header',
|
||||
@ -29,9 +30,9 @@ export class ProfileHeaderComponent {
|
||||
qr06?: string;
|
||||
qr16?: string;
|
||||
userPubKey: string;
|
||||
isValidNip05: boolean = false
|
||||
isValidNip05: boolean = false;
|
||||
|
||||
constructor(private appState: ApplicationState, public ui: UIService, public profileService: ProfileService, public dialog: MatDialog, public circleService: CircleService, public utilities: Utilities) {
|
||||
constructor(public zapUi: ZapUiService, private appState: ApplicationState, public ui: UIService, public profileService: ProfileService, public dialog: MatDialog, public circleService: CircleService, public utilities: Utilities) {
|
||||
this.userPubKey = this.appState.getPublicKey();
|
||||
}
|
||||
|
||||
@ -115,13 +116,13 @@ export class ProfileHeaderComponent {
|
||||
scale: 5,
|
||||
});
|
||||
}
|
||||
if(profile.nip05) {
|
||||
let nip05Data = null
|
||||
if (profile.nip05) {
|
||||
let nip05Data = null;
|
||||
try {
|
||||
nip05Data = await nip05.queryProfile(profile?.nip05)
|
||||
this.isValidNip05 = nip05Data?.pubkey == profile?.pubkey
|
||||
nip05Data = await nip05.queryProfile(profile?.nip05);
|
||||
this.isValidNip05 = nip05Data?.pubkey == profile?.pubkey;
|
||||
} catch (_) {
|
||||
console.log('failed to fetch NIP05 identifier')
|
||||
console.log('failed to fetch NIP05 identifier');
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -154,9 +155,8 @@ export class ProfileHeaderComponent {
|
||||
this.dialog.open(ZapDialogComponent, {
|
||||
width: '400px',
|
||||
data: {
|
||||
profile: profile
|
||||
profile: profile,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -641,7 +641,9 @@ export class RelayWorker {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const sub = this.relay.sub([{ kinds: [1], ids: ids }]) as NostrSub;
|
||||
const kinds = [Kind.Text];
|
||||
|
||||
const sub = this.relay.sub([{ kinds: kinds, ids: ids }]) as NostrSub;
|
||||
this.eventSub = sub;
|
||||
|
||||
sub.on('event', (originalEvent: any) => {
|
||||
|
Loading…
Reference in New Issue
Block a user