diff --git a/app/stacks/BottomTabNavigator.tsx b/app/stacks/BottomTabNavigator.tsx
new file mode 100644
index 00000000000..4e09df7c506
--- /dev/null
+++ b/app/stacks/BottomTabNavigator.tsx
@@ -0,0 +1,275 @@
+import React from 'react';
+import { createNativeStackNavigator } from '@react-navigation/native-stack';
+import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation';
+
+import { ThemeContext } from '../theme';
+import { defaultHeader, themedHeader } from '../lib/methods/helpers/navigation';
+// Chat screens
+import RoomsListView from '../views/RoomsListView';
+import RoomView from '../views/RoomView';
+import RoomActionsView from '../views/RoomActionsView';
+import RoomInfoView from '../views/RoomInfoView';
+import ReportUserView from '../views/ReportUserView';
+import RoomInfoEditView from '../views/RoomInfoEditView';
+import RoomMembersView from '../views/RoomMembersView';
+import SearchMessagesView from '../views/SearchMessagesView';
+import SelectedUsersView from '../views/SelectedUsersView';
+import InviteUsersView from '../views/InviteUsersView';
+import InviteUsersEditView from '../views/InviteUsersEditView';
+import MessagesView from '../views/MessagesView';
+import AutoTranslateView from '../views/AutoTranslateView';
+import DirectoryView from '../views/DirectoryView';
+import NotificationPrefView from '../views/NotificationPreferencesView';
+import E2EEToggleRoomView from '../views/E2EEToggleRoomView';
+import ForwardLivechatView from '../views/ForwardLivechatView';
+import CloseLivechatView from '../views/CloseLivechatView';
+import LivechatEditView from '../views/LivechatEditView';
+import PickerView from '../views/PickerView';
+import ThreadMessagesView from '../views/ThreadMessagesView';
+import TeamChannelsView from '../views/TeamChannelsView';
+import ReadReceiptsView from '../views/ReadReceiptView';
+import CannedResponsesListView from '../views/CannedResponsesListView';
+import CannedResponseDetail from '../views/CannedResponseDetail';
+import DiscussionsView from '../views/DiscussionsView';
+import ChangeAvatarView from '../views/ChangeAvatarView';
+import AddChannelTeamView from '../views/AddChannelTeamView';
+import AddExistingChannelView from '../views/AddExistingChannelView';
+import SelectListView from '../views/SelectListView';
+import QueueListView from '../ee/omnichannel/views/QueueListView';
+import JitsiMeetView from '../views/JitsiMeetView';
+import CreateChannelView from '../views/CreateChannelView';
+import PushTroubleshootView from '../views/PushTroubleshootView';
+// Search
+import SearchView from '../views/SearchView';
+// More tab screens
+import MoreView from '../views/MoreView';
+import ProfileView from '../views/ProfileView';
+import UserPreferencesView from '../views/UserPreferencesView';
+import UserNotificationPrefView from '../views/UserNotificationPreferencesView';
+import ChangePasswordView from '../views/ChangePasswordView';
+import SettingsView from '../views/SettingsView';
+import SecurityPrivacyView from '../views/SecurityPrivacyView';
+import GetHelpView from '../views/GetHelpView';
+import E2EEncryptionSecurityView from '../views/E2EEncryptionSecurityView';
+import LanguageView from '../views/LanguageView';
+import ThemeView from '../views/ThemeView';
+import DefaultBrowserView from '../views/DefaultBrowserView';
+import ScreenLockConfigView from '../views/ScreenLockConfigView';
+import MediaAutoDownloadView from '../views/MediaAutoDownloadView';
+import AdminPanelView from '../views/AdminPanelView';
+import AccessibilityAndAppearanceView from '../views/AccessibilityAndAppearanceView';
+import DisplayPrefsView from '../views/DisplayPrefsView';
+import LegalView from '../views/LegalView';
+import { isIOS } from '../lib/methods/helpers';
+import { type TNavigation } from './stackType';
+import i18n from '../i18n';
+import { type BottomTabParamList, type ChatsStackParamList, type MoreStackParamList, type SearchStackParamList } from './types';
+
+const renderChatScreens = (Stack: any) => (
+ <>
+
+
+ {/* @ts-ignore */}
+
+
+
+ {/* @ts-ignore */}
+
+
+
+ {/* @ts-ignore */}
+
+
+
+ {/* @ts-ignore */}
+
+
+
+
+ {/* @ts-ignore */}
+
+
+
+
+
+ {/* @ts-ignore */}
+
+ {/* @ts-ignore */}
+
+
+ {/* @ts-ignore */}
+
+
+
+
+
+ {/* @ts-ignore */}
+
+
+
+
+
+ >
+);
+
+const HomeStack = createNativeStackNavigator();
+const HomeStackScreen = () => {
+ 'use memo';
+
+ const { theme } = React.useContext(ThemeContext);
+ return (
+
+
+ {renderChatScreens(HomeStack)}
+
+ );
+};
+
+const DiscussionsStack = createNativeStackNavigator();
+const DiscussionsStackScreen = () => {
+ 'use memo';
+
+ const { theme } = React.useContext(ThemeContext);
+ return (
+
+
+ {renderChatScreens(DiscussionsStack)}
+
+ );
+};
+
+const DMsStack = createNativeStackNavigator();
+const DMsStackScreen = () => {
+ 'use memo';
+
+ const { theme } = React.useContext(ThemeContext);
+ return (
+
+
+ {renderChatScreens(DMsStack)}
+
+ );
+};
+
+const SearchStackNav = createNativeStackNavigator();
+const SearchStackScreen = () => {
+ 'use memo';
+
+ const { theme } = React.useContext(ThemeContext);
+ return (
+
+
+
+ );
+};
+
+const MoreStack = createNativeStackNavigator();
+const MoreStackScreen = () => {
+ 'use memo';
+
+ const { theme } = React.useContext(ThemeContext);
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* @ts-ignore */}
+
+
+
+
+
+
+
+ );
+};
+
+const Tab = createNativeBottomTabNavigator();
+const BottomTabNavigator = () => {
+ 'use memo';
+
+ return (
+
+ ({ sfSymbol: 'house.fill' })
+ }}
+ />
+ ({ sfSymbol: 'bubble.left.and.bubble.right.fill' })
+ }}
+ />
+ ({ sfSymbol: 'envelope.fill' })
+ }}
+ />
+ ({ sfSymbol: 'magnifyingglass' })
+ }}
+ />
+ ({ sfSymbol: 'ellipsis' })
+ }}
+ />
+
+ );
+};
+
+export default BottomTabNavigator;
diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx
index a314c801885..f3237f09da5 100644
--- a/app/stacks/InsideStack.tsx
+++ b/app/stacks/InsideStack.tsx
@@ -6,6 +6,7 @@ import { createDrawerNavigator } from '@react-navigation/drawer';
import { ThemeContext } from '../theme';
import { defaultHeader, themedHeader } from '../lib/methods/helpers/navigation';
import Sidebar from '../views/SidebarView';
+import BottomTabNavigator from './BottomTabNavigator';
// Chats Stack
import RoomView from '../views/RoomView';
import RoomsListView from '../views/RoomsListView';
@@ -235,9 +236,8 @@ const AccessibilityStackNavigator = () => {
);
};
-// DrawerNavigator
const Drawer = createDrawerNavigator();
-const DrawerNavigator = () => {
+export const DrawerNavigator = () => {
'use memo';
const { colors } = React.useContext(ThemeContext);
@@ -321,7 +321,7 @@ const InsideStackNavigator = () => {
return (
-
+
;
E2ESaveYourPasswordStackNavigator: NavigatorScreenParams;
@@ -26,7 +28,7 @@ export type ChatsStackParamList = {
SettingsView: any;
NewMessageStackNavigator: any;
NewMessageStack: undefined;
- RoomsListView: undefined;
+ RoomsListView: { roomFilter?: RoomFilterType } | undefined;
RoomView:
| {
rid: string;
@@ -239,6 +241,25 @@ export type DrawerParamList = {
AccessibilityStackNavigator: NavigatorScreenParams;
};
+export type SearchStackParamList = {
+ SearchView: undefined;
+};
+
+export type MoreStackParamList = {
+ MoreView: undefined;
+} & ProfileStackParamList &
+ SettingsStackParamList &
+ AdminPanelStackParamList &
+ AccessibilityStackParamList;
+
+export type BottomTabParamList = {
+ HomeStack: NavigatorScreenParams;
+ DiscussionsStack: NavigatorScreenParams;
+ DMsStack: NavigatorScreenParams;
+ SearchStack: NavigatorScreenParams;
+ MoreStack: NavigatorScreenParams;
+};
+
export type NewMessageStackParamList = {
NewMessageView: undefined;
SelectedUsersView: {
@@ -277,6 +298,7 @@ export type E2EEnterYourPasswordStackParamList = {
export type InsideStackParamList = {
DrawerNavigator: NavigatorScreenParams;
+ BottomTabNavigator: NavigatorScreenParams;
NewMessageStackNavigator: NavigatorScreenParams;
E2ESaveYourPasswordStackNavigator: NavigatorScreenParams;
E2EEnterYourPasswordStackNavigator: NavigatorScreenParams;
diff --git a/app/views/MoreView/index.tsx b/app/views/MoreView/index.tsx
new file mode 100644
index 00000000000..ec28881d581
--- /dev/null
+++ b/app/views/MoreView/index.tsx
@@ -0,0 +1,70 @@
+import React, { memo, useCallback } from 'react';
+import { ScrollView } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+
+import SafeAreaView from '../../containers/SafeAreaView';
+import * as List from '../../containers/List';
+import i18n from '../../i18n';
+import { usePermissions } from '../../lib/hooks/usePermissions';
+
+const MoreView = memo(function MoreView() {
+ 'use memo';
+
+ const navigation = useNavigation();
+ const [viewRoomAdministrationPermission, viewStatisticsPermission, viewPrivilegedSettingPermission] = usePermissions([
+ 'view-room-administration',
+ 'view-statistics',
+ 'view-privileged-setting'
+ ]);
+ const showAdmin = viewRoomAdministrationPermission || viewStatisticsPermission || viewPrivilegedSettingPermission;
+
+ const navigateTo = useCallback(
+ (screen: string) => {
+ navigation.navigate(screen);
+ },
+ [navigation]
+ );
+
+ return (
+
+
+
+ }
+ onPress={() => navigateTo('ProfileView')}
+ testID='more-view-profile'
+ />
+
+ }
+ onPress={() => navigateTo('AccessibilityAndAppearanceView')}
+ testID='more-view-accessibility'
+ />
+
+ }
+ onPress={() => navigateTo('SettingsView')}
+ testID='more-view-settings'
+ />
+
+ {showAdmin ? (
+ <>
+ }
+ onPress={() => navigateTo('AdminPanelView')}
+ testID='more-view-admin'
+ />
+
+ >
+ ) : null}
+
+
+
+ );
+});
+
+export default MoreView;
diff --git a/app/views/RoomsListView/hooks/useHeader.tsx b/app/views/RoomsListView/hooks/useHeader.tsx
index cccc32456fa..cc592212ab6 100644
--- a/app/views/RoomsListView/hooks/useHeader.tsx
+++ b/app/views/RoomsListView/hooks/useHeader.tsx
@@ -11,10 +11,18 @@ import { getUserSelector } from '../../../selectors/login';
import { useTheme } from '../../../theme';
import RoomsListHeaderView from '../components/Header';
import { RoomsSearchContext } from '../contexts/RoomsSearchProvider';
+import { type RoomFilterType } from '../../../stacks/types';
-export const useHeader = () => {
+const TAB_TITLES: Record = {
+ home: 'Chats',
+ discussions: 'Discussions',
+ dms: 'Direct_Messages'
+};
+
+export const useHeader = (roomFilter?: RoomFilterType) => {
'use memo';
+ const isTabLayout = !!roomFilter;
const { searchEnabled, search, startSearch, stopSearch } = useContext(RoomsSearchContext);
const [options, setOptions] = useState(null);
const supportedVersionsStatus = useAppSelector(state => state.supportedVersions.status);
@@ -80,7 +88,8 @@ export const useHeader = () => {
}, [isMasterDetail, navigation]);
useLayoutEffect(() => {
- if (searchEnabled) {
+ // Search mode header (only for drawer layout - tabs use the Search tab instead)
+ if (!isTabLayout && searchEnabled) {
const searchOptions = {
headerLeft: () => (
@@ -97,6 +106,48 @@ export const useHeader = () => {
return;
}
+ // Tab layout header: no drawer toggle, no search button, tab-specific title
+ if (isTabLayout) {
+ const tabOptions = {
+ headerLeft: () => null,
+ title: i18n.t(TAB_TITLES[roomFilter] || 'Home'),
+ headerRight: () => (
+
+ {issuesWithNotifications ? (
+
+ ) : null}
+ {canCreateRoom ? (
+
+ ) : null}
+
+
+ )
+ };
+ navigation.setOptions(tabOptions);
+ if (isTablet) {
+ setOptions(tabOptions);
+ }
+ return;
+ }
+
+ // Default drawer layout header
const options = {
headerLeft: () => (
{
goToNewMessage,
startSearch,
stopSearch,
- search
+ search,
+ isTabLayout,
+ roomFilter
]);
return { options };
diff --git a/app/views/RoomsListView/hooks/useSubscriptions.ts b/app/views/RoomsListView/hooks/useSubscriptions.ts
index 485649f35c4..7ebfe44231a 100644
--- a/app/views/RoomsListView/hooks/useSubscriptions.ts
+++ b/app/views/RoomsListView/hooks/useSubscriptions.ts
@@ -8,6 +8,7 @@ import { SortBy } from '../../../lib/constants/constantDisplayMode';
import database from '../../../lib/database';
import { useAppSelector } from '../../../lib/hooks/useAppSelector';
import { getUserSelector } from '../../../selectors/login';
+import { type RoomFilterType } from '../../../stacks/types';
const CHATS_HEADER = 'Chats';
const UNREAD_HEADER = 'Unread';
@@ -35,7 +36,7 @@ const addRoomsGroup = (data: TSubscriptionModel[], header: string, allData: TSub
return allData;
};
-export const useSubscriptions = () => {
+export const useSubscriptions = (roomFilter?: RoomFilterType) => {
'use memo';
const useRealName = useAppSelector(state => state.settings.UI_Use_Real_Name);
@@ -68,7 +69,19 @@ export const useSubscriptions = () => {
subscriptionRef.current = observable.subscribe(data => {
let tempChats = [] as TSubscriptionModel[];
+
+ // Apply tab-level filter before grouping
let chats = data;
+ if (roomFilter === 'home') {
+ // Home: everything except DMs and discussions
+ chats = data.filter(s => s.t !== 'd' && !s.prid);
+ } else if (roomFilter === 'discussions') {
+ // Discussions only
+ chats = data.filter(s => !!s.prid);
+ } else if (roomFilter === 'dms') {
+ // DMs only
+ chats = data.filter(s => s.t === 'd' && !s.prid);
+ }
// let omnichannelsUpdate: string[] = [];
const isOmnichannelAgent = roles?.includes('livechat-agent');
@@ -124,7 +137,7 @@ export const useSubscriptions = () => {
return () => {
subscriptionRef.current?.unsubscribe();
};
- }, [isGrouping, sortBy, useRealName, showUnread, showFavorites, groupByType, roles, server]);
+ }, [isGrouping, sortBy, useRealName, showUnread, showFavorites, groupByType, roles, server, roomFilter]);
return {
subscriptions,
diff --git a/app/views/RoomsListView/index.tsx b/app/views/RoomsListView/index.tsx
index 0ec091befb3..700de7196b1 100644
--- a/app/views/RoomsListView/index.tsx
+++ b/app/views/RoomsListView/index.tsx
@@ -1,9 +1,10 @@
-import { useNavigation } from '@react-navigation/native';
+import { useNavigation, useRoute, type RouteProp } from '@react-navigation/native';
import React, { memo, useContext, useEffect } from 'react';
import { BackHandler, FlatList, RefreshControl } from 'react-native';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import { shallowEqual } from 'react-redux';
+import { type ChatsStackParamList } from '../../stacks/types';
import ActivityIndicator from '../../containers/ActivityIndicator';
import BackgroundContainer from '../../containers/BackgroundContainer';
import { ChangePasswordRequired } from '../../containers/ChangePasswordRequired';
@@ -33,7 +34,10 @@ const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
const RoomsListView = memo(function RoomsListView() {
'use memo';
- useHeader();
+ const route = useRoute>();
+ const roomFilter = route.params?.roomFilter;
+
+ useHeader(roomFilter);
const { searching, searchEnabled, searchResults, stopSearch } = useContext(RoomsSearchContext);
const { colors } = useTheme();
const username = useAppSelector(state => getUserSelector(state).username);
@@ -45,7 +49,7 @@ const RoomsListView = memo(function RoomsListView() {
const navigation = useNavigation();
const { width } = useSafeAreaFrame();
const getItemLayout = useGetItemLayout();
- const { subscriptions, loading } = useSubscriptions();
+ const { subscriptions, loading } = useSubscriptions(roomFilter);
const subscribedRoom = useAppSelector(state => state.room.subscribedRoom);
const changingServer = useAppSelector(state => state.server.changingServer);
const { refreshing, onRefresh } = useRefresh({ searching });
diff --git a/app/views/SearchView/index.tsx b/app/views/SearchView/index.tsx
new file mode 100644
index 00000000000..02cf1398719
--- /dev/null
+++ b/app/views/SearchView/index.tsx
@@ -0,0 +1,120 @@
+import React, { memo, useCallback, useLayoutEffect, useState } from 'react';
+import { FlatList } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+import { useSafeAreaFrame } from 'react-native-safe-area-context';
+import { shallowEqual } from 'react-redux';
+
+import ActivityIndicator from '../../containers/ActivityIndicator';
+import BackgroundContainer from '../../containers/BackgroundContainer';
+import RoomItem from '../../containers/RoomItem';
+import { type IRoomItem } from '../../containers/RoomItem/interfaces';
+import i18n from '../../i18n';
+import { MAX_SIDEBAR_WIDTH } from '../../lib/constants/tablet';
+import { useAppSelector } from '../../lib/hooks/useAppSelector';
+import { getRoomAvatar, getRoomTitle, getUidDirectMessage, isIOS } from '../../lib/methods/helpers';
+import { goRoom } from '../../lib/methods/helpers/goRoom';
+import { useDebounce } from '../../lib/methods/helpers/debounce';
+import { search as searchMethod } from '../../lib/methods/search';
+import { getUserSelector } from '../../selectors/login';
+import { useTheme } from '../../theme';
+
+const SearchView = memo(function SearchView() {
+ 'use memo';
+
+ const [results, setResults] = useState([]);
+ const [searching, setSearching] = useState(false);
+ const [hasSearched, setHasSearched] = useState(false);
+ const navigation = useNavigation();
+ const { colors } = useTheme();
+ const username = useAppSelector(state => getUserSelector(state).username);
+ const isMasterDetail = useAppSelector(state => state.app.isMasterDetail);
+ const useRealName = useAppSelector(state => state.settings.UI_Use_Real_Name) as boolean;
+ const showLastMessage = useAppSelector(state => state.settings.Store_Last_Message) as boolean;
+ const { displayMode, showAvatar } = useAppSelector(state => state.sortPreferences, shallowEqual);
+ const { width } = useSafeAreaFrame();
+ const subscribedRoom = useAppSelector(state => state.room.subscribedRoom);
+
+ const handleSearch = useDebounce(async (text: string) => {
+ if (!text.trim()) {
+ setResults([]);
+ setSearching(false);
+ setHasSearched(false);
+ return;
+ }
+ setSearching(true);
+ setHasSearched(true);
+ const result = await searchMethod({ text });
+ setResults(result as IRoomItem[]);
+ setSearching(false);
+ }, 300);
+
+ useLayoutEffect(() => {
+ navigation.setOptions({
+ headerSearchBarOptions: {
+ onChangeText: (e: { nativeEvent: { text: string } }) => {
+ handleSearch(e.nativeEvent.text);
+ },
+ placeholder: i18n.t('Search'),
+ autoCapitalize: 'none',
+ hideWhenScrolling: false
+ }
+ });
+ }, [navigation, handleSearch]);
+
+ const onPressItem = useCallback(
+ (item = {} as IRoomItem) => {
+ goRoom({ item, isMasterDetail });
+ },
+ [isMasterDetail]
+ );
+
+ const renderItem = useCallback(
+ ({ item }: { item: IRoomItem }) => {
+ const id = item.t === 'd' ? item._id : getUidDirectMessage(item);
+ return (
+ true}
+ isFocused={subscribedRoom === item.rid}
+ swipeEnabled={false}
+ showAvatar={showAvatar}
+ displayMode={displayMode}
+ />
+ );
+ },
+ [username, showLastMessage, onPressItem, isMasterDetail, width, useRealName, subscribedRoom, showAvatar, displayMode]
+ );
+
+ if (searching) {
+ return ;
+ }
+
+ if (hasSearched && results.length === 0) {
+ return ;
+ }
+
+ if (!hasSearched) {
+ return ;
+ }
+
+ return (
+ item.rid || item._id}
+ renderItem={renderItem}
+ style={{ backgroundColor: colors.surfaceRoom }}
+ keyboardShouldPersistTaps='always'
+ keyboardDismissMode={isIOS ? 'on-drag' : 'none'}
+ />
+ );
+});
+
+export default SearchView;
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 8122f18684a..fd2ae18f6d8 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -164,7 +164,7 @@ PODS:
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- - FirebaseRemoteConfigInterop (11.10.0)
+ - FirebaseRemoteConfigInterop (11.15.0)
- FirebaseSessions (11.10.0):
- FirebaseCore (~> 11.10.0)
- FirebaseCoreExtension (~> 11.10.0)
@@ -185,38 +185,38 @@ PODS:
- GoogleDataTransport (10.1.0):
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- - GoogleUtilities/AppDelegateSwizzler (8.0.2):
+ - GoogleUtilities/AppDelegateSwizzler (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- - GoogleUtilities/Environment (8.0.2):
+ - GoogleUtilities/Environment (8.1.0):
- GoogleUtilities/Privacy
- - GoogleUtilities/Logger (8.0.2):
+ - GoogleUtilities/Logger (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- - GoogleUtilities/MethodSwizzler (8.0.2):
+ - GoogleUtilities/MethodSwizzler (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- - GoogleUtilities/Network (8.0.2):
+ - GoogleUtilities/Network (8.1.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (8.0.2)":
+ - "GoogleUtilities/NSData+zlib (8.1.0)":
- GoogleUtilities/Privacy
- - GoogleUtilities/Privacy (8.0.2)
- - GoogleUtilities/Reachability (8.0.2):
+ - GoogleUtilities/Privacy (8.1.0)
+ - GoogleUtilities/Reachability (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- - GoogleUtilities/UserDefaults (8.0.2):
+ - GoogleUtilities/UserDefaults (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- hermes-engine (0.79.4):
- hermes-engine/Pre-built (= 0.79.4)
- hermes-engine/Pre-built (0.79.4)
- - libavif/core (0.11.1)
- - libavif/libdav1d (0.11.1):
+ - libavif/core (1.0.0)
+ - libavif/libdav1d (1.0.0):
- libavif/core
- libdav1d (>= 0.6.0)
- libdav1d (1.2.0)
@@ -1614,6 +1614,57 @@ PODS:
- Yoga
- react-native-background-timer (2.4.1):
- React-Core
+ - react-native-bottom-tabs (1.1.0):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - react-native-bottom-tabs/common (= 1.1.0)
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SwiftUIIntrospect (~> 1.0)
+ - Yoga
+ - react-native-bottom-tabs/common (1.1.0):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - SwiftUIIntrospect (~> 1.0)
+ - Yoga
- react-native-cameraroll (7.10.0):
- DoubleConversion
- glog
@@ -2506,7 +2557,7 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- - RNScreens (4.13.1):
+ - RNScreens (4.16.0):
- DoubleConversion
- glog
- hermes-engine
@@ -2530,9 +2581,9 @@ PODS:
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- - RNScreens/common (= 4.13.1)
+ - RNScreens/common (= 4.16.0)
- Yoga
- - RNScreens/common (4.13.1):
+ - RNScreens/common (4.16.0):
- DoubleConversion
- glog
- hermes-engine
@@ -2630,10 +2681,10 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- - SDWebImage (5.21.0):
- - SDWebImage/Core (= 5.21.0)
- - SDWebImage/Core (5.21.0)
- - SDWebImageAVIFCoder (0.11.0):
+ - SDWebImage (5.21.7):
+ - SDWebImage/Core (= 5.21.7)
+ - SDWebImage/Core (5.21.7)
+ - SDWebImageAVIFCoder (0.11.1):
- libavif/core (>= 0.11.0)
- SDWebImage (~> 5.10)
- SDWebImageSVGCoder (1.7.0):
@@ -2643,6 +2694,7 @@ PODS:
- SDWebImage/Core (~> 5.17)
- simdjson (3.9.4)
- SocketRocket (0.7.1)
+ - SwiftUIIntrospect (1.3.0)
- TOCropViewController (2.7.4)
- WatermelonDB (0.28.1-0):
- React
@@ -2720,6 +2772,7 @@ DEPENDENCIES:
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-a11y-order (from `../node_modules/react-native-a11y-order`)
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
+ - react-native-bottom-tabs (from `../node_modules/react-native-bottom-tabs`)
- "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)"
- "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)"
- react-native-keyboard-controller (from `../node_modules/react-native-keyboard-controller`)
@@ -2808,6 +2861,7 @@ SPEC REPOS:
- SDWebImageSVGCoder
- SDWebImageWebPCoder
- SocketRocket
+ - SwiftUIIntrospect
- TOCropViewController
- ZXingObjC
@@ -2939,6 +2993,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-a11y-order"
react-native-background-timer:
:path: "../node_modules/react-native-background-timer"
+ react-native-bottom-tabs:
+ :path: "../node_modules/react-native-bottom-tabs"
react-native-cameraroll:
:path: "../node_modules/@react-native-camera-roll/camera-roll"
react-native-cookies:
@@ -3098,15 +3154,15 @@ SPEC CHECKSUMS:
FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
FirebaseCrashlytics: 84b073c997235740e6a951b7ee49608932877e5c
FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
- FirebaseRemoteConfigInterop: 7c9a9c65eff32cbb0f7bf8d18140612ad57dfcc6
+ FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa
FirebaseSessions: 9b3b30947b97a15370e0902ee7a90f50ef60ead6
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
GoogleAppMeasurement: 36684bfb3ee034e2b42b4321eb19da3a1b81e65d
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
- GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
+ GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
hermes-engine: 8b5a5eb386b990287d072fd7b6f6ebd9544dd251
- libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
+ libavif: 5f8e715bea24debec477006f21ef9e95432e254d
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
MobileCrypto: badd466d89e6fb166575c8a5cb74606ee3eec0fe
@@ -3146,6 +3202,7 @@ SPEC CHECKSUMS:
React-microtasksnativemodule: 44180d1c009908666733364261fabf0613ac77e7
react-native-a11y-order: 419a0c2849125d884e1c2a5db3a6ed06c8d45b92
react-native-background-timer: 4638ae3bee00320753647900b21260b10587b6f7
+ react-native-bottom-tabs: 33ebd0e1518501a03b2c80872005a42e47f21ed3
react-native-cameraroll: 23d28040c32ca8b20661e0c41b56ab041779244b
react-native-cookies: d648ab7025833b977c0b19e142503034f5f29411
react-native-keyboard-controller: 9ec7ee23328c30251a399cffd8b54324a00343bf
@@ -3202,20 +3259,21 @@ SPEC CHECKSUMS:
RNImageCropPicker: c78ee80ea778f90cb850f4d26696fd9c1a7bcfbb
RNLocalize: ca86348d88b9a89da0e700af58d428ab3f343c4e
RNReanimated: f52ccd5ceea2bae48d7421eec89b3f0c10d7b642
- RNScreens: b13e4c45f0406f33986a39c0d8da0324bff94435
+ RNScreens: eb3800639b236501d2d6487d930b35fe3db68cb0
RNSVG: 680e961f640e381aab730a04b2371969686ed9f7
RNTrueSheet: e9ee7ff82a7854295eac6fc225e54f1539e6cd7b
- SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
- SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
+ SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
+ SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
simdjson: 7bb9e33d87737cec966e7b427773c67baa4458fe
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
+ SwiftUIIntrospect: fee9aa07293ee280373a591e1824e8ddc869ba5d
TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
WatermelonDB: 4c846c8cb94eef3cba90fa034d15310163226703
- Yoga: dfabf1234ccd5ac41d1b1d43179f024366ae9831
+ Yoga: 2a3a4c38a8441b6359d5e5914d35db7b2b67aebd
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
PODFILE CHECKSUM: 199f6fbbe6fb415c822cca992e6152000ac55b3e
-COCOAPODS: 1.15.2
+COCOAPODS: 1.16.2
diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj
index 5a928d6ed48..c498845b783 100644
--- a/ios/RocketChatRN.xcodeproj/project.pbxproj
+++ b/ios/RocketChatRN.xcodeproj/project.pbxproj
@@ -1825,7 +1825,7 @@
inputFileListPaths = (
);
inputPaths = (
- "$TARGET_BUILD_DIR/$INFOPLIST_PATH",
+ $TARGET_BUILD_DIR/$INFOPLIST_PATH,
);
name = "Upload source maps to Bugsnag";
outputFileListPaths = (
@@ -1845,7 +1845,7 @@
inputFileListPaths = (
);
inputPaths = (
- "$TARGET_BUILD_DIR/$INFOPLIST_PATH",
+ $TARGET_BUILD_DIR/$INFOPLIST_PATH,
);
name = "Upload source maps to Bugsnag";
outputFileListPaths = (
@@ -2593,7 +2593,7 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/rn-extensions-share/ios/**",
"$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**",
- "$PODS_CONFIGURATION_BUILD_DIR/Firebase",
+ $PODS_CONFIGURATION_BUILD_DIR/Firebase,
);
INFOPLIST_FILE = ShareRocketChatRN/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
@@ -2669,7 +2669,7 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/rn-extensions-share/ios/**",
"$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**",
- "$PODS_CONFIGURATION_BUILD_DIR/Firebase",
+ $PODS_CONFIGURATION_BUILD_DIR/Firebase,
);
INFOPLIST_FILE = ShareRocketChatRN/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
diff --git a/ios/RocketChatRN/Info.plist b/ios/RocketChatRN/Info.plist
index d5f34d83938..6184a45ee1a 100644
--- a/ios/RocketChatRN/Info.plist
+++ b/ios/RocketChatRN/Info.plist
@@ -109,7 +109,7 @@
UIViewControllerBasedStatusBarAppearance
UIDesignRequiresCompatibility
-
+
NSUserActivityTypes
INSendMessageIntent
diff --git a/package.json b/package.json
index 4b3e53b0dd1..8819e690e38 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"bugsnag:upload-android": "bugsnag-cli upload react-native-android"
},
"dependencies": {
+ "@bottom-tabs/react-navigation": "^1.1.0",
"@bugsnag/react-native": "8.4.0",
"@expo/vector-icons": "^14.1.0",
"@hookform/resolvers": "^2.9.10",
@@ -89,6 +90,7 @@
"react-native-animatable": "1.3.3",
"react-native-background-timer": "2.4.1",
"react-native-bootsplash": "^6.3.8",
+ "react-native-bottom-tabs": "^1.1.0",
"react-native-config-reader": "4.1.1",
"react-native-console-time-polyfill": "1.2.3",
"react-native-device-info": "11.1.0",
@@ -111,7 +113,7 @@
"react-native-reanimated": "^3.17.1",
"react-native-restart": "0.0.22",
"react-native-safe-area-context": "^5.4.0",
- "react-native-screens": "^4.13.1",
+ "react-native-screens": "4.16.0",
"react-native-skeleton-placeholder": "5.2.4",
"react-native-svg": "^15.12.1",
"react-native-url-polyfill": "2.0.0",
diff --git a/patches/react-native-bottom-tabs+1.1.0.patch b/patches/react-native-bottom-tabs+1.1.0.patch
new file mode 100644
index 00000000000..9fa3bf33fd7
--- /dev/null
+++ b/patches/react-native-bottom-tabs+1.1.0.patch
@@ -0,0 +1,20 @@
+diff --git a/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift b/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift
+index 72938be..9799e4b 100644
+--- a/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift
++++ b/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift
+@@ -117,6 +117,15 @@ struct TabViewImpl: View {
+
+ tabBar.isHidden = props.tabBarHidden
+
++ if #available(iOS 26.0, *) {
++ if props.barTintColor == nil && props.scrollEdgeAppearance != "opaque" {
++ if let inactiveTintColor = props.inactiveTintColor {
++ tabBar.unselectedItemTintColor = inactiveTintColor
++ }
++ return
++ }
++ }
++
+ if props.scrollEdgeAppearance == "transparent" {
+ configureTransparentAppearance(tabBar: tabBar, props: props)
+ return
diff --git a/yarn.lock b/yarn.lock
index 6d8d740fa76..50988ea4f9a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2251,6 +2251,13 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@bottom-tabs/react-navigation@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@bottom-tabs/react-navigation/-/react-navigation-1.1.0.tgz#83e1931e47de2edf6660f3fdf6b06518104edea1"
+ integrity sha512-+4YppCodABcSNIgJiq95QUQ+3ClVBG+rLG3WmYI0+/nbxqKbCz6luFBep4KFOj98Iplj1JY2Ki6ix8CcOZVQ/Q==
+ dependencies:
+ color "^5.0.0"
+
"@bugsnag/cli@^3.2.1":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@bugsnag/cli/-/cli-3.2.1.tgz#0c0149920e940c1a05f4492ef991bbe83741f2de"
@@ -6526,6 +6533,13 @@ color-convert@^2.0.1:
dependencies:
color-name "~1.1.4"
+color-convert@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-3.1.3.tgz#db6627b97181cb8facdfce755ae26f97ab0711f1"
+ integrity sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==
+ dependencies:
+ color-name "^2.0.0"
+
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
@@ -6536,6 +6550,11 @@ color-name@^1.0.0, color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+color-name@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-2.1.0.tgz#0b677385c1c4b4edfdeaf77e38fa338e3a40b693"
+ integrity sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==
+
color-string@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
@@ -6544,6 +6563,13 @@ color-string@^1.9.0:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
+color-string@^2.1.3:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-2.1.4.tgz#9dcf566ff976e23368c8bd673f5c35103ab41058"
+ integrity sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==
+ dependencies:
+ color-name "^2.0.0"
+
color2k@1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/color2k/-/color2k-1.2.4.tgz#af34950ac58e23cf224a01cb8dd0c9911a79605e"
@@ -6557,6 +6583,14 @@ color@^4.2.3:
color-convert "^2.0.1"
color-string "^1.9.0"
+color@^5.0.0:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/color/-/color-5.0.3.tgz#f79390b1b778e222ffbb54304d3dbeaef633f97f"
+ integrity sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==
+ dependencies:
+ color-convert "^3.1.3"
+ color-string "^2.1.3"
+
colorette@^1.0.7:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
@@ -12013,6 +12047,15 @@ react-native-bootsplash@^6.3.8:
ts-dedent "^2.2.0"
xml-formatter "^3.6.5"
+react-native-bottom-tabs@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/react-native-bottom-tabs/-/react-native-bottom-tabs-1.1.0.tgz#8b63340fc8d3bff479d12c49df656b551a63aa74"
+ integrity sha512-Uu1gvM3i1Hb4DjVvR/38J1QVQEs0RkPc7K6yon99HgvRWWOyLs7kjPDhUswtb8ije4pKW712skIXWJ0lgKzbyQ==
+ dependencies:
+ react-freeze "^1.0.0"
+ sf-symbols-typescript "^2.0.0"
+ use-latest-callback "^0.2.1"
+
react-native-config-reader@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-native-config-reader/-/react-native-config-reader-4.1.1.tgz#478b69e32adcc2e9a14f6ef5fa2cbbe012b9a27e"
@@ -12091,9 +12134,9 @@ react-native-is-edge-to-edge@^1.1.6, react-native-is-edge-to-edge@^1.1.7:
integrity sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w==
react-native-is-edge-to-edge@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz#64e10851abd9d176cbf2b40562f751622bde3358"
- integrity sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.3.1.tgz#feb9a6a8faf0874298947edd556e5af22044e139"
+ integrity sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA==
"react-native-katex@git+https://github.com/RocketChat/react-native-katex.git":
version "1.3.0"
@@ -12194,10 +12237,10 @@ react-native-safe-area-context@^5.4.0:
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-5.4.0.tgz#04b51940408c114f75628a12a93569d30c525454"
integrity sha512-JaEThVyJcLhA+vU0NU8bZ0a1ih6GiF4faZ+ArZLqpYbL6j7R3caRqj+mE3lEtKCuHgwjLg3bCxLL1GPUJZVqUA==
-react-native-screens@^4.13.1:
- version "4.13.1"
- resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-4.13.1.tgz#bf19f09b76dee90b5f7bd8aab3c951a565dd111d"
- integrity sha512-EESsMAtyzYcL3gpAI2NKKiIo+Ew0fnX4P4b3Zy/+MTc6SJIo3foJbZwdIWd/SUBswOf7IYCvWBppg+D8tbwnsw==
+react-native-screens@4.16.0:
+ version "4.16.0"
+ resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-4.16.0.tgz#efa42e77a092aa0b5277c9ae41391ea0240e0870"
+ integrity sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==
dependencies:
react-freeze "^1.0.0"
react-native-is-edge-to-edge "^1.2.1"
@@ -12969,6 +13012,11 @@ setprototypeof@1.2.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+sf-symbols-typescript@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/sf-symbols-typescript/-/sf-symbols-typescript-2.2.0.tgz#926d6e0715e3d8784cadf7658431e36581254208"
+ integrity sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw==
+
shallow-clone@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
@@ -14292,6 +14340,11 @@ use-deep-compare-effect@1.6.1:
"@types/react" "^17.0.0"
dequal "^2.0.2"
+use-latest-callback@^0.2.1:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.6.tgz#e5ea752808c86219acc179ace0ae3c1203255e77"
+ integrity sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==
+
use-latest-callback@^0.2.4:
version "0.2.4"
resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.4.tgz#35c0f028f85a3f4cf025b06011110e87cc18f57e"