Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,11 @@
"supportDescription": "Having issues? Explore help articles or open a ticket with Session Support.",
"supportGoTo": "Go to Support Page",
"systemInformationDesktop": "System Information: {information}",
"settingsCannotChangeDesktop": "Cannot Update Setting",
"settingsStartCategoryDesktop": "Startup",
"launchOnStartDesktop": "Launch on Startup",
"launchOnStartDescriptionDesktop": "Launch Session automatically when your computer starts up.",
"launchOnStartupDisabledDesktop": "This setting is managed by your system on Linux. To have Session start automatically, please add it to your startup applications in your system settings.",
Comment on lines +972 to +976
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid commiting those, we want those to come from crowdin only.
The flow should be

  • commit all but those changes, even if that means the CI will fail
  • wait for the strings to be added to crowdin
  • merge the crowdin PR to your branch (you get the new strings)
  • the CI should now be fixed

"tapToRetry": "Tap to retry",
"theContinue": "Continue",
"theDefault": "Default",
Expand Down
25 changes: 25 additions & 0 deletions preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const { isEmpty } = require('lodash');
const { setupI18n } = require('./ts/util/i18n/i18n');
const { UserUtils } = require('./ts/session/utils');
const { BlindingActions } = require('./ts/webworker/workers/browser/libsession_worker_interface');
const { SettingsKey } = require('./ts/data/settings-key');

const { crowdinLocale } = ipc.sendSync('locale-data');

Expand Down Expand Up @@ -135,6 +136,7 @@ window.setStartInTray = async startInTray =>
return;
});
ipc.send('start-in-tray-on-start', startInTray);
void window.setSettingValue(SettingsKey.settingsStartInTray, startInTray);
});

window.getStartInTray = async () => {
Expand All @@ -146,6 +148,29 @@ window.getStartInTray = async () => {
});
};

window.setAutoStartEnabled = async autoStart =>
new Promise((resolve, reject) => {
ipc.once('set-auto-start-enabled-response', (_event, error) => {
if (error) {
reject(error);
return;
}
resolve();
return;
});
ipc.send('set-auto-start-enabled', autoStart);
void window.setSettingValue(SettingsKey.settingsAutoStart, autoStart);
});

window.getAutoStartEnabled = async () => {
return new Promise(resolve => {
ipc.once('get-auto-start-enabled-response', (_event, value) => {
resolve(value);
});
ipc.send('get-auto-start-enabled');
});
};

window.getOpengroupPruning = async () => {
return new Promise(resolve => {
ipc.once('get-opengroup-pruning-response', (_event, value) => {
Expand Down
20 changes: 11 additions & 9 deletions ts/components/dialog/LocalizedPopupDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,17 @@ export function LocalizedPopupDialog(props: LocalizedPopupDialogState) {
</StyledScrollDescriptionContainer>
<SpacerSM />

<ModalFlexContainer>
<SessionButton
buttonType={SessionButtonType.Simple}
onClick={onClose}
dataTestId="session-confirm-ok-button"
>
{tr('okay')}
</SessionButton>
</ModalFlexContainer>
{!props.hideOkayButton ? (
<ModalFlexContainer>
<SessionButton
buttonType={SessionButtonType.Simple}
onClick={onClose}
dataTestId="session-confirm-ok-button"
>
{tr('okay')}
</SessionButton>
</ModalFlexContainer>
) : null}
<SpacerXS />
</SessionWrapperModal>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
import type { SettingsToggles } from 'react';
import { useCallback, type SettingsToggles } from 'react';
import { useDispatch } from 'react-redux';
import { PanelButtonTextWithSubText } from '../../../buttons/panel/PanelButton';
import { PanelToggleButton } from '../../../buttons/panel/PanelToggleButton';
import { type TrArgs } from '../../../../localization/localeTools';
import { showLocalizedPopupDialog } from '../../LocalizedPopupDialog';

export function SettingsToggleBasic({
active,
baseDataTestId,
onClick,
text,
subText,
}: {
type UnavailableProps = {
unavailable: boolean;
modalReasonTitle: TrArgs;
modalReasonDescription: TrArgs;
};

type SettingsToggleBasicProps = {
text: TrArgs;
subText: TrArgs;
baseDataTestId: SettingsToggles;
active: boolean;
unavailableProps?: UnavailableProps;
onClick: () => Promise<void>;
}) {
};

export function SettingsToggleBasic({
text,
subText,
baseDataTestId,
active,
onClick,
unavailableProps,
}: SettingsToggleBasicProps) {
const dispatch = useDispatch();

const handleClick = useCallback(async () => {
if (!unavailableProps?.unavailable) {
return onClick();
}
return showLocalizedPopupDialog(
{
title: unavailableProps?.modalReasonTitle,
description: unavailableProps?.modalReasonDescription,
hideOkayButton: true,
},
dispatch
);
}, [unavailableProps, dispatch, onClick]);

return (
<PanelToggleButton
textElement={
Expand All @@ -27,7 +55,7 @@ export function SettingsToggleBasic({
/>
}
active={active}
onClick={onClick}
onClick={handleClick}
toggleDataTestId={`${baseDataTestId}-settings-toggle`}
rowDataTestId={`${baseDataTestId}-settings-row`}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ import { SettingsKey } from '../../../../data/settings-key';
import { ToastUtils } from '../../../../session/utils';
import { PanelRadioButton } from '../../../buttons/panel/PanelRadioButton';
import { useHasEnterSendEnabled } from '../../../../state/selectors/settings';
import { isLinux } from '../../../../OS';

async function toggleStartInTray() {
try {
const newValue = !(await window.getStartInTray());

// make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false
await window.setSettingValue(SettingsKey.settingsStartInTray, newValue);
await window.setStartInTray(newValue);
if (!newValue) {
ToastUtils.pushRestartNeeded();
Expand All @@ -38,6 +37,16 @@ async function toggleStartInTray() {
}
}

async function toggleAutoStart() {
try {
const newValue = !(await window.getAutoStartEnabled());

await window.setAutoStartEnabled(newValue);
} catch (e) {
window.log.warn('auto start change error:', e);
}
}

function SendWithShiftEnter() {
const initialSetting = useHasEnterSendEnabled();
const selectedWithSettingTrue = 'enterForNewLine';
Expand Down Expand Up @@ -100,6 +109,11 @@ export function PreferencesSettingsPage(modalState: UserSettingsModalState) {
const closeAction = useUserSettingsCloseAction(modalState);
const title = useUserSettingsTitle(modalState);
const isStartInTrayActive = Boolean(window.getSettingValue(SettingsKey.settingsStartInTray));

const platformIsLinux = isLinux();
const isAutoStartActive = platformIsLinux
? false
: Boolean(window.getSettingValue(SettingsKey.settingsAutoStart));
const forceUpdate = useUpdate();

return (
Expand Down Expand Up @@ -144,6 +158,24 @@ export function PreferencesSettingsPage(modalState: UserSettingsModalState) {
active={isStartInTrayActive}
/>
</PanelButtonGroup>
<PanelLabelWithDescription title={{ token: 'settingsStartCategoryDesktop' }} />
<PanelButtonGroup>
<SettingsToggleBasic
baseDataTestId="auto-start"
text={{ token: 'launchOnStartDesktop' }}
subText={{ token: 'launchOnStartDescriptionDesktop' }}
onClick={async () => {
await toggleAutoStart();
forceUpdate();
}}
active={isAutoStartActive}
unavailableProps={{
unavailable: platformIsLinux,
modalReasonTitle: { token: 'settingsCannotChangeDesktop' },
modalReasonDescription: { token: 'launchOnStartupDisabledDesktop' },
}}
/>
</PanelButtonGroup>
<SendWithShiftEnter />
</SessionWrapperModal>
);
Expand Down
2 changes: 2 additions & 0 deletions ts/data/settings-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const settingsSpellCheck = 'spell-check';
const settingsLinkPreview = 'link-preview-setting';
const hasBlindedMsgRequestsEnabled = 'hasBlindedMsgRequestsEnabled';
const settingsStartInTray = 'start-in-tray-setting';
const settingsAutoStart = 'auto-start-setting';
const settingsOpengroupPruning = 'prune-setting';
const settingsNotification = 'notification-setting';
const settingsAudioNotification = 'audio-notification-setting';
Expand All @@ -31,6 +32,7 @@ export const SettingsKey = {
settingsSpellCheck,
settingsLinkPreview,
settingsStartInTray,
settingsAutoStart,
settingsOpengroupPruning,
hasBlindedMsgRequestsEnabled,
settingsNotification,
Expand Down
41 changes: 41 additions & 0 deletions ts/mains/main_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ import { initializeMainProcessLogger } from '../util/logger/main_process_logging
import * as log from '../util/logger/log';
import { DURATION } from '../session/constants';
import { tr } from '../localization/localeTools';
import { isMacOS, isWindows } from '../OS';

function prepareURL(pathSegments: Array<string>, moreKeys?: { theme: any }) {
const urlObject: url.UrlObject = {
Expand Down Expand Up @@ -1023,6 +1024,46 @@ ipc.on('get-start-in-tray', event => {
}
});

ipc.on('set-auto-start-enabled', (event, newValue) => {
try {
// Set the login item settings based on the platform
if (isMacOS()) {
// macOS
app.setLoginItemSettings({
openAtLogin: newValue,
openAsHidden: false,
});
} else if (isWindows()) {
// Windows - For Squirrel-based apps, we need to handle the stub launcher - https://www.electronjs.org/docs/latest/api/app/#appsetloginitemsettingssettings-macos-windows
const appFolder = path.dirname(process.execPath);
const ourExeName = path.basename(process.execPath);
const stubLauncher = path.resolve(appFolder, '..', ourExeName);

app.setLoginItemSettings({
openAtLogin: newValue,
path: stubLauncher,
args: [],
});
Comment on lines +1038 to +1046
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you've tested this right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, works on windows

} else {
throw new Error(`Unsupported platform for auto start: ${process.platform}`);
}

event.sender.send('set-auto-start-enabled-response', null);
} catch (e) {
event.sender.send('set-auto-start-enabled-response', e);
}
});

ipc.on('get-auto-start-enabled', event => {
try {
const loginSettings = app.getLoginItemSettings();
const isEnabled = loginSettings.openAtLogin;
event.sender.send('get-auto-start-enabled-response', isEnabled);
} catch (e) {
event.sender.send('get-auto-start-enabled-response', false);
}
});

ipcMain.on('update-badge-count', (_event, count) => {
if (app.isReady()) {
app.setBadgeCount(isNumber(count) && isFinite(count) && count >= 0 ? count : 0);
Expand Down
1 change: 1 addition & 0 deletions ts/react.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ declare module 'react' {
| 'conversation-trimming'
| 'auto-update'
| 'auto-dark-mode'
| 'auto-start'
| 'hide-menu-bar';

type SettingsRadio =
Expand Down
1 change: 1 addition & 0 deletions ts/state/ducks/modalDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export type OpenUrlModalState = { urlToOpen: string } | null;
export type LocalizedPopupDialogState = {
title: TrArgs;
description: TrArgs;
hideOkayButton?: boolean;
} | null;
export type SessionProInfoState = { variant: SessionProInfoVariant } | null;

Expand Down
2 changes: 2 additions & 0 deletions ts/window.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ declare global {
}) => Promise<void>;
setStartInTray: (val: boolean) => Promise<void>;
getStartInTray: () => Promise<boolean>;
setAutoStartEnabled: (val: boolean) => Promise<void>;
getAutoStartEnabled: () => Promise<boolean>;
getOpengroupPruning: () => Promise<boolean>;
setOpengroupPruning: (val: boolean) => Promise<void>;
closeAbout: () => void;
Expand Down
Loading