Skip to content
This repository was archived by the owner on Oct 25, 2023. It is now read-only.

Commit 4e4694a

Browse files
authored
Merge pull request #194 from app-outlet/feature/180
Feature/180
2 parents bdbe1ae + 5ea74c2 commit 4e4694a

File tree

12 files changed

+151
-34
lines changed

12 files changed

+151
-34
lines changed

core/interface/InterfaceChannel.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ module.exports = {
1414
setTheme: 'settings.setTheme',
1515
getLastSynchronizationDate: 'settings.getLastSynchronizationDate',
1616
},
17+
synchronization: {
18+
isRunning: 'synchronization.isRunning',
19+
isRunningSync: 'synchronization.isRunning.sync',
20+
},
1721
};

core/interface/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
require('./application/ApplicationInterface');
22
require('./settings/SettingsInterface');
3+
require('./synchronization/SynchronizationInterface');
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const synchronizationService = require('../../service/synchronization/SynchornizationService');
2+
const { ipcMain } = require('electron');
3+
const InterfaceChannel = require('../InterfaceChannel');
4+
5+
let isSynchronizingCache = false;
6+
7+
synchronizationService
8+
.getSynchronizationStatus()
9+
.subscribe((isSynchronizing) => {
10+
if (isSynchronizing) {
11+
isSynchronizingCache = isSynchronizing;
12+
}
13+
ipcMain.emit(
14+
InterfaceChannel.synchronization.isRunning,
15+
isSynchronizing,
16+
);
17+
});
18+
19+
ipcMain?.handle(InterfaceChannel.synchronization.isRunningSync, () => {
20+
return isSynchronizingCache;
21+
});

core/service/synchronization/SynchornizationService.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { forkJoin } = require('rxjs');
1+
const { forkJoin, Subject } = require('rxjs');
22

33
const flathubSynchronizer = require('./synchronizer/FlathubSynchronizer');
44
const appImageHubSynchronizer = require('./synchronizer/AppImageHubSynchronizer');
@@ -7,6 +7,9 @@ const settingsService = require('../settings/SettingsService');
77

88
const DAY_IN_MILLIS = 1000 * 60 * 60 * 24 * 7;
99

10+
const isSynchronizationRunning = new Subject();
11+
isSynchronizationRunning.next(false);
12+
1013
async function shouldSynchronize() {
1114
const now = new Date();
1215
const lastSync = await settingsService.getLastSynchronizationDate();
@@ -28,6 +31,7 @@ async function startSynchronization() {
2831
}
2932

3033
function synchronize() {
34+
isSynchronizationRunning.next(true);
3135
forkJoin([
3236
flathubSynchronizer.startSynchronization(),
3337
appImageHubSynchronizer.startSynchronization(),
@@ -36,13 +40,16 @@ function synchronize() {
3640
() => {
3741
console.log('Synchronization succeeded');
3842
settingsService.setLastSynchronizationDate(new Date());
43+
isSynchronizationRunning.next(false);
3944
},
4045
(error) => {
4146
console.error(error);
47+
isSynchronizationRunning.next(false);
4248
},
4349
);
4450
}
4551

4652
module.exports = {
4753
startSynchronization,
54+
getSynchronizationStatus: () => isSynchronizationRunning,
4855
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { SynchronizationService } from './synchronization.service';
2+
3+
describe('SynchronizationService', () => {
4+
let service: SynchronizationService;
5+
6+
const mockCoreService = {
7+
invoke: jest.fn(),
8+
};
9+
10+
beforeEach(() => {
11+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
12+
// @ts-ignore
13+
service = new SynchronizationService(mockCoreService);
14+
});
15+
16+
it('should be created', () => {
17+
expect(service).toBeTruthy();
18+
});
19+
20+
it('should get current synchronization status', async () => {
21+
mockCoreService.invoke.mockReturnValue(Promise.resolve(true));
22+
expect(await service.getCurrentSynchronizationStatus()).toBeTruthy();
23+
});
24+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Injectable } from '@angular/core';
2+
import { CoreService } from '../core/core.service';
3+
import * as InterfaceChannel from '../../../../core/interface/InterfaceChannel';
4+
5+
@Injectable()
6+
export class SynchronizationService {
7+
constructor(private coreService: CoreService) {}
8+
9+
getCurrentSynchronizationStatus(): Promise<boolean> {
10+
return this.coreService.invoke<boolean>(
11+
InterfaceChannel.synchronization.isRunningSync,
12+
);
13+
}
14+
}

src/app/ui/pages/main/main.component.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,14 @@
1111
<nb-layout-column>
1212
<app-toolbar></app-toolbar>
1313
<router-outlet></router-outlet>
14+
<nb-alert
15+
*ngIf="shouldShowSynchronizationMessage && isSynchronizationRunning"
16+
status="warning"
17+
closable="true"
18+
class="synchronization-message"
19+
(close)="closeSynchronizationMessage()"
20+
>
21+
{{ 'PAGES.MAIN.SYNCHRONIZATION_MESSAGE' | translate }}
22+
</nb-alert>
1423
</nb-layout-column>
1524
</nb-layout>

src/app/ui/pages/main/main.component.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ nb-layout-column {
1616
app-main-menu {
1717
padding-bottom: 15rem;
1818
}
19+
20+
.synchronization-message {
21+
position: sticky;
22+
bottom: 0.5rem;
23+
margin-left: 10rem;
24+
margin-right: 10rem;
25+
z-index: 1;
26+
}
Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,35 @@
1-
import { ComponentFixture, TestBed } from '@angular/core/testing';
2-
31
import { MainComponent } from './main.component';
4-
import { MainMenuModule } from '../../components/main-menu/main-menu.module';
5-
import { NbLayoutModule, NbSidebarModule, NbThemeModule } from '@nebular/theme';
6-
import { NbEvaIconsModule } from '@nebular/eva-icons';
7-
import { RouterModule } from '@angular/router';
8-
import { APP_BASE_HREF } from '@angular/common';
9-
import { TranslateModule } from '@ngx-translate/core';
10-
import { ToolbarModule } from '../../components/toolbar/toolbar.module';
112

123
describe('MainComponent', () => {
134
let component: MainComponent;
14-
let fixture: ComponentFixture<MainComponent>;
155

16-
beforeEach(async () => {
17-
await TestBed.configureTestingModule({
18-
imports: [
19-
MainMenuModule,
20-
NbLayoutModule,
21-
NbEvaIconsModule,
22-
NbSidebarModule.forRoot(),
23-
RouterModule.forRoot([]),
24-
NbThemeModule.forRoot(),
25-
TranslateModule.forRoot(),
26-
ToolbarModule,
27-
],
28-
declarations: [MainComponent],
29-
providers: [{ provide: APP_BASE_HREF, useValue: './' }],
30-
}).compileComponents();
31-
});
6+
const mockSynchronizationService = {
7+
getCurrentSynchronizationStatus: jest.fn(),
8+
};
329

3310
beforeEach(() => {
34-
fixture = TestBed.createComponent(MainComponent);
35-
component = fixture.componentInstance;
36-
fixture.detectChanges();
11+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
12+
// @ts-ignore
13+
component = new MainComponent(mockSynchronizationService);
3714
});
3815

3916
it('should create', () => {
4017
expect(component).toBeTruthy();
4118
});
19+
20+
it('should get current synchronization status', (done) => {
21+
mockSynchronizationService.getCurrentSynchronizationStatus.mockReturnValue(
22+
Promise.resolve(true),
23+
);
24+
component.ngOnInit();
25+
setTimeout(() => {
26+
expect(component.isSynchronizationRunning).toBeTruthy();
27+
done();
28+
}, 0);
29+
});
30+
31+
it('should hide synchronization message', () => {
32+
component.closeSynchronizationMessage();
33+
expect(component.shouldShowSynchronizationMessage).toBeFalsy();
34+
});
4235
});
Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
1-
import { Component } from '@angular/core';
1+
import { Component, OnInit } from '@angular/core';
2+
import { SynchronizationService } from '../../../service/synchronization/synchronization.service';
23

34
@Component({
45
selector: 'app-main',
56
templateUrl: './main.component.html',
67
styleUrls: ['./main.component.scss'],
78
})
8-
export class MainComponent {}
9+
export class MainComponent implements OnInit {
10+
shouldShowSynchronizationMessage = true;
11+
isSynchronizationRunning = false;
12+
13+
constructor(private synchronizationService: SynchronizationService) {}
14+
15+
ngOnInit(): void {
16+
this.getCurrentSynchronizationStatus();
17+
}
18+
19+
private getCurrentSynchronizationStatus(): void {
20+
this.synchronizationService
21+
.getCurrentSynchronizationStatus()
22+
.then((status) => {
23+
this.isSynchronizationRunning = status;
24+
});
25+
}
26+
27+
closeSynchronizationMessage(): void {
28+
this.shouldShowSynchronizationMessage = false;
29+
}
30+
}

src/app/ui/pages/main/main.module.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ import { CommonModule } from '@angular/common';
33
import { RouterModule, Routes } from '@angular/router';
44

55
import { MainComponent } from './main.component';
6-
import { NbLayoutModule, NbSidebarModule } from '@nebular/theme';
6+
import {
7+
NbAlertModule,
8+
NbCardModule,
9+
NbLayoutModule,
10+
NbSidebarModule,
11+
} from '@nebular/theme';
712
import { NbEvaIconsModule } from '@nebular/eva-icons';
813
import { MainMenuModule } from '../../components/main-menu/main-menu.module';
914
import { ToolbarModule } from '../../components/toolbar/toolbar.module';
15+
import { TranslateModule } from '@ngx-translate/core';
16+
import { SynchronizationService } from '../../../service/synchronization/synchronization.service';
1017

1118
/* eslint-disable @typescript-eslint/explicit-function-return-type */
1219
const routes: Routes = [
@@ -81,6 +88,12 @@ const routes: Routes = [
8188
NbLayoutModule,
8289
NbEvaIconsModule,
8390
NbSidebarModule.forRoot(),
91+
NbCardModule,
92+
NbAlertModule,
93+
94+
// Other
95+
TranslateModule.forChild(),
8496
],
97+
providers: [SynchronizationService],
8598
})
8699
export class MainModule {}

src/assets/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@
6666
"INTERNET": "Internet and Communication",
6767
"UTILITY": "Utility and Productivity",
6868
"MISC": "Miscellaneous"
69-
}
69+
},
70+
"SYNCHRONIZATION_MESSAGE": "App Outlet is synchronizing its database. It can affect the search performance. When synchronization ends, it will back to normal"
7071
},
7172
"SEARCH": {
7273
"NO_RESULTS_FOUND": "No results found",

0 commit comments

Comments
 (0)