Skip to content

Commit

Permalink
Feature/clickable urls mobile (#1049) (#1050)
Browse files Browse the repository at this point in the history
* Make urls in messages clickable

* Bump babel runtime

* Remove leftover

* Lint fix
  • Loading branch information
siepra authored Nov 18, 2022
1 parent c5a3e88 commit 0b3cb81
Show file tree
Hide file tree
Showing 16 changed files with 831 additions and 914 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ module.exports = {
'@typescript-eslint/default-param-last': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-redeclare': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/dot-notation': 'off',
'generator-star-spacing': ['error', { before: false, after: true }],
'yield-star-spacing': ['error', { before: false, after: true }],
Expand Down
1,581 changes: 755 additions & 826 deletions packages/mobile/package-lock.json

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions packages/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"pvutils": "^1.0.17",
"react": "18.1.0",
"react-i18next": "^11.8.15",
"react-linkify": "^1.0.0-alpha",
"react-native": "0.70.4",
"react-native-blob-util": "^0.16.2",
"react-native-config": "^1.4.2",
Expand Down Expand Up @@ -71,13 +72,13 @@
"devDependencies": {
"@babel/core": "^7.12.9",
"@babel/preset-typescript": "^7.15.0",
"@babel/runtime": "^7.12.5",
"@babel/runtime": "^7.20.1",
"@react-native-community/eslint-config": "^2.0.0",
"@react-native-community/push-notification-ios": "^1.10.1",
"@storybook/addon-actions": "^6.2.9",
"@storybook/addon-controls": "^6.5.9",
"@storybook/addon-actions": "^6.5.13",
"@storybook/addon-controls": "^6.5.13",
"@storybook/addon-ondevice-actions": "^5.3.23",
"@storybook/addon-ondevice-knobs": "^5.3.25",
"@storybook/addon-ondevice-knobs": "^5.3.26",
"@storybook/react-native": "^5.3.25",
"@testing-library/react-native": "^7.2.0",
"@types/chalk": "^2.2.0",
Expand All @@ -91,7 +92,7 @@
"babel-jest": "^26.6.3",
"chalk": "^4.1.1",
"eslint": "^7.32.0",
"jest": "^26.6.3",
"jest": "^26.0.0",
"metro-react-native-babel-preset": "^0.72.3",
"node-libs-react-native": "^1.2.1",
"nodejs-mobile-gyp": "0.3.1",
Expand Down
8 changes: 6 additions & 2 deletions packages/mobile/src/components/Chat/Chat.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export const Chat: FC<ChatProps & FileActionsProps> = ({
downloadStatuses = {},
downloadFile,
cancelDownload,
openImagePreview
openImagePreview,
openUrl
}) => {
const [didKeyboardShow, setKeyboardShow] = useState(false)
const [messageInput, setMessageInput] = useState<string | undefined>()
Expand Down Expand Up @@ -75,6 +76,7 @@ export const Chat: FC<ChatProps & FileActionsProps> = ({
downloadFile={downloadFile}
cancelDownload={cancelDownload}
openImagePreview={openImagePreview}
openUrl={openUrl}
/>
)

Expand Down Expand Up @@ -137,7 +139,8 @@ export const ChannelMessagesComponent: React.FC<ChannelMessagesComponentProps &
downloadStatuses,
downloadFile,
cancelDownload,
openImagePreview
openImagePreview,
openUrl
}) => {
return (
<View key={day}>
Expand All @@ -152,6 +155,7 @@ export const ChannelMessagesComponent: React.FC<ChannelMessagesComponentProps &
downloadFile={downloadFile}
cancelDownload={cancelDownload}
openImagePreview={openImagePreview}
openUrl={openUrl}
pendingMessages={pendingMessages}
/>
})}
Expand Down
2 changes: 2 additions & 0 deletions packages/mobile/src/components/Chat/Chat.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface ChatProps {
pendingMessages?: Dictionary<MessageSendingStatus>
downloadStatuses?: Dictionary<DownloadStatus>
openImagePreview?: (media: FileMetadata) => void
openUrl?: (url: string) => void
}

export interface ChannelMessagesComponentProps {
Expand All @@ -28,4 +29,5 @@ export interface ChannelMessagesComponentProps {
pendingMessages?: Dictionary<MessageSendingStatus>
downloadStatuses?: Dictionary<DownloadStatus>
openImagePreview?: (media: FileMetadata) => void
openUrl?: (url: string) => void
}
40 changes: 24 additions & 16 deletions packages/mobile/src/components/Message/Message.component.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { FC } from 'react'
import { View, Image, StyleSheet, TouchableWithoutFeedback } from 'react-native'
import React, { FC, ReactNode } from 'react'
import { View, Image, StyleSheet } from 'react-native'
import { Typography } from '../Typography/Typography.component'
import { MessageProps } from './Message.types'
import Jdenticon from 'react-native-jdenticon'
Expand All @@ -8,19 +8,26 @@ import { MessageType, AUTODOWNLOAD_SIZE_LIMIT, DisplayableMessage } from '@quiet
import { UploadedImage } from '../UploadedImage/UploadedImage.component'
import { UploadedFile } from '../UploadedFile/UploadedFile.component'
import { FileActionsProps } from '../UploadedFile/UploadedFile.types'
import Linkify from 'react-linkify'

export const Message: FC<MessageProps & FileActionsProps> = ({
data,
data, // Set of messages merged by sender
downloadStatus,
downloadFile,
cancelDownload,
openImagePreview,
openUrl,
pendingMessages
}) => {
const messageDisplayData = data[0]
const renderMessage = (message: DisplayableMessage) => {
const isPendingMessage = pendingMessages[message.id] !== undefined
const componentDecorator = (decoratedHref: string, decoratedText: string, key: number): ReactNode => {
return (
<Typography fontSize={14} color={'link'} onPress={ () => openUrl(decoratedHref) } key={key}>
{decoratedText}
</Typography>
)
}

const renderMessage = (message: DisplayableMessage, pending: boolean) => {
switch (message.type) {
case 2: // MessageType.Image (cypress tests incompatibility with enums)
const size = message?.media?.size
Expand All @@ -40,16 +47,17 @@ export const Message: FC<MessageProps & FileActionsProps> = ({
)
default:
return (
<Typography fontSize={14} color={ isPendingMessage ? 'lightGray' : 'main' }>{message.message}</Typography>
)
<Typography fontSize={14} color={ pending ? 'lightGray' : 'main' }><Linkify componentDecorator={componentDecorator}>{message.message}</Linkify></Typography>
)
}
}

const infoMessage = messageDisplayData.type === MessageType.Info
const representativeMessage = data[0]

const pending: boolean = pendingMessages[messageDisplayData.id] !== undefined
const info = representativeMessage.type === MessageType.Info
const pending: boolean = pendingMessages?.[representativeMessage.id] !== undefined

return (
return (
<View style={{ flex: 1 }}>
<View
style={{
Expand All @@ -62,22 +70,22 @@ export const Message: FC<MessageProps & FileActionsProps> = ({
alignItems: 'center',
paddingRight: 15
}}>
{infoMessage ? (
{info ? (
<Image
resizeMode='cover'
resizeMethod='resize'
source={appImages.quiet_icon}
style={{ width: 37, height: 37 }}
/>
) : (
<Jdenticon value={messageDisplayData.nickname} size={37} style={{ padding: 0 }} />
<Jdenticon value={representativeMessage.nickname} size={37} style={{ padding: 0 }} />
)}
</View>
<View style={{ flex: 8 }}>
<View style={{ flexDirection: 'row', paddingBottom: 3 }}>
<View style={{ alignSelf: 'flex-start' }}>
<Typography fontSize={16} fontWeight={'medium'} color={ pending ? 'lightGray' : 'main' }>
{infoMessage ? 'Quiet' : messageDisplayData.nickname}
{info ? 'Quiet' : representativeMessage.nickname}
</Typography>
</View>
<View
Expand All @@ -87,7 +95,7 @@ export const Message: FC<MessageProps & FileActionsProps> = ({
paddingLeft: 8
}}>
<Typography fontSize={14} color={'subtitle'}>
{messageDisplayData.date}
{representativeMessage.date}
</Typography>
</View>
</View>
Expand All @@ -96,7 +104,7 @@ export const Message: FC<MessageProps & FileActionsProps> = ({
const outerDivStyle = index > 0 ? classes.nextMessage : classes.firstMessage
return (
<View style={outerDivStyle} key={index}>
{renderMessage(message)}
{renderMessage(message, pending)}
</View>
)
})}
Expand Down
21 changes: 21 additions & 0 deletions packages/mobile/src/components/Message/Message.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,24 @@ storiesOf('Message', module).add('Default', () => {
/>
)
})
.add('Link', () => {
const openUrl = (url: string) => {
console.log(`opened url ${url}`)
}
return (
<Message
data={[
{
id: '1',
type: MessageType.Info,
message:
'Check this out https://github.com/orgs/TryQuiet/projects/1',
createdAt: 0,
date: '1:30pm',
nickname: 'holmes'
}
]}
openUrl={openUrl}
/>
)
})
1 change: 1 addition & 0 deletions packages/mobile/src/components/Message/Message.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export interface MessageProps {
pendingMessages?: Dictionary<MessageSendingStatus>
downloadStatus?: DownloadStatus
openImagePreview?: (medi: FileMetadata) => void
openUrl?: (url: string) => void
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { StyledTypography } from './Typography.styles'
import { TypographyProps } from './Typography.types'

export const Typography: FC<TypographyProps> = ({
onPress,
children,
fontSize,
fontWeight,
Expand All @@ -14,6 +15,7 @@ export const Typography: FC<TypographyProps> = ({
numberOfLines
}) => (
<StyledTypography
onPress={onPress}
color={color}
fontSize={fontSize}
fontWeight={fontWeight}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Text } from 'react-native'
import styled, { css } from 'styled-components/native'
import { StyledTypographyProps } from './Typography.types'
import { getFontFamily } from './Typography.utils'
import { defaultTheme } from '../../styles/themes/default.theme'

export const StyledTypography = styled(Text).attrs(
(props: StyledTypographyProps) => ({
Expand All @@ -11,14 +12,13 @@ export const StyledTypography = styled(Text).attrs(
})
)<StyledTypographyProps>`
${({
theme,
fontSize,
fontWeight,
color,
verticalTextAlign,
horizontalTextAlign
}) => css`
color: ${theme.palette.typography[color]};
color: ${defaultTheme.palette.typography[color]};
font-family: ${getFontFamily(fontWeight)};
font-size: ${fontSize}px;
text-align: ${horizontalTextAlign};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type FontWeight = 'bold' | 'medium' | 'thin' | 'normal'

export interface TypographyProps {
// color?: keyof Palette['typography'];
onPress?: () => void
color?: string
fontSize: number
fontWeight?: FontWeight
Expand Down
8 changes: 7 additions & 1 deletion packages/mobile/src/screens/Channel/Channel.screen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { FC, useCallback, useEffect, useState } from 'react'
import { BackHandler, View } from 'react-native'
import { BackHandler, Linking, View } from 'react-native'
import { useDispatch, useSelector } from 'react-redux'
import { Appbar } from '../../components/Appbar/Appbar.component'
import { Chat } from '../../components/Chat/Chat.component'
Expand Down Expand Up @@ -67,6 +67,11 @@ export const ChannelScreen: FC = () => {

const [imagePreview, setImagePreview] = useState<FileMetadata>(null)

const openUrl = useCallback((url: string) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Linking.openURL(url)
}, [])

return (
<>
<View style={{ flex: 1 }}>
Expand All @@ -87,6 +92,7 @@ export const ChannelScreen: FC = () => {
downloadFile={downloadFile}
cancelDownload={cancelDownload}
openImagePreview={setImagePreview}
openUrl={openUrl}
/>
<ImagePreviewModal
imagePreviewData={imagePreview}
Expand Down
1 change: 1 addition & 0 deletions packages/mobile/src/styles/palettes/default.palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const defaultPalette = {
typography: {
main: '#000000',
subtitle: '#999999',
link: '#67BFD3',
hint: '#999999',
error: '#E42656',
grayLight: '#B8B8B8',
Expand Down
6 changes: 1 addition & 5 deletions packages/mobile/storybook/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,15 @@ import {
} from '@storybook/react-native'

import { withNavigation } from './navigationDecorator'
import { withLanguagePicker } from './withLanguagePicker'
import { withThemePicker } from './withThemePicker'

LogBox.ignoreAllLogs()

addDecorator(withKnobs)
addDecorator(withLanguagePicker)
addDecorator(withNavigation)
addDecorator(withThemePicker)

configure(() => {
require('../src/components/JoinCommunity/JoinCommunity.stories')
require('../src/components/Appbar/Appbar.stories')
require('../src/components/Appbar/Appbar.stories')
require('../src/components/Registration/UsernameRegistration.stories')
require('../src/components/ChannelTile/ChannelTile.stories')
require('../src/components/ChannelList/ChannelList.stories')
Expand Down
29 changes: 0 additions & 29 deletions packages/mobile/storybook/withLanguagePicker.js

This file was deleted.

28 changes: 0 additions & 28 deletions packages/mobile/storybook/withThemePicker.js

This file was deleted.

0 comments on commit 0b3cb81

Please sign in to comment.