Merge branch 'travis/communities/tag-panel' into travis/communities/room-behaviour
This commit is contained in:
commit
dc95ca6776
5 changed files with 63 additions and 6 deletions
|
@ -42,6 +42,9 @@ import IconizedContextMenu, {
|
||||||
IconizedContextMenuOption,
|
IconizedContextMenuOption,
|
||||||
IconizedContextMenuOptionList
|
IconizedContextMenuOptionList
|
||||||
} from "../views/context_menus/IconizedContextMenu";
|
} from "../views/context_menus/IconizedContextMenu";
|
||||||
|
import TagOrderStore from "../../stores/TagOrderStore";
|
||||||
|
import * as fbEmitter from "fbemitter";
|
||||||
|
import FlairStore from "../../stores/FlairStore";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
|
@ -52,11 +55,16 @@ type PartialDOMRect = Pick<DOMRect, "width" | "left" | "top" | "height">;
|
||||||
interface IState {
|
interface IState {
|
||||||
contextMenuPosition: PartialDOMRect;
|
contextMenuPosition: PartialDOMRect;
|
||||||
isDarkTheme: boolean;
|
isDarkTheme: boolean;
|
||||||
|
selectedCommunityProfile: {
|
||||||
|
displayName: string;
|
||||||
|
avatarMxc: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class UserMenu extends React.Component<IProps, IState> {
|
export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private themeWatcherRef: string;
|
private themeWatcherRef: string;
|
||||||
|
private tagStoreRef: fbEmitter.EventSubscription;
|
||||||
private buttonRef: React.RefObject<HTMLButtonElement> = createRef();
|
private buttonRef: React.RefObject<HTMLButtonElement> = createRef();
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
|
@ -65,6 +73,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
this.state = {
|
this.state = {
|
||||||
contextMenuPosition: null,
|
contextMenuPosition: null,
|
||||||
isDarkTheme: this.isUserOnDarkTheme(),
|
isDarkTheme: this.isUserOnDarkTheme(),
|
||||||
|
selectedCommunityProfile: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate);
|
OwnProfileStore.instance.on(UPDATE_EVENT, this.onProfileUpdate);
|
||||||
|
@ -77,6 +86,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||||
this.themeWatcherRef = SettingsStore.watchSetting("theme", null, this.onThemeChanged);
|
this.themeWatcherRef = SettingsStore.watchSetting("theme", null, this.onThemeChanged);
|
||||||
|
this.tagStoreRef = TagOrderStore.addListener(this.onTagStoreUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
|
@ -93,6 +103,25 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
return theme === "dark";
|
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 () => {
|
private onProfileUpdate = async () => {
|
||||||
// the store triggered an update, so force a layout update. We don't
|
// the store triggered an update, so force a layout update. We don't
|
||||||
// have any state to store here for that to magically happen.
|
// have any state to store here for that to magically happen.
|
||||||
|
@ -295,7 +324,20 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
public render() {
|
public render() {
|
||||||
const avatarSize = 32; // should match border-radius of the avatar
|
const avatarSize = 32; // should match border-radius of the avatar
|
||||||
|
|
||||||
let name = <span className="mx_UserMenu_userName">{OwnProfileStore.instance.displayName}</span>;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = <span className="mx_UserMenu_userName">{displayName}</span>;
|
||||||
let buttons = (
|
let buttons = (
|
||||||
<span className="mx_UserMenu_headerButtons">
|
<span className="mx_UserMenu_headerButtons">
|
||||||
{/* masked image in CSS */}
|
{/* masked image in CSS */}
|
||||||
|
@ -324,9 +366,9 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
<div className="mx_UserMenu_row">
|
<div className="mx_UserMenu_row">
|
||||||
<span className="mx_UserMenu_userAvatarContainer">
|
<span className="mx_UserMenu_userAvatarContainer">
|
||||||
<BaseAvatar
|
<BaseAvatar
|
||||||
idName={MatrixClientPeg.get().getUserId()}
|
idName={displayName}
|
||||||
name={OwnProfileStore.instance.displayName || MatrixClientPeg.get().getUserId()}
|
name={displayName}
|
||||||
url={OwnProfileStore.instance.getHttpAvatarUrl(avatarSize)}
|
url={avatarUrl}
|
||||||
width={avatarSize}
|
width={avatarSize}
|
||||||
height={avatarSize}
|
height={avatarSize}
|
||||||
resizeMethod="crop"
|
resizeMethod="crop"
|
||||||
|
|
|
@ -30,6 +30,7 @@ import GroupStore from '../../../stores/GroupStore';
|
||||||
import TagOrderStore from '../../../stores/TagOrderStore';
|
import TagOrderStore from '../../../stores/TagOrderStore';
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import AccessibleButton from "./AccessibleButton";
|
import AccessibleButton from "./AccessibleButton";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
// A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents
|
// A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents
|
||||||
// a thing to click on for the user to filter the visible rooms in the RoomList to:
|
// a thing to click on for the user to filter the visible rooms in the RoomList to:
|
||||||
|
@ -112,6 +113,7 @@ export default createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onMouseOver: function() {
|
onMouseOver: function() {
|
||||||
|
if (SettingsStore.getValue("feature_communities_v2_prototypes")) return;
|
||||||
this.setState({ hover: true });
|
this.setState({ hover: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -123,6 +125,7 @@ export default createReactClass({
|
||||||
// Prevent the TagTile onClick event firing as well
|
// Prevent the TagTile onClick event firing as well
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (SettingsStore.getValue("feature_communities_v2_prototypes")) return;
|
||||||
this.setState({ hover: false });
|
this.setState({ hover: false });
|
||||||
this.props.openMenu();
|
this.props.openMenu();
|
||||||
},
|
},
|
||||||
|
|
|
@ -444,6 +444,7 @@
|
||||||
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
|
"%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s",
|
||||||
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
|
"%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s",
|
||||||
"Change notification settings": "Change notification settings",
|
"Change notification settings": "Change notification settings",
|
||||||
|
"Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.",
|
||||||
"New spinner design": "New spinner design",
|
"New spinner design": "New spinner design",
|
||||||
"Message Pinning": "Message Pinning",
|
"Message Pinning": "Message Pinning",
|
||||||
"Custom user status messages": "Custom user status messages",
|
"Custom user status messages": "Custom user status messages",
|
||||||
|
|
|
@ -109,6 +109,15 @@ export interface ISetting {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SETTINGS: {[setting: string]: ISetting} = {
|
export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
|
"feature_communities_v2_prototypes": {
|
||||||
|
isFeature: true,
|
||||||
|
displayName: _td(
|
||||||
|
"Communities v2 prototypes. Requires compatible homeserver. " +
|
||||||
|
"Highly experimental - use with caution.",
|
||||||
|
),
|
||||||
|
supportedLevels: LEVELS_FEATURE,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
"feature_new_spinner": {
|
"feature_new_spinner": {
|
||||||
isFeature: true,
|
isFeature: true,
|
||||||
displayName: _td("New spinner design"),
|
displayName: _td("New spinner design"),
|
||||||
|
|
|
@ -115,9 +115,11 @@ class TagOrderStore extends Store {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'select_tag': {
|
case 'select_tag': {
|
||||||
|
const allowMultiple = !SettingsStore.getValue("feature_communities_v2_prototypes");
|
||||||
|
|
||||||
let newTags = [];
|
let newTags = [];
|
||||||
// Shift-click semantics
|
// Shift-click semantics
|
||||||
if (payload.shiftKey) {
|
if (payload.shiftKey && allowMultiple) {
|
||||||
// Select range of tags
|
// Select range of tags
|
||||||
let start = this._state.orderedTags.indexOf(this._state.anchorTag);
|
let start = this._state.orderedTags.indexOf(this._state.anchorTag);
|
||||||
let end = this._state.orderedTags.indexOf(payload.tag);
|
let end = this._state.orderedTags.indexOf(payload.tag);
|
||||||
|
@ -135,7 +137,7 @@ class TagOrderStore extends Store {
|
||||||
this._state.orderedTags.slice(start, end + 1).concat(newTags),
|
this._state.orderedTags.slice(start, end + 1).concat(newTags),
|
||||||
)];
|
)];
|
||||||
} else {
|
} else {
|
||||||
if (payload.ctrlOrCmdKey) {
|
if (payload.ctrlOrCmdKey && allowMultiple) {
|
||||||
// Toggle individual tag
|
// Toggle individual tag
|
||||||
if (this._state.selectedTags.includes(payload.tag)) {
|
if (this._state.selectedTags.includes(payload.tag)) {
|
||||||
newTags = this._state.selectedTags.filter((t) => t !== payload.tag);
|
newTags = this._state.selectedTags.filter((t) => t !== payload.tag);
|
||||||
|
|
Loading…
Reference in a new issue