diff --git a/public/icons/icon-128x128.png b/public/app-icon/icon-128x128.png
similarity index 100%
rename from public/icons/icon-128x128.png
rename to public/app-icon/icon-128x128.png
diff --git a/public/icons/icon-144x144.png b/public/app-icon/icon-144x144.png
similarity index 100%
rename from public/icons/icon-144x144.png
rename to public/app-icon/icon-144x144.png
diff --git a/public/icons/icon-152x152.png b/public/app-icon/icon-152x152.png
similarity index 100%
rename from public/icons/icon-152x152.png
rename to public/app-icon/icon-152x152.png
diff --git a/public/icons/icon-192x192.png b/public/app-icon/icon-192x192.png
similarity index 100%
rename from public/icons/icon-192x192.png
rename to public/app-icon/icon-192x192.png
diff --git a/public/icons/icon-384x384.png b/public/app-icon/icon-384x384.png
similarity index 100%
rename from public/icons/icon-384x384.png
rename to public/app-icon/icon-384x384.png
diff --git a/public/icons/icon-512x512.png b/public/app-icon/icon-512x512.png
similarity index 100%
rename from public/icons/icon-512x512.png
rename to public/app-icon/icon-512x512.png
diff --git a/public/icons/icon-72x72.png b/public/app-icon/icon-72x72.png
similarity index 100%
rename from public/icons/icon-72x72.png
rename to public/app-icon/icon-72x72.png
diff --git a/public/icons/icon-96x96.png b/public/app-icon/icon-96x96.png
similarity index 100%
rename from public/icons/icon-96x96.png
rename to public/app-icon/icon-96x96.png
diff --git a/src/app/components/explore/explore.component.html b/src/app/components/explore/explore.component.html
index 8c5e622..879b3b3 100644
--- a/src/app/components/explore/explore.component.html
+++ b/src/app/components/explore/explore.component.html
@@ -49,7 +49,7 @@
@@ -58,7 +58,7 @@
diff --git a/src/app/components/explore/explore.component.ts b/src/app/components/explore/explore.component.ts
index 0310395..a1c2a07 100644
--- a/src/app/components/explore/explore.component.ts
+++ b/src/app/components/explore/explore.component.ts
@@ -20,6 +20,7 @@ import { MetadataService } from 'app/services/metadata.service';
import { Subject, takeUntil } from 'rxjs';
import { IndexedDBService } from 'app/services/indexed-db.service';
import { Project } from 'app/interface/project.interface';
+import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
@Component({
selector: 'explore',
@@ -47,7 +48,8 @@ export class ExploreComponent implements OnInit, OnDestroy {
private stateService: StateService,
private metadataService: MetadataService,
private indexedDBService: IndexedDBService,
- private changeDetectorRef: ChangeDetectorRef
+ private changeDetectorRef: ChangeDetectorRef,
+ private sanitizer: DomSanitizer
) {}
ngOnInit(): void {
@@ -236,4 +238,19 @@ export class ExploreComponent implements OnInit, OnDestroy {
this.loading = false;
this.changeDetectorRef.detectChanges();
}
+
+ getSafeUrl(url: any, isBanner: boolean): SafeUrl {
+ if (url && typeof url === 'string' && this.isImageUrl(url)) {
+ return this.sanitizer.bypassSecurityTrustUrl(url);
+ } else {
+ const defaultImage = isBanner ? '/images/pages/profile/cover.jpg' : 'images/avatars/avatar-placeholder.png';
+ return this.sanitizer.bypassSecurityTrustUrl(defaultImage);
+ }
+ }
+
+ private isImageUrl(url: string): boolean {
+ return /\.(jpeg|jpg|gif|png|svg|bmp|webp|tiff|ico)$/i.test(url);
+ }
+
+
}
diff --git a/src/app/components/profile/profile.component.html b/src/app/components/profile/profile.component.html
index 72b3570..f0ce37e 100644
--- a/src/app/components/profile/profile.component.html
+++ b/src/app/components/profile/profile.component.html
@@ -17,7 +17,7 @@
-
+
diff --git a/src/app/components/profile/profile.component.ts b/src/app/components/profile/profile.component.ts
index fbc683c..2018e35 100644
--- a/src/app/components/profile/profile.component.ts
+++ b/src/app/components/profile/profile.component.ts
@@ -21,6 +21,7 @@ import { SignerService } from 'app/services/signer.service';
import { MetadataService } from 'app/services/metadata.service';
import { Subject, takeUntil } from 'rxjs';
import { IndexedDBService } from 'app/services/indexed-db.service';
+import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
@Component({
selector: 'profile',
@@ -54,7 +55,9 @@ export class ProfileComponent implements OnInit, OnDestroy {
private _changeDetectorRef: ChangeDetectorRef,
private _metadataService: MetadataService,
private _signerService: SignerService,
- private _indexedDBService: IndexedDBService
+ private _indexedDBService: IndexedDBService,
+ private _sanitizer: DomSanitizer
+
) { }
ngOnInit(): void {
@@ -117,4 +120,8 @@ export class ProfileComponent implements OnInit, OnDestroy {
this._changeDetectorRef.detectChanges();
}
}
+
+ getSafeUrl(url: string): SafeUrl {
+ return this._sanitizer.bypassSecurityTrustUrl(url);
+ }
}
diff --git a/src/app/components/settings/relay/relay.component.html b/src/app/components/settings/relay/relay.component.html
index 921d0a1..2df7088 100644
--- a/src/app/components/settings/relay/relay.component.html
+++ b/src/app/components/settings/relay/relay.component.html
@@ -19,7 +19,7 @@
class="flex h-10 w-10 flex-0 items-center justify-center overflow-hidden rounded-full"
>
diff --git a/src/app/components/settings/relay/relay.component.ts b/src/app/components/settings/relay/relay.component.ts
index 93979bc..6adae8c 100644
--- a/src/app/components/settings/relay/relay.component.ts
+++ b/src/app/components/settings/relay/relay.component.ts
@@ -14,6 +14,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
+import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { RelayService } from 'app/services/relay.service';
import { Subscription } from 'rxjs';
@@ -44,7 +45,8 @@ export class SettingsRelayComponent implements OnInit {
constructor(
private relayService: RelayService,
private cdr: ChangeDetectorRef,
- private zone: NgZone
+ private zone: NgZone,
+ private sanitizer: DomSanitizer
) {}
ngOnInit(): void {
@@ -106,8 +108,14 @@ export class SettingsRelayComponent implements OnInit {
return relay.connected ? 'Connected' : 'Disconnected';
}
- relayFavIcon(url: string) {
- const favUrl = url.replace('wss://', 'https://');
- return favUrl + '/favicon.ico';
- }
+ relayFavIcon(url: string): string {
+ let safeUrl = url.replace('wss://', 'https://').replace('ws://', 'https://');
+
+ return safeUrl + '/favicon.ico';
+ }
+
+ getSafeUrl(url: string): SafeUrl {
+ return this.sanitizer.bypassSecurityTrustUrl(url);
+ }
+
}
diff --git a/src/app/layout/common/user/user.component.html b/src/app/layout/common/user/user.component.html
index 8b1f889..2385508 100644
--- a/src/app/layout/common/user/user.component.html
+++ b/src/app/layout/common/user/user.component.html
@@ -1,7 +1,7 @@
-
+
diff --git a/src/app/layout/common/user/user.component.ts b/src/app/layout/common/user/user.component.ts
index 0780e03..85a87c5 100644
--- a/src/app/layout/common/user/user.component.ts
+++ b/src/app/layout/common/user/user.component.ts
@@ -17,6 +17,7 @@ import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MetadataService } from 'app/services/metadata.service';
import { IndexedDBService } from 'app/services/indexed-db.service';
+import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
@Component({
selector: 'user',
@@ -53,7 +54,9 @@ export class UserComponent implements OnInit, OnDestroy {
private _angorConfigService: AngorConfigService,
private _metadataService: MetadataService,
private _signerService: SignerService,
- private _indexedDBService: IndexedDBService
+ private _indexedDBService: IndexedDBService,
+ private sanitizer: DomSanitizer
+
) { }
ngOnInit(): void {
@@ -148,4 +151,8 @@ export class UserComponent implements OnInit, OnDestroy {
this._angorConfigService.config = { theme };
this._changeDetectorRef.detectChanges();
}
+
+ getSafeUrl(url: string): SafeUrl {
+ return this.sanitizer.bypassSecurityTrustUrl(url);
+ }
}
diff --git a/src/app/services/indexed-db.service.ts b/src/app/services/indexed-db.service.ts
index 4d8f8ac..96d7bb1 100644
--- a/src/app/services/indexed-db.service.ts
+++ b/src/app/services/indexed-db.service.ts
@@ -45,12 +45,10 @@ export class IndexedDBService {
this.loadAllProjectStatsFromDB();
}
- // Returns projects as observable
getProjectsObservable(): Observable {
return this.projectsSubject.asObservable();
}
- // Save new project and notify subscribers
async saveProject(project: Project): Promise {
try {
await this.projectsStore.setItem(project.projectIdentifier, project);
diff --git a/src/app/services/lightning.service.ts b/src/app/services/lightning.service.ts
new file mode 100644
index 0000000..5f09c72
--- /dev/null
+++ b/src/app/services/lightning.service.ts
@@ -0,0 +1,97 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable, of} from 'rxjs';
+import { catchError } from 'rxjs/operators';
+import { LightningResponse, LightningInvoice } from '../types/post';
+import { Event } from 'nostr-tools';
+
+
+@Injectable({
+ providedIn: 'root'
+})
+export class LightningService {
+
+ constructor(
+ private http: HttpClient
+ ) { }
+
+ getLightning(url: string): Observable {
+ return this.http.get(url)
+ .pipe(
+ catchError(() => of({status: "Failed"} as LightningResponse))
+ )
+ }
+
+ getLightningInvoice(url: string, amount: string): Observable {
+ // amount is in millisats so 5 sats === 5000
+ let aUrl = `${url}?amount=${amount}`;
+ return this.http.get(aUrl);
+ }
+
+ // url would be something like `brah@npubkey.com`
+ // which needs to be processed to make the actual request
+ getLightningAddress(url: string): string {
+ const splitUrl = url.split("@");
+ const username = splitUrl[0];
+ const domain = splitUrl[1];
+ return `https://${domain}/.well-known/lnurlp/${username}`;
+ }
+
+ /*
+ example http post to callback if nostr allowed
+ {
+ "kind": 9734,
+ "content": "Zap!",
+ "tags": [
+ ["relays", "wss://nostr-pub.wellorder.com"],
+ ["amount", "21000"],
+ ["lnurl", "lnurl1dp68gurn8ghj7um5v93kketj9ehx2amn9uh8wetvdskkkmn0wahz7mrww4excup0dajx2mrv92x9xp"],
+ ["p", "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9"],
+ ["e", "9ae37aa68f48645127299e9453eb5d908a0cbb6058ff340d528ed4d37c8994fb"]
+ ],
+ "pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
+ "created_at": 1679673265,
+ "id": "30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93",
+ "sig": "f2cb581a84ed10e4dc84937bd98e27acac71ab057255f6aa8dfa561808c981fe8870f4a03c1e3666784d82a9c802d3704e174371aa13d63e2aeaf24ff5374d9d"
+ }
+ */
+ sendZapRequest(callback: string, zapRequest: Event, amount: string, lnurl: string): Observable {
+ const event: string = encodeURI(JSON.stringify((zapRequest)));
+ const url = `${callback}?amount=${amount}&nostr=${event}&lnurl=${lnurl}`
+ return this.http.get(url);
+ }
+
+ async login(): Promise {
+ if (window.webln && !window.webln.isEnabled()) {
+ await window.webln.enable();
+ }
+ return true;
+ }
+
+ hasWebln() {
+ if (window.webln) {
+ return true;
+ }
+ return false;
+ }
+
+ async sendPayment(pr: string) {
+ return await window.webln?.sendPayment(pr)
+ }
+
+ async payInvoice(pr: string) {
+ await this.login();
+ if (this.hasWebln()) {
+ const rsp = await this.sendPayment(pr).catch((error) => {
+ return false;
+ });
+ if (rsp) {
+ return true;
+ }
+ return false;
+ } else {
+ console.log("WebLN not available");
+ return false;
+ }
+ }
+}
diff --git a/src/app/services/projects.service.ts b/src/app/services/projects.service.ts
index bb0494b..312b55e 100644
--- a/src/app/services/projects.service.ts
+++ b/src/app/services/projects.service.ts
@@ -27,7 +27,7 @@ export interface ProjectStats {
})
export class ProjectsService {
private offset = 0;
- private limit = 48;
+ private limit = 21;
private totalProjects = 0;
private loading = false;
private projects: Project[] = [];
diff --git a/src/index.html b/src/index.html
index 2a127d1..e9fd12a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -18,6 +18,7 @@
+