diff --git a/README.md b/README.md
index 0bf5baf2..b836af10 100644
--- a/README.md
+++ b/README.md
@@ -10,20 +10,19 @@ Try it (possibly older version) live at http://api.tinode.co/x/example-react-js/
License: [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0)
-Photos from https://www.pexels.com/ under [CC0 license](https://www.pexels.com/photo-license/).
+Sample avatar photos from https://www.pexels.com/ under [CC0 license](https://www.pexels.com/photo-license/).
Background pattern from http://subtlepatterns.com/, commercial and non-commercial use allowed with attribution.
## Missing functionality
-* Cannot manage members of group chats.
* Cannot send images or other media.
* No typing indicators.
* No indication of chat status (muted, blocked, etc.).
* Long polling as a wire transport does not work.
* Browser push notifications are missing.
* No encryption.
-* Editing chat parameters is incomplete.
+* Editing chat permissions is incomplete.
## Responsive design
diff --git a/css/base.css b/css/base.css
index af8956e2..a8229b6a 100644
--- a/css/base.css
+++ b/css/base.css
@@ -257,6 +257,16 @@ ul.menu > li.separator:hover {
.red {
color: #D32F2F; /* red 700 */
}
+
+.hr {
+ display: block;
+ width: 100%;
+ height: 0.6rem;
+ background-color: #f0f0f0;
+ box-shadow: inset 0 0.25rem 0.25rem -0.25rem rgba(0,0,0,0.15),
+ inset 0 -0.25rem 0.25rem -0.25rem rgba(0,0,0,0.15);
+}
+
/* END generic text colors */
/* END of basic elements */
@@ -1274,6 +1284,7 @@ ul.tabbar li.active > a:after {
.chip-input {
display: flex;
flex-wrap: wrap;
+ flex-grow: 1;
cursor: text;
font-size: 1.1rem;
font-weight: normal;
@@ -1282,7 +1293,8 @@ ul.tabbar li.active > a:after {
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
transition: all 0.1s ease-in-out;
width: 100%;
- max-height: 8rem;
+ max-height: 10rem;
+ min-height: 4rem;
overflow-y: scroll;
margin: 0.25rem 0rem 0.25rem 0rem;
padding: 0 0 0.5rem 0.5rem;
@@ -1355,3 +1367,10 @@ ul.tabbar li.active > a:after {
.chip .avatar-box .material-icons {
font-size: 1.8rem;
}
+
+.chip .spacer {
+ display: inline-block;
+ margin: 0.3rem;
+ width: 0.25rem;
+ height: 1.175rem;
+}
diff --git a/index.html b/index.html
index 9f2ee3d0..6258fd7a 100644
--- a/index.html
+++ b/index.html
@@ -347,26 +347,55 @@
getInitialState: function() {
return {
placeholder: this.props.chips ? "" : this.props.prompt,
+ sortedChips: this.sortChips(this.props.chips, this.props.required),
+ chipIndex: this.indexChips(this.props.chips),
input: '',
focused: false
};
},
+
componentWillReceiveProps: function(newProps) {
this.setState({
- input: ''
+ sortedChips: this.sortChips(newProps.chips, newProps.required),
+ chipIndex: this.indexChips(newProps.chips)
});
},
+ // Map chip index to user name
+ indexChips: function(chips) {
+ var index = {};
+ var count = 0;
+ chips.map(function(item) {
+ index[item.user] = count;
+ count ++;
+ });
+ return index;
+ },
+
+ // Have non-removable chips appear before all other chips.
+ sortChips: function(chips, keep) {
+ var required = [];
+ var normal = [];
+ chips.map(function(item) {
+ if (item.user === keep) {
+ required.push(item);
+ } else {
+ normal.push(item);
+ }
+ });
+ return required.concat(normal);
+ },
+
handleTextInput: function(e) {
this.setState({input: e.target.value});
- if (this.props.filter) {
- this.props.filter(e.target.value);
+ if (this.props.filterFunc) {
+ this.props.filterFunc(e.target.value);
}
},
removeChipAt: function(idx) {
- var removed = this.props.chips[idx];
- this.props.onChipRemoved(removed.user, idx);
+ var removed = this.state.sortedChips[idx];
+ this.props.onChipRemoved(removed.user, this.state.chipIndex[removed.user]);
},
handleChipCancel: function(item, idx) {
@@ -383,25 +412,30 @@
handleKeyDown: function(e) {
if (e.key === 'Backspace') {
- if (this.state.input.length == 0 && this.props.chips.length > 0) {
- this.removeChipAt(this.props.chips.length-1);
+ if (this.state.input.length == 0 && this.state.sortedChips.length > 0) {
+ var at = this.state.sortedChips.length - 1;
+ if (this.state.sortedChips[at].user !== this.props.required) {
+ this.removeChipAt(at);
+ }
}
}
},
render: function() {
var chips = [];
+
var instance = this;
var count = 0;
- this.props.chips.map(function(item) {
+ this.state.sortedChips.map(function(item) {
chips.push(