Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
|
8142851fde | |
|
0ecfe0f780 | |
|
b9a3828781 | |
|
fd3f0a3417 | |
|
fa2c93fa2b | |
|
118b1352c4 | |
|
3d987cc988 | |
|
766dd8f5e4 | |
|
be718db8a5 | |
|
3be67f5a4f | |
|
77917f66f0 | |
|
7d2f4afaae | |
|
5cf9291fc9 | |
|
db0520ed7b | |
|
0583de7158 | |
|
33edacf087 | |
|
c3a80b6f1e | |
|
f15c755e03 |
|
@ -139,7 +139,7 @@ android {
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode VERSIONCODE as Integer
|
versionCode VERSIONCODE as Integer
|
||||||
versionName "4.8.0"
|
versionName "4.8.1"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
|
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
|
||||||
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
|
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
|
||||||
|
|
|
@ -29,7 +29,8 @@ export default StyleSheet.create({
|
||||||
},
|
},
|
||||||
handle: {
|
handle: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
|
paddingBottom: 8
|
||||||
},
|
},
|
||||||
handleIndicator: {
|
handleIndicator: {
|
||||||
width: 40,
|
width: 40,
|
||||||
|
|
|
@ -14,17 +14,20 @@ import { Button } from '../ActionSheet';
|
||||||
import { useDimensions } from '../../dimensions';
|
import { useDimensions } from '../../dimensions';
|
||||||
|
|
||||||
export const HEADER_HEIGHT = 36;
|
export const HEADER_HEIGHT = 36;
|
||||||
|
const ITEM_SIZE = 36;
|
||||||
|
const CONTAINER_MARGIN = 8;
|
||||||
|
const ITEM_MARGIN = 8;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginHorizontal: 8
|
marginHorizontal: CONTAINER_MARGIN
|
||||||
},
|
},
|
||||||
headerItem: {
|
headerItem: {
|
||||||
height: 36,
|
height: ITEM_SIZE,
|
||||||
width: 36,
|
width: ITEM_SIZE,
|
||||||
borderRadius: 20,
|
borderRadius: ITEM_SIZE / 2,
|
||||||
marginHorizontal: 8,
|
marginHorizontal: ITEM_MARGIN,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center'
|
alignItems: 'center'
|
||||||
},
|
},
|
||||||
|
@ -84,7 +87,7 @@ HeaderFooter.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = React.memo(({
|
const Header = React.memo(({
|
||||||
handleReaction, server, message, theme
|
handleReaction, server, message, isMasterDetail, theme
|
||||||
}) => {
|
}) => {
|
||||||
const [items, setItems] = useState([]);
|
const [items, setItems] = useState([]);
|
||||||
const { width, height } = useDimensions();
|
const { width, height } = useDimensions();
|
||||||
|
@ -96,8 +99,8 @@ const Header = React.memo(({
|
||||||
let freqEmojis = await freqEmojiCollection.query().fetch();
|
let freqEmojis = await freqEmojiCollection.query().fetch();
|
||||||
|
|
||||||
const isLandscape = width > height;
|
const isLandscape = width > height;
|
||||||
const size = isLandscape ? width / 2 : width;
|
const size = (isLandscape || isMasterDetail ? width / 2 : width) - (CONTAINER_MARGIN * 2);
|
||||||
const quantity = (size / 50) - 1;
|
const quantity = (size / (ITEM_SIZE + (ITEM_MARGIN * 2))) - 1;
|
||||||
|
|
||||||
freqEmojis = freqEmojis.concat(DEFAULT_EMOJIS).slice(0, quantity);
|
freqEmojis = freqEmojis.concat(DEFAULT_EMOJIS).slice(0, quantity);
|
||||||
setItems(freqEmojis);
|
setItems(freqEmojis);
|
||||||
|
@ -135,6 +138,7 @@ Header.propTypes = {
|
||||||
handleReaction: PropTypes.func,
|
handleReaction: PropTypes.func,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
message: PropTypes.object,
|
message: PropTypes.object,
|
||||||
|
isMasterDetail: PropTypes.bool,
|
||||||
theme: PropTypes.string
|
theme: PropTypes.string
|
||||||
};
|
};
|
||||||
export default withTheme(Header);
|
export default withTheme(Header);
|
||||||
|
|
|
@ -32,7 +32,8 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
Message_AllowEditing_BlockEditInMinutes,
|
Message_AllowEditing_BlockEditInMinutes,
|
||||||
Message_AllowPinning,
|
Message_AllowPinning,
|
||||||
Message_AllowStarring,
|
Message_AllowStarring,
|
||||||
Message_Read_Receipt_Store_Users
|
Message_Read_Receipt_Store_Users,
|
||||||
|
isMasterDetail
|
||||||
}, ref) => {
|
}, ref) => {
|
||||||
let permissions = {};
|
let permissions = {};
|
||||||
const { showActionSheet, hideActionSheet } = useActionSheet();
|
const { showActionSheet, hideActionSheet } = useActionSheet();
|
||||||
|
@ -116,7 +117,12 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
const handleEdit = message => editInit(message);
|
const handleEdit = message => editInit(message);
|
||||||
|
|
||||||
const handleCreateDiscussion = (message) => {
|
const handleCreateDiscussion = (message) => {
|
||||||
Navigation.navigate('CreateDiscussionView', { message, channel: room });
|
const params = { message, channel: room, showCloseModal: true };
|
||||||
|
if (isMasterDetail) {
|
||||||
|
Navigation.navigate('ModalStackNavigator', { screen: 'CreateDiscussionView', params });
|
||||||
|
} else {
|
||||||
|
Navigation.navigate('NewMessageStackNavigator', { screen: 'CreateDiscussionView', params });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUnread = async(message) => {
|
const handleUnread = async(message) => {
|
||||||
|
@ -377,6 +383,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
<Header
|
<Header
|
||||||
server={server}
|
server={server}
|
||||||
handleReaction={handleReaction}
|
handleReaction={handleReaction}
|
||||||
|
isMasterDetail={isMasterDetail}
|
||||||
message={message}
|
message={message}
|
||||||
/>
|
/>
|
||||||
) : null)
|
) : null)
|
||||||
|
@ -412,7 +419,8 @@ const mapStateToProps = state => ({
|
||||||
Message_AllowEditing_BlockEditInMinutes: state.settings.Message_AllowEditing_BlockEditInMinutes,
|
Message_AllowEditing_BlockEditInMinutes: state.settings.Message_AllowEditing_BlockEditInMinutes,
|
||||||
Message_AllowPinning: state.settings.Message_AllowPinning,
|
Message_AllowPinning: state.settings.Message_AllowPinning,
|
||||||
Message_AllowStarring: state.settings.Message_AllowStarring,
|
Message_AllowStarring: state.settings.Message_AllowStarring,
|
||||||
Message_Read_Receipt_Store_Users: state.settings.Message_Read_Receipt_Store_Users
|
Message_Read_Receipt_Store_Users: state.settings.Message_Read_Receipt_Store_Users,
|
||||||
|
isMasterDetail: state.app.isMasterDetail
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, null, null, { forwardRef: true })(MessageActions);
|
export default connect(mapStateToProps, null, null, { forwardRef: true })(MessageActions);
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default class EmojiKeyboard extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
this.baseUrl = state.server.server;
|
this.baseUrl = state.share.server || state.server.server;
|
||||||
}
|
}
|
||||||
|
|
||||||
onEmojiSelected = (emoji) => {
|
onEmojiSelected = (emoji) => {
|
||||||
|
|
|
@ -541,12 +541,14 @@ class MessageBox extends Component {
|
||||||
setCommandPreview = async(command, name, params) => {
|
setCommandPreview = async(command, name, params) => {
|
||||||
const { rid } = this.props;
|
const { rid } = this.props;
|
||||||
try {
|
try {
|
||||||
const { preview } = await RocketChat.getCommandPreview(name, rid, params);
|
const { success, preview } = await RocketChat.getCommandPreview(name, rid, params);
|
||||||
this.setState({ commandPreview: preview.items, showCommandPreview: true, command });
|
if (success) {
|
||||||
|
return this.setState({ commandPreview: preview?.items, showCommandPreview: true, command });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.setState({ commandPreview: [], showCommandPreview: true, command: {} });
|
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
||||||
|
this.setState({ commandPreview: [], showCommandPreview: true, command: {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
setInput = (text) => {
|
setInput = (text) => {
|
||||||
|
|
|
@ -110,7 +110,9 @@ class DB {
|
||||||
Thread,
|
Thread,
|
||||||
ThreadMessage,
|
ThreadMessage,
|
||||||
Upload,
|
Upload,
|
||||||
Permission
|
Permission,
|
||||||
|
CustomEmoji,
|
||||||
|
FrequentlyUsedEmoji
|
||||||
],
|
],
|
||||||
actionsEnabled: true
|
actionsEnabled: true
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { InteractionManager } from 'react-native';
|
|
||||||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
|
@ -132,48 +131,47 @@ export default async function() {
|
||||||
const filteredSettingsIds = filteredSettings.map(s => s._id);
|
const filteredSettingsIds = filteredSettings.map(s => s._id);
|
||||||
|
|
||||||
reduxStore.dispatch(addSettings(this.parseSettings(filteredSettings)));
|
reduxStore.dispatch(addSettings(this.parseSettings(filteredSettings)));
|
||||||
InteractionManager.runAfterInteractions(async() => {
|
|
||||||
// filter server info
|
|
||||||
const serverInfo = filteredSettings.filter(i1 => serverInfoKeys.includes(i1._id));
|
|
||||||
const iconSetting = data.find(item => item._id === 'Assets_favicon_512');
|
|
||||||
await serverInfoUpdate(serverInfo, iconSetting);
|
|
||||||
|
|
||||||
await db.action(async() => {
|
// filter server info
|
||||||
const settingsCollection = db.collections.get('settings');
|
const serverInfo = filteredSettings.filter(i1 => serverInfoKeys.includes(i1._id));
|
||||||
const allSettingsRecords = await settingsCollection
|
const iconSetting = data.find(item => item._id === 'Assets_favicon_512');
|
||||||
.query(Q.where('id', Q.oneOf(filteredSettingsIds)))
|
await serverInfoUpdate(serverInfo, iconSetting);
|
||||||
.fetch();
|
|
||||||
|
|
||||||
// filter settings
|
await db.action(async() => {
|
||||||
let settingsToCreate = filteredSettings.filter(i1 => !allSettingsRecords.find(i2 => i1._id === i2.id));
|
const settingsCollection = db.collections.get('settings');
|
||||||
let settingsToUpdate = allSettingsRecords.filter(i1 => filteredSettings.find(i2 => i1.id === i2._id));
|
const allSettingsRecords = await settingsCollection
|
||||||
|
.query(Q.where('id', Q.oneOf(filteredSettingsIds)))
|
||||||
|
.fetch();
|
||||||
|
|
||||||
// Create
|
// filter settings
|
||||||
settingsToCreate = settingsToCreate.map(setting => settingsCollection.prepareCreate(protectedFunction((s) => {
|
let settingsToCreate = filteredSettings.filter(i1 => !allSettingsRecords.find(i2 => i1._id === i2.id));
|
||||||
s._raw = sanitizedRaw({ id: setting._id }, settingsCollection.schema);
|
let settingsToUpdate = allSettingsRecords.filter(i1 => filteredSettings.find(i2 => i1.id === i2._id));
|
||||||
Object.assign(s, setting);
|
|
||||||
})));
|
|
||||||
|
|
||||||
// Update
|
// Create
|
||||||
settingsToUpdate = settingsToUpdate.map((setting) => {
|
settingsToCreate = settingsToCreate.map(setting => settingsCollection.prepareCreate(protectedFunction((s) => {
|
||||||
const newSetting = filteredSettings.find(s => s._id === setting.id);
|
s._raw = sanitizedRaw({ id: setting._id }, settingsCollection.schema);
|
||||||
return setting.prepareUpdate(protectedFunction((s) => {
|
Object.assign(s, setting);
|
||||||
Object.assign(s, newSetting);
|
})));
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
const allRecords = [
|
// Update
|
||||||
...settingsToCreate,
|
settingsToUpdate = settingsToUpdate.map((setting) => {
|
||||||
...settingsToUpdate
|
const newSetting = filteredSettings.find(s => s._id === setting.id);
|
||||||
];
|
return setting.prepareUpdate(protectedFunction((s) => {
|
||||||
|
Object.assign(s, newSetting);
|
||||||
try {
|
}));
|
||||||
await db.batch(...allRecords);
|
|
||||||
} catch (e) {
|
|
||||||
log(e);
|
|
||||||
}
|
|
||||||
return allRecords.length;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const allRecords = [
|
||||||
|
...settingsToCreate,
|
||||||
|
...settingsToUpdate
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.batch(...allRecords);
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
return allRecords.length;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
|
|
|
@ -288,6 +288,8 @@ const RocketChat = {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
reduxStore.dispatch(shareSelectServer(server));
|
reduxStore.dispatch(shareSelectServer(server));
|
||||||
|
|
||||||
|
RocketChat.setCustomEmojis();
|
||||||
|
|
||||||
// set User info
|
// set User info
|
||||||
try {
|
try {
|
||||||
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
|
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
|
||||||
|
@ -320,7 +322,7 @@ const RocketChat = {
|
||||||
|
|
||||||
updateJitsiTimeout(roomId) {
|
updateJitsiTimeout(roomId) {
|
||||||
// RC 0.74.0
|
// RC 0.74.0
|
||||||
return this.post('jitsi.updateTimeout', { roomId });
|
return this.post('video-conference/jitsi.update-timeout', { roomId });
|
||||||
},
|
},
|
||||||
|
|
||||||
register(credentials) {
|
register(credentials) {
|
||||||
|
|
|
@ -260,6 +260,21 @@ function bouncy(
|
||||||
const WIDTH = 300;
|
const WIDTH = 300;
|
||||||
const HEIGHT = 300;
|
const HEIGHT = 300;
|
||||||
|
|
||||||
|
class Image extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
imageComponentType: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { imageComponentType } = this.props;
|
||||||
|
|
||||||
|
const Component = ImageComponent(imageComponentType);
|
||||||
|
|
||||||
|
return <Component {...this.props} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const AnimatedImage = Animated.createAnimatedComponent(Image);
|
||||||
|
|
||||||
// it was picked from https://github.com/software-mansion/react-native-reanimated/tree/master/Example/imageViewer
|
// it was picked from https://github.com/software-mansion/react-native-reanimated/tree/master/Example/imageViewer
|
||||||
// and changed to use FastImage animated component
|
// and changed to use FastImage animated component
|
||||||
export class ImageViewer extends React.Component {
|
export class ImageViewer extends React.Component {
|
||||||
|
@ -386,12 +401,9 @@ export class ImageViewer extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
uri, width, height, theme, imageComponentType, ...props
|
uri, width, height, imageComponentType, theme, ...props
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const Component = ImageComponent(imageComponentType);
|
|
||||||
const AnimatedFastImage = Animated.createAnimatedComponent(Component);
|
|
||||||
|
|
||||||
// The below two animated values makes it so that scale appears to be done
|
// The below two animated values makes it so that scale appears to be done
|
||||||
// from the top left corner of the image view instead of its center. This
|
// from the top left corner of the image view instead of its center. This
|
||||||
// is required for the "scale focal point" math to work correctly
|
// is required for the "scale focal point" math to work correctly
|
||||||
|
@ -416,7 +428,7 @@ export class ImageViewer extends React.Component {
|
||||||
onGestureEvent={this._onPanEvent}
|
onGestureEvent={this._onPanEvent}
|
||||||
onHandlerStateChange={this._onPanEvent}
|
onHandlerStateChange={this._onPanEvent}
|
||||||
>
|
>
|
||||||
<AnimatedFastImage
|
<AnimatedImage
|
||||||
style={[
|
style={[
|
||||||
styles.image,
|
styles.image,
|
||||||
{
|
{
|
||||||
|
@ -435,6 +447,7 @@ export class ImageViewer extends React.Component {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
imageComponentType={imageComponentType}
|
||||||
resizeMode='contain'
|
resizeMode='contain'
|
||||||
source={{ uri }}
|
source={{ uri }}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -54,8 +54,7 @@ export const FadeFromCenterModal = {
|
||||||
const forStackAndroid = ({
|
const forStackAndroid = ({
|
||||||
current,
|
current,
|
||||||
inverted,
|
inverted,
|
||||||
layouts: { screen },
|
layouts: { screen }
|
||||||
closing
|
|
||||||
}) => {
|
}) => {
|
||||||
const translateX = multiply(
|
const translateX = multiply(
|
||||||
current.progress.interpolate({
|
current.progress.interpolate({
|
||||||
|
@ -65,13 +64,12 @@ const forStackAndroid = ({
|
||||||
inverted
|
inverted
|
||||||
);
|
);
|
||||||
|
|
||||||
const opacity = conditional(
|
const opacity = multiply(
|
||||||
closing,
|
|
||||||
current.progress,
|
|
||||||
current.progress.interpolate({
|
current.progress.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
outputRange: [0, 1]
|
outputRange: [0, 1]
|
||||||
})
|
}),
|
||||||
|
inverted
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -46,9 +46,9 @@ export const navigationTheme = (theme) => {
|
||||||
|
|
||||||
// Gets the current screen from navigation state
|
// Gets the current screen from navigation state
|
||||||
export const getActiveRoute = (state) => {
|
export const getActiveRoute = (state) => {
|
||||||
const route = state.routes[state.index];
|
const route = state?.routes[state?.index];
|
||||||
|
|
||||||
if (route.state) {
|
if (route?.state) {
|
||||||
// Dive into nested navigators
|
// Dive into nested navigators
|
||||||
return getActiveRoute(route.state);
|
return getActiveRoute(route.state);
|
||||||
}
|
}
|
||||||
|
@ -56,4 +56,4 @@ export const getActiveRoute = (state) => {
|
||||||
return route;
|
return route;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getActiveRouteName = state => getActiveRoute(state).name;
|
export const getActiveRouteName = state => getActiveRoute(state)?.name;
|
||||||
|
|
|
@ -70,10 +70,15 @@ class AttachmentView extends React.Component {
|
||||||
setHeader = () => {
|
setHeader = () => {
|
||||||
const { route, navigation, theme } = this.props;
|
const { route, navigation, theme } = this.props;
|
||||||
const attachment = route.params?.attachment;
|
const attachment = route.params?.attachment;
|
||||||
const { title } = attachment;
|
let { title } = attachment;
|
||||||
|
try {
|
||||||
|
title = decodeURI(title);
|
||||||
|
} catch {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
const options = {
|
const options = {
|
||||||
|
title,
|
||||||
headerLeft: () => <CloseModalButton testID='close-attachment-view' navigation={navigation} buttonStyle={{ color: themes[theme].previewTintColor }} />,
|
headerLeft: () => <CloseModalButton testID='close-attachment-view' navigation={navigation} buttonStyle={{ color: themes[theme].previewTintColor }} />,
|
||||||
title: decodeURI(title),
|
|
||||||
headerRight: () => <SaveButton testID='save-image' onPress={this.handleSave} buttonStyle={{ color: themes[theme].previewTintColor }} />,
|
headerRight: () => <SaveButton testID='save-image' onPress={this.handleSave} buttonStyle={{ color: themes[theme].previewTintColor }} />,
|
||||||
headerBackground: () => <View style={{ flex: 1, backgroundColor: themes[theme].previewBackground }} />,
|
headerBackground: () => <View style={{ flex: 1, backgroundColor: themes[theme].previewBackground }} />,
|
||||||
headerTintColor: themes[theme].previewTintColor,
|
headerTintColor: themes[theme].previewTintColor,
|
||||||
|
|
|
@ -16,6 +16,7 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
|
||||||
const SectionTitle = React.memo(({ title, theme }) => (
|
const SectionTitle = React.memo(({ title, theme }) => (
|
||||||
<Text
|
<Text
|
||||||
|
@ -183,26 +184,30 @@ class NotificationPreferencesView extends React.Component {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
|
|
||||||
await db.action(async() => {
|
|
||||||
await room.update(protectedFunction((r) => {
|
|
||||||
r[key] = value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.saveNotificationSettings(this.rid, params);
|
await db.action(async() => {
|
||||||
if (result.success) {
|
await room.update(protectedFunction((r) => {
|
||||||
return;
|
r[key] = value;
|
||||||
}
|
}));
|
||||||
} catch {
|
});
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.action(async() => {
|
try {
|
||||||
await room.update(protectedFunction((r) => {
|
const result = await RocketChat.saveNotificationSettings(this.rid, params);
|
||||||
r[key] = room[key];
|
if (result.success) {
|
||||||
}));
|
return;
|
||||||
});
|
}
|
||||||
|
} catch {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.action(async() => {
|
||||||
|
await room.update(protectedFunction((r) => {
|
||||||
|
r[key] = room[key];
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onValueChangeSwitch = (key, value) => this.saveNotificationSettings(key, value, { [key]: value ? '1' : '0' });
|
onValueChangeSwitch = (key, value) => this.saveNotificationSettings(key, value, { [key]: value ? '1' : '0' });
|
||||||
|
|
|
@ -145,10 +145,12 @@ class RegisterView extends React.Component {
|
||||||
await loginRequest({ user: email, password });
|
await loginRequest({ user: email, password });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.data && e.data.errorType === 'username-invalid') {
|
if (e.data?.errorType === 'username-invalid') {
|
||||||
return loginRequest({ user: email, password });
|
return loginRequest({ user: email, password });
|
||||||
}
|
}
|
||||||
showErrorAlert(e.data.error, I18n.t('Oops'));
|
if (e.data?.error) {
|
||||||
|
showErrorAlert(e.data.error, I18n.t('Oops'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.setState({ saving: false });
|
this.setState({ saving: false });
|
||||||
}
|
}
|
||||||
|
|
|
@ -755,7 +755,7 @@ class RoomView extends React.Component {
|
||||||
if (handleCommandScroll(event)) {
|
if (handleCommandScroll(event)) {
|
||||||
const offset = input === 'UIKeyInputUpArrow' ? 100 : -100;
|
const offset = input === 'UIKeyInputUpArrow' ? 100 : -100;
|
||||||
this.offset += offset;
|
this.offset += offset;
|
||||||
this.flatList.scrollToOffset({ offset: this.offset });
|
this.flatList?.scrollToOffset({ offset: this.offset });
|
||||||
} else if (handleCommandRoomActions(event)) {
|
} else if (handleCommandRoomActions(event)) {
|
||||||
this.goRoomActionsView();
|
this.goRoomActionsView();
|
||||||
} else if (handleCommandSearchMessages(event)) {
|
} else if (handleCommandSearchMessages(event)) {
|
||||||
|
|
|
@ -411,7 +411,7 @@ class RoomsListView extends React.Component {
|
||||||
let tempChats = [];
|
let tempChats = [];
|
||||||
let chats = [];
|
let chats = [];
|
||||||
if (sortBy === 'alphabetical') {
|
if (sortBy === 'alphabetical') {
|
||||||
chats = orderBy(data, ['name'], ['asc']);
|
chats = orderBy(data, [`${ this.useRealName ? 'fname' : 'name' }`], ['asc']);
|
||||||
} else {
|
} else {
|
||||||
chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
|
chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
|
||||||
}
|
}
|
||||||
|
@ -504,12 +504,7 @@ class RoomsListView extends React.Component {
|
||||||
closeSearchHeader();
|
closeSearchHeader();
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const offset = isAndroid ? 0 : SCROLL_OFFSET;
|
this.scrollToTop();
|
||||||
if (this.scroll.scrollTo) {
|
|
||||||
this.scroll.scrollTo({ x: 0, y: offset, animated: true });
|
|
||||||
} else if (this.scroll.scrollToOffset) {
|
|
||||||
this.scroll.scrollToOffset({ offset });
|
|
||||||
}
|
|
||||||
}, 200);
|
}, 200);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -538,9 +533,7 @@ class RoomsListView extends React.Component {
|
||||||
search: result,
|
search: result,
|
||||||
searching: true
|
searching: true
|
||||||
});
|
});
|
||||||
if (this.scroll && this.scroll.scrollTo) {
|
this.scrollToTop();
|
||||||
this.scroll.scrollTo({ x: 0, y: 0, animated: true });
|
|
||||||
}
|
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
getRoomTitle = item => RocketChat.getRoomTitle(item)
|
getRoomTitle = item => RocketChat.getRoomTitle(item)
|
||||||
|
@ -561,15 +554,17 @@ class RoomsListView extends React.Component {
|
||||||
this.goRoom({ item, isMasterDetail });
|
this.goRoom({ item, isMasterDetail });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scrollToTop = () => {
|
||||||
|
const offset = isAndroid ? 0 : SCROLL_OFFSET;
|
||||||
|
if (this.scroll?.scrollToOffset) {
|
||||||
|
this.scroll.scrollToOffset({ offset });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toggleSort = () => {
|
toggleSort = () => {
|
||||||
const { toggleSortDropdown } = this.props;
|
const { toggleSortDropdown } = this.props;
|
||||||
|
|
||||||
const offset = isAndroid ? 0 : SCROLL_OFFSET;
|
this.scrollToTop();
|
||||||
if (this.scroll.scrollTo) {
|
|
||||||
this.scroll.scrollTo({ x: 0, y: offset, animated: true });
|
|
||||||
} else if (this.scroll.scrollToOffset) {
|
|
||||||
this.scroll.scrollToOffset({ offset });
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toggleSortDropdown();
|
toggleSortDropdown();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
|
@ -123,7 +123,7 @@ class ShareView extends Component {
|
||||||
item.error = error;
|
item.error = error;
|
||||||
|
|
||||||
// get video thumbnails
|
// get video thumbnails
|
||||||
if (item.mime?.match(/video/)) {
|
if (item.mime?.match?.(/video/)) {
|
||||||
try {
|
try {
|
||||||
const { uri } = await VideoThumbnails.getThumbnailAsync(item.path);
|
const { uri } = await VideoThumbnails.getThumbnailAsync(item.path);
|
||||||
item.uri = uri;
|
item.uri = uri;
|
||||||
|
|
|
@ -141,7 +141,15 @@ class Sidebar extends Component {
|
||||||
|
|
||||||
get currentItemKey() {
|
get currentItemKey() {
|
||||||
const { state } = this.props;
|
const { state } = this.props;
|
||||||
return state.routeNames[state.index];
|
return state?.routeNames[state?.index];
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressUser = () => {
|
||||||
|
const { navigation, isMasterDetail } = this.props;
|
||||||
|
if (isMasterDetail) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
navigation.closeDrawer();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAdmin = () => {
|
renderAdmin = () => {
|
||||||
|
@ -210,7 +218,7 @@ class Sidebar extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
user, Site_Name, baseUrl, useRealName, allowStatusMessage, isMasterDetail, theme, navigation
|
user, Site_Name, baseUrl, useRealName, allowStatusMessage, isMasterDetail, theme
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -229,7 +237,7 @@ class Sidebar extends Component {
|
||||||
]}
|
]}
|
||||||
{...scrollPersistTaps}
|
{...scrollPersistTaps}
|
||||||
>
|
>
|
||||||
<TouchableWithoutFeedback onPress={() => navigation.closeDrawer()} testID='sidebar-close-drawer'>
|
<TouchableWithoutFeedback onPress={this.onPressUser} testID='sidebar-close-drawer'>
|
||||||
<View style={styles.header} theme={theme}>
|
<View style={styles.header} theme={theme}>
|
||||||
<Avatar
|
<Avatar
|
||||||
text={user.username}
|
text={user.username}
|
||||||
|
|
|
@ -127,7 +127,7 @@ class ThreadMessagesView extends React.Component {
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
init = () => {
|
init = () => {
|
||||||
if (!this.subscription) {
|
if (!this.subscription) {
|
||||||
this.load();
|
return this.load();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const lastThreadSync = new Date();
|
const lastThreadSync = new Date();
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.8.0</string>
|
<string>4.8.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.8.0</string>
|
<string>4.8.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
|
|
Loading…
Reference in New Issue