Make relays a first class item type

- Move Settings into the right-side profile menu.
- Make Relays a dedicated section on main menu.
This commit is contained in:
SondreB 2023-02-23 16:17:05 +01:00
parent 87315af308
commit 5223bee764
No known key found for this signature in database
GPG Key ID: D6CC44C75005FDBF
6 changed files with 293 additions and 3 deletions

View File

@ -27,6 +27,7 @@ import { FeedPrivateComponent } from './feed-private/feed-private';
import { ConnectKeyComponent } from './connect/key/key';
import { EditorComponent } from './editor/editor';
import { ArticleComponent } from './article/article';
import { RelaysManagementComponent } from './relays/relays';
const routes: Routes = [
{
@ -221,6 +222,14 @@ const routes: Routes = [
data: LoadingResolverService,
},
},
{
path: 'relays',
component: RelaysManagementComponent,
canActivate: [AuthGuard],
resolve: {
data: LoadingResolverService,
},
},
{
path: 'development',
component: DevelopmentComponent,

View File

@ -111,9 +111,9 @@
<mat-icon>construction</mat-icon>
<span *ngIf="displayLabels">Development</span>
</a> -->
<a [routerLink]="['/settings']" mat-menu-item (click)="toggleMenu()" [routerLinkActiveOptions]="{ exact: true }" routerLinkActive="active">
<mat-icon>settings</mat-icon>
<span *ngIf="displayLabels">Settings</span>
<a [routerLink]="['/relays']" mat-menu-item (click)="toggleMenu()" [routerLinkActiveOptions]="{ exact: true }" routerLinkActive="active">
<mat-icon>dns</mat-icon>
<span *ngIf="displayLabels">Relays</span>
</a>
<a mat-menu-item (click)="toggleMenuSize()">
<mat-icon *ngIf="displayLabels">chevron_left</mat-icon>
@ -171,6 +171,10 @@
<mat-icon>edit</mat-icon>
<span>Edit profile</span>
</a>
<a [routerLink]="['/settings']" mat-menu-item (click)="toggleProfileMenu()" [routerLinkActiveOptions]="{ exact: true }" routerLinkActive="active">
<mat-icon>settings</mat-icon>
<span *ngIf="displayLabels">Settings</span>
</a>
<a [routerLink]="['/about']" mat-menu-item (click)="toggleProfileMenu()" [routerLinkActiveOptions]="{ exact: true }" routerLinkActive="active">
<mat-icon>help_outline</mat-icon>
<span>About</span>

View File

@ -124,6 +124,7 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { ArticleComponent } from './article/article';
import { LabelPipe } from './shared/label.pipe';
import { LabelComponent } from './shared/label/label';
import { RelaysManagementComponent } from './relays/relays';
@NgModule({
declarations: [
@ -201,6 +202,7 @@ import { LabelComponent } from './shared/label/label';
ArticleComponent,
LabelComponent,
LabelPipe,
RelaysManagementComponent
],
imports: [
AboutModule,

87
src/app/relays/relays.css Normal file
View File

@ -0,0 +1,87 @@
.example-action-buttons {
padding-bottom: 20px;
}
.example-headers-align .mat-expansion-panel-header-description {
justify-content: space-between;
align-items: center;
}
.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field {
margin-left: 8px;
}
.online {
margin-left: 0.2em;
margin-bottom: -0.2em;
}
.relay-status-0 {
color: silver;
}
.relay-status-1 {
color: green;
}
.relay-status-2 {
color: orange;
}
.relay-status-3 {
color: red;
}
.relay-status-4 {
color: rgb(49, 49, 210);
}
.relay-read-disabled {
color: rgb(49, 49, 210) !important;
}
.relay-disabled {
color: rgb(234, 136, 9) !important;
}
.primary-relay {
color: rgb(198, 3, 181);
}
.relay-options {
margin-top: 0.4em;
margin-bottom: 0.2em;
}
.settings-action-buttons {
padding-top: 0.8em;
padding-bottom: 1em;
}
.settings-action-buttons button {
margin-bottom: 1em;
margin-right: 1em;
}
/* When changing the sidenav-content to flex, the toolbar does not render properly, so a minor hack is needed. */
@media only screen and (max-width: 599px) {
.settings-action-buttons button {
width: 100%;
margin-right: 0;
}
.mat-expansion-panel-header-title {
flex-grow: 2 !important;
}
.mat-expansion-panel-header-description {
flex-grow: 1 !important;
}
}
.relay-button {
margin-top: 0.8em;
}
.options-slider {
margin-left: 1em;
}

View File

@ -0,0 +1,25 @@
<div class="full-page">
<div class="page">
<div class="options">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Options</mat-panel-title>
<mat-panel-description></mat-panel-description>
</mat-expansion-panel-header>
<div class="settings-action-buttons">
<!-- <button mat-stroked-button (click)="toggle()"><span *ngIf="!open">Expand All</span><span *ngIf="open">Collapse All</span></button>
<br /> -->
<button mat-flat-button color="primary" (click)="getRelays()">Append from extension</button><button mat-flat-button color="primary" (click)="getDefaultRelays()">Append from app</button>
<br />
<button mat-stroked-button (click)="dataService.publishContactsAndRelays()">Publish relay (and following) list</button> <button mat-stroked-button (click)="dataService.publishRelays()">Publish relay (NIP-65) list</button><br /><br />
<button mat-flat-button color="warn" (click)="deleteRelays()">Delete all relays</button>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
<app-relays [relays]="relayService.items2"></app-relays>
</div>
</div>

163
src/app/relays/relays.ts Normal file
View File

@ -0,0 +1,163 @@
import { Component, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatAccordion } from '@angular/material/expansion';
import { Relay } from 'nostr-tools';
import { ApplicationState } from '../services/applicationstate';
import { StorageService } from '../services/storage';
import { EventService } from '../services/event';
import { NostrRelay } from '../services/interfaces';
import { ProfileService } from '../services/profile';
import { RelayService } from '../services/relay';
import { ThemeService } from '../services/theme';
import { AddRelayDialog, AddRelayDialogData } from '../shared/add-relay-dialog/add-relay-dialog';
import { OptionsService } from '../services/options';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DataService } from '../services/data';
import { NostrService } from '../services/nostr';
import { UploadService } from '../services/upload';
@Component({
selector: 'app-relays-management',
templateUrl: './relays.html',
styleUrls: ['./relays.css'],
})
export class RelaysManagementComponent {
@ViewChild(MatAccordion) accordion!: MatAccordion;
wiped = false;
wipedNonFollow = false;
wipedNotes = false;
open = false;
constructor(
public uploadService: UploadService,
private nostr: NostrService,
public optionsService: OptionsService,
public relayService: RelayService,
public dialog: MatDialog,
public appState: ApplicationState,
private profileService: ProfileService,
public theme: ThemeService,
public db: StorageService,
private snackBar: MatSnackBar,
public dataService: DataService
) {}
toggle() {
if (this.open) {
this.open = false;
this.accordion.closeAll();
} else {
this.open = true;
this.accordion.openAll();
}
}
openMediaPlayer() {
this.optionsService.values.showMediaPlayer = true;
}
async primaryRelay(relay: NostrRelay) {
this.optionsService.values.primaryRelay = relay.url;
this.optionsService.save();
}
// async deleteRelay(relay: Relay) {
// await this.relayService.deleteRelay(relay.url);
// }
async deleteRelays() {
await this.relayService.deleteRelays([]);
}
async clearProfileCache() {
// await this.profileService.wipeNonFollow();
this.wipedNonFollow = true;
}
// async onRelayChanged(relay: NostrRelay) {
// if (relay.metadata.enabled && relay.metadata.read) {
// await relay.connect();
// } else if (!relay.metadata.read) {
// await relay.close();
// } else {
// await relay.close();
// }
// await this.relayService.putRelayMetadata(relay.metadata);
// }
async clearNotesCache() {
// await this.feedService.wipe();
this.wipedNotes = true;
}
async getDefaultRelays() {
// Append the default relays.
await this.relayService.appendRelays(this.nostr.defaultRelays);
}
// private getPublicPublicKeys() {
// console.log(this.profileService.following);
// const items: string[] = [];
// 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);
// const pubkeys = profiles.map((p) => p.pubkey);
// items.push(...pubkeys);
// }
// }
// return items;
// }
async getRelays() {
const relays = await this.nostr.relays();
// Append the default relays.
await this.relayService.appendRelays(relays);
}
ngOnInit() {
this.appState.updateTitle('Relays');
this.appState.showBackButton = false;
this.appState.actions = [
{
icon: 'add_circle',
tooltip: 'Add Relay',
click: () => {
this.addRelay();
},
},
];
}
registerHandler(protocol: string, parameter: string) {
// navigator.registerProtocolHandler(protocol, `./index.html?${parameter}=%s`);
navigator.registerProtocolHandler(protocol, `/?${parameter}=%s`);
}
addRelay(): void {
const dialogRef = this.dialog.open(AddRelayDialog, {
data: { read: true, write: true },
maxWidth: '100vw',
panelClass: 'full-width-dialog',
});
dialogRef.afterClosed().subscribe(async (result: AddRelayDialogData) => {
if (!result) {
return;
}
// Append the Web Socket prefix if missing.
if (result.url.indexOf('://') === -1) {
result.url = 'wss://' + result.url;
}
await this.relayService.appendRelay(result.url, result.read, result.write);
});
}
}