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

chore: Bump Xmtp #1323

Merged
merged 2 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion components/Chat/ChatGroupUpdatedMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { memo } from "react";
import { ViewStyle } from "react-native";

type IChatGroupUpdatedMessageProps = {
message: DecodedMessage<[GroupUpdatedCodec]>;
message: DecodedMessage<GroupUpdatedCodec>;
};

export function ChatGroupUpdatedMessage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DecodedMessage, RemoteAttachmentCodec } from "@xmtp/react-native-sdk";
import { memo } from "react";

type IMessageRemoteAttachmentProps = {
message: DecodedMessage<[RemoteAttachmentCodec]>;
message: DecodedMessage<RemoteAttachmentCodec>;
};

export const MessageRemoteAttachment = memo(function MessageRemoteAttachment({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { memo } from "react";
import { getCurrentConversationMessages } from "../../../../features/conversation/conversation-service";

export const MessageReply = memo(function MessageReply(props: {
message: DecodedMessage<[ReplyCodec]>;
message: DecodedMessage<ReplyCodec>;
}) {
const { message } = props;

Expand Down Expand Up @@ -163,7 +163,7 @@ const MessageReplyReference = memo(function MessageReplyReference(props: {

const MessageReplyReferenceContent = memo(
function ReplyMessageReferenceMessageContent(props: {
replyMessage: DecodedMessage<[ReplyCodec]>;
replyMessage: DecodedMessage<ReplyCodec>;
}) {
const { replyMessage } = props;

Expand Down Expand Up @@ -213,7 +213,7 @@ const MessageReplyReferenceContent = memo(
}
);

function getReplyMessageSafeText(replyMessage: DecodedMessage<[ReplyCodec]>) {
function getReplyMessageSafeText(replyMessage: DecodedMessage<ReplyCodec>) {
try {
const content = replyMessage.content();
if (typeof content === "string") {
Expand All @@ -229,12 +229,12 @@ function getReplyMessageSafeText(replyMessage: DecodedMessage<[ReplyCodec]>) {
// Needed that in case we need to see the content of a message that is not in the chached list
function useConversationMessageForReplyMessage(
messageId: MessageId
): DecodedMessage<[ReplyCodec]> | undefined {
): DecodedMessage<ReplyCodec> | undefined {
const currentAccount = useCurrentAccount()!;
const messages = getCurrentConversationMessages();

const cachedReplyMessage = messages?.byId[messageId] as
| DecodedMessage<[ReplyCodec]>
| DecodedMessage<ReplyCodec>
| undefined;

// Only fetch the message if it's in the list of messages of the conversation
Expand All @@ -247,7 +247,7 @@ function useConversationMessageForReplyMessage(
});

return (
(replyMessage as DecodedMessage<[ReplyCodec]> | undefined) ??
(replyMessage as DecodedMessage<ReplyCodec> | undefined) ??
cachedReplyMessage
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { DecodedMessage, TextCodec } from "@xmtp/react-native-sdk";
import { memo } from "react";

export const MessageSimpleText = memo(function MessageSimpleText(props: {
message: DecodedMessage<[TextCodec]>;
message: DecodedMessage<TextCodec>;
}) {
const { message } = props;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { memo } from "react";
import RNFS from "react-native-fs";

type IMessageStaticAttachmentProps = {
message: DecodedMessage<[StaticAttachmentCodec]>;
message: DecodedMessage<StaticAttachmentCodec>;
};

export const MessageStaticAttachment = memo(function MessageStaticAttachment({
Expand Down
63 changes: 24 additions & 39 deletions components/Chat/Message/message-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import {
import { queryClient } from "@queries/queryClient";
import { useQuery } from "@tanstack/react-query";
import { getReadableProfile } from "@utils/str";
import { DecodedMessageWithCodecsType } from "@utils/xmtpRN/client";
import {
DecodedMessageWithCodecsType,
SupportedCodecsType,
} from "@utils/xmtpRN/client";
import { getMessageContentType } from "@utils/xmtpRN/contentTypes";
import { CoinbaseMessagingPaymentCodec } from "@utils/xmtpRN/contentTypes/coinbasePayment";
import { getInboxId } from "@utils/xmtpRN/signIn";
Expand All @@ -21,74 +24,56 @@ import {
TextCodec,
} from "@xmtp/react-native-sdk";

// type DecodedMessageAllTypes =
// | DecodedMessage<[TextCodec]>
// | DecodedMessage<[ReactionCodec]>
// | DecodedMessage<[ReadReceiptCodec]>
// | DecodedMessage<[GroupUpdatedCodec]>
// | DecodedMessage<[ReplyCodec]>
// | DecodedMessage<[RemoteAttachmentCodec]>
// | DecodedMessage<[StaticAttachmentCodec]>
// | DecodedMessage<[TransactionReferenceCodec]>
// | DecodedMessage<[CoinbaseMessagingPaymentCodec]>;

/**
* TODO: Move this somewhere else? Maybe to @xmtp/react-native-sdk? Or to @utils/xmtpRN/messages.ts?
*/

export function isTextMessage(
message: any
): message is DecodedMessage<[TextCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<TextCodec> {
return getMessageContentType(message.contentTypeId) === "text";
}
export function isReactionMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[ReactionCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<ReactionCodec> {
return getMessageContentType(message.contentTypeId) === "reaction";
}
export function isReadReceiptMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[ReadReceiptCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<ReadReceiptCodec> {
return getMessageContentType(message.contentTypeId) === "readReceipt";
}
export function isGroupUpdatedMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[GroupUpdatedCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<GroupUpdatedCodec> {
return getMessageContentType(message.contentTypeId) === "groupUpdated";
}
export function isReplyMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[ReplyCodec]> {
return getMessageContentType(message.contentTypeId) === "reply";
message: DecodedMessageWithCodecsType
): message is DecodedMessage<ReplyCodec, SupportedCodecsType> {
const isReply = getMessageContentType(message.contentTypeId) === "reply";
return isReply;
}
export function isRemoteAttachmentMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[RemoteAttachmentCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<RemoteAttachmentCodec> {
return getMessageContentType(message.contentTypeId) === "remoteAttachment";
}
export function isStaticAttachmentMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[StaticAttachmentCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<StaticAttachmentCodec> {
return getMessageContentType(message.contentTypeId) === "attachment";
}
export function isTransactionReferenceMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[TransactionReferenceCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<TransactionReferenceCodec, SupportedCodecsType> {
return (
getMessageContentType(message.contentTypeId) === "transactionReference"
);
}
export function isCoinbasePaymentMessage(
// message: DecodedMessageWithCodecsType
message: any
): message is DecodedMessage<[CoinbaseMessagingPaymentCodec]> {
message: DecodedMessageWithCodecsType
): message is DecodedMessage<CoinbaseMessagingPaymentCodec> {
return getMessageContentType(message.contentTypeId) === "coinbasePayment";
}

Expand Down
4 changes: 3 additions & 1 deletion components/PinnedConversations/PinnedV3DMConversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ export const PinnedV3DMConversation = ({
const title = preferredName;

const displayMessagePreview =
isTextMessage(conversation.lastMessage) && isUnread;
conversation.lastMessage &&
isTextMessage(conversation.lastMessage) &&
isUnread;

const avatarComponent = useMemo(() => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ export const PinnedV3GroupConversation = ({

const title = group?.name;

const displayMessagePreview = isTextMessage(group.lastMessage) && isUnread;
const displayMessagePreview =
group.lastMessage && isTextMessage(group.lastMessage) && isUnread;
Comment on lines +130 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider handling undefined messages more gracefully

While the null check for group.lastMessage improves safety, there's still a non-null assertion (!) being used when passing the message to PinnedMessagePreview. This could be problematic if the message becomes null between the check and render.

Consider this safer approach:

- const displayMessagePreview =
-   group.lastMessage && isTextMessage(group.lastMessage) && isUnread;
+ const lastMessage = group.lastMessage;
+ const displayMessagePreview =
+   lastMessage != null && isTextMessage(lastMessage) && isUnread;

  // Later in JSX
- {displayMessagePreview && <PinnedMessagePreview message={group.lastMessage!} />}
+ {displayMessagePreview && lastMessage && (
+   <PinnedMessagePreview message={lastMessage} />
+ )}

Committable suggestion skipped: line range outside the PR's diff.


const avatarComponent = useMemo(() => {
if (group?.imageUrlSquare) {
Expand Down
1 change: 0 additions & 1 deletion features/GroupInvites/joinGroup/JoinGroup.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,6 @@ export class JoinGroupClient {
const fixtureConversationDataEntity: ConversationDataEntity = {
ids: [GroupIdUserAlreadyWasAMemberOf],
// todo(lustig): how do you create a well typed fixture of the plain conversation type?
// @ts-expect-error
byId: {
[GroupIdUserAlreadyWasAMemberOf]: conversationFixture,
},
Expand Down
2 changes: 1 addition & 1 deletion features/conversation-list/hooks/useMessageText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const useMessageText = (

try {
if (isReplyMessage(message)) {
const messageTyped = message as DecodedMessage<[ReplyCodec]>;
const messageTyped = message as DecodedMessage<ReplyCodec>;
const content = messageTyped.content();

if (typeof content === "string") {
Expand Down
14 changes: 6 additions & 8 deletions features/conversation/composer/composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ export const ReplyPreviewEndContent = memo(
const { theme } = useAppTheme();

if (isReplyMessage(replyMessage)) {
const replyTyped = replyMessage as DecodedMessage<[ReplyCodec]>;
const replyTyped = replyMessage as DecodedMessage<ReplyCodec>;

const content = replyTyped.content();

Expand All @@ -376,9 +376,8 @@ export const ReplyPreviewEndContent = memo(
}

if (isRemoteAttachmentMessage(replyMessage)) {
const messageTyped = replyMessage as DecodedMessage<
[RemoteAttachmentCodec]
>;
const messageTyped =
replyMessage as DecodedMessage<RemoteAttachmentCodec>;

const content = messageTyped.content();

Expand Down Expand Up @@ -417,9 +416,8 @@ const ReplyPreviewMessageContent = memo(
const clearedMessage = messageText?.replace(/(\n)/gm, " ");

if (isStaticAttachmentMessage(replyMessage)) {
const messageTyped = replyMessage as DecodedMessage<
[StaticAttachmentCodec]
>;
const messageTyped =
replyMessage as DecodedMessage<StaticAttachmentCodec>;

const content = messageTyped.content();

Expand Down Expand Up @@ -456,7 +454,7 @@ const ReplyPreviewMessageContent = memo(
}

if (isReplyMessage(replyMessage)) {
const messageTyped = replyMessage as DecodedMessage<[ReplyCodec]>;
const messageTyped = replyMessage as DecodedMessage<ReplyCodec>;
const content = messageTyped.content();

if (typeof content === "string") {
Expand Down
16 changes: 16 additions & 0 deletions ios/Converse.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Converse/Pods-Converse-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift/CryptoSwift.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
Expand All @@ -433,18 +434,23 @@
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoLocalization/ExpoLocalization_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/ReachabilitySwift.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SQLCipher/SQLCipher.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/Sentry/Sentry.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SwiftProtobuf/SwiftProtobuf.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/CryptoSwift.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
Expand All @@ -455,15 +461,19 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoLocalization_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReachabilitySwift.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SQLCipher.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Sentry.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SwiftProtobuf.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand All @@ -477,12 +487,18 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ConverseNotificationExtension/Pods-ConverseNotificationExtension-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift/CryptoSwift.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SQLCipher/SQLCipher.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/Sentry/Sentry.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SwiftProtobuf/SwiftProtobuf.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SQLite.swift/SQLite.swift.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/CryptoSwift.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SQLCipher.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Sentry.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SwiftProtobuf.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SQLite.swift.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
6 changes: 2 additions & 4 deletions ios/ConverseNotificationExtension/Profile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@

import Foundation
import Alamofire
import web3

func getProfile(account: String, address: String) async -> Profile? {
var profileState = getProfilesStore(account: account)?.state
let lowercasedAddress = address.lowercased()
let formattedAddress = EthereumAddress(lowercasedAddress).toChecksumAddress()
if let profile = profileState?.profiles?[address] ?? profileState?.profiles?[formattedAddress] ?? profileState?.profiles?[lowercasedAddress] {
let formattedAddress = address.lowercased()
if let profile = profileState?.profiles?[address] ?? profileState?.profiles?[formattedAddress] {
Comment on lines +13 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add address format validation

While removing the web3 dependency simplifies the code, we should still validate the Ethereum address format to prevent invalid addresses from being processed.

Consider adding a simple regex validation:

+func isValidEthereumAddress(_ address: String) -> Bool {
+    let pattern = "^0x[0-9a-fA-F]{40}$"
+    return address.range(of: pattern, options: .regularExpression) != nil
+}

 func getProfile(account: String, address: String) async -> Profile? {
   var profileState = getProfilesStore(account: account)?.state
+  guard isValidEthereumAddress(address) else { return nil }
   let formattedAddress = address.lowercased()

Committable suggestion skipped: line range outside the PR's diff.

return profile
}

Expand Down
Loading
Loading