Use SessionSettingListItem to display linkedDevice

pull/725/head
Audric Ackermann 5 years ago
parent 805ccef7a1
commit 34458406fd

@ -1,38 +0,0 @@
import React from 'react';
import classNames from 'classnames';
import { SessionButton, SessionButtonColor } from '../SessionButton';
interface Props {
title: string;
description: string;
onClick: any;
}
export class SessionLinkedDeviceListItem extends React.Component<Props> {
public constructor(props: Props) {
super(props);
}
public render(): JSX.Element {
const { title, description, onClick } = this.props;
return (
<div className={classNames('session-settings-item', 'inline')} >
<div className="session-settings-item__info">
<div className="session-settings-item__title">{title}</div>
<div className="session-settings-item__description">
{description}
</div>
</div>
<div className="session-settings-item__content">
<SessionButton
text={window.i18n('unpairDevice')}
buttonColor={SessionButtonColor.Danger}
onClick={onClick}
/>
</div>
</div >
);
}
}

@ -11,7 +11,7 @@ import { SessionRadioGroup } from '../SessionRadioGroup';
interface Props { interface Props {
title: string; title: string;
description?: string; description?: string;
type: SessionSettingType; type: SessionSettingType | undefined;
value: any; value: any;
options?: Array<any>; options?: Array<any>;
onClick?: any; onClick?: any;
@ -40,7 +40,7 @@ export class SessionSettingListItem extends React.Component<Props, State> {
public render(): JSX.Element { public render(): JSX.Element {
const { title, description, type, value, content } = this.props; const { title, description, type, value, content } = this.props;
const inline = ![ const inline = !!type && ![
SessionSettingType.Options, SessionSettingType.Options,
SessionSettingType.Slider, SessionSettingType.Slider,
].includes(type); ].includes(type);

@ -3,7 +3,6 @@ import React from 'react';
import { SettingsHeader } from './SessionSettingsHeader'; import { SettingsHeader } from './SessionSettingsHeader';
import { SessionSettingListItem } from './SessionSettingListItem'; import { SessionSettingListItem } from './SessionSettingListItem';
import { SessionButtonColor } from '../SessionButton'; import { SessionButtonColor } from '../SessionButton';
import { SessionLinkedDeviceListItem } from './SessionLinkedDeviceListItem';
export enum SessionSettingCategory { export enum SessionSettingCategory {
General = 'general', General = 'general',
@ -30,6 +29,19 @@ interface State {
linkedPubKeys: Array<any>; linkedPubKeys: Array<any>;
} }
interface LocalSettingType {
category: SessionSettingCategory;
description: string | undefined;
comparisonValue: string | undefined;
id: any;
content: any | undefined;
hidden: any;
title: string;
type: SessionSettingType | undefined;
setFn: any;
onClick: any;
}
export class SettingsView extends React.Component<SettingsViewProps, State> { export class SettingsView extends React.Component<SettingsViewProps, State> {
public settingsViewRef: React.RefObject<HTMLDivElement>; public settingsViewRef: React.RefObject<HTMLDivElement>;
@ -48,30 +60,160 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
} }
public componentWillMount() { public componentWillMount() {
const ourPubKey = window.textsecure.storage.user.getNumber(); const { category } = this.props;
if (category === SessionSettingCategory.Devices) {
const ourPubKey = window.textsecure.storage.user.getNumber();
window.libloki.storage.getSecondaryDevicesFor(ourPubKey).then((pubKeys: any) => { window.libloki.storage.getSecondaryDevicesFor(ourPubKey).then((pubKeys: any) => {
this.setState({ this.setState({
linkedPubKeys: pubKeys, linkedPubKeys: pubKeys,
});
}); });
}); }
} }
/* tslint:disable-next-line:max-func-body-length */ /* tslint:disable-next-line:max-func-body-length */
public renderSettingInCategory(): JSX.Element { public renderSettingInCategory(): JSX.Element {
const { category } = this.props; const { category } = this.props;
let settings: Array<LocalSettingType>;
if (category === SessionSettingCategory.Devices) { if (category === SessionSettingCategory.Devices) {
// special case for linked devices // special case for linked devices
settings = this.getLinkedDeviceSettings();
} else {
// Grab initial values from database on startup
// ID corresponds to installGetter parameters in preload.js
// They are NOT arbitrary; add with caution
settings = this.getLocalSettings();
}
return (
<>
{this.state.hasPassword !== null &&
settings.map(setting => {
const { category } = this.props;
const content = setting.content || undefined;
const shouldRenderSettings = setting.category === category;
const description = setting.description || '';
const comparisonValue = setting.comparisonValue || null;
const value =
window.getSettingValue(setting.id, comparisonValue) ||
setting.content && setting.content.defaultValue;
const sliderFn =
setting.type === SessionSettingType.Slider
? (settingValue: any) =>
window.setSettingValue(setting.id, settingValue)
: () => null;
const onClickFn =
setting.onClick ||
(() => {
this.updateSetting(setting);
});
return (
<div key={setting.id}>
{shouldRenderSettings &&
!setting.hidden && (
<SessionSettingListItem
title={setting.title}
description={description}
type={setting.type}
value={value}
onClick={onClickFn}
onSliderChange={sliderFn}
content={content}
/>
)}
</div>
);
})}
</>
);
}
public render() {
const { category } = this.props;
return (
<div className="session-settings">
<SettingsHeader category={category} />
<div ref={this.settingsViewRef} className="session-settings-list">
{this.renderSettingInCategory()}
</div>
</div>
);
}
public setOptionsSetting(settingID: string) {
const selectedValue = $(`#${settingID} .session-radio input:checked`).val();
window.setSettingValue(settingID, selectedValue);
}
public hasPassword() {
const hashPromise = window.Signal.Data.getPasswordHash();
hashPromise.then((hash: any) => {
this.setState({
hasPassword: !!hash,
});
});
}
public updateSetting(item: any) {
// If there's a custom afterClick function,
// execute it instead of automatically updating settings
if (item.setFn) {
item.setFn();
} else {
if (item.type === SessionSettingType.Toggle) {
// If no custom afterClick function given, alter values in storage here
// Switch to opposite state
const newValue = ! window.getSettingValue(item.id);
window.setSettingValue(item.id, newValue);
}
}
}
public onPasswordUpdated(action: string) {
if (action === 'set') {
this.setState({
hasPassword: true,
});
}
return this.renderLinkedDevicesCategory(); if (action === 'remove') {
this.setState({
hasPassword: false,
});
}
}
private getPubkeyName(pubKey: string | null) {
if (!pubKey) {
return {};
} }
const secretWords = window.mnemonic.pubkey_to_secret_words(pubKey);
const conv = window.ConversationController.get(pubKey);
const deviceAlias = conv ? conv.getNickname() : 'Unnamed Device';
return { deviceAlias, secretWords };
}
// tslint:disable-next-line: max-func-body-length
private getLocalSettings() : Array<LocalSettingType> {
const { Settings } = window.Signal.Types; const { Settings } = window.Signal.Types;
// Grab initial values from database on startup return [
// ID corresponds to instalGetter parameters in preload.js
// They are NOT arbitrary; add with caution
const localSettings = [
{ {
id: 'theme-setting', id: 'theme-setting',
title: window.i18n('themeToggleTitle'), title: window.i18n('themeToggleTitle'),
@ -81,7 +223,8 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Toggle, type: SessionSettingType.Toggle,
category: SessionSettingCategory.General, category: SessionSettingCategory.General,
setFn: window.toggleTheme, setFn: window.toggleTheme,
content: {}, content: undefined,
onClick: undefined,
}, },
{ {
id: 'hide-menu-bar', id: 'hide-menu-bar',
@ -91,7 +234,9 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Toggle, type: SessionSettingType.Toggle,
category: SessionSettingCategory.General, category: SessionSettingCategory.General,
setFn: window.toggleMenuBar, setFn: window.toggleMenuBar,
content: {}, content: undefined,
comparisonValue: undefined,
onClick: undefined,
}, },
{ {
id: 'spell-check', id: 'spell-check',
@ -101,7 +246,9 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Toggle, type: SessionSettingType.Toggle,
category: SessionSettingCategory.General, category: SessionSettingCategory.General,
setFn: window.toggleSpellCheck, setFn: window.toggleSpellCheck,
content: {}, content: undefined,
comparisonValue: undefined,
onClick: undefined,
}, },
{ {
id: 'link-preview-setting', id: 'link-preview-setting',
@ -111,13 +258,19 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Toggle, type: SessionSettingType.Toggle,
category: SessionSettingCategory.General, category: SessionSettingCategory.General,
setFn: window.toggleLinkPreview, setFn: window.toggleLinkPreview,
content: {}, content: undefined,
comparisonValue: undefined,
onClick: undefined,
}, },
{ {
id: 'notification-setting', id: 'notification-setting',
title: window.i18n('notificationSettingsDialog'), title: window.i18n('notificationSettingsDialog'),
type: SessionSettingType.Options, type: SessionSettingType.Options,
category: SessionSettingCategory.Notifications, category: SessionSettingCategory.Notifications,
comparisonValue: undefined,
description: undefined,
hidden: undefined,
onClick: undefined,
setFn: () => { setFn: () => {
this.setOptionsSetting('notification-setting'); this.setOptionsSetting('notification-setting');
}, },
@ -154,7 +307,9 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Toggle, type: SessionSettingType.Toggle,
category: SessionSettingCategory.Permissions, category: SessionSettingCategory.Permissions,
setFn: window.toggleMediaPermissions, setFn: window.toggleMediaPermissions,
content: {}, content: undefined,
comparisonValue: undefined,
onClick: undefined,
}, },
{ {
id: 'message-ttl', id: 'message-ttl',
@ -164,6 +319,8 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Slider, type: SessionSettingType.Slider,
category: SessionSettingCategory.Privacy, category: SessionSettingCategory.Privacy,
setFn: undefined, setFn: undefined,
comparisonValue: undefined,
onClick: undefined,
content: { content: {
defaultValue: 24, defaultValue: 24,
}, },
@ -176,6 +333,7 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Button, type: SessionSettingType.Button,
category: SessionSettingCategory.Privacy, category: SessionSettingCategory.Privacy,
setFn: undefined, setFn: undefined,
comparisonValue: undefined,
content: { content: {
buttonText: window.i18n('setPassword'), buttonText: window.i18n('setPassword'),
buttonColor: SessionButtonColor.Primary, buttonColor: SessionButtonColor.Primary,
@ -194,6 +352,7 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Button, type: SessionSettingType.Button,
category: SessionSettingCategory.Privacy, category: SessionSettingCategory.Privacy,
setFn: undefined, setFn: undefined,
comparisonValue: undefined,
content: { content: {
buttonText: window.i18n('changePassword'), buttonText: window.i18n('changePassword'),
buttonColor: SessionButtonColor.Primary, buttonColor: SessionButtonColor.Primary,
@ -212,6 +371,7 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Button, type: SessionSettingType.Button,
category: SessionSettingCategory.Privacy, category: SessionSettingCategory.Privacy,
setFn: undefined, setFn: undefined,
comparisonValue: undefined,
content: { content: {
buttonText: window.i18n('removePassword'), buttonText: window.i18n('removePassword'),
buttonColor: SessionButtonColor.Danger, buttonColor: SessionButtonColor.Danger,
@ -223,158 +383,79 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
}), }),
}, },
]; ];
return (
<>
{this.state.hasPassword !== null &&
localSettings.map(setting => {
const { category } = this.props;
const content = setting.content || undefined;
const shouldRenderSettings = setting.category === category;
const description = setting.description || '';
const comparisonValue = setting.comparisonValue || null;
const value =
window.getSettingValue(setting.id, comparisonValue) ||
setting.content.defaultValue;
const sliderFn =
setting.type === SessionSettingType.Slider
? (settingValue: any) =>
window.setSettingValue(setting.id, settingValue)
: () => null;
const onClickFn =
setting.onClick ||
(() => {
this.updateSetting(setting);
});
return (
<div key={setting.id}>
{shouldRenderSettings &&
!setting.hidden && (
<SessionSettingListItem
title={setting.title}
description={description}
type={setting.type}
value={value}
onClick={onClickFn}
onSliderChange={sliderFn}
content={content}
/>
)}
</div>
);
})}
</>
);
}
public hasPassword() {
const hashPromise = window.Signal.Data.getPasswordHash();
hashPromise.then((hash: any) => {
this.setState({
hasPassword: !!hash,
});
});
}
public render() {
const { category } = this.props;
return (
<div className="session-settings">
<SettingsHeader category={category} />
<div ref={this.settingsViewRef} className="session-settings-list">
{this.renderSettingInCategory()}
</div>
</div>
);
}
public updateSetting(item: any) {
// If there's a custom afterClick function,
// execute it instead of automatically updating settings
if (item.setFn) {
item.setFn();
} else {
if (item.type === SessionSettingType.Toggle) {
// If no custom afterClick function given, alter values in storage here
// Switch to opposite state
const newValue = ! window.getSettingValue(item.id);
window.setSettingValue(item.id, newValue);
}
}
}
public setOptionsSetting(settingID: string) {
const selectedValue = $(`#${settingID} .session-radio input:checked`).val();
window.setSettingValue(settingID, selectedValue);
}
public onPasswordUpdated(action: string) {
if (action === 'set') {
this.setState({
hasPassword: true,
});
}
if (action === 'remove') {
this.setState({
hasPassword: false,
});
}
}
private getPubkeyName(pubKey: string | null) {
if (!pubKey) {
return {};
}
const secretWords = window.mnemonic.pubkey_to_secret_words(pubKey);
const conv = window.ConversationController.get(pubKey);
const deviceAlias = conv ? conv.getNickname() : 'Unnamed Device';
return { deviceAlias, secretWords };
} }
private renderLinkedDevicesCategory(): JSX.Element { private getLinkedDeviceSettings() : Array<LocalSettingType> {
const { linkedPubKeys } = this.state; const { linkedPubKeys } = this.state;
/*const li = $('<li>').html(name);
if (window.lokiFeatureFlags.multiDeviceUnpairing) {
const link = $('<a>')
.text('Unpair')
.attr('href', '#');
link.on('click', () => this.requestUnpairDevice(x));
li.append(' - ');
li.append(link);
}*/
if (linkedPubKeys && linkedPubKeys.length > 0) { if (linkedPubKeys && linkedPubKeys.length > 0) {
//this.$('#startPairing').attr('disabled', true); return linkedPubKeys.map((pubkey: any) => {
const items = linkedPubKeys.map((pubkey: any) => {
const { deviceAlias, secretWords } = this.getPubkeyName(pubkey); const { deviceAlias, secretWords } = this.getPubkeyName(pubkey);
const description = `${secretWords} ${window.shortenPubkey(pubkey)}`; const description = `${secretWords} ${window.shortenPubkey(pubkey)}`;
return ( return {
<SessionLinkedDeviceListItem onClick={() => {}} title={deviceAlias} key={pubkey} description={description} /> id: pubkey,
); title: deviceAlias,
description: description,
type: SessionSettingType.Button,
category: SessionSettingCategory.Devices,
content: {
buttonColor: SessionButtonColor.Danger,
buttonText: window.i18n('unpairDevice'),
},
comparisonValue: undefined,
onClick: undefined,
setFn: undefined,
hidden: undefined,
};
}); });
return (
<div>
{items}
</div>);
} else { } else {
//this.$('#startPairing').removeAttr('disabled'); return [{
//this.$('#pairedPubKeys').append('<li>No paired devices</li>'); id: 'no-linked-device',
title: window.i18n('noPairedDevices'),
return (<li>No paired devices</li>); type: undefined,
description: '',
category: SessionSettingCategory.Devices,
content: {},
comparisonValue: undefined,
setFn: undefined,
hidden: undefined,
onClick: undefined,
}];
} }
} }
} }
//
// /*const li = $('<li>').html(name);
// if (window.lokiFeatureFlags.multiDeviceUnpairing) {
// const link = $('<a>')
// .text('Unpair')
// .attr('href', '#');
// link.on('click', () => this.requestUnpairDevice(x));
// li.append(' - ');
// li.append(link);
// }*/
// if (linkedPubKeys && linkedPubKeys.length > 0) {
// //this.$('#startPairing').attr('disabled', true);
// const items = linkedPubKeys.map((pubkey: any) => {
// const { deviceAlias, secretWords } = this.getPubkeyName(pubkey);
// const description = `${secretWords} ${window.shortenPubkey(pubkey)}`;
// return (
// <SessionLinkedDeviceListItem onClick={() => {}} title={deviceAlias} key={pubkey} description={description} />
// );
// });
// return (
// <div>
// {items}
// </div>);
// } else {
// //this.$('#startPairing').removeAttr('disabled');
// //this.$('#pairedPubKeys').append('<li>No paired devices</li>');
// return (<li>No paired devices</li>);
// }

Loading…
Cancel
Save