MOB-512 merge main

This commit is contained in:
sepeterson
2025-12-04 21:31:43 -06:00
322 changed files with 1069 additions and 1410 deletions

View File

@@ -143,7 +143,10 @@ module.exports = {
"@typescript-eslint/no-require-imports": ["error", {
allow: ["\\.(png|jpg|jpeg|gif|svg)$"]
}],
"@typescript-eslint/no-unsafe-function-type": 1
"@typescript-eslint/no-unsafe-function-type": 1,
"@typescript-eslint/consistent-type-imports": ["error", {
fixStyle: "separate-type-imports"
}]
},
ignorePatterns: ["!.detoxrc.js", "/coverage/*", "/vendor/*", "**/flow-typed"],
settings: {
@@ -161,7 +164,8 @@ module.exports = {
rules: {
"@typescript-eslint/no-unsafe-function-type": "off",
"@typescript-eslint/no-wrapper-object-types": "off",
"@typescript-eslint/no-require-imports": "off"
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/consistent-type-imports": "off"
}
},
{

View File

@@ -1,7 +1,7 @@
// Mostly from https://github.com/pmndrs/zustand/blob/main/docs/guides/testing.md#jest
import { cloneDeep } from "lodash";
import * as zustand from "zustand";
import type * as zustand from "zustand";
const { create: actualCreate, createStore: actualCreateStore }
= jest.requireActual<typeof zustand>( "zustand" );

View File

@@ -106,7 +106,7 @@ android {
applicationId "org.inaturalist.iNaturalistMobile"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 186
versionCode 188
versionName "1.0.12"
setProperty("archivesBaseName", applicationId + "-v" + versionName + "+" + versionCode)
manifestPlaceholders = [ GMAPS_API_KEY:project.env.get("GMAPS_API_KEY") ]

View File

Binary file not shown.

View File

@@ -3,7 +3,7 @@
"data": [
{
"path": "assets/fonts/INatIcon.ttf",
"sha1": "5d5f17b0bc5f9c93ed4c91ff0dedb22bd9533c8e"
"sha1": "fd39a22358ae97185bfd8f774c928b64f9743d40"
},
{
"path": "assets/fonts/Lato-Bold.ttf",

View File

Binary file not shown.

View File

@@ -1,32 +0,0 @@
import {
by, element, expect, waitFor
} from "detox";
const TIMEOUT = 10_000;
// Start this on ObsEdit or ObsDetails via uploaded = false / true
export default async function deleteObservation( options = { uploaded: false } ) {
if ( options.uploaded ) {
const editButton = element( by.id( "ObsDetail.editButton" ) );
await waitFor( editButton ).toBeVisible().withTimeout( TIMEOUT );
// Navigate to the edit screen
await editButton.tap();
}
// Check that the edit screen is visible
await waitFor( element( by.text( "EVIDENCE" ) ) )
.toBeVisible()
.withTimeout( TIMEOUT );
// Press header kebab menu
const headerKebabMenu = element( by.id( "KebabMenu.Button" ) );
await expect( headerKebabMenu ).toBeVisible();
await headerKebabMenu.tap();
// Press delete observation
const deleteObservationMenuItem = element( by.id( "Header.delete-observation" ) );
await waitFor( deleteObservationMenuItem ).toBeVisible().withTimeout( TIMEOUT );
await deleteObservationMenuItem.tap();
// Check that the delete button is visible
const deleteObservationButton = element( by.text( "DELETE" ) );
await waitFor( deleteObservationButton ).toBeVisible().withTimeout( TIMEOUT );
// Press delete observation
await deleteObservationButton.tap();
}

View File

@@ -85,10 +85,14 @@ export default async function resetUserForTesting() {
console.log( `Dismissing ${announcementIdsToDismiss.length} announcements` );
await Promise.all( announcementIdsToDismiss.map( async id => {
await inatjs.announcements.dismiss(
{ id },
opts
);
try {
await inatjs.announcements.dismiss(
{ id },
opts
);
} catch ( _error ) {
console.log( `Could not delete announcement: ${id}. Moving on...` );
}
} ) );
const usersEditResponse = await apiClient.get(
"/users/edit.json",

View File

@@ -4,7 +4,6 @@ import {
import { iNatE2eAfterEach, iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers";
import closeOnboarding from "./sharedFlows/closeOnboarding";
import deleteObservation from "./sharedFlows/deleteObservation";
import signIn from "./sharedFlows/signIn";
import uploadObservation from "./sharedFlows/uploadObservation";
@@ -45,10 +44,33 @@ describe( "Signed in user", () => {
return uuid;
}
async function deleteObservationByUUID( uuid, username, options = { uploaded: false } ) {
async function deleteObservationByUUID( uuid, username ) {
const obsListItem = element( by.id( `MyObservations.obsListItem.${uuid}` ) );
await obsListItem.tap();
await deleteObservation( options );
const editButton = element( by.id( "ObsDetail.editButton" ) );
await waitFor( editButton ).toBeVisible().withTimeout( TIMEOUT );
// Navigate to the edit screen
await editButton.tap();
// Check that the edit screen is visible
await waitFor( element( by.text( "EVIDENCE" ) ) )
.toBeVisible()
.withTimeout( TIMEOUT );
// Press header kebab menu
const headerKebabMenu = element( by.id( "KebabMenu.Button" ) );
await expect( headerKebabMenu ).toBeVisible();
await headerKebabMenu.tap();
// Press delete observation
const deleteObservationMenuItem = element( by.id( "Header.delete-observation" ) );
await waitFor( deleteObservationMenuItem ).toBeVisible().withTimeout( TIMEOUT );
await deleteObservationMenuItem.tap();
// Check that the delete button is visible
const deleteObservationButton = element( by.text( "DELETE" ) );
await waitFor( deleteObservationButton ).toBeVisible().withTimeout( TIMEOUT );
// Press delete observation
await deleteObservationButton.tap();
// Make sure we're back on MyObservations
await waitFor( username ).toBeVisible().withTimeout( TIMEOUT );
}
@@ -104,7 +126,7 @@ describe( "Signed in user", () => {
/*
/ 4. Delete the two observations without evidence
*/
await deleteObservationByUUID( uuid, username, { uploaded: true } );
await deleteObservationByUUID( uuid, username );
// It would be nice to test for the "1 observation deleted" status text in
// the toolbar, but that message appears ephemerally and sometimes this
// test doesn't pick it up on the Github runner. Since we created two

View File

@@ -0,0 +1,6 @@
UPDATED
* Observation wheel re-design to sheet
FIXED
* Fix observation wheel/sheet tooltip not showing up
* Carousel titles center align

View File

@@ -0,0 +1,2 @@
UPDATED
* Minor UI updates

View File

@@ -548,7 +548,7 @@
CODE_SIGN_ENTITLEMENTS = iNaturalistReactNative/iNaturalistReactNative.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CURRENT_PROJECT_VERSION = 186;
CURRENT_PROJECT_VERSION = 188;
DEVELOPMENT_TEAM = N5J7L4P93Z;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -675,7 +675,7 @@
CODE_SIGN_ENTITLEMENTS = iNaturalistReactNative/iNaturalistReactNativeRelease.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CURRENT_PROJECT_VERSION = 186;
CURRENT_PROJECT_VERSION = 188;
DEVELOPMENT_TEAM = N5J7L4P93Z;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
HEADER_SEARCH_PATHS = (
@@ -988,7 +988,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "iNaturalistReactNative-ShareExtension/iNaturalistReactNative-ShareExtension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 186;
CURRENT_PROJECT_VERSION = 188;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = N5J7L4P93Z;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
@@ -1033,7 +1033,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 186;
CURRENT_PROJECT_VERSION = 188;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = N5J7L4P93Z;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";

View File

@@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>186</string>
<string>188</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>

View File

@@ -3,7 +3,7 @@
"data": [
{
"path": "assets/fonts/INatIcon.ttf",
"sha1": "5d5f17b0bc5f9c93ed4c91ff0dedb22bd9533c8e"
"sha1": "fd39a22358ae97185bfd8f774c928b64f9743d40"
},
{
"path": "assets/fonts/Lato-Bold.ttf",

View File

@@ -25,7 +25,7 @@ const localPackagePaths = [
*/
const config = {
transformer: {
babelTransformerPath: require.resolve( "react-native-svg-transformer" )
babelTransformerPath: require.resolve( "react-native-svg-transformer/react-native" )
},
resolver: {
assetExts: assetExts.filter( ext => ext !== "svg" ),

9
package-lock.json generated
View File

@@ -94,7 +94,7 @@
"react-native-share-menu": "github:inaturalist/react-native-share-menu#iNaturalistReactNative",
"react-native-store-review": "^0.4.3",
"react-native-svg": "^15.15.0",
"react-native-svg-transformer": "^1.3.0",
"react-native-svg-transformer": "^1.5.2",
"react-native-url-polyfill": "^2.0.0",
"react-native-vision-camera": "^4.7.2",
"react-native-volume-manager": "^2.0.8",
@@ -20325,9 +20325,10 @@
}
},
"node_modules/react-native-svg-transformer": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-native-svg-transformer/-/react-native-svg-transformer-1.3.0.tgz",
"integrity": "sha512-SV92uRjENDuanHLVuLy2Sdvt6f8vu7qnG8vC9CwBiAXV0BpWN4/wPvfc+r2WPAkcctRZLLOvrGnGA2o8nZd0cg==",
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/react-native-svg-transformer/-/react-native-svg-transformer-1.5.2.tgz",
"integrity": "sha512-eW4hOtrd30s4SRdN4X1XYxTCu1czsxDGQKmfQ3RFbZMN5yw4ZmiKGGr+lXbQW4uDGZvSoGd9FHL1f+rgGoKg8Q==",
"license": "MIT",
"dependencies": {
"@svgr/core": "^8.1.0",
"@svgr/plugin-jsx": "^8.1.0",

View File

@@ -130,7 +130,7 @@
"react-native-share-menu": "github:inaturalist/react-native-share-menu#iNaturalistReactNative",
"react-native-store-review": "^0.4.3",
"react-native-svg": "^15.15.0",
"react-native-svg-transformer": "^1.3.0",
"react-native-svg-transformer": "^1.5.2",
"react-native-url-polyfill": "^2.0.0",
"react-native-vision-camera": "^4.7.2",
"react-native-volume-manager": "^2.0.8",

View File

@@ -3,7 +3,7 @@ import { create } from "apisauce";
// eslint-disable-next-line import/no-cycle
import { getAnonymousJWT, getJWT } from "components/LoginSignUp/AuthenticationService";
import Config from "react-native-config";
import { transportFunctionType } from "react-native-logs";
import type { transportFunctionType } from "react-native-logs";
import { getInstallID } from "sharedHelpers/installData";
const API_HOST: string

View File

@@ -1,4 +1,5 @@
import handleError, { ErrorWithResponse, INatApiError } from "api/error";
import type { ErrorWithResponse, INatApiError } from "api/error";
import handleError from "api/error";
import inatjs from "inaturalistjs";
const fetchAvailableLocales = async (

View File

@@ -42,7 +42,7 @@ const AddObsBottomSheet = ( {
const obsCreateItems = useMemo( ( ) => ( {
aiCamera: {
text: t( "ID-with-AI-Camera" ),
text: t( "ID-in-Camera" ),
icon: "aicamera",
onPress: ( ) => navAndCloseBottomSheet( "Camera", { camera: "AI" } ),
testID: "aicamera-button",

View File

@@ -8,7 +8,7 @@ import Zoom from "components/Camera/Buttons/Zoom";
import TabletButtons from "components/Camera/TabletButtons";
import { View } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent, ViewStyle } from "react-native";
import type { GestureResponderEvent, ViewStyle } from "react-native";
import DeviceInfo from "react-native-device-info";
import type { CameraDeviceFormat, TakePhotoOptions } from "react-native-vision-camera";
import { useLayoutPrefs } from "sharedHooks";
@@ -30,10 +30,15 @@ interface Props {
rotatableAnimatedStyle: ViewStyle;
debugFormat?: CameraDeviceFormat;
// Those five are debug only so I don't bother with types
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setConfidenceThreshold?: Function;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setCropRatio?: Function;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setFPS?: Function;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setNumStoredResults?: Function;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
changeDebugFormat?: Function;
showPrediction: boolean;
showZoomButton: boolean;

View File

@@ -1,6 +1,6 @@
import { RealmContext } from "providers/contexts";
import { useState } from "react";
import { Result } from "vision-camera-plugin-inatvision";
import type { Result } from "vision-camera-plugin-inatvision";
const { useRealm } = RealmContext;

View File

@@ -1,6 +1,6 @@
import { TransparentCircleButton } from "components/SharedComponents";
import React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import { useTranslation } from "sharedHooks";
interface Props {

View File

@@ -2,7 +2,7 @@ import classnames from "classnames";
// eslint-disable-next-line max-len
import TransparentCircleButton from "components/SharedComponents/Buttons/TransparentCircleButton";
import React from "react";
import { GestureResponderEvent, ViewStyle } from "react-native";
import type { GestureResponderEvent, ViewStyle } from "react-native";
import DeviceInfo from "react-native-device-info";
import Animated from "react-native-reanimated";
import type { TakePhotoOptions } from "react-native-vision-camera";

View File

@@ -2,7 +2,7 @@ import {
INatIconButton
} from "components/SharedComponents";
import React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import { useTranslation } from "sharedHooks";
import colors from "styles/tailwindColors";

View File

@@ -1,7 +1,7 @@
// eslint-disable-next-line max-len
import TransparentCircleButton from "components/SharedComponents/Buttons/TransparentCircleButton";
import React from "react";
import { GestureResponderEvent, ViewStyle } from "react-native";
import type { GestureResponderEvent, ViewStyle } from "react-native";
import DeviceInfo from "react-native-device-info";
import Animated from "react-native-reanimated";
import { useTranslation } from "sharedHooks";

View File

@@ -2,7 +2,7 @@ import { useNavigation } from "@react-navigation/native";
import classnames from "classnames";
import { INatIconButton } from "components/SharedComponents";
import React from "react";
import { ViewStyle } from "react-native";
import type { ViewStyle } from "react-native";
import DeviceInfo from "react-native-device-info";
import Animated from "react-native-reanimated";
import { useTranslation } from "sharedHooks";

View File

@@ -5,7 +5,7 @@ import {
} from "components/SharedComponents/Buttons/TransparentCircleButton";
import { Pressable } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent, ViewStyle } from "react-native";
import type { GestureResponderEvent, ViewStyle } from "react-native";
import DeviceInfo from "react-native-device-info";
import Animated from "react-native-reanimated";
import { useTranslation } from "sharedHooks";

View File

@@ -1,6 +1,6 @@
import { useNavigation, useRoute } from "@react-navigation/native";
import type { Camera } from "components/Camera/helpers/visionCameraWrapper";
import {
Camera,
useCameraDevice,
useCameraDevices
} from "components/Camera/helpers/visionCameraWrapper";

View File

@@ -11,12 +11,14 @@ import React, {
import {
Dimensions, Platform, StyleSheet
} from "react-native";
import {
Gesture,
GestureDetector,
import type {
PanGesture,
PinchGesture
} from "react-native-gesture-handler";
import {
Gesture,
GestureDetector
} from "react-native-gesture-handler";
import Reanimated from "react-native-reanimated";
import type {
CameraDevice, CameraDeviceFormat, CameraProps, CameraRuntimeError

View File

@@ -3,7 +3,7 @@ import React from "react";
import DeviceInfo from "react-native-device-info";
import type { CameraDevice } from "react-native-vision-camera";
import useDeviceOrientation from "sharedHooks/useDeviceOrientation";
import { UserLocation } from "sharedHooks/useWatchPosition";
import type { UserLocation } from "sharedHooks/useWatchPosition";
import AICamera from "./AICamera/AICamera";
import StandardCamera from "./StandardCamera/StandardCamera";
@@ -16,10 +16,13 @@ interface Props {
camera: object,
flipCamera: ( ) => void,
handleCheckmarkPress: ( ) => void,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
toggleFlash: Function,
takingPhoto: boolean,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
takePhotoAndStoreUri: Function,
newPhotoUris: Array<object>,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setNewPhotoUris: Function,
takePhotoOptions: object,
userLocation: UserLocation | null,

View File

@@ -3,7 +3,7 @@ import PhotoLibraryIcon from "components/Camera/Buttons/PhotoLibraryIcon";
import { CloseButton } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent, ViewStyle } from "react-native";
import type { GestureResponderEvent, ViewStyle } from "react-native";
import DeviceInfo from "react-native-device-info";
import Animated from "react-native-reanimated";
import type { TakePhotoOptions } from "react-native-vision-camera";

View File

@@ -1,5 +1,5 @@
import { Alert } from "react-native";
import { CameraRuntimeError } from "react-native-vision-camera";
import type { CameraRuntimeError } from "react-native-vision-camera";
import { log } from "../../../../react-native-logs.config";

View File

@@ -1,13 +1,16 @@
import { Camera } from "components/Camera/helpers/visionCameraWrapper";
import React, {
import type { Camera } from "components/Camera/helpers/visionCameraWrapper";
import type React from "react";
import {
useCallback, useMemo, useRef, useState
} from "react";
import { Animated } from "react-native";
import {
Gesture,
import type {
GestureStateChangeEvent,
TapGestureHandlerEventPayload
} from "react-native-gesture-handler";
import {
Gesture
} from "react-native-gesture-handler";
const HALF_SIZE_FOCUS_BOX = 33;

View File

@@ -17,8 +17,8 @@ import RNFS from "react-native-fs";
import RNRestart from "react-native-restart";
import useLogs from "sharedHooks/useLogs";
import type { DirectoryEntrySize } from "./hooks/useAppSize";
import useAppSize, {
DirectoryEntrySize,
formatAppSizeString, formatSizeUnits, getTotalDirectorySize
} from "./hooks/useAppSize";

View File

@@ -5,13 +5,14 @@ import {
} 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, MapBoundaries, PLACE_MODE, useExplore
EXPLORE_ACTION, PLACE_MODE, useExplore
} from "providers/ExploreContext";
import React, {
useEffect, useMemo, useRef, useState
} from "react";
import { Region } from "react-native-maps";
import type { Region } from "react-native-maps";
import { useTranslation } from "sharedHooks";
import { getShadow } from "styles/global";
@@ -58,7 +59,9 @@ interface Props {
};
isLoading: boolean,
hasLocationPermissions?: boolean,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
renderLocationPermissionsGate: Function,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
requestLocationPermissions: Function
}

View File

@@ -32,7 +32,7 @@ const ObservationsViewBar = ( {
},
{
value: "list",
icon: "hamburger-menu",
icon: "list",
accessibilityLabel: "List",
testID: "SegmentedButton.list"
}

View File

@@ -1,5 +1,5 @@
import type { RouteProp } from "@react-navigation/native";
import {
RouteProp,
useFocusEffect,
useNavigation,
useRoute

View File

@@ -1,4 +1,5 @@
import { getHeaderTitle, HeaderTitleProps } from "@react-navigation/elements";
import type { HeaderTitleProps } from "@react-navigation/elements";
import { getHeaderTitle } from "@react-navigation/elements";
import classNames from "classnames";
import { Heading4 } from "components/SharedComponents";
import BackButton from "components/SharedComponents/Buttons/BackButton";

View File

@@ -1,7 +1,7 @@
import { Button } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import useTranslation from "sharedHooks/useTranslation";
interface Props {

View File

@@ -7,7 +7,8 @@ import {
} from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import React, { useRef } from "react";
import { Keyboard, TextInput } from "react-native";
import type { TextInput } from "react-native";
import { Keyboard } from "react-native";
import useAuthenticatedQuery from "sharedHooks/useAuthenticatedQuery";
import { getShadow } from "styles/global";

View File

@@ -2,7 +2,8 @@ import type { QueryClient } from "@tanstack/query-core";
import type { ApiUser } from "api/types";
import { getUserAgent } from "api/userAgent";
import { fetchUserEmailAvailable, fetchUserMe } from "api/users";
import { ApiResponse, ApisauceInstance, create } from "apisauce";
import type { ApiResponse, ApisauceInstance } from "apisauce";
import { create } from "apisauce";
import {
computerVisionPath,
photoLibraryPhotosPath,

View File

@@ -1,6 +1,6 @@
import { useNavigation } from "@react-navigation/native";
import { WarningSheet } from "components/SharedComponents";
import { ScrollView } from "components/styledComponents";
import type { ScrollView } from "components/styledComponents";
import { t } from "i18next";
import React, { useCallback, useState } from "react";
import { Keyboard, TouchableWithoutFeedback } from "react-native";

View File

@@ -1,11 +1,10 @@
// @flow
import { useNavigation } from "@react-navigation/native";
import {
Body1,
Button
} from "components/SharedComponents";
import { ScrollView, View } from "components/styledComponents";
import type { ScrollView } from "components/styledComponents";
import { View } from "components/styledComponents";
import { t } from "i18next";
import type { ElementRef, Node } from "react";
import React, {

View File

@@ -1,4 +1,5 @@
import { RouteProp, useNavigation, useRoute } from "@react-navigation/native";
import type { RouteProp } from "@react-navigation/native";
import { useNavigation, useRoute } from "@react-navigation/native";
import classnames from "classnames";
import { authenticateUser } from "components/LoginSignUp/AuthenticationService";
import {
@@ -11,9 +12,9 @@ import React, {
useCallback, useEffect, useRef, useState
} from "react";
import { Trans } from "react-i18next";
import type { TextInput } from "react-native";
import {
Platform,
TextInput,
TouchableWithoutFeedback
} from "react-native";
import { useCurrentUser, useLayoutPrefs } from "sharedHooks";

View File

@@ -1,7 +1,8 @@
import { Heading4 } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React, { forwardRef, Ref } from "react";
import { TextInput as RNTextInput, TextInputProps } from "react-native";
import type { Ref } from "react";
import React, { forwardRef } from "react";
import type { TextInput as RNTextInput, TextInputProps } from "react-native";
import { TextInput } from "react-native-paper";
import colors from "styles/tailwindColors";

View File

@@ -2,9 +2,8 @@ import { useNavigation } from "@react-navigation/native";
import {
ImageBackground, ScrollView, View
} from "components/styledComponents";
import React, {
PropsWithChildren, useEffect, useRef
} from "react";
import type { PropsWithChildren } from "react";
import React, { useEffect, useRef } from "react";
import type {
ImageSourcePropType,
ImageStyle,

View File

@@ -10,7 +10,8 @@ import { t } from "i18next";
import { RealmContext } from "providers/contexts";
import React, { useEffect, useRef, useState } from "react";
import { Trans } from "react-i18next";
import { TextInput, TouchableWithoutFeedback } from "react-native";
import type { TextInput } from "react-native";
import { TouchableWithoutFeedback } from "react-native";
import useStore from "stores/useStore";
import {

View File

@@ -3,7 +3,8 @@ import { Button } from "components/SharedComponents";
import { View } from "components/styledComponents";
import { t } from "i18next";
import React, { useEffect, useRef, useState } from "react";
import { TextInput, TouchableWithoutFeedback } from "react-native";
import type { TextInput } from "react-native";
import { TouchableWithoutFeedback } from "react-native";
import { emailAvailable } from "./AuthenticationService";
import Error from "./Error";

View File

@@ -1,6 +1,7 @@
// Helpers for LoginForm. Might be better in AuthenticationService, but
// there's also some UI-related stuff in here, e.g. alerts
import { appleAuth, AppleError } from "@invertase/react-native-apple-authentication";
import type { AppleError } from "@invertase/react-native-apple-authentication";
import { appleAuth } from "@invertase/react-native-apple-authentication";
import {
GoogleSignin,
statusCodes as googleStatusCodes
@@ -8,7 +9,7 @@ import {
import { t } from "i18next";
import { Alert } from "react-native";
import Config from "react-native-config";
import Realm from "realm";
import type Realm from "realm";
import { log } from "sharedHelpers/logger";
import {

View File

@@ -3,7 +3,8 @@ import {
} from "components/SharedComponents";
import { View } from "components/styledComponents";
import React, { useEffect, useRef } from "react";
import { Animated, ViewStyle } from "react-native";
import type { ViewStyle } from "react-native";
import { Animated } from "react-native";
import { useTranslation } from "sharedHooks";
import colors from "styles/tailwindColors";

View File

@@ -1,4 +1,4 @@
import Taxon from "realmModels/Taxon";
import type Taxon from "realmModels/Taxon";
import type { RealmTaxon } from "realmModels/types";
const tryToReplaceWithLocalTaxon = (

View File

@@ -12,7 +12,7 @@ import { View } from "components/styledComponents";
import { t } from "i18next";
import React, { useCallback, useMemo, useState } from "react";
import createOpenLink from "react-native-open-maps";
import Observation from "realmModels/Observation";
import type Observation from "realmModels/Observation";
import { useCurrentUser } from "sharedHooks";
import DetailsMapHeader from "./DetailsMapHeader";

View File

@@ -26,7 +26,7 @@ const MasonryLayout = ( { items, onImagePress } ) => {
return item;
}
const imageDimensions = await getImageDimensions( photoUrl( item ) );
return { ...item, ...imageDimensions };
return Object.assign( item, imageDimensions );
} );
const itemData = await Promise.all( itemPromises );

View File

@@ -16,8 +16,11 @@ interface Props {
body?: string,
taxon: { id: number }
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
onSuggestId:Function,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
editIdentBody: Function,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
onPressClose: Function
}

View File

@@ -1,5 +1,6 @@
import { Body4, DisplayTaxonName } from "components/SharedComponents";
import React, { FC, useCallback } from "react";
import type { FC } from "react";
import React, { useCallback } from "react";
import { Trans } from "react-i18next";
import { useCurrentUser } from "sharedHooks";

View File

@@ -5,7 +5,7 @@ import { ScrollView, View } from "components/styledComponents";
import React, {
useRef
} from "react";
import Observation from "realmModels/Observation";
import type Observation from "realmModels/Observation";
import type { RealmObservation, RealmUser } from "realmModels/types";
import {
useScrollToOffset

View File

@@ -16,8 +16,11 @@ interface Props {
body?: string,
taxon: { id: number }
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
onSuggestId:Function,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
editIdentBody: Function,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
onPressClose: Function
}

View File

@@ -21,6 +21,7 @@ export type ButtonType = typeof SAVE | typeof UPLOAD | null;
type Props = {
buttonPressed: ButtonType,
canSaveOnly: boolean,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
handlePress: Function,
loading: boolean,
showFocusedChangesButton: boolean,

View File

@@ -25,7 +25,9 @@ type Props = {
observations: Array<object>,
currentObservation: RealmObservation,
currentObservationIndex: number,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setCurrentObservationIndex: Function,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
transitionAnimation: Function
}

View File

@@ -93,7 +93,7 @@ const IdentificationSection = ( {
? "neutral"
: "focus"}
onPress={navToSuggestions}
text={t( "ID-WITH-AI" )}
text={t( "IDENTIFY" )}
className={classnames( "rounded-full py-1 mr-4 h-[36px]", {
"border border-darkGray border-[2px]": identTaxon
} )}

View File

@@ -1,8 +1,10 @@
import classNames, { ArgumentArray } from "classnames";
import type { ArgumentArray } from "classnames";
import classNames from "classnames";
import { INatIcon, PhotoCount } from "components/SharedComponents";
import { LinearGradient, View } from "components/styledComponents";
import React, { PropsWithChildren, useCallback } from "react";
import { ViewStyle } from "react-native";
import type { PropsWithChildren } from "react";
import React, { useCallback } from "react";
import type { ViewStyle } from "react-native";
import { getShadow } from "styles/global";
import colors from "styles/tailwindColors";

View File

@@ -5,7 +5,7 @@ import {
} from "components/SharedComponents";
import { Image, Pressable, View } from "components/styledComponents";
import * as React from "react";
import { ImageSourcePropType, ImageStyle } from "react-native";
import type { ImageSourcePropType, ImageStyle } from "react-native";
import { useTranslation } from "sharedHooks";
import useStore from "stores/useStore";
import colors from "styles/tailwindColors";

View File

@@ -1,6 +1,7 @@
import { INatIconButton, ViewWrapper } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React, { PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
import { StatusBar } from "react-native";
import { useTranslation } from "sharedHooks";
import colors from "styles/tailwindColors";

View File

@@ -14,7 +14,7 @@ import {
SearchBar,
Tabs
} from "components/SharedComponents";
import { Tab } from "components/SharedComponents/Tabs/Tabs";
import type { Tab } from "components/SharedComponents/Tabs/Tabs";
import { View } from "components/styledComponents";
import React, { useCallback, useEffect } from "react";
import {

View File

@@ -8,7 +8,8 @@ import React, { useCallback } from "react";
import {
View
} from "react-native";
import User, { TaxonNamesSettings } from "realmModels/User";
import type { TaxonNamesSettings } from "realmModels/User";
import User from "realmModels/User";
import {
useCurrentUser,
useTranslation

View File

@@ -2,8 +2,9 @@
import classNames from "classnames";
import { INatIcon } from "components/SharedComponents";
import { View } from "components/styledComponents";
import type { PropsWithChildren } from "react";
import React, {
memo, PropsWithChildren, useEffect, useState
memo, useEffect, useState
} from "react";
import { StyleSheet, useWindowDimensions } from "react-native";
import Animated, {

View File

@@ -1,6 +1,7 @@
import React from "react";
import { ViewStyle } from "react-native";
import { ActivityIndicator as RNPActivityIndicator, MD3Theme } from "react-native-paper";
import type { ViewStyle } from "react-native";
import type { MD3Theme } from "react-native-paper";
import { ActivityIndicator as RNPActivityIndicator } from "react-native-paper";
import colors from "styles/tailwindColors";
interface Props {

View File

@@ -1,7 +1,8 @@
import classNames from "classnames";
import { Button } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React, { PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
import { getShadow } from "styles/global";
const DROP_SHADOW = getShadow( {

View File

@@ -2,8 +2,9 @@ import { HeaderBackButton } from "@react-navigation/elements";
import { useNavigation } from "@react-navigation/native";
import { Image } from "components/styledComponents";
import React from "react";
import type { ImageStyle, StyleProp } from "react-native";
import {
I18nManager, ImageStyle, Platform, StyleProp
I18nManager, Platform
} from "react-native";
import {
useTranslation

View File

@@ -3,7 +3,7 @@ import classnames from "classnames";
import { ActivityIndicator, Heading4, INatIcon } from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import React, { useRef, useState } from "react";
import { AccessibilityRole, GestureResponderEvent, ViewStyle } from "react-native";
import type { AccessibilityRole, GestureResponderEvent, ViewStyle } from "react-native";
import colors from "styles/tailwindColors";
interface ButtonProps {

View File

@@ -2,7 +2,7 @@ import { INatIcon } from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import { t } from "i18next";
import * as React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import LinearGradient from "react-native-linear-gradient";
import { dropShadow } from "styles/global";
import colors from "styles/tailwindColors";

View File

@@ -2,13 +2,16 @@ import classnames from "classnames";
import { INatIcon } from "components/SharedComponents";
import { View } from "components/styledComponents";
import { getCurrentRoute } from "navigation/navigationUtils";
import React, { PropsWithChildren } from "react";
import {
import type { PropsWithChildren } from "react";
import React from "react";
import type {
GestureResponderEvent,
Platform,
Pressable,
ViewStyle
} from "react-native";
import {
Platform,
Pressable
} from "react-native";
import { log } from "sharedHelpers/logger";
import colors from "styles/tailwindColors";

View File

@@ -1,8 +1,8 @@
import { getAnalytics, logEvent } from "@react-native-firebase/analytics";
import { getCurrentRoute } from "navigation/navigationUtils";
import React from "react";
import type { PressableProps } from "react-native";
import { GestureResponderEvent, Pressable } from "react-native";
import type { GestureResponderEvent, PressableProps } from "react-native";
import { Pressable } from "react-native";
import { log } from "sharedHelpers/logger";
const logger = log.extend( "PressableWithTracking" );

View File

@@ -1,7 +1,7 @@
import classnames from "classnames";
import { INatIconButton } from "components/SharedComponents";
import React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import colors from "styles/tailwindColors";
export const CIRCLE_OPTIONS_CLASSES = [

View File

@@ -5,9 +5,9 @@
// and height are set in the style component. Tailwind classes do not always
// seem to work for some reason.
import React from "react";
import type { FlatListProps } from "react-native";
import {
FlatList,
FlatListProps,
I18nManager
} from "react-native";

View File

@@ -43,81 +43,82 @@
"map-layers": 61738,
"magnifying-glass": 61739,
"location-crosshairs": 61740,
"list-square": 61741,
"leaf": 61742,
"layers": 61743,
"laptop": 61744,
"label": 61745,
"label-outline": 61746,
"kebab-menu": 61747,
"info-circle-outline": 61748,
"inaturalist": 61749,
"identifiers": 61750,
"id-agree": 61751,
"iconic-unknown": 61752,
"iconic-reptilia": 61753,
"iconic-protozoa": 61754,
"iconic-plantae": 61755,
"iconic-mollusca": 61756,
"iconic-mammalia": 61757,
"iconic-insecta": 61758,
"iconic-fungi": 61759,
"iconic-chromista": 61760,
"iconic-aves": 61761,
"iconic-arachnida": 61762,
"iconic-animalia": 61763,
"iconic-amphibia": 61764,
"iconic-actinopterygii": 61765,
"help": 61766,
"help-circle": 61767,
"help-circle-outline": 61768,
"heart": 61769,
"hamburger-menu": 61770,
"grid": 61771,
"grid-square": 61772,
"globe-outline": 61773,
"gear": 61774,
"flip": 61775,
"flash-on": 61776,
"flash-off": 61777,
"flag": 61778,
"feedback": 61779,
"edit-comment": 61780,
"door-exit": 61781,
"door-enter": 61782,
"currentlocation": 61783,
"crop": 61784,
"creative-commons": 61785,
"copyright": 61786,
"copy": 61787,
"compass-rose-outline": 61788,
"comments": 61789,
"comments-outline": 61790,
"close": 61791,
"close-bold": 61792,
"clock-outline": 61793,
"circle-dots": 61794,
"chevron-right-circle": 61795,
"chevron-left": 61796,
"chevron-left-circle": 61797,
"checkmark-circle": 61798,
"checkmark-circle-outline": 61799,
"check": 61800,
"caret": 61801,
"camera": 61802,
"briefcase": 61803,
"book": 61804,
"binoculars": 61805,
"ban": 61806,
"arrow-up": 61807,
"arrow-up-small": 61808,
"arrow-up-circle-dots": 61809,
"arrow-up-bold-circle": 61810,
"arrow-up-bold-circle-outline": 61811,
"arrow-turn-down-right": 61812,
"arrow-down-bold-circle": 61813,
"arrow-down-bold-circle-outline": 61814,
"apple": 61815,
"aicamera": 61816,
"add-comment-outline": 61817
"list": 61741,
"list-square": 61742,
"leaf": 61743,
"layers": 61744,
"laptop": 61745,
"label": 61746,
"label-outline": 61747,
"kebab-menu": 61748,
"info-circle-outline": 61749,
"inaturalist": 61750,
"identifiers": 61751,
"id-agree": 61752,
"iconic-unknown": 61753,
"iconic-reptilia": 61754,
"iconic-protozoa": 61755,
"iconic-plantae": 61756,
"iconic-mollusca": 61757,
"iconic-mammalia": 61758,
"iconic-insecta": 61759,
"iconic-fungi": 61760,
"iconic-chromista": 61761,
"iconic-aves": 61762,
"iconic-arachnida": 61763,
"iconic-animalia": 61764,
"iconic-amphibia": 61765,
"iconic-actinopterygii": 61766,
"help": 61767,
"help-circle": 61768,
"help-circle-outline": 61769,
"heart": 61770,
"hamburger-menu": 61771,
"grid": 61772,
"grid-square": 61773,
"globe-outline": 61774,
"gear": 61775,
"flip": 61776,
"flash-on": 61777,
"flash-off": 61778,
"flag": 61779,
"feedback": 61780,
"edit-comment": 61781,
"door-exit": 61782,
"door-enter": 61783,
"currentlocation": 61784,
"crop": 61785,
"creative-commons": 61786,
"copyright": 61787,
"copy": 61788,
"compass-rose-outline": 61789,
"comments": 61790,
"comments-outline": 61791,
"close": 61792,
"close-bold": 61793,
"clock-outline": 61794,
"circle-dots": 61795,
"chevron-right-circle": 61796,
"chevron-left": 61797,
"chevron-left-circle": 61798,
"checkmark-circle": 61799,
"checkmark-circle-outline": 61800,
"check": 61801,
"caret": 61802,
"camera": 61803,
"briefcase": 61804,
"book": 61805,
"binoculars": 61806,
"ban": 61807,
"arrow-up": 61808,
"arrow-up-small": 61809,
"arrow-up-circle-dots": 61810,
"arrow-up-bold-circle": 61811,
"arrow-up-bold-circle-outline": 61812,
"arrow-turn-down-right": 61813,
"arrow-down-bold-circle": 61814,
"arrow-down-bold-circle-outline": 61815,
"apple": 61816,
"aicamera": 61817,
"add-comment-outline": 61818
}

View File

@@ -54,6 +54,7 @@ const ALIASES: Aliases = {
geoprivacy: "globe",
gridview: "grid-square",
listview: "list-square",
list: "list",
"id-large-fill": "label",
"id-small-outline": "label-outline",
journalposts: "book",

View File

@@ -2,7 +2,8 @@ import classnames from "classnames";
import { INatIconButton } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React, { useCallback } from "react";
import { FlatList, ListRenderItemInfo } from "react-native";
import type { ListRenderItemInfo } from "react-native";
import { FlatList } from "react-native";
import { useTranslation } from "sharedHooks";
import colors from "styles/tailwindColors";

View File

@@ -1,4 +1,5 @@
import classnames, { ArgumentArray } from "classnames";
import type { ArgumentArray } from "classnames";
import classnames from "classnames";
import { INatIcon } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React from "react";

View File

@@ -6,7 +6,8 @@ import UserIcon from "components/SharedComponents/UserIcon";
import {
Pressable, View
} from "components/styledComponents";
import React, { PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
import { useTranslation } from "react-i18next";
import type { TextProps } from "react-native";
import User from "realmModels/User";

View File

@@ -1,6 +1,7 @@
import { TextInput } from "components/styledComponents";
import * as React from "react";
import { KeyboardTypeOptions, Platform, TextInputIOSProps } from "react-native";
import type { KeyboardTypeOptions, TextInputIOSProps } from "react-native";
import { Platform } from "react-native";
import colors from "styles/tailwindColors";
interface Props {

View File

@@ -6,9 +6,11 @@ import React from "react";
type Props = {
label: string;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
LabelComponent?: Function;
valueSelectable?: boolean;
value: string | number;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
ValueComponent?: Function;
}

View File

@@ -2,7 +2,8 @@ import PermissionGateContainer, {
LOCATION_PERMISSIONS
} from "components/SharedComponents/PermissionGateContainer";
import { t } from "i18next";
import React, { PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
interface Props extends PropsWithChildren {
permissionNeeded?: boolean;

View File

@@ -1,5 +1,3 @@
// @flow
import Clipboard from "@react-native-clipboard/clipboard";
import { HeaderBackButton } from "@react-navigation/elements";
import classnames from "classnames";
@@ -13,27 +11,31 @@ import {
} from "components/SharedComponents";
import { View } from "components/styledComponents";
import { t } from "i18next";
import type { Node } from "react";
import React, { useState } from "react";
import type { GestureResponderEvent } from "react-native";
import type { Region } from "react-native-maps";
import openMap from "react-native-open-maps";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import type Observation from "realmModels/Observation";
import type { RealmObservation } from "realmModels/types";
import { getShadow } from "styles/global";
import colors from "styles/tailwindColors";
type Props = {
closeModal: Function,
interface Props {
closeModal: () => void,
coordinateString?: string,
headerTitle?: Object,
observation?: {
latitude?: number,
privateLatitude?: number,
longitude?: number,
privateLongitude?: number,
obscured?: boolean
},
region?: Object,
showLocationIndicator: boolean,
tileMapParams: Object,
headerTitle?: React.ReactNode,
// TODO MOB-1038: reconcile the type issues here requiring the intersection
observation?: Observation & RealmObservation,
region?: Region,
tileMapParams: Record<string, string> | null,
}
interface FloatingActionButtonProps {
accessibilityLabel: string,
buttonClassName: string,
icon: string,
onPress: ( event?: GestureResponderEvent ) => void,
}
const FloatingActionButton = ( {
@@ -41,7 +43,7 @@ const FloatingActionButton = ( {
buttonClassName,
icon,
onPress
} ) => {
}: FloatingActionButtonProps ) => {
const fabClassNames = classnames(
"absolute",
"bg-white",
@@ -67,9 +69,8 @@ const DetailsMap = ( {
headerTitle,
observation,
region,
showLocationIndicator,
tileMapParams
}: Props ): Node => {
}: Props ) => {
const insets = useSafeAreaInsets();
const [showNotificationModal, setShowNotificationModal] = useState( false );
@@ -115,7 +116,6 @@ const DetailsMap = ( {
observation={observation}
region={region}
showCurrentLocationButton
showLocationIndicator={showLocationIndicator}
showSwitchMapTypeButton
tileMapParams={tileMapParams}
withObsTiles={tileMapParams !== null}

View File

@@ -10,11 +10,13 @@ import React, {
useRef,
useState
} from "react";
import { DimensionValue, Platform, ViewStyle } from "react-native";
import MapView, {
BoundingBox, LatLng, MapType, Region, UrlTile
import type { DimensionValue, ViewStyle } from "react-native";
import { Platform } from "react-native";
import type {
BoundingBox, LatLng, MapType, Region
} from "react-native-maps";
import Observation from "realmModels/Observation";
import MapView, { UrlTile } from "react-native-maps";
import type Observation from "realmModels/Observation";
import fetchCoarseUserLocation from "sharedHelpers/fetchCoarseUserLocation";
import mapTracker from "sharedHelpers/mapPerformanceTracker";
import { useDebugMode, useDeviceOrientation } from "sharedHooks";

View File

@@ -12,7 +12,7 @@ const DROP_SHADOW = getShadow( );
interface Props {
currentMapType?: string;
mapType?: string;
setCurrentMapType: Function;
setCurrentMapType: ( mapType: string|number ) => void;
showSwitchMapTypeButton?: boolean;
switchMapTypeButtonClassName?: string;
}

View File

@@ -1,6 +1,6 @@
import { MapBoundaries } from "providers/ExploreContext";
import type { MapBoundaries } from "providers/ExploreContext";
import Config from "react-native-config";
import { LatLng, Region } from "react-native-maps";
import type { LatLng, Region } from "react-native-maps";
import createUTFPosition from "sharedHelpers/createUTFPosition";
import getDataForPixel from "sharedHelpers/fetchUTFGridData";

View File

@@ -1,5 +1,5 @@
import * as React from "react";
import { ViewStyle } from "react-native";
import type { ViewStyle } from "react-native";
import RNModal from "react-native-modal";
// repurposed from Seek: https://github.com/inaturalist/SeekReactNative/blob/main/components/UIComponents/Modals/Modal.js

View File

@@ -5,7 +5,8 @@ import {
import {
View
} from "components/styledComponents";
import React, { PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
import colors from "styles/tailwindColors";
interface Props extends PropsWithChildren {

View File

@@ -18,7 +18,8 @@ import {
StatusBar
} from "react-native";
import DeviceInfo from "react-native-device-info";
import { PermissionStatus, RESULTS } from "react-native-permissions";
import type { PermissionStatus } from "react-native-permissions";
import { RESULTS } from "react-native-permissions";
import colors from "styles/tailwindColors";
const BACKGROUND_IMAGE_STYLE = {

View File

@@ -1,20 +1,23 @@
import { useNavigation } from "@react-navigation/native";
import Modal from "components/SharedComponents/Modal";
import _ from "lodash";
import type { PropsWithChildren } from "react";
import React, {
PropsWithChildren,
useCallback,
useEffect,
useRef,
useState
} from "react";
import { AppState, AppStateStatus, Platform } from "react-native";
import {
import type { AppStateStatus } from "react-native";
import { AppState, Platform } from "react-native";
import type {
AndroidPermission,
checkMultiple,
Permission,
PermissionStatus
} from "react-native-permissions";
import {
checkMultiple,
PERMISSIONS,
PermissionStatus,
requestMultiple,
RESULTS
} from "react-native-permissions";

View File

@@ -6,7 +6,7 @@ import {
} from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import { RadioButton } from "react-native-paper";
import colors from "styles/tailwindColors";

View File

@@ -3,7 +3,8 @@ import classNames from "classnames";
import { INatIcon, INatIconButton } from "components/SharedComponents";
import { View } from "components/styledComponents";
import React, { useCallback, useRef, useState } from "react";
import { Keyboard, TextInput as RNTextInput } from "react-native";
import type { TextInput as RNTextInput } from "react-native";
import { Keyboard } from "react-native";
import { TextInput, useTheme } from "react-native-paper";
import { useTranslation } from "sharedHooks";
import { getShadow } from "styles/global";

View File

@@ -1,7 +1,9 @@
import {
BottomSheetBackdrop,
import type {
BottomSheetBackdropProps
} from "@gorhom/bottom-sheet";
import {
BottomSheetBackdrop
} from "@gorhom/bottom-sheet";
import React from "react";
type Props = {

View File

@@ -1,25 +1,23 @@
import checkCamelAndSnakeCase from "components/ObsDetails/helpers/checkCamelAndSnakeCase";
import { Heading2 } from "components/SharedComponents";
import React, { useMemo } from "react";
import { Subheading2 } from "components/SharedComponents";
import React from "react";
import { useTranslation } from "sharedHooks";
interface Props {
observation: object;
observation: {
private_place_guess?: string
};
}
const SimpleObservationLocation = ( {
observation
}: Props ) => {
const { t } = useTranslation( );
const displayLocation = useMemo(
( ) => checkCamelAndSnakeCase(
observation,
observation.private_place_guess
? "privatePlaceGuess"
: "placeGuess"
),
[observation]
const displayLocation = checkCamelAndSnakeCase(
observation,
observation.private_place_guess
? "privatePlaceGuess"
: "placeGuess"
);
if ( !observation ) {
@@ -27,7 +25,7 @@ const SimpleObservationLocation = ( {
}
return (
<Heading2
<Subheading2
className="text-darkGray"
ellipsizeMode="tail"
accessible
@@ -37,7 +35,7 @@ const SimpleObservationLocation = ( {
}}
>
{displayLocation}
</Heading2>
</Subheading2>
);
};

View File

@@ -6,7 +6,7 @@ import {
} from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent } from "react-native";
import type { GestureResponderEvent } from "react-native";
import { Switch } from "react-native-paper";
import colors from "styles/tailwindColors";

View File

@@ -1,9 +1,10 @@
import Divider from "components/SharedComponents/Divider/Divider";
import Heading4 from "components/SharedComponents/Typography/Heading4";
import Heading5 from "components/SharedComponents/Typography/Heading5";
import type Heading5 from "components/SharedComponents/Typography/Heading5";
import { View } from "components/styledComponents";
import React from "react";
import { GestureResponderEvent, TouchableOpacity } from "react-native";
import type { GestureResponderEvent } from "react-native";
import { TouchableOpacity } from "react-native";
import useTranslation from "sharedHooks/useTranslation";
import colors from "styles/tailwindColors";

View File

@@ -8,7 +8,8 @@ import {
INatIconButton
} from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import React, { PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import React from "react";
import type { GestureResponderEvent } from "react-native";
import type { RealmTaxon, RealmTaxonPhoto } from "realmModels/types";
import { accessibleTaxonName } from "sharedHelpers/taxon";

View File

@@ -1,6 +1,6 @@
import { tailwindFontMedium } from "appConstants/fontFamilies";
import React from "react";
import { TextProps } from "react-native";
import type { TextProps } from "react-native";
import InatText from "./InatText";

Some files were not shown because too many files have changed in this diff Show More