Rebuild the room summary card's widgets section
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
ed30750f63
commit
23d95df30b
3 changed files with 144 additions and 72 deletions
|
@ -109,9 +109,57 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomSummaryCard_appsGroup {
|
.mx_RoomSummaryCard_appsGroup {
|
||||||
|
.mx_RoomSummaryCard_widgetRow {
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.mx_RoomSummaryCard_app_pinToggle,
|
||||||
|
.mx_RoomSummaryCard_app_options {
|
||||||
|
position: relative;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(141, 151, 165, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center;
|
||||||
|
mask-size: 16px;
|
||||||
|
background-color: $icon-button-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomSummaryCard_app_pinToggle {
|
||||||
|
&::before {
|
||||||
|
mask-image: url('$(res)/img/element-icons/room/pin-upright.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_RoomSummaryCard_app_pinned {
|
||||||
|
&::before {
|
||||||
|
background-color: $accent-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomSummaryCard_app_options {
|
||||||
|
&::before {
|
||||||
|
mask-image: url('$(res)/img/element-icons/room/ellipsis.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mx_RoomSummaryCard_Button {
|
.mx_RoomSummaryCard_Button {
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
color: $tertiary-fg-color;
|
color: $tertiary-fg-color;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: $primary-fg-color;
|
color: $primary-fg-color;
|
||||||
|
@ -127,12 +175,6 @@ limitations under the License.
|
||||||
content: unset;
|
content: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomSummaryCard_icon_app_pinned::after {
|
|
||||||
mask-image: url('$(res)/img/element-icons/room/pin-upright.svg');
|
|
||||||
background-color: $accent-color;
|
|
||||||
transform: unset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AccessibleButton_kind_link {
|
.mx_AccessibleButton_kind_link {
|
||||||
|
|
|
@ -43,6 +43,9 @@ import WidgetStore, {IApp} from "../../../stores/WidgetStore";
|
||||||
import { E2EStatus } from "../../../utils/ShieldUtils";
|
import { E2EStatus } from "../../../utils/ShieldUtils";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
import RoomContext from "../../../contexts/RoomContext";
|
||||||
import {UIFeature} from "../../../settings/UIFeature";
|
import {UIFeature} from "../../../settings/UIFeature";
|
||||||
|
import {ContextMenuButton} from "../../../accessibility/context_menu/ContextMenuButton";
|
||||||
|
import {ChevronFace, useContextMenu} from "../../structures/ContextMenu";
|
||||||
|
import RoomWidgetContextMenu from "../context_menus/RoomWidgetContextMenu";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -82,8 +85,93 @@ export const useWidgets = (room: Room) => {
|
||||||
return apps;
|
return apps;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppsSection: React.FC<IAppsSectionProps> = ({ room }) => {
|
interface IAppRowProps {
|
||||||
|
app: IApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppRow: React.FC<IAppRowProps> = ({ app }) => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
|
|
||||||
|
const name = WidgetUtils.getWidgetName(app);
|
||||||
|
const dataTitle = WidgetUtils.getWidgetDataTitle(app);
|
||||||
|
const subtitle = dataTitle && " - " + dataTitle;
|
||||||
|
|
||||||
|
let iconUrls = [require("../../../../res/img/element-icons/room/default_app.svg")];
|
||||||
|
// heuristics for some better icons until Widgets support their own icons
|
||||||
|
if (app.type.includes("meeting") || app.type.includes("calendar")) {
|
||||||
|
iconUrls = [require("../../../../res/img/element-icons/room/default_cal.svg")];
|
||||||
|
} else if (app.type.includes("pad") || app.type.includes("doc") || app.type.includes("calc")) {
|
||||||
|
iconUrls = [require("../../../../res/img/element-icons/room/default_doc.svg")];
|
||||||
|
} else if (app.type.includes("clock")) {
|
||||||
|
iconUrls = [require("../../../../res/img/element-icons/room/default_clock.svg")];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app.avatar_url) { // MSC2765
|
||||||
|
iconUrls.unshift(getHttpUriForMxc(cli.getHomeserverUrl(), app.avatar_url, 20, 20, "crop"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const onOpenWidgetClick = () => {
|
||||||
|
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||||
|
action: Action.SetRightPanelPhase,
|
||||||
|
phase: RightPanelPhases.Widget,
|
||||||
|
refireParams: {
|
||||||
|
widgetId: app.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const isPinned = WidgetStore.instance.isPinned(app.id);
|
||||||
|
const togglePin = isPinned
|
||||||
|
? () => { WidgetStore.instance.unpinWidget(app.id); }
|
||||||
|
: () => { WidgetStore.instance.pinWidget(app.id); };
|
||||||
|
|
||||||
|
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLDivElement>();
|
||||||
|
let contextMenu;
|
||||||
|
if (menuDisplayed) {
|
||||||
|
const rect = handle.current.getBoundingClientRect();
|
||||||
|
contextMenu = <RoomWidgetContextMenu
|
||||||
|
chevronFace={ChevronFace.None}
|
||||||
|
right={window.innerWidth - rect.right}
|
||||||
|
bottom={window.innerHeight - rect.top}
|
||||||
|
onFinished={closeMenu}
|
||||||
|
app={app}
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="mx_RoomSummaryCard_widgetRow" ref={handle}>
|
||||||
|
<AccessibleTooltipButton
|
||||||
|
className="mx_BaseCard_Button mx_RoomSummaryCard_Button mx_RoomSummaryCard_icon_app"
|
||||||
|
onClick={onOpenWidgetClick}
|
||||||
|
// only show a tooltip if the widget is pinned
|
||||||
|
title={isPinned ? _t("You can't view pinned widgets in the right panel") : ""}
|
||||||
|
forceHide={!isPinned}
|
||||||
|
disabled={isPinned}
|
||||||
|
>
|
||||||
|
<BaseAvatar name={app.id} urls={iconUrls} width={20} height={20} />
|
||||||
|
<span>{name}</span>
|
||||||
|
{ subtitle }
|
||||||
|
</AccessibleTooltipButton>
|
||||||
|
|
||||||
|
<AccessibleTooltipButton
|
||||||
|
className={classNames("mx_RoomSummaryCard_app_pinToggle", {
|
||||||
|
mx_RoomSummaryCard_app_pinned: isPinned,
|
||||||
|
})}
|
||||||
|
onClick={togglePin}
|
||||||
|
title={isPinned ? _t("Unpin") : _t("Pin")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ContextMenuButton
|
||||||
|
className="mx_RoomSummaryCard_app_options"
|
||||||
|
isExpanded={menuDisplayed}
|
||||||
|
onClick={openMenu}
|
||||||
|
label={_t("Options")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{ contextMenu }
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppsSection: React.FC<IAppsSectionProps> = ({ room }) => {
|
||||||
const apps = useWidgets(room);
|
const apps = useWidgets(room);
|
||||||
|
|
||||||
const onManageIntegrations = () => {
|
const onManageIntegrations = () => {
|
||||||
|
@ -100,65 +188,7 @@ const AppsSection: React.FC<IAppsSectionProps> = ({ room }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Group className="mx_RoomSummaryCard_appsGroup" title={_t("Widgets")}>
|
return <Group className="mx_RoomSummaryCard_appsGroup" title={_t("Widgets")}>
|
||||||
{ apps.map(app => {
|
{ apps.map(app => <AppRow key={app.id} app={app} />) }
|
||||||
const name = WidgetUtils.getWidgetName(app);
|
|
||||||
const dataTitle = WidgetUtils.getWidgetDataTitle(app);
|
|
||||||
const subtitle = dataTitle && " - " + dataTitle;
|
|
||||||
|
|
||||||
let iconUrls = [require("../../../../res/img/element-icons/room/default_app.svg")];
|
|
||||||
// heuristics for some better icons until Widgets support their own icons
|
|
||||||
if (app.type.includes("meeting") || app.type.includes("calendar")) {
|
|
||||||
iconUrls = [require("../../../../res/img/element-icons/room/default_cal.svg")];
|
|
||||||
} else if (app.type.includes("pad") || app.type.includes("doc") || app.type.includes("calc")) {
|
|
||||||
iconUrls = [require("../../../../res/img/element-icons/room/default_doc.svg")];
|
|
||||||
} else if (app.type.includes("clock")) {
|
|
||||||
iconUrls = [require("../../../../res/img/element-icons/room/default_clock.svg")];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app.avatar_url) { // MSC2765
|
|
||||||
iconUrls.unshift(getHttpUriForMxc(cli.getHomeserverUrl(), app.avatar_url, 20, 20, "crop"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const isPinned = WidgetStore.instance.isPinned(app.id);
|
|
||||||
const classes = classNames("mx_RoomSummaryCard_icon_app", {
|
|
||||||
mx_RoomSummaryCard_icon_app_pinned: isPinned,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isPinned) {
|
|
||||||
const onClick = () => {
|
|
||||||
WidgetStore.instance.unpinWidget(app.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
return <AccessibleTooltipButton
|
|
||||||
key={app.id}
|
|
||||||
className={classNames("mx_BaseCard_Button mx_RoomSummaryCard_Button", classes)}
|
|
||||||
onClick={onClick}
|
|
||||||
title={_t("Unpin app")}
|
|
||||||
>
|
|
||||||
<BaseAvatar name={app.id} urls={iconUrls} width={20} height={20} />
|
|
||||||
<span>{name}</span>
|
|
||||||
{ subtitle }
|
|
||||||
</AccessibleTooltipButton>
|
|
||||||
}
|
|
||||||
|
|
||||||
const onOpenWidgetClick = () => {
|
|
||||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
|
||||||
action: Action.SetRightPanelPhase,
|
|
||||||
phase: RightPanelPhases.Widget,
|
|
||||||
refireParams: {
|
|
||||||
widgetId: app.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Button key={app.id} className={classes} onClick={onOpenWidgetClick}>
|
|
||||||
<BaseAvatar name={app.id} urls={iconUrls} width={20} height={20} />
|
|
||||||
<span>{name}</span>
|
|
||||||
{ subtitle }
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}) }
|
|
||||||
|
|
||||||
<AccessibleButton kind="link" onClick={onManageIntegrations}>
|
<AccessibleButton kind="link" onClick={onManageIntegrations}>
|
||||||
{ apps.length > 0 ? _t("Edit widgets, bridges & bots") : _t("Add widgets, bridges & bots") }
|
{ apps.length > 0 ? _t("Edit widgets, bridges & bots") : _t("Add widgets, bridges & bots") }
|
||||||
|
|
|
@ -1274,8 +1274,10 @@
|
||||||
"Yours, or the other users’ session": "Yours, or the other users’ session",
|
"Yours, or the other users’ session": "Yours, or the other users’ session",
|
||||||
"Members": "Members",
|
"Members": "Members",
|
||||||
"Room Info": "Room Info",
|
"Room Info": "Room Info",
|
||||||
|
"You can't view pinned widgets in the right panel": "You can't view pinned widgets in the right panel",
|
||||||
|
"Unpin": "Unpin",
|
||||||
|
"Options": "Options",
|
||||||
"Widgets": "Widgets",
|
"Widgets": "Widgets",
|
||||||
"Unpin app": "Unpin app",
|
|
||||||
"Edit widgets, bridges & bots": "Edit widgets, bridges & bots",
|
"Edit widgets, bridges & bots": "Edit widgets, bridges & bots",
|
||||||
"Add widgets, bridges & bots": "Add widgets, bridges & bots",
|
"Add widgets, bridges & bots": "Add widgets, bridges & bots",
|
||||||
"Not encrypted": "Not encrypted",
|
"Not encrypted": "Not encrypted",
|
||||||
|
@ -1298,7 +1300,6 @@
|
||||||
"Invite": "Invite",
|
"Invite": "Invite",
|
||||||
"Share Link to User": "Share Link to User",
|
"Share Link to User": "Share Link to User",
|
||||||
"Direct message": "Direct message",
|
"Direct message": "Direct message",
|
||||||
"Options": "Options",
|
|
||||||
"Demote yourself?": "Demote yourself?",
|
"Demote yourself?": "Demote yourself?",
|
||||||
"You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.",
|
"You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.",
|
||||||
"Demote": "Demote",
|
"Demote": "Demote",
|
||||||
|
@ -1362,9 +1363,6 @@
|
||||||
"You cancelled verification.": "You cancelled verification.",
|
"You cancelled verification.": "You cancelled verification.",
|
||||||
"Verification cancelled": "Verification cancelled",
|
"Verification cancelled": "Verification cancelled",
|
||||||
"Compare emoji": "Compare emoji",
|
"Compare emoji": "Compare emoji",
|
||||||
"Take a picture": "Take a picture",
|
|
||||||
"Remove for everyone": "Remove for everyone",
|
|
||||||
"Remove for me": "Remove for me",
|
|
||||||
"Edit": "Edit",
|
"Edit": "Edit",
|
||||||
"Pin to room": "Pin to room",
|
"Pin to room": "Pin to room",
|
||||||
"You can only pin 2 widgets at a time": "You can only pin 2 widgets at a time",
|
"You can only pin 2 widgets at a time": "You can only pin 2 widgets at a time",
|
||||||
|
@ -1924,12 +1922,14 @@
|
||||||
"Source URL": "Source URL",
|
"Source URL": "Source URL",
|
||||||
"Collapse Reply Thread": "Collapse Reply Thread",
|
"Collapse Reply Thread": "Collapse Reply Thread",
|
||||||
"Report Content": "Report Content",
|
"Report Content": "Report Content",
|
||||||
|
"Take a picture": "Take a picture",
|
||||||
|
"Remove for everyone": "Remove for everyone",
|
||||||
|
"Remove for me": "Remove for me",
|
||||||
"Clear status": "Clear status",
|
"Clear status": "Clear status",
|
||||||
"Update status": "Update status",
|
"Update status": "Update status",
|
||||||
"Set status": "Set status",
|
"Set status": "Set status",
|
||||||
"Set a new status...": "Set a new status...",
|
"Set a new status...": "Set a new status...",
|
||||||
"View Community": "View Community",
|
"View Community": "View Community",
|
||||||
"Unpin": "Unpin",
|
|
||||||
"Reload": "Reload",
|
"Reload": "Reload",
|
||||||
"Take picture": "Take picture",
|
"Take picture": "Take picture",
|
||||||
"This room is public": "This room is public",
|
"This room is public": "This room is public",
|
||||||
|
|
Loading…
Reference in a new issue