begin popover for UI launch select

This commit is contained in:
Matt Hill
2023-03-07 19:48:49 -07:00
committed by Aiden McClelland
parent cb7790ccba
commit ee9c328606
7 changed files with 93 additions and 53 deletions

View File

@@ -6,8 +6,8 @@ import { SharedPipesModule } from '@start9labs/shared'
import {
AppInterfacesItemComponent,
AppInterfacesPage,
AddressTypePipe,
} from './app-interfaces.page'
import { UiPipeModule } from 'src/app/pipes/ui/ui.module'
const routes: Routes = [
{
@@ -22,11 +22,8 @@ const routes: Routes = [
IonicModule,
RouterModule.forChild(routes),
SharedPipesModule,
UiPipeModule,
],
declarations: [
AppInterfacesPage,
AppInterfacesItemComponent,
AddressTypePipe,
],
declarations: [AppInterfacesPage, AppInterfacesItemComponent],
})
export class AppInterfacesPageModule {}

View File

@@ -1,10 +1,4 @@
import {
ChangeDetectionStrategy,
Component,
Input,
Pipe,
PipeTransform,
} from '@angular/core'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { ModalController, ToastController } from '@ionic/angular'
import { getPkgId, copyToClipboard } from '@start9labs/shared'
@@ -80,31 +74,3 @@ export class AppInterfacesItemComponent {
await toast.present()
}
}
@Pipe({
name: 'addressType',
})
export class AddressTypePipe implements PipeTransform {
transform(address: string): string {
if (isValidIpv4(address)) return 'IPv4'
if (isValidIpv6(address)) return 'IPv6'
const hostname = new URL(address).hostname
if (hostname.endsWith('.onion')) return 'Tor'
if (hostname.endsWith('.local')) return 'Local'
return 'Custom'
}
}
function isValidIpv4(address: string): boolean {
const regexExp =
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
return regexExp.test(address)
}
function isValidIpv6(address: string): boolean {
const regexExp =
/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/gi
return regexExp.test(address)
}

View File

@@ -25,10 +25,35 @@
slot="end"
fill="clear"
color="primary"
(click)="launchUi($event, installed['address-info'])"
(click)="openPopover($event)"
[disabled]="status !== 'running'"
>
<ion-icon slot="icon-only" name="open-outline"></ion-icon>
</ion-button>
<ion-popover
#popover
[isOpen]="isPopoverOpen"
(didDismiss)="isPopoverOpen = false"
mode="ios"
type="event"
>
<ng-template>
<ion-content>
<ion-item-group>
<ng-container
*ngFor="let uiAddress of installed['address-info'] | uiAddresses"
>
<ion-item-divider>{{ uiAddress.name }}</ion-item-divider>
<ion-item button *ngFor="let address of uiAddress.addresses">
<ion-label>
<h2>{{ address | addressType }}</h2>
<p>{{ address }}</p>
</ion-label>
</ion-item>
</ng-container>
</ion-item-group>
</ion-content>
</ng-template>
</ion-popover>
</ng-container>
</ion-item>

View File

@@ -0,0 +1,3 @@
ion-popover {
--min-width: 300px;
}

View File

@@ -1,21 +1,25 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import {
InstalledPackageInfo,
PackageMainStatus,
} from 'src/app/services/patch-db/data-model'
ChangeDetectionStrategy,
Component,
Input,
ViewChild,
} from '@angular/core'
import { PackageMainStatus } from 'src/app/services/patch-db/data-model'
import { PkgInfo } from 'src/app/util/get-package-info'
import { UiLauncherService } from 'src/app/services/ui-launcher.service'
@Component({
selector: 'app-list-pkg',
templateUrl: 'app-list-pkg.component.html',
styleUrls: ['app-list-pkg.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppListPkgComponent {
@ViewChild('popover') popover!: HTMLIonPopoverElement
@Input()
pkg!: PkgInfo
constructor(private readonly launcherService: UiLauncherService) {}
isPopoverOpen = false
get status(): PackageMainStatus {
return (
@@ -23,9 +27,10 @@ export class AppListPkgComponent {
)
}
launchUi(e: Event, addressInfo: InstalledPackageInfo['address-info']): void {
openPopover(e: Event): void {
e.stopPropagation()
e.preventDefault()
this.launcherService.launch(addressInfo)
this.popover.event = e
this.isPopoverOpen = true
}
}

View File

@@ -1,8 +1,8 @@
import { NgModule } from '@angular/core'
import { UiPipe } from './ui.pipe'
import { UiPipe, UiAddressesPipe, AddressTypePipe } from './ui.pipe'
@NgModule({
declarations: [UiPipe],
exports: [UiPipe],
declarations: [UiPipe, UiAddressesPipe, AddressTypePipe],
exports: [UiPipe, UiAddressesPipe, AddressTypePipe],
})
export class UiPipeModule {}

View File

@@ -10,3 +10,47 @@ export class UiPipe implements PipeTransform {
return hasUi(addressInfo)
}
}
@Pipe({
name: 'uiAddresses',
})
export class UiAddressesPipe implements PipeTransform {
transform(
addressInfo: InstalledPackageInfo['address-info'],
): { name: string; addresses: string[] }[] {
return Object.values(addressInfo)
.filter(info => info.ui)
.map(info => ({
name: info.name,
addresses: info.addresses,
}))
}
}
@Pipe({
name: 'addressType',
})
export class AddressTypePipe implements PipeTransform {
transform(address: string): string {
if (isValidIpv4(address)) return 'IPv4'
if (isValidIpv6(address)) return 'IPv6'
const hostname = new URL(address).hostname
if (hostname.endsWith('.onion')) return 'Tor'
if (hostname.endsWith('.local')) return 'Local'
return 'Custom'
}
}
function isValidIpv4(address: string): boolean {
const regexExp =
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
return regexExp.test(address)
}
function isValidIpv6(address: string): boolean {
const regexExp =
/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/gi
return regexExp.test(address)
}