Merge branch 'develop' into chore.console-error
This commit is contained in:
commit
6168926600
|
@ -359,7 +359,7 @@ jobs:
|
|||
- run:
|
||||
name: Test
|
||||
command: |
|
||||
yarn test
|
||||
yarn test -w 8
|
||||
|
||||
- run:
|
||||
name: Codecov
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
import initStoryshots, { Stories2SnapsConverter } from '@storybook/addon-storyshots';
|
||||
import { render } from '@testing-library/react-native';
|
||||
|
||||
jest.mock('rn-fetch-blob', () => ({
|
||||
fs: {
|
||||
|
@ -19,4 +20,15 @@ jest.mock('react-native-file-viewer', () => ({
|
|||
jest.mock('../app/lib/database', () => jest.fn(() => null));
|
||||
global.Date.now = jest.fn(() => new Date('2019-10-10').getTime());
|
||||
|
||||
initStoryshots();
|
||||
const converter = new Stories2SnapsConverter();
|
||||
|
||||
initStoryshots({
|
||||
test: ({ story, context }) => {
|
||||
const snapshotFilename = converter.getSnapshotFileName(context);
|
||||
const storyElement = story.render();
|
||||
const { update, toJSON } = render(storyElement);
|
||||
update(storyElement);
|
||||
const json = toJSON();
|
||||
expect(JSON.stringify(json)).toMatchSpecificSnapshot(snapshotFilename);
|
||||
}
|
||||
});
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
|||
import { SetUsernameStackParamList, StackParamList } from './definitions/navigationTypes';
|
||||
import Navigation from './lib/Navigation';
|
||||
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
||||
import { ROOT_INSIDE, ROOT_LOADING, ROOT_OUTSIDE, ROOT_SET_USERNAME } from './actions/app';
|
||||
import { RootEnum } from './definitions';
|
||||
// Stacks
|
||||
import AuthLoadingView from './views/AuthLoadingView';
|
||||
// SetUsername Stack
|
||||
|
@ -56,13 +56,13 @@ const App = React.memo(({ root, isMasterDetail }: { root: string; isMasterDetail
|
|||
}}>
|
||||
<Stack.Navigator screenOptions={{ headerShown: false, animationEnabled: false }}>
|
||||
<>
|
||||
{root === ROOT_LOADING ? <Stack.Screen name='AuthLoading' component={AuthLoadingView} /> : null}
|
||||
{root === ROOT_OUTSIDE ? <Stack.Screen name='OutsideStack' component={OutsideStack} /> : null}
|
||||
{root === ROOT_INSIDE && isMasterDetail ? (
|
||||
{root === RootEnum.ROOT_LOADING ? <Stack.Screen name='AuthLoading' component={AuthLoadingView} /> : null}
|
||||
{root === RootEnum.ROOT_OUTSIDE ? <Stack.Screen name='OutsideStack' component={OutsideStack} /> : null}
|
||||
{root === RootEnum.ROOT_INSIDE && isMasterDetail ? (
|
||||
<Stack.Screen name='MasterDetailStack' component={MasterDetailStack} />
|
||||
) : null}
|
||||
{root === ROOT_INSIDE && !isMasterDetail ? <Stack.Screen name='InsideStack' component={InsideStack} /> : null}
|
||||
{root === ROOT_SET_USERNAME ? <Stack.Screen name='SetUsernameStack' component={SetUsernameStack} /> : null}
|
||||
{root === RootEnum.ROOT_INSIDE && !isMasterDetail ? <Stack.Screen name='InsideStack' component={InsideStack} /> : null}
|
||||
{root === RootEnum.ROOT_SET_USERNAME ? <Stack.Screen name='SetUsernameStack' component={SetUsernameStack} /> : null}
|
||||
</>
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
|
|
|
@ -2,8 +2,8 @@ const REQUEST = 'REQUEST';
|
|||
const SUCCESS = 'SUCCESS';
|
||||
const FAILURE = 'FAILURE';
|
||||
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
||||
function createRequestTypes(base = {}, types = defaultTypes): Record<any, any> {
|
||||
const res: Record<any, any> = {};
|
||||
function createRequestTypes(base = {}, types = defaultTypes): Record<string, string> {
|
||||
const res: Record<string, string> = {};
|
||||
types.forEach(type => (res[type] = `${base}_${type}`));
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Action } from 'redux';
|
|||
import { IActiveUsers } from '../reducers/activeUsers';
|
||||
import { SET_ACTIVE_USERS } from './actionsTypes';
|
||||
|
||||
export interface ISetActiveUsers extends Action {
|
||||
interface ISetActiveUsers extends Action {
|
||||
activeUsers: IActiveUsers;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
import { APP } from './actionsTypes';
|
||||
|
||||
export const ROOT_OUTSIDE = 'outside';
|
||||
export const ROOT_INSIDE = 'inside';
|
||||
export const ROOT_LOADING = 'loading';
|
||||
export const ROOT_SET_USERNAME = 'setUsername';
|
||||
|
||||
export function appStart({ root, ...args }) {
|
||||
return {
|
||||
type: APP.START,
|
||||
root,
|
||||
...args
|
||||
};
|
||||
}
|
||||
|
||||
export function appReady() {
|
||||
return {
|
||||
type: APP.READY
|
||||
};
|
||||
}
|
||||
|
||||
export function appInit() {
|
||||
return {
|
||||
type: APP.INIT
|
||||
};
|
||||
}
|
||||
|
||||
export function appInitLocalSettings() {
|
||||
return {
|
||||
type: APP.INIT_LOCAL_SETTINGS
|
||||
};
|
||||
}
|
||||
|
||||
export function setMasterDetail(isMasterDetail) {
|
||||
return {
|
||||
type: APP.SET_MASTER_DETAIL,
|
||||
isMasterDetail
|
||||
};
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { RootEnum } from '../definitions';
|
||||
import { APP } from './actionsTypes';
|
||||
|
||||
interface IAppStart extends Action {
|
||||
root: RootEnum;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
interface ISetMasterDetail extends Action {
|
||||
isMasterDetail: boolean;
|
||||
}
|
||||
|
||||
export type TActionApp = IAppStart & ISetMasterDetail;
|
||||
|
||||
interface Params {
|
||||
root: RootEnum;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export function appStart({ root, ...args }: Params): IAppStart {
|
||||
return {
|
||||
type: APP.START,
|
||||
root,
|
||||
...args
|
||||
};
|
||||
}
|
||||
|
||||
export function appReady(): Action {
|
||||
return {
|
||||
type: APP.READY
|
||||
};
|
||||
}
|
||||
|
||||
export function appInit(): Action {
|
||||
return {
|
||||
type: APP.INIT
|
||||
};
|
||||
}
|
||||
|
||||
export function appInitLocalSettings(): Action {
|
||||
return {
|
||||
type: APP.INIT_LOCAL_SETTINGS
|
||||
};
|
||||
}
|
||||
|
||||
export function setMasterDetail(isMasterDetail: boolean): ISetMasterDetail {
|
||||
return {
|
||||
type: APP.SET_MASTER_DETAIL,
|
||||
isMasterDetail
|
||||
};
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function connectRequest() {
|
||||
return {
|
||||
type: types.METEOR.REQUEST
|
||||
};
|
||||
}
|
||||
|
||||
export function connectSuccess() {
|
||||
return {
|
||||
type: types.METEOR.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function disconnect(err) {
|
||||
return {
|
||||
type: types.METEOR.DISCONNECT,
|
||||
err
|
||||
};
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import * as types from './actionsTypes';
|
||||
|
||||
export function connectRequest(): Action {
|
||||
return {
|
||||
type: types.METEOR.REQUEST
|
||||
};
|
||||
}
|
||||
|
||||
export function connectSuccess(): Action {
|
||||
return {
|
||||
type: types.METEOR.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function disconnect(): Action {
|
||||
return {
|
||||
type: types.METEOR.DISCONNECT
|
||||
};
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function createChannelRequest(data) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.REQUEST,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelSuccess(data) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.SUCCESS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelFailure(err, isTeam) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.FAILURE,
|
||||
err,
|
||||
isTeam
|
||||
};
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { TCreateChannelResult } from '../reducers/createChannel';
|
||||
import { CREATE_CHANNEL } from './actionsTypes';
|
||||
|
||||
interface ICreateChannelRequest extends Action {
|
||||
data: TCreateChannelResult;
|
||||
}
|
||||
|
||||
interface ICreateChannelSuccess extends Action {
|
||||
data: TCreateChannelResult;
|
||||
}
|
||||
|
||||
interface ICreateChannelFailure extends Action {
|
||||
err: any;
|
||||
isTeam: boolean;
|
||||
}
|
||||
|
||||
export type TActionCreateChannel = ICreateChannelRequest & ICreateChannelSuccess & ICreateChannelFailure;
|
||||
|
||||
export function createChannelRequest(data: TCreateChannelResult): ICreateChannelRequest {
|
||||
return {
|
||||
type: CREATE_CHANNEL.REQUEST,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelSuccess(data: TCreateChannelResult): ICreateChannelSuccess {
|
||||
return {
|
||||
type: CREATE_CHANNEL.SUCCESS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelFailure(err: any, isTeam: boolean): ICreateChannelFailure {
|
||||
return {
|
||||
type: CREATE_CHANNEL.FAILURE,
|
||||
err,
|
||||
isTeam
|
||||
};
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function createDiscussionRequest(data) {
|
||||
return {
|
||||
type: types.CREATE_DISCUSSION.REQUEST,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createDiscussionSuccess(data) {
|
||||
return {
|
||||
type: types.CREATE_DISCUSSION.SUCCESS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createDiscussionFailure(err) {
|
||||
return {
|
||||
type: types.CREATE_DISCUSSION.FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { CREATE_DISCUSSION } from './actionsTypes';
|
||||
|
||||
interface ICreateDiscussionRequest extends Action {
|
||||
data: any;
|
||||
}
|
||||
|
||||
interface ICreateDiscussionSuccess extends Action {
|
||||
data: any;
|
||||
}
|
||||
|
||||
interface ICreateDiscussionFailure extends Action {
|
||||
err: any;
|
||||
}
|
||||
|
||||
export type TActionCreateDiscussion = ICreateDiscussionRequest & ICreateDiscussionSuccess & ICreateDiscussionFailure;
|
||||
|
||||
export function createDiscussionRequest(data: any): ICreateDiscussionRequest {
|
||||
return {
|
||||
type: CREATE_DISCUSSION.REQUEST,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createDiscussionSuccess(data: any): ICreateDiscussionSuccess {
|
||||
return {
|
||||
type: CREATE_DISCUSSION.SUCCESS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createDiscussionFailure(err: any): ICreateDiscussionFailure {
|
||||
return {
|
||||
type: CREATE_DISCUSSION.FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function setCustomEmojis(emojis) {
|
||||
return {
|
||||
type: types.SET_CUSTOM_EMOJIS,
|
||||
emojis
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { ICustomEmojis } from '../reducers/customEmojis';
|
||||
import { SET_CUSTOM_EMOJIS } from './actionsTypes';
|
||||
|
||||
export interface ISetCustomEmojis extends Action {
|
||||
emojis: ICustomEmojis;
|
||||
}
|
||||
|
||||
export type TActionCustomEmojis = ISetCustomEmojis;
|
||||
|
||||
export function setCustomEmojis(emojis: ICustomEmojis): ISetCustomEmojis {
|
||||
return {
|
||||
type: SET_CUSTOM_EMOJIS,
|
||||
emojis
|
||||
};
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function deepLinkingOpen(params) {
|
||||
return {
|
||||
type: types.DEEP_LINKING.OPEN,
|
||||
params
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { DEEP_LINKING } from './actionsTypes';
|
||||
|
||||
interface IParams {
|
||||
path: string;
|
||||
rid: string;
|
||||
messageId: string;
|
||||
host: string;
|
||||
isCall: boolean;
|
||||
fullURL: string;
|
||||
type: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
interface IDeepLinkingOpen extends Action {
|
||||
params: Partial<IParams>;
|
||||
}
|
||||
|
||||
export function deepLinkingOpen(params: Partial<IParams>): IDeepLinkingOpen {
|
||||
return {
|
||||
type: DEEP_LINKING.OPEN,
|
||||
params
|
||||
};
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function encryptionInit() {
|
||||
return {
|
||||
type: types.ENCRYPTION.INIT
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionStop() {
|
||||
return {
|
||||
type: types.ENCRYPTION.STOP
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionSet(enabled = false, banner = null) {
|
||||
return {
|
||||
type: types.ENCRYPTION.SET,
|
||||
enabled,
|
||||
banner
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionSetBanner(banner) {
|
||||
return {
|
||||
type: types.ENCRYPTION.SET_BANNER,
|
||||
banner
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionDecodeKey(password) {
|
||||
return {
|
||||
type: types.ENCRYPTION.DECODE_KEY,
|
||||
password
|
||||
};
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IBanner } from '../reducers/encryption';
|
||||
import { ENCRYPTION } from './actionsTypes';
|
||||
|
||||
export interface IEncryptionSet extends Action {
|
||||
enabled: boolean;
|
||||
banner: IBanner;
|
||||
}
|
||||
|
||||
export interface IEncryptionSetBanner extends Action {
|
||||
banner: IBanner;
|
||||
}
|
||||
export interface IEncryptionDecodeKey extends Action {
|
||||
password: string;
|
||||
}
|
||||
|
||||
export type TActionEncryption = IEncryptionSet & IEncryptionSetBanner & IEncryptionDecodeKey;
|
||||
|
||||
export function encryptionInit(): Action {
|
||||
return {
|
||||
type: ENCRYPTION.INIT
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionStop(): Action {
|
||||
return {
|
||||
type: ENCRYPTION.STOP
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionSet(enabled = false, banner: IBanner = ''): IEncryptionSet {
|
||||
return {
|
||||
type: ENCRYPTION.SET,
|
||||
enabled,
|
||||
banner
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionSetBanner(banner: IBanner = ''): IEncryptionSetBanner {
|
||||
return {
|
||||
type: ENCRYPTION.SET_BANNER,
|
||||
banner
|
||||
};
|
||||
}
|
||||
|
||||
export function encryptionDecodeKey(password: string): IEncryptionDecodeKey {
|
||||
return {
|
||||
type: ENCRYPTION.DECODE_KEY,
|
||||
password
|
||||
};
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function inviteLinksSetToken(token) {
|
||||
return {
|
||||
type: types.INVITE_LINKS.SET_TOKEN,
|
||||
token
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksRequest(token) {
|
||||
return {
|
||||
type: types.INVITE_LINKS.REQUEST,
|
||||
token
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksSuccess() {
|
||||
return {
|
||||
type: types.INVITE_LINKS.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksFailure() {
|
||||
return {
|
||||
type: types.INVITE_LINKS.FAILURE
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksClear() {
|
||||
return {
|
||||
type: types.INVITE_LINKS.CLEAR
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksCreate(rid) {
|
||||
return {
|
||||
type: types.INVITE_LINKS.CREATE,
|
||||
rid
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksSetParams(params) {
|
||||
return {
|
||||
type: types.INVITE_LINKS.SET_PARAMS,
|
||||
params
|
||||
};
|
||||
}
|
||||
|
||||
export function inviteLinksSetInvite(invite) {
|
||||
return {
|
||||
type: types.INVITE_LINKS.SET_INVITE,
|
||||
invite
|
||||
};
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { TInvite } from '../reducers/inviteLinks';
|
||||
import { INVITE_LINKS } from './actionsTypes';
|
||||
|
||||
interface IInviteLinksGeneric extends Action {
|
||||
token: string;
|
||||
}
|
||||
|
||||
interface IInviteLinksCreate extends Action {
|
||||
rid: string;
|
||||
}
|
||||
|
||||
interface IInviteLinksSetInvite extends Action {
|
||||
invite: TInvite;
|
||||
}
|
||||
|
||||
type TParams = Record<string, any>;
|
||||
|
||||
interface IInviteLinksSetParams extends Action {
|
||||
params: TParams;
|
||||
}
|
||||
|
||||
export type TActionInviteLinks = IInviteLinksGeneric & IInviteLinksCreate & IInviteLinksSetInvite & IInviteLinksSetParams;
|
||||
|
||||
export const inviteLinksSetToken = (token: string): IInviteLinksGeneric => ({
|
||||
type: INVITE_LINKS.SET_TOKEN,
|
||||
token
|
||||
});
|
||||
|
||||
export const inviteLinksRequest = (token: string): IInviteLinksGeneric => ({
|
||||
type: INVITE_LINKS.REQUEST,
|
||||
token
|
||||
});
|
||||
|
||||
export const inviteLinksSuccess = (): Action => ({
|
||||
type: INVITE_LINKS.SUCCESS
|
||||
});
|
||||
|
||||
export const inviteLinksFailure = (): Action => ({
|
||||
type: INVITE_LINKS.FAILURE
|
||||
});
|
||||
|
||||
export const inviteLinksClear = (): Action => ({
|
||||
type: INVITE_LINKS.CLEAR
|
||||
});
|
||||
|
||||
export const inviteLinksCreate = (rid: string): IInviteLinksCreate => ({
|
||||
type: INVITE_LINKS.CREATE,
|
||||
rid
|
||||
});
|
||||
|
||||
export const inviteLinksSetParams = (params: TParams): IInviteLinksSetParams => ({
|
||||
type: INVITE_LINKS.SET_PARAMS,
|
||||
params
|
||||
});
|
||||
|
||||
export const inviteLinksSetInvite = (invite: TInvite): IInviteLinksSetInvite => ({
|
||||
type: INVITE_LINKS.SET_INVITE,
|
||||
invite
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function replyBroadcast(message) {
|
||||
return {
|
||||
type: types.MESSAGES.REPLY_BROADCAST,
|
||||
message
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { MESSAGES } from './actionsTypes';
|
||||
|
||||
type IMessage = Record<string, string>;
|
||||
|
||||
interface IReplyBroadcast extends Action {
|
||||
message: IMessage;
|
||||
}
|
||||
|
||||
export function replyBroadcast(message: IMessage): IReplyBroadcast {
|
||||
return {
|
||||
type: MESSAGES.REPLY_BROADCAST,
|
||||
message
|
||||
};
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function setPermissions(permissions) {
|
||||
return {
|
||||
type: types.PERMISSIONS.SET,
|
||||
permissions
|
||||
};
|
||||
}
|
||||
|
||||
export function updatePermission(id, roles) {
|
||||
return {
|
||||
type: types.PERMISSIONS.UPDATE,
|
||||
payload: { id, roles }
|
||||
};
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IPermissions } from '../reducers/permissions';
|
||||
import { PERMISSIONS } from './actionsTypes';
|
||||
|
||||
interface ISetPermissions extends Action {
|
||||
permissions: IPermissions;
|
||||
}
|
||||
|
||||
interface IUpdatePermissions extends Action {
|
||||
payload: { id: string; roles: string };
|
||||
}
|
||||
|
||||
export type TActionPermissions = ISetPermissions & IUpdatePermissions;
|
||||
|
||||
export function setPermissions(permissions: IPermissions): ISetPermissions {
|
||||
return {
|
||||
type: PERMISSIONS.SET,
|
||||
permissions
|
||||
};
|
||||
}
|
||||
|
||||
export function updatePermission(id: string, roles: string): IUpdatePermissions {
|
||||
return {
|
||||
type: PERMISSIONS.UPDATE,
|
||||
payload: { id, roles }
|
||||
};
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function setRoles(roles) {
|
||||
return {
|
||||
type: types.ROLES.SET,
|
||||
roles
|
||||
};
|
||||
}
|
||||
export function updateRoles(id, desc) {
|
||||
return {
|
||||
type: types.ROLES.UPDATE,
|
||||
payload: { id, desc }
|
||||
};
|
||||
}
|
||||
export function removeRoles(id) {
|
||||
return {
|
||||
type: types.ROLES.REMOVE,
|
||||
payload: { id }
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IRoles } from '../reducers/roles';
|
||||
import { ROLES } from './actionsTypes';
|
||||
|
||||
export interface ISetRoles extends Action {
|
||||
roles: IRoles;
|
||||
}
|
||||
|
||||
export interface IUpdateRoles extends Action {
|
||||
payload: { id: string; desc: string };
|
||||
}
|
||||
|
||||
export interface IRemoveRoles extends Action {
|
||||
payload: { id: string };
|
||||
}
|
||||
|
||||
export type IActionRoles = ISetRoles & IUpdateRoles & IRemoveRoles;
|
||||
|
||||
export function setRoles(roles: IRoles): ISetRoles {
|
||||
return {
|
||||
type: ROLES.SET,
|
||||
roles
|
||||
};
|
||||
}
|
||||
|
||||
export function updateRoles(id: string, desc: string): IUpdateRoles {
|
||||
return {
|
||||
type: ROLES.UPDATE,
|
||||
payload: { id, desc }
|
||||
};
|
||||
}
|
||||
|
||||
export function removeRoles(id: string): IRemoveRoles {
|
||||
return {
|
||||
type: ROLES.REMOVE,
|
||||
payload: { id }
|
||||
};
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function roomsRequest(params = { allData: false }) {
|
||||
return {
|
||||
type: types.ROOMS.REQUEST,
|
||||
params
|
||||
};
|
||||
}
|
||||
|
||||
export function roomsSuccess() {
|
||||
return {
|
||||
type: types.ROOMS.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function roomsFailure(err) {
|
||||
return {
|
||||
type: types.ROOMS.FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function roomsRefresh() {
|
||||
return {
|
||||
type: types.ROOMS.REFRESH
|
||||
};
|
||||
}
|
||||
|
||||
export function setSearch(searchText) {
|
||||
return {
|
||||
type: types.ROOMS.SET_SEARCH,
|
||||
searchText
|
||||
};
|
||||
}
|
||||
|
||||
export function closeServerDropdown() {
|
||||
return {
|
||||
type: types.ROOMS.CLOSE_SERVER_DROPDOWN
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleServerDropdown() {
|
||||
return {
|
||||
type: types.ROOMS.TOGGLE_SERVER_DROPDOWN
|
||||
};
|
||||
}
|
||||
|
||||
export function openSearchHeader() {
|
||||
return {
|
||||
type: types.ROOMS.OPEN_SEARCH_HEADER
|
||||
};
|
||||
}
|
||||
|
||||
export function closeSearchHeader() {
|
||||
return {
|
||||
type: types.ROOMS.CLOSE_SEARCH_HEADER
|
||||
};
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { ROOMS } from './actionsTypes';
|
||||
|
||||
export interface IRoomsRequest extends Action {
|
||||
params: any;
|
||||
}
|
||||
|
||||
export interface ISetSearch extends Action {
|
||||
searchText: string;
|
||||
}
|
||||
|
||||
export interface IRoomsFailure extends Action {
|
||||
err: Record<string, any> | string;
|
||||
}
|
||||
|
||||
export type IRoomsAction = IRoomsRequest & ISetSearch & IRoomsFailure;
|
||||
|
||||
export function roomsRequest(
|
||||
params: {
|
||||
allData: boolean;
|
||||
} = { allData: false }
|
||||
): IRoomsRequest {
|
||||
return {
|
||||
type: ROOMS.REQUEST,
|
||||
params
|
||||
};
|
||||
}
|
||||
|
||||
export function roomsSuccess(): Action {
|
||||
return {
|
||||
type: ROOMS.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function roomsFailure(err: string): IRoomsFailure {
|
||||
return {
|
||||
type: ROOMS.FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function roomsRefresh(): Action {
|
||||
return {
|
||||
type: ROOMS.REFRESH
|
||||
};
|
||||
}
|
||||
|
||||
export function setSearch(searchText: string): ISetSearch {
|
||||
return {
|
||||
type: ROOMS.SET_SEARCH,
|
||||
searchText
|
||||
};
|
||||
}
|
||||
|
||||
export function closeServerDropdown(): Action {
|
||||
return {
|
||||
type: ROOMS.CLOSE_SERVER_DROPDOWN
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleServerDropdown(): Action {
|
||||
return {
|
||||
type: ROOMS.TOGGLE_SERVER_DROPDOWN
|
||||
};
|
||||
}
|
||||
|
||||
export function openSearchHeader(): Action {
|
||||
return {
|
||||
type: ROOMS.OPEN_SEARCH_HEADER
|
||||
};
|
||||
}
|
||||
|
||||
export function closeSearchHeader(): Action {
|
||||
return {
|
||||
type: ROOMS.CLOSE_SEARCH_HEADER
|
||||
};
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
import { SERVER } from './actionsTypes';
|
||||
|
||||
export function selectServerRequest(server, version, fetchVersion = true, changeServer = false) {
|
||||
return {
|
||||
type: SERVER.SELECT_REQUEST,
|
||||
server,
|
||||
version,
|
||||
fetchVersion,
|
||||
changeServer
|
||||
};
|
||||
}
|
||||
|
||||
export function selectServerSuccess(server, version) {
|
||||
return {
|
||||
type: SERVER.SELECT_SUCCESS,
|
||||
server,
|
||||
version
|
||||
};
|
||||
}
|
||||
|
||||
export function selectServerFailure() {
|
||||
return {
|
||||
type: SERVER.SELECT_FAILURE
|
||||
};
|
||||
}
|
||||
|
||||
export function serverRequest(server, username = null, fromServerHistory = false) {
|
||||
return {
|
||||
type: SERVER.REQUEST,
|
||||
server,
|
||||
username,
|
||||
fromServerHistory
|
||||
};
|
||||
}
|
||||
|
||||
export function serverSuccess() {
|
||||
return {
|
||||
type: SERVER.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function serverFailure(err) {
|
||||
return {
|
||||
type: SERVER.FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function serverInitAdd(previousServer) {
|
||||
return {
|
||||
type: SERVER.INIT_ADD,
|
||||
previousServer
|
||||
};
|
||||
}
|
||||
|
||||
export function serverFinishAdd() {
|
||||
return {
|
||||
type: SERVER.FINISH_ADD
|
||||
};
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { SERVER } from './actionsTypes';
|
||||
|
||||
interface ISelectServer extends Action {
|
||||
server: string;
|
||||
version?: string;
|
||||
fetchVersion: boolean;
|
||||
changeServer: boolean;
|
||||
}
|
||||
|
||||
interface ISelectServerSuccess extends Action {
|
||||
server: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
interface IServer extends Action {
|
||||
server: string;
|
||||
username: string | null;
|
||||
fromServerHistory: boolean;
|
||||
}
|
||||
|
||||
interface IServerInit extends Action {
|
||||
previousServer: string;
|
||||
}
|
||||
|
||||
interface IServerFailure extends Action {
|
||||
err: any;
|
||||
}
|
||||
|
||||
export type TActionServer = ISelectServer & ISelectServerSuccess & IServer & IServerInit & IServerFailure;
|
||||
|
||||
export function selectServerRequest(server: string, version?: string, fetchVersion = true, changeServer = false): ISelectServer {
|
||||
return {
|
||||
type: SERVER.SELECT_REQUEST,
|
||||
server,
|
||||
version,
|
||||
fetchVersion,
|
||||
changeServer
|
||||
};
|
||||
}
|
||||
|
||||
export function selectServerSuccess(server: string, version: string): ISelectServerSuccess {
|
||||
return {
|
||||
type: SERVER.SELECT_SUCCESS,
|
||||
server,
|
||||
version
|
||||
};
|
||||
}
|
||||
|
||||
export function selectServerFailure(): Action {
|
||||
return {
|
||||
type: SERVER.SELECT_FAILURE
|
||||
};
|
||||
}
|
||||
|
||||
export function serverRequest(server: string, username: string | null = null, fromServerHistory = false): IServer {
|
||||
return {
|
||||
type: SERVER.REQUEST,
|
||||
server,
|
||||
username,
|
||||
fromServerHistory
|
||||
};
|
||||
}
|
||||
|
||||
export function serverSuccess(): Action {
|
||||
return {
|
||||
type: SERVER.SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function serverFailure(err: any): IServerFailure {
|
||||
return {
|
||||
type: SERVER.FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function serverInitAdd(previousServer: string): IServerInit {
|
||||
return {
|
||||
type: SERVER.INIT_ADD,
|
||||
previousServer
|
||||
};
|
||||
}
|
||||
|
||||
export function serverFinishAdd(): Action {
|
||||
return {
|
||||
type: SERVER.FINISH_ADD
|
||||
};
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import { SETTINGS } from './actionsTypes';
|
||||
|
||||
export function addSettings(settings) {
|
||||
return {
|
||||
type: SETTINGS.ADD,
|
||||
payload: settings
|
||||
};
|
||||
}
|
||||
|
||||
export function updateSettings(id, value) {
|
||||
return {
|
||||
type: SETTINGS.UPDATE,
|
||||
payload: { id, value }
|
||||
};
|
||||
}
|
||||
|
||||
export function clearSettings() {
|
||||
return {
|
||||
type: SETTINGS.CLEAR
|
||||
};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { ISettings, TSettings } from '../reducers/settings';
|
||||
import { SETTINGS } from './actionsTypes';
|
||||
|
||||
interface IAddSettings extends Action {
|
||||
payload: ISettings;
|
||||
}
|
||||
|
||||
interface IUpdateSettings extends Action {
|
||||
payload: { id: string; value: TSettings };
|
||||
}
|
||||
|
||||
export type IActionSettings = IAddSettings & IUpdateSettings;
|
||||
|
||||
export function addSettings(settings: ISettings): IAddSettings {
|
||||
return {
|
||||
type: SETTINGS.ADD,
|
||||
payload: settings
|
||||
};
|
||||
}
|
||||
|
||||
export function updateSettings(id: string, value: TSettings): IUpdateSettings {
|
||||
return {
|
||||
type: SETTINGS.UPDATE,
|
||||
payload: { id, value }
|
||||
};
|
||||
}
|
||||
|
||||
export function clearSettings(): Action {
|
||||
return {
|
||||
type: SETTINGS.CLEAR
|
||||
};
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
import { SHARE } from './actionsTypes';
|
||||
|
||||
export function shareSelectServer(server) {
|
||||
return {
|
||||
type: SHARE.SELECT_SERVER,
|
||||
server
|
||||
};
|
||||
}
|
||||
|
||||
export function shareSetSettings(settings) {
|
||||
return {
|
||||
type: SHARE.SET_SETTINGS,
|
||||
settings
|
||||
};
|
||||
}
|
||||
|
||||
export function shareSetUser(user) {
|
||||
return {
|
||||
type: SHARE.SET_USER,
|
||||
user
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IShareServer, IShareUser, TShareSettings } from '../reducers/share';
|
||||
import { SHARE } from './actionsTypes';
|
||||
|
||||
interface IShareSelectServer extends Action {
|
||||
server: IShareServer;
|
||||
}
|
||||
|
||||
interface IShareSetSettings extends Action {
|
||||
settings: TShareSettings;
|
||||
}
|
||||
|
||||
interface IShareSetUser extends Action {
|
||||
user: IShareUser;
|
||||
}
|
||||
|
||||
export type TActionsShare = IShareSelectServer & IShareSetSettings & IShareSetUser;
|
||||
|
||||
export function shareSelectServer(server: IShareServer): IShareSelectServer {
|
||||
return {
|
||||
type: SHARE.SELECT_SERVER,
|
||||
server
|
||||
};
|
||||
}
|
||||
|
||||
export function shareSetSettings(settings: TShareSettings): IShareSetSettings {
|
||||
return {
|
||||
type: SHARE.SET_SETTINGS,
|
||||
settings
|
||||
};
|
||||
}
|
||||
|
||||
export function shareSetUser(user: IShareUser): IShareSetUser {
|
||||
return {
|
||||
type: SHARE.SET_USER,
|
||||
user
|
||||
};
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function setAllPreferences(preferences) {
|
||||
return {
|
||||
type: types.SORT_PREFERENCES.SET_ALL,
|
||||
preferences
|
||||
};
|
||||
}
|
||||
|
||||
export function setPreference(preference) {
|
||||
return {
|
||||
type: types.SORT_PREFERENCES.SET,
|
||||
preference
|
||||
};
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IPreferences } from '../definitions';
|
||||
import { SORT_PREFERENCES } from './actionsTypes';
|
||||
|
||||
interface ISetAllPreferences extends Action {
|
||||
preferences: IPreferences;
|
||||
}
|
||||
|
||||
interface ISetPreference extends Action {
|
||||
preference: Partial<IPreferences>;
|
||||
}
|
||||
|
||||
export type TActionSortPreferences = ISetAllPreferences & ISetPreference;
|
||||
|
||||
export function setAllPreferences(preferences: IPreferences): ISetAllPreferences {
|
||||
return {
|
||||
type: SORT_PREFERENCES.SET_ALL,
|
||||
preferences
|
||||
};
|
||||
}
|
||||
|
||||
export function setPreference(preference: Partial<IPreferences>): ISetPreference {
|
||||
return {
|
||||
type: SORT_PREFERENCES.SET,
|
||||
preference
|
||||
};
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import { USERS_TYPING } from './actionsTypes';
|
||||
|
||||
export function addUserTyping(username) {
|
||||
return {
|
||||
type: USERS_TYPING.ADD,
|
||||
username
|
||||
};
|
||||
}
|
||||
|
||||
export function removeUserTyping(username) {
|
||||
return {
|
||||
type: USERS_TYPING.REMOVE,
|
||||
username
|
||||
};
|
||||
}
|
||||
|
||||
export function clearUserTyping() {
|
||||
return {
|
||||
type: USERS_TYPING.CLEAR
|
||||
};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { USERS_TYPING } from './actionsTypes';
|
||||
|
||||
export interface IUsersTypingGenericAction extends Action {
|
||||
username: string;
|
||||
}
|
||||
|
||||
export type TActionUserTyping = IUsersTypingGenericAction & Action;
|
||||
|
||||
export function addUserTyping(username: string): IUsersTypingGenericAction {
|
||||
return {
|
||||
type: USERS_TYPING.ADD,
|
||||
username
|
||||
};
|
||||
}
|
||||
|
||||
export function removeUserTyping(username: string): IUsersTypingGenericAction {
|
||||
return {
|
||||
type: USERS_TYPING.REMOVE,
|
||||
username
|
||||
};
|
||||
}
|
||||
|
||||
export function clearUserTyping(): Action {
|
||||
return {
|
||||
type: USERS_TYPING.CLEAR
|
||||
};
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import database from '../../lib/database';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import { TSubscriptionModel, TUserModel } from '../../definitions';
|
||||
import Avatar from './Avatar';
|
||||
import { IAvatar } from './interfaces';
|
||||
|
||||
class AvatarContainer extends React.Component<IAvatar, any> {
|
||||
private mounted: boolean;
|
||||
|
||||
private subscription: any;
|
||||
private subscription?: Subscription;
|
||||
|
||||
static defaultProps = {
|
||||
text: '',
|
||||
|
@ -59,15 +61,17 @@ class AvatarContainer extends React.Component<IAvatar, any> {
|
|||
record = user;
|
||||
} else {
|
||||
const { rid } = this.props;
|
||||
record = await subsCollection.find(rid);
|
||||
if (rid) {
|
||||
record = await subsCollection.find(rid);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Record not found
|
||||
}
|
||||
|
||||
if (record) {
|
||||
const observable = record.observe();
|
||||
this.subscription = observable.subscribe((r: any) => {
|
||||
const observable = record.observe() as Observable<TSubscriptionModel | TUserModel>;
|
||||
this.subscription = observable.subscribe(r => {
|
||||
const { avatarETag } = r;
|
||||
if (this.mounted) {
|
||||
this.setState({ avatarETag });
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots BackgroundContainer basic 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_light\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer black theme - loading 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_black\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"animating\\":true,\\"color\\":\\"#f9f9f9\\",\\"hidesWhenStopped\\":true,\\"size\\":\\"small\\",\\"style\\":{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"}},\\"children\\":null}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer black theme - text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_black\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#f9f9f9\\"}]},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer dark theme - loading 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_dark\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"animating\\":true,\\"color\\":\\"#f9f9f9\\",\\"hidesWhenStopped\\":true,\\"size\\":\\"small\\",\\"style\\":{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"}},\\"children\\":null}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer dark theme - text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_dark\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#f9f9f9\\"}]},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer loading 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_light\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"animating\\":true,\\"color\\":\\"#6C727A\\",\\"hidesWhenStopped\\":true,\\"size\\":\\"small\\",\\"style\\":{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"}},\\"children\\":null}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer long text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_light\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#6C727A\\"}]},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}"`;
|
||||
|
||||
exports[`Storyshots BackgroundContainer text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessibilityIgnoresInvertColors\\":true,\\"style\\":{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\",\\"position\\":\\"absolute\\"}},\\"children\\":[{\\"type\\":\\"Image\\",\\"props\\":{\\"source\\":{\\"uri\\":\\"message_empty_light\\"},\\"style\\":[{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},{\\"width\\":\\"100%\\",\\"height\\":\\"100%\\"},null]},\\"children\\":null}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"position\\":\\"absolute\\",\\"top\\":60,\\"left\\":0,\\"right\\":0,\\"fontSize\\":16,\\"paddingHorizontal\\":24,\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#6C727A\\"}]},\\"children\\":[\\"Text here\\"]}]}"`;
|
|
@ -35,7 +35,7 @@ const styles = StyleSheet.create({
|
|||
const BackgroundContainer = ({ theme, text, loading }: IBackgroundContainer) => (
|
||||
<View style={styles.container}>
|
||||
<ImageBackground source={{ uri: `message_empty_${theme}` }} style={styles.image} />
|
||||
{text ? <Text style={[styles.text, { color: themes[theme!].auxiliaryTintColor }]}>{text}</Text> : null}
|
||||
{text && !loading ? <Text style={[styles.text, { color: themes[theme!].auxiliaryTintColor }]}>{text}</Text> : null}
|
||||
{loading ? <ActivityIndicator style={styles.text} color={themes[theme!].auxiliaryTintColor} /> : null}
|
||||
</View>
|
||||
);
|
||||
|
|
|
@ -36,7 +36,7 @@ interface IEmojiPickerProps {
|
|||
}
|
||||
|
||||
interface IEmojiPickerState {
|
||||
frequentlyUsed: [];
|
||||
frequentlyUsed: (string | { content?: string; extension?: string; isCustom: boolean })[];
|
||||
customEmojis: any;
|
||||
show: boolean;
|
||||
width: number | null;
|
||||
|
@ -114,7 +114,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
|||
// Do nothing
|
||||
}
|
||||
|
||||
await db.action(async () => {
|
||||
await db.write(async () => {
|
||||
if (freqEmojiRecord) {
|
||||
await freqEmojiRecord.update((f: any) => {
|
||||
f.count += 1;
|
||||
|
@ -132,8 +132,8 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
|||
updateFrequentlyUsed = async () => {
|
||||
const db = database.active;
|
||||
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
|
||||
let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
|
||||
frequentlyUsed = frequentlyUsed.map((item: IEmoji) => {
|
||||
const frequentlyUsedOrdered = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
|
||||
const frequentlyUsed = frequentlyUsedOrdered.map(item => {
|
||||
if (item.isCustom) {
|
||||
return { content: item.content, extension: item.extension, isCustom: item.isCustom };
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import database from '../../lib/database';
|
|||
import { Button } from '../ActionSheet';
|
||||
import { useDimensions } from '../../dimensions';
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { TFrequentlyUsedEmojiModel } from '../../definitions/IFrequentlyUsedEmoji';
|
||||
import { IEmoji } from '../EmojiPicker/interfaces';
|
||||
|
||||
interface IHeader {
|
||||
|
@ -90,14 +91,14 @@ const HeaderFooter = React.memo(({ onReaction, theme }: THeaderFooter) => (
|
|||
));
|
||||
|
||||
const Header = React.memo(({ handleReaction, server, message, isMasterDetail, theme }: IHeader) => {
|
||||
const [items, setItems] = useState([]);
|
||||
const [items, setItems] = useState<(TFrequentlyUsedEmojiModel | string)[]>([]);
|
||||
const { width, height }: any = useDimensions();
|
||||
|
||||
const setEmojis = async () => {
|
||||
try {
|
||||
const db = database.active;
|
||||
const freqEmojiCollection = db.get('frequently_used_emojis');
|
||||
let freqEmojis = await freqEmojiCollection.query().fetch();
|
||||
let freqEmojis: (TFrequentlyUsedEmojiModel | string)[] = await freqEmojiCollection.query().fetch();
|
||||
|
||||
const isLandscape = width > height;
|
||||
const size = (isLandscape || isMasterDetail ? width / 2 : width) - CONTAINER_MARGIN * 2;
|
||||
|
|
|
@ -15,6 +15,7 @@ import { showConfirmationAlert } from '../../utils/info';
|
|||
import { useActionSheet } from '../ActionSheet';
|
||||
import Header, { HEADER_HEIGHT } from './Header';
|
||||
import events from '../../utils/log/events';
|
||||
import { TMessageModel } from '../../definitions/IMessage';
|
||||
|
||||
interface IMessageActions {
|
||||
room: {
|
||||
|
@ -182,9 +183,9 @@ const MessageActions = React.memo(
|
|||
if (result.success) {
|
||||
const subCollection = db.get('subscriptions');
|
||||
const subRecord = await subCollection.find(rid);
|
||||
await db.action(async () => {
|
||||
await db.write(async () => {
|
||||
try {
|
||||
await subRecord.update((sub: any) => (sub.lastOpen = ts));
|
||||
await subRecord.update(sub => (sub.lastOpen = ts));
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -269,11 +270,11 @@ const MessageActions = React.memo(
|
|||
}
|
||||
};
|
||||
|
||||
const handleToggleTranslation = async (message: any) => {
|
||||
const handleToggleTranslation = async (message: TMessageModel) => {
|
||||
try {
|
||||
const db = database.active;
|
||||
await db.action(async () => {
|
||||
await message.update((m: any) => {
|
||||
await db.write(async () => {
|
||||
await message.update(m => {
|
||||
m.autoTranslate = !m.autoTranslate;
|
||||
m._updatedAt = new Date();
|
||||
});
|
||||
|
@ -320,7 +321,7 @@ const MessageActions = React.memo(
|
|||
});
|
||||
};
|
||||
|
||||
const getOptions = (message: any) => {
|
||||
const getOptions = (message: TMessageModel) => {
|
||||
let options: any = [];
|
||||
|
||||
// Reply
|
||||
|
@ -446,7 +447,7 @@ const MessageActions = React.memo(
|
|||
return options;
|
||||
};
|
||||
|
||||
const showMessageActions = async (message: any) => {
|
||||
const showMessageActions = async (message: TMessageModel) => {
|
||||
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
|
||||
await getPermissions();
|
||||
showActionSheet({
|
||||
|
|
|
@ -36,7 +36,7 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
|||
try {
|
||||
// Find the thread header and update it
|
||||
const msg = await msgCollection.find(tmid);
|
||||
if (msg.tcount <= 1) {
|
||||
if (msg?.tcount && msg.tcount <= 1) {
|
||||
deleteBatch.push(
|
||||
msg.prepareUpdate((m: any) => {
|
||||
m.tcount = null;
|
||||
|
@ -62,7 +62,7 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
|||
// Do nothing: message not found
|
||||
}
|
||||
}
|
||||
await db.action(async () => {
|
||||
await db.write(async () => {
|
||||
await db.batch(...deleteBatch);
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,11 @@
|
|||
import { dequal } from 'dequal';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { dequal } from 'dequal';
|
||||
|
||||
import RoomHeader from './RoomHeader';
|
||||
import { IApplicationState } from '../../definitions';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
import I18n from '../../i18n';
|
||||
import RoomHeader from './RoomHeader';
|
||||
|
||||
interface IRoomHeaderContainerProps {
|
||||
title: string;
|
||||
|
@ -122,8 +123,8 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: any, ownProps: any) => {
|
||||
let statusText;
|
||||
const mapStateToProps = (state: IApplicationState, ownProps: any) => {
|
||||
let statusText = '';
|
||||
let status = 'offline';
|
||||
const { roomUserId, type, visitor = {}, tmid } = ownProps;
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
import { withTheme } from '../theme';
|
||||
import I18n from '../i18n';
|
||||
import { useTheme } from '../theme';
|
||||
import sharedStyles from '../views/Styles';
|
||||
import { themes } from '../constants/colors';
|
||||
import TextInput from '../presentation/TextInput';
|
||||
|
@ -19,14 +20,13 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface ISearchHeader {
|
||||
theme?: string;
|
||||
interface ISearchHeaderProps {
|
||||
onSearchChangeText?: (text: string) => void;
|
||||
testID: string;
|
||||
}
|
||||
|
||||
// TODO: it might be useful to refactor this component for reusage
|
||||
const SearchHeader = ({ theme, onSearchChangeText }: ISearchHeader) => {
|
||||
const titleColorStyle = { color: themes[theme!].headerTitleColor };
|
||||
const SearchHeader = ({ onSearchChangeText, testID }: ISearchHeaderProps): JSX.Element => {
|
||||
const { theme } = useTheme();
|
||||
const isLight = theme === 'light';
|
||||
const { isLandscape } = useOrientation();
|
||||
const scale = isIOS && isLandscape && !isTablet ? 0.8 : 1;
|
||||
|
@ -36,14 +36,14 @@ const SearchHeader = ({ theme, onSearchChangeText }: ISearchHeader) => {
|
|||
<View style={styles.container}>
|
||||
<TextInput
|
||||
autoFocus
|
||||
style={[styles.title, isLight && titleColorStyle, { fontSize: titleFontSize }]}
|
||||
placeholder='Search'
|
||||
style={[styles.title, isLight && { color: themes[theme].headerTitleColor }, { fontSize: titleFontSize }]}
|
||||
placeholder={I18n.t('Search')}
|
||||
onChangeText={onSearchChangeText}
|
||||
theme={theme!}
|
||||
testID='thread-messages-view-search-header'
|
||||
theme={theme}
|
||||
testID={testID}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTheme(SearchHeader);
|
||||
export default SearchHeader;
|
||||
|
|
|
@ -5,7 +5,7 @@ import Touchable from 'react-native-platform-touchable';
|
|||
import { CustomIcon } from '../lib/Icons';
|
||||
import { themes } from '../constants/colors';
|
||||
import sharedStyles from '../views/Styles';
|
||||
import { withTheme } from '../theme';
|
||||
import { useTheme } from '../theme';
|
||||
import { TThreadModel } from '../definitions/IThread';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -48,12 +48,12 @@ interface IThreadDetails {
|
|||
badgeColor?: string;
|
||||
toggleFollowThread: Function;
|
||||
style: ViewStyle;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, theme }: IThreadDetails) => {
|
||||
const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style }: IThreadDetails): JSX.Element => {
|
||||
const { theme } = useTheme();
|
||||
let { tcount } = item;
|
||||
if (tcount! >= 1000) {
|
||||
if (tcount && tcount >= 1000) {
|
||||
tcount = '+999';
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,6 @@ const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, them
|
|||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.badgeContainer}>
|
||||
{badgeColor ? <View style={[styles.badge, { backgroundColor: badgeColor }]} /> : null}
|
||||
<Touchable onPress={() => toggleFollowThread?.(isFollowing, item.id)}>
|
||||
|
@ -96,4 +95,4 @@ const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, them
|
|||
);
|
||||
};
|
||||
|
||||
export default withTheme(ThreadDetails);
|
||||
export default ThreadDetails;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Text Input Short and Long Text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"paddingHorizontal\\":14}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"marginBottom\\":10},null]},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"marginBottom\\":10,\\"fontSize\\":14,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"color\\":\\"#0d0e12\\"},null]},\\"children\\":[\\"Short Text\\"]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"position\\":\\"relative\\"}},\\"children\\":[{\\"type\\":\\"TextInput\\",\\"props\\":{\\"allowFontScaling\\":true,\\"rejectResponderTermination\\":true,\\"underlineColorAndroid\\":\\"transparent\\",\\"style\\":[{\\"color\\":\\"#0d0e12\\"},[{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\",\\"height\\":48,\\"fontSize\\":16,\\"padding\\":14,\\"borderWidth\\":0.5,\\"borderRadius\\":2},null,null,{\\"backgroundColor\\":\\"#ffffff\\",\\"borderColor\\":\\"#cbcbcc\\",\\"color\\":\\"#0d0e12\\"},null,null],{\\"textAlign\\":\\"auto\\"}],\\"placeholderTextColor\\":\\"#9ca2a8\\",\\"keyboardAppearance\\":\\"light\\",\\"autoCorrect\\":false,\\"autoCapitalize\\":\\"none\\",\\"accessibilityLabel\\":\\"placeholder\\",\\"placeholder\\":\\"placeholder\\",\\"value\\":\\"Rocket.Chat\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"marginBottom\\":10},null]},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"marginBottom\\":10,\\"fontSize\\":14,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"color\\":\\"#0d0e12\\"},null]},\\"children\\":[\\"Long Text\\"]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"position\\":\\"relative\\"}},\\"children\\":[{\\"type\\":\\"TextInput\\",\\"props\\":{\\"allowFontScaling\\":true,\\"rejectResponderTermination\\":true,\\"underlineColorAndroid\\":\\"transparent\\",\\"style\\":[{\\"color\\":\\"#0d0e12\\"},[{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\",\\"height\\":48,\\"fontSize\\":16,\\"padding\\":14,\\"borderWidth\\":0.5,\\"borderRadius\\":2},null,null,{\\"backgroundColor\\":\\"#ffffff\\",\\"borderColor\\":\\"#cbcbcc\\",\\"color\\":\\"#0d0e12\\"},null,null],{\\"textAlign\\":\\"auto\\"}],\\"placeholderTextColor\\":\\"#9ca2a8\\",\\"keyboardAppearance\\":\\"light\\",\\"autoCorrect\\":false,\\"autoCapitalize\\":\\"none\\",\\"accessibilityLabel\\":\\"placeholder\\",\\"placeholder\\":\\"placeholder\\",\\"value\\":\\"https://open.rocket.chat/images/logo/android-chrome-512x512.png\\"},\\"children\\":null}]}]}]}"`;
|
|
@ -25,7 +25,7 @@ import { isValidURL } from '../../utils/url';
|
|||
import NewMarkdown from './new';
|
||||
|
||||
interface IMarkdownProps {
|
||||
msg: string;
|
||||
msg?: string;
|
||||
md: MarkdownAST;
|
||||
mentions: UserMention[];
|
||||
getCustomEmoji: Function;
|
||||
|
|
|
@ -182,7 +182,7 @@ const Fields = React.memo(
|
|||
<Text style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>{field.title}</Text>
|
||||
{/* @ts-ignore*/}
|
||||
<Markdown
|
||||
msg={field.value!}
|
||||
msg={field?.value || ''}
|
||||
baseUrl={baseUrl}
|
||||
username={user.username}
|
||||
getCustomEmoji={getCustomEmoji}
|
||||
|
|
|
@ -24,7 +24,6 @@ const Thread = React.memo(
|
|||
item={{
|
||||
tcount,
|
||||
replies,
|
||||
tlm,
|
||||
id
|
||||
}}
|
||||
user={user}
|
||||
|
|
|
@ -147,6 +147,12 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
if ((item.tlm || item.tmid) && !isThreadRoom) {
|
||||
this.onThreadPress();
|
||||
}
|
||||
|
||||
const { onDiscussionPress } = this.props;
|
||||
|
||||
if (onDiscussionPress) {
|
||||
onDiscussionPress(item);
|
||||
}
|
||||
},
|
||||
300,
|
||||
true
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||
|
||||
export type TMessageType = 'discussion-created' | 'jitsi_call_started';
|
||||
|
||||
export interface IMessageAttachments {
|
||||
attachments: any;
|
||||
timeFormat: string;
|
||||
|
@ -101,7 +103,7 @@ export interface IMessageThread {
|
|||
msg: string;
|
||||
tcount: number;
|
||||
theme: string;
|
||||
tlm: string;
|
||||
tlm: Date;
|
||||
isThreadRoom: boolean;
|
||||
id: string;
|
||||
}
|
||||
|
@ -140,7 +142,7 @@ export interface IMessageInner
|
|||
IMessageThread,
|
||||
IMessageAttachments,
|
||||
IMessageBroadcast {
|
||||
type: string;
|
||||
type: TMessageType;
|
||||
blocks: [];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { TMessageModel } from '../../definitions/IMessage';
|
||||
import I18n from '../../i18n';
|
||||
import { DISCUSSION } from './constants';
|
||||
|
||||
|
@ -149,7 +150,7 @@ export const getInfoMessage = ({ type, role, msg, author }: TInfoMessage) => {
|
|||
return '';
|
||||
};
|
||||
|
||||
export const getMessageTranslation = (message: { translations: any }, autoTranslateLanguage: string) => {
|
||||
export const getMessageTranslation = (message: TMessageModel, autoTranslateLanguage: string) => {
|
||||
if (!autoTranslateLanguage) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ export interface IFrequentlyUsedEmoji {
|
|||
count: number;
|
||||
}
|
||||
|
||||
export type TFrequentlyUsedEmoji = IFrequentlyUsedEmoji & Model;
|
||||
export type TFrequentlyUsedEmojiModel = IFrequentlyUsedEmoji & Model;
|
||||
|
|
|
@ -15,4 +15,4 @@ export interface ILoggedUser {
|
|||
enableMessageParserEarlyAdoption?: boolean;
|
||||
}
|
||||
|
||||
export type TLoggedUser = ILoggedUser & Model;
|
||||
export type TLoggedUserModel = ILoggedUser & Model;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import { SortBy, DisplayMode } from '../constants/constantDisplayMode';
|
||||
|
||||
export interface IPreferences {
|
||||
sortBy: SortBy;
|
||||
groupByType: boolean;
|
||||
showFavorites: boolean;
|
||||
showUnread: boolean;
|
||||
showAvatar: boolean;
|
||||
displayMode: DisplayMode;
|
||||
}
|
|
@ -7,4 +7,4 @@ export interface IServerHistory {
|
|||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export type TServerHistory = IServerHistory & Model;
|
||||
export type TServerHistoryModel = IServerHistory & Model;
|
||||
|
|
|
@ -79,8 +79,6 @@ export interface ISubscription {
|
|||
avatarETag?: string;
|
||||
teamId?: string;
|
||||
teamMain?: boolean;
|
||||
search?: boolean;
|
||||
username?: string;
|
||||
// https://nozbe.github.io/WatermelonDB/Relation.html#relation-api
|
||||
messages: Relation<TMessageModel>;
|
||||
threads: Relation<TThreadModel>;
|
||||
|
|
|
@ -43,7 +43,7 @@ export interface IThread {
|
|||
id: string;
|
||||
msg?: string;
|
||||
t?: SubscriptionType;
|
||||
rid?: string;
|
||||
rid: string;
|
||||
_updatedAt?: Date;
|
||||
ts?: Date;
|
||||
u?: IUserMessage;
|
||||
|
@ -61,10 +61,10 @@ export interface IThread {
|
|||
reactions?: IReaction[];
|
||||
role?: string;
|
||||
drid?: string;
|
||||
dcount?: number;
|
||||
dcount?: number | string;
|
||||
dlm?: number;
|
||||
tmid?: string;
|
||||
tcount: number | string;
|
||||
tcount?: number | string;
|
||||
tlm?: string;
|
||||
replies?: string[];
|
||||
mentions?: IUserMention[];
|
||||
|
|
|
@ -3,11 +3,24 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
|||
import { Dispatch } from 'redux';
|
||||
|
||||
export * from './IAttachment';
|
||||
export * from './IMessage';
|
||||
export * from './INotification';
|
||||
export * from './IRoom';
|
||||
export * from './IServer';
|
||||
export * from './IPreferences';
|
||||
export * from './ISubscription';
|
||||
export * from './IRoom';
|
||||
export * from './IMessage';
|
||||
export * from './IThread';
|
||||
export * from './IThreadMessage';
|
||||
export * from './ICustomEmoji';
|
||||
export * from './IFrequentlyUsedEmoji';
|
||||
export * from './IUpload';
|
||||
export * from './ISettings';
|
||||
export * from './IRole';
|
||||
export * from './IPermission';
|
||||
export * from './ISlashCommand';
|
||||
export * from './IUser';
|
||||
export * from './IServer';
|
||||
export * from './ILoggedUser';
|
||||
export * from './IServerHistory';
|
||||
|
||||
export interface IBaseScreen<T extends Record<string, object | undefined>, S extends string> {
|
||||
navigation: StackNavigationProp<T, S>;
|
||||
|
@ -17,3 +30,4 @@ export interface IBaseScreen<T extends Record<string, object | undefined>, S ext
|
|||
}
|
||||
|
||||
export * from './redux';
|
||||
export * from './redux/TRootEnum';
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export enum RootEnum {
|
||||
ROOT_OUTSIDE = 'outside',
|
||||
ROOT_INSIDE = 'inside',
|
||||
ROOT_LOADING = 'loading',
|
||||
ROOT_SET_USERNAME = 'setUsername'
|
||||
}
|
|
@ -1,31 +1,67 @@
|
|||
import { TActionSelectedUsers } from '../../actions/selectedUsers';
|
||||
// ACTIONS
|
||||
import { TActionActiveUsers } from '../../actions/activeUsers';
|
||||
import { TActionApp } from '../../actions/app';
|
||||
import { TActionCreateChannel } from '../../actions/createChannel';
|
||||
import { TActionCreateDiscussion } from '../../actions/createDiscussion';
|
||||
import { TActionCustomEmojis } from '../../actions/customEmojis';
|
||||
import { TActionEncryption } from '../../actions/encryption';
|
||||
import { TActionInviteLinks } from '../../actions/inviteLinks';
|
||||
import { IActionRoles } from '../../actions/roles';
|
||||
import { TActionSelectedUsers } from '../../actions/selectedUsers';
|
||||
import { TActionServer } from '../../actions/server';
|
||||
import { IActionSettings } from '../../actions/settings';
|
||||
import { TActionsShare } from '../../actions/share';
|
||||
import { TActionSortPreferences } from '../../actions/sortPreferences';
|
||||
import { TActionUserTyping } from '../../actions/usersTyping';
|
||||
// REDUCERS
|
||||
import { IActiveUsers } from '../../reducers/activeUsers';
|
||||
import { IApp } from '../../reducers/app';
|
||||
import { IConnect } from '../../reducers/connect';
|
||||
import { ICreateChannel } from '../../reducers/createChannel';
|
||||
import { ICreateDiscussion } from '../../reducers/createDiscussion';
|
||||
import { IEncryption } from '../../reducers/encryption';
|
||||
import { IInviteLinks } from '../../reducers/inviteLinks';
|
||||
import { IRoles } from '../../reducers/roles';
|
||||
import { ISelectedUsers } from '../../reducers/selectedUsers';
|
||||
import { IServer } from '../../reducers/server';
|
||||
import { ISettings } from '../../reducers/settings';
|
||||
import { IShare } from '../../reducers/share';
|
||||
|
||||
export interface IApplicationState {
|
||||
settings: any;
|
||||
settings: ISettings;
|
||||
login: any;
|
||||
meteor: any;
|
||||
server: any;
|
||||
meteor: IConnect;
|
||||
server: IServer;
|
||||
selectedUsers: ISelectedUsers;
|
||||
createChannel: any;
|
||||
app: any;
|
||||
app: IApp;
|
||||
createChannel: ICreateChannel;
|
||||
room: any;
|
||||
rooms: any;
|
||||
sortPreferences: any;
|
||||
share: any;
|
||||
share: IShare;
|
||||
customEmojis: any;
|
||||
activeUsers: IActiveUsers;
|
||||
usersTyping: any;
|
||||
inviteLinks: any;
|
||||
createDiscussion: any;
|
||||
inviteLinks: IInviteLinks;
|
||||
createDiscussion: ICreateDiscussion;
|
||||
inquiry: any;
|
||||
enterpriseModules: any;
|
||||
encryption: any;
|
||||
encryption: IEncryption;
|
||||
permissions: any;
|
||||
roles: any;
|
||||
roles: IRoles;
|
||||
}
|
||||
|
||||
export type TApplicationActions = TActionActiveUsers & TActionSelectedUsers;
|
||||
export type TApplicationActions = TActionActiveUsers &
|
||||
TActionSelectedUsers &
|
||||
TActionCustomEmojis &
|
||||
TActionInviteLinks &
|
||||
IActionRoles &
|
||||
IActionSettings &
|
||||
TActionEncryption &
|
||||
TActionSortPreferences &
|
||||
TActionUserTyping &
|
||||
TActionCreateDiscussion&
|
||||
TActionCreateChannel &
|
||||
TActionsShare &
|
||||
TActionServer &
|
||||
TActionApp;
|
||||
|
|
|
@ -775,6 +775,7 @@
|
|||
"creating_discussion": "creating discussion",
|
||||
"Canned_Responses": "Canned Responses",
|
||||
"No_match_found": "No match found.",
|
||||
"No_discussions": "No discussions",
|
||||
"Check_canned_responses": "Check on canned responses.",
|
||||
"Searching": "Searching",
|
||||
"Use": "Use",
|
||||
|
|
|
@ -25,6 +25,7 @@ import serversSchema from './schema/servers';
|
|||
import appSchema from './schema/app';
|
||||
import migrations from './model/migrations';
|
||||
import serversMigrations from './model/servers/migrations';
|
||||
import { TAppDatabase, TServerDatabase } from './interfaces';
|
||||
|
||||
const appGroupPath = isIOS ? appGroup.path : '';
|
||||
|
||||
|
@ -32,9 +33,9 @@ if (__DEV__ && isIOS) {
|
|||
console.log(appGroupPath);
|
||||
}
|
||||
|
||||
const getDatabasePath = name => `${appGroupPath}${name}${isOfficial ? '' : '-experimental'}.db`;
|
||||
const getDatabasePath = (name: string) => `${appGroupPath}${name}${isOfficial ? '' : '-experimental'}.db`;
|
||||
|
||||
export const getDatabase = (database = '') => {
|
||||
export const getDatabase = (database = ''): Database => {
|
||||
const path = database.replace(/(^\w+:|^)\/\//, '').replace(/\//g, '.');
|
||||
const dbName = getDatabasePath(path);
|
||||
|
||||
|
@ -64,8 +65,14 @@ export const getDatabase = (database = '') => {
|
|||
});
|
||||
};
|
||||
|
||||
interface IDatabases {
|
||||
shareDB?: TAppDatabase;
|
||||
serversDB: TServerDatabase;
|
||||
activeDB?: TAppDatabase;
|
||||
}
|
||||
|
||||
class DB {
|
||||
databases = {
|
||||
databases: IDatabases = {
|
||||
serversDB: new Database({
|
||||
adapter: new SQLiteAdapter({
|
||||
dbName: getDatabasePath('default'),
|
||||
|
@ -73,11 +80,12 @@ class DB {
|
|||
migrations: serversMigrations
|
||||
}),
|
||||
modelClasses: [Server, LoggedUser, ServersHistory]
|
||||
})
|
||||
}) as TServerDatabase
|
||||
};
|
||||
|
||||
get active() {
|
||||
return this.databases.shareDB || this.databases.activeDB;
|
||||
// Expected at least one database
|
||||
get active(): TAppDatabase {
|
||||
return this.databases.shareDB || this.databases.activeDB!;
|
||||
}
|
||||
|
||||
get share() {
|
||||
|
@ -116,11 +124,11 @@ class DB {
|
|||
Setting,
|
||||
User
|
||||
]
|
||||
});
|
||||
}) as TAppDatabase;
|
||||
}
|
||||
|
||||
setActiveDB(database) {
|
||||
this.databases.activeDB = getDatabase(database);
|
||||
setActiveDB(database: string) {
|
||||
this.databases.activeDB = getDatabase(database) as TAppDatabase;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import { Database, Collection } from '@nozbe/watermelondb';
|
||||
|
||||
import * as models from './model';
|
||||
import * as definitions from '../../definitions';
|
||||
|
||||
export type TAppDatabaseNames =
|
||||
| typeof models.SUBSCRIPTIONS_TABLE
|
||||
| typeof models.ROOMS_TABLE
|
||||
| typeof models.MESSAGES_TABLE
|
||||
| typeof models.THREADS_TABLE
|
||||
| typeof models.THREAD_MESSAGES_TABLE
|
||||
| typeof models.CUSTOM_EMOJIS_TABLE
|
||||
| typeof models.FREQUENTLY_USED_EMOJIS_TABLE
|
||||
| typeof models.UPLOADS_TABLE
|
||||
| typeof models.SETTINGS_TABLE
|
||||
| typeof models.ROLES_TABLE
|
||||
| typeof models.PERMISSIONS_TABLE
|
||||
| typeof models.SLASH_COMMANDS_TABLE
|
||||
| typeof models.USERS_TABLE;
|
||||
|
||||
// Verify if T extends one type from TAppDatabaseNames, and if is truly,
|
||||
// returns the specific model type.
|
||||
// https://stackoverflow.com/a/54166010 TypeScript function return type based on input parameter
|
||||
type ObjectType<T> = T extends typeof models.SUBSCRIPTIONS_TABLE
|
||||
? definitions.TSubscriptionModel
|
||||
: T extends typeof models.ROOMS_TABLE
|
||||
? definitions.TRoomModel
|
||||
: T extends typeof models.MESSAGES_TABLE
|
||||
? definitions.TMessageModel
|
||||
: T extends typeof models.THREADS_TABLE
|
||||
? definitions.TThreadModel
|
||||
: T extends typeof models.THREAD_MESSAGES_TABLE
|
||||
? definitions.TThreadMessageModel
|
||||
: T extends typeof models.CUSTOM_EMOJIS_TABLE
|
||||
? definitions.TCustomEmojiModel
|
||||
: T extends typeof models.FREQUENTLY_USED_EMOJIS_TABLE
|
||||
? definitions.TFrequentlyUsedEmojiModel
|
||||
: T extends typeof models.UPLOADS_TABLE
|
||||
? definitions.TUploadModel
|
||||
: T extends typeof models.SETTINGS_TABLE
|
||||
? definitions.TSettingsModel
|
||||
: T extends typeof models.ROLES_TABLE
|
||||
? definitions.TRoleModel
|
||||
: T extends typeof models.PERMISSIONS_TABLE
|
||||
? definitions.TPermissionModel
|
||||
: T extends typeof models.SLASH_COMMANDS_TABLE
|
||||
? definitions.TSlashCommandModel
|
||||
: T extends typeof models.USERS_TABLE
|
||||
? definitions.TUserModel
|
||||
: never;
|
||||
|
||||
export type TAppDatabase = {
|
||||
get: <T extends TAppDatabaseNames>(db: T) => Collection<ObjectType<T>>;
|
||||
} & Database;
|
||||
|
||||
// Migration to server database
|
||||
export type TServerDatabaseNames =
|
||||
| typeof models.SERVERS_TABLE
|
||||
| typeof models.LOGGED_USERS_TABLE
|
||||
| typeof models.SERVERS_HISTORY_TABLE;
|
||||
|
||||
type ObjectServerType<T> = T extends typeof models.SERVERS_TABLE
|
||||
? definitions.TServerModel
|
||||
: T extends typeof models.LOGGED_USERS_TABLE
|
||||
? definitions.TLoggedUserModel
|
||||
: T extends typeof models.SERVERS_HISTORY_TABLE
|
||||
? definitions.TServerHistoryModel
|
||||
: never;
|
||||
|
||||
export type TServerDatabase = {
|
||||
get: <T extends TServerDatabaseNames>(db: T) => Collection<ObjectServerType<T>>;
|
||||
} & Database;
|
|
@ -3,8 +3,10 @@ import { date, field, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const CUSTOM_EMOJIS_TABLE = 'custom_emojis';
|
||||
|
||||
export default class CustomEmoji extends Model {
|
||||
static table = 'custom_emojis';
|
||||
static table = CUSTOM_EMOJIS_TABLE;
|
||||
|
||||
@field('name') name;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { Model } from '@nozbe/watermelondb';
|
||||
import { field } from '@nozbe/watermelondb/decorators';
|
||||
|
||||
export const FREQUENTLY_USED_EMOJIS_TABLE = 'frequently_used_emojis';
|
||||
export default class FrequentlyUsedEmoji extends Model {
|
||||
static table = 'frequently_used_emojis';
|
||||
static table = FREQUENTLY_USED_EMOJIS_TABLE;
|
||||
|
||||
@field('content') content;
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ import { date, field, json, relation } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const TABLE_NAME = 'messages';
|
||||
export const MESSAGES_TABLE = 'messages';
|
||||
|
||||
export default class Message extends Model {
|
||||
static table = TABLE_NAME;
|
||||
static table = MESSAGES_TABLE;
|
||||
|
||||
static associations = {
|
||||
subscriptions: { type: 'belongs_to', key: 'rid' }
|
||||
|
|
|
@ -3,8 +3,10 @@ import { date, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const PERMISSIONS_TABLE = 'permissions';
|
||||
|
||||
export default class Permission extends Model {
|
||||
static table = 'permissions';
|
||||
static table = PERMISSIONS_TABLE;
|
||||
|
||||
@json('roles', sanitizer) roles;
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { Model } from '@nozbe/watermelondb';
|
||||
import { field } from '@nozbe/watermelondb/decorators';
|
||||
|
||||
export const ROLES_TABLE = 'roles';
|
||||
|
||||
export default class Role extends Model {
|
||||
static table = 'roles';
|
||||
static table = ROLES_TABLE;
|
||||
|
||||
@field('description') description;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ import { field, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const ROOMS_TABLE = 'rooms';
|
||||
|
||||
export default class Room extends Model {
|
||||
static table = 'rooms';
|
||||
static table = ROOMS_TABLE;
|
||||
|
||||
@json('custom_fields', sanitizer) customFields;
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { Model } from '@nozbe/watermelondb';
|
||||
import { date, field, readonly } from '@nozbe/watermelondb/decorators';
|
||||
|
||||
export const SERVERS_HISTORY_TABLE = 'servers_history';
|
||||
|
||||
export default class ServersHistory extends Model {
|
||||
static table = 'servers_history';
|
||||
static table = SERVERS_HISTORY_TABLE;
|
||||
|
||||
@field('url') url;
|
||||
|
||||
|
|
|
@ -3,8 +3,10 @@ import { date, field, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const SETTINGS_TABLE = 'settings';
|
||||
|
||||
export default class Setting extends Model {
|
||||
static table = 'settings';
|
||||
static table = SETTINGS_TABLE;
|
||||
|
||||
@field('value_as_string') valueAsString;
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { Model } from '@nozbe/watermelondb';
|
||||
import { field } from '@nozbe/watermelondb/decorators';
|
||||
|
||||
export const SLASH_COMMANDS_TABLE = 'slash_commands';
|
||||
|
||||
export default class SlashCommand extends Model {
|
||||
static table = 'slash_commands';
|
||||
static table = SLASH_COMMANDS_TABLE;
|
||||
|
||||
@field('params') params;
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ import { children, date, field, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const TABLE_NAME = 'subscriptions';
|
||||
export const SUBSCRIPTIONS_TABLE = 'subscriptions';
|
||||
|
||||
export default class Subscription extends Model {
|
||||
static table = TABLE_NAME;
|
||||
static table = SUBSCRIPTIONS_TABLE;
|
||||
|
||||
static associations = {
|
||||
messages: { type: 'has_many', foreignKey: 'rid' },
|
||||
|
|
|
@ -3,10 +3,10 @@ import { date, field, json, relation } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const TABLE_NAME = 'threads';
|
||||
export const THREADS_TABLE = 'threads';
|
||||
|
||||
export default class Thread extends Model {
|
||||
static table = TABLE_NAME;
|
||||
static table = THREADS_TABLE;
|
||||
|
||||
static associations = {
|
||||
subscriptions: { type: 'belongs_to', key: 'rid' }
|
||||
|
|
|
@ -3,10 +3,10 @@ import { date, field, json, relation } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const TABLE_NAME = 'thread_messages';
|
||||
export const THREAD_MESSAGES_TABLE = 'thread_messages';
|
||||
|
||||
export default class ThreadMessage extends Model {
|
||||
static table = TABLE_NAME;
|
||||
static table = THREAD_MESSAGES_TABLE;
|
||||
|
||||
static associations = {
|
||||
subscriptions: { type: 'belongs_to', key: 'subscription_id' }
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { Model } from '@nozbe/watermelondb';
|
||||
import { field, relation } from '@nozbe/watermelondb/decorators';
|
||||
|
||||
export const UPLOADS_TABLE = 'uploads';
|
||||
|
||||
export default class Upload extends Model {
|
||||
static table = 'uploads';
|
||||
static table = UPLOADS_TABLE;
|
||||
|
||||
static associations = {
|
||||
subscriptions: { type: 'belongs_to', key: 'rid' }
|
||||
|
|
|
@ -3,8 +3,10 @@ import { field, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../utils';
|
||||
|
||||
export const USERS_TABLE = 'users';
|
||||
|
||||
export default class User extends Model {
|
||||
static table = 'users';
|
||||
static table = USERS_TABLE;
|
||||
|
||||
@field('_id') _id;
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
export * from './CustomEmoji';
|
||||
export * from './FrequentlyUsedEmoji';
|
||||
export * from './Message';
|
||||
export * from './Permission';
|
||||
export * from './Role';
|
||||
export * from './Room';
|
||||
export * from './Setting';
|
||||
export * from './SlashCommand';
|
||||
export * from './Subscription';
|
||||
export * from './Thread';
|
||||
export * from './ThreadMessage';
|
||||
export * from './Upload';
|
||||
export * from './User';
|
||||
export * from './ServersHistory';
|
||||
export * from './servers/Server';
|
||||
export * from './servers/User';
|
|
@ -1,8 +1,10 @@
|
|||
import { Model } from '@nozbe/watermelondb';
|
||||
import { date, field } from '@nozbe/watermelondb/decorators';
|
||||
|
||||
export const SERVERS_TABLE = 'servers';
|
||||
|
||||
export default class Server extends Model {
|
||||
static table = 'servers';
|
||||
static table = SERVERS_TABLE;
|
||||
|
||||
@field('name') name;
|
||||
|
||||
|
|
|
@ -3,8 +3,10 @@ import { field, json } from '@nozbe/watermelondb/decorators';
|
|||
|
||||
import { sanitizer } from '../../utils';
|
||||
|
||||
export const LOGGED_USERS_TABLE = 'users';
|
||||
|
||||
export default class User extends Model {
|
||||
static table = 'users';
|
||||
static table = LOGGED_USERS_TABLE;
|
||||
|
||||
@field('token') token;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import database from '..';
|
||||
import { TABLE_NAME } from '../model/Message';
|
||||
import { MESSAGES_TABLE } from '../model/Message';
|
||||
|
||||
const getCollection = db => db.get(TABLE_NAME);
|
||||
const getCollection = db => db.get(MESSAGES_TABLE);
|
||||
|
||||
export const getMessageById = async messageId => {
|
||||
const db = database.active;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import database from '..';
|
||||
import { TABLE_NAME } from '../model/Subscription';
|
||||
import { SUBSCRIPTIONS_TABLE } from '../model/Subscription';
|
||||
|
||||
const getCollection = db => db.get(TABLE_NAME);
|
||||
const getCollection = db => db.get(SUBSCRIPTIONS_TABLE);
|
||||
|
||||
export const getSubscriptionByRoomId = async rid => {
|
||||
const db = database.active;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import database from '..';
|
||||
import { TABLE_NAME } from '../model/Thread';
|
||||
import { THREADS_TABLE } from '../model/Thread';
|
||||
|
||||
const getCollection = db => db.get(TABLE_NAME);
|
||||
const getCollection = db => db.get(THREADS_TABLE);
|
||||
|
||||
export const getThreadById = async tmid => {
|
||||
const db = database.active;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import database from '..';
|
||||
import { TABLE_NAME } from '../model/ThreadMessage';
|
||||
import { THREAD_MESSAGES_TABLE } from '../model/ThreadMessage';
|
||||
|
||||
const getCollection = db => db.get(TABLE_NAME);
|
||||
const getCollection = db => db.get(THREAD_MESSAGES_TABLE);
|
||||
|
||||
export const getThreadMessageById = async messageId => {
|
||||
const db = database.active;
|
||||
|
|
|
@ -61,7 +61,7 @@ const PERMISSIONS = [
|
|||
|
||||
export async function setPermissions() {
|
||||
const db = database.active;
|
||||
const permissionsCollection = db.collections.get('permissions');
|
||||
const permissionsCollection = db.get('permissions');
|
||||
const allPermissions = await permissionsCollection.query(Q.where('id', Q.oneOf(PERMISSIONS))).fetch();
|
||||
const parsed = allPermissions.reduce((acc, item) => ({ ...acc, [item.id]: item.roles }), {});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import protectedFunction from './helpers/protectedFunction';
|
|||
|
||||
export async function setRoles() {
|
||||
const db = database.active;
|
||||
const rolesCollection = db.collections.get('roles');
|
||||
const rolesCollection = db.get('roles');
|
||||
const allRoles = await rolesCollection.query().fetch();
|
||||
const parsed = allRoles.reduce((acc, item) => ({ ...acc, [item.id]: item.description || item.id }), {});
|
||||
reduxStore.dispatch(setRolesAction(parsed));
|
||||
|
|
|
@ -811,6 +811,16 @@ const RocketChat = {
|
|||
encrypted
|
||||
});
|
||||
},
|
||||
getDiscussions({ roomId, offset, count, text }) {
|
||||
const params = {
|
||||
roomId,
|
||||
offset,
|
||||
count,
|
||||
...(text && { text })
|
||||
};
|
||||
// RC 2.4.0
|
||||
return this.sdk.get('chat.getDiscussions', params);
|
||||
},
|
||||
createTeam({ name, users, type, readOnly, broadcast, encrypted }) {
|
||||
const params = {
|
||||
name,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { SET_ACTIVE_USERS } from '../actions/actionsTypes';
|
|||
type TUserStatus = 'online' | 'offline';
|
||||
export interface IActiveUser {
|
||||
status: TUserStatus;
|
||||
statusText?: string;
|
||||
statusText: string;
|
||||
}
|
||||
|
||||
export interface IActiveUsers {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { appStart, appInit, setMasterDetail } from '../actions/app';
|
||||
import { initialState } from './app';
|
||||
import { mockedStore } from './mockedStore';
|
||||
import { RootEnum } from '../definitions';
|
||||
import { APP_STATE } from '../actions/actionsTypes';
|
||||
|
||||
describe('test reducer', () => {
|
||||
it('should return initial state', () => {
|
||||
const state = mockedStore.getState().app;
|
||||
expect(state).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return root state after dispatch appStart action', () => {
|
||||
mockedStore.dispatch(appStart({ root: RootEnum.ROOT_INSIDE }));
|
||||
const { root } = mockedStore.getState().app;
|
||||
expect(root).toEqual(RootEnum.ROOT_INSIDE);
|
||||
});
|
||||
|
||||
it('should return ready state after dispatch appInit action', () => {
|
||||
mockedStore.dispatch(appInit());
|
||||
const { ready } = mockedStore.getState().app;
|
||||
expect(ready).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return ready state after dispatch setMasterDetail action', () => {
|
||||
mockedStore.dispatch(setMasterDetail(false));
|
||||
const { isMasterDetail } = mockedStore.getState().app;
|
||||
expect(isMasterDetail).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return correct state after app go to foreground', () => {
|
||||
mockedStore.dispatch({ type: APP_STATE.FOREGROUND });
|
||||
const { foreground, background } = mockedStore.getState().app;
|
||||
expect(foreground).toEqual(true);
|
||||
expect(background).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return correct state after app go to background', () => {
|
||||
mockedStore.dispatch({ type: APP_STATE.BACKGROUND });
|
||||
const { foreground, background } = mockedStore.getState().app;
|
||||
expect(foreground).toEqual(false);
|
||||
expect(background).toEqual(true);
|
||||
});
|
||||
});
|
|
@ -1,15 +1,26 @@
|
|||
import { TActionApp } from '../actions/app';
|
||||
import { RootEnum } from '../definitions';
|
||||
import { APP, APP_STATE } from '../actions/actionsTypes';
|
||||
|
||||
const initialState = {
|
||||
root: null,
|
||||
export interface IApp {
|
||||
root?: RootEnum;
|
||||
isMasterDetail: boolean;
|
||||
text?: string;
|
||||
ready: boolean;
|
||||
foreground: boolean;
|
||||
background: boolean;
|
||||
}
|
||||
|
||||
export const initialState: IApp = {
|
||||
root: undefined,
|
||||
isMasterDetail: false,
|
||||
text: null,
|
||||
text: undefined,
|
||||
ready: false,
|
||||
foreground: true,
|
||||
background: false
|
||||
};
|
||||
|
||||
export default function app(state = initialState, action) {
|
||||
export default function app(state = initialState, action: TActionApp): IApp {
|
||||
switch (action.type) {
|
||||
case APP_STATE.FOREGROUND:
|
||||
return {
|
|
@ -0,0 +1,28 @@
|
|||
import { connectRequest, connectSuccess, disconnect } from '../actions/connect';
|
||||
import { initialState } from './connect';
|
||||
import { mockedStore } from './mockedStore';
|
||||
|
||||
describe('test reducer', () => {
|
||||
it('should return initial state', () => {
|
||||
const { meteor } = mockedStore.getState();
|
||||
expect(meteor).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return correct meteor state after dispatch connectRequest action', () => {
|
||||
mockedStore.dispatch(connectRequest());
|
||||
const { meteor } = mockedStore.getState();
|
||||
expect(meteor).toEqual({ connecting: true, connected: false });
|
||||
});
|
||||
|
||||
it('should return correct meteor state after dispatch connectSuccess action', () => {
|
||||
mockedStore.dispatch(connectSuccess());
|
||||
const { meteor } = mockedStore.getState();
|
||||
expect(meteor).toEqual({ connecting: false, connected: true });
|
||||
});
|
||||
|
||||
it('should return correct meteor state after dispatch disconnect action', () => {
|
||||
mockedStore.dispatch(disconnect());
|
||||
const { meteor } = mockedStore.getState();
|
||||
expect(meteor).toEqual(initialState);
|
||||
});
|
||||
});
|
|
@ -1,11 +1,18 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { METEOR } from '../actions/actionsTypes';
|
||||
|
||||
const initialState = {
|
||||
export interface IConnect {
|
||||
connecting: boolean;
|
||||
connected: boolean;
|
||||
}
|
||||
|
||||
export const initialState: IConnect = {
|
||||
connecting: false,
|
||||
connected: false
|
||||
};
|
||||
|
||||
export default function connect(state = initialState, action) {
|
||||
export default function connect(state = initialState, action: Action): IConnect {
|
||||
switch (action.type) {
|
||||
case METEOR.REQUEST:
|
||||
return {
|
|
@ -1,36 +0,0 @@
|
|||
import { CREATE_CHANNEL } from '../actions/actionsTypes';
|
||||
|
||||
const initialState = {
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: {},
|
||||
error: {}
|
||||
};
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case CREATE_CHANNEL.REQUEST:
|
||||
return {
|
||||
...state,
|
||||
isFetching: true,
|
||||
failure: false,
|
||||
error: {}
|
||||
};
|
||||
case CREATE_CHANNEL.SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: action.data
|
||||
};
|
||||
case CREATE_CHANNEL.FAILURE:
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: true,
|
||||
error: action.err
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue