Merge branch 'develop' into chore.dehydrate-login-methods-from-rocketchatjs
This commit is contained in:
commit
ff44417b32
|
@ -1,59 +0,0 @@
|
||||||
import * as types from './actionsTypes';
|
|
||||||
|
|
||||||
export function loginRequest(credentials, logoutOnError, isFromWebView) {
|
|
||||||
return {
|
|
||||||
type: types.LOGIN.REQUEST,
|
|
||||||
credentials,
|
|
||||||
logoutOnError,
|
|
||||||
isFromWebView
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loginSuccess(user) {
|
|
||||||
return {
|
|
||||||
type: types.LOGIN.SUCCESS,
|
|
||||||
user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loginFailure(err) {
|
|
||||||
return {
|
|
||||||
type: types.LOGIN.FAILURE,
|
|
||||||
err
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function logout(forcedByServer = false) {
|
|
||||||
return {
|
|
||||||
type: types.LOGOUT,
|
|
||||||
forcedByServer
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setUser(user) {
|
|
||||||
return {
|
|
||||||
type: types.USER.SET,
|
|
||||||
user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setLoginServices(data) {
|
|
||||||
return {
|
|
||||||
type: types.LOGIN.SET_SERVICES,
|
|
||||||
data
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setPreference(preference) {
|
|
||||||
return {
|
|
||||||
type: types.LOGIN.SET_PREFERENCE,
|
|
||||||
preference
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setLocalAuthenticated(isLocalAuthenticated) {
|
|
||||||
return {
|
|
||||||
type: types.LOGIN.SET_LOCAL_AUTHENTICATED,
|
|
||||||
isLocalAuthenticated
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
|
import { IUser } from '../definitions';
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
interface ICredentials {
|
||||||
|
resume: string;
|
||||||
|
user: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoginRequest extends Action {
|
||||||
|
credentials: any;
|
||||||
|
logoutOnError?: boolean;
|
||||||
|
isFromWebView?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoginSuccess extends Action {
|
||||||
|
user: Partial<IUser>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoginFailure extends Action {
|
||||||
|
err: Partial<IUser>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILogout extends Action {
|
||||||
|
forcedByServer: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISetUser extends Action {
|
||||||
|
user: Partial<IUser>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISetServices extends Action {
|
||||||
|
data: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISetPreference extends Action {
|
||||||
|
preference: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISetLocalAuthenticated extends Action {
|
||||||
|
isLocalAuthenticated: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TActionsLogin = ILoginRequest &
|
||||||
|
ILoginSuccess &
|
||||||
|
ILoginFailure &
|
||||||
|
ILogout &
|
||||||
|
ISetUser &
|
||||||
|
ISetServices &
|
||||||
|
ISetPreference &
|
||||||
|
ISetLocalAuthenticated;
|
||||||
|
|
||||||
|
export function loginRequest(
|
||||||
|
credentials: Partial<ICredentials>,
|
||||||
|
logoutOnError?: boolean,
|
||||||
|
isFromWebView?: boolean
|
||||||
|
): ILoginRequest {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.REQUEST,
|
||||||
|
credentials,
|
||||||
|
logoutOnError,
|
||||||
|
isFromWebView
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loginSuccess(user: Partial<IUser>): ILoginSuccess {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SUCCESS,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loginFailure(err: Record<string, any>): ILoginFailure {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.FAILURE,
|
||||||
|
err
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logout(forcedByServer = false): ILogout {
|
||||||
|
return {
|
||||||
|
type: types.LOGOUT,
|
||||||
|
forcedByServer
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setUser(user: Partial<IUser>): ISetUser {
|
||||||
|
return {
|
||||||
|
type: types.USER.SET,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setLoginServices(data: Record<string, any>): ISetServices {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SET_SERVICES,
|
||||||
|
data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPreference(preference: Record<string, any>): ISetPreference {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SET_PREFERENCE,
|
||||||
|
preference
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setLocalAuthenticated(isLocalAuthenticated: boolean): ISetLocalAuthenticated {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SET_LOCAL_AUTHENTICATED,
|
||||||
|
isLocalAuthenticated
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,62 +0,0 @@
|
||||||
import * as types from './actionsTypes';
|
|
||||||
|
|
||||||
export function subscribeRoom(rid) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.SUBSCRIBE,
|
|
||||||
rid
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unsubscribeRoom(rid) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.UNSUBSCRIBE,
|
|
||||||
rid
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function leaveRoom(roomType, room, selected) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.LEAVE,
|
|
||||||
room,
|
|
||||||
roomType,
|
|
||||||
selected
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteRoom(roomType, room, selected) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.DELETE,
|
|
||||||
room,
|
|
||||||
roomType,
|
|
||||||
selected
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function closeRoom(rid) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.CLOSE,
|
|
||||||
rid
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function forwardRoom(rid, transferData) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.FORWARD,
|
|
||||||
transferData,
|
|
||||||
rid
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removedRoom() {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.REMOVED
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function userTyping(rid, status = true) {
|
|
||||||
return {
|
|
||||||
type: types.ROOM.USER_TYPING,
|
|
||||||
rid,
|
|
||||||
status
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
|
import { ERoomType } from '../definitions/ERoomType';
|
||||||
|
import { ROOM } from './actionsTypes';
|
||||||
|
|
||||||
|
// TYPE RETURN RELATED
|
||||||
|
type ISelected = Record<string, string>;
|
||||||
|
|
||||||
|
export interface ITransferData {
|
||||||
|
roomId: string;
|
||||||
|
userId?: string;
|
||||||
|
departmentId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACTION RETURN RELATED
|
||||||
|
interface IBaseReturn extends Action {
|
||||||
|
rid: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type TSubscribeRoom = IBaseReturn;
|
||||||
|
type TUnsubscribeRoom = IBaseReturn;
|
||||||
|
type TCloseRoom = IBaseReturn;
|
||||||
|
|
||||||
|
type TRoom = Record<string, any>;
|
||||||
|
|
||||||
|
interface ILeaveRoom extends Action {
|
||||||
|
roomType: ERoomType;
|
||||||
|
room: TRoom;
|
||||||
|
selected?: ISelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IDeleteRoom extends Action {
|
||||||
|
roomType: ERoomType;
|
||||||
|
room: TRoom;
|
||||||
|
selected?: ISelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IForwardRoom extends Action {
|
||||||
|
transferData: ITransferData;
|
||||||
|
rid: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IUserTyping extends Action {
|
||||||
|
rid: string;
|
||||||
|
status: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TActionsRoom = TSubscribeRoom & TUnsubscribeRoom & TCloseRoom & ILeaveRoom & IDeleteRoom & IForwardRoom & IUserTyping;
|
||||||
|
|
||||||
|
export function subscribeRoom(rid: string): TSubscribeRoom {
|
||||||
|
return {
|
||||||
|
type: ROOM.SUBSCRIBE,
|
||||||
|
rid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unsubscribeRoom(rid: string): TUnsubscribeRoom {
|
||||||
|
return {
|
||||||
|
type: ROOM.UNSUBSCRIBE,
|
||||||
|
rid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function leaveRoom(roomType: ERoomType, room: TRoom, selected?: ISelected): ILeaveRoom {
|
||||||
|
return {
|
||||||
|
type: ROOM.LEAVE,
|
||||||
|
room,
|
||||||
|
roomType,
|
||||||
|
selected
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteRoom(roomType: ERoomType, room: TRoom, selected?: ISelected): IDeleteRoom {
|
||||||
|
return {
|
||||||
|
type: ROOM.DELETE,
|
||||||
|
room,
|
||||||
|
roomType,
|
||||||
|
selected
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeRoom(rid: string): TCloseRoom {
|
||||||
|
return {
|
||||||
|
type: ROOM.CLOSE,
|
||||||
|
rid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function forwardRoom(rid: string, transferData: ITransferData): IForwardRoom {
|
||||||
|
return {
|
||||||
|
type: ROOM.FORWARD,
|
||||||
|
transferData,
|
||||||
|
rid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removedRoom(): Action {
|
||||||
|
return {
|
||||||
|
type: ROOM.REMOVED
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userTyping(rid: string, status = true): IUserTyping {
|
||||||
|
return {
|
||||||
|
type: ROOM.USER_TYPING,
|
||||||
|
rid,
|
||||||
|
status
|
||||||
|
};
|
||||||
|
}
|
|
@ -82,6 +82,7 @@ interface IMessageBoxProps {
|
||||||
isFocused(): boolean;
|
isFocused(): boolean;
|
||||||
user: {
|
user: {
|
||||||
id: string;
|
id: string;
|
||||||
|
_id: string;
|
||||||
username: string;
|
username: string;
|
||||||
token: string;
|
token: string;
|
||||||
};
|
};
|
||||||
|
@ -1184,5 +1185,5 @@ const mapStateToProps = (state: any) => ({
|
||||||
const dispatchToProps = {
|
const dispatchToProps = {
|
||||||
typing: (rid: any, status: any) => userTypingAction(rid, status)
|
typing: (rid: any, status: any) => userTypingAction(rid, status)
|
||||||
};
|
};
|
||||||
// @ts-ignore
|
|
||||||
export default connect(mapStateToProps, dispatchToProps, null, { forwardRef: true })(withActionSheet(MessageBox)) as any;
|
export default connect(mapStateToProps, dispatchToProps, null, { forwardRef: true })(withActionSheet(MessageBox)) as any;
|
||||||
|
|
|
@ -45,7 +45,14 @@ export const SYSTEM_MESSAGES = [
|
||||||
'message_snippeted',
|
'message_snippeted',
|
||||||
'thread-created',
|
'thread-created',
|
||||||
'room_e2e_enabled',
|
'room_e2e_enabled',
|
||||||
'room_e2e_disabled'
|
'room_e2e_disabled',
|
||||||
|
'removed-user-from-team',
|
||||||
|
'added-user-to-team',
|
||||||
|
'user-added-room-to-team',
|
||||||
|
'user-converted-to-team',
|
||||||
|
'user-converted-to-channel',
|
||||||
|
'user-deleted-room-from-team',
|
||||||
|
'user-removed-room-from-team'
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SYSTEM_MESSAGE_TYPES = {
|
export const SYSTEM_MESSAGE_TYPES = {
|
||||||
|
@ -56,7 +63,14 @@ export const SYSTEM_MESSAGE_TYPES = {
|
||||||
USER_JOINED_TEAM: 'ujt',
|
USER_JOINED_TEAM: 'ujt',
|
||||||
USER_JOINED_DISCUSSION: 'ut',
|
USER_JOINED_DISCUSSION: 'ut',
|
||||||
USER_LEFT_CHANNEL: 'ul',
|
USER_LEFT_CHANNEL: 'ul',
|
||||||
USER_LEFT_TEAM: 'ult'
|
USER_LEFT_TEAM: 'ult',
|
||||||
|
REMOVED_USER_FROM_TEAM: 'removed-user-from-team',
|
||||||
|
ADDED_USER_TO_TEAM: 'added-user-to-team',
|
||||||
|
ADDED_ROOM_TO_TEAM: 'user-added-room-to-team',
|
||||||
|
CONVERTED_TO_TEAM: 'user-converted-to-team',
|
||||||
|
CONVERTED_TO_CHANNEL: 'user-converted-to-channel',
|
||||||
|
DELETED_ROOM_FROM_TEAM: 'user-deleted-room-from-team',
|
||||||
|
REMOVED_ROOM_FROM_TEAM: 'user-removed-room-from-team'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SYSTEM_MESSAGE_TYPES_WITH_AUTHOR_NAME = [
|
export const SYSTEM_MESSAGE_TYPES_WITH_AUTHOR_NAME = [
|
||||||
|
@ -67,7 +81,14 @@ export const SYSTEM_MESSAGE_TYPES_WITH_AUTHOR_NAME = [
|
||||||
SYSTEM_MESSAGE_TYPES.USER_JOINED_TEAM,
|
SYSTEM_MESSAGE_TYPES.USER_JOINED_TEAM,
|
||||||
SYSTEM_MESSAGE_TYPES.USER_JOINED_DISCUSSION,
|
SYSTEM_MESSAGE_TYPES.USER_JOINED_DISCUSSION,
|
||||||
SYSTEM_MESSAGE_TYPES.USER_LEFT_CHANNEL,
|
SYSTEM_MESSAGE_TYPES.USER_LEFT_CHANNEL,
|
||||||
SYSTEM_MESSAGE_TYPES.USER_LEFT_TEAM
|
SYSTEM_MESSAGE_TYPES.USER_LEFT_TEAM,
|
||||||
|
SYSTEM_MESSAGE_TYPES.REMOVED_USER_FROM_TEAM,
|
||||||
|
SYSTEM_MESSAGE_TYPES.ADDED_USER_TO_TEAM,
|
||||||
|
SYSTEM_MESSAGE_TYPES.ADDED_ROOM_TO_TEAM,
|
||||||
|
SYSTEM_MESSAGE_TYPES.CONVERTED_TO_TEAM,
|
||||||
|
SYSTEM_MESSAGE_TYPES.CONVERTED_TO_CHANNEL,
|
||||||
|
SYSTEM_MESSAGE_TYPES.DELETED_ROOM_FROM_TEAM,
|
||||||
|
SYSTEM_MESSAGE_TYPES.REMOVED_ROOM_FROM_TEAM
|
||||||
];
|
];
|
||||||
|
|
||||||
type TInfoMessage = {
|
type TInfoMessage = {
|
||||||
|
@ -76,6 +97,7 @@ type TInfoMessage = {
|
||||||
msg: string;
|
msg: string;
|
||||||
author: { username: string };
|
author: { username: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getInfoMessage = ({ type, role, msg, author }: TInfoMessage): string => {
|
export const getInfoMessage = ({ type, role, msg, author }: TInfoMessage): string => {
|
||||||
const { username } = author;
|
const { username } = author;
|
||||||
if (type === 'rm') {
|
if (type === 'rm') {
|
||||||
|
@ -147,6 +169,27 @@ export const getInfoMessage = ({ type, role, msg, author }: TInfoMessage): strin
|
||||||
if (type === 'room_e2e_enabled') {
|
if (type === 'room_e2e_enabled') {
|
||||||
return I18n.t('This_room_encryption_has_been_enabled_by__username_', { username });
|
return I18n.t('This_room_encryption_has_been_enabled_by__username_', { username });
|
||||||
}
|
}
|
||||||
|
if (type === 'removed-user-from-team') {
|
||||||
|
return I18n.t('Removed__username__from_team', { user_removed: username });
|
||||||
|
}
|
||||||
|
if (type === 'added-user-to-team') {
|
||||||
|
return I18n.t('Added__username__to_team', { user_added: username });
|
||||||
|
}
|
||||||
|
if (type === 'user-added-room-to-team') {
|
||||||
|
return I18n.t('added__roomName__to_team', { roomName: msg });
|
||||||
|
}
|
||||||
|
if (type === 'user-converted-to-team') {
|
||||||
|
return I18n.t('Converted__roomName__to_team', { roomName: msg });
|
||||||
|
}
|
||||||
|
if (type === 'user-converted-to-channel') {
|
||||||
|
return I18n.t('Converted__roomName__to_channel', { roomName: msg });
|
||||||
|
}
|
||||||
|
if (type === 'user-deleted-room-from-team') {
|
||||||
|
return I18n.t('Deleted__roomName__', { roomName: msg });
|
||||||
|
}
|
||||||
|
if (type === 'user-removed-room-from-team') {
|
||||||
|
return I18n.t('Removed__roomName__from_this_team', { roomName: msg });
|
||||||
|
}
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
export enum ERoomType {
|
||||||
|
p = 'group',
|
||||||
|
c = 'channel',
|
||||||
|
d = 'direct',
|
||||||
|
t = 'team',
|
||||||
|
l = 'omnichannel'
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
export interface IAttachment {
|
export interface IAttachment {
|
||||||
ts: Date;
|
ts: string | Date;
|
||||||
title: string;
|
title: string;
|
||||||
type: string;
|
type: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import Model from '@nozbe/watermelondb/Model';
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
|
||||||
export interface ICustomEmoji {
|
export interface ICustomEmoji {
|
||||||
|
_id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
aliases?: string;
|
aliases?: string[];
|
||||||
extension: string;
|
extension: string;
|
||||||
_updatedAt: Date;
|
_updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ export interface IMessage {
|
||||||
_id: string;
|
_id: string;
|
||||||
rid: string;
|
rid: string;
|
||||||
msg?: string;
|
msg?: string;
|
||||||
id?: string;
|
id: string;
|
||||||
t?: MessageType;
|
t?: MessageType;
|
||||||
ts: string | Date;
|
ts: string | Date;
|
||||||
u: IUserMessage;
|
u: IUserMessage;
|
||||||
|
@ -74,7 +74,7 @@ export interface IMessage {
|
||||||
emoji?: string;
|
emoji?: string;
|
||||||
attachments?: IAttachment[];
|
attachments?: IAttachment[];
|
||||||
urls?: IUrl[];
|
urls?: IUrl[];
|
||||||
_updatedAt: Date;
|
_updatedAt: string | Date;
|
||||||
status?: number;
|
status?: number;
|
||||||
pinned?: boolean;
|
pinned?: boolean;
|
||||||
starred?: boolean;
|
starred?: boolean;
|
||||||
|
@ -83,10 +83,10 @@ export interface IMessage {
|
||||||
role?: string;
|
role?: string;
|
||||||
drid?: string;
|
drid?: string;
|
||||||
dcount?: number;
|
dcount?: number;
|
||||||
dlm?: Date;
|
dlm?: string | Date;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
tcount?: number;
|
tcount?: number;
|
||||||
tlm?: Date;
|
tlm?: string | Date;
|
||||||
replies?: string[];
|
replies?: string[];
|
||||||
mentions?: IUserMention[];
|
mentions?: IUserMention[];
|
||||||
channels?: IUserChannel[];
|
channels?: IUserChannel[];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export interface IRocketChatRecord {
|
export interface IRocketChatRecord {
|
||||||
_id: string;
|
_id?: string;
|
||||||
_updatedAt: Date;
|
_updatedAt?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RocketChatRecordDeleted<T> = T &
|
export type RocketChatRecordDeleted<T> = T &
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import Model from '@nozbe/watermelondb/Model';
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||||
|
|
||||||
|
import { IAttachment } from './IAttachment';
|
||||||
import { IMessage } from './IMessage';
|
import { IMessage } from './IMessage';
|
||||||
import { IServedBy } from './IServedBy';
|
import { IServedBy } from './IServedBy';
|
||||||
import { SubscriptionType } from './ISubscription';
|
import { SubscriptionType } from './ISubscription';
|
||||||
|
@ -37,6 +39,7 @@ export interface IRoom {
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
e2eKeyId?: string;
|
e2eKeyId?: string;
|
||||||
avatarETag?: string;
|
avatarETag?: string;
|
||||||
|
latest?: string;
|
||||||
default?: true;
|
default?: true;
|
||||||
featured?: true;
|
featured?: true;
|
||||||
}
|
}
|
||||||
|
@ -100,3 +103,52 @@ export interface IOmnichannelRoom extends Omit<IRoom, 'default' | 'featured' | '
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TRoomModel = IRoom & Model;
|
export type TRoomModel = IRoom & Model;
|
||||||
|
|
||||||
|
export interface IServerRoomItem {
|
||||||
|
_id: string;
|
||||||
|
name: string;
|
||||||
|
fname: string;
|
||||||
|
t: SubscriptionType;
|
||||||
|
u: {
|
||||||
|
_id: string;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
customFields: {};
|
||||||
|
ts: string;
|
||||||
|
ro: boolean;
|
||||||
|
_updatedAt: string;
|
||||||
|
lm: string;
|
||||||
|
lastMessage: {
|
||||||
|
alias: string;
|
||||||
|
msg: string;
|
||||||
|
attachments: IAttachment[];
|
||||||
|
parseUrls: boolean;
|
||||||
|
bot: {
|
||||||
|
i: string;
|
||||||
|
};
|
||||||
|
groupable: boolean;
|
||||||
|
avatar: string;
|
||||||
|
ts: string;
|
||||||
|
u: IUser;
|
||||||
|
rid: string;
|
||||||
|
_id: string;
|
||||||
|
_updatedAt: string;
|
||||||
|
mentions: [];
|
||||||
|
channels: [];
|
||||||
|
md: MarkdownAST;
|
||||||
|
};
|
||||||
|
topic: string;
|
||||||
|
joinCodeRequired: boolean;
|
||||||
|
description: string;
|
||||||
|
jitsiTimeout: string;
|
||||||
|
usersCount: number;
|
||||||
|
e2eKeyId: string;
|
||||||
|
avatarETag: string;
|
||||||
|
encrypted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IServerRoom {
|
||||||
|
update: IServerRoomItem[];
|
||||||
|
remove: IServerRoomItem[];
|
||||||
|
success: boolean;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import Model from '@nozbe/watermelondb/Model';
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
|
||||||
|
import { IEnterpriseModules } from '../reducers/enterpriseModules';
|
||||||
|
|
||||||
export interface IServer {
|
export interface IServer {
|
||||||
name: string;
|
name: string;
|
||||||
iconURL: string;
|
iconURL: string;
|
||||||
|
@ -13,7 +15,7 @@ export interface IServer {
|
||||||
autoLockTime?: number;
|
autoLockTime?: number;
|
||||||
biometry?: boolean;
|
biometry?: boolean;
|
||||||
uniqueID: string;
|
uniqueID: string;
|
||||||
enterpriseModules: string;
|
enterpriseModules: IEnterpriseModules;
|
||||||
E2E_Enable: boolean;
|
E2E_Enable: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,22 @@ export interface ISettings {
|
||||||
_updatedAt?: Date;
|
_updatedAt?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPreparedSettings {
|
||||||
|
_id: string;
|
||||||
|
value: string;
|
||||||
|
enterprise: boolean;
|
||||||
|
valueAsString?: string;
|
||||||
|
valueAsBoolean?: boolean;
|
||||||
|
valueAsNumber?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISettingsIcon {
|
||||||
|
_id: string;
|
||||||
|
value: {
|
||||||
|
defaultUrl: string;
|
||||||
|
url?: string;
|
||||||
|
};
|
||||||
|
enterprise: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type TSettingsModel = ISettings & Model;
|
export type TSettingsModel = ISettings & Model;
|
||||||
|
|
|
@ -9,4 +9,8 @@ export interface ISlashCommand {
|
||||||
appId?: string;
|
appId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISlashCommandResult extends ISlashCommand {
|
||||||
|
command: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type TSlashCommandModel = ISlashCommand & Model;
|
export type TSlashCommandModel = ISlashCommand & Model;
|
||||||
|
|
|
@ -24,12 +24,20 @@ export interface IVisitor {
|
||||||
lastMessageTs: Date;
|
lastMessageTs: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ERoomTypes {
|
||||||
|
DIRECT = 'direct',
|
||||||
|
GROUP = 'group',
|
||||||
|
CHANNEL = 'channel'
|
||||||
|
}
|
||||||
|
|
||||||
export interface ISubscription {
|
export interface ISubscription {
|
||||||
_id: string; // _id belongs watermelonDB
|
_id: string; // _id belongs watermelonDB
|
||||||
id: string; // id from server
|
id: string; // id from server
|
||||||
|
_updatedAt?: string; // from server
|
||||||
|
v?: IVisitor;
|
||||||
f: boolean;
|
f: boolean;
|
||||||
t: SubscriptionType;
|
t: SubscriptionType;
|
||||||
ts: Date;
|
ts: string | Date;
|
||||||
ls: Date;
|
ls: Date;
|
||||||
name: string;
|
name: string;
|
||||||
fname?: string;
|
fname?: string;
|
||||||
|
@ -38,12 +46,14 @@ export interface ISubscription {
|
||||||
alert: boolean;
|
alert: boolean;
|
||||||
roles?: string[];
|
roles?: string[];
|
||||||
unread: number;
|
unread: number;
|
||||||
|
lm: string;
|
||||||
|
lr: string;
|
||||||
userMentions: number;
|
userMentions: number;
|
||||||
groupMentions: number;
|
groupMentions: number;
|
||||||
tunread?: string[];
|
tunread?: string[];
|
||||||
tunreadUser?: string[];
|
tunreadUser?: string[];
|
||||||
tunreadGroup?: string[];
|
tunreadGroup?: string[];
|
||||||
roomUpdatedAt: Date;
|
roomUpdatedAt: Date | number;
|
||||||
ro: boolean;
|
ro: boolean;
|
||||||
lastOpen?: Date;
|
lastOpen?: Date;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
@ -59,7 +69,7 @@ export interface ISubscription {
|
||||||
ignored?: string[];
|
ignored?: string[];
|
||||||
broadcast?: boolean;
|
broadcast?: boolean;
|
||||||
prid?: string;
|
prid?: string;
|
||||||
draftMessage?: string;
|
draftMessage?: string | null;
|
||||||
lastThreadSync?: Date;
|
lastThreadSync?: Date;
|
||||||
jitsiTimeout?: number;
|
jitsiTimeout?: number;
|
||||||
autoTranslate?: boolean;
|
autoTranslate?: boolean;
|
||||||
|
@ -88,3 +98,30 @@ export interface ISubscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TSubscriptionModel = ISubscription & Model;
|
export type TSubscriptionModel = ISubscription & Model;
|
||||||
|
|
||||||
|
export interface IServerSubscriptionItem {
|
||||||
|
_id: string;
|
||||||
|
rid: string;
|
||||||
|
u: {
|
||||||
|
_id: string;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
_updatedAt: string;
|
||||||
|
alert: boolean;
|
||||||
|
fname: string;
|
||||||
|
groupMentions: number;
|
||||||
|
name: string;
|
||||||
|
open: boolean;
|
||||||
|
t: string;
|
||||||
|
unread: number;
|
||||||
|
userMentions: number;
|
||||||
|
ls: string;
|
||||||
|
lr: string;
|
||||||
|
tunread: number[] | [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IServerSubscription {
|
||||||
|
update: IServerSubscriptionItem[];
|
||||||
|
remove: IServerSubscriptionItem[];
|
||||||
|
success: boolean;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ interface IFileThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IThreadResult {
|
export interface IThreadResult {
|
||||||
|
id: string;
|
||||||
_id: string;
|
_id: string;
|
||||||
rid: string;
|
rid: string;
|
||||||
ts: string | Date;
|
ts: string | Date;
|
||||||
|
@ -23,13 +24,13 @@ export interface IThreadResult {
|
||||||
attachments?: IAttachment[];
|
attachments?: IAttachment[];
|
||||||
md?: MarkdownAST;
|
md?: MarkdownAST;
|
||||||
u: IUserMessage;
|
u: IUserMessage;
|
||||||
_updatedAt: Date;
|
_updatedAt: string | Date;
|
||||||
urls?: IUrl[];
|
urls?: IUrl[];
|
||||||
mentions?: IUserMention[];
|
mentions?: IUserMention[];
|
||||||
channels?: IUserChannel[];
|
channels?: IUserChannel[];
|
||||||
replies?: string[];
|
replies?: string[];
|
||||||
tcount?: number;
|
tcount?: number;
|
||||||
tlm?: Date;
|
tlm?: string | Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IThread {
|
export interface IThread {
|
||||||
|
@ -38,8 +39,8 @@ export interface IThread {
|
||||||
msg?: string;
|
msg?: string;
|
||||||
t?: MessageType;
|
t?: MessageType;
|
||||||
rid: string;
|
rid: string;
|
||||||
_updatedAt?: Date;
|
_updatedAt?: string | Date;
|
||||||
ts?: Date;
|
ts?: string | Date;
|
||||||
u?: IUserMessage;
|
u?: IUserMessage;
|
||||||
alias?: string;
|
alias?: string;
|
||||||
parseUrls?: boolean;
|
parseUrls?: boolean;
|
||||||
|
@ -56,10 +57,10 @@ export interface IThread {
|
||||||
role?: string;
|
role?: string;
|
||||||
drid?: string;
|
drid?: string;
|
||||||
dcount?: number | string;
|
dcount?: number | string;
|
||||||
dlm?: number;
|
dlm?: string | Date;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
tcount?: number | string;
|
tcount?: number | string;
|
||||||
tlm?: string;
|
tlm?: string | Date;
|
||||||
replies?: string[];
|
replies?: string[];
|
||||||
mentions?: IUserMention[];
|
mentions?: IUserMention[];
|
||||||
channels?: IUserChannel[];
|
channels?: IUserChannel[];
|
||||||
|
@ -67,7 +68,7 @@ export interface IThread {
|
||||||
autoTranslate?: boolean;
|
autoTranslate?: boolean;
|
||||||
translations?: any;
|
translations?: any;
|
||||||
e2e?: string;
|
e2e?: string;
|
||||||
subscription: { id: string };
|
subscription?: { id: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TThreadModel = IThread & Model;
|
export type TThreadModel = IThread & Model;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { IReaction } from './IReaction';
|
||||||
import { IUrl } from './IUrl';
|
import { IUrl } from './IUrl';
|
||||||
|
|
||||||
export interface IThreadMessage {
|
export interface IThreadMessage {
|
||||||
|
id: string;
|
||||||
_id: string;
|
_id: string;
|
||||||
tmsg?: string;
|
tmsg?: string;
|
||||||
msg?: string;
|
msg?: string;
|
||||||
|
@ -20,7 +21,7 @@ export interface IThreadMessage {
|
||||||
emoji?: string;
|
emoji?: string;
|
||||||
attachments?: IAttachment[];
|
attachments?: IAttachment[];
|
||||||
urls?: IUrl[];
|
urls?: IUrl[];
|
||||||
_updatedAt?: Date;
|
_updatedAt?: string | Date;
|
||||||
status?: number;
|
status?: number;
|
||||||
pinned?: boolean;
|
pinned?: boolean;
|
||||||
starred?: boolean;
|
starred?: boolean;
|
||||||
|
@ -29,10 +30,10 @@ export interface IThreadMessage {
|
||||||
role?: string;
|
role?: string;
|
||||||
drid?: string;
|
drid?: string;
|
||||||
dcount?: number;
|
dcount?: number;
|
||||||
dlm?: Date;
|
dlm?: string | Date;
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
tcount?: number;
|
tcount?: number;
|
||||||
tlm?: Date;
|
tlm?: string | Date;
|
||||||
replies?: string[];
|
replies?: string[];
|
||||||
mentions?: IUserMention[];
|
mentions?: IUserMention[];
|
||||||
channels?: IUserChannel[];
|
channels?: IUserChannel[];
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import Model from '@nozbe/watermelondb/Model';
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
|
||||||
export interface IUpload {
|
export interface IUpload {
|
||||||
id: string;
|
id?: string;
|
||||||
path?: string;
|
rid?: string;
|
||||||
|
path: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
size: number;
|
size: number;
|
||||||
type?: string;
|
type?: string;
|
||||||
store?: string;
|
store?: string;
|
||||||
progress: number;
|
progress?: number;
|
||||||
error: boolean;
|
error?: boolean;
|
||||||
subscription: { id: string };
|
subscription?: { id: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TUploadModel = IUpload & Model;
|
export type TUploadModel = IUpload & Model;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Model from '@nozbe/watermelondb/Model';
|
||||||
|
|
||||||
import { UserStatus } from './UserStatus';
|
import { UserStatus } from './UserStatus';
|
||||||
import { IRocketChatRecord } from './IRocketChatRecord';
|
import { IRocketChatRecord } from './IRocketChatRecord';
|
||||||
|
import { ILoggedUser } from './ILoggedUser';
|
||||||
|
|
||||||
export interface ILoginToken {
|
export interface ILoginToken {
|
||||||
hashedToken: string;
|
hashedToken: string;
|
||||||
|
@ -93,14 +94,16 @@ export interface IUserSettings {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUser extends IRocketChatRecord {
|
export interface IUser extends IRocketChatRecord, Omit<ILoggedUser, 'username' | 'name' | 'status'> {
|
||||||
_id: string;
|
_id: string;
|
||||||
createdAt: Date;
|
id: string;
|
||||||
roles: string[];
|
token: string;
|
||||||
type: string;
|
createdAt?: Date;
|
||||||
active: boolean;
|
roles?: string[];
|
||||||
name?: string;
|
type?: string;
|
||||||
|
active?: boolean;
|
||||||
username: string;
|
username: string;
|
||||||
|
name?: string;
|
||||||
services?: IUserServices;
|
services?: IUserServices;
|
||||||
emails?: IUserEmail[];
|
emails?: IUserEmail[];
|
||||||
status?: UserStatus;
|
status?: UserStatus;
|
||||||
|
@ -115,7 +118,6 @@ export interface IUser extends IRocketChatRecord {
|
||||||
oauth?: {
|
oauth?: {
|
||||||
authorizedClients: string[];
|
authorizedClients: string[];
|
||||||
};
|
};
|
||||||
_updatedAt: Date;
|
|
||||||
statusLivechat?: string;
|
statusLivechat?: string;
|
||||||
e2e?: {
|
e2e?: {
|
||||||
private_key: string;
|
private_key: string;
|
||||||
|
|
|
@ -23,7 +23,9 @@ import { ICreateChannel } from '../../reducers/createChannel';
|
||||||
import { ICreateDiscussion } from '../../reducers/createDiscussion';
|
import { ICreateDiscussion } from '../../reducers/createDiscussion';
|
||||||
import { IEncryption } from '../../reducers/encryption';
|
import { IEncryption } from '../../reducers/encryption';
|
||||||
import { IInviteLinks } from '../../reducers/inviteLinks';
|
import { IInviteLinks } from '../../reducers/inviteLinks';
|
||||||
|
import { ILogin } from '../../reducers/login';
|
||||||
import { IRoles } from '../../reducers/roles';
|
import { IRoles } from '../../reducers/roles';
|
||||||
|
import { IRoom } from '../../reducers/room';
|
||||||
import { ISelectedUsers } from '../../reducers/selectedUsers';
|
import { ISelectedUsers } from '../../reducers/selectedUsers';
|
||||||
import { IServer } from '../../reducers/server';
|
import { IServer } from '../../reducers/server';
|
||||||
import { ISettings } from '../../reducers/settings';
|
import { ISettings } from '../../reducers/settings';
|
||||||
|
@ -33,13 +35,13 @@ import { IEnterpriseModules } from '../../reducers/enterpriseModules';
|
||||||
|
|
||||||
export interface IApplicationState {
|
export interface IApplicationState {
|
||||||
settings: ISettings;
|
settings: ISettings;
|
||||||
login: any;
|
|
||||||
meteor: IConnect;
|
meteor: IConnect;
|
||||||
|
login: ILogin;
|
||||||
server: IServer;
|
server: IServer;
|
||||||
selectedUsers: ISelectedUsers;
|
selectedUsers: ISelectedUsers;
|
||||||
app: IApp;
|
app: IApp;
|
||||||
createChannel: ICreateChannel;
|
createChannel: ICreateChannel;
|
||||||
room: any;
|
room: IRoom;
|
||||||
rooms: any;
|
rooms: any;
|
||||||
sortPreferences: any;
|
sortPreferences: any;
|
||||||
share: IShare;
|
share: IShare;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export type E2eEndpoints = {
|
||||||
|
'e2e.setUserPublicAndPrivateKeys': {
|
||||||
|
POST: (params: { public_key: string; private_key: string }) => void;
|
||||||
|
};
|
||||||
|
};
|
|
@ -9,7 +9,7 @@ export type EmojiCustomEndpoints = {
|
||||||
} & PaginatedResult;
|
} & PaginatedResult;
|
||||||
};
|
};
|
||||||
'emoji-custom.list': {
|
'emoji-custom.list': {
|
||||||
GET: (params: { query: string }) => {
|
GET: (params: { updatedSince: string }) => {
|
||||||
emojis?: {
|
emojis?: {
|
||||||
update: ICustomEmojiDescriptor[];
|
update: ICustomEmojiDescriptor[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { OauthCustomConfiguration } from './settings';
|
||||||
import { UserEndpoints } from './user';
|
import { UserEndpoints } from './user';
|
||||||
import { UsersEndpoints } from './users';
|
import { UsersEndpoints } from './users';
|
||||||
import { TeamsEndpoints } from './teams';
|
import { TeamsEndpoints } from './teams';
|
||||||
|
import { E2eEndpoints } from './e2e';
|
||||||
|
|
||||||
export type Endpoints = ChannelsEndpoints &
|
export type Endpoints = ChannelsEndpoints &
|
||||||
ChatEndpoints &
|
ChatEndpoints &
|
||||||
|
@ -30,4 +31,5 @@ export type Endpoints = ChannelsEndpoints &
|
||||||
OauthCustomConfiguration &
|
OauthCustomConfiguration &
|
||||||
UserEndpoints &
|
UserEndpoints &
|
||||||
UsersEndpoints &
|
UsersEndpoints &
|
||||||
TeamsEndpoints;
|
TeamsEndpoints &
|
||||||
|
E2eEndpoints;
|
||||||
|
|
|
@ -788,5 +788,24 @@
|
||||||
"Enable_Message_Parser": "Enable Message Parser",
|
"Enable_Message_Parser": "Enable Message Parser",
|
||||||
"Unsupported_format": "Unsupported format",
|
"Unsupported_format": "Unsupported format",
|
||||||
"Downloaded_file": "Downloaded file",
|
"Downloaded_file": "Downloaded file",
|
||||||
"Error_Download_file": "Error while downloading file"
|
"Error_Download_file": "Error while downloading file",
|
||||||
|
"added__roomName__to_team": "added #{{roomName}} to this Team",
|
||||||
|
"Added__username__to_team": "added @{{user_added}} to this Team",
|
||||||
|
"Converted__roomName__to_team": "converted #{{roomName}} to a Team",
|
||||||
|
"Converted__roomName__to_channel": "converted #{{roomName}} to a Channel",
|
||||||
|
"Converting_team_to_channel": "Converting Team to Channel",
|
||||||
|
"Deleted__roomName__": "deleted #{{roomName}}",
|
||||||
|
"Message_HideType_added_user_to_team": "Hide \"User Added to Team\" messages",
|
||||||
|
"Message_HideType_removed_user_from_team": "Hide \"User Removed from Team\" messages",
|
||||||
|
"Message_HideType_ujt": "Hide \"User Joined Team\" messages",
|
||||||
|
"Message_HideType_ult": "Hide \"User Left Team\" messages",
|
||||||
|
"Message_HideType_user_added_room_to_team": "Hide \"User Added Room to Team\" messages",
|
||||||
|
"Message_HideType_user_converted_to_channel": "Hide \"User converted team to a Channel\" messages",
|
||||||
|
"Message_HideType_user_converted_to_team": "Hide \"User converted channel to a Team\" messages",
|
||||||
|
"Message_HideType_user_deleted_room_from_team": "Hide \"User deleted room from Team\" messages",
|
||||||
|
"Message_HideType_user_removed_room_from_team": "Hide \"User removed room from Team\" messages",
|
||||||
|
"Removed__roomName__from_this_team": "removed #{{roomName}} from this Team",
|
||||||
|
"Removed__username__from_team": "removed @{{user_removed}} from this Team",
|
||||||
|
"User_joined_team": "joined this Team",
|
||||||
|
"User_left_team": "left this Team"
|
||||||
}
|
}
|
|
@ -443,7 +443,7 @@ class Encryption {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Decrypt a message
|
// Decrypt a message
|
||||||
decryptMessage = async (message: Partial<IMessage>) => {
|
decryptMessage = async (message: Pick<IMessage, 't' | 'e2e' | 'rid' | 'msg' | 'tmsg'>) => {
|
||||||
const { t, e2e } = message;
|
const { t, e2e } = message;
|
||||||
|
|
||||||
// Prevent create a new instance if this room was encrypted sometime ago
|
// Prevent create a new instance if this room was encrypted sometime ago
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { store as reduxStore } from '../auxStore';
|
import { ISubscription } from '../../definitions';
|
||||||
import Navigation from '../Navigation';
|
|
||||||
import { events, logEvent } from '../../utils/log';
|
import { events, logEvent } from '../../utils/log';
|
||||||
|
import { store } from '../auxStore';
|
||||||
|
import Navigation from '../Navigation';
|
||||||
|
import sdk from '../rocketchat';
|
||||||
|
|
||||||
async function jitsiURL({ room }) {
|
async function jitsiURL({ room }: { room: ISubscription }) {
|
||||||
const { settings } = reduxStore.getState();
|
const { settings } = store.getState();
|
||||||
const { Jitsi_Enabled } = settings;
|
const { Jitsi_Enabled } = settings;
|
||||||
|
|
||||||
if (!Jitsi_Enabled) {
|
if (!Jitsi_Enabled) {
|
||||||
|
@ -19,7 +21,7 @@ async function jitsiURL({ room }) {
|
||||||
let queryString = '';
|
let queryString = '';
|
||||||
if (Jitsi_Enabled_TokenAuth) {
|
if (Jitsi_Enabled_TokenAuth) {
|
||||||
try {
|
try {
|
||||||
const accessToken = await this.methodCallWrapper('jitsi:generateAccessToken', room?.rid);
|
const accessToken = await sdk.methodCallWrapper('jitsi:generateAccessToken', room?.rid);
|
||||||
queryString = `?jwt=${accessToken}`;
|
queryString = `?jwt=${accessToken}`;
|
||||||
} catch {
|
} catch {
|
||||||
logEvent(events.RA_JITSI_F);
|
logEvent(events.RA_JITSI_F);
|
||||||
|
@ -30,23 +32,23 @@ async function jitsiURL({ room }) {
|
||||||
if (Jitsi_URL_Room_Hash) {
|
if (Jitsi_URL_Room_Hash) {
|
||||||
rname = uniqueID + room?.rid;
|
rname = uniqueID + room?.rid;
|
||||||
} else {
|
} else {
|
||||||
rname = encodeURIComponent(room.t === 'd' ? room?.usernames?.join?.(' x ') : room?.name);
|
rname = encodeURIComponent(room.t === 'd' ? (room?.usernames?.join?.(' x ') as string) : room?.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${protocol}${domain}${prefix}${rname}${queryString}`;
|
return `${protocol}${domain}${prefix}${rname}${queryString}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function callJitsiWithoutServer(path) {
|
export function callJitsiWithoutServer(path: string): void {
|
||||||
logEvent(events.RA_JITSI_VIDEO);
|
logEvent(events.RA_JITSI_VIDEO);
|
||||||
const { Jitsi_SSL } = reduxStore.getState().settings;
|
const { Jitsi_SSL } = store.getState().settings;
|
||||||
const protocol = Jitsi_SSL ? 'https://' : 'http://';
|
const protocol = Jitsi_SSL ? 'https://' : 'http://';
|
||||||
const url = `${protocol}${path}`;
|
const url = `${protocol}${path}`;
|
||||||
Navigation.navigate('JitsiMeetView', { url, onlyAudio: false });
|
Navigation.navigate('JitsiMeetView', { url, onlyAudio: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callJitsi(room, onlyAudio = false) {
|
async function callJitsi(room: ISubscription, onlyAudio = false): Promise<void> {
|
||||||
logEvent(onlyAudio ? events.RA_JITSI_AUDIO : events.RA_JITSI_VIDEO);
|
logEvent(onlyAudio ? events.RA_JITSI_AUDIO : events.RA_JITSI_VIDEO);
|
||||||
const url = await jitsiURL.call(this, { room });
|
const url = await jitsiURL({ room });
|
||||||
Navigation.navigate('JitsiMeetView', { url, onlyAudio, rid: room?.rid });
|
Navigation.navigate('JitsiMeetView', { url, onlyAudio, rid: room?.rid });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import database from '../database';
|
import { ERoomTypes } from '../../definitions';
|
||||||
import { store } from '../auxStore';
|
import { store } from '../auxStore';
|
||||||
|
import database from '../database';
|
||||||
|
import RocketChat from '../rocketchat';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
|
||||||
const restTypes = {
|
const restTypes = {
|
||||||
channel: 'channels',
|
channel: 'channels',
|
||||||
|
@ -7,27 +10,28 @@ const restTypes = {
|
||||||
group: 'groups'
|
group: 'groups'
|
||||||
};
|
};
|
||||||
|
|
||||||
async function open({ type, rid, name }) {
|
async function open({ type, rid, name }: { type: ERoomTypes; rid: string; name: string }) {
|
||||||
try {
|
try {
|
||||||
const params = rid ? { roomId: rid } : { roomName: name };
|
const params = rid ? { roomId: rid } : { roomName: name };
|
||||||
|
|
||||||
// if it's a direct link without rid we'll create a new dm
|
// if it's a direct link without rid we'll create a new dm
|
||||||
// if the dm already exists it'll return the existent
|
// if the dm already exists it'll return the existent
|
||||||
if (type === 'direct' && !rid) {
|
if (type === ERoomTypes.DIRECT && !rid) {
|
||||||
const result = await this.createDirectMessage(name);
|
const result = await RocketChat.createDirectMessage(name);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const { room } = result;
|
const { room } = result;
|
||||||
room.rid = room._id;
|
room.rid = room._id as string;
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it's a group we need to check if you can open
|
// if it's a group we need to check if you can open
|
||||||
if (type === 'group') {
|
if (type === ERoomTypes.GROUP) {
|
||||||
try {
|
try {
|
||||||
// RC 0.61.0
|
// RC 0.61.0
|
||||||
await this.sdk.post(`${restTypes[type]}.open`, params);
|
// @ts-ignore
|
||||||
} catch (e) {
|
await sdk.post(`${restTypes[type]}.open`, params);
|
||||||
|
} catch (e: any) {
|
||||||
if (!(e.data && /is already open/.test(e.data.error))) {
|
if (!(e.data && /is already open/.test(e.data.error))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -36,9 +40,10 @@ async function open({ type, rid, name }) {
|
||||||
|
|
||||||
// if it's a channel or group and the link don't have rid
|
// if it's a channel or group and the link don't have rid
|
||||||
// we'll get info from the room
|
// we'll get info from the room
|
||||||
if ((type === 'channel' || type === 'group') && !rid) {
|
if ((type === ERoomTypes.CHANNEL || type === ERoomTypes.GROUP) && !rid) {
|
||||||
// RC 0.72.0
|
// RC 0.72.0
|
||||||
const result = await this.sdk.get(`${restTypes[type]}.info`, params);
|
// @ts-ignore
|
||||||
|
const result: any = await sdk.get(`channel.info`, params);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const room = result[type];
|
const room = result[type];
|
||||||
room.rid = room._id;
|
room.rid = room._id;
|
||||||
|
@ -56,7 +61,7 @@ async function open({ type, rid, name }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function canOpenRoom({ rid, path, isCall }) {
|
export default async function canOpenRoom({ rid, path, isCall }: { rid: string; isCall: boolean; path: string }): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const subsCollection = db.get('subscriptions');
|
const subsCollection = db.get('subscriptions');
|
||||||
|
@ -86,8 +91,9 @@ export default async function canOpenRoom({ rid, path, isCall }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const [type, name] = path.split('/');
|
const [type, name] = path.split('/');
|
||||||
|
const t = type as ERoomTypes;
|
||||||
try {
|
try {
|
||||||
const result = await open.call(this, { type, rid, name });
|
const result = await open({ type: t, rid, name });
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
|
@ -1,11 +1,12 @@
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
import { compareServerVersion } from '../utils';
|
import { compareServerVersion } from '../utils';
|
||||||
import { store as reduxStore } from '../auxStore';
|
import { store as reduxStore } from '../auxStore';
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { clearEnterpriseModules, setEnterpriseModules as setEnterpriseModulesAction } from '../../actions/enterpriseModules';
|
import { clearEnterpriseModules, setEnterpriseModules as setEnterpriseModulesAction } from '../../actions/enterpriseModules';
|
||||||
|
|
||||||
export const LICENSE_OMNICHANNEL_MOBILE_ENTERPRISE = 'omnichannel-mobile-enterprise';
|
const LICENSE_OMNICHANNEL_MOBILE_ENTERPRISE = 'omnichannel-mobile-enterprise';
|
||||||
export const LICENSE_LIVECHAT_ENTERPRISE = 'livechat-enterprise';
|
const LICENSE_LIVECHAT_ENTERPRISE = 'livechat-enterprise';
|
||||||
|
|
||||||
export async function setEnterpriseModules() {
|
export async function setEnterpriseModules() {
|
||||||
try {
|
try {
|
||||||
|
@ -29,17 +30,17 @@ export async function setEnterpriseModules() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnterpriseModules() {
|
export function getEnterpriseModules() {
|
||||||
return new Promise(async resolve => {
|
return new Promise<void>(async resolve => {
|
||||||
try {
|
try {
|
||||||
const { version: serverVersion, server: serverId } = reduxStore.getState().server;
|
const { version: serverVersion, server: serverId } = reduxStore.getState().server;
|
||||||
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.1.0')) {
|
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.1.0')) {
|
||||||
// RC 3.1.0
|
// RC 3.1.0
|
||||||
const enterpriseModules = await this.methodCallWrapper('license:getModules');
|
const enterpriseModules = await sdk.methodCallWrapper('license:getModules');
|
||||||
if (enterpriseModules) {
|
if (enterpriseModules) {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serversCollection = serversDB.get('servers');
|
const serversCollection = serversDB.get('servers');
|
||||||
const server = await serversCollection.find(serverId);
|
const server = await serversCollection.find(serverId);
|
||||||
await serversDB.action(async () => {
|
await serversDB.write(async () => {
|
||||||
await server.update(s => {
|
await server.update(s => {
|
||||||
s.enterpriseModules = enterpriseModules.join(',');
|
s.enterpriseModules = enterpriseModules.join(',');
|
||||||
});
|
});
|
||||||
|
@ -56,7 +57,7 @@ export function getEnterpriseModules() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasLicense(module) {
|
export function hasLicense(module: string) {
|
||||||
const { enterpriseModules } = reduxStore.getState();
|
const { enterpriseModules } = reduxStore.getState();
|
||||||
return enterpriseModules.includes(module);
|
return enterpriseModules.includes(module);
|
||||||
}
|
}
|
|
@ -1,13 +1,22 @@
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
|
|
||||||
|
import { ICustomEmojis } from '../../reducers/customEmojis';
|
||||||
import { compareServerVersion } from '../utils';
|
import { compareServerVersion } from '../utils';
|
||||||
import { store as reduxStore } from '../auxStore';
|
import { store as reduxStore } from '../auxStore';
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { setCustomEmojis as setCustomEmojisAction } from '../../actions/customEmojis';
|
import { setCustomEmojis as setCustomEmojisAction } from '../../actions/customEmojis';
|
||||||
|
import { ICustomEmoji, TCustomEmojiModel } from '../../definitions';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
|
||||||
const getUpdatedSince = allEmojis => {
|
interface IUpdateEmojis {
|
||||||
|
update: TCustomEmojiModel[];
|
||||||
|
remove?: TCustomEmojiModel[];
|
||||||
|
allRecords: TCustomEmojiModel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUpdatedSince = (allEmojis: ICustomEmoji[]) => {
|
||||||
if (!allEmojis.length) {
|
if (!allEmojis.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -19,27 +28,27 @@ const getUpdatedSince = allEmojis => {
|
||||||
return ordered && ordered[0]._updatedAt.toISOString();
|
return ordered && ordered[0]._updatedAt.toISOString();
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateEmojis = async ({ update = [], remove = [], allRecords }) => {
|
const updateEmojis = async ({ update = [], remove = [], allRecords }: IUpdateEmojis) => {
|
||||||
if (!((update && update.length) || (remove && remove.length))) {
|
if (!((update && update.length) || (remove && remove.length))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const emojisCollection = db.get('custom_emojis');
|
const emojisCollection = db.get('custom_emojis');
|
||||||
let emojisToCreate = [];
|
let emojisToCreate: TCustomEmojiModel[] = [];
|
||||||
let emojisToUpdate = [];
|
let emojisToUpdate: TCustomEmojiModel[] = [];
|
||||||
let emojisToDelete = [];
|
let emojisToDelete: TCustomEmojiModel[] = [];
|
||||||
|
|
||||||
// Create or update
|
// Create or update
|
||||||
if (update && update.length) {
|
if (update && update.length) {
|
||||||
emojisToCreate = update.filter(i1 => !allRecords.find(i2 => i1._id === i2.id));
|
const filterEmojisToCreate = update.filter(i1 => !allRecords.find(i2 => i1._id === i2.id));
|
||||||
emojisToUpdate = allRecords.filter(i1 => update.find(i2 => i1.id === i2._id));
|
const filterEmojisToUpdate = allRecords.filter(i1 => update.find(i2 => i1.id === i2._id));
|
||||||
emojisToCreate = emojisToCreate.map(emoji =>
|
emojisToCreate = filterEmojisToCreate.map(emoji =>
|
||||||
emojisCollection.prepareCreate(e => {
|
emojisCollection.prepareCreate(e => {
|
||||||
e._raw = sanitizedRaw({ id: emoji._id }, emojisCollection.schema);
|
e._raw = sanitizedRaw({ id: emoji._id }, emojisCollection.schema);
|
||||||
Object.assign(e, emoji);
|
Object.assign(e, emoji);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
emojisToUpdate = emojisToUpdate.map(emoji => {
|
emojisToUpdate = filterEmojisToUpdate.map(emoji => {
|
||||||
const newEmoji = update.find(e => e._id === emoji.id);
|
const newEmoji = update.find(e => e._id === emoji.id);
|
||||||
return emoji.prepareUpdate(e => {
|
return emoji.prepareUpdate(e => {
|
||||||
Object.assign(e, newEmoji);
|
Object.assign(e, newEmoji);
|
||||||
|
@ -48,12 +57,12 @@ const updateEmojis = async ({ update = [], remove = [], allRecords }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove && remove.length) {
|
if (remove && remove.length) {
|
||||||
emojisToDelete = allRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
const filterEmojisToDelete = allRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||||
emojisToDelete = emojisToDelete.map(emoji => emoji.prepareDestroyPermanently());
|
emojisToDelete = filterEmojisToDelete.map(emoji => emoji.prepareDestroyPermanently());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await db.batch(...emojisToCreate, ...emojisToUpdate, ...emojisToDelete);
|
await db.batch(...emojisToCreate, ...emojisToUpdate, ...emojisToDelete);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
@ -66,26 +75,34 @@ export async function setCustomEmojis() {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const emojisCollection = db.get('custom_emojis');
|
const emojisCollection = db.get('custom_emojis');
|
||||||
const allEmojis = await emojisCollection.query().fetch();
|
const allEmojis = await emojisCollection.query().fetch();
|
||||||
const parsed = allEmojis.reduce((ret, item) => {
|
const parsed = allEmojis.reduce((ret: ICustomEmojis, item) => {
|
||||||
ret[item.name] = {
|
if (item.name) {
|
||||||
name: item.name,
|
ret[item.name] = {
|
||||||
extension: item.extension
|
|
||||||
};
|
|
||||||
item.aliases.forEach(alias => {
|
|
||||||
ret[alias] = {
|
|
||||||
name: item.name,
|
name: item.name,
|
||||||
extension: item.extension
|
extension: item.extension
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (item.aliases) {
|
||||||
|
item.aliases.forEach(alias => {
|
||||||
|
if (item.name) {
|
||||||
|
ret[alias] = {
|
||||||
|
name: item.name,
|
||||||
|
extension: item.extension
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}, {});
|
}, {});
|
||||||
reduxStore.dispatch(setCustomEmojisAction(parsed));
|
reduxStore.dispatch(setCustomEmojisAction(parsed));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCustomEmojis() {
|
export function getCustomEmojis() {
|
||||||
return new Promise(async resolve => {
|
return new Promise<void>(async resolve => {
|
||||||
try {
|
try {
|
||||||
const serverVersion = reduxStore.getState().server.version;
|
const serverVersion = reduxStore.getState().server.version as string;
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const emojisCollection = db.get('custom_emojis');
|
const emojisCollection = db.get('custom_emojis');
|
||||||
const allRecords = await emojisCollection.query().fetch();
|
const allRecords = await emojisCollection.query().fetch();
|
||||||
|
@ -94,10 +111,11 @@ export function getCustomEmojis() {
|
||||||
// if server version is lower than 0.75.0, fetches from old api
|
// if server version is lower than 0.75.0, fetches from old api
|
||||||
if (compareServerVersion(serverVersion, 'lowerThan', '0.75.0')) {
|
if (compareServerVersion(serverVersion, 'lowerThan', '0.75.0')) {
|
||||||
// RC 0.61.0
|
// RC 0.61.0
|
||||||
const result = await this.sdk.get('emoji-custom');
|
// @ts-ignore
|
||||||
|
const result = await sdk.get('emoji-custom');
|
||||||
|
// @ts-ignore
|
||||||
let { emojis } = result;
|
let { emojis } = result;
|
||||||
emojis = emojis.filter(emoji => !updatedSince || emoji._updatedAt > updatedSince);
|
emojis = emojis.filter((emoji: TCustomEmojiModel) => !updatedSince || emoji._updatedAt.toISOString() > updatedSince);
|
||||||
const changedEmojis = await updateEmojis({ update: emojis, allRecords });
|
const changedEmojis = await updateEmojis({ update: emojis, allRecords });
|
||||||
|
|
||||||
// `setCustomEmojis` is fired on selectServer
|
// `setCustomEmojis` is fired on selectServer
|
||||||
|
@ -106,28 +124,28 @@ export function getCustomEmojis() {
|
||||||
setCustomEmojis();
|
setCustomEmojis();
|
||||||
}
|
}
|
||||||
return resolve();
|
return resolve();
|
||||||
} else {
|
}
|
||||||
const params = {};
|
const params: { updatedSince: string } = { updatedSince: '' };
|
||||||
if (updatedSince) {
|
if (updatedSince) {
|
||||||
params.updatedSince = updatedSince;
|
params.updatedSince = updatedSince;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RC 0.75.0
|
// RC 0.75.0
|
||||||
const result = await this.sdk.get('emoji-custom.list', params);
|
const result = await sdk.get('emoji-custom.list', params);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { emojis } = result;
|
const { emojis } = result;
|
||||||
const { update, remove } = emojis;
|
// @ts-ignore
|
||||||
const changedEmojis = await updateEmojis({ update, remove, allRecords });
|
const { update, remove } = emojis;
|
||||||
|
const changedEmojis = await updateEmojis({ update, remove, allRecords });
|
||||||
|
|
||||||
// `setCustomEmojis` is fired on selectServer
|
// `setCustomEmojis` is fired on selectServer
|
||||||
// We run it again only if emojis were changed
|
// We run it again only if emojis were changed
|
||||||
if (changedEmojis) {
|
if (changedEmojis) {
|
||||||
setCustomEmojis();
|
setCustomEmojis();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
|
@ -1,4 +1,5 @@
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
import { getRoleById } from '../database/services/Role';
|
import { getRoleById } from '../database/services/Role';
|
||||||
|
@ -6,8 +7,10 @@ import log from '../../utils/log';
|
||||||
import { store as reduxStore } from '../auxStore';
|
import { store as reduxStore } from '../auxStore';
|
||||||
import { removeRoles, setRoles as setRolesAction, updateRoles } from '../../actions/roles';
|
import { removeRoles, setRoles as setRolesAction, updateRoles } from '../../actions/roles';
|
||||||
import protectedFunction from './helpers/protectedFunction';
|
import protectedFunction from './helpers/protectedFunction';
|
||||||
|
import { TRoleModel } from '../../definitions';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
|
||||||
export async function setRoles() {
|
export async function setRoles(): Promise<void> {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const rolesCollection = db.get('roles');
|
const rolesCollection = db.get('roles');
|
||||||
const allRoles = await rolesCollection.query().fetch();
|
const allRoles = await rolesCollection.query().fetch();
|
||||||
|
@ -15,7 +18,17 @@ export async function setRoles() {
|
||||||
reduxStore.dispatch(setRolesAction(parsed));
|
reduxStore.dispatch(setRolesAction(parsed));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function onRolesChanged(ddpMessage) {
|
interface IRolesChanged {
|
||||||
|
fields: {
|
||||||
|
args: {
|
||||||
|
type: string;
|
||||||
|
_id: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function onRolesChanged(ddpMessage: IRolesChanged): Promise<void> {
|
||||||
const { type, _id, description } = ddpMessage.fields.args[0];
|
const { type, _id, description } = ddpMessage.fields.args[0];
|
||||||
if (/changed/.test(type)) {
|
if (/changed/.test(type)) {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
|
@ -42,7 +55,6 @@ export async function onRolesChanged(ddpMessage) {
|
||||||
}
|
}
|
||||||
if (/removed/.test(type)) {
|
if (/removed/.test(type)) {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const rolesCollection = db.get('roles');
|
|
||||||
try {
|
try {
|
||||||
const roleRecord = await getRoleById(_id);
|
const roleRecord = await getRoleById(_id);
|
||||||
if (roleRecord) {
|
if (roleRecord) {
|
||||||
|
@ -57,12 +69,12 @@ export async function onRolesChanged(ddpMessage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRoles() {
|
export function getRoles(): Promise<void> {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
try {
|
try {
|
||||||
// RC 0.70.0
|
// RC 0.70.0
|
||||||
const result = await this.sdk.get('roles.list');
|
const result = await sdk.get('roles.list');
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return resolve();
|
return resolve();
|
||||||
|
@ -71,18 +83,18 @@ export function getRoles() {
|
||||||
const { roles } = result;
|
const { roles } = result;
|
||||||
|
|
||||||
if (roles && roles.length) {
|
if (roles && roles.length) {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
const rolesCollections = db.get('roles');
|
const rolesCollections = db.get('roles');
|
||||||
const allRolesRecords = await rolesCollections.query().fetch();
|
const allRolesRecords = await rolesCollections.query().fetch();
|
||||||
|
|
||||||
// filter roles
|
// filter roles
|
||||||
let rolesToCreate = roles.filter(i1 => !allRolesRecords.find(i2 => i1._id === i2.id));
|
const filteredRolesToCreate = roles.filter(i1 => !allRolesRecords.find(i2 => i1._id === i2.id));
|
||||||
let rolesToUpdate = allRolesRecords.filter(i1 => roles.find(i2 => i1.id === i2._id));
|
const filteredRolesToUpdate = allRolesRecords.filter(i1 => roles.find(i2 => i1.id === i2._id));
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
rolesToCreate = rolesToCreate.map(role =>
|
const rolesToCreate = filteredRolesToCreate.map(role =>
|
||||||
rolesCollections.prepareCreate(
|
rolesCollections.prepareCreate(
|
||||||
protectedFunction(r => {
|
protectedFunction((r: TRoleModel) => {
|
||||||
r._raw = sanitizedRaw({ id: role._id }, rolesCollections.schema);
|
r._raw = sanitizedRaw({ id: role._id }, rolesCollections.schema);
|
||||||
Object.assign(r, role);
|
Object.assign(r, role);
|
||||||
})
|
})
|
||||||
|
@ -90,16 +102,16 @@ export function getRoles() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
rolesToUpdate = rolesToUpdate.map(role => {
|
const rolesToUpdate = filteredRolesToUpdate.map(role => {
|
||||||
const newRole = roles.find(r => r._id === role.id);
|
const newRole = roles.find(r => r._id === role.id);
|
||||||
return role.prepareUpdate(
|
return role.prepareUpdate(
|
||||||
protectedFunction(r => {
|
protectedFunction((r: TRoleModel) => {
|
||||||
Object.assign(r, newRole);
|
Object.assign(r, newRole);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const allRecords = [...rolesToCreate, ...rolesToUpdate];
|
const allRecords: Model[] = [...rolesToCreate, ...rolesToUpdate];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.batch(...allRecords);
|
await db.batch(...allRecords);
|
|
@ -1,7 +1,8 @@
|
||||||
|
import { IRoom } from '../../definitions';
|
||||||
import { getSubscriptionByRoomId } from '../database/services/Subscription';
|
import { getSubscriptionByRoomId } from '../database/services/Subscription';
|
||||||
import RocketChat from '../rocketchat';
|
import RocketChat from '../rocketchat';
|
||||||
|
|
||||||
const getRoomInfo = async rid => {
|
const getRoomInfo = async (rid: string): Promise<Pick<IRoom, 'rid' | 'name' | 'fname' | 't'> | null> => {
|
||||||
let result;
|
let result;
|
||||||
result = await getSubscriptionByRoomId(rid);
|
result = await getSubscriptionByRoomId(rid);
|
||||||
if (result) {
|
if (result) {
|
|
@ -6,8 +6,12 @@ export default function (updatedSince: Date) {
|
||||||
if (updatedSince) {
|
if (updatedSince) {
|
||||||
const updatedDate = updatedSince.toISOString();
|
const updatedDate = updatedSince.toISOString();
|
||||||
// TODO: missing definitions from server
|
// TODO: missing definitions from server
|
||||||
// @ts-ignore
|
return Promise.all([
|
||||||
return Promise.all([sdk.get('subscriptions.get', { updatedDate }), sdk.get('rooms.get', { updatedDate })]);
|
// @ts-ignore
|
||||||
|
sdk.get('subscriptions.get', { updatedSince: updatedDate }),
|
||||||
|
// @ts-ignore
|
||||||
|
sdk.get('rooms.get', { updatedSince: updatedDate })
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
// TODO: missing definitions from server
|
// TODO: missing definitions from server
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
|
|
||||||
import { addSettings, clearSettings } from '../../actions/settings';
|
import { addSettings, clearSettings } from '../../actions/settings';
|
||||||
import RocketChat from '../rocketchat';
|
|
||||||
import { store as reduxStore } from '../auxStore';
|
|
||||||
import settings from '../../constants/settings';
|
|
||||||
import log from '../../utils/log';
|
|
||||||
import database from '../database';
|
|
||||||
import fetch from '../../utils/fetch';
|
|
||||||
import { DEFAULT_AUTO_LOCK } from '../../constants/localAuthentication';
|
import { DEFAULT_AUTO_LOCK } from '../../constants/localAuthentication';
|
||||||
|
import settings from '../../constants/settings';
|
||||||
|
import { IPreparedSettings, ISettingsIcon } from '../../definitions';
|
||||||
|
import fetch from '../../utils/fetch';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import { store as reduxStore } from '../auxStore';
|
||||||
|
import database from '../database';
|
||||||
|
import RocketChat from '../rocketchat';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
import protectedFunction from './helpers/protectedFunction';
|
import protectedFunction from './helpers/protectedFunction';
|
||||||
|
|
||||||
const serverInfoKeys = [
|
const serverInfoKeys = [
|
||||||
|
@ -41,7 +43,7 @@ const loginSettings = [
|
||||||
'Accounts_Iframe_api_method'
|
'Accounts_Iframe_api_method'
|
||||||
];
|
];
|
||||||
|
|
||||||
const serverInfoUpdate = async (serverInfo, iconSetting) => {
|
const serverInfoUpdate = async (serverInfo: IPreparedSettings[], iconSetting: ISettingsIcon) => {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serverId = reduxStore.getState().server.server;
|
const serverId = reduxStore.getState().server.server;
|
||||||
const serversCollection = serversDB.get('servers');
|
const serversCollection = serversDB.get('servers');
|
||||||
|
@ -73,7 +75,7 @@ const serverInfoUpdate = async (serverInfo, iconSetting) => {
|
||||||
return { ...allSettings, autoLockTime: DEFAULT_AUTO_LOCK };
|
return { ...allSettings, autoLockTime: DEFAULT_AUTO_LOCK };
|
||||||
}
|
}
|
||||||
// if Force_Screen_Lock_After > 0 and forceScreenLock is enabled, use it
|
// if Force_Screen_Lock_After > 0 and forceScreenLock is enabled, use it
|
||||||
if (setting.valueAsNumber > 0 && forceScreenLock) {
|
if (setting.valueAsNumber && setting.valueAsNumber > 0 && forceScreenLock) {
|
||||||
return { ...allSettings, autoLockTime: setting.valueAsNumber };
|
return { ...allSettings, autoLockTime: setting.valueAsNumber };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +93,7 @@ const serverInfoUpdate = async (serverInfo, iconSetting) => {
|
||||||
info = { ...info, iconURL };
|
info = { ...info, iconURL };
|
||||||
}
|
}
|
||||||
|
|
||||||
await serversDB.action(async () => {
|
await serversDB.write(async () => {
|
||||||
try {
|
try {
|
||||||
await server.update(record => {
|
await server.update(record => {
|
||||||
Object.assign(record, info);
|
Object.assign(record, info);
|
||||||
|
@ -102,7 +104,7 @@ const serverInfoUpdate = async (serverInfo, iconSetting) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getLoginSettings({ server }) {
|
export async function getLoginSettings({ server }: { server: string }): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const settingsParams = JSON.stringify(loginSettings);
|
const settingsParams = JSON.stringify(loginSettings);
|
||||||
const result = await fetch(`${server}/api/v1/settings.public?query={"_id":{"$in":${settingsParams}}}`).then(response =>
|
const result = await fetch(`${server}/api/v1/settings.public?query={"_id":{"$in":${settingsParams}}}`).then(response =>
|
||||||
|
@ -111,14 +113,14 @@ export async function getLoginSettings({ server }) {
|
||||||
|
|
||||||
if (result.success && result.settings.length) {
|
if (result.success && result.settings.length) {
|
||||||
reduxStore.dispatch(clearSettings());
|
reduxStore.dispatch(clearSettings());
|
||||||
reduxStore.dispatch(addSettings(this.parseSettings(this._prepareSettings(result.settings))));
|
reduxStore.dispatch(addSettings(RocketChat.parseSettings(RocketChat._prepareSettings(result.settings))));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setSettings() {
|
export async function setSettings(): Promise<void> {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const settingsCollection = db.get('settings');
|
const settingsCollection = db.get('settings');
|
||||||
const settingsRecords = await settingsCollection.query().fetch();
|
const settingsRecords = await settingsCollection.query().fetch();
|
||||||
|
@ -133,17 +135,19 @@ export async function setSettings() {
|
||||||
reduxStore.dispatch(addSettings(RocketChat.parseSettings(parsed.slice(0, parsed.length))));
|
reduxStore.dispatch(addSettings(RocketChat.parseSettings(parsed.slice(0, parsed.length))));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function subscribeSettings() {
|
export function subscribeSettings(): void {
|
||||||
return RocketChat.subscribe('stream-notify-all', 'public-settings-changed');
|
return RocketChat.subscribe('stream-notify-all', 'public-settings-changed');
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function () {
|
type IData = ISettingsIcon | IPreparedSettings;
|
||||||
|
|
||||||
|
export default async function (): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const settingsParams = Object.keys(settings).filter(key => !loginSettings.includes(key));
|
const settingsParams = Object.keys(settings).filter(key => !loginSettings.includes(key));
|
||||||
// RC 0.60.0
|
// RC 0.60.0
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
`${this.sdk.client.host}/api/v1/settings.public?query={"_id":{"$in":${JSON.stringify(settingsParams)}}}&count=${
|
`${sdk.current.client.host}/api/v1/settings.public?query={"_id":{"$in":${JSON.stringify(settingsParams)}}}&count=${
|
||||||
settingsParams.length
|
settingsParams.length
|
||||||
}`
|
}`
|
||||||
).then(response => response.json());
|
).then(response => response.json());
|
||||||
|
@ -151,33 +155,32 @@ export default async function () {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = result.settings || [];
|
const data: IData[] = result.settings || [];
|
||||||
const filteredSettings = this._prepareSettings(data);
|
const filteredSettings: IPreparedSettings[] = RocketChat._prepareSettings(data);
|
||||||
const filteredSettingsIds = filteredSettings.map(s => s._id);
|
const filteredSettingsIds = filteredSettings.map(s => s._id);
|
||||||
|
|
||||||
reduxStore.dispatch(addSettings(this.parseSettings(filteredSettings)));
|
reduxStore.dispatch(addSettings(RocketChat.parseSettings(filteredSettings)));
|
||||||
|
|
||||||
// filter server info
|
// filter server info
|
||||||
const serverInfo = filteredSettings.filter(i1 => serverInfoKeys.includes(i1._id));
|
const serverInfo = filteredSettings.filter(i1 => serverInfoKeys.includes(i1._id));
|
||||||
const iconSetting = data.find(item => item._id === 'Assets_favicon_512');
|
const iconSetting = data.find(icon => icon._id === 'Assets_favicon_512');
|
||||||
try {
|
try {
|
||||||
await serverInfoUpdate(serverInfo, iconSetting);
|
await serverInfoUpdate(serverInfo, iconSetting as ISettingsIcon);
|
||||||
} catch {
|
} catch {
|
||||||
// Server not found
|
// Server not found
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
const settingsCollection = db.get('settings');
|
const settingsCollection = db.get('settings');
|
||||||
const allSettingsRecords = await settingsCollection.query(Q.where('id', Q.oneOf(filteredSettingsIds))).fetch();
|
const allSettingsRecords = await settingsCollection.query(Q.where('id', Q.oneOf(filteredSettingsIds))).fetch();
|
||||||
|
|
||||||
// filter settings
|
// filter settings
|
||||||
let settingsToCreate = filteredSettings.filter(i1 => !allSettingsRecords.find(i2 => i1._id === i2.id));
|
const settingsToCreate = filteredSettings.filter(i1 => !allSettingsRecords.find(i2 => i1._id === i2.id));
|
||||||
let settingsToUpdate = allSettingsRecords.filter(i1 => filteredSettings.find(i2 => i1.id === i2._id));
|
const settingsToUpdate = allSettingsRecords.filter(i1 => filteredSettings.find(i2 => i1.id === i2._id));
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
settingsToCreate = settingsToCreate.map(setting =>
|
const settingsToCreateMapped = settingsToCreate.map(setting =>
|
||||||
settingsCollection.prepareCreate(
|
settingsCollection.prepareCreate(
|
||||||
protectedFunction(s => {
|
protectedFunction((s: any) => {
|
||||||
s._raw = sanitizedRaw({ id: setting._id }, settingsCollection.schema);
|
s._raw = sanitizedRaw({ id: setting._id }, settingsCollection.schema);
|
||||||
Object.assign(s, setting);
|
Object.assign(s, setting);
|
||||||
})
|
})
|
||||||
|
@ -185,16 +188,16 @@ export default async function () {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
settingsToUpdate = settingsToUpdate.map(setting => {
|
const settingsToUpdateMapped = settingsToUpdate.map(setting => {
|
||||||
const newSetting = filteredSettings.find(s => s._id === setting.id);
|
const newSetting = filteredSettings.find(s => s._id === setting.id);
|
||||||
return setting.prepareUpdate(
|
return setting.prepareUpdate(
|
||||||
protectedFunction(s => {
|
protectedFunction((s: any) => {
|
||||||
Object.assign(s, newSetting);
|
Object.assign(s, newSetting);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const allRecords = [...settingsToCreate, ...settingsToUpdate];
|
const allRecords = [...settingsToCreateMapped, ...settingsToUpdateMapped];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.batch(...allRecords);
|
await db.batch(...allRecords);
|
|
@ -1,6 +1,7 @@
|
||||||
import RocketChat from '../rocketchat';
|
import RocketChat from '../rocketchat';
|
||||||
|
import { IMessage } from '../../definitions';
|
||||||
|
|
||||||
const getSingleMessage = (messageId: string) =>
|
const getSingleMessage = (messageId: string): Promise<IMessage> =>
|
||||||
new Promise(async (resolve, reject) => {
|
new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.getSingleMessage(messageId);
|
const result = await RocketChat.getSingleMessage(messageId);
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
|
||||||
|
|
||||||
import database from '../database';
|
|
||||||
import log from '../../utils/log';
|
|
||||||
import protectedFunction from './helpers/protectedFunction';
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
const db = database.active;
|
|
||||||
return new Promise(async resolve => {
|
|
||||||
try {
|
|
||||||
// RC 0.60.2
|
|
||||||
const result = await this.sdk.get('commands.list');
|
|
||||||
|
|
||||||
if (!result.success) {
|
|
||||||
console.log(result);
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { commands } = result;
|
|
||||||
|
|
||||||
if (commands && commands.length) {
|
|
||||||
await db.action(async () => {
|
|
||||||
const slashCommandsCollection = db.get('slash_commands');
|
|
||||||
const allSlashCommandsRecords = await slashCommandsCollection.query().fetch();
|
|
||||||
|
|
||||||
// filter slash commands
|
|
||||||
let slashCommandsToCreate = commands.filter(i1 => !allSlashCommandsRecords.find(i2 => i1.command === i2.id));
|
|
||||||
let slashCommandsToUpdate = allSlashCommandsRecords.filter(i1 => commands.find(i2 => i1.id === i2.command));
|
|
||||||
let slashCommandsToDelete = allSlashCommandsRecords.filter(
|
|
||||||
i1 => !slashCommandsToCreate.find(i2 => i2.command === i1.id) && !slashCommandsToUpdate.find(i2 => i2.id === i1.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create
|
|
||||||
slashCommandsToCreate = slashCommandsToCreate.map(command =>
|
|
||||||
slashCommandsCollection.prepareCreate(
|
|
||||||
protectedFunction(s => {
|
|
||||||
s._raw = sanitizedRaw({ id: command.command }, slashCommandsCollection.schema);
|
|
||||||
Object.assign(s, command);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update
|
|
||||||
slashCommandsToUpdate = slashCommandsToUpdate.map(command => {
|
|
||||||
const newCommand = commands.find(s => s.command === command.id);
|
|
||||||
return command.prepareUpdate(
|
|
||||||
protectedFunction(s => {
|
|
||||||
Object.assign(s, newCommand);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete
|
|
||||||
slashCommandsToDelete = slashCommandsToDelete.map(command => command.prepareDestroyPermanently());
|
|
||||||
|
|
||||||
const allRecords = [...slashCommandsToCreate, ...slashCommandsToUpdate, ...slashCommandsToDelete];
|
|
||||||
|
|
||||||
try {
|
|
||||||
await db.batch(...allRecords);
|
|
||||||
} catch (e) {
|
|
||||||
log(e);
|
|
||||||
}
|
|
||||||
return allRecords.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log(e);
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
|
|
||||||
|
import database from '../database';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import protectedFunction from './helpers/protectedFunction';
|
||||||
|
import { ISlashCommandResult, TSlashCommandModel } from '../../definitions';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
|
||||||
|
export default function getSlashCommands() {
|
||||||
|
const db = database.active;
|
||||||
|
return new Promise<void>(async resolve => {
|
||||||
|
try {
|
||||||
|
// RC 0.60.2
|
||||||
|
// @ts-ignore
|
||||||
|
const result = await sdk.get('commands.list');
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const { commands } = result;
|
||||||
|
if (commands && commands.length) {
|
||||||
|
await db.write(async () => {
|
||||||
|
const slashCommandsCollection = db.get('slash_commands');
|
||||||
|
const allSlashCommandsRecords = await slashCommandsCollection.query().fetch();
|
||||||
|
|
||||||
|
// filter slash commands
|
||||||
|
const filteredSlashCommandsToCreate = commands.filter(
|
||||||
|
(i1: ISlashCommandResult) => !allSlashCommandsRecords.find(i2 => i1.command === i2.id)
|
||||||
|
);
|
||||||
|
const filteredSlashCommandsToUpdate = allSlashCommandsRecords.filter(i1 =>
|
||||||
|
commands.find((i2: ISlashCommandResult) => i1.id === i2.command)
|
||||||
|
);
|
||||||
|
const filteredSlashCommandsToDelete = allSlashCommandsRecords.filter(
|
||||||
|
i1 =>
|
||||||
|
!filteredSlashCommandsToCreate.find((i2: ISlashCommandResult) => i2.command === i1.id) &&
|
||||||
|
!filteredSlashCommandsToUpdate.find(i2 => i2.id === i1.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create
|
||||||
|
const slashCommandsToCreate = filteredSlashCommandsToCreate.map((command: ISlashCommandResult) =>
|
||||||
|
slashCommandsCollection.prepareCreate(
|
||||||
|
protectedFunction((s: TSlashCommandModel) => {
|
||||||
|
s._raw = sanitizedRaw({ id: command.command }, slashCommandsCollection.schema);
|
||||||
|
Object.assign(s, command);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update
|
||||||
|
const slashCommandsToUpdate = filteredSlashCommandsToUpdate.map(command => {
|
||||||
|
const newCommand = commands.find((s: ISlashCommandResult) => s.command === command.id);
|
||||||
|
return command.prepareUpdate(
|
||||||
|
protectedFunction((s: TSlashCommandModel) => {
|
||||||
|
Object.assign(s, newCommand);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
const slashCommandsToDelete = filteredSlashCommandsToDelete.map(command => command.prepareDestroyPermanently());
|
||||||
|
|
||||||
|
const allRecords = [...slashCommandsToCreate, ...slashCommandsToUpdate, ...slashCommandsToDelete];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.batch(...allRecords);
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
return allRecords.length;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -6,11 +6,12 @@ import { getThreadById } from '../database/services/Thread';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { Encryption } from '../encryption';
|
import { Encryption } from '../encryption';
|
||||||
import getSingleMessage from './getSingleMessage';
|
import getSingleMessage from './getSingleMessage';
|
||||||
|
import { IThread, TThreadModel } from '../../definitions';
|
||||||
|
|
||||||
const buildThreadName = thread => thread.msg || thread?.attachments?.[0]?.title;
|
const buildThreadName = (thread: IThread): string | undefined => thread.msg || thread?.attachments?.[0]?.title;
|
||||||
|
|
||||||
const getThreadName = async (rid, tmid, messageId) => {
|
const getThreadName = async (rid: string, tmid: string, messageId: string): Promise<string | undefined> => {
|
||||||
let tmsg;
|
let tmsg: string | undefined;
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const threadCollection = db.get('threads');
|
const threadCollection = db.get('threads');
|
||||||
|
@ -18,7 +19,7 @@ const getThreadName = async (rid, tmid, messageId) => {
|
||||||
const threadRecord = await getThreadById(tmid);
|
const threadRecord = await getThreadById(tmid);
|
||||||
if (threadRecord) {
|
if (threadRecord) {
|
||||||
tmsg = buildThreadName(threadRecord);
|
tmsg = buildThreadName(threadRecord);
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await messageRecord?.update(m => {
|
await messageRecord?.update(m => {
|
||||||
m.tmsg = tmsg;
|
m.tmsg = tmsg;
|
||||||
});
|
});
|
||||||
|
@ -27,11 +28,11 @@ const getThreadName = async (rid, tmid, messageId) => {
|
||||||
let thread = await getSingleMessage(tmid);
|
let thread = await getSingleMessage(tmid);
|
||||||
thread = await Encryption.decryptMessage(thread);
|
thread = await Encryption.decryptMessage(thread);
|
||||||
tmsg = buildThreadName(thread);
|
tmsg = buildThreadName(thread);
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await db.batch(
|
await db.batch(
|
||||||
threadCollection?.prepareCreate(t => {
|
threadCollection?.prepareCreate((t: TThreadModel) => {
|
||||||
t._raw = sanitizedRaw({ id: thread._id }, threadCollection.schema);
|
t._raw = sanitizedRaw({ id: thread._id }, threadCollection.schema);
|
||||||
t.subscription.id = rid;
|
if (t.subscription) t.subscription.id = rid;
|
||||||
Object.assign(t, thread);
|
Object.assign(t, thread);
|
||||||
}),
|
}),
|
||||||
messageRecord?.prepareUpdate(m => {
|
messageRecord?.prepareUpdate(m => {
|
|
@ -1,14 +1,17 @@
|
||||||
import { InteractionManager } from 'react-native';
|
import { InteractionManager } from 'react-native';
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
|
|
||||||
|
import { IActiveUsers } from '../../reducers/activeUsers';
|
||||||
import { compareServerVersion } from '../utils';
|
import { compareServerVersion } from '../utils';
|
||||||
import { store as reduxStore } from '../auxStore';
|
import { store as reduxStore } from '../auxStore';
|
||||||
import { setActiveUsers } from '../../actions/activeUsers';
|
import { setActiveUsers } from '../../actions/activeUsers';
|
||||||
import { setUser } from '../../actions/login';
|
import { setUser } from '../../actions/login';
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
|
import { IRocketChat, IUser } from '../../definitions';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
|
||||||
export function subscribeUsersPresence() {
|
export function subscribeUsersPresence(this: IRocketChat) {
|
||||||
const serverVersion = reduxStore.getState().server.version;
|
const serverVersion = reduxStore.getState().server.version as string;
|
||||||
|
|
||||||
// if server is lower than 1.1.0
|
// if server is lower than 1.1.0
|
||||||
if (compareServerVersion(serverVersion, 'lowerThan', '1.1.0')) {
|
if (compareServerVersion(serverVersion, 'lowerThan', '1.1.0')) {
|
||||||
|
@ -17,22 +20,22 @@ export function subscribeUsersPresence() {
|
||||||
this.activeUsersSubTimeout = false;
|
this.activeUsersSubTimeout = false;
|
||||||
}
|
}
|
||||||
this.activeUsersSubTimeout = setTimeout(() => {
|
this.activeUsersSubTimeout = setTimeout(() => {
|
||||||
this.sdk.subscribe('activeUsers');
|
sdk.subscribe('activeUsers');
|
||||||
}, 5000);
|
}, 5000);
|
||||||
} else if (compareServerVersion(serverVersion, 'lowerThan', '4.1.0')) {
|
} else if (compareServerVersion(serverVersion, 'lowerThan', '4.1.0')) {
|
||||||
this.sdk.subscribe('stream-notify-logged', 'user-status');
|
sdk.subscribe('stream-notify-logged', 'user-status');
|
||||||
}
|
}
|
||||||
|
|
||||||
// RC 0.49.1
|
// RC 0.49.1
|
||||||
this.sdk.subscribe('stream-notify-logged', 'updateAvatar');
|
sdk.subscribe('stream-notify-logged', 'updateAvatar');
|
||||||
// RC 0.58.0
|
// RC 0.58.0
|
||||||
this.sdk.subscribe('stream-notify-logged', 'Users:NameChanged');
|
sdk.subscribe('stream-notify-logged', 'Users:NameChanged');
|
||||||
}
|
}
|
||||||
|
|
||||||
let ids = [];
|
let ids: string[] = [];
|
||||||
|
|
||||||
export default async function getUsersPresence() {
|
export default async function getUsersPresence() {
|
||||||
const serverVersion = reduxStore.getState().server.version;
|
const serverVersion = reduxStore.getState().server.version as string;
|
||||||
const { user: loggedUser } = reduxStore.getState().login;
|
const { user: loggedUser } = reduxStore.getState().login;
|
||||||
|
|
||||||
// if server is greather than or equal 1.1.0
|
// if server is greather than or equal 1.1.0
|
||||||
|
@ -51,17 +54,17 @@ export default async function getUsersPresence() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// RC 1.1.0
|
// RC 1.1.0
|
||||||
const result = await this.sdk.get('users.presence', params);
|
const result = (await sdk.get('users.presence' as any, params as any)) as any;
|
||||||
|
|
||||||
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '4.1.0')) {
|
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '4.1.0')) {
|
||||||
this.sdk.subscribeRaw('stream-user-presence', ['', { added: ids }]);
|
sdk.subscribeRaw('stream-user-presence', ['', { added: ids }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const { users } = result;
|
const { users } = result;
|
||||||
|
|
||||||
const activeUsers = ids.reduce((ret, id) => {
|
const activeUsers = ids.reduce((ret: IActiveUsers, id) => {
|
||||||
const user = users.find(u => u._id === id) ?? { _id: id, status: 'offline' };
|
const user = users.find((u: IUser) => u._id === id) ?? { _id: id, status: 'offline' };
|
||||||
const { _id, status, statusText } = user;
|
const { _id, status, statusText } = user;
|
||||||
|
|
||||||
if (loggedUser && loggedUser.id === _id) {
|
if (loggedUser && loggedUser.id === _id) {
|
||||||
|
@ -78,17 +81,17 @@ export default async function getUsersPresence() {
|
||||||
|
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const userCollection = db.get('users');
|
const userCollection = db.get('users');
|
||||||
users.forEach(async user => {
|
users.forEach(async (user: IUser) => {
|
||||||
try {
|
try {
|
||||||
const userRecord = await userCollection.find(user._id);
|
const userRecord = await userCollection.find(user._id);
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await userRecord.update(u => {
|
await userRecord.update(u => {
|
||||||
Object.assign(u, user);
|
Object.assign(u, user);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// User not found
|
// User not found
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await userCollection.create(u => {
|
await userCollection.create(u => {
|
||||||
u._raw = sanitizedRaw({ id: user._id }, userCollection.schema);
|
u._raw = sanitizedRaw({ id: user._id }, userCollection.schema);
|
||||||
Object.assign(u, user);
|
Object.assign(u, user);
|
||||||
|
@ -103,11 +106,11 @@ export default async function getUsersPresence() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let usersTimer = null;
|
let usersTimer: number | null = null;
|
||||||
export function getUserPresence(uid) {
|
export function getUserPresence(uid: string) {
|
||||||
if (!usersTimer) {
|
if (!usersTimer) {
|
||||||
usersTimer = setTimeout(() => {
|
usersTimer = setTimeout(() => {
|
||||||
getUsersPresence.call(this);
|
getUsersPresence();
|
||||||
usersTimer = null;
|
usersTimer = null;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
|
@ -1,15 +1,18 @@
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
|
import { IServerSubscriptionItem, IServerRoomItem } from '../../../definitions';
|
||||||
import database from '../../database';
|
import database from '../../database';
|
||||||
|
|
||||||
export default async (subscriptions = [], rooms = []) => {
|
export default async (subscriptions: IServerSubscriptionItem[], rooms: IServerRoomItem[]) => {
|
||||||
|
let sub = subscriptions;
|
||||||
|
let room = rooms;
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
|
|
||||||
const roomIds = rooms.filter(r => !subscriptions.find(s => s.rid === r._id)).map(r => r._id);
|
const roomIds = rooms.filter(r => !subscriptions.find(s => s.rid === r._id)).map(r => r._id);
|
||||||
let existingSubs = await subCollection.query(Q.where('rid', Q.oneOf(roomIds))).fetch();
|
const existingSubs = await subCollection.query(Q.where('rid', Q.oneOf(roomIds))).fetch();
|
||||||
existingSubs = existingSubs.map(s => ({
|
const mappedExistingSubs = existingSubs.map(s => ({
|
||||||
_id: s._id,
|
_id: s._id,
|
||||||
f: s.f,
|
f: s.f,
|
||||||
t: s.t,
|
t: s.t,
|
||||||
|
@ -55,11 +58,12 @@ export default async (subscriptions = [], rooms = []) => {
|
||||||
E2EKey: s.E2EKey,
|
E2EKey: s.E2EKey,
|
||||||
avatarETag: s.avatarETag
|
avatarETag: s.avatarETag
|
||||||
}));
|
}));
|
||||||
subscriptions = subscriptions.concat(existingSubs);
|
// Assign
|
||||||
|
sub = subscriptions.concat(mappedExistingSubs as unknown as IServerSubscriptionItem);
|
||||||
|
|
||||||
const subsIds = subscriptions.filter(s => !rooms.find(r => s.rid === r._id)).map(s => s._id);
|
const subsIds = subscriptions.filter(s => !rooms.find(r => s.rid === r._id)).map(s => s._id);
|
||||||
let existingRooms = await subCollection.query(Q.where('id', Q.oneOf(subsIds))).fetch();
|
const existingRooms = await subCollection.query(Q.where('id', Q.oneOf(subsIds))).fetch();
|
||||||
existingRooms = existingRooms.map(r => ({
|
const mappedExistingRooms = existingRooms.map(r => ({
|
||||||
_updatedAt: r._updatedAt,
|
_updatedAt: r._updatedAt,
|
||||||
lastMessage: r.lastMessage,
|
lastMessage: r.lastMessage,
|
||||||
description: r.description,
|
description: r.description,
|
||||||
|
@ -84,13 +88,14 @@ export default async (subscriptions = [], rooms = []) => {
|
||||||
e2eKeyId: r.e2eKeyId,
|
e2eKeyId: r.e2eKeyId,
|
||||||
avatarETag: r.avatarETag
|
avatarETag: r.avatarETag
|
||||||
}));
|
}));
|
||||||
rooms = rooms.concat(existingRooms);
|
// Assign
|
||||||
|
room = rooms.concat(mappedExistingRooms as unknown as IServerRoomItem);
|
||||||
} catch {
|
} catch {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscriptions,
|
subscriptions: sub,
|
||||||
rooms
|
rooms: room
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
export default function (message) {
|
export default function (message: { type: string; url: string }) {
|
||||||
if (/image/.test(message.type)) {
|
if (/image/.test(message.type)) {
|
||||||
return { image_url: message.url };
|
return { image_url: message.url };
|
||||||
}
|
}
|
|
@ -5,17 +5,18 @@ import { store as reduxStore } from '../../auxStore';
|
||||||
import { compareServerVersion } from '../../utils';
|
import { compareServerVersion } from '../../utils';
|
||||||
import findSubscriptionsRooms from './findSubscriptionsRooms';
|
import findSubscriptionsRooms from './findSubscriptionsRooms';
|
||||||
import normalizeMessage from './normalizeMessage';
|
import normalizeMessage from './normalizeMessage';
|
||||||
|
import { ISubscription, IServerRoom, IServerSubscription, IServerSubscriptionItem, IServerRoomItem } from '../../../definitions';
|
||||||
// TODO: delete and update
|
// TODO: delete and update
|
||||||
|
|
||||||
export const merge = (subscription, room) => {
|
export const merge = (
|
||||||
const serverVersion = reduxStore.getState().server.version;
|
subscription: ISubscription | IServerSubscriptionItem,
|
||||||
subscription = EJSON.fromJSONValue(subscription);
|
room?: ISubscription | IServerRoomItem
|
||||||
room = EJSON.fromJSONValue(room);
|
): ISubscription => {
|
||||||
|
const serverVersion = reduxStore.getState().server.version as string;
|
||||||
|
subscription = EJSON.fromJSONValue(subscription) as ISubscription;
|
||||||
|
|
||||||
if (!subscription) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (room) {
|
if (room) {
|
||||||
|
room = EJSON.fromJSONValue(room) as ISubscription;
|
||||||
if (room._updatedAt) {
|
if (room._updatedAt) {
|
||||||
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
||||||
subscription.description = room.description;
|
subscription.description = room.description;
|
||||||
|
@ -28,15 +29,21 @@ export const merge = (subscription, room) => {
|
||||||
subscription.usernames = room.usernames;
|
subscription.usernames = room.usernames;
|
||||||
subscription.uids = room.uids;
|
subscription.uids = room.uids;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compareServerVersion(serverVersion, 'lowerThan', '3.7.0')) {
|
if (compareServerVersion(serverVersion, 'lowerThan', '3.7.0')) {
|
||||||
const updatedAt = room?._updatedAt ? new Date(room._updatedAt) : null;
|
const updatedAt = room?._updatedAt ? new Date(room._updatedAt) : null;
|
||||||
const lastMessageTs = subscription?.lastMessage?.ts ? new Date(subscription.lastMessage.ts) : null;
|
const lastMessageTs = subscription?.lastMessage?.ts ? new Date(subscription.lastMessage.ts) : null;
|
||||||
|
// @ts-ignore
|
||||||
|
// If all parameters are null it will return zero, if only one is null it will return its timestamp only.
|
||||||
|
// "It works", but it's not the best solution. It does not accept "Date" as a parameter, but it works.
|
||||||
subscription.roomUpdatedAt = Math.max(updatedAt, lastMessageTs);
|
subscription.roomUpdatedAt = Math.max(updatedAt, lastMessageTs);
|
||||||
} else {
|
} else {
|
||||||
// https://github.com/RocketChat/Rocket.Chat/blob/develop/app/ui-sidenav/client/roomList.js#L180
|
// https://github.com/RocketChat/Rocket.Chat/blob/develop/app/ui-sidenav/client/roomList.js#L180
|
||||||
const lastRoomUpdate = room.lm || subscription.ts || subscription._updatedAt;
|
const lastRoomUpdate = room.lm || subscription.ts || subscription._updatedAt;
|
||||||
|
// @ts-ignore Same as above scenario
|
||||||
subscription.roomUpdatedAt = subscription.lr
|
subscription.roomUpdatedAt = subscription.lr
|
||||||
? Math.max(new Date(subscription.lr), new Date(lastRoomUpdate))
|
? // @ts-ignore Same as above scenario
|
||||||
|
Math.max(new Date(subscription.lr), new Date(lastRoomUpdate))
|
||||||
: lastRoomUpdate;
|
: lastRoomUpdate;
|
||||||
}
|
}
|
||||||
subscription.ro = room.ro;
|
subscription.ro = room.ro;
|
||||||
|
@ -76,7 +83,7 @@ export const merge = (subscription, room) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subscription.name) {
|
if (!subscription.name) {
|
||||||
subscription.name = subscription.fname;
|
subscription.name = subscription.fname as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subscription.autoTranslate) {
|
if (!subscription.autoTranslate) {
|
||||||
|
@ -88,29 +95,24 @@ export const merge = (subscription, room) => {
|
||||||
return subscription;
|
return subscription;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async (subscriptions = [], rooms = []) => {
|
export default async (serverSubscriptions: IServerSubscription, serverRooms: IServerRoom): Promise<ISubscription[]> => {
|
||||||
if (subscriptions.update) {
|
const subscriptions = serverSubscriptions.update;
|
||||||
subscriptions = subscriptions.update;
|
const rooms = serverRooms.update;
|
||||||
rooms = rooms.update;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find missing rooms/subscriptions on local database
|
// Find missing rooms/subscriptions on local database
|
||||||
({ subscriptions, rooms } = await findSubscriptionsRooms(subscriptions, rooms));
|
const findData = await findSubscriptionsRooms(subscriptions, rooms);
|
||||||
// Merge each subscription into a room
|
// Merge each subscription into a room
|
||||||
subscriptions = subscriptions.map(s => {
|
const mergedSubscriptions = findData.subscriptions.map(subscription => {
|
||||||
const index = rooms.findIndex(({ _id }) => _id === s.rid);
|
const index = rooms.findIndex(({ _id }) => _id === subscription.rid);
|
||||||
// Room not found
|
// Room not found
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return merge(s);
|
return merge(subscription);
|
||||||
}
|
}
|
||||||
const [room] = rooms.splice(index, 1);
|
const [room] = rooms.splice(index, 1);
|
||||||
return merge(s, room);
|
return merge(subscription, room);
|
||||||
});
|
});
|
||||||
// Decrypt all subscriptions missing decryption
|
// Decrypt all subscriptions missing decryption
|
||||||
subscriptions = await Encryption.decryptSubscriptions(subscriptions);
|
const decryptedSubscriptions = (await Encryption.decryptSubscriptions(mergedSubscriptions)) as ISubscription[];
|
||||||
|
|
||||||
return {
|
return decryptedSubscriptions;
|
||||||
subscriptions,
|
|
||||||
rooms
|
|
||||||
};
|
|
||||||
};
|
};
|
|
@ -5,32 +5,41 @@ import log from '../../utils/log';
|
||||||
import { getMessageById } from '../database/services/Message';
|
import { getMessageById } from '../database/services/Message';
|
||||||
import { generateLoadMoreId } from '../utils';
|
import { generateLoadMoreId } from '../utils';
|
||||||
import updateMessages from './updateMessages';
|
import updateMessages from './updateMessages';
|
||||||
|
import { IMessage, TMessageModel } from '../../definitions';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
import roomTypeToApiType, { RoomTypes } from '../rocketchat/methods/roomTypeToApiType';
|
||||||
|
|
||||||
const COUNT = 50;
|
const COUNT = 50;
|
||||||
|
|
||||||
async function load({ rid: roomId, latest, t }) {
|
async function load({ rid: roomId, latest, t }: { rid: string; latest?: string; t: RoomTypes }) {
|
||||||
let params = { roomId, count: COUNT };
|
let params = { roomId, count: COUNT } as { roomId: string; count: number; latest?: string };
|
||||||
if (latest) {
|
if (latest) {
|
||||||
params = { ...params, latest: new Date(latest).toISOString() };
|
params = { ...params, latest: new Date(latest).toISOString() };
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiType = this.roomTypeToApiType(t);
|
const apiType = roomTypeToApiType(t);
|
||||||
if (!apiType) {
|
if (!apiType) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// RC 0.48.0
|
// RC 0.48.0
|
||||||
const data = await this.sdk.get(`${apiType}.history`, params);
|
// @ts-ignore
|
||||||
|
const data: any = await sdk.get(`${apiType}.history`, params);
|
||||||
if (!data || data.status === 'error') {
|
if (!data || data.status === 'error') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return data.messages;
|
return data.messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function loadMessagesForRoom(args) {
|
export default function loadMessagesForRoom(args: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomTypes;
|
||||||
|
latest: string;
|
||||||
|
loaderItem: TMessageModel;
|
||||||
|
}): Promise<IMessage[] | []> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const data = await load.call(this, args);
|
const data = await load(args);
|
||||||
if (data?.length) {
|
if (data?.length) {
|
||||||
const lastMessage = data[data.length - 1];
|
const lastMessage = data[data.length - 1];
|
||||||
const lastMessageRecord = await getMessageById(lastMessage._id);
|
const lastMessageRecord = await getMessageById(lastMessage._id);
|
||||||
|
@ -46,9 +55,8 @@ export default function loadMessagesForRoom(args) {
|
||||||
}
|
}
|
||||||
await updateMessages({ rid: args.rid, update: data, loaderItem: args.loaderItem });
|
await updateMessages({ rid: args.rid, update: data, loaderItem: args.loaderItem });
|
||||||
return resolve(data);
|
return resolve(data);
|
||||||
} else {
|
|
||||||
return resolve([]);
|
|
||||||
}
|
}
|
||||||
|
return resolve([]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
reject(e);
|
reject(e);
|
|
@ -1,44 +0,0 @@
|
||||||
import database from '../database';
|
|
||||||
import log from '../../utils/log';
|
|
||||||
import updateMessages from './updateMessages';
|
|
||||||
|
|
||||||
const getLastUpdate = async rid => {
|
|
||||||
try {
|
|
||||||
const db = database.active;
|
|
||||||
const subsCollection = db.get('subscriptions');
|
|
||||||
const sub = await subsCollection.find(rid);
|
|
||||||
return sub.lastOpen.toISOString();
|
|
||||||
} catch (e) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function load({ rid: roomId, lastOpen }) {
|
|
||||||
let lastUpdate;
|
|
||||||
if (lastOpen) {
|
|
||||||
lastUpdate = new Date(lastOpen).toISOString();
|
|
||||||
} else {
|
|
||||||
lastUpdate = await getLastUpdate(roomId);
|
|
||||||
}
|
|
||||||
// RC 0.60.0
|
|
||||||
const { result } = await this.sdk.get('chat.syncMessages', { roomId, lastUpdate });
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function loadMissedMessages(args) {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
try {
|
|
||||||
const data = await load.call(this, { rid: args.rid, lastOpen: args.lastOpen });
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
const { updated, deleted } = data;
|
|
||||||
await updateMessages({ rid: args.rid, update: updated, remove: deleted });
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
} catch (e) {
|
|
||||||
log(e);
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { ILastMessage } from '../../definitions';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import database from '../database';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
import updateMessages from './updateMessages';
|
||||||
|
|
||||||
|
const getLastUpdate = async (rid: string) => {
|
||||||
|
try {
|
||||||
|
const db = database.active;
|
||||||
|
const subsCollection = db.get('subscriptions');
|
||||||
|
const sub = await subsCollection.find(rid);
|
||||||
|
return sub.lastOpen?.toISOString();
|
||||||
|
} catch (e) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function load({ rid: roomId, lastOpen }: { rid: string; lastOpen: string }) {
|
||||||
|
let lastUpdate;
|
||||||
|
if (lastOpen) {
|
||||||
|
lastUpdate = new Date(lastOpen).toISOString();
|
||||||
|
} else {
|
||||||
|
lastUpdate = await getLastUpdate(roomId);
|
||||||
|
}
|
||||||
|
// RC 0.60.0
|
||||||
|
// @ts-ignore // this method dont have type
|
||||||
|
const { result } = await sdk.get('chat.syncMessages', { roomId, lastUpdate });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function loadMissedMessages(args: { rid: string; lastOpen: string }): Promise<void> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const data = await load({ rid: args.rid, lastOpen: args.lastOpen });
|
||||||
|
if (data) {
|
||||||
|
const { updated, deleted }: { updated: ILastMessage[]; deleted: ILastMessage[] } = data;
|
||||||
|
// @ts-ignore // TODO: remove loaderItem obligatoriness
|
||||||
|
await updateMessages({ rid: args.rid, update: updated, remove: deleted });
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -7,13 +7,22 @@ import { getMessageById } from '../database/services/Message';
|
||||||
import { MESSAGE_TYPE_LOAD_NEXT_CHUNK } from '../../constants/messageTypeLoad';
|
import { MESSAGE_TYPE_LOAD_NEXT_CHUNK } from '../../constants/messageTypeLoad';
|
||||||
import { generateLoadMoreId } from '../utils';
|
import { generateLoadMoreId } from '../utils';
|
||||||
import updateMessages from './updateMessages';
|
import updateMessages from './updateMessages';
|
||||||
|
import { IMessage, TMessageModel } from '../../definitions';
|
||||||
|
import RocketChat from '../rocketchat';
|
||||||
|
|
||||||
const COUNT = 50;
|
const COUNT = 50;
|
||||||
|
|
||||||
export default function loadNextMessages(args) {
|
interface ILoadNextMessages {
|
||||||
|
rid: string;
|
||||||
|
ts: string;
|
||||||
|
tmid: string;
|
||||||
|
loaderItem: TMessageModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function loadNextMessages(args: ILoadNextMessages): Promise<IMessage | []> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const data = await this.methodCallWrapper('loadNextMessages', args.rid, args.ts, COUNT);
|
const data = await RocketChat.methodCallWrapper('loadNextMessages', args.rid, args.ts, COUNT);
|
||||||
let messages = EJSON.fromJSONValue(data?.messages);
|
let messages = EJSON.fromJSONValue(data?.messages);
|
||||||
messages = orderBy(messages, 'ts');
|
messages = orderBy(messages, 'ts');
|
||||||
if (messages?.length) {
|
if (messages?.length) {
|
||||||
|
@ -31,9 +40,8 @@ export default function loadNextMessages(args) {
|
||||||
}
|
}
|
||||||
await updateMessages({ rid: args.rid, update: messages, loaderItem: args.loaderItem });
|
await updateMessages({ rid: args.rid, update: messages, loaderItem: args.loaderItem });
|
||||||
return resolve(messages);
|
return resolve(messages);
|
||||||
} else {
|
|
||||||
return resolve([]);
|
|
||||||
}
|
}
|
||||||
|
return resolve([]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
reject(e);
|
reject(e);
|
|
@ -1,18 +1,22 @@
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
import { settings as RocketChatSettings } from '@rocket.chat/sdk';
|
import { settings as RocketChatSettings } from '@rocket.chat/sdk';
|
||||||
|
import { FetchBlobResponse, StatefulPromise } from 'rn-fetch-blob';
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
import FileUpload from '../../utils/fileUpload';
|
import FileUpload from '../../utils/fileUpload';
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
|
import { IUpload, IUser, TUploadModel } from '../../definitions';
|
||||||
|
import { IFileUpload } from '../../utils/fileUpload/interfaces';
|
||||||
|
|
||||||
const uploadQueue = {};
|
const uploadQueue: { [index: string]: StatefulPromise<FetchBlobResponse> } = {};
|
||||||
|
|
||||||
export function isUploadActive(path) {
|
export function isUploadActive(path: string): boolean {
|
||||||
return !!uploadQueue[path];
|
return !!uploadQueue[path];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cancelUpload(item) {
|
export async function cancelUpload(item: TUploadModel): Promise<void> {
|
||||||
if (uploadQueue[item.path]) {
|
if (!isEmpty(uploadQueue[item.path])) {
|
||||||
try {
|
try {
|
||||||
await uploadQueue[item.path].cancel();
|
await uploadQueue[item.path].cancel();
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -20,7 +24,7 @@ export async function cancelUpload(item) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await item.destroyPermanently();
|
await item.destroyPermanently();
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -30,7 +34,13 @@ export async function cancelUpload(item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
export function sendFileMessage(
|
||||||
|
rid: string,
|
||||||
|
fileInfo: IUpload,
|
||||||
|
tmid: string,
|
||||||
|
server: string,
|
||||||
|
user: IUser
|
||||||
|
): Promise<FetchBlobResponse | void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const { id, token } = user;
|
const { id, token } = user;
|
||||||
|
@ -41,16 +51,18 @@ export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
|
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const uploadsCollection = db.get('uploads');
|
const uploadsCollection = db.get('uploads');
|
||||||
let uploadRecord;
|
let uploadRecord: TUploadModel;
|
||||||
try {
|
try {
|
||||||
uploadRecord = await uploadsCollection.find(fileInfo.path);
|
uploadRecord = await uploadsCollection.find(fileInfo.path);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
uploadRecord = await uploadsCollection.create(u => {
|
uploadRecord = await uploadsCollection.create(u => {
|
||||||
u._raw = sanitizedRaw({ id: fileInfo.path }, uploadsCollection.schema);
|
u._raw = sanitizedRaw({ id: fileInfo.path }, uploadsCollection.schema);
|
||||||
Object.assign(u, fileInfo);
|
Object.assign(u, fileInfo);
|
||||||
u.subscription.id = rid;
|
if (u.subscription) {
|
||||||
|
u.subscription.id = rid;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -58,7 +70,7 @@ export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = [];
|
const formData: IFileUpload[] = [];
|
||||||
formData.push({
|
formData.push({
|
||||||
name: 'file',
|
name: 'file',
|
||||||
type: fileInfo.type,
|
type: fileInfo.type,
|
||||||
|
@ -89,9 +101,9 @@ export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
|
|
||||||
uploadQueue[fileInfo.path] = FileUpload.fetch('POST', uploadUrl, headers, formData);
|
uploadQueue[fileInfo.path] = FileUpload.fetch('POST', uploadUrl, headers, formData);
|
||||||
|
|
||||||
uploadQueue[fileInfo.path].uploadProgress(async (loaded, total) => {
|
uploadQueue[fileInfo.path].uploadProgress(async (loaded: number, total: number) => {
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await uploadRecord.update(u => {
|
await uploadRecord.update(u => {
|
||||||
u.progress = Math.floor((loaded / total) * 100);
|
u.progress = Math.floor((loaded / total) * 100);
|
||||||
});
|
});
|
||||||
|
@ -105,7 +117,7 @@ export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
if (response.respInfo.status >= 200 && response.respInfo.status < 400) {
|
if (response.respInfo.status >= 200 && response.respInfo.status < 400) {
|
||||||
// If response is all good...
|
// If response is all good...
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await uploadRecord.destroyPermanently();
|
await uploadRecord.destroyPermanently();
|
||||||
});
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
|
@ -114,7 +126,7 @@ export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await uploadRecord.update(u => {
|
await uploadRecord.update(u => {
|
||||||
u.error = true;
|
u.error = true;
|
||||||
});
|
});
|
||||||
|
@ -132,7 +144,7 @@ export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
|
|
||||||
uploadQueue[fileInfo.path].catch(async error => {
|
uploadQueue[fileInfo.path].catch(async error => {
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await uploadRecord.update(u => {
|
await uploadRecord.update(u => {
|
||||||
u.error = true;
|
u.error = true;
|
||||||
});
|
});
|
|
@ -1,4 +1,5 @@
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
|
import { Model } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
import messagesStatus from '../../constants/messagesStatus';
|
import messagesStatus from '../../constants/messagesStatus';
|
||||||
import database from '../database';
|
import database from '../database';
|
||||||
|
@ -6,12 +7,14 @@ import log from '../../utils/log';
|
||||||
import random from '../../utils/random';
|
import random from '../../utils/random';
|
||||||
import { Encryption } from '../encryption';
|
import { Encryption } from '../encryption';
|
||||||
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../encryption/constants';
|
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../encryption/constants';
|
||||||
|
import { IMessage, IUser, TMessageModel } from '../../definitions';
|
||||||
|
import sdk from '../rocketchat/services/sdk';
|
||||||
|
|
||||||
const changeMessageStatus = async (id, tmid, status, message) => {
|
const changeMessageStatus = async (id: string, status: number, tmid?: string, message?: IMessage) => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const msgCollection = db.get('messages');
|
const msgCollection = db.get('messages');
|
||||||
const threadMessagesCollection = db.get('thread_messages');
|
const threadMessagesCollection = db.get('thread_messages');
|
||||||
const successBatch = [];
|
const successBatch: Model[] = [];
|
||||||
const messageRecord = await msgCollection.find(id);
|
const messageRecord = await msgCollection.find(id);
|
||||||
successBatch.push(
|
successBatch.push(
|
||||||
messageRecord.prepareUpdate(m => {
|
messageRecord.prepareUpdate(m => {
|
||||||
|
@ -37,7 +40,7 @@ const changeMessageStatus = async (id, tmid, status, message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await db.batch(...successBatch);
|
await db.batch(...successBatch);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -45,48 +48,44 @@ const changeMessageStatus = async (id, tmid, status, message) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function sendMessageCall(message) {
|
export async function sendMessageCall(message: any) {
|
||||||
const { _id, tmid } = message;
|
const { _id, tmid } = message;
|
||||||
try {
|
try {
|
||||||
const sdk = this.shareSDK || this.sdk;
|
|
||||||
// RC 0.60.0
|
// RC 0.60.0
|
||||||
|
// @ts-ignore
|
||||||
const result = await sdk.post('chat.sendMessage', { message });
|
const result = await sdk.post('chat.sendMessage', { message });
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
return changeMessageStatus(_id, tmid, messagesStatus.SENT, result.message);
|
// @ts-ignore
|
||||||
|
return changeMessageStatus(_id, messagesStatus.SENT, tmid, result.message);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
return changeMessageStatus(_id, tmid, messagesStatus.ERROR);
|
return changeMessageStatus(_id, messagesStatus.ERROR, tmid);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function resendMessage(message, tmid) {
|
export async function resendMessage(message: TMessageModel, tmid?: string) {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await message.update(m => {
|
await message.update(m => {
|
||||||
m.status = messagesStatus.TEMP;
|
m.status = messagesStatus.TEMP;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
let m = {
|
const m = await Encryption.encryptMessage({
|
||||||
_id: message.id,
|
_id: message.id,
|
||||||
rid: message.subscription.id,
|
rid: message.subscription ? message.subscription.id : '',
|
||||||
msg: message.msg
|
msg: message.msg,
|
||||||
};
|
...(tmid && { tmid })
|
||||||
if (tmid) {
|
} as IMessage);
|
||||||
m = {
|
|
||||||
...m,
|
await sendMessageCall(m);
|
||||||
tmid
|
|
||||||
};
|
|
||||||
}
|
|
||||||
m = await Encryption.encryptMessage(m);
|
|
||||||
await sendMessageCall.call(this, m);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function (rid, msg, tmid, user, tshow) {
|
export default async function (rid: string, msg: string, tmid: string, user: IUser, tshow?: boolean) {
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const subsCollection = db.get('subscriptions');
|
const subsCollection = db.get('subscriptions');
|
||||||
|
@ -94,19 +93,18 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
const threadCollection = db.get('threads');
|
const threadCollection = db.get('threads');
|
||||||
const threadMessagesCollection = db.get('thread_messages');
|
const threadMessagesCollection = db.get('thread_messages');
|
||||||
const messageId = random(17);
|
const messageId = random(17);
|
||||||
const batch = [];
|
const batch: Model[] = [];
|
||||||
|
|
||||||
let message = {
|
const message = await Encryption.encryptMessage({
|
||||||
_id: messageId,
|
_id: messageId,
|
||||||
rid,
|
rid,
|
||||||
msg,
|
msg,
|
||||||
tmid,
|
tmid,
|
||||||
tshow
|
tshow
|
||||||
};
|
} as IMessage);
|
||||||
message = await Encryption.encryptMessage(message);
|
|
||||||
|
|
||||||
const messageDate = new Date();
|
const messageDate = new Date();
|
||||||
let tMessageRecord;
|
let tMessageRecord: TMessageModel;
|
||||||
|
|
||||||
// If it's replying to a thread
|
// If it's replying to a thread
|
||||||
if (tmid) {
|
if (tmid) {
|
||||||
|
@ -116,7 +114,9 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
batch.push(
|
batch.push(
|
||||||
tMessageRecord.prepareUpdate(m => {
|
tMessageRecord.prepareUpdate(m => {
|
||||||
m.tlm = messageDate;
|
m.tlm = messageDate;
|
||||||
m.tcount += 1;
|
if (m.tcount) {
|
||||||
|
m.tcount += 1;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -128,7 +128,9 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
batch.push(
|
batch.push(
|
||||||
threadCollection.prepareCreate(tm => {
|
threadCollection.prepareCreate(tm => {
|
||||||
tm._raw = sanitizedRaw({ id: tmid }, threadCollection.schema);
|
tm._raw = sanitizedRaw({ id: tmid }, threadCollection.schema);
|
||||||
tm.subscription.id = rid;
|
if (tm.subscription) {
|
||||||
|
tm.subscription.id = rid;
|
||||||
|
}
|
||||||
tm.tmid = tmid;
|
tm.tmid = tmid;
|
||||||
tm.msg = tMessageRecord.msg;
|
tm.msg = tMessageRecord.msg;
|
||||||
tm.ts = tMessageRecord.ts;
|
tm.ts = tMessageRecord.ts;
|
||||||
|
@ -147,7 +149,9 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
batch.push(
|
batch.push(
|
||||||
threadMessagesCollection.prepareCreate(tm => {
|
threadMessagesCollection.prepareCreate(tm => {
|
||||||
tm._raw = sanitizedRaw({ id: messageId }, threadMessagesCollection.schema);
|
tm._raw = sanitizedRaw({ id: messageId }, threadMessagesCollection.schema);
|
||||||
tm.subscription.id = rid;
|
if (tm.subscription) {
|
||||||
|
tm.subscription.id = rid;
|
||||||
|
}
|
||||||
tm.rid = tmid;
|
tm.rid = tmid;
|
||||||
tm.msg = msg;
|
tm.msg = msg;
|
||||||
tm.ts = messageDate;
|
tm.ts = messageDate;
|
||||||
|
@ -173,7 +177,9 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
batch.push(
|
batch.push(
|
||||||
msgCollection.prepareCreate(m => {
|
msgCollection.prepareCreate(m => {
|
||||||
m._raw = sanitizedRaw({ id: messageId }, msgCollection.schema);
|
m._raw = sanitizedRaw({ id: messageId }, msgCollection.schema);
|
||||||
m.subscription.id = rid;
|
if (m.subscription) {
|
||||||
|
m.subscription.id = rid;
|
||||||
|
}
|
||||||
m.msg = msg;
|
m.msg = msg;
|
||||||
m.ts = messageDate;
|
m.ts = messageDate;
|
||||||
m._updatedAt = messageDate;
|
m._updatedAt = messageDate;
|
||||||
|
@ -210,7 +216,7 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.action(async () => {
|
await db.write(async () => {
|
||||||
await db.batch(...batch);
|
await db.batch(...batch);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -218,7 +224,7 @@ export default async function (rid, msg, tmid, user, tshow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendMessageCall.call(this, message);
|
await sendMessageCall(message);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
|
@ -127,8 +127,11 @@ const createOrUpdateSubscription = async (subscription, room) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmp = merge(subscription, room);
|
let tmp;
|
||||||
tmp = await Encryption.decryptSubscription(tmp);
|
if (subscription) {
|
||||||
|
tmp = merge(subscription, room);
|
||||||
|
tmp = await Encryption.decryptSubscription(tmp);
|
||||||
|
}
|
||||||
let sub;
|
let sub;
|
||||||
try {
|
try {
|
||||||
sub = await subCollection.find(tmp.rid);
|
sub = await subCollection.find(tmp.rid);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { getSubscriptionByRoomId } from '../database/services/Subscription';
|
||||||
interface IUpdateMessages {
|
interface IUpdateMessages {
|
||||||
rid: string;
|
rid: string;
|
||||||
update: IMessage[];
|
update: IMessage[];
|
||||||
remove: IMessage[];
|
remove?: IMessage[];
|
||||||
loaderItem?: TMessageModel;
|
loaderItem?: TMessageModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ export default async function updateMessages({
|
||||||
threadCollection.prepareCreate(
|
threadCollection.prepareCreate(
|
||||||
protectedFunction((t: TThreadModel) => {
|
protectedFunction((t: TThreadModel) => {
|
||||||
t._raw = sanitizedRaw({ id: thread._id }, threadCollection.schema);
|
t._raw = sanitizedRaw({ id: thread._id }, threadCollection.schema);
|
||||||
t.subscription.id = sub.id;
|
if (t.subscription) t.subscription.id = sub.id;
|
||||||
Object.assign(t, thread);
|
Object.assign(t, thread);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import RNFetchBlob from 'rn-fetch-blob';
|
||||||
|
|
||||||
|
export const getServerTimeSync = async (server: string) => {
|
||||||
|
try {
|
||||||
|
const response = await Promise.race([
|
||||||
|
RNFetchBlob.fetch('GET', `${server}/_timesync`),
|
||||||
|
new Promise<undefined>(res => setTimeout(res, 2000))
|
||||||
|
]);
|
||||||
|
if (response?.data) {
|
||||||
|
return parseInt(response.data);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
|
@ -34,10 +34,8 @@ export const createChannel = ({
|
||||||
return sdk.post(type ? 'groups.create' : 'channels.create', params);
|
return sdk.post(type ? 'groups.create' : 'channels.create', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const e2eSetUserPublicAndPrivateKeys = (public_key: string, private_key: string): any =>
|
export const e2eSetUserPublicAndPrivateKeys = (public_key: string, private_key: string) =>
|
||||||
// RC 2.2.0
|
// RC 2.2.0
|
||||||
// TODO: missing definitions from server
|
|
||||||
// @ts-ignore
|
|
||||||
sdk.post('e2e.setUserPublicAndPrivateKeys', { public_key, private_key });
|
sdk.post('e2e.setUserPublicAndPrivateKeys', { public_key, private_key });
|
||||||
|
|
||||||
export const e2eRequestSubscriptionKeys = (): any =>
|
export const e2eRequestSubscriptionKeys = (): any =>
|
||||||
|
@ -221,12 +219,6 @@ export const teamListRoomsOfUser = ({ teamId, userId }: { teamId: string; userId
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
sdk.get('teams.listRoomsOfUser', { teamId, userId });
|
sdk.get('teams.listRoomsOfUser', { teamId, userId });
|
||||||
|
|
||||||
export const getTeamInfo = ({ teamId }: { teamId: string }): any =>
|
|
||||||
// RC 3.13.0
|
|
||||||
// TODO: missing definitions from server
|
|
||||||
// @ts-ignore
|
|
||||||
sdk.get('teams.info', { teamId });
|
|
||||||
|
|
||||||
export const convertChannelToTeam = ({ rid, name, type }: { rid: string; name: string; type: 'c' | 'p' }): any => {
|
export const convertChannelToTeam = ({ rid, name, type }: { rid: string; name: string; type: 'c' | 'p' }): any => {
|
||||||
const params = {
|
const params = {
|
||||||
...(type === 'c'
|
...(type === 'c'
|
||||||
|
|
|
@ -18,7 +18,7 @@ const methods = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const compareServerVersion = (
|
export const compareServerVersion = (
|
||||||
currentServerVersion: string,
|
currentServerVersion: string | null,
|
||||||
method: keyof typeof methods,
|
method: keyof typeof methods,
|
||||||
versionToCompare: string
|
versionToCompare: string
|
||||||
): boolean =>
|
): boolean =>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { clearActiveUsers, setActiveUsers } from '../actions/activeUsers';
|
import { clearActiveUsers, setActiveUsers } from '../actions/activeUsers';
|
||||||
|
import { UserStatus } from '../definitions/UserStatus';
|
||||||
import { IActiveUsers, initialState } from './activeUsers';
|
import { IActiveUsers, initialState } from './activeUsers';
|
||||||
import { mockedStore } from './mockedStore';
|
import { mockedStore } from './mockedStore';
|
||||||
|
|
||||||
|
@ -8,7 +9,7 @@ describe('test reducer', () => {
|
||||||
expect(state).toEqual(initialState);
|
expect(state).toEqual(initialState);
|
||||||
});
|
});
|
||||||
it('should return modified store after action', () => {
|
it('should return modified store after action', () => {
|
||||||
const activeUsers: IActiveUsers = { any: { status: 'online', statusText: 'any' } };
|
const activeUsers: IActiveUsers = { any: { status: UserStatus.ONLINE, statusText: 'any' } };
|
||||||
mockedStore.dispatch(setActiveUsers(activeUsers));
|
mockedStore.dispatch(setActiveUsers(activeUsers));
|
||||||
const state = mockedStore.getState().activeUsers;
|
const state = mockedStore.getState().activeUsers;
|
||||||
expect(state).toEqual({ ...activeUsers });
|
expect(state).toEqual({ ...activeUsers });
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { TApplicationActions } from '../definitions';
|
|
||||||
import { ACTIVE_USERS } from '../actions/actionsTypes';
|
import { ACTIVE_USERS } from '../actions/actionsTypes';
|
||||||
|
import { TApplicationActions } from '../definitions';
|
||||||
|
import { UserStatus } from '../definitions/UserStatus';
|
||||||
|
|
||||||
type TUserStatus = 'online' | 'offline' | 'away' | 'busy';
|
|
||||||
export interface IActiveUser {
|
export interface IActiveUser {
|
||||||
status: TUserStatus;
|
status: UserStatus;
|
||||||
statusText: string;
|
statusText: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { TActionEnterpriseModules } from '../actions/enterpriseModules';
|
import { TActionEnterpriseModules } from '../actions/enterpriseModules';
|
||||||
import { ENTERPRISE_MODULES } from '../actions/actionsTypes';
|
import { ENTERPRISE_MODULES } from '../actions/actionsTypes';
|
||||||
|
|
||||||
export type IEnterpriseModules = 'omnichannel-mobile-enterprise' | 'livechat-enterprise';
|
export type IEnterpriseModules = string;
|
||||||
|
|
||||||
export const initialState: IEnterpriseModules[] = [];
|
export const initialState: IEnterpriseModules[] = [];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
import {
|
||||||
|
loginFailure,
|
||||||
|
loginRequest,
|
||||||
|
loginSuccess,
|
||||||
|
logout,
|
||||||
|
setLocalAuthenticated,
|
||||||
|
setLoginServices,
|
||||||
|
setUser
|
||||||
|
} from '../actions/login';
|
||||||
|
import { UserStatus } from '../definitions/UserStatus';
|
||||||
|
import { initialState } from './login';
|
||||||
|
import { mockedStore } from './mockedStore';
|
||||||
|
|
||||||
|
describe('test selectedUsers reducer', () => {
|
||||||
|
it('should return initial state', () => {
|
||||||
|
const state = mockedStore.getState().login;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after loginRequest', () => {
|
||||||
|
mockedStore.dispatch(loginRequest({ user: 'carlitos@email.com', password: '123456' }));
|
||||||
|
const state = mockedStore.getState().login;
|
||||||
|
expect(state).toEqual({ ...initialState, isFetching: true, isAuthenticated: false, failure: false, error: {} });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after loginFailure', () => {
|
||||||
|
mockedStore.dispatch(loginFailure({ error: 'error' }));
|
||||||
|
const state = mockedStore.getState().login.error.error;
|
||||||
|
expect(state).toEqual('error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after loginSuccess', () => {
|
||||||
|
const user = {
|
||||||
|
id: 'ajhsiahsa',
|
||||||
|
token: 'asdasdasdas',
|
||||||
|
username: 'carlitos',
|
||||||
|
name: 'Carlitos',
|
||||||
|
customFields: {
|
||||||
|
phonenumber: ''
|
||||||
|
},
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'carlitos@email.com',
|
||||||
|
verified: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: ['user'],
|
||||||
|
isFromWebView: false,
|
||||||
|
showMessageInMainThread: false,
|
||||||
|
enableMessageParserEarlyAdoption: false,
|
||||||
|
status: UserStatus.ONLINE,
|
||||||
|
statusText: 'online'
|
||||||
|
};
|
||||||
|
mockedStore.dispatch(loginSuccess(user));
|
||||||
|
const state = mockedStore.getState().login.user;
|
||||||
|
expect(state).toEqual(user);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after setUser', () => {
|
||||||
|
const user = {
|
||||||
|
id: 'ajhsiahsa',
|
||||||
|
token: 'asdasdasdas',
|
||||||
|
username: 'carlito',
|
||||||
|
name: 'Carlitos',
|
||||||
|
customFields: {
|
||||||
|
phonenumber: ''
|
||||||
|
},
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'carlitos@email.com',
|
||||||
|
verified: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: ['user'],
|
||||||
|
isFromWebView: false,
|
||||||
|
showMessageInMainThread: false,
|
||||||
|
enableMessageParserEarlyAdoption: false
|
||||||
|
};
|
||||||
|
mockedStore.dispatch(setUser(user));
|
||||||
|
const state = mockedStore.getState().login.user.username;
|
||||||
|
expect(state).toEqual(user.username);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO PREFERENCE REDUCER WITH EMPTY PREFERENCE - NON USED?
|
||||||
|
// it('should return modified store after setPreference', () => {
|
||||||
|
// mockedStore.dispatch(setPreference({ showAvatar: true }));
|
||||||
|
// const state = mockedStore.getState().login;
|
||||||
|
// console.log(state);
|
||||||
|
// expect(state).toEqual('error');
|
||||||
|
// });
|
||||||
|
|
||||||
|
it('should return modified store after setLocalAuthenticated', () => {
|
||||||
|
mockedStore.dispatch(setLocalAuthenticated(true));
|
||||||
|
const state = mockedStore.getState().login.isLocalAuthenticated;
|
||||||
|
expect(state).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after setLoginServices', () => {
|
||||||
|
mockedStore.dispatch(setLoginServices({ facebook: { clientId: 'xxx' } }));
|
||||||
|
const state = mockedStore.getState().login.services.facebook.clientId;
|
||||||
|
expect(state).toEqual('xxx');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after logout', () => {
|
||||||
|
mockedStore.dispatch(logout());
|
||||||
|
const state = mockedStore.getState().login;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,15 +1,47 @@
|
||||||
|
import { UserStatus } from '../definitions/UserStatus';
|
||||||
import * as types from '../actions/actionsTypes';
|
import * as types from '../actions/actionsTypes';
|
||||||
|
import { TActionsLogin } from '../actions/login';
|
||||||
|
import { IUser } from '../definitions';
|
||||||
|
|
||||||
const initialState = {
|
export interface IUserLogin {
|
||||||
|
id: string;
|
||||||
|
token: string;
|
||||||
|
username: string;
|
||||||
|
name: string;
|
||||||
|
language?: string;
|
||||||
|
status: UserStatus;
|
||||||
|
statusText: string;
|
||||||
|
roles: string[];
|
||||||
|
avatarETag?: string;
|
||||||
|
isFromWebView: boolean;
|
||||||
|
showMessageInMainThread: boolean;
|
||||||
|
enableMessageParserEarlyAdoption: boolean;
|
||||||
|
emails: Record<string, any>[];
|
||||||
|
customFields: Record<string, string>;
|
||||||
|
settings?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILogin {
|
||||||
|
user: Partial<IUser>;
|
||||||
|
isLocalAuthenticated: boolean;
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
isFetching: boolean;
|
||||||
|
error: Record<string, any>;
|
||||||
|
services: Record<string, any>;
|
||||||
|
failure: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: ILogin = {
|
||||||
isLocalAuthenticated: true,
|
isLocalAuthenticated: true,
|
||||||
isAuthenticated: false,
|
isAuthenticated: false,
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
user: {},
|
user: {},
|
||||||
error: {},
|
error: {},
|
||||||
services: {}
|
services: {},
|
||||||
|
failure: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function login(state = initialState, action) {
|
export default function login(state = initialState, action: TActionsLogin): ILogin {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case types.APP.INIT:
|
case types.APP.INIT:
|
||||||
return initialState;
|
return initialState;
|
||||||
|
@ -60,13 +92,14 @@ export default function login(state = initialState, action) {
|
||||||
...state,
|
...state,
|
||||||
user: {
|
user: {
|
||||||
...state.user,
|
...state.user,
|
||||||
settings: {
|
settings: state.user?.settings
|
||||||
...state.user.settings,
|
? {
|
||||||
preferences: {
|
...state.user?.settings,
|
||||||
...state.user.settings.preferences,
|
preferences: state.user?.settings?.preferences
|
||||||
...action.preference
|
? { ...state.user.settings.preferences, ...action.preference }
|
||||||
}
|
: { ...action.preference }
|
||||||
}
|
}
|
||||||
|
: { profile: {}, preferences: {} }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
case types.LOGIN.SET_LOCAL_AUTHENTICATED:
|
case types.LOGIN.SET_LOCAL_AUTHENTICATED:
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { closeRoom, deleteRoom, forwardRoom, leaveRoom, removedRoom, subscribeRoom, unsubscribeRoom } from '../actions/room';
|
||||||
|
import { ERoomType } from '../definitions/ERoomType';
|
||||||
|
import { mockedStore } from './mockedStore';
|
||||||
|
import { initialState } from './room';
|
||||||
|
|
||||||
|
describe('test room reducer', () => {
|
||||||
|
it('should return initial state', () => {
|
||||||
|
const state = mockedStore.getState().room;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after subscribeRoom', () => {
|
||||||
|
mockedStore.dispatch(subscribeRoom('GENERAL'));
|
||||||
|
const state = mockedStore.getState().room;
|
||||||
|
expect(state.rooms).toEqual(['GENERAL']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty store after remove unsubscribeRoom', () => {
|
||||||
|
mockedStore.dispatch(unsubscribeRoom('GENERAL'));
|
||||||
|
const state = mockedStore.getState().room;
|
||||||
|
expect(state.rooms).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return initial state after leaveRoom', () => {
|
||||||
|
mockedStore.dispatch(leaveRoom(ERoomType.c, { rid: ERoomType.c }));
|
||||||
|
const { rid, isDeleting } = mockedStore.getState().room;
|
||||||
|
expect(rid).toEqual(ERoomType.c);
|
||||||
|
expect(isDeleting).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return initial state after deleteRoom', () => {
|
||||||
|
mockedStore.dispatch(deleteRoom(ERoomType.l, { rid: ERoomType.l }));
|
||||||
|
const { rid, isDeleting } = mockedStore.getState().room;
|
||||||
|
expect(rid).toEqual(ERoomType.l);
|
||||||
|
expect(isDeleting).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return initial state after closeRoom', () => {
|
||||||
|
mockedStore.dispatch(closeRoom('CLOSING'));
|
||||||
|
const { rid, isDeleting } = mockedStore.getState().room;
|
||||||
|
expect(rid).toEqual('CLOSING');
|
||||||
|
expect(isDeleting).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return initial state after forwardRoom', () => {
|
||||||
|
const transferData = { roomId: 'FORWARDING' };
|
||||||
|
mockedStore.dispatch(forwardRoom('FORWARDING', transferData));
|
||||||
|
const { rid, isDeleting } = mockedStore.getState().room;
|
||||||
|
expect(rid).toEqual('FORWARDING');
|
||||||
|
expect(isDeleting).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return loading after call removedRoom', () => {
|
||||||
|
mockedStore.dispatch(removedRoom());
|
||||||
|
const { isDeleting } = mockedStore.getState().room;
|
||||||
|
expect(isDeleting).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,12 +1,21 @@
|
||||||
|
import { TActionsRoom } from '../actions/room';
|
||||||
import { ROOM } from '../actions/actionsTypes';
|
import { ROOM } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
export type IRoomRecord = string[];
|
||||||
rid: null,
|
|
||||||
|
export interface IRoom {
|
||||||
|
rid: string;
|
||||||
|
isDeleting: boolean;
|
||||||
|
rooms: IRoomRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: IRoom = {
|
||||||
|
rid: '',
|
||||||
isDeleting: false,
|
isDeleting: false,
|
||||||
rooms: []
|
rooms: []
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function (state = initialState, action) {
|
export default function (state = initialState, action: TActionsRoom): IRoom {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ROOM.SUBSCRIBE:
|
case ROOM.SUBSCRIBE:
|
||||||
return {
|
return {
|
|
@ -57,8 +57,7 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
||||||
const { subscriptions } = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
const subscriptions = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
||||||
|
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
const messagesCollection = db.get('messages');
|
const messagesCollection = db.get('messages');
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
import { IApplicationState } from '../definitions';
|
import { IApplicationState, IUser } from '../definitions';
|
||||||
|
|
||||||
interface IServices {
|
interface IServices {
|
||||||
facebook: { clientId: string };
|
facebook: { clientId: string };
|
||||||
|
@ -13,7 +13,7 @@ interface IServices {
|
||||||
wordpress: { clientId: string; serverURL: string };
|
wordpress: { clientId: string; serverURL: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
const getUser = (state: IApplicationState) => {
|
const getUser = (state: IApplicationState): Partial<IUser> => {
|
||||||
if (!isEmpty(state.share?.user)) {
|
if (!isEmpty(state.share?.user)) {
|
||||||
return state.share.user;
|
return state.share.user;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ const getLoginServices = (state: IApplicationState) => (state.login.services as
|
||||||
const getShowFormLoginSetting = (state: IApplicationState) => (state.settings.Accounts_ShowFormLogin as boolean) || false;
|
const getShowFormLoginSetting = (state: IApplicationState) => (state.settings.Accounts_ShowFormLogin as boolean) || false;
|
||||||
const getIframeEnabledSetting = (state: IApplicationState) => (state.settings.Accounts_iframe_enabled as boolean) || false;
|
const getIframeEnabledSetting = (state: IApplicationState) => (state.settings.Accounts_iframe_enabled as boolean) || false;
|
||||||
|
|
||||||
export const getUserSelector = createSelector([getUser], user => user);
|
// TODO: we need to change 42 files to fix a correct type, i believe is better to do this later
|
||||||
|
export const getUserSelector = createSelector([getUser], user => user) as any;
|
||||||
|
|
||||||
export const getShowLoginButton = createSelector(
|
export const getShowLoginButton = createSelector(
|
||||||
[getLoginServices, getShowFormLoginSetting, getIframeEnabledSetting],
|
[getLoginServices, getShowFormLoginSetting, getIframeEnabledSetting],
|
||||||
|
|
|
@ -43,6 +43,7 @@ class FileUpload {
|
||||||
upload.formData.append(item.name, {
|
upload.formData.append(item.name, {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
uri: item.uri,
|
uri: item.uri,
|
||||||
|
// @ts-ignore
|
||||||
type: item.type,
|
type: item.type,
|
||||||
name: item.filename
|
name: item.filename
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export interface IFileUpload {
|
export interface IFileUpload {
|
||||||
name: string;
|
name: string;
|
||||||
uri?: string;
|
uri?: string;
|
||||||
type: string;
|
type?: string;
|
||||||
filename: string;
|
filename?: string;
|
||||||
data: any;
|
data?: any;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import * as LocalAuthentication from 'expo-local-authentication';
|
import * as LocalAuthentication from 'expo-local-authentication';
|
||||||
import moment from 'moment';
|
|
||||||
import RNBootSplash from 'react-native-bootsplash';
|
import RNBootSplash from 'react-native-bootsplash';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import { sha256 } from 'js-sha256';
|
import { sha256 } from 'js-sha256';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
import UserPreferences from '../lib/userPreferences';
|
import UserPreferences from '../lib/userPreferences';
|
||||||
import { store } from '../lib/auxStore';
|
import { store } from '../lib/auxStore';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
|
import { getServerTimeSync } from '../lib/rocketchat/services/getServerTimeSync';
|
||||||
import {
|
import {
|
||||||
ATTEMPTS_KEY,
|
ATTEMPTS_KEY,
|
||||||
BIOMETRY_ENABLED_KEY,
|
BIOMETRY_ENABLED_KEY,
|
||||||
|
@ -21,16 +22,25 @@ import { TServerModel } from '../definitions/IServer';
|
||||||
import EventEmitter from './events';
|
import EventEmitter from './events';
|
||||||
import { isIOS } from './deviceInfo';
|
import { isIOS } from './deviceInfo';
|
||||||
|
|
||||||
export const saveLastLocalAuthenticationSession = async (server: string, serverRecord?: TServerModel): Promise<void> => {
|
export const saveLastLocalAuthenticationSession = async (
|
||||||
|
server: string,
|
||||||
|
serverRecord?: TServerModel,
|
||||||
|
timesync?: number | null
|
||||||
|
): Promise<void> => {
|
||||||
|
if (!timesync) {
|
||||||
|
timesync = new Date().getTime();
|
||||||
|
}
|
||||||
|
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serversCollection = serversDB.get('servers');
|
const serversCollection = serversDB.get('servers');
|
||||||
await serversDB.write(async () => {
|
await serversDB.write(async () => {
|
||||||
try {
|
try {
|
||||||
if (!serverRecord) {
|
if (!serverRecord) {
|
||||||
serverRecord = (await serversCollection.find(server)) as TServerModel;
|
serverRecord = await serversCollection.find(server);
|
||||||
}
|
}
|
||||||
|
const time = timesync || 0;
|
||||||
await serverRecord.update(record => {
|
await serverRecord.update(record => {
|
||||||
record.lastLocalAuthenticatedSession = new Date();
|
record.lastLocalAuthenticatedSession = new Date(time);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
@ -103,6 +113,9 @@ export const localAuthenticate = async (server: string): Promise<void> => {
|
||||||
|
|
||||||
// if screen lock is enabled
|
// if screen lock is enabled
|
||||||
if (serverRecord?.autoLock) {
|
if (serverRecord?.autoLock) {
|
||||||
|
// Get time from server
|
||||||
|
const timesync = await getServerTimeSync(server);
|
||||||
|
|
||||||
// Make sure splash screen has been hidden
|
// Make sure splash screen has been hidden
|
||||||
try {
|
try {
|
||||||
await RNBootSplash.hide();
|
await RNBootSplash.hide();
|
||||||
|
@ -116,10 +129,10 @@ export const localAuthenticate = async (server: string): Promise<void> => {
|
||||||
// `checkHasPasscode` results newPasscode = true if a passcode has been set
|
// `checkHasPasscode` results newPasscode = true if a passcode has been set
|
||||||
if (!result?.newPasscode) {
|
if (!result?.newPasscode) {
|
||||||
// diff to last authenticated session
|
// diff to last authenticated session
|
||||||
const diffToLastSession = moment().diff(serverRecord?.lastLocalAuthenticatedSession, 'seconds');
|
const diffToLastSession = moment(timesync).diff(serverRecord?.lastLocalAuthenticatedSession, 'seconds');
|
||||||
|
|
||||||
// if last authenticated session is older than configured auto lock time, authentication is required
|
// if it was not possible to get `timesync` from server or the last authenticated session is older than the configured auto lock time, authentication is required
|
||||||
if (diffToLastSession >= serverRecord.autoLockTime!) {
|
if (!timesync || (serverRecord?.autoLockTime && diffToLastSession >= serverRecord.autoLockTime)) {
|
||||||
// set isLocalAuthenticated to false
|
// set isLocalAuthenticated to false
|
||||||
store.dispatch(setLocalAuthenticated(false));
|
store.dispatch(setLocalAuthenticated(false));
|
||||||
|
|
||||||
|
@ -141,7 +154,7 @@ export const localAuthenticate = async (server: string): Promise<void> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
await resetAttempts();
|
await resetAttempts();
|
||||||
await saveLastLocalAuthenticationSession(server, serverRecord);
|
await saveLastLocalAuthenticationSession(server, serverRecord, timesync);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -58,5 +58,33 @@ export const MessageTypeValues = [
|
||||||
{
|
{
|
||||||
value: 'room_unarchived',
|
value: 'room_unarchived',
|
||||||
text: 'Message_HideType_room_unarchived'
|
text: 'Message_HideType_room_unarchived'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'removed-user-from-team',
|
||||||
|
text: 'Message_HideType_removed_user_from_team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'added-user-to-team',
|
||||||
|
text: 'Message_HideType_added_user_to_team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'user-added-room-to-team',
|
||||||
|
text: 'Message_HideType_user_added_room_to_team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'user-converted-to-channel',
|
||||||
|
text: 'Message_HideType_user_converted_to_channel'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'user-converted-to-team',
|
||||||
|
text: 'Message_HideType_user_converted_to_team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'user-deleted-room-from-team',
|
||||||
|
text: 'Message_HideType_user_deleted_room_from_team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'user-removed-room-from-team',
|
||||||
|
text: 'Message_HideType_user_removed_room_from_team'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const capitalize = (s: string): string => {
|
||||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const formatDate = (date: Date): string =>
|
export const formatDate = (date: string | Date): string =>
|
||||||
moment(date).calendar(null, {
|
moment(date).calendar(null, {
|
||||||
lastDay: `[${I18n.t('Yesterday')}]`,
|
lastDay: `[${I18n.t('Yesterday')}]`,
|
||||||
sameDay: 'LT',
|
sameDay: 'LT',
|
||||||
|
@ -30,7 +30,7 @@ export const formatDate = (date: Date): string =>
|
||||||
sameElse: 'L'
|
sameElse: 'L'
|
||||||
});
|
});
|
||||||
|
|
||||||
export const formatDateThreads = (date: Date): string =>
|
export const formatDateThreads = (date: string | Date): string =>
|
||||||
moment(date).calendar(null, {
|
moment(date).calendar(null, {
|
||||||
sameDay: 'LT',
|
sameDay: 'LT',
|
||||||
lastDay: `[${I18n.t('Yesterday')}] LT`,
|
lastDay: `[${I18n.t('Yesterday')}] LT`,
|
||||||
|
|
|
@ -260,7 +260,7 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
|
||||||
/>
|
/>
|
||||||
</HeaderButton.Container>
|
</HeaderButton.Container>
|
||||||
),
|
),
|
||||||
headerTitle: () => <SearchHeader onSearchChangeText={onChangeText} />,
|
headerTitle: () => <SearchHeader onSearchChangeText={onChangeText} testID='team-channels-view-search-header' />,
|
||||||
headerTitleContainerStyle: {
|
headerTitleContainerStyle: {
|
||||||
left: headerTitlePosition.left,
|
left: headerTitlePosition.left,
|
||||||
right: headerTitlePosition.right
|
right: headerTitlePosition.right
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { RouteProp } from '@react-navigation/native';
|
|
||||||
import { StyleSheet, View } from 'react-native';
|
|
||||||
import { Dispatch } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import { forwardRoom, ITransferData } from '../actions/room';
|
||||||
import { withTheme } from '../theme';
|
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import OrSeparator from '../containers/OrSeparator';
|
import OrSeparator from '../containers/OrSeparator';
|
||||||
import Input from '../containers/UIKit/MultiSelect/Input';
|
import Input from '../containers/UIKit/MultiSelect/Input';
|
||||||
import { forwardRoom as forwardRoomAction } from '../actions/room';
|
import { IBaseScreen, IRoom } from '../definitions';
|
||||||
import { IRoom } from '../definitions';
|
import I18n from '../i18n';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
import { ChatsStackParamList } from '../stacks/types';
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
import { IOptionsField } from './NotificationPreferencesView/options';
|
import { IOptionsField } from './NotificationPreferencesView/options';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -23,33 +20,26 @@ const styles = StyleSheet.create({
|
||||||
padding: 16
|
padding: 16
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ITransferData {
|
|
||||||
roomId: string;
|
|
||||||
userId?: string;
|
|
||||||
departmentId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IUser {
|
interface IUser {
|
||||||
username: string;
|
username: string;
|
||||||
_id: string;
|
_id: string;
|
||||||
}
|
}
|
||||||
interface IForwardLivechatViewProps {
|
|
||||||
navigation: StackNavigationProp<ChatsStackParamList, 'ForwardLivechatView'>;
|
interface IParsedData {
|
||||||
route: RouteProp<ChatsStackParamList, 'ForwardLivechatView'>;
|
label: string;
|
||||||
theme: string;
|
value: string;
|
||||||
forwardRoom: (rid: string, transferData: ITransferData) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const COUNT_DEPARTMENT = 50;
|
const COUNT_DEPARTMENT = 50;
|
||||||
|
|
||||||
const ForwardLivechatView = ({ forwardRoom, navigation, route, theme }: IForwardLivechatViewProps) => {
|
const ForwardLivechatView = ({ navigation, route, theme }: IBaseScreen<ChatsStackParamList, 'ForwardLivechatView'>) => {
|
||||||
const [departments, setDepartments] = useState<IOptionsField[]>([]);
|
const [departments, setDepartments] = useState<IParsedData[]>([]);
|
||||||
const [departmentId, setDepartment] = useState('');
|
const [departmentId, setDepartment] = useState('');
|
||||||
const [departmentTotal, setDepartmentTotal] = useState(0);
|
const [departmentTotal, setDepartmentTotal] = useState(0);
|
||||||
const [users, setUsers] = useState<IOptionsField[]>([]);
|
const [users, setUsers] = useState<IOptionsField[]>([]);
|
||||||
const [userId, setUser] = useState();
|
const [userId, setUser] = useState();
|
||||||
const [room, setRoom] = useState<IRoom>({} as IRoom);
|
const [room, setRoom] = useState<IRoom>({} as IRoom);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const rid = route.params?.rid;
|
const rid = route.params?.rid;
|
||||||
|
|
||||||
|
@ -57,7 +47,7 @@ const ForwardLivechatView = ({ forwardRoom, navigation, route, theme }: IForward
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.getDepartments({ count: COUNT_DEPARTMENT, text, offset });
|
const result = await RocketChat.getDepartments({ count: COUNT_DEPARTMENT, text, offset });
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const parsedDepartments: IOptionsField[] = result.departments.map(department => ({
|
const parsedDepartments: IParsedData[] = result.departments.map(department => ({
|
||||||
label: department.name,
|
label: department.name,
|
||||||
value: department._id
|
value: department._id
|
||||||
}));
|
}));
|
||||||
|
@ -116,7 +106,7 @@ const ForwardLivechatView = ({ forwardRoom, navigation, route, theme }: IForward
|
||||||
transferData.departmentId = departmentId;
|
transferData.departmentId = departmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
forwardRoom(rid, transferData);
|
dispatch(forwardRoom(rid, transferData));
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -171,8 +161,4 @@ const ForwardLivechatView = ({ forwardRoom, navigation, route, theme }: IForward
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
export default withTheme(ForwardLivechatView);
|
||||||
forwardRoom: (rid: string, transferData: ITransferData) => dispatch(forwardRoomAction(rid, transferData))
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(withTheme(ForwardLivechatView));
|
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
|
import { dequal } from 'dequal';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Alert, Keyboard, StyleSheet, Text, View } from 'react-native';
|
import { Alert, Keyboard, StyleSheet, Text, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { RouteProp } from '@react-navigation/core';
|
|
||||||
|
|
||||||
import Button from '../containers/Button';
|
import { loginRequest } from '../actions/login';
|
||||||
import I18n from '../i18n';
|
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { withTheme } from '../theme';
|
import Button from '../containers/Button';
|
||||||
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
||||||
import TextInput from '../containers/TextInput';
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
|
||||||
import LoginServices from '../containers/LoginServices';
|
import LoginServices from '../containers/LoginServices';
|
||||||
import sharedStyles from './Styles';
|
import TextInput from '../containers/TextInput';
|
||||||
|
import { IApplicationState, IBaseScreen } from '../definitions';
|
||||||
|
import I18n from '../i18n';
|
||||||
import { OutsideParamList } from '../stacks/types';
|
import { OutsideParamList } from '../stacks/types';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
|
import sharedStyles from './Styles';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
registerDisabled: {
|
registerDisabled: {
|
||||||
|
@ -48,9 +47,7 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ILoginViewProps {
|
interface ILoginViewProps extends IBaseScreen<OutsideParamList, 'LoginView'> {
|
||||||
navigation: StackNavigationProp<OutsideParamList, 'LoginView'>;
|
|
||||||
route: RouteProp<OutsideParamList, 'LoginView'>;
|
|
||||||
Site_Name: string;
|
Site_Name: string;
|
||||||
Accounts_RegistrationForm: string;
|
Accounts_RegistrationForm: string;
|
||||||
Accounts_RegistrationForm_LinkReplacementText: string;
|
Accounts_RegistrationForm_LinkReplacementText: string;
|
||||||
|
@ -63,7 +60,6 @@ interface ILoginViewProps {
|
||||||
error: string;
|
error: string;
|
||||||
};
|
};
|
||||||
failure: boolean;
|
failure: boolean;
|
||||||
theme: string;
|
|
||||||
loginRequest: Function;
|
loginRequest: Function;
|
||||||
inviteLinkToken: string;
|
inviteLinkToken: string;
|
||||||
}
|
}
|
||||||
|
@ -132,9 +128,9 @@ class LoginView extends React.Component<ILoginViewProps, any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { user, password } = this.state;
|
const { user, password } = this.state;
|
||||||
const { loginRequest } = this.props;
|
const { dispatch } = this.props;
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
loginRequest({ user, password });
|
dispatch(loginRequest({ user, password }));
|
||||||
};
|
};
|
||||||
|
|
||||||
renderUserForm = () => {
|
renderUserForm = () => {
|
||||||
|
@ -243,23 +239,19 @@ class LoginView extends React.Component<ILoginViewProps, any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
Site_Name: state.settings.Site_Name,
|
Site_Name: state.settings.Site_Name as string,
|
||||||
Accounts_ShowFormLogin: state.settings.Accounts_ShowFormLogin,
|
Accounts_ShowFormLogin: state.settings.Accounts_ShowFormLogin as boolean,
|
||||||
Accounts_RegistrationForm: state.settings.Accounts_RegistrationForm,
|
Accounts_RegistrationForm: state.settings.Accounts_RegistrationForm as string,
|
||||||
Accounts_RegistrationForm_LinkReplacementText: state.settings.Accounts_RegistrationForm_LinkReplacementText,
|
Accounts_RegistrationForm_LinkReplacementText: state.settings.Accounts_RegistrationForm_LinkReplacementText as string,
|
||||||
isFetching: state.login.isFetching,
|
isFetching: state.login.isFetching,
|
||||||
failure: state.login.failure,
|
failure: state.login.failure,
|
||||||
error: state.login.error && state.login.error.data,
|
error: state.login.error && state.login.error.data,
|
||||||
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
|
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder as string,
|
||||||
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder,
|
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder as string,
|
||||||
Accounts_PasswordReset: state.settings.Accounts_PasswordReset,
|
Accounts_PasswordReset: state.settings.Accounts_PasswordReset as boolean,
|
||||||
inviteLinkToken: state.inviteLinks.token
|
inviteLinkToken: state.inviteLinks.token
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any) => ({
|
export default connect(mapStateToProps)(withTheme(LoginView));
|
||||||
loginRequest: (params: any) => dispatch(loginRequestAction(params))
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(LoginView));
|
|
||||||
|
|
|
@ -71,6 +71,8 @@ interface IMessageItem {
|
||||||
msg?: string;
|
msg?: string;
|
||||||
starred: boolean;
|
starred: boolean;
|
||||||
pinned: boolean;
|
pinned: boolean;
|
||||||
|
type: string;
|
||||||
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
|
|
|
@ -1,26 +1,25 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Keyboard, StyleSheet, Text, View } from 'react-native';
|
import { Keyboard, StyleSheet, Text, View } from 'react-native';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { RouteProp } from '@react-navigation/core';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import RNPickerSelect from 'react-native-picker-select';
|
import RNPickerSelect from 'react-native-picker-select';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { OutsideParamList } from '../stacks/types';
|
import { loginRequest } from '../actions/login';
|
||||||
import log, { events, logEvent } from '../utils/log';
|
|
||||||
import Button from '../containers/Button';
|
|
||||||
import I18n from '../i18n';
|
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { withTheme } from '../theme';
|
import Button from '../containers/Button';
|
||||||
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
||||||
import TextInput from '../containers/TextInput';
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import isValidEmail from '../utils/isValidEmail';
|
|
||||||
import { showErrorAlert } from '../utils/info';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
|
||||||
import openLink from '../utils/openLink';
|
|
||||||
import LoginServices from '../containers/LoginServices';
|
import LoginServices from '../containers/LoginServices';
|
||||||
|
import TextInput from '../containers/TextInput';
|
||||||
|
import { IApplicationState, IBaseScreen } from '../definitions';
|
||||||
|
import I18n from '../i18n';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
import { getShowLoginButton } from '../selectors/login';
|
import { getShowLoginButton } from '../selectors/login';
|
||||||
|
import { OutsideParamList } from '../stacks/types';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
|
import { showErrorAlert } from '../utils/info';
|
||||||
|
import isValidEmail from '../utils/isValidEmail';
|
||||||
|
import log, { events, logEvent } from '../utils/log';
|
||||||
|
import openLink from '../utils/openLink';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -51,9 +50,7 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IProps {
|
interface IProps extends IBaseScreen<OutsideParamList, 'RegisterView'> {
|
||||||
navigation: StackNavigationProp<OutsideParamList, 'RegisterView'>;
|
|
||||||
route: RouteProp<OutsideParamList, 'RegisterView'>;
|
|
||||||
server: string;
|
server: string;
|
||||||
Site_Name: string;
|
Site_Name: string;
|
||||||
Gitlab_URL: string;
|
Gitlab_URL: string;
|
||||||
|
@ -63,8 +60,6 @@ interface IProps {
|
||||||
Accounts_EmailVerification: boolean;
|
Accounts_EmailVerification: boolean;
|
||||||
Accounts_ManuallyApproveNewUsers: boolean;
|
Accounts_ManuallyApproveNewUsers: boolean;
|
||||||
showLoginButton: boolean;
|
showLoginButton: boolean;
|
||||||
loginRequest: Function;
|
|
||||||
theme: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RegisterView extends React.Component<IProps, any> {
|
class RegisterView extends React.Component<IProps, any> {
|
||||||
|
@ -130,7 +125,7 @@ class RegisterView extends React.Component<IProps, any> {
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
|
|
||||||
const { name, email, password, username, customFields } = this.state;
|
const { name, email, password, username, customFields } = this.state;
|
||||||
const { loginRequest, Accounts_EmailVerification, navigation, Accounts_ManuallyApproveNewUsers } = this.props;
|
const { dispatch, Accounts_EmailVerification, navigation, Accounts_ManuallyApproveNewUsers } = this.props;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await RocketChat.register({
|
await RocketChat.register({
|
||||||
|
@ -148,11 +143,11 @@ class RegisterView extends React.Component<IProps, any> {
|
||||||
await navigation.goBack();
|
await navigation.goBack();
|
||||||
showErrorAlert(I18n.t('Wait_activation_warning'), I18n.t('Registration_Succeeded'));
|
showErrorAlert(I18n.t('Wait_activation_warning'), I18n.t('Registration_Succeeded'));
|
||||||
} else {
|
} else {
|
||||||
await loginRequest({ user: email, password });
|
dispatch(loginRequest({ user: email, password }));
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e.data?.errorType === 'username-invalid') {
|
if (e.data?.errorType === 'username-invalid') {
|
||||||
return loginRequest({ user: email, password });
|
return dispatch(loginRequest({ user: email, password }));
|
||||||
}
|
}
|
||||||
if (e.data?.error) {
|
if (e.data?.error) {
|
||||||
logEvent(events.REGISTER_DEFAULT_SIGN_UP_F);
|
logEvent(events.REGISTER_DEFAULT_SIGN_UP_F);
|
||||||
|
@ -349,20 +344,16 @@ class RegisterView extends React.Component<IProps, any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
Site_Name: state.settings.Site_Name,
|
Site_Name: state.settings.Site_Name as string,
|
||||||
Gitlab_URL: state.settings.API_Gitlab_URL,
|
Gitlab_URL: state.settings.API_Gitlab_URL as string,
|
||||||
CAS_enabled: state.settings.CAS_enabled,
|
CAS_enabled: state.settings.CAS_enabled as boolean,
|
||||||
CAS_login_url: state.settings.CAS_login_url,
|
CAS_login_url: state.settings.CAS_login_url as string,
|
||||||
Accounts_CustomFields: state.settings.Accounts_CustomFields,
|
Accounts_CustomFields: state.settings.Accounts_CustomFields as string,
|
||||||
Accounts_EmailVerification: state.settings.Accounts_EmailVerification,
|
Accounts_EmailVerification: state.settings.Accounts_EmailVerification as boolean,
|
||||||
Accounts_ManuallyApproveNewUsers: state.settings.Accounts_ManuallyApproveNewUsers,
|
Accounts_ManuallyApproveNewUsers: state.settings.Accounts_ManuallyApproveNewUsers as boolean,
|
||||||
showLoginButton: getShowLoginButton(state)
|
showLoginButton: getShowLoginButton(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any) => ({
|
export default connect(mapStateToProps)(withTheme(RegisterView));
|
||||||
loginRequest: (params: any) => dispatch(loginRequestAction(params))
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(RegisterView));
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ import { Q } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
import { compareServerVersion } from '../../lib/utils';
|
import { compareServerVersion } from '../../lib/utils';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import { setLoading as setLoadingAction } from '../../actions/selectedUsers';
|
import { setLoading } from '../../actions/selectedUsers';
|
||||||
import { closeRoom as closeRoomAction, leaveRoom as leaveRoomAction } from '../../actions/room';
|
import { closeRoom, leaveRoom } from '../../actions/room';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
import Status from '../../containers/Status';
|
import Status from '../../containers/Status';
|
||||||
|
@ -334,9 +334,9 @@ class RoomActionsView extends React.Component {
|
||||||
const {
|
const {
|
||||||
room: { rid }
|
room: { rid }
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { closeRoom } = this.props;
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
closeRoom(rid);
|
dispatch(closeRoom(rid));
|
||||||
};
|
};
|
||||||
|
|
||||||
returnLivechat = () => {
|
returnLivechat = () => {
|
||||||
|
@ -375,16 +375,16 @@ class RoomActionsView extends React.Component {
|
||||||
|
|
||||||
addUser = async () => {
|
addUser = async () => {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
const { setLoadingInvite, navigation } = this.props;
|
const { dispatch, navigation } = this.props;
|
||||||
const { rid } = room;
|
const { rid } = room;
|
||||||
try {
|
try {
|
||||||
setLoadingInvite(true);
|
dispatch(setLoading(true));
|
||||||
await RocketChat.addUsersToRoom(rid);
|
await RocketChat.addUsersToRoom(rid);
|
||||||
navigation.pop();
|
navigation.pop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingInvite(false);
|
dispatch(setLoading(false));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -458,12 +458,12 @@ class RoomActionsView extends React.Component {
|
||||||
|
|
||||||
leaveChannel = () => {
|
leaveChannel = () => {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
const { leaveRoom } = this.props;
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
showConfirmationAlert({
|
showConfirmationAlert({
|
||||||
message: I18n.t('Are_you_sure_you_want_to_leave_the_room', { room: RocketChat.getRoomTitle(room) }),
|
message: I18n.t('Are_you_sure_you_want_to_leave_the_room', { room: RocketChat.getRoomTitle(room) }),
|
||||||
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
||||||
onPress: () => leaveRoom('channel', room)
|
onPress: () => dispatch(leaveRoom('channel', room))
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -522,7 +522,7 @@ class RoomActionsView extends React.Component {
|
||||||
|
|
||||||
leaveTeam = async () => {
|
leaveTeam = async () => {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
const { navigation, leaveRoom } = this.props;
|
const { navigation, dispatch } = this.props;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.teamListRoomsOfUser({ teamId: room.teamId, userId: room.u._id });
|
const result = await RocketChat.teamListRoomsOfUser({ teamId: room.teamId, userId: room.u._id });
|
||||||
|
@ -538,21 +538,21 @@ class RoomActionsView extends React.Component {
|
||||||
title: 'Leave_Team',
|
title: 'Leave_Team',
|
||||||
data: teamChannels,
|
data: teamChannels,
|
||||||
infoText: 'Select_Team_Channels',
|
infoText: 'Select_Team_Channels',
|
||||||
nextAction: data => leaveRoom('team', room, data),
|
nextAction: data => dispatch(leaveRoom('team', room, data)),
|
||||||
showAlert: () => showErrorAlert(I18n.t('Last_owner_team_room'), I18n.t('Cannot_leave'))
|
showAlert: () => showErrorAlert(I18n.t('Last_owner_team_room'), I18n.t('Cannot_leave'))
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
showConfirmationAlert({
|
showConfirmationAlert({
|
||||||
message: I18n.t('You_are_leaving_the_team', { team: RocketChat.getRoomTitle(room) }),
|
message: I18n.t('You_are_leaving_the_team', { team: RocketChat.getRoomTitle(room) }),
|
||||||
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
||||||
onPress: () => leaveRoom('team', room)
|
onPress: () => dispatch(leaveRoom('team', room))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showConfirmationAlert({
|
showConfirmationAlert({
|
||||||
message: I18n.t('You_are_leaving_the_team', { team: RocketChat.getRoomTitle(room) }),
|
message: I18n.t('You_are_leaving_the_team', { team: RocketChat.getRoomTitle(room) }),
|
||||||
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
||||||
onPress: () => leaveRoom('team', room)
|
onPress: () => dispatch(leaveRoom('team', room))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1242,10 +1242,4 @@ const mapStateToProps = state => ({
|
||||||
viewCannedResponsesPermission: state.permissions['view-canned-responses']
|
viewCannedResponsesPermission: state.permissions['view-canned-responses']
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
export default connect(mapStateToProps)(withTheme(withDimensions(RoomActionsView)));
|
||||||
leaveRoom: (roomType, room, selected) => dispatch(leaveRoomAction(roomType, room, selected)),
|
|
||||||
closeRoom: rid => dispatch(closeRoomAction(rid)),
|
|
||||||
setLoadingInvite: loading => dispatch(setLoadingAction(loading))
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(withDimensions(RoomActionsView)));
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import { isIOS } from '../../utils/deviceInfo';
|
||||||
import { compareServerVersion } from '../../lib/utils';
|
import { compareServerVersion } from '../../lib/utils';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { InsideStackParamList, ChatsStackParamList } from '../../stacks/types';
|
import { InsideStackParamList, ChatsStackParamList } from '../../stacks/types';
|
||||||
|
import { IRoom } from '../../definitions';
|
||||||
import { IEmoji } from '../../definitions/IEmoji';
|
import { IEmoji } from '../../definitions/IEmoji';
|
||||||
|
|
||||||
const QUERY_SIZE = 50;
|
const QUERY_SIZE = 50;
|
||||||
|
@ -81,7 +82,7 @@ class SearchMessagesView extends React.Component<ISearchMessagesViewProps, ISear
|
||||||
|
|
||||||
private encrypted: boolean | undefined;
|
private encrypted: boolean | undefined;
|
||||||
|
|
||||||
private room: { rid: any; name: any; fname: any; t: any } | null | undefined;
|
private room: Pick<IRoom, 'rid' | 'name' | 'fname' | 't'> | null | undefined;
|
||||||
|
|
||||||
static navigationOptions = ({ navigation, route }: INavigationOption) => {
|
static navigationOptions = ({ navigation, route }: INavigationOption) => {
|
||||||
const options: StackNavigationOptions = {
|
const options: StackNavigationOptions = {
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
import React from 'react';
|
|
||||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { Dispatch } from 'redux';
|
|
||||||
import { ScrollView, StyleSheet, Text } from 'react-native';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import Orientation from 'react-native-orientation-locker';
|
|
||||||
import { RouteProp } from '@react-navigation/native';
|
import { RouteProp } from '@react-navigation/native';
|
||||||
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import React from 'react';
|
||||||
|
import { ScrollView, StyleSheet, Text } from 'react-native';
|
||||||
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
import { loginRequest } from '../actions/login';
|
||||||
import TextInput from '../containers/TextInput';
|
import { themes } from '../constants/colors';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
import TextInput from '../containers/TextInput';
|
||||||
|
import { IApplicationState } from '../definitions';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
import { withTheme } from '../theme';
|
|
||||||
import { themes } from '../constants/colors';
|
|
||||||
import { isTablet } from '../utils/deviceInfo';
|
|
||||||
import { getUserSelector } from '../selectors/login';
|
import { getUserSelector } from '../selectors/login';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
|
import { isTablet } from '../utils/deviceInfo';
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -39,9 +40,9 @@ interface ISetUsernameViewProps {
|
||||||
route: RouteProp<{ SetUsernameView: { title: string } }, 'SetUsernameView'>;
|
route: RouteProp<{ SetUsernameView: { title: string } }, 'SetUsernameView'>;
|
||||||
server: string;
|
server: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
loginRequest: ({ resume }: { resume: string }) => void;
|
|
||||||
token: string;
|
token: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
|
dispatch: Dispatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernameViewState> {
|
class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernameViewState> {
|
||||||
|
@ -86,7 +87,7 @@ class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernam
|
||||||
|
|
||||||
submit = async () => {
|
submit = async () => {
|
||||||
const { username } = this.state;
|
const { username } = this.state;
|
||||||
const { loginRequest, token } = this.props;
|
const { dispatch, token } = this.props;
|
||||||
|
|
||||||
if (!username.trim()) {
|
if (!username.trim()) {
|
||||||
return;
|
return;
|
||||||
|
@ -95,7 +96,7 @@ class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernam
|
||||||
this.setState({ saving: true });
|
this.setState({ saving: true });
|
||||||
try {
|
try {
|
||||||
await RocketChat.saveUserProfile({ username });
|
await RocketChat.saveUserProfile({ username });
|
||||||
await loginRequest({ resume: token });
|
dispatch(loginRequest({ resume: token }));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
showErrorAlert(e.message, I18n.t('Oops'));
|
showErrorAlert(e.message, I18n.t('Oops'));
|
||||||
}
|
}
|
||||||
|
@ -144,13 +145,9 @@ class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
token: getUserSelector(state).token
|
token: getUserSelector(state).token
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
export default connect(mapStateToProps)(withTheme(SetUsernameView));
|
||||||
loginRequest: (params: { resume: string }) => dispatch(loginRequestAction(params))
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(SetUsernameView));
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import Header from './Header';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { IAttachment } from './interfaces';
|
import { IAttachment } from './interfaces';
|
||||||
import { ISubscription } from '../../definitions/ISubscription';
|
import { ISubscription } from '../../definitions/ISubscription';
|
||||||
|
import { IUser } from '../../definitions';
|
||||||
|
|
||||||
interface IShareViewState {
|
interface IShareViewState {
|
||||||
selected: IAttachment;
|
selected: IAttachment;
|
||||||
|
@ -230,6 +231,7 @@ class ShareView extends Component<IShareViewProps, IShareViewState> {
|
||||||
},
|
},
|
||||||
thread?.id,
|
thread?.id,
|
||||||
server,
|
server,
|
||||||
|
// @ts-ignore
|
||||||
{ id: user.id, token: user.token }
|
{ id: user.id, token: user.token }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -239,7 +241,7 @@ class ShareView extends Component<IShareViewProps, IShareViewState> {
|
||||||
|
|
||||||
// Send text message
|
// Send text message
|
||||||
} else if (text.length) {
|
} else if (text.length) {
|
||||||
await RocketChat.sendMessage(room.rid, text, thread?.id, { id: user.id, token: user.token });
|
await RocketChat.sendMessage(room.rid, text, thread?.id, { id: user.id, token: user.token } as IUser);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { FlatList, StyleSheet } from 'react-native';
|
import { FlatList, StyleSheet } from 'react-native';
|
||||||
import { Dispatch } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import { UserStatus } from '../definitions/UserStatus';
|
||||||
|
import { setUser } from '../actions/login';
|
||||||
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
|
import Loading from '../containers/Loading';
|
||||||
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import Status from '../containers/Status/Status';
|
import Status from '../containers/Status/Status';
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
|
import { LISTENER } from '../containers/Toast';
|
||||||
|
import { IApplicationState, IBaseScreen } from '../definitions';
|
||||||
|
import I18n from '../i18n';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import { getUserSelector } from '../selectors/login';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
import Loading from '../containers/Loading';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import log, { events, logEvent } from '../utils/log';
|
import log, { events, logEvent } from '../utils/log';
|
||||||
import { LISTENER } from '../containers/Toast';
|
|
||||||
import { withTheme } from '../theme';
|
|
||||||
import { getUserSelector } from '../selectors/login';
|
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
|
||||||
import { setUser as setUserAction } from '../actions/login';
|
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
|
||||||
|
|
||||||
const STATUS = [
|
const STATUS = [
|
||||||
{
|
{
|
||||||
|
@ -65,12 +65,9 @@ interface IStatusViewState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IStatusViewProps {
|
interface IStatusViewProps extends IBaseScreen<any, 'StatusView'> {
|
||||||
navigation: StackNavigationProp<any, 'StatusView'>;
|
|
||||||
user: IUser;
|
user: IUser;
|
||||||
theme: string;
|
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
setUser: (user: IUser) => void;
|
|
||||||
Accounts_AllowInvisibleStatusOption: boolean;
|
Accounts_AllowInvisibleStatusOption: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +108,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
setCustomStatus = async (statusText: string) => {
|
setCustomStatus = async (statusText: string) => {
|
||||||
const { user, setUser } = this.props;
|
const { user, dispatch } = this.props;
|
||||||
|
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
|
@ -119,7 +116,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
|
||||||
const result = await RocketChat.setUserStatus(user.status, statusText);
|
const result = await RocketChat.setUserStatus(user.status, statusText);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
logEvent(events.STATUS_CUSTOM);
|
logEvent(events.STATUS_CUSTOM);
|
||||||
setUser({ statusText });
|
dispatch(setUser({ statusText }));
|
||||||
EventEmitter.emit(LISTENER, { message: I18n.t('Status_saved_successfully') });
|
EventEmitter.emit(LISTENER, { message: I18n.t('Status_saved_successfully') });
|
||||||
} else {
|
} else {
|
||||||
logEvent(events.STATUS_CUSTOM_F);
|
logEvent(events.STATUS_CUSTOM_F);
|
||||||
|
@ -156,7 +153,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
|
||||||
|
|
||||||
renderItem = ({ item }: { item: { id: string; name: string } }) => {
|
renderItem = ({ item }: { item: { id: string; name: string } }) => {
|
||||||
const { statusText } = this.state;
|
const { statusText } = this.state;
|
||||||
const { user, setUser } = this.props;
|
const { user, dispatch } = this.props;
|
||||||
const { id, name } = item;
|
const { id, name } = item;
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<List.Item
|
||||||
|
@ -168,7 +165,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.setUserStatus(item.id, statusText);
|
const result = await RocketChat.setUserStatus(item.id, statusText);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setUser({ status: item.id });
|
dispatch(setUser({ status: item.id as UserStatus }));
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
showErrorAlert(I18n.t(e.data.errorType));
|
showErrorAlert(I18n.t(e.data.errorType));
|
||||||
|
@ -205,14 +202,10 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
user: getUserSelector(state),
|
user: getUserSelector(state),
|
||||||
isMasterDetail: state.app.isMasterDetail,
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
Accounts_AllowInvisibleStatusOption: state.settings.Accounts_AllowInvisibleStatusOption ?? true
|
Accounts_AllowInvisibleStatusOption: (state.settings.Accounts_AllowInvisibleStatusOption as boolean) ?? true
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
export default connect(mapStateToProps)(withTheme(StatusView));
|
||||||
setUser: (user: IUser) => dispatch(setUserAction(user))
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(StatusView));
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
import { Alert, FlatList, Keyboard } from 'react-native';
|
import { Alert, FlatList, Keyboard } from 'react-native';
|
||||||
import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context';
|
import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { deleteRoom } from '../actions/room';
|
import { deleteRoom } from '../actions/room';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
|
@ -17,6 +18,7 @@ import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import SearchHeader from '../containers/SearchHeader';
|
import SearchHeader from '../containers/SearchHeader';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import { IApplicationState, IBaseScreen } from '../definitions';
|
import { IApplicationState, IBaseScreen } from '../definitions';
|
||||||
|
import { ERoomType } from '../definitions/ERoomType';
|
||||||
import { withDimensions } from '../dimensions';
|
import { withDimensions } from '../dimensions';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
|
@ -48,7 +50,7 @@ const keyExtractor = (item: IItem) => item._id;
|
||||||
|
|
||||||
// This interface comes from request RocketChat.getTeamListRoom
|
// This interface comes from request RocketChat.getTeamListRoom
|
||||||
interface IItem {
|
interface IItem {
|
||||||
_id: string;
|
_id: ERoomType;
|
||||||
fname: string;
|
fname: string;
|
||||||
customFields: object;
|
customFields: object;
|
||||||
broadcast: boolean;
|
broadcast: boolean;
|
||||||
|
@ -97,6 +99,7 @@ interface ITeamChannelsViewProps extends IProps {
|
||||||
showActionSheet: (options: any) => void;
|
showActionSheet: (options: any) => void;
|
||||||
showAvatar: boolean;
|
showAvatar: boolean;
|
||||||
displayMode: string;
|
displayMode: string;
|
||||||
|
dispatch: Dispatch;
|
||||||
}
|
}
|
||||||
class TeamChannelsView extends React.Component<ITeamChannelsViewProps, ITeamChannelsViewState> {
|
class TeamChannelsView extends React.Component<ITeamChannelsViewProps, ITeamChannelsViewState> {
|
||||||
private teamId: string;
|
private teamId: string;
|
||||||
|
@ -438,7 +441,8 @@ class TeamChannelsView extends React.Component<ITeamChannelsViewProps, ITeamChan
|
||||||
{
|
{
|
||||||
text: I18n.t('Yes_action_it', { action: I18n.t('delete') }),
|
text: I18n.t('Yes_action_it', { action: I18n.t('delete') }),
|
||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: () => dispatch(deleteRoom(item._id, item.t))
|
// VERIFY ON PR
|
||||||
|
onPress: () => dispatch(deleteRoom(item._id, item))
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
{ cancelable: false }
|
{ cancelable: false }
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/node_modules/@types/ejson/index.d.ts b/node_modules/@types/ejson/index.d.ts
|
||||||
|
index 3a35636..278ef98 100755
|
||||||
|
--- a/node_modules/@types/ejson/index.d.ts
|
||||||
|
+++ b/node_modules/@types/ejson/index.d.ts
|
||||||
|
@@ -17,7 +17,7 @@ export function parse(str: string): any;
|
||||||
|
export function stringify(obj: any, options?: StringifyOptions): string;
|
||||||
|
|
||||||
|
export function toJSONValue(obj: any): string;
|
||||||
|
-export function fromJSONValue(obj: string): any;
|
||||||
|
+export function fromJSONValue(obj: Object): any;
|
||||||
|
export function isBinary(value: any): boolean;
|
||||||
|
export function newBinary(len: number): Uint8Array;
|
||||||
|
export function equals(a: any, b: any, options?: CloneOptions): boolean;
|
|
@ -797,6 +797,13 @@ stories.add('System messages', () => (
|
||||||
<Message msg='public' type='room_changed_privacy' isInfo />
|
<Message msg='public' type='room_changed_privacy' isInfo />
|
||||||
<Message type='room_e2e_disabled' isInfo />
|
<Message type='room_e2e_disabled' isInfo />
|
||||||
<Message type='room_e2e_enabled' isInfo />
|
<Message type='room_e2e_enabled' isInfo />
|
||||||
|
<Message type='removed-user-from-team' isInfo />
|
||||||
|
<Message type='added-user-to-team' isInfo />
|
||||||
|
<Message type='user-added-room-to-team' isInfo msg='channel-name' />
|
||||||
|
<Message type='user-converted-to-team' isInfo msg='channel-name' />
|
||||||
|
<Message type='user-converted-to-channel' isInfo msg='channel-name' />
|
||||||
|
<Message type='user-deleted-room-from-team' isInfo msg='channel-name' />
|
||||||
|
<Message type='user-removed-room-from-team' isInfo msg='channel-name' />
|
||||||
</>
|
</>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue