Skip to content

Commit

Permalink
Add about view
Browse files Browse the repository at this point in the history
  • Loading branch information
SRichner committed Feb 21, 2024
1 parent 4615dc2 commit 360ba9b
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
import { ExperienceSamplingService } from '../main/services/ExperienceSamplingService';
import { ipcMain, IpcMainInvokeEvent } from 'electron';
import { app, ipcMain, IpcMainInvokeEvent } from 'electron';
import { WindowService } from '../main/services/WindowService';
import { getLogger } from '../shared/Logger';
import { TypedIpcMain } from '../../src/utils/TypedIpcMain';
import Commands from '../../src/utils/Commands';
import Events from '../../src/utils/Events';
import StudyInfoDto from '../../shared/dto/StudyInfoDto';
import { Settings } from '../main/entities/Settings';
import studyConfig from '../../shared/study.config';
import { TrackerService } from '../main/services/trackers/TrackerService';

const LOG = getLogger('IpcHandler');

const LOG = getLogger('IpcHandler')
export class IpcHandler {
private readonly actions: any;
private readonly windowService: WindowService;
private readonly trackerService: TrackerService;

private readonly experienceSamplingService: ExperienceSamplingService;
private typedIpcMain: TypedIpcMain<Events, Commands> = ipcMain as TypedIpcMain<Events, Commands>;

constructor(windowService: WindowService, experienceSamplingService: ExperienceSamplingService) {
constructor(
windowService: WindowService,
trackerService: TrackerService,
experienceSamplingService: ExperienceSamplingService
) {
this.windowService = windowService;
this.trackerService = trackerService;
this.experienceSamplingService = experienceSamplingService;
this.actions = {
createExperienceSample: this.createExperienceSample,
closeExperienceSamplingWindow: this.closeExperienceSamplingWindow
closeExperienceSamplingWindow: this.closeExperienceSamplingWindow,
getStudyInfo: this.getStudyInfo
};
}

Expand All @@ -45,4 +56,19 @@ export class IpcHandler {
private async closeExperienceSamplingWindow(): Promise<void> {
await this.windowService.closeExperienceSamplingWindow();
}

private async getStudyInfo(): Promise<StudyInfoDto> {
const settings: Settings = await Settings.findOne({ where: { onlyOneEntityShouldExist: 1 } });
return {
studyName: settings.studyName,
subjectId: settings.subjectId,
shortDescription: studyConfig.shortDescription,
infoUrl: studyConfig.infoUrl,
privacyPolicyUrl: studyConfig.privacyPolicyUrl,
contactName: studyConfig.contactName,
contactEmail: studyConfig.contactEmail,
appVersion: app.getVersion(),
currentlyActiveTrackers: this.trackerService.getRunningTrackerNames()
};
}
}
8 changes: 4 additions & 4 deletions src/electron/electron/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'reflect-metadata';
import { app, BrowserWindow, dialog, powerMonitor } from 'electron';
import { app, dialog, powerMonitor } from 'electron';
import { release } from 'node:os';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
Expand All @@ -13,7 +13,7 @@ import { UserInputTrackerService } from './services/trackers/UserInputTrackerSer
import { TrackerService } from './services/trackers/TrackerService';
import AppUpdaterService from './services/AppUpdaterService';
import { WindowService } from './services/WindowService';
import { IpcHandler } from '../ipc/Api';
import { IpcHandler } from '../ipc/IpcHandler';
import { ExperienceSamplingService } from './services/ExperienceSamplingService';
import studyConfig from '../../shared/study.config';
import { SchedulingService } from './services/SchedulingService';
Expand All @@ -32,7 +32,8 @@ const settingsService: SettingsService = new SettingsService();
const appUpdaterService: AppUpdaterService = new AppUpdaterService();
const windowService: WindowService = new WindowService(appUpdaterService);
const experienceSamplingService: ExperienceSamplingService = new ExperienceSamplingService();
const ipcHandler: IpcHandler = new IpcHandler(windowService, experienceSamplingService);
const trackers: TrackerService = new TrackerService(studyConfig.trackers);
const ipcHandler: IpcHandler = new IpcHandler(windowService, trackers, experienceSamplingService);
const schedulingService: SchedulingService = new SchedulingService(windowService);

// Disable GPU Acceleration for Windows 7
Expand Down Expand Up @@ -70,7 +71,6 @@ app.whenReady().then(async () => {
await appUpdaterService.checkForUpdates({ silent: true });
appUpdaterService.startCheckForUpdatesInterval();

const trackers: TrackerService = new TrackerService(studyConfig.trackers);
await trackers.registerTrackerCallback(
TrackerType.WindowsActivityTracker,
WindowActivityTrackerService.handleWindowChange
Expand Down
33 changes: 32 additions & 1 deletion src/electron/electron/main/services/WindowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const LOG = getLogger('WindowService');
export class WindowService {
private readonly appUpdaterService: AppUpdaterService;
private tray: Tray;
private readonly isDevelopment: boolean = is.dev;
private experienceSamplingWindow: BrowserWindow;

constructor(appUpdaterService: AppUpdaterService) {
Expand Down Expand Up @@ -96,6 +95,34 @@ export class WindowService {
}
}

public async createAboutWindow() {
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const preload = join(__dirname, '../preload/index.mjs');
const aboutWindow = new BrowserWindow({
width: 800,
height: 600,
show: false,
minimizable: false,
maximizable: false,
fullscreenable: false,
resizable: false,
title: 'About',
webPreferences: {
preload
}
});

if (process.env.VITE_DEV_SERVER_URL) {
await aboutWindow.loadURL(process.env.VITE_DEV_SERVER_URL + '#about');
} else {
await aboutWindow.loadFile(path.join(process.env.DIST, 'index.html'), {
hash: 'about'
});
}
aboutWindow.show();
}

public updateTray(
updaterLabel: string = 'Check for updates',
updaterMenuEnabled: boolean = false
Expand Down Expand Up @@ -134,6 +161,10 @@ export class WindowService {
label: 'Open Experience Sampling',
click: () => this.createExperienceSamplingWindow()
},
{
label: 'About',
click: () => this.createAboutWindow()
},
{ type: 'separator' }
];
const otherMenu: MenuItemConstructorOptions[] = [
Expand Down
2 changes: 1 addition & 1 deletion src/electron/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<title>PersonalAnalytics</title>
</head>
<body>
<body class="h-screen">
<div id="app"></div>
<script type="module" src="src/main.ts"></script>
</body>
Expand Down
11 changes: 11 additions & 0 deletions src/electron/shared/dto/StudyInfoDto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface StudyInfoDto {
subjectId: string;
studyName: string;
shortDescription: string;
infoUrl: string;
privacyPolicyUrl: string;
contactName: string;
contactEmail: string;
appVersion: string;
currentlyActiveTrackers: string[];
}
2 changes: 1 addition & 1 deletion src/electron/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</template>
<style lang="less">
#app {
@apply bg-white;
@apply h-full overflow-hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
Expand Down
11 changes: 8 additions & 3 deletions src/electron/src/router/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { createRouter, createWebHashHistory } from 'vue-router';
import { createRouter, createWebHashHistory, Router } from 'vue-router';

const router = createRouter({
const router: Router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/about',
name: 'About',
component: () => import('../views/AboutView.vue')
},
{
path: '/experience-sampling',
name: 'ExperienceSampling',
component: () => import('../views/ExperienceSampling.vue')
component: () => import('../views/ExperienceSamplingView.vue')
}
]
});
Expand Down
3 changes: 3 additions & 0 deletions src/electron/src/utils/Commands.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { StudyInfoDto } from '../../shared/dto/StudyInfoDto';

type Commands = {
createExperienceSample: (promptedAt: number, question: string, response: number) => Promise<void>;
closeExperienceSamplingWindow: () => Promise<void>;
getStudyInfo: () => Promise<StudyInfoDto>;
};
export default Commands;
60 changes: 60 additions & 0 deletions src/electron/src/views/AboutView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script lang="ts" setup>
import typedIpcRenderer from '../utils/typedIpcRenderer';
import { onMounted, ref } from 'vue';
import { StudyInfoDto } from '../../shared/dto/StudyInfoDto';
const studyInfo = ref<StudyInfoDto>();
onMounted(async () => {
studyInfo.value = await typedIpcRenderer.invoke('getStudyInfo');
});
</script>
<template>
<div class="h-full p-4">
<!-- center spinner across the screen -->
<div v-if="!studyInfo" class="flex h-full items-center justify-center">
<span class="loading loading-spinner loading-lg"></span>
</div>
<article v-else class="lg:prose-lg prose mx-auto mt-8 align-top">
<h1>
<span class="primary-blue">{{ studyInfo.studyName }}</span>
</h1>
<div class="badge badge-neutral fixed right-0 top-0 mr-4 mt-4">
Version {{ studyInfo.appVersion }}
</div>
<p>{{ studyInfo.shortDescription }}</p>
<table class="table-auto">
<tbody>
<tr>
<td>Your Subject Id:</td>
<td>
<span class="badge badge-neutral">{{ studyInfo.subjectId }}</span>
</td>
</tr>
<tr>
<td>Contact:</td>
<td>{{ studyInfo.contactName }} ({{ studyInfo.contactEmail }})</td>
</tr>
<tr>
<td>Study Website:</td>
<td>{{ studyInfo.infoUrl }}</td>
</tr>
<tr>
<td>Privacy Policy:</td>
<td>{{ studyInfo.privacyPolicyUrl }}</td>
</tr>
<tr>
<td>Active Trackers:</td>
<td>{{ studyInfo.currentlyActiveTrackers.join(', ') }}</td>
</tr>
</tbody>
</table>
</article>
</div>
</template>
<style lang="less">
@import '../styles/index';
.primary-blue {
color: @primary-color;
}
</style>

0 comments on commit 360ba9b

Please sign in to comment.