Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Move new search experience to a Beta #7718

Merged
merged 24 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions res/css/views/beta/_BetaCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ limitations under the License.
line-height: $font-15px;
color: $secondary-content;
margin-top: 20px;

> h4 {
margin: 0;
}

> p {
margin-top: 0;
}
}
}

Expand Down
23 changes: 7 additions & 16 deletions res/css/views/dialogs/_SpotlightDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -251,28 +251,19 @@ limitations under the License.
font-size: $font-12px;
line-height: $font-15px;
color: $secondary-content;
padding: 16px 16px 20px;
padding: 12px 16px 16px;
display: flex;
border-top: 1px solid $quinary-content;

.mx_BetaCard_betaPill {
margin-right: 12px;
}

> span {
position: relative;
padding-left: 20px;
align-self: center;

&::before {
background-color: $secondary-content;
content: "";
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
mask-image: url('$(res)/img/element-icons/room/room-summary.svg');
width: 16px;
height: 16px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
.mx_AccessibleButton_kind_link_inline {
padding: 0;
}
}

Expand Down
Binary file added res/img/betas/new_search_experience.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 33 additions & 1 deletion src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ import { RoomUpdateCause } from "../../stores/room-list/models";
import SecurityCustomisations from "../../customisations/Security";
import Spinner from "../views/elements/Spinner";
import QuestionDialog from "../views/dialogs/QuestionDialog";
import UserSettingsDialog from '../views/dialogs/UserSettingsDialog';
import UserSettingsDialog, { UserTab } from '../views/dialogs/UserSettingsDialog';
import CreateGroupDialog from '../views/dialogs/CreateGroupDialog';
import CreateRoomDialog from '../views/dialogs/CreateRoomDialog';
import RoomDirectory from './RoomDirectory';
Expand Down Expand Up @@ -1553,6 +1553,38 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
showNotificationsToast(false);
}

if (!localStorage.getItem("mx_seen_feature_spotlight_toast")) {
setTimeout(() => {
if (SettingsStore.getValue("feature_spotlight")) return;

const key = "BETA_SPOTLIGHT_TOAST";
ToastStore.sharedInstance().addOrReplaceToast({
key,
title: _t("New search beta available"),
props: {
description: _t("We're testing a new search to make finding what you want quicker.\n"),
acceptLabel: _t("Learn more"),
onAccept: () => {
dis.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Labs,
});
localStorage.setItem("mx_seen_feature_spotlight_toast", "true");
ToastStore.sharedInstance().dismissToast(key);
},
rejectLabel: _t("Dismiss"),
onReject: () => {
localStorage.setItem("mx_seen_feature_spotlight_toast", "true");
ToastStore.sharedInstance().dismissToast(key);
},
},
icon: "labs",
component: GenericToast,
priority: 9,
});
}, 5 * 60 * 1000); // show after 5 minutes to not overload user with toasts on launch
}

if (!localStorage.getItem("mx_seen_ia_1.1_changes_toast") && SettingsStore.getValue(UIFeature.Feedback)) {
const key = "IA_1.1_TOAST";
ToastStore.sharedInstance().addOrReplaceToast({
Expand Down
5 changes: 3 additions & 2 deletions src/components/views/beta/BetaCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Modal from "../../../Modal";
import BetaFeedbackDialog from "../dialogs/BetaFeedbackDialog";
import SdkConfig from "../../../SdkConfig";
import SettingsFlag from "../elements/SettingsFlag";
import { useFeatureEnabled } from "../../../hooks/useSettings";

// XXX: Keep this around for re-use in future Betas

Expand Down Expand Up @@ -67,10 +68,10 @@ export const BetaPill = ({ onClick }: { onClick?: () => void }) => {

const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
const info = SettingsStore.getBetaInfo(featureId);
const value = useFeatureEnabled(featureId);
if (!info) return null; // Beta is invalid/disabled

const { title, caption, disclaimer, image, feedbackLabel, feedbackSubheading, extraSettings } = info;
const value = SettingsStore.getValue(featureId);

let feedbackButton;
if (value && feedbackLabel && feedbackSubheading && SdkConfig.get().bug_report_endpoint_url) {
Expand All @@ -91,7 +92,7 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
{ titleOverride || _t(title) }
<BetaPill />
</h3>
<span className="mx_BetaCard_caption">{ _t(caption) }</span>
<span className="mx_BetaCard_caption">{ caption() }</span>
<div className="mx_BetaCard_buttons">
{ feedbackButton }
<AccessibleButton
Expand Down
96 changes: 72 additions & 24 deletions src/components/views/dialogs/SpotlightDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import React, {
ChangeEvent,
ComponentProps,
KeyboardEvent,
RefObject,
useCallback,
useContext,
useEffect,
Expand Down Expand Up @@ -63,6 +64,8 @@ import RoomViewStore from "../../../stores/RoomViewStore";
import { showStartChatInviteDialog } from "../../../RoomInvite";
import SettingsStore from "../../../settings/SettingsStore";
import { SettingLevel } from "../../../settings/SettingLevel";
import { BetaPill } from "../beta/BetaCard";
import { UserTab } from "./UserSettingsDialog";

const MAX_RECENT_SEARCHES = 10;
const SECTION_LIMIT = 50; // only show 50 results per section for performance reasons
Expand Down Expand Up @@ -165,6 +168,10 @@ const useSpaceResults = (space?: Room, query?: string): [IHierarchyRoom[], boole
return [results, hierarchy?.loading ?? false];
};

function refIsForRecentlyViewed(ref: RefObject<HTMLElement>): boolean {
return ref.current?.id.startsWith("mx_SpotlightDialog_button_recentlyViewed_");
}

const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) => {
const cli = MatrixClientPeg.get();
const rovingContext = useContext(RovingTabIndexContext);
Expand Down Expand Up @@ -447,25 +454,45 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
};

const onKeyDown = (ev: KeyboardEvent) => {
let ref: RefObject<HTMLElement>;

switch (ev.key) {
case Key.ARROW_UP:
case Key.ARROW_DOWN:
ev.stopPropagation();
ev.preventDefault();

if (rovingContext.state.refs.length > 0) {
const idx = rovingContext.state.refs.indexOf(rovingContext.state.activeRef);
const ref = findSiblingElement(rovingContext.state.refs, idx + (ev.key === Key.ARROW_UP ? -1 : 1));

if (ref) {
rovingContext.dispatch({
type: Type.SetFocus,
payload: { ref },
});
ref.current?.scrollIntoView({
block: "nearest",
});
let refs = rovingContext.state.refs;
if (!query) {
// If the current selection is not in the recently viewed row then only include the
// first recently viewed so that is the target when the user is switching into recently viewed.
const keptRecentlyViewedRef = refIsForRecentlyViewed(rovingContext.state.activeRef)
? rovingContext.state.activeRef
: refs.find(refIsForRecentlyViewed);
// exclude all other recently viewed items from the list so up/down arrows skip them
refs = refs.filter(ref => ref === keptRecentlyViewedRef || !refIsForRecentlyViewed(ref));
}

const idx = refs.indexOf(rovingContext.state.activeRef);
ref = findSiblingElement(refs, idx + (ev.key === Key.ARROW_UP ? -1 : 1));
}
break;

case Key.ARROW_LEFT:
case Key.ARROW_RIGHT:
// only handle these keys when we are in the recently viewed row of options
if (!query &&
rovingContext.state.refs.length > 0 &&
refIsForRecentlyViewed(rovingContext.state.activeRef)
) {
// we only intercept left/right arrows when the field is empty, and they'd do nothing anyway
ev.stopPropagation();
ev.preventDefault();

const refs = rovingContext.state.refs.filter(refIsForRecentlyViewed);
const idx = refs.indexOf(rovingContext.state.activeRef);
ref = findSiblingElement(refs, idx + (ev.key === Key.ARROW_LEFT ? -1 : 1));
}
break;

Expand All @@ -475,6 +502,25 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
rovingContext.state.activeRef?.current?.click();
break;
}

if (ref) {
rovingContext.dispatch({
type: Type.SetFocus,
payload: { ref },
});
ref.current?.scrollIntoView({
block: "nearest",
});
}
};

const openFeedback = () => {
Modal.createTrackedDialog("Spotlight Feedback", "", GenericFeatureFeedbackDialog, {
title: _t("Spotlight search feedback"),
subheading: _t("Thank you for trying Spotlight search. " +
"Your feedback will help inform the next versions."),
rageshakeLabel: "spotlight-feedback",
});
};

const activeDescendant = rovingContext.state.activeRef?.current?.id;
Expand All @@ -485,6 +531,8 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
arrows: () => <>
<div>↓</div>
<div>↑</div>
{ !query && <div>←</div> }
{ !query && <div>→</div> }
</>,
}) }
</div>
Expand Down Expand Up @@ -514,21 +562,21 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
</div>

<div className="mx_SpotlightDialog_footer">
<span>
{ activeSpace
? _t("Searching rooms and chats you're in and %(spaceName)s", { spaceName: activeSpace.name })
: _t("Searching rooms and chats you're in") }
</span>
<BetaPill onClick={() => {
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Labs,
});
onFinished();
}} />
{ _t("Results not as expected? Please <a>feedback</a>.", {}, {
a: sub => <AccessibleButton kind="link_inline" onClick={openFeedback}>
{ sub }
</AccessibleButton>,
}) }
<AccessibleButton
kind="primary_outline"
onClick={() => {
Modal.createTrackedDialog("Spotlight Feedback", "", GenericFeatureFeedbackDialog, {
title: _t("Spotlight search feedback"),
subheading: _t("Thank you for trying Spotlight search. " +
"Your feedback will help inform the next versions."),
rageshakeLabel: "spotlight-feedback",
});
}}
onClick={openFeedback}
>
{ _t("Feedback") }
</AccessibleButton>
Expand Down
16 changes: 11 additions & 5 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,13 @@
"Show extensible event representation of events": "Show extensible event representation of events",
"Show info about bridges in room settings": "Show info about bridges in room settings",
"Use new room breadcrumbs": "Use new room breadcrumbs",
"New spotlight search experience": "New spotlight search experience",
"New search experience": "New search experience",
"A new quick way to search spaces and rooms you're in.": "A new quick way to search spaces and rooms you're in.",
"This feature is a work in progress, so all feedback is very welcome.": "This feature is a work in progress, so all feedback is very welcome.",
"Leave beta": "Leave beta",
"Just return to this page or tap on the beta badge when you search.": "Just return to this page or tap on the beta badge when you search.",
"Feedback": "Feedback",
"Search and click on feedback": "Search and click on feedback",
"Right panel stays open (defaults to room member list)": "Right panel stays open (defaults to room member list)",
"Jump to date (adds /jumptodate and jump to date headers)": "Jump to date (adds /jumptodate and jump to date headers)",
"Don't send read receipts": "Don't send read receipts",
Expand Down Expand Up @@ -2552,7 +2558,6 @@
"Feedback sent": "Feedback sent",
"Comment": "Comment",
"Your platform and username will be noted to help us use your feedback as much as we can.": "Your platform and username will be noted to help us use your feedback as much as we can.",
"Feedback": "Feedback",
"You may contact me if you want to follow up or to let me test out upcoming ideas": "You may contact me if you want to follow up or to let me test out upcoming ideas",
"Rate %(brand)s": "Rate %(brand)s",
"Tell us below how you feel about %(brand)s so far.": "Tell us below how you feel about %(brand)s so far.",
Expand Down Expand Up @@ -2778,11 +2783,10 @@
"To search messages, look for this icon at the top of a room <icon/>": "To search messages, look for this icon at the top of a room <icon/>",
"Recent searches": "Recent searches",
"Clear": "Clear",
"Use <arrows/> to scroll results": "Use <arrows/> to scroll results",
"Searching rooms and chats you're in and %(spaceName)s": "Searching rooms and chats you're in and %(spaceName)s",
"Searching rooms and chats you're in": "Searching rooms and chats you're in",
"Spotlight search feedback": "Spotlight search feedback",
"Thank you for trying Spotlight search. Your feedback will help inform the next versions.": "Thank you for trying Spotlight search. Your feedback will help inform the next versions.",
"Use <arrows/> to scroll results": "Use <arrows/> to scroll results",
"Results not as expected? Please <a>feedback</a>.": "Results not as expected? Please <a>feedback</a>.",
"To help us prevent this in future, please <a>send us logs</a>.": "To help us prevent this in future, please <a>send us logs</a>.",
"Missing session data": "Missing session data",
"Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.",
Expand Down Expand Up @@ -3036,6 +3040,8 @@
"Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s",
"Unable to copy room link": "Unable to copy room link",
"Unable to copy a link to the room to the clipboard.": "Unable to copy a link to the room to the clipboard.",
"New search beta available": "New search beta available",
"We're testing a new search to make finding what you want quicker.\n": "We're testing a new search to make finding what you want quicker.\n",
"Testing small changes": "Testing small changes",
"Your feedback is wanted as we try out some design changes.": "Your feedback is wanted as we try out some design changes.",
"More info": "More info",
Expand Down
30 changes: 25 additions & 5 deletions src/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ limitations under the License.
*/

import { MatrixClient } from 'matrix-js-sdk/src/client';
import { ReactNode } from "react";
import React, { ReactNode } from "react";

import { _td } from '../languageHandler';
import { _t, _td } from '../languageHandler';
import {
NotificationBodyEnabledController,
NotificationsEnabledController,
Expand Down Expand Up @@ -155,7 +155,7 @@ interface IBaseSetting {
// XXX: Keep this around for re-use in future Betas
betaInfo?: {
title: string; // _td
caption: string; // _td
caption: () => ReactNode;
disclaimer?: (enabled: boolean) => ReactNode;
image: string; // require(...)
feedbackSubheading?: string;
Expand Down Expand Up @@ -336,8 +336,28 @@ export const SETTINGS: {[setting: string]: ISetting} = {
isFeature: true,
labsGroup: LabGroup.Rooms,
supportedLevels: LEVELS_FEATURE,
displayName: _td("New spotlight search experience"),
default: false,
displayName: _td("New search experience"),
default: false,
betaInfo: {
title: _td("New search experience"),
caption: () => <>
<p>{ _t("A new quick way to search spaces and rooms you're in.") }</p>
<p>{ _t("This feature is a work in progress, so all feedback is very welcome.") }</p>
</>,
disclaimer: enabled => enabled
? <>
<h4>{ _t("Leave beta") }</h4>
<p>{ _t("Just return to this page or tap on the beta badge when you search.") }</p>
<h4>{ _t("Feedback") }</h4>
<p>{ _t("Search and click on feedback") }</p>
</>
: <>
<h4>{ _t("Feedback") }</h4>
<p>{ _t("Search and click on feedback") }</p>
</>,
feedbackLabel: "spotlight-feedback",
image: require("../../res/img/betas/new_search_experience.gif"),
},
},
"feature_right_panel_default_open": {
isFeature: true,
Expand Down