Merge pull request #5873 from matrix-org/travis/dnd
Labs: Add quick/cheap "do not disturb" flagpull/21833/head
						commit
						bf70666f9b
					
				|  | @ -117,6 +117,32 @@ limitations under the License. | |||
|         .mx_UserMenu_headerButtons { | ||||
|             // No special styles: the rest of the layout happens to make it work. | ||||
|         } | ||||
| 
 | ||||
|         .mx_UserMenu_dnd { | ||||
|             width: 24px; | ||||
|             height: 24px; | ||||
|             margin-right: 8px; | ||||
|             position: relative; | ||||
| 
 | ||||
|             &::before { | ||||
|                 content: ''; | ||||
|                 position: absolute; | ||||
|                 width: 24px; | ||||
|                 height: 24px; | ||||
|                 mask-position: center; | ||||
|                 mask-size: contain; | ||||
|                 mask-repeat: no-repeat; | ||||
|                 background: $muted-fg-color; | ||||
|             } | ||||
| 
 | ||||
|             &.mx_UserMenu_dnd_noisy::before { | ||||
|                 mask-image: url('$(res)/img/element-icons/notifications.svg'); | ||||
|             } | ||||
| 
 | ||||
|             &.mx_UserMenu_dnd_muted::before { | ||||
|                 mask-image: url('$(res)/img/element-icons/roomlist/notifications-off.svg'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     &.mx_UserMenu_minimized { | ||||
|  |  | |||
|  | @ -383,6 +383,10 @@ export const Notifier = { | |||
|                 // don't bother notifying as user was recently active in this room
 | ||||
|                 return; | ||||
|             } | ||||
|             if (SettingsStore.getValue("doNotDisturb")) { | ||||
|                 // Don't bother the user if they didn't ask to be bothered
 | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (this.isEnabled()) { | ||||
|                 this._displayPopupNotification(ev, room); | ||||
|  |  | |||
|  | @ -74,6 +74,7 @@ interface IState { | |||
| export default class UserMenu extends React.Component<IProps, IState> { | ||||
|     private dispatcherRef: string; | ||||
|     private themeWatcherRef: string; | ||||
|     private dndWatcherRef: string; | ||||
|     private buttonRef: React.RefObject<HTMLButtonElement> = createRef(); | ||||
|     private tagStoreRef: fbEmitter.EventSubscription; | ||||
| 
 | ||||
|  | @ -89,6 +90,9 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
|         if (SettingsStore.getValue("feature_spaces")) { | ||||
|             SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdate); | ||||
|         } | ||||
| 
 | ||||
|         // Force update is the easiest way to trigger the UI update (we don't store state for this)
 | ||||
|         this.dndWatcherRef = SettingsStore.watchSetting("doNotDisturb", null, () => this.forceUpdate()); | ||||
|     } | ||||
| 
 | ||||
|     private get hasHomePage(): boolean { | ||||
|  | @ -103,6 +107,7 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
| 
 | ||||
|     public componentWillUnmount() { | ||||
|         if (this.themeWatcherRef) SettingsStore.unwatchSetting(this.themeWatcherRef); | ||||
|         if (this.dndWatcherRef) SettingsStore.unwatchSetting(this.dndWatcherRef); | ||||
|         if (this.dispatcherRef) defaultDispatcher.unregister(this.dispatcherRef); | ||||
|         OwnProfileStore.instance.off(UPDATE_EVENT, this.onProfileUpdate); | ||||
|         this.tagStoreRef.remove(); | ||||
|  | @ -288,6 +293,12 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
|         this.setState({contextMenuPosition: null}); // also close the menu
 | ||||
|     }; | ||||
| 
 | ||||
|     private onDndToggle = (ev) => { | ||||
|         ev.stopPropagation(); | ||||
|         const current = SettingsStore.getValue("doNotDisturb"); | ||||
|         SettingsStore.setValue("doNotDisturb", null, SettingLevel.DEVICE, !current); | ||||
|     }; | ||||
| 
 | ||||
|     private renderContextMenu = (): React.ReactNode => { | ||||
|         if (!this.state.contextMenuPosition) return null; | ||||
| 
 | ||||
|  | @ -534,6 +545,7 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
|                 {/* masked image in CSS */} | ||||
|             </span> | ||||
|         ); | ||||
|         let dnd; | ||||
|         if (this.state.selectedSpace) { | ||||
|             name = ( | ||||
|                 <div className="mx_UserMenu_doubleName"> | ||||
|  | @ -560,6 +572,16 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
|                 </div> | ||||
|             ); | ||||
|             isPrototype = true; | ||||
|         } else if (SettingsStore.getValue("feature_dnd")) { | ||||
|             const isDnd = SettingsStore.getValue("doNotDisturb"); | ||||
|             dnd = <AccessibleButton | ||||
|                 onClick={this.onDndToggle} | ||||
|                 className={classNames({ | ||||
|                     "mx_UserMenu_dnd": true, | ||||
|                     "mx_UserMenu_dnd_noisy": !isDnd, | ||||
|                     "mx_UserMenu_dnd_muted": isDnd, | ||||
|                 })} | ||||
|             />; | ||||
|         } | ||||
|         if (this.props.isMinimized) { | ||||
|             name = null; | ||||
|  | @ -595,6 +617,7 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
|                             /> | ||||
|                         </span> | ||||
|                         {name} | ||||
|                         {dnd} | ||||
|                         {buttons} | ||||
|                     </div> | ||||
|                 </ContextMenuButton> | ||||
|  |  | |||
|  | @ -786,6 +786,7 @@ | |||
|     "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", | ||||
|     "Change notification settings": "Change notification settings", | ||||
|     "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.", | ||||
|     "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", | ||||
|     "Send and receive voice messages (in development)": "Send and receive voice messages (in development)", | ||||
|     "Render LaTeX maths in messages": "Render LaTeX maths in messages", | ||||
|     "Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.": "Communities v2 prototypes. Requires compatible homeserver. Highly experimental - use with caution.", | ||||
|  |  | |||
|  | @ -128,6 +128,12 @@ export const SETTINGS: {[setting: string]: ISetting} = { | |||
|         default: false, | ||||
|         controller: new ReloadOnChangeController(), | ||||
|     }, | ||||
|     "feature_dnd": { | ||||
|         isFeature: true, | ||||
|         displayName: _td("Show options to enable 'Do not disturb' mode"), | ||||
|         supportedLevels: LEVELS_FEATURE, | ||||
|         default: false, | ||||
|     }, | ||||
|     "feature_voice_messages": { | ||||
|         isFeature: true, | ||||
|         displayName: _td("Send and receive voice messages (in development)"), | ||||
|  | @ -226,6 +232,10 @@ export const SETTINGS: {[setting: string]: ISetting} = { | |||
|         supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, | ||||
|         default: false, | ||||
|     }, | ||||
|     "doNotDisturb": { | ||||
|         supportedLevels: [SettingLevel.DEVICE], | ||||
|         default: false, | ||||
|     }, | ||||
|     "mjolnirRooms": { | ||||
|         supportedLevels: [SettingLevel.ACCOUNT], | ||||
|         default: [], | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Travis Ralston
						Travis Ralston