476 lines
14 KiB
JavaScript
476 lines
14 KiB
JavaScript
// Copyright 2016-2021 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
/* global i18n: false */
|
|
/* global Whisper: false */
|
|
/* global $: false */
|
|
|
|
/* eslint-disable no-new */
|
|
|
|
// eslint-disable-next-line func-names
|
|
(function () {
|
|
window.Whisper = window.Whisper || {};
|
|
const { Settings } = window.Signal.Types;
|
|
|
|
const {
|
|
DEFAULT_DURATIONS_IN_SECONDS,
|
|
DEFAULT_DURATIONS_SET,
|
|
format: formatExpirationTimer,
|
|
} = window.Signal.Util.expirationTimer;
|
|
|
|
const CheckboxView = Whisper.View.extend({
|
|
initialize(options) {
|
|
this.name = options.name;
|
|
this.setFn = options.setFn;
|
|
this.value = options.value;
|
|
this.populate();
|
|
},
|
|
events: {
|
|
change: 'change',
|
|
},
|
|
change(e) {
|
|
const value = e.target.checked;
|
|
this.setFn(value);
|
|
window.log.info(this.name, 'changed to', value);
|
|
},
|
|
populate() {
|
|
this.$('input').prop('checked', !!this.value);
|
|
},
|
|
});
|
|
|
|
const MediaPermissionsSettingView = Whisper.View.extend({
|
|
initialize(options) {
|
|
this.value = options.value;
|
|
this.setFn = options.setFn;
|
|
this.populate();
|
|
},
|
|
events: {
|
|
change: 'change',
|
|
},
|
|
change(e) {
|
|
this.value = e.target.checked;
|
|
this.setFn(this.value);
|
|
window.log.info('media-permissions changed to', this.value);
|
|
},
|
|
populate() {
|
|
this.$('input').prop('checked', Boolean(this.value));
|
|
},
|
|
});
|
|
|
|
const MediaCameraPermissionsSettingView = Whisper.View.extend({
|
|
initialize(options) {
|
|
this.value = options.value;
|
|
this.setFn = options.setFn;
|
|
this.populate();
|
|
},
|
|
events: {
|
|
change: 'change',
|
|
},
|
|
change(e) {
|
|
this.value = e.target.checked;
|
|
this.setFn(this.value);
|
|
window.log.info('media-camera-permissions changed to', this.value);
|
|
},
|
|
populate() {
|
|
this.$('input').prop('checked', Boolean(this.value));
|
|
},
|
|
});
|
|
|
|
const DisappearingMessagesView = Whisper.View.extend({
|
|
template: () => $('#disappearingMessagesSettings').html(),
|
|
initialize(options) {
|
|
this.timeDialog = null;
|
|
|
|
this.value = options.value || 0;
|
|
|
|
this.render();
|
|
},
|
|
|
|
render_attributes() {
|
|
const isCustomValue = this.isCustomValue();
|
|
|
|
return {
|
|
title: i18n('disappearingMessages'),
|
|
timerValues: DEFAULT_DURATIONS_IN_SECONDS.map(seconds => {
|
|
const text = formatExpirationTimer(i18n, seconds, {
|
|
capitalizeOff: true,
|
|
});
|
|
return {
|
|
selected: seconds === this.value ? 'selected' : undefined,
|
|
value: seconds,
|
|
text,
|
|
};
|
|
}),
|
|
customSelected: isCustomValue ? 'selected' : undefined,
|
|
customText: i18n(
|
|
isCustomValue
|
|
? 'selectedCustomDisappearingTimeOption'
|
|
: 'customDisappearingTimeOption'
|
|
),
|
|
customInfo: isCustomValue
|
|
? {
|
|
text: formatExpirationTimer(i18n, this.value),
|
|
}
|
|
: undefined,
|
|
timerLabel: i18n('settings__DisappearingMessages__timer__label'),
|
|
footer: i18n('settings__DisappearingMessages__footer'),
|
|
};
|
|
},
|
|
|
|
events: {
|
|
change: 'change',
|
|
},
|
|
|
|
change(e) {
|
|
const value = parseInt(e.target.value, 10);
|
|
|
|
if (value === -1) {
|
|
this.showDialog();
|
|
return;
|
|
}
|
|
|
|
this.updateValue(value);
|
|
window.log.info('disappearing-messages-timer changed to', this.value);
|
|
},
|
|
|
|
isCustomValue() {
|
|
return this.value && !DEFAULT_DURATIONS_SET.has(this.value);
|
|
},
|
|
|
|
showDialog() {
|
|
this.closeDialog();
|
|
|
|
this.timeDialog = new window.Whisper.ReactWrapperView({
|
|
className: 'disappearing-time-dialog-wrapper',
|
|
Component: window.Signal.Components.DisappearingTimeDialog,
|
|
props: {
|
|
i18n,
|
|
initialValue: this.value,
|
|
onSubmit: newValue => {
|
|
this.updateValue(newValue);
|
|
this.closeDialog();
|
|
|
|
window.log.info(
|
|
'disappearing-messages-timer changed to custom value',
|
|
this.value
|
|
);
|
|
},
|
|
onClose: () => {
|
|
this.closeDialog();
|
|
},
|
|
},
|
|
});
|
|
},
|
|
|
|
closeDialog() {
|
|
if (this.timeDialog) {
|
|
this.timeDialog.remove();
|
|
}
|
|
this.timeDialog = null;
|
|
},
|
|
|
|
updateValue(newValue) {
|
|
this.value = newValue;
|
|
window.setUniversalExpireTimer(newValue);
|
|
this.render();
|
|
},
|
|
});
|
|
|
|
const RadioButtonGroupView = Whisper.View.extend({
|
|
initialize(options) {
|
|
this.name = options.name;
|
|
this.setFn = options.setFn;
|
|
this.value = options.value;
|
|
this.populate();
|
|
},
|
|
events: {
|
|
change: 'change',
|
|
},
|
|
change(e) {
|
|
const value = this.$(e.target).val();
|
|
this.setFn(value);
|
|
window.log.info(this.name, 'changed to', value);
|
|
},
|
|
populate() {
|
|
this.$(`#${this.name}-${this.value}`).attr('checked', 'checked');
|
|
},
|
|
});
|
|
Whisper.SettingsView = Whisper.View.extend({
|
|
className: 'settings modal expand',
|
|
template: () => $('#settings').html(),
|
|
initialize() {
|
|
this.render();
|
|
new RadioButtonGroupView({
|
|
el: this.$('.notification-settings'),
|
|
name: 'notification-setting',
|
|
value: window.initialData.notificationSetting,
|
|
setFn: window.setNotificationSetting,
|
|
});
|
|
new RadioButtonGroupView({
|
|
el: this.$('.theme-settings'),
|
|
name: 'theme-setting',
|
|
value: window.initialData.themeSetting,
|
|
setFn: theme => {
|
|
$(document.body)
|
|
.removeClass('dark-theme')
|
|
.removeClass('light-theme')
|
|
.addClass(
|
|
`${theme === 'system' ? window.systemTheme : theme}-theme`
|
|
);
|
|
window.setThemeSetting(theme);
|
|
},
|
|
});
|
|
if (Settings.isDrawAttentionSupported()) {
|
|
new CheckboxView({
|
|
el: this.$('.draw-attention-setting'),
|
|
name: 'draw-attention-setting',
|
|
value: window.initialData.notificationDrawAttention,
|
|
setFn: window.setNotificationDrawAttention,
|
|
});
|
|
}
|
|
if (Settings.isAudioNotificationSupported()) {
|
|
new CheckboxView({
|
|
el: this.$('.audio-notification-setting'),
|
|
name: 'audio-notification-setting',
|
|
value: window.initialData.audioNotification,
|
|
setFn: window.setAudioNotification,
|
|
});
|
|
}
|
|
new CheckboxView({
|
|
el: this.$('.badge-count-muted-conversations-setting'),
|
|
name: 'badge-count-muted-conversations-setting',
|
|
value: window.initialData.countMutedConversations,
|
|
setFn: window.setCountMutedConversations,
|
|
});
|
|
new CheckboxView({
|
|
el: this.$('.spell-check-setting'),
|
|
name: 'spell-check-setting',
|
|
value: window.initialData.spellCheck,
|
|
setFn: val => {
|
|
const $msg = this.$('.spell-check-setting-message');
|
|
if (val !== window.appStartInitialSpellcheckSetting) {
|
|
$msg.show();
|
|
$msg.attr('aria-hidden', false);
|
|
} else {
|
|
$msg.hide();
|
|
$msg.attr('aria-hidden', true);
|
|
}
|
|
window.setSpellCheck(val);
|
|
},
|
|
});
|
|
if (Settings.isAutoLaunchSupported()) {
|
|
new CheckboxView({
|
|
el: this.$('.auto-launch-setting'),
|
|
name: 'auto-launch-setting',
|
|
value: window.initialData.autoLaunch,
|
|
setFn: window.setAutoLaunch,
|
|
});
|
|
}
|
|
if (Settings.isHideMenuBarSupported()) {
|
|
new CheckboxView({
|
|
el: this.$('.menu-bar-setting'),
|
|
name: 'menu-bar-setting',
|
|
value: window.initialData.hideMenuBar,
|
|
setFn: window.setHideMenuBar,
|
|
});
|
|
}
|
|
new window.Whisper.ReactWrapperView({
|
|
el: this.$('.system-tray-setting-container'),
|
|
Component: window.Signal.Components.SystemTraySettingsCheckboxes,
|
|
props: {
|
|
i18n,
|
|
initialValue: window.initialData.systemTray,
|
|
isSystemTraySupported: Settings.isSystemTraySupported(
|
|
window.getVersion()
|
|
),
|
|
onChange: window.setSystemTraySetting,
|
|
},
|
|
});
|
|
new CheckboxView({
|
|
el: this.$('.always-relay-calls-setting'),
|
|
name: 'always-relay-calls-setting',
|
|
value: window.initialData.alwaysRelayCalls,
|
|
setFn: window.setAlwaysRelayCalls,
|
|
});
|
|
new CheckboxView({
|
|
el: this.$('.call-ringtone-notification-setting'),
|
|
name: 'call-ringtone-notification-setting',
|
|
value: window.initialData.callRingtoneNotification,
|
|
setFn: window.setCallRingtoneNotification,
|
|
});
|
|
new CheckboxView({
|
|
el: this.$('.call-system-notification-setting'),
|
|
name: 'call-system-notification-setting',
|
|
value: window.initialData.callSystemNotification,
|
|
setFn: window.setCallSystemNotification,
|
|
});
|
|
new CheckboxView({
|
|
el: this.$('.incoming-call-notification-setting'),
|
|
name: 'incoming-call-notification-setting',
|
|
value: window.initialData.incomingCallNotification,
|
|
setFn: window.setIncomingCallNotification,
|
|
});
|
|
new MediaPermissionsSettingView({
|
|
el: this.$('.media-permissions'),
|
|
value: window.initialData.mediaPermissions,
|
|
setFn: window.setMediaPermissions,
|
|
});
|
|
new MediaCameraPermissionsSettingView({
|
|
el: this.$('.media-camera-permissions'),
|
|
value: window.initialData.mediaCameraPermissions,
|
|
setFn: window.setMediaCameraPermissions,
|
|
});
|
|
|
|
const disappearingMessagesView = new DisappearingMessagesView({
|
|
value: window.initialData.universalExpireTimer,
|
|
name: 'disappearing-messages-setting',
|
|
});
|
|
this.$('.disappearing-messages-setting').append(
|
|
disappearingMessagesView.el
|
|
);
|
|
|
|
if (!window.initialData.isPrimary) {
|
|
const syncView = new SyncView().render();
|
|
this.$('.sync-setting').append(syncView.el);
|
|
}
|
|
},
|
|
events: {
|
|
'click .close': 'onClose',
|
|
'click .clear-data': 'onClearData',
|
|
},
|
|
render_attributes() {
|
|
const appStartSpellCheck = window.appStartInitialSpellcheckSetting;
|
|
const spellCheckDirty =
|
|
window.initialData.spellCheck !== appStartSpellCheck;
|
|
|
|
return {
|
|
deviceNameLabel: i18n('deviceName'),
|
|
deviceName: window.initialData.deviceName,
|
|
theme: i18n('theme'),
|
|
notifications: i18n('notifications'),
|
|
notificationSettingsDialog: i18n('notificationSettingsDialog'),
|
|
settings: i18n('Keyboard--preferences'),
|
|
disableNotifications: i18n('disableNotifications'),
|
|
nameAndMessage: i18n('nameAndMessage'),
|
|
noNameOrMessage: i18n('noNameOrMessage'),
|
|
nameOnly: i18n('nameOnly'),
|
|
notificationDrawAttention: i18n('notificationDrawAttention'),
|
|
audioNotificationDescription: i18n('audioNotificationDescription'),
|
|
isAudioNotificationSupported: Settings.isAudioNotificationSupported(),
|
|
isHideMenuBarSupported: Settings.isHideMenuBarSupported(),
|
|
isDrawAttentionSupported: Settings.isDrawAttentionSupported(),
|
|
isAutoLaunchSupported: Settings.isAutoLaunchSupported(),
|
|
hasSystemTheme: true,
|
|
themeLight: i18n('themeLight'),
|
|
themeDark: i18n('themeDark'),
|
|
themeSystem: i18n('themeSystem'),
|
|
hideMenuBar: i18n('hideMenuBar'),
|
|
clearDataHeader: i18n('clearDataHeader'),
|
|
clearDataButton: i18n('clearDataButton'),
|
|
clearDataExplanation: i18n('clearDataExplanation'),
|
|
calling: i18n('calling'),
|
|
countMutedConversationsDescription: i18n(
|
|
'countMutedConversationsDescription'
|
|
),
|
|
alwaysRelayCallsDescription: i18n('alwaysRelayCallsDescription'),
|
|
alwaysRelayCallsDetail: i18n('alwaysRelayCallsDetail'),
|
|
callRingtoneNotificationDescription: i18n(
|
|
'callRingtoneNotificationDescription'
|
|
),
|
|
callSystemNotificationDescription: i18n(
|
|
'callSystemNotificationDescription'
|
|
),
|
|
incomingCallNotificationDescription: i18n(
|
|
'incomingCallNotificationDescription'
|
|
),
|
|
permissions: i18n('permissions'),
|
|
mediaPermissionsDescription: i18n('mediaPermissionsDescription'),
|
|
mediaCameraPermissionsDescription: i18n(
|
|
'mediaCameraPermissionsDescription'
|
|
),
|
|
generalHeader: i18n('general'),
|
|
spellCheckDescription: i18n('spellCheckDescription'),
|
|
spellCheckHidden: spellCheckDirty ? 'false' : 'true',
|
|
spellCheckDisplay: spellCheckDirty ? 'inherit' : 'none',
|
|
spellCheckDirtyText: appStartSpellCheck
|
|
? i18n('spellCheckWillBeDisabled')
|
|
: i18n('spellCheckWillBeEnabled'),
|
|
autoLaunchDescription: i18n('autoLaunchDescription'),
|
|
};
|
|
},
|
|
onClose() {
|
|
window.closeSettings();
|
|
},
|
|
onClearData() {
|
|
window.deleteAllData();
|
|
window.closeSettings();
|
|
},
|
|
});
|
|
|
|
const SyncView = Whisper.View.extend({
|
|
template: () => $('#syncSettings').html(),
|
|
className: 'syncSettings',
|
|
events: {
|
|
'click .sync': 'sync',
|
|
},
|
|
initialize() {
|
|
this.lastSyncTime = window.initialData.lastSyncTime;
|
|
},
|
|
enable() {
|
|
this.$('.sync').text(i18n('syncNow'));
|
|
this.$('.sync').removeAttr('disabled');
|
|
},
|
|
disable() {
|
|
this.$('.sync').attr('disabled', 'disabled');
|
|
this.$('.sync').text(i18n('syncing'));
|
|
},
|
|
onsuccess() {
|
|
window.setLastSyncTime(Date.now());
|
|
this.lastSyncTime = Date.now();
|
|
window.log.info('sync successful');
|
|
this.enable();
|
|
this.render();
|
|
},
|
|
ontimeout() {
|
|
window.log.error('sync timed out');
|
|
this.$('.synced_at').hide();
|
|
this.$('.sync_failed').show();
|
|
this.enable();
|
|
},
|
|
async sync() {
|
|
this.$('.sync_failed').hide();
|
|
if (window.initialData.isPrimary) {
|
|
window.log.warn('Tried to sync from device 1');
|
|
return;
|
|
}
|
|
|
|
this.disable();
|
|
try {
|
|
await window.makeSyncRequest();
|
|
this.onsuccess();
|
|
} catch (error) {
|
|
window.log.error(
|
|
'settings sync timeout error:',
|
|
error && error.stack ? error.stack : error
|
|
);
|
|
this.ontimeout();
|
|
}
|
|
},
|
|
render_attributes() {
|
|
const attrs = {
|
|
sync: i18n('sync'),
|
|
syncNow: i18n('syncNow'),
|
|
syncExplanation: i18n('syncExplanation'),
|
|
syncFailed: i18n('syncFailed'),
|
|
};
|
|
let date = this.lastSyncTime;
|
|
if (date) {
|
|
date = new Date(date);
|
|
attrs.lastSynced = i18n('lastSynced');
|
|
attrs.syncDate = date.toLocaleDateString();
|
|
attrs.syncTime = date.toLocaleTimeString();
|
|
}
|
|
return attrs;
|
|
},
|
|
});
|
|
})();
|