mirror of
https://github.com/block-core/blockcore-notes.git
synced 2024-09-29 06:20:42 +00:00
Fix Circle Service with new database code
This commit is contained in:
parent
54074601f0
commit
391a2a71e0
@ -185,6 +185,7 @@ export class AppComponent {
|
||||
|
||||
/** Run initialize whenever user has been authenticated. */
|
||||
async initialize() {
|
||||
debugger;
|
||||
// await this.storage.open();
|
||||
// await this.storage.initialize();
|
||||
await this.db.initialize('blockcore-' + this.appState.getPublicKey());
|
||||
@ -253,6 +254,8 @@ export class AppComponent {
|
||||
},
|
||||
});
|
||||
|
||||
debugger;
|
||||
|
||||
// Create the listeners (filters) for relays:
|
||||
// TODO: There is limit on maximum following, we need a strategy to handle that.
|
||||
// potentially subscribing and unsubscribing on intervals with a .since field between each interval.
|
||||
@ -263,7 +266,11 @@ export class AppComponent {
|
||||
|
||||
console.log('PUB KEYS:', pubKeys);
|
||||
|
||||
this.relayService.queueSubscription([{ authors: pubKeys }]);
|
||||
// Subscribe to new events but don't get any history (limit: 0).
|
||||
|
||||
console.log('queueSubscription:', { authors: pubKeys, since: this.db.state.since });
|
||||
|
||||
this.relayService.queueSubscription([{ authors: pubKeys, since: this.db.state.since }]);
|
||||
|
||||
// this.relayService.
|
||||
|
||||
|
@ -2,53 +2,44 @@
|
||||
|
||||
<div class="feed-page">
|
||||
<!-- <p>Circles is how you organize people you follow. Different circles can have different rules applied and circles is an important way to make the experience more enjoyable.</p> -->
|
||||
|
||||
|
||||
<div *ngIf="items$ | withStatus | async as items">
|
||||
<ng-template [ngIf]="items.value">
|
||||
<mat-card class="circle-container" *ngFor="let circle of items.value">
|
||||
<div class="circle-item"><mat-icon matListItemIcon [style.color]="circle.color">trip_origin</mat-icon></div>
|
||||
<div class="circle-item">
|
||||
{{ circle.name }}<br />
|
||||
<span class="dimmed"
|
||||
><span>Count: {{ countMembers(circle) }}</span></span
|
||||
><br />
|
||||
<span class="dimmed"><span *ngIf="circle.public">Public</span> <span *ngIf="!circle.public">Private</span> - {{ circle.style | circlestyle }} - Created: {{ circle.created | ago }}</span>
|
||||
</div>
|
||||
<div class="circle-item">
|
||||
<button class="circle-button" mat-icon-button [matMenuTriggerFor]="menu">
|
||||
<mat-icon class="circle-button-icon">more_vert</mat-icon>
|
||||
</button>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item [matMenuTriggerFor]="copyMenu">
|
||||
<mat-icon>copy_all</mat-icon>
|
||||
<span>Copy</span>
|
||||
</button>
|
||||
<button *ngIf="circle.id" mat-menu-item (click)="deleteCircle(circle.id)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>Delete Circle</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #copyMenu="matMenu">
|
||||
<button mat-menu-item (click)="copyPubKeys(circle)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
<span>Public Keys (npub)</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="copyPubKeysHex(circle)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
<span>Public Keys (hex)</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</mat-card>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="items.loading"><mat-spinner class="loading"></mat-spinner></ng-template>
|
||||
<ng-template [ngIf]="items.error">Error {{ items.error }}</ng-template>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<mat-card class="circle-container" *ngFor="let circle of circleService.circles">
|
||||
<div class="circle-item"><mat-icon matListItemIcon [style.color]="circle.color">trip_origin</mat-icon></div>
|
||||
<div class="circle-item">
|
||||
{{ circle.name }}<br />
|
||||
<span class="dimmed"><span>Count: {{ countMembers(circle) }}</span></span
|
||||
><br />
|
||||
<span class="dimmed"><span *ngIf="circle.public">Public</span> <span *ngIf="!circle.public">Private</span> - {{ circle.style | circlestyle }} - Created: {{ circle.created | ago }}</span>
|
||||
</div>
|
||||
<div class="circle-item">
|
||||
<button class="circle-button" mat-icon-button [matMenuTriggerFor]="menu">
|
||||
<mat-icon class="circle-button-icon">more_vert</mat-icon>
|
||||
</button>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item [matMenuTriggerFor]="copyMenu">
|
||||
<mat-icon>copy_all</mat-icon>
|
||||
<span>Copy</span>
|
||||
</button>
|
||||
<button *ngIf="circle.id" mat-menu-item (click)="deleteCircle(circle.id)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>Delete Circle</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #copyMenu="matMenu">
|
||||
<button mat-menu-item (click)="copyPubKeys(circle)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
<span>Public Keys (npub)</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="copyPubKeysHex(circle)">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
<span>Public Keys (hex)</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</mat-card>
|
||||
|
||||
<!-- <mat-card class="circle-container" *ngFor="let circle of circles">
|
||||
<div class="circle-item"><mat-icon matListItemIcon [style.color]="circle.color">trip_origin</mat-icon></div>
|
||||
<div class="circle-item">
|
||||
|
@ -26,12 +26,12 @@ export class CirclesComponent {
|
||||
following: NostrProfileDocument[] = [];
|
||||
searchTerm: any;
|
||||
|
||||
items: Circle[] = [];
|
||||
items$ = this.circleService.items$.pipe(
|
||||
tap((items) => {
|
||||
this.items = items;
|
||||
})
|
||||
);
|
||||
// items: Circle[] = [];
|
||||
// items$ = this.circleService.items$.pipe(
|
||||
// tap((items) => {
|
||||
// this.items = items;
|
||||
// })
|
||||
// );
|
||||
|
||||
constructor(
|
||||
public appState: ApplicationState,
|
||||
@ -104,13 +104,13 @@ export class CirclesComponent {
|
||||
}
|
||||
|
||||
private getPublicPublicKeys() {
|
||||
console.log(this.items);
|
||||
// console.log(this.items);
|
||||
console.log(this.following);
|
||||
|
||||
const items: string[] = [];
|
||||
|
||||
for (let i = 0; i < this.items.length; i++) {
|
||||
const circle = this.items[i];
|
||||
for (let i = 0; i < this.circleService.circles.length; i++) {
|
||||
const circle = this.circleService.circles[i];
|
||||
|
||||
if (circle.public) {
|
||||
const profiles = this.getFollowingInCircle(circle.id);
|
||||
@ -242,6 +242,6 @@ export class CirclesComponent {
|
||||
},
|
||||
];
|
||||
|
||||
this.subscriptions.push(this.profileService.items$.subscribe((profiles) => (this.following = profiles)) as Subscription);
|
||||
// this.subscriptions.push(this.profileService.items$.subscribe((profiles) => (this.following = profiles)) as Subscription);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ 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;
|
||||
@ -182,6 +182,8 @@ export class HomeComponent {
|
||||
// Do what should be done next...
|
||||
});
|
||||
|
||||
await this.db.storage.delete();
|
||||
|
||||
location.reload();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Circle } from './interfaces';
|
||||
import { BehaviorSubject, from, Observable } from 'rxjs';
|
||||
import { liveQuery } from 'dexie';
|
||||
import { StorageService } from './storage';
|
||||
import { CacheService } from './cache';
|
||||
import { Utilities } from './utilities';
|
||||
@ -11,32 +10,30 @@ import { dexieToRx } from '../shared/utilities';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class CircleService {
|
||||
static DEFAULT: Circle[] = [{ id: 0, name: 'Following', color: '#e91e63', style: 1, public: true },
|
||||
{id: 1, name: "Text", color: '#7cb342', style: 2, public: true},
|
||||
{id: 2, name: "Photo", color: '#ffb300', style: 3, public: true},
|
||||
{id: 3, name: "Film", color: '#26c6da', style: 4, public: true},
|
||||
{id: 4, name: "Music", color: '#ba9eea', style: 5, public: true},
|
||||
{id: 5, name: "Podcast", color: '#ff8a65', style: 6, public: true}];
|
||||
|
||||
private get table() {
|
||||
return this.db.circles;
|
||||
}
|
||||
static DEFAULT: Circle[] = [
|
||||
{ id: 0, name: 'Following', color: '#e91e63', style: 1, public: true },
|
||||
{ id: 1, name: 'Text', color: '#7cb342', style: 2, public: true },
|
||||
{ id: 2, name: 'Photo', color: '#ffb300', style: 3, public: true },
|
||||
{ id: 3, name: 'Film', color: '#26c6da', style: 4, public: true },
|
||||
{ id: 4, name: 'Music', color: '#ba9eea', style: 5, public: true },
|
||||
{ id: 5, name: 'Podcast', color: '#ff8a65', style: 6, public: true },
|
||||
];
|
||||
|
||||
circles: Circle[] = [];
|
||||
|
||||
cache = new CacheService();
|
||||
|
||||
items$ = dexieToRx(liveQuery(() => this.items()));
|
||||
// items$ = dexieToRx(liveQuery(() => this.items()));
|
||||
|
||||
async items() {
|
||||
return await this.table.toArray();
|
||||
}
|
||||
// async items() {
|
||||
// return await this.table.toArray();
|
||||
// }
|
||||
|
||||
constructor(private db: StorageService, private utilities: Utilities) {}
|
||||
|
||||
/** Important to call to ensure we have the default circle added */
|
||||
async initialize() {
|
||||
const defaultCircle = await this.table.get(0);
|
||||
const defaultCircle = await this.db.storage.getCircle(0);
|
||||
|
||||
if (!defaultCircle) {
|
||||
for (let index = 0; index < CircleService.DEFAULT.length; index++) {
|
||||
@ -45,10 +42,7 @@ export class CircleService {
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the circle so we can lookup quickly.
|
||||
this.items$.subscribe((circles) => {
|
||||
this.circles = circles;
|
||||
});
|
||||
this.circles = await this.db.storage.getCircles();
|
||||
}
|
||||
|
||||
getSync(id?: number) {
|
||||
@ -68,7 +62,7 @@ export class CircleService {
|
||||
if (this.circles.length > 0) {
|
||||
return this.circles.find((c) => c.id == id);
|
||||
} else {
|
||||
return await this.table.get(id);
|
||||
return await this.db.storage.getCircle(id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,15 +74,10 @@ export class CircleService {
|
||||
}
|
||||
|
||||
document.modified = now;
|
||||
await this.table.put(document);
|
||||
await this.db.storage.putCircle(document);
|
||||
}
|
||||
|
||||
async delete(id: number) {
|
||||
await this.table.delete(id);
|
||||
}
|
||||
|
||||
/** Wipes all circles. */
|
||||
async wipe() {
|
||||
this.table.clear();
|
||||
await this.db.storage.deleteCircle(id);
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,12 @@ export interface NostrRelaySubscription {
|
||||
filters: Filter[];
|
||||
}
|
||||
|
||||
export interface StateDocument {
|
||||
id: number;
|
||||
since: number;
|
||||
modified?: number;
|
||||
}
|
||||
|
||||
export interface NostrRelayDocument {
|
||||
url: string;
|
||||
// read: boolean;
|
||||
|
@ -206,8 +206,6 @@ export class RelayService {
|
||||
const index = this.workers.findIndex((v) => v.url == url);
|
||||
const worker = this.workers[index];
|
||||
|
||||
debugger;
|
||||
|
||||
for (let index = 0; index < this.subs2.length; index++) {
|
||||
const sub = this.subs2[index];
|
||||
worker.subscribe(sub.filters, sub.id);
|
||||
|
@ -2,8 +2,9 @@ import { Injectable } from '@angular/core';
|
||||
import Dexie, { Table } from 'dexie';
|
||||
import { ApplicationState } from './applicationstate';
|
||||
import { DatabaseService } from './database';
|
||||
import { Circle, NostrEventDocument, NostrNoteDocument, NostrProfileDocument, NostrRelayDocument } from './interfaces';
|
||||
import { Circle, NostrEventDocument, NostrNoteDocument, NostrProfileDocument, NostrRelayDocument, StateDocument } from './interfaces';
|
||||
import { Storage } from '../types/storage';
|
||||
import * as moment from 'moment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@ -34,15 +35,42 @@ export class StorageService {
|
||||
}
|
||||
|
||||
db!: DatabaseService;
|
||||
state!: StateDocument;
|
||||
|
||||
async initialize(databaseName: string) {
|
||||
// Open the new storage database.
|
||||
this.storage = new Storage('blockcore-notes-' + this.appState.getPublicKey(), 1);
|
||||
await this.storage.open();
|
||||
|
||||
let state = await this.storage.getState();
|
||||
|
||||
if (!state) {
|
||||
// The initial since we will use is two days past.
|
||||
const timeAgo = moment().subtract(2, 'days').unix();
|
||||
|
||||
state = {
|
||||
id: 1,
|
||||
since: timeAgo,
|
||||
};
|
||||
}
|
||||
|
||||
this.state = state;
|
||||
|
||||
// Update the state on interval.
|
||||
setTimeout(async () => {
|
||||
console.log('Persisting state...');
|
||||
|
||||
// The since will always be set slightly back in time to counteract difference in clocks
|
||||
// for different event creators on the nostr network.
|
||||
const timeAgo = moment().subtract(10, 'minutes').unix();
|
||||
this.state.since = timeAgo;
|
||||
|
||||
await this.storage.putState(this.state);
|
||||
}, 60 * 1000);
|
||||
|
||||
// TODO: Remove, old code.
|
||||
this.db = new DatabaseService(databaseName);
|
||||
return this.db.open();
|
||||
// this.db = new DatabaseService(databaseName);
|
||||
// return this.db.open();
|
||||
}
|
||||
|
||||
close() {
|
||||
|
@ -68,7 +68,7 @@
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #categories="matMenu">
|
||||
<button *ngFor="let circle of circleService.items$ | async" mat-menu-item (click)="follow(circle.id)">
|
||||
<button *ngFor="let circle of circleService.circles" mat-menu-item (click)="follow(circle.id)">
|
||||
<mat-icon [style.color]="circle.color">trip_origin</mat-icon>
|
||||
<span>{{ circle.name }}</span>
|
||||
</button>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { openDB, deleteDB, wrap, unwrap, IDBPDatabase, DBSchema } from 'idb';
|
||||
import { Circle, NostrEventDocument, NostrNoteDocument, NostrProfileDocument, NostrRelayDocument } from '../services/interfaces';
|
||||
import { Circle, NostrEventDocument, NostrNoteDocument, NostrProfileDocument, NostrRelayDocument, StateDocument } from '../services/interfaces';
|
||||
|
||||
/** Make sure you read and learn: https://github.com/jakearchibald/idb */
|
||||
|
||||
@ -8,6 +8,10 @@ export function now() {
|
||||
}
|
||||
|
||||
interface NotesDB extends DBSchema {
|
||||
state: {
|
||||
value: StateDocument;
|
||||
key: number;
|
||||
};
|
||||
relays: {
|
||||
value: NostrRelayDocument;
|
||||
key: string;
|
||||
@ -35,7 +39,7 @@ interface NotesDB extends DBSchema {
|
||||
export class Storage {
|
||||
public db!: IDBPDatabase<NotesDB>;
|
||||
|
||||
constructor(private name: string, private version: number) { }
|
||||
constructor(private name: string, private version: number) {}
|
||||
|
||||
async open() {
|
||||
this.db = await openDB<NotesDB>(this.name, this.version, {
|
||||
@ -43,6 +47,7 @@ export class Storage {
|
||||
db.createObjectStore('relays', { keyPath: 'url' });
|
||||
db.createObjectStore('notes', { keyPath: 'id' });
|
||||
db.createObjectStore('circles', { keyPath: 'id' });
|
||||
db.createObjectStore('state', { keyPath: 'id' });
|
||||
|
||||
const eventsStore = db.createObjectStore('events', { keyPath: 'id' });
|
||||
eventsStore.createIndex('pubkey', 'pubkey');
|
||||
@ -67,10 +72,24 @@ export class Storage {
|
||||
this.db.close();
|
||||
}
|
||||
|
||||
async getState() {
|
||||
return this.db.get('state', 1);
|
||||
}
|
||||
|
||||
async putState(value: StateDocument) {
|
||||
value.id = 1;
|
||||
value.modified = now();
|
||||
return this.db.put('state', value);
|
||||
}
|
||||
|
||||
async getCircle(key: number) {
|
||||
return this.db.get('circles', key);
|
||||
}
|
||||
|
||||
async getCircles() {
|
||||
return this.db.getAll('circles');
|
||||
}
|
||||
|
||||
async putCircle(value: Circle) {
|
||||
value.modified = now();
|
||||
return this.db.put('circles', value);
|
||||
@ -118,6 +137,10 @@ export class Storage {
|
||||
return this.db.put('relays', value);
|
||||
}
|
||||
|
||||
async deleteCircle(key: number) {
|
||||
return this.db.delete('circles', key);
|
||||
}
|
||||
|
||||
async deleteRelay(key: string) {
|
||||
return this.db.delete('relays', key);
|
||||
}
|
||||
|
@ -78,7 +78,6 @@ addEventListener('message', async (ev: MessageEvent) => {
|
||||
await relayWorker.publish(request.data);
|
||||
break;
|
||||
case 'subscribe':
|
||||
debugger;
|
||||
await relayWorker.subscribe(request.data.filters, request.data.id);
|
||||
break;
|
||||
case 'unsubscribe':
|
||||
@ -136,7 +135,6 @@ export class RelayWorker {
|
||||
|
||||
relay.on('disconnect', () => {
|
||||
console.log(`DISCONNECTED! ${relay?.url}`);
|
||||
debugger;
|
||||
this.subscriptions = [];
|
||||
postMessage({ type: 'status', data: 0, url: relay.url } as RelayResponse);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user