diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 6e704861b..45d2886f7 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -58,6 +58,7 @@ export const SERVER = createRequestTypes('SERVER', [ ...defaultTypes, 'SELECT_SUCCESS', 'SELECT_REQUEST', + 'SELECT_FAILURE', 'INIT_ADD', 'FINISH_ADD' ]); diff --git a/app/actions/server.js b/app/actions/server.js index 3a383781c..a5441c7ba 100644 --- a/app/actions/server.js +++ b/app/actions/server.js @@ -17,6 +17,12 @@ export function selectServerSuccess(server, version) { }; } +export function selectServerFailure() { + return { + type: SERVER.SELECT_FAILURE + }; +} + export function serverRequest(server) { return { type: SERVER.REQUEST, diff --git a/app/i18n/locales/de.js b/app/i18n/locales/de.js index e0b0c6f6e..9e2c45b2f 100644 --- a/app/i18n/locales/de.js +++ b/app/i18n/locales/de.js @@ -81,6 +81,7 @@ export default { Add_Reaction: 'Reaktion hinzufügen', Add_Server: 'Server hinzufügen', Add_user: 'Nutzer hinzufügen', + Admin_Panel: 'Admin Panel', Alert: 'Warnen', alert: 'warnen', alerts: 'Warnungen', @@ -124,7 +125,9 @@ export default { Connect: 'Verbinden', Connect_to_a_server: 'Verbinden Sie sich mit einem Server', Connected: 'Verbunden', + connecting_server: 'verbinde zum Server', Connecting: 'Verbinden ...', + Contact_us: 'Kontaktiere uns', Continue_with: 'Weitermachen mit', Copied_to_clipboard: 'In die Zwischenablage kopiert!', Copy: 'Kopieren', @@ -140,24 +143,29 @@ export default { DELETE: 'LÖSCHEN', description: 'Beschreibung', Description: 'Beschreibung', - Disable_notifications: 'Benachrichtigungen ausschalten', + Directory: 'Verzeichnis', Direct_Messages: 'Direkte Nachrichten', + Disable_notifications: 'Benachrichtigungen deaktiveren', + Discussions: 'Diskussionen', Dont_Have_An_Account: 'Sie haben noch kein Konto?', Do_you_really_want_to_key_this_room_question_mark: 'Möchten Sie diesen Raum wirklich {{key}}?', edit: 'bearbeiten', - erasing_room: 'Raum löschen', + edited: 'bearbeitet', Edit: 'Bearbeiten', Email_or_password_field_is_empty: 'Das E-Mail- oder Passwortfeld ist leer', Email: 'Email', email: 'Email', + Enable_markdown: 'Markdown 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', Favorites: 'Favoriten', Files: 'Dateien', File_description: 'Dateibeschreibung', File_name: 'Dateiname', Finish_recording: 'Beenden Sie die Aufnahme', + Following_thread: 'Thread folgen', For_your_security_you_must_enter_your_current_password_to_continue: 'Zu Ihrer Sicherheit müssen Sie Ihr aktuelles Passwort eingeben, um fortzufahren', Forgot_my_password: 'Ich habe mein Passwort vergessen', Forgot_password_If_this_email_is_registered: 'Wenn diese E-Mail registriert ist, senden wir Anweisungen zum Zurücksetzen Ihres Passworts. Wenn Sie in Kürze keine E-Mail erhalten, kommen Sie bitte zurück und versuchen Sie es erneut.', @@ -166,6 +174,7 @@ export default { Group_by_favorites: 'Nach Favoriten gruppieren', Group_by_type: 'Gruppieren nach Typ', Has_joined_the_channel: 'Ist dem Kanal beigetreten', + Has_joined_the_conversation: 'Hat sich dem Gespräch angeschlossen', Has_left_the_channel: 'Hat den Kanal verlassen', Invisible: 'Unsichtbar', Invite: 'Einladen', @@ -182,6 +191,7 @@ export default { leaving_room: 'Raum verlassen', leave: 'verlassen', Legal: 'Rechtliches', + License: 'Lizenz', Livechat: 'Live-Chat', Login: 'Anmeldung', Login_error: 'Ihre Referenzen wurden abgelehnt! Bitte versuche es erneut.', @@ -196,7 +206,10 @@ export default { Message_actions: 'Nachrichtenaktionen', Message_pinned: 'Eine Nachricht wurde angeheftet', Message_removed: 'Nachricht entfernt', + message: 'Nachricht', + messages: 'Nachrichten', Messages: 'Mitteilungen', + Message_Reported: 'Nachricht gemeldet', Microphone_Permission_Message: 'Rocket Chat benötigt Zugriff auf Ihr Mikrofon, damit Sie eine Audionachricht senden können.', Microphone_Permission: 'Mikrofonberechtigung', Mute: 'Stumm', @@ -215,11 +228,14 @@ export default { No_pinned_messages: 'Keine angehefteten Nachrichten', No_results_found: 'keine Ergebnisse gefunden', No_starred_messages: 'Keine markierten Nachrichten', + No_thread_messages: 'Keine Threadnachrichten', No_announcement_provided: 'Keine Ankündigung erfolgt.', No_description_provided: 'Keine Beschreibung angegeben.', No_topic_provided: 'Kein Thema bereitgestellt', No_Message: 'Keine Nachricht', + No_messages_yet: 'Noch keine Nachrichten', No_Reactions: 'Keine Reaktionen', + No_Read_Receipts: 'Keine Lesebestätigungen', Not_logged: 'Nicht protokolliert', Nothing_to_save: 'Nichts zu speichern!', Notify_active_in_this_room: 'Aktive Benutzer in diesem Raum benachrichtigen', @@ -252,9 +268,14 @@ export default { Reactions: 'Reaktionen', Read_Only_Channel: 'Nur-Lese-Kanal', Read_Only: 'Schreibgeschützt', + Read_Receipt: 'Lesebestätigung', Register: 'Registrieren', Repeat_Password: 'Wiederhole das Passwort', + Replied_on: 'Antwortete am:', + replies: 'Antworten', + reply: 'Antworten', Reply: 'Antworten', + Report: 'Bericht', Resend: 'Erneut senden', Reset_password: 'Passwort zurücksetzen', resetting_password: 'Passwort zurücksetzen', @@ -278,35 +299,47 @@ export default { saving_settings: 'Einstellungen speichern', Search_Messages: 'Nachrichten suchen', Search: 'Suche', + Search_by: 'Suche nach', + Search_global_users: 'Suche nach globalen Benutzern', + Search_global_users_description: 'Beim Einschalten können Sie nach Benutzern von anderen Unternehmen oder Servern suchen.', Select_Avatar: 'Wählen Sie einen Avatar aus', Select_Users: 'Wählen Sie einen Benutzer aus', Send: 'Senden', Send_audio_message: 'Audio-Nachricht senden', + Send_crash_report: 'Absturzbericht senden', Send_message: 'Nachricht senden', + Sent_an_attachment: 'Sende einen Anhang', Server: 'Server', Servers: 'Server', + Server_version: 'Server version: {{version}}', Set_username_subtitle: 'Der Benutzername wird verwendet, damit andere Personen Sie in Nachrichten erwähnen können', Settings: 'Einstellungen', Settings_succesfully_changed: 'Einstellungen erfolgreich geändert!', Share: 'Teilen', + Share_this_app: 'Teile diese App', Sign_in_your_server: 'Melden Sie sich bei Ihrem Server an', Sign_Up: 'Anmelden', Some_field_is_invalid_or_empty: 'Ein Feld ist ungültig oder leer', Sorting_by: 'Sortierung nach {{key}}', Star_room: 'Favorisierter Raum', + Star: 'Favoriten', Starred_Messages: 'Favorisierte Nachrichten', starred: 'favorisiert', Starred: 'Favorisiert', Start_of_conversation: 'Beginn des Gesprächs', + Started_discussion: 'Hat eine Diskussion gestartet:', Submit: 'einreichen', - Take_a_photo: 'Mach ein Foto', + Take_a_photo: 'Foto aufnehmen', tap_to_change_status: 'Tippen um den Status zu ändern', Tap_to_view_servers_list: 'Tippen Sie hier, um die Serverliste anzuzeigen', Terms_of_Service: ' Nutzungsbedingungen', + Theme: 'Theme', The_URL_is_invalid: 'Die eingegebene URL ist ungültig. Überprüfen Sie es und versuchen Sie es erneut, bitte!', There_was_an_error_while_action: 'Während {{action}} ist ein Fehler aufgetreten!', This_room_is_blocked: 'Dieser Raum ist gesperrt', This_room_is_read_only: 'Dieser Raum kann nur gelesen werden', + Thread: 'Thread', + Threads: 'Threads', Timezone: 'Zeitzone', topic: 'Thema', Topic: 'Thema', @@ -316,6 +349,7 @@ export default { unarchive: 'wiederherstellen', UNARCHIVE: 'WIEDERHERSTELLEN', Unblock_user: 'Nutzer entblockieren', + Unfollowed_thread: 'Thread nicht mehr folgen', Unmute: 'Stummschaltung aufheben', unmuted: 'Stummschaltung aufgehoben', Unpin: 'Nachricht nicht mehr anheften', @@ -326,6 +360,7 @@ export default { Updating: 'Aktualisierung...', Uploading: 'Hochladen', Upload_file_question_mark: 'Datei hochladen?', + Users: 'Benutzer', User_added_by: 'Benutzer {{userAdded}} hinzugefügt von {{userBy}}', User_has_been_key: 'Benutzer wurde {{key}}!', User_is_no_longer_role_by_: '{{user}} ist nicht länger {{role}} von {{userBy}}', @@ -343,7 +378,7 @@ export default { Welcome: 'Herzlich willkommen', Welcome_to_RocketChat: 'Willkommen bei Rocket.Chat', Whats_your_2fa: 'Wie ist dein 2FA-Code?', - Yes_action_it: 'Ja, {{action}} es!', + Yes_action_it: 'Ja, {{action}}!', Yesterday: 'Gestern', You_are_in_preview_mode: 'Sie befinden sich im Vorschaumodus', You_are_offline: 'Sie sind offline', @@ -352,5 +387,8 @@ export default { you_were_mentioned: 'Sie wurden erwähnt', you: 'sie', You: 'Sie', - You_will_not_be_able_to_recover_this_message: 'Sie können diese Nachricht nicht wiederherstellen!' + Version_no: 'Version: {{version}}', + You_will_not_be_able_to_recover_this_message: 'Sie können diese Nachricht nicht wiederherstellen!', + Change_Language: 'Sprache ändern', + Crash_report_disclaimer: 'Wir verfolgen niemals den Inhalt Ihrer Chats. Der Crash-Report enthält nur für uns relevante Informationen in der Reihenfolge ' }; diff --git a/app/lib/methods/getCustomEmojis.js b/app/lib/methods/getCustomEmojis.js index be2701f6c..e2fa2790d 100644 --- a/app/lib/methods/getCustomEmojis.js +++ b/app/lib/methods/getCustomEmojis.js @@ -23,57 +23,62 @@ const create = (customEmojis) => { }; -export default async function() { - try { - const serverVersion = reduxStore.getState().server.version; - const updatedSince = getUpdatedSince(); +export default function() { + return new Promise(async(resolve) => { + try { + const serverVersion = reduxStore.getState().server.version; + const updatedSince = getUpdatedSince(); - // if server version is lower than 0.75.0, fetches from old api - if (semver.lt(serverVersion, '0.75.0')) { - // RC 0.61.0 - const result = await this.sdk.get('emoji-custom'); + // if server version is lower than 0.75.0, fetches from old api + if (semver.lt(serverVersion, '0.75.0')) { + // RC 0.61.0 + const result = await this.sdk.get('emoji-custom'); - InteractionManager.runAfterInteractions(() => { - let { emojis } = result; - emojis = emojis.filter(emoji => !updatedSince || emoji._updatedAt > updatedSince); - database.write(() => { - create(emojis); + InteractionManager.runAfterInteractions(() => { + let { emojis } = result; + emojis = emojis.filter(emoji => !updatedSince || emoji._updatedAt > updatedSince); + database.write(() => { + create(emojis); + }); + return resolve(); }); - }); - } else { - const params = {}; - if (updatedSince) { - params.updatedSince = updatedSince; - } + } else { + const params = {}; + if (updatedSince) { + params.updatedSince = updatedSince; + } - // RC 0.75.0 - const result = await this.sdk.get('emoji-custom.list', params); + // RC 0.75.0 + const result = await this.sdk.get('emoji-custom.list', params); - if (!result.success) { - return; - } + if (!result.success) { + return resolve(); + } - InteractionManager.runAfterInteractions( - () => database.write(() => { - const { emojis } = result; - create(emojis.update); + InteractionManager.runAfterInteractions( + () => database.write(() => { + const { emojis } = result; + create(emojis.update); - if (emojis.delete && emojis.delete.length) { - emojis.delete.forEach((emoji) => { - try { - const emojiRecord = database.objectForPrimaryKey('customEmojis', emoji._id); - if (emojiRecord) { - database.delete(emojiRecord); + if (emojis.delete && emojis.delete.length) { + emojis.delete.forEach((emoji) => { + try { + const emojiRecord = database.objectForPrimaryKey('customEmojis', emoji._id); + if (emojiRecord) { + database.delete(emojiRecord); + } + } catch (e) { + log('err_get_emojis_delete', e); } - } catch (e) { - log('err_get_emojis_delete', e); - } - }); - } - }) - ); + }); + } + return resolve(); + }) + ); + } + } catch (e) { + log('err_get_custom_emojis', e); + return resolve(); } - } catch (e) { - log('err_get_custom_emojis', e); - } + }); } diff --git a/app/lib/methods/getPermissions.js b/app/lib/methods/getPermissions.js index c4d4a860d..b6c9c1c50 100644 --- a/app/lib/methods/getPermissions.js +++ b/app/lib/methods/getPermissions.js @@ -22,55 +22,60 @@ const create = (permissions) => { } }; -export default async function() { - try { - const serverVersion = reduxStore.getState().server.version; +export default function() { + return new Promise(async(resolve) => { + try { + const serverVersion = reduxStore.getState().server.version; - // if server version is lower than 0.73.0, fetches from old api - if (semver.lt(serverVersion, '0.73.0')) { - // RC 0.66.0 - const result = await this.sdk.get('permissions.list'); - if (!result.success) { - return; - } - InteractionManager.runAfterInteractions(() => { - database.write(() => { - create(result.permissions); + // if server version is lower than 0.73.0, fetches from old api + if (semver.lt(serverVersion, '0.73.0')) { + // RC 0.66.0 + const result = await this.sdk.get('permissions.list'); + if (!result.success) { + return resolve(); + } + InteractionManager.runAfterInteractions(() => { + database.write(() => { + create(result.permissions); + }); + return resolve(); }); - }); - } else { - const params = {}; - const updatedSince = getUpdatedSince(); - if (updatedSince) { - params.updatedSince = updatedSince; - } - // RC 0.73.0 - const result = await this.sdk.get('permissions.listAll', params); + } else { + const params = {}; + const updatedSince = getUpdatedSince(); + if (updatedSince) { + params.updatedSince = updatedSince; + } + // RC 0.73.0 + const result = await this.sdk.get('permissions.listAll', params); - if (!result.success) { - return; - } + if (!result.success) { + return resolve(); + } - InteractionManager.runAfterInteractions( - () => database.write(() => { - create(result.update); + InteractionManager.runAfterInteractions( + () => database.write(() => { + create(result.update); - if (result.delete && result.delete.length) { - result.delete.forEach((p) => { - try { - const permission = database.objectForPrimaryKey('permissions', p._id); - if (permission) { - database.delete(permission); + if (result.delete && result.delete.length) { + result.delete.forEach((p) => { + try { + const permission = database.objectForPrimaryKey('permissions', p._id); + if (permission) { + database.delete(permission); + } + } catch (e) { + log('err_get_permissions_delete', e); } - } catch (e) { - log('err_get_permissions_delete', e); - } - }); - } - }) - ); + }); + } + return resolve(); + }) + ); + } + } catch (e) { + log('err_get_permissions', e); + return resolve(); } - } catch (e) { - log('err_get_permissions', e); - } + }); } diff --git a/app/lib/methods/getRoles.js b/app/lib/methods/getRoles.js index 6b7a06da7..c668a55ae 100644 --- a/app/lib/methods/getRoles.js +++ b/app/lib/methods/getRoles.js @@ -3,29 +3,33 @@ import { InteractionManager } from 'react-native'; import database from '../realm'; import log from '../../utils/log'; -export default async function() { - try { - // RC 0.70.0 - const result = await this.sdk.get('roles.list'); +export default function() { + return new Promise(async(resolve) => { + try { + // RC 0.70.0 + const result = await this.sdk.get('roles.list'); - if (!result.success) { - return; + if (!result.success) { + return resolve(); + } + + const { roles } = result; + + if (roles && roles.length) { + InteractionManager.runAfterInteractions(() => { + database.write(() => roles.forEach((role) => { + try { + database.create('roles', role, true); + } catch (e) { + log('err_get_roles_create', e); + } + })); + return resolve(); + }); + } + } catch (e) { + log('err_get_roles', e); + return resolve(); } - - const { roles } = result; - - if (roles && roles.length) { - InteractionManager.runAfterInteractions(() => { - database.write(() => roles.forEach((role) => { - try { - database.create('roles', role, true); - } catch (e) { - log('err_get_roles_create', e); - } - })); - }); - } - } catch (e) { - log('err_get_roles', e); - } + }); } diff --git a/app/lib/methods/getSlashCommands.js b/app/lib/methods/getSlashCommands.js index 401c11807..6c20624e3 100644 --- a/app/lib/methods/getSlashCommands.js +++ b/app/lib/methods/getSlashCommands.js @@ -3,29 +3,34 @@ import { InteractionManager } from 'react-native'; import database from '../realm'; import log from '../../utils/log'; -export default async function() { - try { - // RC 0.60.2 - const result = await this.sdk.get('commands.list'); +export default function() { + return new Promise(async(resolve) => { + try { + // RC 0.60.2 + const result = await this.sdk.get('commands.list'); - if (!result.success) { - return log('getSlashCommand fetch', result); + if (!result.success) { + log('getSlashCommand fetch', result); + return resolve(); + } + + const { commands } = result; + + if (commands && commands.length) { + InteractionManager.runAfterInteractions(() => { + database.write(() => commands.forEach((command) => { + try { + database.create('slashCommand', command, true); + } catch (e) { + log('get_slash_command', e); + } + })); + return resolve(); + }); + } + } catch (e) { + log('err_get_slash_command', e); + return resolve(); } - - const { commands } = result; - - if (commands && commands.length) { - InteractionManager.runAfterInteractions(() => { - database.write(() => commands.forEach((command) => { - try { - database.create('slashCommand', command, true); - } catch (e) { - log('get_slash_command', e); - } - })); - }); - } - } catch (e) { - log('err_get_slash_command', e); - } + }); } diff --git a/app/lib/methods/subscriptions/rooms.js b/app/lib/methods/subscriptions/rooms.js index 50a35c551..5b23fbda7 100644 --- a/app/lib/methods/subscriptions/rooms.js +++ b/app/lib/methods/subscriptions/rooms.js @@ -13,6 +13,7 @@ const removeListener = listener => listener.stop(); let connectedListener; let disconnectedListener; let streamListener; +let subServer; export default async function subscribeRooms() { let timer = null; @@ -41,6 +42,10 @@ export default async function subscribeRooms() { }; const handleStreamMessageReceived = protectedFunction((ddpMessage) => { + // check if the server from variable is the same as the js sdk client + if (this.sdk && this.sdk.client && this.sdk.client.host !== subServer) { + return; + } if (ddpMessage.msg === 'added') { return; } @@ -149,6 +154,8 @@ export default async function subscribeRooms() { streamListener = this.sdk.onStreamData('stream-notify-user', handleStreamMessageReceived); try { + // set the server that started this task + subServer = this.sdk.client.host; await this.sdk.subscribeNotifyUser(); } catch (e) { log('err_subscribe_rooms', e); diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 156e34b72..21ad4b1e4 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -8,7 +8,6 @@ import messagesStatus from '../constants/messagesStatus'; import database from './realm'; import log from '../utils/log'; import { isIOS, getBundleId } from '../utils/deviceInfo'; -import EventEmitter from '../utils/events'; import { setUser, setLoginServices, loginRequest, loginFailure, logout @@ -24,7 +23,7 @@ import getSettings from './methods/getSettings'; import getRooms from './methods/getRooms'; import getPermissions from './methods/getPermissions'; -import getCustomEmoji from './methods/getCustomEmojis'; +import getCustomEmojis from './methods/getCustomEmojis'; import getSlashCommands from './methods/getSlashCommands'; import getRoles from './methods/getRoles'; import canOpenRoom from './methods/canOpenRoom'; @@ -37,7 +36,6 @@ import sendMessage, { getMessage, sendMessageCall } from './methods/sendMessage' import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFileMessage'; import { getDeviceToken } from '../notifications/push'; -import { roomsRequest } from '../actions/rooms'; const TOKEN_KEY = 'reactnativemeteor_usertoken'; const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY'; @@ -141,23 +139,6 @@ const RocketChat = { }; } }, - async loginSuccess({ user }) { - EventEmitter.emit('connected'); - reduxStore.dispatch(setUser(user)); - reduxStore.dispatch(roomsRequest()); - - if (this.roomsSub) { - this.roomsSub.stop(); - } - this.roomsSub = await this.subscribeRooms(); - - this.getPermissions(); - this.getCustomEmoji(); - this.getRoles(); - this.getSlashCommands(); - this.registerPushToken().catch(e => console.log(e)); - this.getUserPresence(); - }, connect({ server, user }) { return new Promise((resolve) => { database.setActiveDB(server); @@ -167,6 +148,10 @@ const RocketChat = { clearTimeout(this.connectTimeout); } + if (this.roomsSub) { + this.roomsSub.stop(); + } + if (this.sdk) { this.sdk.disconnect(); this.sdk = null; @@ -195,10 +180,10 @@ const RocketChat = { this.sdk.onStreamData('connected', () => { reduxStore.dispatch(connectSuccess()); - const { isAuthenticated } = reduxStore.getState().login; - if (isAuthenticated) { - this.getUserPresence(); - } + // const { isAuthenticated } = reduxStore.getState().login; + // if (isAuthenticated) { + // this.getUserPresence(); + // } }); this.sdk.onStreamData('close', () => { @@ -349,7 +334,7 @@ const RocketChat = { } }, registerPushToken() { - return new Promise((resolve) => { + return new Promise(async(resolve) => { const token = getDeviceToken(); if (token) { const type = isIOS ? 'apn' : 'gcm'; @@ -358,8 +343,12 @@ const RocketChat = { type, appName: getBundleId }; - // RC 0.60.0 - return this.sdk.post('push.token', data); + try { + // RC 0.60.0 + await this.sdk.post('push.token', data); + } catch (error) { + console.log(error); + } } return resolve(); }); @@ -468,7 +457,7 @@ const RocketChat = { isUploadActive, getSettings, getPermissions, - getCustomEmoji, + getCustomEmojis, getSlashCommands, getRoles, parseSettings: settings => settings.reduce((ret, item) => { @@ -824,41 +813,45 @@ const RocketChat = { command, params, roomId, previewItem }); }, - async getUserPresence() { - const serverVersion = reduxStore.getState().server.version; + getUserPresence() { + return new Promise(async(resolve) => { + const serverVersion = reduxStore.getState().server.version; - // if server is lower than 1.1.0 - if (semver.lt(semver.coerce(serverVersion), '1.1.0')) { - if (this.activeUsersSubTimeout) { - clearTimeout(this.activeUsersSubTimeout); - this.activeUsersSubTimeout = false; - } - this.activeUsersSubTimeout = setTimeout(() => { - this.sdk.subscribe('activeUsers'); - }, 5000); - } else { - const params = {}; - if (this.lastUserPresenceFetch) { - params.from = this.lastUserPresenceFetch.toISOString(); - } + // if server is lower than 1.1.0 + if (semver.lt(semver.coerce(serverVersion), '1.1.0')) { + if (this.activeUsersSubTimeout) { + clearTimeout(this.activeUsersSubTimeout); + this.activeUsersSubTimeout = false; + } + this.activeUsersSubTimeout = setTimeout(() => { + this.sdk.subscribe('activeUsers'); + }, 5000); + return resolve(); + } else { + const params = {}; + // if (this.lastUserPresenceFetch) { + // params.from = this.lastUserPresenceFetch.toISOString(); + // } - // RC 1.1.0 - const result = await this.sdk.get('users.presence', params); - if (result.success) { - this.lastUserPresenceFetch = new Date(); - database.memoryDatabase.write(() => { - result.users.forEach((item) => { - try { - item.id = item._id; - database.memoryDatabase.create('activeUsers', item, true); - } catch (error) { - console.log(error); - } + // RC 1.1.0 + const result = await this.sdk.get('users.presence', params); + if (result.success) { + // this.lastUserPresenceFetch = new Date(); + database.memoryDatabase.write(() => { + result.users.forEach((item) => { + try { + item.id = item._id; + database.memoryDatabase.create('activeUsers', item, true); + } catch (error) { + console.log(error); + } + }); }); - }); - this.sdk.subscribe('stream-notify-logged', 'user-status'); + this.sdk.subscribe('stream-notify-logged', 'user-status'); + return resolve(); + } } - } + }); }, getDirectory({ query, count, offset, sort diff --git a/app/reducers/server.js b/app/reducers/server.js index a2a04bd94..7eda3767f 100644 --- a/app/reducers/server.js +++ b/app/reducers/server.js @@ -44,6 +44,13 @@ export default function server(state = initialState, action) { connected: true, loading: false }; + case SERVER.SELECT_FAILURE: + return { + ...state, + connecting: false, + connected: false, + loading: false + }; case SERVER.INIT_ADD: return { ...state, diff --git a/app/sagas/login.js b/app/sagas/login.js index 28c723215..66b4183ad 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -1,16 +1,18 @@ import { AsyncStorage } from 'react-native'; import { - put, call, takeLatest, select + put, call, takeLatest, select, take, fork, cancel } from 'redux-saga/effects'; import * as types from '../actions/actionsTypes'; import { appStart } from '../actions'; import { serverFinishAdd, selectServerRequest } from '../actions/server'; -import { loginFailure, loginSuccess } from '../actions/login'; +import { loginFailure, loginSuccess, setUser } from '../actions/login'; +import { roomsRequest } from '../actions/rooms'; import RocketChat from '../lib/rocketchat'; import log from '../utils/log'; import I18n from '../i18n'; import database from '../lib/realm'; +import EventEmitter from '../utils/events'; const getServer = state => state.server.server; const loginWithPasswordCall = args => RocketChat.loginWithPassword(args); @@ -31,27 +33,59 @@ const handleLoginRequest = function* handleLoginRequest({ credentials }) { } }; -const handleLoginSuccess = function* handleLoginSuccess({ user }) { - const adding = yield select(state => state.server.adding); - yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token); +const fetchPermissions = function* fetchPermissions() { + yield RocketChat.getPermissions(); +}; - const server = yield select(getServer); +const fetchCustomEmojis = function* fetchCustomEmojis() { + yield RocketChat.getCustomEmojis(); +}; + +const fetchRoles = function* fetchRoles() { + yield RocketChat.getRoles(); +}; + +const fetchSlashCommands = function* fetchSlashCommands() { + yield RocketChat.getSlashCommands(); +}; + +const registerPushToken = function* registerPushToken() { + yield RocketChat.registerPushToken(); +}; + +const fetchUserPresence = function* fetchUserPresence() { + yield RocketChat.getUserPresence(); +}; + +const handleLoginSuccess = function* handleLoginSuccess({ user }) { try { - RocketChat.loginSuccess({ user }); + const adding = yield select(state => state.server.adding); + yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token); + + const server = yield select(getServer); + yield put(roomsRequest()); + yield fork(fetchPermissions); + yield fork(fetchCustomEmojis); + yield fork(fetchRoles); + yield fork(fetchSlashCommands); + yield fork(registerPushToken); + yield fork(fetchUserPresence); + I18n.locale = user.language; yield AsyncStorage.setItem(`${ RocketChat.TOKEN_KEY }-${ server }`, JSON.stringify(user)); - } catch (error) { - console.log('loginSuccess saga -> error', error); - } + yield put(setUser(user)); + EventEmitter.emit('connected'); - if (!user.username) { - RocketChat.loginSuccess({ user }); - yield put(appStart('setUsername')); - } else if (adding) { - yield put(serverFinishAdd()); - yield put(appStart('inside')); - } else { - yield put(appStart('inside')); + if (!user.username) { + yield put(appStart('setUsername')); + } else if (adding) { + yield put(serverFinishAdd()); + yield put(appStart('inside')); + } else { + yield put(appStart('inside')); + } + } catch (e) { + log('err_handle_login_success', e); } }; @@ -93,8 +127,14 @@ const handleSetUser = function handleSetUser({ user }) { const root = function* root() { yield takeLatest(types.LOGIN.REQUEST, handleLoginRequest); - yield takeLatest(types.LOGIN.SUCCESS, handleLoginSuccess); yield takeLatest(types.LOGOUT, handleLogout); yield takeLatest(types.USER.SET, handleSetUser); + + while (true) { + const params = yield take(types.LOGIN.SUCCESS); + const loginSuccessTask = yield fork(handleLoginSuccess, params); + yield take(types.SERVER.SELECT_REQUEST); + yield cancel(loginSuccessTask); + } }; export default root; diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js index ad5d862f4..bc900f2d2 100644 --- a/app/sagas/rooms.js +++ b/app/sagas/rooms.js @@ -1,6 +1,7 @@ import { - put, takeLatest, select + put, select, race, take, fork, cancel, takeLatest } from 'redux-saga/effects'; +import { BACKGROUND } from 'redux-enhancer-react-native-appstate'; import * as types from '../actions/actionsTypes'; import { roomsSuccess, roomsFailure } from '../actions/rooms'; @@ -9,8 +10,18 @@ import log from '../utils/log'; import mergeSubscriptionsRooms from '../lib/methods/helpers/mergeSubscriptionsRooms'; import RocketChat from '../lib/rocketchat'; +let roomsSub; + +const removeSub = function removeSub() { + if (roomsSub && roomsSub.stop) { + roomsSub.stop(); + } +}; + const handleRoomsRequest = function* handleRoomsRequest() { try { + removeSub(); + roomsSub = yield RocketChat.subscribeRooms(); const newRoomsUpdatedAt = new Date(); const server = yield select(state => state.server.server); const [serverRecord] = database.databases.serversDB.objects('servers').filtered('id = $0', server); @@ -42,7 +53,21 @@ const handleRoomsRequest = function* handleRoomsRequest() { } }; +const handleLogout = function handleLogout() { + removeSub(); +}; + const root = function* root() { - yield takeLatest(types.ROOMS.REQUEST, handleRoomsRequest); + yield takeLatest(types.LOGOUT, handleLogout); + while (true) { + const params = yield take(types.ROOMS.REQUEST); + const roomsRequestTask = yield fork(handleRoomsRequest, params); + yield race({ + serverReq: take(types.SERVER.SELECT_REQUEST), + background: take(BACKGROUND), + logout: take(types.LOGOUT) + }); + yield cancel(roomsRequestTask); + } }; export default root; diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index 859103901..b6f1efec5 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -1,10 +1,14 @@ -import { put, takeLatest } from 'redux-saga/effects'; +import { + put, take, takeLatest, fork, cancel, race +} from 'redux-saga/effects'; import { AsyncStorage, Alert } from 'react-native'; import Navigation from '../lib/Navigation'; import { SERVER } from '../actions/actionsTypes'; import * as actions from '../actions'; -import { serverFailure, selectServerRequest, selectServerSuccess } from '../actions/server'; +import { + serverFailure, selectServerRequest, selectServerSuccess, selectServerFailure +} from '../actions/server'; import { setUser } from '../actions/login'; import RocketChat from '../lib/rocketchat'; import database from '../lib/realm'; @@ -58,6 +62,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch // Return server version even when offline yield put(selectServerSuccess(server, (serverInfo && serverInfo.version) || version)); } catch (e) { + yield put(selectServerFailure()); log('err_select_server', e); } }; @@ -81,7 +86,17 @@ const handleServerRequest = function* handleServerRequest({ server }) { }; const root = function* root() { - yield takeLatest(SERVER.SELECT_REQUEST, handleSelectServer); yield takeLatest(SERVER.REQUEST, handleServerRequest); + + while (true) { + const params = yield take(SERVER.SELECT_REQUEST); + const selectServerTask = yield fork(handleSelectServer, params); + yield race({ + request: take(SERVER.SELECT_REQUEST), + success: take(SERVER.SELECT_SUCCESS), + failure: take(SERVER.SELECT_FAILURE) + }); + yield cancel(selectServerTask); + } }; export default root; diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index f29d62348..a8297a166 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -29,6 +29,7 @@ import RoomsListHeaderView from './Header'; import { DrawerButton, CustomHeaderButtons, Item } from '../../containers/HeaderButton'; import StatusBar from '../../containers/StatusBar'; import ListHeader from './ListHeader'; +import { selectServerRequest as selectServerRequestAction } from '../../actions/server'; const SCROLL_OFFSET = 56; @@ -56,7 +57,8 @@ const keyExtractor = item => item.rid; openSearchHeader: () => dispatch(openSearchHeaderAction()), closeSearchHeader: () => dispatch(closeSearchHeaderAction()), appStart: () => dispatch(appStartAction()), - roomsRequest: () => dispatch(roomsRequestAction()) + roomsRequest: () => dispatch(roomsRequestAction()), + selectServerRequest: server => dispatch(selectServerRequestAction(server)) })) export default class RoomsListView extends React.Component { static navigationOptions = ({ navigation }) => {