diff --git a/app/reducers/views/channel.js b/app/reducers/views/channel.js index 3ffce2343..f9c771fbb 100644 --- a/app/reducers/views/channel.js +++ b/app/reducers/views/channel.js @@ -348,6 +348,11 @@ function lastChannelViewTime(state = {}, action) { return state; } + case ChannelTypes.POST_UNREAD_SUCCESS: { + const data = action.data; + return {...state, [data.channelId]: data.lastViewedAt}; + } + default: return state; } diff --git a/app/screens/post_options/__snapshots__/post_options.test.js.snap b/app/screens/post_options/__snapshots__/post_options.test.js.snap index 7139754cc..596d208c3 100644 --- a/app/screens/post_options/__snapshots__/post_options.test.js.snap +++ b/app/screens/post_options/__snapshots__/post_options.test.js.snap @@ -1,192 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PostOptions should match snapshot, no option for system message to user who doesn't have the permission to delete 1`] = ` - - - - - - - - -`; - -exports[`PostOptions should match snapshot, showing Delete option only for system message to user who has permission to delete 1`] = ` + + + + +`; + +exports[`PostOptions should match snapshot, showing Delete option only for system message to user who has permission to delete 1`] = ` + + + + + + + { - const actions = [ - this.getEditOption(), - this.getReplyOption(), - this.getFlagOption(), - this.getPinOption(), - this.getAddReactionOption(), - this.getCopyPermalink(), - this.getCopyText(), - this.getDeleteOption(), - ]; + getMarkAsUnreadOption = () => { + const {post, isLandscape, theme} = this.props; + const {formatMessage} = this.context.intl; - return actions.filter((a) => a !== null); - }; - - getOthersPostOptions = () => { - const actions = [ - this.getReplyOption(), - this.getFlagOption(), - this.getAddReactionOption(), - this.getPinOption(), - this.getCopyPermalink(), - this.getCopyText(), - this.getEditOption(), - this.getDeleteOption(), - ]; - - return actions.filter((a) => a !== null); + if (!isSystemMessage(post)) { + return ( + + ); + } + return null; }; getPostOptions = () => { - const {isMyPost} = this.props; + const actions = [ + this.getReplyOption(), + this.getAddReactionOption(), + this.getMarkAsUnreadOption(), + this.getCopyPermalink(), + this.getFlagOption(), + this.getCopyText(), + this.getPinOption(), + this.getEditOption(), + this.getDeleteOption(), + ]; - return isMyPost ? this.getMyPostOptions() : this.getOthersPostOptions(); + return actions.filter((a) => a !== null); }; handleAddReaction = () => { @@ -324,6 +326,15 @@ export default class PostOptions extends PureComponent { }); }; + handleMarkUnread = () => { + const {actions, post, currentUserId} = this.props; + + this.closeWithAnimation(); + requestAnimationFrame(() => { + actions.setUnreadPost(currentUserId, post.id); + }); + } + handlePostDelete = () => { const {formatMessage} = this.context.intl; const {actions, post} = this.props; diff --git a/app/screens/post_options/post_options.test.js b/app/screens/post_options/post_options.test.js index 6be5ab8e1..d2e7e9a0a 100644 --- a/app/screens/post_options/post_options.test.js +++ b/app/screens/post_options/post_options.test.js @@ -26,6 +26,7 @@ describe('PostOptions', () => { removePost: jest.fn(), unflagPost: jest.fn(), unpinPost: jest.fn(), + setUnreadPost: jest.fn(), }; const post = { @@ -46,6 +47,7 @@ describe('PostOptions', () => { canEditUntil: -1, channelIsReadOnly: false, currentTeamUrl: 'http://localhost:8065/team-name', + currentUserId: 'user1', deviceHeight: 600, hasBeenDeleted: false, isFlagged: false, diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 057487627..a99e0da2e 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -360,6 +360,7 @@ "mobile.post_info.add_reaction": "Add Reaction", "mobile.post_info.copy_text": "Copy Text", "mobile.post_info.flag": "Flag", + "mobile.post_info.mark_unread": "Mark post as unread", "mobile.post_info.pin": "Pin to Channel", "mobile.post_info.reply": "Reply", "mobile.post_info.unflag": "Unflag", diff --git a/assets/base/images/post_menu/bookmark.png b/assets/base/images/post_menu/bookmark.png new file mode 100755 index 000000000..df28ccf58 Binary files /dev/null and b/assets/base/images/post_menu/bookmark.png differ diff --git a/assets/base/images/post_menu/bookmark@2x.png b/assets/base/images/post_menu/bookmark@2x.png new file mode 100755 index 000000000..7f1db3004 Binary files /dev/null and b/assets/base/images/post_menu/bookmark@2x.png differ diff --git a/assets/base/images/post_menu/bookmark@3x.png b/assets/base/images/post_menu/bookmark@3x.png new file mode 100755 index 000000000..805a4c668 Binary files /dev/null and b/assets/base/images/post_menu/bookmark@3x.png differ diff --git a/package-lock.json b/package-lock.json index 830ce926c..2020b0fa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14133,8 +14133,8 @@ "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" }, "mattermost-redux": { - "version": "github:mattermost/mattermost-redux#3bb89a5450b94da564d3a286fefb5945a1c3fca8", - "from": "github:mattermost/mattermost-redux#3bb89a5450b94da564d3a286fefb5945a1c3fca8", + "version": "github:mattermost/mattermost-redux#dc5f8c1f30cbc6a25d4304f2923f5b78e674099d", + "from": "github:mattermost/mattermost-redux#dc5f8c1f30cbc6a25d4304f2923f5b78e674099d", "requires": { "deep-equal": "1.0.1", "eslint-plugin-header": "3.0.0", @@ -14147,7 +14147,7 @@ "redux": "4.0.4", "redux-action-buffer": "1.2.0", "redux-batched-actions": "0.4.1", - "redux-offline": "git+https://github.com/enahum/redux-offline.git#4bd85e7e3b279a2b11fb4d587808d583d2b5e7b5", + "redux-offline": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df", "redux-persist": "4.9.1", "redux-thunk": "2.3.0", "reselect": "4.0.0", @@ -17575,8 +17575,8 @@ } }, "redux-offline": { - "version": "git+https://github.com/enahum/redux-offline.git#4bd85e7e3b279a2b11fb4d587808d583d2b5e7b5", - "from": "git+https://github.com/enahum/redux-offline.git#4bd85e7e3b279a2b11fb4d587808d583d2b5e7b5", + "version": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df", + "from": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df", "requires": { "@react-native-community/netinfo": "^4.1.3", "redux-persist": "^4.5.0" diff --git a/package.json b/package.json index be2be758d..7ef0ff97c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "intl": "1.2.5", "jail-monkey": "2.2.0", "jsc-android": "241213.2.0", - "mattermost-redux": "github:mattermost/mattermost-redux#3bb89a5450b94da564d3a286fefb5945a1c3fca8", + "mattermost-redux": "github:mattermost/mattermost-redux#dc5f8c1f30cbc6a25d4304f2923f5b78e674099d", "mime-db": "1.40.0", "moment-timezone": "0.5.25", "prop-types": "15.7.2", diff --git a/packager/moduleNames.js b/packager/moduleNames.js index 9a92fb941..a7c0e11a1 100644 --- a/packager/moduleNames.js +++ b/packager/moduleNames.js @@ -303,6 +303,7 @@ module.exports = [ 'dist/assets/images/icons/word.png', 'dist/assets/images/post_header/flag.png', 'dist/assets/images/post_header/pin.png', + 'dist/assets/images/post_header/bookmark.png', 'dist/assets/images/profile.jpg', 'dist/assets/images/status/away.png', 'dist/assets/images/status/dnd.png',