diff --git a/src/app/feed-private/feed-private.ts b/src/app/feed-private/feed-private.ts index c278780..07f25ba 100644 --- a/src/app/feed-private/feed-private.ts +++ b/src/app/feed-private/feed-private.ts @@ -2,12 +2,9 @@ import { ChangeDetectorRef, Component, NgZone } from '@angular/core'; import { Router } from '@angular/router'; import { ApplicationState } from '../services/applicationstate'; import { Utilities } from '../services/utilities'; -import { relayInit, Relay } from 'nostr-tools'; -import * as moment from 'moment'; import { DataValidation } from '../services/data-validation'; import { NostrEvent, NostrEventDocument, NostrNoteDocument, NostrProfile, NostrProfileDocument } from '../services/interfaces'; import { ProfileService } from '../services/profile'; -import { SettingsService } from '../services/settings'; import { map, Observable, shareReplay, Subscription } from 'rxjs'; import { BreakpointObserver } from '@angular/cdk/layout'; import { OptionsService } from '../services/options'; @@ -62,13 +59,9 @@ export class FeedPrivateComponent { private snackBar: MatSnackBar, private ngZone: NgZone ) { - console.log('HOME constructor!!'); // Hm.. called twice, why? + // console.log('HOME constructor!!'); // Hm.. called twice, why? } - // get eventsView$(): Observable { - // return this.feedService.events$.pipe(map((x) => x.slice(0, this.eventsCount))); - // } - ngAfterViewInit() { console.log('ngAfterViewInit'); } @@ -153,16 +146,6 @@ export class FeedPrivateComponent { } } - // async optionsUpdated($event: any, type: any) { - // if (type == 1) { - // this.showCached = false; - // } else { - // this.showBlocked = false; - // } - - // await this.load(); - // } - subscriptions: Subscription[] = []; hasFollowers = false; @@ -175,11 +158,5 @@ export class FeedPrivateComponent { this.showMore(); }) ); - - // const followList = await this.profileService.followList(); - // this.hasFollowers = followList.length > 0; - - // useReactiveContext // New construct in Angular 14 for subscription. - // https://medium.com/generic-ui/the-new-way-of-subscribing-in-an-angular-component-f74ef79a8ffc } } diff --git a/src/app/feed-public/feed-public.ts b/src/app/feed-public/feed-public.ts index fc926aa..ed66848 100644 --- a/src/app/feed-public/feed-public.ts +++ b/src/app/feed-public/feed-public.ts @@ -7,7 +7,6 @@ import * as moment from 'moment'; import { DataValidation } from '../services/data-validation'; import { NostrEvent, NostrNoteDocument, NostrProfile, NostrProfileDocument } from '../services/interfaces'; import { ProfileService } from '../services/profile'; -import { SettingsService } from '../services/settings'; import { NotesService } from '../services/notes'; import { map, Observable, shareReplay, Subscription } from 'rxjs'; import { BreakpointObserver } from '@angular/cdk/layout'; diff --git a/src/app/feed/feed.ts b/src/app/feed/feed.ts index e8fa838..55992cf 100644 --- a/src/app/feed/feed.ts +++ b/src/app/feed/feed.ts @@ -3,16 +3,11 @@ import { Router } from '@angular/router'; import { ApplicationState } from '../services/applicationstate'; import { Utilities } from '../services/utilities'; import { relayInit, Relay, Event } from 'nostr-tools'; -import * as moment from 'moment'; import { DataValidation } from '../services/data-validation'; import { NostrEvent, NostrNoteDocument, NostrProfile, NostrProfileDocument } from '../services/interfaces'; import { ProfileService } from '../services/profile'; -import { SettingsService } from '../services/settings'; -import { NotesService } from '../services/notes'; -import { map, Observable, shareReplay, Subscription } from 'rxjs'; import { BreakpointObserver } from '@angular/cdk/layout'; import { MatDialog } from '@angular/material/dialog'; -import { NoteDialog } from '../shared/create-note-dialog/create-note-dialog'; import { OptionsService } from '../services/options'; import { AuthenticationService } from '../services/authentication'; import { NavigationService } from '../services/navigation'; diff --git a/src/app/home/home.ts b/src/app/home/home.ts index 3fe3a13..02f0da9 100644 --- a/src/app/home/home.ts +++ b/src/app/home/home.ts @@ -3,28 +3,22 @@ import { Router } from '@angular/router'; import { ApplicationState } from '../services/applicationstate'; import { Utilities } from '../services/utilities'; import { relayInit, Relay, Event } from 'nostr-tools'; -import * as moment from 'moment'; import { DataValidation } from '../services/data-validation'; -import { NostrEvent, NostrEventDocument, NostrNoteDocument, NostrProfile, NostrProfileDocument } from '../services/interfaces'; +import { NostrEvent, NostrEventDocument, NostrNoteDocument } from '../services/interfaces'; import { ProfileService } from '../services/profile'; -import { SettingsService } from '../services/settings'; -import { NotesService } from '../services/notes'; import { map, Observable, shareReplay, Subscription } from 'rxjs'; import { BreakpointObserver } from '@angular/cdk/layout'; import { MatDialog } from '@angular/material/dialog'; -import { NoteDialog } from '../shared/create-note-dialog/create-note-dialog'; import { OptionsService } from '../services/options'; import { AuthenticationService } from '../services/authentication'; import { NavigationService } from '../services/navigation'; import { MatSnackBar } from '@angular/material/snack-bar'; -import { BehaviorSubject, combineLatest } from 'rxjs'; -import { animate, style, transition, trigger } from '@angular/animations'; import { DataService } from '../services/data'; import { StorageService } from '../services/storage'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { dexieToRx } from '../shared/utilities'; import { liveQuery } from 'dexie'; - + interface DefaultProfile { pubkey: string; pubkeynpub: string; @@ -108,24 +102,6 @@ export class HomeComponent { }, ]; - // #defaultsChanged: BehaviorSubject = new BehaviorSubject(this.defaults); - - // THIS CAUSED MASSIVE MEMORY LEAK!! - // get defaults$(): Observable { - // return combineLatest([this.#defaultsChanged, this.profileService.items$]).pipe( - // map(([defaultProfiles, followProfiles]) => { - // return defaultProfiles.filter((item) => { - // debugger; - // if (followProfiles.find((p) => p.pubkey === item.pubkey) != null) { - // return undefined; - // } else { - // return item; - // } - // }); - // }) - // ); - // } - constructor( private db: StorageService, public appState: ApplicationState, @@ -164,156 +140,12 @@ export class HomeComponent { alert('coming soon!'); } - downloadProfiles() { - const array = [ - '00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700', - '17e2889fba01021d048a13fd0ba108ad31c38326295460c21e69c43fa8fbe515', - '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245', - '3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d', - '65594f279a789982b55c02a38c92a99b986f891d2814c5f553d1bbfe3e23853d', - '82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2', - 'a341f45ff9758f570a21b000c17d4e53a3a497c8397f26c0e6d61e5acffc7a98', - 'd987084c48390a290f5d2a34603ae64f55137d9b4affced8c0eae030eb222a25', - 'edcd20558f17d99327d841e4582f9b006331ac4010806efa020ef0d40078e6da', - ]; - - array.map((pubkey) => { - this.dataService.enque({ identifier: pubkey, type: 'Profile' }); - }); - - // const observable = this.dataService.downloadNewestProfiles(array); - - // .subscribe((profile) => { - // console.log('PROFILE RECEIVED:', profile); - - // // let doc = profile as NostrEventDocument; - // // const index = array.findIndex((a) => a == doc.pubkey); - - // // if (index > -1) { - // // array.splice(index, 1); - // // } - - // // if (array.length === 0) { - // // console.log('FOUND ALL!!!!'); - // // } - // }); - - // setInterval(() => { - // console.log('observable.closed:', observable.closed); - // }, 250); - } - - downloadProfiles2() { - const array = [ - '00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700', - '17e2889fba01021d048a13fd0ba108ad31c38326295460c21e69c43fa8fbe515', - '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245', - '3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d', - '65594f279a789982b55c02a38c92a99b986f891d2814c5f553d1bbfe3e23853d', - '82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2', - 'a341f45ff9758f570a21b000c17d4e53a3a497c8397f26c0e6d61e5acffc7a98', - 'd987084c48390a290f5d2a34603ae64f55137d9b4affced8c0eae030eb222a25', - 'edcd20558f17d99327d841e4582f9b006331ac4010806efa020ef0d40078e6da', - ]; - - const observable = this.profileService.getProfile(array[0]).subscribe(async (profile) => { - console.log('GOT CACHED PROFILE:', profile); - - debugger; - await this.profileService.follow(profile.pubkey); - }); - - // this.profileService.getProfile(array[1]).subscribe((profile) => { - // console.log('GOT CACHED PROFILE:', profile); - // }); - - // this.profileService.getProfile(array[2]).subscribe((profile) => { - // console.log('GOT CACHED PROFILE:', profile); - // }); - - // this.profileService.getProfile(array[3]).subscribe((profile) => { - // console.log('GOT CACHED PROFILE:', profile); - // }); - - // const observable = this.profileService.getProfile2(array[0]).dataService.downloadNewestProfiles(array).subscribe((profile) => { - // console.log('PROFILE RECEIVED:', profile); - - // let doc = profile as NostrEventDocument; - - // const index = array.findIndex((a) => a == doc.pubkey); - - // if (index > -1) { - // array.splice(index, 1); - // } - - // if (array.length === 0) { - // console.log('FOUND ALL!!!!'); - // } - // }); - - // setInterval(() => { - // console.log('observable.closed:', observable.closed); - // }, 2000); - } - - subscribeEvents() { - const observable = this.dataService.subscribeLatestEvents([1], [], 100).subscribe((event) => { - console.log('EVENT RECEIVED:', event); - }); - - // setInterval(() => { - // console.log('observable.closed:', observable.closed); - // }, 2000); - - // setTimeout(() => { - // observable.unsubscribe(); - // }, 20000); - } - - subscribeEvents2() { - const observable = this.dataService.subscribeLatestEvents([0, 3], [], 100).subscribe((event) => { - console.log('EVENT RECEIVED22:', event); - }); - - // setInterval(() => { - // console.log('observable.closed22:', observable.closed); - // }, 2000); - - // setTimeout(() => { - // observable.unsubscribe(); - // }, 20000); - } - async follow(profile: DefaultProfile) { if (profile.checked) { await this.profileService.follow(profile.pubkey, 0, profile as any); - - // this.feedService.downloadRecent([profile.pubkeyhex]); - - // Perform a detected changes now, since 'profileService.profiles.length' should be updated. - // this.#defaultsChanged.next(this.defaults); - // this.profileService.updated(); } } - // async follow() { - // const pubKeys = this.defaults.filter((p) => p.checked); - - // if (pubKeys.length === 0) { - // return; - // } - - // for (let i = 0; i < pubKeys.length; i++) { - // console.log('LOOP KEY:', pubKeys[i]); - // await this.profileService.follow(pubKeys[i].pubkeyhex, undefined, pubKeys[i] as any); - // } - - // this.feedService.downloadRecent(pubKeys.map((p) => p.pubkeyhex)); - - // // Perform a detected changes now, since 'profileService.profiles.length' should be updated. - // this.cd.detectChanges(); - // } - public trackByFn(index: number, item: NostrEvent) { return item.id; } @@ -370,110 +202,6 @@ export class HomeComponent { }); } - // import(pubkey: string) { - // // TODO: This is a copy-paste of code in circles, refactor ASAP! - - // this.snackBar.open('Importing followers process has started', 'Hide', { - // duration: 2000, - // horizontalPosition: 'center', - // verticalPosition: 'bottom', - // }); - - // pubkey = this.utilities.ensureHexIdentifier(pubkey); - - // this.dataService.downloadNewestContactsEvents([pubkey]).subscribe((event) => { - // const nostrEvent = event as NostrEventDocument; - // const publicKeys = nostrEvent.tags.map((t) => t[1]); - - // for (let i = 0; i < publicKeys.length; i++) { - // const publicKey = publicKeys[i]; - // this.profileService.follow(publicKey); - // } - // }); - - // // TODO: Add ability to slowly query one after one relay, we don't want to receive multiple - // // follow lists and having to process everything multiple times. Just query one by one until - // // we find the list. Until then, we simply grab the first relay only. - // // this.subscriptions.push( - // // this.feedService.downloadContacts(pubkey).subscribe(async (contacts) => { - // // const publicKeys = contacts.tags.map((t) => t[1]); - - // // for (let i = 0; i < publicKeys.length; i++) { - // // const publicKey = publicKeys[i]; - // // const profile = await this.profileService.getProfile(publicKey); - - // // // If the user already exists in our database of profiles, make sure we keep their previous circle (if unfollowed before). - // // if (profile) { - // // await this.profileService.follow(publicKeys[i], profile.circle); - // // } else { - // // await this.profileService.follow(publicKeys[i]); - // // } - // // } - - // // this.router.navigateByUrl('/people'); - - // // // this.ngZone.run(() => { - // // // this.cd.detectChanges(); - // // // }); - // // }) - // // ); - // } - - fetchProfiles(relay: Relay, authors: string[]) { - // const filteredAuthors = authors.filter((a) => { - // return this.profile.profiles[a] == null; - // }); - // console.log('authors:', authors); - // console.log('filteredAuthors:', filteredAuthors); - // if (filteredAuthors.length === 0) { - // return; - // } - // const profileSub = relay.sub([{ kinds: [0], authors: authors }], {}); - // profileSub.on('event', async (originalEvent: NostrEvent) => { - // const event = this.processEvent(originalEvent); - // if (!event) { - // return; - // } - // // const parsed = this.validator.sanitizeProfile(event); - // // const test1 = JSON.parse('{"name":"stat","picture":"https://i.imgur.com/s1scsdH_d.webp?maxwidth=640&shape=thumb&fidelity=medium","about":"senior software engineer at amazon\\n\\n#bitcoin","nip05":"stat@no.str.cr"}'); - // // console.log('WHAT IS WRONG WITH THIS??'); - // // console.log(test1); - // try { - // const profile = this.validator.sanitizeProfile(JSON.parse(event.content) as NostrProfileDocument) as NostrProfileDocument; - // // Persist the profile. - // await this.profile.putProfile(event.pubkey, profile); - // const displayName = encodeURIComponent(profile.name); - // const url = `https://www.nostr.directory/.well-known/nostr.json?name=${displayName}`; - // const rawResponse = await fetch(url, { - // method: 'GET', - // mode: 'cors', - // }); - // if (rawResponse.status === 200) { - // const content = await rawResponse.json(); - // const directoryPublicKey = content.names[displayName]; - // if (event.pubkey === directoryPublicKey) { - // if (!profile.verifications) { - // profile.verifications = []; - // } - // profile.verifications.push('@nostr.directory'); - // // Update the profile with verification data. - // await this.profile.putProfile(event.pubkey, profile); - // } else { - // // profile.verified = false; - // console.warn('Nickname reuse:', url); - // } - // } else { - // // profile.verified = false; - // } - // } catch (err) { - // console.warn('This profile event was not parsed due to errors:', event); - // } - // }); - // profileSub.on('eose', () => { - // profileSub.unsub(); - // }); - } - ngOnDestroy() { this.utilities.unsubscribe(this.subscriptions); } @@ -496,16 +224,6 @@ export class HomeComponent { } } - // async optionsUpdated($event: any, type: any) { - // if (type == 1) { - // this.showCached = false; - // } else { - // this.showBlocked = false; - // } - - // await this.load(); - // } - images = [ 'https://picsum.photos/seed/1/800/600', 'https://picsum.photos/seed/2/600/800', diff --git a/src/app/services/data-validation.ts b/src/app/services/data-validation.ts index 728dc2c..d43cd28 100644 --- a/src/app/services/data-validation.ts +++ b/src/app/services/data-validation.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { NostrEvent, NostrProfile } from './interfaces'; import * as sanitizeHtml from 'sanitize-html'; -import { SettingsService } from './settings'; import { OptionsService } from './options'; @Injectable({ diff --git a/src/app/services/settings.ts b/src/app/services/settings.ts deleted file mode 100644 index 1f0013e..0000000 --- a/src/app/services/settings.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -export class SettingsService { - constructor() {} -} diff --git a/src/app/services/storage.base.ts b/src/app/services/storage.base.ts deleted file mode 100644 index 7ba493e..0000000 --- a/src/app/services/storage.base.ts +++ /dev/null @@ -1,84 +0,0 @@ -// import { StorageService } from './storage.service'; -// import { BehaviorSubject, Observable } from 'rxjs'; - -// export class StorageBase { -// protected table; - -// items: T[] = []; - -// // Just a basic observable that triggers whenever any profile has changed. -// #changedSubject: BehaviorSubject = new BehaviorSubject(this.items); - -// get items$(): Observable { -// return this.#changedSubject.asObservable(); -// } - -// constructor(type: string, private storage: StorageService) { -// this.table = this.storage.table(type); -// } - -// #changed() { -// this.#changedSubject.next(this.items); -// } - -// async #filter(predicate: (value: T, key: string) => boolean): Promise { -// const iterator = this.table.iterator({ keyEncoding: 'utf8', valueEncoding: 'json' }); -// const results = []; - -// for await (const [key, value] of iterator) { -// if (predicate(value, key)) { -// results.push(value); -// } -// } - -// return results; -// } - -// /** Populate the observable with items which we are following. */ -// async initialize() { -// this.items = await this.list(); -// this.#changed(); -// } - -// async list() { -// return this.#filter((value, key) => true); -// } - -// /** Items are upserts, we replace the existing item and only keep latest. */ -// async put(document: T | any) { -// const id = document.id; - -// await this.table.put(id, document); - -// const index = this.items.findIndex((i: any) => i.id == id); - -// if (index === -1) { -// this.items.push(document); -// } else { -// this.items[index] = document; -// } - -// this.#changed(); -// } - -// /** Delete a single item */ -// async delete(id: string) { -// await this.table.del(id); - -// const index = this.items.findIndex((i: any) => i.id == id); -// this.items.splice(index, 1); - -// this.#changed(); -// } - -// /** Wipes all items. */ -// async wipe() { -// for await (const [key, value] of this.table.iterator({})) { -// await this.table.del(key); -// } - -// this.items = []; - -// this.#changed(); -// } -// } diff --git a/src/app/services/thread.ts b/src/app/services/thread.ts index f581e0f..f41c8d8 100644 --- a/src/app/services/thread.ts +++ b/src/app/services/thread.ts @@ -369,21 +369,5 @@ export class ThreadService { this.loadEventThread(eventId); } } - - // Get the event itself. - // const event = await this.storage.get(eventId, 'events'); - - // if (event) { - // this.#event = event; - // this.#eventChanged.next(this.#event); - // } else { - // // console.log('DOWNLOADING2:', eventId); - // // Go grab it from relays. - // this.feedService.downloadEvent(eventId).subscribe((event) => { - // // console.log('DOWNLOAD EVENT CALLBACK 2:', event); - // this.#event = event; - // this.#eventChanged.next(this.#event); - // }); - // } } } diff --git a/src/app/services/ui.ts b/src/app/services/ui.ts index 795f19f..62e3248 100644 --- a/src/app/services/ui.ts +++ b/src/app/services/ui.ts @@ -88,14 +88,4 @@ export class UIService { this.events = []; this.#eventsChanged.next(this.events); } - - // get profile$(): Observable { - // return this.#pubkeyChanged.pipe((pubkey) => { - // if (!pubkey) { - // return null; - // } - - // return this.profileService.getProfile(pubkey); - // }); - // } } diff --git a/src/app/services/user.ts b/src/app/services/user.ts deleted file mode 100644 index fa4b78c..0000000 --- a/src/app/services/user.ts +++ /dev/null @@ -1,75 +0,0 @@ -// import { Injectable } from '@angular/core'; -// import { Circle } from './interfaces'; -// import { BehaviorSubject, from, Observable } from 'rxjs'; -// import { liveQuery } from 'dexie'; -// import { StorageService } from './storage.service'; -// import { CacheService } from './cache.service'; -// import { Utilities } from './utilities.service'; - -// @Injectable({ -// providedIn: 'root', -// }) -// export class UserService { -// private table; - -// circles: Circle[] = []; - -// cache = new CacheService(); - -// items$ = liveQuery(() => this.items()); - -// async items() { -// return await this.table.toArray(); -// } - -// constructor(private db: StorageService, private utilities: Utilities) { -// this.table = this.db.notes; -// } - -// /** Important to call to ensure we have the default circle added */ -// async initialize() { -// const defaultCircle = await this.table.get(0); - -// if (!defaultCircle) { -// await this.put(CircleService.DEFAULT); -// } - -// // Cache the circle so we can lookup quickly. -// this.items$.subscribe((circles) => { -// this.circles = circles; -// }); -// } - -// async get(id?: number) { -// if (id == null) { -// return undefined; -// } - -// // Use the cache if loaded already. -// if (this.circles.length > 0) { -// return this.circles.find((c) => c.id == id); -// } else { -// return await this.table.get(id); -// } -// } - -// async put(document: Circle | any) { -// const now = this.utilities.now(); - -// if (!document.created) { -// document.created = now; -// } - -// document.modified = now; -// await this.table.put(document); -// } - -// async delete(id: number) { -// await this.table.delete(id); -// } - -// /** Wipes all circles. */ -// async wipe() { -// this.table.clear(); -// } -// } diff --git a/src/app/user/user.ts b/src/app/user/user.ts index 61c465c..28e7cdc 100644 --- a/src/app/user/user.ts +++ b/src/app/user/user.ts @@ -7,7 +7,6 @@ import * as moment from 'moment'; import { DataValidation } from '../services/data-validation'; import { Circle, NostrEvent, NostrEventDocument, NostrProfile, NostrProfileDocument, ProfileStatus } from '../services/interfaces'; import { ProfileService } from '../services/profile'; -import { SettingsService } from '../services/settings'; import { OptionsService } from '../services/options'; import { NavigationService } from '../services/navigation'; import { CircleService } from '../services/circle';