Improve storing of the state on change rather than periodically

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent f652785ccf
commit 08632080cb

@ -1,4 +1,4 @@
import {Component, OnInit, ViewChild} from "@angular/core";
import {Component, ViewChild} from "@angular/core";
import {Repository} from "../../models/Repository";
import {RepositoryService} from "../../services/repository/repository.service";
import {MatTabChangeEvent, MatTabGroup} from "@angular/material/tabs";
@ -7,55 +7,59 @@ import {TabService} from "../../services/tab/tab.service";
import {TabCategory} from "../../models/TabCategory";
import {TabState} from "../../models/TabState.rs";
import {AppState} from "../../models/AppState";
import {StateService} from "../../services/state/state.service";
@Component({
selector: "app-core",
templateUrl: "./core.component.html",
styleUrls: ["./core.component.scss"]
})
export class CoreComponent implements OnInit {
export class CoreComponent {
public selectedRepository: Repository | undefined;
public tabs: TabState[] = [];
public appState: AppState = new AppState();
private stateInterval?: number;
public appState: AppState;
public newTab = false;
@ViewChild("tabGroup") tabGroup!: MatTabGroup;
public newTab = false;
constructor(
private tabService: TabService,
private repoService: RepositoryService,
private stateService: StateService,
private tagService: TagService) {
}
public async ngOnInit(): Promise<void> {
this.selectedRepository = this.repoService.selectedRepository.getValue();
this.repoService.selectedRepository.subscribe(async (selected) => {
this.selectedRepository = selected;
if (this.selectedRepository) {
await this.loadRepoData();
if (this.appState.tabs.length === 0) {
this.addTab();
}
} else {
clearInterval(this.stateInterval);
this.newTab = false;
this.tabService.closeAllTabs();
this.appState = new AppState();
}
});
this.tabService.tabs.subscribe(tabs => {
this.tabs = tabs;
});
this.appState = this.stateService.state.getValue();
this.stateService.state.subscribe(state => {
this.appState = state;
console.log("new state", state);
if (this.appState.tabs.value.length === 0) {
this.addTab();
}
state.tabs.subscribe(tabs => {
console.log("new tabs", tabs);
this.tabs = tabs;
console.log(tabs);
if (this.tabs.length === 0) {
this.addTab();
}
});
})
}
async loadRepoData() {
await this.tagService.loadTags();
this.appState = await this.repoService.getFrontendState();
this.tabService.restoreFromState(this.appState);
this.startStateSaveRoutine();
}
public onTabSelectionChange(event: MatTabChangeEvent): void {
@ -63,25 +67,27 @@ export class CoreComponent implements OnInit {
}
public addFilesTab(): void {
this.tabService.addTab(TabCategory.Files);
this.appState.addTab(TabCategory.Files);
this.tabGroup.selectedIndex = this.tabs.length;
this.newTab = false;
}
public addImportTab(): void {
this.tabService.addTab(TabCategory.Import);
this.appState.addTab(TabCategory.Import);
this.tabGroup.selectedIndex = this.tabs.length;
this.newTab = false;
}
public addTab(): void {
this.newTab = true;
this.tabGroup.selectedIndex = this.tabs.length + 1;
if (this.tabGroup) {
this.newTab = true;
this.tabGroup.selectedIndex = this.tabs.length + 1;
}
}
public closeTab(tab: TabState): void {
public async closeTab(tab: TabState) {
const previousIndex = this.tabGroup.selectedIndex;
this.tabService.closeTab(tab.uuid);
await this.appState.closeTab(tab.uuid);
if (previousIndex) {
if (previousIndex === 1 && this.tabs.length >= 1) {
@ -94,19 +100,10 @@ export class CoreComponent implements OnInit {
}
}
public onMouseClickTabLabel(tab: TabState, event: MouseEvent): void {
public async onMouseClickTabLabel(tab: TabState, event: MouseEvent) {
console.log(event);
if (event.button === 1) { // middle mouse button
this.closeTab(tab);
await this.closeTab(tab);
}
}
private startStateSaveRoutine() {
clearInterval(this.stateInterval);
this.stateInterval = setInterval(async () => this.saveState(), 10000);
}
private async saveState() {
await this.repoService.setFrontendState(this.appState);
}
}

@ -1,11 +1,17 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {CoreComponent} from "./core.component";
import {RepositoriesTabComponent} from "./repositories-tab/repositories-tab.component";
import {
RepositoriesTabComponent
} from "./repositories-tab/repositories-tab.component";
import {FilesTabComponent} from "./files-tab/files-tab.component";
import {FilesTabSidebarComponent} from "./files-tab/files-tab-sidebar/files-tab-sidebar.component";
import {
FilesTabSidebarComponent
} from "./files-tab/files-tab-sidebar/files-tab-sidebar.component";
import {ImportTabComponent} from "./import-tab/import-tab.component";
import {ImportTabSidebarComponent} from "./import-tab/import-tab-sidebar/import-tab-sidebar.component";
import {
ImportTabSidebarComponent
} from "./import-tab/import-tab-sidebar/import-tab-sidebar.component";
import {MatButtonModule} from "@angular/material/button";
import {MatSidenavModule} from "@angular/material/sidenav";
import {MatProgressBarModule} from "@angular/material/progress-bar";
@ -24,17 +30,27 @@ import {SidebarModule} from "../shared/sidebar/sidebar.module";
import {FileModule} from "../shared/file/file.module";
import {AppCommonModule} from "../shared/app-common/app-common.module";
import {ReactiveFormsModule} from "@angular/forms";
import {RepositoryCardComponent} from "./repositories-tab/repository-card/repository-card.component";
import {AddRepositoryDialogComponent} from "./repositories-tab/add-repository-dialog/add-repository-dialog.component";
import {
RepositoryCardComponent
} from "./repositories-tab/repository-card/repository-card.component";
import {
AddRepositoryDialogComponent
} from "./repositories-tab/add-repository-dialog/add-repository-dialog.component";
import {MatCardModule} from "@angular/material/card";
import {MatListModule} from "@angular/material/list";
import {MatDialogModule} from "@angular/material/dialog";
import {MatTooltipModule} from "@angular/material/tooltip";
import {MatInputModule} from "@angular/material/input";
import {TagModule} from "../shared/tag/tag.module";
import { RepositoryFormComponent } from "./repositories-tab/repository-form/repository-form.component";
import { EditRepositoryDialogComponent } from "./repositories-tab/edit-repository-dialog/edit-repository-dialog.component";
import { DownloadDaemonDialogComponent } from "./repositories-tab/download-daemon-dialog/download-daemon-dialog.component";
import {
RepositoryFormComponent
} from "./repositories-tab/repository-form/repository-form.component";
import {
EditRepositoryDialogComponent
} from "./repositories-tab/edit-repository-dialog/edit-repository-dialog.component";
import {
DownloadDaemonDialogComponent
} from "./repositories-tab/download-daemon-dialog/download-daemon-dialog.component";
@NgModule({

@ -1,7 +1,11 @@
import {Component, Inject, ViewChild} from "@angular/core";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {RepositoryService} from "../../../../services/repository/repository.service";
import {ErrorBrokerService} from "../../../../services/error-broker/error-broker.service";
import {
RepositoryService
} from "../../../../services/repository/repository.service";
import {
ErrorBrokerService
} from "../../../../services/error-broker/error-broker.service";
import {
RepositoryFormComponent
} from "../repository-form/repository-form.component";

@ -1,25 +1,27 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { DownloadDaemonDialogComponent } from './download-daemon-dialog.component';
import {
DownloadDaemonDialogComponent
} from "./download-daemon-dialog.component";
describe('DownloadDaemonDialogComponent', () => {
let component: DownloadDaemonDialogComponent;
let fixture: ComponentFixture<DownloadDaemonDialogComponent>;
describe("DownloadDaemonDialogComponent", () => {
let component: DownloadDaemonDialogComponent;
let fixture: ComponentFixture<DownloadDaemonDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DownloadDaemonDialogComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DownloadDaemonDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DownloadDaemonDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(DownloadDaemonDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -1,25 +1,27 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { EditRepositoryDialogComponent } from './edit-repository-dialog.component';
import {
EditRepositoryDialogComponent
} from "./edit-repository-dialog.component";
describe('EditRepositoryDialogComponent', () => {
let component: EditRepositoryDialogComponent;
let fixture: ComponentFixture<EditRepositoryDialogComponent>;
describe("EditRepositoryDialogComponent", () => {
let component: EditRepositoryDialogComponent;
let fixture: ComponentFixture<EditRepositoryDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ EditRepositoryDialogComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ EditRepositoryDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(EditRepositoryDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(EditRepositoryDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -1,4 +1,4 @@
import {Component, Inject, OnInit, ViewChild} from "@angular/core";
import {Component, Inject, ViewChild} from "@angular/core";
import {
RepositoryFormComponent
} from "../repository-form/repository-form.component";

@ -1,11 +1,12 @@
import {AfterViewInit, Component, OnInit} from "@angular/core";
import {Repository} from "../../../models/Repository";
import {RepositoryService} from "../../../services/repository/repository.service";
import {
RepositoryService
} from "../../../services/repository/repository.service";
import {MatDialog} from "@angular/material/dialog";
import {AddRepositoryDialogComponent} from "./add-repository-dialog/add-repository-dialog.component";
import {
ConfirmDialogComponent
} from "../../shared/app-common/confirm-dialog/confirm-dialog.component";
AddRepositoryDialogComponent
} from "./add-repository-dialog/add-repository-dialog.component";
import {
DownloadDaemonDialogComponent
} from "./download-daemon-dialog/download-daemon-dialog.component";

@ -1,10 +1,18 @@
import {Component, Input, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {Repository} from "../../../../models/Repository";
import {RepositoryService} from "../../../../services/repository/repository.service";
import {ErrorBrokerService} from "../../../../services/error-broker/error-broker.service";
import {
RepositoryService
} from "../../../../services/repository/repository.service";
import {
ErrorBrokerService
} from "../../../../services/error-broker/error-broker.service";
import {MatDialog} from "@angular/material/dialog";
import {ConfirmDialogComponent} from "../../../shared/app-common/confirm-dialog/confirm-dialog.component";
import {BusyIndicatorComponent} from "../../../shared/app-common/busy-indicator/busy-indicator.component";
import {
ConfirmDialogComponent
} from "../../../shared/app-common/confirm-dialog/confirm-dialog.component";
import {
BusyIndicatorComponent
} from "../../../shared/app-common/busy-indicator/busy-indicator.component";
import {
EditRepositoryDialogComponent
} from "../edit-repository-dialog/edit-repository-dialog.component";

@ -1,25 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { RepositoryFormComponent } from './repository-form.component';
import {RepositoryFormComponent} from "./repository-form.component";
describe('RepositoryFormComponent', () => {
let component: RepositoryFormComponent;
let fixture: ComponentFixture<RepositoryFormComponent>;
describe("RepositoryFormComponent", () => {
let component: RepositoryFormComponent;
let fixture: ComponentFixture<RepositoryFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RepositoryFormComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RepositoryFormComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RepositoryFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(RepositoryFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -2,7 +2,8 @@ import {Component, Input, OnInit, Output} from "@angular/core";
import {
AbstractControl,
FormControl,
FormGroup, ValidationErrors,
FormGroup,
ValidationErrors,
Validators
} from "@angular/forms";
import {Repository} from "../../../../models/Repository";
@ -10,9 +11,6 @@ import {
RepositoryService
} from "../../../../services/repository/repository.service";
import {dialog} from "@tauri-apps/api";
import {
ErrorBrokerService
} from "../../../../services/error-broker/error-broker.service";
import {MatDialog} from "@angular/material/dialog";
@Component({

@ -1,6 +1,10 @@
import {NgModule} from "@angular/core";
import {ConfirmDialogComponent} from "./confirm-dialog/confirm-dialog.component";
import {BusyIndicatorComponent} from "./busy-indicator/busy-indicator.component";
import {
ConfirmDialogComponent
} from "./confirm-dialog/confirm-dialog.component";
import {
BusyIndicatorComponent
} from "./busy-indicator/busy-indicator.component";
import {ContextMenuComponent} from "./context-menu/context-menu.component";
import {CommonModule} from "@angular/common";
import {NgIconsModule} from "@ng-icons/core";
@ -8,7 +12,9 @@ import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
import {MatButtonModule} from "@angular/material/button";
import {MatDialogModule} from "@angular/material/dialog";
import {MatMenuModule} from "@angular/material/menu";
import {ContentAwareImageComponent} from "./content-aware-image/content-aware-image.component";
import {
ContentAwareImageComponent
} from "./content-aware-image/content-aware-image.component";
@NgModule({

@ -11,8 +11,12 @@ import {SafeResourceUrl} from "@angular/platform-browser";
import {File} from "../../../../models/File";
import {FileService} from "../../../../services/file/file.service";
import {FileHelper} from "../../../../services/file/file.helper";
import {ErrorBrokerService} from "../../../../services/error-broker/error-broker.service";
import {BusyIndicatorComponent} from "../../app-common/busy-indicator/busy-indicator.component";
import {
ErrorBrokerService
} from "../../../../services/error-broker/error-broker.service";
import {
BusyIndicatorComponent
} from "../../app-common/busy-indicator/busy-indicator.component";
type ContentType = "image" | "video" | "audio" | "other";

@ -10,7 +10,6 @@ import {
ViewChild
} from "@angular/core";
import {File} from "../../../../models/File";
import {SafeResourceUrl} from "@angular/platform-browser";
import {Selectable} from "../../../../models/Selectable";
@Component({

@ -1,9 +1,13 @@
import {Component, ViewChild} from "@angular/core";
import {File} from "../../../../models/File";
import {ContextMenuComponent} from "../../app-common/context-menu/context-menu.component";
import {
ContextMenuComponent
} from "../../app-common/context-menu/context-menu.component";
import {clipboard} from "@tauri-apps/api";
import {FileService} from "../../../../services/file/file.service";
import {ErrorBrokerService} from "../../../../services/error-broker/error-broker.service";
import {
ErrorBrokerService
} from "../../../../services/error-broker/error-broker.service";
import {FileHelper} from "../../../../services/file/file.helper";
@Component({

@ -1,8 +1,8 @@
import {
Component, EventEmitter,
Component,
Input,
OnChanges,
OnInit, Output,
OnInit,
SimpleChanges
} from "@angular/core";
import {File} from "../../../../models/File";

@ -1,19 +1,45 @@
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import {FileMultiviewComponent} from "./file-multiview/file-multiview.component";
import {FileGridComponent} from "./file-multiview/file-grid/file-grid.component";
import {FileGalleryComponent} from "./file-multiview/file-gallery/file-gallery.component";
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {
FileMultiviewComponent
} from "./file-multiview/file-multiview.component";
import {
FileGridComponent
} from "./file-multiview/file-grid/file-grid.component";
import {
FileGalleryComponent
} from "./file-multiview/file-gallery/file-gallery.component";
import {FileCardComponent} from "./file-card/file-card.component";
import {FileContextMenuComponent} from "./file-context-menu/file-context-menu.component";
import {FileThumbnailComponent} from "./file-thumbnail/file-thumbnail.component";
import {ContentViewerComponent} from "./content-viewer/content-viewer.component";
import {AudioViewerComponent} from "./content-viewer/audio-viewer/audio-viewer.component";
import {ImageViewerComponent} from "./content-viewer/image-viewer/image-viewer.component";
import {VideoViewerComponent} from "./content-viewer/video-viewer/video-viewer.component";
import {
FileContextMenuComponent
} from "./file-context-menu/file-context-menu.component";
import {
FileThumbnailComponent
} from "./file-thumbnail/file-thumbnail.component";
import {
ContentViewerComponent
} from "./content-viewer/content-viewer.component";
import {
AudioViewerComponent
} from "./content-viewer/audio-viewer/audio-viewer.component";
import {
ImageViewerComponent
} from "./content-viewer/image-viewer/image-viewer.component";
import {
VideoViewerComponent
} from "./content-viewer/video-viewer/video-viewer.component";
import {AppCommonModule} from "../app-common/app-common.module";
import {MatSliderModule} from "@angular/material/slider";
import {NgIconsModule} from "@ng-icons/core";
import {MatRefresh, MatClose, MatImage, MatMovie, MatGif, MatAudiotrack, MatDescription} from "@ng-icons/material-icons";
import {
MatAudiotrack,
MatClose,
MatDescription,
MatGif,
MatImage,
MatMovie,
MatRefresh
} from "@ng-icons/material-icons";
import {DragDropModule} from "@angular/cdk/drag-drop";
import {MatButtonModule} from "@angular/material/button";
import {MatMenuModule} from "@angular/material/menu";

@ -1,13 +1,15 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {NativeFileSelectComponent} from "./native-file-select/native-file-select.component";
import {
NativeFileSelectComponent
} from "./native-file-select/native-file-select.component";
import {TagInputComponent} from "./tag-input/tag-input.component";
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {MatFormFieldModule} from "@angular/material/form-field";
import {ReactiveFormsModule} from "@angular/forms";
import {MatInputModule} from "@angular/material/input";
import {NgIconsModule} from "@ng-icons/core";
import {MatInsertDriveFile, MatFolder} from "@ng-icons/material-icons";
import {MatFolder, MatInsertDriveFile} from "@ng-icons/material-icons";
import {MatButtonModule} from "@angular/material/button";
import {FlexModule} from "@angular/flex-layout";

@ -1,25 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { FileImportComponent } from './file-import.component';
import {FileImportComponent} from "./file-import.component";
describe('FileImportComponent', () => {
let component: FileImportComponent;
let fixture: ComponentFixture<FileImportComponent>;
describe("FileImportComponent", () => {
let component: FileImportComponent;
let fixture: ComponentFixture<FileImportComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FileImportComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FileImportComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FileImportComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(FileImportComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -1,4 +1,4 @@
import {Component, EventEmitter, OnInit, Output} from "@angular/core";
import {Component, EventEmitter, Output} from "@angular/core";
import {File} from "../../../../models/File";
@Component({

@ -1,7 +1,9 @@
import {Component, EventEmitter, Output} from "@angular/core";
import {FileOsMetadata} from "../../../../../models/FileOsMetadata";
import {ImportService} from "../../../../../services/import/import.service";
import {ErrorBrokerService} from "../../../../../services/error-broker/error-broker.service";
import {
ErrorBrokerService
} from "../../../../../services/error-broker/error-broker.service";
import {AddFileOptions} from "../../../../../models/AddFileOptions";
import {File} from "../../../../../models/File";
import {DialogFilter} from "@tauri-apps/api/dialog";

@ -1,25 +1,27 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { EditableMetadataEntryComponent } from './editable-metadata-entry.component';
import {
EditableMetadataEntryComponent
} from "./editable-metadata-entry.component";
describe('EditableMetadataEntryComponent', () => {
let component: EditableMetadataEntryComponent;
let fixture: ComponentFixture<EditableMetadataEntryComponent>;
describe("EditableMetadataEntryComponent", () => {
let component: EditableMetadataEntryComponent;
let fixture: ComponentFixture<EditableMetadataEntryComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ EditableMetadataEntryComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ EditableMetadataEntryComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(EditableMetadataEntryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(EditableMetadataEntryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -1,11 +1,4 @@
import {
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output
} from "@angular/core";
import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core";
import {FormControl} from "@angular/forms";
@Component({

@ -1,25 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { FileMetadataComponent } from './file-metadata.component';
import {FileMetadataComponent} from "./file-metadata.component";
describe('FileMetadataComponent', () => {
let component: FileMetadataComponent;
let fixture: ComponentFixture<FileMetadataComponent>;
describe("FileMetadataComponent", () => {
let component: FileMetadataComponent;
let fixture: ComponentFixture<FileMetadataComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FileMetadataComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FileMetadataComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FileMetadataComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(FileMetadataComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -1,10 +1,4 @@
import {
Component,
Input,
OnChanges,
OnInit,
SimpleChanges
} from "@angular/core";
import {Component, Input} from "@angular/core";
import {File} from "../../../../models/File";
import {FileService} from "../../../../services/file/file.service";

@ -1,25 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from "@angular/core/testing";
import { MetadataEntryComponent } from './metadata-entry.component';
import {MetadataEntryComponent} from "./metadata-entry.component";
describe('MetadataEntryComponent', () => {
let component: MetadataEntryComponent;
let fixture: ComponentFixture<MetadataEntryComponent>;
describe("MetadataEntryComponent", () => {
let component: MetadataEntryComponent;
let fixture: ComponentFixture<MetadataEntryComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MetadataEntryComponent ]
})
.compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MetadataEntryComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MetadataEntryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(MetadataEntryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

@ -8,7 +8,9 @@ import {
} from "../../../../../models/FilterExpression";
import {TagQuery} from "../../../../../models/TagQuery";
import {Tag} from "../../../../../models/Tag";
import {TagFilterListItemComponent} from "./tag-filter-list-item/tag-filter-list-item.component";
import {
TagFilterListItemComponent
} from "./tag-filter-list-item/tag-filter-list-item.component";
import {Selectable} from "../../../../../models/Selectable";
@Component({

@ -3,7 +3,14 @@ import {CommonModule} from "@angular/common";
import {TagEditComponent} from "./tag-edit/tag-edit.component";
import {FileSearchComponent} from "./file-search/file-search.component";
import {NgIconsModule} from "@ng-icons/core";
import {MatRemove, MatChangeCircle, MatAddCircle, MatRemoveCircle, MatDeleteSweep, MatFilterAlt, MatSave, MatEdit} from "@ng-icons/material-icons";
import {
MatAddCircle,
MatChangeCircle,
MatDeleteSweep,
MatFilterAlt,
MatRemove,
MatRemoveCircle
} from "@ng-icons/material-icons";
import {MatRippleModule} from "@angular/material/core";
import {MatButtonModule} from "@angular/material/button";
import {InputModule} from "../input/input.module";
@ -13,22 +20,34 @@ import {MatDividerModule} from "@angular/material/divider";
import {FlexModule} from "@angular/flex-layout";
import {MatSelectModule} from "@angular/material/select";
import {MatInputModule} from "@angular/material/input";
import {TagFilterListItemComponent} from "./file-search/filter-dialog/tag-filter-list-item/tag-filter-list-item.component";
import {SortDialogComponent} from "./file-search/sort-dialog/sort-dialog.component";
import {FilterDialogComponent} from "./file-search/filter-dialog/filter-dialog.component";
import {
TagFilterListItemComponent
} from "./file-search/filter-dialog/tag-filter-list-item/tag-filter-list-item.component";
import {
SortDialogComponent
} from "./file-search/sort-dialog/sort-dialog.component";
import {
FilterDialogComponent
} from "./file-search/filter-dialog/filter-dialog.component";
import {MatListModule} from "@angular/material/list";
import {MatDialogModule} from "@angular/material/dialog";
import {AppCommonModule} from "../app-common/app-common.module";
import {DragDropModule} from "@angular/cdk/drag-drop";
import {TagModule} from "../tag/tag.module";
import { FileImportComponent } from "./file-import/file-import.component";
import {FilesystemImportComponent} from "./file-import/filesystem-import/filesystem-import.component";
import {FileImportComponent} from "./file-import/file-import.component";
import {
FilesystemImportComponent
} from "./file-import/filesystem-import/filesystem-import.component";
import {MatCheckboxModule} from "@angular/material/checkbox";
import {MatProgressBarModule} from "@angular/material/progress-bar";
import {MatMenuModule} from "@angular/material/menu";
import { FileMetadataComponent } from "./file-metadata/file-metadata.component";
import { MetadataEntryComponent } from "./file-metadata/metadata-entry/metadata-entry.component";
import { EditableMetadataEntryComponent } from "./file-metadata/editable-metadata-entry/editable-metadata-entry.component";
import {FileMetadataComponent} from "./file-metadata/file-metadata.component";
import {
MetadataEntryComponent
} from "./file-metadata/metadata-entry/metadata-entry.component";
import {
EditableMetadataEntryComponent
} from "./file-metadata/editable-metadata-entry/editable-metadata-entry.component";
import {ReactiveFormsModule} from "@angular/forms";

@ -1,6 +1,5 @@
import {
Component,
ElementRef,
Input,
OnChanges,
OnInit,

@ -1,27 +1,48 @@
import {TabState} from "./TabState.rs";
import {FileService} from "../services/file/file.service";
import {BehaviorSubject} from "rxjs";
import {TabCategory} from "./TabCategory";
export class AppState {
public tabs: TabState[] = [];
private tabIdCounter = 0;
public tabs = new BehaviorSubject<TabState[]>([]);
constructor() {
private readonly fileService: FileService
constructor(fileService: FileService) {
this.fileService = fileService;
}
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 static deserializeJson(stateString: string, fileService: FileService): AppState {
let state = JSON.parse(stateString);
let appState = new AppState();
for (let tab of state.tabs) {
appState.tabs.push(TabState.fromDTO(tab, fileService));
}
let appState = new AppState(fileService);
const tabs = state.tabs.map((tab: any) => TabState.fromDTO(tab, fileService));
appState.tabs.next(tabs);
appState.tabIdCounter = state.tabIdCounter;
return appState
}
public serializeJson(): string {
const tabDTOs = this.tabs.map(tab => tab.getDTO());
const tabDTOs = this.tabs.value.map(tab => tab.getDTO());
return JSON.stringify({
tabs: tabDTOs
tabs: tabDTOs,
tabIdCounter: this.tabIdCounter,
});
}
}

@ -2,9 +2,7 @@ import {Inject, Injectable} from "@angular/core";
import {File} from "../../models/File";
import {invoke} from "@tauri-apps/api/tauri";
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";
import {Thumbnail} from "../../models/Thumbnail";
import {SortKey} from "../../models/SortKey";
import {RepositoryService} from "../repository/repository.service";
import {FilterExpression} from "../../models/FilterExpression";

@ -5,7 +5,6 @@ import {invoke} from "@tauri-apps/api/tauri";
import {listen} from "@tauri-apps/api/event";
import {Info} from "../../models/Info";
import {ErrorBrokerService} from "../error-broker/error-broker.service";
import {AppState} from "../../models/AppState";
import {FileService} from "../file/file.service";
@Injectable({
@ -156,28 +155,6 @@ export class RepositoryService {
await invoke("plugin:mediarepo|init_repository", {repoPath});
}
/**
* Returns the state of the frontend
* @returns {Promise<AppState>}
*/
public async getFrontendState(): Promise<AppState> {
let stateString = await invoke<string | undefined>("plugin:mediarepo|get_frontend_state");
if (stateString) {
return AppState.deserializeJson(stateString, this.fileService)
} else {
return new AppState();
}
}
/**
* Sets the state of the frontend
* @param {AppState} state
* @returns {Promise<void>}
*/
public async setFrontendState(state: AppState): Promise<void> {
await invoke("plugin:mediarepo|set_frontend_state", {state: state.serializeJson()})
}
async loadSelectedRepository() {
let active_repo = await invoke<Repository | undefined>(
"plugin:mediarepo|get_active_repository");

@ -0,0 +1,16 @@
import {TestBed} from "@angular/core/testing";
import {StateService} from "./state.service";
describe("StateServiceService", () => {
let service: StateService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(StateService);
});
it("should be created", () => {
expect(service).toBeTruthy();
});
});

@ -0,0 +1,76 @@
import {Injectable} from "@angular/core";
import {BehaviorSubject, Subscription} from "rxjs";
import {AppState} from "../../models/AppState";
import {invoke} from "@tauri-apps/api/tauri";
import {FileService} from "../file/file.service";
import {RepositoryService} from "../repository/repository.service";
import {TabState} from "../../models/TabState.rs";
import {debounceTime} from "rxjs/operators";
@Injectable({
providedIn: "root"
})
export class StateService {
public state: BehaviorSubject<AppState>;
private tabSubscriptions: Subscription[] = [];
private stateChange = new BehaviorSubject<void>(undefined);
constructor(private fileService: FileService, private repoService: RepositoryService) {
this.state = new BehaviorSubject(new AppState(fileService));
this.repoService.selectedRepository.subscribe(async (repo) => {
if (repo) {
await this.loadState();
} else {
const state = new AppState(this.fileService);
this.subscribeToState(state);
this.state.next(state);
}
});
this.stateChange.pipe(debounceTime(1000)).subscribe(async () => this.saveState());
}
/**
* Returns the state of the frontend
* @returns {Promise<void>}
*/
public async loadState() {
let stateString = await invoke<string | undefined>(
"plugin:mediarepo|get_frontend_state");
let state;
if (stateString) {
state = AppState.deserializeJson(stateString, this.fileService)
} else {
state = new AppState(this.fileService);
}
this.subscribeToState(state);
this.state.next(state);
}
private subscribeToState(state: AppState) {
state.tabs.subscribe(async tabs => {
this.tabSubscriptions.forEach(s => s.unsubscribe());
tabs.forEach((tab) => this.subscribeToTab(tab));
this.stateChange.next();
})
}
private subscribeToTab(tab: TabState) {
this.tabSubscriptions.push(tab.filters
.subscribe(() => this.stateChange.next()));
this.tabSubscriptions.push(tab.sortKeys
.subscribe(() => this.stateChange.next()));
}
/**
* Sets the state of the frontend
* @returns {Promise<void>}
*/
public async saveState(): Promise<void> {
await invoke("plugin:mediarepo|set_frontend_state",
{state: this.state.value.serializeJson()})
}
}

@ -1,55 +1,17 @@
import {Injectable} from "@angular/core";
import {BehaviorSubject} from "rxjs";
import {TabState} from "../../models/TabState.rs";
import {TabCategory} from "../../models/TabCategory";
import {FileService} from "../file/file.service";
import {AppState} from "../../models/AppState";
@Injectable({
providedIn: "root"
})
export class TabService {
private tabIdCounter = 0;
public selectedTab = new BehaviorSubject<number>(0);
public tabs = new BehaviorSubject<TabState[]>([]);
private appState?: AppState;
constructor(private fileService: FileService) {
}
public restoreFromState(appState: AppState) {
this.tabs.next(appState.tabs);
this.appState = appState;
constructor() {
}
public setSelectedTab(index: number) {
this.selectedTab.next(index);
}
public addTab(category: TabCategory): TabState {
const state = new TabState(this.tabIdCounter++, category, this.fileService);
this.tabs.next([...this.tabs.value, state]);
this.saveState();
return state;
}
public closeTab(uuid: number) {
const index = this.tabs.value.findIndex(t => t.uuid === uuid);
const tabs = this.tabs.value;
tabs.splice(index, 1)
this.saveState();
this.tabs.next(tabs);
}
public closeAllTabs() {
this.tabs.next([]);
this.saveState();
}
private saveState() {
if (this.appState) {
this.appState.tabs = this.tabs.value;
}
}
}

@ -2,20 +2,20 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="120"
height="120"
viewBox="0 0 120 120"
version="1.1"
id="svg5"
sodipodi:docname="mediarepo-icon.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
inkscape:export-filename="/home/trivernis/Pictures/mediarepo-icon_32x32.png"
inkscape:export-xdpi="25.6"
inkscape:export-ydpi="25.6"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
width="120"
height="120"
viewBox="0 0 120 120"
version="1.1"
id="svg5"
sodipodi:docname="mediarepo-icon.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
inkscape:export-filename="/home/trivernis/Pictures/mediarepo-icon_32x32.png"
inkscape:export-xdpi="25.6"
inkscape:export-ydpi="25.6"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
>
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Loading…
Cancel
Save