From bfbbf44dfcc85e990eb579bd67aa7782d6280d6a Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Wed, 16 Sep 2020 17:23:37 -0600
Subject: [PATCH 1/3] Add a note to use the desktop builds when seshat isn't
 available

Fixes https://github.com/vector-im/element-web/issues/15184

This is currently temporary design for https://github.com/vector-im/element-web/issues/12896 but does not fix it.
---
 res/css/_components.scss                      |   1 +
 .../views/elements/_DesktopBuildsNotice.scss  |  28 ++++
 res/css/views/rooms/_SearchBar.scss           |   1 +
 res/img/element-desktop-logo.svg              | 157 ++++++++++++++++++
 src/SdkConfig.ts                              |   5 +
 src/components/structures/FilePanel.js        |   4 +
 src/components/structures/RoomView.tsx        |   1 +
 .../views/elements/DesktopBuildsNotice.tsx    |  77 +++++++++
 src/components/views/rooms/SearchBar.js       |  35 ++--
 src/i18n/strings/en_EN.json                   |   4 +
 10 files changed, 299 insertions(+), 14 deletions(-)
 create mode 100644 res/css/views/elements/_DesktopBuildsNotice.scss
 create mode 100644 res/img/element-desktop-logo.svg
 create mode 100644 src/components/views/elements/DesktopBuildsNotice.tsx

diff --git a/res/css/_components.scss b/res/css/_components.scss
index 54e7436886..4c83dd7a31 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -100,6 +100,7 @@
 @import "./views/elements/_AccessibleButton.scss";
 @import "./views/elements/_AddressSelector.scss";
 @import "./views/elements/_AddressTile.scss";
+@import "./views/elements/_DesktopBuildsNotice.scss";
 @import "./views/elements/_DirectorySearchBox.scss";
 @import "./views/elements/_Dropdown.scss";
 @import "./views/elements/_EditableItemList.scss";
diff --git a/res/css/views/elements/_DesktopBuildsNotice.scss b/res/css/views/elements/_DesktopBuildsNotice.scss
new file mode 100644
index 0000000000..3672595bf1
--- /dev/null
+++ b/res/css/views/elements/_DesktopBuildsNotice.scss
@@ -0,0 +1,28 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_DesktopBuildsNotice {
+    text-align: center;
+    padding: 0 16px;
+
+    > * {
+        vertical-align: middle;
+    }
+
+    > img {
+        margin-right: 8px;
+    }
+}
diff --git a/res/css/views/rooms/_SearchBar.scss b/res/css/views/rooms/_SearchBar.scss
index fecc8d78d8..d9f730a8b6 100644
--- a/res/css/views/rooms/_SearchBar.scss
+++ b/res/css/views/rooms/_SearchBar.scss
@@ -68,3 +68,4 @@ limitations under the License.
         cursor: pointer;
     }
 }
+
diff --git a/res/img/element-desktop-logo.svg b/res/img/element-desktop-logo.svg
new file mode 100644
index 0000000000..2031733ce3
--- /dev/null
+++ b/res/img/element-desktop-logo.svg
@@ -0,0 +1,157 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_dd)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M16.1438 2.34375H7.85617C5.93938 2.34375 5.24431 2.54333 4.54356 2.91809C3.84281 3.29286 3.29286 3.84281 2.91809 4.54356C2.54333 5.24431 2.34375 5.93938 2.34375 7.85617V16.1438C2.34375 18.0606 2.54333 18.7557 2.91809 19.4564C3.29286 20.1572 3.84281 20.7071 4.54356 21.0819C5.24431 21.4567 5.93938 21.6562 7.85617 21.6562H16.1438C18.0606 21.6562 18.7557 21.4567 19.4564 21.0819C20.1572 20.7071 20.7071 20.1572 21.0819 19.4564C21.4567 18.7557 21.6562 18.0606 21.6562 16.1438V7.85617C21.6562 5.93938 21.4567 5.24431 21.0819 4.54356C20.7071 3.84281 20.1572 3.29286 19.4564 2.91809C18.7557 2.54333 18.0606 2.34375 16.1438 2.34375Z" fill="url(#paint0_linear)"/>
+</g>
+<g filter="url(#filter1_ddddi)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0969 6.01875C10.0969 5.56829 10.462 5.20312 10.9125 5.20312C13.9155 5.20312 16.35 7.63758 16.35 10.6406C16.35 11.0911 15.9848 11.4562 15.5344 11.4562C15.0839 11.4562 14.7187 11.0911 14.7187 10.6406C14.7187 8.53849 13.0146 6.83437 10.9125 6.83437C10.462 6.83437 10.0969 6.46921 10.0969 6.01875Z" fill="white"/>
+</g>
+<g filter="url(#filter2_ddddi)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9031 17.9813C13.9031 18.4317 13.538 18.7969 13.0875 18.7969C10.0845 18.7969 7.65001 16.3624 7.65001 13.3594C7.65001 12.9089 8.01518 12.5437 8.46564 12.5437C8.9161 12.5437 9.28126 12.9089 9.28126 13.3594C9.28126 15.4615 10.9854 17.1656 13.0875 17.1656C13.538 17.1656 13.9031 17.5308 13.9031 17.9813Z" fill="white"/>
+</g>
+<g filter="url(#filter3_ddddi)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M6.01875 13.9031C5.56829 13.9031 5.20312 13.538 5.20312 13.0875C5.20312 10.0845 7.63758 7.65001 10.6406 7.65001C11.0911 7.65001 11.4562 8.01518 11.4562 8.46564C11.4562 8.91609 11.0911 9.28126 10.6406 9.28126C8.53849 9.28126 6.83437 10.9854 6.83437 13.0875C6.83437 13.538 6.46921 13.9031 6.01875 13.9031Z" fill="white"/>
+</g>
+<g filter="url(#filter4_ddddi)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M17.9812 10.0969C18.4317 10.0969 18.7969 10.462 18.7969 10.9125C18.7969 13.9155 16.3624 16.35 13.3594 16.35C12.9089 16.35 12.5437 15.9848 12.5437 15.5344C12.5437 15.0839 12.9089 14.7187 13.3594 14.7187C15.4615 14.7187 17.1656 13.0146 17.1656 10.9125C17.1656 10.462 17.5308 10.0969 17.9812 10.0969Z" fill="white"/>
+</g>
+<defs>
+<filter id="filter0_dd" x="1.54688" y="1.92188" width="20.9062" height="20.9062" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="0.375"/>
+<feGaussianBlur stdDeviation="0.398438"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="0.234375"/>
+<feGaussianBlur stdDeviation="0.28125"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
+</filter>
+<filter id="filter1_ddddi" x="6.95624" y="4.03125" width="12.5344" height="12.5344" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="0.328125"/>
+<feGaussianBlur stdDeviation="0.515625"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.26562"/>
+<feGaussianBlur stdDeviation="0.632812"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.96875"/>
+<feGaussianBlur stdDeviation="1.57031"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dx="-0.1875" dy="0.421875"/>
+<feGaussianBlur stdDeviation="0.339844"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="-0.679688"/>
+<feGaussianBlur stdDeviation="0.269531"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
+<feBlend mode="normal" in2="shape" result="effect5_innerShadow"/>
+</filter>
+<filter id="filter2_ddddi" x="4.5094" y="11.3719" width="12.5344" height="12.5344" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="0.328125"/>
+<feGaussianBlur stdDeviation="0.515625"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.26562"/>
+<feGaussianBlur stdDeviation="0.632812"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.96875"/>
+<feGaussianBlur stdDeviation="1.57031"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dx="-0.1875" dy="0.421875"/>
+<feGaussianBlur stdDeviation="0.339844"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="-0.679688"/>
+<feGaussianBlur stdDeviation="0.269531"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
+<feBlend mode="normal" in2="shape" result="effect5_innerShadow"/>
+</filter>
+<filter id="filter3_ddddi" x="2.0625" y="6.47815" width="12.5344" height="12.5344" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="0.328125"/>
+<feGaussianBlur stdDeviation="0.515625"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.26562"/>
+<feGaussianBlur stdDeviation="0.632812"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.96875"/>
+<feGaussianBlur stdDeviation="1.57031"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dx="-0.1875" dy="0.421875"/>
+<feGaussianBlur stdDeviation="0.339844"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="-0.679688"/>
+<feGaussianBlur stdDeviation="0.269531"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
+<feBlend mode="normal" in2="shape" result="effect5_innerShadow"/>
+</filter>
+<filter id="filter4_ddddi" x="9.40314" y="8.92499" width="12.5344" height="12.5344" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="0.328125"/>
+<feGaussianBlur stdDeviation="0.515625"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.26562"/>
+<feGaussianBlur stdDeviation="0.632812"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dy="1.96875"/>
+<feGaussianBlur stdDeviation="1.57031"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
+<feOffset dx="-0.1875" dy="0.421875"/>
+<feGaussianBlur stdDeviation="0.339844"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="-0.679688"/>
+<feGaussianBlur stdDeviation="0.269531"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
+<feBlend mode="normal" in2="shape" result="effect5_innerShadow"/>
+</filter>
+<linearGradient id="paint0_linear" x1="12" y1="2.34375" x2="12" y2="21.6562" gradientUnits="userSpaceOnUse">
+<stop stop-color="#1ED9A3"/>
+<stop offset="1" stop-color="#0DBD8B"/>
+</linearGradient>
+</defs>
+</svg>
diff --git a/src/SdkConfig.ts b/src/SdkConfig.ts
index b914aaaf6d..7d7caa2d24 100644
--- a/src/SdkConfig.ts
+++ b/src/SdkConfig.ts
@@ -33,6 +33,11 @@ export const DEFAULTS: ConfigOptions = {
         // Default conference domain
         preferredDomain: "jitsi.riot.im",
     },
+    desktopBuilds: {
+        available: true,
+        logo: require("../res/img/element-desktop-logo.svg"),
+        url: "https://element.io/get-started",
+    },
 };
 
 export default class SdkConfig {
diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js
index 6d618d0b9d..4836b0f554 100644
--- a/src/components/structures/FilePanel.js
+++ b/src/components/structures/FilePanel.js
@@ -25,6 +25,7 @@ import EventIndexPeg from "../../indexing/EventIndexPeg";
 import { _t } from '../../languageHandler';
 import BaseCard from "../views/right_panel/BaseCard";
 import {RightPanelPhases} from "../../stores/RightPanelStorePhases";
+import DesktopBuildsNotice, {WarningKind} from "../views/elements/DesktopBuildsNotice";
 
 /*
  * Component which shows the filtered file using a TimelinePanel
@@ -222,6 +223,8 @@ class FilePanel extends React.Component {
             <p>{_t('Attach files from chat or just drag and drop them anywhere in a room.')}</p>
         </div>);
 
+        const isRoomEncrypted = this.noRoom ? false : MatrixClientPeg.get().isRoomEncrypted(this.props.roomId);
+
         if (this.state.timelineSet) {
             // console.log("rendering TimelinePanel for timelineSet " + this.state.timelineSet.room.roomId + " " +
             //             "(" + this.state.timelineSet._timelines.join(", ") + ")" + " with key " + this.props.roomId);
@@ -232,6 +235,7 @@ class FilePanel extends React.Component {
                     previousPhase={RightPanelPhases.RoomSummary}
                     withoutScrollContainer
                 >
+                    <DesktopBuildsNotice isRoomEncrypted={isRoomEncrypted} kind={WarningKind.Files} />
                     <TimelinePanel
                         manageReadReceipts={false}
                         manageReadMarkers={false}
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx
index 039d36a8de..3fed7d9e23 100644
--- a/src/components/structures/RoomView.tsx
+++ b/src/components/structures/RoomView.tsx
@@ -1879,6 +1879,7 @@ export default class RoomView extends React.Component<IProps, IState> {
                 searchInProgress={this.state.searchInProgress}
                 onCancelClick={this.onCancelSearchClick}
                 onSearch={this.onSearch}
+                isRoomEncrypted={this.context.isRoomEncrypted(this.state.room.roomId)}
             />;
         } else if (showRoomUpgradeBar) {
             aux = <RoomUpgradeWarningBar room={this.state.room} recommendation={roomVersionRecommendation} />;
diff --git a/src/components/views/elements/DesktopBuildsNotice.tsx b/src/components/views/elements/DesktopBuildsNotice.tsx
new file mode 100644
index 0000000000..688d0669da
--- /dev/null
+++ b/src/components/views/elements/DesktopBuildsNotice.tsx
@@ -0,0 +1,77 @@
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import EventIndexPeg from "../../../indexing/EventIndexPeg";
+import { _t } from "../../../languageHandler";
+import SdkConfig from "../../../SdkConfig";
+import React from "react";
+
+export enum WarningKind {
+    Files,
+    Search,
+}
+
+interface IProps {
+    isRoomEncrypted: boolean;
+    kind: WarningKind;
+}
+
+export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) {
+    if (!isRoomEncrypted) return null;
+    if (EventIndexPeg.get()) return null;
+
+    const {desktopBuilds, brand} = SdkConfig.get();
+
+    let text = null;
+    let logo = null;
+    if (desktopBuilds.available) {
+        logo = <img src={desktopBuilds.logo} />;
+        switch(kind) {
+            case WarningKind.Files:
+                text = _t("Use the <a>Desktop app</a> to see encrypted files", {}, {
+                    a: sub => (<a href={desktopBuilds.url} target="_blank" rel="noreferrer noopener">{sub}</a>),
+                });
+                break;
+            case WarningKind.Search:
+                text = _t("Use the <a>Desktop app</a> to search encrypted messages", {}, {
+                    a: sub => (<a href={desktopBuilds.url} target="_blank" rel="noreferrer noopener">{sub}</a>),
+                });
+                break;
+        }
+    } else {
+        switch(kind) {
+            case WarningKind.Files:
+                text = _t("This version of %(brand)s does not support viewing encrypted files", {brand});
+                break;
+            case WarningKind.Search:
+                text = _t("This version of %(brand)s does not support searching encrypted messages", {brand});
+                break;
+        }
+    }
+
+    // for safety
+    if (!text) {
+        console.warn("Unknown desktop builds warning kind: ", kind);
+        return null;
+    }
+
+    return (
+        <div className="mx_DesktopBuildsNotice">
+            {logo}
+            <span>{text}</span>
+        </div>
+    );
+}
diff --git a/src/components/views/rooms/SearchBar.js b/src/components/views/rooms/SearchBar.js
index 767f5a35f5..4bf97aac10 100644
--- a/src/components/views/rooms/SearchBar.js
+++ b/src/components/views/rooms/SearchBar.js
@@ -1,5 +1,6 @@
 /*
 Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2020 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,6 +20,9 @@ import AccessibleButton from "../elements/AccessibleButton";
 import classNames from "classnames";
 import { _t } from '../../../languageHandler';
 import {Key} from "../../../Keyboard";
+import SdkConfig from "../../../SdkConfig";
+import EventIndexPeg from "../../../indexing/EventIndexPeg";
+import DesktopBuildsNotice, {WarningKind} from "../elements/DesktopBuildsNotice";
 
 export default class SearchBar extends React.Component {
     constructor(props) {
@@ -72,21 +76,24 @@ export default class SearchBar extends React.Component {
         });
 
         return (
-            <div className="mx_SearchBar">
-                <div className="mx_SearchBar_buttons" role="radiogroup">
-                    <AccessibleButton className={ thisRoomClasses } onClick={this.onThisRoomClick} aria-checked={this.state.scope === 'Room'} role="radio">
-                        {_t("This Room")}
-                    </AccessibleButton>
-                    <AccessibleButton className={ allRoomsClasses } onClick={this.onAllRoomsClick} aria-checked={this.state.scope === 'All'} role="radio">
-                        {_t("All Rooms")}
-                    </AccessibleButton>
+            <>
+                <div className="mx_SearchBar">
+                    <div className="mx_SearchBar_buttons" role="radiogroup">
+                        <AccessibleButton className={ thisRoomClasses } onClick={this.onThisRoomClick} aria-checked={this.state.scope === 'Room'} role="radio">
+                            {_t("This Room")}
+                        </AccessibleButton>
+                        <AccessibleButton className={ allRoomsClasses } onClick={this.onAllRoomsClick} aria-checked={this.state.scope === 'All'} role="radio">
+                            {_t("All Rooms")}
+                        </AccessibleButton>
+                    </div>
+                    <div className="mx_SearchBar_input mx_textinput">
+                        <input ref={this._search_term} type="text" autoFocus={true} placeholder={_t("Search…")} onKeyDown={this.onSearchChange} />
+                        <AccessibleButton className={ searchButtonClasses } onClick={this.onSearch} />
+                    </div>
+                    <AccessibleButton className="mx_SearchBar_cancel" onClick={this.props.onCancelClick} />
                 </div>
-                <div className="mx_SearchBar_input mx_textinput">
-                    <input ref={this._search_term} type="text" autoFocus={true} placeholder={_t("Search…")} onKeyDown={this.onSearchChange} />
-                    <AccessibleButton className={ searchButtonClasses } onClick={this.onSearch} />
-                </div>
-                <AccessibleButton className="mx_SearchBar_cancel" onClick={this.props.onCancelClick} />
-            </div>
+                <DesktopBuildsNotice isRoomEncrypted={this.props.isRoomEncrypted} kind={WarningKind.Search} />
+            </>
         );
     }
 }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index b2b4e01202..d4053f4418 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1493,6 +1493,10 @@
     "Maximize apps": "Maximize apps",
     "Popout widget": "Popout widget",
     "More options": "More options",
+    "Use the <a>Desktop app</a> to see encrypted files": "Use the <a>Desktop app</a> to see encrypted files",
+    "Use the <a>Desktop app</a> to search encrypted messages": "Use the <a>Desktop app</a> to search encrypted messages",
+    "This version of %(brand)s does not support viewing encrypted files": "This version of %(brand)s does not support viewing encrypted files",
+    "This version of %(brand)s does not support searching encrypted messages": "This version of %(brand)s does not support searching encrypted messages",
     "Join": "Join",
     "No results": "No results",
     "Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.": "Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.",

From c3a37544323da3c2d7801114563c597fd57e352a Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Wed, 16 Sep 2020 17:27:45 -0600
Subject: [PATCH 2/3] Appease the linter

---
 src/components/views/elements/DesktopBuildsNotice.tsx | 4 ++--
 src/components/views/rooms/SearchBar.js               | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/components/views/elements/DesktopBuildsNotice.tsx b/src/components/views/elements/DesktopBuildsNotice.tsx
index 688d0669da..cc5b9174d1 100644
--- a/src/components/views/elements/DesktopBuildsNotice.tsx
+++ b/src/components/views/elements/DesktopBuildsNotice.tsx
@@ -39,7 +39,7 @@ export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) {
     let logo = null;
     if (desktopBuilds.available) {
         logo = <img src={desktopBuilds.logo} />;
-        switch(kind) {
+        switch (kind) {
             case WarningKind.Files:
                 text = _t("Use the <a>Desktop app</a> to see encrypted files", {}, {
                     a: sub => (<a href={desktopBuilds.url} target="_blank" rel="noreferrer noopener">{sub}</a>),
@@ -52,7 +52,7 @@ export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) {
                 break;
         }
     } else {
-        switch(kind) {
+        switch (kind) {
             case WarningKind.Files:
                 text = _t("This version of %(brand)s does not support viewing encrypted files", {brand});
                 break;
diff --git a/src/components/views/rooms/SearchBar.js b/src/components/views/rooms/SearchBar.js
index 4bf97aac10..ac637673e4 100644
--- a/src/components/views/rooms/SearchBar.js
+++ b/src/components/views/rooms/SearchBar.js
@@ -20,8 +20,6 @@ import AccessibleButton from "../elements/AccessibleButton";
 import classNames from "classnames";
 import { _t } from '../../../languageHandler';
 import {Key} from "../../../Keyboard";
-import SdkConfig from "../../../SdkConfig";
-import EventIndexPeg from "../../../indexing/EventIndexPeg";
 import DesktopBuildsNotice, {WarningKind} from "../elements/DesktopBuildsNotice";
 
 export default class SearchBar extends React.Component {

From 8838bd724b1a23805e61e92565c1992ddc7c88a8 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Fri, 18 Sep 2020 10:58:17 -0600
Subject: [PATCH 3/3] Update copy for files

---
 src/components/views/elements/DesktopBuildsNotice.tsx | 4 ++--
 src/i18n/strings/en_EN.json                           | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/views/elements/DesktopBuildsNotice.tsx b/src/components/views/elements/DesktopBuildsNotice.tsx
index cc5b9174d1..fd1c7848aa 100644
--- a/src/components/views/elements/DesktopBuildsNotice.tsx
+++ b/src/components/views/elements/DesktopBuildsNotice.tsx
@@ -41,7 +41,7 @@ export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) {
         logo = <img src={desktopBuilds.logo} />;
         switch (kind) {
             case WarningKind.Files:
-                text = _t("Use the <a>Desktop app</a> to see encrypted files", {}, {
+                text = _t("Use the <a>Desktop app</a> to see all encrypted files", {}, {
                     a: sub => (<a href={desktopBuilds.url} target="_blank" rel="noreferrer noopener">{sub}</a>),
                 });
                 break;
@@ -54,7 +54,7 @@ export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) {
     } else {
         switch (kind) {
             case WarningKind.Files:
-                text = _t("This version of %(brand)s does not support viewing encrypted files", {brand});
+                text = _t("This version of %(brand)s does not support viewing some encrypted files", {brand});
                 break;
             case WarningKind.Search:
                 text = _t("This version of %(brand)s does not support searching encrypted messages", {brand});
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 024809f214..01fd172879 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1487,9 +1487,9 @@
     "Maximize apps": "Maximize apps",
     "Popout widget": "Popout widget",
     "More options": "More options",
-    "Use the <a>Desktop app</a> to see encrypted files": "Use the <a>Desktop app</a> to see encrypted files",
+    "Use the <a>Desktop app</a> to see all encrypted files": "Use the <a>Desktop app</a> to see all encrypted files",
     "Use the <a>Desktop app</a> to search encrypted messages": "Use the <a>Desktop app</a> to search encrypted messages",
-    "This version of %(brand)s does not support viewing encrypted files": "This version of %(brand)s does not support viewing encrypted files",
+    "This version of %(brand)s does not support viewing some encrypted files": "This version of %(brand)s does not support viewing some encrypted files",
     "This version of %(brand)s does not support searching encrypted messages": "This version of %(brand)s does not support searching encrypted messages",
     "Join": "Join",
     "No results": "No results",