Skip to content

Commit

Permalink
refactor model and grid layout
Browse files Browse the repository at this point in the history
  • Loading branch information
Joao Leonardo Pereira committed Jul 19, 2024
1 parent 85ff053 commit c0f7792
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 110 deletions.
13 changes: 3 additions & 10 deletions src/app/components/account-detail/account-detail.component.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
<div id="code-container-component" class="ion-justify-content-center ion-align-items-center">
<ng-container *ngIf="account;else selectAccountContainer">

<ion-row *ngIf="account.logo; else serviceNameInfo">
<ion-row>
<ion-col size="12">
<img src="{{account.getLogo()}}" alt="code" class="service-logo">
</ion-col>
</ion-row>
<ng-template #serviceNameInfo>
<ion-row>
<ion-col size="12">
<h2>{{account.serviceName}}</h2>
</ion-col>
</ion-row>
</ng-template>
<ion-row>
<ion-col size="12">
<p>{{account.accountName}}</p>
{{account.label}}
</ion-col>
</ion-row>
<ion-row class="center-vertical">
Expand All @@ -29,7 +22,7 @@ <h2>{{account.serviceName}}</h2>
</ion-row>
<ion-row>
<ion-col size="12">
<p>Token expires in: {{timer}}s</p>
Expira em: <h2><strong>{{timer}}</strong>s</h2>
</ion-col>
</ion-row>
</ng-container>
Expand Down
24 changes: 0 additions & 24 deletions src/app/components/account-detail/account-detail.component.spec.ts

This file was deleted.

32 changes: 30 additions & 2 deletions src/app/components/account-detail/account-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class AccountDetailComponent {
private timerRefreshInterval: any
private _account?: Account2FA
timer: number = 0
token = '000000'
private _token = '000 000'

@Input() set account(value: Account2FA | undefined) {
this._account = value
Expand All @@ -26,11 +26,39 @@ export class AccountDetailComponent {

constructor(private otpService: OtpService, private toastController: ToastController) { }

set token(value: string) {
if(value.length <= 4) { // if token length is 4 or less, use it as is
this._token = value
} else if(value.length % 7 == 0) { // if token has a length divisible by 7, separate in groups of (2,3,2) characters
this._token = value.replace(/(.{2})(.{3})(.{2})/g, '$1 $2 $3 ').trim()
} else if(value.length % 5 == 0) { // if token has a length divisible by 5, separate in groups of (2,3) characters
this._token = value.replace(/(.{2})(.{3})/g, '$1 $2 ').trim()
} else if(value.length % 3 == 0) { // if token has a length divisible by 3, add a space every 3 characters
this._token = value.replace(/(.{3})/g, '$1 ').trim()
} else if(value.length % 2 == 0) { // if token has a length divisible by 2, add a space every 2 characters
this._token = value.replace(/(.{2})/g, '$1 ').trim()
} else { // if token has an odd length, add space every 3 characters, starting from the end
const reversedChars = value.split('').reverse()
let token = ''
reversedChars.forEach((char, index) => {
if(index % 3 == 0) {
token += ' '
}
token += char
})
this._token = token.trim().split('').reverse().join('')
}
}

get token(): string {
return this._token
}

async copyCode(evt: any) {
if(!this.account) {
return
}
const code = this.token
const code = this.token.replace(/\s/g, '')
await navigator.clipboard.writeText(code)
const toast = await this.toastController.create({
message: `Código copiado`,
Expand Down
22 changes: 9 additions & 13 deletions src/app/components/account-list/account-list.component.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
<div class="account-list-container">
<ion-grid *ngIf="isGridType; else listView">
<ion-row>
<ion-col *ngFor="let account of accounts" class="square-ratio" size-xs="6" size-sm="4" size-md="4" size-lg="3" size-xl="2">
<ion-card (click)="selectAccount(account)" class="fill-parent">
<ion-card-header>
<ion-card-title>
<ion-thumbnail>
<img class="thumb-img" [src]="account.getLogo()">
</ion-thumbnail>
</ion-card-title>
</ion-card-header>
<ion-card-content>
<p class="small-text">{{account.accountName}}</p>
<ion-col *ngFor="let account of accounts" size-xs="4" size-sm="3" size-md="2" size-lg="2" size-xl="2">
<ion-card (click)="selectAccount(account)" class="ion-no-padding ion-no-margin square fill-parent ion-activatable ripple-parent">
<ion-ripple-effect></ion-ripple-effect>
<ion-card-content class="ion-no-padding">
<ion-thumbnail class="thumb ion-no-padding ion-padding-top">
<img class="thumb-img" [src]="account.getLogo()">
</ion-thumbnail>
<p class="small-text ion-text-center ion-padding-top">{{account.label}}</p>
</ion-card-content>
</ion-card>
</ion-col>
Expand All @@ -24,8 +21,7 @@
<img class="thumb-img" [src]="account.getLogo()">
</ion-thumbnail>
<ion-label>
<h2>{{account.serviceName}}</h2>
<p>{{account.accountName}}</p>
<h2>{{account.label}}</h2>
</ion-label>
</ion-item>
</ion-list>
Expand Down
18 changes: 11 additions & 7 deletions src/app/components/account-list/account-list.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@
object-fit: scale-down;
}

.fill-parent {
.thumb {
width: 100%;
height: 100%;
}

.small-text {
font-size: 0.87em;
max-height: 20%;
display: flex;
justify-content: center;
align-items: center;
}

.square-ratio {
.fill-parent {
width: 100%;
height: 100%;
aspect-ratio: 1;
}

.small-text {
font-size: 0.8em;
padding: 16px 8px 0 8px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>
countdown-timer works!
</p>
Empty file.
14 changes: 14 additions & 0 deletions src/app/components/countdown-timer/countdown-timer.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-countdown-timer',
templateUrl: './countdown-timer.component.html',
styleUrls: ['./countdown-timer.component.scss'],
})
export class CountdownTimerComponent implements OnInit {

constructor() { }

ngOnInit() {}

}
7 changes: 2 additions & 5 deletions src/app/home/home.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</ion-toolbar>
</ion-header>

<ion-content>
<ion-content scroll-y="false">
<div id="container" [ngClass]="layoutOrientationClass">
<app-account-detail [ngClass]="layoutOrientationClass" id="code-container" [account]="selectedAccount"></app-account-detail>
<app-account-list [ngClass]="layoutOrientationClass" id="accounts-container" [accounts]="accounts$ | async | accountFilter: searchTxt" [type]="accountListType" (accountSelected)="selectAccount($event)"></app-account-list>
Expand Down Expand Up @@ -59,10 +59,7 @@
<ng-template #manualForm>
<form [formGroup]="validations_form" (ngSubmit)="createAccount(validations_form.value)">
<ion-item>
<ion-input label="Nome do serviço" labelPlacement="stacked" formControlName="serviceName" placeholder="ex.: Google"></ion-input>
</ion-item>
<ion-item>
<ion-input label="Nome da conta" labelPlacement="stacked" formControlName="accountName" placeholder="ex.: [email protected]"></ion-input>
<ion-input label="Label" labelPlacement="stacked" formControlName="label" placeholder="ex.: Google:[email protected]"></ion-input>
</ion-item>
<ion-item>
<ion-input label="Chave-segredo" labelPlacement="stacked" formControlName="secret" placeholder="ex.: QAPERTPEO123"></ion-input>
Expand Down
5 changes: 4 additions & 1 deletion src/app/home/home.page.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
ion-content {
overflow: hidden;
}

#container {
display: flex;
height: 100%;
Expand Down Expand Up @@ -29,7 +33,6 @@

#accounts-container {
overflow-y: auto;
border: 1px blue solid;
}

#accounts-container.landscape {
Expand Down
24 changes: 0 additions & 24 deletions src/app/home/home.page.spec.ts

This file was deleted.

12 changes: 2 additions & 10 deletions src/app/home/home.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,20 @@ export class HomePage implements OnInit {

constructor(
private authService: AuthenticationService,
private navCtrl: NavController,
private accountsService: Account2faService,
private otpService: OtpService,
private logoService: LogoService,
private loadingController: LoadingController,
private toastController: ToastController,
formBuilder: FormBuilder
) {
this.validations_form = formBuilder.group({
accountName: new FormControl('', Validators.compose([
label: new FormControl('', Validators.compose([
Validators.required,
])),
secret: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(8),
Validators.pattern('^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=)?$')
])),
serviceName: new FormControl('', Validators.compose([
Validators.required,
])),
tokenLength: new FormControl(6, Validators.compose([
Validators.required,
Validators.pattern('^[1-9]+[0-9]*$')
Expand Down Expand Up @@ -209,13 +203,11 @@ export class HomePage implements OnInit {
const account = Account2FA.fromOTPAuthURL(evt)
console.log({account})

this.validations_form.controls['accountName'].setValue(account.accountName)
this.validations_form.controls['label'].setValue(account.label)
this.validations_form.controls['secret'].setValue(account.secret)
this.validations_form.controls['serviceName'].setValue(account.serviceName)
this.validations_form.controls['tokenLength'].setValue(account.tokenLength)
this.validations_form.controls['interval'].setValue(account.interval)


this.manualInput = true
}

Expand Down
37 changes: 25 additions & 12 deletions src/app/models/account2FA.model.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
export class Account2FA {
export interface IAccount2FA {
id: string;
serviceName: string;
accountName: string;
label: string;
secret: string;
tokenLength: number;
interval: number;
algorithm: string;
issuer?: string;
active?: boolean;
logo?: string;
}
export class Account2FA implements IAccount2FA {
id: string;
label: string;
secret: string;
tokenLength: number;
interval: number;
algorithm: string;
issuer?: string;
active?: boolean;
logo?: string;

constructor(id: string, serviceName: string, accountName: string, secret: string, tokenLength?: number, interval?: number, active?: boolean, logo?: string) {
constructor(id: string, label: string, secret: string, tokenLength?: number, interval?: number, algorithm?: string, issuer?:string, active?: boolean, logo?: string) {
this.id = id;
this.serviceName = serviceName;
this.accountName = accountName;
this.label = label;
this.secret = secret;
this.tokenLength = tokenLength || 6;
this.interval = interval || 30;
this.algorithm = algorithm || 'SHA1';
this.issuer = issuer;
this.active = active;
this.logo = logo;
}

static fromDictionary(data: any): Account2FA {
return new Account2FA(data.id, data.serviceName, data.accountName, data.secret, data.tokenLength, data.interval, data.active, data.logo);
static fromDictionary(data: IAccount2FA): Account2FA {
return new Account2FA(data.id, data.label, data.secret, data.tokenLength, data.interval, data.algorithm, data.issuer, data.active, data.logo);
}

static fromOTPAuthURL(url: string): Account2FA {
Expand All @@ -36,9 +49,7 @@ export class Account2FA {
}

const label = pathComponents[1];
const serviceName = label.split(':')[0] || label;
const accountName = label.split(':')[1] || '';
if(!serviceName) {
if(!label) {
throw new Error('Missing required fields');
}

Expand All @@ -47,10 +58,12 @@ export class Account2FA {
throw new Error('Missing secret key');
}

const issuer = params.get('issuer') ?? undefined;
const algorithm = params.get('algorithm') ?? 'SHA1';
const tokenLength = params.get('digits') ? parseInt(params.get('digits')!) : undefined;
const interval = params.get('period') ? parseInt(params.get('period')!) : undefined;

return new Account2FA('', serviceName, accountName, secret, tokenLength, interval);
return new Account2FA('', label, secret, tokenLength, interval, algorithm, issuer);
}

getLogo(): string {
Expand Down
4 changes: 2 additions & 2 deletions src/app/pipes/account-filter.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export class AccountFilterPipe implements PipeTransform {
}

return data.filter((account) => {
return (account.serviceName.toLocaleLowerCase().includes(search.toLocaleLowerCase()) ||
account.accountName.toLocaleLowerCase().includes(search.toLocaleLowerCase()))
return (account.label.toLocaleLowerCase().includes(search.toLocaleLowerCase()) ||
account.issuer?.toLocaleLowerCase().includes(search.toLocaleLowerCase()))
})
}
}

0 comments on commit c0f7792

Please sign in to comment.