diff --git a/.detoxrc.js b/.detoxrc.js index 93b489e79..836f6866d 100644 --- a/.detoxrc.js +++ b/.detoxrc.js @@ -11,12 +11,12 @@ module.exports = { $0: "jest", args: { config: "e2e/jest.config.js", - _: ["e2e"] + _: ["e2e"], }, jest: { setupTimeout: 900000, - teardownTimeout: 900000 - } + teardownTimeout: 900000, + }, }, apps: { "ios.debug": { @@ -25,7 +25,7 @@ module.exports = { "ios/build/Build/Products/Debug-iphonesimulator/iNaturalistReactNative.app", build: /* eslint-disable-next-line max-len */ - "xcodebuild -workspace ios/iNaturalistReactNative.xcworkspace -scheme iNaturalistReactNative -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build" + "xcodebuild -workspace ios/iNaturalistReactNative.xcworkspace -scheme iNaturalistReactNative -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build", }, "ios.release": { type: "ios.app", @@ -33,7 +33,7 @@ module.exports = { "ios/build/Build/Products/Release-iphonesimulator/iNaturalistReactNative.app", build: /* eslint-disable-next-line max-len */ - "xcodebuild -workspace ios/iNaturalistReactNative.xcworkspace -scheme iNaturalistReactNative -configuration Release -sdk iphonesimulator -derivedDataPath ios/build" + "xcodebuild -workspace ios/iNaturalistReactNative.xcworkspace -scheme iNaturalistReactNative -configuration Release -sdk iphonesimulator -derivedDataPath ios/build", }, "android.debug": { type: "android.apk", @@ -41,7 +41,7 @@ module.exports = { /* eslint-disable-next-line max-len */ testBinaryPath: `android/app/build/outputs/apk/androidTest/debug/${apkFilenamePrefix}-debug-androidTest.apk`, build: - "(cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug)" + "(cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug)", }, "android.release": { type: "android.apk", @@ -49,40 +49,40 @@ module.exports = { /* eslint-disable-next-line max-len */ testBinaryPath: `android/app/build/outputs/apk/androidTest/release/${apkFilenamePrefix}-release-androidTest.apk`, build: - "(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)" - } + "(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)", + }, }, devices: { simulator: { type: "ios.simulator", device: { type: "iPhone 16 Pro", - os: "iOS 18.6" - } + os: "iOS 18.6", + }, }, emulator: { type: "android.emulator", device: { - avdName: "Pixel_5_API_31_AOSP" - } - } + avdName: "Pixel_5_API_31_AOSP", + }, + }, }, configurations: { "ios.debug": { device: "simulator", - app: "ios.debug" + app: "ios.debug", }, "ios.release": { device: "simulator", - app: "ios.release" + app: "ios.release", }, "android.debug": { device: "emulator", - app: "android.debug" + app: "android.debug", }, "android.release": { device: "emulator", - app: "android.release" - } - } + app: "android.release", + }, + }, }; diff --git a/.eslintrc.js b/.eslintrc.js index 8438b20d3..dec3cef40 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,15 +4,15 @@ module.exports = { parserOptions: { requireConfigFile: false, babelOptions: { - presets: ["@babel/preset-react"] - } + presets: ["@babel/preset-react"], + }, }, extends: [ "airbnb", "plugin:i18next/recommended", "plugin:@tanstack/eslint-plugin-query/recommended", "plugin:react-native-a11y/ios", - "plugin:@typescript-eslint/recommended" + "plugin:@typescript-eslint/recommended", ], plugins: [ "module-resolver", @@ -21,11 +21,13 @@ module.exports = { "simple-import-sort", "@tanstack/query", "@typescript-eslint", - "@stylistic" + "@stylistic", ], rules: { "arrow-parens": [2, "as-needed"], - "comma-dangle": [2, "never"], + // enforces trailing comma in objects / arrays except inline: no [1,2,3,] + // functionally, this improves git deltas when the last items of {}/[] are changed + "comma-dangle": ["error", "always-multiline"], "consistent-return": [2, { treatUndefinedAsUnspecified: true }], "func-names": 0, "global-require": 0, @@ -34,9 +36,9 @@ module.exports = { { words: { // Minor change to the default to disallow all-caps string literals as well - exclude: ["[0-9!-/:-@[-`{-~]+"] - } - } + exclude: ["[0-9!-/:-@[-`{-~]+"], + }, + }, ], // The AirBNB approach at // https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/imports.js#L71 @@ -54,7 +56,7 @@ module.exports = { jsx: "never", json: "always", ts: "never", - tsx: "never" + tsx: "never", }], indent: ["error", 2, { SwitchCase: 1 }], "max-len": [ @@ -66,8 +68,8 @@ module.exports = { ignoreComments: false, ignoreRegExpLiterals: true, ignoreStrings: false, - ignoreTemplateLiterals: false - } + ignoreTemplateLiterals: false, + }, ], "no-alert": 0, "no-underscore-dangle": 0, @@ -92,7 +94,7 @@ module.exports = { "react/jsx-filename-extension": 0, "react/function-component-definition": [ 2, - { namedComponents: "arrow-function" } + { namedComponents: "arrow-function" }, ], "react/require-default-props": 0, @@ -127,6 +129,9 @@ module.exports = { // https://eslint.org/docs/latest/rules/no-undef#handled_by_typescript "no-undef": "error", + "@typescript-eslint/array-type": ["error", { + default: "array", + }], "@typescript-eslint/no-unused-vars": [ "error", { @@ -138,18 +143,18 @@ module.exports = { ignoreRestSiblings: true, caughtErrors: "all", // needed a special case for catch blocks that use _ to define an unused error - caughtErrorsIgnorePattern: "^_" - } + caughtErrorsIgnorePattern: "^_", + }, ], "@typescript-eslint/no-require-imports": ["error", { - allow: ["\\.(png|jpg|jpeg|gif|svg)$"] + allow: ["\\.(png|jpg|jpeg|gif|svg)$"], }], "@typescript-eslint/no-unsafe-function-type": 1, "@typescript-eslint/consistent-type-imports": ["error", { - fixStyle: "separate-type-imports" + fixStyle: "separate-type-imports", }], "import/consistent-type-specifier-style": ["error", "prefer-top-level"], - "@stylistic/member-delimiter-style": "error" + "@stylistic/member-delimiter-style": "error", }, ignorePatterns: ["!.detoxrc.js", "/coverage/*", "/vendor/*", "**/flow-typed"], settings: { @@ -157,9 +162,9 @@ module.exports = { "babel-module": { allowExistingDirectories: true }, node: { extensions: [".js", ".jsx", ".ts", ".tsx"], - moduleDirectory: ["node_modules", "src"] - } - } + moduleDirectory: ["node_modules", "src"], + }, + }, }, overrides: [ { @@ -170,29 +175,29 @@ module.exports = { "@typescript-eslint/no-require-imports": "off", "@typescript-eslint/consistent-type-imports": "off", "import/consistent-type-specifier-style": "off", - "@stylistic/member-delimiter-style": "off" - } + "@stylistic/member-delimiter-style": "off", + }, }, { files: ["*.test.js", "*.test.tsx"], rules: { - "react/jsx-props-no-spreading": "off" - } + "react/jsx-props-no-spreading": "off", + }, }, { files: ["**/__mocks__/**/*", "**/*mock*", "**/*.mock.*"], rules: { - "@typescript-eslint/no-require-imports": "off" - } + "@typescript-eslint/no-require-imports": "off", + }, }, { files: ["tests/**/*", "__mocks__/**/*", "e2e/**/*"], - env: { jest: true } + env: { jest: true }, }, { files: ["tests/**/*"], plugins: ["testing-library"], - extends: ["plugin:testing-library/react"] - } - ] + extends: ["plugin:testing-library/react"], + }, + ], }; diff --git a/__mocks__/@bam.tech/react-native-image-resizer.ts b/__mocks__/@bam.tech/react-native-image-resizer.ts index 62098434e..fee477387 100644 --- a/__mocks__/@bam.tech/react-native-image-resizer.ts +++ b/__mocks__/@bam.tech/react-native-image-resizer.ts @@ -9,10 +9,10 @@ export default ( { _compressFormat, _quality, _rotation, - outputPath + outputPath, ) => { const filename = mockNodePath.basename( path ); return { uri: mockNodePath.join( outputPath, filename ) }; - } - ) + }, + ), } ); diff --git a/__mocks__/@react-native-camera-roll/camera-roll.ts b/__mocks__/@react-native-camera-roll/camera-roll.ts index 51e689bda..ac9b60f81 100644 --- a/__mocks__/@react-native-camera-roll/camera-roll.ts +++ b/__mocks__/@react-native-camera-roll/camera-roll.ts @@ -6,7 +6,7 @@ export const CameraRoll = { resolve( { page_info: { end_cursor: jest.fn( ), - has_next_page: false + has_next_page: false, }, edges: [ { @@ -20,16 +20,16 @@ export const CameraRoll = { width: 1080, fileSize: 123456, playableDuration: NaN, - orientation: 1 - } - } - } - ] + orientation: 1, + }, + }, + }, + ], } ); } ) ), getAlbums: jest.fn( ( ) => ( { // Expecting album titles as keys and photo counts as values // "My Amazing album": 12 } ) ), - save: jest.fn( ( _uri, _options = {} ) => mockFaker.system.filePath( ) ) + save: jest.fn( ( _uri, _options = {} ) => mockFaker.system.filePath( ) ), }; diff --git a/__mocks__/@react-native-community/geolocation.ts b/__mocks__/@react-native-community/geolocation.ts index 13795f0e9..c4cbadc0d 100644 --- a/__mocks__/@react-native-community/geolocation.ts +++ b/__mocks__/@react-native-community/geolocation.ts @@ -3,6 +3,6 @@ export default ( { watchPosition: jest.fn( ( ) => 0 ), clearWatch: jest.fn( ), setRNConfiguration: jest.fn( ( ) => ( { - skipPermissionRequests: true - } ) ) + skipPermissionRequests: true, + } ) ), } ); diff --git a/__mocks__/@react-navigation/native.ts b/__mocks__/@react-navigation/native.ts index e415a78eb..fe20af787 100644 --- a/__mocks__/@react-navigation/native.ts +++ b/__mocks__/@react-navigation/native.ts @@ -13,11 +13,11 @@ const useNavigation = ( ) => ( { addListener: jest.fn( ), canGoBack: jest.fn( ( ) => true ), goBack: jest.fn( ), - setOptions: jest.fn( ) + setOptions: jest.fn( ), } ); module.exports = { ...actualNav, useNavigation, - useRoute + useRoute, }; diff --git a/__mocks__/react-native-config.ts b/__mocks__/react-native-config.ts index 350d7f9c6..a4010b2e8 100644 --- a/__mocks__/react-native-config.ts +++ b/__mocks__/react-native-config.ts @@ -2,5 +2,5 @@ export default ( { OAUTH_CLIENT_ID: process.env.OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET: process.env.OAUTH_CLIENT_SECRET, JWT_ANONYMOUS_API_SECRET: process.env.JWT_ANONYMOUS_API_SECRET, - API_URL: process.env.API_URL + API_URL: process.env.API_URL, } ); diff --git a/__mocks__/react-native-fs.ts b/__mocks__/react-native-fs.ts index 8a22ccf90..193c5be77 100644 --- a/__mocks__/react-native-fs.ts +++ b/__mocks__/react-native-fs.ts @@ -9,15 +9,15 @@ module.exports = { copyFile: async ( ) => "testdata", copyAssetsFileIOS: async ( ) => "testdata", stat: jest.fn( ( ) => ( { - mtime: new Date() + mtime: new Date(), } ) ), readFile: jest.fn( ( ) => "testdata" ), readDir: jest.fn( async ( ) => ( [ { ctime: new Date(), mtime: new Date(), - name: "testdata" - } + name: "testdata", + }, ] ) ), writeFile: jest.fn( async ( filePath, contents, _encoding ) => { mockFs.writeFile( filePath, contents, jest.fn( ) ); @@ -29,5 +29,5 @@ module.exports = { if ( !path ) return; if ( typeof ( path ) !== "string" ) return; mockFs.unlink( path, jest.fn( ) ); - } ) + } ), }; diff --git a/__mocks__/react-native-geocoder-reborn.ts b/__mocks__/react-native-geocoder-reborn.ts index 1b1d9417a..97c7bd491 100644 --- a/__mocks__/react-native-geocoder-reborn.ts +++ b/__mocks__/react-native-geocoder-reborn.ts @@ -3,6 +3,6 @@ export default ( { `Somewhere near ${coord.lat}, ${coord.lng}`, "Somewhere", "Somewheria", - "SW" - ] ) + "SW", + ] ), } ); diff --git a/__mocks__/react-native-keyboard-aware-scroll-view.ts b/__mocks__/react-native-keyboard-aware-scroll-view.ts index b1a0c8aa0..a8b74420d 100644 --- a/__mocks__/react-native-keyboard-aware-scroll-view.ts +++ b/__mocks__/react-native-keyboard-aware-scroll-view.ts @@ -3,5 +3,5 @@ module.exports = { KeyboardAwareScrollView: jest .fn( ) - .mockImplementation( ( { children } ) => children ) + .mockImplementation( ( { children } ) => children ), }; diff --git a/__mocks__/react-native-orientation-locker.ts b/__mocks__/react-native-orientation-locker.ts index 1059f47bc..8b8e3659a 100644 --- a/__mocks__/react-native-orientation-locker.ts +++ b/__mocks__/react-native-orientation-locker.ts @@ -2,5 +2,5 @@ export const useDeviceOrientationChange = jest.fn(); export default ( { lockToPortrait: jest.fn( ), - unlockAllOrientations: jest.fn( ) + unlockAllOrientations: jest.fn( ), } ); diff --git a/__mocks__/react-native-paper.ts b/__mocks__/react-native-paper.ts index 1d72593ba..1a95b441b 100644 --- a/__mocks__/react-native-paper.ts +++ b/__mocks__/react-native-paper.ts @@ -1,5 +1,5 @@ const actualPaper = jest.requireActual( "react-native-paper" ); module.exports = { ...actualPaper, - Portal: ( { children } ) => children + Portal: ( { children } ) => children, }; diff --git a/__mocks__/react-native-sensitive-info.ts b/__mocks__/react-native-sensitive-info.ts index 836834689..e232f5782 100644 --- a/__mocks__/react-native-sensitive-info.ts +++ b/__mocks__/react-native-sensitive-info.ts @@ -54,7 +54,7 @@ class RNSInfo { if ( service?.size ) { mappedValues = Array.from( service.entries() ).map( - ( [key, value] ) => ( { key, value, service: serviceName } ) + ( [key, value] ) => ( { key, value, service: serviceName } ), ); } diff --git a/__mocks__/react-native-share-menu.ts b/__mocks__/react-native-share-menu.ts index a7b5dc497..8a53ac48c 100644 --- a/__mocks__/react-native-share-menu.ts +++ b/__mocks__/react-native-share-menu.ts @@ -25,7 +25,7 @@ const ShareMenu = { __reset: ( ) => { mockShareData = null; mockListeners = []; - } + }, }; export default ShareMenu; diff --git a/__mocks__/react-native-vision-camera.ts b/__mocks__/react-native-vision-camera.ts index f46d77e3d..63e63800f 100644 --- a/__mocks__/react-native-vision-camera.ts +++ b/__mocks__/react-native-vision-camera.ts @@ -3,7 +3,7 @@ import { mockSortDevices, mockUseCameraDevice, mockUseCameraDevices, - mockUseCameraFormat + mockUseCameraFormat, } from "tests/vision-camera/vision-camera"; export const Camera = mockCamera; @@ -12,6 +12,6 @@ export const useCameraDevice = mockUseCameraDevice; export const useCameraDevices = mockUseCameraDevices; export const useCameraFormat = mockUseCameraFormat; export const VisionCameraProxy = { - initFrameProcessorPlugin: jest.fn( ) + initFrameProcessorPlugin: jest.fn( ), }; export const useFrameProcessor = jest.fn( ); diff --git a/__mocks__/react-native-worklets-core.ts b/__mocks__/react-native-worklets-core.ts index 10493dbb0..0ca148216 100644 --- a/__mocks__/react-native-worklets-core.ts +++ b/__mocks__/react-native-worklets-core.ts @@ -2,6 +2,6 @@ export const useSharedValue = jest.fn(); export const Worklets = { createRunOnJS: jest.fn(), defaultContext: { - createRunAsync: jest.fn() - } + createRunAsync: jest.fn(), + }, }; diff --git a/__mocks__/vision-camera-plugin-inatvision.ts b/__mocks__/vision-camera-plugin-inatvision.ts index 984712292..4cfdf27c7 100644 --- a/__mocks__/vision-camera-plugin-inatvision.ts +++ b/__mocks__/vision-camera-plugin-inatvision.ts @@ -1,21 +1,21 @@ export const getPredictionsForImage = jest.fn( () => Promise.resolve( { predictions: [], - commonAncestor: undefined + commonAncestor: undefined, } ) ); export const getPredictionsForLocation = jest.fn( () => Promise.resolve( { predictions: [] } ) ); export const removeLogListener = jest.fn( ); export const resetStoredResults = jest.fn( ); export const getCellLocation = jest.fn( location => ( { ...location, - elevation: 12 + elevation: 12, } ) ); export const MODE = { BEST_BRANCH: "BEST_BRANCH", - COMMON_ANCESTOR: "COMMON_ANCESTOR" + COMMON_ANCESTOR: "COMMON_ANCESTOR", }; export const COMMON_ANCESTOR_RANK_TYPE = { MAJOR: "major", - UNRESTRICTED: "unrestricted" + UNRESTRICTED: "unrestricted", }; diff --git a/babel.config.js b/babel.config.js index 9a031e609..3b3ea7c68 100644 --- a/babel.config.js +++ b/babel.config.js @@ -23,20 +23,20 @@ module.exports = { stores: "./src/stores", styles: "./src/styles", tests: "./tests", - uploaders: "./src/uploaders" - } + uploaders: "./src/uploaders", + }, }], // Reanimated plugin has to be listed last https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation/ [ "react-native-reanimated/plugin", { - processNestedWorklets: true - } - ] + processNestedWorklets: true, + }, + ], ], env: { production: { - plugins: ["react-native-paper/babel", "transform-remove-console"] - } - } + plugins: ["react-native-paper/babel", "transform-remove-console"], + }, + }, }; diff --git a/e2e/aiCamera.e2e.js b/e2e/aiCamera.e2e.js index cb4173b3d..ee7bb4d83 100644 --- a/e2e/aiCamera.e2e.js +++ b/e2e/aiCamera.e2e.js @@ -1,5 +1,5 @@ import { - by, device, element, waitFor + by, device, element, waitFor, } from "detox"; import { iNatE2eAfterEach, iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers"; @@ -46,7 +46,7 @@ describe( "AICamera", () => { const otherSuggestionsTitle = element( by.text( "OTHER SUGGESTIONS" ) ); await waitFor( otherSuggestionsTitle ).toBeVisible( ).withTimeout( 30_000 ); const firstSuggestion = element( by.id( /SuggestionsList\.taxa\..*/ ) ).atIndex( - 0 + 0, ); await waitFor( firstSuggestion ).toBeVisible().withTimeout( TIMEOUT ); const suggestionAttributes = await firstSuggestion.getAttributes(); @@ -64,9 +64,9 @@ describe( "AICamera", () => { // Check that the display taxon name is visible const displayTaxonName = element( by.id( `display-taxon-name.${taxonID}` ) ).atIndex( - 0 + 0, ); await waitFor( displayTaxonName ).toBeVisible().withTimeout( TIMEOUT ); - } + }, ); } ); diff --git a/e2e/helpers.js b/e2e/helpers.js index 439ddc15c..a5490fb9b 100644 --- a/e2e/helpers.js +++ b/e2e/helpers.js @@ -12,8 +12,8 @@ export async function iNatE2eBeforeAll( device ) { location: "always", camera: "YES", medialibrary: "YES", - photos: "YES" - } + photos: "YES", + }, } ); } } @@ -31,8 +31,8 @@ export async function iNatE2eBeforeEach( device ) { location: "always", camera: "YES", medialibrary: "YES", - photos: "YES" - } + photos: "YES", + }, }; try { await device.launchApp( launchAppOptions ); @@ -46,15 +46,15 @@ export async function iNatE2eBeforeEach( device ) { // disable password autofill execSync( // eslint-disable-next-line max-len - `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist` + `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist`, ); execSync( // eslint-disable-next-line max-len - `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist` + `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist`, ); execSync( // eslint-disable-next-line max-len - `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist` + `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist`, ); } @@ -131,7 +131,7 @@ export async function iNatE2eAfterEach( device ) { } catch ( detoxError ) { console.log( "Detox terminateApp failed, falling back to manual termination:", - detoxError.message + detoxError.message, ); } } diff --git a/e2e/jest.config.js b/e2e/jest.config.js index 7847e330e..461432e47 100644 --- a/e2e/jest.config.js +++ b/e2e/jest.config.js @@ -7,5 +7,5 @@ module.exports = { reporters: ["detox/runners/jest/reporter"], globalSetup: "detox/runners/jest/globalSetup", globalTeardown: "detox/runners/jest/globalTeardown", - testEnvironment: "detox/runners/jest/testEnvironment" + testEnvironment: "detox/runners/jest/testEnvironment", }; diff --git a/e2e/sharedFlows/closeOnboarding.js b/e2e/sharedFlows/closeOnboarding.js index 7cd8aa171..b556b4ebd 100644 --- a/e2e/sharedFlows/closeOnboarding.js +++ b/e2e/sharedFlows/closeOnboarding.js @@ -1,7 +1,7 @@ import { by, element, - waitFor + waitFor, } from "detox"; const VISIBILITY_TIMEOUT = 10_000; diff --git a/e2e/sharedFlows/resetUserForTesting.js b/e2e/sharedFlows/resetUserForTesting.js index 659e8171e..09fb553b1 100644 --- a/e2e/sharedFlows/resetUserForTesting.js +++ b/e2e/sharedFlows/resetUserForTesting.js @@ -7,7 +7,7 @@ import { CHUCKS_PAD as sampleObservation } from "../../src/appConstants/e2e"; const apiHost = Config.OAUTH_API_URL; const testUsernameAllowlist = [ - "inaturalist-test" + "inaturalist-test", ]; const userAgent = "iNaturalistRN/e2e"; @@ -15,14 +15,14 @@ const userAgent = "iNaturalistRN/e2e"; inatjs.setConfig( { apiURL: Config.API_URL, writeApiURL: Config.API_URL, - userAgent + userAgent, } ); // programatically dismisses announcements for user and resets to a lone sample observation // in order to set up consistent testing conditions and remove need to wait for announcements export default async function resetUserForTesting() { console.log( - "Test user reset: dismissing announcements and resetting observations..." + "Test user reset: dismissing announcements and resetting observations...", ); if ( !testUsernameAllowlist.includes( Config.E2E_TEST_USERNAME ) ) { @@ -35,8 +35,8 @@ export default async function resetUserForTesting() { const apiClient = create( { baseURL: apiHost, headers: { - "User-Agent": userAgent - } + "User-Agent": userAgent, + }, } ); await apiClient.get( "/logout" ); @@ -48,7 +48,7 @@ export default async function resetUserForTesting() { client_secret: Config.OAUTH_CLIENT_SECRET, username: Config.E2E_TEST_USERNAME, password: Config.E2E_TEST_PASSWORD, - locale: "en" + locale: "en", }; const tokenResponse = await apiClient.post( "/oauth/token", formData ); @@ -59,7 +59,7 @@ export default async function resetUserForTesting() { const jwtResponse = await apiClient.get( "/users/api_token.json" ); const opts = { - api_token: jwtResponse.data.api_token + api_token: jwtResponse.data.api_token, }; const announcementSearchParams = { @@ -68,13 +68,13 @@ export default async function resetUserForTesting() { per_page: 20, fields: { id: true, - dismissible: true - } + dismissible: true, + }, }; const announcementResponse = await inatjs.announcements.search( announcementSearchParams, - opts + opts, ); const announcementIdsToDismiss = announcementResponse @@ -88,7 +88,7 @@ export default async function resetUserForTesting() { try { await inatjs.announcements.dismiss( { id }, - opts + opts, ); } catch ( _error ) { console.log( `Could not delete announcement: ${id}. Moving on...` ); @@ -100,9 +100,9 @@ export default async function resetUserForTesting() { { headers: { Authorization: `Bearer ${accessToken}`, - "User-Agent": userAgent - } - } + "User-Agent": userAgent, + }, + }, ); const userId = usersEditResponse.data.id; @@ -131,7 +131,7 @@ export default async function resetUserForTesting() { try { await inatjs.observations.delete( { uuid }, - opts + opts, ); } catch ( _error ) { console.log( `Could not delete observation: ${uuid}. Moving on...` ); @@ -142,17 +142,17 @@ export default async function resetUserForTesting() { const sampleObservationParams = { observation: { latitude: sampleObservation.latitude, - longitude: sampleObservation.longitude - } + longitude: sampleObservation.longitude, + }, }; await inatjs.observations.create( sampleObservationParams, - opts + opts, ); await apiClient.get( "/logout" ); console.log( - "Test user reset: announcements dismissed and observations reset" + "Test user reset: announcements dismissed and observations reset", ); } diff --git a/e2e/sharedFlows/signIn.js b/e2e/sharedFlows/signIn.js index 0d798d94c..7a7f76986 100644 --- a/e2e/sharedFlows/signIn.js +++ b/e2e/sharedFlows/signIn.js @@ -1,5 +1,5 @@ import { - by, element, expect, waitFor + by, element, expect, waitFor, } from "detox"; import Config from "react-native-config-node"; diff --git a/e2e/sharedFlows/switchPowerMode.js b/e2e/sharedFlows/switchPowerMode.js index 3787e7db3..39b007136 100644 --- a/e2e/sharedFlows/switchPowerMode.js +++ b/e2e/sharedFlows/switchPowerMode.js @@ -1,5 +1,5 @@ import { - by, element, waitFor + by, element, waitFor, } from "detox"; const TIMEOUT = 10_000; diff --git a/e2e/sharedFlows/uploadObservation.js b/e2e/sharedFlows/uploadObservation.js index 908089fb7..f3b4ca2e9 100644 --- a/e2e/sharedFlows/uploadObservation.js +++ b/e2e/sharedFlows/uploadObservation.js @@ -1,5 +1,5 @@ import { - by, element, expect, waitFor + by, element, expect, waitFor, } from "detox"; // This needs to be a relative path for the e2e-mock version to be used diff --git a/e2e/signedIn.e2e.js b/e2e/signedIn.e2e.js index 9731fd15e..409e96f39 100644 --- a/e2e/signedIn.e2e.js +++ b/e2e/signedIn.e2e.js @@ -1,5 +1,5 @@ import { - by, device, element, expect, waitFor + by, device, element, expect, waitFor, } from "detox"; import { iNatE2eAfterEach, iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers"; @@ -25,7 +25,7 @@ describe( "Signed in user", () => { await expect( element( by.id( "observe-without-evidence-button" ) ) ).toBeVisible(); // Observe without evidence const obsWithoutEvidenceButton = element( - by.id( "observe-without-evidence-button" ) + by.id( "observe-without-evidence-button" ), ); await expect( obsWithoutEvidenceButton ).toBeVisible(); await obsWithoutEvidenceButton.tap(); diff --git a/e2e/signedOut.e2e.js b/e2e/signedOut.e2e.js index 3bd020d2e..8a1a28522 100644 --- a/e2e/signedOut.e2e.js +++ b/e2e/signedOut.e2e.js @@ -3,7 +3,7 @@ import { device, element, expect, - waitFor + waitFor, } from "detox"; import { iNatE2eAfterEach, iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers"; diff --git a/index.js b/index.js index e7b144c1c..66acda030 100644 --- a/index.js +++ b/index.js @@ -11,13 +11,13 @@ import "react-native-url-polyfill/auto"; import { BottomSheetModalProvider } from "@gorhom/bottom-sheet"; import { - useColorScheme, Alert, AppRegistry, View + useColorScheme, Alert, AppRegistry, View, } from "react-native"; import { getCurrentRoute } from "navigation/navigationUtils"; import { zustandStorage } from "stores/useStore"; import { QueryClient, - QueryClientProvider + QueryClientProvider, } from "@tanstack/react-query"; import App from "components/App"; import ErrorBoundary from "components/ErrorBoundary"; @@ -58,7 +58,7 @@ if ( allRejections: true, onUnhandled: ( id, error ) => { logger.error( "Unhandled promise rejection: ", error ); - } + }, } ); } /* eslint-enable no-undef */ @@ -68,7 +68,7 @@ const jsErrorHandler = ( e, isFatal ) => { Alert.alert( "Device-storage-full", "iNaturalist may not be able to save your photos or may crash.", - [{ text: t( "OK" ) }] + [{ text: t( "OK" ) }], ); } @@ -104,7 +104,7 @@ setNativeExceptionHandler( screen: getCurrentRoute()?.name || "", memoryUsage: await DeviceInfo.getUsedMemory(), timestamp: new Date().toISOString(), - appVersion: await DeviceInfo.getVersion() + appVersion: await DeviceInfo.getVersion(), }; // Store crash data for retrieval on next app launch @@ -117,7 +117,7 @@ setNativeExceptionHandler( } }, true, // Force quit the app to prevent zombie states - true // Enable on iOS + true, // Enable on iOS ); initI18next(); @@ -128,16 +128,16 @@ inatjs.setConfig( { writeApiURL: Config.API_URL, userAgent: getUserAgent(), headers: { - "X-Installation-ID": getInstallID( ) - } + "X-Installation-ID": getInstallID( ), + }, } ); const queryClient = new QueryClient( { defaultOptions: { queries: { - retry: reactQueryRetry - } - } + retry: reactQueryRetry, + }, + }, } ); const AppWithProviders = ( ) => { diff --git a/jest.config.ts b/jest.config.ts index dda28649c..bcb44dbfc 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,27 +7,27 @@ const ignorePatterns = "node_modules/(?!(jest-)?@react-native|react-native|" const config: Config = { moduleNameMapper: { - "\\.svg": "/tests/mocks/svgMock.js" + "\\.svg": "/tests/mocks/svgMock.js", }, preset: "react-native", setupFiles: [ "./node_modules/react-native-gesture-handler/jestSetup.js", "./node_modules/@react-native-google-signin/google-signin/jest/build/jest/setup.js", - "/tests/jest.setup.js" + "/tests/jest.setup.js", ], globalSetup: "/tests/jest.globalSetup.js", setupFilesAfterEnv: [ "/tests/jest.post-setup.js", "/tests/realm.setup.js", - "/tests/initI18next.setup.js" + "/tests/initI18next.setup.js", ], transformIgnorePatterns: [ignorePatterns], // uncomment the line below to enable verbose logging of test results // verbose: true, testPathIgnorePatterns: [ "/tests/integration/broken", - "/tests/integration/navigation/broken" - ] + "/tests/integration/navigation/broken", + ], // uncomment reporters below to see which tests are running the slowest in jest // reporters: [ // ["jest-slow-test-reporter", {"numTests": 8, "warnOnSlowerThan": 300, "color": true}] diff --git a/metro.config.js b/metro.config.js index 89856a572..4eeb024bb 100644 --- a/metro.config.js +++ b/metro.config.js @@ -10,7 +10,7 @@ const { getDefaultConfig, mergeConfig } = require( "@react-native/metro-config" ); const { - resolver: { sourceExts, assetExts } + resolver: { sourceExts, assetExts }, } = getDefaultConfig(); const localPackagePaths = [ @@ -25,7 +25,7 @@ const localPackagePaths = [ */ const config = { transformer: { - babelTransformerPath: require.resolve( "react-native-svg-transformer/react-native" ) + babelTransformerPath: require.resolve( "react-native-svg-transformer/react-native" ), }, resolver: { assetExts: assetExts.filter( ext => ext !== "svg" ), @@ -33,9 +33,9 @@ const config = { process.env.MOCK_MODE === "e2e" ? ["e2e-mock", ...sourceExts, "svg"] : [...sourceExts, "svg"], - nodeModulesPaths: [...localPackagePaths] + nodeModulesPaths: [...localPackagePaths], }, - watchFolders: [...localPackagePaths] + watchFolders: [...localPackagePaths], }; module.exports = mergeConfig( getDefaultConfig( __dirname ), config ); diff --git a/react-native-logs.config.js b/react-native-logs.config.js index 8986d9b5b..0a838d147 100644 --- a/react-native-logs.config.js +++ b/react-native-logs.config.js @@ -3,7 +3,7 @@ import RNFS from "react-native-fs"; import { consoleTransport, fileAsyncTransport, - logger + logger, } from "react-native-logs"; const fileName = "inaturalist-rn-log.txt"; @@ -23,19 +23,19 @@ const config = { transport, transportOptions: { FS: RNFS, - fileName - } + fileName, + }, }; const log = logger.createLogger( config ); const logWithoutRemote = logger.createLogger( { ...config, - transport: [consoleTransport, fileAsyncTransport] + transport: [consoleTransport, fileAsyncTransport], } ); export { log, logFilePath, - logWithoutRemote + logWithoutRemote, }; diff --git a/react-native.config.js b/react-native.config.js index 480b01e95..6d0a15edc 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -1,3 +1,3 @@ module.exports = { - assets: ["./assets/fonts/"] + assets: ["./assets/fonts/"], }; diff --git a/scripts/add-example-model.js b/scripts/add-example-model.js index 78b7f8938..9ef089caa 100644 --- a/scripts/add-example-model.js +++ b/scripts/add-example-model.js @@ -28,12 +28,12 @@ const downloadAndroid = async argv => { "src", androidFlavor, "assets", - "camera" + "camera", ); const androidModel = path.join( androidDestination, - `${cvModelFilename}.${androidExt}` + `${cvModelFilename}.${androidExt}`, ); console.log( "Checking android model files..." ); @@ -50,7 +50,7 @@ const downloadAndroid = async argv => { } console.log( - `Android model files missing, downloading from '${binariesBaseDir}'...` + `Android model files missing, downloading from '${binariesBaseDir}'...`, ); await fs.mkdir( androidDestination, { recursive: true } ); @@ -93,7 +93,7 @@ const downloadIOS = async () => { } console.log( - `iOS Model files missing, downloading from '${binariesBaseDir}'...` + `iOS Model files missing, downloading from '${binariesBaseDir}'...`, ); await fs.mkdir( iosDestination, { recursive: true } ); @@ -123,7 +123,7 @@ yargs .option( "androidFlavor", { alias: "f", type: "string", - description: "Android flavor to download model files into" + description: "Android flavor to download model files into", } ) .command( "$0", @@ -133,6 +133,6 @@ yargs async argv => { await downloadAndroid( argv ); await downloadIOS(); - } + }, ) .help().argv; diff --git a/src/api/announcements.js b/src/api/announcements.js index 4712fd5ed..e5575aca8 100644 --- a/src/api/announcements.js +++ b/src/api/announcements.js @@ -9,19 +9,19 @@ const ANNOUNCEMENTS_FIELDS = { body: true, dismissible: true, start: true, - placement: true + placement: true, }; const PARAMS = { fields: ANNOUNCEMENTS_FIELDS, - placement: "mobile" + placement: "mobile", }; const searchAnnouncements = async ( params: Object = {}, opts: Object = {} ): Promise => { try { const { results } = await inatjs.announcements.search( { ...PARAMS, ...params }, - opts + opts, ); return results; } catch ( e ) { diff --git a/src/api/comments.js b/src/api/comments.js index 9a09b5ccb..5af1ec651 100644 --- a/src/api/comments.js +++ b/src/api/comments.js @@ -6,12 +6,12 @@ import Comment from "realmModels/Comment"; import handleError from "./error"; const PARAMS = { - fields: Comment.COMMENT_FIELDS + fields: Comment.COMMENT_FIELDS, }; const createComment = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.comments.create( { ...PARAMS, ...params }, opts ); @@ -23,7 +23,7 @@ const createComment = async ( const updateComment = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.comments.update( { ...PARAMS, ...params }, opts ); @@ -35,7 +35,7 @@ const updateComment = async ( const deleteComments = async ( id: number, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.comments.delete( { id }, opts ); @@ -48,5 +48,5 @@ const deleteComments = async ( export { createComment, deleteComments, - updateComment + updateComment, }; diff --git a/src/api/computerVision.ts b/src/api/computerVision.ts index fa960f680..e693e9e09 100644 --- a/src/api/computerVision.ts +++ b/src/api/computerVision.ts @@ -9,13 +9,13 @@ const PARAMS = { fields: { combined_score: true, vision_score: true, - taxon: Taxon.LIMITED_TAXON_FIELDS - } + taxon: Taxon.LIMITED_TAXON_FIELDS, + }, }; const scoreImage = async ( params = {}, - opts = {} + opts = {}, ): Promise => { try { return inatjs.computervision.score_image( { ...PARAMS, ...params }, opts ); diff --git a/src/api/error.ts b/src/api/error.ts index 193c491d3..5c9570522 100644 --- a/src/api/error.ts +++ b/src/api/error.ts @@ -15,7 +15,7 @@ export class INatApiError extends Error { constructor( json: Record & { status: string | number }, status?: number, - context?: Record | null + context?: Record | null, ) { super( JSON.stringify( json ) ); this.name = "INatApiError"; @@ -30,7 +30,7 @@ export class INatApiUnauthorizedError extends INatApiError { const errorJson = { error: "Unauthorized", status: 401, - context + context, }; super( errorJson, 401, context ); this.name = "INatApiUnauthorizedError"; @@ -42,7 +42,7 @@ export class INatApiTooManyRequestsError extends INatApiError { const errorJson = { error: "Too Many Requests", status: 429, - context + context, }; super( errorJson, 429, context ); this.name = "INatApiTooManyRequestsError"; @@ -65,12 +65,12 @@ export interface ErrorWithResponse { url: string; json: () => Promise<{ status: string; - errors: Array<{ + errors: { errorCode: string; message: string; from: string | null; stack: string | null; - }>; + }[]; }>; }; status?: number; @@ -82,7 +82,7 @@ export interface ErrorWithResponse { function createContext( e: ErrorWithResponse, options: HandleErrorOptions, - extraContext: Record | null + extraContext: Record | null, ) { const context = { queryKey: options?.queryKey @@ -97,19 +97,19 @@ function createContext( url: e?.response?.url, routeName: options?.routeName || e?.routeName, routeParams: options?.routeParams || e?.routeParams, - ...( extraContext || {} ) + ...( extraContext || {} ), }; // Remove nullish values (null or undefined) from context return Object.fromEntries( Object.entries( context ).filter( - ( [_, value] ) => value !== null && value !== undefined - ) + ( [_, value] ) => value !== null && value !== undefined, + ), ); } async function handleError( e: ErrorWithResponse, - options: HandleErrorOptions = {} + options: HandleErrorOptions = {}, ): Promise { // Get context from options if available const originalContext = options?.context || null; @@ -177,7 +177,7 @@ async function handleError( error, error.context ? JSON.stringify( error.context ) - : "No context" + : "No context", ); if ( typeof ( options.onApiError ) === "function" ) { options.onApiError( error ); diff --git a/src/api/identifications.js b/src/api/identifications.js index f531412b8..5973bd2fd 100644 --- a/src/api/identifications.js +++ b/src/api/identifications.js @@ -6,12 +6,12 @@ import Identification from "realmModels/Identification"; import handleError from "./error"; const PARAMS = { - fields: Identification.ID_FIELDS + fields: Identification.ID_FIELDS, }; const createIdentification = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.identifications.create( { ...PARAMS, ...params }, opts ); @@ -23,7 +23,7 @@ const createIdentification = async ( const updateIdentification = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.identifications.update( { ...PARAMS, ...params }, opts ); @@ -35,5 +35,5 @@ const updateIdentification = async ( export { createIdentification, - updateIdentification + updateIdentification, }; diff --git a/src/api/log.ts b/src/api/log.ts index e8ed4c0a5..593de6a05 100644 --- a/src/api/log.ts +++ b/src/api/log.ts @@ -13,8 +13,8 @@ const api = create( { baseURL: API_HOST, headers: { "User-Agent": getUserAgent( ), - "X-Installation-ID": getInstallID( ) - } + "X-Installation-ID": getInstallID( ), + }, } ); function isError( error: { message?: string; stack?: string } ) { @@ -71,16 +71,16 @@ const iNatLogstashTransport: transportFunctionType = async props => { context: props.extension, timestamp: new Date().toISOString(), error_type: errorType, - backtrace + backtrace, }; try { await api.post( "/log", formData, { headers: { Authorization: [ userToken, - anonymousToken - ].flat( ).join( ", " ) - } + anonymousToken, + ].flat( ).join( ", " ), + }, } ); } catch ( e ) { const postLogError = e as Error; diff --git a/src/api/messages.ts b/src/api/messages.ts index 15f093317..75c2420df 100644 --- a/src/api/messages.ts +++ b/src/api/messages.ts @@ -7,11 +7,11 @@ const MESSAGE_FIELDS = { subject: true, body: true, from_user: User.FIELDS, - to_user: User.FIELDS + to_user: User.FIELDS, }; const PARAMS = { - fields: MESSAGE_FIELDS + fields: MESSAGE_FIELDS, }; const searchMessages = async ( params: object = {}, opts: object = {} ): Promise => { diff --git a/src/api/observationSounds.js b/src/api/observationSounds.js index 1b93f951d..33cc2f2d4 100644 --- a/src/api/observationSounds.js +++ b/src/api/observationSounds.js @@ -6,7 +6,7 @@ import handleError from "./error"; const deleteRemoteObservationSound = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ) : Promise => { try { return await inatjs.observation_sounds.delete( params, opts ); diff --git a/src/api/observations.js b/src/api/observations.js index d6069f02e..7e19f8ca0 100644 --- a/src/api/observations.js +++ b/src/api/observations.js @@ -46,13 +46,13 @@ const unfaveObservation = async ( params: Object = {}, opts: Object = {} ): Prom const fetchRemoteObservation = async ( uuid: string, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.observations.fetch( uuid, params, - opts + opts, ); if ( !response ) { return null; } const { results } = response; @@ -66,15 +66,15 @@ const fetchRemoteObservation = async ( }; const fetchRemoteObservations = async ( - uuids: Array, + uuids: string[], params: Object = {}, - opts: Object = {} -): Promise> => { + opts: Object = {}, +): Promise => { try { const response = await inatjs.observations.fetch( uuids, params, - opts + opts, ); if ( !response ) { return null; } const { results } = response; @@ -97,7 +97,7 @@ const markAsReviewed = async ( params: Object = {}, opts: Object = {} ): Promise const markObservationUpdatesViewed = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { return await inatjs.observations.viewedUpdates( params, opts ); @@ -108,7 +108,7 @@ const markObservationUpdatesViewed = async ( const createObservation = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { return await inatjs.observations.create( params, opts ); @@ -119,7 +119,7 @@ const createObservation = async ( const updateObservation = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { return await inatjs.observations.update( params, opts ); @@ -135,7 +135,7 @@ const updateObservation = async ( const createOrUpdateEvidence = async ( apiEndpoint: Function, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { return await apiEndpoint( params, opts ); @@ -146,7 +146,7 @@ const createOrUpdateEvidence = async ( const fetchObservationUpdates = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.observations.updates( params, opts ); @@ -158,28 +158,28 @@ const fetchObservationUpdates = async ( const fetchUnviewedObservationUpdatesCount = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { total_results: updatesCount } = await inatjs.observations.updates( { ...params, viewed: false, - per_page: 0 + per_page: 0, }, opts ); return updatesCount; } catch ( e ) { return handleError( e, { context: { functionName: "fetchUnviewedObservationUpdatesCount", - opts - } + opts, + }, } ); } }; const deleteRemoteObservation = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ) : Promise => { try { return await inatjs.observations.delete( params, opts ); @@ -206,7 +206,7 @@ const fetchIdentifiers = async ( params: Object = {} ) : Promise => { const fetchSpeciesCounts = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ) : Promise => { try { return inatjs.observations.speciesCounts( params, opts ); @@ -217,7 +217,7 @@ const fetchSpeciesCounts = async ( const checkForDeletedObservations = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ) : Promise => { try { return await inatjs.observations.deleted( params, opts ); @@ -228,7 +228,7 @@ const checkForDeletedObservations = async ( const fetchSubscriptions = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ) : Promise => { try { return inatjs.observations.subscriptions( params, opts ); @@ -239,7 +239,7 @@ const fetchSubscriptions = async ( const createSubscription = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ) : Promise => { try { return inatjs.observations.subscribe( params, opts ); @@ -267,5 +267,5 @@ export { markObservationUpdatesViewed, searchObservations, unfaveObservation, - updateObservation + updateObservation, }; diff --git a/src/api/places.js b/src/api/places.js index af29cc518..4a0036fb7 100644 --- a/src/api/places.js +++ b/src/api/places.js @@ -5,9 +5,9 @@ import inatjs from "inaturalistjs"; import handleError from "./error"; const fetchPlace = async ( - id: number | Array, + id: number | number[], params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.places.fetch( id, params, opts ); diff --git a/src/api/projects.js b/src/api/projects.js index 7ba9536b8..862197e71 100644 --- a/src/api/projects.js +++ b/src/api/projects.js @@ -7,17 +7,17 @@ import handleError from "./error"; const FIELDS = { title: true, icon: true, - project_type: true + project_type: true, }; const PARAMS = { - fields: FIELDS + fields: FIELDS, }; const fetchProjects = async ( id: number, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.projects.fetch( id, params, opts ); @@ -29,7 +29,7 @@ const fetchProjects = async ( const fetchProjectMembers = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { return await inatjs.projects.members( params, opts ); @@ -40,7 +40,7 @@ const fetchProjectMembers = async ( const fetchProjectPosts = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.projects.posts( params, opts ); @@ -92,5 +92,5 @@ export { fetchProjects, joinProject, leaveProject, - searchProjects + searchProjects, }; diff --git a/src/api/qualityMetrics.js b/src/api/qualityMetrics.js index cc890072b..8905c7ee7 100644 --- a/src/api/qualityMetrics.js +++ b/src/api/qualityMetrics.js @@ -6,7 +6,7 @@ import handleError from "./error"; const setQualityMetric = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.observations.setQualityMetric( params, opts ); @@ -18,7 +18,7 @@ const setQualityMetric = async ( const deleteQualityMetric = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const { results } = await inatjs.observations.deleteQualityMetric( params, opts ); @@ -30,7 +30,7 @@ const deleteQualityMetric = async ( const fetchQualityMetrics = async ( params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.observations.qualityMetrics( params, opts ); @@ -43,5 +43,5 @@ const fetchQualityMetrics = async ( export { deleteQualityMetric, fetchQualityMetrics, - setQualityMetric + setQualityMetric, }; diff --git a/src/api/relationships.js b/src/api/relationships.js index 3163cd88d..6be9020bf 100644 --- a/src/api/relationships.js +++ b/src/api/relationships.js @@ -5,7 +5,7 @@ import inatjs from "inaturalistjs"; import handleError from "./error"; const PARAMS = { - fields: "all" + fields: "all", }; const fetchRelationships = async ( params: Object = {}, opts: Object = {} ): Promise => { @@ -48,5 +48,5 @@ export { createRelationships, deleteRelationships, fetchRelationships, - updateRelationships + updateRelationships, }; diff --git a/src/api/search.ts b/src/api/search.ts index 6e646854a..536e7d163 100644 --- a/src/api/search.ts +++ b/src/api/search.ts @@ -8,7 +8,7 @@ import type { ApiProject, ApiResponse, ApiTaxon, - ApiUser + ApiUser, } from "./types"; interface SearchResponse extends ApiResponse { @@ -30,13 +30,13 @@ interface SearchParams extends ApiParams { const PARAMS: ApiParams = { per_page: 10, - fields: "all" + fields: "all", }; // Vanilla search wrapper with error handling const search = async ( params: SearchParams = {}, - opts: ApiOpts = {} + opts: ApiOpts = {}, ): Promise => { let response: SearchResponse; try { @@ -53,7 +53,7 @@ const search = async ( // Hits /search AND maps results so it just returns and array of results const fetchSearchResults = async ( params: SearchParams = {}, - opts: ApiOpts = {} + opts: ApiOpts = {}, ): Promise => { const response = await search( params, opts ); if ( !response ) { return null; } diff --git a/src/api/taxa.js b/src/api/taxa.js index 990e607e7..c6c20b8ce 100644 --- a/src/api/taxa.js +++ b/src/api/taxa.js @@ -8,31 +8,31 @@ const ANCESTOR_FIELDS = { name: true, preferred_common_name: true, rank: true, - rank_level: true + rank_level: true, }; const PHOTO_FIELDS = { id: true, attribution: true, license_code: true, - url: true + url: true, }; // These fields should work with all /taxa endpoints const FIELDS = { ancestor_ids: true, default_photo: { - url: true + url: true, }, name: true, preferred_common_name: true, rank: true, rank_level: true, - wikipedia_url: true + wikipedia_url: true, }; const PARAMS = { - fields: FIELDS + fields: FIELDS, }; function mapTaxonPhotoToLocalSchema( taxonPhoto ) { @@ -47,9 +47,9 @@ function mapToLocalSchema( taxon ) { } async function fetchTaxon( - id: number | Array, + id: number | number[], params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise { try { const fetchParams = { @@ -64,24 +64,24 @@ async function fetchTaxon( id: true, place: { id: true, - display_name: true - } + display_name: true, + }, }, listed_taxa: { establishment_means: true, id: true, list: { - title: true + title: true, }, place: { - id: true - } + id: true, + }, }, taxon_photos: { - photo: PHOTO_FIELDS + photo: PHOTO_FIELDS, }, - wikipedia_summary: true - } + wikipedia_summary: true, + }, }; const response = await inatjs.taxa.fetch( id, fetchParams, opts ); if ( typeof id === "number" ) { @@ -108,5 +108,5 @@ async function searchTaxa( params: Object = {}, opts: Object = {} ): Promise = {}, - opts: Record = {} + opts: Record = {}, ): Promise | null | ErrorWithResponse | INatApiError> => { try { const response = await inatjs.translations.locales( params, opts ); @@ -13,7 +13,7 @@ const fetchAvailableLocales = async ( } catch ( e ) { return handleError( e as ErrorWithResponse, - { context: { functionName: "fetchAvailableLocales", opts } } + { context: { functionName: "fetchAvailableLocales", opts } }, ); } }; diff --git a/src/api/userAgent.ts b/src/api/userAgent.ts index 09350de90..e946f6ac5 100644 --- a/src/api/userAgent.ts +++ b/src/api/userAgent.ts @@ -7,14 +7,14 @@ import { getDeviceType, getSystemName, getSystemVersion, - getVersion + getVersion, } from "react-native-device-info"; const DETAILS = [ `Build ${getBuildNumber()}`, `${getSystemName()} ${getSystemVersion()}`, getDeviceId( ), - getDeviceType( ) + getDeviceType( ), ]; async function getOtherDetails( ) { @@ -32,5 +32,5 @@ function getUserAgent( ) { export { DETAILS, - getUserAgent + getUserAgent, }; diff --git a/src/api/users.js b/src/api/users.js index 801b5e5de..f3cd47d99 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -19,16 +19,16 @@ const REMOTE_USER_FIELDS = { place_id: true, roles: true, site: { - name: true + name: true, }, species_count: true, updated_at: true, prefers_common_names: true, - prefers_scientific_name_first: true + prefers_scientific_name_first: true, }; const REMOTE_USER_PARAMS = { - fields: REMOTE_USER_FIELDS + fields: REMOTE_USER_FIELDS, }; const fetchUserMe = async ( params: Object = {}, opts: Object = {} ): Promise => { @@ -44,7 +44,7 @@ const fetchUserProjects = async ( params: Object = {}, opts: Object = {} ): Prom try { const response = await inatjs.users.projects( params, - opts + opts, ); return response?.results; } catch ( e ) { @@ -55,14 +55,14 @@ const fetchUserProjects = async ( params: Object = {}, opts: Object = {} ): Prom const fetchRemoteUser = async ( id: number | string, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { if ( !id ) return null; try { const { results } = await inatjs.users.fetch( id, { ...REMOTE_USER_PARAMS, ...params, - ...opts + ...opts, } ); return results[0]; } catch ( e ) { @@ -71,9 +71,9 @@ const fetchRemoteUser = async ( }; const fetchUsers = async ( - ids: Array, + ids: number[], params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { return await inatjs.users.fetch( ids, params, opts ); @@ -85,12 +85,12 @@ const fetchUsers = async ( const blockUser = async ( id: number, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.users.block( { id }, { ...params, - ...opts + ...opts, } ); return response; } catch ( e ) { @@ -101,12 +101,12 @@ const blockUser = async ( const muteUser = async ( id: number, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.users.mute( { id }, { ...params, - ...opts + ...opts, } ); return response; } catch ( e ) { @@ -117,12 +117,12 @@ const muteUser = async ( const unblockUser = async ( id: number, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.users.unblock( { id }, { ...params, - ...opts + ...opts, } ); return response; } catch ( e ) { @@ -133,12 +133,12 @@ const unblockUser = async ( const unmuteUser = async ( id: number, params: Object = {}, - opts: Object = {} + opts: Object = {}, ): Promise => { try { const response = await inatjs.users.unmute( { id }, { ...params, - ...opts + ...opts, } ); return response; } catch ( e ) { @@ -157,7 +157,7 @@ const updateUsers = async ( params: Object = {}, opts: Object = {} ): Promise => { try { return await inatjs.users.emailAvailable( { email }, { ...params, ...opts } ); @@ -176,5 +176,5 @@ export { muteUser, unblockUser, unmuteUser, - updateUsers + updateUsers, }; diff --git a/src/appConstants/e2e.ts b/src/appConstants/e2e.ts index c51d466fd..117de1b88 100644 --- a/src/appConstants/e2e.ts +++ b/src/appConstants/e2e.ts @@ -16,5 +16,5 @@ export const CHUCKS_PAD = { altitude: 120.0234, altitudeAccuracy: 2.123, heading: null, - speed: null + speed: null, }; diff --git a/src/components/About.tsx b/src/components/About.tsx index d6537c9db..76b4daddf 100644 --- a/src/components/About.tsx +++ b/src/components/About.tsx @@ -6,7 +6,7 @@ import { Heading4, ScrollViewWrapper, Tabs, - UnderlinedLink + UnderlinedLink, } from "components/SharedComponents"; import { Image, Pressable, View } from "components/styledComponents"; import { t } from "i18next"; @@ -30,7 +30,7 @@ const About = ( ) => { navigation.navigate( "FullPageWebView", { title: t( "TERMS-OF-USE" ), initialUrl: url, - loggedIn: false + loggedIn: false, } ); }; @@ -39,7 +39,7 @@ const About = ( ) => { navigation.navigate( "FullPageWebView", { title: t( "PRIVACY-POLICY" ), initialUrl: url, - loggedIn: false + loggedIn: false, } ); }; @@ -48,7 +48,7 @@ const About = ( ) => { navigation.navigate( "FullPageWebView", { title: t( "COMMUNITY-GUIDELINES" ), initialUrl: url, - loggedIn: false + loggedIn: false, } ); }; @@ -68,15 +68,15 @@ const About = ( ) => { text: t( "ABOUT" ), onPress: () => { setActiveTab( aboutID ); - } + }, }, { id: teamID, text: t( "TEAM" ), onPress: () => { setActiveTab( teamID ); - } - } + }, + }, ]} activeId={activeTab} /> diff --git a/src/components/AddObsBottomSheet/AddObsBottomSheet.tsx b/src/components/AddObsBottomSheet/AddObsBottomSheet.tsx index 60b40360d..b603124f8 100644 --- a/src/components/AddObsBottomSheet/AddObsBottomSheet.tsx +++ b/src/components/AddObsBottomSheet/AddObsBottomSheet.tsx @@ -1,5 +1,5 @@ import { - Body3, BottomSheet, INatIcon, INatIconButton + Body3, BottomSheet, INatIcon, INatIconButton, } from "components/SharedComponents"; import { Pressable, View } from "components/styledComponents"; import React, { useMemo } from "react"; @@ -34,7 +34,7 @@ const GREEN_CIRCLE_CLASS = "bg-inatGreen rounded-full h-[36px] w-[36px] mb-2"; const ROW_CLASS = "flex-row justify-center space-x-4 w-full flex-1"; const AddObsBottomSheet = ( { - closeBottomSheet, navAndCloseBottomSheet, hidden + closeBottomSheet, navAndCloseBottomSheet, hidden, }: Props ) => { const { t } = useTranslation( ); @@ -47,7 +47,7 @@ const AddObsBottomSheet = ( { onPress: ( ) => navAndCloseBottomSheet( "Camera", { camera: "AI" } ), testID: "aicamera-button", accessibilityLabel: t( "AI-Camera" ), - accessibilityHint: t( "Navigates-to-AI-camera" ) + accessibilityHint: t( "Navigates-to-AI-camera" ), }, standardCamera: { text: t( "Take-photos" ), @@ -55,7 +55,7 @@ const AddObsBottomSheet = ( { onPress: ( ) => navAndCloseBottomSheet( "Camera", { camera: "Standard" } ), testID: "camera-button", accessibilityLabel: t( "Camera" ), - accessibilityHint: t( "Navigates-to-camera" ) + accessibilityHint: t( "Navigates-to-camera" ), }, photoLibrary: { text: t( "Upload-photos" ), @@ -63,7 +63,7 @@ const AddObsBottomSheet = ( { onPress: ( ) => navAndCloseBottomSheet( "PhotoLibrary" ), testID: "import-media-button", accessibilityLabel: t( "Photo-importer" ), - accessibilityHint: t( "Navigates-to-photo-importer" ) + accessibilityHint: t( "Navigates-to-photo-importer" ), }, soundRecorder: { text: t( "Record-a-sound" ), @@ -71,7 +71,7 @@ const AddObsBottomSheet = ( { onPress: ( ) => navAndCloseBottomSheet( "SoundRecorder" ), testID: "record-sound-button", accessibilityLabel: t( "Sound-recorder" ), - accessibilityHint: t( "Navigates-to-sound-recorder" ) + accessibilityHint: t( "Navigates-to-sound-recorder" ), }, noEvidence: { text: t( "Create-observation-with-no-evidence" ), @@ -83,22 +83,22 @@ const AddObsBottomSheet = ( { }, testID: "observe-without-evidence-button", accessibilityLabel: t( "Observation-with-no-evidence" ), - accessibilityHint: t( "Navigates-to-observation-edit-screen" ) - } + accessibilityHint: t( "Navigates-to-observation-edit-screen" ), + }, } ), [ navAndCloseBottomSheet, prepareObsEdit, - t + t, ] ); const optionRows = AI_CAMERA_SUPPORTED ? [ [obsCreateItems.standardCamera, obsCreateItems.photoLibrary], - [obsCreateItems.soundRecorder, obsCreateItems.aiCamera] + [obsCreateItems.soundRecorder, obsCreateItems.aiCamera], ] : [ [obsCreateItems.standardCamera], - [obsCreateItems.soundRecorder, obsCreateItems.photoLibrary] + [obsCreateItems.soundRecorder, obsCreateItems.photoLibrary], ]; const renderAddObsIcon = ( { @@ -107,7 +107,7 @@ const AddObsBottomSheet = ( { icon, onPress, testID, - text + text, }: ObsCreateItem ) => ( { justFinishedSignup, currentUser, isAllAddObsOptionsMode, - shownOnce + shownOnce, ] ); const dismissTooltip = () => { @@ -133,13 +133,13 @@ const AddObsButton = ( ): React.Node => { routes: [ { name: screen, - params: { ...params, previousScreen: currentRoute } - } - ] - } - } - ] - } ) + params: { ...params, previousScreen: currentRoute }, + }, + ], + }, + }, + ], + } ), ); closeBottomSheet( ); diff --git a/src/components/AddObsBottomSheet/AddObsTooltip.tsx b/src/components/AddObsBottomSheet/AddObsTooltip.tsx index 1226b0513..5d13c0f45 100644 --- a/src/components/AddObsBottomSheet/AddObsTooltip.tsx +++ b/src/components/AddObsBottomSheet/AddObsTooltip.tsx @@ -22,7 +22,7 @@ const AddObsTooltip = ( { isVisible, dismissTooltip }: Props ) => { + data: string | string[] }; const handleShare = ( navigation, item: ?SharedItem ) => { @@ -41,7 +41,7 @@ const handleShare = ( navigation, item: ?SharedItem ) => { // while observations are created navigation?.navigate( "NoBottomTabStackNavigator", { screen: "PhotoSharing", - params: { item } + params: { item }, } ); }; @@ -55,7 +55,7 @@ type Props = { const App = ( { children }: Props ): Node => { const navigation = useNavigation( ); const { loadTime } = usePerformance( { - screenName: "App" + screenName: "App", } ); if ( isDebugMode( ) ) { logger.info( loadTime ); @@ -65,7 +65,7 @@ const App = ( { children }: Props ): Node => { // for performance reasons const onShare = useCallback( item => handleShare( navigation, item ), - [navigation] + [navigation], ); const currentUser = useCurrentUser( ); diff --git a/src/components/AppStateListener.ts b/src/components/AppStateListener.ts index fb9848bd0..5ba3d9a1b 100644 --- a/src/components/AppStateListener.ts +++ b/src/components/AppStateListener.ts @@ -4,7 +4,7 @@ import { useEffect, useState } from "react"; import { AppState } from "react-native"; import { log } from "sharedHelpers/logger"; import { - usePerformance + usePerformance, } from "sharedHooks"; import { isDebugMode } from "sharedHooks/useDebugMode"; @@ -13,7 +13,7 @@ const logger = log.extend( "AppStateListener" ); const AppStateListener = ( ) => { const { loadTime } = usePerformance( { screenName: "AppStateListener", - isLoading: false + isLoading: false, } ); if ( isDebugMode( ) ) { logger.info( loadTime ); diff --git a/src/components/Camera/AICamera/AICamera.js b/src/components/Camera/AICamera/AICamera.js index c8c7a7214..ceb0b6ce5 100644 --- a/src/components/Camera/AICamera/AICamera.js +++ b/src/components/Camera/AICamera/AICamera.js @@ -21,7 +21,7 @@ import { useDebugMode, useLayoutPrefs, usePerformance, - useTranslation + useTranslation, } from "sharedHooks"; import { isDebugMode } from "sharedHooks/useDebugMode"; import useStore from "stores/useStore"; @@ -32,7 +32,7 @@ import { handleCaptureError, handleClassifierError, handleDeviceNotSupported, - handleLog + handleLog, } from "../helpers"; import AICameraButtons from "./AICameraButtons"; import FrameProcessorCamera from "./FrameProcessorCamera"; @@ -76,7 +76,7 @@ const AICamera = ( { takePhotoOptions, userLocation, hasLocationPermissions, - requestLocationPermissions + requestLocationPermissions, }: Props ): Node => { const navigation = useNavigation( ); const sentinelFileName = useStore( state => state.sentinelFileName ); @@ -92,10 +92,10 @@ const AICamera = ( { pinchToZoom, showZoomButton, zoomTextValue, - resetZoom + resetZoom, } = useZoom( device ); const { - rotatableAnimatedStyle + rotatableAnimatedStyle, } = useRotation( ); const { confidenceThreshold, @@ -109,7 +109,7 @@ const AICamera = ( { setConfidenceThreshold, setFPS, setNumStoredResults, - setCropRatio + setCropRatio, } = usePredictions( ); const [inactive, setInactive] = React.useState( false ); const [initialVolume, setInitialVolume] = useState( null ); @@ -149,7 +149,7 @@ const AICamera = ( { const { t } = useTranslation(); const { loadTime } = usePerformance( { - isLoading: camera?.current !== null + isLoading: camera?.current !== null, } ); if ( isDebugMode( ) && loadTime ) { logger.info( loadTime ); @@ -189,7 +189,7 @@ const AICamera = ( { replaceExisting: true, inactivateCallback: () => setInactive( true ), navigateImmediately: true, - visionResult + visionResult, } ); setHasTakenPhoto( false ); }, [ @@ -198,7 +198,7 @@ const AICamera = ( { sentinelFileName, takePhotoAndStoreUri, result, - hasLocationPermissions + hasLocationPermissions, ] ); useEffect( () => { @@ -234,8 +234,8 @@ const AICamera = ( { navigation.navigate( "TabNavigator", { screen: "ObservationsTab", params: { - screen: "ObsList" - } + screen: "ObsList", + }, } ); }; @@ -274,7 +274,7 @@ const AICamera = ( { 0.001, isTablet && isLandscapeMode ? 0.3 - : 1 + : 1, ]} className="w-full h-[219px]" > @@ -282,7 +282,7 @@ const AICamera = ( { className={classnames( "self-center", { "w-[493px]": isTablet, "w-[346px] top-8": !isTablet, - "top-14": insets.top > 0 + "top-14": insets.top > 0, } )} > {showPrediction && result diff --git a/src/components/Camera/AICamera/AICameraButtons.tsx b/src/components/Camera/AICamera/AICameraButtons.tsx index af5d06164..a5bd5c80a 100644 --- a/src/components/Camera/AICamera/AICameraButtons.tsx +++ b/src/components/Camera/AICamera/AICameraButtons.tsx @@ -78,7 +78,7 @@ const AICameraButtons = ( { zoomTextValue, useLocation, toggleLocation, - deleteSentinelFile + deleteSentinelFile, }: Props ) => { const { isDefaultMode } = useLayoutPrefs(); if ( isTablet ) { diff --git a/src/components/Camera/AICamera/AIDebugButton.tsx b/src/components/Camera/AICamera/AIDebugButton.tsx index 4fc734a1f..0537b9e72 100644 --- a/src/components/Camera/AICamera/AIDebugButton.tsx +++ b/src/components/Camera/AICamera/AIDebugButton.tsx @@ -2,16 +2,16 @@ import classnames from "classnames"; import { Button, Heading4, - INatIconButton + INatIconButton, } from "components/SharedComponents"; import { - CIRCLE_SIZE + CIRCLE_SIZE, } from "components/SharedComponents/Buttons/TransparentCircleButton"; import { Text, View } from "components/styledComponents"; import React, { useState } from "react"; import { Modal, - Portal + Portal, } from "react-native-paper"; import type { CameraDeviceFormat } from "react-native-vision-camera"; import { useDebugMode } from "sharedHooks"; @@ -42,7 +42,7 @@ const AIDebugButton = ( { numStoredResults, setNumStoredResults, cropRatio, - setCropRatio + setCropRatio, }: Props ) => { const [modalVisible, setModalVisible] = useState( false ); const [slideIndex, setSlideIndex] = useState( 0 ); @@ -57,7 +57,7 @@ const AIDebugButton = ( { "items-center", "justify-center", "rounded-full", - CIRCLE_SIZE + CIRCLE_SIZE, )} backgroundColor={colors.deeppink} onPress={() => setModalVisible( true )} diff --git a/src/components/Camera/AICamera/FrameProcessorCamera.js b/src/components/Camera/AICamera/FrameProcessorCamera.js index 696fb190d..96bf232a3 100644 --- a/src/components/Camera/AICamera/FrameProcessorCamera.js +++ b/src/components/Camera/AICamera/FrameProcessorCamera.js @@ -2,14 +2,14 @@ import { useNavigation } from "@react-navigation/native"; import CameraView from "components/Camera/CameraView"; import { - useFrameProcessor + useFrameProcessor, } from "components/Camera/helpers/visionCameraWrapper"; import InatVision from "components/Camera/helpers/visionPluginWrapper"; import type { Node } from "react"; import React, { useEffect, useRef, - useState + useState, } from "react"; import { Platform } from "react-native"; import { Worklets } from "react-native-worklets-core"; @@ -17,7 +17,7 @@ import { geomodelPath, modelPath, modelVersion, - taxonomyPath + taxonomyPath, } from "sharedHelpers/mlModel"; import { logStage } from "sharedHelpers/sentinelFiles"; import usePatchedRunAsync from "sharedHelpers/visionCameraPatches"; @@ -75,7 +75,7 @@ const FrameProcessorCamera = ( { inactive, resetCameraOnFocus, userLocation, - useLocation + useLocation, }: Props ): Node => { const sentinelFileName = useStore( state => state.sentinelFileName ); const { isDefaultMode } = useLayoutPrefs( ); @@ -185,8 +185,8 @@ const FrameProcessorCamera = ( { location: { latitude: geoModelCellLocation?.latitude, longitude: geoModelCellLocation?.longitude, - elevation: geoModelCellLocation?.elevation - } + elevation: geoModelCellLocation?.elevation, + }, } ); const timeAfter = Date.now(); const timeTaken = timeAfter - timeBefore; @@ -207,8 +207,8 @@ const FrameProcessorCamera = ( { lastTimestamp, fps, useGeomodel, - geoModelCellLocation - ] + geoModelCellLocation, + ], ); return ( diff --git a/src/components/Camera/AICamera/LocationStatus.tsx b/src/components/Camera/AICamera/LocationStatus.tsx index ed45ddc57..5de81c761 100644 --- a/src/components/Camera/AICamera/LocationStatus.tsx +++ b/src/components/Camera/AICamera/LocationStatus.tsx @@ -21,14 +21,14 @@ const LocationStatus = ( { useLocation, visible, onAnimationEnd }: Props ) => { Animated.timing( opacity, { toValue: 1, duration: 200, - useNativeDriver: true + useNativeDriver: true, } ), Animated.delay( 2000 ), Animated.timing( opacity, { toValue: 0, duration: 200, - useNativeDriver: true - } ) + useNativeDriver: true, + } ), ] ).start( () => onAnimationEnd() ); } }, [visible, opacity, onAnimationEnd] ); diff --git a/src/components/Camera/AICamera/SliderControl.tsx b/src/components/Camera/AICamera/SliderControl.tsx index e6248a8d0..15c968a14 100644 --- a/src/components/Camera/AICamera/SliderControl.tsx +++ b/src/components/Camera/AICamera/SliderControl.tsx @@ -2,7 +2,7 @@ import Slider from "@react-native-community/slider"; import { Body1, Heading4, - P + P, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import { round } from "lodash"; @@ -28,7 +28,7 @@ const SliderControl = ( { min, max, precision = 0, - step = 1 + step = 1, }: SliderControlProps ) => (

{/* eslint-disable-next-line i18next/no-literal-string */} diff --git a/src/components/Camera/AICamera/hooks/usePredictions.ts b/src/components/Camera/AICamera/hooks/usePredictions.ts index 7763bbc90..d8204be54 100644 --- a/src/components/Camera/AICamera/hooks/usePredictions.ts +++ b/src/components/Camera/AICamera/hooks/usePredictions.ts @@ -42,7 +42,7 @@ const usePredictions = ( ) => { name: p.name, rank_level: p.rank_level, combined_score: p.combined_score, - taxon_id: p.taxon_id + taxon_id: p.taxon_id, } ) ) .sort( ( a, b ) => a.rank_level - b.rank_level ); const branchIDs = branch.map( t => t.taxon_id ); @@ -56,10 +56,10 @@ const usePredictions = ( ) => { rank_level: finestPrediction.rank_level, id: finestPrediction.taxon_id, name: finestPrediction.name, - iconic_taxon_name: iconicTaxon?.name + iconic_taxon_name: iconicTaxon?.name, }, combined_score: finestPrediction.combined_score, - timestamp: cvResult.timestamp + timestamp: cvResult.timestamp, }; } setResult( prediction ); @@ -78,7 +78,7 @@ const usePredictions = ( ) => { setConfidenceThreshold, setFPS, setNumStoredResults, - setCropRatio + setCropRatio, }; }; diff --git a/src/components/Camera/Buttons/CameraFlip.tsx b/src/components/Camera/Buttons/CameraFlip.tsx index 8025ac5e8..3917aa685 100644 --- a/src/components/Camera/Buttons/CameraFlip.tsx +++ b/src/components/Camera/Buttons/CameraFlip.tsx @@ -10,7 +10,7 @@ interface Props { const CameraFlip = ( { flipCamera, - cameraFlipClasses + cameraFlipClasses, }: Props ) => { const { t } = useTranslation( ); diff --git a/src/components/Camera/Buttons/Flash.tsx b/src/components/Camera/Buttons/Flash.tsx index 6e170927b..dcd7ab3cd 100644 --- a/src/components/Camera/Buttons/Flash.tsx +++ b/src/components/Camera/Buttons/Flash.tsx @@ -23,7 +23,7 @@ const Flash = ( { toggleFlash, hasFlash, takePhotoOptions, - flashClassName + flashClassName, }: Props ) => { const { t } = useTranslation( ); @@ -49,7 +49,7 @@ const Flash = ( { className={classnames( "m-0", "border-0", - flashClassName + flashClassName, )} > { const { t } = useTranslation( ); diff --git a/src/components/Camera/Buttons/Location.tsx b/src/components/Camera/Buttons/Location.tsx index 0649b774e..3c4b80862 100644 --- a/src/components/Camera/Buttons/Location.tsx +++ b/src/components/Camera/Buttons/Location.tsx @@ -17,7 +17,7 @@ interface Props { const Location = ( { rotatableAnimatedStyle, toggleLocation, - useLocation + useLocation, }: Props ) => { const { t } = useTranslation( ); diff --git a/src/components/Camera/Buttons/PhotoLibraryIcon.tsx b/src/components/Camera/Buttons/PhotoLibraryIcon.tsx index 99b0742c6..8ed176b49 100644 --- a/src/components/Camera/Buttons/PhotoLibraryIcon.tsx +++ b/src/components/Camera/Buttons/PhotoLibraryIcon.tsx @@ -19,7 +19,7 @@ const isTablet = DeviceInfo.isTablet(); const PhotoLibraryIcon = ( { rotatableAnimatedStyle, deleteSentinelFile, - disabled + disabled, }: Props ) => { const { t } = useTranslation( ); const navigation = useNavigation( ); @@ -36,14 +36,14 @@ const PhotoLibraryIcon = ( { "justify-center", "border-white", "border-2", - "rounded" + "rounded", )} onPress={() => { deleteSentinelFile(); navigation.push( "PhotoLibrary", { cmonBack: true, lastScreen: "Camera", - fromAICamera: true + fromAICamera: true, } ); }} accessibilityLabel={t( "Photo-importer" )} diff --git a/src/components/Camera/Buttons/TakePhoto.tsx b/src/components/Camera/Buttons/TakePhoto.tsx index f17a5fe71..6a3fcecaf 100644 --- a/src/components/Camera/Buttons/TakePhoto.tsx +++ b/src/components/Camera/Buttons/TakePhoto.tsx @@ -1,6 +1,6 @@ import classnames from "classnames"; import { - INatIcon + INatIcon, } from "components/SharedComponents"; import { Pressable, View } from "components/styledComponents"; import React from "react"; @@ -19,7 +19,7 @@ interface Props { const TakePhoto = ( { takePhoto, disabled, - showPrediction + showPrediction, }: Props ) => { const { t } = useTranslation( ); @@ -35,8 +35,8 @@ const TakePhoto = ( { "justify-center", "items-center", { - "opacity-50": disabled - } + "opacity-50": disabled, + }, )} onPress={takePhoto} accessibilityLabel={t( "Take-photo" )} @@ -51,7 +51,7 @@ const TakePhoto = ( { { const { t } = useTranslation(); diff --git a/src/components/Camera/CameraContainer.tsx b/src/components/Camera/CameraContainer.tsx index c98597d49..607f14fd3 100644 --- a/src/components/Camera/CameraContainer.tsx +++ b/src/components/Camera/CameraContainer.tsx @@ -2,7 +2,7 @@ import { useNavigation, useRoute } from "@react-navigation/native"; import type { Camera } from "components/Camera/helpers/visionCameraWrapper"; import { useCameraDevice, - useCameraDevices + useCameraDevices, } from "components/Camera/helpers/visionCameraWrapper"; import { ActivityIndicator } from "components/SharedComponents"; import { View } from "components/styledComponents"; @@ -11,11 +11,11 @@ import React, { useEffect, useMemo, useRef, - useState + useState, } from "react"; import { Alert, StatusBar } from "react-native"; import type { - TakePhotoOptions + TakePhotoOptions, } from "react-native-vision-camera"; import fetchAccurateUserLocation from "sharedHelpers/fetchAccurateUserLocation"; import { log } from "sharedHelpers/logger"; @@ -75,7 +75,7 @@ const CameraContainer = ( ) => { const logStageIfAICamera = useCallback( async ( stageName: string, - stageData: string + stageData: string, ) => { if ( cameraType !== "AI" ) { return; } await logStage( sentinelFileName, stageName, stageData ); @@ -89,7 +89,7 @@ const CameraContainer = ( ) => { const { hasPermissions: hasLocationPermissions, renderPermissionsGate: renderLocationPermissionsGate, - requestPermissions: requestLocationPermissions + requestPermissions: requestLocationPermissions, } = useLocationPermission( ); // we don't want to use this for the observation location because // a user could be walking with the camera open for a while, so this location @@ -105,13 +105,13 @@ const CameraContainer = ( ) => { physicalDevices: [ "ultra-wide-angle-camera", "wide-angle-camera", - "telephoto-camera" - ] + "telephoto-camera", + ], } ); const devices = useCameraDevices( ); const [loadingDevices, setLoadingDevices] = useState( true ); const [timeoutId, setTimeoutId] = useState | null>( - undefined + undefined, ); if ( timeoutId === undefined ) { setTimeoutId( setTimeout( () => { @@ -125,7 +125,7 @@ const CameraContainer = ( ) => { // We had this set to true in Seek but received many reports of it not respecting OS-wide sound // level and scared away wildlife. So maybe better to just disable it. enableShutterSound: false, - ...( hasFlash && { flash: "off" } as const ) + ...( hasFlash && { flash: "off" } as const ), } as const; const [takePhotoOptions, setTakePhotoOptions] = useState( initialPhotoOptions ); const [takingPhoto, setTakingPhoto] = useState( false ); @@ -146,7 +146,7 @@ const CameraContainer = ( ) => { hasPermissions: hasSavePhotoPermission, hasBlockedPermissions: hasBlockedSavePhotoPermission, renderPermissionsGate: renderSavePhotoPermissionGate, - requestPermissions: requestSavePhotoPermission + requestPermissions: requestSavePhotoPermission, } = useSavePhotoPermission( ); const showPhotoPermissionsGate = !( hasSavePhotoPermission || hasBlockedSavePhotoPermission ); @@ -163,7 +163,7 @@ const CameraContainer = ( ) => { }; const navigationOptions = useMemo( ( ) => ( { - addPhotoPermissionResult + addPhotoPermissionResult, } ), [addPhotoPermissionResult] ); const prepareStoreAndNavigate = usePrepareStoreAndNavigate( ); @@ -174,11 +174,11 @@ const CameraContainer = ( ) => { const handleNavigation = useCallback( async ( newPhotoState: PhotoState, hasSavePhotoPermission: boolean, - visionResult?: StoredResult | null + visionResult?: StoredResult | null, ) => { startFirebaseTrace( FIREBASE_TRACES.AI_CAMERA_TO_MATCH, - { [FIREBASE_TRACE_ATTRIBUTES.HAS_SAVE_PHOTO_PERMISSION]: `${hasSavePhotoPermission}` } + { [FIREBASE_TRACE_ATTRIBUTES.HAS_SAVE_PHOTO_PERMISSION]: `${hasSavePhotoPermission}` }, ); // fetch accurate user location, with a fallback to a course location // at the time the user taps AI shutter or multicapture checkmark @@ -192,19 +192,19 @@ const CameraContainer = ( ) => { newPhotoState, logStageIfAICamera, deleteStageIfAICamera, - visionResult + visionResult, } ); }, [ prepareStoreAndNavigate, navigationOptions, logStageIfAICamera, deleteStageIfAICamera, - startFirebaseTrace + startFirebaseTrace, ] ); const handleCheckmarkPress = useCallback( async ( newPhotoState: PhotoState, - visionResult: StoredResult | null + visionResult: StoredResult | null, ) => { if ( !showPhotoPermissionsGate ) { await handleNavigation( newPhotoState, true, visionResult ); @@ -216,7 +216,7 @@ const CameraContainer = ( ) => { handleNavigation, requestSavePhotoPermission, showPhotoPermissionsGate, - logStageIfAICamera + logStageIfAICamera, ] ); const toggleFlash = ( ) => { @@ -224,13 +224,13 @@ const CameraContainer = ( ) => { ...takePhotoOptions, flash: takePhotoOptions.flash === "on" ? "off" - : "on" + : "on", } ); }; const updateTakePhotoStore = async ( uri: string, - options?: { replaceExisting?: boolean } + options?: { replaceExisting?: boolean }, ): Promise => { const replaceExisting = options?.replaceExisting || false; @@ -252,7 +252,7 @@ const CameraContainer = ( ) => { const newCameraState = { cameraUris: [...newCameraUris], - evidenceToAdd: [...newEvidenceToAdd] + evidenceToAdd: [...newEvidenceToAdd], }; setCameraState( newCameraState ); @@ -316,11 +316,11 @@ const CameraContainer = ( ) => { if ( !loadingDevices && !device ) { Alert.alert( t( "No-Camera-Available" ), - t( "Could-not-find-a-camera-on-this-device" ) + t( "Could-not-find-a-camera-on-this-device" ), ); logger.error( "Camera started but no device was found. Length of the list of all devices: ", - devices.length + devices.length, ); navigation.goBack(); return null; @@ -362,23 +362,23 @@ const CameraContainer = ( ) => { await logStageIfAICamera( "request_save_photo_permission_complete" ); await handleNavigation( { cameraUris, - evidenceToAdd + evidenceToAdd, }, true ); }, onModalHide: async ( ) => { await logStageIfAICamera( "request_save_photo_permission_complete" ); await handleNavigation( { cameraUris, - evidenceToAdd + evidenceToAdd, }, false ); - } + }, } )} {renderLocationPermissionsGate( { onRequestGranted: ( ) => console.log( "granted in location permission gate" ), onRequestBlocked: ( ) => console.log( "blocked in location permission gate" ), onModalHide: async ( ) => { await logStageIfAICamera( "request_location_permission_complete" ); - } + }, } )} ); diff --git a/src/components/Camera/CameraView.tsx b/src/components/Camera/CameraView.tsx index 5bec2be22..08a040f84 100644 --- a/src/components/Camera/CameraView.tsx +++ b/src/components/Camera/CameraView.tsx @@ -2,33 +2,33 @@ import { useAppState } from "@react-native-community/hooks"; import { useIsFocused } from "@react-navigation/native"; import { Camera, - useCameraFormat + useCameraFormat, } from "components/Camera/helpers/visionCameraWrapper"; import useFocusTap from "components/Camera/hooks/useFocusTap"; import React, { - useCallback + useCallback, } from "react"; import { - Dimensions, Platform, StyleSheet + Dimensions, Platform, StyleSheet, } from "react-native"; import type { PanGesture, - PinchGesture + PinchGesture, } from "react-native-gesture-handler"; import { Gesture, - GestureDetector + GestureDetector, } from "react-native-gesture-handler"; import Reanimated from "react-native-reanimated"; import type { - CameraDevice, CameraDeviceFormat, CameraProps, CameraRuntimeError + CameraDevice, CameraDeviceFormat, CameraProps, CameraRuntimeError, } from "react-native-vision-camera"; import FocusSquare from "./FocusSquare"; const ReanimatedCamera = Reanimated.createAnimatedComponent( Camera ); Reanimated.addWhitelistedNativeProps( { - zoom: true + zoom: true, } ); interface Props { @@ -64,11 +64,11 @@ const CameraView = ( { panToZoom, pinchToZoom, resizeMode, - inactive + inactive, }: Props ) => { const { animatedStyle, - tapToFocus + tapToFocus, } = useFocusTap( cameraRef, device.supportsFocus ); // check if camera page is active @@ -87,15 +87,15 @@ const CameraView = ( { { videoAspectRatio: cameraScreen === "standard" ? standardVideoAspectRatio - : aiVideoAspectRatio + : aiVideoAspectRatio, }, { photoAspectRatio: cameraScreen === "standard" ? standardPhotoAspectRatio - : aiPhotoAspectRatio + : aiPhotoAspectRatio, }, { photoResolution: "max" }, - { videoResolution: "max" } + { videoResolution: "max" }, ] ); if ( Platform.OS === "android" ) { console.log( "Android is not using a specific camera format because we never got around to" ); @@ -154,8 +154,8 @@ const CameraView = ( { onClassifierError, onDeviceNotSupported, onCaptureError, - onCameraError - ] + onCameraError, + ], ); // Note that overflow-hidden handles what seems to be a bug in android in diff --git a/src/components/Camera/CameraWithDevice.tsx b/src/components/Camera/CameraWithDevice.tsx index 442c82eda..927c404d7 100644 --- a/src/components/Camera/CameraWithDevice.tsx +++ b/src/components/Camera/CameraWithDevice.tsx @@ -21,7 +21,7 @@ interface Props { takingPhoto: boolean; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type takePhotoAndStoreUri: Function; - newPhotoUris: Array; + newPhotoUris: object[]; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type setNewPhotoUris: Function; takePhotoOptions: object; @@ -44,7 +44,7 @@ const CameraWithDevice = ( { takePhotoOptions, userLocation, hasLocationPermissions, - requestLocationPermissions + requestLocationPermissions, }: Props ) => { const { isLandscapeMode } = useDeviceOrientation( ); const flexDirection = isTablet && isLandscapeMode diff --git a/src/components/Camera/FadeInOutView.tsx b/src/components/Camera/FadeInOutView.tsx index b4a67d5f2..7b56af45d 100644 --- a/src/components/Camera/FadeInOutView.tsx +++ b/src/components/Camera/FadeInOutView.tsx @@ -11,7 +11,7 @@ interface Props { const fade = value => ( { toValue: value, duration: 100, - useNativeDriver: true + useNativeDriver: true, } ); const FadeInOutView = ( { takingPhoto, cameraType }: Props ) => { @@ -21,7 +21,7 @@ const FadeInOutView = ( { takingPhoto, cameraType }: Props ) => { if ( takingPhoto ) { Animated.sequence( [ Animated.timing( fadeAnimation, fade( 1 ) ), - Animated.timing( fadeAnimation, fade( 0 ) ) + Animated.timing( fadeAnimation, fade( 0 ) ), ] ).start( ); } }, [takingPhoto, fadeAnimation] ); @@ -37,7 +37,7 @@ const FadeInOutView = ( { takingPhoto, cameraType }: Props ) => { height: "100%", width: "100%", backgroundColor: colors.black, - opacity: fadeAnimation + opacity: fadeAnimation, }} /> {( takingPhoto && cameraType === "AI" ) && ( diff --git a/src/components/Camera/SavePhotoPermissionGate.tsx b/src/components/Camera/SavePhotoPermissionGate.tsx index 8c593238e..40a95ad16 100644 --- a/src/components/Camera/SavePhotoPermissionGate.tsx +++ b/src/components/Camera/SavePhotoPermissionGate.tsx @@ -1,5 +1,5 @@ import PermissionGateContainer, { - WRITE_MEDIA_PERMISSIONS + WRITE_MEDIA_PERMISSIONS, } from "components/SharedComponents/PermissionGateContainer"; import React from "react"; import { useTranslation } from "sharedHooks"; @@ -15,7 +15,7 @@ const SavePhotoPermissionGate = ( { onPhotoPermissionGranted, onPhotoPermissionBlocked, permissionNeeded, - onModalHide + onModalHide, }: Props ) => { const { t } = useTranslation( ); return ( diff --git a/src/components/Camera/StandardCamera/CameraNavButtons.js b/src/components/Camera/StandardCamera/CameraNavButtons.js index 718bae518..08db56f45 100644 --- a/src/components/Camera/StandardCamera/CameraNavButtons.js +++ b/src/components/Camera/StandardCamera/CameraNavButtons.js @@ -24,7 +24,7 @@ const CameraNavButtons = ( { handleClose, photosTaken, rotatableAnimatedStyle, - takePhoto + takePhoto, }: Props ): Node => { const takePhotoButton = useMemo( ( ) => ( { const renderPhoneCameraOptions = () => ( <> diff --git a/src/components/Camera/StandardCamera/DiscardChangesSheet.js b/src/components/Camera/StandardCamera/DiscardChangesSheet.js index 63f03518b..ab004134b 100644 --- a/src/components/Camera/StandardCamera/DiscardChangesSheet.js +++ b/src/components/Camera/StandardCamera/DiscardChangesSheet.js @@ -1,7 +1,7 @@ // @flow import { - WarningSheet + WarningSheet, } from "components/SharedComponents"; import type { Node } from "react"; import React from "react"; @@ -16,7 +16,7 @@ type Props = { const DiscardChangesSheet = ( { setShowDiscardSheet, onDiscard, - hidden + hidden, }: Props ): Node => { const { t } = useTranslation( ); diff --git a/src/components/Camera/StandardCamera/PhotoCarousel.tsx b/src/components/Camera/StandardCamera/PhotoCarousel.tsx index f7e95010e..41da9c887 100644 --- a/src/components/Camera/StandardCamera/PhotoCarousel.tsx +++ b/src/components/Camera/StandardCamera/PhotoCarousel.tsx @@ -3,16 +3,16 @@ import MediaViewerModal from "components/MediaViewer/MediaViewerModal"; import { ActivityIndicator, INatIconButton } from "components/SharedComponents"; import { ImageBackground, Pressable, View } from "components/styledComponents"; import React, { - useCallback, useRef, useState + useCallback, useRef, useState, } from "react"; import { - FlatList + FlatList, } from "react-native"; import Modal from "react-native-modal"; import type { SharedValue } from "react-native-reanimated"; import Animated, { useAnimatedStyle, - withTiming + withTiming, } from "react-native-reanimated"; import { useTranslation } from "sharedHooks"; import useStore from "stores/useStore"; @@ -37,13 +37,13 @@ const SMALL_PHOTO_CLASSES = [ "rounded-sm", "w-[42px]", "h-[42x]", - "mx-[3px]" + "mx-[3px]", ] as const; const LARGE_PHOTO_CLASSES = [ "rounded-md", "w-[83px]", "h-[83px]", - "m-[8.5px]" + "m-[8.5px]", ] as const; const PhotoCarousel = ( { @@ -53,7 +53,7 @@ const PhotoCarousel = ( { isTablet, rotation, photoUris, - onDelete + onDelete, }: Props ) => { const deletePhotoFromObservation = useStore( state => state.deletePhotoFromObservation ); const { t } = useTranslation( ); @@ -76,10 +76,10 @@ const PhotoCarousel = ( { { rotateZ: rotation ? withTiming( `${-1 * rotation.get( )}deg` ) - : "0" - } - ] - } ) + : "0", + }, + ], + } ), ); const renderSkeleton = useCallback( ( ) => ( takingPhoto @@ -88,15 +88,15 @@ const PhotoCarousel = ( { className={classnames( "flex", { - "w-fit h-full": isTablet && isLandscapeMode + "w-fit h-full": isTablet && isLandscapeMode, }, - ...IMAGE_CONTAINER_CLASSES + ...IMAGE_CONTAINER_CLASSES, )} > @@ -107,7 +107,7 @@ const PhotoCarousel = ( { isTablet, isLandscapeMode, photoClasses, - takingPhoto + takingPhoto, ] ); const showDeletePhotoMode = useCallback( ( ) => { @@ -119,12 +119,12 @@ const PhotoCarousel = ( { const viewPhotoAtIndex = useCallback( ( index: number ) => { setTappedPhotoIndex( index ); }, [ - setTappedPhotoIndex + setTappedPhotoIndex, ] ); const renderPhotoOrEvidenceButton = useCallback( ( { item: photoUri, - index + index, } ) => ( <> {index === 0 && renderSkeleton( )} @@ -136,7 +136,7 @@ const PhotoCarousel = ( { testID="PhotoCarousel.photo" className={classnames( "overflow-hidden", - ...photoClasses + ...photoClasses, )} > { @@ -196,7 +196,7 @@ const PhotoCarousel = ( { renderSkeleton, showDeletePhotoMode, t, - viewPhotoAtIndex + viewPhotoAtIndex, ] ); const photoPreviewsList = ( @@ -231,7 +231,7 @@ const PhotoCarousel = ( { height: isTablet && isLandscapeMode ? photoUris.length * ( photoDim + photoGutter ) + photoGutter : photoDim + ( photoGutter * 2 ), - padding: photoGutter / 2 + padding: photoGutter / 2, }; return ( @@ -246,8 +246,8 @@ const PhotoCarousel = ( { x: pageX, y: pageY, w, - h - } ) + h, + } ), ) } // Dynamic calculation of these values kind of just doesn't work with tailwind. @@ -276,7 +276,7 @@ const PhotoCarousel = ( { position: "absolute", left: containerPos.x, top: containerPos.y, - ...containerStyle + ...containerStyle, }} > { photoPreviewsList } diff --git a/src/components/Camera/StandardCamera/PhotoPreview.tsx b/src/components/Camera/StandardCamera/PhotoPreview.tsx index 583a9f5fe..7d843276e 100644 --- a/src/components/Camera/StandardCamera/PhotoPreview.tsx +++ b/src/components/Camera/StandardCamera/PhotoPreview.tsx @@ -8,7 +8,7 @@ import PhotoCarousel, { LARGE_PHOTO_DIM, LARGE_PHOTO_GUTTER, SMALL_PHOTO_DIM, - SMALL_PHOTO_GUTTER + SMALL_PHOTO_GUTTER, } from "./PhotoCarousel"; interface Props { @@ -24,7 +24,7 @@ interface Props { const STYLE = { justifyContent: "center", flex: 0, - flexShrink: 1 + flexShrink: 1, } as const; const PhotoPreview = ( { @@ -34,7 +34,7 @@ const PhotoPreview = ( { onDelete, photoUris, rotation, - takingPhoto + takingPhoto, }: Props ) => { const { t } = useTranslation( ); const wrapperDim = isLargeScreen @@ -47,7 +47,7 @@ const PhotoPreview = ( { "text-white", "text-center", "text-xl", - "w-full" + "w-full", )} > {t( "Photos-you-take-will-appear-here" )} @@ -64,7 +64,7 @@ const PhotoPreview = ( { "w-[500px]", "-rotate-90", "left-[-190px]", - "top-[50%]" + "top-[50%]", )} > {t( "Photos-you-take-will-appear-here" )} diff --git a/src/components/Camera/StandardCamera/StandardCamera.js b/src/components/Camera/StandardCamera/StandardCamera.js index 3ba1a4f41..b3ba47bfb 100644 --- a/src/components/Camera/StandardCamera/StandardCamera.js +++ b/src/components/Camera/StandardCamera/StandardCamera.js @@ -12,7 +12,7 @@ import type { Node } from "react"; import React, { useCallback, useEffect, useMemo, - useState + useState, } from "react"; import DeviceInfo from "react-native-device-info"; import { Snackbar } from "react-native-paper"; @@ -29,7 +29,7 @@ import { handleCameraError, handleCaptureError, handleClassifierError, - handleDeviceNotSupported + handleDeviceNotSupported, } from "../helpers"; import CameraNavButtons from "./CameraNavButtons"; import CameraOptionsButtons from "./CameraOptionsButtons"; @@ -53,7 +53,7 @@ type Props = { takingPhoto: boolean, takePhotoAndStoreUri: Function, takePhotoOptions: Object, - newPhotoUris: Array, + newPhotoUris: Object[], setNewPhotoUris: Function }; @@ -68,7 +68,7 @@ const StandardCamera = ( { takePhotoAndStoreUri, takePhotoOptions, newPhotoUris, - setNewPhotoUris + setNewPhotoUris, }: Props ): Node => { "use no memo"; @@ -80,17 +80,17 @@ const StandardCamera = ( { pinchToZoom, resetZoom, showZoomButton, - zoomTextValue + zoomTextValue, } = useZoom( device ); const { rotatableAnimatedStyle, - rotation + rotation, } = useRotation( ); const navigation = useNavigation( ); const insets = useSafeAreaInsets(); const { loadTime } = usePerformance( { - isLoading: camera?.current !== null + isLoading: camera?.current !== null, } ); if ( isDebugMode( ) && loadTime ) { logger.info( loadTime ); @@ -103,7 +103,7 @@ const StandardCamera = ( { const totalObsPhotoUris = useMemo( ( ) => [...cameraUris, ...photoLibraryUris].length, - [cameraUris, photoLibraryUris] + [cameraUris, photoLibraryUris], ); const disallowAddingPhotos = totalObsPhotoUris >= MAX_PHOTOS_ALLOWED; @@ -120,7 +120,7 @@ const StandardCamera = ( { const { handleBackButtonPress, setShowDiscardSheet, - showDiscardSheet + showDiscardSheet, } = useBackPress( photosTaken ); useFocusEffect( @@ -132,7 +132,7 @@ const StandardCamera = ( { // for this hook // eslint-disable-next-line react-hooks/react-compiler // eslint-disable-next-line react-hooks/exhaustive-deps - }, [] ) + }, [] ), ); const deletePhotoByUri = useCallback( async ( photoUri: string ) => { diff --git a/src/components/Camera/StandardCamera/hooks/useBackPress.ts b/src/components/Camera/StandardCamera/hooks/useBackPress.ts index d7af83668..6fe89ef4c 100644 --- a/src/components/Camera/StandardCamera/hooks/useBackPress.ts +++ b/src/components/Camera/StandardCamera/hooks/useBackPress.ts @@ -2,10 +2,10 @@ import { useFocusEffect, useNavigation } from "@react-navigation/native"; import { getCurrentRoute } from "navigation/navigationUtils"; import { useCallback, - useState + useState, } from "react"; import { - BackHandler + BackHandler, } from "react-native"; import useExitObservationFlow from "sharedHooks/useExitObservationFlow"; @@ -30,7 +30,7 @@ const useBackPress = ( shouldShowDiscardSheet: boolean ) => { exitObservationFlow, navigation, setShowDiscardSheet, - shouldShowDiscardSheet + shouldShowDiscardSheet, ] ); useFocusEffect( @@ -46,13 +46,13 @@ const useBackPress = ( shouldShowDiscardSheet: boolean ) => { const backHandler = BackHandler.addEventListener( "hardwareBackPress", onBackPress ); return ( ) => backHandler.remove( ); - }, [handleBackButtonPress] ) + }, [handleBackButtonPress] ), ); return { handleBackButtonPress, setShowDiscardSheet, - showDiscardSheet + showDiscardSheet, }; }; diff --git a/src/components/Camera/TabletButtons.tsx b/src/components/Camera/TabletButtons.tsx index 870b0005a..84e18910a 100644 --- a/src/components/Camera/TabletButtons.tsx +++ b/src/components/Camera/TabletButtons.tsx @@ -25,7 +25,7 @@ const checkmarkClasses = [ `h-[${CAMERA_BUTTON_DIM}px]`, `w-[${CAMERA_BUTTON_DIM}px]`, "justify-center", - "items-center" + "items-center", ].join( " " ); const cameraOptionsClasses = [ @@ -34,7 +34,7 @@ const cameraOptionsClasses = [ "items-center", "justify-center", "rounded-full", - `w-[${CAMERA_BUTTON_DIM}px]` + `w-[${CAMERA_BUTTON_DIM}px]`, ].join( " " ); interface Props { @@ -70,7 +70,7 @@ const CameraButtonPlaceholder = ( { extraClassName }: { extraClassName?: string // "bg-deeppink", `w-[${CAMERA_BUTTON_DIM}px]`, `h-[${CAMERA_BUTTON_DIM}px]`, - extraClassName + extraClassName, )} /> ); @@ -95,7 +95,7 @@ const TabletButtons = ( { useLocation, toggleLocation, isDefaultMode, - deleteSentinelFile + deleteSentinelFile, }: Props ) => { const tabletCameraOptionsClasses = [ "absolute", @@ -104,7 +104,7 @@ const TabletButtons = ( { "mr-5", "p-0", "right-0", - "h-full" + "h-full", ]; return ( @@ -155,7 +155,7 @@ const TabletButtons = ( { { const path = rotatedOriginalPhotosPath; await RNFS.mkdir( path ); @@ -20,8 +20,8 @@ const savePhotoToDocumentsDirectory = async ( { width: cameraPhoto.width, height: cameraPhoto.height, - outputPath: path - } + outputPath: path, + }, ); // Remove original photo await unlink( cameraPhoto.path ); diff --git a/src/components/Camera/helpers/savePhotosToPhotoLibrary.ts b/src/components/Camera/helpers/savePhotosToPhotoLibrary.ts index fd5ded283..45ff5adfa 100644 --- a/src/components/Camera/helpers/savePhotosToPhotoLibrary.ts +++ b/src/components/Camera/helpers/savePhotosToPhotoLibrary.ts @@ -1,11 +1,11 @@ import { CameraRoll } from "@react-native-camera-roll/camera-roll"; import { permissionResultFromMultiple, - READ_WRITE_MEDIA_PERMISSIONS + READ_WRITE_MEDIA_PERMISSIONS, } from "components/SharedComponents/PermissionGateContainer"; import { t } from "i18next"; import { - Alert + Alert, } from "react-native"; import { checkMultiple, RESULTS } from "react-native-permissions"; import { log } from "sharedHelpers/logger"; @@ -24,10 +24,10 @@ const logger = log.extend( "savePhotosToPhotoLibrary" ); // $FlowIgnore export async function savePhotosToPhotoLibrary( uris: [string], - location: object + location: object, ) { const readWritePermissionResult = permissionResultFromMultiple( - await checkMultiple( READ_WRITE_MEDIA_PERMISSIONS ) + await checkMultiple( READ_WRITE_MEDIA_PERMISSIONS ), ); const savedPhotoUris = await uris.reduce( async ( memo, uri ) => { @@ -63,7 +63,7 @@ export async function savePhotosToPhotoLibrary( Alert.alert( t( "Not-enough-space-left-on-device" ), t( "Not-enough-space-left-on-device-try-again" ), - [{ text: t( "OK" ) }] + [{ text: t( "OK" ) }], ); return savedUris; } @@ -83,7 +83,7 @@ export async function savePhotosToPhotoLibrary( // We need the initial value even if we're not using it, otherwise reduce // will treat the first item in the array as the initial value and not // call the reducer function on it - Promise.resolve( [] ) + Promise.resolve( [] ), ); return savedPhotoUris; } diff --git a/src/components/Camera/helpers/visionCameraWrapper.ts b/src/components/Camera/helpers/visionCameraWrapper.ts index 9a12787f7..bf7a4b550 100644 --- a/src/components/Camera/helpers/visionCameraWrapper.ts +++ b/src/components/Camera/helpers/visionCameraWrapper.ts @@ -5,7 +5,7 @@ import { useCameraDevice, useCameraDevices, useCameraFormat, - useFrameProcessor + useFrameProcessor, } from "react-native-vision-camera"; export { @@ -13,5 +13,5 @@ export { useCameraDevice, useCameraDevices, useCameraFormat, - useFrameProcessor + useFrameProcessor, }; diff --git a/src/components/Camera/hooks/useDeviceStorageFull.js b/src/components/Camera/hooks/useDeviceStorageFull.js index e1359b392..6beff1197 100644 --- a/src/components/Camera/hooks/useDeviceStorageFull.js +++ b/src/components/Camera/hooks/useDeviceStorageFull.js @@ -1,9 +1,9 @@ import { useCallback, - useState + useState, } from "react"; import { - Alert + Alert, } from "react-native"; import DeviceInfo from "react-native-device-info"; import { useTranslation } from "sharedHooks"; @@ -22,7 +22,7 @@ const useDeviceStorageFull = ( ) => { const showStorageFullAlert = useCallback( () => Alert.alert( t( "Device-storage-full" ), t( "Device-storage-full-description" ), - [{ text: t( "OK" ) }] + [{ text: t( "OK" ) }], ), [t] ); DeviceInfo.getFreeDiskStorage().then( freeDiskStorage => { @@ -33,7 +33,7 @@ const useDeviceStorageFull = ( ) => { return { deviceStorageFull, - showStorageFullAlert + showStorageFullAlert, }; }; diff --git a/src/components/Camera/hooks/useFocusTap.ts b/src/components/Camera/hooks/useFocusTap.ts index 70b330866..ed430afac 100644 --- a/src/components/Camera/hooks/useFocusTap.ts +++ b/src/components/Camera/hooks/useFocusTap.ts @@ -1,15 +1,15 @@ import type { Camera } from "components/Camera/helpers/visionCameraWrapper"; import type React from "react"; import { - useCallback, useMemo, useRef, useState + useCallback, useMemo, useRef, useState, } from "react"; import { Animated } from "react-native"; import type { GestureStateChangeEvent, - TapGestureHandlerEventPayload + TapGestureHandlerEventPayload, } from "react-native-gesture-handler"; import { - Gesture + Gesture, } from "react-native-gesture-handler"; const HALF_SIZE_FOCUS_BOX = 33; @@ -28,7 +28,7 @@ const useFocusTap = ( cameraRef: React.RefObject, supportsFocus: return ( { left: tappedCoordinates.x - HALF_SIZE_FOCUS_BOX, top: tappedCoordinates.y - HALF_SIZE_FOCUS_BOX, - opacity: focusOpacity + opacity: focusOpacity, } ); }, [tappedCoordinates, focusOpacity] ); @@ -46,13 +46,13 @@ const useFocusTap = ( cameraRef: React.RefObject, supportsFocus: { toValue: 0, duration: 2000, - useNativeDriver: true - } + useNativeDriver: true, + }, ).start( ); }, [ cameraRef, supportsFocus, - focusOpacity + focusOpacity, ] ); const tapToFocus = useMemo( ( ) => Gesture.Tap( ) @@ -62,7 +62,7 @@ const useFocusTap = ( cameraRef: React.RefObject, supportsFocus: return { animatedStyle, tapToFocus, - tappedCoordinates + tappedCoordinates, }; }; diff --git a/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts b/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts index 8115e3d75..816e6ba08 100644 --- a/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts +++ b/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts @@ -1,13 +1,13 @@ import { useNavigation, useRoute } from "@react-navigation/native"; import useDeviceStorageFull from "components/Camera/hooks/useDeviceStorageFull"; import { - useCallback + useCallback, } from "react"; import Observation from "realmModels/Observation"; import ObservationPhoto from "realmModels/ObservationPhoto"; import fetchPlaceName from "sharedHelpers/fetchPlaceName"; import { - useLayoutPrefs + useLayoutPrefs, } from "sharedHooks"; import { SCREEN_AFTER_PHOTO_EVIDENCE } from "stores/createLayoutSlice"; import useStore from "stores/useStore"; @@ -39,7 +39,7 @@ const usePrepareStoreAndNavigate = ( ) => { uris, addPhotoPermissionResult, userLocation, - logStageIfAICamera + logStageIfAICamera, ) => { await logStageIfAICamera( "save_photos_to_photo_library_start" ); if ( addPhotoPermissionResult !== "granted" ) { @@ -68,7 +68,7 @@ const usePrepareStoreAndNavigate = ( ) => { deviceStorageFull, setCameraState, setSavingPhoto, - showStorageFullAlert + showStorageFullAlert, ] ); const createObsWithCameraPhotos = useCallback( async ( @@ -76,7 +76,7 @@ const usePrepareStoreAndNavigate = ( ) => { addPhotoPermissionResult, userLocation, logStageIfAICamera, - visionResult + visionResult, ) => { const newObservation = await Observation.new( ); @@ -93,7 +93,7 @@ const usePrepareStoreAndNavigate = ( ) => { newObservation.observationPhotos = await ObservationPhoto .createObsPhotosWithPosition( uris, { position: 0, - local: true + local: true, } ); if ( !isDefaultMode && screenAfterPhotoEvidence === SCREEN_AFTER_PHOTO_EVIDENCE.OBS_EDIT @@ -105,26 +105,26 @@ const usePrepareStoreAndNavigate = ( ) => { uris, addPhotoPermissionResult, userLocation, - logStageIfAICamera + logStageIfAICamera, ); }, [ isDefaultMode, screenAfterPhotoEvidence, setObservations, - handleSavingToPhotoLibrary + handleSavingToPhotoLibrary, ] ); const updateObsWithCameraPhotos = useCallback( async ( addPhotoPermissionResult, userLocation, - logStageIfAICamera + logStageIfAICamera, ) => { const obsPhotos = await ObservationPhoto.createObsPhotosWithPosition( evidenceToAdd, { position: numOfObsPhotos, - local: true - } + local: true, + }, ); const updatedCurrentObservation = Observation .appendObsPhotos( obsPhotos, currentObservation ); @@ -137,7 +137,7 @@ const usePrepareStoreAndNavigate = ( ) => { evidenceToAdd, addPhotoPermissionResult, userLocation, - logStageIfAICamera + logStageIfAICamera, ); }, [ evidenceToAdd, @@ -146,7 +146,7 @@ const usePrepareStoreAndNavigate = ( ) => { observations, currentObservationIndex, updateObservations, - handleSavingToPhotoLibrary + handleSavingToPhotoLibrary, ] ); const prepareStoreAndNavigate = useCallback( async ( { @@ -155,7 +155,7 @@ const usePrepareStoreAndNavigate = ( ) => { newPhotoState, logStageIfAICamera, deleteStageIfAICamera, - visionResult + visionResult, } ) => { if ( userLocation !== null ) { logStageIfAICamera( "fetch_user_location_complete" ); @@ -175,7 +175,7 @@ const usePrepareStoreAndNavigate = ( ) => { addPhotoPermissionResult, userLocation, logStageIfAICamera, - visionResult + visionResult, ); await deleteStageIfAICamera( ); setSentinelFileName( null ); @@ -184,13 +184,13 @@ const usePrepareStoreAndNavigate = ( ) => { if ( isDefaultMode ) { return navigation.push( "Match", { entryScreen: "CameraWithDevice", - lastScreen: "CameraWithDevice" + lastScreen: "CameraWithDevice", } ); } // Camera navigates based on user settings to Match, Suggestions, or ObsEdit return navigation.push( screenAfterPhotoEvidence, { entryScreen: "CameraWithDevice", - lastScreen: "CameraWithDevice" + lastScreen: "CameraWithDevice", } ); }, [ cameraUris, @@ -200,7 +200,7 @@ const usePrepareStoreAndNavigate = ( ) => { navigation, updateObsWithCameraPhotos, screenAfterPhotoEvidence, - isDefaultMode + isDefaultMode, ] ); return prepareStoreAndNavigate; diff --git a/src/components/Camera/hooks/useRotation.ts b/src/components/Camera/hooks/useRotation.ts index d65653453..6f58b2e0a 100644 --- a/src/components/Camera/hooks/useRotation.ts +++ b/src/components/Camera/hooks/useRotation.ts @@ -2,12 +2,12 @@ import { useEffect } from "react"; import { useAnimatedStyle, useSharedValue, - withTiming + withTiming, } from "react-native-reanimated"; import useDeviceOrientation, { LANDSCAPE_LEFT, LANDSCAPE_RIGHT, - PORTRAIT_UPSIDE_DOWN + PORTRAIT_UPSIDE_DOWN, } from "sharedHooks/useDeviceOrientation"; const rotationValue = ( deviceOrientation: string | undefined ) => { @@ -36,15 +36,15 @@ const useRotation = ( ) => { () => ( { transform: [ { - rotateZ: withTiming( `${-1 * ( rotation.get( ) || 0 )}deg` ) - } - ] - } ) + rotateZ: withTiming( `${-1 * ( rotation.get( ) || 0 )}deg` ), + }, + ], + } ), ); return { rotatableAnimatedStyle, - rotation + rotation, }; }; diff --git a/src/components/Camera/hooks/useSavePhotoPermission.tsx b/src/components/Camera/hooks/useSavePhotoPermission.tsx index 0f56fc3ef..7ca7e8752 100644 --- a/src/components/Camera/hooks/useSavePhotoPermission.tsx +++ b/src/components/Camera/hooks/useSavePhotoPermission.tsx @@ -1,11 +1,11 @@ import { permissionResultFromMultiple, - WRITE_MEDIA_PERMISSIONS + WRITE_MEDIA_PERMISSIONS, } from "components/SharedComponents/PermissionGateContainer"; import React, { useCallback, useEffect, useState } from "react"; import { checkMultiple, - RESULTS + RESULTS, } from "react-native-permissions"; import SavePhotoPermissionGate from "../SavePhotoPermissionGate"; @@ -38,7 +38,7 @@ const useSavePhotoPermission = ( ) => { const { onPermissionGranted, onPermissionBlocked, - onModalHide + onModalHide, } = callbacks || { }; // this prevents infinite rerenders of the SavePhotoPermissionGate component @@ -74,12 +74,12 @@ const useSavePhotoPermission = ( ) => { // referential stability const requestPermissions = useCallback( ( ) => setShowPermissionGate( true ), - [] + [], ); const checkPermissions = useCallback( async () => { const permissionsResult = permissionResultFromMultiple( - await checkMultiple( WRITE_MEDIA_PERMISSIONS ) + await checkMultiple( WRITE_MEDIA_PERMISSIONS ), ); if ( permissionsResult === RESULTS.GRANTED ) { setHasPermissions( true ); @@ -101,7 +101,7 @@ const useSavePhotoPermission = ( ) => { renderPermissionsGate, requestPermissions, hasBlockedPermissions, - checkPermissions + checkPermissions, }; }; diff --git a/src/components/Camera/hooks/useZoom.ts b/src/components/Camera/hooks/useZoom.ts index 4ac24eaab..6815670e1 100644 --- a/src/components/Camera/hooks/useZoom.ts +++ b/src/components/Camera/hooks/useZoom.ts @@ -3,10 +3,10 @@ import { useCallback, useEffect, useMemo, - useState + useState, } from "react"; import { - Gesture + Gesture, } from "react-native-gesture-handler"; import { Extrapolation, @@ -14,7 +14,7 @@ import { runOnJS, useAnimatedProps, useSharedValue, - withSpring + withSpring, } from "react-native-reanimated"; import type { CameraDevice, CameraProps } from "react-native-vision-camera"; @@ -98,7 +98,7 @@ const useZoom = ( device: CameraDevice ): object => { Math.abs( curr - newZoom ) < Math.abs( prev - newZoom ) ? curr : prev ); - } + }, ); setZoomTextValue( closestZoomTextValue ); }, [zoomButtonOptions, minZoom] ); @@ -110,7 +110,7 @@ const useZoom = ( device: CameraDevice ): object => { newValue, [-1, 0, 1], [minZoom, startZoom.get( ), maxZoomWithPinch], - Extrapolation.CLAMP + Extrapolation.CLAMP, ); zoom.set( newZoom ); @@ -118,7 +118,7 @@ const useZoom = ( device: CameraDevice ): object => { }, [maxZoomWithPinch, minZoom, updateZoomTextValue, startZoom, zoom] ); const animatedProps = useAnimatedProps < CameraProps >( - () => ( { zoom: zoom.get( ) } ) + () => ( { zoom: zoom.get( ) } ), ); const pinchToZoom = useMemo( ( ) => Gesture.Pinch( ) @@ -133,12 +133,12 @@ const useZoom = ( device: CameraDevice ): object => { e.scale, [1 - 1 / SCALE_FULL_ZOOM, 1, SCALE_FULL_ZOOM], [-1, 0, 1], - Extrapolation.CLAMP + Extrapolation.CLAMP, ); onZoomChange( newValue ); } ), [ onZoomChange, - onZoomStart + onZoomStart, ] ); const yDiff = useSharedValue( 0 ); @@ -159,7 +159,7 @@ const useZoom = ( device: CameraDevice ): object => { yDiff.get( ), [PAN_ZOOM_MIN_DISTANCE, 0, PAN_ZOOM_MAX_DISTANCE], [-1, 0, 1], - Extrapolation.CLAMP + Extrapolation.CLAMP, ) * -1; onZoomChange( newValue ); } ) @@ -174,7 +174,7 @@ const useZoom = ( device: CameraDevice ): object => { pinchToZoom, resetZoom, showZoomButton: device?.isMultiCam, - zoomTextValue + zoomTextValue, }; }; diff --git a/src/components/Developer/Developer.tsx b/src/components/Developer/Developer.tsx index ff766e775..cacea3387 100644 --- a/src/components/Developer/Developer.tsx +++ b/src/components/Developer/Developer.tsx @@ -6,7 +6,7 @@ import { Button, Heading1, Heading2, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import { fontMonoClass, View } from "components/styledComponents"; import { t } from "i18next"; @@ -20,7 +20,7 @@ import useLogs from "sharedHooks/useLogs"; import type { DirectoryEntrySize } from "./hooks/useAppSize"; import useAppSize, { - formatAppSizeString, formatSizeUnits, getTotalDirectorySize + formatAppSizeString, formatSizeUnits, getTotalDirectorySize, } from "./hooks/useAppSize"; const H1 = ( { children }: PropsWithChildren ) => ( @@ -47,7 +47,7 @@ const CODE = ( { children, optionalClassName }: CODEProps ) => ( selectable className={classnames( fontMonoClass, - optionalClassName + optionalClassName, )} > {children} @@ -56,21 +56,21 @@ const CODE = ( { children, optionalClassName }: CODEProps ) => ( const modelFileName = Platform.select( { ios: Config.IOS_MODEL_FILE_NAME, - android: Config.ANDROID_MODEL_FILE_NAME + android: Config.ANDROID_MODEL_FILE_NAME, } ); const taxonomyFileName = Platform.select( { ios: Config.IOS_TAXONOMY_FILE_NAME, - android: Config.ANDROID_TAXONOMY_FILE_NAME + android: Config.ANDROID_TAXONOMY_FILE_NAME, } ); const geomodelFileName = Platform.select( { ios: Config.IOS_GEOMODEL_FILE_NAME, - android: Config.ANDROID_GEOMODEL_FILE_NAME + android: Config.ANDROID_GEOMODEL_FILE_NAME, } ); const boldClassname = ( line: string, isDirectory = false ) => classnames( { "text-red font-bold": line.includes( "MB" ), - "text-blue": isDirectory - } + "text-blue": isDirectory, + }, ); interface DirectorySizesProps { @@ -167,8 +167,8 @@ const Developer = () => { status: 422, context: { routeName: "MyObservations", - timestamp: new Date().toISOString() - } + timestamp: new Date().toISOString(), + }, } ); }} text="TEST INATAPIERROR" @@ -178,7 +178,7 @@ const Developer = () => { onPress={() => { throw new INatApiTooManyRequestsError( { routeName: "TaxonDetails", - timestamp: new Date().toISOString() + timestamp: new Date().toISOString(), } ); }} text="TEST API TOO MANY REQUESTS ERROR" diff --git a/src/components/Developer/Log.js b/src/components/Developer/Log.js index 6049a7fcc..7c2f1a4a4 100644 --- a/src/components/Developer/Log.js +++ b/src/components/Developer/Log.js @@ -3,18 +3,18 @@ import { Button, Heading4, INatIconButton, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import { fontMonoClass, TextInput, - View + View, } from "components/styledComponents"; import type { Node } from "react"; import React, { useCallback, useEffect, - useState + useState, } from "react"; import { Platform, Text } from "react-native"; import useLogs from "sharedHooks/useLogs"; @@ -47,7 +47,7 @@ const Log = (): Node => { useEffect( ( ) => navigation.setOptions( { headerRight } ), - [headerRight, navigation] + [headerRight, navigation], ); useEffect( ( ) => { diff --git a/src/components/Developer/UiLibrary.js b/src/components/Developer/UiLibrary.js index 3231a50ec..d713e2c4b 100644 --- a/src/components/Developer/UiLibrary.js +++ b/src/components/Developer/UiLibrary.js @@ -1,16 +1,16 @@ import { useNavigation } from "@react-navigation/native"; import { Body1, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { - Pressable + Pressable, } from "components/styledComponents"; import { sortBy } from "lodash"; import type { Node } from "react"; import React from "react"; import { - FlatList + FlatList, } from "react-native"; // Note: you need to add here and in UiLibraryItem @@ -24,7 +24,7 @@ const ITEMS = sortBy( [ { title: "TaxonResult", component: "TaxonResultDemo" }, { title: "ObsGridItem", component: "ObsGridItemDemo" }, { title: "TaxonGridItem", component: "TaxonGridItemDemo" }, - { title: "PivotCards", component: "PivotCardsDemo" } + { title: "PivotCards", component: "PivotCardsDemo" }, ], item => item.title ); ITEMS.push( { title: "Everything Else", component: "Misc" } ); diff --git a/src/components/Developer/UiLibrary/ActivityIndicatorDemo.js b/src/components/Developer/UiLibrary/ActivityIndicatorDemo.js index 4424add87..6eed5819d 100644 --- a/src/components/Developer/UiLibrary/ActivityIndicatorDemo.js +++ b/src/components/Developer/UiLibrary/ActivityIndicatorDemo.js @@ -1,5 +1,5 @@ import { - ActivityIndicator + ActivityIndicator, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; diff --git a/src/components/Developer/UiLibrary/Buttons.js b/src/components/Developer/UiLibrary/Buttons.js index 182dd2480..bf0c7ea66 100644 --- a/src/components/Developer/UiLibrary/Buttons.js +++ b/src/components/Developer/UiLibrary/Buttons.js @@ -9,7 +9,7 @@ import { Heading2, Heading3, INatIconButton, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React, { useState } from "react"; @@ -220,7 +220,7 @@ const Buttons = ( ) => { className="bg-yellow" onPress={() => Alert.alert( "Default INatIconButton", - "Should be the minimum accessible size by default" + "Should be the minimum accessible size by default", )} accessibilityLabel="Close button" /> @@ -230,7 +230,7 @@ const Buttons = ( ) => { className="bg-yellow" onPress={() => Alert.alert( "Custom INatIconButton", - "The point is to adjust the interactive area and the icon size independently" + "The point is to adjust the interactive area and the icon size independently", )} size={10} width={50} diff --git a/src/components/Developer/UiLibrary/FloatingActionBarDemo.js b/src/components/Developer/UiLibrary/FloatingActionBarDemo.js index 937dc0b9d..447da1094 100644 --- a/src/components/Developer/UiLibrary/FloatingActionBarDemo.js +++ b/src/components/Developer/UiLibrary/FloatingActionBarDemo.js @@ -1,7 +1,7 @@ import { FloatingActionBar, Heading2, - INatIconButton + INatIconButton, } from "components/SharedComponents"; import React from "react"; import colors from "styles/tailwindColors"; diff --git a/src/components/Developer/UiLibrary/Icons.js b/src/components/Developer/UiLibrary/Icons.js index b6e5f3225..2ab4dae96 100644 --- a/src/components/Developer/UiLibrary/Icons.js +++ b/src/components/Developer/UiLibrary/Icons.js @@ -1,7 +1,7 @@ import { Body1, INatIcon, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import glyphmap from "components/SharedComponents/INatIcon/glyphmap.json"; import { View } from "components/styledComponents"; diff --git a/src/components/Developer/UiLibrary/Misc.js b/src/components/Developer/UiLibrary/Misc.js index 00550f750..a33317893 100644 --- a/src/components/Developer/UiLibrary/Misc.js +++ b/src/components/Developer/UiLibrary/Misc.js @@ -28,7 +28,7 @@ import { Tabs, UploadStatus, UserIcon, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { ScrollView, View } from "components/styledComponents"; import { RealmContext } from "providers/contexts"; @@ -56,22 +56,22 @@ const Misc = (): Node => { taxon: { // eslint-disable-next-line max-len default_photo: { - attribution: "(c) Ján Svetlík, some rights reserved (CC BY-NC-ND)", id: 3688643, license_code: "cc-by-nc-nd", url: "https://inaturalist-open-data.s3.amazonaws.com/photos/3688643/square.jpg" + attribution: "(c) Ján Svetlík, some rights reserved (CC BY-NC-ND)", id: 3688643, license_code: "cc-by-nc-nd", url: "https://inaturalist-open-data.s3.amazonaws.com/photos/3688643/square.jpg", }, id: 4343, name: "Larus", preferred_common_name: "Large White-headed Gulls", rank: "genus", - rank_level: 10 + rank_level: 10, }, user: { icon_url: "https://static.inaturalist.org/attachments/users/icons/1044550/medium.jpg?1653532155", id: 1, locale: null, - login: "frogfinder" + login: "frogfinder", }, uuid: "9abd103b-097e-4d32-a0a3-6a23f98ca333", - vision: false + vision: false, }; const aves = { @@ -81,7 +81,7 @@ const Misc = (): Node => { rank: "family", rank_level: 60, iconic_taxon_name: "Aves", - isIconic: true + isIconic: true, }; const taxonWithPhoto = realm.objects( "Taxon" ).filtered( "defaultPhoto.url != nil" )[0] || aves; const species = realm.objects( "Taxon" ) @@ -116,7 +116,7 @@ const Misc = (): Node => { currentUser || { icon_url: "https://static.inaturalist.org/attachments/users/icons/1044550/medium.jpg?1653532155", - login: "turtletamer74" + login: "turtletamer74", } } /> @@ -137,15 +137,15 @@ const Misc = (): Node => { text: "TAB1", onPress: () => { console.log( "TAB1" ); - } + }, }, { id: "TAB2", text: "TAB2", onPress: () => { console.log( "TAB2" ); - } - } + }, + }, ]} activeId="TAB1" /> @@ -160,7 +160,7 @@ const Misc = (): Node => { @@ -168,7 +168,7 @@ const Misc = (): Node => { observation={{ latitude: 30.18183, longitude: -85.760449, - place_guess: "Panama City Beach, Florida" + place_guess: "Panama City Beach, Florida", }} /> @@ -322,7 +322,7 @@ const Misc = (): Node => { layout="vertical" observation={{ comments: [1, 2, 3], - identifications: [1, 2, 3, 4, 5, 6] + identifications: [1, 2, 3, 4, 5, 6], }} /> PhotoCount @@ -370,7 +370,7 @@ const Misc = (): Node => { id: 1, title: "Project Title", project_type: "collection", - icon: "https://static.inaturalist.org/attachments/users/icons/1044550/medium.jpg?1653532155" + icon: "https://static.inaturalist.org/attachments/users/icons/1044550/medium.jpg?1653532155", }} /> { id: 2, title: "Project Title with a very long title that should wrap to the next line", project_type: "collection", - icon: "https://static.inaturalist.org/attachments/users/icons/1044550/medium.jpg?1653532155" + icon: "https://static.inaturalist.org/attachments/users/icons/1044550/medium.jpg?1653532155", }} /> RadioButtonRow diff --git a/src/components/Developer/UiLibrary/ObsGridItemDemo.js b/src/components/Developer/UiLibrary/ObsGridItemDemo.js index 39634bf36..e19e68585 100644 --- a/src/components/Developer/UiLibrary/ObsGridItemDemo.js +++ b/src/components/Developer/UiLibrary/ObsGridItemDemo.js @@ -2,7 +2,7 @@ import ObsGridItem from "components/ObservationsFlashList/ObsGridItem"; import { Heading1, Heading2, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; @@ -10,7 +10,7 @@ import React from "react"; import { makeObservation, makeObservationPhoto, - makeObservationSound + makeObservationSound, } from "./ObsListItemDemo"; /* eslint-disable i18next/no-literal-string */ @@ -22,7 +22,7 @@ const ObsGridItemDemo = ( ) => ( Photo Photos @@ -30,21 +30,21 @@ const ObsGridItemDemo = ( ) => ( observation={makeObservation( { observationPhotos: [ makeObservationPhoto(), - makeObservationPhoto() - ] + makeObservationPhoto(), + ], } )} /> 20 Photos makeObservationPhoto() ) + observationPhotos: [...Array( 20 ).keys()].map( _idx => makeObservationPhoto() ), } )} /> Sound + Photo Sound + Photos @@ -52,15 +52,15 @@ const ObsGridItemDemo = ( ) => ( observation={makeObservation( { observationPhotos: [ makeObservationPhoto(), - makeObservationPhoto() + makeObservationPhoto(), ], - observationSounds: [makeObservationSound()] + observationSounds: [makeObservationSound()], } )} /> Sound No Media @@ -76,7 +76,7 @@ const ObsGridItemDemo = ( ) => ( true, - missingBasics: () => true + missingBasics: () => true, } )} uploadProgress={0} /> diff --git a/src/components/Developer/UiLibrary/ObsListItemDemo.js b/src/components/Developer/UiLibrary/ObsListItemDemo.js index 2301f73ee..ef56e1f7b 100644 --- a/src/components/Developer/UiLibrary/ObsListItemDemo.js +++ b/src/components/Developer/UiLibrary/ObsListItemDemo.js @@ -3,7 +3,7 @@ import ObsListItem from "components/ObservationsFlashList/ObsListItem"; import { Heading1, Heading2, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; @@ -12,7 +12,7 @@ export function makeObservation( options = {} ) { return { uuid: faker.string.uuid( ), missingBasics: ( ) => false, - ...options + ...options, }; } @@ -22,7 +22,7 @@ export function makePhoto( options = { } ) { attribution: faker.lorem.sentence( ), licenseCode: "cc-by-nc", url: faker.image.url( ), - ...options + ...options, }; } @@ -30,7 +30,7 @@ export function makeObservationPhoto( options = {} ) { return { uuid: faker.string.uuid( ), photo: makePhoto( ), - ...options + ...options, }; } @@ -38,7 +38,7 @@ export function makeObservationSound( options = {} ) { return { uuid: faker.string.uuid( ), file_url: faker.system.filePath( ), - ...options + ...options, }; } @@ -51,7 +51,7 @@ const ObsListItemDemo = ( ) => ( Photo Photos @@ -59,15 +59,15 @@ const ObsListItemDemo = ( ) => ( observation={makeObservation( { observationPhotos: [ makeObservationPhoto(), - makeObservationPhoto() - ] + makeObservationPhoto(), + ], } )} /> Sound + Photo Sound + Photos @@ -75,15 +75,15 @@ const ObsListItemDemo = ( ) => ( observation={makeObservation( { observationPhotos: [ makeObservationPhoto(), - makeObservationPhoto() + makeObservationPhoto(), ], - observationSounds: [makeObservationSound()] + observationSounds: [makeObservationSound()], } )} /> Sound No Media @@ -97,8 +97,8 @@ const ObsListItemDemo = ( ) => ( iconic_taxon_name: "Insecta", preferred_common_name: "Some weird insect", name: "Foo bar", - rank_level: 10 - } + rank_level: 10, + }, } )} /> Upload statuses @@ -110,7 +110,7 @@ const ObsListItemDemo = ( ) => ( true, - missingBasics: () => true + missingBasics: () => true, } )} uploadProgress={0} /> @@ -132,7 +132,7 @@ const ObsListItemDemo = ( ) => ( diff --git a/src/components/Developer/UiLibrary/PivotCardsDemo.js b/src/components/Developer/UiLibrary/PivotCardsDemo.js index adfad726c..ea59afb65 100644 --- a/src/components/Developer/UiLibrary/PivotCardsDemo.js +++ b/src/components/Developer/UiLibrary/PivotCardsDemo.js @@ -3,11 +3,11 @@ import { FiftyObservationCard, FiveObservationCard, NotificationOnboarding, - OneObservationCard + OneObservationCard, } from "components/OnboardingModal/PivotCards"; import { Button, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React, { useState } from "react"; @@ -26,24 +26,24 @@ const Buttons = ( ) => { const pivotCards = [ { title: "Account Creation", - component: AccountCreationCard + component: AccountCreationCard, }, { title: "First Observation", - component: OneObservationCard + component: OneObservationCard, }, { title: "Five Observation", - component: FiveObservationCard + component: FiveObservationCard, }, { title: "Fifty Observation", - component: FiftyObservationCard + component: FiftyObservationCard, }, { title: "Notification Onboarding", - component: NotificationOnboarding - } + component: NotificationOnboarding, + }, ]; return ( @@ -66,7 +66,7 @@ const Buttons = ( ) => { onPress={() => setShowingModal( index )} /> {React.createElement( component, { - triggerCondition: modalIndex === index + triggerCondition: modalIndex === index, } )} ) )} diff --git a/src/components/Developer/UiLibrary/TaxonGridItemDemo.js b/src/components/Developer/UiLibrary/TaxonGridItemDemo.js index 3acae2886..b7ad4d60e 100644 --- a/src/components/Developer/UiLibrary/TaxonGridItemDemo.js +++ b/src/components/Developer/UiLibrary/TaxonGridItemDemo.js @@ -2,7 +2,7 @@ import { faker } from "@faker-js/faker"; import { Heading1, Heading2, - ScrollViewWrapper + ScrollViewWrapper, } from "components/SharedComponents"; import TaxonGridItem from "components/SharedComponents/TaxonGridItem"; import { View } from "components/styledComponents"; @@ -19,7 +19,7 @@ function makeTaxon( options = {} ) { preferred_common_name: faker.person.fullName(), rank: "species", rank_level: 10, - ...options + ...options, }; } @@ -27,13 +27,13 @@ export function makeTaxonPhoto( options = {} ) { return { uuid: faker.string.uuid( ), photo: makePhoto( ), - ...options + ...options, }; } const STYLE = { width: 200, - height: 200 + height: 200, }; /* eslint-disable i18next/no-literal-string */ @@ -46,7 +46,7 @@ const TaxonGridItemDemo = ( ) => ( Photo @@ -55,14 +55,14 @@ const TaxonGridItemDemo = ( ) => ( No Media w/ Iconic Taxon Species Seen { @@ -33,7 +33,7 @@ const UiLibraryItem = ( ) => { const { params } = useRoute( ); useEffect( ( ) => navigation.setOptions( { title: params.title } ), - [navigation, params.title] + [navigation, params.title], ); // For reasons I don't understand hot reload doesn't work with this LIBRARY diff --git a/src/components/Developer/hooks/useAppSize.ts b/src/components/Developer/hooks/useAppSize.ts index e5c2a9965..2288ae296 100644 --- a/src/components/Developer/hooks/useAppSize.ts +++ b/src/components/Developer/hooks/useAppSize.ts @@ -3,7 +3,7 @@ import { photoLibraryPhotosPath, photoUploadPath, rotatedOriginalPhotosPath, - soundUploadPath + soundUploadPath, } from "appConstants/paths"; import _ from "lodash"; import { useEffect, useState } from "react"; @@ -37,62 +37,62 @@ export function formatSizeUnits( bytes: number ) { const sharedDirectories = [ { path: RNFS.DocumentDirectoryPath, - directoryName: "DocumentDirectory" + directoryName: "DocumentDirectory", }, { path: RNFS.CachesDirectoryPath, - directoryName: "CachesDirectory" + directoryName: "CachesDirectory", }, { path: RNFS.TemporaryDirectoryPath, - directoryName: "TemporaryDirectory" + directoryName: "TemporaryDirectory", }, { path: computerVisionPath, - directoryName: "ComputerVisionSuggestions" + directoryName: "ComputerVisionSuggestions", }, { path: photoLibraryPhotosPath, - directoryName: "PhotoLibraryPhotos" + directoryName: "PhotoLibraryPhotos", }, { path: photoUploadPath, - directoryName: "PhotoUploads" + directoryName: "PhotoUploads", }, { path: rotatedOriginalPhotosPath, - directoryName: "RotatedOriginalPhotos" + directoryName: "RotatedOriginalPhotos", }, { path: soundUploadPath, - directoryName: "SoundUploads" - } + directoryName: "SoundUploads", + }, ]; const iOSDirectories = [ { path: RNFS.MainBundlePath, - directoryName: "MainBundle" + directoryName: "MainBundle", }, { path: RNFS.LibraryDirectoryPath, - directoryName: "LibraryDirectory" - } + directoryName: "LibraryDirectory", + }, ]; const androidDirectories = [ { path: RNFS.DownloadDirectoryPath, - directoryName: "DownloadDirectory" + directoryName: "DownloadDirectory", }, { path: RNFS.ExternalDirectoryPath, - directoryName: "ExternalDirectory" + directoryName: "ExternalDirectory", }, { path: RNFS.ExternalStorageDirectoryPath, - directoryName: "ExternalStorageDirectory" - } + directoryName: "ExternalStorageDirectory", + }, ]; export const directories = sharedDirectories.concat( Platform.OS === "android" @@ -108,7 +108,7 @@ export async function getDirectoryEntrySizes( directory: string ): Promise ( { name, - size + size, } ) ); } @@ -128,8 +128,8 @@ async function fetchAppSize(): Promise { const maybeExistingDirectories = await Promise.all( directories.map( async directory => ( { directory, - exists: await RNFS.exists( directory.path ) - } ) ) + exists: await RNFS.exists( directory.path ), + } ) ), ); const existingDirectories = maybeExistingDirectories .filter( dir => dir.exists ) @@ -139,7 +139,7 @@ async function fetchAppSize(): Promise { existingDirectories.map( async dir => { const directoryEntrySizes = await getDirectoryEntrySizes( dir.path ); return [dir.directoryName, directoryEntrySizes] as [string, DirectoryEntrySize[]]; - } ) + } ), ); const directorySizesByDirectory = Object.fromEntries( directoryToDirectorySizesKvps ); return directorySizesByDirectory; diff --git a/src/components/Donate/Donate.tsx b/src/components/Donate/Donate.tsx index 590d33db5..5100d22bf 100644 --- a/src/components/Donate/Donate.tsx +++ b/src/components/Donate/Donate.tsx @@ -1,6 +1,6 @@ // import { useNavigation } from "@react-navigation/native"; import { - Body2, Button, Heading4, ScrollViewWrapper + Body2, Button, Heading4, ScrollViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import { t } from "i18next"; diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx index 6711a7729..dbd44ff40 100644 --- a/src/components/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary.tsx @@ -2,11 +2,11 @@ import { Body1, Button, Heading1, - Heading2 + Heading2, } from "components/SharedComponents"; import { SafeAreaView, - ScrollView + ScrollView, } from "components/styledComponents"; import { t } from "i18next"; import type { ErrorInfo, PropsWithChildren } from "react"; diff --git a/src/components/Explore/Explore.js b/src/components/Explore/Explore.js index 3aa37db09..f060d54a5 100644 --- a/src/components/Explore/Explore.js +++ b/src/components/Explore/Explore.js @@ -9,7 +9,7 @@ import { INatIconButton, OfflineNotice, RadioButtonSheet, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import { PLACE_MODE } from "providers/ExploreContext"; @@ -19,7 +19,7 @@ import { Alert } from "react-native"; import { useDebugMode, useStoredLayout, - useTranslation + useTranslation, } from "sharedHooks"; import { getShadow } from "styles/global"; import colors from "styles/tailwindColors"; @@ -33,14 +33,14 @@ import SpeciesView from "./SpeciesView"; const DROP_SHADOW = getShadow( { offsetHeight: 4, - elevation: 6 + elevation: 6, } ); const exploreViewIcon = { observations: "binoculars", species: "leaf", observers: "observers", - identifiers: "identifiers" + identifiers: "identifiers", }; type Props = { @@ -90,7 +90,7 @@ const Explore = ( { updateLocation, updateProject, updateTaxon, - updateUser + updateUser, }: Props ): Node => { const { t } = useTranslation( ); const [showExploreBottomSheet, setShowExploreBottomSheet] = useState( false ); @@ -101,7 +101,7 @@ const Explore = ( { observations: t( "Observations-View" ), species: t( "Species-View" ), observers: t( "Observers-View" ), - identifiers: t( "Identifiers-View" ) + identifiers: t( "Identifiers-View" ), }; const icon = exploreViewIcon[currentExploreView]; @@ -201,29 +201,29 @@ const Explore = ( { text: t( "Organisms-that-are-identified-to-species" ), buttonText: t( "EXPLORE-SPECIES" ), icon: "species", - value: "species" + value: "species", }, observations: { label: t( "Observations" ), text: t( "Individual-encounters-with-organisms" ), buttonText: t( "EXPLORE-OBSERVATIONS" ), icon: "observations", - value: "observations" + value: "observations", }, observers: { label: t( "Observers" ), text: t( "iNaturalist-users-who-have-observed" ), buttonText: t( "EXPLORE-OBSERVERS" ), icon: "observers", - value: "observers" + value: "observers", }, identifiers: { label: t( "Identifiers" ), text: t( "iNaturalist-users-who-have-left-an-identification" ), buttonText: t( "EXPLORE-IDENTIFIERS" ), icon: "identifiers", - value: "identifiers" - } + value: "identifiers", + }, }; return ( @@ -268,20 +268,20 @@ const Explore = ( { "right-5", "rounded-full", "w-[55px]", - "z-10" + "z-10", )} color="white" size={27} style={[ DROP_SHADOW, // eslint-disable-next-line react-native/no-inline-styles - { backgroundColor: "deeppink" } + { backgroundColor: "deeppink" }, ]} accessibilityLabel="Diagnostics" onPress={() => { Alert.alert( "Explore Info", - `queryParams: ${JSON.stringify( queryParams )}` + `queryParams: ${JSON.stringify( queryParams )}`, ); }} /> @@ -292,7 +292,7 @@ const Explore = ( { size={27} className={classnames( whiteCircleClass, - "absolute bottom-5 z-10 right-5" + "absolute bottom-5 z-10 right-5", )} accessibilityLabel={a11yLabel} onPress={() => setShowExploreBottomSheet( true )} diff --git a/src/components/Explore/ExploreContainer.js b/src/components/Explore/ExploreContainer.js index 8813c4a3a..f6a7e3f1a 100644 --- a/src/components/Explore/ExploreContainer.js +++ b/src/components/Explore/ExploreContainer.js @@ -1,14 +1,14 @@ // @flow import { - useNetInfo + useNetInfo, } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import { EXPLORE_ACTION, ExploreProvider, PLACE_MODE, - useExplore + useExplore, } from "providers/ExploreContext"; import type { Node } from "react"; import React, { useCallback, useEffect, useState } from "react"; @@ -33,7 +33,7 @@ const ExploreContainerWithContext = ( ): Node => { const { hasPermissions: hasLocationPermissions, renderPermissionsGate, - requestPermissions: requestLocationPermissions + requestPermissions: requestLocationPermissions, } = useLocationPermission( ); const currentUser = useCurrentUser(); @@ -55,7 +55,7 @@ const ExploreContainerWithContext = ( ): Node => { dispatch( { type: EXPLORE_ACTION.SET_PLACE_MODE_WORLDWIDE } ); dispatch( { type: EXPLORE_ACTION.SET_PLACE, - placeId: null + placeId: null, } ); } else { navigation.setParams( { place } ); @@ -64,7 +64,7 @@ const ExploreContainerWithContext = ( ): Node => { type: EXPLORE_ACTION.SET_PLACE, place, placeId: place?.id, - placeGuess: place?.display_name + placeGuess: place?.display_name, } ); } }; @@ -73,13 +73,13 @@ const ExploreContainerWithContext = ( ): Node => { if ( exclude ) { dispatch( { type: EXPLORE_ACTION.EXCLUDE_USER, - excludeUser: user + excludeUser: user, } ); } else { dispatch( { type: EXPLORE_ACTION.SET_USER, user, - userId: user?.id + userId: user?.id, } ); } }; @@ -88,18 +88,18 @@ const ExploreContainerWithContext = ( ): Node => { dispatch( { type: EXPLORE_ACTION.SET_PROJECT, project, - projectId: project?.id + projectId: project?.id, } ); }; const filteredParams = mapParamsToAPI( state, - currentUser + currentUser, ); const queryParams = { ...filteredParams, - per_page: 20 + per_page: 20, }; // need this hook to be top-level enough that ExploreHeaderCount rerenders @@ -107,7 +107,7 @@ const ExploreContainerWithContext = ( ): Node => { count, isFetching: isFetchingHeaderCount, handleUpdateCount, - setIsFetching: setIsFetchingHeaderCount + setIsFetching: setIsFetchingHeaderCount, } = useExploreHeaderCount( ); const closeFiltersModal = ( ) => setShowFiltersModal( false ); @@ -127,7 +127,7 @@ const ExploreContainerWithContext = ( ): Node => { }, [ hasLocationPermissions, setIsFetchingHeaderCount, - state?.placeMode + state?.placeMode, ] ); useEffect( ( ) => { @@ -179,7 +179,7 @@ const ExploreContainerWithContext = ( ): Node => { /> )} {renderPermissionsGate( { - onPermissionGranted: startFetching + onPermissionGranted: startFetching, } ) } ); diff --git a/src/components/Explore/ExploreFlashList.js b/src/components/Explore/ExploreFlashList.js index 089e11721..d3fc6cc2c 100644 --- a/src/components/Explore/ExploreFlashList.js +++ b/src/components/Explore/ExploreFlashList.js @@ -1,6 +1,6 @@ // @flow import { - ActivityIndicator, Body3, CustomFlashList, InfiniteScrollLoadingWheel + ActivityIndicator, Body3, CustomFlashList, InfiniteScrollLoadingWheel, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import UserList from "components/UserList/UserList"; @@ -11,7 +11,7 @@ import { useTranslation } from "sharedHooks"; type Props = { canFetch?: boolean, contentContainerStyle?: Object, - data: Array, + data: Object[], fetchNextPage: boolean, hideLoadingWheel: boolean, isFetchingNextPage: boolean, @@ -39,7 +39,7 @@ const ExploreFlashList = ( { renderItem, renderItemSeparator, testID, - totalResults + totalResults, }: Props ): Node => { const { t } = useTranslation( ); diff --git a/src/components/Explore/ExploreTaxonGridItem.tsx b/src/components/Explore/ExploreTaxonGridItem.tsx index 9f8114185..4f3b4d920 100644 --- a/src/components/Explore/ExploreTaxonGridItem.tsx +++ b/src/components/Explore/ExploreTaxonGridItem.tsx @@ -11,7 +11,7 @@ const ExploreTaxonGridItem = ( { count, showSpeciesSeenCheckmark = false, style, - taxon + taxon, }: Props ) => { const { t } = useTranslation( ); return ( diff --git a/src/components/Explore/ExploreV2.tsx b/src/components/Explore/ExploreV2.tsx index ec737aab0..1ff8e520b 100644 --- a/src/components/Explore/ExploreV2.tsx +++ b/src/components/Explore/ExploreV2.tsx @@ -5,7 +5,7 @@ import { Button, INatIconButton, OfflineNotice, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import { PLACE_MODE } from "providers/ExploreContext"; @@ -14,7 +14,7 @@ import { Alert } from "react-native"; import { useDebugMode, useStoredLayout, - useTranslation + useTranslation, } from "sharedHooks"; import type { RenderLocationPermissionsGateFunction } from "sharedHooks/useLocationPermission"; import { getShadow } from "styles/global"; @@ -27,7 +27,7 @@ import SpeciesView from "./SpeciesView"; const DROP_SHADOW = getShadow( { offsetHeight: 4, - elevation: 6 + elevation: 6, } ); enum EXPLORE_VIEW { @@ -64,7 +64,7 @@ const ExploreV2 = ( { placeMode, queryParams, renderLocationPermissionsGate, - requestLocationPermissions + requestLocationPermissions, }: Props ) => { const { t } = useTranslation( ); const { layout, writeLayoutToStorage } = useStoredLayout( "exploreObservationsLayout" ) as { @@ -161,20 +161,20 @@ const ExploreV2 = ( { "right-5", "rounded-full", "w-[55px]", - "z-10" + "z-10", )} color="white" size={27} style={[ DROP_SHADOW, // eslint-disable-next-line react-native/no-inline-styles - { backgroundColor: "deeppink" } + { backgroundColor: "deeppink" }, ]} accessibilityLabel="Diagnostics" onPress={() => { Alert.alert( "ExploreV2 Info", - `queryParams: ${JSON.stringify( queryParams )}` + `queryParams: ${JSON.stringify( queryParams )}`, ); }} /> diff --git a/src/components/Explore/Header/ExploreHeader.js b/src/components/Explore/Header/ExploreHeader.js index a68f6a284..8b0435182 100644 --- a/src/components/Explore/Header/ExploreHeader.js +++ b/src/components/Explore/Header/ExploreHeader.js @@ -9,7 +9,7 @@ import { Body3, DisplayTaxon, INatIcon, - INatIconButton + INatIconButton, } from "components/SharedComponents"; import { Pressable, View } from "components/styledComponents"; import { useExplore } from "providers/ExploreContext"; @@ -49,7 +49,7 @@ const Header = ( { renderLocationPermissionsGate, requestLocationPermissions, updateLocation, - updateTaxon + updateTaxon, }: Props ): Node => { const { t } = useTranslation( ); const { state, numberOfFilters } = useExplore( ); @@ -64,7 +64,7 @@ const Header = ( { backgroundColor: colors.darkGray, borderBottomLeftRadius: 20, borderBottomRightRadius: 20, - marginBottom: -40 + marginBottom: -40, }; return ( @@ -122,7 +122,7 @@ const Header = ( { numberOfFilters !== 0 ? "bg-inatGreen" : "bg-darkGray", - "rounded-md" + "rounded-md", )} onPress={() => openFiltersModal()} accessibilityLabel={t( "Filters" )} diff --git a/src/components/Explore/Header/ExploreHeaderCount.js b/src/components/Explore/Header/ExploreHeaderCount.js index 54b5e21b3..cfa939d79 100644 --- a/src/components/Explore/Header/ExploreHeaderCount.js +++ b/src/components/Explore/Header/ExploreHeaderCount.js @@ -3,7 +3,7 @@ import { ActivityIndicator, Body2, - INatIcon + INatIcon, } from "components/SharedComponents"; import { Pressable } from "components/styledComponents"; import type { Node } from "react"; @@ -24,7 +24,7 @@ const ExploreHeaderCount = ( { exploreView, exploreViewIcon, isFetching, - onPress + onPress, }: Props ): Node => { const { t } = useTranslation( ); diff --git a/src/components/Explore/IdentifiersView.js b/src/components/Explore/IdentifiersView.js index cfdbccf6d..2c45d7c3a 100644 --- a/src/components/Explore/IdentifiersView.js +++ b/src/components/Explore/IdentifiersView.js @@ -20,13 +20,13 @@ const IdentifiersView = ( { canFetch, isConnected, queryParams, - handleUpdateCount + handleUpdateCount, }: Props ): Node => { const { data, fetchNextPage, isFetchingNextPage, - totalResults + totalResults, } = useInfiniteScroll( "fetchIdentifiers", fetchIdentifiers, @@ -34,12 +34,12 @@ const IdentifiersView = ( { ...queryParams, fields: { identifications_count: true, - user: User.LIMITED_FIELDS - } + user: User.LIMITED_FIELDS, + }, }, { - enabled: canFetch - } + enabled: canFetch, + }, ); useEffect( ( ) => { diff --git a/src/components/Explore/MapView.tsx b/src/components/Explore/MapView.tsx index 1b9c7e79c..aae412dad 100644 --- a/src/components/Explore/MapView.tsx +++ b/src/components/Explore/MapView.tsx @@ -1,16 +1,16 @@ import { ActivityIndicator, Button, - Map + Map, } from "components/SharedComponents"; import { getMapRegion } from "components/SharedComponents/Map/helpers/mapHelpers"; import { View } from "components/styledComponents"; import type { MapBoundaries } from "providers/ExploreContext"; import { - EXPLORE_ACTION, PLACE_MODE, useExplore + EXPLORE_ACTION, PLACE_MODE, useExplore, } from "providers/ExploreContext"; import React, { - useEffect, useMemo, useRef, useState + useEffect, useMemo, useRef, useState, } from "react"; import type { Region } from "react-native-maps"; import { useTranslation } from "sharedHooks"; @@ -25,12 +25,12 @@ const worldwideRegion = { latitude: WORLDWIDE_LAT_LNG, longitude: WORLDWIDE_LAT_LNG, latitudeDelta: WORLDWIDE_DELTA, - longitudeDelta: WORLDWIDE_DELTA + longitudeDelta: WORLDWIDE_DELTA, }; const DROP_SHADOW = getShadow( { offsetHeight: 4, - elevation: 6 + elevation: 6, } ); const activityIndicatorSize = 50; @@ -40,12 +40,12 @@ const centeredLoadingWheel = { left: "50%", transform: [ { translateX: -( activityIndicatorSize / 2 ) }, - { translateY: -( activityIndicatorSize / 2 ) } + { translateY: -( activityIndicatorSize / 2 ) }, ], backgroundColor: "rgba(0,0,0,0)", alignItems: "center", justifyContent: "center", - zIndex: 20 + zIndex: 20, }; interface Props { @@ -71,7 +71,7 @@ const MapView = ( { isLoading, hasLocationPermissions, renderLocationPermissionsGate, - requestLocationPermissions + requestLocationPermissions, }: Props ) => { const { t } = useTranslation( ); const { state: exploreState, dispatch, defaultExploreLocation } = useExplore( ); @@ -84,7 +84,7 @@ const MapView = ( { latitude: exploreState.lat, longitude: exploreState.lng, latitudeDelta: NEARBY_DELTA, - longitudeDelta: NEARBY_DELTA + longitudeDelta: NEARBY_DELTA, } ), [exploreState.lat, exploreState.lng] ); const regionFromCoordinates = useMemo( ( ) => { @@ -94,7 +94,7 @@ const MapView = ( { latitude, longitude, latitudeDelta: NEARBY_DELTA, - longitudeDelta: NEARBY_DELTA + longitudeDelta: NEARBY_DELTA, }; } return null; @@ -140,7 +140,7 @@ const MapView = ( { nearbyRegion, regionFromCoordinates, observationBounds, - exploreState.place?.id + exploreState.place?.id, ] ); const handleRedoSearch = async ( ) => { @@ -153,13 +153,13 @@ const MapView = ( { swlat: currentBounds.southWest.latitude, swlng: currentBounds.southWest.longitude, nelat: currentBounds.northEast.latitude, - nelng: currentBounds.northEast.longitude - } + nelng: currentBounds.northEast.longitude, + }, } ); }; const tileMapParams = { - ...queryParams + ...queryParams, }; // Tile queries never need these params delete tileMapParams.return_bounds; @@ -189,7 +189,7 @@ const MapView = ( { const exploreLocation = await defaultExploreLocation( ); dispatch( { type: EXPLORE_ACTION.SET_EXPLORE_LOCATION, - exploreLocation + exploreLocation, } ); } else { requestLocationPermissions( ); diff --git a/src/components/Explore/Modals/ExploreFiltersModal.js b/src/components/Explore/Modals/ExploreFiltersModal.js index 4f96c5398..84b8806e6 100644 --- a/src/components/Explore/Modals/ExploreFiltersModal.js +++ b/src/components/Explore/Modals/ExploreFiltersModal.js @@ -27,7 +27,7 @@ const ExploreFiltersModal = ( { updateTaxon, updateLocation, updateUser, - updateProject + updateProject, }: Props ): Node => ( ( ( { const navigation = useNavigation( ); return ( diff --git a/src/components/Explore/Modals/ExploreUserSearchModal.tsx b/src/components/Explore/Modals/ExploreUserSearchModal.tsx index ed41f4eb3..1633c92eb 100644 --- a/src/components/Explore/Modals/ExploreUserSearchModal.tsx +++ b/src/components/Explore/Modals/ExploreUserSearchModal.tsx @@ -12,7 +12,7 @@ interface Props { const ExploreUserSearchModal = ( { showModal, closeModal, - updateUser + updateUser, }: Props ) => ( { const { t } = useTranslation(); const realm = useRealm(); @@ -91,7 +91,7 @@ const FilterModal = ( { differsFromSnapshot, discardChanges, isNotInitialState, - numberOfFilters + numberOfFilters, } = useExplore(); const { casual, @@ -120,7 +120,7 @@ const FilterModal = ( { taxon, user, excludeUser, - wildStatus + wildStatus, } = state; const NONE = "NONE"; @@ -163,374 +163,374 @@ const FilterModal = ( { [SORT_BY.DATE_UPLOADED_NEWEST]: { label: t( "Date-uploaded" ), text: t( "Newest-to-oldest" ), - value: SORT_BY.DATE_UPLOADED_NEWEST + value: SORT_BY.DATE_UPLOADED_NEWEST, }, [SORT_BY.DATE_UPLOADED_OLDEST]: { label: t( "Date-uploaded" ), text: t( "Oldest-to-newest" ), - value: SORT_BY.DATE_UPLOADED_OLDEST + value: SORT_BY.DATE_UPLOADED_OLDEST, }, [SORT_BY.DATE_OBSERVED_NEWEST]: { label: t( "Date-observed" ), text: t( "Newest-to-oldest" ), - value: SORT_BY.DATE_OBSERVED_NEWEST + value: SORT_BY.DATE_OBSERVED_NEWEST, }, [SORT_BY.DATE_OBSERVED_OLDEST]: { label: t( "Date-observed" ), text: t( "Oldest-to-newest" ), - value: SORT_BY.DATE_OBSERVED_OLDEST + value: SORT_BY.DATE_OBSERVED_OLDEST, }, [SORT_BY.MOST_FAVED]: { label: t( "Most-faved" ), - value: SORT_BY.MOST_FAVED - } + value: SORT_BY.MOST_FAVED, + }, }; const taxonomicRankValues = { [TAXONOMIC_RANK.none]: { label: t( "NONE--ranks" ), - value: TAXONOMIC_RANK.none + value: TAXONOMIC_RANK.none, }, [TAXONOMIC_RANK.kingdom]: { label: t( "Ranks-KINGDOM" ), - value: TAXONOMIC_RANK.kingdom + value: TAXONOMIC_RANK.kingdom, }, [TAXONOMIC_RANK.phylum]: { label: t( "Ranks-PHYLUM" ), - value: TAXONOMIC_RANK.phylum + value: TAXONOMIC_RANK.phylum, }, [TAXONOMIC_RANK.subphylum]: { label: t( "Ranks-SUBPHYLUM" ), - value: TAXONOMIC_RANK.subphylum + value: TAXONOMIC_RANK.subphylum, }, [TAXONOMIC_RANK.superclass]: { label: t( "Ranks-SUPERCLASS" ), - value: TAXONOMIC_RANK.superclass + value: TAXONOMIC_RANK.superclass, }, [TAXONOMIC_RANK.class]: { label: t( "Ranks-CLASS" ), - value: TAXONOMIC_RANK.class + value: TAXONOMIC_RANK.class, }, [TAXONOMIC_RANK.subclass]: { label: t( "Ranks-SUBCLASS" ), - value: TAXONOMIC_RANK.subclass + value: TAXONOMIC_RANK.subclass, }, [TAXONOMIC_RANK.infraclass]: { label: t( "Ranks-INFRACLASS" ), - value: TAXONOMIC_RANK.infraclass + value: TAXONOMIC_RANK.infraclass, }, [TAXONOMIC_RANK.subterclass]: { label: t( "Ranks-SUBTERCLASS" ), - value: TAXONOMIC_RANK.subterclass + value: TAXONOMIC_RANK.subterclass, }, [TAXONOMIC_RANK.superorder]: { label: t( "Ranks-SUPERORDER" ), - value: TAXONOMIC_RANK.superorder + value: TAXONOMIC_RANK.superorder, }, [TAXONOMIC_RANK.order]: { label: t( "Ranks-ORDER" ), - value: TAXONOMIC_RANK.order + value: TAXONOMIC_RANK.order, }, [TAXONOMIC_RANK.suborder]: { label: t( "Ranks-SUBORDER" ), - value: TAXONOMIC_RANK.suborder + value: TAXONOMIC_RANK.suborder, }, [TAXONOMIC_RANK.infraorder]: { label: t( "Ranks-INFRAORDER" ), - value: TAXONOMIC_RANK.infraorder + value: TAXONOMIC_RANK.infraorder, }, [TAXONOMIC_RANK.parvorder]: { label: t( "Ranks-PARVORDER" ), - value: TAXONOMIC_RANK.parvorder + value: TAXONOMIC_RANK.parvorder, }, [TAXONOMIC_RANK.zoosection]: { label: t( "Ranks-ZOOSECTION" ), - value: TAXONOMIC_RANK.zoosection + value: TAXONOMIC_RANK.zoosection, }, [TAXONOMIC_RANK.zoosubsection]: { label: t( "Ranks-ZOOSUBSECTION" ), - value: TAXONOMIC_RANK.zoosubsection + value: TAXONOMIC_RANK.zoosubsection, }, [TAXONOMIC_RANK.superfamily]: { label: t( "Ranks-SUPERFAMILY" ), - value: TAXONOMIC_RANK.superfamily + value: TAXONOMIC_RANK.superfamily, }, [TAXONOMIC_RANK.epifamily]: { label: t( "Ranks-EPIFAMILY" ), - value: TAXONOMIC_RANK.epifamily + value: TAXONOMIC_RANK.epifamily, }, [TAXONOMIC_RANK.family]: { label: t( "Ranks-FAMILY" ), - value: TAXONOMIC_RANK.family + value: TAXONOMIC_RANK.family, }, [TAXONOMIC_RANK.subfamily]: { label: t( "Ranks-SUBFAMILY" ), - value: TAXONOMIC_RANK.subfamily + value: TAXONOMIC_RANK.subfamily, }, [TAXONOMIC_RANK.supertribe]: { label: t( "Ranks-SUPERTRIBE" ), - value: TAXONOMIC_RANK.supertribe + value: TAXONOMIC_RANK.supertribe, }, [TAXONOMIC_RANK.tribe]: { label: t( "Ranks-TRIBE" ), - value: TAXONOMIC_RANK.tribe + value: TAXONOMIC_RANK.tribe, }, [TAXONOMIC_RANK.subtribe]: { label: t( "Ranks-SUBTRIBE" ), - value: TAXONOMIC_RANK.subtribe + value: TAXONOMIC_RANK.subtribe, }, [TAXONOMIC_RANK.genus]: { label: t( "Ranks-GENUS" ), - value: TAXONOMIC_RANK.genus + value: TAXONOMIC_RANK.genus, }, [TAXONOMIC_RANK.genushybrid]: { label: t( "Ranks-GENUSHYBRID" ), - value: TAXONOMIC_RANK.genushybrid + value: TAXONOMIC_RANK.genushybrid, }, [TAXONOMIC_RANK.subgenus]: { label: t( "Ranks-SUBGENUS" ), - value: TAXONOMIC_RANK.subgenus + value: TAXONOMIC_RANK.subgenus, }, [TAXONOMIC_RANK.section]: { label: t( "Ranks-SECTION" ), - value: TAXONOMIC_RANK.section + value: TAXONOMIC_RANK.section, }, [TAXONOMIC_RANK.subsection]: { label: t( "Ranks-SUBSECTION" ), - value: TAXONOMIC_RANK.subsection + value: TAXONOMIC_RANK.subsection, }, [TAXONOMIC_RANK.complex]: { label: t( "Ranks-COMPLEX" ), - value: TAXONOMIC_RANK.complex + value: TAXONOMIC_RANK.complex, }, [TAXONOMIC_RANK.species]: { label: t( "Ranks-SPECIES" ), - value: TAXONOMIC_RANK.species + value: TAXONOMIC_RANK.species, }, [TAXONOMIC_RANK.hybrid]: { label: t( "Ranks-HYBRID" ), - value: TAXONOMIC_RANK.hybrid + value: TAXONOMIC_RANK.hybrid, }, [TAXONOMIC_RANK.subspecies]: { label: t( "Ranks-SUBSPECIES" ), - value: TAXONOMIC_RANK.subspecies + value: TAXONOMIC_RANK.subspecies, }, [TAXONOMIC_RANK.variety]: { label: t( "Ranks-VARIETY" ), - value: TAXONOMIC_RANK.variety + value: TAXONOMIC_RANK.variety, }, [TAXONOMIC_RANK.form]: { label: t( "Ranks-FORM" ), - value: TAXONOMIC_RANK.form + value: TAXONOMIC_RANK.form, }, [TAXONOMIC_RANK.infrahybrid]: { label: t( "Ranks-INFRAHYBRID" ), - value: TAXONOMIC_RANK.infrahybrid - } + value: TAXONOMIC_RANK.infrahybrid, + }, }; const dateObservedValues = { [DATE_OBSERVED.ALL]: { label: t( "All" ), labelCaps: t( "ALL" ), - value: DATE_OBSERVED.ALL + value: DATE_OBSERVED.ALL, }, [DATE_OBSERVED.EXACT_DATE]: { label: t( "Exact-Date" ), labelCaps: t( "EXACT-DATE" ), text: t( "Filter-by-observed-on-date" ), - value: DATE_OBSERVED.EXACT_DATE + value: DATE_OBSERVED.EXACT_DATE, }, [DATE_OBSERVED.DATE_RANGE]: { label: t( "Date-Range" ), labelCaps: t( "DATE-RANGE" ), text: t( "Filter-by-observed-between-dates" ), - value: DATE_OBSERVED.DATE_RANGE + value: DATE_OBSERVED.DATE_RANGE, }, [DATE_OBSERVED.MONTHS]: { label: t( "Months" ), labelCaps: t( "MONTHS" ), text: t( "Filter-by-observed-during-months" ), - value: DATE_OBSERVED.MONTHS - } + value: DATE_OBSERVED.MONTHS, + }, }; const dateUploadedValues = { [DATE_UPLOADED.ALL]: { label: t( "All" ), labelCaps: t( "ALL" ), - value: DATE_UPLOADED.ALL + value: DATE_UPLOADED.ALL, }, [DATE_UPLOADED.EXACT_DATE]: { label: t( "Exact-Date" ), labelCaps: t( "EXACT-DATE" ), text: t( "Filter-by-uploaded-on-date" ), - value: DATE_UPLOADED.EXACT_DATE + value: DATE_UPLOADED.EXACT_DATE, }, [DATE_UPLOADED.DATE_RANGE]: { label: t( "Date-Range" ), labelCaps: t( "DATE-RANGE" ), text: t( "Filter-by-uploaded-between-dates" ), - value: DATE_UPLOADED.DATE_RANGE - } + value: DATE_UPLOADED.DATE_RANGE, + }, }; const monthValues = { 1: { label: t( "January" ), - value: 1 + value: 1, }, 2: { label: t( "February" ), - value: 2 + value: 2, }, 3: { label: t( "March" ), - value: 3 + value: 3, }, 4: { label: t( "April" ), - value: 4 + value: 4, }, 5: { label: t( "May" ), - value: 5 + value: 5, }, 6: { label: t( "June" ), - value: 6 + value: 6, }, 7: { label: t( "July" ), - value: 7 + value: 7, }, 8: { label: t( "August" ), - value: 8 + value: 8, }, 9: { label: t( "September" ), - value: 9 + value: 9, }, 10: { label: t( "October" ), - value: 10 + value: 10, }, 11: { label: t( "November" ), - value: 11 + value: 11, }, 12: { label: t( "December" ), - value: 12 - } + value: 12, + }, }; const mediaValues = { [MEDIA.ALL]: { label: t( "All" ), - value: MEDIA.ALL + value: MEDIA.ALL, }, [MEDIA.PHOTOS]: { label: t( "Photos" ), - value: MEDIA.PHOTOS + value: MEDIA.PHOTOS, }, [MEDIA.SOUNDS]: { label: t( "Sounds" ), - value: MEDIA.SOUNDS + value: MEDIA.SOUNDS, }, [MEDIA.NONE]: { label: t( "No-Media" ), - value: MEDIA.NONE - } + value: MEDIA.NONE, + }, }; const establishmentValues = { [ESTABLISHMENT_MEAN.ANY]: { label: t( "Any--establishment-means" ), - value: ESTABLISHMENT_MEAN.ANY + value: ESTABLISHMENT_MEAN.ANY, }, [ESTABLISHMENT_MEAN.INTRODUCED]: { label: t( "Introduced" ), - value: ESTABLISHMENT_MEAN.INTRODUCED + value: ESTABLISHMENT_MEAN.INTRODUCED, }, [ESTABLISHMENT_MEAN.NATIVE]: { label: t( "Native" ), - value: ESTABLISHMENT_MEAN.NATIVE + value: ESTABLISHMENT_MEAN.NATIVE, }, [ESTABLISHMENT_MEAN.ENDEMIC]: { label: t( "Endemic" ), - value: ESTABLISHMENT_MEAN.ENDEMIC - } + value: ESTABLISHMENT_MEAN.ENDEMIC, + }, }; const wildValues = { [WILD_STATUS.ALL]: { label: t( "All" ), - value: WILD_STATUS.ALL + value: WILD_STATUS.ALL, }, [WILD_STATUS.WILD]: { label: t( "Wild" ), - value: WILD_STATUS.WILD + value: WILD_STATUS.WILD, }, [WILD_STATUS.CAPTIVE]: { label: t( "Captive-Cultivated" ), - value: WILD_STATUS.CAPTIVE - } + value: WILD_STATUS.CAPTIVE, + }, }; const reviewedValues = { [REVIEWED.ALL]: { label: t( "All-observations" ), - value: REVIEWED.ALL + value: REVIEWED.ALL, }, [REVIEWED.REVIEWED]: { label: t( "Reviewed-observations-only" ), - value: REVIEWED.REVIEWED + value: REVIEWED.REVIEWED, }, [REVIEWED.UNREVIEWED]: { label: t( "Unreviewed-observations-only" ), - value: REVIEWED.UNREVIEWED - } + value: REVIEWED.UNREVIEWED, + }, }; const photoLicenseValues = { [PHOTO_LICENSE.ALL]: { label: t( "ALL" ), - value: PHOTO_LICENSE.ALL + value: PHOTO_LICENSE.ALL, }, [PHOTO_LICENSE.CC0]: { label: t( "CC0" ), - value: PHOTO_LICENSE.CC0 + value: PHOTO_LICENSE.CC0, }, [PHOTO_LICENSE.CCBY]: { label: t( "CC-BY" ), - value: PHOTO_LICENSE.CCBY + value: PHOTO_LICENSE.CCBY, }, [PHOTO_LICENSE.CCBYNC]: { label: t( "CC-BY-NC" ), - value: PHOTO_LICENSE.CCBYNC + value: PHOTO_LICENSE.CCBYNC, }, [PHOTO_LICENSE.CCBYSA]: { label: t( "CC-BY-SA" ), - value: PHOTO_LICENSE.CCBYSA + value: PHOTO_LICENSE.CCBYSA, }, [PHOTO_LICENSE.CCBYND]: { label: t( "CC-BY-ND" ), - value: PHOTO_LICENSE.CCBYND + value: PHOTO_LICENSE.CCBYND, }, [PHOTO_LICENSE.CCBYNCSA]: { label: t( "CC-BY-NC-SA" ), - value: PHOTO_LICENSE.CCBYNCSA + value: PHOTO_LICENSE.CCBYNCSA, }, [PHOTO_LICENSE.CCBYNCND]: { label: t( "CC-BY-NC-ND" ), - value: PHOTO_LICENSE.CCBYNCND - } + value: PHOTO_LICENSE.CCBYNCND, + }, }; const updateDateObserved = ( { - newDateObserved, newObservedOn, newD1, newD2, newMonths + newDateObserved, newObservedOn, newD1, newD2, newMonths, } ) => { const today = new Date( ).toISOString( ).split( "T" )[0]; // Array with the numbers from 1 to 12 @@ -538,23 +538,23 @@ const FilterModal = ( { if ( newDateObserved === DATE_OBSERVED.ALL ) { dispatch( { - type: EXPLORE_ACTION.SET_DATE_OBSERVED_ALL + type: EXPLORE_ACTION.SET_DATE_OBSERVED_ALL, } ); } else if ( newDateObserved === DATE_OBSERVED.EXACT_DATE ) { dispatch( { type: EXPLORE_ACTION.SET_DATE_OBSERVED_EXACT, - observedOn: newObservedOn || today + observedOn: newObservedOn || today, } ); } else if ( newDateObserved === DATE_OBSERVED.DATE_RANGE ) { dispatch( { type: EXPLORE_ACTION.SET_DATE_OBSERVED_RANGE, d1: newD1 || today, - d2: newD2 || today + d2: newD2 || today, } ); } else if ( newDateObserved === DATE_OBSERVED.MONTHS ) { dispatch( { type: EXPLORE_ACTION.SET_DATE_OBSERVED_MONTHS, - months: newMonths || allMonths + months: newMonths || allMonths, } ); } }; @@ -562,7 +562,7 @@ const FilterModal = ( { const updateObservedExact = date => { updateDateObserved( { newDateObserved: DATE_OBSERVED.EXACT_DATE, - newObservedOn: date.toISOString().split( "T" )[0] + newObservedOn: date.toISOString().split( "T" )[0], } ); }; @@ -570,7 +570,7 @@ const FilterModal = ( { updateDateObserved( { newDateObserved: DATE_OBSERVED.DATE_RANGE, newD1: date.toISOString().split( "T" )[0], - newD2: d2 + newD2: d2, } ); }; @@ -578,7 +578,7 @@ const FilterModal = ( { updateDateObserved( { newDateObserved: DATE_OBSERVED.DATE_RANGE, newD1: d1, - newD2: date.toISOString().split( "T" )[0] + newD2: date.toISOString().split( "T" )[0], } ); }; @@ -588,7 +588,7 @@ const FilterModal = ( { : [...months, monthInteger]; updateDateObserved( { newDateObserved: DATE_OBSERVED.MONTHS, - newMonths + newMonths, } ); }; @@ -596,18 +596,18 @@ const FilterModal = ( { const today = new Date().toISOString().split( "T" )[0]; if ( newDateUploaded === DATE_UPLOADED.ALL ) { dispatch( { - type: EXPLORE_ACTION.SET_DATE_UPLOADED_ALL + type: EXPLORE_ACTION.SET_DATE_UPLOADED_ALL, } ); } else if ( newDateUploaded === DATE_UPLOADED.EXACT_DATE ) { dispatch( { type: EXPLORE_ACTION.SET_DATE_UPLOADED_EXACT, - createdOn: newD1 || today + createdOn: newD1 || today, } ); } else if ( newDateUploaded === DATE_UPLOADED.DATE_RANGE ) { dispatch( { type: EXPLORE_ACTION.SET_DATE_UPLOADED_RANGE, createdD1: newD1 || today, - createdD2: newD2 || today + createdD2: newD2 || today, } ); } }; @@ -616,7 +616,7 @@ const FilterModal = ( { updateDateUploaded( { newDateUploaded: DATE_UPLOADED.DATE_RANGE, newD1: date.toISOString().split( "T" )[0], - newD2: createdD2 + newD2: createdD2, } ); }; @@ -624,7 +624,7 @@ const FilterModal = ( { updateDateUploaded( { newDateUploaded: DATE_UPLOADED.DATE_RANGE, newD1: createdD1, - newD2: date.toISOString().split( "T" )[0] + newD2: date.toISOString().split( "T" )[0], } ); }; @@ -973,7 +973,7 @@ const FilterModal = ( { {d1} @@ -1062,7 +1062,7 @@ const FilterModal = ( { toggleDateTimePicker={() => setOpenSheet( NONE )} onDatePicked={date => updateDateUploaded( { newDateUploaded: DATE_UPLOADED.EXACT_DATE, - newD1: date.toISOString().split( "T" )[0] + newD1: date.toISOString().split( "T" )[0], } )} /> @@ -1072,7 +1072,7 @@ const FilterModal = ( { {createdD1} @@ -1133,7 +1133,7 @@ const FilterModal = ( { checked={mediaValues[mediaKey].value === media} onPress={() => dispatch( { type: EXPLORE_ACTION.SET_MEDIA, - media: mediaValues[mediaKey].value + media: mediaValues[mediaKey].value, } )} label={mediaValues[mediaKey].label} /> @@ -1156,7 +1156,7 @@ const FilterModal = ( { onPress={() => dispatch( { type: EXPLORE_ACTION.SET_ESTABLISHMENT_MEAN, establishmentMean: - establishmentValues[establishmentKey].value + establishmentValues[establishmentKey].value, } )} label={establishmentValues[establishmentKey].label} /> @@ -1175,7 +1175,7 @@ const FilterModal = ( { checked={wildValues[wildKey].value === wildStatus} onPress={() => dispatch( { type: EXPLORE_ACTION.SET_WILD_STATUS, - wildStatus: wildValues[wildKey].value + wildStatus: wildValues[wildKey].value, } )} label={wildValues[wildKey].label} /> @@ -1196,7 +1196,7 @@ const FilterModal = ( { checked={reviewedValues[reviewedKey].value === reviewedFilter} onPress={() => dispatch( { type: EXPLORE_ACTION.SET_REVIEWED, - reviewedFilter: reviewedValues[reviewedKey].value + reviewedFilter: reviewedValues[reviewedKey].value, } )} label={reviewedValues[reviewedKey].label} /> @@ -1238,7 +1238,7 @@ const FilterModal = ( { confirm={newSortBy => { dispatch( { type: EXPLORE_ACTION.CHANGE_SORT_BY, - sortBy: newSortBy + sortBy: newSortBy, } ); setOpenSheet( NONE ); }} @@ -1254,7 +1254,7 @@ const FilterModal = ( { confirm={newRank => { dispatch( { type: EXPLORE_ACTION.SET_HIGHEST_TAXONOMIC_RANK, - hrank: newRank + hrank: newRank, } ); setOpenSheet( NONE ); }} @@ -1270,7 +1270,7 @@ const FilterModal = ( { confirm={newRank => { dispatch( { type: EXPLORE_ACTION.SET_LOWEST_TAXONOMIC_RANK, - lrank: newRank + lrank: newRank, } ); setOpenSheet( NONE ); }} @@ -1312,7 +1312,7 @@ const FilterModal = ( { confirm={newLicense => { dispatch( { type: EXPLORE_ACTION.SET_PHOTO_LICENSE, - photoLicense: newLicense + photoLicense: newLicense, } ); setOpenSheet( NONE ); }} diff --git a/src/components/Explore/NumberBadge.tsx b/src/components/Explore/NumberBadge.tsx index b57a2ede2..fa8302988 100644 --- a/src/components/Explore/NumberBadge.tsx +++ b/src/components/Explore/NumberBadge.tsx @@ -8,7 +8,7 @@ import { getShadow } from "styles/global"; const DROP_SHADOW = getShadow( { offsetHeight: 4, elevation: 6, - shadowRadius: 4 + shadowRadius: 4, } ); interface Props { @@ -28,7 +28,7 @@ const NumberBadge = ( { number, light }: Props ) => { diff --git a/src/components/Explore/ObservationsView.js b/src/components/Explore/ObservationsView.js index a86d53846..ff5a2a984 100644 --- a/src/components/Explore/ObservationsView.js +++ b/src/components/Explore/ObservationsView.js @@ -1,16 +1,16 @@ // @flow import { - useNetInfo + useNetInfo, } from "@react-native-community/netinfo"; import { - searchObservations + searchObservations, } from "api/observations"; import useInfiniteExploreScroll from "components/Explore/hooks/useInfiniteExploreScroll"; import ObservationsFlashList from "components/ObservationsFlashList/ObservationsFlashList"; import { View } from "components/styledComponents"; import { - useExplore + useExplore, } from "providers/ExploreContext"; import type { Node } from "react"; import React, { useEffect } from "react"; @@ -18,7 +18,7 @@ import { Dimensions } from "react-native"; import { useCurrentUser, useDeviceOrientation, - useQuery + useQuery, } from "sharedHooks"; import MapView from "./MapView"; @@ -44,7 +44,7 @@ const ObservationsView = ( { handleUpdateCount, hasLocationPermissions, renderLocationPermissionsGate, - requestLocationPermissions + requestLocationPermissions, }: Props ): Node => { const currentUser = useCurrentUser( ); const { state } = useExplore(); @@ -57,11 +57,11 @@ const ObservationsView = ( { user_id: currentUser?.id, ...queryParams, fields: { - } + }, } ), { - enabled: ( !!currentUser && !!excludeUser ) - } + enabled: ( !!currentUser && !!excludeUser ), + }, ); const { @@ -71,7 +71,7 @@ const ObservationsView = ( { observations, totalBounds, totalResults, - isLoading + isLoading, } = useInfiniteExploreScroll( { params: queryParams, enabled: canFetch } ); const curUserObsCount = currentUserObs?.total_results; @@ -83,7 +83,7 @@ const ObservationsView = ( { isLandscapeMode, isTablet, screenHeight, - screenWidth + screenWidth, } = useDeviceOrientation( ); useEffect( ( ) => { @@ -119,7 +119,7 @@ const ObservationsView = ( { style={{ left: layout === "map" ? -containerWidth - : 0 + : 0, }} > { const buttons = [ { value: "grid", icon: "grid", accessibilityLabel: "Grid", - testID: "SegmentedButton.grid" + testID: "SegmentedButton.grid", }, { value: "list", icon: "list", accessibilityLabel: "List", - testID: "SegmentedButton.list" - } + testID: "SegmentedButton.list", + }, ]; if ( !hideMap ) { buttons.unshift( { value: "map", icon: "map", accessibilityLabel: "Map", - testID: "SegmentedButton.map" + testID: "SegmentedButton.map", } ); } @@ -51,7 +51,7 @@ const ObservationsViewBar = ( { className="absolute bottom-5 left-5 z-10 h-11 flex-row" > {buttons.map( ( { - value, icon, accessibilityLabel, testID + value, icon, accessibilityLabel, testID, }, i ) => { const checked = value === layout; const isFirst = i === 0; @@ -68,18 +68,18 @@ const ObservationsViewBar = ( { : 0, borderBottomRightRadius: isLast ? 20 - : 0 + : 0, }; const spacerStyle = { borderRightWidth: isLast ? 0 : 1, - borderRightColor: colors.lightGray + borderRightColor: colors.lightGray, }; const backgroundColor = { backgroundColor: checked ? colors.inatGreen - : colors.white + : colors.white, }; return ( @@ -99,7 +99,7 @@ const ObservationsViewBar = ( { DROP_SHADOW, outerBorderStyle, spacerStyle, - backgroundColor + backgroundColor, ]} testID={testID} backgroundColor={value === layout diff --git a/src/components/Explore/ObserversView.js b/src/components/Explore/ObserversView.js index 2fa555b58..3b73fb803 100644 --- a/src/components/Explore/ObserversView.js +++ b/src/components/Explore/ObserversView.js @@ -20,13 +20,13 @@ const ObserversView = ( { canFetch, isConnected, queryParams, - handleUpdateCount + handleUpdateCount, }: Props ): Node => { const { data, isFetchingNextPage, fetchNextPage, - totalResults + totalResults, } = useInfiniteScroll( "fetchObservers", fetchObservers, @@ -34,12 +34,12 @@ const ObserversView = ( { ...queryParams, order_by: "observation_count", fields: { - user: User.LIMITED_FIELDS - } + user: User.LIMITED_FIELDS, + }, }, { - enabled: canFetch - } + enabled: canFetch, + }, ); useEffect( ( ) => { diff --git a/src/components/Explore/RootExploreContainer.js b/src/components/Explore/RootExploreContainer.js index 8b98904ea..b31066de7 100644 --- a/src/components/Explore/RootExploreContainer.js +++ b/src/components/Explore/RootExploreContainer.js @@ -1,21 +1,21 @@ // @flow import { - useNetInfo + useNetInfo, } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import { EXPLORE_ACTION, ExploreProvider, PLACE_MODE, - useExplore + useExplore, } from "providers/ExploreContext"; import type { Node } from "react"; import React, { useCallback, useEffect, useRef, - useState + useState, } from "react"; import { useCurrentUser, useDebugMode } from "sharedHooks"; import useLocationPermission from "sharedHooks/useLocationPermission"; @@ -41,12 +41,12 @@ const RootExploreContainerWithContext = ( ): Node => { renderPermissionsGate, requestPermissions: requestLocationPermissions, hasBlockedPermissions: hasBlockedLocationPermissions, - checkPermissions + checkPermissions, } = useLocationPermission( ); const previousHasLocationPermissions = useRef(); const { - state, dispatch, makeSnapshot, defaultExploreLocation + state, dispatch, makeSnapshot, defaultExploreLocation, } = useExplore( ); const [showFiltersModal, setShowFiltersModal] = useState( false ); @@ -60,7 +60,7 @@ const RootExploreContainerWithContext = ( ): Node => { const exploreLocation = await defaultExploreLocation(); dispatch( { type: EXPLORE_ACTION.SET_EXPLORE_LOCATION, - exploreLocation + exploreLocation, } ); } @@ -82,7 +82,7 @@ const RootExploreContainerWithContext = ( ): Node => { dispatch( { type: EXPLORE_ACTION.SET_PLACE_MODE_WORLDWIDE } ); dispatch( { type: EXPLORE_ACTION.SET_PLACE, - placeId: null + placeId: null, } ); } else if ( place === "nearby" ) { const exploreLocation = await defaultExploreLocation( ); @@ -90,7 +90,7 @@ const RootExploreContainerWithContext = ( ): Node => { // dispatch( { type: EXPLORE_ACTION.SET_PLACE_MODE_NEARBY } ); dispatch( { type: EXPLORE_ACTION.SET_EXPLORE_LOCATION, - exploreLocation + exploreLocation, } ); } else { navigation.setParams( { place } ); @@ -99,7 +99,7 @@ const RootExploreContainerWithContext = ( ): Node => { type: EXPLORE_ACTION.SET_PLACE, place, placeId: place?.id, - placeGuess: place?.display_name + placeGuess: place?.display_name, } ); } }, [checkPermissions, defaultExploreLocation, dispatch, navigation] ); @@ -109,13 +109,13 @@ const RootExploreContainerWithContext = ( ): Node => { if ( exclude ) { dispatch( { type: EXPLORE_ACTION.EXCLUDE_USER, - excludeUser: user + excludeUser: user, } ); } else { dispatch( { type: EXPLORE_ACTION.SET_USER, user, - userId: user?.id + userId: user?.id, } ); } }; @@ -124,18 +124,18 @@ const RootExploreContainerWithContext = ( ): Node => { dispatch( { type: EXPLORE_ACTION.SET_PROJECT, project, - projectId: project?.id + projectId: project?.id, } ); }; const filteredParams = mapParamsToAPI( state, - currentUser + currentUser, ); const queryParams = { ...filteredParams, - per_page: 20 + per_page: 20, }; // need this hook to be top-level enough that ExploreHeaderCount rerenders @@ -143,7 +143,7 @@ const RootExploreContainerWithContext = ( ): Node => { count, isFetching: isFetchingHeaderCount, handleUpdateCount, - setIsFetching: setIsFetchingHeaderCount + setIsFetching: setIsFetchingHeaderCount, } = useExploreHeaderCount( ); const closeFiltersModal = ( ) => { @@ -204,7 +204,7 @@ const RootExploreContainerWithContext = ( ): Node => { }, [ hasLocationPermissions, setIsFetchingHeaderCount, - state?.placeMode + state?.placeMode, ] ); useEffect( ( ) => { @@ -259,7 +259,7 @@ const RootExploreContainerWithContext = ( ): Node => { onPermissionGranted: async ( ) => { await updateLocation( "nearby" ); startFetching( ); - } + }, } )} ); diff --git a/src/components/Explore/SearchScreens/EmptySearchResults.tsx b/src/components/Explore/SearchScreens/EmptySearchResults.tsx index 82367a3c1..fc211a100 100644 --- a/src/components/Explore/SearchScreens/EmptySearchResults.tsx +++ b/src/components/Explore/SearchScreens/EmptySearchResults.tsx @@ -2,12 +2,12 @@ import { useNetInfo } from "@react-native-community/netinfo"; import { ActivityIndicator, Body2, - OfflineNotice + OfflineNotice, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; import { - useTranslation + useTranslation, } from "sharedHooks"; interface Props { @@ -21,7 +21,7 @@ const EmptySearchResults = ( { isLoading, searchQuery, refetch, - skipOfflineNotice + skipOfflineNotice, }: Props ) => { const { t } = useTranslation( ); const { isConnected } = useNetInfo( ); diff --git a/src/components/Explore/SearchScreens/ExploreLocationSearch.tsx b/src/components/Explore/SearchScreens/ExploreLocationSearch.tsx index dd7bdfb4d..5ce090db9 100644 --- a/src/components/Explore/SearchScreens/ExploreLocationSearch.tsx +++ b/src/components/Explore/SearchScreens/ExploreLocationSearch.tsx @@ -5,17 +5,17 @@ import { ButtonBar, List2, SearchBar, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { Pressable, View } from "components/styledComponents"; import inatPlaceTypes from "dictionaries/places"; import { EXPLORE_ACTION, - useExplore + useExplore, } from "providers/ExploreContext"; import React, { useCallback, - useState + useState, } from "react"; import { FlatList } from "react-native"; import { useAuthenticatedQuery, useTranslation } from "sharedHooks"; @@ -26,7 +26,7 @@ import EmptySearchResults from "./EmptySearchResults"; import ExploreSearchHeader from "./ExploreSearchHeader"; const DROP_SHADOW = getShadow( { - offsetHeight: 4 + offsetHeight: 4, } ); interface Props { @@ -42,7 +42,7 @@ const ExploreLocationSearch = ( { hasPermissions, renderPermissionsGate, requestPermissions, - updateLocation + updateLocation, }: Props ) => { const { t } = useTranslation( ); const { dispatch, defaultExploreLocation } = useExplore( ); @@ -54,7 +54,7 @@ const ExploreLocationSearch = ( { updateLocation( "worldwide" ); closeModal(); }, - [updateLocation, closeModal] + [updateLocation, closeModal], ); const { data: placeResults, isLoading, refetch }: { @@ -69,13 +69,13 @@ const ExploreLocationSearch = ( { sources: "places", fields: "place,place.display_name,place.point_geojson,place.place_type", - per_page: 50 + per_page: 50, }, - optsWithAuth + optsWithAuth, ), { - enabled: locationName.length > 0 - } + enabled: locationName.length > 0, + }, ); const onPlaceSelected = useCallback( ( place: ApiPlace ) => { @@ -100,7 +100,7 @@ const ExploreLocationSearch = ( { ); }, - [onPlaceSelected] + [onPlaceSelected], ); const data = placeResults || []; @@ -139,14 +139,14 @@ const ExploreLocationSearch = ( { title: t( "NEARBY" ), onPress: onNearbyPressed, isPrimary: false, - className: "w-1/2 mx-6" + className: "w-1/2 mx-6", }, { title: t( "WORLDWIDE" ), onPress: resetPlace, isPrimary: false, - className: "w-1/2 mx-6" - } + className: "w-1/2 mx-6", + }, ]; return ( diff --git a/src/components/Explore/SearchScreens/ExploreProjectSearch.tsx b/src/components/Explore/SearchScreens/ExploreProjectSearch.tsx index 1d96f0a8d..07116aeec 100644 --- a/src/components/Explore/SearchScreens/ExploreProjectSearch.tsx +++ b/src/components/Explore/SearchScreens/ExploreProjectSearch.tsx @@ -3,12 +3,12 @@ import type { ApiProject } from "api/types"; import ProjectList from "components/ProjectList/ProjectList"; import { SearchBar, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React, { useCallback, - useState + useState, } from "react"; import { useInfiniteScroll, useTranslation } from "sharedHooks"; import { getShadow } from "styles/global"; @@ -17,7 +17,7 @@ import EmptySearchResults from "./EmptySearchResults"; import ExploreSearchHeader from "./ExploreSearchHeader"; const DROP_SHADOW = getShadow( { - offsetHeight: 4 + offsetHeight: 4, } ); type Props = { @@ -35,7 +35,7 @@ const ExploreProjectSearch = ( { closeModal, updateProject }: Props ) => { data, isFetching, fetchNextPage, - refetch + refetch, } = useInfiniteScroll( ["ExploreProjectSearch", projectQuery], search, @@ -47,10 +47,10 @@ const ExploreProjectSearch = ( { closeModal, updateProject }: Props ) => { id: true, title: true, icon: true, - project_type: true - } - } - } + project_type: true, + }, + }, + }, ); const projects = data.map( ( r: { project: ApiProject } ) => r.project ); @@ -70,7 +70,7 @@ const ExploreProjectSearch = ( { closeModal, updateProject }: Props ) => { updateProject( null ); closeModal(); }, - [updateProject, closeModal] + [updateProject, closeModal], ); return ( diff --git a/src/components/Explore/SearchScreens/ExploreSearchHeader.tsx b/src/components/Explore/SearchScreens/ExploreSearchHeader.tsx index 1b603ffbd..130f3ee2e 100644 --- a/src/components/Explore/SearchScreens/ExploreSearchHeader.tsx +++ b/src/components/Explore/SearchScreens/ExploreSearchHeader.tsx @@ -1,7 +1,7 @@ import { BackButton, Body3, - Heading4 + Heading4, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; @@ -18,7 +18,7 @@ const ExploreSearchHeader = ( { closeModal, headerText, resetFilters, - testID + testID, }: Props ) => { const { t } = useTranslation( ); diff --git a/src/components/Explore/SearchScreens/ExploreTaxonSearch.js b/src/components/Explore/SearchScreens/ExploreTaxonSearch.js index 9a2089758..13a33c604 100644 --- a/src/components/Explore/SearchScreens/ExploreTaxonSearch.js +++ b/src/components/Explore/SearchScreens/ExploreTaxonSearch.js @@ -3,12 +3,12 @@ import { TaxonResult, TaxonSearch, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import type { Node } from "react"; import React, { useCallback, - useState + useState, } from "react"; import { useTranslation } from "sharedHooks"; import useTaxonSearch from "sharedHooks/useTaxonSearch"; @@ -26,7 +26,7 @@ const ExploreTaxonSearch = ( { closeModal, hideInfoButton, onPressInfo, - updateTaxon + updateTaxon, }: Props ): Node => { const { t } = useTranslation( ); const [taxonQuery, setTaxonQuery] = useState( "" ); @@ -34,7 +34,7 @@ const ExploreTaxonSearch = ( { const { taxa, isLoading, - isLocal + isLocal, } = useTaxonSearch( taxonQuery ); const onTaxonSelected = useCallback( async newTaxon => { @@ -47,7 +47,7 @@ const ExploreTaxonSearch = ( { updateTaxon( null ); closeModal(); }, - [updateTaxon, closeModal] + [updateTaxon, closeModal], ); const renderItem = useCallback( ( { item: taxon, index } ) => ( @@ -64,7 +64,7 @@ const ExploreTaxonSearch = ( { ), [ hideInfoButton, onPressInfo, - onTaxonSelected + onTaxonSelected, ] ); return ( diff --git a/src/components/Explore/SearchScreens/ExploreUserSearch.js b/src/components/Explore/SearchScreens/ExploreUserSearch.js index 300c21bcf..cd074eca6 100644 --- a/src/components/Explore/SearchScreens/ExploreUserSearch.js +++ b/src/components/Explore/SearchScreens/ExploreUserSearch.js @@ -4,14 +4,14 @@ import { fetchSearchResults } from "api/search"; import { ButtonBar, SearchBar, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import UserList from "components/UserList/UserList"; import type { Node } from "react"; import React, { useCallback, - useState + useState, } from "react"; import { useAuthenticatedQuery, useCurrentUser, useTranslation } from "sharedHooks"; import { getShadow } from "styles/global"; @@ -20,7 +20,7 @@ import EmptySearchResults from "./EmptySearchResults"; import ExploreSearchHeader from "./ExploreSearchHeader"; const DROP_SHADOW = getShadow( { - offsetHeight: 4 + offsetHeight: 4, } ); type Props = { @@ -40,10 +40,10 @@ const ExploreUserSearch = ( { closeModal, updateUser }: Props ): Node => { { q: userQuery, sources: "users", - fields: "user.id,user.login,user.icon_url,user.observations_count" + fields: "user.id,user.login,user.icon_url,user.observations_count", }, - optsWithAuth - ) + optsWithAuth, + ), ); const onUserSelected = useCallback( async ( user, exclude ) => { @@ -61,7 +61,7 @@ const ExploreUserSearch = ( { closeModal, updateUser }: Props ): Node => { updateUser( null ); closeModal(); }, - [updateUser, closeModal] + [updateUser, closeModal], ); // TODO: pagination like in ExploreFlashList ? @@ -83,7 +83,7 @@ const ExploreUserSearch = ( { closeModal, updateUser }: Props ): Node => { } }, isPrimary: false, - className: "w-1/2 mx-2" + className: "w-1/2 mx-2", }, { title: t( "NOT-BY-ME" ), @@ -93,8 +93,8 @@ const ExploreUserSearch = ( { closeModal, updateUser }: Props ): Node => { } }, isPrimary: false, - className: "w-1/2 mx-2" - } + className: "w-1/2 mx-2", + }, ]; return ( diff --git a/src/components/Explore/SpeciesView.js b/src/components/Explore/SpeciesView.js index df5052b50..646805d4e 100644 --- a/src/components/Explore/SpeciesView.js +++ b/src/components/Explore/SpeciesView.js @@ -5,7 +5,7 @@ import ExploreTaxonGridItem from "components/Explore/ExploreTaxonGridItem"; import i18n from "i18next"; import _ from "lodash"; import { - useExplore + useExplore, } from "providers/ExploreContext"; import type { Node } from "react"; import React, { useEffect, useMemo, useState } from "react"; @@ -14,7 +14,7 @@ import { useCurrentUser, useGridLayout, useInfiniteScroll, - useQuery + useQuery, } from "sharedHooks"; import ExploreFlashList from "./ExploreFlashList"; @@ -30,7 +30,7 @@ const SpeciesView = ( { canFetch, isConnected, queryParams, - handleUpdateCount + handleUpdateCount, }: Props ): Node => { // 20240814 - amanda: not sure if we actually need observedTaxonIds in state in the long // run, but for now, it prevents flickering when a user scrolls and new species are loaded @@ -42,7 +42,7 @@ const SpeciesView = ( { const { flashListStyle, gridItemStyle, - numColumns + numColumns, } = useGridLayout( ); // query all of current users seen species if "not by me" explore filter @@ -53,17 +53,17 @@ const SpeciesView = ( { ttl: -1, fields: { taxon: { - id: true - } - } + id: true, + }, + }, } ), { - enabled: ( !!currentUser && !!excludeUser ) - } + enabled: ( !!currentUser && !!excludeUser ), + }, ); const pageObservedTaxonIdsAll = useMemo( ( ) => seenByCurrentUserAll?.results?.map( - r => r.taxon.id + r => r.taxon.id, ) || [], [seenByCurrentUserAll?.results] ); const params = excludeUser @@ -76,7 +76,7 @@ const SpeciesView = ( { data, isFetchingNextPage, fetchNextPage, - totalResults + totalResults, } = useInfiniteScroll( "fetchSpeciesCounts", fetchSpeciesCounts, @@ -84,12 +84,12 @@ const SpeciesView = ( { ...params, ...( !currentUser && { locale } ), fields: { - taxon: Taxon.LIMITED_TAXON_FIELDS - } + taxon: Taxon.LIMITED_TAXON_FIELDS, + }, }, { - enabled: canFetch - } + enabled: canFetch, + }, ); const taxonIds = data.map( r => r.taxon.id ); @@ -101,17 +101,17 @@ const SpeciesView = ( { taxon_id: taxonIds, fields: { taxon: { - id: true - } - } + id: true, + }, + }, } ), { - enabled: !!( taxonIds.length > 0 && currentUser ) - } + enabled: !!( taxonIds.length > 0 && currentUser ), + }, ); const pageObservedTaxonIds = useMemo( ( ) => seenByCurrentUser?.results?.map( - r => r.taxon.id + r => r.taxon.id, ) || [], [seenByCurrentUser?.results] ); useEffect( ( ) => { @@ -147,7 +147,7 @@ const SpeciesView = ( { const contentContainerStyle = useMemo( ( ) => ( { ...flashListStyle, - paddingTop: 50 + paddingTop: 50, } ), [flashListStyle] ); return ( diff --git a/src/components/Explore/helpers/exploreParams.ts b/src/components/Explore/helpers/exploreParams.ts index 88bcbc479..79fad680c 100644 --- a/src/components/Explore/helpers/exploreParams.ts +++ b/src/components/Explore/helpers/exploreParams.ts @@ -2,7 +2,7 @@ import type { ApiObservationsSearchParams, - ApiObservationsSearchResponse + ApiObservationsSearchResponse, } from "api/types"; import { addSeconds, formatISO, parseISO } from "date-fns"; import { last } from "lodash"; @@ -23,7 +23,7 @@ interface ApiObservationsSearchParamsForInfiniteQuery extends ApiObservationsSea // above. function getNextPageParamForExplore( lastPage: ApiObservationsSearchResponse, - params: ApiObservationsSearchParams + params: ApiObservationsSearchParams, ) { const lastObs = last( lastPage.results ); const orderBy = params.order_by; @@ -115,5 +115,5 @@ function addPageParamsForExplore( params: ApiObservationsSearchParamsForInfinite export { addPageParamsForExplore, - getNextPageParamForExplore + getNextPageParamForExplore, }; diff --git a/src/components/Explore/helpers/mapParamsToAPI.js b/src/components/Explore/helpers/mapParamsToAPI.js index b62d7aed2..2d3a47b52 100644 --- a/src/components/Explore/helpers/mapParamsToAPI.js +++ b/src/components/Explore/helpers/mapParamsToAPI.js @@ -6,7 +6,7 @@ import { PHOTO_LICENSE, REVIEWED, SORT_BY, - WILD_STATUS + WILD_STATUS, } from "providers/ExploreContext"; const mapParamsToAPI = ( params: Object, currentUser: Object ): Object => { @@ -29,7 +29,7 @@ const mapParamsToAPI = ( params: Object, currentUser: Object ): Object => { } return newParams; }, - {} + {}, ); // DATE_UPLOADED_NEWEST is the default sort order @@ -111,7 +111,7 @@ const mapParamsToAPI = ( params: Object, currentUser: Object ): Object => { [PHOTO_LICENSE.CCBYSA]: "cc-by-sa", [PHOTO_LICENSE.CCBYND]: "cc-by-nd", [PHOTO_LICENSE.CCBYNCSA]: "cc-by-nc-sa", - [PHOTO_LICENSE.CCBYNCND]: "cc-by-nc-nd" + [PHOTO_LICENSE.CCBYNCND]: "cc-by-nc-nd", }; filteredParams.photo_license = licenseParams[params.photoLicense]; } diff --git a/src/components/Explore/hooks/useExploreHeaderCount.js b/src/components/Explore/hooks/useExploreHeaderCount.js index d5401d1cb..43ef67387 100644 --- a/src/components/Explore/hooks/useExploreHeaderCount.js +++ b/src/components/Explore/hooks/useExploreHeaderCount.js @@ -1,7 +1,7 @@ // @flow import { - useCallback, useMemo, useState + useCallback, useMemo, useState, } from "react"; const useExploreHeaderCount = ( ): Object => { @@ -9,14 +9,14 @@ const useExploreHeaderCount = ( ): Object => { observations: null, species: null, observers: null, - identifiers: null + identifiers: null, } ); const [isFetching, setIsFetching] = useState( false ); const updateCount = useCallback( newCount => { setCount( { ...count, - ...newCount + ...newCount, } ); setIsFetching( false ); }, [count] ); @@ -38,7 +38,7 @@ const useExploreHeaderCount = ( ): Object => { count: memoizedCount, isFetching, handleUpdateCount, - setIsFetching + setIsFetching, }; }; diff --git a/src/components/Explore/hooks/useInfiniteExploreScroll.js b/src/components/Explore/hooks/useInfiniteExploreScroll.js index 2d3a9062f..31cf72a90 100644 --- a/src/components/Explore/hooks/useInfiniteExploreScroll.js +++ b/src/components/Explore/hooks/useInfiniteExploreScroll.js @@ -9,7 +9,7 @@ import { useAuthenticatedInfiniteQuery } from "sharedHooks"; import { addPageParamsForExplore, - getNextPageParamForExplore + getNextPageParamForExplore, } from "../helpers/exploreParams"; const useInfiniteExploreScroll = ( { params: newInputParams, enabled }: Object ): Object => { @@ -24,10 +24,10 @@ const useInfiniteExploreScroll = ( { params: newInputParams, enabled }: Object ) user: { // included here for "exclude by current user" in explore filters id: true, uuid: true, - login: true - } + login: true, + }, }, - ttl: -1 + ttl: -1, } ), [newInputParams] ); const excludedUser = newInputParams.excludeUser; @@ -36,7 +36,7 @@ const useInfiniteExploreScroll = ( { params: newInputParams, enabled }: Object ) const getNextPageParam = useCallback( lastPage => getNextPageParamForExplore( lastPage, baseParams ), - [baseParams] + [baseParams], ); const { @@ -46,17 +46,17 @@ const useInfiniteExploreScroll = ( { params: newInputParams, enabled }: Object ) fetchNextPage, refetch, isRefetching, - status + status, } = useAuthenticatedInfiniteQuery( queryKey, async ( params, optsWithAuth ) => searchObservations( addPageParamsForExplore( { ...baseParams, ...params } ), - optsWithAuth + optsWithAuth, ), { getNextPageParam, - enabled - } + enabled, + }, ); const handlePullToRefresh = async ( ) => { @@ -86,7 +86,7 @@ const useInfiniteExploreScroll = ( { params: newInputParams, enabled }: Object ) observations, status, totalBounds: data?.pages?.[0].total_bounds, - totalResults + totalResults, }; }; diff --git a/src/components/Explore/hooks/useParams.js b/src/components/Explore/hooks/useParams.js index 9afa2f039..5f0c8c142 100644 --- a/src/components/Explore/hooks/useParams.js +++ b/src/components/Explore/hooks/useParams.js @@ -3,7 +3,7 @@ import { useRoute } from "@react-navigation/native"; import { EXPLORE_ACTION, - useExplore + useExplore, } from "providers/ExploreContext"; import { useCallback, useEffect } from "react"; @@ -17,7 +17,7 @@ const useParams = ( ): Object => { dispatch( { type: EXPLORE_ACTION.SET_PLACE, place: null, - placeId: null + placeId: null, } ); }; @@ -30,7 +30,7 @@ const useParams = ( ): Object => { // dispatch( { type: EXPLORE_ACTION.SET_PLACE_MODE_NEARBY } ); dispatch( { type: EXPLORE_ACTION.SET_EXPLORE_LOCATION, - exploreLocation + exploreLocation, } ); } if ( params?.taxon ) { @@ -38,7 +38,7 @@ const useParams = ( ): Object => { type: EXPLORE_ACTION.CHANGE_TAXON, taxon: params.taxon, taxonId: params.taxon?.id, - taxonName: params.taxon?.preferred_common_name || params.taxon?.name + taxonName: params.taxon?.preferred_common_name || params.taxon?.name, } ); } if ( params?.place ) { @@ -47,33 +47,33 @@ const useParams = ( ): Object => { type: EXPLORE_ACTION.SET_PLACE, place: params.place, placeId: params.place?.id, - placeGuess: params.place?.display_name + placeGuess: params.place?.display_name, } ); } if ( params?.user && params?.user.id ) { dispatch( { type: EXPLORE_ACTION.SET_USER, user: params.user, - userId: params.user.id + userId: params.user.id, } ); } if ( params?.project && params?.project.id ) { dispatch( { type: EXPLORE_ACTION.SET_PROJECT, project: params.project, - projectId: params.project.id + projectId: params.project.id, } ); } }, [ dispatch, params, - defaultExploreLocation + defaultExploreLocation, ] ); useEffect( ( ) => { updateContextWithParams( ); }, [ - updateContextWithParams + updateContextWithParams, ] ); return null; diff --git a/src/components/FullPageWebView/FullPageWebView.tsx b/src/components/FullPageWebView/FullPageWebView.tsx index 8828f57e2..0dd695f7e 100644 --- a/src/components/FullPageWebView/FullPageWebView.tsx +++ b/src/components/FullPageWebView/FullPageWebView.tsx @@ -2,7 +2,7 @@ import type { RouteProp } from "@react-navigation/native"; import { useFocusEffect, useNavigation, - useRoute + useRoute, } from "@react-navigation/native"; import { getUserAgent } from "api/userAgent"; import { getJWT } from "components/LoginSignUp/AuthenticationService"; @@ -31,7 +31,7 @@ export const ALLOWED_DOMAINS = [ "plaid.com", "stripecdn.com", "stripe.network", - "hcaptcha.com" + "hcaptcha.com", ]; const ALLOWED_ORIGINS = ["https://*", "mailto:*"]; @@ -57,7 +57,7 @@ type FullPageWebViewParams = { title?: string; loggedIn?: boolean; skipSetSourceInShouldStartLoadWithRequest?: boolean; - clickablePathnames?: Array; + clickablePathnames?: string[]; shouldLoadUrl?: ( url: string ) => boolean; } @@ -76,7 +76,7 @@ export function onShouldStartLoadWithRequest( request: ShouldStartLoadRequest, source: WebViewSource, params: FullPageWebViewParams, - setSource?: ( source: WebViewSource ) => void + setSource?: ( source: WebViewSource ) => void, ) { if ( typeof ( params.shouldLoadUrl ) === "function" ) { if ( !params.shouldLoadUrl( request.url ) ) return false; @@ -184,13 +184,13 @@ const FullPageWebView = ( ) => { React.useCallback( () => { if ( params.title ) { navigation.setOptions( { - headerTitle: params.title + headerTitle: params.title, } ); } setSource( { ...source, - uri: params.initialUrl + uri: params.initialUrl, } ); // Make the WebView logged in for the current user @@ -199,8 +199,8 @@ const FullPageWebView = ( ) => { setSource( { ...source, headers: { - Authorization: jwt - } + Authorization: jwt, + }, } ); } ); } @@ -208,7 +208,7 @@ const FullPageWebView = ( ) => { // for this hook // eslint-disable-next-line react-hooks/react-compiler // eslint-disable-next-line react-hooks/exhaustive-deps - }, [navigation, params.loggedIn, params.title] ) + }, [navigation, params.loggedIn, params.title] ), ); const fontScalingJS = ` @@ -239,7 +239,7 @@ const FullPageWebView = ( ) => { request, source, params, - setSource + setSource, ) } originWhitelist={ALLOWED_ORIGINS} diff --git a/src/components/FullPageWebView/FullPageWebViewHeader.tsx b/src/components/FullPageWebView/FullPageWebViewHeader.tsx index c2c940983..a0847c7a0 100644 --- a/src/components/FullPageWebView/FullPageWebViewHeader.tsx +++ b/src/components/FullPageWebView/FullPageWebViewHeader.tsx @@ -23,17 +23,17 @@ interface Props { } const HEADER_STYLE = { - backgroundColor: "white" + backgroundColor: "white", } as const; const BACK_BUTTON_STYLE = { position: "relative", - start: 11 + start: 11, } as const; const FullPageWebViewHeader = ( { route, - options + options, }: Props ) => { const insets = useSafeAreaInsets(); @@ -57,7 +57,7 @@ const FullPageWebViewHeader = ( { ...( options.headerShadowVisible && dropShadow ), paddingTop: insets.top, paddingLeft: insets.left, - paddingRight: insets.right + paddingRight: insets.right, }} > ( text={t( "VIEW-EDUCATORS-GUIDE" )} onPress={ ( ) => openExternalWebBrowser( - "https://help.inaturalist.org/support/solutions/articles/151000170805" + "https://help.inaturalist.org/support/solutions/articles/151000170805", ) } /> diff --git a/src/components/LocationPicker/CrosshairCircle.tsx b/src/components/LocationPicker/CrosshairCircle.tsx index 504c41fdf..b8b23bb95 100644 --- a/src/components/LocationPicker/CrosshairCircle.tsx +++ b/src/components/LocationPicker/CrosshairCircle.tsx @@ -35,8 +35,8 @@ const CrosshairCircle = ( { accuracy }: Props ) => { { "border-inatGreen": accuracyTest === "pass", "border-warningYellow border-dashed": accuracyTest === "acceptable", - "border-warningRed": accuracyTest === "fail" - } + "border-warningRed": accuracyTest === "fail", + }, ) } > diff --git a/src/components/LocationPicker/DisplayLatLng.js b/src/components/LocationPicker/DisplayLatLng.js index 6d67741a6..fc5fdf448 100644 --- a/src/components/LocationPicker/DisplayLatLng.js +++ b/src/components/LocationPicker/DisplayLatLng.js @@ -1,7 +1,7 @@ // @flow import { - Body4 + Body4, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import type { Node } from "react"; @@ -24,12 +24,12 @@ const DisplayLatLng = ( { region, accuracy }: Props ): Node => { displayLocation = t( "Lat-Lon-Acc", { latitude: region.latitude, longitude: region.longitude, - accuracy + accuracy, } ); } else { displayLocation = t( "Lat-Lon", { latitude: region.latitude, - longitude: region.longitude + longitude: region.longitude, } ); } } diff --git a/src/components/LocationPicker/LoadingIndicator.tsx b/src/components/LocationPicker/LoadingIndicator.tsx index 3a94151fe..efe3773e4 100644 --- a/src/components/LocationPicker/LoadingIndicator.tsx +++ b/src/components/LocationPicker/LoadingIndicator.tsx @@ -16,7 +16,7 @@ const LoadingIndicator = ( ) => ( "right-[40px]", "bottom-[40px]", "justify-center", - "rounded-full" + "rounded-full", )} > diff --git a/src/components/LocationPicker/LocationPicker.js b/src/components/LocationPicker/LocationPicker.js index b1a2225fe..693178e65 100644 --- a/src/components/LocationPicker/LocationPicker.js +++ b/src/components/LocationPicker/LocationPicker.js @@ -6,7 +6,7 @@ import { Heading4, KeyboardDismissableView, Map, - ViewWrapper + ViewWrapper, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import type { Node } from "react"; @@ -50,7 +50,7 @@ const LocationPicker = ( { onRegionChangeComplete, region, selectPlaceResult, - updateLocationName + updateLocationName, }: Props ): Node => { const { t } = useTranslation( ); @@ -86,7 +86,7 @@ const LocationPicker = ( { "items-center", "justify-center", "w-full", - "h-full" + "h-full", )} pointerEvents="none" > diff --git a/src/components/LocationPicker/LocationPickerContainer.js b/src/components/LocationPicker/LocationPickerContainer.js index ab34a0475..2daedf3d8 100644 --- a/src/components/LocationPicker/LocationPickerContainer.js +++ b/src/components/LocationPicker/LocationPickerContainer.js @@ -6,7 +6,7 @@ import type { Node } from "react"; import React, { useCallback, useEffect, - useReducer + useReducer, } from "react"; import { Dimensions } from "react-native"; import fetchPlaceName from "sharedHelpers/fetchPlaceName"; @@ -28,7 +28,7 @@ const setInitialRegion = currentObservation => { const latitudeDelta = latitude && currentObservation?.positional_accuracy ? metersToLatitudeDelta( currentObservation?.positional_accuracy, - latitude + latitude, ) : 90; const longitudeDelta = longitude && currentObservation?.positional_accuracy @@ -41,7 +41,7 @@ const setInitialRegion = currentObservation => { latitude: latitude || 0.0, longitude: longitude || 0.0, latitudeDelta, - longitudeDelta + longitudeDelta, }; }; @@ -52,14 +52,14 @@ const initializeMap = ( state, action ) => { locationName: action.currentObservation?.place_guess, region: { ...state.region, - ...setInitialRegion( action.currentObservation ) - } + ...setInitialRegion( action.currentObservation ), + }, }; if ( newMap.region.latitude !== 0.0 ) { newMap.region.latitudeDelta = metersToLatitudeDelta( newMap.accuracy, - newMap.region.latitude + newMap.region.latitude, ); newMap.region.longitudeDelta = newMap.region.latitudeDelta; } @@ -73,7 +73,7 @@ const DEFAULT_REGION = { latitude: 0.0, longitude: 0.0, latitudeDelta: DELTA, - longitudeDelta: DELTA + longitudeDelta: DELTA, }; const initialState = { @@ -84,7 +84,7 @@ const initialState = { locationName: "", mapType: "standard", region: DEFAULT_REGION, - regionToAnimate: null + regionToAnimate: null, }; const reducer = ( state, action ) => { @@ -93,18 +93,18 @@ const reducer = ( state, action ) => { return { ...state, loading: true, - isFirstMapRender: false + isFirstMapRender: false, }; case "HANDLE_FIRST_MAP_RENDER": return { ...state, isFirstMapRender: false, - loading: false + loading: false, }; case "HANDLE_MAP_READY": return { ...state, - loading: false + loading: false, }; case "HANDLE_REGION_CHANGE": return { @@ -112,7 +112,7 @@ const reducer = ( state, action ) => { locationName: action.locationName, region: action.region, accuracy: action.accuracy, - loading: false + loading: false, }; case "INITIALIZE_MAP": { const newMap = initializeMap( state, action ); @@ -125,18 +125,18 @@ const reducer = ( state, action ) => { region: action.region, hidePlaceResults: true, regionToAnimate: action.region, - loading: true + loading: true, }; case "SET_MAP_TYPE": return { ...state, - mapType: action.mapType + mapType: action.mapType, }; case "UPDATE_LOCATION_NAME": return { ...state, locationName: action.locationName, - hidePlaceResults: false + hidePlaceResults: false, }; default: throw new Error( ); @@ -158,7 +158,7 @@ const LocationPickerContainer = ( ): Node => { locationName, mapType, region, - regionToAnimate + regionToAnimate, } = state; const initialRegion = setInitialRegion( currentObservation ); @@ -176,7 +176,7 @@ const LocationPickerContainer = ( ): Node => { type: "HANDLE_REGION_CHANGE", locationName: placeName || "", region: newRegion, - accuracy: newAccuracy + accuracy: newAccuracy, } ); }; @@ -193,7 +193,7 @@ const LocationPickerContainer = ( ): Node => { return unsubscribe; }, - [navigation, currentObservation] + [navigation, currentObservation], ); const selectPlaceResult = place => { @@ -204,13 +204,13 @@ const LocationPickerContainer = ( ): Node => { region: { ...region, latitude: coordinates[1], - longitude: coordinates[0] + longitude: coordinates[0], }, regionToAnimate: { ...region, latitude: coordinates[1], - longitude: coordinates[0] - } + longitude: coordinates[0], + }, } ); }; @@ -222,7 +222,7 @@ const LocationPickerContainer = ( ): Node => { latitude: region.latitude, longitude: region.longitude, positional_accuracy: accuracy, - place_guess: locationName + place_guess: locationName, }; updateObservationKeys( keysToUpdate ); diff --git a/src/components/LocationPicker/LocationSearch.tsx b/src/components/LocationPicker/LocationSearch.tsx index 3278a585b..de3f2feef 100644 --- a/src/components/LocationPicker/LocationSearch.tsx +++ b/src/components/LocationPicker/LocationSearch.tsx @@ -3,7 +3,7 @@ import { fetchSearchResults } from "api/search"; import type { ApiOpts } from "api/types"; import { Body3, - SearchBar + SearchBar, } from "components/SharedComponents"; import { Pressable, View } from "components/styledComponents"; import React, { useRef } from "react"; @@ -29,7 +29,7 @@ interface Props { } const LocationSearch = ( { - locationName = "", updateLocationName, selectPlaceResult, hidePlaceResults + locationName = "", updateLocationName, selectPlaceResult, hidePlaceResults, }: Props ) => { const queryClient = useQueryClient( ); const locationInput = useRef( undefined ); @@ -38,14 +38,14 @@ const LocationSearch = ( { queryClient.invalidateQueries( { queryKey: ["fetchSearchResults"] } ); const { - data: placeResults + data: placeResults, } = useAuthenticatedQuery( ["fetchSearchResults", locationName], ( optsWithAuth: ApiOpts ) => fetchSearchResults( { q: locationName, sources: "places", - fields: "place,place.display_name,place.point_geojson" - }, optsWithAuth ) + fields: "place,place.display_name,place.point_geojson", + }, optsWithAuth ), ); return ( diff --git a/src/components/LocationPicker/WarningText.tsx b/src/components/LocationPicker/WarningText.tsx index 52668561d..80af06066 100644 --- a/src/components/LocationPicker/WarningText.tsx +++ b/src/components/LocationPicker/WarningText.tsx @@ -1,6 +1,6 @@ import classnames from "classnames"; import { - Body3 + Body3, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; @@ -35,7 +35,7 @@ const WarningText = ( { accuracyTest }: Props ) => { pointerEvents="none" className={classnames( "p-4 rounded-xl", { "bg-white": accuracyTest === "acceptable", - "bg-warningRed": accuracyTest === "fail" + "bg-warningRed": accuracyTest === "fail", } )} style={DROP_SHADOW} > @@ -44,8 +44,8 @@ const WarningText = ( { accuracyTest }: Props ) => { "text-darkGray", "text-center", { - "text-white": accuracyTest === "fail" - } + "text-white": accuracyTest === "fail", + }, )} > {displayWarningText( )} diff --git a/src/components/LoginSignUp/AuthenticationService.ts b/src/components/LoginSignUp/AuthenticationService.ts index 54083aca0..dee20ea61 100644 --- a/src/components/LoginSignUp/AuthenticationService.ts +++ b/src/components/LoginSignUp/AuthenticationService.ts @@ -9,7 +9,7 @@ import { photoLibraryPhotosPath, photoUploadPath, rotatedOriginalPhotosPath, - soundUploadPath + soundUploadPath, } from "appConstants/paths"; import { getInatLocaleFromSystemLocale } from "i18n/initI18next"; import i18next from "i18next"; @@ -57,7 +57,7 @@ interface AuthCache { const authCache: AuthCache = { isLoggedIn: null, lastChecked: null, - cacheTimeout: 5000 + cacheTimeout: 5000, }; /** @@ -138,8 +138,8 @@ const createAPI = ( additionalHeaders?: { [header: string]: string } ) => create headers: { "User-Agent": getUserAgent(), "X-Installation-ID": getInstallID( ), - ...additionalHeaders - } + ...additionalHeaders, + }, } ); /** @@ -192,8 +192,8 @@ const signOut = async ( queryClient?: QueryClient; } = { clearRealm: false, - queryClient: undefined - } + queryClient: undefined, + }, ) => { // This makes sure also any cookies will be deleted too (MOB-589) const apiClient = createAPI(); @@ -256,7 +256,7 @@ const encodeJWT = ( payload: object, key: string, algorithm?: string ) => { algorithm, JSON.stringify( { alg: algorithm, typ: "JWT" } ), JSON.stringify( payload ), - key + key, ); }; @@ -268,7 +268,7 @@ const encodeJWT = ( payload: object, key: string, algorithm?: string ) => { const getAnonymousJWT = (): string => { const claims = { application: Platform.OS, - exp: Date.now() / 1000 + 300 + exp: Date.now() / 1000 + 300, }; return encodeJWT( claims, Config.JWT_ANONYMOUS_API_SECRET || "not-a-real-secret", "HS512" ); @@ -283,7 +283,7 @@ const getAnonymousJWT = (): string => { */ const getJWT = async ( allowAnonymousJWT = false, - logContext: string | null = null + logContext: string | null = null, ): Promise => { let jwtToken: string | undefined = await getSensitiveItem( "jwtToken" ); const storedJwtGeneratedAt = await getSensitiveItem( "jwtGeneratedAt" ); @@ -339,7 +339,7 @@ const getJWT = async ( if ( !response.ok ) { logger.error( `JWT [${logContext}]: Token refresh failed - status: ${response.status}`, - `- originalError: ${response.originalError} - problem: ${response.problem}` + `- originalError: ${response.originalError} - problem: ${response.problem}`, ); // this deletes the user JWT and saved login details when a user is not // actually signed in anymore for example, if they installed, deleted, @@ -376,7 +376,7 @@ const getJWT = async ( const showErrorAlert = ( errorText: string ) => { Alert.alert( "", - errorText + errorText, ); }; @@ -412,7 +412,7 @@ interface UserDetails { async function afterVerifyCredentials( tokenResponse: ApiResponse, - apiClient: ApisauceInstance + apiClient: ApisauceInstance, ): Promise { if ( !tokenResponse.ok ) { showErrorAlert( errorDescriptionFromResponse( tokenResponse ) ); @@ -430,9 +430,9 @@ async function afterVerifyCredentials( { headers: { Authorization: `Bearer ${accessToken}`, - "User-Agent": getUserAgent( ) - } - } + "User-Agent": getUserAgent( ), + }, + }, ); if ( !usersEditResponse.ok ) { @@ -441,7 +441,7 @@ async function afterVerifyCredentials( console.error( "verifyCredentials failed when calling /users/edit.json - ", usersEditResponse.problem, - usersEditResponse.status + usersEditResponse.status, ); } @@ -457,7 +457,7 @@ async function afterVerifyCredentials( return { accessToken, username: iNatUsername, - userId: iNatID + userId: iNatID, }; } @@ -471,7 +471,7 @@ async function afterVerifyCredentials( */ async function verifyCredentials( username: string, - password: string + password: string, ): Promise { const formData = { format: "json", @@ -480,7 +480,7 @@ async function verifyCredentials( client_secret: Config.OAUTH_CLIENT_SECRET, password, username, - locale: i18next.language + locale: i18next.language, }; const apiClient = createAPI(); @@ -517,13 +517,13 @@ async function afterAuthenticateUser( userDetails: UserDetails | null, realm: Re // try to fetch user data (especially for loading user icon) from userMe const apiToken = await getJWT( ); const options = { - api_token: apiToken + api_token: apiToken, }; const remoteUser = await fetchUserMe( { }, options ) as ApiUser; const localUser = remoteUser ? { ...remoteUser, - signedIn: true + signedIn: true, } : currentUser; @@ -550,7 +550,7 @@ async function afterAuthenticateUser( userDetails: UserDetails | null, realm: Re const authenticateUser = async ( username: string, password: string, - realm: Realm + realm: Realm, ): Promise => { const userDetails = await verifyCredentials( username, password ); @@ -560,7 +560,7 @@ const authenticateUser = async ( async function authenticateUserByAssertion( assertionType: "apple" | "google", assertion: string, - realm: Realm + realm: Realm, ) { const apiClient = createAPI( { Accept: "application/json" } ); const formData = { @@ -568,11 +568,11 @@ async function authenticateUserByAssertion( client_secret: Config.OAUTH_CLIENT_SECRET, locale: i18next.language, assertion, - assertion_type: assertionType + assertion_type: assertionType, }; const tokenResponse = await apiClient.post( "/oauth/assertion_token", - formData + formData, ); const userDetails = await afterVerifyCredentials( tokenResponse, apiClient ); return afterAuthenticateUser( userDetails, realm ); @@ -599,8 +599,8 @@ const registerUser = async ( user: { password: string } ) => { user: { ...user, password_confirmation: user.password, - locale: locales[0].languageCode - } + locale: locales[0].languageCode, + }, }; const api = createAPI(); @@ -610,7 +610,7 @@ const registerUser = async ( user: { password: string } ) => { console.error( "registerUser failed when calling /users.json - ", response.problem, - response.status + response.status, ); return response.data?.errors?.[0]; } @@ -637,8 +637,8 @@ interface ChangePasswordResponse { const resetPassword = async ( email: string ) => { const formData = { user: { - email - } + email, + }, }; const api = createAPI( ); @@ -664,7 +664,7 @@ const emailAvailable = async ( email: string ) => { // try to fetch user data (especially for loading user icon) from userMe const apiToken = await getAnonymousJWT( ); const options = { - api_token: apiToken + api_token: apiToken, }; const response = await fetchUserEmailAvailable( email, options ) as { available: boolean }; return response?.available; @@ -683,5 +683,5 @@ export { isLoggedIn, registerUser, resetPassword, - signOut + signOut, }; diff --git a/src/components/LoginSignUp/Error.tsx b/src/components/LoginSignUp/Error.tsx index cfd19bac5..aa254c406 100644 --- a/src/components/LoginSignUp/Error.tsx +++ b/src/components/LoginSignUp/Error.tsx @@ -1,6 +1,6 @@ import { INatIcon, - List2 + List2, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React from "react"; diff --git a/src/components/LoginSignUp/ForgotPassword.tsx b/src/components/LoginSignUp/ForgotPassword.tsx index 9103f19c5..f10ab90a9 100644 --- a/src/components/LoginSignUp/ForgotPassword.tsx +++ b/src/components/LoginSignUp/ForgotPassword.tsx @@ -7,7 +7,7 @@ import { Keyboard, TouchableWithoutFeedback } from "react-native"; import { openInbox } from "sharedHelpers/mail"; import { - resetPassword + resetPassword, } from "./AuthenticationService"; import ForgotPasswordForm from "./ForgotPasswordForm"; import Header from "./Header"; diff --git a/src/components/LoginSignUp/ForgotPasswordForm.tsx b/src/components/LoginSignUp/ForgotPasswordForm.tsx index b1979587e..6c95f9798 100644 --- a/src/components/LoginSignUp/ForgotPasswordForm.tsx +++ b/src/components/LoginSignUp/ForgotPasswordForm.tsx @@ -1,14 +1,14 @@ import { useNavigation } from "@react-navigation/native"; import { Body1, - Button + Button, } from "components/SharedComponents"; import type { ScrollView } from "components/styledComponents"; import { View } from "components/styledComponents"; import { t } from "i18next"; import type { ElementRef, Node } from "react"; import React, { - useCallback, useEffect, useRef, useState + useCallback, useEffect, useRef, useState, } from "react"; import { TouchableWithoutFeedback } from "react-native"; import useKeyboardInfo from "sharedHooks/useKeyboardInfo"; @@ -53,7 +53,7 @@ const ForgotPasswordForm = ( { reset, scrollViewRef }: Props ): Node => { ( _, y ) => { scrollViewRef.current?.scrollTo( { y, animated: true } ); }, - () => console.log( "Failed to measure" ) + () => console.log( "Failed to measure" ), ); } }, [scrollViewRef] ); diff --git a/src/components/LoginSignUp/LearnMore.tsx b/src/components/LoginSignUp/LearnMore.tsx index f2275b976..5dad483d7 100644 --- a/src/components/LoginSignUp/LearnMore.tsx +++ b/src/components/LoginSignUp/LearnMore.tsx @@ -1,6 +1,6 @@ import { useNavigation } from "@react-navigation/native"; import { - Button + Button, } from "components/SharedComponents"; import { View } from "components/styledComponents"; import React, { useCallback } from "react"; @@ -20,7 +20,7 @@ const LearnMore = ( ) => { navigation.navigate( "FullPageWebView", { title, initialUrl: url, - loggedIn: false + loggedIn: false, } ) ), [navigation] ); @@ -41,7 +41,7 @@ const LearnMore = ( ) => { text={t( "COMMUNITY-GUIDELINES" )} onPress={() => navToUrl( `${BASE_URL}/pages/community+guidelines`, - t( "COMMUNITY-GUIDELINES" ) + t( "COMMUNITY-GUIDELINES" ), )} className="mt-5" /> diff --git a/src/components/LoginSignUp/LoginForm.tsx b/src/components/LoginSignUp/LoginForm.tsx index 486dc69c3..68b6c26c7 100644 --- a/src/components/LoginSignUp/LoginForm.tsx +++ b/src/components/LoginSignUp/LoginForm.tsx @@ -3,19 +3,19 @@ import { useNavigation, useRoute } from "@react-navigation/native"; import classnames from "classnames"; import { authenticateUser } from "components/LoginSignUp/AuthenticationService"; import { - Body1, Body2, Button, Heading4, INatIcon, INatIconButton, List2 + Body1, Body2, Button, Heading4, INatIcon, INatIconButton, List2, } from "components/SharedComponents"; import { Image, View } from "components/styledComponents"; import { t } from "i18next"; import { RealmContext } from "providers/contexts"; import React, { - useCallback, useEffect, useRef, useState + useCallback, useEffect, useRef, useState, } from "react"; import { Trans } from "react-i18next"; import type { TextInput } from "react-native"; import { Platform, - TouchableWithoutFeedback + TouchableWithoutFeedback, } from "react-native"; import { useCurrentUser, useLayoutPrefs } from "sharedHooks"; import useKeyboardInfo from "sharedHooks/useKeyboardInfo"; @@ -42,7 +42,7 @@ type ParamList = { } const LoginForm = ( { - scrollViewRef + scrollViewRef, }: Props ) => { const navigation = useNavigation( ); const { params } = useRoute>( ); @@ -105,9 +105,9 @@ const LoginForm = ( { params: { screen: "ProjectDetails", params: { - id: params?.projectId - } - } + id: params?.projectId, + }, + }, } ); } else { navigation.getParent( )?.goBack( ); @@ -116,7 +116,7 @@ const LoginForm = ( { navigation, params, isDefaultMode, - setLoggedInWhileInDefaultMode + setLoggedInWhileInDefaultMode, ] ); const scrollToItem = useCallback( ( ) => { @@ -125,7 +125,7 @@ const LoginForm = ( { ( _, y ) => { scrollViewRef.current.scrollTo( { y, animated: true } ); }, - () => console.log( "Failed to measure" ) + () => console.log( "Failed to measure" ), ); }, [scrollViewRef] ); @@ -186,7 +186,7 @@ const LoginForm = ( { "self-center mt-[31px] underline", // When the keyboard is up this pushes the form up enough to cut // off the username label on some devices - !keyboardShown && "mb-[35px]" + !keyboardShown && "mb-[35px]", )} i18nKey="Dont-have-an-account" onPress={( ) => navigation.navigate( "SignUp" )} @@ -198,7 +198,7 @@ const LoginForm = ( { + />, ]} /> @@ -281,7 +281,7 @@ const LoginForm = ( { {error && }