Skip to content
This repository has been archived by the owner on Mar 29, 2024. It is now read-only.

Commit

Permalink
Implement review suggestions, add "logout completely" button and only…
Browse files Browse the repository at this point in the history
… show prompt icon when globally enabled or pending prompts are available
  • Loading branch information
ppacher committed May 23, 2023
1 parent 2358e31 commit 064bdd4
Show file tree
Hide file tree
Showing 17 changed files with 1,315 additions and 5,162 deletions.
6,336 changes: 1,236 additions & 5,100 deletions modules/portmaster/package-lock.json

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions modules/portmaster/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"zone.js": "^0.13.0"
},
"devDependencies": {
"@angular-builders/custom-webpack": "^15.0.0",
"@angular-builders/custom-webpack": "^16.0.0-beta.1",
"@angular-devkit/build-angular": "^16.0.1",
"@angular-eslint/builder": "16.0.1",
"@angular-eslint/eslint-plugin": "16.0.1",
Expand All @@ -67,16 +67,10 @@
"@types/topojson-simplify": "^3.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6",
"codelyzer": "^6.0.2",
"eslint": "^8.40.0",
"jasmine-core": "^5.0.0",
"jasmine-spec-reporter": "^7.0.0",
"js-yaml-loader": "^1.2.2",
"karma": "~6.4.2",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "^2.0.0",
"ng-packagr": "^16.0.1",
"postcss-import": "^15.1.0",
"postcss-loader": "^7.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,13 @@ export class PortapiService {
msg => {
const observer = this._streams$.get(msg.id);
if (!observer) {
console.warn(`Received message for unknown request id ${msg.id} (type=${msg.type})`, msg);
// it's expected that we receive done messages from time to time here
// as portmaster sends a "done" message after we "cancel" a subscription
// and we already remove the observer from _streams$ if the subscription
// is unsubscribed. So just hide that warning message for "done"
if (msg.type !== 'done') {
console.warn(`Received message for unknown request id ${msg.id} (type=${msg.type})`, msg);
}
return;
}

Expand Down
17 changes: 7 additions & 10 deletions modules/portmaster/projects/safing/ui/src/lib/select/select.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { ListKeyManager, ListKeyManagerOption } from '@angular/cdk/a11y';
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, Directive, ElementRef, EventEmitter, forwardRef, HostBinding, HostListener, Input, OnDestroy, Output, QueryList, TemplateRef, ViewChild, ViewChildren } from '@angular/core';
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, DestroyRef, Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, OnDestroy, Output, QueryList, TemplateRef, ViewChild, ViewChildren, forwardRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
import { startWith, takeUntil } from 'rxjs/operators';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { startWith } from 'rxjs/operators';
import { SfngDropdownComponent } from '../dropdown';
import { SelectOption, SfngSelectValueDirective } from './item';

Expand Down Expand Up @@ -58,7 +59,7 @@ export class SfngSelectComponent<T> implements AfterViewInit, ControlValueAccess
private search$ = new BehaviorSubject('');

/** emits and completes when the component is destroyed. */
private destroy$ = new Subject<void>();
private destroyRef = inject(DestroyRef);

/** the key manager used for keyboard support */
private keyManager!: ListKeyManager<SfngSelectRenderedItemDirective>;
Expand Down Expand Up @@ -264,9 +265,7 @@ export class SfngSelectComponent<T> implements AfterViewInit, ControlValueAccess
.withTypeAhead();

this.keyManager.change
.pipe(
takeUntil(this.destroy$)
)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(itemIdx => {
this.renderedItems.forEach(item => {
item.focused = false;
Expand Down Expand Up @@ -307,7 +306,7 @@ export class SfngSelectComponent<T> implements AfterViewInit, ControlValueAccess
.pipe(startWith(undefined)),
this.search$
])
.pipe(takeUntil(this.destroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(
([_, search]) => {
this.updateItems();
Expand Down Expand Up @@ -349,8 +348,6 @@ export class SfngSelectComponent<T> implements AfterViewInit, ControlValueAccess

ngOnDestroy(): void {
this.search$.complete();
this.destroy$.next();
this.destroy$.complete();
}

@HostListener('blur')
Expand Down
20 changes: 8 additions & 12 deletions modules/portmaster/projects/safing/ui/src/lib/tabs/tab-group.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ListKeyManager } from "@angular/cdk/a11y";
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { CdkPortalOutlet, ComponentPortal } from "@angular/cdk/portal";
import { AfterContentInit, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentRef, ContentChildren, ElementRef, EventEmitter, Injector, Input, OnDestroy, OnInit, Output, QueryList, ViewChild, ViewChildren } from "@angular/core";
import { AfterContentInit, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentRef, ContentChildren, DestroyRef, ElementRef, EventEmitter, Injector, Input, OnInit, Output, QueryList, ViewChild, ViewChildren, inject } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { ActivatedRoute, Router } from "@angular/router";
import { Observable, Subject } from "rxjs";
import { distinctUntilChanged, map, takeUntil } from "rxjs/operators";
import { SfngTabComponent, TabOutletComponent, TAB_ANIMATION_DIRECTION, TAB_PORTAL, TAB_SCROLL_HANDLER } from "./tab";
import { distinctUntilChanged, map } from "rxjs/operators";
import { SfngTabComponent, TAB_ANIMATION_DIRECTION, TAB_PORTAL, TAB_SCROLL_HANDLER, TabOutletComponent } from "./tab";

export interface SfngTabContentScrollEvent {
event?: Event;
Expand Down Expand Up @@ -43,7 +44,7 @@ export interface SfngTabContentScrollEvent {
templateUrl: './tab-group.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SfngTabGroupComponent implements AfterContentInit, AfterViewInit, OnInit, OnDestroy {
export class SfngTabGroupComponent implements AfterContentInit, AfterViewInit, OnInit {
@ContentChildren(SfngTabComponent)
tabs: QueryList<SfngTabComponent> | null = null;

Expand Down Expand Up @@ -88,7 +89,7 @@ export class SfngTabGroupComponent implements AfterContentInit, AfterViewInit, O
private _customHeader = false;

private tabActivate$ = new Subject<string>();
private destroy$ = new Subject<void>();
private destroyRef = inject(DestroyRef);

/** onActivate fires when a tab has been activated. */
get onActivate(): Observable<string> { return this.tabActivate$.asObservable() }
Expand Down Expand Up @@ -127,7 +128,7 @@ export class SfngTabGroupComponent implements AfterContentInit, AfterViewInit, O
ngOnInit(): void {
this.route.queryParamMap
.pipe(
takeUntil(this.destroy$),
takeUntilDestroyed(this.destroyRef),
map(params => params.get(this.name)),
distinctUntilChanged(),
)
Expand Down Expand Up @@ -156,7 +157,7 @@ export class SfngTabGroupComponent implements AfterContentInit, AfterViewInit, O
.withWrap()

this.keymanager.change
.pipe(takeUntil(this.destroy$))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(change => {
const activeTab = this.tabs!.get(change);
if (!!activeTab && !!activeTab.tabContent) {
Expand Down Expand Up @@ -225,11 +226,6 @@ export class SfngTabGroupComponent implements AfterContentInit, AfterViewInit, O
setTimeout(() => this.repositionTabBar(), 250)
}

ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}

/**
* @private
* Activates a new tab
Expand Down
4 changes: 3 additions & 1 deletion modules/portmaster/src/app/layout/navigation/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@

<!-- The prompt list drop-down -->
<div class="relative link" cdkOverlayOrigin #promptOrigin="cdkOverlayOrigin"
(click)="promptDropDown.toggle(promptOrigin)" [class.active]="promptDropDown.isOpen">
*ngIf="hasNewPrompts || globalPromptingEnabled" (click)="promptDropDown.toggle(promptOrigin)"
[class.active]="promptDropDown.isOpen">

<span *ngIf="hasNewPrompts" class="absolute w-1.5 h-1.5 bg-yellow-300 rounded-full top-1.5 right-1.5"></span>

Expand Down Expand Up @@ -199,6 +200,7 @@
Show Intro Screen
</app-menu-item>
<app-menu-item (click)="reinitSPN($event)">Re-Initialize SPN</app-menu-item>
<app-menu-item (click)="logoutCompletely($event)">Logout Completely</app-menu-item>
<app-menu-item (click)="resetBroadcastState()">Reset Broadcast State</app-menu-item>
<app-menu-item (click)="clearDNSCache($event)">Clear DNS Cache</app-menu-item>
<app-menu-item (click)="openDataDir($event)">Open Data Directory</app-menu-item>
Expand Down
24 changes: 22 additions & 2 deletions modules/portmaster/src/app/layout/navigation/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ConnectedPosition } from '@angular/cdk/overlay';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core';
import { DebugAPI, PortapiService } from '@safing/portmaster-api';
import { ConfigService, DebugAPI, PortapiService, SPNService, StringSetting } from '@safing/portmaster-api';
import { tap } from 'rxjs/operators';
import { AppComponent } from 'src/app/app.component';
import { NotificationsService, NotificationType, StatusService, VersionStatus } from 'src/app/services';
import { NotificationType, NotificationsService, StatusService, VersionStatus } from 'src/app/services';
import { ActionIndicatorService } from 'src/app/shared/action-indicator';
import { fadeInAnimation, fadeOutAnimation } from 'src/app/shared/animations';
import { ExitService } from 'src/app/shared/exit-screen';
Expand Down Expand Up @@ -35,6 +35,9 @@ export class NavigationComponent implements OnInit {
/** Whether or not we have new, unseen prompts */
hasNewPrompts = false;

/** Whether or not prompting is globally enabled. */
globalPromptingEnabled = false;

@Output()
sideDashChange = new EventEmitter<'collapsed' | 'expanded' | 'force-overlay'>();

Expand All @@ -45,10 +48,12 @@ export class NavigationComponent implements OnInit {
private portapi: PortapiService,
private exitService: ExitService,
private statusService: StatusService,
private configService: ConfigService,
private appComponent: AppComponent,
private debugAPI: DebugAPI,
private actionIndicator: ActionIndicatorService,
private notificationService: NotificationsService,
private spnService: SPNService,
private cdr: ChangeDetectorRef
) { }

Expand Down Expand Up @@ -84,6 +89,12 @@ export class NavigationComponent implements OnInit {
this.cdr.markForCheck();
});

this.configService.watch<StringSetting>('filter/defaultAction')
.subscribe(defaultAction => {
this.globalPromptingEnabled = defaultAction === 'ask';
this.cdr.markForCheck();
})

this.notificationService.new$
.subscribe(notif => {
if (notif.some(n => n.Type === NotificationType.Prompt && n.EventID.startsWith("filter:prompt"))) {
Expand Down Expand Up @@ -156,6 +167,15 @@ export class NavigationComponent implements OnInit {
))
}

/** Logs the user out of the SPN completely by purgin the user profile from the local storage */
logoutCompletely(_: Event) {
this.spnService.logout(true)
.subscribe(this.actionIndicator.httpObserver(
'Logout',
'You have been logged out of the SPN completely.'
))
}

/**
* @private
* Clear the DNS name cache.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ <h1 class="flex flex-row items-center gap-2" cdkDragHandle cdkDrag cdkDragRootEl
<!-- Tab that displays all apps that exit in this country -->
<sfng-tab id="profiles" title="Apps">
<div *sfngTabContent>
<span class="inline-block p-2 mb-2 text-tertiary">The following Apps have connections that are routed throught the
<span class="inline-block p-2 mb-2 text-tertiary">The following Apps have connections that are routed through the
SPN and use an
exit node in {{ countryName }}({{ countryCode }}):</span>
exit node in {{ countryName }} ({{ countryCode }}):</span>
<table class="w-full custom ">
<tbody>
<tr *ngFor="let app of profiles; trackBy: trackProfile"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { takeWhile } from 'rxjs/operators';
import { MapPin, MapService } from './../map.service';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'spn-map-country-overlay',
templateUrl: './country-overlay.html',
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<td class="p-2">
<span class="pl-5">
<spn-node-icon bySafing="true" isActive="true"></spn-node-icon>
in Use
used as Transit
</span>
</td>
<td class="p-2">{{ safingActiveCount }}</td>
Expand All @@ -20,7 +20,7 @@
<td class="p-2">
<span class="pl-5">
<spn-node-icon bySafing="true" isExit="true"></spn-node-icon>
Exit Nodes
used as Exit
</span>
</td>
<td class="p-2">{{ safingExitCount }}</td>
Expand All @@ -36,7 +36,7 @@
<td class="p-2">
<span class="pl-5">
<spn-node-icon bySafing="false" isActive="true"></spn-node-icon>
in Use
used as Transit
</span>
</td>
<td class="p-2">{{ communityActiveCount }}</td>
Expand All @@ -45,7 +45,7 @@
<td class="p-2">
<span class="pl-5">
<spn-node-icon bySafing="false" isExit="true"></spn-node-icon>
Exit Nodes
used as Exit
</span>
</td>
<td class="p-2">{{ communityExitCount }}</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Subscription } from 'rxjs';
import { MapService } from './../map.service';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'spn-map-legend',
templateUrl: './map-legend.html',
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export class MapRendererComponent implements AfterViewInit, OnDestroy {
.attrTween('stroke-dasharray', tweenDashEnter)

renderedPaths.exit()
.interrupt("enter-lane")
.transition("leave-lane")
.duration(200)
.attrTween('stroke-dasharray', tweenDashExit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@

polygon {
stroke: #039af4;
fill: #0376bb;
}

circle {
stroke: #30ae20;
fill: #239215;
}
}

Expand Down Expand Up @@ -147,7 +149,6 @@
}

path.selected {
// FIXME(ppacher): move to TOP
stroke: var(--map-country-border-color-selected);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { ChangeDetectionStrategy, Component, Input } from "@angular/core";

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'spn-node-icon',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './node-icon.html',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<thead>
<th>Name</th>
<th><span class="pl-5">Operator</span></th>
<th>Usage</th>
<th>Used As</th>
<th *ngIf="!!lanes">Latency</th>
<th *ngIf="!!lanes">Capacity</th>
<th>IPv4</th>
Expand Down
8 changes: 4 additions & 4 deletions modules/portmaster/src/app/pages/spn/spn-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@

<spn-map-legend *ngIf="!hoveredCountry" class="absolute right-10 bottom-10"></spn-map-legend>

<div class="absolute bottom-0 left-0 right-0 flex items-center justify-center gap-1" *ngIf="!!proTipTemplate">
<svg xmlns="http://www.w3.org/2000/svg" class="w-3 h-3 -mt-0.5 text-primary" viewBox="0 0 20 20"
fill="currentColor">
<div class="absolute bottom-1.5 left-0 right-0 flex items-center justify-center gap-1 text-secondary"
*ngIf="!!proTipTemplate">
<svg xmlns="http://www.w3.org/2000/svg" class="w-3 h-3 -mt-0.5 " viewBox="0 0 20 20" fill="currentColor">
<path
d="M11 3a1 1 0 10-2 0v1a1 1 0 102 0V3zM15.657 5.757a1 1 0 00-1.414-1.414l-.707.707a1 1 0 001.414 1.414l.707-.707zM18 10a1 1 0 01-1 1h-1a1 1 0 110-2h1a1 1 0 011 1zM5.05 6.464A1 1 0 106.464 5.05l-.707-.707a1 1 0 00-1.414 1.414l.707.707zM5 10a1 1 0 01-1 1H3a1 1 0 110-2h1a1 1 0 011 1zM8 16v-1h4v1a2 2 0 11-4 0zM12 14c.015-.34.208-.646.477-.859a4 4 0 10-4.954 0c.27.213.462.519.476.859h4.002z" />
</svg>
<span class="font-semibold text-primary">Pro Tip:</span>
<span class="font-semibold ">Pro Tip:</span>
<ng-container *ngTemplateOutlet="proTipTemplate"></ng-container>
</div>

Expand Down
Loading

0 comments on commit 064bdd4

Please sign in to comment.