diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss
index 6c85341aaf..2683a32dae 100644
--- a/res/css/structures/_TagPanel.scss
+++ b/res/css/structures/_TagPanel.scss
@@ -76,12 +76,56 @@ limitations under the License.
// opacity: 0.5;
position: relative;
}
+
+.mx_TagPanel .mx_TagTile.mx_TagTile_prototype {
+ padding: 3px;
+}
+
.mx_TagPanel .mx_TagTile:focus,
.mx_TagPanel .mx_TagTile:hover,
.mx_TagPanel .mx_TagTile.mx_TagTile_selected {
// opacity: 1;
}
+.mx_TagPanel .mx_TagTile.mx_TagTile_selected_prototype {
+ background-color: $primary-bg-color;
+ border-radius: 6px;
+}
+
+.mx_TagTile_selected_prototype {
+ .mx_TagTile_homeIcon::before {
+ background-color: $primary-fg-color; // dark-on-light
+ }
+}
+
+.mx_TagTile:not(.mx_TagTile_selected_prototype) .mx_TagTile_homeIcon {
+ background-color: $icon-button-color; // XXX: Variable abuse
+ border-radius: 48px;
+
+ &::before {
+ background-color: $primary-bg-color; // light-on-grey
+ }
+}
+
+.mx_TagTile_homeIcon {
+ width: 32px;
+ height: 32px;
+ position: relative;
+
+ &::before {
+ mask-image: url('$(res)/img/element-icons/home.svg');
+ mask-position: center;
+ mask-repeat: no-repeat;
+ width: 21px;
+ height: 21px;
+ content: '';
+ display: inline-block;
+ position: absolute;
+ top: calc(50% - 10.5px);
+ left: calc(50% - 10.5px);
+ }
+}
+
.mx_TagPanel .mx_TagTile_plus {
margin-bottom: 12px;
height: 32px;
@@ -116,10 +160,6 @@ limitations under the License.
border-radius: 0 3px 3px 0;
}
-.mx_TagPanel .mx_TagTile.mx_TagTile_large.mx_TagTile_selected::before {
- left: -10px;
-}
-
.mx_TagPanel .mx_TagTile.mx_AccessibleButton:focus {
filter: none;
}
diff --git a/res/img/element-icons/home.svg b/res/img/element-icons/home.svg
new file mode 100644
index 0000000000..d65812cafd
--- /dev/null
+++ b/res/img/element-icons/home.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx
index 839d4bccda..30be71abcb 100644
--- a/src/components/structures/UserMenu.tsx
+++ b/src/components/structures/UserMenu.tsx
@@ -42,9 +42,6 @@ import IconizedContextMenu, {
IconizedContextMenuOption,
IconizedContextMenuOptionList
} from "../views/context_menus/IconizedContextMenu";
-import TagOrderStore from "../../stores/TagOrderStore";
-import * as fbEmitter from "fbemitter";
-import FlairStore from "../../stores/FlairStore";
interface IProps {
isMinimized: boolean;
@@ -55,16 +52,11 @@ type PartialDOMRect = Pick;
interface IState {
contextMenuPosition: PartialDOMRect;
isDarkTheme: boolean;
- selectedCommunityProfile: {
- displayName: string;
- avatarMxc: string;
- };
}
export default class UserMenu extends React.Component {
private dispatcherRef: string;
private themeWatcherRef: string;
- private tagStoreRef: fbEmitter.EventSubscription;
private buttonRef: React.RefObject = createRef();
constructor(props: IProps) {
@@ -73,7 +65,6 @@ export default class UserMenu extends React.Component {
this.state = {
contextMenuPosition: null,
isDarkTheme: this.isUserOnDarkTheme(),
- selectedCommunityProfile: null,
};
OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate);
@@ -86,7 +77,6 @@ export default class UserMenu extends React.Component {
public componentDidMount() {
this.dispatcherRef = defaultDispatcher.register(this.onAction);
this.themeWatcherRef = SettingsStore.watchSetting("theme", null, this.onThemeChanged);
- this.tagStoreRef = TagOrderStore.addListener(this.onTagStoreUpdate);
}
public componentWillUnmount() {
@@ -103,25 +93,6 @@ export default class UserMenu extends React.Component {
return theme === "dark";
}
- private onTagStoreUpdate = async () => {
- if (!SettingsStore.getValue("feature_communities_v2_prototypes")) {
- return;
- }
-
- const selectedId = TagOrderStore.getSelectedTags()[0];
- if (!selectedId) {
- this.setState({selectedCommunityProfile: null});
- return;
- }
-
- // For some reason the group's profile info isn't on the js-sdk Group object but
- // is in the flair store, so get it from there.
- const profile = await FlairStore.getGroupProfileCached(MatrixClientPeg.get(), selectedId);
- const displayName = profile.name || selectedId;
- const avatarMxc = profile.avatarUrl;
- this.setState({selectedCommunityProfile: {displayName, avatarMxc}});
- };
-
private onProfileUpdate = async () => {
// the store triggered an update, so force a layout update. We don't
// have any state to store here for that to magically happen.
@@ -324,18 +295,8 @@ export default class UserMenu extends React.Component {
public render() {
const avatarSize = 32; // should match border-radius of the avatar
- let displayName = OwnProfileStore.instance.displayName || MatrixClientPeg.get().getUserId();
- let avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
-
- if (this.state.selectedCommunityProfile) {
- displayName = this.state.selectedCommunityProfile.displayName
- const mxc = this.state.selectedCommunityProfile.avatarMxc;
- if (mxc) {
- avatarUrl = MatrixClientPeg.get().mxcUrlToHttp(mxc, avatarSize, avatarSize);
- } else {
- avatarUrl = null;
- }
- }
+ const displayName = OwnProfileStore.instance.displayName || MatrixClientPeg.get().getUserId();
+ const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
let name = {displayName};
let buttons = (
diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js
index 49b336a577..db5eedc274 100644
--- a/src/components/views/elements/TagTile.js
+++ b/src/components/views/elements/TagTile.js
@@ -141,9 +141,12 @@ export default createReactClass({
profile.avatarUrl, avatarHeight, avatarHeight, "crop",
) : null;
+ const isPrototype = SettingsStore.getValue("feature_communities_v2_prototypes");
const className = classNames({
mx_TagTile: true,
- mx_TagTile_selected: this.props.selected,
+ mx_TagTile_prototype: isPrototype,
+ mx_TagTile_selected: this.props.selected && !isPrototype,
+ mx_TagTile_selected_prototype: this.props.selected && isPrototype,
});
const badge = TagOrderStore.getGroupBadge(this.props.tag);
diff --git a/src/components/views/elements/UserTagTile.tsx b/src/components/views/elements/UserTagTile.tsx
index c652423753..912f54edc7 100644
--- a/src/components/views/elements/UserTagTile.tsx
+++ b/src/components/views/elements/UserTagTile.tsx
@@ -16,16 +16,14 @@ limitations under the License.
import React from "react";
import defaultDispatcher from "../../../dispatcher/dispatcher";
-import { OwnProfileStore } from "../../../stores/OwnProfileStore";
-import { UPDATE_EVENT } from "../../../stores/AsyncStore";
import * as fbEmitter from "fbemitter";
import TagOrderStore from "../../../stores/TagOrderStore";
import AccessibleTooltipButton from "./AccessibleTooltipButton";
-import BaseAvatar from "../avatars/BaseAvatar";
-import { MatrixClientPeg } from "../../../MatrixClientPeg";
import classNames from "classnames";
+import { _t } from "../../../languageHandler";
-interface IProps{}
+interface IProps {
+}
interface IState {
selected: boolean;
@@ -43,18 +41,13 @@ export default class UserTagTile extends React.PureComponent {
}
public componentDidMount() {
- OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate);
this.tagStoreRef = TagOrderStore.addListener(this.onTagStoreUpdate);
}
public componentWillUnmount() {
- OwnProfileStore.instance.off(UPDATE_EVENT, this.onProfileUpdate);
+ this.tagStoreRef.remove();
}
- private onProfileUpdate = () => {
- this.forceUpdate();
- };
-
private onTagStoreUpdate = () => {
const selected = TagOrderStore.getSelectedTags().length === 0;
this.setState({selected});
@@ -71,27 +64,20 @@ export default class UserTagTile extends React.PureComponent {
public render() {
// XXX: We reuse TagTile classes for ease of demonstration - we should probably generify
// TagTile instead if we continue to use this component.
- const avatarHeight = 36;
- const name = OwnProfileStore.instance.displayName || MatrixClientPeg.get().getUserId();
const className = classNames({
mx_TagTile: true,
- mx_TagTile_selected: this.state.selected,
- mx_TagTile_large: true,
+ mx_TagTile_prototype: true,
+ mx_TagTile_selected_prototype: this.state.selected,
+ mx_TagTile_home: true,
});
return (
);
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index f3cd1d80b7..d6ba736a76 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1556,6 +1556,7 @@
"And %(count)s more...|other": "And %(count)s more...",
"ex. @bob:example.com": "ex. @bob:example.com",
"Add User": "Add User",
+ "Home": "Home",
"Enter a server name": "Enter a server name",
"Looks good": "Looks good",
"Can't find this server or its room list": "Can't find this server or its room list",
@@ -2113,7 +2114,6 @@
"Uploading %(filename)s and %(count)s others|other": "Uploading %(filename)s and %(count)s others",
"Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s",
"Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other",
- "Home": "Home",
"Switch to light mode": "Switch to light mode",
"Switch to dark mode": "Switch to dark mode",
"Switch theme": "Switch theme",
diff --git a/src/stores/TagOrderStore.js b/src/stores/TagOrderStore.js
index 2b72a963b0..f02fce0769 100644
--- a/src/stores/TagOrderStore.js
+++ b/src/stores/TagOrderStore.js
@@ -166,6 +166,25 @@ class TagOrderStore extends Store {
selectedTags: newTags,
});
+ if (!allowMultiple && newTags.length === 1) {
+ // We're in prototype behaviour: select the general chat for the community
+ const rooms = GroupStore.getGroupRooms(newTags[0])
+ .map(r => MatrixClientPeg.get().getRoom(r.roomId))
+ .filter(r => !!r);
+ let chat = rooms.find(r => {
+ const idState = r.currentState.getStateEvents("im.vector.general_chat", "");
+ if (!idState || idState.getContent()['groupId'] !== newTags[0]) return false;
+ return true;
+ });
+ if (!chat) chat = rooms[0];
+ if (chat) {
+ dis.dispatch({
+ action: 'view_room',
+ room_id: chat.roomId,
+ });
+ }
+ }
+
Analytics.trackEvent('FilterStore', 'select_tag');
}
break;