aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/settings
diff options
context:
space:
mode:
authorLibravatar Bennett <hello@vantezzen.io>2020-01-31 17:24:30 +0100
committerLibravatar GitHub <noreply@github.com>2020-01-31 17:24:30 +0100
commit9277d42ee8fd6d9e3eccf948f71c8688f726784e (patch)
tree6f167ea9eb2ed50a079596048993a79c7aeb9447 /src/components/settings
parentUpdate (diff)
parentFix lint (diff)
downloadferdium-app-9277d42ee8fd6d9e3eccf948f71c8688f726784e.tar.gz
ferdium-app-9277d42ee8fd6d9e3eccf948f71c8688f726784e.tar.zst
ferdium-app-9277d42ee8fd6d9e3eccf948f71c8688f726784e.zip
Merge branch 'develop' into start-in-tray
Diffstat (limited to 'src/components/settings')
-rw-r--r--src/components/settings/account/AccountDashboard.js316
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js4
-rw-r--r--src/components/settings/recipes/RecipesDashboard.js6
-rw-r--r--src/components/settings/settings/EditSettingsForm.js77
-rw-r--r--src/components/settings/team/TeamDashboard.js9
5 files changed, 259 insertions, 153 deletions
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 83dc34a52..7d6bad883 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -3,9 +3,7 @@ import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import { 6import { ProBadge, H1, H2 } from '@meetfranz/ui';
7 ProBadge, H1, H2,
8} from '@meetfranz/ui';
9import moment from 'moment'; 7import moment from 'moment';
10 8
11import Loader from '../../ui/Loader'; 9import Loader from '../../ui/Loader';
@@ -13,6 +11,7 @@ import Button from '../../ui/Button';
13import Infobox from '../../ui/Infobox'; 11import Infobox from '../../ui/Infobox';
14import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen'; 12import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen';
15import { i18nPlanName } from '../../../helpers/plan-helpers'; 13import { i18nPlanName } from '../../../helpers/plan-helpers';
14import { LOCAL_SERVER } from '../../../config';
16 15
17const messages = defineMessages({ 16const messages = defineMessages({
18 headline: { 17 headline: {
@@ -69,11 +68,13 @@ const messages = defineMessages({
69 }, 68 },
70 deleteInfo: { 69 deleteInfo: {
71 id: 'settings.account.deleteInfo', 70 id: 'settings.account.deleteInfo',
72 defaultMessage: '!!!If you don\'t need your Ferdi account any longer, you can delete your account and all related data here.', 71 defaultMessage:
72 "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.",
73 }, 73 },
74 deleteEmailSent: { 74 deleteEmailSent: {
75 id: 'settings.account.deleteEmailSent', 75 id: 'settings.account.deleteEmailSent',
76 defaultMessage: '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', 76 defaultMessage:
77 '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!',
77 }, 78 },
78 trial: { 79 trial: {
79 id: 'settings.account.trial', 80 id: 'settings.account.trial',
@@ -89,7 +90,16 @@ const messages = defineMessages({
89 }, 90 },
90 trialUpdateBillingInformation: { 91 trialUpdateBillingInformation: {
91 id: 'settings.account.trialUpdateBillingInfo', 92 id: 'settings.account.trialUpdateBillingInfo',
92 defaultMessage: '!!!Please update your billing info to continue using {license} after your trial period.', 93 defaultMessage:
94 '!!!Please update your billing info to continue using {license} after your trial period.',
95 },
96 accountUnavailable: {
97 id: 'settings.account.accountUnavailable',
98 defaultMessage: 'Account is unavailable',
99 },
100 accountUnavailableInfo: {
101 id: 'settings.account.accountUnavailableInfo',
102 defaultMessage: 'You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.',
93 }, 103 },
94}); 104});
95 105
@@ -110,6 +120,7 @@ class AccountDashboard extends Component {
110 upgradeToPro: PropTypes.func.isRequired, 120 upgradeToPro: PropTypes.func.isRequired,
111 openInvoices: PropTypes.func.isRequired, 121 openInvoices: PropTypes.func.isRequired,
112 onCloseSubscriptionWindow: PropTypes.func.isRequired, 122 onCloseSubscriptionWindow: PropTypes.func.isRequired,
123 server: PropTypes.string.isRequired,
113 }; 124 };
114 125
115 static contextTypes = { 126 static contextTypes = {
@@ -132,6 +143,7 @@ class AccountDashboard extends Component {
132 upgradeToPro, 143 upgradeToPro,
133 openInvoices, 144 openInvoices,
134 onCloseSubscriptionWindow, 145 onCloseSubscriptionWindow,
146 server,
135 } = this.props; 147 } = this.props;
136 const { intl } = this.context; 148 const { intl } = this.context;
137 149
@@ -141,6 +153,8 @@ class AccountDashboard extends Component {
141 planName = i18nPlanName(user.team.plan, intl); 153 planName = i18nPlanName(user.team.plan, intl);
142 } 154 }
143 155
156 const isUsingWithoutAccount = server === LOCAL_SERVER;
157
144 return ( 158 return (
145 <div className="settings__main"> 159 <div className="settings__main">
146 <div className="settings__header"> 160 <div className="settings__header">
@@ -149,154 +163,186 @@ class AccountDashboard extends Component {
149 </span> 163 </span>
150 </div> 164 </div>
151 <div className="settings__body"> 165 <div className="settings__body">
152 {isLoading && ( 166 {isUsingWithoutAccount && (
153 <Loader /> 167 <>
168 <h1 style={{ marginBottom: 0 }}>
169 {intl.formatMessage(messages.accountUnavailable)}
170 </h1>
171 <p
172 className="settings__message"
173 style={{
174 borderTop: 0,
175 marginTop: 0,
176 }}
177 >
178 {intl.formatMessage(messages.accountUnavailableInfo)}
179 </p>
180 </>
154 )} 181 )}
182 {!isUsingWithoutAccount && (
183 <>
184 {isLoading && <Loader />}
155 185
156 {!isLoading && userInfoRequestFailed && ( 186 {!isLoading && userInfoRequestFailed && (
157 <Infobox 187 <Infobox
158 icon="alert" 188 icon="alert"
159 type="danger" 189 type="danger"
160 ctaLabel={intl.formatMessage(messages.tryReloadUserInfoRequest)} 190 ctaLabel={intl.formatMessage(
161 ctaLoading={isLoading} 191 messages.tryReloadUserInfoRequest,
162 ctaOnClick={retryUserInfoRequest} 192 )}
163 > 193 ctaLoading={isLoading}
164 {intl.formatMessage(messages.userInfoRequestFailed)} 194 ctaOnClick={retryUserInfoRequest}
165 </Infobox> 195 >
166 )} 196 {intl.formatMessage(messages.userInfoRequestFailed)}
197 </Infobox>
198 )}
167 199
168 {!userInfoRequestFailed && ( 200 {!userInfoRequestFailed && (
169 <>
170 {!isLoading && (
171 <> 201 <>
172 <div className="account"> 202 {!isLoading && (
173 <div className="account__box account__box--flex"> 203 <>
174 <div className="account__avatar"> 204 <div className="account">
175 <img 205 <div className="account__box account__box--flex">
176 src="./assets/images/logo.svg" 206 <div className="account__avatar">
177 alt="" 207 <img src="./assets/images/logo.svg" alt="" />
178 /> 208 </div>
179 </div> 209 <div className="account__info">
180 <div className="account__info"> 210 <H1>
181 <H1> 211 <span className="username">{`${user.firstname} ${user.lastname}`}</span>
182 <span className="username">{`${user.firstname} ${user.lastname}`}</span> 212 {user.isPremium && (
183 {user.isPremium && ( 213 <>
184 <> 214 {' '}
185 {' '} 215 <ProBadge />
186 <ProBadge /> 216 </>
187 </> 217 )}
188 )} 218 </H1>
189 </H1> 219 <p>
190 <p> 220 {user.organization && `${user.organization}, `}
191 {user.organization && `${user.organization}, `} 221 {user.email}
192 {user.email} 222 </p>
193 </p> 223 {user.isPremium && (
194 {user.isPremium && ( 224 <div className="manage-user-links">
195 <div className="manage-user-links"> 225 <Button
226 label={intl.formatMessage(
227 messages.accountEditButton,
228 )}
229 className="franz-form__button--inverted"
230 onClick={openEditAccount}
231 />
232 </div>
233 )}
234 </div>
235 {!user.isPremium && (
196 <Button 236 <Button
197 label={intl.formatMessage(messages.accountEditButton)} 237 label={intl.formatMessage(
238 messages.accountEditButton,
239 )}
198 className="franz-form__button--inverted" 240 className="franz-form__button--inverted"
199 onClick={openEditAccount} 241 onClick={openEditAccount}
200 /> 242 />
201 </div>
202 )}
203 </div>
204 {!user.isPremium && (
205 <Button
206 label={intl.formatMessage(messages.accountEditButton)}
207 className="franz-form__button--inverted"
208 onClick={openEditAccount}
209 />
210 )}
211 </div>
212 </div>
213 {user.isPremium && user.isSubscriptionOwner && (
214 <div className="account">
215 <div className="account__box">
216 <H2>
217 {intl.formatMessage(messages.yourLicense)}
218 </H2>
219 <p>
220 Franz
221 {' '}
222 {isPremiumOverrideUser ? 'Premium' : planName}
223 {user.team.isTrial && (
224 <>
225 {' – '}
226 {intl.formatMessage(messages.trial)}
227 </>
228 )} 243 )}
229 </p> 244 </div>
230 {user.team.isTrial && ( 245 </div>
231 <> 246 {user.isPremium && user.isSubscriptionOwner && (
232 <br /> 247 <div className="account">
233 <p> 248 <div className="account__box">
234 {intl.formatMessage(messages.trialEndsIn, { 249 <H2>{intl.formatMessage(messages.yourLicense)}</H2>
235 duration: moment.duration(moment().diff(user.team.trialEnd)).humanize(),
236 })}
237 </p>
238 <p> 250 <p>
239 {intl.formatMessage(messages.trialUpdateBillingInformation, { 251 Franz
240 license: planName, 252 {' '}
241 })} 253 {isPremiumOverrideUser ? 'Premium' : planName}
254 {user.team.isTrial && (
255 <>
256 {' – '}
257 {intl.formatMessage(messages.trial)}
258 </>
259 )}
242 </p> 260 </p>
243 </> 261 {user.team.isTrial && (
244 )} 262 <>
245 {!isProUser && ( 263 <br />
246 <div className="manage-user-links"> 264 <p>
247 <Button 265 {intl.formatMessage(messages.trialEndsIn, {
248 label={intl.formatMessage(messages.upgradeAccountToPro)} 266 duration: moment
249 className="franz-form__button--primary" 267 .duration(
250 onClick={upgradeToPro} 268 moment().diff(user.team.trialEnd),
269 )
270 .humanize(),
271 })}
272 </p>
273 <p>
274 {intl.formatMessage(
275 messages.trialUpdateBillingInformation,
276 {
277 license: planName,
278 },
279 )}
280 </p>
281 </>
282 )}
283 {!isProUser && (
284 <div className="manage-user-links">
285 <Button
286 label={intl.formatMessage(
287 messages.upgradeAccountToPro,
288 )}
289 className="franz-form__button--primary"
290 onClick={upgradeToPro}
291 />
292 </div>
293 )}
294 <div className="manage-user-links">
295 <Button
296 label={intl.formatMessage(
297 messages.manageSubscriptionButtonLabel,
298 )}
299 className="franz-form__button--inverted"
300 onClick={openBilling}
301 />
302 <Button
303 label={intl.formatMessage(
304 messages.invoicesButton,
305 )}
306 className="franz-form__button--inverted"
307 onClick={openInvoices}
308 />
309 </div>
310 </div>
311 </div>
312 )}
313 {!user.isPremium && (
314 <div className="account franz-form">
315 <div className="account__box">
316 <SubscriptionForm
317 onCloseWindow={onCloseSubscriptionWindow}
251 /> 318 />
252 </div> 319 </div>
253 )} 320 </div>
254 <div className="manage-user-links"> 321 )}
255 <Button 322 </>
256 label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} 323 )}
257 className="franz-form__button--inverted" 324
258 onClick={openBilling} 325 <div className="account franz-form">
259 /> 326 <div className="account__box">
327 <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2>
328 {!isDeleteAccountSuccessful && (
329 <div className="account__subscription">
330 <p>{intl.formatMessage(messages.deleteInfo)}</p>
260 <Button 331 <Button
261 label={intl.formatMessage(messages.invoicesButton)} 332 label={intl.formatMessage(messages.deleteAccount)}
262 className="franz-form__button--inverted" 333 buttonType="danger"
263 onClick={openInvoices} 334 onClick={() => deleteAccount()}
335 loaded={!isLoadingDeleteAccount}
264 /> 336 />
265 </div> 337 </div>
266 </div> 338 )}
267 </div> 339 {isDeleteAccountSuccessful && (
268 )} 340 <p>{intl.formatMessage(messages.deleteEmailSent)}</p>
269 {!user.isPremium && ( 341 )}
270 <div className="account franz-form">
271 <div className="account__box">
272 <SubscriptionForm
273 onCloseWindow={onCloseSubscriptionWindow}
274 />
275 </div>
276 </div> 342 </div>
277 )} 343 </div>
278 </> 344 </>
279 )} 345 )}
280
281 <div className="account franz-form">
282 <div className="account__box">
283 <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2>
284 {!isDeleteAccountSuccessful && (
285 <div className="account__subscription">
286 <p>{intl.formatMessage(messages.deleteInfo)}</p>
287 <Button
288 label={intl.formatMessage(messages.deleteAccount)}
289 buttonType="danger"
290 onClick={() => deleteAccount()}
291 loaded={!isLoadingDeleteAccount}
292 />
293 </div>
294 )}
295 {isDeleteAccountSuccessful && (
296 <p>{intl.formatMessage(messages.deleteEmailSent)}</p>
297 )}
298 </div>
299 </div>
300 </> 346 </>
301 )} 347 )}
302 </div> 348 </div>
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 192cfde7a..eb3249fa0 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -119,6 +119,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
119 to="/settings/services" 119 to="/settings/services"
120 className="settings-navigation__link" 120 className="settings-navigation__link"
121 activeClassName="is-active" 121 activeClassName="is-active"
122 disabled={!isLoggedIn}
122 > 123 >
123 {intl.formatMessage(messages.yourServices)} 124 {intl.formatMessage(messages.yourServices)}
124 {' '} 125 {' '}
@@ -134,6 +135,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
134 to="/settings/workspaces" 135 to="/settings/workspaces"
135 className="settings-navigation__link" 136 className="settings-navigation__link"
136 activeClassName="is-active" 137 activeClassName="is-active"
138 disabled={!isLoggedIn}
137 > 139 >
138 {intl.formatMessage(messages.yourWorkspaces)} 140 {intl.formatMessage(messages.yourWorkspaces)}
139 {' '} 141 {' '}
@@ -148,6 +150,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
148 to="/settings/user" 150 to="/settings/user"
149 className="settings-navigation__link" 151 className="settings-navigation__link"
150 activeClassName="is-active" 152 activeClassName="is-active"
153 disabled={!isLoggedIn}
151 > 154 >
152 {intl.formatMessage(messages.account)} 155 {intl.formatMessage(messages.account)}
153 </Link> 156 </Link>
@@ -155,6 +158,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
155 to="/settings/team" 158 to="/settings/team"
156 className="settings-navigation__link" 159 className="settings-navigation__link"
157 activeClassName="is-active" 160 activeClassName="is-active"
161 disabled={!isLoggedIn}
158 > 162 >
159 {intl.formatMessage(messages.team)} 163 {intl.formatMessage(messages.team)}
160 {!user.data.isPremium && ( 164 {!user.data.isPremium && (
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js
index 877cbc588..d08e6cbc2 100644
--- a/src/components/settings/recipes/RecipesDashboard.js
+++ b/src/components/settings/recipes/RecipesDashboard.js
@@ -153,6 +153,8 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
153 const communityRecipes = recipes.filter(r => !r.isDevRecipe); 153 const communityRecipes = recipes.filter(r => !r.isDevRecipe);
154 const devRecipes = recipes.filter(r => r.isDevRecipe); 154 const devRecipes = recipes.filter(r => r.isDevRecipe);
155 155
156 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
157
156 return ( 158 return (
157 <div className="settings__main"> 159 <div className="settings__main">
158 <div className="settings__header"> 160 <div className="settings__header">
@@ -265,7 +267,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
265 <RecipeItem 267 <RecipeItem
266 key={recipe.id} 268 key={recipe.id}
267 recipe={recipe} 269 recipe={recipe}
268 onClick={() => showAddServiceInterface({ recipeId: recipe.id })} 270 onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })}
269 /> 271 />
270 ))} 272 ))}
271 </div> 273 </div>
@@ -278,7 +280,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
278 <RecipeItem 280 <RecipeItem
279 key={recipe.id} 281 key={recipe.id}
280 recipe={recipe} 282 recipe={recipe}
281 onClick={() => showAddServiceInterface({ recipeId: recipe.id })} 283 onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })}
282 /> 284 />
283 ))} 285 ))}
284 </div> 286 </div>
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 0badd3b98..efb6eaa18 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -36,6 +36,10 @@ const messages = defineMessages({
36 id: 'settings.app.hibernateInfo', 36 id: 'settings.app.hibernateInfo',
37 defaultMessage: '!!!By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.', 37 defaultMessage: '!!!By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.',
38 }, 38 },
39 inactivityLockInfo: {
40 id: 'settings.app.inactivityLockInfo',
41 defaultMessage: '!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable',
42 },
39 serverInfo: { 43 serverInfo: {
40 id: 'settings.app.serverInfo', 44 id: 'settings.app.serverInfo',
41 defaultMessage: '!!!We advice you to logout after changing your server as your settings might not be saved otherwise.', 45 defaultMessage: '!!!We advice you to logout after changing your server as your settings might not be saved otherwise.',
@@ -50,7 +54,7 @@ const messages = defineMessages({
50 }, 54 },
51 lockedPassword: { 55 lockedPassword: {
52 id: 'settings.app.lockedPassword', 56 id: 'settings.app.lockedPassword',
53 defaultMessage: '!!!Ferdi Lock Password', 57 defaultMessage: '!!!Password',
54 }, 58 },
55 lockedPasswordInfo: { 59 lockedPasswordInfo: {
56 id: 'settings.app.lockedPasswordInfo', 60 id: 'settings.app.lockedPasswordInfo',
@@ -58,7 +62,7 @@ const messages = defineMessages({
58 }, 62 },
59 lockInfo: { 63 lockInfo: {
60 id: 'settings.app.lockInfo', 64 id: 'settings.app.lockInfo',
61 defaultMessage: '!!!Ferdi password lock allows you to keep your messages protected.\nUsing Ferdi password lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut CMD/CTRL+Shift+L.', 65 defaultMessage: '!!!Password Lock allows you to keep your messages protected.\nUsing Password Lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut CMD/CTRL+Shift+L.',
62 }, 66 },
63 scheduledDNDTimeInfo: { 67 scheduledDNDTimeInfo: {
64 id: 'settings.app.scheduledDNDTimeInfo', 68 id: 'settings.app.scheduledDNDTimeInfo',
@@ -142,6 +146,10 @@ const messages = defineMessages({
142 }, 146 },
143}); 147});
144 148
149const Hr = () => (
150 <hr style={{ marginBottom: 20 }} />
151);
152
145export default @observer class EditSettingsForm extends Component { 153export default @observer class EditSettingsForm extends Component {
146 static propTypes = { 154 static propTypes = {
147 checkForUpdates: PropTypes.func.isRequired, 155 checkForUpdates: PropTypes.func.isRequired,
@@ -163,6 +171,7 @@ export default @observer class EditSettingsForm extends Component {
163 hibernationEnabled: PropTypes.bool.isRequired, 171 hibernationEnabled: PropTypes.bool.isRequired,
164 isDarkmodeEnabled: PropTypes.bool.isRequired, 172 isDarkmodeEnabled: PropTypes.bool.isRequired,
165 isTrayEnabled: PropTypes.bool.isRequired, 173 isTrayEnabled: PropTypes.bool.isRequired,
174 isAdaptableDarkModeEnabled: PropTypes.bool.isRequired,
166 openProcessManager: PropTypes.func.isRequired, 175 openProcessManager: PropTypes.func.isRequired,
167 }; 176 };
168 177
@@ -187,6 +196,7 @@ export default @observer class EditSettingsForm extends Component {
187 installUpdate, 196 installUpdate,
188 form, 197 form,
189 isCheckingForUpdates, 198 isCheckingForUpdates,
199 isAdaptableDarkModeEnabled,
190 isUpdateAvailable, 200 isUpdateAvailable,
191 noUpdateAvailable, 201 noUpdateAvailable,
192 updateIsReadyToInstall, 202 updateIsReadyToInstall,
@@ -240,6 +250,9 @@ export default @observer class EditSettingsForm extends Component {
240 {isTrayEnabled && <Toggle field={form.$('startMinimized')} />} 250 {isTrayEnabled && <Toggle field={form.$('startMinimized')} />}
241 <Toggle field={form.$('privateNotifications')} /> 251 <Toggle field={form.$('privateNotifications')} />
242 <Toggle field={form.$('showServiceNavigationBar')} /> 252 <Toggle field={form.$('showServiceNavigationBar')} />
253
254 <Hr />
255
243 <Toggle field={form.$('hibernate')} /> 256 <Toggle field={form.$('hibernate')} />
244 {hibernationEnabled && ( 257 {hibernationEnabled && (
245 <Select field={form.$('hibernationStrategy')} /> 258 <Select field={form.$('hibernationStrategy')} />
@@ -254,9 +267,13 @@ export default @observer class EditSettingsForm extends Component {
254 { intl.formatMessage(messages.hibernateInfo) } 267 { intl.formatMessage(messages.hibernateInfo) }
255 </span> 268 </span>
256 </p> 269 </p>
270
271 <Hr />
272
257 {process.platform === 'win32' && ( 273 {process.platform === 'win32' && (
258 <Toggle field={form.$('minimizeToSystemTray')} /> 274 <Toggle field={form.$('minimizeToSystemTray')} />
259 )} 275 )}
276
260 <Input 277 <Input
261 placeholder="Server" 278 placeholder="Server"
262 onChange={e => this.submit(e)} 279 onChange={e => this.submit(e)}
@@ -264,7 +281,14 @@ export default @observer class EditSettingsForm extends Component {
264 autoFocus 281 autoFocus
265 /> 282 />
266 {isLoggedIn && ( 283 {isLoggedIn && (
267 <p>{ intl.formatMessage(messages.serverInfo) }</p> 284 <p
285 className="settings__message"
286 style={{
287 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem',
288 }}
289 >
290 { intl.formatMessage(messages.serverInfo) }
291 </p>
268 )} 292 )}
269 {server === 'https://api.franzinfra.com' && ( 293 {server === 'https://api.franzinfra.com' && (
270 <p 294 <p
@@ -292,6 +316,10 @@ export default @observer class EditSettingsForm extends Component {
292 {isWorkspaceEnabled && ( 316 {isWorkspaceEnabled && (
293 <Toggle field={form.$('keepAllWorkspacesLoaded')} /> 317 <Toggle field={form.$('keepAllWorkspacesLoaded')} />
294 )} 318 )}
319
320
321 <Hr />
322
295 {isTodosEnabled && ( 323 {isTodosEnabled && (
296 <> 324 <>
297 <Toggle field={form.$('enableTodos')} /> 325 <Toggle field={form.$('enableTodos')} />
@@ -300,10 +328,19 @@ export default @observer class EditSettingsForm extends Component {
300 onChange={e => this.submit(e)} 328 onChange={e => this.submit(e)}
301 field={form.$('todoServer')} 329 field={form.$('todoServer')}
302 /> 330 />
303 <p>{ intl.formatMessage(messages.todoServerInfo) }</p> 331 <p
332 className="settings__message"
333 style={{
334 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem',
335 }}
336 >
337 { intl.formatMessage(messages.todoServerInfo) }
338 </p>
304 </> 339 </>
305 )} 340 )}
306 341
342 <Hr />
343
307 <Toggle field={form.$('lockingFeatureEnabled')} /> 344 <Toggle field={form.$('lockingFeatureEnabled')} />
308 {lockingFeatureEnabled && ( 345 {lockingFeatureEnabled && (
309 <> 346 <>
@@ -318,6 +355,16 @@ export default @observer class EditSettingsForm extends Component {
318 <p> 355 <p>
319 { intl.formatMessage(messages.lockedPasswordInfo) } 356 { intl.formatMessage(messages.lockedPasswordInfo) }
320 </p> 357 </p>
358
359 <Input
360 placeholder="Lock after inactivity"
361 onChange={e => this.submit(e)}
362 field={form.$('inactivityLock')}
363 autoFocus
364 />
365 <p>
366 { intl.formatMessage(messages.inactivityLockInfo) }
367 </p>
321 </> 368 </>
322 )} 369 )}
323 <p 370 <p
@@ -331,6 +378,7 @@ export default @observer class EditSettingsForm extends Component {
331 </span> 378 </span>
332 </p> 379 </p>
333 380
381 <Hr />
334 382
335 <Toggle field={form.$('scheduledDNDEnabled')} /> 383 <Toggle field={form.$('scheduledDNDEnabled')} />
336 {scheduledDNDEnabled && ( 384 {scheduledDNDEnabled && (
@@ -386,11 +434,10 @@ export default @observer class EditSettingsForm extends Component {
386 <h2 id="apperance">{intl.formatMessage(messages.headlineAppearance)}</h2> 434 <h2 id="apperance">{intl.formatMessage(messages.headlineAppearance)}</h2>
387 <Toggle field={form.$('showDisabledServices')} /> 435 <Toggle field={form.$('showDisabledServices')} />
388 <Toggle field={form.$('showMessageBadgeWhenMuted')} /> 436 <Toggle field={form.$('showMessageBadgeWhenMuted')} />
389 <Toggle field={form.$('darkMode')} /> 437 {isMac && <Toggle field={form.$('adaptableDarkMode')} />}
390 {isMac && <Toggle field={form.$('adaptableDarkMode')} disabled={isDarkmodeEnabled} />} 438 {!(isMac && isAdaptableDarkModeEnabled) && <Toggle field={form.$('darkMode')} disabled={isAdaptableDarkModeEnabled} />}
391 {isDarkmodeEnabled && ( 439 {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && (
392 <> 440 <>
393 <Toggle field={form.$('adaptableDarkMode')} />
394 <Toggle field={form.$('universalDarkMode')} /> 441 <Toggle field={form.$('universalDarkMode')} />
395 <p 442 <p
396 className="settings__message" 443 className="settings__message"
@@ -488,20 +535,17 @@ export default @observer class EditSettingsForm extends Component {
488 loaded={!isCheckingForUpdates || !isUpdateAvailable} 535 loaded={!isCheckingForUpdates || !isUpdateAvailable}
489 /> 536 />
490 )} 537 )}
491 {noUpdateAvailable && (
492 <p>{intl.formatMessage(messages.updateStatusUpToDate)}</p>
493 )}
494 <br /> 538 <br />
495 <Toggle field={form.$('beta')} /> 539 <Toggle field={form.$('beta')} />
496 <Toggle field={form.$('noUpdates')} /> 540 <Toggle field={form.$('noUpdates')} />
497 {intl.formatMessage(messages.currentVersion)} 541 {intl.formatMessage(messages.currentVersion)}
498 {' '} 542 {' '}
499 {remote.app.getVersion()} 543 {remote.app.getVersion()}
544 <br />
545 <br />
546 {noUpdateAvailable && intl.formatMessage(messages.updateStatusUpToDate)}
500 <p className="settings__message"> 547 <p className="settings__message">
501 <span className="mdi mdi-information" /> 548
502 {intl.formatMessage(messages.languageDisclaimer)}
503 </p>
504 <p className="settings__message">
505 <span className="mdi mdi-github-face" /> 549 <span className="mdi mdi-github-face" />
506 <span> 550 <span>
507 Ferdi is based on 551 Ferdi is based on
@@ -512,6 +556,9 @@ export default @observer class EditSettingsForm extends Component {
512 {' '} 556 {' '}
513 <a href="https://github.com/meetfranz/franz/blob/master/LICENSE" target="_blank">Apache-2.0 License</a> 557 <a href="https://github.com/meetfranz/franz/blob/master/LICENSE" target="_blank">Apache-2.0 License</a>
514 </span> 558 </span>
559 <br />
560 <span className="mdi mdi-information" />
561 {intl.formatMessage(messages.languageDisclaimer)}
515 </p> 562 </p>
516 </form> 563 </form>
517 </div> 564 </div>
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js
index 7e6d93997..3d5358d89 100644
--- a/src/components/settings/team/TeamDashboard.js
+++ b/src/components/settings/team/TeamDashboard.js
@@ -210,7 +210,14 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
210 <h1 className={classes.headline}> 210 <h1 className={classes.headline}>
211 {intl.formatMessage(messages.teamsUnavailable)} 211 {intl.formatMessage(messages.teamsUnavailable)}
212 </h1> 212 </h1>
213 {intl.formatMessage(messages.teamsUnavailableInfo)} 213 <p
214 className="settings__message"
215 style={{
216 borderTop: 0, marginTop: 0,
217 }}
218 >
219 {intl.formatMessage(messages.teamsUnavailableInfo)}
220 </p>
214 </div> 221 </div>
215 </div> 222 </div>
216 ); 223 );