diff --git a/README.md b/README.md index 810e810..ee9a38f 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,12 @@ A greeter theme for [nody-greeter](https://github.com/JezerM/nody-greeter)/web-g - Customizable background image and logo - Greeter can be used as a lock screen when someone is already logged in (replacement for ft_lock) - Automatically log students out after 42 minutes of inactivity, either in-session or on the lock screen -- Display user's profile picture (from `~/.face`) on the lock screen +- Display user's Intra picture on the lock screen - Display user's Gnome wallpaper on the lock screen - Keybinding to gracefully reboot the computer (Ctrl+Alt+Del) - Display network status on-screen without having to log in -- Custom screensaver support (HTML5 canvas) +- Screen brightness control support +- Choose between light or dark mode upon installation ## Screenshots @@ -168,6 +169,15 @@ if [ "$DISPLAY" != ":0" ]; then fi ``` +### Users are sometimes randomly logged out after locking their screen once +Add the following lines to the top of the logout hook defined in */etc/lightdm/lightdm.conf*: +```bash +# Delete any lock_time files in /tmp (used by codam-web-greeter to know when the screen was locked +# and when to automatically log out the user) +/usr/bin/rm -f /tmp/codam_web_greeter_lock_timestamp_* +``` +Make sure to add these lines above the lines added in the previous section (the check for the greeter logout event). + ### My custom wallpaper or logo doesn't show up Make sure the folders mentioned for branding in */etc/lightdm/web-greeter.yml* exist and contain the correct files. ```yaml diff --git a/client/uis/screen.ts b/client/uis/screen.ts index 6e5cd01..3eaedf8 100644 --- a/client/uis/screen.ts +++ b/client/uis/screen.ts @@ -23,6 +23,7 @@ export interface UIExamModeElements { examStartText: HTMLSpanElement; examEndText: HTMLSpanElement; examStartButton: HTMLButtonElement; + examStartTimer: HTMLParagraphElement; } export abstract class UIScreen { diff --git a/client/uis/screens/examscreen.ts b/client/uis/screens/examscreen.ts index 2a5da9c..959a8a4 100644 --- a/client/uis/screens/examscreen.ts +++ b/client/uis/screens/examscreen.ts @@ -11,6 +11,8 @@ export class ExamModeUI extends UIScreen { private _examMode: boolean = false; private _examIds: number[] = []; private _loginScreen: LoginScreenUI; + private _examStartButtonEnableInterval: ReturnType | null = null; + private _examStartTime = new Date("2099-01-01T00:00:00Z"); // Set to a future date so that the button is disabled by default protected _events: AuthenticatorEvents = { authenticationStart: () => { this._disableForm(); @@ -43,6 +45,7 @@ export class ExamModeUI extends UIScreen { examStartText: document.getElementById('exam-mode-start') as HTMLSpanElement, examEndText: document.getElementById('exam-mode-end') as HTMLSpanElement, examStartButton: document.getElementById('exam-mode-start-button') as HTMLButtonElement, + examStartTimer: document.getElementById('exam-mode-start-timer') as HTMLParagraphElement, } as UIExamModeElements; this._initForm(); @@ -100,6 +103,16 @@ export class ExamModeUI extends UIScreen { }); } + private _clearExamStartTimer(): void { + const form = this._form as UIExamModeElements; + if (this._examStartButtonEnableInterval) { + clearTimeout(this._examStartButtonEnableInterval); + this._examStartButtonEnableInterval = null; + } + form.examStartTimer.innerText = "Click the arrow below to start your exam."; + this._enableOrDisableSubmitButton(); + } + private _populateData(examsToPopulate: ExamForHost[]): void { const form = this._form as UIExamModeElements; @@ -108,6 +121,9 @@ export class ExamModeUI extends UIScreen { form.examProjectsText.innerText = ''; form.examStartText.innerText = 'unknown'; form.examEndText.innerText = 'unknown'; + // Clear the timeout for the exam start button and disable it + this._examStartTime = new Date("2099-01-01T00:00:00Z"); + this._clearExamStartTimer(); } else { // Find all exams in the data.json file that match the ids in the exams variable @@ -144,14 +160,42 @@ export class ExamModeUI extends UIScreen { form.examProjectsText.innerText = projectsText; form.examStartText.innerText = earliestExam.toLocaleTimeString("en-NL", { hour: '2-digit', minute: '2-digit' }); form.examEndText.innerText = latestExam.toLocaleTimeString("en-NL", { hour: '2-digit', minute: '2-digit' }); + + // Enable or disable the exam start button based on the current time + this._clearExamStartTimer(); + this._examStartTime = earliestExam; + this._enableOrDisableSubmitButton(); + if (this._examStartTime.getTime() > Date.now()) { + this._examStartButtonEnableInterval = setInterval(() => { + const timeLeft = Math.floor((this._examStartTime.getTime() - Date.now()) / 1000); + const minutes = Math.floor(timeLeft / 60); + const seconds = timeLeft % 60; + const formattedTime = `${(minutes > 0 ? `${minutes} minutes and ` : '')} ${seconds} seconds`; + form.examStartTimer.innerText = `You may start your exam in ${formattedTime}.`; + + if (this._examStartTime.getTime() <= Date.now()) { + // Clear the timer and enable the button + this._clearExamStartTimer(); + return; + } + }, 1000); + } } } // Returns true if the exam-start button is disabled, false otherwise protected _enableOrDisableSubmitButton(): boolean { const form = this._form as UIExamModeElements; - form.examStartButton.disabled = false; // Always enable the button - return false; + const buttonDisabled = this._examStartTime.getTime() > Date.now(); // Disable the button if the exam start time is in the future + form.examStartButton.disabled = buttonDisabled; + if (!buttonDisabled) { + form.examStartTimer.innerText = "Click the arrow below to start your exam."; + const focusInput = this._getInputToFocusOn(); + if (focusInput) { + focusInput.focus(); + } + } + return buttonDisabled; } protected _wigglePasswordInput(clearInput: boolean = true): void { diff --git a/package-lock.json b/package-lock.json index 013c7bd..7ac5b2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codam-web-greeter", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codam-web-greeter", - "version": "1.3.0", + "version": "1.3.1", "license": "MIT", "devDependencies": { "nody-greeter-types": "^1.1.0", diff --git a/package.json b/package.json index 44adcf7..44e03ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codam-web-greeter", - "version": "1.3.0", + "version": "1.3.1", "description": "LightDM greeter theme for Codam Coding College, compatible with nody-greeter and web-greeter", "main": "main.js", "scripts": { diff --git a/server/package-lock.json b/server/package-lock.json index 2bf9b53..2b082ed 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "codam-web-greeter-server", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codam-web-greeter-server", - "version": "1.3.0", + "version": "1.3.1", "license": "MIT", "dependencies": { "@codam/fast42": "^2.1.6", diff --git a/server/package.json b/server/package.json index 1418876..c4a89d2 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "codam-web-greeter-server", - "version": "1.3.0", + "version": "1.3.1", "description": "Back-end server for the codam-web-greeter", "main": "src/server.js", "scripts": { diff --git a/static/index.html b/static/index.html index 65ffa46..6928d9f 100644 --- a/static/index.html +++ b/static/index.html @@ -53,7 +53,7 @@

username

This computer is reserved for an exam between ... and ....


-

Click the arrow below to start your exam.

+

Click the arrow below to start your exam.