Page MenuHomePhabricator

D12907.id43579.diff
No OneTemporary

D12907.id43579.diff

diff --git a/native/profile/keyserver-selection-list.react.js b/native/profile/keyserver-selection-list.react.js
--- a/native/profile/keyserver-selection-list.react.js
+++ b/native/profile/keyserver-selection-list.react.js
@@ -87,13 +87,6 @@
marginBottom: 24,
paddingVertical: 2,
},
- keyserverListItemContainer: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- paddingHorizontal: 24,
- paddingVertical: 10,
- },
separator: {
backgroundColor: 'panelForegroundBorder',
height: 1,
diff --git a/native/profile/linked-devices-list-item.react.js b/native/profile/linked-devices-list-item.react.js
new file mode 100644
--- /dev/null
+++ b/native/profile/linked-devices-list-item.react.js
@@ -0,0 +1,102 @@
+// @flow
+
+import * as React from 'react';
+import { View, TouchableOpacity } from 'react-native';
+
+import {
+ type IdentityPlatformDetails,
+ identityDeviceTypes,
+} from 'lib/types/identity-service-types.js';
+
+import Pill from '../components/pill.react.js';
+import SWMIcon from '../components/swmansion-icon.react.js';
+import { useStyles, useColors } from '../themes/colors.js';
+
+type Props = {
+ +deviceID: string,
+ +platformDetails: ?IdentityPlatformDetails,
+ +isPrimary: boolean,
+ +isThisDevice: boolean,
+};
+
+function LinkedDevicesListItem(props: Props): React.Node {
+ const { deviceID, platformDetails, isPrimary, isThisDevice } = props;
+
+ const styles = useStyles(unboundStyles);
+ const colors = useColors();
+
+ const deviceType = platformDetails?.deviceType;
+
+ const deviceIcon = React.useMemo(() => {
+ let name;
+ if (
+ deviceType === identityDeviceTypes.IOS ||
+ deviceType === identityDeviceTypes.ANDROID
+ ) {
+ name = 'phone';
+ } else if (deviceType === identityDeviceTypes.KEYSERVER) {
+ name = 'cloud';
+ } else if (deviceType === identityDeviceTypes.WEB) {
+ name = 'globe-1';
+ } else {
+ name = 'question';
+ }
+ return (
+ <SWMIcon name={name} size={12} color={colors.panelForegroundLabel} />
+ );
+ }, [deviceType, colors.panelForegroundLabel]);
+
+ const label = React.useMemo(() => {
+ const baseLabel = deviceID.substr(0, 7);
+ let finalLabel = baseLabel;
+
+ if (isPrimary) {
+ finalLabel += ' (primary)';
+ }
+
+ if (isThisDevice) {
+ finalLabel += ' (this device)';
+ }
+
+ return finalLabel;
+ }, [deviceID, isPrimary, isThisDevice]);
+
+ const deviceListItem = React.useMemo(
+ () => (
+ <TouchableOpacity style={styles.listItemContainer}>
+ <View style={styles.pillContainer}>
+ <Pill
+ label={label}
+ backgroundColor={colors.codeBackground}
+ icon={deviceIcon}
+ />
+ </View>
+ </TouchableOpacity>
+ ),
+ [
+ styles.listItemContainer,
+ styles.pillContainer,
+ label,
+ colors.codeBackground,
+ deviceIcon,
+ ],
+ );
+
+ return deviceListItem;
+}
+
+const unboundStyles = {
+ listItemContainer: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ paddingHorizontal: 24,
+ paddingVertical: 10,
+ },
+ pillContainer: {
+ flex: 1,
+ alignItems: 'baseline',
+ },
+};
+
+export default LinkedDevicesListItem;
diff --git a/native/profile/linked-devices.react.js b/native/profile/linked-devices.react.js
--- a/native/profile/linked-devices.react.js
+++ b/native/profile/linked-devices.react.js
@@ -1,17 +1,125 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
+import { Text, View, FlatList } from 'react-native';
+import {
+ getOwnPeerDevices,
+ type DeviceIDAndPlatformDetails,
+} from 'lib/selectors/user-selectors.js';
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
+
+import LinkedDevicesListItem from './linked-devices-list-item.react.js';
import type { ProfileNavigationProp } from './profile.react.js';
import type { NavigationRoute } from '../navigation/route-names.js';
+import { useSelector } from '../redux/redux-utils.js';
+import { useStyles } from '../themes/colors.js';
+
+function keyExtractor(item: DeviceIDAndPlatformDetails) {
+ return item.deviceID;
+}
+function renderDeviceListItem({
+ item,
+ index,
+ thisDeviceID,
+}: {
+ +item: DeviceIDAndPlatformDetails,
+ +index: number,
+ +thisDeviceID: ?string,
+ ...
+}) {
+ return (
+ <LinkedDevicesListItem
+ {...item}
+ isPrimary={index === 0}
+ isThisDevice={item.deviceID === thisDeviceID}
+ />
+ );
+}
type Props = {
+navigation: ProfileNavigationProp<'LinkedDevices'>,
+route: NavigationRoute<'LinkedDevices'>,
};
// eslint-disable-next-line no-unused-vars
function LinkedDevices(props: Props): React.Node {
- return null;
+ const styles = useStyles(unboundStyles);
+
+ const userDevicesInfos: $ReadOnlyArray<DeviceIDAndPlatformDetails> =
+ useSelector(getOwnPeerDevices);
+
+ const identityContext = React.useContext(IdentityClientContext);
+ invariant(identityContext, 'identity context not set');
+ const { getAuthMetadata } = identityContext;
+ const [thisDeviceID, setThisDeviceID] = React.useState<?string>(null);
+
+ React.useEffect(() => {
+ void (async () => {
+ const { deviceID } = await getAuthMetadata();
+ setThisDeviceID(deviceID);
+ })();
+ }, [getAuthMetadata]);
+
+ const separatorComponent = React.useCallback(
+ () => <View style={styles.separator} />,
+ [styles.separator],
+ );
+
+ const userDeviceList = React.useMemo(
+ () => (
+ <View style={styles.container}>
+ <Text style={styles.header}>USER DEVICES</Text>
+ <FlatList
+ data={userDevicesInfos}
+ renderItem={({ item, index }) =>
+ renderDeviceListItem({ item, index, thisDeviceID })
+ }
+ keyExtractor={keyExtractor}
+ contentContainerStyle={styles.deviceListContentContainer}
+ ItemSeparatorComponent={separatorComponent}
+ />
+ </View>
+ ),
+ [
+ separatorComponent,
+ userDevicesInfos,
+ styles.container,
+ styles.header,
+ styles.deviceListContentContainer,
+ thisDeviceID,
+ ],
+ );
+
+ return userDeviceList;
}
+const unboundStyles = {
+ container: {
+ flex: 1,
+ backgroundColor: 'panelBackground',
+ paddingTop: 24,
+ },
+ header: {
+ color: 'panelBackgroundLabel',
+ fontSize: 12,
+ fontWeight: '400',
+ paddingBottom: 3,
+ paddingHorizontal: 24,
+ },
+ deviceListContentContainer: {
+ backgroundColor: 'panelForeground',
+ borderBottomWidth: 1,
+ borderColor: 'panelForegroundBorder',
+ borderTopWidth: 1,
+ marginBottom: 24,
+ paddingVertical: 2,
+ },
+ separator: {
+ backgroundColor: 'panelForegroundBorder',
+ height: 1,
+ marginHorizontal: 16,
+ },
+};
+
export default LinkedDevices;

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 30, 6:42 PM (10 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2384059
Default Alt Text
D12907.id43579.diff (6 KB)

Event Timeline