Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kg deep linking #116

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="https"
android:host="gitter.im" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
Expand Down
12 changes: 12 additions & 0 deletions app/api/gitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ export function currentUserSuggested(token, id) {
return callApi(endpoint, token)
}

/**
* Groups
*/

export function groupRooms(token, id) {
return callApi(`groups/${id}/rooms`, token)
}

/**
* Rooms resource
*/
Expand All @@ -71,6 +79,10 @@ export function room(token, id) {
return callApi('rooms/' + id, token)
}

export function roomsByUri(token, uri) {
return callApi(`rooms?q=${uri}`, token)
}

export function roomMessages(token, id, limit) {
return callApi(`rooms/${id}/chatMessages?limit=${limit}`, token)
}
Expand Down
6 changes: 3 additions & 3 deletions app/components/ParsedText/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import PropTypes from 'prop-types'
import React from 'react'
import {Text} from 'react-native';
import {Text, Linking} from 'react-native'
import Parser from 'react-native-parsed-text'
import Emoji from '../Emoji'
import s from './styles'
Expand Down Expand Up @@ -33,9 +33,9 @@ const renderCodespan = (matchingString, matches) => {
return component
}

const ParsedText = ({text, username, handleUrlPress}) => {
const ParsedText = ({text, username}) => {
const patterns = [
{type: 'url', style: s.url, onPress: handleUrlPress},
{type: 'url', style: s.url, onPress: (url) => Linking.openURL(url)},
{pattern: new RegExp(`@${username}`), style: s.selfMention},
{pattern: MENTION_REGEX, style: s.mention},
{pattern: GROUP_MENTION_REGEX, style: s.groupMention},
Expand Down
7 changes: 7 additions & 0 deletions app/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,10 @@ export const icons = {
'forward': iOS ? {icon: 'chevron-right', color: 'white', size: 40} : {icon: 'arrow-forward', color: 'white', size: 24},
'expand-more': {icon: 'expand-more', color: 'white', size: 24}
}

export const GITTER_REGEXPS = {
baseUrl: /\bhttps:\/\/gitter.im\/\b/,
roomParamsExp: /([a-zA-Z0-9]+)\/\b([a-zA-Z0-9]+)\b/,
messageParamsExp: /\b([a-zA-Z0-9/]+)\b\?at=([a-z0-9]{24})/,
groupParamsExp: /([a-zA-Z0-9]+)\/\bhome\b/
}
135 changes: 135 additions & 0 deletions app/modules/groups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import _ from 'lodash'
import * as Api from '../api/gitter'
import {LOGOUT} from './auth'

/**
* Action Creators
*/

export const GROUP_ROOMS = 'groups/GROUPS_ROOMS'
export const GROUP_ROOMS_RECEIVED = 'groups/GROUP_ROOMS_RECEIVED'
export const GROUP_FOUND = 'groups/GROUP_FOUND'
export const GROUP_ROOMS_FAILED = 'groups/GROUP_ROOMS_FAILED'
const func = () => {}

export function getGroupIdByName(groupName, navigateOnSuccess = func, handleError = func) {
return async (dispatch, getState) => {
try {
const {token} = getState().auth
const {results: rooms} = await Api.roomsByUri(token, groupName)
const groupRegExp = new RegExp(`\\b${groupName}\/`)

if (!rooms) {
throw new Error('Probably such group is not exist.')
}

// Get group id
const matchedGroup = _.find(rooms, ({uri}) => groupRegExp.test(uri))

if (!matchedGroup) {
throw new Error(`Group '${groupName}' not found.`)
}

const payload = {
id: matchedGroup.groupId,
name: groupName
}

dispatch({type: GROUP_FOUND, payload})
navigateOnSuccess(matchedGroup.groupId)
} catch (error) {
handleError(error)
}
}
}

export function getGroupRooms(groupId) {
return async (dispatch, getState) => {
dispatch({type: GROUP_ROOMS})

try {
const {token} = getState().auth

const results = await Api.groupRooms(token, groupId)
const payload = {
groupId,
rooms: results
}

dispatch({type: GROUP_ROOMS_RECEIVED, payload})
} catch (error) {
dispatch({type: GROUP_ROOMS_FAILED, error})
}
}
}

/**
* Reducer
*/

const initialState = {
isLoading: false,
ids: [],
groups: {},
error: false,
errors: []
}

export default function groups(state = initialState, action) {
switch (action.type) {
case GROUP_ROOMS: {
return {...state,
isLoading: true
}
}

case GROUP_FOUND: {
const groupId = action.payload.id
const group = state.groups[groupId]

return {...state,
isLoading: false,
ids: state.ids.concat(groupId),
groups: {
...state.groups,
[groupId]: {
...group,
...action.payload
}
}
}
}

case GROUP_ROOMS_RECEIVED: {
const currentGroupId = action.payload.groupId
const group = state.groups[currentGroupId]

return {...state,
isLoading: false,
ids: state.ids.concat(currentGroupId),
groups: {
...state.groups,
[currentGroupId]: {
...group,
rooms: action.payload.rooms
}
}
}
}

case GROUP_ROOMS_FAILED: {
return {...state,
isLoading: false,
error: true,
errors: action.error
}
}

case LOGOUT: {
return initialState
}

default :
return state
}
}
2 changes: 2 additions & 0 deletions app/modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import settings from './settings'
import realtime from './realtime'
import activity from './activity'
import navigation from './navigation'
import groups from './groups'

const rootReducer = combineReducers({
ui,
Expand All @@ -29,6 +30,7 @@ const rootReducer = combineReducers({
settings,
realtime,
activity,
groups,
navigation
})

Expand Down
18 changes: 12 additions & 6 deletions app/modules/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ export function getRoomMessagesIfNeeded(roomId) {
export function receiveRoomMessagesSnapshot(roomId, snapshot) {
return (dispatch, getState) => {
const listView = getState().messages.listView[roomId]
if (!listView.data.length | !snapshot.length) {
if (!listView || !listView.data.length || !snapshot.length) {
return
}

const index = _.findIndex(snapshot, listView.data[0])
if (index === -1 | index === 29) {
if (index === -1 || index === 29) {
return
}

Expand Down Expand Up @@ -297,8 +297,8 @@ export function deleteFailedMessage(rowId, roomId) {

export function getSingleMessage(roomId, messageId) {
return async (dispatch, getState) => {
dispatch({type: SINGLE_MESSAGE})
const {token} = getState().auth
dispatch({type: SINGLE_MESSAGE, roomId, messageId})

try {
const payload = await Api.getMessage(token, roomId, messageId)
Expand Down Expand Up @@ -358,6 +358,7 @@ const initialState = {
// [id]: bool
},
isLoadingMessage: false,
singleMessageError: false,
messages: {}
}

Expand Down Expand Up @@ -752,12 +753,12 @@ export default function messages(state = initialState, action) {
case SINGLE_MESSAGE_OK:
return {...state,
isLoadingMessage: false,
messages: {...state.messages,
entities: {...state.entities,
[action.messageId]: action.payload
}
},
singleMessageError: false
}

case SINGLE_MESSAGE_ERROR:
case ROOM_MESSAGES_BEFORE_FAILED:
case ROOM_MESSAGES_FAILED:
return {...state,
Expand All @@ -768,6 +769,11 @@ export default function messages(state = initialState, action) {
errors: action.error
}

case SINGLE_MESSAGE_ERROR:
return {...state,
singleMessageError: true
}

default:
return state
}
Expand Down
26 changes: 26 additions & 0 deletions app/modules/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const GET_NOTIFICATION_SETTINGS_OK = 'rooms/GET_NOTIFICATION_SETTINGS_OK'
export const GET_NOTIFICATION_SETTINGS_ERROR = 'rooms/GET_NOTIFICATION_SETTINGS_ERROR'
export const CHANGE_NOTIFICATION_SETTINGS_OK = 'rooms/CHANGE_NOTIFICATION_SETTINGS_OK'
export const CHANGE_NOTIFICATION_SETTINGS_ERROR = 'rooms/CHANGE_NOTIFICATION_SETTINGS_ERROR'
const func = () => {}

/**
* Action Creators
Expand Down Expand Up @@ -93,6 +94,30 @@ export function getRoom(id) {
}
}

/**
* Return room by uri
*/

export function getRoomByUrl(url, navigateOnSuccess = func, handleError = func) {
return async (dispatch, getState) => {
const {token} = getState().auth
dispatch({type: ROOM})
try {
const {results: [room]} = await Api.roomsByUri(token, url)
if (!room) {
throw new Error('Room not found.')
}

dispatch({type: ROOM_RECEIVED, payload: room})

navigateOnSuccess(room.id)
} catch (error) {
handleError(error)
dispatch({type: ROOM_FAILED, error})
}
}
}

/**
* Returns suggested rooms by user id
*/
Expand Down Expand Up @@ -172,6 +197,7 @@ export function joinUserRoom(username) {
const payload = await Api.joinRoomByUserName(token, username)

dispatch({type: JOIN_USER_ROOM_OK, payload})
return Promise.resolve(payload)
} catch (error) {
dispatch({type: JOIN_USER_ROOM_FAILED, error})
}
Expand Down
Loading