Merge branch 'clearnet' into audio-messages-play-all

This commit is contained in:
Warrick Corfe-Tan 2021-06-24 14:01:34 +10:00
commit 397b0d09dc
24 changed files with 175 additions and 188 deletions

View file

@ -32,4 +32,3 @@ ts/**/*.js
# Libloki specific files
libloki/test/components.js
libloki/modules/mnemonic.js
session-file-server/**

View file

@ -20,9 +20,6 @@ jobs:
- name: Checkout git repo
uses: actions/checkout@v2
- name: Pull git submodules
run: git submodule update --init
- name: Install node
uses: actions/setup-node@v1
with:

View file

@ -22,9 +22,6 @@ jobs:
- name: Checkout git repo
uses: actions/checkout@v2
- name: Pull git submodules
run: git submodule update --init
- name: Install node
uses: actions/setup-node@v1
with:

View file

@ -20,9 +20,6 @@ jobs:
- name: Checkout git repo
uses: actions/checkout@v2
- name: Pull git submodules
run: git submodule update --init
- name: Install node
uses: actions/setup-node@v1
with:

4
.gitmodules vendored
View file

@ -1,4 +0,0 @@
[submodule "session-file-server"]
path = session-file-server
url = https://github.com/loki-project/session-file-server/
branch = session

View file

@ -49,5 +49,4 @@ stylesheets/_intlTelInput.scss
# Coverage
coverage/**
.nyc_output/**
session-file-server/**
release/**

View file

@ -2,7 +2,7 @@
"name": "session-desktop",
"productName": "Session",
"description": "Private messaging from your desktop",
"version": "1.6.5",
"version": "1.6.6",
"license": "GPL-3.0",
"author": {
"name": "Loki Project",

View file

@ -18,6 +18,10 @@
word-break: break-all;
}
.session-icon-button svg path {
transition: fill 0.3s ease;
}
input,
textarea {
caret-color: $session-color-green !important;

View file

@ -13,8 +13,8 @@ files = [y for x in os.walk(dir_path) for y in glob(os.path.join(x[0], '*.js'))]
files += [y for x in os.walk(dir_path) for y in glob(os.path.join(x[0], '*.ts'))]
files += [y for x in os.walk(dir_path) for y in glob(os.path.join(x[0], '*.tsx'))]
# exclude node_modules and session-file-server directories
filtered_files = [f for f in files if "node_modules" not in f and "session-file-server" not in f]
# exclude node_modules directories
filtered_files = [f for f in files if "node_modules" not in f]
# search for this pattern in _locales/en/messages.json: it is a defined localized string
patternLocalizedString = re.compile("^ \".*\"\: {")

View file

@ -11,7 +11,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { StateType } from '../state/reducer';
import { SessionIcon, SessionIconButton, SessionIconSize, SessionIconType } from './session/icon';
import { SessionWrapperModal } from '../components/session/SessionWrapperModal';
import { SessionWrapperModal } from './session/SessionWrapperModal';
import ip2country from 'ip2country';
import countryLookup from 'country-code-lookup';
@ -26,6 +26,7 @@ import {
// tslint:disable-next-line: no-submodule-imports
import useNetworkState from 'react-use/lib/useNetworkState';
import { SessionSpinner } from './session/SessionSpinner';
export type StatusLightType = {
glowStartDelay: number;
@ -37,6 +38,10 @@ const OnionPathModalInner = () => {
const onionPath = useSelector(getFirstOnionPath);
// including the device and destination in calculation
const glowDuration = onionPath.length + 2;
console.warn('onionPath', onionPath);
if (!onionPath || onionPath.length === 0) {
return <SessionSpinner loading={true} />;
}
const nodes = [
{
@ -116,7 +121,7 @@ export const ModalStatusLight = (props: StatusLightType) => {
glowDuration={glowDuration}
glowStartDelay={glowStartDelay}
iconType={SessionIconType.Circle}
iconSize={SessionIconSize.Medium}
iconSize={SessionIconSize.Small}
theme={theme}
/>
);

View file

@ -41,8 +41,6 @@ const InviteContactsDialogInner = (props: Props) => {
}
const chatName = convo.get('name');
// const chatServer = convo.get('server');
// const channelId = convo.get('channelId');
const isPublicConvo = convo.isPublic();
const [contactList, setContactList] = useState(

View file

@ -78,7 +78,7 @@ export class UpdateGroupNameDialog extends React.Component<Props, State> {
);
const isAdmin = this.convo.isPublic()
? this.convo.isAdmin(window.storage.get('primaryDevicePubKey'))
? false // disable editing of opengroup rooms as we don't handle them for now
: true;
return (

View file

@ -45,7 +45,7 @@ import { FSv2 } from '../../fileserver';
import { debounce } from 'lodash';
import { DURATION } from '../../session/constants';
import { actions as conversationActions } from '../../state/ducks/conversations';
import { ActionPanelOnionStatusLight, OnionPathModal } from '../OnionStatusDialog';
import { ActionPanelOnionStatusLight, OnionPathModal } from '../OnionStatusPathDialog';
import { EditProfileDialog } from '../EditProfileDialog';
import { SessionConfirm } from './SessionConfirm';
import {
@ -73,6 +73,7 @@ import { editProfileModal, onionPathModal } from '../../state/ducks/modalDialog'
import { SessionSeedModal } from './SessionSeedModal';
import { AdminLeaveClosedGroupDialog } from '../conversation/AdminLeaveClosedGroupDialog';
import { uploadOurAvatar } from '../../interactions/conversationInteractions';
import { ModalContainer } from './ModalContainer';
// tslint:disable-next-line: no-import-side-effect no-submodule-imports
@ -279,42 +280,6 @@ const doAppStartUp = () => {
SwarmPolling.getInstance().start();
};
const ModalContainer = () => {
const confirmModalState = useSelector(getConfirmModal);
const inviteModalState = useSelector(getInviteContactModal);
const addModeratorsModalState = useSelector(getAddModeratorsModal);
const removeModeratorsModalState = useSelector(getRemoveModeratorsModal);
const updateGroupMembersModalState = useSelector(getUpdateGroupMembersModal);
const updateGroupNameModalState = useSelector(getUpdateGroupNameModal);
const userDetailsModalState = useSelector(getUserDetailsModal);
const changeNicknameModal = useSelector(getChangeNickNameDialog);
const editProfileModalState = useSelector(getEditProfileDialog);
const onionPathModalState = useSelector(getOnionPathDialog);
const recoveryPhraseModalState = useSelector(getRecoveryPhraseDialog);
const adminLeaveClosedGroupModalState = useSelector(getAdminLeaveClosedGroupDialog);
return (
<>
{confirmModalState && <SessionConfirm {...confirmModalState} />}
{inviteModalState && <InviteContactsDialog {...inviteModalState} />}
{addModeratorsModalState && <AddModeratorsDialog {...addModeratorsModalState} />}
{removeModeratorsModalState && <RemoveModeratorsDialog {...removeModeratorsModalState} />}
{updateGroupMembersModalState && (
<UpdateGroupMembersDialog {...updateGroupMembersModalState} />
)}
{updateGroupNameModalState && <UpdateGroupNameDialog {...updateGroupNameModalState} />}
{userDetailsModalState && <UserDetailsDialog {...userDetailsModalState} />}
{changeNicknameModal && <SessionNicknameDialog {...changeNicknameModal} />}
{editProfileModalState && <EditProfileDialog {...editProfileModalState} />}
{onionPathModalState && <OnionPathModal {...onionPathModalState} />}
{recoveryPhraseModalState && <SessionSeedModal {...recoveryPhraseModalState} />}
{adminLeaveClosedGroupModalState && (
<AdminLeaveClosedGroupDialog {...adminLeaveClosedGroupModalState} />
)}
</>
);
};
/**
* ActionsPanel is the far left banner (not the left pane).
* The panel with buttons to switch between the message/contact/settings/theme views

View file

@ -0,0 +1,68 @@
import React from 'react';
import { useSelector } from 'react-redux';
import {
getAddModeratorsModal,
getAdminLeaveClosedGroupDialog,
getChangeNickNameDialog,
getConfirmModal,
getEditProfileDialog,
getInviteContactModal,
getOnionPathDialog,
getRecoveryPhraseDialog,
getRemoveModeratorsModal,
getSessionPasswordDialog,
getUpdateGroupMembersModal,
getUpdateGroupNameModal,
getUserDetailsModal,
} from '../../state/selectors/modal';
import { AdminLeaveClosedGroupDialog } from '../conversation/AdminLeaveClosedGroupDialog';
import { InviteContactsDialog } from '../conversation/InviteContactsDialog';
import { AddModeratorsDialog } from '../conversation/ModeratorsAddDialog';
import { RemoveModeratorsDialog } from '../conversation/ModeratorsRemoveDialog';
import { UpdateGroupMembersDialog } from '../conversation/UpdateGroupMembersDialog';
import { UpdateGroupNameDialog } from '../conversation/UpdateGroupNameDialog';
import { EditProfileDialog } from '../EditProfileDialog';
import { OnionPathModal } from '../OnionStatusPathDialog';
import { UserDetailsDialog } from '../UserDetailsDialog';
import { SessionConfirm } from './SessionConfirm';
import { SessionNicknameDialog } from './SessionNicknameDialog';
import { SessionPasswordModal } from './SessionPasswordModal';
import { SessionSeedModal } from './SessionSeedModal';
export const ModalContainer = () => {
const confirmModalState = useSelector(getConfirmModal);
const inviteModalState = useSelector(getInviteContactModal);
const addModeratorsModalState = useSelector(getAddModeratorsModal);
const removeModeratorsModalState = useSelector(getRemoveModeratorsModal);
const updateGroupMembersModalState = useSelector(getUpdateGroupMembersModal);
const updateGroupNameModalState = useSelector(getUpdateGroupNameModal);
const userDetailsModalState = useSelector(getUserDetailsModal);
const changeNicknameModal = useSelector(getChangeNickNameDialog);
const editProfileModalState = useSelector(getEditProfileDialog);
const onionPathModalState = useSelector(getOnionPathDialog);
const recoveryPhraseModalState = useSelector(getRecoveryPhraseDialog);
const adminLeaveClosedGroupModalState = useSelector(getAdminLeaveClosedGroupDialog);
const sessionPasswordModalState = useSelector(getSessionPasswordDialog);
return (
<>
{confirmModalState && <SessionConfirm {...confirmModalState} />}
{inviteModalState && <InviteContactsDialog {...inviteModalState} />}
{addModeratorsModalState && <AddModeratorsDialog {...addModeratorsModalState} />}
{removeModeratorsModalState && <RemoveModeratorsDialog {...removeModeratorsModalState} />}
{updateGroupMembersModalState && (
<UpdateGroupMembersDialog {...updateGroupMembersModalState} />
)}
{updateGroupNameModalState && <UpdateGroupNameDialog {...updateGroupNameModalState} />}
{userDetailsModalState && <UserDetailsDialog {...userDetailsModalState} />}
{changeNicknameModal && <SessionNicknameDialog {...changeNicknameModal} />}
{editProfileModalState && <EditProfileDialog {...editProfileModalState} />}
{onionPathModalState && <OnionPathModal {...onionPathModalState} />}
{recoveryPhraseModalState && <SessionSeedModal {...recoveryPhraseModalState} />}
{adminLeaveClosedGroupModalState && (
<AdminLeaveClosedGroupDialog {...adminLeaveClosedGroupModalState} />
)}
{sessionPasswordModalState && <SessionPasswordModal {...sessionPasswordModalState} />}
</>
);
};

View file

@ -1,25 +1,19 @@
import React from 'react';
import { SessionModal } from './SessionModal';
import { SessionButton, SessionButtonColor } from './SessionButton';
import { missingCaseError, PasswordUtil } from '../../util/';
import { ToastUtils } from '../../session/utils';
import { SessionIconType } from './icon';
import { DefaultTheme, withTheme } from 'styled-components';
import { getPasswordHash } from '../../data/data';
import { SessionWrapperModal } from './SessionWrapperModal';
import { SpacerLG, SpacerSM } from '../basic/Text';
export enum PasswordAction {
Set = 'set',
Change = 'change',
Remove = 'remove',
}
import autoBind from 'auto-bind';
import { sessionPassword } from '../../state/ducks/modalDialog';
export type PasswordAction = 'set' | 'change' | 'remove';
interface Props {
action: PasswordAction;
onOk: any;
onClose: any;
theme: DefaultTheme;
passwordAction: PasswordAction;
onOk: () => void;
}
interface State {
@ -29,7 +23,7 @@ interface State {
currentPasswordRetypeEntered: string | null;
}
class SessionPasswordModalInner extends React.Component<Props, State> {
export class SessionPasswordModal extends React.Component<Props, State> {
private passportInput: HTMLInputElement | null = null;
constructor(props: any) {
@ -42,14 +36,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
currentPasswordRetypeEntered: null,
};
this.showError = this.showError.bind(this);
this.setPassword = this.setPassword.bind(this);
this.closeDialog = this.closeDialog.bind(this);
this.onPasswordInput = this.onPasswordInput.bind(this);
this.onPasswordConfirmInput = this.onPasswordConfirmInput.bind(this);
this.onPasswordRetypeInput = this.onPasswordRetypeInput.bind(this);
autoBind(this);
}
public componentDidMount() {
@ -60,9 +47,9 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
}
public render() {
const { action, onOk } = this.props;
const { passwordAction } = this.props;
const placeholders =
action === PasswordAction.Change
passwordAction === 'change'
? [
window.i18n('typeInOldPassword'),
window.i18n('enterPassword'),
@ -71,10 +58,13 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
: [window.i18n('enterPassword'), window.i18n('confirmPassword')];
const confirmButtonColor =
action === PasswordAction.Remove ? SessionButtonColor.Danger : SessionButtonColor.Primary;
passwordAction === 'remove' ? SessionButtonColor.Danger : SessionButtonColor.Primary;
return (
<SessionWrapperModal title={window.i18n(`${action}Password`)} onClose={this.closeDialog}>
<SessionWrapperModal
title={window.i18n(`${passwordAction}Password`)}
onClose={this.closeDialog}
>
<SpacerSM />
<div className="session-modal__input-group">
@ -87,7 +77,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
placeholder={placeholders[0]}
onKeyUp={this.onPasswordInput}
/>
{action !== PasswordAction.Remove && (
{passwordAction !== 'remove' && (
<input
type="password"
id="password-modal-input-confirm"
@ -95,7 +85,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
onKeyUp={this.onPasswordConfirmInput}
/>
)}
{action === PasswordAction.Change && (
{passwordAction === 'change' && (
<input
type="password"
id="password-modal-input-reconfirm"
@ -183,7 +173,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
SessionIconType.Lock
);
this.props.onOk(this.props.action);
this.props.onOk();
this.closeDialog();
}
@ -222,7 +212,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
SessionIconType.Lock
);
this.props.onOk(this.props.action);
this.props.onOk();
this.closeDialog();
}
@ -243,31 +233,30 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
window.i18n('removePasswordToastDescription')
);
this.props.onOk(this.props.action);
this.props.onOk();
this.closeDialog();
}
// tslint:disable-next-line: cyclomatic-complexity
private async setPassword() {
const { action } = this.props;
const { passwordAction } = this.props;
const {
currentPasswordEntered,
currentPasswordConfirmEntered,
currentPasswordRetypeEntered,
} = this.state;
const { Set, Remove, Change } = PasswordAction;
// Trim leading / trailing whitespace for UX
const firstPasswordEntered = (currentPasswordEntered || '').trim();
const secondPasswordEntered = (currentPasswordConfirmEntered || '').trim();
const thirdPasswordEntered = (currentPasswordRetypeEntered || '').trim();
switch (action) {
case Set: {
switch (passwordAction) {
case 'set': {
await this.handleActionSet(firstPasswordEntered, secondPasswordEntered);
return;
}
case Change: {
case 'change': {
await this.handleActionChange(
firstPasswordEntered,
secondPasswordEntered,
@ -275,19 +264,17 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
);
return;
}
case Remove: {
case 'remove': {
await this.handleActionRemove(firstPasswordEntered);
return;
}
default:
throw missingCaseError(action);
throw missingCaseError(passwordAction);
}
}
private closeDialog() {
if (this.props.onClose) {
this.props.onClose();
}
window.inboxStore?.dispatch(sessionPassword(null));
}
private async onPasswordInput(event: any) {
@ -317,5 +304,3 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
this.setState({ currentPasswordRetypeEntered });
}
}
export const SessionPasswordModal = withTheme(SessionPasswordModalInner);

View file

@ -33,15 +33,9 @@ import { SessionMemberListItem } from '../SessionMemberListItem';
import autoBind from 'auto-bind';
import { SectionType } from '../ActionsPanel';
import { SessionSettingCategory } from '../settings/SessionSettings';
import {
defaultMentionsInputReducer,
updateMentionsMembers,
} from '../../../state/ducks/mentionsInput';
import { getMentionsInput } from '../../../state/selectors/mentionsInput';
import { useDispatch } from 'react-redux';
import { updateConfirmModal } from '../../../state/ducks/modalDialog';
import { SessionButtonColor } from '../SessionButton';
import { any } from 'underscore';
import { SessionConfirmDialogProps } from '../SessionConfirm';
export interface ReplyingToMessageProps {
@ -93,7 +87,6 @@ interface Props {
showLeftPaneSection: (section: SectionType) => void;
showSettingsSection: (category: SessionSettingCategory) => void;
theme: DefaultTheme;
updateConfirmModal: (props: SessionConfirmDialogProps) => any;
}
interface State {
@ -247,15 +240,17 @@ export class SessionCompositionBox extends React.Component<Props, State> {
private showLinkSharingConfirmationModalDialog(e: any) {
const pastedText = e.clipboardData.getData('text');
if (this.isURL(pastedText)) {
this.props.updateConfirmModal({
shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'),
title: window.i18n('linkPreviewsTitle'),
message: window.i18n('linkPreviewsConfirmMessage'),
okTheme: SessionButtonColor.Danger,
onClickOk: () => {
window.setSettingValue('link-preview-setting', true);
},
});
window.inboxStore?.dispatch(
updateConfirmModal({
shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'),
title: window.i18n('linkPreviewsTitle'),
message: window.i18n('linkPreviewsConfirmMessage'),
okTheme: SessionButtonColor.Danger,
onClickOk: () => {
window.setSettingValue('link-preview-setting', true);
},
})
);
}
}

View file

@ -304,7 +304,6 @@ export class SessionConversation extends React.Component<Props, State> {
removeAttachment={this.removeAttachment}
onChoseAttachments={this.onChoseAttachments}
theme={this.props.theme}
updateConfirmModal={actions.updateConfirmModal}
/>
</div>

View file

@ -62,43 +62,51 @@ const rotate = keyframes`
* Creates a glow animation made for multiple element sequentially
*/
const glow = (color: string, glowDuration: number, glowStartDelay: number) => {
const dropShadowType = `drop-shadow(0px 0px 4px ${color}) `;
//increase shadow intensity by 3
const dropShadow = `${dropShadowType.repeat(1)};`;
const dropShadow = `drop-shadow(0px 0px 6px ${color});`;
// creating keyframe for sequential animations
let kf = '';
for (let i = 0; i <= glowDuration; i++) {
// const percent = (100 / glowDuration) * i;
const percent = (100 / glowDuration) * i;
if (i === glowStartDelay) {
const durationWithLoop = glowDuration + 1;
for (let i = 0; i <= durationWithLoop; i++) {
const percent = (100 / durationWithLoop) * i;
if (i === glowStartDelay + 1) {
kf += `${percent}% {
filter: ${dropShadow}
transform: scale(1.5);
transform: scale(1.1);
}`;
} else {
kf += `${percent}% {
filter: none;
transform: scale(0.8);
transform: scale(0.9);
}`;
}
}
return keyframes`${kf}`;
};
const animation = (props: any) => {
const animation = (props: {
rotateDuration?: number;
glowDuration?: number;
glowStartDelay?: number;
iconColor?: string;
}) => {
if (props.rotateDuration) {
return css`
${rotate} ${props.rotateDuration}s infinite linear;
`;
} else if (props.glowDuration !== undefined && props.glowStartDelay !== undefined) {
} else if (
props.glowDuration !== undefined &&
props.glowStartDelay !== undefined &&
props.iconColor
) {
return css`
${glow(
props.iconColor,
props.glowDuration,
props.glowStartDelay
)} ${props.glowDuration}s ease-in infinite;
)} ${props.glowDuration}s ease infinite;
`;
} else {
return;

View file

@ -10,7 +10,6 @@ import {
updateConfirmModal,
} from '../../../state/ducks/modalDialog';
import { ConversationController } from '../../../session/conversations';
import { UserUtils } from '../../../session/utils';
import {
blockConvoById,
clearNickNameByConvoId,

View file

@ -1,6 +1,8 @@
import React from 'react';
// tslint:disable-next-line: no-submodule-imports
import useNetworkState from 'react-use/lib/useNetworkState';
import styled from 'styled-components';
import { useNetwork } from '../../../hooks/useNetwork';
type ContainerProps = {
show: boolean;
@ -24,8 +26,7 @@ const OfflineTitle = styled.h3`
const OfflineMessage = styled.div``;
export const SessionOffline = () => {
const isOnline = useNetwork();
const isOnline = useNetworkState().online;
return (
<OfflineContainer show={!isOnline}>
<OfflineTitle>{window.i18n('offline')}</OfflineTitle>

View file

@ -12,11 +12,12 @@ import { connect, useSelector } from 'react-redux';
import { getPasswordHash } from '../../../../ts/data/data';
import { SpacerLG, SpacerXS } from '../../basic/Text';
import { shell } from 'electron';
import { PasswordAction, SessionPasswordModal } from '../SessionPasswordModal';
import { SessionConfirmDialogProps } from '../SessionConfirm';
import { mapDispatchToProps } from '../../../state/actions';
import { unblockConvoById } from '../../../interactions/conversationInteractions';
import { toggleAudioAutoplay } from '../../../state/ducks/userConfig';
import { sessionPassword } from '../../../state/ducks/modalDialog';
import { PasswordAction } from '../SessionPasswordModal';
export enum SessionSettingCategory {
Appearance = 'appearance',
@ -47,7 +48,6 @@ interface State {
pwdLockError: string | null;
mediaSetting: boolean | null;
shouldLockSettings: boolean | null;
modal: JSX.Element | null;
}
interface ConfirmationDialogParams extends SessionConfirmDialogProps {
@ -80,7 +80,6 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
pwdLockError: null,
mediaSetting: null,
shouldLockSettings: true,
modal: null,
};
this.settingsViewRef = React.createRef();
@ -174,12 +173,8 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
<h3>{window.i18n('password')}</h3>
<input type="password" id="password-lock-input" defaultValue="" placeholder="Password" />
<SpacerXS />
{this.state.pwdLockError && (
<>
<div className="session-label warning">{this.state.pwdLockError}</div>
<SpacerLG />
</>
<div className="session-label warning">{this.state.pwdLockError}</div>
)}
<SessionButton
@ -234,8 +229,6 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
categoryTitle={window.i18n(`${category}SettingsTitle`)}
/>
{this.state.modal ? this.state.modal : null}
<div className="session-settings-view">
{shouldRenderPasswordLock ? (
this.renderPasswordLock()
@ -529,7 +522,7 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
buttonColor: SessionButtonColor.Primary,
},
onClick: () => {
this.displayPasswordModal(PasswordAction.Set);
this.displayPasswordModal('set');
},
confirmationDialogParams: undefined,
},
@ -547,7 +540,7 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
buttonColor: SessionButtonColor.Primary,
},
onClick: () => {
this.displayPasswordModal(PasswordAction.Change);
this.displayPasswordModal('change');
},
confirmationDialogParams: undefined,
},
@ -565,7 +558,7 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
buttonColor: SessionButtonColor.Danger,
},
onClick: () => {
this.displayPasswordModal(PasswordAction.Remove);
this.displayPasswordModal('remove');
},
confirmationDialogParams: undefined,
},
@ -573,25 +566,14 @@ class SettingsViewInner extends React.Component<SettingsViewProps, State> {
}
private displayPasswordModal(passwordAction: PasswordAction) {
this.setState({
...this.state,
modal: (
<SessionPasswordModal
onClose={() => {
this.clearModal();
}}
onOk={this.onPasswordUpdated}
action={passwordAction}
/>
),
});
}
private clearModal(): void {
this.setState({
...this.state,
modal: null,
});
window.inboxStore?.dispatch(
sessionPassword({
passwordAction,
onOk: () => {
this.onPasswordUpdated(passwordAction);
},
})
);
}
private getBlockedUserSettings(): Array<LocalSettingType> {

View file

@ -1,22 +0,0 @@
import { useEffect, useState } from 'react';
export function useNetwork() {
const [isOnline, setNetwork] = useState(window.navigator.onLine);
const updateNetwork = () => {
setNetwork(window.navigator.onLine);
};
// there are some weird behavior with this api.
// basically, online events might not be called if the pc has a virtual machine running
// https://github.com/electron/electron/issues/11290#issuecomment-348598311
useEffect(() => {
window.addEventListener('offline', updateNetwork);
window.addEventListener('online', updateNetwork);
return () => {
window.removeEventListener('offline', updateNetwork);
window.removeEventListener('online', updateNetwork);
};
});
return isOnline;
}

View file

@ -1,5 +1,6 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { SessionConfirmDialogProps } from '../../components/session/SessionConfirm';
import { PasswordAction } from '../../components/session/SessionPasswordModal';
export type ConfirmModalState = SessionConfirmDialogProps | null;
export type InviteContactModalState = { conversationId: string } | null;
@ -13,6 +14,8 @@ export type EditProfileModalState = {} | null;
export type OnionPathModalState = EditProfileModalState;
export type RecoveryPhraseModalState = EditProfileModalState;
export type SessionPasswordModalState = { passwordAction: PasswordAction; onOk: () => void } | null;
export type UserDetailsModalState = {
conversationId: string;
authorAvatarPath?: string;
@ -32,6 +35,7 @@ export type ModalState = {
onionPathModal: OnionPathModalState;
recoveryPhraseModal: RecoveryPhraseModalState;
adminLeaveClosedGroup: AdminLeaveClosedGroupModalState;
sessionPasswordModal: SessionPasswordModalState;
};
export const initialModalState: ModalState = {
@ -47,6 +51,7 @@ export const initialModalState: ModalState = {
onionPathModal: null,
recoveryPhraseModal: null,
adminLeaveClosedGroup: null,
sessionPasswordModal: null,
};
const ModalSlice = createSlice({
@ -89,6 +94,9 @@ const ModalSlice = createSlice({
adminLeaveClosedGroup(state, action: PayloadAction<AdminLeaveClosedGroupModalState | null>) {
return { ...state, adminLeaveClosedGroup: action.payload };
},
sessionPassword(state, action: PayloadAction<SessionPasswordModalState>) {
return { ...state, sessionPasswordModal: action.payload };
},
},
});
@ -106,5 +114,6 @@ export const {
onionPathModal,
recoveryPhraseModal,
adminLeaveClosedGroup,
sessionPassword,
} = actions;
export const modalReducer = reducer;

View file

@ -12,6 +12,7 @@ import {
OnionPathModalState,
RecoveryPhraseModalState,
RemoveModeratorsModalState,
SessionPasswordModalState,
UpdateGroupMembersModalState,
UpdateGroupNameModalState,
UserDetailsModalState,
@ -80,3 +81,8 @@ export const getAdminLeaveClosedGroupDialog = createSelector(
getModal,
(state: ModalState): AdminLeaveClosedGroupModalState => state.adminLeaveClosedGroup
);
export const getSessionPasswordDialog = createSelector(
getModal,
(state: ModalState): SessionPasswordModalState => state.sessionPasswordModal
);