Skip to content

Commit cecf4c4

Browse files
committed
Update text matching function semantics and naming
It is now called `hasTextMatchesForAll()`, and returns true only if there are matches for all patterns.
1 parent 9318de0 commit cecf4c4

7 files changed

Lines changed: 67 additions & 81 deletions

File tree

src/app/components/HighlightedText/index.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,29 @@ export const HighlightedText: FC<HighlightedTextProps> = ({
8989

9090
const pieces: ReactNode[] = []
9191
let processedChars = 0
92-
let processedTasks = 0
92+
let processedMatches = 0
9393

9494
while (processedChars < text.length) {
95-
// Do we still have tasks?
96-
if (processedTasks < sortedMatches.length) {
97-
// Yes, there are more tasks
98-
const task = sortedMatches[processedTasks]
99-
if (task.startPos < processedChars) {
100-
// This task with collude
101-
processedTasks++ // just skip this task
95+
// Do we still have matches to highlight?
96+
if (processedMatches < sortedMatches.length) {
97+
// Yes, there are more matches
98+
const match = sortedMatches[processedMatches]
99+
if (match.startPos < processedChars) {
100+
// This match would collude with something already highlighted
101+
processedMatches++ // just skip this match
102102
} else {
103-
// We use this task
104-
pieces.push(text.substring(processedChars, task.startPos))
105-
const focus = text.substring(task.startPos, task.endPos)
103+
// We want to highlight this match
104+
pieces.push(text.substring(processedChars, match.startPos))
105+
const focus = text.substring(match.startPos, match.endPos)
106106
pieces.push(
107-
<Box key={processedTasks} component="mark" sx={sx}>
107+
<Box key={processedMatches} component="mark" sx={sx}>
108108
{focus}
109109
</Box>,
110110
)
111-
processedChars = task.endPos
111+
processedChars = match.endPos
112112
}
113113
} else {
114-
// No more tasks, just grab the remaining string
114+
// No more matches, just grab the remaining string
115115
pieces.push(text.substring(processedChars))
116116
processedChars = text.length
117117
}

src/app/components/HighlightedText/text-matching.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,19 @@ export const findTextMatch = (
6161
}
6262

6363
/**
64-
* Check if a pattern matches within a corpus, also considering normalization
64+
* Check if all patterns match within a corpus, also considering normalization
6565
*
6666
* NOTE: depending on normalization options, the string length can change,
6767
* and in that case, match position can be incorrect.
68+
*
69+
* Also NOTE: if there are no patterns given, the result will be true.
70+
*
6871
*/
69-
export const hasTextMatch = (
72+
export const hasTextMatchesForAll = (
7073
rawCorpus: string | null | undefined,
71-
search: (string | undefined)[],
74+
patterns: (string | undefined)[],
7275
options: NormalizerOptions = {},
73-
): boolean => findTextMatch(rawCorpus, search, options) !== NO_MATCH
76+
): boolean =>
77+
patterns
78+
.filter(pattern => !!pattern)
79+
.every(pattern => findTextMatch(rawCorpus, [pattern], options) !== NO_MATCH)

src/app/data/oasis-account-names.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
AccountNameSearchResults,
1717
AccountNameSearchRuntimeMatch,
1818
} from './named-accounts'
19-
import { hasTextMatch } from '../components/HighlightedText/text-matching'
19+
import { hasTextMatchesForAll } from '../components/HighlightedText/text-matching'
2020
import * as externalLinks from '../utils/externalLinks'
2121
import { getOasisAddress } from '../utils/helpers'
2222
import { isUrlSafe } from '../utils/url'
@@ -121,20 +121,18 @@ export const useSearchForOasisAccountsByName = (
121121
console.log('Failed to load Oasis account metadata', metadataError)
122122
}
123123

124-
const textMatcher =
125-
nameFragments.length && queryOptions.enabled
126-
? (account: AccountMetadata) =>
127-
nameFragments.every(nameFragment => hasTextMatch(account.name, [nameFragment]))
128-
: () => false
129-
130124
const matches =
131-
namedAccounts?.list.filter(textMatcher).map(
132-
(account): AccountNameSearchMatch => ({
133-
network,
134-
layer,
135-
address: account.address,
136-
}),
137-
) ?? []
125+
!isMetadataLoading && nameFragments.length && queryOptions.enabled && namedAccounts
126+
? namedAccounts.list
127+
.filter(account => hasTextMatchesForAll(account.name, nameFragments))
128+
.map(
129+
(account): AccountNameSearchMatch => ({
130+
network,
131+
layer,
132+
address: account.address,
133+
}),
134+
)
135+
: []
138136

139137
const consensusMatches = layer === Layer.consensus ? (matches as AccountNameSearchConsensusMatch[]) : []
140138
const runtimeMatches = layer === Layer.consensus ? [] : (matches as AccountNameSearchRuntimeMatch[])

src/app/data/pontusx-account-names.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from './named-accounts'
1010
import { Layer, useGetRuntimeAccountsAddresses } from '../../oasis-nexus/api'
1111
import { Network } from '../../types/network'
12-
import { hasTextMatch } from '../components/HighlightedText/text-matching'
12+
import { hasTextMatchesForAll } from '../components/HighlightedText/text-matching'
1313
import { getOasisAddress } from '../utils/helpers'
1414
import * as externalLinks from '../utils/externalLinks'
1515

@@ -83,22 +83,18 @@ export const useSearchForPontusXAccountsByName = (
8383
console.log('Failed to load Pontus-X account names', metadataError)
8484
}
8585

86-
const textMatcher =
87-
nameFragments.length && queryOptions.enabled
88-
? (account: AccountMetadata) =>
89-
nameFragments.every(nameFragment => hasTextMatch(account.name, [nameFragment]))
90-
: () => false
91-
9286
const matches =
93-
isMetadataLoading || isMetadataLoading
87+
isMetadataLoading || !nameFragments.length || !queryOptions.enabled
9488
? undefined
95-
: namedAccounts?.list.filter(textMatcher).map(
96-
(account): AccountNameSearchRuntimeMatch => ({
97-
network,
98-
layer: Layer.pontusxtest,
99-
address: account.address,
100-
}),
101-
)
89+
: namedAccounts?.list
90+
.filter(account => hasTextMatchesForAll(account.name, nameFragments))
91+
.map(
92+
(account): AccountNameSearchRuntimeMatch => ({
93+
network,
94+
layer: Layer.pontusxtest,
95+
address: account.address,
96+
}),
97+
)
10298

10399
const {
104100
isLoading: areAccountsLoading,

src/app/hooks/useSearchForValidatorsByName.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { hasTextMatch } from 'app/components/HighlightedText/text-matching'
1+
import { hasTextMatchesForAll } from 'app/components/HighlightedText/text-matching'
22
import {
33
Layer,
44
useGetConsensusValidatorsAddressNameMap,
@@ -10,13 +10,13 @@ import { AccountNameSearchResults, AccountNameSearchConsensusMatch } from '../da
1010

1111
function findAddressesWithMatch(
1212
addressMap: ValidatorAddressNameMap,
13-
nameFragment: string[],
13+
nameFragments: string[],
1414
network: Network,
1515
) {
1616
const matchedAddresses: AccountNameSearchConsensusMatch[] = []
1717

1818
for (const [address, name] of Object.entries(addressMap)) {
19-
if (nameFragment.every(nameFragment => hasTextMatch(name, [nameFragment]))) {
19+
if (hasTextMatchesForAll(name, nameFragments)) {
2020
matchedAddresses.push({ address, layer: Layer.consensus, network })
2121
}
2222
}

src/app/utils/vote.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ExtendedVote, ProposalVoteValue, VoteFilter, VoteType } from '../../types/vote'
2-
import { hasTextMatch } from '../components/HighlightedText/text-matching'
2+
import { hasTextMatchesForAll } from '../components/HighlightedText/text-matching'
33

44
export const getRandomVote = (): ProposalVoteValue =>
55
[ProposalVoteValue.yes, ProposalVoteValue.no, ProposalVoteValue.abstain][Math.floor(Math.random() * 3)]
@@ -13,10 +13,7 @@ const voteFilters: Record<VoteType, VoteFilter> = {
1313

1414
export const getFilterForVoteType = (voteType: VoteType): VoteFilter => voteFilters[voteType]
1515

16-
export const getFilterForVoterNameFragment = (fragment: string[]) => {
17-
if (!fragment.length) {
18-
return () => true
19-
}
20-
return (vote: ExtendedVote) =>
21-
fragment.every(fragment => hasTextMatch(vote.validator?.media?.name, [fragment]))
22-
}
16+
export const getFilterForVoterNameFragment = (fragments: string[]) =>
17+
fragments.length
18+
? (vote: ExtendedVote) => hasTextMatchesForAll(vote.validator?.media?.name, fragments)
19+
: () => true

src/oasis-nexus/api.ts

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { toChecksumAddress } from '@ethereumjs/util'
3232
import { fromBaseUnits } from '../app/utils/number-utils'
3333
import { getConsensusTransactionAmount, getConsensusTransactionToAddress } from '../app/utils/transaction'
3434
import { API_MAX_TOTAL_COUNT } from '../config'
35-
import { hasTextMatch } from '../app/components/HighlightedText/text-matching'
35+
import { hasTextMatchesForAll } from '../app/components/HighlightedText/text-matching'
3636

3737
export * from './generated/api'
3838
export type { RuntimeEvmBalance as Token } from './generated/api'
@@ -1112,28 +1112,17 @@ export const useGetConsensusProposalsByName = (network: Network, nameFragments:
11121112
const query = useGetConsensusProposals(network, {}, { query: { enabled: !!nameFragments.length } })
11131113
const { isError, isLoading, isInitialLoading, data, status, error } = query
11141114
const textMatcher = nameFragments.length
1115-
? (proposal: generated.Proposal): boolean =>
1116-
nameFragments.every(nameFragment => {
1117-
if (hasTextMatch(proposal.title, [nameFragment])) {
1118-
return true
1119-
}
1120-
1121-
if (hasTextMatch(proposal.handler, [nameFragment])) {
1122-
return true
1123-
}
1124-
1125-
if (hasTextMatch(getCancelTitle(proposal.cancels), [nameFragment])) {
1126-
return true
1127-
}
1128-
1129-
return (
1130-
!!proposal.parameters_change &&
1131-
hasTextMatch(
1132-
getParameterChangeTitle(proposal.parameters_change_module, proposal.parameters_change),
1133-
[nameFragment],
1134-
)
1135-
)
1136-
})
1115+
? ({
1116+
title,
1117+
handler,
1118+
cancels,
1119+
parameters_change,
1120+
parameters_change_module,
1121+
}: generated.Proposal): boolean =>
1122+
hasTextMatchesForAll(
1123+
`${title} ${handler} ${getCancelTitle(cancels)} ${getParameterChangeTitle(parameters_change_module, parameters_change)}`,
1124+
nameFragments,
1125+
)
11371126
: () => false
11381127
const results = data ? query.data.data.proposals.filter(textMatcher) : undefined
11391128
return {

0 commit comments

Comments
 (0)