summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorSaturnino Abril <saturnino.abril@gmail.com>2017-07-22 07:02:14 +0800
committerJoram Wilander <jwawilander@gmail.com>2017-07-21 19:02:14 -0400
commit58c6a70d3e225fcc423d4f0ee9316150e097b2c2 (patch)
tree90e688ea86a1db241b2d57aa9b3129563e34de90 /webapp
parent816bfbeb91b9cd64a8a85dc37cc0e82554409c14 (diff)
downloadchat-58c6a70d3e225fcc423d4f0ee9316150e097b2c2.tar.gz
chat-58c6a70d3e225fcc423d4f0ee9316150e097b2c2.tar.bz2
chat-58c6a70d3e225fcc423d4f0ee9316150e097b2c2.zip
Add [...] menu to search results list (#6663)
* Add [...] menu to search results list * fix updates on search results when post is pinned or edited * remove app dispatcher from component
Diffstat (limited to 'webapp')
-rw-r--r--webapp/actions/post_actions.jsx6
-rw-r--r--webapp/actions/websocket_actions.jsx6
-rw-r--r--webapp/components/search_results_item.jsx136
-rw-r--r--webapp/stores/search_store.jsx19
-rw-r--r--webapp/utils/constants.jsx3
-rw-r--r--webapp/yarn.lock129
6 files changed, 116 insertions, 183 deletions
diff --git a/webapp/actions/post_actions.jsx b/webapp/actions/post_actions.jsx
index 09cc14e40..e96e8306b 100644
--- a/webapp/actions/post_actions.jsx
+++ b/webapp/actions/post_actions.jsx
@@ -326,7 +326,8 @@ export function pinPost(postId) {
await PostActions.pinPost(postId)(doDispatch, doGetState);
AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_POST_PINNED
+ type: ActionTypes.RECEIVED_POST_PINNED,
+ postId
});
};
}
@@ -336,7 +337,8 @@ export function unpinPost(postId) {
await PostActions.unpinPost(postId)(doDispatch, doGetState);
AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_POST_UNPINNED
+ type: ActionTypes.RECEIVED_POST_UNPINNED,
+ postId
});
};
}
diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx
index 184013179..da64e209d 100644
--- a/webapp/actions/websocket_actions.jsx
+++ b/webapp/actions/websocket_actions.jsx
@@ -261,6 +261,12 @@ function handlePostEditEvent(msg) {
viewChannel(ChannelStore.getCurrentId())(dispatch, getState);
}
}
+
+ // Needed for search store
+ AppDispatcher.handleViewAction({
+ type: Constants.ActionTypes.POST_UPDATED,
+ post
+ });
}
function handlePostDeleteEvent(msg) {
diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx
index 56b91fe68..929dc379e 100644
--- a/webapp/components/search_results_item.jsx
+++ b/webapp/components/search_results_item.jsx
@@ -1,25 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
import PostMessageContainer from 'components/post_view/post_message_view';
import UserProfile from './user_profile.jsx';
import FileAttachmentListContainer from 'components/file_attachment_list';
import ProfilePicture from './profile_picture.jsx';
import CommentIcon from 'components/common/comment_icon.jsx';
+import DotMenu from 'components/dot_menu';
+import PostFlagIcon from 'components/post_view/post_flag_icon.jsx';
import TeamStore from 'stores/team_store.jsx';
-import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
-import {flagPost, unflagPost} from 'actions/post_actions.jsx';
-import PostFlagIcon from 'components/post_view/post_flag_icon.jsx';
-
import * as Utils from 'utils/utils.jsx';
import * as PostUtils from 'utils/post_utils.jsx';
-
import Constants from 'utils/constants.jsx';
-const ActionTypes = Constants.ActionTypes;
import React from 'react';
import PropTypes from 'prop-types';
@@ -31,17 +26,34 @@ export default class SearchResultsItem extends React.Component {
super(props);
this.handleFocusRHSClick = this.handleFocusRHSClick.bind(this);
+ this.handleJumpClick = this.handleJumpClick.bind(this);
+ this.handleDropdownOpened = this.handleDropdownOpened.bind(this);
this.shrinkSidebar = this.shrinkSidebar.bind(this);
- this.unflagPost = this.unflagPost.bind(this);
- this.flagPost = this.flagPost.bind(this);
this.state = {
currentTeamDisplayName: TeamStore.getCurrent().name,
width: '',
- height: ''
+ height: '',
+ dropdownOpened: false
};
}
+ shouldComponentUpdate(nextProps, nextState) {
+ if (!Utils.areObjectsEqual(nextState.post, this.props.post)) {
+ return true;
+ }
+
+ if (nextProps.isFlagged !== this.props.isFlagged) {
+ return true;
+ }
+
+ if (nextState.dropdownOpened !== this.state.dropdownOpened) {
+ return true;
+ }
+
+ return false;
+ }
+
componentDidMount() {
window.addEventListener('resize', () => {
Utils.updateWindowDimensions(this);
@@ -54,10 +66,6 @@ export default class SearchResultsItem extends React.Component {
});
}
- hideSidebar() {
- $('.sidebar--right').removeClass('move--left');
- }
-
shrinkSidebar() {
setTimeout(() => {
this.props.shrink();
@@ -69,14 +77,19 @@ export default class SearchResultsItem extends React.Component {
GlobalActions.emitPostFocusRightHandSideFromSearch(this.props.post, this.props.isMentionSearch);
}
- flagPost(e) {
- e.preventDefault();
- flagPost(this.props.post.id);
+ handleJumpClick() {
+ if (Utils.isMobile()) {
+ GlobalActions.toggleSideBarAction(false);
+ }
+
+ this.shrinkSidebar();
+ browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/pl/' + this.props.post.id);
}
- unflagPost(e) {
- e.preventDefault();
- unflagPost(this.props.post.id);
+ handleDropdownOpened = (isOpened) => {
+ this.setState({
+ dropdownOpened: isOpened
+ });
}
timeTag(post) {
@@ -109,6 +122,20 @@ export default class SearchResultsItem extends React.Component {
);
}
+ getClassName = () => {
+ let className = 'post post--thread';
+
+ if (this.props.compactDisplay) {
+ className = ' post--compact';
+ }
+
+ if (this.state.dropdownOpened) {
+ className += ' post--hovered';
+ }
+
+ return className;
+ }
+
render() {
let channelName = null;
const channel = this.props.channel;
@@ -160,11 +187,7 @@ export default class SearchResultsItem extends React.Component {
);
- let compactClass = '';
const profilePicContainer = (<div className='post__img'>{profilePic}</div>);
- if (this.props.compactDisplay) {
- compactClass = ' post--compact';
- }
let postClass = '';
if (PostUtils.isEdited(this.props.post)) {
@@ -205,6 +228,13 @@ export default class SearchResultsItem extends React.Component {
rhsControls = (
<div className='col__controls'>
+ <DotMenu
+ idPrefix={Constants.SEARCH_POST}
+ idCount={idCount}
+ post={post}
+ isFlagged={this.props.isFlagged}
+ handleDropdownOpened={this.handleDropdownOpened}
+ />
<CommentIcon
idPrefix={'searchCommentIcon'}
idCount={idCount}
@@ -212,32 +242,7 @@ export default class SearchResultsItem extends React.Component {
searchStyle={'search-item__comment'}
/>
<a
- onClick={
- () => {
- if (Utils.isMobile()) {
- AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_SEARCH,
- results: null
- });
-
- AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_SEARCH_TERM,
- term: null,
- do_search: false,
- is_mention_search: false
- });
-
- AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_POST_SELECTED,
- postId: null
- });
-
- this.hideSidebar();
- }
- this.shrinkSidebar();
- browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/pl/' + post.id);
- }
- }
+ onClick={this.handleJumpClick}
className='search-item__jump'
>
<FormattedMessage
@@ -284,28 +289,23 @@ export default class SearchResultsItem extends React.Component {
/>
</div>
</div>
- <div
- className={'post post--thread ' + compactClass}
- >
- <div
- id={idCount === -1 ? null : Utils.createSafeId('searchChannelName' + idCount)}
- className='search-channel__name'
- >
- {channelName}
- </div>
+ <div className={this.getClassName()}>
+ <div className='search-channel__name'>{channelName}</div>
<div className='post__content'>
{profilePicContainer}
<div>
<div className='post__header'>
- <div className='col col__name'><strong>
- <UserProfile
- user={user}
- overwriteName={overrideUsername}
- disablePopover={disableProfilePopover}
- status={this.props.status}
- isBusy={this.props.isBusy}
- />
- </strong></div>
+ <div className='col col__name'>
+ <strong>
+ <UserProfile
+ user={user}
+ overwriteName={overrideUsername}
+ disablePopover={disableProfilePopover}
+ status={this.props.status}
+ isBusy={this.props.isBusy}
+ />
+ </strong>
+ </div>
{botIndicator}
<div className='col'>
{this.renderTimeTag(post)}
diff --git a/webapp/stores/search_store.jsx b/webapp/stores/search_store.jsx
index 7c9c4b8ef..5dfea6867 100644
--- a/webapp/stores/search_store.jsx
+++ b/webapp/stores/search_store.jsx
@@ -120,6 +120,17 @@ class SearchStoreClass extends EventEmitter {
}
}
+ updatePost(post) {
+ const results = this.getSearchResults();
+ if (results == null) {
+ return;
+ }
+
+ if (post.id in results.posts) {
+ results.posts[post.id] = Object.assign({}, post);
+ }
+ }
+
togglePinPost(postId, isPinned) {
const results = this.getSearchResults();
if (results == null || results.posts == null) {
@@ -176,12 +187,16 @@ SearchStore.dispatchToken = AppDispatcher.register((payload) => {
SearchStore.deletePost(action.post);
SearchStore.emitSearchChange();
break;
+ case ActionTypes.POST_UPDATED:
+ SearchStore.updatePost(action.post);
+ SearchStore.emitSearchChange();
+ break;
case ActionTypes.RECEIVED_POST_PINNED:
- SearchStore.togglePinPost(action.reaction, true);
+ SearchStore.togglePinPost(action.postId, true);
SearchStore.emitSearchChange();
break;
case ActionTypes.RECEIVED_POST_UNPINNED:
- SearchStore.togglePinPost(action.reaction, false);
+ SearchStore.togglePinPost(action.postId, false);
SearchStore.emitSearchChange();
break;
case ActionTypes.REMOVE_POST:
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 4ff20854f..ddebec293 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -965,7 +965,8 @@ export const Constants = {
SHOW_USERNAME: 'username',
SHOW_NICKNAME_FULLNAME: 'nickname_full_name',
SHOW_FULLNAME: 'full_name'
- }
+ },
+ SEARCH_POST: 'searchpost'
};
export default Constants;
diff --git a/webapp/yarn.lock b/webapp/yarn.lock
index a2e48a39d..0b6275bcf 100644
--- a/webapp/yarn.lock
+++ b/webapp/yarn.lock
@@ -111,13 +111,7 @@ ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-ansi-styles@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.0.0.tgz#5404e93a544c4fec7f048262977bebfe3155e0c1"
- dependencies:
- color-convert "^1.0.0"
-
-ansi-styles@^3.1.0:
+ansi-styles@^3.0.0, ansi-styles@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750"
dependencies:
@@ -274,13 +268,7 @@ async@^1.4.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
-async@^2.1.2, async@^2.1.4, async@^2.1.5:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
- dependencies:
- lodash "^4.14.0"
-
-async@^2.4.1:
+async@^2.1.2, async@^2.1.4, async@^2.1.5, async@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
dependencies:
@@ -342,7 +330,7 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
-babel-core@6.25.0:
+babel-core@6.25.0, babel-core@^6.0.0, babel-core@^6.24.1:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729"
dependencies:
@@ -366,30 +354,6 @@ babel-core@6.25.0:
slash "^1.0.0"
source-map "^0.5.0"
-babel-core@^6.0.0, babel-core@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83"
- dependencies:
- babel-code-frame "^6.22.0"
- babel-generator "^6.24.1"
- babel-helpers "^6.24.1"
- babel-messages "^6.23.0"
- babel-register "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
- babylon "^6.11.0"
- convert-source-map "^1.1.0"
- debug "^2.1.1"
- json5 "^0.5.0"
- lodash "^4.2.0"
- minimatch "^3.0.2"
- path-is-absolute "^1.0.0"
- private "^0.1.6"
- slash "^1.0.0"
- source-map "^0.5.0"
-
babel-eslint@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.1.1.tgz#8a6a884f085aa7060af69cfc77341c2f99370fb2"
@@ -400,20 +364,7 @@ babel-eslint@7.1.1:
babylon "^6.13.0"
lodash.pickby "^4.6.0"
-babel-generator@^6.18.0, babel-generator@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497"
- dependencies:
- babel-messages "^6.23.0"
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
- detect-indent "^4.0.0"
- jsesc "^1.3.0"
- lodash "^4.2.0"
- source-map "^0.5.0"
- trim-right "^1.0.1"
-
-babel-generator@^6.25.0:
+babel-generator@^6.18.0, babel-generator@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc"
dependencies:
@@ -1071,17 +1022,7 @@ babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0:
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
-babel-template@^6.16.0, babel-template@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
- dependencies:
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
- babylon "^6.11.0"
- lodash "^4.2.0"
-
-babel-template@^6.25.0:
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071"
dependencies:
@@ -1091,21 +1032,7 @@ babel-template@^6.25.0:
babylon "^6.17.2"
lodash "^4.2.0"
-babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
- dependencies:
- babel-code-frame "^6.22.0"
- babel-messages "^6.23.0"
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
- babylon "^6.15.0"
- debug "^2.2.0"
- globals "^9.0.0"
- invariant "^2.2.0"
- lodash "^4.2.0"
-
-babel-traverse@^6.25.0:
+babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1"
dependencies:
@@ -1119,16 +1046,7 @@ babel-traverse@^6.25.0:
invariant "^2.2.0"
lodash "^4.2.0"
-babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
- dependencies:
- babel-runtime "^6.22.0"
- esutils "^2.0.2"
- lodash "^4.2.0"
- to-fast-properties "^1.0.1"
-
-babel-types@^6.25.0:
+babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e"
dependencies:
@@ -1137,11 +1055,7 @@ babel-types@^6.25.0:
lodash "^4.2.0"
to-fast-properties "^1.0.1"
-babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0:
- version "6.17.0"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.0.tgz#37da948878488b9c4e3c4038893fa3314b3fc932"
-
-babylon@^6.17.2:
+babylon@^6.13.0, babylon@^6.17.2:
version "6.17.4"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a"
@@ -2098,13 +2012,13 @@ debug@2.6.1:
dependencies:
ms "0.7.2"
-debug@2.6.7, debug@^2.6.3:
+debug@2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
dependencies:
ms "2.0.0"
-debug@^2.1.1, debug@^2.2.0:
+debug@^2.1.1, debug@^2.2.0, debug@^2.6.3:
version "2.6.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0"
dependencies:
@@ -5095,7 +5009,6 @@ mattermost-redux@mattermost/mattermost-redux#master:
deep-equal "1.0.1"
harmony-reflect "1.5.1"
isomorphic-fetch "2.2.1"
- key-mirror "1.0.1"
mime-db "1.27.0"
redux "3.6.0"
redux-action-buffer "1.0.1"
@@ -5488,11 +5401,7 @@ number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
-"nwmatcher@>= 1.3.9 < 2.0.0":
- version "1.3.9"
- resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a"
-
-nwmatcher@^1.4.1:
+"nwmatcher@>= 1.3.9 < 2.0.0", nwmatcher@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f"
@@ -7656,18 +7565,18 @@ ua-parser-js@^0.7.9:
version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
-uglify-js@^2.6, uglify-js@~2.8.22:
- version "2.8.22"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
+uglify-js@^2.6, uglify-js@^2.8.29:
+ version "2.8.29"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
optionalDependencies:
uglify-to-browserify "~1.0.0"
-uglify-js@^2.8.29:
- version "2.8.29"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+uglify-js@~2.8.22:
+ version "2.8.22"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
@@ -7816,7 +7725,7 @@ utils-merge@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
-uuid@3.0.1, uuid@^3.0.0:
+uuid@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
@@ -7824,7 +7733,7 @@ uuid@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
-uuid@^3.0.1:
+uuid@^3.0.0, uuid@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"