-
-
Notifications
You must be signed in to change notification settings - Fork 827
Conversation
such that: - it takes a targetTag to be replaced instead the previous tag to insert after - it optionally displaces the targetTag before or after the inserted tag
Also, make defaults sensible
This has sprouted a riot-web PR - element-hq/element-web#5790 |
Becuase the tests rely on being able to inspect the state of MatrixChat
React DnD specifies functions with upper-case first letters
tag: monitor.getItem().tag, | ||
targetTag: props.groupProfile.groupId, | ||
// Note: we indicate that the tag should be after the target when | ||
// it's being dragged over the top half of the target. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bottom half, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually no, it really is being dragged over the top half. I just found this snappier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, so it is - so after == above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, after == below. It feels snappier when you move a tile over the top half of another tile and the target is replaced with the one you're dragging, i.e. it's placed after the target.
src/stores/TagOrderStore.js
Outdated
// Initialise the state such that if account data is unset, default to the existing ordering | ||
case 'all_tags': | ||
this._setState({ | ||
allTags: payload.tags.sort(), // Sort lexically |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will do the right thing when you join a new group: the new group will be added to allTags
but won't propagate to orderedTags
which is what the TagPanel reads, so they new group won't show up? Somewhere we'll have to work out what changed in the new set of tags and make the equivalent change to the orderedTags
, preserving the order.
I assume the idea here is that the TagOrderStore knows nothing about groups, but it doesn't seem great that it's the responsibility of a component to give the store the set of all tags, ie. that component has to be mounted once (and only once?) in the view for the store to work. I'd guess the pattern I'd expect here would be to have another store or something for the complete set of tags, then the TagOrderStore consumes that and exposes the same info but ordered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's the responsibility of a component to give the store the set of all tags
I could move the fetch to get the list of groups to the TagOrderStore. The issue is that this would be perfect in an action creator, something that we haven't done before. Perhaps we should go and make a bunch of action creators and formalises all of our existing dispatches by wrapping them in functions (which is standard in other apps AFAICT).
have another store or something for the complete set of tags, then the TagOrderStore consumes that
Stores really should not communicate. all_tags
is already being consumed by another store, and I believe the general pattern is to duplicate state as required such that the state of the store really only depends on its own previous state and the actions it receives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will do the right thing when you join a new group
This is true. If only our store could listen for the group membership update...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having TagOrderStore fetch the list of groups is fine by me
@@ -344,3 +346,5 @@ export default React.createClass({ | |||
); | |||
}, | |||
}); | |||
|
|||
export default DragDropContext(HTML5Backend)(LoggedInView); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know little about react-dnd but I assume this still allows us to have other drag-n-drop contexts within it (ie. is it going to break the RoomTile DND?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point of moving it to the root LoggedInView is such that we can actually do DnD wherever we please. The instructions said to wrap the entire app, using two contexts (on e.g. TagPanel and LeftPanel) causes bugs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok 👍
These can be used to dispatch actions immediately, or after some asynchronous work has been done. Also, create GroupActions.fetchJoinedGroups as an example. The concept of async action creators can be used in the following cases: - stores or views that do async work, dispatching based on the results - actions that have complicated payloads, would make more sense as functions with documentation that dispatch created actions.
We agreed that I shall:
|
This introduces a generic way to register certain events emitted by the js-sdk as those that should be propagated through as dispatched actions. This allows the store to treat the js-sdk as the "Server" in the Flux data flow model. It also allows for stores to not be aware specifically of the matrix client if they are only reading from it.
422f083
to
1251544
Compare
Separating actions from views is mostly separation of concerns (we don't want our views doing async requests) but it's also nice to be able to use them from anywhere (without refactoring them later). |
src/actions/GroupActions.js
Outdated
@@ -18,6 +18,14 @@ import { asyncAction } from './actionCreators'; | |||
|
|||
const GroupActions = {}; | |||
|
|||
/** | |||
* Create a GroupActions.fetchJoinedGroups action that represents an | |||
* asyncronous request to fetch the groups to which a user is joined. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asynchronous
src/actions/GroupActions.js
Outdated
@@ -18,6 +18,14 @@ import { asyncAction } from './actionCreators'; | |||
|
|||
const GroupActions = {}; | |||
|
|||
/** | |||
* Create a GroupActions.fetchJoinedGroups action that represents an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not aiui.
It returns an action creator: ie, a function which, when called, will start such a request and create such a (set of) actions.
src/actions/MatrixActionCreators.js
Outdated
@@ -19,8 +19,7 @@ import dis from '../dispatcher'; | |||
// TODO: migrate from sync_state to MatrixActions.sync so that more js-sdk events | |||
// become dispatches in the same place. | |||
/** | |||
* An action creator that will map a `sync` event to a MatrixActions.sync action, | |||
* each parameter mapping to a key-value in the action. | |||
* Create a MatrixActions.sync action that represents a MatrixClient `sync` event. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, we should still document the members of the action object imho.
src/actions/MatrixActionCreators.js
Outdated
* An action creator that will map an account data matrix event to a | ||
* MatrixActions.accountData action. | ||
* Create a MatrixActions.accountData action that represents a MatrixClient `accountData` | ||
* matrix event. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(it would help my brain if you could give some examples of what event_type
is likely to be, here)
src/actions/MatrixActionCreators.js
Outdated
* | ||
* @param {MatrixClient} matrixClient the matrix client with which to | ||
* register a listener. | ||
* @param {MatrixClient} matrixClient the matrix client. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we pass this in, given it's ignored?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically so that we can handle both action creators the same in _addMatrixClientListener
src/actions/MatrixActionCreators.js
Outdated
start(matrixClient) { | ||
this._addMatrixClientListener(matrixClient, 'sync', createSyncAction); | ||
this._addMatrixClientListener(matrixClient, 'accountData', createAccountDataAction); | ||
}, | ||
|
||
/** | ||
* Start listening to events emitted by matrixClient, dispatch an action created by the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a word missing here?
src/actions/MatrixActionCreators.js
Outdated
* actionCreator function. | ||
* @param {MatrixClient} matrixClient a MatrixClient to register a listener with. | ||
* @param {string} eventName the event to listen to on MatrixClient. | ||
* @param {function} actionCreator a function that should return an action to dispatch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you also specify that the function will be passed the MatrixClient event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming you meant MatrixClient itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both, but yes.
@@ -36,7 +36,15 @@ const TagPanel = React.createClass({ | |||
|
|||
getInitialState() { | |||
return { | |||
orderedGroupTagProfiles: [], | |||
// A list of group profiles for group tags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't mean a great deal to me. Probably merits a longer explanation.
think luke has addressed dave's concerns
// A list of group profiles for group tags | ||
// A list of group profiles for tags that are group IDs. The intention in future | ||
// is to allow arbitrary tags to be selected in the TagPanel, not just groups. | ||
// For now, it suffices to maintain a list of ordered group profiles. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/actions/GroupActions.js
Outdated
const GroupActions = {}; | ||
|
||
/** | ||
* Create a GroupActions.fetchJoinedGroups action that represents an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is still incorrect
src/actions/TagOrderActions.js
Outdated
const TagOrderActions = {}; | ||
|
||
/** | ||
* Create a TagOrderActions.commitTagOrdering action that represents an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as with GroupActions.fetchJoinedGroups, I don't think this is correct.
Note: element-hq/element-web#5790 needs to merged in parallel this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
Add ability to reorder the TagPanel items.
This works by having a TagOrderStore that stores the tags shown in the TagPanel in an order that the user controls via DnD. The full list of tags is stored in the im.vector.web.tag_ordering account event. By default, the ordering is alphabetical.