Skip to content

Commit

Permalink
feat: Show icons associated with a preset (#348)
Browse files Browse the repository at this point in the history
* add get image url to preset icon

* handle error, and show default icon

* update packages, add snipet to get all presets

* add ability to show icon based on iconId, get icon based on presetName, pass new props in all components

* rename interface in PresetIcon component, generate again package-lock.json

* rename interface in PresetIcon component, generate again package-lock.json

* restore package-lock.file
  • Loading branch information
bohdanprog authored May 16, 2024
1 parent 2d7cdea commit 907d251
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 87 deletions.
22 changes: 22 additions & 0 deletions src/frontend/hooks/server/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import {
useSuspenseQuery,
useMutation,
useQueryClient,
useQuery,
} from '@tanstack/react-query';

import {useProject} from './projects';
import {PresetValue} from '@mapeo/schema';
import {IconSize} from '../../sharedTypes';

export function usePresetsQuery() {
const project = useProject();
Expand Down Expand Up @@ -33,3 +35,23 @@ export function usePresetsMutation() {
},
});
}

export function useGetPresetIcon(size: IconSize, name?: string) {
const project = useProject();

return useQuery({
queryKey: ['presetIcon', name],
enabled: !!name,
queryFn: async () => {
const currentPreset = await project.preset
.getMany()
.then(res => res.find(p => p.name === name));

return await project.$icons.getIconUrl(currentPreset?.iconId!, {
mimeType: 'image/png',
size: size,
pixelDensity: 3,
});
},
});
}
5 changes: 3 additions & 2 deletions src/frontend/screens/Observation/PresetHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {BLACK} from '../../lib/styles';
import {FormattedPresetName} from '../../sharedComponents/FormattedData';
import {CategoryCircleIcon} from '../../sharedComponents/icons/CategoryIcon';
import {PresetCircleIcon} from '../../sharedComponents/icons/PresetIcon';
import {Preset} from '@mapeo/schema';

export const PresetHeader = ({preset}: {preset: Preset}) => {
return (
<View style={styles.categoryIconContainer}>
<CategoryCircleIcon color={BLACK} size="medium" />
<PresetCircleIcon size="medium" name={preset.name} />
<Text style={styles.categoryLabel} numberOfLines={1}>
<FormattedPresetName preset={preset} />
</Text>
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/screens/ObservationEdit/PresetView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {defineMessages, useIntl} from 'react-intl';
import {View, Text, StyleSheet} from 'react-native';
import {BLACK, LIGHT_BLUE} from '../../lib/styles';
import {TextButton} from '../../sharedComponents/TextButton';
import {CategoryCircleIcon} from '../../sharedComponents/icons/CategoryIcon';
import {PresetCircleIcon} from '../../sharedComponents/icons/PresetIcon';
import {useNavigationFromRoot} from '../../hooks/useNavigationWithTypes';
import {useDraftObservation} from '../../hooks/useDraftObservation';

Expand Down Expand Up @@ -32,7 +32,7 @@ export const PresetView = () => {
return (
<View style={styles.categoryContainer}>
<View style={styles.categoryIcon}>
<CategoryCircleIcon />
<PresetCircleIcon name={preset?.name} />
</View>
<Text style={styles.categoryName}>{name}</Text>
<TextButton
Expand Down
15 changes: 3 additions & 12 deletions src/frontend/screens/ObservationsList/ObservationListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import {StyleSheet, View} from 'react-native';
import {Text} from '../../sharedComponents/Text';

import {TouchableHighlight} from '../../sharedComponents/Touchables';
import {CategoryCircleIcon} from '../../sharedComponents/icons/CategoryIcon';
import {PresetCircleIcon} from '../../sharedComponents/icons/PresetIcon';
import {Attachment, ViewStyleProp} from '../../sharedTypes';
import {BLACK} from '../../lib/styles';
import {Observation} from '@mapeo/schema';
import {
FormattedObservationDate,
Expand Down Expand Up @@ -35,10 +34,6 @@ function ObservationListItemNotMemoized({
}: ObservationListItemProps) {
const {preset} = useObservationWithPreset(observation.docId);
const deviceId = '';
//const iconId = preset && preset.icon;
const iconId = '';
// const iconColor = preset && preset.color;
const iconColor = BLACK;

// const photos = !observationQuery.data ? [] : filterPhotosFromAttachments(
// observationQuery.data && observationQuery.data.attachments
Expand Down Expand Up @@ -69,15 +64,11 @@ function ObservationListItemNotMemoized({
<View style={styles.photoContainer}>
<PhotoStack attachments={observation.attachments} />
<View style={styles.smallIconContainer}>
<CategoryCircleIcon
iconId={iconId}
color={iconColor}
size="small"
/>
<PresetCircleIcon name={preset.name} size="small" />
</View>
</View>
) : (
<CategoryCircleIcon iconId={iconId} color={iconColor} size="medium" />
<PresetCircleIcon name={preset.name} size="medium" />
)}
</View>
</TouchableHighlight>
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/screens/PresetChooser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import {defineMessages, FormattedMessage} from 'react-intl';

import {useDraftObservation} from '../hooks/useDraftObservation';
import {CategoryCircleIcon} from '../sharedComponents/icons/CategoryIcon';
import {PresetCircleIcon} from '../sharedComponents/icons/PresetIcon';
import {WHITE} from '../lib/styles';
import {NativeNavigationComponent} from '../sharedTypes/navigation';
import {CustomHeaderLeftClose} from '../sharedComponents/CustomHeaderLeftClose';
Expand Down Expand Up @@ -118,7 +118,7 @@ const Item = React.memo(
underlayColor="#000033"
testID={`${item.docId}CategoryButton`}>
<View style={styles.cellContainer}>
<CategoryCircleIcon size="medium" />
<PresetCircleIcon size="medium" name={item.name} />
<Text numberOfLines={3} style={styles.categoryName}>
<DynFormattedMessage
id={`presets.${item.docId}.name`}
Expand Down
69 changes: 0 additions & 69 deletions src/frontend/sharedComponents/icons/CategoryIcon.tsx

This file was deleted.

53 changes: 53 additions & 0 deletions src/frontend/sharedComponents/icons/PresetIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, {memo} from 'react';
import {Image} from 'react-native';

import {Circle} from './Circle';
import {IconSize} from '../../sharedTypes';
import {UIActivityIndicator} from 'react-native-indicators';
import {useGetPresetIcon} from '../../hooks/server/presets';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';

interface PresetIconProps {
size?: IconSize;
name?: string;
}

const iconSizes = {
small: 22,
medium: 35,
large: 50,
};

const radii = {
small: 15,
medium: 25,
large: 35,
};

export const PresetIcon = memo<PresetIconProps>(({size = 'medium', name}) => {
const iconSize = iconSizes[size] || 35;
const {data, isLoading} = useGetPresetIcon(size, name);
const [error, setError] = React.useState(false);

if (isLoading) return <UIActivityIndicator size={30} />;

// Fallback to a default icon if we can't load the icon from mapeo-server
if (error || !name) return <MaterialIcon name="place" size={iconSize} />;

return (
<Image
style={{width: iconSize, height: iconSize}}
resizeMode="contain"
source={{uri: data}}
onError={() => setError(true)}
/>
);
});

export const PresetCircleIcon = ({name, size = 'medium'}: PresetIconProps) => {
return (
<Circle radius={radii[size]}>
<PresetIcon name={name} size={size} />
</Circle>
);
};

0 comments on commit 907d251

Please sign in to comment.