mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-18 11:05:41 +01:00
manage state for vault pages
This commit is contained in:
parent
9d737f76d1
commit
a3fc1c8d30
@ -9,6 +9,7 @@ import {
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
NavigationEnd,
|
||||
Router,
|
||||
RouterOutlet,
|
||||
} from '@angular/router';
|
||||
@ -22,6 +23,7 @@ import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||
|
||||
import { AuthService } from 'jslib/abstractions/auth.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
import { StorageService } from 'jslib/abstractions/storage.service';
|
||||
|
||||
import { ConstantsService } from 'jslib/services/constants.service';
|
||||
@ -49,11 +51,13 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
|
||||
private lastActivity: number = null;
|
||||
private previousUrl: string = '';
|
||||
|
||||
constructor(private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics, private analytics: Angulartics2,
|
||||
private toasterService: ToasterService, private storageService: StorageService,
|
||||
private broadcasterService: BroadcasterService, private authService: AuthService,
|
||||
private i18nService: I18nService, private router: Router) { }
|
||||
private i18nService: I18nService, private router: Router,
|
||||
private stateService: StateService) { }
|
||||
|
||||
ngOnInit() {
|
||||
window.onmousemove = () => this.recordActivity();
|
||||
@ -80,6 +84,17 @@ export class AppComponent implements OnInit {
|
||||
};
|
||||
|
||||
BrowserApi.messageListener((window as any).bitwardenPopupMainMessageListener);
|
||||
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
const url = event.urlAfterRedirects || event.url || '';
|
||||
if (url.startsWith('/tabs/') && this.previousUrl.startsWith('/tabs/')) {
|
||||
this.stateService.remove('GroupingsComponent');
|
||||
this.stateService.remove('CiphersComponent');
|
||||
}
|
||||
this.previousUrl = url;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getState(outlet: RouterOutlet) {
|
||||
|
@ -18,4 +18,16 @@ export class PopupUtilsService {
|
||||
return win.location.search === '' || win.location.search.indexOf('uilocation=') === -1 ||
|
||||
win.location.search.indexOf('uilocation=popup') > -1;
|
||||
}
|
||||
|
||||
getContentScrollY(win: Window): number {
|
||||
const content = win.document.getElementsByTagName('content')[0];
|
||||
return content.scrollTop;
|
||||
}
|
||||
|
||||
setContentScrollY(win: Window, scrollY: number): void {
|
||||
if (scrollY != null) {
|
||||
const content = win.document.getElementsByTagName('content')[0];
|
||||
content.scrollTop = scrollY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,4 @@
|
||||
import {
|
||||
Component,
|
||||
ComponentFactoryResolver,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Type,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tabs',
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
} from '@angular/router';
|
||||
|
||||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
|
||||
import { CipherView } from 'jslib/models/view/cipherView';
|
||||
|
||||
@ -19,7 +20,9 @@ import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||
|
||||
import { CiphersComponent as BaseCiphersComponent } from 'jslib/angular/components/ciphers.component';
|
||||
|
||||
const BroadcasterSubscriptionId = 'CiphersComponent';
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
const ComponentId = 'CiphersComponent';
|
||||
|
||||
@Component({
|
||||
selector: 'app-vault-ciphers',
|
||||
@ -27,11 +30,13 @@ const BroadcasterSubscriptionId = 'CiphersComponent';
|
||||
})
|
||||
export class CiphersComponent extends BaseCiphersComponent implements OnInit, OnDestroy {
|
||||
searchText: string;
|
||||
state: any;
|
||||
|
||||
constructor(cipherService: CipherService, private route: ActivatedRoute,
|
||||
private router: Router, private location: Location,
|
||||
private ngZone: NgZone, private broadcasterService: BroadcasterService,
|
||||
private changeDetectorRef: ChangeDetectorRef) {
|
||||
private changeDetectorRef: ChangeDetectorRef, private stateService: StateService,
|
||||
private popupUtils: PopupUtilsService) {
|
||||
super(cipherService);
|
||||
}
|
||||
|
||||
@ -47,9 +52,15 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On
|
||||
} else {
|
||||
await super.load();
|
||||
}
|
||||
|
||||
this.state = (await this.stateService.get<any>(ComponentId)) || {};
|
||||
if (this.state.searchText) {
|
||||
this.searchText = this.state.searchText;
|
||||
}
|
||||
window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY), 0);
|
||||
});
|
||||
|
||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||
this.broadcasterService.subscribe(ComponentId, (message: any) => {
|
||||
this.ngZone.run(async () => {
|
||||
switch (message.command) {
|
||||
case 'syncCompleted':
|
||||
@ -67,7 +78,8 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||
this.saveState();
|
||||
this.broadcasterService.unsubscribe(ComponentId);
|
||||
}
|
||||
|
||||
selectCipher(cipher: CipherView) {
|
||||
@ -83,4 +95,12 @@ export class CiphersComponent extends BaseCiphersComponent implements OnInit, On
|
||||
back() {
|
||||
this.location.back();
|
||||
}
|
||||
|
||||
private async saveState() {
|
||||
this.state = {
|
||||
scrollY: this.popupUtils.getContentScrollY(window),
|
||||
searchText: this.searchText,
|
||||
};
|
||||
await this.stateService.save(ComponentId, this.state);
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,15 @@ import { FolderView } from 'jslib/models/view/folderView';
|
||||
import { CollectionService } from 'jslib/abstractions/collection.service';
|
||||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||
|
||||
import { GroupingsComponent as BaseGroupingsComponent } from 'jslib/angular/components/groupings.component';
|
||||
|
||||
const BroadcasterSubscriptionId = 'GroupingsComponent';
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
const ComponentId = 'GroupingsComponent';
|
||||
|
||||
@Component({
|
||||
selector: 'app-vault-groupings',
|
||||
@ -40,16 +43,20 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit
|
||||
typeCounts = new Map<CipherType, number>();
|
||||
showNoFolderCiphers = false;
|
||||
searchText: string;
|
||||
state: any;
|
||||
|
||||
constructor(collectionService: CollectionService, folderService: FolderService,
|
||||
private cipherService: CipherService, private router: Router,
|
||||
private ngZone: NgZone, private broadcasterService: BroadcasterService,
|
||||
private changeDetectorRef: ChangeDetectorRef, private route: ActivatedRoute) {
|
||||
private changeDetectorRef: ChangeDetectorRef, private route: ActivatedRoute,
|
||||
private stateService: StateService, private popupUtils: PopupUtilsService) {
|
||||
super(collectionService, folderService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => {
|
||||
this.stateService.remove('CiphersComponent');
|
||||
|
||||
this.broadcasterService.subscribe(ComponentId, (message: any) => {
|
||||
this.ngZone.run(async () => {
|
||||
switch (message.command) {
|
||||
case 'syncCompleted':
|
||||
@ -66,16 +73,21 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit
|
||||
});
|
||||
|
||||
this.route.queryParams.subscribe(async (params) => {
|
||||
if (params.searchText) {
|
||||
this.state = (await this.stateService.get<any>(ComponentId)) || {};
|
||||
if (this.state.searchText) {
|
||||
this.searchText = this.state.searchText;
|
||||
} else if (params.searchText) {
|
||||
this.searchText = params.searchText;
|
||||
}
|
||||
|
||||
this.load();
|
||||
window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state.scrollY), 0);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||
this.saveState();
|
||||
this.broadcasterService.unsubscribe(ComponentId);
|
||||
}
|
||||
|
||||
async load() {
|
||||
@ -137,26 +149,34 @@ export class GroupingsComponent extends BaseGroupingsComponent implements OnInit
|
||||
});
|
||||
}
|
||||
|
||||
selectType(type: CipherType) {
|
||||
async selectType(type: CipherType) {
|
||||
super.selectType(type);
|
||||
this.router.navigate(['/ciphers'], { queryParams: { type: type } });
|
||||
}
|
||||
|
||||
selectFolder(folder: FolderView) {
|
||||
async selectFolder(folder: FolderView) {
|
||||
super.selectFolder(folder);
|
||||
this.router.navigate(['/ciphers'], { queryParams: { folderId: folder.id } });
|
||||
}
|
||||
|
||||
selectCollection(collection: CollectionView) {
|
||||
async selectCollection(collection: CollectionView) {
|
||||
super.selectCollection(collection);
|
||||
this.router.navigate(['/ciphers'], { queryParams: { collectionId: collection.id } });
|
||||
}
|
||||
|
||||
selectCipher(cipher: CipherView) {
|
||||
async selectCipher(cipher: CipherView) {
|
||||
this.router.navigate(['/view-cipher'], { queryParams: { cipherId: cipher.id } });
|
||||
}
|
||||
|
||||
addCipher() {
|
||||
async addCipher() {
|
||||
this.router.navigate(['/add-cipher']);
|
||||
}
|
||||
|
||||
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