Message Requests: Add new "Report spam and block" button

This commit is contained in:
Evan Hahn 2021-05-27 16:17:05 -04:00 committed by Scott Nonnenberg
parent 20e501d9f1
commit d4dc9b8e39
33 changed files with 630 additions and 92 deletions

View file

@ -0,0 +1,30 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { WebAPIConnectType, WebAPIType } from '../textsecure/WebAPI';
// We define a stricter storage here that returns `unknown` instead of `any`.
type Storage = {
get(key: string): unknown;
};
export function connectToServerWithStoredCredentials(
WebAPI: WebAPIConnectType,
storage: Storage
): WebAPIType {
const username = storage.get('uuid_id') || storage.get('number_id');
if (typeof username !== 'string') {
throw new Error(
'Username in storage was not a string. Cannot connect to WebAPI'
);
}
const password = storage.get('password');
if (typeof password !== 'string') {
throw new Error(
'Password in storage was not a string. Cannot connect to WebAPI'
);
}
return WebAPI.connect({ username, password });
}

View file

@ -4,6 +4,7 @@
import * as React from 'react';
import { ActionCreatorsMapObject, bindActionCreators } from 'redux';
import { useDispatch } from 'react-redux';
import { first, last, noop } from 'lodash';
export function usePrevious<T>(initialValue: T, currentValue: T): T {
const previousValueRef = React.useRef<T>(initialValue);
@ -132,3 +133,57 @@ export function useIntersectionObserver(): [
return [setRef, intersectionObserverEntry];
}
function getTop(element: Readonly<Element>): number {
return element.getBoundingClientRect().top;
}
function isWrapped(element: Readonly<null | HTMLElement>): boolean {
if (!element) {
return false;
}
const { children } = element;
const firstChild = first(children);
const lastChild = last(children);
return Boolean(
firstChild &&
lastChild &&
firstChild !== lastChild &&
getTop(firstChild) !== getTop(lastChild)
);
}
/**
* A hook that returns a ref (to put on your element) and a boolean. The boolean will be
* `true` if the element's children have different `top`s, and `false` otherwise.
*/
export function useHasWrapped<T extends HTMLElement>(): [
React.Ref<T>,
boolean
] {
const [element, setElement] = React.useState<null | T>(null);
const [hasWrapped, setHasWrapped] = React.useState(isWrapped(element));
React.useEffect(() => {
if (!element) {
return noop;
}
// We can remove this `any` when we upgrade to TypeScript 4.2+, which adds
// `ResizeObserver` type definitions.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const observer = new (window as any).ResizeObserver(() => {
setHasWrapped(isWrapped(element));
});
observer.observe(element);
return () => {
observer.disconnect();
};
}, [element]);
return [setElement, hasWrapped];
}