From 0cf5ebbad04eb8c78b637bc29bc6bf599b1e5a35 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 31 Jan 2025 13:03:51 +0100 Subject: [PATCH 01/55] working highlighting --- src/libs/runOnLiveMarkdownRuntime/index.native.tsx | 8 ++++++++ src/libs/runOnLiveMarkdownRuntime/index.tsx | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 src/libs/runOnLiveMarkdownRuntime/index.native.tsx create mode 100644 src/libs/runOnLiveMarkdownRuntime/index.tsx diff --git a/src/libs/runOnLiveMarkdownRuntime/index.native.tsx b/src/libs/runOnLiveMarkdownRuntime/index.native.tsx new file mode 100644 index 000000000000..8927fe0a936c --- /dev/null +++ b/src/libs/runOnLiveMarkdownRuntime/index.native.tsx @@ -0,0 +1,8 @@ +import {getWorkletRuntime} from '@expensify/react-native-live-markdown'; +import {runOnRuntime} from 'react-native-reanimated'; + +function runOnLiveMarkdownRuntime(worklet: (...args: Args) => ReturnValue) { + return runOnRuntime(getWorkletRuntime(), worklet); +} + +export default runOnLiveMarkdownRuntime; diff --git a/src/libs/runOnLiveMarkdownRuntime/index.tsx b/src/libs/runOnLiveMarkdownRuntime/index.tsx new file mode 100644 index 000000000000..c8e072693323 --- /dev/null +++ b/src/libs/runOnLiveMarkdownRuntime/index.tsx @@ -0,0 +1,6 @@ +// Reanimated does not support runOnRuntime() on web +function runOnLiveMarkdownRuntime(worklet: (...args: Args) => ReturnValue) { + return worklet; +} + +export default runOnLiveMarkdownRuntime; From 85d543554cc3b1a4320de755eb2a95518334ac19 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 31 Jan 2025 13:13:16 +0100 Subject: [PATCH 02/55] add syntax highlighting --- .../Search/SearchAutocompleteInput.tsx | 89 +++++++++++++++++-- .../SearchInputSelectionWrapper/index.tsx | 2 +- .../Search/SearchPageHeaderInput.tsx | 1 + .../Search/SearchRouter/SearchRouter.tsx | 1 + src/libs/SearchAutocompleteUtils.ts | 52 ++++++++--- 5 files changed, 126 insertions(+), 19 deletions(-) diff --git a/src/components/Search/SearchAutocompleteInput.tsx b/src/components/Search/SearchAutocompleteInput.tsx index 215599952c50..3e260a9bda96 100644 --- a/src/components/Search/SearchAutocompleteInput.tsx +++ b/src/components/Search/SearchAutocompleteInput.tsx @@ -1,20 +1,27 @@ +import isEqual from 'lodash/isEqual'; import type {ForwardedRef, ReactNode, RefObject} from 'react'; -import React, {forwardRef, useState} from 'react'; +import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import {useSharedValue} from 'react-native-reanimated'; import FormHelpMessage from '@components/FormHelpMessage'; import type {SelectionListHandle} from '@components/SelectionList/types'; import TextInput from '@components/TextInput'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; +import useActiveWorkspace from '@hooks/useActiveWorkspace'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; -import {parseForLiveMarkdown} from '@libs/SearchAutocompleteUtils'; +import runOnLiveMarkdownRuntime from '@libs/runOnLiveMarkdownRuntime'; +import {getAutocompleteCategories, getAutocompleteTags, parseForLiveMarkdown} from '@libs/SearchAutocompleteUtils'; import handleKeyPress from '@libs/SearchInputOnKeyPress'; import shouldDelayFocus from '@libs/shouldDelayFocus'; import variables from '@styles/variables'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {SubstitutionMap} from './SearchRouter/getQueryWithSubstitutions'; type SearchAutocompleteInputProps = { /** Value of TextInput */ @@ -59,6 +66,9 @@ type SearchAutocompleteInputProps = { /** Whether the search reports API call is running */ isSearchingForReports?: boolean; + /** Map of autocomplete suggestions. Required for highlighting to work properly */ + substitutionMap: SubstitutionMap; + /** input style */ inputStyle?: StyleProp; } & Pick; @@ -83,6 +93,7 @@ function SearchAutocompleteInput( isSearchingForReports, selection, inputStyle, + substitutionMap, }: SearchAutocompleteInputProps, ref: ForwardedRef, ) { @@ -90,9 +101,75 @@ function SearchAutocompleteInput( const {translate} = useLocalize(); const [isFocused, setIsFocused] = useState(false); const {isOffline} = useNetwork(); + const {activeWorkspaceID} = useActiveWorkspace(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const personalDetailsSharedValue = useSharedValue({login: currentUserPersonalDetails.login, userDisplayName: currentUserPersonalDetails.displayName}); + const lastMap = useRef({}); + const [map, setMap] = useState({}); + + const [currencyList] = useOnyx(ONYXKEYS.CURRENCY_LIST); + const currencyAutocompleteList = Object.keys(currencyList ?? {}); + const currencySharedValue = useSharedValue(currencyAutocompleteList); + + const [allPolicyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES); + const categoryAutocompleteList = useMemo(() => { + return getAutocompleteCategories(allPolicyCategories, activeWorkspaceID); + }, [activeWorkspaceID, allPolicyCategories]); + const categorySharedValue = useSharedValue(categoryAutocompleteList); + + const [allPoliciesTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS); + const tagAutocompleteList = useMemo(() => { + return getAutocompleteTags(allPoliciesTags, activeWorkspaceID); + }, [activeWorkspaceID, allPoliciesTags]); + const tagSharedValue = useSharedValue(tagAutocompleteList); + + useEffect(() => { + if (lastMap.current && !isEqual(lastMap.current, substitutionMap)) { + lastMap.current = substitutionMap; + } + setMap(lastMap.current ?? {}); + }, [substitutionMap, lastMap]); + const offlineMessage: string = isOffline && shouldShowOfflineMessage ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; + useEffect(() => { + runOnLiveMarkdownRuntime(() => { + 'worklet'; + + personalDetailsSharedValue.set({login: currentUserPersonalDetails.login, userDisplayName: currentUserPersonalDetails.displayName}); + })(); + }, [currentUserPersonalDetails, personalDetailsSharedValue]); + useEffect(() => { + runOnLiveMarkdownRuntime(() => { + 'worklet'; + + currencySharedValue.set(currencyAutocompleteList); + })(); + }, [currencyAutocompleteList, currencySharedValue]); + useEffect(() => { + runOnLiveMarkdownRuntime(() => { + 'worklet'; + + categorySharedValue.set(categoryAutocompleteList); + })(); + }, [categorySharedValue, categoryAutocompleteList]); + useEffect(() => { + runOnLiveMarkdownRuntime(() => { + 'worklet'; + + tagSharedValue.set(tagAutocompleteList); + }); + }, [tagSharedValue, tagAutocompleteList]); + + const parser = useCallback( + (input: string) => { + 'worklet'; + + return parseForLiveMarkdown(input, personalDetailsSharedValue, map, currencySharedValue, categorySharedValue, tagSharedValue); + }, + [personalDetailsSharedValue, map, currencySharedValue, categorySharedValue, tagSharedValue], + ); + const inputWidth = isFullWidth ? styles.w100 : {width: variables.popoverWidth}; return ( @@ -121,7 +198,7 @@ function SearchAutocompleteInput( maxLength={CONST.SEARCH_QUERY_LIMIT} onSubmitEditing={onSubmit} shouldUseDisabledStyles={false} - textInputContainerStyles={[styles.borderNone, styles.pb0]} + textInputContainerStyles={[styles.borderNone, styles.pb0, styles.pr3]} inputStyle={[inputWidth, inputStyle]} onFocus={() => { setIsFocused(true); @@ -138,11 +215,7 @@ function SearchAutocompleteInput( onKeyPress={handleKeyPress(onSubmit)} isMarkdownEnabled multiline={false} - parser={(input: string) => { - 'worklet'; - - return parseForLiveMarkdown(input, currentUserPersonalDetails.login ?? '', currentUserPersonalDetails.displayName ?? ''); - }} + parser={parser} selection={selection} /> diff --git a/src/components/Search/SearchInputSelectionWrapper/index.tsx b/src/components/Search/SearchInputSelectionWrapper/index.tsx index a806cea9afd4..1a0a18ffaa47 100644 --- a/src/components/Search/SearchInputSelectionWrapper/index.tsx +++ b/src/components/Search/SearchInputSelectionWrapper/index.tsx @@ -10,7 +10,7 @@ function SearchInputSelectionWrapper({selection, ...props}: SearchAutocompleteIn return ( , + map: SubstitutionMap, + currencyList: SharedValue, + categoryList: SharedValue, + tagList: SharedValue, +) { 'worklet'; const parsedAutocomplete = parse(input) as SearchAutocompleteResult; const ranges = parsedAutocomplete.ranges; - return ranges.map((range) => { - let type = 'mention-user'; - - if ((range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) && (range.value === userLogin || range.value === userDisplayName)) { - type = 'mention-here'; - } - - return {...range, type}; - }) as MarkdownRange[]; + const typeList = Object.values(CONST.SEARCH.DATA_TYPES) as string[]; + const expenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE) as string[]; + const statusList = Object.values({...CONST.SEARCH.STATUS.TRIP, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}) as string[]; + const subMap = map; + return ranges + .filter( + (range) => + !( + range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || + range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM || + range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN || + range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE || + range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID + ) || subMap[`${range.key}:${range.value}`] !== undefined, + ) + .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY || currencyList.get().includes(range.value)) + .filter((range) => range.key !== CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE || typeList.includes(range.value)) + .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE || expenseTypeList.includes(range.value)) + .filter((range) => range.key !== CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS || statusList.includes(range.value)) + .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY || categoryList.get().includes(range.value)) + .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG || tagList.get().includes(range.value)) + .map((range) => { + let type = 'mention-user'; + if ( + (range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) && + (range.value === details.get().login || range.value === details.get().userDisplayName) + ) { + type = 'mention-here'; + } + + return {...range, type}; + }) as MarkdownRange[]; } export { From 944fbdd2344a2663746588dc29ed65d064922b40 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 31 Jan 2025 13:35:45 +0100 Subject: [PATCH 03/55] add supporting text --- .../Search/SearchRouter/buildSubstitutionsMap.ts | 2 +- .../Search/SearchRouter/getQueryWithSubstitutions.ts | 2 +- .../Search/SearchRouter/getUpdatedSubstitutionsMap.ts | 2 +- src/components/Search/types.ts | 4 +++- src/libs/SearchAutocompleteUtils.ts | 3 +++ src/libs/SearchParser/autocompleteParser.js | 9 +++++---- src/libs/SearchParser/autocompleteParser.peggy | 9 +++++---- 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/components/Search/SearchRouter/buildSubstitutionsMap.ts b/src/components/Search/SearchRouter/buildSubstitutionsMap.ts index 892aa050ef9d..0a3c49819b38 100644 --- a/src/components/Search/SearchRouter/buildSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/buildSubstitutionsMap.ts @@ -33,7 +33,7 @@ function buildSubstitutionsMap( ): SubstitutionMap { const parsedQuery = parse(query) as {ranges: SearchAutocompleteQueryRange[]}; - const searchAutocompleteQueryRanges = parsedQuery.ranges; + const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== 'syntax'); if (searchAutocompleteQueryRanges.length === 0) { return {}; diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index 84895efb33a5..b976371135a6 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -21,7 +21,7 @@ const getSubstitutionMapKey = (filterKey: SearchFilterKey, value: string) => `${ function getQueryWithSubstitutions(changedQuery: string, substitutions: SubstitutionMap) { const parsed = parse(changedQuery) as {ranges: SearchAutocompleteQueryRange[]}; - const searchAutocompleteQueryRanges = parsed.ranges; + const searchAutocompleteQueryRanges = parsed.ranges.filter((range) => range.key !== 'syntax'); if (searchAutocompleteQueryRanges.length === 0) { return changedQuery; diff --git a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts index ee7bf3850259..a681ae6030f0 100644 --- a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts @@ -18,7 +18,7 @@ const getSubstitutionsKey = (filterKey: SearchFilterKey, value: string) => `${fi function getUpdatedSubstitutionsMap(query: string, substitutions: SubstitutionMap): SubstitutionMap { const parsedQuery = parser.parse(query) as {ranges: SearchAutocompleteQueryRange[]}; - const searchAutocompleteQueryRanges = parsedQuery.ranges; + const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== 'syntax'); if (searchAutocompleteQueryRanges.length === 0) { return {}; diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 0a402358d73e..b5c58c798b9f 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -95,7 +95,8 @@ type SearchFilterKey = | ValueOf | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS - | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID; + | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID + | 'syntax'; type UserFriendlyKey = ValueOf; @@ -128,6 +129,7 @@ type SearchAutocompleteResult = { ranges: SearchAutocompleteQueryRange[]; }; +// TODO FIX types type SearchAutocompleteQueryRange = { key: SearchFilterKey; length: number; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index a591e08c2314..d9abec7abf3e 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -182,6 +182,9 @@ function parseForLiveMarkdown( ) { type = 'mention-here'; } + if (range.key === 'syntax') { + type = 'syntax'; + } return {...range, type}; }) as MarkdownRange[]; diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 5a787c5d8048..16e135deb222 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -282,20 +282,21 @@ function peg$parse(input, options) { start: location().end.offset, length: 0, }; - return; + return {key:"syntax",value:key, start:location().start.offset, length:location().end.offset-location().start.offset}; } autocomplete = { key, ...value[value.length - 1], }; - - return value + const result = value .filter((filter) => filter.length > 0) .map((filter) => ({ key, ...filter, - })); + })) + + return [{key:"syntax",value:key, start:location().start.offset, length:result[0].start - location().start.offset}, ...result]; }; var peg$f3 = function() { autocomplete = null; }; var peg$f4 = function(parts, empty) { diff --git a/src/libs/SearchParser/autocompleteParser.peggy b/src/libs/SearchParser/autocompleteParser.peggy index 928d1751f8ce..93b1b7e52fa7 100644 --- a/src/libs/SearchParser/autocompleteParser.peggy +++ b/src/libs/SearchParser/autocompleteParser.peggy @@ -31,20 +31,21 @@ defaultFilter start: location().end.offset, length: 0, }; - return; + return {key:"syntax",value:key, start:location().start.offset, length:location().end.offset-location().start.offset}; } autocomplete = { key, ...value[value.length - 1], }; - - return value + const result = value .filter((filter) => filter.length > 0) .map((filter) => ({ key, ...filter, - })); + })) + + return [{key:"syntax",value:key, start:location().start.offset, length:result[0].start - location().start.offset}, ...result]; } freeTextFilter = _ (identifier/ ",") _ { autocomplete = null; } From 7eb5861937a61f2f1ff5408dcc7c171bccd987b6 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 31 Jan 2025 13:47:35 +0100 Subject: [PATCH 04/55] grammar formatting --- src/libs/SearchParser/autocompleteParser.js | 23 +++++++++++++---- .../SearchParser/autocompleteParser.peggy | 25 ++++++++++++++----- src/libs/SearchParser/searchParser.js | 18 ++++++------- src/libs/SearchParser/searchParser.peggy | 18 +++++++------ 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 16e135deb222..092a0022889f 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -278,11 +278,16 @@ function peg$parse(input, options) { if (!value) { autocomplete = { key, - value: '', + value: "", start: location().end.offset, length: 0, }; - return {key:"syntax",value:key, start:location().start.offset, length:location().end.offset-location().start.offset}; + return { + key: "syntax", + value: key, + start: location().start.offset, + length: location().end.offset - location().start.offset, + }; } autocomplete = { @@ -294,9 +299,17 @@ function peg$parse(input, options) { .map((filter) => ({ key, ...filter, - })) - - return [{key:"syntax",value:key, start:location().start.offset, length:result[0].start - location().start.offset}, ...result]; + })); + + return [ + { + key: "syntax", + value: key, + start: location().start.offset, + length: result[0].start - location().start.offset, + }, + ...result, + ]; }; var peg$f3 = function() { autocomplete = null; }; var peg$f4 = function(parts, empty) { diff --git a/src/libs/SearchParser/autocompleteParser.peggy b/src/libs/SearchParser/autocompleteParser.peggy index 93b1b7e52fa7..0b8e15f3364a 100644 --- a/src/libs/SearchParser/autocompleteParser.peggy +++ b/src/libs/SearchParser/autocompleteParser.peggy @@ -27,11 +27,16 @@ defaultFilter if (!value) { autocomplete = { key, - value: '', + value: "", start: location().end.offset, length: 0, }; - return {key:"syntax",value:key, start:location().start.offset, length:location().end.offset-location().start.offset}; + return { + key: "syntax", + value: key, + start: location().start.offset, + length: location().end.offset - location().start.offset, + }; } autocomplete = { @@ -43,12 +48,20 @@ defaultFilter .map((filter) => ({ key, ...filter, - })) - - return [{key:"syntax",value:key, start:location().start.offset, length:result[0].start - location().start.offset}, ...result]; + })); + + return [ + { + key: "syntax", + value: key, + start: location().start.offset, + length: result[0].start - location().start.offset, + }, + ...result, + ]; } -freeTextFilter = _ (identifier/ ",") _ { autocomplete = null; } +freeTextFilter = _ (identifier / ",") _ { autocomplete = null; } autocompleteKey "key" = @( diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 804a5928a909..aee1033bef31 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -298,7 +298,9 @@ function peg$parse(input, options) { const keywordFilter = buildFilter( "eq", "keyword", - keywords.map((filter) => filter.right).flat() + keywords + .map((filter) => filter.right.replace(/^(['"])(.*)\1$/, "$2")) + .flat() ); if (keywordFilter.right.length > 0) { nonKeywords.push(keywordFilter); @@ -310,20 +312,18 @@ function peg$parse(input, options) { var peg$f2 = function(key, op, value) { updateDefaultValues(key, value); }; - var peg$f3 = function(value) { //handle no-breaking space - let word + var peg$f3 = function(value) { + //handle no-breaking space + let word; if (Array.isArray(value)) { - word = value.join("") - // return buildFilter("eq", "keyword", value.join("")); - }else{ - word = value + word = value.join(""); + } else { + word = value; } if (word.startsWith('"') && word.endsWith('"') && word.length >= 2) { return buildFilter("eq", "keyword", word.slice(1, -1)); } return buildFilter("eq", "keyword", word); - - // return buildFilter("eq", "keyword", value); }; var peg$f4 = function(field, op, values) { return buildFilter(op, field, values); diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 28f5c3d8a96f..3bbe57722b88 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -66,7 +66,9 @@ filterList const keywordFilter = buildFilter( "eq", "keyword", - keywords.map((filter) => filter.right.replace(/^(['"])(.*)\1$/, '$2')).flat() + keywords + .map((filter) => filter.right.replace(/^(['"])(.*)\1$/, "$2")) + .flat() ); if (keywordFilter.right.length > 0) { nonKeywords.push(keywordFilter); @@ -84,12 +86,13 @@ defaultFilter } freeTextFilter - = _ value:(quotedString / [^ \t\r\n\xA0]+) _ { //handle no-breaking space - let word + = _ value:(quotedString / [^ \t\r\n\xA0]+) _ { + //handle no-breaking space + let word; if (Array.isArray(value)) { - word = value.join("") - }else{ - word = value + word = value.join(""); + } else { + word = value; } if (word.startsWith('"') && word.endsWith('"') && word.length >= 2) { return buildFilter("eq", "keyword", word.slice(1, -1)); @@ -126,8 +129,7 @@ key "key" / posted ) -defaultKey "default key" - = @(type / status / sortBy / sortOrder / policyID) +defaultKey "default key" = @(type / status / sortBy / sortOrder / policyID) identifier = (","+)? parts:(quotedString / alphanumeric)|1.., ","+| empty:(","+)? { From 7b55bf539911900a559c652e00613674865423b4 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Sun, 2 Feb 2025 20:02:35 +0530 Subject: [PATCH 05/55] Fixed submit button layout in Company card transaction start date page --- .../assignCard/TransactionStartDateSelectorModal.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx b/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx index 8c0990800bb4..5e5e258912a8 100644 --- a/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx +++ b/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx @@ -51,7 +51,6 @@ function TransactionStartDateSelectorModal({isVisible, date, handleSelectDate, o Date: Sun, 2 Feb 2025 20:13:09 +0530 Subject: [PATCH 06/55] Fix lint --- .../assignCard/TransactionStartDateSelectorModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx b/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx index 5e5e258912a8..1b2ba15bdbd7 100644 --- a/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx +++ b/src/pages/workspace/companyCards/assignCard/TransactionStartDateSelectorModal.tsx @@ -8,7 +8,7 @@ import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors} from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/AssignCardForm'; @@ -32,7 +32,7 @@ function TransactionStartDateSelectorModal({isVisible, date, handleSelectDate, o const {translate} = useLocalize(); const validate = (values: FormOnyxValues): FormInputErrors => - ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.START_DATE]); + getFieldRequiredErrors(values, [INPUT_IDS.START_DATE]); const submit = (values: FormOnyxValues) => { handleSelectDate(values[INPUT_IDS.START_DATE]); From 68b3262906132b97b367e102d50a4564ad073c4c Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 3 Feb 2025 16:24:26 +0100 Subject: [PATCH 07/55] fix merge --- .../Search/SearchAutocompleteInput.tsx | 16 +++------------- src/libs/SearchAutocompleteUtils.ts | 9 ++------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/components/Search/SearchAutocompleteInput.tsx b/src/components/Search/SearchAutocompleteInput.tsx index 0c2dd8124b46..6a3c9c8c5e5e 100644 --- a/src/components/Search/SearchAutocompleteInput.tsx +++ b/src/components/Search/SearchAutocompleteInput.tsx @@ -2,11 +2,9 @@ import isEqual from 'lodash/isEqual'; import type {ForwardedRef, ReactNode, RefObject} from 'react'; import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; -import type {StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; -import {useSharedValue} from 'react-native-reanimated'; import type {StyleProp, TextInputProps, ViewStyle} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import {useSharedValue} from 'react-native-reanimated'; import FormHelpMessage from '@components/FormHelpMessage'; import type {SelectionListHandle} from '@components/SelectionList/types'; import TextInput from '@components/TextInput'; @@ -101,7 +99,6 @@ function SearchAutocompleteInput( const {isOffline} = useNetwork(); const {activeWorkspaceID} = useActiveWorkspace(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const personalDetailsSharedValue = useSharedValue({login: currentUserPersonalDetails.login, userDisplayName: currentUserPersonalDetails.displayName}); const lastMap = useRef({}); const [map, setMap] = useState({}); @@ -133,13 +130,6 @@ function SearchAutocompleteInput( const offlineMessage: string = isOffline && shouldShowOfflineMessage ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; - useEffect(() => { - runOnLiveMarkdownRuntime(() => { - 'worklet'; - - personalDetailsSharedValue.set({login: currentUserPersonalDetails.login, userDisplayName: currentUserPersonalDetails.displayName}); - })(); - }, [currentUserPersonalDetails, personalDetailsSharedValue]); useEffect(() => { runOnLiveMarkdownRuntime(() => { 'worklet'; @@ -166,9 +156,9 @@ function SearchAutocompleteInput( (input: string) => { 'worklet'; - return parseForLiveMarkdown(input, emailList, personalDetailsSharedValue, map, currencySharedValue, categorySharedValue, tagSharedValue); + return parseForLiveMarkdown(input, emailList, currentUserPersonalDetails.displayName ?? '', map, currencySharedValue, categorySharedValue, tagSharedValue); }, - [personalDetailsSharedValue, map, currencySharedValue, categorySharedValue, tagSharedValue, emailList], + [currentUserPersonalDetails.displayName, map, currencySharedValue, categorySharedValue, tagSharedValue, emailList], ); const inputWidth = isFullWidth ? styles.w100 : {width: variables.popoverWidth}; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index fc5836a2c1da..e798e88a5514 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -143,7 +143,7 @@ function getAutocompleteQueryWithComma(prevQuery: string, newQuery: string) { function parseForLiveMarkdown( input: string, userLogins: string[], - details: SharedValue<{login: string | undefined; userDisplayName: string | undefined}>, + userDisplayName: string, map: SubstitutionMap, currencyList: SharedValue, categoryList: SharedValue, @@ -177,12 +177,7 @@ function parseForLiveMarkdown( .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG || tagList.get().includes(range.value)) .map((range) => { let type = 'mention-user'; - if ( - (range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) && - (range.value === details.get().login || range.value === details.get().userDisplayName) - ) { - type = 'mention-here'; - } + if (range.key === 'syntax') { type = 'syntax'; } From d5acdeee562539eef52d46ef60ab8d9bcd220e64 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 3 Feb 2025 17:14:44 +0100 Subject: [PATCH 08/55] make emailList shared value --- .../Search/SearchAutocompleteInput.tsx | 21 ++++++++++++++----- src/libs/SearchAutocompleteUtils.ts | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/components/Search/SearchAutocompleteInput.tsx b/src/components/Search/SearchAutocompleteInput.tsx index 6a3c9c8c5e5e..ab6ecd333dfe 100644 --- a/src/components/Search/SearchAutocompleteInput.tsx +++ b/src/components/Search/SearchAutocompleteInput.tsx @@ -118,6 +118,10 @@ function SearchAutocompleteInput( }, [activeWorkspaceID, allPoliciesTags]); const tagSharedValue = useSharedValue(tagAutocompleteList); + const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); + const emailList = Object.keys(loginList ?? {}); + const emailListSharedValue = useSharedValue(emailList); + useEffect(() => { if (lastMap.current && !isEqual(lastMap.current, substitutionMap)) { lastMap.current = substitutionMap; @@ -125,11 +129,16 @@ function SearchAutocompleteInput( setMap(lastMap.current ?? {}); }, [substitutionMap, lastMap]); - const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); - const emailList = Object.keys(loginList ?? {}); - const offlineMessage: string = isOffline && shouldShowOfflineMessage ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; + useEffect(() => { + runOnLiveMarkdownRuntime(() => { + 'worklet'; + + emailListSharedValue.set(emailList); + })(); + }, [emailList, emailListSharedValue]); + useEffect(() => { runOnLiveMarkdownRuntime(() => { 'worklet'; @@ -137,6 +146,7 @@ function SearchAutocompleteInput( currencySharedValue.set(currencyAutocompleteList); })(); }, [currencyAutocompleteList, currencySharedValue]); + useEffect(() => { runOnLiveMarkdownRuntime(() => { 'worklet'; @@ -144,6 +154,7 @@ function SearchAutocompleteInput( categorySharedValue.set(categoryAutocompleteList); })(); }, [categorySharedValue, categoryAutocompleteList]); + useEffect(() => { runOnLiveMarkdownRuntime(() => { 'worklet'; @@ -156,9 +167,9 @@ function SearchAutocompleteInput( (input: string) => { 'worklet'; - return parseForLiveMarkdown(input, emailList, currentUserPersonalDetails.displayName ?? '', map, currencySharedValue, categorySharedValue, tagSharedValue); + return parseForLiveMarkdown(input, currentUserPersonalDetails.displayName ?? '', map, emailListSharedValue, currencySharedValue, categorySharedValue, tagSharedValue); }, - [currentUserPersonalDetails.displayName, map, currencySharedValue, categorySharedValue, tagSharedValue, emailList], + [currentUserPersonalDetails.displayName, map, currencySharedValue, categorySharedValue, tagSharedValue, emailListSharedValue], ); const inputWidth = isFullWidth ? styles.w100 : {width: variables.popoverWidth}; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index e798e88a5514..73b35ac0ed21 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -142,9 +142,9 @@ function getAutocompleteQueryWithComma(prevQuery: string, newQuery: string) { */ function parseForLiveMarkdown( input: string, - userLogins: string[], userDisplayName: string, map: SubstitutionMap, + userLogins: SharedValue, currencyList: SharedValue, categoryList: SharedValue, tagList: SharedValue, @@ -182,7 +182,7 @@ function parseForLiveMarkdown( type = 'syntax'; } - if ((range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) && (userLogins.includes(range.value) || range.value === userDisplayName)) { + if ((range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) && (userLogins.get().includes(range.value) || range.value === userDisplayName)) { type = 'mention-here'; } From 3341f9ca7ee4ca0074e7b3d6eafbf4316c7472bb Mon Sep 17 00:00:00 2001 From: Christina Dobrzynski <51066321+Christinadobrzyn@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:55:23 -0800 Subject: [PATCH 09/55] Update Cardholder-Settings-and-Features.md Tracking GH: https://github.com/Expensify/Expensify/issues/463351 Removing mention of the free plan - I don't think it makes sense to edit the sentence to anything else since this article is for the cardholder --- .../expensify-card/Cardholder-Settings-and-Features.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md b/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md index 38686462a1c2..ee03a18033ea 100644 --- a/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md +++ b/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md @@ -54,8 +54,6 @@ To add your Expensify Card to a digital wallet, follow the steps below: - **Restricted Country**: Transactions from restricted countries will be declined. {% include faq-begin.md %} -## Can I use Smart Limits with a free Expensify account? -If you're on the Free plan, you won't have the option to use Smart Limits. Your card limit will simply reset at the end of each calendar month. ## I still haven't received my Expensify Card. What should I do? For more information on why your card hasn't arrived, you can check out this resource on [Requesting a Card](https://help.expensify.com/articles/expensify-classic/expensify-card/Request-the-Card#what-if-i-havent-received-my-card-after-multiple-weeks). From 068f04c8aac3de91d1401979843f1c9f081ab56d Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 4 Feb 2025 13:07:29 +0100 Subject: [PATCH 10/55] fix changed files lint --- .../Search/SearchRouter/getUpdatedSubstitutionsMap.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts index a681ae6030f0..fca4ad525600 100644 --- a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts @@ -1,5 +1,5 @@ import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; -import * as parser from '@libs/SearchParser/autocompleteParser'; +import {parse} from '@libs/SearchParser/autocompleteParser'; import type {SubstitutionMap} from './getQueryWithSubstitutions'; const getSubstitutionsKey = (filterKey: SearchFilterKey, value: string) => `${filterKey}:${value}`; @@ -16,7 +16,7 @@ const getSubstitutionsKey = (filterKey: SearchFilterKey, value: string) => `${fi * return: {} */ function getUpdatedSubstitutionsMap(query: string, substitutions: SubstitutionMap): SubstitutionMap { - const parsedQuery = parser.parse(query) as {ranges: SearchAutocompleteQueryRange[]}; + const parsedQuery = parse(query) as {ranges: SearchAutocompleteQueryRange[]}; const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== 'syntax'); From 62b16170858494acd9386bf6fb3d02e68584fde5 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 4 Feb 2025 13:24:42 +0100 Subject: [PATCH 11/55] fix parser --- src/libs/SearchParser/searchParser.peggy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index a369b8aa754b..cfbf076e381c 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -98,7 +98,7 @@ freeTextFilter } else { word = value; } - return buildFilter("eq", "keyword", value); + return buildFilter("eq", "keyword", word); } standardFilter From 56a5c8dad6f7e2b40e3d668e2d44ba8834bff2af Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 4 Feb 2025 13:26:10 +0100 Subject: [PATCH 12/55] generate serach parser --- src/libs/SearchParser/searchParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index cbae90c1461b..66846116ca35 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -324,7 +324,7 @@ function peg$parse(input, options) { } else { word = value; } - return buildFilter("eq", "keyword", value); + return buildFilter("eq", "keyword", word); }; var peg$f4 = function(field, op, values) { return buildFilter(op, field, values); From 568d42f85f32eb674d327acd95c82c40cac60bde Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 4 Feb 2025 13:56:36 +0100 Subject: [PATCH 13/55] fix types and remove unnecessary ref --- src/CONST.ts | 1 + src/components/Search/SearchAutocompleteInput.tsx | 9 ++++----- src/components/Search/types.ts | 3 +-- src/libs/SearchAutocompleteUtils.ts | 15 ++++++++------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 1250092cb910..e5e6c7593532 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6136,6 +6136,7 @@ const CONST = { LOWER_THAN: 'lt', LOWER_THAN_OR_EQUAL_TO: 'lte', }, + SYNTAX_KEY: 'syntax', SYNTAX_ROOT_KEYS: { TYPE: 'type', STATUS: 'status', diff --git a/src/components/Search/SearchAutocompleteInput.tsx b/src/components/Search/SearchAutocompleteInput.tsx index ca828679cdfe..f59558f2740a 100644 --- a/src/components/Search/SearchAutocompleteInput.tsx +++ b/src/components/Search/SearchAutocompleteInput.tsx @@ -99,7 +99,6 @@ function SearchAutocompleteInput( const {isOffline} = useNetwork(); const {activeWorkspaceID} = useActiveWorkspace(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const lastMap = useRef({}); const [map, setMap] = useState({}); const [currencyList] = useOnyx(ONYXKEYS.CURRENCY_LIST); @@ -123,11 +122,11 @@ function SearchAutocompleteInput( const emailListSharedValue = useSharedValue(emailList); useEffect(() => { - if (lastMap.current && !isEqual(lastMap.current, substitutionMap)) { - lastMap.current = substitutionMap; + if (isEqual(map, substitutionMap)) { + return; } - setMap(lastMap.current ?? {}); - }, [substitutionMap, lastMap]); + setMap(substitutionMap); + }, [substitutionMap, map]); const offlineMessage: string = isOffline && shouldShowOfflineMessage ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index b5c58c798b9f..b4c7d9d4dd20 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -96,7 +96,7 @@ type SearchFilterKey = | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID - | 'syntax'; + | typeof CONST.SEARCH.SYNTAX_KEY; type UserFriendlyKey = ValueOf; @@ -129,7 +129,6 @@ type SearchAutocompleteResult = { ranges: SearchAutocompleteQueryRange[]; }; -// TODO FIX types type SearchAutocompleteQueryRange = { key: SearchFilterKey; length: number; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index 73b35ac0ed21..e458b186b6a8 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -161,13 +161,14 @@ function parseForLiveMarkdown( return ranges .filter( (range) => - !( - range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || - range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM || - range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN || - range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE || - range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID - ) || subMap[`${range.key}:${range.value}`] !== undefined, + !(range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN || range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE || range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID) || + subMap[`${range.key}:${range.value}`] !== undefined, + ) + .filter( + (range) => + !(range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) || + subMap[`${range.key}:${range.value}`] !== undefined || + userLogins.get().includes(range.value), ) .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY || currencyList.get().includes(range.value)) .filter((range) => range.key !== CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE || typeList.includes(range.value)) From ee8297b9ca09e070be9c36ec14669188a9416fa0 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 4 Feb 2025 15:30:42 +0100 Subject: [PATCH 14/55] fix tests for autocomplete parser --- .../Search/SearchAutocompleteInput.tsx | 2 +- tests/unit/SearchAutocompleteParserTest.ts | 42 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/components/Search/SearchAutocompleteInput.tsx b/src/components/Search/SearchAutocompleteInput.tsx index f59558f2740a..358b82d380a0 100644 --- a/src/components/Search/SearchAutocompleteInput.tsx +++ b/src/components/Search/SearchAutocompleteInput.tsx @@ -1,6 +1,6 @@ import isEqual from 'lodash/isEqual'; import type {ForwardedRef, ReactNode, RefObject} from 'react'; -import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; +import React, {forwardRef, useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import type {StyleProp, TextInputProps, ViewStyle} from 'react-native'; import {useOnyx} from 'react-native-onyx'; diff --git a/tests/unit/SearchAutocompleteParserTest.ts b/tests/unit/SearchAutocompleteParserTest.ts index 995d23eaeff5..e9ef145ed9ad 100644 --- a/tests/unit/SearchAutocompleteParserTest.ts +++ b/tests/unit/SearchAutocompleteParserTest.ts @@ -13,7 +13,9 @@ const tests = [ length: 3, }, ranges: [ + {key: 'syntax', value: 'type', start: 0, length: 5}, {key: 'type', value: 'expense', start: 5, length: 7}, + {key: 'syntax', value: 'status', start: 13, length: 7}, {key: 'status', value: 'all', start: 20, length: 3}, ], }, @@ -23,8 +25,11 @@ const tests = [ expected: { autocomplete: null, ranges: [ + {key: 'syntax', value: 'taxRate', start: 0, length: 9}, {key: 'taxRate', value: 'rate1', start: 9, length: 5}, + {key: 'syntax', value: 'expenseType', start: 15, length: 13}, {key: 'expenseType', value: 'card', start: 28, length: 4}, + {key: 'syntax', value: 'cardID', start: 33, length: 5}, {key: 'cardID', value: 'Big Bank', start: 38, length: 10}, ], }, @@ -34,8 +39,11 @@ const tests = [ expected: { autocomplete: null, ranges: [ + {key: 'syntax', value: 'taxRate', start: 0, length: 8}, {key: 'taxRate', value: 'rate1', start: 8, length: 5}, + {key: 'syntax', value: 'expenseType', start: 14, length: 12}, {key: 'expenseType', value: 'card', start: 26, length: 4}, + {key: 'syntax', value: 'cardID', start: 31, length: 7}, {key: 'cardID', value: 'Big Bank', start: 38, length: 10}, ], }, @@ -50,8 +58,10 @@ const tests = [ value: 'meal & entertainment', }, ranges: [ + {key: 'syntax', value: 'expenseType', start: 11, length: 13}, {key: 'expenseType', length: 4, start: 24, value: 'cash'}, {key: 'expenseType', length: 4, start: 29, value: 'card'}, + {key: 'syntax', value: 'category', start: 80, length: 9}, {key: 'category', length: 6, start: 89, value: 'travel'}, {key: 'category', length: 5, start: 96, value: 'hotel'}, {key: 'category', length: 22, start: 102, value: 'meal & entertainment'}, @@ -68,8 +78,11 @@ const tests = [ value: 'a b', }, ranges: [ + {key: 'syntax', value: 'type', start: 0, length: 5}, {key: 'type', value: 'expense', start: 5, length: 7}, + {key: 'syntax', value: 'status', start: 13, length: 7}, {key: 'status', value: 'all', start: 20, length: 3}, + {key: 'syntax', value: 'category', start: 24, length: 9}, {key: 'category', value: 'a b', start: 33, length: 5}, ], }, @@ -92,7 +105,7 @@ const tests = [ query: 'tag:,,', expected: { autocomplete: null, - ranges: [], + ranges: [{key: 'syntax', value: 'tag', start: 0, length: 4}], }, }, { @@ -105,7 +118,9 @@ const tests = [ length: 3, }, ranges: [ + {key: 'syntax', value: 'in', start: 0, length: 3}, {key: 'in', value: '123456', start: 3, length: 6}, + {key: 'syntax', value: 'currency', start: 10, length: 9}, {key: 'currency', value: 'USD', start: 19, length: 3}, ], }, @@ -120,6 +135,7 @@ const tests = [ length: 4, }, ranges: [ + {key: 'syntax', value: 'tag', start: 0, length: 4}, {key: 'tag', value: 'aa', start: 4, length: 2}, {key: 'tag', value: 'bbb', start: 7, length: 3}, {key: 'tag', value: 'cccc', start: 11, length: 4}, @@ -135,7 +151,7 @@ const tests = [ start: 9, length: 0, }, - ranges: [], + ranges: [{key: 'syntax', value: 'category', start: 0, length: 9}], }, }, { @@ -147,7 +163,10 @@ const tests = [ start: 21, length: 0, }, - ranges: [{key: 'category', value: 'Advertising', start: 9, length: 11}], + ranges: [ + {key: 'syntax', value: 'category', start: 0, length: 9}, + {key: 'category', value: 'Advertising', start: 9, length: 11}, + ], }, }, { @@ -160,6 +179,7 @@ const tests = [ length: 12, }, ranges: [ + {key: 'syntax', value: 'in', start: 0, length: 3}, {key: 'in', value: 'Big Room', start: 3, length: 10}, {key: 'in', value: 'small room', start: 14, length: 12}, ], @@ -174,7 +194,10 @@ const tests = [ start: 12, length: 3, }, - ranges: [{key: 'category', value: 'Car', start: 12, length: 3}], + ranges: [ + {key: 'syntax', value: 'category', start: 0, length: 12}, + {key: 'category', value: 'Car', start: 12, length: 3}, + ], }, }, { @@ -182,7 +205,9 @@ const tests = [ expected: { autocomplete: null, ranges: [ + {key: 'syntax', value: 'type', start: 0, length: 5}, {key: 'type', value: 'expense', start: 5, length: 7}, + {key: 'syntax', value: 'status', start: 13, length: 7}, {key: 'status', value: 'all', start: 20, length: 3}, ], }, @@ -197,11 +222,16 @@ const tests = [ length: 4, }, ranges: [ + {key: 'syntax', value: 'in', start: 0, length: 3}, {key: 'in', value: 'Big Room', start: 3, length: 10}, + {key: 'syntax', value: 'from', start: 14, length: 5}, {key: 'from', value: 'Friend', start: 19, length: 6}, + {key: 'syntax', value: 'category', start: 26, length: 9}, {key: 'category', value: 'Car', start: 35, length: 3}, {key: 'category', value: 'Cell Phone', start: 39, length: 12}, + {key: 'syntax', value: 'status', start: 52, length: 7}, {key: 'status', value: 'all', start: 59, length: 3}, + {key: 'syntax', value: 'expenseType', start: 63, length: 13}, {key: 'expenseType', value: 'card', start: 76, length: 4}, {key: 'expenseType', value: 'cash', start: 81, length: 4}, ], @@ -217,11 +247,15 @@ const tests = [ length: 8, }, ranges: [ + {key: 'syntax', value: 'currency', start: 0, length: 9}, {key: 'currency', value: 'PLN', start: 9, length: 3}, {key: 'currency', value: 'USD', start: 13, length: 3}, + {key: 'syntax', value: 'taxRate', start: 25, length: 9}, {key: 'taxRate', value: 'tax', start: 34, length: 3}, + {key: 'syntax', value: 'tag', start: 66, length: 4}, {key: 'tag', value: 'General Overhead', start: 70, length: 18}, {key: 'tag', value: 'IT', start: 89, length: 2}, + {key: 'syntax', value: 'expenseType', start: 92, length: 13}, {key: 'expenseType', value: 'card', start: 105, length: 4}, {key: 'expenseType', value: 'distance', start: 110, length: 8}, ], From efb018a5445ef87564e51f85dc5bb2076c074541 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 4 Feb 2025 16:03:56 +0100 Subject: [PATCH 15/55] fix types and perf-tests --- .../Search/SearchRouter/getQueryWithSubstitutions.ts | 3 ++- .../Search/SearchRouter/getUpdatedSubstitutionsMap.ts | 3 ++- src/components/Search/types.ts | 5 ++--- tests/perf-test/SearchRouter.perf-test.tsx | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index b976371135a6..4262f1df8529 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -1,10 +1,11 @@ import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; import {parse} from '@libs/SearchParser/autocompleteParser'; import {sanitizeSearchValue} from '@libs/SearchQueryUtils'; +import type CONST from '@src/CONST'; type SubstitutionMap = Record; -const getSubstitutionMapKey = (filterKey: SearchFilterKey, value: string) => `${filterKey}:${value}`; +const getSubstitutionMapKey = (filterKey: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_KEY, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, this function will return a transformed query where: diff --git a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts index fca4ad525600..ac9f8a7a807d 100644 --- a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts @@ -1,8 +1,9 @@ import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; import {parse} from '@libs/SearchParser/autocompleteParser'; +import type CONST from '@src/CONST'; import type {SubstitutionMap} from './getQueryWithSubstitutions'; -const getSubstitutionsKey = (filterKey: SearchFilterKey, value: string) => `${filterKey}:${value}`; +const getSubstitutionsKey = (filterKey: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_KEY, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index b4c7d9d4dd20..436cc33ad373 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -95,8 +95,7 @@ type SearchFilterKey = | ValueOf | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS - | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID - | typeof CONST.SEARCH.SYNTAX_KEY; + | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID; type UserFriendlyKey = ValueOf; @@ -130,7 +129,7 @@ type SearchAutocompleteResult = { }; type SearchAutocompleteQueryRange = { - key: SearchFilterKey; + key: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_KEY; length: number; start: number; value: string; diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 089f08b14fb3..ea260eb4b83d 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -117,6 +117,7 @@ function SearchAutocompleteInputWrapper() { value={value} onSearchQueryChange={(searchTerm) => setValue(searchTerm)} isFullWidth={false} + substitutionMap={{}} /> ); From f56ae479fd5f2a8981db8f7809201a5eb04e7106 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 5 Feb 2025 12:26:22 +0100 Subject: [PATCH 16/55] fix perf tests and changed files lint --- tests/perf-test/SearchRouter.perf-test.tsx | 5 +++++ tests/unit/SearchAutocompleteParserTest.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index ea260eb4b83d..44309ab5e720 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -69,6 +69,11 @@ jest.mock('@react-navigation/native', () => { }; }); +jest.mock('@libs/runOnLiveMarkdownRuntime', () => { + const runOnLiveMarkdownRuntime = (worklet: (...args: Args) => ReturnValue) => worklet; + return runOnLiveMarkdownRuntime; +}); + const getMockedReports = (length = 100) => createCollection( (item) => `${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`, diff --git a/tests/unit/SearchAutocompleteParserTest.ts b/tests/unit/SearchAutocompleteParserTest.ts index e9ef145ed9ad..84fbf70b3aeb 100644 --- a/tests/unit/SearchAutocompleteParserTest.ts +++ b/tests/unit/SearchAutocompleteParserTest.ts @@ -1,5 +1,5 @@ import type {SearchQueryJSON} from '@components/Search/types'; -import * as autocompleteParser from '@libs/SearchParser/autocompleteParser'; +import {parse} from '@libs/SearchParser/autocompleteParser'; import parserCommonTests from '../utils/fixtures/searchParsersCommonQueries'; const tests = [ @@ -265,7 +265,7 @@ const tests = [ describe('autocomplete parser', () => { test.each(tests)(`parsing: $query`, ({query, expected}) => { - const result = autocompleteParser.parse(query) as SearchQueryJSON; + const result = parse(query) as SearchQueryJSON; expect(result).toEqual(expected); }); From 3e3221f25848e106cb5b5e14e6ce2145e171ecdf Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 5 Feb 2025 13:34:22 +0100 Subject: [PATCH 17/55] fix names and consts --- src/CONST.ts | 2 +- src/components/Search/SearchAutocompleteInput.tsx | 13 ++----------- src/components/Search/SearchPageHeaderInput.tsx | 5 ++++- src/components/Search/SearchRouter/SearchRouter.tsx | 5 ++++- .../Search/SearchRouter/buildSubstitutionsMap.ts | 2 +- .../SearchRouter/getQueryWithSubstitutions.ts | 8 ++++---- .../SearchRouter/getUpdatedSubstitutionsMap.ts | 8 ++++---- src/components/Search/types.ts | 5 ++++- src/libs/SearchAutocompleteUtils.ts | 4 ++-- src/libs/runOnLiveMarkdownRuntime/index.native.tsx | 2 +- tests/perf-test/SearchRouter.perf-test.tsx | 2 +- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index b687afe4c8fa..9c44e6539071 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6189,7 +6189,7 @@ const CONST = { LOWER_THAN: 'lt', LOWER_THAN_OR_EQUAL_TO: 'lte', }, - SYNTAX_KEY: 'syntax', + SYNTAX_RANGE_NAME: 'syntax', SYNTAX_ROOT_KEYS: { TYPE: 'type', STATUS: 'status', diff --git a/src/components/Search/SearchAutocompleteInput.tsx b/src/components/Search/SearchAutocompleteInput.tsx index 84756b9806e9..a89c68364ad9 100644 --- a/src/components/Search/SearchAutocompleteInput.tsx +++ b/src/components/Search/SearchAutocompleteInput.tsx @@ -1,4 +1,3 @@ -import isEqual from 'lodash/isEqual'; import type {ForwardedRef, ReactNode, RefObject} from 'react'; import React, {forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; @@ -100,7 +99,6 @@ function SearchAutocompleteInput( const {isOffline} = useNetwork(); const {activeWorkspaceID} = useActiveWorkspace(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const [map, setMap] = useState({}); const [currencyList] = useOnyx(ONYXKEYS.CURRENCY_LIST); const currencyAutocompleteList = Object.keys(currencyList ?? {}); @@ -122,13 +120,6 @@ function SearchAutocompleteInput( const emailList = Object.keys(loginList ?? {}); const emailListSharedValue = useSharedValue(emailList); - useEffect(() => { - if (isEqual(map, substitutionMap)) { - return; - } - setMap(substitutionMap); - }, [substitutionMap, map]); - const offlineMessage: string = isOffline && shouldShowOfflineMessage ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; useEffect(() => { @@ -167,9 +158,9 @@ function SearchAutocompleteInput( (input: string) => { 'worklet'; - return parseForLiveMarkdown(input, currentUserPersonalDetails.displayName ?? '', map, emailListSharedValue, currencySharedValue, categorySharedValue, tagSharedValue); + return parseForLiveMarkdown(input, currentUserPersonalDetails.displayName ?? '', substitutionMap, emailListSharedValue, currencySharedValue, categorySharedValue, tagSharedValue); }, - [currentUserPersonalDetails.displayName, map, currencySharedValue, categorySharedValue, tagSharedValue, emailListSharedValue], + [currentUserPersonalDetails.displayName, substitutionMap, currencySharedValue, categorySharedValue, tagSharedValue, emailListSharedValue], ); const inputWidth = isFullWidth ? styles.w100 : {width: variables.popoverWidth}; diff --git a/src/components/Search/SearchPageHeaderInput.tsx b/src/components/Search/SearchPageHeaderInput.tsx index f763a22d6aeb..d39c58f9edea 100644 --- a/src/components/Search/SearchPageHeaderInput.tsx +++ b/src/components/Search/SearchPageHeaderInput.tsx @@ -1,4 +1,5 @@ import {useIsFocused} from '@react-navigation/native'; +import isEqual from 'lodash/isEqual'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; @@ -123,7 +124,9 @@ function SearchPageHeaderInput({queryJSON, children}: SearchPageHeaderInputProps setAutocompleteQueryValue(updatedUserQuery); const updatedSubstitutionsMap = getUpdatedSubstitutionsMap(userQuery, autocompleteSubstitutions); - setAutocompleteSubstitutions(updatedSubstitutionsMap); + if (!isEqual(autocompleteSubstitutions, updatedSubstitutionsMap)) { + setAutocompleteSubstitutions(updatedSubstitutionsMap); + } if (updatedUserQuery) { listRef.current?.updateAndScrollToFocusedIndex(0); diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 51b86812694c..6c6b4dc689d3 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -1,4 +1,5 @@ import {useNavigationState} from '@react-navigation/native'; +import isEqual from 'lodash/isEqual'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; import type {TextInputProps} from 'react-native'; @@ -185,7 +186,9 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) setAutocompleteQueryValue(updatedUserQuery); const updatedSubstitutionsMap = getUpdatedSubstitutionsMap(userQuery, autocompleteSubstitutions); - setAutocompleteSubstitutions(updatedSubstitutionsMap); + if (!isEqual(autocompleteSubstitutions, updatedSubstitutionsMap)) { + setAutocompleteSubstitutions(updatedSubstitutionsMap); + } if (updatedUserQuery || textInputValue.length > 0) { listRef.current?.updateAndScrollToFocusedIndex(0); diff --git a/src/components/Search/SearchRouter/buildSubstitutionsMap.ts b/src/components/Search/SearchRouter/buildSubstitutionsMap.ts index 0a3c49819b38..1972a487c92f 100644 --- a/src/components/Search/SearchRouter/buildSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/buildSubstitutionsMap.ts @@ -33,7 +33,7 @@ function buildSubstitutionsMap( ): SubstitutionMap { const parsedQuery = parse(query) as {ranges: SearchAutocompleteQueryRange[]}; - const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== 'syntax'); + const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== CONST.SEARCH.SYNTAX_RANGE_NAME); if (searchAutocompleteQueryRanges.length === 0) { return {}; diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index 4262f1df8529..e20577b7df45 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -1,11 +1,11 @@ -import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; +import type {SearchAutocompleteQueryRange, SearchAutocompleteQueryRangeKey} from '@components/Search/types'; import {parse} from '@libs/SearchParser/autocompleteParser'; import {sanitizeSearchValue} from '@libs/SearchQueryUtils'; -import type CONST from '@src/CONST'; +import CONST from '@src/CONST'; type SubstitutionMap = Record; -const getSubstitutionMapKey = (filterKey: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_KEY, value: string) => `${filterKey}:${value}`; +const getSubstitutionMapKey = (filterKey: SearchAutocompleteQueryRangeKey, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, this function will return a transformed query where: @@ -22,7 +22,7 @@ const getSubstitutionMapKey = (filterKey: SearchFilterKey | typeof CONST.SEARCH. function getQueryWithSubstitutions(changedQuery: string, substitutions: SubstitutionMap) { const parsed = parse(changedQuery) as {ranges: SearchAutocompleteQueryRange[]}; - const searchAutocompleteQueryRanges = parsed.ranges.filter((range) => range.key !== 'syntax'); + const searchAutocompleteQueryRanges = parsed.ranges.filter((range) => range.key !== CONST.SEARCH.SYNTAX_RANGE_NAME); if (searchAutocompleteQueryRanges.length === 0) { return changedQuery; diff --git a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts index ac9f8a7a807d..aa37f84acc68 100644 --- a/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/getUpdatedSubstitutionsMap.ts @@ -1,9 +1,9 @@ -import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; +import type {SearchAutocompleteQueryRange, SearchAutocompleteQueryRangeKey} from '@components/Search/types'; import {parse} from '@libs/SearchParser/autocompleteParser'; -import type CONST from '@src/CONST'; +import CONST from '@src/CONST'; import type {SubstitutionMap} from './getQueryWithSubstitutions'; -const getSubstitutionsKey = (filterKey: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_KEY, value: string) => `${filterKey}:${value}`; +const getSubstitutionsKey = (filterKey: SearchAutocompleteQueryRangeKey, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, @@ -19,7 +19,7 @@ const getSubstitutionsKey = (filterKey: SearchFilterKey | typeof CONST.SEARCH.SY function getUpdatedSubstitutionsMap(query: string, substitutions: SubstitutionMap): SubstitutionMap { const parsedQuery = parse(query) as {ranges: SearchAutocompleteQueryRange[]}; - const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== 'syntax'); + const searchAutocompleteQueryRanges = parsedQuery.ranges.filter((range) => range.key !== CONST.SEARCH.SYNTAX_RANGE_NAME); if (searchAutocompleteQueryRanges.length === 0) { return {}; diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index e716be38f9d2..887c70944660 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -98,6 +98,8 @@ type SearchFilterKey = | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID; +type SearchAutocompleteQueryRangeKey = SearchFilterKey | typeof CONST.SEARCH.SYNTAX_RANGE_NAME; + type UserFriendlyKey = ValueOf; type QueryFilters = Array<{ @@ -130,7 +132,7 @@ type SearchAutocompleteResult = { }; type SearchAutocompleteQueryRange = { - key: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_KEY; + key: SearchAutocompleteQueryRangeKey; length: number; start: number; value: string; @@ -159,4 +161,5 @@ export type { SearchAutocompleteResult, PaymentData, SearchAutocompleteQueryRange, + SearchAutocompleteQueryRangeKey, }; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index e458b186b6a8..aca441abd700 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -179,8 +179,8 @@ function parseForLiveMarkdown( .map((range) => { let type = 'mention-user'; - if (range.key === 'syntax') { - type = 'syntax'; + if (range.key === CONST.SEARCH.SYNTAX_RANGE_NAME) { + type = CONST.SEARCH.SYNTAX_RANGE_NAME; } if ((range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) && (userLogins.get().includes(range.value) || range.value === userDisplayName)) { diff --git a/src/libs/runOnLiveMarkdownRuntime/index.native.tsx b/src/libs/runOnLiveMarkdownRuntime/index.native.tsx index 8927fe0a936c..fe7bd2441cf3 100644 --- a/src/libs/runOnLiveMarkdownRuntime/index.native.tsx +++ b/src/libs/runOnLiveMarkdownRuntime/index.native.tsx @@ -1,7 +1,7 @@ import {getWorkletRuntime} from '@expensify/react-native-live-markdown'; import {runOnRuntime} from 'react-native-reanimated'; -function runOnLiveMarkdownRuntime(worklet: (...args: Args) => ReturnValue) { +function runOnLiveMarkdownRuntime(worklet: (...args: Args) => ReturnType) { return runOnRuntime(getWorkletRuntime(), worklet); } diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 44309ab5e720..95807a12cd1b 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -122,7 +122,7 @@ function SearchAutocompleteInputWrapper() { value={value} onSearchQueryChange={(searchTerm) => setValue(searchTerm)} isFullWidth={false} - substitutionMap={{}} + substitutionMap={CONST.EMPTY_OBJECT} /> ); From 11b4639e707201e608fdede1faf1a11a3625e254 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 5 Feb 2025 14:01:07 +0100 Subject: [PATCH 18/55] improve readability - extract logic from parser --- src/libs/SearchAutocompleteUtils.ts | 67 +++++++++++++++++++---------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index aca441abd700..365134546c2b 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -2,7 +2,7 @@ import type {MarkdownRange} from '@expensify/react-native-live-markdown'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {SharedValue} from 'react-native-reanimated/lib/typescript/commonTypes'; import type {SubstitutionMap} from '@components/Search/SearchRouter/getQueryWithSubstitutions'; -import type {SearchAutocompleteResult} from '@components/Search/types'; +import type {SearchAutocompleteQueryRange, SearchAutocompleteResult} from '@components/Search/types'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, PolicyCategories, PolicyTagLists, RecentlyUsedCategories, RecentlyUsedTags} from '@src/types/onyx'; @@ -135,6 +135,48 @@ function getAutocompleteQueryWithComma(prevQuery: string, newQuery: string) { return newQuery; } +function filterOutRangesWithCorrectValue( + range: SearchAutocompleteQueryRange, + userDisplayName: string, + substitutionMap: SubstitutionMap, + userLogins: SharedValue, + currencyList: SharedValue, + categoryList: SharedValue, + tagList: SharedValue, +) { + 'worklet'; + + const typeList = Object.values(CONST.SEARCH.DATA_TYPES) as string[]; + const expenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE) as string[]; + const statusList = Object.values({...CONST.SEARCH.STATUS.TRIP, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}) as string[]; + + switch (range.key) { + case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID: + return substitutionMap[`${range.key}:${range.value}`] !== undefined; + + case CONST.SEARCH.SYNTAX_FILTER_KEYS.TO: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM: + return substitutionMap[`${range.key}:${range.value}`] !== undefined || userLogins.get().includes(range.value); + + case CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY: + return currencyList.get().includes(range.value); + case CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE: + return typeList.includes(range.value); + case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE: + return expenseTypeList.includes(range.value); + case CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS: + return statusList.includes(range.value); + case CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY: + return categoryList.get().includes(range.value); + case CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG: + return tagList.get().includes(range.value); + default: + return true; + } +} + /** * Parses input string using the autocomplete parser and returns array of * markdown ranges that can be used by RNMarkdownTextInput. @@ -153,29 +195,8 @@ function parseForLiveMarkdown( const parsedAutocomplete = parse(input) as SearchAutocompleteResult; const ranges = parsedAutocomplete.ranges; - - const typeList = Object.values(CONST.SEARCH.DATA_TYPES) as string[]; - const expenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE) as string[]; - const statusList = Object.values({...CONST.SEARCH.STATUS.TRIP, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}) as string[]; - const subMap = map; return ranges - .filter( - (range) => - !(range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN || range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE || range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID) || - subMap[`${range.key}:${range.value}`] !== undefined, - ) - .filter( - (range) => - !(range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO || range.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM) || - subMap[`${range.key}:${range.value}`] !== undefined || - userLogins.get().includes(range.value), - ) - .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY || currencyList.get().includes(range.value)) - .filter((range) => range.key !== CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE || typeList.includes(range.value)) - .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE || expenseTypeList.includes(range.value)) - .filter((range) => range.key !== CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS || statusList.includes(range.value)) - .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY || categoryList.get().includes(range.value)) - .filter((range) => range.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG || tagList.get().includes(range.value)) + .filter((range) => filterOutRangesWithCorrectValue(range, userDisplayName, map, userLogins, currencyList, categoryList, tagList)) .map((range) => { let type = 'mention-user'; From 829f608354456e7f2295d7c2679c7da6bb030f74 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 5 Feb 2025 14:24:42 +0100 Subject: [PATCH 19/55] fix type --- src/libs/runOnLiveMarkdownRuntime/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/runOnLiveMarkdownRuntime/index.tsx b/src/libs/runOnLiveMarkdownRuntime/index.tsx index c8e072693323..928e7a34ea3f 100644 --- a/src/libs/runOnLiveMarkdownRuntime/index.tsx +++ b/src/libs/runOnLiveMarkdownRuntime/index.tsx @@ -1,5 +1,5 @@ // Reanimated does not support runOnRuntime() on web -function runOnLiveMarkdownRuntime(worklet: (...args: Args) => ReturnValue) { +function runOnLiveMarkdownRuntime(worklet: (...args: Args) => ReturnType) { return worklet; } From 94a6d3fa1491cc89ccc33c6bc0e37eaa8772bd0b Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 11:12:33 -0800 Subject: [PATCH 20/55] Use 1P for OS Botify's GPG key --- .../composite/setupGitForOSBotify/action.yml | 14 +++++++------- .../composite/setupGitForOSBotifyApp/action.yml | 9 +++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/actions/composite/setupGitForOSBotify/action.yml b/.github/actions/composite/setupGitForOSBotify/action.yml index 456cef93676a..bf0ac5e8b064 100644 --- a/.github/actions/composite/setupGitForOSBotify/action.yml +++ b/.github/actions/composite/setupGitForOSBotify/action.yml @@ -9,9 +9,14 @@ inputs: runs: using: composite steps: - - name: Decrypt OSBotify GPG key - run: cd .github/workflows && gpg --quiet --batch --yes --decrypt --passphrase=${{ inputs.GPG_PASSPHRASE }} --output OSBotify-private-key.asc OSBotify-private-key.asc.gpg + - name: Install 1Password CLI + uses: 1password/install-cli-action@v1 + + - name: Load files from 1Password shell: bash + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + run: op read "op://Mobile-Deploy-CI/OSBotify-private-key.asc/OSBotify-private-key.asc" --force --out-file ./OSBotify-private-key.asc - name: Import OSBotify GPG Key shell: bash @@ -24,8 +29,3 @@ runs: git config --global commit.gpgsign true git config --global user.name OSBotify git config --global user.email infra+osbotify@expensify.com - - - name: Enable debug logs for git - shell: bash - if: runner.debug == '1' - run: echo "GIT_TRACE=true" >> "$GITHUB_ENV" diff --git a/.github/actions/composite/setupGitForOSBotifyApp/action.yml b/.github/actions/composite/setupGitForOSBotifyApp/action.yml index 404ddc55e954..d931183fd2cf 100644 --- a/.github/actions/composite/setupGitForOSBotifyApp/action.yml +++ b/.github/actions/composite/setupGitForOSBotifyApp/action.yml @@ -39,9 +39,14 @@ runs: sparse-checkout: | .github - - name: Decrypt OSBotify GPG key - run: cd .github/workflows && gpg --quiet --batch --yes --decrypt --passphrase=${{ inputs.GPG_PASSPHRASE }} --output OSBotify-private-key.asc OSBotify-private-key.asc.gpg + - name: Install 1Password CLI + uses: 1password/install-cli-action@v1 + + - name: Load files from 1Password shell: bash + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + run: op read "op://Mobile-Deploy-CI/OSBotify-private-key.asc/OSBotify-private-key.asc" --force --out-file ./OSBotify-private-key.asc - name: Import OSBotify GPG Key shell: bash From 7b8c85544260c06005497d326cade67f17d4d0ff Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 15:02:25 -0800 Subject: [PATCH 21/55] Try on AdHoc build --- .github/workflows/testBuild.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index ea62bca794fe..8e42e078ff73 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -242,10 +242,14 @@ jobs: - name: Setup Node uses: ./.github/actions/composite/setupNode - - name: Decrypt Developer ID Certificate - run: cd desktop && gpg --quiet --batch --yes --decrypt --passphrase="$DEVELOPER_ID_SECRET_PASSPHRASE" --output developer_id.p12 developer_id.p12.gpg + - name: Load Desktop credentials from 1Password + id: load-credentials + uses: 1password/load-secrets-action@v2 + with: + export-env: false env: - DEVELOPER_ID_SECRET_PASSPHRASE: ${{ secrets.DEVELOPER_ID_SECRET_PASSPHRASE }} + DESKTOP_CERTIFICATE_BASE64: "op://Mobile-Deploy-CI/Desktop Certificates.p12/CSC_LINK" + DESKTOP_CERTIFICATE_PASSWORD: "op://Mobile-Deploy-CI/Desktop Certificates.p12/CSC_KEY_PASSWORD" - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 @@ -257,8 +261,8 @@ jobs: - name: Build desktop app for testing run: npm run desktop-build-adhoc env: - CSC_LINK: ${{ secrets.CSC_LINK }} - CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + CSC_LINK: ${{ secrets.DESKTOP_CERTIFICATE_BASE64 }} + CSC_KEY_PASSWORD: ${{ secrets.DESKTOP_CERTIFICATE_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} From 256be7ac84f6caa97fd03398ff8b3658101b2503 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 15:08:42 -0800 Subject: [PATCH 22/55] Add 1P token --- .github/workflows/testBuild.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 8e42e078ff73..7cd88e4d9ccd 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -248,6 +248,7 @@ jobs: with: export-env: false env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} DESKTOP_CERTIFICATE_BASE64: "op://Mobile-Deploy-CI/Desktop Certificates.p12/CSC_LINK" DESKTOP_CERTIFICATE_PASSWORD: "op://Mobile-Deploy-CI/Desktop Certificates.p12/CSC_KEY_PASSWORD" From d527000244a0689978c6a937c64c3c6a29df3e2b Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 15:14:08 -0800 Subject: [PATCH 23/55] Use step load instead of secret --- .github/workflows/testBuild.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 7cd88e4d9ccd..80918d65462c 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -262,8 +262,8 @@ jobs: - name: Build desktop app for testing run: npm run desktop-build-adhoc env: - CSC_LINK: ${{ secrets.DESKTOP_CERTIFICATE_BASE64 }} - CSC_KEY_PASSWORD: ${{ secrets.DESKTOP_CERTIFICATE_PASSWORD }} + CSC_LINK: ${{ steps.load-credentials.outputs.DESKTOP_CERTIFICATE_BASE64 }} + CSC_KEY_PASSWORD: ${{ steps.load-credentials.outputs.DESKTOP_CERTIFICATE_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} From cee69984dc793103fff27938a8e0253abe141c8c Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 15:38:42 -0800 Subject: [PATCH 24/55] Remove GPG encrypted files --- .github/workflows/OSBotify-private-key.asc.gpg | Bin 3940 -> 0 bytes desktop/developer_id.p12.gpg | Bin 3300 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/workflows/OSBotify-private-key.asc.gpg delete mode 100644 desktop/developer_id.p12.gpg diff --git a/.github/workflows/OSBotify-private-key.asc.gpg b/.github/workflows/OSBotify-private-key.asc.gpg deleted file mode 100644 index 03f06222d0fe956cdb4d3cc00df9b2ff3566da21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3940 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 diff --git a/desktop/developer_id.p12.gpg b/desktop/developer_id.p12.gpg deleted file mode 100644 index ad166e3f83344b1234ee146e806bfaaa7ad40cef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3300 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 i4z|=Z@5!(TMLmWQV7!KSK87Ko*& Date: Wed, 5 Feb 2025 15:38:59 -0800 Subject: [PATCH 25/55] Remove all uses of gpg decrytion password --- .github/workflows/README.md | 8 -------- .github/workflows/cherryPick.yml | 1 - .github/workflows/createNewVersion.yml | 5 ----- .github/workflows/deploy.yml | 16 ++++++++++------ .github/workflows/finishReleaseCycle.yml | 3 --- .github/workflows/preDeploy.yml | 1 - 6 files changed, 10 insertions(+), 24 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 45dacacd0b16..525afa3a8cea 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -80,14 +80,6 @@ git fetch origin tag 1.0.1-0 --no-tags --shallow-exclude=1.0.0-0 # This will fet ## Secrets The GitHub workflows require a large list of secrets to deploy, notify and test the code: -1. `LARGE_SECRET_PASSPHRASE` - decrypts secrets stored in various encrypted files stored in GitHub repository. To create updated versions of these encrypted files, refer to steps 1-4 of [this encrypted secrets help page](https://docs.github.com/en/actions/reference/encrypted-secrets#limits-for-secrets) using the `LARGE_SECRET_PASSPHRASE`. - 1. `android/app/my-upload-key.keystore.gpg` - 1. `android/app/android-fastlane-json-key.json.gpg` - 1. `ios/NewApp_AdHoc.mobileprovision` - 1. `ios/NewApp_AdHoc_Notification_Service.mobileprovision` - 1. `ios/NewApp_AppStore.mobileprovision.gpg` - 1. `ios/NewApp_AppStore_Notification_Service.mobileprovision.gpg` - 1. `ios/Certificates.p12.gpg` 1. `SLACK_WEBHOOK` - Sends Slack notifications via Slack WebHook https://expensify.slack.com/services/B01AX48D7MM 1. `OS_BOTIFY_TOKEN` - Personal access token for @OSBotify user in GitHub 1. `CLA_BOTIFY_TOKEN` - Personal access token for @CLABotify user in GitHub diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 5cb0a99730c9..683568e255ef 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -45,7 +45,6 @@ jobs: id: setupGitForOSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} diff --git a/.github/workflows/createNewVersion.yml b/.github/workflows/createNewVersion.yml index 85c928707c6c..6245af07a121 100644 --- a/.github/workflows/createNewVersion.yml +++ b/.github/workflows/createNewVersion.yml @@ -23,9 +23,6 @@ on: value: ${{ jobs.createNewVersion.outputs.NEW_VERSION }} secrets: - LARGE_SECRET_PASSPHRASE: - description: Passphrase used to decrypt GPG key - required: true SLACK_WEBHOOK: description: Webhook used to comment in slack required: true @@ -73,8 +70,6 @@ jobs: - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotify id: setupGitForOSBotify - with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} - name: Generate new E/App version id: bumpVersion diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 99c38a2d2e5b..65fc2f2fbe9b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,7 +45,6 @@ jobs: uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} @@ -301,10 +300,15 @@ jobs: - name: Setup Node uses: ./.github/actions/composite/setupNode - - name: Decrypt Developer ID Certificate - run: cd desktop && gpg --quiet --batch --yes --decrypt --passphrase="$DEVELOPER_ID_SECRET_PASSPHRASE" --output developer_id.p12 developer_id.p12.gpg + - name: Load Desktop credentials from 1Password + id: load-credentials + uses: 1password/load-secrets-action@v2 + with: + export-env: false env: - DEVELOPER_ID_SECRET_PASSPHRASE: ${{ secrets.DEVELOPER_ID_SECRET_PASSPHRASE }} + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + DESKTOP_CERTIFICATE_BASE64: "op://Mobile-Deploy-CI/Desktop Certificates.p12/CSC_LINK" + DESKTOP_CERTIFICATE_PASSWORD: "op://Mobile-Deploy-CI/Desktop Certificates.p12/CSC_KEY_PASSWORD" - name: Build desktop app run: | @@ -314,8 +318,8 @@ jobs: npm run desktop-build-staging fi env: - CSC_LINK: ${{ secrets.CSC_LINK }} - CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + CSC_LINK: ${{ steps.load-credentials.outputs.DESKTOP_CERTIFICATE_BASE64 }} + CSC_KEY_PASSWORD: ${{ steps.load-credentials.outputs.DESKTOP_CERTIFICATE_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} diff --git a/.github/workflows/finishReleaseCycle.yml b/.github/workflows/finishReleaseCycle.yml index 2285eec56065..7a6690c27456 100644 --- a/.github/workflows/finishReleaseCycle.yml +++ b/.github/workflows/finishReleaseCycle.yml @@ -22,7 +22,6 @@ jobs: uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} @@ -87,7 +86,6 @@ jobs: id: setupGitForOSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} @@ -128,7 +126,6 @@ jobs: - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index bfe860e60224..f8723f55866c 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -104,7 +104,6 @@ jobs: - name: Setup Git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: - GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} From 9b44aca6f5fde244ca5d94da9a45c855b1828685 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 15:51:01 -0800 Subject: [PATCH 26/55] Add note about 1p --- .github/workflows/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 525afa3a8cea..73b62556ffd4 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -97,6 +97,11 @@ The GitHub workflows require a large list of secrets to deploy, notify and test 1. `APPLE_DEMO_PASSWORD` - Demo account password used for https://appstoreconnect.apple.com/ 1. `BROWSERSTACK` - Used to access Browserstack's API +We use 1Password for many secrets and in general use two different actions from 1Password to fetch secrets: + +1. `1password/install-cli-action` - This action is used to install 1Password cli `op` and is used to grab **files** using the `op read` command. +1. `1password/load-secrets-action` - This action is used to fetch **strings** from 1Password. + ### Important note about Secrets Secrets are available by default in most workflows. The exception to the rule is callable workflows. If a workflow is triggered by the `workflow_call` event, it will only have access to repo secrets if the workflow that called it passed in the secrets explicitly (for example, using `secrets: inherit`). From dbe1fc620a0f9a4ea8e4fbb08a031e465d815621 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 15:55:12 -0800 Subject: [PATCH 27/55] Remove unused input --- .github/actions/composite/setupGitForOSBotify/action.yml | 5 ----- .github/actions/composite/setupGitForOSBotifyApp/action.yml | 3 --- 2 files changed, 8 deletions(-) diff --git a/.github/actions/composite/setupGitForOSBotify/action.yml b/.github/actions/composite/setupGitForOSBotify/action.yml index bf0ac5e8b064..a655a67f1f44 100644 --- a/.github/actions/composite/setupGitForOSBotify/action.yml +++ b/.github/actions/composite/setupGitForOSBotify/action.yml @@ -1,11 +1,6 @@ name: 'Setup Git for OSBotify' description: 'Setup Git for OSBotify' -inputs: - GPG_PASSPHRASE: - description: 'Passphrase used to decrypt GPG key' - required: true - runs: using: composite steps: diff --git a/.github/actions/composite/setupGitForOSBotifyApp/action.yml b/.github/actions/composite/setupGitForOSBotifyApp/action.yml index d931183fd2cf..1321a3043649 100644 --- a/.github/actions/composite/setupGitForOSBotifyApp/action.yml +++ b/.github/actions/composite/setupGitForOSBotifyApp/action.yml @@ -5,9 +5,6 @@ name: "Setup Git for OSBotify" description: "Setup Git for OSBotify" inputs: - GPG_PASSPHRASE: - description: "Passphrase used to decrypt GPG key" - required: true OS_BOTIFY_APP_ID: description: "Application ID for OS Botify" required: true From 7257636dc7910397c1bb372170f692f4870ce08b Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 16:26:50 -0800 Subject: [PATCH 28/55] Add `OP_SERVICE_ACCOUNT_TOKEN` input instead of secret --- .github/actions/composite/setupGitForOSBotify/action.yml | 7 ++++++- .../actions/composite/setupGitForOSBotifyApp/action.yml | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/actions/composite/setupGitForOSBotify/action.yml b/.github/actions/composite/setupGitForOSBotify/action.yml index a655a67f1f44..0b212f7b40d7 100644 --- a/.github/actions/composite/setupGitForOSBotify/action.yml +++ b/.github/actions/composite/setupGitForOSBotify/action.yml @@ -1,6 +1,11 @@ name: 'Setup Git for OSBotify' description: 'Setup Git for OSBotify' +inputs: + OP_SERVICE_ACCOUNT_TOKEN: + description: "1Password service account token" + required: true + runs: using: composite steps: @@ -10,7 +15,7 @@ runs: - name: Load files from 1Password shell: bash env: - OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.OP_SERVICE_ACCOUNT_TOKEN }} run: op read "op://Mobile-Deploy-CI/OSBotify-private-key.asc/OSBotify-private-key.asc" --force --out-file ./OSBotify-private-key.asc - name: Import OSBotify GPG Key diff --git a/.github/actions/composite/setupGitForOSBotifyApp/action.yml b/.github/actions/composite/setupGitForOSBotifyApp/action.yml index 1321a3043649..d8e5e8e1e18f 100644 --- a/.github/actions/composite/setupGitForOSBotifyApp/action.yml +++ b/.github/actions/composite/setupGitForOSBotifyApp/action.yml @@ -5,6 +5,9 @@ name: "Setup Git for OSBotify" description: "Setup Git for OSBotify" inputs: + OP_SERVICE_ACCOUNT_TOKEN: + description: "1Password service account token" + required: true OS_BOTIFY_APP_ID: description: "Application ID for OS Botify" required: true @@ -42,7 +45,7 @@ runs: - name: Load files from 1Password shell: bash env: - OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.OP_SERVICE_ACCOUNT_TOKEN }} run: op read "op://Mobile-Deploy-CI/OSBotify-private-key.asc/OSBotify-private-key.asc" --force --out-file ./OSBotify-private-key.asc - name: Import OSBotify GPG Key From 5c10b746455f73761056ae4057e4d3bffff2997e Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 16:29:45 -0800 Subject: [PATCH 29/55] Add service account to all instances --- .github/workflows/cherryPick.yml | 1 + .github/workflows/createNewVersion.yml | 2 ++ .github/workflows/deploy.yml | 1 + .github/workflows/finishReleaseCycle.yml | 3 +++ .github/workflows/preDeploy.yml | 1 + 5 files changed, 8 insertions(+) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 683568e255ef..425baa37eb15 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -45,6 +45,7 @@ jobs: id: setupGitForOSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} diff --git a/.github/workflows/createNewVersion.yml b/.github/workflows/createNewVersion.yml index 6245af07a121..6c5a18bf4425 100644 --- a/.github/workflows/createNewVersion.yml +++ b/.github/workflows/createNewVersion.yml @@ -70,6 +70,8 @@ jobs: - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotify id: setupGitForOSBotify + with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} - name: Generate new E/App version id: bumpVersion diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 65fc2f2fbe9b..4b4ea2413ae5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,6 +45,7 @@ jobs: uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} diff --git a/.github/workflows/finishReleaseCycle.yml b/.github/workflows/finishReleaseCycle.yml index 7a6690c27456..ca030e95de1d 100644 --- a/.github/workflows/finishReleaseCycle.yml +++ b/.github/workflows/finishReleaseCycle.yml @@ -22,6 +22,7 @@ jobs: uses: ./.github/actions/composite/setupGitForOSBotifyApp id: setupGitForOSBotify with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} @@ -86,6 +87,7 @@ jobs: id: setupGitForOSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} @@ -126,6 +128,7 @@ jobs: - name: Setup git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index f8723f55866c..10ca10882464 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -104,6 +104,7 @@ jobs: - name: Setup Git for OSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp with: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} From ae548a75024f100dc25ab61d9f70193242369317 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 16:36:56 -0800 Subject: [PATCH 30/55] Add secret to fix lint --- .github/workflows/createNewVersion.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/createNewVersion.yml b/.github/workflows/createNewVersion.yml index 6c5a18bf4425..a933c2f1686f 100644 --- a/.github/workflows/createNewVersion.yml +++ b/.github/workflows/createNewVersion.yml @@ -29,6 +29,9 @@ on: OS_BOTIFY_COMMIT_TOKEN: description: OSBotify personal access token, used to workaround committing to protected branch required: true + OP_SERVICE_ACCOUNT_TOKEN: + description: 1Password service account token + required: true jobs: validateActor: From 6fb4402b5616303a1ad78f3daf308463470bb39c Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 16:53:04 -0800 Subject: [PATCH 31/55] Fix path for gpg key for OSBotify --- .github/actions/composite/setupGitForOSBotify/action.yml | 2 +- .../actions/composite/setupGitForOSBotifyApp/action.yml | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/actions/composite/setupGitForOSBotify/action.yml b/.github/actions/composite/setupGitForOSBotify/action.yml index 0b212f7b40d7..9495ba07b0ac 100644 --- a/.github/actions/composite/setupGitForOSBotify/action.yml +++ b/.github/actions/composite/setupGitForOSBotify/action.yml @@ -20,7 +20,7 @@ runs: - name: Import OSBotify GPG Key shell: bash - run: cd .github/workflows && gpg --import OSBotify-private-key.asc + run: gpg --import OSBotify-private-key.asc - name: Set up git for OSBotify shell: bash diff --git a/.github/actions/composite/setupGitForOSBotifyApp/action.yml b/.github/actions/composite/setupGitForOSBotifyApp/action.yml index d8e5e8e1e18f..45d85663bfa6 100644 --- a/.github/actions/composite/setupGitForOSBotifyApp/action.yml +++ b/.github/actions/composite/setupGitForOSBotifyApp/action.yml @@ -50,7 +50,7 @@ runs: - name: Import OSBotify GPG Key shell: bash - run: cd .github/workflows && gpg --import OSBotify-private-key.asc + run: gpg --import OSBotify-private-key.asc - name: Set up git for OSBotify shell: bash @@ -60,11 +60,6 @@ runs: git config user.name OSBotify git config user.email infra+osbotify@expensify.com - - name: Enable debug logs for git - shell: bash - if: runner.debug == '1' - run: echo "GIT_TRACE=true" >> "$GITHUB_ENV" - - name: Sync clock shell: bash run: sudo sntp -sS time.windows.com From 4e07d44a255a59b5d5e8c4b4ad0945c149527358 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 00:58:47 +0000 Subject: [PATCH 32/55] Update version to 9.0.94-11 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 928d6d648d7e..66e3bec9e4e1 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009410 - versionName "9.0.94-10" + versionCode 1009009411 + versionName "9.0.94-11" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 45abb8c07c76..7448d93bd58c 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.10 + 9.0.94.11 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 72dd59cee48d..2817bfa29808 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.10 + 9.0.94.11 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 613b3a038aa3..cf47b6a6284e 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.10 + 9.0.94.11 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index f2df00cbb83b..8968cf04cb8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-10", + "version": "9.0.94-11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-10", + "version": "9.0.94-11", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 9892aba77bd7..f15715195c0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-10", + "version": "9.0.94-11", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From f25555c64a9d1d8ee121155465b646a1eaa70455 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 00:58:47 +0000 Subject: [PATCH 33/55] Update Mobile-Expensify submodule version to 9.0.94-11 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 9e6ead35b763..b8bcc6f027b7 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 9e6ead35b76303685fa83ac22cad83d0955ce3d3 +Subproject commit b8bcc6f027b7a9ebbd57dc9db1e8ba7d2aa31716 From eee408672d936b3864f9eb788869e285f1076aef Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 17:15:46 -0800 Subject: [PATCH 34/55] Tweak which branch we pull for set up git for OSBotify App action --- .github/workflows/cherryPick.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 425baa37eb15..6bb55b7bea1c 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -43,7 +43,7 @@ jobs: - name: Set up git for OSBotify id: setupGitForOSBotify - uses: ./.github/actions/composite/setupGitForOSBotifyApp + uses: ./.github/actions/composite/setupGitForOSBotifyApp@main with: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} From c780f4709eb5ffab5cb6741f17de8c5bd14176d8 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:21:04 +0000 Subject: [PATCH 35/55] Update version to 9.0.94-12 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 66e3bec9e4e1..1546bcdb47b5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009411 - versionName "9.0.94-11" + versionCode 1009009412 + versionName "9.0.94-12" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 7448d93bd58c..2b9dfc39555c 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.11 + 9.0.94.12 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 2817bfa29808..1b3a74c0e2ba 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.11 + 9.0.94.12 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index cf47b6a6284e..81ff15f3d6ae 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.11 + 9.0.94.12 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 8968cf04cb8e..2ad0ad02d64a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-11", + "version": "9.0.94-12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-11", + "version": "9.0.94-12", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index f15715195c0d..8f4956e7f267 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-11", + "version": "9.0.94-12", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From b2323104861467ef468bc2309ddaee75d0221022 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:21:04 +0000 Subject: [PATCH 36/55] Update Mobile-Expensify submodule version to 9.0.94-12 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index b8bcc6f027b7..aaccdc4e15a4 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit b8bcc6f027b7a9ebbd57dc9db1e8ba7d2aa31716 +Subproject commit aaccdc4e15a41123bc7162b9ca61e9d2a6867f28 From b572b592ac25c19563da3157c306549ff5e64423 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 17:23:01 -0800 Subject: [PATCH 37/55] Run a git fetch in order to fix setupGitForOSBotify --- .github/workflows/cherryPick.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 6bb55b7bea1c..875b5c2e559a 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -41,6 +41,9 @@ jobs: token: ${{ secrets.OS_BOTIFY_TOKEN }} submodules: true + - name: Run git fetch + run: git fetch + - name: Set up git for OSBotify id: setupGitForOSBotify uses: ./.github/actions/composite/setupGitForOSBotifyApp@main From 70082f65cef83da6795a11b5a57aa88a8c66f19c Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:30:12 +0000 Subject: [PATCH 38/55] Update version to 9.0.94-13 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 1546bcdb47b5..6a3045514faf 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009412 - versionName "9.0.94-12" + versionCode 1009009413 + versionName "9.0.94-13" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 2b9dfc39555c..5a72554f4c84 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.12 + 9.0.94.13 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 1b3a74c0e2ba..6c1c5fb659f6 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.12 + 9.0.94.13 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 81ff15f3d6ae..f082ebb95cdf 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.12 + 9.0.94.13 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 2ad0ad02d64a..b1f01488868d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-12", + "version": "9.0.94-13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-12", + "version": "9.0.94-13", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 8f4956e7f267..0757eac96c08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-12", + "version": "9.0.94-13", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 67c8915302e1c68a40f0c0b574c8bf6e7dac53d0 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:30:12 +0000 Subject: [PATCH 39/55] Update Mobile-Expensify submodule version to 9.0.94-13 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index aaccdc4e15a4..9d723f8dfde0 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit aaccdc4e15a41123bc7162b9ca61e9d2a6867f28 +Subproject commit 9d723f8dfde03733f4530892daa08410012c5c4f From 945fbe2c10a92bee34f18dcfa42000d192328406 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 17:39:34 -0800 Subject: [PATCH 40/55] Only fetch the main branch --- .github/workflows/cherryPick.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 875b5c2e559a..3f80963f34a8 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -42,7 +42,7 @@ jobs: submodules: true - name: Run git fetch - run: git fetch + run: git fetch origin main --fetch-depth=1 - name: Set up git for OSBotify id: setupGitForOSBotify From d66055c13793012c42dbeb86a61d009925d33172 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:47:58 +0000 Subject: [PATCH 41/55] Update version to 9.0.94-14 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 6a3045514faf..c762416a1ca8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009413 - versionName "9.0.94-13" + versionCode 1009009414 + versionName "9.0.94-14" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 5a72554f4c84..86a66c117e48 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.13 + 9.0.94.14 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 6c1c5fb659f6..bfccaa613f2f 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.13 + 9.0.94.14 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index f082ebb95cdf..0dc358d28619 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.13 + 9.0.94.14 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index b1f01488868d..219aa517fa50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-13", + "version": "9.0.94-14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-13", + "version": "9.0.94-14", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 0757eac96c08..fbae14c6046f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-13", + "version": "9.0.94-14", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 596e37364c5a5c9c8b1c53ef78e95b1aa96766ef Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:47:58 +0000 Subject: [PATCH 42/55] Update Mobile-Expensify submodule version to 9.0.94-14 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 9d723f8dfde0..65db5a2c4de6 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 9d723f8dfde03733f4530892daa08410012c5c4f +Subproject commit 65db5a2c4de6361ed9d23029d5e8b72bdacbd7a4 From 439ac01f8829f7241b6524698304c441960ed891 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 17:49:00 -0800 Subject: [PATCH 43/55] Change to depth flag --- .github/workflows/cherryPick.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 3f80963f34a8..32d6006d82ff 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -42,7 +42,7 @@ jobs: submodules: true - name: Run git fetch - run: git fetch origin main --fetch-depth=1 + run: git fetch origin main --depth=1 - name: Set up git for OSBotify id: setupGitForOSBotify From b08cdaea202353042ab480cb463252c07f079e2d Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:53:42 +0000 Subject: [PATCH 44/55] Update version to 9.0.94-15 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index c762416a1ca8..568b3d83d31e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009414 - versionName "9.0.94-14" + versionCode 1009009415 + versionName "9.0.94-15" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 86a66c117e48..cbcd52c120ab 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.14 + 9.0.94.15 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index bfccaa613f2f..f92abc1c9ade 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.14 + 9.0.94.15 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 0dc358d28619..ba17b9a78a8c 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.14 + 9.0.94.15 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 219aa517fa50..a85d77bdb1a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-14", + "version": "9.0.94-15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-14", + "version": "9.0.94-15", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index fbae14c6046f..181223e1f077 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-14", + "version": "9.0.94-15", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 18ad58740e6ab6320b3ec2fa40dbd66fe42b6cd2 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 01:53:42 +0000 Subject: [PATCH 45/55] Update Mobile-Expensify submodule version to 9.0.94-15 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 65db5a2c4de6..649cbeeebcfa 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 65db5a2c4de6361ed9d23029d5e8b72bdacbd7a4 +Subproject commit 649cbeeebcfabc03f9a604582e8c4fe91aa120b9 From db6928638b90df146145d302bd499bbfdb073f56 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 17:59:22 -0800 Subject: [PATCH 46/55] Add owner and repo to composite action --- .github/workflows/cherryPick.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 32d6006d82ff..67bf80bae9c7 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -46,7 +46,7 @@ jobs: - name: Set up git for OSBotify id: setupGitForOSBotify - uses: ./.github/actions/composite/setupGitForOSBotifyApp@main + uses: Expensify/App/.github/actions/composite/setupGitForOSBotifyApp@main with: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} From d9ba4e54023250e8fb3470a418c8a23d4d083804 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:06:47 +0000 Subject: [PATCH 47/55] Update version to 9.0.94-16 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 568b3d83d31e..a589fdabd58a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009415 - versionName "9.0.94-15" + versionCode 1009009416 + versionName "9.0.94-16" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index cbcd52c120ab..6da3b563f906 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.15 + 9.0.94.16 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index f92abc1c9ade..6baba1bffcaa 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.15 + 9.0.94.16 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index ba17b9a78a8c..1e6ac2146eb7 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.15 + 9.0.94.16 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index a85d77bdb1a4..f38c83746457 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-15", + "version": "9.0.94-16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-15", + "version": "9.0.94-16", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 181223e1f077..e048ce2ba707 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-15", + "version": "9.0.94-16", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 4425c814307364df1b30c1f390ce33b50709ec62 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:06:47 +0000 Subject: [PATCH 48/55] Update Mobile-Expensify submodule version to 9.0.94-16 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 649cbeeebcfa..6a4777e58822 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 649cbeeebcfabc03f9a604582e8c4fe91aa120b9 +Subproject commit 6a4777e588228cea0fc162d2761b7b7c4216e186 From f093befe3786d06f453dc766d0487da58656a6ab Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:23:45 +0000 Subject: [PATCH 49/55] Update version to 9.0.94-17 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index a589fdabd58a..9b4a06132ca5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009416 - versionName "9.0.94-16" + versionCode 1009009417 + versionName "9.0.94-17" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 6da3b563f906..b5756ca6aa93 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.16 + 9.0.94.17 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 6baba1bffcaa..0af077c23fc4 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.16 + 9.0.94.17 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 1e6ac2146eb7..a0f3ab71f46a 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.16 + 9.0.94.17 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index f38c83746457..1b28cec56e55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-16", + "version": "9.0.94-17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-16", + "version": "9.0.94-17", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index e048ce2ba707..fb58022b3f6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-16", + "version": "9.0.94-17", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 36278b2c16cd37fe2c1668723413efe3ad666f98 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:23:45 +0000 Subject: [PATCH 50/55] Update Mobile-Expensify submodule version to 9.0.94-17 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 6a4777e58822..54a8c7d6a20b 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 6a4777e588228cea0fc162d2761b7b7c4216e186 +Subproject commit 54a8c7d6a20b9ec5831fb2ab06e3646eaaa5e843 From 795e3af40962f4763b98bebaaecb94f67876474f Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:26:17 +0000 Subject: [PATCH 51/55] Update version to 9.0.94-18 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 9b4a06132ca5..7409aa2a2941 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009417 - versionName "9.0.94-17" + versionCode 1009009418 + versionName "9.0.94-18" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b5756ca6aa93..02ae024cbe6d 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.17 + 9.0.94.18 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 0af077c23fc4..9f5458d69021 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.17 + 9.0.94.18 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index a0f3ab71f46a..bb1bcae53c87 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.17 + 9.0.94.18 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 1b28cec56e55..aec3936d3e8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-17", + "version": "9.0.94-18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-17", + "version": "9.0.94-18", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index fb58022b3f6c..c2b1ae80d3b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-17", + "version": "9.0.94-18", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 63adfcf9ef1227fb31006ff6ae1ee90ca1abd664 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:26:17 +0000 Subject: [PATCH 52/55] Update Mobile-Expensify submodule version to 9.0.94-18 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 54a8c7d6a20b..8aab8cd656da 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 54a8c7d6a20b9ec5831fb2ab06e3646eaaa5e843 +Subproject commit 8aab8cd656da1f4914d3b51921b73644f57068f3 From a49c5df4b0b9d76fcd51f3c4524b743128248f54 Mon Sep 17 00:00:00 2001 From: Andrew Gable Date: Wed, 5 Feb 2025 18:36:27 -0800 Subject: [PATCH 53/55] Remove extra git fetch --- .github/workflows/cherryPick.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 67bf80bae9c7..a4ec14ff6825 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -41,9 +41,6 @@ jobs: token: ${{ secrets.OS_BOTIFY_TOKEN }} submodules: true - - name: Run git fetch - run: git fetch origin main --depth=1 - - name: Set up git for OSBotify id: setupGitForOSBotify uses: Expensify/App/.github/actions/composite/setupGitForOSBotifyApp@main From 91a52b44c20214c996779bb6495bb0aeedde457c Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:45:42 +0000 Subject: [PATCH 54/55] Update version to 9.0.94-19 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7409aa2a2941..156718f4c3c2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009009418 - versionName "9.0.94-18" + versionCode 1009009419 + versionName "9.0.94-19" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 02ae024cbe6d..2043ee4a2cb6 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.0.94.18 + 9.0.94.19 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 9f5458d69021..6c71db15b8f1 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.94.18 + 9.0.94.19 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index bb1bcae53c87..73074d2a200e 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.94 CFBundleVersion - 9.0.94.18 + 9.0.94.19 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index aec3936d3e8a..30002a164a28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.94-18", + "version": "9.0.94-19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.94-18", + "version": "9.0.94-19", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c2b1ae80d3b3..42e75636878a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.94-18", + "version": "9.0.94-19", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From a8daefb0570311171c7b5a25f90615e12cb8f3a9 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 6 Feb 2025 02:45:42 +0000 Subject: [PATCH 55/55] Update Mobile-Expensify submodule version to 9.0.94-19 --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 8aab8cd656da..1feafc32db9c 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 8aab8cd656da1f4914d3b51921b73644f57068f3 +Subproject commit 1feafc32db9c2596b02598228a56be57fd8d39d6