Separate import and files tab state
Signed-off-by: trivernis <trivernis@protonmail.com>pull/14/head
parent
3f37fb4e5e
commit
642222e0c4
@ -1,53 +0,0 @@
|
|||||||
import {TabState} from "./TabState";
|
|
||||||
import {FileService} from "../services/file/file.service";
|
|
||||||
import {BehaviorSubject} from "rxjs";
|
|
||||||
import {TabCategory} from "./TabCategory";
|
|
||||||
|
|
||||||
export class AppState {
|
|
||||||
|
|
||||||
public tabs = new BehaviorSubject<TabState[]>([]);
|
|
||||||
public selectedTab = new BehaviorSubject<number | undefined>(undefined);
|
|
||||||
public repoName: string | undefined;
|
|
||||||
private tabIdCounter = 0;
|
|
||||||
private readonly fileService: FileService;
|
|
||||||
|
|
||||||
constructor(fileService: FileService) {
|
|
||||||
this.fileService = fileService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static deserializeJson(stateString: string, fileService: FileService): AppState {
|
|
||||||
let state = JSON.parse(stateString);
|
|
||||||
let appState = new AppState(fileService);
|
|
||||||
const tabs = state.tabs.map((tab: any) => TabState.fromDTO(tab, fileService));
|
|
||||||
appState.tabs.next(tabs);
|
|
||||||
|
|
||||||
appState.tabIdCounter = state.tabIdCounter;
|
|
||||||
appState.selectedTab.next(state.selectedTab);
|
|
||||||
appState.repoName = state.repoName;
|
|
||||||
|
|
||||||
return appState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public addTab(category: TabCategory): TabState {
|
|
||||||
const state = new TabState(this.tabIdCounter++, category, this.fileService);
|
|
||||||
this.tabs.next([...this.tabs.value, state]);
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async closeTab(uuid: number) {
|
|
||||||
const index = this.tabs.value.findIndex(t => t.uuid === uuid);
|
|
||||||
const tabs = this.tabs.value;
|
|
||||||
tabs.splice(index, 1);
|
|
||||||
this.tabs.next(tabs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public serializeJson(): string {
|
|
||||||
const tabDTOs = this.tabs.value.map(tab => tab.getDTO());
|
|
||||||
return JSON.stringify({
|
|
||||||
repoName: this.repoName,
|
|
||||||
tabs: tabDTOs,
|
|
||||||
tabIdCounter: this.tabIdCounter,
|
|
||||||
selectedTab: this.selectedTab.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
import {BehaviorSubject} from "rxjs";
|
|
||||||
import {TabCategory} from "./TabCategory";
|
|
||||||
import {FileService} from "../services/file/file.service";
|
|
||||||
import {File} from "../../api/models/File";
|
|
||||||
import {SortKey} from "../../api/models/SortKey";
|
|
||||||
import {debounceTime} from "rxjs/operators";
|
|
||||||
import {mapNew} from "../../api/models/adaptors";
|
|
||||||
import {SearchFilters} from "../../api/models/SearchFilters";
|
|
||||||
import {SortingPreset} from "../../api/models/SortingPreset";
|
|
||||||
|
|
||||||
export class TabState {
|
|
||||||
public uuid: number;
|
|
||||||
public category: TabCategory;
|
|
||||||
public mode = new BehaviorSubject<"grid" | "gallery">("grid");
|
|
||||||
public selectedCD = new BehaviorSubject<string | undefined>(undefined);
|
|
||||||
public loading = new BehaviorSubject<boolean>(false);
|
|
||||||
|
|
||||||
public files = new BehaviorSubject<File[]>([]);
|
|
||||||
public filters = new BehaviorSubject<SearchFilters>(new SearchFilters([]));
|
|
||||||
public sortingPreset = new BehaviorSubject<SortingPreset>(SortingPreset.fromValues(
|
|
||||||
-1,
|
|
||||||
[SortKey.fromValues(
|
|
||||||
"FileImportedTime",
|
|
||||||
"Ascending",
|
|
||||||
undefined
|
|
||||||
)]
|
|
||||||
));
|
|
||||||
|
|
||||||
private fileService: FileService;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
uuid: number,
|
|
||||||
category: TabCategory,
|
|
||||||
fileService: FileService
|
|
||||||
) {
|
|
||||||
this.category = category;
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.fileService = fileService;
|
|
||||||
if (this.category === TabCategory.Files) {
|
|
||||||
this.filters.pipe(debounceTime(500))
|
|
||||||
.subscribe(async () => await this.findFiles());
|
|
||||||
this.sortingPreset.pipe(debounceTime(100))
|
|
||||||
.subscribe(async () => await this.findFiles());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromDTO(
|
|
||||||
dto: any,
|
|
||||||
fileService: FileService
|
|
||||||
): TabState {
|
|
||||||
const state = new TabState(
|
|
||||||
dto.uuid,
|
|
||||||
dto.category,
|
|
||||||
fileService
|
|
||||||
);
|
|
||||||
|
|
||||||
state.filters.next(new SearchFilters(dto.filters ?? []));
|
|
||||||
state.sortingPreset.next(new SortingPreset(dto.sortingPreset));
|
|
||||||
state.mode.next(dto.mode ?? "grid");
|
|
||||||
state.selectedCD.next(dto.selectedFileHash);
|
|
||||||
state.files.next((dto.files ?? []).map(mapNew(File)));
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async findFiles() {
|
|
||||||
this.loading.next(true);
|
|
||||||
const files = await this.fileService.findFiles(
|
|
||||||
this.filters.value,
|
|
||||||
this.sortingPreset.value.sortKeys
|
|
||||||
);
|
|
||||||
this.files.next(files);
|
|
||||||
this.loading.next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setTagFilters(filters: SearchFilters) {
|
|
||||||
this.filters.next(filters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setSortingPreset(preset: SortingPreset) {
|
|
||||||
this.sortingPreset.next(preset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getDTO(): any {
|
|
||||||
return {
|
|
||||||
uuid: this.uuid,
|
|
||||||
category: this.category,
|
|
||||||
filters: this.filters.value.getFilters(),
|
|
||||||
sortingPreset: this.sortingPreset.value.rawData,
|
|
||||||
mode: this.mode.value,
|
|
||||||
selectedFileHash: this.selectedCD.value,
|
|
||||||
files: this.category === TabCategory.Import ? this.files.value.map(
|
|
||||||
f => f.rawData) : [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,75 @@
|
|||||||
|
import {FilesTabSaveState, FilesTabState} from "./FilesTabState";
|
||||||
|
import {BehaviorSubject} from "rxjs";
|
||||||
|
import {TabCategory} from "./TabCategory";
|
||||||
|
import {TabSaveState, TabState} from "./TabState";
|
||||||
|
import {StateServices} from "./StateServices";
|
||||||
|
import {ImportTabSaveState, ImportTabState} from "./ImportTabState";
|
||||||
|
|
||||||
|
export class AppState {
|
||||||
|
|
||||||
|
public tabs = new BehaviorSubject<TabState[]>([]);
|
||||||
|
public selectedTab = new BehaviorSubject<number | undefined>(undefined);
|
||||||
|
public repoName: string | undefined;
|
||||||
|
private tabIdCounter = 0;
|
||||||
|
private readonly services: StateServices;
|
||||||
|
|
||||||
|
constructor(services: StateServices) {
|
||||||
|
this.services = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static deserializeJson(stateString: string, services: StateServices): AppState {
|
||||||
|
let state = JSON.parse(stateString);
|
||||||
|
let appState = new AppState(services);
|
||||||
|
|
||||||
|
const tabs = state.tabs.map((saveState: TabSaveState) => {
|
||||||
|
let tab;
|
||||||
|
|
||||||
|
if (saveState.category === TabCategory.Files) {
|
||||||
|
tab = new FilesTabState(saveState.uuid, services);
|
||||||
|
tab.restoreSaveState(saveState as FilesTabSaveState);
|
||||||
|
} else if (saveState.category === TabCategory.Import) {
|
||||||
|
tab = new ImportTabState(saveState.uuid, services);
|
||||||
|
tab.restoreSaveState(saveState as ImportTabSaveState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
});
|
||||||
|
appState.tabs.next(tabs);
|
||||||
|
|
||||||
|
appState.tabIdCounter = state.tabIdCounter;
|
||||||
|
appState.selectedTab.next(state.selectedTab);
|
||||||
|
appState.repoName = state.repoName;
|
||||||
|
|
||||||
|
return appState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addTab(category: TabCategory): TabState {
|
||||||
|
let state;
|
||||||
|
|
||||||
|
if (category == TabCategory.Files) {
|
||||||
|
state = new FilesTabState(this.tabIdCounter++, this.services);
|
||||||
|
} else {
|
||||||
|
state = new ImportTabState(this.tabIdCounter++, this.services);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tabs.next([...this.tabs.value, state]);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async closeTab(uuid: number) {
|
||||||
|
const index = this.tabs.value.findIndex(t => t.uuid === uuid);
|
||||||
|
const tabs = this.tabs.value;
|
||||||
|
tabs.splice(index, 1);
|
||||||
|
this.tabs.next(tabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public serializeJson(): string {
|
||||||
|
const tabDTOs = this.tabs.value.map(tab => tab.toSaveState());
|
||||||
|
return JSON.stringify({
|
||||||
|
repoName: this.repoName,
|
||||||
|
tabs: tabDTOs,
|
||||||
|
tabIdCounter: this.tabIdCounter,
|
||||||
|
selectedTab: this.selectedTab.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
import {BehaviorSubject} from "rxjs";
|
||||||
|
import {TabCategory} from "./TabCategory";
|
||||||
|
import {File} from "../../../api/models/File";
|
||||||
|
import {SortKey} from "../../../api/models/SortKey";
|
||||||
|
import {debounceTime} from "rxjs/operators";
|
||||||
|
import {mapNew} from "../../../api/models/adaptors";
|
||||||
|
import {SearchFilters} from "../../../api/models/SearchFilters";
|
||||||
|
import {SortingPreset} from "../../../api/models/SortingPreset";
|
||||||
|
import {TabSaveState, TabState} from "./TabState";
|
||||||
|
import {StateServices} from "./StateServices";
|
||||||
|
import {FileBasicData, FilterExpression} from "../../../api/api-types/files";
|
||||||
|
import {SortingPresetData} from "../../../api/api-types/presets";
|
||||||
|
import {SaveState} from "./SaveState";
|
||||||
|
|
||||||
|
export type FilesTabSaveState = {
|
||||||
|
mode: "gallery" | "grid",
|
||||||
|
selectedCd: string | undefined,
|
||||||
|
files: FileBasicData[],
|
||||||
|
filters: FilterExpression[],
|
||||||
|
sortingPreset: SortingPresetData,
|
||||||
|
} & TabSaveState;
|
||||||
|
|
||||||
|
export class FilesTabState extends TabState implements SaveState<FilesTabSaveState> {
|
||||||
|
|
||||||
|
public mode = new BehaviorSubject<"grid" | "gallery">("grid");
|
||||||
|
public selectedCD = new BehaviorSubject<string | undefined>(undefined);
|
||||||
|
public loading = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
|
public files = new BehaviorSubject<File[]>([]);
|
||||||
|
public filters = new BehaviorSubject<SearchFilters>(new SearchFilters([]));
|
||||||
|
public sortingPreset = new BehaviorSubject<SortingPreset>(SortingPreset.fromValues(
|
||||||
|
-1,
|
||||||
|
[SortKey.fromValues(
|
||||||
|
"FileImportedTime",
|
||||||
|
"Ascending",
|
||||||
|
undefined
|
||||||
|
)]
|
||||||
|
));
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
uuid: number,
|
||||||
|
services: StateServices,
|
||||||
|
) {
|
||||||
|
super(uuid, TabCategory.Files, services);
|
||||||
|
this.subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public restoreSaveState(
|
||||||
|
state: FilesTabSaveState,
|
||||||
|
) {
|
||||||
|
super.restoreSaveState(state);
|
||||||
|
this.filters = new BehaviorSubject(new SearchFilters(state.filters ?? []));
|
||||||
|
this.sortingPreset = new BehaviorSubject(new SortingPreset(state.sortingPreset));
|
||||||
|
this.mode = new BehaviorSubject(state.mode ?? "grid");
|
||||||
|
this.selectedCD = new BehaviorSubject(state.selectedCd);
|
||||||
|
this.files = new BehaviorSubject((state.files ?? []).map(mapNew(File)));
|
||||||
|
this.subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findFiles() {
|
||||||
|
this.loading.next(true);
|
||||||
|
const files = await this.services.fileService.findFiles(
|
||||||
|
this.filters.value,
|
||||||
|
this.sortingPreset.value.sortKeys
|
||||||
|
);
|
||||||
|
this.files.next(files);
|
||||||
|
this.loading.next(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTagFilters(filters: SearchFilters) {
|
||||||
|
this.filters.next(filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSortingPreset(preset: SortingPreset) {
|
||||||
|
this.sortingPreset.next(preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toSaveState(): FilesTabSaveState {
|
||||||
|
return {
|
||||||
|
uuid: this.uuid,
|
||||||
|
category: this.category,
|
||||||
|
filters: this.filters.value.getFilters(),
|
||||||
|
sortingPreset: this.sortingPreset.value.rawData,
|
||||||
|
mode: this.mode.value,
|
||||||
|
selectedCd: this.selectedCD.value,
|
||||||
|
files: this.category === TabCategory.Import ? this.files.value.map(
|
||||||
|
f => f.rawData) : [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private subscribe() {
|
||||||
|
this.filters.pipe(debounceTime(500))
|
||||||
|
.subscribe(async () => await this.findFiles());
|
||||||
|
this.sortingPreset.pipe(debounceTime(100))
|
||||||
|
.subscribe(async () => await this.findFiles());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
import {TabSaveState, TabState} from "./TabState";
|
||||||
|
import {SaveState} from "./SaveState";
|
||||||
|
import {StateServices} from "./StateServices";
|
||||||
|
import {TabCategory} from "./TabCategory";
|
||||||
|
import {BehaviorSubject} from "rxjs";
|
||||||
|
import {File} from "../../../api/models/File";
|
||||||
|
import {FileBasicData} from "../../../api/api-types/files";
|
||||||
|
import {mapNew} from "../../../api/models/adaptors";
|
||||||
|
|
||||||
|
export type ImportTabSaveState = {
|
||||||
|
selectedCd: string | undefined,
|
||||||
|
mode: "grid" | "gallery",
|
||||||
|
files: FileBasicData[],
|
||||||
|
} & TabSaveState;
|
||||||
|
|
||||||
|
export class ImportTabState extends TabState implements SaveState<ImportTabSaveState> {
|
||||||
|
|
||||||
|
public mode = new BehaviorSubject<"grid" | "gallery">("grid");
|
||||||
|
public selectedCD = new BehaviorSubject<string | undefined>(undefined);
|
||||||
|
public files = new BehaviorSubject<File[]>([]);
|
||||||
|
|
||||||
|
constructor(uuid: number, services: StateServices) {
|
||||||
|
super(uuid, TabCategory.Import, services);
|
||||||
|
}
|
||||||
|
|
||||||
|
public restoreSaveState(state: ImportTabSaveState) {
|
||||||
|
super.restoreSaveState(state);
|
||||||
|
this.selectedCD = new BehaviorSubject<string | undefined>(state.selectedCd);
|
||||||
|
this.files = new BehaviorSubject<File[]>(state.files.map(mapNew(File)));
|
||||||
|
this.mode = new BehaviorSubject<"grid" | "gallery">(state.mode);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toSaveState(): ImportTabSaveState {
|
||||||
|
return {
|
||||||
|
uuid: this.uuid,
|
||||||
|
category: this.category,
|
||||||
|
selectedCd: this.selectedCD.value,
|
||||||
|
files: this.files.value.map(f => f.rawData),
|
||||||
|
mode: this.mode.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
export interface SaveState<State> {
|
||||||
|
restoreSaveState(state: State): void;
|
||||||
|
|
||||||
|
toSaveState(): State;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
import {FileService} from "../../services/file/file.service";
|
||||||
|
|
||||||
|
export class StateServices {
|
||||||
|
constructor(public fileService: FileService) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
import {TabCategory} from "./TabCategory";
|
||||||
|
import {StateServices} from "./StateServices";
|
||||||
|
import {SaveState} from "./SaveState";
|
||||||
|
import {FilesTabState} from "./FilesTabState";
|
||||||
|
import {ImportTabState} from "./ImportTabState";
|
||||||
|
|
||||||
|
export type TabSaveState = {
|
||||||
|
uuid: number,
|
||||||
|
category: TabCategory,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TabState implements SaveState<TabSaveState> {
|
||||||
|
constructor(
|
||||||
|
public uuid: number,
|
||||||
|
public category: TabCategory,
|
||||||
|
protected services: StateServices
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public toSaveState(): TabSaveState {
|
||||||
|
return {
|
||||||
|
uuid: this.uuid,
|
||||||
|
category: this.category
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public restoreSaveState(state: TabSaveState): void {
|
||||||
|
this.uuid = state.uuid;
|
||||||
|
this.category = state.category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the state into a files tab state
|
||||||
|
* Warning: This should only be called when it's guaranteed that this tab is a files tab
|
||||||
|
* @returns {ImportTabState}
|
||||||
|
*/
|
||||||
|
public filesTab(): FilesTabState {
|
||||||
|
return this as unknown as FilesTabState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the state into an import tab state
|
||||||
|
* Warning: This should only be called when it's guaranteed that this tab is an import tab
|
||||||
|
* @returns {ImportTabState}
|
||||||
|
*/
|
||||||
|
public importTab(): ImportTabState {
|
||||||
|
return this as unknown as ImportTabState;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue