chore: add server switcher (#2717)
* wip * wip2 * refactor: use radio button group * chore: add persisting host per workspace * chore: header style * chore: update server picker title style * chore: margin * chore: label * chore: remove separator * rename migration to latest snjs version --------- Co-authored-by: Aman Harwara <amanharwara@protonmail.com>
This commit is contained in:
@@ -64,7 +64,7 @@ export interface ApplicationInterface {
|
|||||||
setPreference<K extends PrefKey>(key: K, value: PrefValue[K]): Promise<void>
|
setPreference<K extends PrefKey>(key: K, value: PrefValue[K]): Promise<void>
|
||||||
|
|
||||||
hasAccount(): boolean
|
hasAccount(): boolean
|
||||||
setCustomHost(host: string): Promise<void>
|
setCustomHost(host: string, websocketUrl?: string): Promise<void>
|
||||||
isUsingHomeServer(): Promise<boolean>
|
isUsingHomeServer(): Promise<boolean>
|
||||||
|
|
||||||
importData(data: BackupFile, awaitSync?: boolean): Promise<Result<ImportDataResult>>
|
importData(data: BackupFile, awaitSync?: boolean): Promise<Result<ImportDataResult>>
|
||||||
|
|||||||
@@ -576,10 +576,10 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
|||||||
return compareVersions(userVersion, ProtocolVersion.V004) >= 0
|
return compareVersions(userVersion, ProtocolVersion.V004) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setCustomHost(host: string): Promise<void> {
|
public async setCustomHost(host: string, websocketUrl?: string): Promise<void> {
|
||||||
await this.setHost.execute(host)
|
await this.setHost.execute(host)
|
||||||
|
|
||||||
this.sockets.setWebSocketUrl(undefined)
|
this.sockets.setWebSocketUrl(websocketUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUserPasswordCreationDate(): Date | undefined {
|
public getUserPasswordCreationDate(): Date | undefined {
|
||||||
|
|||||||
@@ -1528,6 +1528,7 @@ export class Dependencies {
|
|||||||
this.get<HttpService>(TYPES.HttpService),
|
this.get<HttpService>(TYPES.HttpService),
|
||||||
this.get<DiskStorageService>(TYPES.DiskStorageService),
|
this.get<DiskStorageService>(TYPES.DiskStorageService),
|
||||||
this.options.defaultHost,
|
this.options.defaultHost,
|
||||||
|
this.options.identifier,
|
||||||
this.get<InMemoryStore>(TYPES.InMemoryStore),
|
this.get<InMemoryStore>(TYPES.InMemoryStore),
|
||||||
this.get<PureCryptoInterface>(TYPES.Crypto),
|
this.get<PureCryptoInterface>(TYPES.Crypto),
|
||||||
this.get<SessionStorageMapper>(TYPES.SessionStorageMapper),
|
this.get<SessionStorageMapper>(TYPES.SessionStorageMapper),
|
||||||
|
|||||||
27
packages/snjs/lib/Migrations/Versions/2_204_8.ts
Normal file
27
packages/snjs/lib/Migrations/Versions/2_204_8.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { ApplicationStage, StorageKey } from '@standardnotes/services'
|
||||||
|
import { Migration } from '@Lib/Migrations/Migration'
|
||||||
|
|
||||||
|
export class Migration2_204_8 extends Migration {
|
||||||
|
static override version(): string {
|
||||||
|
return '2.204.8'
|
||||||
|
}
|
||||||
|
|
||||||
|
protected registerStageHandlers(): void {
|
||||||
|
this.registerStageHandler(ApplicationStage.Launched_10, async () => {
|
||||||
|
await this.migrateHostKeyStoredToWorkspaceIdentified()
|
||||||
|
|
||||||
|
this.markDone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private async migrateHostKeyStoredToWorkspaceIdentified(): Promise<void> {
|
||||||
|
const existingHostKeyValue = this.services.storageService.getValue<string | undefined>(StorageKey.ServerHost)
|
||||||
|
if (existingHostKeyValue === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.services.storageService.setValue(`${StorageKey.ServerHost}:${this.services.identifier}`, existingHostKeyValue)
|
||||||
|
|
||||||
|
await this.services.storageService.removeValue(StorageKey.ServerHost)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -106,6 +106,7 @@ export class LegacyApiService
|
|||||||
private httpService: HttpServiceInterface,
|
private httpService: HttpServiceInterface,
|
||||||
private storageService: DiskStorageService,
|
private storageService: DiskStorageService,
|
||||||
private host: string,
|
private host: string,
|
||||||
|
private workspaceIdentifier: string,
|
||||||
private inMemoryStore: KeyValueStoreInterface<string>,
|
private inMemoryStore: KeyValueStoreInterface<string>,
|
||||||
private crypto: PureCryptoInterface,
|
private crypto: PureCryptoInterface,
|
||||||
private sessionStorageMapper: MapperInterface<Session, Record<string, unknown>>,
|
private sessionStorageMapper: MapperInterface<Session, Record<string, unknown>>,
|
||||||
@@ -142,14 +143,16 @@ export class LegacyApiService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public loadHost(): string {
|
public loadHost(): string {
|
||||||
const storedValue = this.storageService.getValue<string | undefined>(StorageKey.ServerHost)
|
const storedValue = this.storageService.getValue<string | undefined>(
|
||||||
|
`${StorageKey.ServerHost}:${this.workspaceIdentifier}`,
|
||||||
|
)
|
||||||
this.host = storedValue || this.host
|
this.host = storedValue || this.host
|
||||||
return this.host
|
return this.host
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setHost(host: string): Promise<void> {
|
public async setHost(host: string): Promise<void> {
|
||||||
this.host = host
|
this.host = host
|
||||||
this.storageService.setValue(StorageKey.ServerHost, host)
|
this.storageService.setValue(`${StorageKey.ServerHost}:${this.workspaceIdentifier}`, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getHost(): string {
|
public getHost(): string {
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ export class SessionManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverHost = this.storage.getValue<string>(StorageKey.ServerHost)
|
const serverHost = this.storage.getValue<string | undefined>(`${StorageKey.ServerHost}:${this.workspaceIdentifier}`)
|
||||||
if (serverHost) {
|
if (serverHost) {
|
||||||
void this.apiService.setHost(serverHost)
|
void this.apiService.setHost(serverHost)
|
||||||
this.httpService.setHost(serverHost)
|
this.httpService.setHost(serverHost)
|
||||||
|
|||||||
4
packages/snjs/lib/Url/DefaultHost.ts
Normal file
4
packages/snjs/lib/Url/DefaultHost.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum DefaultHost {
|
||||||
|
Api = 'https://api.standardnotes.com',
|
||||||
|
WebSocket = 'wss://sockets.standardnotes.com',
|
||||||
|
}
|
||||||
1
packages/snjs/lib/Url/index.ts
Normal file
1
packages/snjs/lib/Url/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './DefaultHost'
|
||||||
@@ -7,6 +7,7 @@ export * from './Log'
|
|||||||
export * from './Migrations'
|
export * from './Migrations'
|
||||||
export * from './Services'
|
export * from './Services'
|
||||||
export * from './Types'
|
export * from './Types'
|
||||||
|
export * from './Url'
|
||||||
export * from './Version'
|
export * from './Version'
|
||||||
export { KeyParamsOrigination } from '@standardnotes/common'
|
export { KeyParamsOrigination } from '@standardnotes/common'
|
||||||
export * from '@standardnotes/domain-core'
|
export * from '@standardnotes/domain-core'
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { observer } from 'mobx-react-lite'
|
import { observer } from 'mobx-react-lite'
|
||||||
import { ChangeEventHandler, FunctionComponent, ReactNode, useCallback, useEffect, useState } from 'react'
|
import { FunctionComponent, ReactNode, useCallback, useEffect, useState } from 'react'
|
||||||
import Checkbox from '@/Components/Checkbox/Checkbox'
|
import Checkbox from '@/Components/Checkbox/Checkbox'
|
||||||
import DecoratedInput from '@/Components/Input/DecoratedInput'
|
import DecoratedInput from '@/Components/Input/DecoratedInput'
|
||||||
import Icon from '@/Components/Icon/Icon'
|
import Icon from '@/Components/Icon/Icon'
|
||||||
import { useApplication } from '../ApplicationProvider'
|
import { useApplication } from '../ApplicationProvider'
|
||||||
|
import ServerPicker from './ServerPicker/ServerPicker'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
@@ -22,7 +23,7 @@ const AdvancedOptions: FunctionComponent<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const application = useApplication()
|
const application = useApplication()
|
||||||
|
|
||||||
const { server, setServer, enableServerOption, setEnableServerOption } = application.accountMenuController
|
const { server, setServer } = application.accountMenuController
|
||||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||||
|
|
||||||
const [isPrivateUsername, setIsPrivateUsername] = useState(false)
|
const [isPrivateUsername, setIsPrivateUsername] = useState(false)
|
||||||
@@ -71,9 +72,8 @@ const AdvancedOptions: FunctionComponent<Props> = ({
|
|||||||
if (!isRecoveryCodes) {
|
if (!isRecoveryCodes) {
|
||||||
setIsPrivateUsername(false)
|
setIsPrivateUsername(false)
|
||||||
setIsStrictSignin(false)
|
setIsStrictSignin(false)
|
||||||
setEnableServerOption(false)
|
|
||||||
}
|
}
|
||||||
}, [isRecoveryCodes, setIsPrivateUsername, setIsStrictSignin, setEnableServerOption, onRecoveryCodesChange])
|
}, [isRecoveryCodes, setIsPrivateUsername, setIsStrictSignin, onRecoveryCodesChange])
|
||||||
|
|
||||||
const handleRecoveryCodesChange = useCallback(
|
const handleRecoveryCodesChange = useCallback(
|
||||||
(recoveryCodes: string) => {
|
(recoveryCodes: string) => {
|
||||||
@@ -85,19 +85,10 @@ const AdvancedOptions: FunctionComponent<Props> = ({
|
|||||||
[onRecoveryCodesChange],
|
[onRecoveryCodesChange],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleServerOptionChange: ChangeEventHandler<HTMLInputElement> = useCallback(
|
|
||||||
(e) => {
|
|
||||||
if (e.target instanceof HTMLInputElement) {
|
|
||||||
setEnableServerOption(e.target.checked)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[setEnableServerOption],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleSyncServerChange = useCallback(
|
const handleSyncServerChange = useCallback(
|
||||||
(server: string) => {
|
(server: string, websocketUrl?: string) => {
|
||||||
setServer(server)
|
setServer(server)
|
||||||
application.setCustomHost(server).catch(console.error)
|
application.setCustomHost(server, websocketUrl).catch(console.error)
|
||||||
},
|
},
|
||||||
[application, setServer],
|
[application, setServer],
|
||||||
)
|
)
|
||||||
@@ -124,100 +115,87 @@ const AdvancedOptions: FunctionComponent<Props> = ({
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
{showAdvanced ? (
|
{showAdvanced ? (
|
||||||
<div className="my-2 px-3">
|
<>
|
||||||
{children}
|
<div className="my-2 px-3">
|
||||||
|
{children}
|
||||||
|
|
||||||
<div className="mb-1 flex items-center justify-between">
|
|
||||||
<Checkbox
|
|
||||||
name="private-workspace"
|
|
||||||
label="Private username mode"
|
|
||||||
checked={isPrivateUsername}
|
|
||||||
disabled={disabled || isRecoveryCodes}
|
|
||||||
onChange={handleIsPrivateUsernameChange}
|
|
||||||
/>
|
|
||||||
<a href="https://standardnotes.com/help/80" target="_blank" rel="noopener noreferrer" title="Learn more">
|
|
||||||
<Icon type="info" className="text-neutral" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{isPrivateUsername && (
|
|
||||||
<>
|
|
||||||
<DecoratedInput
|
|
||||||
className={{ container: 'mb-2' }}
|
|
||||||
left={[<Icon type="account-circle" className="text-neutral" />]}
|
|
||||||
type="text"
|
|
||||||
placeholder="Username"
|
|
||||||
value={privateUsername}
|
|
||||||
onChange={handlePrivateUsernameNameChange}
|
|
||||||
disabled={disabled || isRecoveryCodes}
|
|
||||||
spellcheck={false}
|
|
||||||
autocomplete={false}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{onStrictSignInChange && (
|
|
||||||
<div className="mb-1 flex items-center justify-between">
|
<div className="mb-1 flex items-center justify-between">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
name="use-strict-signin"
|
name="private-workspace"
|
||||||
label="Use strict sign-in"
|
label="Private username mode"
|
||||||
checked={isStrictSignin}
|
checked={isPrivateUsername}
|
||||||
disabled={disabled || isRecoveryCodes}
|
disabled={disabled || isRecoveryCodes}
|
||||||
onChange={handleStrictSigninChange}
|
onChange={handleIsPrivateUsernameChange}
|
||||||
/>
|
/>
|
||||||
<a
|
<a href="https://standardnotes.com/help/80" target="_blank" rel="noopener noreferrer" title="Learn more">
|
||||||
href="https://standardnotes.com/help/security"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
title="Learn more"
|
|
||||||
>
|
|
||||||
<Icon type="info" className="text-neutral" />
|
<Icon type="info" className="text-neutral" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="mb-1 flex items-center justify-between">
|
{isPrivateUsername && (
|
||||||
<Checkbox
|
<>
|
||||||
name="recovery-codes"
|
<DecoratedInput
|
||||||
label="Use recovery code"
|
className={{ container: 'mb-2' }}
|
||||||
checked={isRecoveryCodes}
|
left={[<Icon type="account-circle" className="text-neutral" />]}
|
||||||
disabled={disabled}
|
type="text"
|
||||||
onChange={handleIsRecoveryCodesChange}
|
placeholder="Username"
|
||||||
/>
|
value={privateUsername}
|
||||||
</div>
|
onChange={handlePrivateUsernameNameChange}
|
||||||
|
disabled={disabled || isRecoveryCodes}
|
||||||
|
spellcheck={false}
|
||||||
|
autocomplete={false}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{isRecoveryCodes && (
|
{onStrictSignInChange && (
|
||||||
<>
|
<div className="mb-1 flex items-center justify-between">
|
||||||
<DecoratedInput
|
<Checkbox
|
||||||
className={{ container: 'mb-2' }}
|
name="use-strict-signin"
|
||||||
left={[<Icon type="security" className="text-neutral" />]}
|
label="Use strict sign-in"
|
||||||
type="text"
|
checked={isStrictSignin}
|
||||||
placeholder="Recovery code"
|
disabled={disabled || isRecoveryCodes}
|
||||||
value={recoveryCodes}
|
onChange={handleStrictSigninChange}
|
||||||
onChange={handleRecoveryCodesChange}
|
/>
|
||||||
|
<a
|
||||||
|
href="https://standardnotes.com/help/security"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
title="Learn more"
|
||||||
|
>
|
||||||
|
<Icon type="info" className="text-neutral" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mb-1 flex items-center justify-between">
|
||||||
|
<Checkbox
|
||||||
|
name="recovery-codes"
|
||||||
|
label="Use recovery code"
|
||||||
|
checked={isRecoveryCodes}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
spellcheck={false}
|
onChange={handleIsRecoveryCodesChange}
|
||||||
autocomplete={false}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
<Checkbox
|
{isRecoveryCodes && (
|
||||||
name="custom-sync-server"
|
<>
|
||||||
label="Custom sync server"
|
<DecoratedInput
|
||||||
checked={enableServerOption}
|
className={{ container: 'mb-2' }}
|
||||||
onChange={handleServerOptionChange}
|
left={[<Icon type="security" className="text-neutral" />]}
|
||||||
disabled={disabled || isRecoveryCodes}
|
type="text"
|
||||||
/>
|
placeholder="Recovery code"
|
||||||
<DecoratedInput
|
value={recoveryCodes}
|
||||||
type="text"
|
onChange={handleRecoveryCodesChange}
|
||||||
left={[<Icon type="server" className="text-neutral" />]}
|
disabled={disabled}
|
||||||
placeholder="https://api.standardnotes.com"
|
spellcheck={false}
|
||||||
value={server}
|
autocomplete={false}
|
||||||
onChange={handleSyncServerChange}
|
/>
|
||||||
disabled={!enableServerOption && !disabled && !isRecoveryCodes}
|
</>
|
||||||
/>
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<ServerPicker customServerAddress={server} handleCustomServerAddressChange={handleSyncServerChange} />
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { useMemo, useState } from 'react'
|
||||||
|
import { ServerType } from './ServerType'
|
||||||
|
import DecoratedInput from '@/Components/Input/DecoratedInput'
|
||||||
|
import Icon from '@/Components/Icon/Icon'
|
||||||
|
import { useApplication } from '@/Components/ApplicationProvider'
|
||||||
|
import { isDesktopApplication } from '@/Utils'
|
||||||
|
import RadioButtonGroup from '@/Components/RadioButtonGroup/RadioButtonGroup'
|
||||||
|
import { DefaultHost } from '@standardnotes/snjs'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
customServerAddress?: string
|
||||||
|
handleCustomServerAddressChange: (value: string, websocketUrl?: string) => void
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ServerPicker = ({ className, customServerAddress, handleCustomServerAddressChange }: Props) => {
|
||||||
|
const application = useApplication()
|
||||||
|
|
||||||
|
const [currentType, setCurrentType] = useState<ServerType>('standard')
|
||||||
|
|
||||||
|
const selectTab = async (type: ServerType) => {
|
||||||
|
setCurrentType(type)
|
||||||
|
if (type === 'standard') {
|
||||||
|
handleCustomServerAddressChange(DefaultHost.Api, DefaultHost.WebSocket)
|
||||||
|
}
|
||||||
|
if (type === 'home server') {
|
||||||
|
if (!application.homeServer) {
|
||||||
|
application.alerts
|
||||||
|
.alert('Home server is not running. Please open the prefences and home server tab to start it.')
|
||||||
|
.catch(console.error)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const homeServerUrl = await application.homeServer.getHomeServerUrl()
|
||||||
|
if (!homeServerUrl) {
|
||||||
|
application.alerts
|
||||||
|
.alert('Home server is not running. Please open the prefences and home server tab to start it.')
|
||||||
|
.catch(console.error)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCustomServerAddressChange(homeServerUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = useMemo(
|
||||||
|
() =>
|
||||||
|
[
|
||||||
|
{ label: 'Default', value: 'standard' },
|
||||||
|
{ label: 'Custom', value: 'custom' },
|
||||||
|
].concat(isDesktopApplication() ? [{ label: 'Home Server', value: 'home server' }] : []) as {
|
||||||
|
label: string
|
||||||
|
value: ServerType
|
||||||
|
}[],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`flex h-full flex-grow flex-col px-3 pb-1.5 ${className}`}>
|
||||||
|
<div className="mb-2 flex font-bold">Sync Server</div>
|
||||||
|
<RadioButtonGroup value={currentType} items={options} onChange={selectTab} />
|
||||||
|
{currentType === 'custom' && (
|
||||||
|
<DecoratedInput
|
||||||
|
className={{
|
||||||
|
container: 'mt-1',
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
left={[<Icon type="server" className="text-neutral" />]}
|
||||||
|
placeholder={DefaultHost.Api}
|
||||||
|
value={customServerAddress}
|
||||||
|
onChange={handleCustomServerAddressChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServerPicker
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export type ServerType = 'standard' | 'custom' | 'home server'
|
||||||
@@ -19,7 +19,6 @@ export class AccountMenuController extends AbstractViewController implements Int
|
|||||||
signingOut = false
|
signingOut = false
|
||||||
otherSessionsSignOut = false
|
otherSessionsSignOut = false
|
||||||
server: string | undefined = undefined
|
server: string | undefined = undefined
|
||||||
enableServerOption = false
|
|
||||||
notesAndTags: (SNNote | SNTag)[] = []
|
notesAndTags: (SNNote | SNTag)[] = []
|
||||||
isEncryptionEnabled = false
|
isEncryptionEnabled = false
|
||||||
encryptionStatusString = ''
|
encryptionStatusString = ''
|
||||||
@@ -48,7 +47,6 @@ export class AccountMenuController extends AbstractViewController implements Int
|
|||||||
signingOut: observable,
|
signingOut: observable,
|
||||||
otherSessionsSignOut: observable,
|
otherSessionsSignOut: observable,
|
||||||
server: observable,
|
server: observable,
|
||||||
enableServerOption: observable,
|
|
||||||
notesAndTags: observable,
|
notesAndTags: observable,
|
||||||
isEncryptionEnabled: observable,
|
isEncryptionEnabled: observable,
|
||||||
encryptionStatusString: observable,
|
encryptionStatusString: observable,
|
||||||
@@ -66,7 +64,6 @@ export class AccountMenuController extends AbstractViewController implements Int
|
|||||||
setIsBackupEncrypted: action,
|
setIsBackupEncrypted: action,
|
||||||
setOtherSessionsSignOut: action,
|
setOtherSessionsSignOut: action,
|
||||||
setCurrentPane: action,
|
setCurrentPane: action,
|
||||||
setEnableServerOption: action,
|
|
||||||
setServer: action,
|
setServer: action,
|
||||||
setDeletingAccount: action,
|
setDeletingAccount: action,
|
||||||
|
|
||||||
@@ -113,10 +110,6 @@ export class AccountMenuController extends AbstractViewController implements Int
|
|||||||
this.server = server
|
this.server = server
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnableServerOption = (enableServerOption: boolean): void => {
|
|
||||||
this.enableServerOption = enableServerOption
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsEncryptionEnabled = (isEncryptionEnabled: boolean): void => {
|
setIsEncryptionEnabled = (isEncryptionEnabled: boolean): void => {
|
||||||
this.isEncryptionEnabled = isEncryptionEnabled
|
this.isEncryptionEnabled = isEncryptionEnabled
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user