Labs: Add quick/cheap "do not disturb" flag
This just disables audio notifications and the popup, which is the easiest way to do "do not disturb" for a device. This needs spec changes to be done properly, as it's a shame that mobile devices for the user will still go off. Disabling all of push doesn't sound ideal as it would potentially mean missing highlights for when leaving DND mode.
This commit is contained in:
parent
2fb241cfc2
commit
eed5efdbe1
5 changed files with 64 additions and 0 deletions
|
@ -117,6 +117,32 @@ limitations under the License.
|
||||||
.mx_UserMenu_headerButtons {
|
.mx_UserMenu_headerButtons {
|
||||||
// No special styles: the rest of the layout happens to make it work.
|
// 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 {
|
&.mx_UserMenu_minimized {
|
||||||
|
|
|
@ -383,6 +383,10 @@ export const Notifier = {
|
||||||
// don't bother notifying as user was recently active in this room
|
// don't bother notifying as user was recently active in this room
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (SettingsStore.getValue("doNotDisturb")) {
|
||||||
|
// Don't bother the user if they didn't ask to be bothered
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isEnabled()) {
|
if (this.isEnabled()) {
|
||||||
this._displayPopupNotification(ev, room);
|
this._displayPopupNotification(ev, room);
|
||||||
|
|
|
@ -74,6 +74,7 @@ interface IState {
|
||||||
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 dndWatcherRef: string;
|
||||||
private buttonRef: React.RefObject<HTMLButtonElement> = createRef();
|
private buttonRef: React.RefObject<HTMLButtonElement> = createRef();
|
||||||
private tagStoreRef: fbEmitter.EventSubscription;
|
private tagStoreRef: fbEmitter.EventSubscription;
|
||||||
|
|
||||||
|
@ -89,6 +90,9 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
if (SettingsStore.getValue("feature_spaces")) {
|
if (SettingsStore.getValue("feature_spaces")) {
|
||||||
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdate);
|
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 {
|
private get hasHomePage(): boolean {
|
||||||
|
@ -103,6 +107,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
if (this.themeWatcherRef) SettingsStore.unwatchSetting(this.themeWatcherRef);
|
if (this.themeWatcherRef) SettingsStore.unwatchSetting(this.themeWatcherRef);
|
||||||
|
if (this.dndWatcherRef) SettingsStore.unwatchSetting(this.dndWatcherRef);
|
||||||
if (this.dispatcherRef) defaultDispatcher.unregister(this.dispatcherRef);
|
if (this.dispatcherRef) defaultDispatcher.unregister(this.dispatcherRef);
|
||||||
OwnProfileStore.instance.off(UPDATE_EVENT, this.onProfileUpdate);
|
OwnProfileStore.instance.off(UPDATE_EVENT, this.onProfileUpdate);
|
||||||
this.tagStoreRef.remove();
|
this.tagStoreRef.remove();
|
||||||
|
@ -288,6 +293,12 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
this.setState({contextMenuPosition: null}); // also close the menu
|
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 => {
|
private renderContextMenu = (): React.ReactNode => {
|
||||||
if (!this.state.contextMenuPosition) return null;
|
if (!this.state.contextMenuPosition) return null;
|
||||||
|
|
||||||
|
@ -534,6 +545,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
{/* masked image in CSS */}
|
{/* masked image in CSS */}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
let dnd;
|
||||||
if (this.state.selectedSpace) {
|
if (this.state.selectedSpace) {
|
||||||
name = (
|
name = (
|
||||||
<div className="mx_UserMenu_doubleName">
|
<div className="mx_UserMenu_doubleName">
|
||||||
|
@ -560,6 +572,16 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
isPrototype = true;
|
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) {
|
if (this.props.isMinimized) {
|
||||||
name = null;
|
name = null;
|
||||||
|
@ -595,6 +617,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
{name}
|
{name}
|
||||||
|
{dnd}
|
||||||
{buttons}
|
{buttons}
|
||||||
</div>
|
</div>
|
||||||
</ContextMenuButton>
|
</ContextMenuButton>
|
||||||
|
|
|
@ -786,6 +786,7 @@
|
||||||
"%(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",
|
||||||
"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.",
|
"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)",
|
"Send and receive voice messages (in development)": "Send and receive voice messages (in development)",
|
||||||
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
|
"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.",
|
"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,
|
default: false,
|
||||||
controller: new ReloadOnChangeController(),
|
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": {
|
"feature_voice_messages": {
|
||||||
isFeature: true,
|
isFeature: true,
|
||||||
displayName: _td("Send and receive voice messages (in development)"),
|
displayName: _td("Send and receive voice messages (in development)"),
|
||||||
|
@ -226,6 +232,10 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
"doNotDisturb": {
|
||||||
|
supportedLevels: [SettingLevel.DEVICE],
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
"mjolnirRooms": {
|
"mjolnirRooms": {
|
||||||
supportedLevels: [SettingLevel.ACCOUNT],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [],
|
default: [],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue