This repository has been archived by the owner on Mar 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Support for Renaming Threads (#1084)
* Refactored some group code. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Added rename-group to features. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Added button to group screen that goes to RenameGroup screen. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Styled rename group container. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Successfully makes API call to rename group. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Navigate to thread after renaming it. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Convert RenameGroup compoonent into a modal. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Refresh thread after changing its name. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Close modal upon completion. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed linting issues and missing imports. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed linting issues. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Switched to using yarn. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed some review issues. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed renaming threads workflow, styling. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed disabled opacity. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Use constants for fontFamily styling. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Added types to styles, moved them into container where they are used. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed consecutive blank lines. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Added test for rename-group reducer. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fixed bug in success test. Signed-off-by: Thomas Hobohm <public@thomashobohm.com> * Fleshed out tests, fixed snapshot. Signed-off-by: Thomas Hobohm <public@thomashobohm.com>
- Loading branch information
Showing
16 changed files
with
371 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
/* | ||
Container to rename a group. | ||
URL: "RenameGroup" | ||
Parameters: | ||
- threadId: the ID of the group to be renamed | ||
When the user submits a new name or presses back, they are taken back to the | ||
group screen. | ||
*/ | ||
|
||
import React from 'react' | ||
import { Dispatch } from 'redux' | ||
import { connect } from 'react-redux' | ||
|
||
import { | ||
View, | ||
Text, | ||
TouchableOpacity, | ||
ViewStyle, | ||
TextStyle | ||
} from 'react-native' | ||
import Modal from 'react-native-modal' | ||
import { color, spacing, size, fontSize, fontFamily } from '../styles' | ||
|
||
import { TextileHeaderButtons, Item as TextileHeaderButtonsItem } from '../Components/HeaderButtons' | ||
import Button from '../Components/LargeButton' | ||
import Input from '../SB/components/Input' | ||
|
||
import { RootState, RootAction } from '../Redux/Types' | ||
import { groupActions } from '../features/group' | ||
|
||
const container: ViewStyle = { | ||
flex: 1, | ||
backgroundColor: color.grey_6, | ||
flexDirection: 'column', | ||
justifyContent: 'center', | ||
alignItems: 'stretch', | ||
padding: spacing._024 | ||
} | ||
|
||
const inputStyle: TextStyle = { | ||
height: size._064, | ||
fontSize: fontSize._20, | ||
color: color.grey_1 | ||
} | ||
|
||
const buttonContainer: ViewStyle = { | ||
flex: 1, | ||
justifyContent: 'center', | ||
alignItems: 'center' | ||
} | ||
|
||
const buttons: ViewStyle = { | ||
marginTop: spacing._048, | ||
flexDirection: 'row', | ||
justifyContent: 'center', | ||
alignItems: 'center' | ||
} | ||
|
||
const cancelButtonText: TextStyle = { | ||
color: color.grey_2, | ||
fontSize: fontSize._20, | ||
fontFamily: fontFamily.regular, | ||
textAlign: 'center' | ||
} | ||
|
||
const confirmButtonText: TextStyle = { | ||
color: color.action_2, | ||
fontSize: fontSize._20, | ||
fontFamily: fontFamily.regular, | ||
textAlign: 'center' | ||
} | ||
|
||
interface StateProps { | ||
renaming: boolean | ||
} | ||
|
||
interface DispatchProps { | ||
rename: (newName: string) => void | ||
} | ||
|
||
interface ModalProps { | ||
isVisible: boolean | ||
threadId: string | ||
groupName: string | ||
cancel: () => void | ||
complete: () => void | ||
} | ||
|
||
interface State { | ||
newName: string, | ||
startedRename: boolean | ||
} | ||
|
||
type Props = StateProps & DispatchProps & ModalProps | ||
|
||
class RenameGroupModal extends React.Component<Props, State> { | ||
|
||
constructor(props: Props) { | ||
super(props) | ||
this.state = { | ||
newName: props.groupName, | ||
startedRename: false | ||
} | ||
} | ||
|
||
componentDidUpdate() { | ||
if (this.state.startedRename && !this.props.renaming) { | ||
this.setState({ | ||
startedRename: false | ||
}) | ||
this.props.complete() | ||
} | ||
} | ||
|
||
render() { | ||
const groupName = this.props.groupName | ||
const disabled = this.state.newName === '' || this.props.renaming | ||
return ( | ||
<Modal | ||
isVisible={this.props.isVisible} | ||
animationIn={'fadeInUp'} | ||
animationOut={'fadeOutDown'} | ||
avoidKeyboard={true} | ||
backdropOpacity={0} | ||
style={{margin: 0, padding: 0}} | ||
> | ||
<View style={container}> | ||
<Input | ||
style={inputStyle} | ||
value={this.state.newName} | ||
label={this.state.newName === '' ? 'Change the group name' : ''} | ||
onChangeText={this.handleNewText} | ||
/> | ||
<View style={buttons}> | ||
<TouchableOpacity | ||
style={buttonContainer} | ||
onPress={this.props.cancel} | ||
> | ||
<Text style={cancelButtonText}>Cancel</Text> | ||
</TouchableOpacity> | ||
<TouchableOpacity | ||
style={[buttonContainer, disabled ? { opacity: 0.2 } : {}]} | ||
disabled={disabled} | ||
onPress={this.rename} | ||
> | ||
<Text style={confirmButtonText}>Rename</Text> | ||
</TouchableOpacity> | ||
</View> | ||
</View> | ||
</Modal> | ||
) | ||
} | ||
|
||
handleNewText = (text: string) => { | ||
this.setState({ | ||
newName: text | ||
}) | ||
} | ||
|
||
rename = () => { | ||
this.props.rename(this.state.newName) | ||
this.setState({ | ||
startedRename: true | ||
}) | ||
} | ||
} | ||
|
||
const mapStateToProps = (state: RootState, ownProps: ModalProps): StateProps => { | ||
const threadId = ownProps.threadId | ||
const renaming = Object.keys(state.group.renameGroup).indexOf(threadId) > -1 | ||
return { | ||
renaming | ||
} | ||
} | ||
|
||
const mapDispatchToProps = (dispatch: Dispatch<RootAction>, ownProps: ModalProps): DispatchProps => { | ||
const threadId = ownProps.threadId | ||
return { | ||
rename: (newName: string) => { dispatch(groupActions.renameGroup.renameGroup.request({ threadId, name: newName })) } | ||
} | ||
} | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(RenameGroupModal) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import { feedActions as feed } from './feed' | ||
import { addMessageActions as addMessage } from './add-message' | ||
import { addPhotoActions as addPhoto } from './add-photo' | ||
import { renameGroupActions as renameGroup } from './rename-group' | ||
|
||
export { feed, addMessage, addPhoto } | ||
export { feed, addMessage, addPhoto, renameGroup } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,20 @@ | ||
import { createAsyncAction } from 'typesafe-actions' | ||
|
||
export interface AddMessagePayload { | ||
id: string | ||
groupId: string | ||
} | ||
|
||
export interface AddMessageRequestPayload extends AddMessagePayload { | ||
body: string | ||
} | ||
|
||
export interface AddMessageFailurePayload extends AddMessagePayload { | ||
error: any | ||
} | ||
|
||
export const addMessage = createAsyncAction( | ||
'group/add-message/ADD_MESSAGE_REQUEST', | ||
'group/add-message/ADD_MESSAGE_SUCCESS', | ||
'group/add-message/ADD_MESSAGE_FAILURE' | ||
)<{ id: string, groupId: string, body: string }, { id: string, groupId: string }, { id: string, groupId: string, error: any }>() | ||
)<AddMessageRequestPayload, AddMessagePayload, AddMessageFailurePayload>() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
import { combineReducers } from 'redux' | ||
import { ActionType, getType } from 'typesafe-actions' | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
App/features/group/rename-group/__snapshots__/reducer.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`renaming groups initial state should match snapshot 1`] = `Object {}`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { createAsyncAction } from 'typesafe-actions' | ||
|
||
export const renameGroup = createAsyncAction( | ||
'group/rename-group/RENAME_GROUP_REQUEST', | ||
'group/rename-group/RENAME_GROUP_SUCCESS', | ||
'group/rename-group/RENAME_GROUP_FAILURE' | ||
)<{ threadId: string, name: string }, { threadId: string }, { threadId: string, error: any }>() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import * as renameGroupActions from './actions' | ||
import renameGroupReducer, { RenameGroupState, RenameGroupAction } from './reducer' | ||
import renameGroupSaga from './sagas' | ||
|
||
export { renameGroupActions, renameGroupReducer, RenameGroupState, RenameGroupAction, renameGroupSaga } |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
renameGroupReducer as reducer, | ||
renameGroupActions as actions | ||
} from './' | ||
|
||
const threadId1 = 'id1' | ||
const threadId2 = 'id2' | ||
const name1 = 'name1' | ||
const name2 = 'name2' | ||
const error = 'error' | ||
const initialState = reducer(undefined, {} as any) | ||
|
||
describe('renaming groups', () => { | ||
describe('initial state', () => { | ||
it('should match snapshot', () => { | ||
expect(initialState).toMatchSnapshot() | ||
}) | ||
}) | ||
describe('request to rename group', () => { | ||
it('should manage async renaming the group', () => { | ||
const state0 = reducer(initialState, actions.renameGroup.request({ threadId: threadId1, name: name1 })) | ||
expect(state0[threadId1]).toBeDefined() | ||
const state1 = reducer(state0, actions.renameGroup.success({ threadId: threadId1 })) | ||
expect(state1[threadId1]).toBeUndefined() | ||
const state2 = reducer(state1, actions.renameGroup.request({ threadId: threadId2, name: name2 })) | ||
expect(state2[threadId2]).toBeDefined() | ||
const state3 = reducer(state2, actions.renameGroup.failure({ threadId: threadId2, error })) | ||
expect(state3[threadId2].error).toEqual(error) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { combineReducers } from 'redux' | ||
import { ActionType, getType } from 'typesafe-actions' | ||
|
||
import * as actions from './actions' | ||
|
||
export interface RenameGroupState { | ||
readonly [threadId: string]: { | ||
readonly error?: string | ||
} | ||
} | ||
|
||
export type RenameGroupAction = ActionType<typeof actions> | ||
|
||
export default (state: RenameGroupState = {}, action: RenameGroupAction) => { | ||
switch (action.type) { | ||
case getType(actions.renameGroup.request): { | ||
return { | ||
...state, | ||
[action.payload.threadId]: {} | ||
} | ||
} | ||
case getType(actions.renameGroup.success): { | ||
const { [action.payload.threadId]: renamed, ...renameGroup } = state | ||
return renameGroup | ||
} | ||
case getType(actions.renameGroup.failure): { | ||
const { threadId, error } = action.payload | ||
const errorMessage = error.message as string || error as string || 'unknown' | ||
return { | ||
...state, | ||
[threadId]: { | ||
error: errorMessage | ||
} | ||
} | ||
} | ||
default: | ||
return state | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { ActionType, getType } from 'typesafe-actions' | ||
import { call, put, takeEvery, all } from 'redux-saga/effects' | ||
import Textile from '@textile/react-native-sdk' | ||
import { renameGroup } from './actions' | ||
import PhotoViewingActions from '../../../Redux/PhotoViewingRedux' | ||
|
||
export function *handleRenameGroupRequest(action: ActionType<typeof renameGroup.request>) { | ||
const { threadId, name } = action.payload | ||
try { | ||
yield call(Textile.threads.rename, threadId, name) | ||
yield put(PhotoViewingActions.updateThreadName(threadId, name)) | ||
yield put(renameGroup.success({ threadId })) | ||
} catch (error) { | ||
yield put(renameGroup.failure({ threadId, error })) | ||
} | ||
} | ||
|
||
export default function *() { | ||
yield all([ | ||
takeEvery(getType(renameGroup.request), handleRenameGroupRequest) | ||
]) | ||
} |
Oops, something went wrong.