Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Fix focus issues#3505

Merged
jasonLaster merged 2 commits into
firefox-devtools:masterfrom
wldcordeiro:fix-focus-issues
Aug 7, 2017
Merged

Fix focus issues#3505
jasonLaster merged 2 commits into
firefox-devtools:masterfrom
wldcordeiro:fix-focus-issues

Conversation

@wldcordeiro
Copy link
Copy Markdown
Contributor

Associated Issue: #3495

Summary of Changes

  • Fixes the focus issue across all search inputs. They now take focus when enabled.
  • Bump yarn.lock to match updated devtools-reps version
  • CSS got reformatted by prettier?

Test Plan

Example test plan:

  • Command-P opens the panel with focus
  • Command-F opens search panel with focus
  • Comman-Shift-O opens symbol search with focus

@codecov
Copy link
Copy Markdown

codecov Bot commented Jul 31, 2017

Codecov Report

Merging #3505 into master will increase coverage by 0.08%.
The diff coverage is 86.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3505      +/-   ##
==========================================
+ Coverage   54.35%   54.44%   +0.08%     
==========================================
  Files         119      119              
  Lines        4660     4662       +2     
  Branches      962      962              
==========================================
+ Hits         2533     2538       +5     
+ Misses       2127     2124       -3
Impacted Files Coverage Δ
src/components/shared/SearchInput.js 92.59% <100%> (+0.92%) ⬆️
src/components/shared/Modal.js 88.23% <100%> (+19.81%) ⬆️
src/components/SymbolModal.js 43.07% <33.33%> (-1.11%) ⬇️
src/actions/ast.js 78.57% <0%> (+1.78%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2a90c35...2188a50. Read the comment docs.

Copy link
Copy Markdown
Contributor

@codehag codehag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, I like this pattern, using refs instead of using componentDidMount + reactDom.findDOMNode for associating a node to the component. I think we should use it elsewhere too!

A couple of comments, and can you also add the test from the issue?

Comment thread src/components/shared/SearchInput.js Outdated
static defaultProps: Object;

componentDidMount() {
this.input.focus();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment thread src/components/shared/SearchInput.js Outdated

componentDidMount() {
this.input.focus();
this.input.select();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the old code, we used setSelectionRange -- was this to move the cursor to the end of the input? I also noticed that in both cases we only fire select when the component is opened, and in that case it is empty. perhaps we don't need this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were using it but we were making a selection of the end to the end? So I wasn't sure what exactly that was achieving. I don't think it nor .select() make a ton of sense so I don't care for keeping them.

@wldcordeiro
Copy link
Copy Markdown
Contributor Author

can you also add the test from the issue?

Sure! I forgot that the issue had a test associated. Thanks @codehag

pressKey(dbg, "sourceSearch");
yield waitForElement(dbg, "input");
findElementWithSelector(dbg, "input").focus();
ok(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong but this is the way to assert in mochitest?

Copy link
Copy Markdown
Contributor

@jasonLaster jasonLaster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of comments, but overall this is great!

Comment thread src/components/shared/SearchInput.js Outdated
value: query,
spellCheck: false,
ref: "input"
ref: c => (this.input = c)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the preferred style?

perhaps? ref: c => (this.$input = c)

it's funny, i prefer refs because their namespaced, but i'll support anything.

Also this style is fine w/ me too
https://github.com/devtools-html/debugger.html/blob/master/src/components/shared/Autocomplete.js#L51-L53

Comment thread src/components/SymbolModal.js Outdated
if (
this.refs.searchInput &&
this.refs.searchInput.input &&
this.props.enabled
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: but lets put this.props.enabled first


if (selectedSource && enabled) {
modalEnabled = true;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we might be playing too much of a dance w/ enabled, perhaps a new method is in order:

  • we dont need enabled prop
  • we can consolidate logic
isEnabled() {
  const {activeSearch, selectedSource} = this.props
  return activeSearch === "symbol" && selectedSource
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So enabled is also used for whether to update the results or not. I figured that I could instead modify the value we get in the connect call.

export default connect(
  state => {
    const source = getSelectedSource(state);
    return {
      enabled: getActiveSearchState(state) === "symbol" && source,
      symbolType: getSymbolSearchType(state),
      symbols: _getFormattedSymbols(state, source)
    };
  },
  dispatch => bindActionCreators(actions, dispatch)
)(SymbolModal);

pressKey(dbg, "sourceSearch");
yield waitForElement(dbg, "input");
findElementWithSelector(dbg, "input").focus();
ok(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, that will work!

i guess i was assuming it because the next action is typing... and it will work or fail based on that, but i don't care. this is nice to have.

Copy link
Copy Markdown
Contributor

@jasonLaster jasonLaster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of comments, but overall this is great!

Comment thread src/components/shared/SearchInput.js Outdated
value: query,
spellCheck: false,
ref: "input"
ref: c => (this.input = c)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the preferred style?

perhaps? ref: c => (this.$input = c)

it's funny, i prefer refs because their namespaced, but i'll support anything.

Also this style is fine w/ me too
https://github.com/devtools-html/debugger.html/blob/master/src/components/shared/Autocomplete.js#L51-L53

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting that we use the $ to prefix it as a ref?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i prefer $ if we do the property style. I still like ReactDOM.findNode or this.ref as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I could put the ref into the refs object as well by changing the line to this.refs.input = c

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction. Seems like you can't add the property to the refs object via a function ref.

Comment thread src/components/SymbolModal.js Outdated
if (
this.refs.searchInput &&
this.refs.searchInput.input &&
this.props.enabled
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: but lets put this.props.enabled first


if (selectedSource && enabled) {
modalEnabled = true;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we might be playing too much of a dance w/ enabled, perhaps a new method is in order:

  • we dont need enabled prop
  • we can consolidate logic
isEnabled() {
  const {activeSearch, selectedSource} = this.props
  return activeSearch === "symbol" && selectedSource
}

pressKey(dbg, "sourceSearch");
yield waitForElement(dbg, "input");
findElementWithSelector(dbg, "input").focus();
ok(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, that will work!

i guess i was assuming it because the next action is typing... and it will work or fail based on that, but i don't care. this is nice to have.

Comment thread src/components/shared/Modal.js Outdated

componentDidUpdate() {
const shortcuts = this.context.shortcuts;
if (this.props.enabled) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, this worries me because we might be doing too many on calls.

Should we add a check in here like !props.enabled && nextProps.enabled?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this and it wouldn't work after the first time you toggled on.

@jasonLaster jasonLaster changed the base branch from next to master August 1, 2017 18:43
@codehag
Copy link
Copy Markdown
Contributor

codehag commented Aug 3, 2017

Rebased

@codehag
Copy link
Copy Markdown
Contributor

codehag commented Aug 3, 2017

Not sure what is happening with the tests; they pass on master and locally. looks like the problem is again with pretty print:


The following tests failed:

3522 INFO TEST-UNEXPECTED-FAIL | devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js | Uncaught exception - at chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/head.js:382 - Error: Unable to find source: math.min.js:formatted

Stack trace:

    findSource@chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/head.js:382:11

    @chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/browser_dbg-pretty-print.js:13:17

    Tester_execTest@chrome://mochikit/content/browser-test.js:735:9

    Tester.prototype.nextTest</<@chrome://mochikit/content/browser-test.js:655:7

    SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:791:59

    Tester_execTest@chrome://mochikit/content/browser-test.js:735:9

    Tester.prototype.nextTest</<@chrome://mochikit/content/browser-test.js:655:7

    SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:791:59

3523 INFO TEST-UNEXPECTED-FAIL | devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js | focused on input - 

Stack trace:

    chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js:null:10

    Tester_execTest@chrome://mochikit/content/browser-test.js:735:9

    Tester.prototype.nextTest</<@chrome://mochikit/content/browser-test.js:655:7

    SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:791:59

3524 INFO TEST-UNEXPECTED-FAIL | devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js | focused on input - 

Stack trace:

    chrome://mochitests/content/browser/devtools/client/debugger/new/test/mochitest/browser_dbg-searching.js:null:23

    Tester_execTest@chrome://mochikit/content/browser-test.js:735:9

    Tester.prototype.nextTest</<@chrome://mochikit/content/browser-test.js:655:7

    SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:791:59

Buffered messages finished

SUITE-END | took 150s


./bin/run-mochitests-docker returned exit code 1

Copy link
Copy Markdown
Contributor

@codehag codehag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed a bit of an issue with a parent component controlling a child components behavior -- i think we should change that but overall it looks good

const shortcuts = this.context.shortcuts;
if (this.refs.searchInput) {
this.refs.searchInput.refs.input.focus();
this.refs.searchInput.$input.focus();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this looks like it might give us trouble later on -- we are controlling a child component from a parent component; this makes it difficult to separate them -- we probably want searchInput to do this, rather than doing it here.

static defaultProps: Object;

componentDidMount() {
this.$input.focus();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be enough... was it not working with this ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the modal is mounted the symbol modal needs to have that if block to focus the input. I'll research further to see if there's a solution that's cleaner but this gets the focus events working on all the search dialogs and ensures we have no regressions on the shortcuts.

@wldcordeiro wldcordeiro force-pushed the fix-focus-issues branch 2 times, most recently from 800073e to f68c3fb Compare August 3, 2017 23:28
Comment thread package.json Outdated
"wasmparser": "^0.4.10"
},
"files": ["src", "assets"],
"files": [
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yarn reformats this file when you use yarn add 🤷‍♂️

}

.theme-dark .symbol-modal {
box-shadow: 2px 4px 6px var(--popup-shadow-color);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant rule? It's on the modal itself just above.

@wldcordeiro wldcordeiro force-pushed the fix-focus-issues branch 2 times, most recently from f7c39fe to 672a559 Compare August 4, 2017 01:18
componentDidMount() {
const shortcuts = this.context.shortcuts;
shortcuts.on(L10N.getStr("symbolSearch.search.key2"), this.openSymbolModal);
shortcuts.on("Escape", this.closeModal);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was problematic adding shortcuts to the modal itself and would leave the shortcut disabled on its dismount. Letting the consumer's handle it seems like a simpler API.

return Transition({
in: inProp,
timeout: 175,
appear: true,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally a component is not transitioned if it shown when the component mounts. If you want to transition on the first mount set appear to true, and the component will transition in as soon as the mounts.

This prop is awesome but sadly there doesn't seem to be a leave that is the equivalent. I've opened an issue on react-transition-group requesting one to see what they recommend.

@wldcordeiro
Copy link
Copy Markdown
Contributor Author

wldcordeiro commented Aug 4, 2017

So now the two assertions I added to the mochitests fail but from testing all three search inputs get focus when you open them. 🙁

Edit: Ran locally and they passed.

@wldcordeiro wldcordeiro force-pushed the fix-focus-issues branch 6 times, most recently from 3aa564f to 1e118e5 Compare August 7, 2017 15:59
@jasonLaster jasonLaster merged commit 4069f0f into firefox-devtools:master Aug 7, 2017
@wldcordeiro wldcordeiro deleted the fix-focus-issues branch August 7, 2017 17:55
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants