Skip to content

Commit

Permalink
Add option to hide menu bar (#1215)
Browse files Browse the repository at this point in the history
Closes #293
Based on #1216

This adds an option to auto-hide the menu bar on Windows/Linux Electron. The option will be in Settings ▸ Display.

screen shot 2019-02-21 at 23 26 17

We have to be careful not to get the user stuck in a situation where they can't bring back the menu bar, so we'll show the Settings button and footer links in the Navigation Bar when auto-hide is enabled.
  • Loading branch information
mirka authored and belcherj committed Oct 16, 2019
1 parent 7e6c067 commit 6f8005a
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 35 deletions.
5 changes: 5 additions & 0 deletions desktop/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ module.exports = function main() {
});
});

ipcMain.on('setAutoHideMenuBar', function(event, autoHideMenuBar) {
mainWindow.setAutoHideMenuBar(autoHideMenuBar || false);
mainWindow.setMenuBarVisibility(!autoHideMenuBar);
});

mainWindowState.manage(mainWindow);

mainWindow.webContents.on('new-window', function(event, linkUrl) {
Expand Down
7 changes: 6 additions & 1 deletion lib/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function mapDispatchToProps(dispatch, { noteBucket }) {
'setNoteDisplay',
'setMarkdown',
'setAccountName',
'toggleAutoHideMenuBar',
'toggleFocusMode',
'toggleSpellCheck',
]),
Expand Down Expand Up @@ -145,6 +146,7 @@ export const App = connect(

componentDidMount() {
ipc.on('appCommand', this.onAppCommand);
ipc.send('setAutoHideMenuBar', this.props.settings.autoHideMenuBar);
ipc.send('settingsUpdate', this.props.settings);

this.props.noteBucket
Expand Down Expand Up @@ -435,7 +437,9 @@ export const App = connect(
{isDevConfig && <DevBadge />}
{isAuthorized ? (
<div className={mainClasses}>
{state.showNavigation && <NavigationBar />}
{state.showNavigation && (
<NavigationBar isElectron={isElectron()} />
)}
<AppLayout
isFocusMode={settings.focusModeEnabled}
isNavigationOpen={state.showNavigation}
Expand Down Expand Up @@ -470,6 +474,7 @@ export const App = connect(
closeDialog={this.props.actions.closeDialog}
dialogs={this.props.appState.dialogs}
isElectron={isElectron()}
isMacApp={isMacApp}
/>
</div>
);
Expand Down
3 changes: 3 additions & 0 deletions lib/dialog-renderer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const DialogRenderer = props => {
closeDialog,
dialogs,
isElectron,
isMacApp,
} = props;

const renderDialog = dialog => {
Expand Down Expand Up @@ -40,6 +41,7 @@ export const DialogRenderer = props => {
dialog={dialog}
requestClose={closeThisDialog}
isElectron={isElectron}
isMacApp={isMacApp}
{...appProps}
/>
</Modal>
Expand All @@ -56,6 +58,7 @@ DialogRenderer.propTypes = {
closeDialog: PropTypes.func.isRequired,
dialogs: PropTypes.array.isRequired,
isElectron: PropTypes.bool.isRequired,
isMacApp: PropTypes.bool.isRequired,
};

export default DialogRenderer;
16 changes: 14 additions & 2 deletions lib/dialogs/settings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class SettingsDialog extends Component {
dialog: PropTypes.shape({ title: PropTypes.string.isRequired }),
onSignOut: PropTypes.func.isRequired,
isElectron: PropTypes.bool.isRequired,
isMacApp: PropTypes.bool.isRequired,
onSetWPToken: PropTypes.func.isRequired,
requestClose: PropTypes.func.isRequired,
settings: PropTypes.object.isRequired,
Expand Down Expand Up @@ -118,7 +119,14 @@ export class SettingsDialog extends Component {
};

render() {
const { buckets, dialog, requestClose, settings } = this.props;
const {
buckets,
dialog,
isElectron,
isMacApp,
requestClose,
settings,
} = this.props;
const { analyticsEnabled } = this.props.appState.preferences;

return (
Expand All @@ -132,7 +140,11 @@ export class SettingsDialog extends Component {
this.onToggleShareAnalyticsPreference
}
/>
<DisplayPanel buckets={buckets} />
<DisplayPanel
buckets={buckets}
isElectron={isElectron}
isMacApp={isMacApp}
/>
<ToolsPanel />
</TabPanels>
</Dialog>
Expand Down
20 changes: 20 additions & 0 deletions lib/dialogs/settings/panels/display.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ const DisplayPanel = props => {
const {
actions,
activeTheme,
autoHideMenuBar,
buckets: { noteBucket },
isElectron,
isMacApp,
lineLength,
loadNotes,
noteDisplay,
Expand Down Expand Up @@ -108,16 +111,32 @@ const DisplayPanel = props => {
<Item title="Light" slug="light" />
<Item title="Dark" slug="dark" />
</SettingsGroup>

{isElectron && !isMacApp && (
<SettingsGroup
title="Menu Bar"
slug="autoHideMenuBar"
activeSlug={autoHideMenuBar ? 'autoHide' : ''}
description="When set to auto-hide, press the Alt key to toggle."
onChange={actions.toggleAutoHideMenuBar}
renderer={ToggleGroup}
>
<Item title="Hide Automatically" slug="autoHide" />
</SettingsGroup>
)}
</Fragment>
);
};

DisplayPanel.propTypes = {
actions: PropTypes.object.isRequired,
activeTheme: PropTypes.string.isRequired,
autoHideMenuBar: PropTypes.bool,
buckets: PropTypes.shape({
noteBucket: PropTypes.object.isRequired,
}),
isElectron: PropTypes.bool.isRequired,
isMacApp: PropTypes.bool.isRequired,
lineLength: PropTypes.string.isRequired,
loadNotes: PropTypes.func.isRequired,
loadTags: PropTypes.func.isRequired,
Expand All @@ -130,6 +149,7 @@ DisplayPanel.propTypes = {
const mapStateToProps = ({ settings }) => {
return {
activeTheme: settings.theme,
autoHideMenuBar: settings.autoHideMenuBar,
lineLength: settings.lineLength,
noteDisplay: settings.noteDisplay,
sortIsReversed: settings.sortReversed,
Expand Down
61 changes: 36 additions & 25 deletions lib/navigation-bar/index.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import onClickOutside from 'react-onclickoutside';
Expand All @@ -18,7 +18,9 @@ export class NavigationBar extends Component {
static displayName = 'NavigationBar';

static propTypes = {
autoHideMenuBar: PropTypes.bool,
dialogs: PropTypes.array.isRequired,
isElectron: PropTypes.bool.isRequired,
isOffline: PropTypes.bool.isRequired,
onAbout: PropTypes.func.isRequired,
onOutsideClick: PropTypes.func.isRequired,
Expand Down Expand Up @@ -65,6 +67,8 @@ export class NavigationBar extends Component {

render() {
const {
autoHideMenuBar,
isElectron,
isOffline,
onAbout,
onSettings,
Expand All @@ -91,29 +95,35 @@ export class NavigationBar extends Component {
<div className="navigation-bar__tags theme-color-border">
<TagList />
</div>
<div className="navigation-bar__tools theme-color-border">
<NavigationBarItem
icon={<SettingsIcon />}
label="Settings"
onClick={onSettings}
/>
</div>
<div className="navigation-bar__footer">
<button
type="button"
className="navigation-bar__footer-item theme-color-fg-dim"
onClick={this.onHelpClicked}
>
Help &amp; Support
</button>
<button
type="button"
className="navigation-bar__footer-item theme-color-fg-dim"
onClick={onAbout}
>
About
</button>
</div>

{(!isElectron || autoHideMenuBar) && (
<Fragment>
<div className="navigation-bar__tools theme-color-border">
<NavigationBarItem
icon={<SettingsIcon />}
label="Settings"
onClick={onSettings}
/>
</div>
<div className="navigation-bar__footer">
<button
type="button"
className="navigation-bar__footer-item theme-color-fg-dim"
onClick={this.onHelpClicked}
>
Help &amp; Support
</button>
<button
type="button"
className="navigation-bar__footer-item theme-color-fg-dim"
onClick={onAbout}
>
About
</button>
</div>
</Fragment>
)}

<div className="navigation-bar__sync-status theme-color-fg-dim theme-color-border">
<SyncStatus isOffline={isOffline} unsyncedNoteIds={unsyncedNoteIds} />
</div>
Expand All @@ -122,7 +132,8 @@ export class NavigationBar extends Component {
}
}

const mapStateToProps = ({ appState: state }) => ({
const mapStateToProps = ({ appState: state, settings }) => ({
autoHideMenuBar: settings.autoHideMenuBar,
dialogs: state.dialogs,
isOffline: state.isOffline,
selectedTag: state.tag,
Expand Down
7 changes: 0 additions & 7 deletions lib/navigation-bar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,6 @@
color: $studio-gray-80;
}

.is-electron {
.navigation-bar__tools,
.navigation-bar__footer {
display: none;
}
}

.navigation-bar__footer-item {
margin-right: 10px;

Expand Down
15 changes: 15 additions & 0 deletions lib/state/settings/actions.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { getIpcRenderer } from '../../utils/electron';

const ipc = getIpcRenderer();

export const setFontSize = fontSize => ({
type: 'setFontSize',
fontSize,
Expand Down Expand Up @@ -83,3 +87,14 @@ export const toggleSpellCheck = () => (dispatch, getState) => {
spellCheckEnabled: !getState().settings.spellCheckEnabled,
});
};

export const toggleAutoHideMenuBar = () => (dispatch, getState) => {
const newValue = !getState().settings.autoHideMenuBar;

ipc.send('setAutoHideMenuBar', newValue);

dispatch({
type: 'setAutoHideMenuBar',
autoHideMenuBar: newValue,
});
};
3 changes: 3 additions & 0 deletions lib/state/settings/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { clamp } from 'lodash';

export const initialState = {
accountName: null,
autoHideMenuBar: false,
focusModeEnabled: false,
fontSize: 16,
lineLength: 'narrow',
Expand All @@ -19,6 +20,8 @@ function reducer(state = initialState, action) {
switch (action.type) {
case 'setAccountName':
return { ...state, accountName: action.accountName };
case 'setAutoHideMenuBar':
return { ...state, autoHideMenuBar: action.autoHideMenuBar };
case 'setFocusMode':
return { ...state, focusModeEnabled: action.focusModeEnabled };
case 'setFontSize':
Expand Down

0 comments on commit 6f8005a

Please sign in to comment.