1. 30 Mar, 2022 1 commit
    • Robert Knight's avatar
      Install shortcut listener on document element · d9de7bde
      Robert Knight authored
      Listen for key events for keyboard shortcuts on the document element rather than
      body element, to make them work in XHTML documents.
      
      When no interactive element (eg. an input field) is focused in an HTML document,
      keyboard events are sent to the body element. In an XHTML document however
      keyboard events are sent to the document element instead in Safari and Chrome
      (in Firefox they are still sent to the body). The key event listeners used for
      the adder's shortcuts were installed on the body element, so they didn't work in
      XHTML documents in Safari and Chrome.
      
      My guess is that the reason for this behavioral quirk is that HTML documents are
      guaranteed to have a body element - an empty one will be generated if none
      is present in the markup, whereas XHTML documents are not.
      
      Fixes https://github.com/hypothesis/client/issues/4364
      d9de7bde
  2. 29 Mar, 2022 5 commits
  3. 28 Mar, 2022 13 commits
  4. 25 Mar, 2022 2 commits
  5. 24 Mar, 2022 3 commits
    • Robert Knight's avatar
      Introduce a pattern for fully typed store modules · 9d40fff9
      Robert Knight authored
      Introduce a pattern for creating store modules which are fully typed,
      using the "activity" module as a test case / example. This allows
      TypeScript to check both external usage of the module, as well as
      internal consistency between the different elements of it (initial
      state, reducers, action creators, selectors).
      
      The elements of this pattern are:
      
       - A `State` type is defined in each module, which is typically whatever
         shape the module's initial state has.
      
       - Each function in the `reducers` map specifies the type of its `state`
         parameter as `State` and defines the fields of the action.
      
       - Action creators use a new `makeAction` helper, which ensures that the
         type of dispatched actions matches what the reducer expects
      
       - The `createStoreModule` helper ties all the elements of the module
         (reducers, actions, selectors) together and makes sure they are
         consistent with one another.
      
      The general structure of a typed store module, to which the various existing
      modules will converge, is:
      
      ```js
      import { createStoreModule, makeAction } from '../create-store';
      
      const initialState = { ... }
      
      /** @typedef {typeof initialState} State */
      
      const reducers = {
        /**
         * @param {State} state
         * @param {{ id: string }} action
         */
        SOME_ACTION(state, action) {
          ...
        }
      }
      
      /**
       * @param {string} id
       */
      function someAction(id) {
        return makeAction(reducers, 'SOME_ACTION', { id });
      }
      
      /**
       * @param {State}
       */
      function someSelector(state) {
        ...
      }
      
      export someModule = createStoreModule(initialState, {
        namespace: 'someModule',
        reducers,
        actionCreators: { someAction },
        selectors: { someSelector },
      });
      ```
      9d40fff9
    • Robert Knight's avatar
      Remove `DefaultIfAny` helper · 788697ec
      Robert Knight authored
      Remove a cryptic piece of code that is no longer needed given the ability to
      specify default values for template arguments [1]
      
      [1] https://github.com/microsoft/TypeScript/pull/45483
      788697ec
    • Lyza Danger Gardner's avatar
      a95447b1
  6. 23 Mar, 2022 6 commits
  7. 22 Mar, 2022 2 commits
    • Robert Knight's avatar
      Reset callback before checking for absence of call · d5ace953
      Robert Knight authored
      This pattern makes it clearer that we are testing for a callback not
      being invoked after a sequence of events.
      d5ace953
    • Robert Knight's avatar
      Fix issues that could cause unexpected `onDocumentReady` firing · f7ab8ac0
      Robert Knight authored
      Fix various issues that could cause the callback to `onDocumentReady` to
      fire after the subscription had been canceled.
      
       - `pollOnUnload` was called twice for the initial document, once at the
         top level of the function and once by the first call to
         `checkForDocumentChange`. This resulted into "unload" listeners being
         added for the same window.
      
       - The initial async `checkForDocumentChange` call would still fire if
         the subscription was immediately canceled
      
       - If the current window's "unload" event fired after the subscription
         was canceled, polling would be restarted, effectively re-subscribing
         to document changes.
      f7ab8ac0
  8. 21 Mar, 2022 8 commits