From 34458406fda7b01a22181a5e01d73ec21df633e0 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 20 Jan 2020 11:08:16 +1100 Subject: [PATCH] Use SessionSettingListItem to display linkedDevice --- .../settings/SessionLinkedDeviceListItem.tsx | 38 -- .../settings/SessionSettingListItem.tsx | 4 +- .../session/settings/SessionSettings.tsx | 397 +++++++++++------- 3 files changed, 241 insertions(+), 198 deletions(-) delete mode 100644 ts/components/session/settings/SessionLinkedDeviceListItem.tsx diff --git a/ts/components/session/settings/SessionLinkedDeviceListItem.tsx b/ts/components/session/settings/SessionLinkedDeviceListItem.tsx deleted file mode 100644 index 2e818ce55..000000000 --- a/ts/components/session/settings/SessionLinkedDeviceListItem.tsx +++ /dev/null @@ -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 { - public constructor(props: Props) { - super(props); - } - - public render(): JSX.Element { - const { title, description, onClick } = this.props; - - return ( -
-
-
{title}
-
- {description} -
-
-
- -
-
- ); - } -} diff --git a/ts/components/session/settings/SessionSettingListItem.tsx b/ts/components/session/settings/SessionSettingListItem.tsx index 61df69626..a01361aad 100644 --- a/ts/components/session/settings/SessionSettingListItem.tsx +++ b/ts/components/session/settings/SessionSettingListItem.tsx @@ -11,7 +11,7 @@ import { SessionRadioGroup } from '../SessionRadioGroup'; interface Props { title: string; description?: string; - type: SessionSettingType; + type: SessionSettingType | undefined; value: any; options?: Array; onClick?: any; @@ -40,7 +40,7 @@ export class SessionSettingListItem extends React.Component { public render(): JSX.Element { const { title, description, type, value, content } = this.props; - const inline = ![ + const inline = !!type && ![ SessionSettingType.Options, SessionSettingType.Slider, ].includes(type); diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index 47bf849d4..8b39eba7c 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -3,7 +3,6 @@ import React from 'react'; import { SettingsHeader } from './SessionSettingsHeader'; import { SessionSettingListItem } from './SessionSettingListItem'; import { SessionButtonColor } from '../SessionButton'; -import { SessionLinkedDeviceListItem } from './SessionLinkedDeviceListItem'; export enum SessionSettingCategory { General = 'general', @@ -30,6 +29,19 @@ interface State { linkedPubKeys: Array; } +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 { public settingsViewRef: React.RefObject; @@ -48,30 +60,160 @@ export class SettingsView extends React.Component { } 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) => { - this.setState({ - linkedPubKeys: pubKeys, + window.libloki.storage.getSecondaryDevicesFor(ourPubKey).then((pubKeys: any) => { + this.setState({ + linkedPubKeys: pubKeys, + }); }); - }); + } } /* tslint:disable-next-line:max-func-body-length */ public renderSettingInCategory(): JSX.Element { const { category } = this.props; + + let settings: Array; + if (category === SessionSettingCategory.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 ( +
+ {shouldRenderSettings && + !setting.hidden && ( + + )} +
+ ); + })} + + ); + } + + + public render() { + const { category } = this.props; + + return ( +
+ +
+ {this.renderSettingInCategory()} +
+
+ ); + } + + + + 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 { const { Settings } = window.Signal.Types; - // Grab initial values from database on startup - // ID corresponds to instalGetter parameters in preload.js - // They are NOT arbitrary; add with caution - const localSettings = [ + return [ { id: 'theme-setting', title: window.i18n('themeToggleTitle'), @@ -81,7 +223,8 @@ export class SettingsView extends React.Component { type: SessionSettingType.Toggle, category: SessionSettingCategory.General, setFn: window.toggleTheme, - content: {}, + content: undefined, + onClick: undefined, }, { id: 'hide-menu-bar', @@ -91,7 +234,9 @@ export class SettingsView extends React.Component { type: SessionSettingType.Toggle, category: SessionSettingCategory.General, setFn: window.toggleMenuBar, - content: {}, + content: undefined, + comparisonValue: undefined, + onClick: undefined, }, { id: 'spell-check', @@ -101,7 +246,9 @@ export class SettingsView extends React.Component { type: SessionSettingType.Toggle, category: SessionSettingCategory.General, setFn: window.toggleSpellCheck, - content: {}, + content: undefined, + comparisonValue: undefined, + onClick: undefined, }, { id: 'link-preview-setting', @@ -111,13 +258,19 @@ export class SettingsView extends React.Component { type: SessionSettingType.Toggle, category: SessionSettingCategory.General, setFn: window.toggleLinkPreview, - content: {}, + content: undefined, + comparisonValue: undefined, + onClick: undefined, }, { id: 'notification-setting', title: window.i18n('notificationSettingsDialog'), type: SessionSettingType.Options, category: SessionSettingCategory.Notifications, + comparisonValue: undefined, + description: undefined, + hidden: undefined, + onClick: undefined, setFn: () => { this.setOptionsSetting('notification-setting'); }, @@ -154,7 +307,9 @@ export class SettingsView extends React.Component { type: SessionSettingType.Toggle, category: SessionSettingCategory.Permissions, setFn: window.toggleMediaPermissions, - content: {}, + content: undefined, + comparisonValue: undefined, + onClick: undefined, }, { id: 'message-ttl', @@ -164,6 +319,8 @@ export class SettingsView extends React.Component { type: SessionSettingType.Slider, category: SessionSettingCategory.Privacy, setFn: undefined, + comparisonValue: undefined, + onClick: undefined, content: { defaultValue: 24, }, @@ -176,6 +333,7 @@ export class SettingsView extends React.Component { type: SessionSettingType.Button, category: SessionSettingCategory.Privacy, setFn: undefined, + comparisonValue: undefined, content: { buttonText: window.i18n('setPassword'), buttonColor: SessionButtonColor.Primary, @@ -194,6 +352,7 @@ export class SettingsView extends React.Component { type: SessionSettingType.Button, category: SessionSettingCategory.Privacy, setFn: undefined, + comparisonValue: undefined, content: { buttonText: window.i18n('changePassword'), buttonColor: SessionButtonColor.Primary, @@ -212,6 +371,7 @@ export class SettingsView extends React.Component { type: SessionSettingType.Button, category: SessionSettingCategory.Privacy, setFn: undefined, + comparisonValue: undefined, content: { buttonText: window.i18n('removePassword'), buttonColor: SessionButtonColor.Danger, @@ -223,158 +383,79 @@ export class SettingsView extends React.Component { }), }, ]; - - 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 ( -
- {shouldRenderSettings && - !setting.hidden && ( - - )} -
- ); - })} - - ); - } - - public hasPassword() { - const hashPromise = window.Signal.Data.getPasswordHash(); - - hashPromise.then((hash: any) => { - this.setState({ - hasPassword: !!hash, - }); - }); - } - - public render() { - const { category } = this.props; - - return ( -
- -
- {this.renderSettingInCategory()} -
-
- ); - } - - 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 { const { linkedPubKeys } = this.state; - /*const li = $('
  • ').html(name); - if (window.lokiFeatureFlags.multiDeviceUnpairing) { - const link = $('') - .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) => { + return linkedPubKeys.map((pubkey: any) => { const { deviceAlias, secretWords } = this.getPubkeyName(pubkey); const description = `${secretWords} ${window.shortenPubkey(pubkey)}`; - return ( - {}} title={deviceAlias} key={pubkey} description={description} /> - ); + return { + 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 ( -
    - {items} -
    ); } else { - //this.$('#startPairing').removeAttr('disabled'); - //this.$('#pairedPubKeys').append('
  • No paired devices
  • '); - - return (
  • No paired devices
  • ); + return [{ + id: 'no-linked-device', + title: window.i18n('noPairedDevices'), + type: undefined, + description: '', + category: SessionSettingCategory.Devices, + content: {}, + comparisonValue: undefined, + setFn: undefined, + hidden: undefined, + onClick: undefined, + }]; } } } + + // + + // /*const li = $('
  • ').html(name); + // if (window.lokiFeatureFlags.multiDeviceUnpairing) { + // const link = $('') + // .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 ( + // {}} title={deviceAlias} key={pubkey} description={description} /> + // ); + // }); + + // return ( + //
    + // {items} + //
    ); + // } else { + // //this.$('#startPairing').removeAttr('disabled'); + // //this.$('#pairedPubKeys').append('
  • No paired devices
  • '); + + // return (
  • No paired devices
  • ); + // }