Clean up inviteLink handling, harden compose input
This commit is contained in:
parent
986d8a66bc
commit
fc12d02a8d
12 changed files with 59 additions and 3 deletions
6
main.js
6
main.js
|
@ -593,6 +593,12 @@ ipc.on('show-window', () => {
|
||||||
showWindow();
|
showWindow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipc.on('set-secure-input', (_sender, enabled) => {
|
||||||
|
if (app.setSecureKeyboardEntryEnabled) {
|
||||||
|
app.setSecureKeyboardEntryEnabled(enabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipc.on('title-bar-double-click', () => {
|
ipc.on('title-bar-double-click', () => {
|
||||||
if (!mainWindow) {
|
if (!mainWindow) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -138,6 +138,9 @@ try {
|
||||||
window.log.info('show window');
|
window.log.info('show window');
|
||||||
ipc.send('show-window');
|
ipc.send('show-window');
|
||||||
};
|
};
|
||||||
|
window.setSecureInput = enabled => {
|
||||||
|
ipc.send('set-secure-input', enabled);
|
||||||
|
};
|
||||||
|
|
||||||
window.titleBarDoubleClick = () => {
|
window.titleBarDoubleClick = () => {
|
||||||
ipc.send('title-bar-double-click');
|
ipc.send('title-bar-double-click');
|
||||||
|
|
|
@ -40,6 +40,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
clearQuotedMessage: action('clearQuotedMessage'),
|
clearQuotedMessage: action('clearQuotedMessage'),
|
||||||
getQuotedMessage: action('getQuotedMessage'),
|
getQuotedMessage: action('getQuotedMessage'),
|
||||||
sortedGroupMembers: [],
|
sortedGroupMembers: [],
|
||||||
|
setSecureInput: action('setSecureInput'),
|
||||||
// EmojiButton
|
// EmojiButton
|
||||||
onPickEmoji: action('onPickEmoji'),
|
onPickEmoji: action('onPickEmoji'),
|
||||||
onSetSkinTone: action('onSetSkinTone'),
|
onSetSkinTone: action('onSetSkinTone'),
|
||||||
|
|
|
@ -67,6 +67,7 @@ export type Props = Pick<
|
||||||
| 'draftBodyRanges'
|
| 'draftBodyRanges'
|
||||||
| 'clearQuotedMessage'
|
| 'clearQuotedMessage'
|
||||||
| 'getQuotedMessage'
|
| 'getQuotedMessage'
|
||||||
|
| 'setSecureInput'
|
||||||
> &
|
> &
|
||||||
Pick<
|
Pick<
|
||||||
EmojiButtonProps,
|
EmojiButtonProps,
|
||||||
|
@ -113,6 +114,7 @@ export const CompositionArea = ({
|
||||||
clearQuotedMessage,
|
clearQuotedMessage,
|
||||||
getQuotedMessage,
|
getQuotedMessage,
|
||||||
sortedGroupMembers,
|
sortedGroupMembers,
|
||||||
|
setSecureInput,
|
||||||
// EmojiButton
|
// EmojiButton
|
||||||
onPickEmoji,
|
onPickEmoji,
|
||||||
onSetSkinTone,
|
onSetSkinTone,
|
||||||
|
@ -470,6 +472,7 @@ export const CompositionArea = ({
|
||||||
clearQuotedMessage={clearQuotedMessage}
|
clearQuotedMessage={clearQuotedMessage}
|
||||||
getQuotedMessage={getQuotedMessage}
|
getQuotedMessage={getQuotedMessage}
|
||||||
sortedGroupMembers={sortedGroupMembers}
|
sortedGroupMembers={sortedGroupMembers}
|
||||||
|
setSecureInput={setSecureInput}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{!large ? (
|
{!large ? (
|
||||||
|
|
|
@ -28,6 +28,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
getQuotedMessage: action('getQuotedMessage'),
|
getQuotedMessage: action('getQuotedMessage'),
|
||||||
onPickEmoji: action('onPickEmoji'),
|
onPickEmoji: action('onPickEmoji'),
|
||||||
large: boolean('large', overrideProps.large || false),
|
large: boolean('large', overrideProps.large || false),
|
||||||
|
setSecureInput: action('setSecureInput'),
|
||||||
sortedGroupMembers: overrideProps.sortedGroupMembers || [],
|
sortedGroupMembers: overrideProps.sortedGroupMembers || [],
|
||||||
skinTone: select(
|
skinTone: select(
|
||||||
'skinTone',
|
'skinTone',
|
||||||
|
|
|
@ -76,6 +76,7 @@ export type Props = {
|
||||||
onSubmit(message: string, mentions: Array<BodyRangeType>): unknown;
|
onSubmit(message: string, mentions: Array<BodyRangeType>): unknown;
|
||||||
getQuotedMessage(): unknown;
|
getQuotedMessage(): unknown;
|
||||||
clearQuotedMessage(): unknown;
|
clearQuotedMessage(): unknown;
|
||||||
|
setSecureInput(enabled: boolean): unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_LENGTH = 64 * 1024;
|
const MAX_LENGTH = 64 * 1024;
|
||||||
|
@ -103,6 +104,7 @@ export const CompositionInput: React.ComponentType<Props> = props => {
|
||||||
skinTone,
|
skinTone,
|
||||||
draftText,
|
draftText,
|
||||||
draftBodyRanges,
|
draftBodyRanges,
|
||||||
|
setSecureInput,
|
||||||
getQuotedMessage,
|
getQuotedMessage,
|
||||||
clearQuotedMessage,
|
clearQuotedMessage,
|
||||||
sortedGroupMembers,
|
sortedGroupMembers,
|
||||||
|
@ -259,6 +261,20 @@ export const CompositionInput: React.ComponentType<Props> = props => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onFocus = (): void => {
|
||||||
|
setSecureInput(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBlur = (): void => {
|
||||||
|
setSecureInput(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
setSecureInput(false);
|
||||||
|
};
|
||||||
|
}, [setSecureInput]);
|
||||||
|
|
||||||
const onEnter = (): boolean => {
|
const onEnter = (): boolean => {
|
||||||
const quill = quillRef.current;
|
const quill = quillRef.current;
|
||||||
const emojiCompletion = emojiCompletionRef.current;
|
const emojiCompletion = emojiCompletionRef.current;
|
||||||
|
@ -494,6 +510,8 @@ export const CompositionInput: React.ComponentType<Props> = props => {
|
||||||
onChange,
|
onChange,
|
||||||
onEnter,
|
onEnter,
|
||||||
onEscape,
|
onEscape,
|
||||||
|
onFocus,
|
||||||
|
onBlur,
|
||||||
onPickEmoji,
|
onPickEmoji,
|
||||||
onShortKeyEnter,
|
onShortKeyEnter,
|
||||||
onTab,
|
onTab,
|
||||||
|
@ -508,6 +526,8 @@ export const CompositionInput: React.ComponentType<Props> = props => {
|
||||||
return (
|
return (
|
||||||
<ReactQuill
|
<ReactQuill
|
||||||
className="module-composition-input__quill"
|
className="module-composition-input__quill"
|
||||||
|
onFocus={() => callbacksRef.current.onFocus()}
|
||||||
|
onBlur={() => callbacksRef.current.onBlur()}
|
||||||
onChange={() => callbacksRef.current.onChange()}
|
onChange={() => callbacksRef.current.onChange()}
|
||||||
defaultValue={delta}
|
defaultValue={delta}
|
||||||
modules={{
|
modules={{
|
||||||
|
|
|
@ -53,6 +53,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
onSetSkinTone: action('onSetSkinTone'),
|
onSetSkinTone: action('onSetSkinTone'),
|
||||||
recentEmojis: [],
|
recentEmojis: [],
|
||||||
removeLinkPreview: action('removeLinkPreview'),
|
removeLinkPreview: action('removeLinkPreview'),
|
||||||
|
setSecureInput: action('setSecureInput'),
|
||||||
skinTone: 0,
|
skinTone: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ export type DataPropsType = {
|
||||||
caretLocation?: number
|
caretLocation?: number
|
||||||
) => unknown;
|
) => unknown;
|
||||||
onTextTooLong: () => void;
|
onTextTooLong: () => void;
|
||||||
|
setSecureInput: (enabled: boolean) => void;
|
||||||
} & Pick<EmojiButtonProps, 'recentEmojis' | 'skinTone'>;
|
} & Pick<EmojiButtonProps, 'recentEmojis' | 'skinTone'>;
|
||||||
|
|
||||||
type ActionPropsType = Pick<
|
type ActionPropsType = Pick<
|
||||||
|
@ -78,6 +79,7 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
|
||||||
recentEmojis,
|
recentEmojis,
|
||||||
removeLinkPreview,
|
removeLinkPreview,
|
||||||
skinTone,
|
skinTone,
|
||||||
|
setSecureInput,
|
||||||
}) => {
|
}) => {
|
||||||
const inputRef = useRef<null | HTMLInputElement>(null);
|
const inputRef = useRef<null | HTMLInputElement>(null);
|
||||||
const inputApiRef = React.useRef<InputApi | undefined>();
|
const inputApiRef = React.useRef<InputApi | undefined>();
|
||||||
|
@ -306,6 +308,7 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
|
||||||
onPickEmoji={onPickEmoji}
|
onPickEmoji={onPickEmoji}
|
||||||
onSubmit={forwardMessage}
|
onSubmit={forwardMessage}
|
||||||
onTextTooLong={onTextTooLong}
|
onTextTooLong={onTextTooLong}
|
||||||
|
setSecureInput={setSecureInput}
|
||||||
/>
|
/>
|
||||||
<div className="module-ForwardMessageModal__emoji">
|
<div className="module-ForwardMessageModal__emoji">
|
||||||
<EmojiButton
|
<EmojiButton
|
||||||
|
|
|
@ -34,6 +34,7 @@ export type SmartForwardMessageModalProps = {
|
||||||
caretLocation?: number
|
caretLocation?: number
|
||||||
) => unknown;
|
) => unknown;
|
||||||
onTextTooLong: () => void;
|
onTextTooLong: () => void;
|
||||||
|
setSecureInput: (enabled: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (
|
const mapStateToProps = (
|
||||||
|
@ -48,6 +49,7 @@ const mapStateToProps = (
|
||||||
onClose,
|
onClose,
|
||||||
onEditorStateChange,
|
onEditorStateChange,
|
||||||
onTextTooLong,
|
onTextTooLong,
|
||||||
|
setSecureInput,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const candidateConversations = getAllComposableConversations(state);
|
const candidateConversations = getAllComposableConversations(state);
|
||||||
|
@ -68,6 +70,7 @@ const mapStateToProps = (
|
||||||
recentEmojis,
|
recentEmojis,
|
||||||
skinTone,
|
skinTone,
|
||||||
onTextTooLong,
|
onTextTooLong,
|
||||||
|
setSecureInput,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2119,6 +2119,7 @@ export function initialize({
|
||||||
auth.groupPublicParamsHex,
|
auth.groupPublicParamsHex,
|
||||||
auth.authCredentialPresentationHex
|
auth.authCredentialPresentationHex
|
||||||
);
|
);
|
||||||
|
const safeInviteLinkPassword = toWebSafeBase64(inviteLinkPassword);
|
||||||
|
|
||||||
const response: ArrayBuffer = await _ajax({
|
const response: ArrayBuffer = await _ajax({
|
||||||
basicAuth,
|
basicAuth,
|
||||||
|
@ -2127,7 +2128,8 @@ export function initialize({
|
||||||
host: storageUrl,
|
host: storageUrl,
|
||||||
httpType: 'GET',
|
httpType: 'GET',
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
urlParameters: `/${toWebSafeBase64(inviteLinkPassword)}`,
|
urlParameters: `/${safeInviteLinkPassword}`,
|
||||||
|
redactUrl: _createRedactor(safeInviteLinkPassword),
|
||||||
});
|
});
|
||||||
|
|
||||||
return window.textsecure.protobuf.GroupJoinInfo.decode(response);
|
return window.textsecure.protobuf.GroupJoinInfo.decode(response);
|
||||||
|
@ -2143,6 +2145,9 @@ export function initialize({
|
||||||
options.authCredentialPresentationHex
|
options.authCredentialPresentationHex
|
||||||
);
|
);
|
||||||
const data = changes.toArrayBuffer();
|
const data = changes.toArrayBuffer();
|
||||||
|
const safeInviteLinkPassword = inviteLinkBase64
|
||||||
|
? toWebSafeBase64(inviteLinkBase64)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const response: ArrayBuffer = await _ajax({
|
const response: ArrayBuffer = await _ajax({
|
||||||
basicAuth,
|
basicAuth,
|
||||||
|
@ -2152,8 +2157,11 @@ export function initialize({
|
||||||
host: storageUrl,
|
host: storageUrl,
|
||||||
httpType: 'PATCH',
|
httpType: 'PATCH',
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
urlParameters: inviteLinkBase64
|
urlParameters: safeInviteLinkPassword
|
||||||
? `?inviteLinkPassword=${toWebSafeBase64(inviteLinkBase64)}`
|
? `?inviteLinkPassword=${safeInviteLinkPassword}`
|
||||||
|
: undefined,
|
||||||
|
redactUrl: safeInviteLinkPassword
|
||||||
|
? _createRedactor(safeInviteLinkPassword)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -631,6 +631,9 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
bodyRanges: Array<typeof window.Whisper.BodyRangeType>,
|
bodyRanges: Array<typeof window.Whisper.BodyRangeType>,
|
||||||
caretLocation?: number
|
caretLocation?: number
|
||||||
) => this.onEditorStateChange(msg, bodyRanges, caretLocation),
|
) => this.onEditorStateChange(msg, bodyRanges, caretLocation),
|
||||||
|
setSecureInput: (enabled: boolean) => {
|
||||||
|
window.setSecureInput(enabled);
|
||||||
|
},
|
||||||
onTextTooLong: () => this.showToast(Whisper.MessageBodyTooLongToast),
|
onTextTooLong: () => this.showToast(Whisper.MessageBodyTooLongToast),
|
||||||
onChooseAttachment: this.onChooseAttachment.bind(this),
|
onChooseAttachment: this.onChooseAttachment.bind(this),
|
||||||
getQuotedMessage: () => this.model.get('quotedMessageId'),
|
getQuotedMessage: () => this.model.get('quotedMessageId'),
|
||||||
|
@ -2255,6 +2258,9 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
{},
|
{},
|
||||||
document.querySelector('.module-ForwardMessageModal')
|
document.querySelector('.module-ForwardMessageModal')
|
||||||
),
|
),
|
||||||
|
setSecureInput: (enabled: boolean) => {
|
||||||
|
window.setSecureInput(enabled);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
1
ts/window.d.ts
vendored
1
ts/window.d.ts
vendored
|
@ -224,6 +224,7 @@ declare global {
|
||||||
setAutoHideMenuBar: (value: WhatIsThis) => void;
|
setAutoHideMenuBar: (value: WhatIsThis) => void;
|
||||||
setBadgeCount: (count: number) => void;
|
setBadgeCount: (count: number) => void;
|
||||||
setMenuBarVisibility: (value: WhatIsThis) => void;
|
setMenuBarVisibility: (value: WhatIsThis) => void;
|
||||||
|
setSecureInput: (enabled: boolean) => void;
|
||||||
showConfirmationDialog: (options: ConfirmationDialogViewProps) => void;
|
showConfirmationDialog: (options: ConfirmationDialogViewProps) => void;
|
||||||
showKeyboardShortcuts: () => void;
|
showKeyboardShortcuts: () => void;
|
||||||
storage: {
|
storage: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue