Skip to content

Commit

Permalink
Warn users about single-char shortcuts - Closes #25
Browse files Browse the repository at this point in the history
  • Loading branch information
andyshand committed Mar 9, 2021
1 parent 871142a commit 8d80652
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 33 deletions.
40 changes: 8 additions & 32 deletions src/renderer/settings/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ModLogs } from './ModLogs'
import { SettingsFooter } from './SettingsFooter'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { ModwigComponent } from '../core/ModwigComponent'
import { ShortcutsView } from './ShortcutsView'
const xPad = `4rem`
const SettingsViewWrap = styled.div`
background: #1e1e1e;
Expand Down Expand Up @@ -295,6 +296,9 @@ const ModsWrap = styled.div`
height: 100%;
overflow-y: auto;
`
const ContentWrap = styled.div`
position: relative;
`
const SettingItem = ({setting: sett, focused}) => {
return <SettingItemWrap id={sett.key} focused={focused}>
<div>
Expand Down Expand Up @@ -342,7 +346,7 @@ const SearchIconWrap = ({ onClick }) => {
export class SettingsView extends ModwigComponent<Props> {

state = {
category: 'mod',
category: undefined,
settings: [],
loading: true,
searchQuery: '',
Expand Down Expand Up @@ -475,37 +479,9 @@ export class SettingsView extends ModwigComponent<Props> {
const filteredSettings = this.state.settings.filter(s => {
return this.state.searchQuery === '' || (s.key + s.description).toLowerCase().indexOf(this.state.searchQuery) >= 0
})
const addedByMod = _.groupBy(filteredSettings, setting => setting.modName)
return <NavSplit>
<div>
{Object.keys(addedByMod).map(mod => {
const settings = addedByMod[mod]
return <SidebarSection key={mod}>
<div style={{color: '#777'}}>{mod == 'null' ? 'Modwig Core' : mod}</div>
<div>
{settings.map(setting => {
const onClick = () => {
this.setState({
focusedSettingKey: setting.key
})
document.getElementById(setting.key).scrollIntoView({behavior: 'auto', block: 'center'})
}
return <SidebarSetting focused={setting.key === this.state.focusedSettingKey} title={settingTitle(setting)} onClick={onClick} key={setting.key}>
<span style={{
whiteSpace: `normal`,
wordBreak: `break-word`
}}>{shortcutToTextDescription(setting)}</span>
<span>{settingTitle(setting)}</span>
</SidebarSetting>
})}
</div>
</SidebarSection>
})}
</div>
<div>
{this.renderShortcutList(addedByMod)}
</div>
</NavSplit>
return <ContentWrap>
<ShortcutsView settings={filteredSettings} />
</ContentWrap>
}

render() {
Expand Down
136 changes: 136 additions & 0 deletions src/renderer/settings/ShortcutsView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React, { useState } from 'react'
import { styled } from 'linaria/react'
import { settingShortDescription, settingTitle, shortcutToTextDescription, shouldShortcutWarn } from './helpers/settingTitle'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faExclamation } from '@fortawesome/free-solid-svg-icons'
import { SettingShortcut } from './setting/SettingShortcut'
const TableWrap = styled.div`
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 33.3%;
overflow-y: auto;
tbody tr {
&:hover {
background: #181818;
}
}
th, td {
padding: 0.2em 1.2rem;
&:not(:last-child) {
border-right: 1px solid #111;
}
}
th {
text-align: left;
font-weight: 400;
padding-top: .9em;
padding-bottom: 1em;
color: #5b5b5b;
}
td {
font-size: .9em;
/* color: #ccc; */
color: #818181;
/* &:not(:first-child) { */
/* } */
}
table {
width: 100%;
}
table, th, td {
/* border: 1px solid black; */
border-collapse: collapse;
}
cursor: pointer;
`
const Wrap = styled.div`
`
const InfoPanelWrap = styled.div`
position: absolute;
top: 0;
left: 66.7%;
bottom: 0;
right: 0;
overflow-y: auto;
background: #121212;
border-left: 1px solid black;
> div {
padding: 2.5rem;
>h1 {
font-size: 1.2em;
font-weight: 400;
}
>p {
margin-top: 2rem;
color: #717171;
}
>div {
margin-top: 5.5rem;
max-width: 11.9rem;
margin: 2.5rem auto;
}
}
`
const InfoPanel = ({selectedSetting}) => {
if (selectedSetting) {
return <InfoPanelWrap>
<div>
<h1>{settingTitle(selectedSetting)}</h1>
<p>{settingShortDescription(selectedSetting)}</p>
<div><SettingShortcut setting={selectedSetting} /></div>
</div>
</InfoPanelWrap>
} else {
return <InfoPanelWrap>Select a setting to see more info.</InfoPanelWrap>
}
}

const WarningIcon = styled.div`
background: #ecec58;
border-radius: 1000px;
height: 1.6em;
color: #606029;
width: 1.6em;
font-size: 0.7em;
border: 1px solid #606029;
display: inline-flex;
align-items: center;
justify-content: center;
`
const Warning = () => {
return <WarningIcon title={`Please note it's currently not possible to prevent single character shortcuts from triggering in text fields`}>
<FontAwesomeIcon icon={faExclamation} />
</WarningIcon>
}

export const ShortcutsView = ({ settings }) => {
const [selectedSetting, setSelectedSetting] = useState(null)

return <Wrap>
<TableWrap>
<table>
<thead>
<tr>
<th>Name</th>
<th>Mod</th>
<th>Shortcut</th>
</tr>
</thead>
<tbody>
{settings.map(sett => {
return <tr key={sett.key} onClick={() => setSelectedSetting(sett)} style={sett.key === (selectedSetting?.key ?? null) ? {background: '#111'} : {}}>
<td>{settingTitle(sett)}</td>
<td>{sett.mod}</td>
<td>{shortcutToTextDescription(sett)} {shouldShortcutWarn(sett) ? <Warning /> : null}</td>
{/* <td></td> */}
</tr>
})}
</tbody>
</table>
</TableWrap>
<InfoPanel selectedSetting={selectedSetting} />
</Wrap>
}
5 changes: 5 additions & 0 deletions src/renderer/settings/helpers/settingTitle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ export const settingTitle = setting => {
return setting.name || setting.title || titleize(humanise(setting.key))
}

export function shouldShortcutWarn (sett) {
const keys = sett.value.keys || []
return keys.length === 1 && keys[0].length === 1 && /[a-z0-9]/i.test(keys[0])
}

export const settingShortDescription = setting => {
if (typeof setting.description !== 'string') {
return 'No description available.'
Expand Down
13 changes: 12 additions & 1 deletion src/renderer/settings/setting/SettingShortcut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React, {useEffect, useState} from 'react'
import { styled } from 'linaria/react'
import { sendPromise } from '../../bitwig-api/Bitwig'
import { shortcutToTextDescription } from '../helpers/settingTitle'
import { shortcutToTextDescription, shouldShortcutWarn } from '../helpers/settingTitle'
import { Checkbox } from '../../core/Checkbox'

const ShortcutInput = styled.input`
Expand All @@ -20,13 +20,17 @@ const ShortcutInput = styled.input`
const ShortcutWrap = styled.div`
user-select: none;
cursor: default;
`
const InputWrap = styled.div`
border: 1px solid ${(props: any) => props.focused ? `#CCC` : `#272727`};
background: ${(props: any) => props.noShortcut ? `transparent` : `#272727`};;
border-radius: 0.3rem;
cursor: pointer;
position: relative;
display: flex;
align-items: center;
justify-content: center;
input {
color: ${(props: any) => props.noShortcut ? `#555` : `#a6a6a6`};
}
Expand Down Expand Up @@ -123,6 +127,12 @@ const Option = ({value, id, onChange, label}) => {
</OptionWrap>
}

const WarningText = styled.div`
font-size: 0.7em;
margin: 1em 0;
color: #8c8c8c;
`

export const SettingShortcut = ({setting}) => {

const [value, setValue] = useState(setting.value)
Expand Down Expand Up @@ -233,6 +243,7 @@ export const SettingShortcut = ({setting}) => {
<ShortcutInput {...props} />
<div className="setdefault"><FontAwesomeIcon onClick={() => updateValue({...value, keys: []})} icon={faTimesCircle} /></div>
</InputWrap>
{shouldShortcutWarn(setting) ? <WarningText>Please note it's currently not possible to prevent single character shortcuts from triggering in text fields</WarningText> : null}
<OptionsWrap>
{options.map(option => {
return <Option {...option} />
Expand Down

0 comments on commit 8d80652

Please sign in to comment.