Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
5f82322e
Commit
5f82322e
authored
Mar 17, 2022
by
Robert Knight
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add missing types to various callbacks / props in components
parent
6986607d
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
64 additions
and
21 deletions
+64
-21
AnnotationEditor.js
src/sidebar/components/Annotation/AnnotationEditor.js
+1
-0
Excerpt.js
src/sidebar/components/Excerpt.js
+3
-2
HelpPanel.js
src/sidebar/components/HelpPanel.js
+13
-6
MarkdownEditor.js
src/sidebar/components/MarkdownEditor.js
+2
-0
Menu.js
src/sidebar/components/Menu.js
+3
-0
MenuItem.js
src/sidebar/components/MenuItem.js
+2
-0
MenuKeyboardNavigation.js
src/sidebar/components/MenuKeyboardNavigation.js
+3
-1
NotebookView.js
src/sidebar/components/NotebookView.js
+2
-1
PaginationNavigation.js
src/sidebar/components/PaginationNavigation.js
+21
-5
SearchInput.js
src/sidebar/components/SearchInput.js
+1
-0
ShareLinks.js
src/sidebar/components/ShareLinks.js
+3
-3
StreamSearchInput.js
src/sidebar/components/StreamSearchInput.js
+1
-0
StreamView.js
src/sidebar/components/StreamView.js
+1
-2
ToastMessages.js
src/sidebar/components/ToastMessages.js
+1
-1
Tutorial.js
src/sidebar/components/Tutorial.js
+3
-0
UserMenu.js
src/sidebar/components/UserMenu.js
+3
-0
use-filter-options.js
src/sidebar/components/hooks/use-filter-options.js
+1
-0
No files found.
src/sidebar/components/Annotation/AnnotationEditor.js
View file @
5f82322e
...
...
@@ -116,6 +116,7 @@ function AnnotationEditor({
};
// Allow saving of annotation by pressing CMD/CTRL-Enter
/** @param {KeyboardEvent} event */
const
onKeyDown
=
event
=>
{
const
key
=
normalizeKeyName
(
event
.
key
);
if
(
isEmpty
)
{
...
...
src/sidebar/components/Excerpt.js
View file @
5f82322e
...
...
@@ -10,7 +10,7 @@ import { applyTheme } from '../helpers/theme';
* @typedef InlineControlsProps
* @prop {boolean} isCollapsed
* @prop {(collapsed: boolean) => any} setCollapsed
* @prop {
object
} [linkStyle]
* @prop {
Record<string, string>
} [linkStyle]
*/
/**
...
...
@@ -120,12 +120,13 @@ function Excerpt({
const
isCollapsed
=
inlineControls
?
collapsedByInlineControls
:
collapse
;
const
isExpandable
=
isOverflowing
&&
isCollapsed
;
/** @type {
object
} */
/** @type {
Record<string, number>
} */
const
contentStyle
=
{};
if
(
contentHeight
!==
0
)
{
contentStyle
[
'max-height'
]
=
isExpandable
?
collapsedHeight
:
contentHeight
;
}
/** @param {boolean} collapsed */
const
setCollapsed
=
collapsed
=>
inlineControls
?
setCollapsedByInlineControls
(
collapsed
)
...
...
src/sidebar/components/HelpPanel.js
View file @
5f82322e
...
...
@@ -74,8 +74,15 @@ function HelpPanel({ auth, session }) {
const
hasAutoDisplayPreference
=
!!
store
.
profile
().
preferences
.
show_sidebar_tutorial
;
const
subPanelTitles
=
{
tutorial
:
'Getting started'
,
versionInfo
:
'About this version'
,
};
// The "Tutorial" (getting started) subpanel is the default panel shown
const
[
activeSubPanel
,
setActiveSubPanel
]
=
useState
(
'tutorial'
);
const
[
activeSubPanel
,
setActiveSubPanel
]
=
useState
(
/** @type {keyof subPanelTitles} */
(
'tutorial'
)
);
// Build version details about this session/app
const
versionData
=
useMemo
(()
=>
{
...
...
@@ -100,17 +107,17 @@ function HelpPanel({ auth, session }) {
// create-new-ticket form
const
supportTicketURL
=
`https://web.hypothes.is/get-help/?sys_info=
${
versionData
.
asEncodedURLString
()}
`
;
const
subPanelTitles
=
{
tutorial
:
'Getting started'
,
versionInfo
:
'About this version'
,
};
/**
* @param {Event} e
* @param {keyof subPanelTitles} panelName
*/
const
openSubPanel
=
(
e
,
panelName
)
=>
{
e
.
preventDefault
();
setActiveSubPanel
(
panelName
);
};
const
onActiveChanged
=
useCallback
(
/** @param {boolean} active */
active
=>
{
if
(
!
active
&&
hasAutoDisplayPreference
)
{
// If the tutorial is currently being auto-displayed, update the user
...
...
src/sidebar/components/MarkdownEditor.js
View file @
5f82322e
...
...
@@ -213,6 +213,8 @@ function Toolbar({ isPreviewing, onCommand, onTogglePreview }) {
/**
* Handles left and right arrow navigation as well as home and end
* keys so the user may navigate the toolbar without multiple tab stops.
*
* @param {KeyboardEvent} e
*/
const
handleKeyDown
=
e
=>
{
let
lowerLimit
=
0
;
...
...
src/sidebar/components/Menu.js
View file @
5f82322e
...
...
@@ -116,6 +116,7 @@ export default function Menu({
// Toggle menu when user presses toggle button. The menu is shown on mouse
// press for a more responsive/native feel but also handles a click event for
// activation via other input methods.
/** @param {Event} event */
const
toggleMenu
=
event
=>
{
// If the menu was opened on press, don't close it again on the subsequent
// mouse up ("click") event.
...
...
@@ -144,9 +145,11 @@ export default function Menu({
// are user interactions outside of it (e.g. clicks) in the document
useElementShouldClose
(
menuRef
,
isOpen
,
closeMenu
);
/** @param {Event} e */
const
stopPropagation
=
e
=>
e
.
stopPropagation
();
// It should also close if the user presses a key which activates menu items.
/** @param {KeyboardEvent} event */
const
handleMenuKeyDown
=
event
=>
{
const
key
=
normalizeKeyName
(
event
.
key
);
if
(
key
===
'Enter'
||
key
===
' '
)
{
...
...
src/sidebar/components/MenuItem.js
View file @
5f82322e
...
...
@@ -110,6 +110,7 @@ export default function MenuItem({
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[]);
/** @param {Event} event */
const
onCloseSubmenu
=
event
=>
{
if
(
onToggleSubmenu
)
{
onToggleSubmenu
(
event
);
...
...
@@ -120,6 +121,7 @@ export default function MenuItem({
});
};
/** @param {KeyboardEvent} event */
const
onKeyDown
=
event
=>
{
switch
(
normalizeKeyName
(
event
.
key
))
{
case
'ArrowRight'
:
...
...
src/sidebar/components/MenuKeyboardNavigation.js
View file @
5f82322e
import
{
normalizeKeyName
}
from
'@hypothesis/frontend-shared'
;
import
{
useEffect
,
useRef
}
from
'preact/hooks'
;
/** @param {HTMLElement} element */
function
isElementVisible
(
element
)
{
return
element
.
offsetParent
!==
null
;
}
...
...
@@ -10,7 +11,7 @@ function isElementVisible(element) {
* @prop {string} [className]
* @prop {(e: KeyboardEvent) => any} [closeMenu] - Callback when the menu is closed via keyboard input
* @prop {boolean} [visible] - When true`, sets focus on the first item in the list
* @prop {
object
} children - Array of nodes which may contain <MenuItems> or any nodes
* @prop {
import('preact').ComponentChildren
} children - Array of nodes which may contain <MenuItems> or any nodes
*/
/**
...
...
@@ -47,6 +48,7 @@ export default function MenuKeyboardNavigation({
};
},
[
visible
]);
/** @param {KeyboardEvent} event */
const
onKeyDown
=
event
=>
{
const
menuItems
=
Array
.
from
(
/** @type {NodeListOf<HTMLElement>} */
...
...
src/sidebar/components/NotebookView.js
View file @
5f82322e
...
...
@@ -56,6 +56,7 @@ function NotebookView({ loadAnnotationsService, streamer }) {
// of them: this is a performance safety valve.
const
maxResults
=
5000
;
/** @param {Error} error */
const
onLoadError
=
error
=>
{
if
(
error
instanceof
ResultSizeError
)
{
setHasTooManyAnnotationsError
(
true
);
...
...
@@ -101,7 +102,7 @@ function NotebookView({ loadAnnotationsService, streamer }) {
}
},
[
loadAnnotationsService
,
groupId
,
store
]);
/
/ Pagination-page-changing callback
/
** @param {number} newPage */
const
onChangePage
=
newPage
=>
{
setPaginationPage
(
newPage
);
};
...
...
src/sidebar/components/PaginationNavigation.js
View file @
5f82322e
...
...
@@ -22,13 +22,17 @@ function PaginationNavigation({ currentPage, onChangePage, totalPages }) {
const
hasPreviousPage
=
currentPage
>
1
;
const
pageNumbers
=
pageNumberOptions
(
currentPage
,
totalPages
);
const
changePageTo
=
(
pageNumber
,
eventTarget
)
=>
{
/**
* @param {number} pageNumber
* @param {HTMLElement} element
*/
const
changePageTo
=
(
pageNumber
,
element
)
=>
{
onChangePage
(
pageNumber
);
// Because changing pagination page doesn't reload the page (as it would
// in a "traditional" HTML context), the clicked-upon navigation button
// will awkwardly retain focus unless it is actively removed.
// TODO: Evaluate this for a11y issues
/** @type HTMLElement */
(
eventTarget
)?
.
blur
();
element
.
blur
();
};
return
(
...
...
@@ -39,7 +43,12 @@ function PaginationNavigation({ currentPage, onChangePage, totalPages }) {
classes
=
"PaginationPageButton"
icon
=
"arrow-left"
title
=
"Go to previous page"
onClick
=
{
e
=>
changePageTo
(
currentPage
-
1
,
e
.
target
)}
onClick
=
{
e
=>
changePageTo
(
currentPage
-
1
,
/** @type {HTMLElement} */
(
e
.
target
)
)
}
variant
=
"dark"
>
prev
...
...
@@ -57,7 +66,9 @@ function PaginationNavigation({ currentPage, onChangePage, totalPages }) {
key
=
{
`page-
${
idx
}
`
}
title
=
{
`Go to page
${
page
}
`
}
pressed
=
{
page
===
currentPage
}
onClick
=
{
e
=>
changePageTo
(
page
,
e
.
target
)}
onClick
=
{
e
=>
changePageTo
(
page
,
/** @type {HTMLElement} */
(
e
.
target
))
}
variant
=
"dark"
>
{
page
.
toString
()}
...
...
@@ -73,7 +84,12 @@ function PaginationNavigation({ currentPage, onChangePage, totalPages }) {
icon
=
"arrow-right"
iconPosition
=
"right"
title
=
"Go to next page"
onClick
=
{
e
=>
changePageTo
(
currentPage
+
1
,
e
.
target
)}
onClick
=
{
e
=>
changePageTo
(
currentPage
+
1
,
/** @type {HTMLElement} */
(
e
.
target
)
)
}
variant
=
"dark"
>
next
...
...
src/sidebar/components/SearchInput.js
View file @
5f82322e
...
...
@@ -36,6 +36,7 @@ export default function SearchInput({ alwaysExpanded, query, onSearch }) {
// The query that the user is currently typing, but may not yet have applied.
const
[
pendingQuery
,
setPendingQuery
]
=
useState
(
query
);
/** @param {Event} e */
const
onSubmit
=
e
=>
{
e
.
preventDefault
();
if
(
input
.
current
.
value
||
prevQuery
)
{
...
...
src/sidebar/components/ShareLinks.js
View file @
5f82322e
...
...
@@ -35,8 +35,10 @@ function ShareLink({ label, iconName, uri }) {
/**
* A list of share links to social-media platforms.
*
* @param {ShareLinksProps} props
*/
function
ShareLinks
({
shareURI
})
{
export
default
function
ShareLinks
({
shareURI
})
{
// This is the double-encoded format needed for other services (the entire
// URI needs to be encoded because it's used as the value of querystring params)
const
encodedURI
=
encodeURIComponent
(
shareURI
);
...
...
@@ -65,5 +67,3 @@ function ShareLinks({ shareURI }) {
<
/ul
>
);
}
export
default
ShareLinks
;
src/sidebar/components/StreamSearchInput.js
View file @
5f82322e
...
...
@@ -18,6 +18,7 @@ import SearchInput from './SearchInput';
function
StreamSearchInput
({
router
})
{
const
store
=
useStoreProxy
();
const
query
=
store
.
routeParams
().
q
;
/** @param {string} query */
const
setQuery
=
query
=>
{
// Re-route the user to `/stream` if they are on `/a/:id` and then set
// the search query.
...
...
src/sidebar/components/StreamView.js
View file @
5f82322e
...
...
@@ -24,10 +24,9 @@ function StreamView({ api, toastMessenger }) {
/**
* Fetch annotations from the API and display them in the stream.
*
* @param {string} query - The user-supplied search query
*/
const
loadAnnotations
=
useCallback
(
/** @param {string} query */
async
query
=>
{
const
queryParams
=
{
_separate_replies
:
true
,
...
...
src/sidebar/components/ToastMessages.js
View file @
5f82322e
...
...
@@ -76,7 +76,7 @@ function ToastMessage({ message, onDismiss }) {
/**
* @typedef ToastMessagesProps
* @prop {
object} toastMessenger - Injected service
* @prop {
import('../services/toast-messenger').ToastMessengerService} toastMessenger
*/
/**
...
...
src/sidebar/components/Tutorial.js
View file @
5f82322e
...
...
@@ -30,6 +30,9 @@ function TutorialInstruction({ commandName, iconName }) {
/**
* Tutorial for using the sidebar app
*
* @param {object} props
* @param {import('../../types/config').SidebarSettings} props.settings
*/
function
Tutorial
({
settings
})
{
const
canCreatePrivateGroups
=
!
isThirdPartyService
(
settings
);
...
...
src/sidebar/components/UserMenu.js
View file @
5f82322e
...
...
@@ -48,6 +48,7 @@ function UserMenu({ auth, frameSync, onLogout, settings }) {
const
isNotebookEnabled
=
store
.
isFeatureEnabled
(
'notebook_launch'
);
const
[
isOpen
,
setOpen
]
=
useState
(
false
);
/** @param {keyof import('../../types/config').Service} feature */
const
serviceSupports
=
feature
=>
service
&&
!!
service
[
feature
];
const
isSelectableProfile
=
...
...
@@ -61,6 +62,8 @@ function UserMenu({ auth, frameSync, onLogout, settings }) {
// Temporary access to the Notebook without feature flag:
// type the key 'n' when user menu is focused/open
/** @param {KeyboardEvent} event */
const
onKeyDown
=
event
=>
{
if
(
event
.
key
===
'n'
)
{
onSelectNotebook
();
...
...
src/sidebar/components/hooks/use-filter-options.js
View file @
5f82322e
...
...
@@ -22,6 +22,7 @@ export function useUserFilterOptions() {
return
useMemo
(()
=>
{
// Determine unique users (authors) in annotation collection
/** @type {Record<string, string>} */
const
users
=
{};
annotations
.
forEach
(
annotation
=>
{
const
username_
=
username
(
annotation
.
user
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment