Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

native: integrate new contacts into UI #4127

Open
wants to merge 41 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
297e95e
add/remove button
latter-bolden Oct 25, 2024
f9d169d
Merge branch 'develop' into lb/contacts-ui
latter-bolden Oct 28, 2024
0241eb5
wire up sub, add ub -> client transformers, fix add contact, add upda…
latter-bolden Oct 28, 2024
ef8ca66
editable nickname & avatar
latter-bolden Oct 29, 2024
d25fb00
Merge branch 'develop' into lb/contacts-ui
latter-bolden Oct 29, 2024
50353dc
handle dupe peer fact when contacts update their own profiles
latter-bolden Oct 29, 2024
34c9dc3
initial contacts tab
latter-bolden Oct 29, 2024
52d600a
use existing edit screen, render contacts in contacts tab (just list …
latter-bolden Oct 30, 2024
39cc42d
feature flag all tabs and handle custom field removes
latter-bolden Oct 30, 2024
9900a67
remove early returns if trying to clear both avatar and nickname
latter-bolden Oct 30, 2024
d893c1a
stub suggestion hide
latter-bolden Oct 30, 2024
e2f54b9
Merge branch 'develop' into lb/contacts-ui
latter-bolden Oct 31, 2024
d777bd9
polish
latter-bolden Nov 1, 2024
6f35785
fix tests
latter-bolden Nov 1, 2024
d32d90b
Merge branch 'develop' into lb/contacts-ui
latter-bolden Nov 1, 2024
5485570
fix sync response
latter-bolden Nov 1, 2024
5779bf3
Merge branch 'develop' into lb/contacts-ui
latter-bolden Nov 1, 2024
e266b8c
Merge branch 'develop' into lb/contacts-ui
latter-bolden Nov 1, 2024
640127a
empty field handling for contact updates
latter-bolden Nov 4, 2024
1ef68af
Merge branch 'develop' into lb/contacts-ui
latter-bolden Nov 7, 2024
452ff36
upgrade drizzle, use generated columns for computed nicknam/avatarImage
latter-bolden Nov 7, 2024
b68f751
use generated columns in UI references, fix conflict update helper, h…
latter-bolden Nov 8, 2024
24fe9bf
flesh out UI
latter-bolden Nov 8, 2024
a910722
not everyone is chillin
latter-bolden Nov 8, 2024
5528808
analytics for contact adds/edits
latter-bolden Nov 8, 2024
ac830f4
add inviter as contact during boot sequence
latter-bolden Nov 8, 2024
b006f63
Merge branch 'develop' into lb/contacts-ui
latter-bolden Nov 18, 2024
ddee8ac
add contact profile update activity ui
latter-bolden Nov 19, 2024
4709fa6
update fixture, nav to profile when you click activity event
latter-bolden Nov 19, 2024
7737184
logic fixes
latter-bolden Nov 20, 2024
e93d884
Merge branch 'develop' into lb/contacts-ui
latter-bolden Nov 20, 2024
b86ea59
style spot fixes
latter-bolden Nov 20, 2024
52d572a
fix tamagui compiler unread dot error
latter-bolden Nov 21, 2024
bb15ddb
sensible status cap, fix stale data, fix end content taking up way to…
latter-bolden Nov 21, 2024
529cab8
remove placeholder suggestions
latter-bolden Nov 21, 2024
80c97d5
cleanup comments
latter-bolden Nov 21, 2024
da6dc16
ContactsScreenView: list padding, self-item styling
jamesacklin Nov 21, 2024
81255ff
lonpress shortcut kinda works
latter-bolden Nov 21, 2024
46776d6
update contacts flag to audition full tab
latter-bolden Nov 21, 2024
1e0a246
gear haptic
latter-bolden Nov 21, 2024
9bccc6d
fix reset migration script, update drizzle patch for new version
latter-bolden Nov 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion apps/tlon-mobile/drizzle-studio.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Config } from 'drizzle-kit';

export default {
schema: '../../packages/shared/src/db/schema.ts',
driver: 'better-sqlite',
dialect: 'sqlite',
dbCredentials: {
url: (process.env as any).DB_URL ?? '',
Expand Down
2 changes: 1 addition & 1 deletion apps/tlon-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
"connect": "^3.7.0",
"cross-env": "^7.0.3",
"dotenv": "^16.0.3",
"drizzle-kit": "^0.21.1",
"drizzle-kit": "^0.28.0",
"jest": "^29.7.0",
"jest-expo": "^50.0.3",
"jest-fetch-mock": "^3.0.3",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"@10play/[email protected]": "patches/@[email protected]",
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"@react-navigation/[email protected]": "patches/@[email protected]",
"@likashefqet/[email protected]": "patches/@[email protected]",
"[email protected]": "patches/[email protected]"
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]"
},
"allowNonAppliedPatches": true,
"overrides": {
Expand Down
16 changes: 13 additions & 3 deletions packages/app/features/settings/EditProfileScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,30 @@ import {
} from '@tloncorp/ui';
import { useCallback } from 'react';

import { useCurrentUserId } from '../../hooks/useCurrentUser';
import { RootStackParamList } from '../../navigation/types';

type Props = NativeStackScreenProps<RootStackParamList, 'EditProfile'>;

export function EditProfileScreen({ navigation }: Props) {
export function EditProfileScreen({ route, navigation }: Props) {
const currentUserId = useCurrentUserId();
const { data: groups } = store.useGroups({ includeUnjoined: true });

const onSaveProfile = useCallback(
(update: api.ProfileUpdate | null) => {
if (update) {
store.updateCurrentUserProfile(update);
if (route.params.userId === currentUserId) {
store.updateCurrentUserProfile(update);
} else {
store.updateContactMetadata(route.params.userId, {
nickname: update.nickname,
avatarImage: update.avatarImage,
});
}
}
navigation.goBack();
},
[navigation]
[currentUserId, navigation, route.params.userId]
);

const onUpdateCoverImage = useCallback((coverImage: string) => {
Expand All @@ -39,6 +48,7 @@ export function EditProfileScreen({ navigation }: Props) {
<GroupsProvider groups={groups ?? []}>
<AttachmentProvider canUpload={canUpload} uploadAsset={store.uploadAsset}>
<EditProfileScreenView
userId={route.params.userId}
onGoBack={() => navigation.goBack()}
onSaveProfile={onSaveProfile}
onUpdatePinnedGroups={store.updateProfilePinnedGroups}
Expand Down
30 changes: 23 additions & 7 deletions packages/app/features/settings/ProfileScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useDMLureLink } from '../../hooks/useBranchLink';
import { useCurrentUserId } from '../../hooks/useCurrentUser';
import { useHandleLogout } from '../../hooks/useHandleLogout';
import { useResetDb } from '../../hooks/useResetDb';
import { useFeatureFlag } from '../../lib/featureFlags';
import { RootStackParamList } from '../../navigation/types';
import { getHostingToken, getHostingUserId } from '../../utils/hosting';

Expand All @@ -17,6 +18,7 @@ export default function ProfileScreen(props: Props) {
const resetDb = useResetDb();
const handleLogout = useHandleLogout({ resetDb });
const currentUserId = useCurrentUserId();
const [contactsTabEnabled] = useFeatureFlag('contactsTab');
const { dmLink } = useDMLureLink();
const hasHostedAuth = useHasHostedAuth();
const navigationRef = useMutableRef(props.navigation);
Expand Down Expand Up @@ -61,6 +63,14 @@ export default function ProfileScreen(props: Props) {
navigationRef.current.navigate('Profile');
}, [navigationRef]);

const onNavigateToContacts = useCallback(() => {
navigationRef.current.navigate('Contacts');
}, [navigationRef]);

const onBack = useCallback(() => {
navigationRef.current.goBack();
}, [navigationRef]);

return (
<View backgroundColor="$background" flex={1}>
<ProfileScreenView
Expand All @@ -75,14 +85,20 @@ export default function ProfileScreen(props: Props) {
onManageAccountPressed={onManageAccountPressed}
onExperimentalFeaturesPressed={onExperimentalFeaturesPressed}
dmLink={dmLink}
contactsTabEnabled={contactsTabEnabled}
onBackPressed={onBack}
/>
<NavBarView
navigateToHome={onNavigateToHome}
navigateToNotifications={onNavigateToNotifications}
navigateToProfileSettings={onNavigateToProfileSettings}
currentRoute="Profile"
currentUserId={currentUserId}
/>
{contactsTabEnabled ? null : (
<NavBarView
navigateToContacts={onNavigateToContacts}
navigateToHome={onNavigateToHome}
navigateToNotifications={onNavigateToNotifications}
navigateToProfileSettings={onNavigateToProfileSettings}
currentRoute="Profile"
currentUserId={currentUserId}
showContactsTab={contactsTabEnabled}
/>
)}
</View>
);
}
Expand Down
15 changes: 15 additions & 0 deletions packages/app/features/top/ActivityScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { useCallback, useMemo } from 'react';

// import ErrorBoundary from '../../ErrorBoundary';
import { useCurrentUserId } from '../../hooks/useCurrentUser';
import { useGroupActions } from '../../hooks/useGroupActions';
import { useFeatureFlag } from '../../lib/featureFlags';
import { RootStackParamList } from '../../navigation/types';
import { screenNameFromChannelId } from '../../navigation/utils';

Expand All @@ -15,6 +17,8 @@ type Props = NativeStackScreenProps<RootStackParamList, 'Activity'>;
export function ActivityScreen(props: Props) {
const isFocused = useIsFocused();
const currentUserId = useCurrentUserId();
const [contactsTabEnabled] = useFeatureFlag('contactsTab');
const { performGroupAction } = useGroupActions();

const allFetcher = store.useInfiniteBucketedActivity('all');
const mentionsFetcher = store.useInfiniteBucketedActivity('mentions');
Expand Down Expand Up @@ -67,6 +71,13 @@ export function ActivityScreen(props: Props) {
[props.navigation]
);

const handleGoToUserProfile = useCallback(
(userId: string) => {
props.navigation.navigate('UserProfile', { userId });
},
[props.navigation]
);

return (
<View backgroundColor="$background" flex={1}>
<ActivityScreenView
Expand All @@ -75,14 +86,18 @@ export function ActivityScreen(props: Props) {
goToChannel={handleGoToChannel}
goToThread={handleGoToThread}
goToGroup={handleGoToGroup}
goToUserProfile={handleGoToUserProfile}
refresh={handleRefreshActivity}
onGroupAction={performGroupAction}
/>
<NavBarView
navigateToContacts={() => props.navigation.navigate('Contacts')}
navigateToHome={() => props.navigation.navigate('ChatList')}
navigateToNotifications={() => props.navigation.navigate('Activity')}
navigateToProfileSettings={() => props.navigation.navigate('Profile')}
currentRoute="Activity"
currentUserId={currentUserId}
showContactsTab={contactsTabEnabled}
/>
</View>
);
Expand Down
19 changes: 19 additions & 0 deletions packages/app/features/top/ChatListScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
ScreenHeader,
View,
WelcomeSheet,
triggerHaptic,
} from '@tloncorp/ui';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

Expand Down Expand Up @@ -54,6 +55,7 @@ export function ChatListScreenView({
const [screenTitle, setScreenTitle] = useState('Home');
const [inviteSheetGroup, setInviteSheetGroup] = useState<db.Group | null>();
const chatOptionsSheetRef = useRef<ChatOptionsSheetMethods>(null);
const [contactsTabEnabled] = useFeatureFlag('contactsTab');
const [longPressedChat, setLongPressedChat] = useState<
db.Channel | db.Group | null
>(null);
Expand Down Expand Up @@ -289,6 +291,11 @@ export function ChatListScreenView({
setShowSearchInput(!showSearchInput);
}, [showSearchInput]);

const goToContacts = useCallback(() => {
triggerHaptic('baseButtonClick');
navigation.navigate('Contacts');
}, [navigation]);

const handleGroupAction = useCallback(
(action: GroupPreviewAction, group: db.Group) => {
performGroupAction(action, group);
Expand Down Expand Up @@ -317,6 +324,14 @@ export function ChatListScreenView({
<View flex={1}>
<ScreenHeader
title={notReadyMessage ?? screenTitle}
leftControls={
contactsTabEnabled ? undefined : (
<ScreenHeader.IconButton
type="ChannelMultiDM"
onPress={goToContacts}
/>
)
}
rightControls={
<>
<ScreenHeader.IconButton
Expand Down Expand Up @@ -366,6 +381,9 @@ export function ChatListScreenView({
/>
</View>
<NavBarView
navigateToContacts={() => {
navigation.navigate('Contacts');
}}
navigateToHome={() => {
navigation.navigate('ChatList');
}}
Expand All @@ -377,6 +395,7 @@ export function ChatListScreenView({
}}
currentRoute="ChatList"
currentUserId={currentUser}
showContactsTab={contactsTabEnabled}
/>
</ChatOptionsProvider>

Expand Down
115 changes: 115 additions & 0 deletions packages/app/features/top/ContactsScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import * as db from '@tloncorp/shared/db';
import * as store from '@tloncorp/shared/store';
import {
AppDataContextProvider,
ContactsScreenView,
NavBarView,
ScreenHeader,
View,
getDisplayName,
isWeb,
triggerHaptic,
} from '@tloncorp/ui';
import { useCallback } from 'react';
import { Alert } from 'react-native';

import { useCurrentUserId } from '../../hooks/useCurrentUser';
import { useFeatureFlag } from '../../lib/featureFlags';
import type { RootStackParamList } from '../../navigation/types';

type Props = NativeStackScreenProps<RootStackParamList, 'Contacts'>;

export default function ContactsScreen(props: Props) {
const {
navigation: { navigate },
} = props;

const [contactsTabEnabled] = useFeatureFlag('contactsTab');
const currentUser = useCurrentUserId();

const { data: userContacts } = store.useUserContacts();
const { data: contacts } = store.useContacts();
const { data: suggestions } = store.useSuggestedContacts();

const onContactPress = useCallback(
(contact: db.Contact) => {
navigate('UserProfile', { userId: contact.id });
},
[navigate]
);

const onContactLongPress = useCallback((contact: db.Contact) => {
if (!isWeb && contact.isContactSuggestion) {
Alert.alert(`Add ${getDisplayName(contact)}?`, '', [
{
text: 'Cancel',
style: 'cancel',
},
{
text: 'Add Contact',
style: 'default',
onPress: () => {
store.addContact(contact.id);
},
},
{
text: 'Decline Suggestion',
style: 'destructive',
onPress: () => {
store.removeContactSuggestion(contact.id);
},
},
]);
}
}, []);

const backAction = useCallback(() => {
triggerHaptic('baseButtonClick');
navigate('ChatList');
}, [navigate]);

return (
<AppDataContextProvider contacts={contacts} currentUserId={currentUser}>
<View flex={1}>
<ScreenHeader
title="Contacts"
backAction={contactsTabEnabled ? undefined : backAction}
rightControls={
contactsTabEnabled ? (
<ScreenHeader.IconButton
type="Settings"
onPress={() => {
navigate('Profile');
}}
/>
) : undefined
}
/>
<ContactsScreenView
contacts={userContacts ?? []}
suggestions={suggestions ?? []}
onContactPress={onContactPress}
onContactLongPress={onContactLongPress}
/>
<NavBarView
navigateToContacts={() => {
navigate('Contacts');
}}
navigateToHome={() => {
navigate('ChatList');
}}
navigateToNotifications={() => {
navigate('Activity');
}}
navigateToProfileSettings={() => {
navigate('Profile');
}}
currentRoute="Contacts"
currentUserId={currentUser}
showContactsTab={contactsTabEnabled}
/>
</View>
</AppDataContextProvider>
);
}
Loading