Refactoring to see if (and how easy) it is to use the same chat component (with its properties) in 2 different contextes.
This commit is contained in:
parent
9bb2f48d4a
commit
dca68e17e4
|
@ -1,11 +1,7 @@
|
||||||
import { locationOutline } from 'ionicons/icons';
|
|
||||||
import React, { useId } from 'react';
|
import React, { useId } from 'react';
|
||||||
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { geoPoint, lat2tile, lon2tile, Point } from '../../lib/geo';
|
import { geoPoint, lat2tile, lon2tile, Point } from '../../lib/geo';
|
||||||
|
|
||||||
import { MapState } from '../../store/map';
|
|
||||||
import { getSTile } from './Reticle';
|
|
||||||
import { tileProviders } from './tile';
|
import { tileProviders } from './tile';
|
||||||
|
|
||||||
interface AvatarForLocationProps {
|
interface AvatarForLocationProps {
|
||||||
|
|
|
@ -12,24 +12,12 @@ import {
|
||||||
IonSpinner,
|
IonSpinner,
|
||||||
} from '@ionic/react';
|
} from '@ionic/react';
|
||||||
import React, { Fragment, useRef, useState } from 'react';
|
import React, { Fragment, useRef, useState } from 'react';
|
||||||
import {
|
|
||||||
MainContainer,
|
|
||||||
Sidebar,
|
|
||||||
ConversationList,
|
|
||||||
Conversation,
|
|
||||||
ConversationHeader,
|
|
||||||
ChatContainer,
|
|
||||||
MessageList,
|
|
||||||
Message,
|
|
||||||
Avatar,
|
|
||||||
} from '@chatscope/chat-ui-kit-react';
|
|
||||||
import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
|
|
||||||
|
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import { geoPoint } from '../../lib/geo';
|
import { geoPoint } from '../../lib/geo';
|
||||||
import { MapState } from '../../store/map';
|
import { MapState } from '../../store/map';
|
||||||
import AvatarForLocation from './AvatarForLocation';
|
import OsmNotesChat from './OsmNotesChat';
|
||||||
|
|
||||||
const LocationInfo: React.FC<{}> = () => {
|
const LocationInfo: React.FC<{}> = () => {
|
||||||
const scope = useSelector((state: { map: MapState }) => state.map.scope);
|
const scope = useSelector((state: { map: MapState }) => state.map.scope);
|
||||||
|
@ -72,10 +60,17 @@ const LocationInfo: React.FC<{}> = () => {
|
||||||
console.log(`address: ${JSON.stringify(data)}`);
|
console.log(`address: ${JSON.stringify(data)}`);
|
||||||
setAddress(data);
|
setAddress(data);
|
||||||
};
|
};
|
||||||
|
const roughDistance = (a: geoPoint, b: geoPoint): number => {
|
||||||
|
const pseudoDistanceInDegrees = Math.sqrt(
|
||||||
|
(a.lat - b.lat) ** 2 + (a.lon - b.lon) ** 2
|
||||||
|
);
|
||||||
|
const metresPerDegree =
|
||||||
|
111111 * Math.cos((scope.center.lat * Math.PI) / 180);
|
||||||
|
return pseudoDistanceInDegrees * metresPerDegree;
|
||||||
|
};
|
||||||
|
|
||||||
const findNotes = async () => {
|
const findNotes = async () => {
|
||||||
setNotes(undefined);
|
setNotes(undefined);
|
||||||
setNoteIndex(0);
|
|
||||||
const metresPerDegree =
|
const metresPerDegree =
|
||||||
111111 * Math.cos((scope.center.lat * Math.PI) / 180);
|
111111 * Math.cos((scope.center.lat * Math.PI) / 180);
|
||||||
const deltaDegrees = 5000 / metresPerDegree;
|
const deltaDegrees = 5000 / metresPerDegree;
|
||||||
|
@ -109,15 +104,6 @@ const LocationInfo: React.FC<{}> = () => {
|
||||||
findNotes();
|
findNotes();
|
||||||
};
|
};
|
||||||
|
|
||||||
const roughDistance = (a: geoPoint, b: geoPoint): number => {
|
|
||||||
const pseudoDistanceInDegrees = Math.sqrt(
|
|
||||||
(a.lat - b.lat) ** 2 + (a.lon - b.lon) ** 2
|
|
||||||
);
|
|
||||||
const metresPerDegree =
|
|
||||||
111111 * Math.cos((scope.center.lat * Math.PI) / 180);
|
|
||||||
return pseudoDistanceInDegrees * metresPerDegree;
|
|
||||||
};
|
|
||||||
|
|
||||||
const localDate = (isoDate: string) => {
|
const localDate = (isoDate: string) => {
|
||||||
const date = new Date(isoDate);
|
const date = new Date(isoDate);
|
||||||
const format = new Intl.DateTimeFormat(i18n.getLanguage(), {
|
const format = new Intl.DateTimeFormat(i18n.getLanguage(), {
|
||||||
|
@ -127,32 +113,12 @@ const LocationInfo: React.FC<{}> = () => {
|
||||||
return format.format(date);
|
return format.format(date);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [noteIndex, setNoteIndex] = useState(0);
|
const osmNotesChat =
|
||||||
const conversationClickHandlerFactory = (index: number) => (event: any) => {
|
notes !== undefined && notes.features.length ? (
|
||||||
setNoteIndex(index);
|
<OsmNotesChat notes={notes} />
|
||||||
};
|
) : (
|
||||||
|
<></>
|
||||||
const AvatarForFeature: React.FC<{
|
|
||||||
feature: any;
|
|
||||||
size: number;
|
|
||||||
as: any;
|
|
||||||
}> = (props: { feature: any; size: number; as: any }) => {
|
|
||||||
const distance = roughDistance(scope.center, {
|
|
||||||
lon: props.feature.geometry.coordinates[0],
|
|
||||||
lat: props.feature.geometry.coordinates[1],
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<Avatar size={props.size <= 50 ? 'sm' : 'lg'}>
|
|
||||||
<AvatarForLocation
|
|
||||||
location={{
|
|
||||||
lon: props.feature.geometry.coordinates[0],
|
|
||||||
lat: props.feature.geometry.coordinates[1],
|
|
||||||
}}
|
|
||||||
size={props.size}
|
|
||||||
/>
|
|
||||||
</Avatar>
|
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IonModal
|
<IonModal
|
||||||
|
@ -210,88 +176,7 @@ const LocationInfo: React.FC<{}> = () => {
|
||||||
{notes === undefined && <IonSpinner name='lines' />}
|
{notes === undefined && <IonSpinner name='lines' />}
|
||||||
</IonLabel>
|
</IonLabel>
|
||||||
</IonListHeader>
|
</IonListHeader>
|
||||||
{notes !== undefined && notes.features.length > 0 && (
|
{osmNotesChat}
|
||||||
<div style={{ position: 'relative' }}>
|
|
||||||
<MainContainer responsive>
|
|
||||||
<Sidebar position='left' id='chat-sidebar'>
|
|
||||||
<ConversationList>
|
|
||||||
{notes
|
|
||||||
.features!.slice(0, 5)
|
|
||||||
.map((feature: any, index: number) => (
|
|
||||||
<Conversation
|
|
||||||
onClick={conversationClickHandlerFactory(index)}
|
|
||||||
key={feature.properties.id}
|
|
||||||
name={i18n.locationInfo!.at!(
|
|
||||||
roughDistance(scope.center, {
|
|
||||||
lon: feature.geometry.coordinates[0],
|
|
||||||
lat: feature.geometry.coordinates[1],
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
info={feature.properties.status}
|
|
||||||
>
|
|
||||||
<AvatarForFeature
|
|
||||||
feature={feature}
|
|
||||||
size={42}
|
|
||||||
as={Avatar}
|
|
||||||
/>
|
|
||||||
</Conversation>
|
|
||||||
))}
|
|
||||||
</ConversationList>
|
|
||||||
</Sidebar>
|
|
||||||
<ChatContainer>
|
|
||||||
<ConversationHeader>
|
|
||||||
<AvatarForFeature
|
|
||||||
feature={notes.features[noteIndex]}
|
|
||||||
size={68}
|
|
||||||
as={Avatar}
|
|
||||||
/>
|
|
||||||
<ConversationHeader.Content>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
alignSelf: 'flex-center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{i18n.locationInfo!.at!(
|
|
||||||
roughDistance(scope.center, {
|
|
||||||
lon: notes.features[noteIndex].geometry
|
|
||||||
.coordinates[0],
|
|
||||||
lat: notes.features[noteIndex].geometry
|
|
||||||
.coordinates[1],
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</ConversationHeader.Content>
|
|
||||||
</ConversationHeader>
|
|
||||||
<MessageList>
|
|
||||||
{noteIndex < notes.features.length &&
|
|
||||||
notes.features[noteIndex].properties.comments.map(
|
|
||||||
(comment: any, index: number) => (
|
|
||||||
<Message
|
|
||||||
key={`${notes.features[noteIndex].properties.id}/${index}`}
|
|
||||||
model={{
|
|
||||||
direction: 'incoming',
|
|
||||||
position: 'single',
|
|
||||||
sender: comment.user,
|
|
||||||
sentTime: comment.date,
|
|
||||||
payload: comment.html,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Message.Header
|
|
||||||
sender={comment.user}
|
|
||||||
sentTime={comment.date}
|
|
||||||
/>
|
|
||||||
<Message.Footer sentTime={comment.action} />
|
|
||||||
<Avatar>
|
|
||||||
{comment.user ? comment.user : '??'}
|
|
||||||
</Avatar>
|
|
||||||
</Message>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</MessageList>
|
|
||||||
</ChatContainer>
|
|
||||||
</MainContainer>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</IonList>
|
</IonList>
|
||||||
</IonContent>
|
</IonContent>
|
||||||
</IonModal>
|
</IonModal>
|
||||||
|
|
Loading…
Reference in New Issue