mirror of
https://github.com/ever-co/ever-gauzy.git
synced 2026-10-02 01:54:50 +08:00
Fix/last screen capture (#9484)
* fix: last screen capture on app starting up * fix: window automatically grow after start timer at first time * fix: image-viewer handle last capture image * fix: image-viewer handle last capture image
This commit is contained in:
@@ -359,6 +359,13 @@ export function ipcMainHandler(store, startServer, knex, config, timeTrackerWind
|
||||
return LocalStore.getStore('appSetting').theme;
|
||||
});
|
||||
|
||||
ipcMain.handle('GET_LAST_CAPTURE', async () => {
|
||||
const lastCapture = await timerService.findLastCapture();
|
||||
return {
|
||||
timeSlotId: lastCapture?.timeslotId
|
||||
};
|
||||
});
|
||||
|
||||
pluginListeners();
|
||||
}
|
||||
|
||||
@@ -1242,7 +1249,8 @@ export function removeAllHandlers() {
|
||||
'DESKTOP_CAPTURER_GET_SOURCES',
|
||||
'FINISH_SYNCED_TIMER',
|
||||
'COLLECT_ACTIVITIES',
|
||||
'START_SERVER'
|
||||
'START_SERVER',
|
||||
'GET_LAST_CAPTURE'
|
||||
];
|
||||
channels.forEach((channel: string) => {
|
||||
ipcMain.removeHandler(channel);
|
||||
|
||||
@@ -36,6 +36,7 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
items = [];
|
||||
|
||||
item: any = {};
|
||||
private readonly _showImageHandler = this.showImageEventHandler.bind(this);
|
||||
constructor(
|
||||
// private dialogRef: NbDialogRef<any>
|
||||
private readonly _electronService: ElectronService,
|
||||
@@ -49,9 +50,18 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
getImages(_, arg: any[]) {
|
||||
async showImageEventHandler(_, arg) {
|
||||
if (arg.timeSlotId) {
|
||||
const screenshots: any[] = await this.getLastScreenshot(arg.timeSlotId);
|
||||
this.getImages(screenshots);
|
||||
} else {
|
||||
this.getImages(arg.screenshots);
|
||||
}
|
||||
}
|
||||
|
||||
getImages(screenshots: any[]) {
|
||||
this._ngZone.run(() => {
|
||||
this.items = arg
|
||||
this.items = screenshots
|
||||
.sort((a, b) => {
|
||||
const c: any = new Date(b.recordedAt);
|
||||
const d: any = new Date(a.recordedAt);
|
||||
@@ -67,13 +77,13 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._electronService.ipcRenderer.on('show_image', this.getImages.bind(this));
|
||||
this._electronService.ipcRenderer.on('show_image', this._showImageHandler);
|
||||
this._electronService.ipcRenderer.send('image_view_ready');
|
||||
this.active_index = 0;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this._electronService.ipcRenderer.removeListener('show_image', this.getImages.bind(this));
|
||||
this._electronService.ipcRenderer.removeListener('show_image', this._showImageHandler);
|
||||
}
|
||||
|
||||
close() {
|
||||
@@ -133,4 +143,16 @@ export class ImageViewerComponent implements OnInit, OnDestroy {
|
||||
public trackById(index: number, item: any): number {
|
||||
return item.id;
|
||||
}
|
||||
|
||||
private async getLastScreenshot(timeSlotId: string) {
|
||||
try {
|
||||
const lastTimeSlot = await this._imageViewerService.getTimeSlot({
|
||||
timeSlotId
|
||||
});
|
||||
return lastTimeSlot?.screenshots || [];
|
||||
} catch(err) {
|
||||
console.error('[ImageViewer] showImageEventHandler error:', err);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||
import { shareReplay, firstValueFrom, concatMap } from 'rxjs';
|
||||
import { ImageCacheService } from '../services';
|
||||
import { shareReplay, firstValueFrom, concatMap, map } from 'rxjs';
|
||||
import { ImageCacheService, Store, TimeSlotCacheService } from '../services';
|
||||
import { ITimeSlot } from '@gauzy/contracts';
|
||||
import { API_PREFIX } from '../constants';
|
||||
import { toParams } from '@gauzy/ui-core/common';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ImageViewerService {
|
||||
constructor(
|
||||
private readonly _imageCacheService: ImageCacheService,
|
||||
private readonly _domSanitizer: DomSanitizer,
|
||||
private readonly _http: HttpClient
|
||||
) { }
|
||||
private readonly _http: HttpClient,
|
||||
private readonly _store: Store,
|
||||
private readonly _timeSlotCacheService: TimeSlotCacheService
|
||||
) {}
|
||||
|
||||
public source(imageUrl: string): Promise<string> {
|
||||
this._imageCacheService.clear();
|
||||
let image$ = this._imageCacheService.getValue(imageUrl);
|
||||
if (!image$) {
|
||||
image$ = this._http.get(imageUrl, { responseType: 'blob' }).pipe(
|
||||
concatMap((response: Blob) =>
|
||||
this.getBase64ImageFromBlob(response)
|
||||
),
|
||||
concatMap((response: Blob) => this.getBase64ImageFromBlob(response)),
|
||||
shareReplay(1)
|
||||
);
|
||||
this._imageCacheService.setValue(image$, imageUrl);
|
||||
@@ -70,4 +73,36 @@ export class ImageViewerService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async getTimeSlot(values: { timeSlotId: string }): Promise<ITimeSlot | null> {
|
||||
const { timeSlotId } = values;
|
||||
if (!timeSlotId) {
|
||||
return null;
|
||||
}
|
||||
const { tenantId, organizationId } = this._store;
|
||||
const params = toParams({
|
||||
tenantId,
|
||||
organizationId,
|
||||
relations: ['screenshots'],
|
||||
order: {
|
||||
createdAt: 'DESC',
|
||||
screenshots: {
|
||||
recordedAt: 'DESC'
|
||||
}
|
||||
}
|
||||
});
|
||||
let timeSlots$ = this._timeSlotCacheService.getValue(timeSlotId);
|
||||
if (!timeSlots$) {
|
||||
timeSlots$ = this._http
|
||||
.get<ITimeSlot>(`${API_PREFIX}/timesheet/time-slot/${timeSlotId}`, {
|
||||
params
|
||||
})
|
||||
.pipe(
|
||||
map((response: any) => response),
|
||||
shareReplay(1)
|
||||
);
|
||||
this._timeSlotCacheService.setValue(timeSlots$, timeSlotId);
|
||||
}
|
||||
return firstValueFrom(timeSlots$);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1871,11 +1871,13 @@ export class TimeTrackerComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
public async getLastTimeSlotImage(arg): Promise<void> {
|
||||
if (this._isOffline || this.lastTimeSlot?.id === arg?.timeSlotId) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await this.timeTrackerService.getTimeSlot(arg);
|
||||
const lastTimeSlot: { timeSlotId?: string } = await this.electronService.invoke('GET_LAST_CAPTURE');
|
||||
if (this._isOffline || !lastTimeSlot?.timeSlotId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await this.timeTrackerService.getTimeSlot({ timeSlotId: lastTimeSlot.timeSlotId });
|
||||
const { screenshots = [] } = res || {};
|
||||
if (screenshots && screenshots.length > 0) {
|
||||
const [lastCaptureScreen] = screenshots;
|
||||
@@ -2006,7 +2008,11 @@ export class TimeTrackerComponent implements OnInit, AfterViewInit {
|
||||
this._loggerService.warn(`WARN: ${message}`);
|
||||
return;
|
||||
}
|
||||
this.electronService.ipcRenderer.send('show_image', this.screenshots);
|
||||
|
||||
this.electronService.ipcRenderer.send('show_image', {
|
||||
screenshots: this.screenshots,
|
||||
timeSlotId: !this._isOffline ? this.lastTimeSlot?.id : null
|
||||
});
|
||||
}
|
||||
|
||||
public open(dialog: TemplateRef<any>, option): void {
|
||||
|
||||
Reference in New Issue
Block a user