Skip to content

Commit

Permalink
Feature/feat 1307 reload config on file change (#1325)
Browse files Browse the repository at this point in the history
* changing the config error and adding a config warning message. refactoring the event names to all be kebab-case, instead of a mix of camelCase and kebab-case. adding watchConfigFile option to watch the config file and restart the app if it changes, and other small refactoring

* intune refactoring to be allways inTune (internal code)

* adding release notes

* merge with main
  • Loading branch information
IsmaelMartinez authored Jul 2, 2024
1 parent f166704 commit 190efc1
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 55 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@ Read about the history of this project in the [`HISTORY.md`](HISTORY.md) file.

## License

Some icons are from (Icon Duck)[https://iconduck.com/sets/hugeicons-essential-free-icons] under the `CC BY 4.0` license.

License: [`GPLv3`](LICENSE.md)
Binary file added app/assets/icons/alert-diamond.256x256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/icons/setting-error.256x256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const ActivityManager = require('./notifications/activityManager');

let config;
ipcRenderer.invoke('getConfig').then(mainConfig => {
ipcRenderer.invoke('get-config').then(mainConfig => {
config = mainConfig;
initializeModules(config, ipcRenderer);

Expand Down
2 changes: 1 addition & 1 deletion app/browser/notifications/activityManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ActivityManager {

watchSystemIdleState() {
const self = this;
self.ipcRenderer.invoke('getSystemIdleState').then((state) => {
self.ipcRenderer.invoke('get-system-idle-state').then((state) => {
activityHub.setMachineState(state.system === 'active' ? 1 : 2);
const timeOut = (state.system === 'active' ? self.config.appIdleTimeoutCheckInterval : self.config.appActiveCheckInterval) * 1000;

Expand Down
2 changes: 1 addition & 1 deletion app/browser/tools/customBackgrounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async function overrideMSMethod(inst) {

async function customBGProvider(...args) {
const ms_response = config.customBGServiceIgnoreMSDefaults ? [] : await bgMSMethod.apply(bgMSService, [...args]);
const customList = await ipRenderer.invoke('getCustomBGList');
const customList = await ipRenderer.invoke('get-custom-bg-list');
ms_response.push(...customList);
return ms_response;
}
Expand Down
4 changes: 2 additions & 2 deletions app/browser/tools/zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Zoom {
}

function restoreZoomLevelInternal(config) {
ipcRenderer.invoke('getZoomLevel', config.partition).then(zoomLevel => {
ipcRenderer.invoke('get-zoom-level', config.partition).then(zoomLevel => {
webFrame.setZoomLevel(zoomLevel);
});
}
Expand All @@ -72,7 +72,7 @@ function setNextZoomLevel(keyName, config) {
zoomLevel = zoomOffset === 0 ? 0 : zoomLevel + zoomOffset * zoomFactor;
if (zoomLevel < zoomMin || zoomLevel > zoomMax) return;
webFrame.setZoomLevel(zoomLevel);
ipcRenderer.invoke('saveZoomLevel', {
ipcRenderer.invoke('save-zoom-level', {
partition: config.partition,
zoomLevel: webFrame.getZoomLevel()
});
Expand Down
1 change: 1 addition & 0 deletions app/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Here is the list of available arguments and its usage:
| url | Microsoft Teams URL (string) | https://teams.microsoft.com/ |
| useMutationTitleLogic | Use MutationObserver to update counter from title | true |
| version | Show the version number | false |
| watchConfigFile | Watch for changes in the config file and restarts the app | false |
| webDebug | Enable web debugging | false |


Expand Down
48 changes: 30 additions & 18 deletions app/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const { LucidLog } = require('lucid-log');
const {type}=require('os');
const { ipcMain } = require('electron');

let logger;

Expand All @@ -19,22 +19,28 @@ function getConfigFile(configPath) {
}

function argv(configPath, appVersion) {
let configFile = null;
let configError = null;
const configObject = {
configFile: {},
configError: null,
configWarning: null,
isConfigFile: false
}

if (checkConfigFileExistance(configPath)) {
try {
configFile = getConfigFile(configPath);
configObject.configFile = getConfigFile(configPath);
configObject.isConfigFile = true;
} catch (e) {
configError = e.message;
configObject.configError = e.message;
console.warn('Error in config file, using default values:\n' + configObject.configError);
}
} else {
console.warn('No config file found, using default values');
}

const missingConfig = configFile == null;
configFile = configFile || {};
let config = yargs
.env(true)
.config(configFile)
.config(configObject.configFile)
.version(appVersion)
.options({
appActiveCheckInterval: {
Expand Down Expand Up @@ -313,6 +319,11 @@ function argv(configPath, appVersion) {
describe: 'Use MutationObserver to update counter from title',
type: 'boolean'
},
watchConfigFile: {
default: false,
describe: 'Watch for changes in the config file and reload the app',
type: 'boolean'
},
webDebug: {
default: false,
describe: 'Enable debug at start',
Expand All @@ -321,22 +332,23 @@ function argv(configPath, appVersion) {
})
.parse(process.argv.slice(1));

if (configError) {
config['error'] = configError;
if (configObject.configError) {
config['error'] = configObject.configError;
}

if (configObject.isConfigFile && config.watchConfigFile) {
fs.watch(getConfigFilePath(configPath), (event, filename) => {
logger.info(`Config file ${filename} changed ${event}. Relaunching app...`);
ipcMain.emit('config-file-changed');
});
}

logger = new LucidLog({
levels: config.appLogLevels.split(',')
});

logger.debug('configPath:', configPath);
if (missingConfig) {
if (configError) {
logger.warn('Error in config file, using default values:\n' + configError);
} else {
logger.warn('No config file found, using default values');
}
}
logger.debug('configFile:', configFile);
logger.debug('configFile:', configObject.configFile);

return config;
}
Expand Down
46 changes: 30 additions & 16 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,25 @@ if (!gotTheLock) {
app.on('certificate-error', handleCertificateError);
app.on('browser-window-focus', handleGlobalShortcutDisabled);
app.on('browser-window-blur', handleGlobalShortcutDisabledRevert);
ipcMain.handle('getConfig', handleGetConfig);
ipcMain.handle('getSystemIdleTime', handleGetSystemIdleTime);
ipcMain.handle('getSystemIdleState', handleGetSystemIdleState);
ipcMain.handle('getZoomLevel', handleGetZoomLevel);
ipcMain.handle('saveZoomLevel', handleSaveZoomLevel);
ipcMain.handle('desktopCapturerGetSources', (event, opts) => desktopCapturer.getSources(opts));
ipcMain.handle('getCustomBGList', handleGetCustomBGList);
ipcMain.on('config-file-changed', restartApp);
ipcMain.handle('get-config', async () => { return config } );
ipcMain.handle('get-system-idle-state', handleGetSystemIdleState);
ipcMain.handle('get-zoom-level', handleGetZoomLevel);
ipcMain.handle('save-zoom-level', handleSaveZoomLevel);
ipcMain.handle('desktop-capturer-get-sources', (event, opts) => desktopCapturer.getSources(opts));
ipcMain.handle('get-custom-bg-list', handleGetCustomBGList);
ipcMain.handle('play-notification-sound', playNotificationSound);
ipcMain.handle('show-notification', showNotification);
ipcMain.handle('user-status-changed', userStatusChangedHandler);
ipcMain.handle('set-badge-count', setBadgeCountHandler);
}

function restartApp() {
console.log('Restarting app...');
app.relaunch();
app.exit();
}

function addCommandLineSwitchesBeforeConfigLoad() {
// Custom user data directory
if (app.commandLine.hasSwitch('customUserDir')) {
Expand Down Expand Up @@ -214,7 +220,23 @@ function onAppTerminated(signal) {
function handleAppReady() {
// check for configuration errors
if (config.error) {
dialog.showErrorBox('Configuration error', config.error);
dialog.showMessageBox(
{
title: 'Configuration error',
icon: nativeImage.createFromPath(path.join(config.appPath, 'assets/icons/setting-error.256x256.png')),
message: `Error in config file ${config.error}.\n Loading default configuration`
}
);
}
if (config.warning) {
// check for configuration warnings
dialog.showMessageBox(
{
title: 'Configuration Warning',
icon: nativeImage.createFromPath(path.join(config.appPath, 'assets/icons/alert-diamond.256x256.png')),
message: config.warning
}
);
}

if (config.isCustomBackgroundEnabled) {
Expand All @@ -228,14 +250,6 @@ function handleAppReady() {
mainAppWindow.onAppReady(appConfig);
}

async function handleGetConfig() {
return config;
}

async function handleGetSystemIdleTime() {
return powerMonitor.getSystemIdleTime();
}

async function handleGetSystemIdleState() {
const systemIdleState = powerMonitor.getSystemIdleState(config.appIdleTimeout);
logger.debug(`GetSystemIdleState => IdleTimeout: ${config.appIdleTimeout}s, IdleTimeoutPollInterval: ${config.appIdleTimeoutCheckInterval}s, ActiveCheckPollInterval: ${config.appActiveCheckInterval}s, IdleTime: ${powerMonitor.getSystemIdleTime()}s, IdleState: '${systemIdleState}'`);
Expand Down
25 changes: 12 additions & 13 deletions app/intune/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const dbus = require('@homebridge/dbus-native');
const { LucidLog } = require('lucid-log');

let intuneAccount = null;
let inTuneAccount = null;
const brokerService = dbus.sessionBus().getService('com.microsoft.identity.broker1');

function processInTuneAccounts(logger, resp, ssoInTuneAuthUser) {
Expand All @@ -12,18 +11,18 @@ function processInTuneAccounts(logger, resp, ssoInTuneAuthUser) {
};

if (ssoInTuneAuthUser == '') {
intuneAccount = response.accounts[0];
logger.debug('Using first available InTune account (' + intuneAccount.username + ')');
inTuneAccount = response.accounts[0];
logger.debug('Using first available InTune account (' + inTuneAccount.username + ')');
} else {
for (const account in response.accounts) {
if (account.username == ssoIntuneAuthUser) {
intuneAccount = account;
logger.debug('Found matching InTune account (' + intuneAccount.username + ')');
if (account.username == ssoInTuneAuthUser) {
inTuneAccount = account;
logger.debug('Found matching InTune account (' + inTuneAccount.username + ')');
break;
}
}
if (intuneAccount == null) {
logger.warn('Failed to find matching InTune account for ' + ssoIntuneAuthUser + '.');
if (inTuneAccount == null) {
logger.warn('Failed to find matching InTune account for ' + ssoInTuneAuthUser + '.');
}
}
}
Expand Down Expand Up @@ -52,11 +51,11 @@ exports.setupUrlFilter = function setupUrlFilter(filter) {
}

exports.isSsoUrl = function isSsoUrl(url) {
return intuneAccount != null && url.startsWith('https://login.microsoftonline.com/');
return inTuneAccount != null && url.startsWith('https://login.microsoftonline.com/');
}

function processPrtResponse(logger, resp, detail) {
response = JSON.parse(resp);
const response = JSON.parse(resp);
if ('error' in response) {
logger.warn('Failed to retrieve Intune SSO cookie: ' + response.error.context);
} else {
Expand All @@ -67,7 +66,7 @@ function processPrtResponse(logger, resp, detail) {

exports.addSsoCookie = function addIntuneSsoCookie(logger, detail, callback) {
logger.debug('Retrieving InTune SSO cookie');
if (intuneAccount == null) {
if (inTuneAccount == null) {
logger.info("InTune SSO not active");
callback({
requestHeaders: detail.requestHeaders
Expand All @@ -77,7 +76,7 @@ exports.addSsoCookie = function addIntuneSsoCookie(logger, detail, callback) {
brokerService.getInterface(
'/com/microsoft/identity/broker1',
'com.microsoft.identity.Broker1', function(err, broker) {
broker.acquirePrtSsoCookie('0.0', '', JSON.stringify({'ssoUrl':detail.url, 'account':intuneAccount, 'authParameters':{'authority':'https://login.microsoftonline.com/common/'}}), function(err, resp) {
broker.acquirePrtSsoCookie('0.0', '', JSON.stringify({'ssoUrl':detail.url, 'account':inTuneAccount, 'authParameters':{'authority':'https://login.microsoftonline.com/common/'}}), function(err, resp) {
processPrtResponse(logger, resp, detail);
callback({
requestHeaders: detail.requestHeaders
Expand Down
2 changes: 1 addition & 1 deletion app/mainAppWindow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ exports.onAppReady = async function onAppReady(configGroup) {
}

if (config.trayIconEnabled) {
iconChooser = new TrayIconChooser(configGroup.startupConfig);
iconChooser = new TrayIconChooser(config);
}

const browserWindowManager = new BrowserWindowManager({
Expand Down
2 changes: 1 addition & 1 deletion app/streamSelector/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function createPreviewScreen(screens) {
let windowsIndex = 0;
const sscontainer = document.getElementById('screen-size');
createEventHandlers({ screens, sscontainer });
ipcRenderer.invoke('desktopCapturerGetSources', { types: ['window', 'screen'] }).then(async (sources) => {
ipcRenderer.invoke('desktop-capturer-get-sources', { types: ['window', 'screen'] }).then(async (sources) => {
const rowElement = document.querySelector('.container-fluid .row');
for (const source of sources) {
await createPreview({
Expand Down
11 changes: 11 additions & 0 deletions com.github.IsmaelMartinez.teams_for_linux.appdata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@
<url type="bugtracker">https://github.com/IsmaelMartinez/teams-for-linux/issues</url>
<launchable type="desktop-id">com.github.IsmaelMartinez.teams_for_linux.desktop</launchable>
<releases>
<release version="1.7.5" date="2024-07-02">
<description>
<ul>
<li>Add watchConfigFile option to restart the app if the configuration changes</li>
<li>Modify configError message to have an icon and adding the ability to provide warning dialogs (for config deprecations)</li>
<li>Changing app description to be more flathub compliat</li>
<li>Refactoring around inTune and the config file handling</li>
<li>Refactoring events to all be kebab-case instead of a mix of kebab-case and camelCase</li>
</ul>
</description>
</release>
<release version="1.7.4" date="2024-06-25">
<description>
<ul>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "teams-for-linux",
"version": "1.7.4",
"version": "1.7.5",
"main": "app/index.js",
"description": "Unofficial client for Microsoft Teams for Linux",
"homepage": "https://github.com/IsmaelMartinez/teams-for-linux",
Expand Down

0 comments on commit 190efc1

Please sign in to comment.