diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 8fda57de..bf07a329 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -31,7 +31,7 @@ export const ROOMS = createRequestTypes('ROOMS', [ 'OPEN_SEARCH_HEADER', 'CLOSE_SEARCH_HEADER' ]); -export const ROOM = createRequestTypes('ROOM', ['LEAVE', 'ERASE', 'USER_TYPING']); +export const ROOM = createRequestTypes('ROOM', ['LEAVE', 'DELETE_INIT', 'DELETE_FINISH', 'USER_TYPING']); export const APP = createRequestTypes('APP', ['START', 'READY', 'INIT', 'INIT_LOCAL_SETTINGS']); export const MESSAGES = createRequestTypes('MESSAGES', ['REPLY_BROADCAST']); export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes]); diff --git a/app/actions/room.js b/app/actions/room.js index 64eb223d..8d4e17e9 100644 --- a/app/actions/room.js +++ b/app/actions/room.js @@ -8,14 +8,20 @@ export function leaveRoom(rid, t) { }; } -export function eraseRoom(rid, t) { +export function deleteRoomInit(rid, t) { return { - type: types.ROOM.ERASE, + type: types.ROOM.DELETE_INIT, rid, t }; } +export function deleteRoomFinish() { + return { + type: types.ROOM.DELETE_FINISH + }; +} + export function userTyping(rid, status = true) { return { type: types.ROOM.USER_TYPING, diff --git a/app/i18n/locales/de.js b/app/i18n/locales/de.js index f64b1319..ed625c63 100644 --- a/app/i18n/locales/de.js +++ b/app/i18n/locales/de.js @@ -166,6 +166,7 @@ export default { delete: 'löschen', Delete: 'Löschen', DELETE: 'LÖSCHEN', + deleting_room: 'lösche Raum', description: 'Beschreibung', Description: 'Beschreibung', DESKTOP_OPTIONS: 'Desktop-Einstellungen', @@ -187,7 +188,6 @@ export default { Enable_Auto_Translate: 'Automatische Übersetzung aktivieren', Enable_notifications: 'Benachrichtigungen aktivieren', Everyone_can_access_this_channel: 'Jeder kann auf diesen Kanal zugreifen', - erasing_room: 'lösche Raum', Error_uploading: 'Fehler beim Hochladen', Expiration_Days: 'läuft ab (Tage)', Favorite: 'Favorisieren', diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index 2c4ab076..d5cf5429 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -166,6 +166,7 @@ export default { delete: 'delete', Delete: 'Delete', DELETE: 'DELETE', + deleting_room: 'deleting room', description: 'description', Description: 'Description', DESKTOP_OPTIONS: 'DESKTOP OPTIONS', @@ -187,7 +188,6 @@ export default { Enable_Auto_Translate: 'Enable Auto-Translate', Enable_notifications: 'Enable notifications', Everyone_can_access_this_channel: 'Everyone can access this channel', - erasing_room: 'erasing room', Error_uploading: 'Error uploading', Expiration_Days: 'Expiration (Days)', Favorite: 'Favorite', diff --git a/app/i18n/locales/es-ES.js b/app/i18n/locales/es-ES.js index c893da66..f1aa707f 100644 --- a/app/i18n/locales/es-ES.js +++ b/app/i18n/locales/es-ES.js @@ -158,6 +158,7 @@ export default { delete: 'eliminar', Delete: 'Eliminar', DELETE: 'ELIMINAR', + deleting_room: 'eliminando sala', description: 'descripción', Description: 'Descripción', DESKTOP_OPTIONS: 'OPCIONES DE ESCRITORIO', @@ -178,7 +179,6 @@ export default { Enable_Auto_Translate: 'Permitir Auto-Translate', Enable_notifications: 'Permitir notificaciones', Everyone_can_access_this_channel: 'Todos los usuarios pueden acceder a este canal', - erasing_room: 'eliminando sala', Error_uploading: 'Error en la subida', Favorite: 'Favorito', Favorites: 'Favoritos', diff --git a/app/i18n/locales/fr.js b/app/i18n/locales/fr.js index 3dde29c6..2247b448 100644 --- a/app/i18n/locales/fr.js +++ b/app/i18n/locales/fr.js @@ -138,6 +138,7 @@ export default { delete: 'supprimez', Delete: 'Supprimez', DELETE: 'SUPPRIMEZ', + deleting_room: 'effacement de la salle', description: 'la description', Description: 'La description', Disable_notifications: 'Désactiver les notifications', @@ -145,7 +146,6 @@ export default { Dont_Have_An_Account: 'Vous n\'avez pas de compte?', Do_you_really_want_to_key_this_room_question_mark: 'Voulez-vous vraiment {{key}} cette salle?', edit: 'modifier', - erasing_room: 'effacement de la salle', Edit: 'Modifier', Email_or_password_field_is_empty: 'Le champ e-mail ou mot de passe est vide', Email: 'E-mail', diff --git a/app/i18n/locales/it.js b/app/i18n/locales/it.js index c4b97fa6..f6c3dba3 100644 --- a/app/i18n/locales/it.js +++ b/app/i18n/locales/it.js @@ -160,6 +160,7 @@ export default { delete: 'elimina', Delete: 'Elimina', DELETE: 'ELIMINA', + deleting_room: 'cancellazione stanza', description: 'descrizione', Description: 'Descrizione', DESKTOP_OPTIONS: 'OPZIONI DESKTOP', @@ -181,7 +182,6 @@ export default { Enable_Auto_Translate: 'Abilita traduzione automatica', Enable_notifications: 'Abilita notifiche', Everyone_can_access_this_channel: 'Tutti hanno accesso a questo canale', - erasing_room: 'cancellazione stanza', Error_uploading: 'Errore nel caricamento di', Expiration_Days: 'Scadenza (giorni)', Favorite: 'Preferito', diff --git a/app/i18n/locales/ja.js b/app/i18n/locales/ja.js index 8f29d91d..36777550 100644 --- a/app/i18n/locales/ja.js +++ b/app/i18n/locales/ja.js @@ -181,6 +181,7 @@ export default { delete: '削除', Delete: '削除', DELETE: '削除', + deleting_room: 'ルームを削除', description: '概要', Description: '概要', DESKTOP_OPTIONS: 'デスクトップオプション', @@ -204,7 +205,6 @@ export default { Enable_markdown: 'マークダウンを有効にする', Enable_notifications: '通知を有効にする', Everyone_can_access_this_channel: '全員このチャンネルにアクセスできます', - erasing_room: 'ルームを削除', Error_uploading: 'アップロードエラー', Expiration_Days: '期限切れ (日)', Favorite: 'お気に入り', diff --git a/app/i18n/locales/nl.js b/app/i18n/locales/nl.js index dd870381..12820472 100644 --- a/app/i18n/locales/nl.js +++ b/app/i18n/locales/nl.js @@ -160,6 +160,7 @@ export default { delete: 'delete', Delete: 'Delete', DELETE: 'DELETE', + deleting_room: 'kamer legen', description: 'beschrijving', Description: 'Beschrijving', DESKTOP_OPTIONS: 'DESKTOP OPTIES', @@ -181,7 +182,6 @@ export default { Enable_Auto_Translate: 'Zet Auto-Translate aan', Enable_notifications: 'Zet notifications aan', Everyone_can_access_this_channel: 'Iedereen kan bij dit kanaal', - erasing_room: 'kamer legen', Error_uploading: 'Error tijdens uploaden', Expiration_Days: 'Vervalt in (Dagen)', Favorite: 'Favoriet', diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js index 1d0b5429..a10a770c 100644 --- a/app/i18n/locales/pt-BR.js +++ b/app/i18n/locales/pt-BR.js @@ -163,6 +163,7 @@ export default { delete: 'excluir', Delete: 'Excluir', DELETE: 'EXCLUIR', + deleting_room: 'excluindo sala', Direct_Messages: 'Mensagens Diretas', Directory: 'Diretório', description: 'descrição', @@ -173,7 +174,6 @@ export default { Do_you_really_want_to_key_this_room_question_mark: 'Você quer realmente {{key}} esta sala?', edit: 'editar', edited: 'editado', - erasing_room: 'apagando sala', Edit: 'Editar', Edit_Invite: 'Editar convite', Email_or_password_field_is_empty: 'Email ou senha estão vazios', diff --git a/app/i18n/locales/pt-PT.js b/app/i18n/locales/pt-PT.js index cf24203d..70b84bae 100644 --- a/app/i18n/locales/pt-PT.js +++ b/app/i18n/locales/pt-PT.js @@ -145,7 +145,7 @@ export default { Dont_Have_An_Account: 'Não tem uma conta?', Do_you_really_want_to_key_this_room_question_mark: 'Você quer mesmo {{key}} esta sala?', edit: 'editar', - erasing_room: 'apagando sala', + deleting_room: 'apagando sala', Edit: 'Editar', Email_or_password_field_is_empty: 'O campo de e-mail ou palavra-passe está vazio', Email: 'E-mail', diff --git a/app/i18n/locales/ru.js b/app/i18n/locales/ru.js index 4fdb7e74..50472969 100644 --- a/app/i18n/locales/ru.js +++ b/app/i18n/locales/ru.js @@ -173,7 +173,7 @@ export default { Enable_Auto_Translate: 'Включить автоперевод', Enable_notifications: 'Включить уведомления', Everyone_can_access_this_channel: 'Каждый может получить доступ к этому каналу', - erasing_room: 'стирание комнаты', + deleting_room: 'стирание комнаты', Error_uploading: 'Ошибка при загрузке', Favorite: 'Избранное', Favorites: 'Избранные', diff --git a/app/i18n/locales/zh-CN.js b/app/i18n/locales/zh-CN.js index a88cffb1..fb8ece22 100644 --- a/app/i18n/locales/zh-CN.js +++ b/app/i18n/locales/zh-CN.js @@ -144,7 +144,7 @@ export default { Dont_Have_An_Account: '还没有账号?', Do_you_really_want_to_key_this_room_question_mark: '你真的想要{{key}}这个房间吗?', edit: '编辑', - erasing_room: '正抹去房间', + deleting_room: '正抹去房间', Edit: '编辑', Email_or_password_field_is_empty: '邮件或密码字段为空', Email: '邮箱', diff --git a/app/lib/methods/subscriptions/rooms.js b/app/lib/methods/subscriptions/rooms.js index 8436e0af..8ecb8370 100644 --- a/app/lib/methods/subscriptions/rooms.js +++ b/app/lib/methods/subscriptions/rooms.js @@ -14,6 +14,7 @@ import { handlePayloadUserInteraction } from '../actions'; import buildMessage from '../helpers/buildMessage'; import RocketChat from '../../rocketchat'; import EventEmmiter from '../../../utils/events'; +import { deleteRoomFinish } from '../../../actions/room'; const removeListener = listener => listener.stop(); @@ -239,7 +240,15 @@ export default function subscribeRooms() { ...threadMessagesToDelete ); }); - EventEmmiter.emit('removed', { rid: data.rid }); + + const roomState = store.getState().room; + // Delete and remove events come from this stream + // Here we identify which one was triggered + if (data.rid === roomState.rid && roomState.isDeleting) { + store.dispatch(deleteRoomFinish()); + } else { + EventEmmiter.emit('ROOM_REMOVED', { rid: data.rid }); + } } catch (e) { log(e); } diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 884061ef..226ffbbb 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -787,7 +787,7 @@ const RocketChat = { // RC 0.48.0 return this.sdk.post(`${ this.roomTypeToApiType(t) }.leave`, { roomId }); }, - eraseRoom(roomId, t) { + deleteRoom(roomId, t) { // RC 0.49.0 return this.sdk.post(`${ this.roomTypeToApiType(t) }.delete`, { roomId }); }, diff --git a/app/reducers/index.js b/app/reducers/index.js index 1962f044..c156fb78 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -2,6 +2,7 @@ import { combineReducers } from 'redux'; import settings from './reducers'; import login from './login'; import meteor from './connect'; +import room from './room'; import rooms from './rooms'; import server from './server'; import selectedUsers from './selectedUsers'; @@ -24,6 +25,7 @@ export default combineReducers({ selectedUsers, createChannel, app, + room, rooms, sortPreferences, notification, diff --git a/app/reducers/room.js b/app/reducers/room.js new file mode 100644 index 00000000..a689a448 --- /dev/null +++ b/app/reducers/room.js @@ -0,0 +1,24 @@ +import { ROOM } from '../actions/actionsTypes'; + +const initialState = { + rid: null, + isDeleting: false +}; + +export default function(state = initialState, action) { + switch (action.type) { + case ROOM.DELETE_INIT: + return { + ...state, + rid: action.rid, + isDeleting: true + }; + case ROOM.DELETE_FINISH: + return { + ...state, + isDeleting: false + }; + default: + return state; + } +} diff --git a/app/sagas/room.js b/app/sagas/room.js index 1ad7c235..13eb8c75 100644 --- a/app/sagas/room.js +++ b/app/sagas/room.js @@ -1,10 +1,11 @@ import { Alert } from 'react-native'; import { - takeLatest, take, select, delay + takeLatest, take, select, delay, race, put } from 'redux-saga/effects'; import Navigation from '../lib/Navigation'; import * as types from '../actions/actionsTypes'; +import { deleteRoomFinish } from '../actions/room'; import RocketChat from '../lib/rocketchat'; import log from '../utils/log'; import I18n from '../i18n'; @@ -42,20 +43,28 @@ const handleLeaveRoom = function* handleLeaveRoom({ rid, t }) { } }; -const handleEraseRoom = function* handleEraseRoom({ rid, t }) { +const handleDeleteRoom = function* handleDeleteRoom({ rid, t }) { try { - const result = yield RocketChat.eraseRoom(rid, t); + const result = yield RocketChat.deleteRoom(rid, t); if (result.success) { yield Navigation.navigate('RoomsListView'); } + // types.ROOM.DELETE_FINISH is triggered by `subscriptions-changed` with `removed` arg + const { timeout } = yield race({ + deleteFinished: take(types.ROOM.DELETE_FINISH), + timeout: delay(3000) + }); + if (timeout) { + put(deleteRoomFinish()); + } } catch (e) { - Alert.alert(I18n.t('Oops'), I18n.t('There_was_an_error_while_action', { action: I18n.t('erasing_room') })); + Alert.alert(I18n.t('Oops'), I18n.t('There_was_an_error_while_action', { action: I18n.t('deleting_room') })); } }; const root = function* root() { yield takeLatest(types.ROOM.USER_TYPING, watchUserTyping); yield takeLatest(types.ROOM.LEAVE, handleLeaveRoom); - yield takeLatest(types.ROOM.ERASE, handleEraseRoom); + yield takeLatest(types.ROOM.DELETE_INIT, handleDeleteRoom); }; export default root; diff --git a/app/tablet.js b/app/tablet.js index 4b4530b7..3fadb747 100644 --- a/app/tablet.js +++ b/app/tablet.js @@ -129,6 +129,17 @@ export const initTabletNav = (setState) => { return null; } + if (routeName === 'RoomsListView') { + const resetAction = StackActions.reset({ + index: 0, + actions: [NavigationActions.navigate({ routeName: 'RoomView', params: {} })] + }); + roomRef.dispatch(resetAction); + notificationRef.dispatch(resetAction); + setState({ showModal: false }); + return null; + } + if (routeName === 'NewMessageView') { modalRef.dispatch(NavigationActions.navigate({ routeName, params })); setState({ showModal: true }); diff --git a/app/views/RoomInfoEditView/index.js b/app/views/RoomInfoEditView/index.js index a3920e9e..58e8f124 100644 --- a/app/views/RoomInfoEditView/index.js +++ b/app/views/RoomInfoEditView/index.js @@ -8,7 +8,7 @@ import { SafeAreaView } from 'react-navigation'; import equal from 'deep-equal'; import database from '../../lib/database'; -import { eraseRoom as eraseRoomAction } from '../../actions/room'; +import { deleteRoomInit as deleteRoomInitAction } from '../../actions/room'; import KeyboardView from '../../presentation/KeyboardView'; import sharedStyles from '../Styles'; import styles from './styles'; @@ -51,7 +51,7 @@ class RoomInfoEditView extends React.Component { static propTypes = { navigation: PropTypes.object, - eraseRoom: PropTypes.func, + deleteRoomInit: PropTypes.func, theme: PropTypes.string }; @@ -237,7 +237,7 @@ class RoomInfoEditView extends React.Component { delete = () => { const { room } = this.state; - const { eraseRoom } = this.props; + const { deleteRoomInit } = this.props; Alert.alert( I18n.t('Are_you_sure_question_mark'), @@ -250,7 +250,7 @@ class RoomInfoEditView extends React.Component { { text: I18n.t('Yes_action_it', { action: I18n.t('delete') }), style: 'destructive', - onPress: () => eraseRoom(room.rid, room.t) + onPress: () => deleteRoomInit(room.rid, room.t) } ], { cancelable: false } @@ -498,7 +498,7 @@ class RoomInfoEditView extends React.Component { } const mapDispatchToProps = dispatch => ({ - eraseRoom: (rid, t) => dispatch(eraseRoomAction(rid, t)) + deleteRoomInit: (rid, t) => dispatch(deleteRoomInitAction(rid, t)) }); export default connect(null, mapDispatchToProps)(withTheme(RoomInfoEditView)); diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 3d15f63f..1da342dc 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -54,6 +54,7 @@ import RoomClass from '../../lib/methods/subscriptions/room'; import { getUserSelector } from '../../selectors/login'; import { CONTAINER_TYPES } from '../../lib/methods/actions'; import Markdown from '../../containers/markdown'; +import Navigation from '../../lib/Navigation'; const stateAttrsUpdate = [ 'joined', @@ -229,7 +230,7 @@ class RoomView extends React.Component { if (isTablet) { EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands); } - EventEmitter.addEventListener('removed', this.handleRemoved); + EventEmitter.addEventListener('ROOM_REMOVED', this.handleRoomRemoved); console.timeEnd(`${ this.constructor.name } mount`); } @@ -312,7 +313,7 @@ class RoomView extends React.Component { if (isTablet) { EventEmitter.removeListener(KEY_COMMAND, this.handleCommands); } - EventEmitter.removeListener('removed', this.handleRemoved); + EventEmitter.removeListener('ROOM_REMOVED', this.handleRoomRemoved); console.countReset(`${ this.constructor.name }.render calls`); } @@ -553,11 +554,10 @@ class RoomView extends React.Component { EventEmitter.removeListener('connected', this.handleConnected); } - handleRemoved = ({ rid }) => { + handleRoomRemoved = ({ rid }) => { const { room } = this.state; - const { navigation } = this.props; if (rid === this.rid) { - navigation.pop(); + Navigation.navigate('RoomsListView'); showErrorAlert(I18n.t('You_were_removed_from_channel', { channel: this.getRoomTitle(room) }), I18n.t('Oops')); } }