mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-27 12:36:14 +01:00
[Send] Type component (#1608)
* Initial commit of send type component * Update jslib (ee164be
->0951424
) * Update constructor for new jslib
This commit is contained in:
parent
0d6e212463
commit
8d2e436a05
2
jslib
2
jslib
@ -1 +1 @@
|
|||||||
Subproject commit ee164bebc65aa56e41a122eb4ece8971eb23119b
|
Subproject commit 0951424de77fbb61a38616d13d6c67f74ee19775
|
@ -187,4 +187,7 @@ export const routerTransition = trigger('routerTransition', [
|
|||||||
transition('premium => tabs', outSlideRight),
|
transition('premium => tabs', outSlideRight),
|
||||||
|
|
||||||
transition('tabs => lock', inSlideDown),
|
transition('tabs => lock', inSlideDown),
|
||||||
|
|
||||||
|
transition('tabs => send-type', inSlideLeft),
|
||||||
|
transition('send-type => tabs', outSlideRight),
|
||||||
]);
|
]);
|
||||||
|
@ -47,6 +47,7 @@ import { ShareComponent } from './vault/share.component';
|
|||||||
import { ViewComponent } from './vault/view.component';
|
import { ViewComponent } from './vault/view.component';
|
||||||
|
|
||||||
import { SendGroupingsComponent } from './send/send-groupings.component';
|
import { SendGroupingsComponent } from './send/send-groupings.component';
|
||||||
|
import { SendTypeComponent } from './send/send-type.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -236,6 +237,12 @@ const routes: Routes = [
|
|||||||
canActivate: [AuthGuardService],
|
canActivate: [AuthGuardService],
|
||||||
data: { state: 'clone-cipher' },
|
data: { state: 'clone-cipher' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'send-type',
|
||||||
|
component: SendTypeComponent,
|
||||||
|
canActivate: [AuthGuardService],
|
||||||
|
data: { state: 'send-type' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'tabs',
|
path: 'tabs',
|
||||||
component: TabsComponent,
|
component: TabsComponent,
|
||||||
|
@ -146,9 +146,13 @@ export class AppComponent implements OnInit {
|
|||||||
(window as any).previousPopupUrl.startsWith('/tabs/')) {
|
(window as any).previousPopupUrl.startsWith('/tabs/')) {
|
||||||
this.stateService.remove('GroupingsComponent');
|
this.stateService.remove('GroupingsComponent');
|
||||||
this.stateService.remove('CiphersComponent');
|
this.stateService.remove('CiphersComponent');
|
||||||
|
this.stateService.remove('SendGroupingsComponent');
|
||||||
|
this.stateService.remove('SendGroupingsComponentScope');
|
||||||
|
this.stateService.remove('SendTypeComponent');
|
||||||
}
|
}
|
||||||
if (url.startsWith('/tabs/')) {
|
if (url.startsWith('/tabs/')) {
|
||||||
this.stateService.remove('addEditCipherInfo');
|
this.stateService.remove('addEditCipherInfo');
|
||||||
|
// TODO Remove any Send add/edit state information (?)
|
||||||
}
|
}
|
||||||
(window as any).previousPopupUrl = url;
|
(window as any).previousPopupUrl = url;
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ import { ShareComponent } from './vault/share.component';
|
|||||||
import { ViewComponent } from './vault/view.component';
|
import { ViewComponent } from './vault/view.component';
|
||||||
|
|
||||||
import { SendGroupingsComponent } from './send/send-groupings.component';
|
import { SendGroupingsComponent } from './send/send-groupings.component';
|
||||||
|
import { SendTypeComponent } from './send/send-type.component';
|
||||||
|
|
||||||
import { A11yTitleDirective } from 'jslib/angular/directives/a11y-title.directive';
|
import { A11yTitleDirective } from 'jslib/angular/directives/a11y-title.directive';
|
||||||
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
|
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
|
||||||
@ -214,6 +215,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
|||||||
SelectCopyDirective,
|
SelectCopyDirective,
|
||||||
SendGroupingsComponent,
|
SendGroupingsComponent,
|
||||||
SendListComponent,
|
SendListComponent,
|
||||||
|
SendTypeComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
ShareComponent,
|
ShareComponent,
|
||||||
StopClickDirective,
|
StopClickDirective,
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<span class="text">
|
<span class="text">
|
||||||
{{s.name}}
|
{{s.name}}
|
||||||
<ng-container *ngIf="s.disabled">
|
<ng-container *ngIf="s.disabled">
|
||||||
<i class="fa fa-ban text-muted" title="{{'disabled' | i18n}}" aria-hidden="true"></i>
|
<i class="fa fa-warning text-muted" title="{{'disabled' | i18n}}" aria-hidden="true"></i>
|
||||||
<span class="sr-only">{{'disabled' | i18n}}</span>
|
<span class="sr-only">{{'disabled' | i18n}}</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="s.password">
|
<ng-container *ngIf="s.password">
|
||||||
@ -19,8 +19,7 @@
|
|||||||
<span class="sr-only">{{'passwordProtected' | i18n}}</span>
|
<span class="sr-only">{{'passwordProtected' | i18n}}</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="s.maxAccessCountReached">
|
<ng-container *ngIf="s.maxAccessCountReached">
|
||||||
<i class="fa fa-warning text-muted" title="{{'maxAccessCountReached' | i18n}}"
|
<i class="fa fa-ban text-muted" title="{{'maxAccessCountReached' | i18n}}" aria-hidden="true"></i>
|
||||||
aria-hidden="true"></i>
|
|
||||||
<span class="sr-only">{{'maxAccessCountReached' | i18n}}</span>
|
<span class="sr-only">{{'maxAccessCountReached' | i18n}}</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="s.expired">
|
<ng-container *ngIf="s.expired">
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
NgZone,
|
NgZone,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
@ -46,21 +47,24 @@ export class SendGroupingsComponent extends BaseSendComponent {
|
|||||||
private loadedTimeout: number;
|
private loadedTimeout: number;
|
||||||
|
|
||||||
constructor(sendService: SendService, i18nService: I18nService,
|
constructor(sendService: SendService, i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
|
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService, ngZone: NgZone,
|
||||||
broadcasterService: BroadcasterService, ngZone: NgZone, policyService: PolicyService,
|
policyService: PolicyService, userService: UserService, searchService: SearchService,
|
||||||
userService: UserService, searchService: SearchService,
|
|
||||||
private popupUtils: PopupUtilsService, private stateService: StateService,
|
private popupUtils: PopupUtilsService, private stateService: StateService,
|
||||||
private route: ActivatedRoute, private router: Router, private syncService: SyncService) {
|
private route: ActivatedRoute, private router: Router, private syncService: SyncService,
|
||||||
super(sendService, i18nService, platformUtilsService, environmentService, broadcasterService, ngZone,
|
private changeDetectorRef: ChangeDetectorRef, private broadcasterService: BroadcasterService) {
|
||||||
searchService, policyService, userService);
|
super(sendService, i18nService, platformUtilsService, environmentService, ngZone, searchService,
|
||||||
|
policyService, userService);
|
||||||
super.onSuccessfulLoad = async () => {
|
super.onSuccessfulLoad = async () => {
|
||||||
this.calculateTypeCounts();
|
this.calculateTypeCounts();
|
||||||
|
this.selectAll();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
// Determine Header details
|
// Determine Header details
|
||||||
this.showLeftHeader = !(this.popupUtils.inSidebar(window) && this.platformUtilsService.isFirefox());
|
this.showLeftHeader = !(this.popupUtils.inSidebar(window) && this.platformUtilsService.isFirefox());
|
||||||
|
// Clear state of Send Type Component
|
||||||
|
this.stateService.remove('SendTypeComponent');
|
||||||
// Let super class finish
|
// Let super class finish
|
||||||
await super.ngOnInit();
|
await super.ngOnInit();
|
||||||
// Handle State Restore if necessary
|
// Handle State Restore if necessary
|
||||||
@ -83,6 +87,23 @@ export class SendGroupingsComponent extends BaseSendComponent {
|
|||||||
if (!this.syncService.syncInProgress || restoredScopeState) {
|
if (!this.syncService.syncInProgress || restoredScopeState) {
|
||||||
window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY), 0);
|
window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load all sends if sync completed in background
|
||||||
|
this.broadcasterService.subscribe(ComponentId, (message: any) => {
|
||||||
|
this.ngZone.run(async () => {
|
||||||
|
switch (message.command) {
|
||||||
|
case 'syncCompleted':
|
||||||
|
window.setTimeout(() => {
|
||||||
|
this.load();
|
||||||
|
}, 500);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@ -92,12 +113,12 @@ export class SendGroupingsComponent extends BaseSendComponent {
|
|||||||
}
|
}
|
||||||
// Save state
|
// Save state
|
||||||
this.saveState();
|
this.saveState();
|
||||||
// Allow super to finish
|
// Unsubscribe
|
||||||
super.ngOnDestroy();
|
this.broadcasterService.unsubscribe(ComponentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectType(type: SendType) {
|
async selectType(type: SendType) {
|
||||||
// TODO this.router.navigate(['/send-type-list'], { queryParams: { type: type } });
|
this.router.navigate(['/send-type'], { queryParams: { type: type } });
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectSend(s: SendView) {
|
async selectSend(s: SendView) {
|
||||||
@ -115,7 +136,7 @@ export class SendGroupingsComponent extends BaseSendComponent {
|
|||||||
private calculateTypeCounts() {
|
private calculateTypeCounts() {
|
||||||
// Create type counts
|
// Create type counts
|
||||||
const typeCounts = new Map<SendType, number>();
|
const typeCounts = new Map<SendType, number>();
|
||||||
this.sends.forEach((s) => {
|
this.sends.forEach(s => {
|
||||||
if (typeCounts.has(s.type)) {
|
if (typeCounts.has(s.type)) {
|
||||||
typeCounts.set(s.type, typeCounts.get(s.type) + 1);
|
typeCounts.set(s.type, typeCounts.get(s.type) + 1);
|
||||||
} else {
|
} else {
|
||||||
|
41
src/popup/send/send-type.component.html
Normal file
41
src/popup/send/send-type.component.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<header>
|
||||||
|
<div class="left">
|
||||||
|
<button type="button" appBlurClick (click)="back()">
|
||||||
|
<span class="header-icon"><i class="fa fa-chevron-left" aria-hidden="true"></i></span>
|
||||||
|
<span>{{'back' | i18n}}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="search">
|
||||||
|
<input type="search" placeholder="{{'searchType' | i18n}}" id="search" [(ngModel)]="searchText"
|
||||||
|
(input)="search(200)" autocomplete="off" appAutofocus>
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<button appBlurClick (click)="addSend()" appA11yTitle="{{'addSend' | i18n}}">
|
||||||
|
<i class="fa fa-plus fa-lg fa-fw" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<content>
|
||||||
|
<div class="no-items" *ngIf="!filteredSends.length">
|
||||||
|
<i class="fa fa-spinner fa-spin fa-3x" *ngIf="!loaded" aria-hidden="true"></i>
|
||||||
|
<ng-container *ngIf="loaded">
|
||||||
|
<p>{{'noItemsInList' | i18n}}</p>
|
||||||
|
<button (click)="addSend()" class="btn block primary link">
|
||||||
|
{{'addSend' | i18n}}
|
||||||
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
<div class="box list only-list" *ngIf="filteredSends.length">
|
||||||
|
<div class="box-header">
|
||||||
|
{{groupingTitle}}
|
||||||
|
<span class="flex-right">{{filteredSends.length}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<app-send-list [sends]="filteredSends" title="{{'editItem' | i18n}}" (onSelected)="selectSend($event)"
|
||||||
|
(onCopySendLink)="copy($event)" (onRemovePassword)="removePassword($event)"
|
||||||
|
(onDeleteSend)="delete($event)">
|
||||||
|
</app-send-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</content>
|
149
src/popup/send/send-type.component.ts
Normal file
149
src/popup/send/send-type.component.ts
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
NgZone,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ActivatedRoute,
|
||||||
|
} from '@angular/router';
|
||||||
|
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
|
||||||
|
import { SendView } from 'jslib/models/view/sendView';
|
||||||
|
|
||||||
|
import { SendComponent as BaseSendComponent } from 'jslib/angular/components/send/send.component';
|
||||||
|
|
||||||
|
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
||||||
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
|
import { PolicyService } from 'jslib/abstractions/policy.service';
|
||||||
|
import { SearchService } from 'jslib/abstractions/search.service';
|
||||||
|
import { SendService } from 'jslib/abstractions/send.service';
|
||||||
|
import { StateService } from 'jslib/abstractions/state.service';
|
||||||
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
|
|
||||||
|
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||||
|
|
||||||
|
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||||
|
|
||||||
|
import { SendType } from 'jslib/enums/sendType';
|
||||||
|
|
||||||
|
const ComponentId = 'SendTypeComponent';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-send-type',
|
||||||
|
templateUrl: 'send-type.component.html',
|
||||||
|
})
|
||||||
|
export class SendTypeComponent extends BaseSendComponent {
|
||||||
|
groupingTitle: string;
|
||||||
|
// State Handling
|
||||||
|
state: any;
|
||||||
|
private refreshTimeout: number;
|
||||||
|
private applySavedState = true;
|
||||||
|
|
||||||
|
constructor(sendService: SendService, i18nService: I18nService,
|
||||||
|
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService, ngZone: NgZone,
|
||||||
|
policyService: PolicyService, userService: UserService, searchService: SearchService,
|
||||||
|
private popupUtils: PopupUtilsService, private stateService: StateService,
|
||||||
|
private route: ActivatedRoute, private location: Location, private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private broadcasterService: BroadcasterService) {
|
||||||
|
super(sendService, i18nService, platformUtilsService, environmentService, ngZone, searchService,
|
||||||
|
policyService, userService);
|
||||||
|
super.onSuccessfulLoad = async () => {
|
||||||
|
this.selectType(this.type);
|
||||||
|
};
|
||||||
|
this.applySavedState = (window as any).previousPopupUrl != null &&
|
||||||
|
!(window as any).previousPopupUrl.startsWith('/send-type');
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
// Let super class finish
|
||||||
|
await super.ngOnInit();
|
||||||
|
const queryParamsSub = this.route.queryParams.subscribe(async params => {
|
||||||
|
if (this.applySavedState) {
|
||||||
|
this.state = (await this.stateService.get<any>(ComponentId)) || {};
|
||||||
|
if (this.state.searchText != null) {
|
||||||
|
this.searchText = this.state.searchText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.type != null) {
|
||||||
|
this.type = parseInt(params.type, null);
|
||||||
|
switch (this.type) {
|
||||||
|
case SendType.Text:
|
||||||
|
this.groupingTitle = this.i18nService.t('sendTypeText');
|
||||||
|
break;
|
||||||
|
case SendType.File:
|
||||||
|
this.groupingTitle = this.i18nService.t('sendTypeFile');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await this.load(s => s.type === this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore state and remove reference
|
||||||
|
if (this.applySavedState && this.state != null) {
|
||||||
|
window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY), 0);
|
||||||
|
}
|
||||||
|
this.stateService.remove(ComponentId);
|
||||||
|
|
||||||
|
// Unsubscribe
|
||||||
|
if (queryParamsSub != null) {
|
||||||
|
queryParamsSub.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Refresh Send list if sync completed in background
|
||||||
|
this.broadcasterService.subscribe(ComponentId, (message: any) => {
|
||||||
|
this.ngZone.run(async () => {
|
||||||
|
switch (message.command) {
|
||||||
|
case 'syncCompleted':
|
||||||
|
if (message.successfully) {
|
||||||
|
this.refreshTimeout = window.setTimeout(() => {
|
||||||
|
this.refresh();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
// Remove timeout
|
||||||
|
if (this.refreshTimeout != null) {
|
||||||
|
window.clearTimeout(this.refreshTimeout);
|
||||||
|
}
|
||||||
|
// Save state
|
||||||
|
this.saveState();
|
||||||
|
// Unsubscribe
|
||||||
|
this.broadcasterService.unsubscribe(ComponentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectSend(s: SendView) {
|
||||||
|
// TODO -> Route to edit send
|
||||||
|
}
|
||||||
|
|
||||||
|
async addSend() {
|
||||||
|
// TODO -> Route to create send
|
||||||
|
}
|
||||||
|
|
||||||
|
back() {
|
||||||
|
(window as any).routeDirection = 'b';
|
||||||
|
this.location.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async saveState() {
|
||||||
|
this.state = {
|
||||||
|
scrollY: this.popupUtils.getContentScrollY(window),
|
||||||
|
searchText: this.searchText,
|
||||||
|
};
|
||||||
|
await this.stateService.save(ComponentId, this.state);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user