diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js
index 8b3a368f4d..2ab635081f 100644
--- a/src/HtmlUtils.js
+++ b/src/HtmlUtils.js
@@ -186,7 +186,7 @@ module.exports = {
*
* highlights: optional list of words to highlight, ordered by longest word first
*
- * opts.highlightLink: optional href to add to highlights
+ * opts.highlightLink: optional href to add to highlighted words
*/
bodyToHtml: function(content, highlights, opts) {
opts = opts || {};
diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js
index 305994aa0e..39f393b242 100644
--- a/src/UserSettingsStore.js
+++ b/src/UserSettingsStore.js
@@ -113,6 +113,35 @@ module.exports = {
});
},
+ getUrlPreviewsDisabled: function() {
+ var event = MatrixClientPeg.get().getAccountData("org.matrix.preview_urls");
+ return (event && event.getContent().disable);
+ },
+
+ setUrlPreviewsDisabled: function(disabled) {
+ // FIXME: handle errors
+ MatrixClientPeg.get().setAccountData("org.matrix.preview_urls", {
+ disable: disabled
+ });
+ },
+
+ getSyncedSettings: function() {
+ var event = MatrixClientPeg.get().getAccountData("im.vector.web.settings");
+ return event ? event.getContent() : {};
+ },
+
+ getSyncedSetting: function(type) {
+ var settings = this.getSyncedSettings();
+ return settings[type];
+ },
+
+ setSyncedSetting: function(type, value) {
+ var settings = this.getSyncedSettings();
+ settings[type] = value;
+ // FIXME: handle errors
+ MatrixClientPeg.get().setAccountData("im.vector.web.settings", settings);
+ },
+
isFeatureEnabled: function(feature: string): boolean {
return localStorage.getItem(`mx_labs_feature_${feature}`) === 'true';
},
diff --git a/src/component-index.js b/src/component-index.js
index 4aa0efe21f..5fadb18b6a 100644
--- a/src/component-index.js
+++ b/src/component-index.js
@@ -74,6 +74,8 @@ module.exports.components['views.messages.TextualEvent'] = require('./components
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
module.exports.components['views.room_settings.AliasSettings'] = require('./components/views/room_settings/AliasSettings');
module.exports.components['views.room_settings.ColorSettings'] = require('./components/views/room_settings/ColorSettings');
+module.exports.components['views.room_settings.UrlPreviewSettings'] = require('./components/views/room_settings/UrlPreviewSettings');
+module.exports.components['views.rooms.Autocomplete'] = require('./components/views/rooms/Autocomplete');
module.exports.components['views.rooms.AuxPanel'] = require('./components/views/rooms/AuxPanel');
module.exports.components['views.rooms.EntityTile'] = require('./components/views/rooms/EntityTile');
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index c8e878118b..53efac6406 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -44,6 +44,9 @@ module.exports = React.createClass({
// ID of an event to highlight. If undefined, no event will be highlighted.
highlightedEventId: React.PropTypes.string,
+ // Should we show URL Previews
+ showUrlPreview: React.PropTypes.bool,
+
// event after which we should show a read marker
readMarkerEventId: React.PropTypes.string,
@@ -365,6 +368,7 @@ module.exports = React.createClass({
onWidgetLoad={this._onWidgetLoad}
readReceipts={readReceipts}
readReceiptMap={this._readReceiptMap}
+ showUrlPreview={this.props.showUrlPreview}
checkUnmounting={this._isUnmounting}
eventSendStatus={mxEv.status}
last={last} isSelectedEvent={highlight}/>
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index abcccc48b8..f73b90ae28 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -338,6 +338,10 @@ module.exports = React.createClass({
// ignore events for other rooms
if (!this.state.room || room.roomId != this.state.room.roomId) return;
+ if (ev.getType() === "org.matrix.room.preview_urls") {
+ this._updatePreviewUrlVisibility(room);
+ }
+
// ignore anything but real-time updates at the end of the room:
// updates from pagination will happen when the paginate completes.
if (toStartOfTimeline || !data || !data.liveEvent) return;
@@ -371,6 +375,7 @@ module.exports = React.createClass({
// after a successful peek, or after we join the room).
_onRoomLoaded: function(room) {
this._calculatePeekRules(room);
+ this._updatePreviewUrlVisibility(room);
},
_calculatePeekRules: function(room) {
@@ -389,6 +394,42 @@ module.exports = React.createClass({
}
},
+ _updatePreviewUrlVisibility: function(room) {
+ console.log("_updatePreviewUrlVisibility");
+
+ // check our per-room overrides
+ var roomPreviewUrls = room.getAccountData("org.matrix.room.preview_urls");
+ if (roomPreviewUrls && roomPreviewUrls.getContent().disable !== undefined) {
+ this.setState({
+ showUrlPreview: !roomPreviewUrls.getContent().disable
+ });
+ return;
+ }
+
+ // check our global disable override
+ var userRoomPreviewUrls = MatrixClientPeg.get().getAccountData("org.matrix.preview_urls");
+ if (userRoomPreviewUrls && userRoomPreviewUrls.getContent().disable) {
+ this.setState({
+ showUrlPreview: false
+ });
+ return;
+ }
+
+ // check the room state event
+ var roomStatePreviewUrls = room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
+ if (roomStatePreviewUrls && roomStatePreviewUrls.getContent().disable) {
+ this.setState({
+ showUrlPreview: false
+ });
+ return;
+ }
+
+ // otherwise, we assume they're on.
+ this.setState({
+ showUrlPreview: true
+ });
+ },
+
onRoom: function(room) {
// This event is fired when the room is 'stored' by the JS SDK, which
// means it's now a fully-fledged room object ready to be used, so
@@ -419,14 +460,17 @@ module.exports = React.createClass({
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
},
- onRoomAccountData: function(room, event) {
- if (room.roomId == this.props.roomId) {
- if (event.getType === "org.matrix.room.color_scheme") {
+ onRoomAccountData: function(event, room) {
+ if (room.roomId == this.state.roomId) {
+ if (event.getType() === "org.matrix.room.color_scheme") {
var color_scheme = event.getContent();
// XXX: we should validate the event
console.log("Tinter.tint from onRoomAccountData");
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
}
+ else if (event.getType() === "org.matrix.room.preview_urls") {
+ this._updatePreviewUrlVisibility(room);
+ }
}
},
@@ -1506,6 +1550,8 @@ module.exports = React.createClass({
hideMessagePanel = true;
}
+ console.log("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
+
var messagePanel = (