@cometchat/chat-uikit-react-native
Version:
Ready-to-use Chat UI Components for React Native
144 lines (123 loc) • 4.17 kB
text/typescript
import React from "react";
import { DeepPartial } from "./types";
import { useCometChatTranslation } from "../resources/CometChatLocalizeNew";
import { localizedDateHelperInstance } from "./LocalizedDateHelper";
import dayjs from "dayjs";
export function deepMerge<
T extends Record<string, any>,
U extends DeepPartial<T> & Record<string, any>
>(obj1: T, obj2: U, ...rest: (DeepPartial<T> & Record<string, any>)[]): T & U {
// Helper function to determine if a value is a plain object
function isObject(value: any): value is object {
if (React.isValidElement(value)) return false;
return value && typeof value === "object" && !Array.isArray(value);
}
// Main deep merge function
function merge(
target: Record<string, any>,
source: Record<string, any>,
replace: boolean = false
): Record<string, any> {
const output = replace ? target : { ...target };
for (const key in source) {
if (isObject(source[key])) {
if (isObject(target[key])) {
output[key] = merge(target[key], source[key]);
} else {
output[key] = merge({}, source[key]);
}
} else if (source[key] !== undefined) {
output[key] = source[key];
}
}
return output;
}
// Start merging obj1 and obj2, then recursively merge the rest of the objects
let result = merge(obj1, obj2) as T & U;
for (const obj of rest) {
merge(result, obj, true) as T & U;
}
return result;
}
export function deepClone<T>(obj: T, seen = new WeakMap()): T {
if (typeof obj !== "object" || obj === null) {
return obj;
}
if (seen.has(obj)) {
return seen.get(obj);
}
let clone: any;
if (Array.isArray(obj)) {
clone = [];
seen.set(obj, clone);
for (const item of obj) {
clone.push(deepClone(item, seen));
}
} else {
clone = Object.create(null); // Avoid prototype issues
seen.set(obj, clone);
for (const key of Object.keys(obj)) {
clone[key] = deepClone((obj as any)[key], seen);
}
}
return clone as T;
}
export function getLastSeenTime(timestamp: number | null | undefined): string {
try {
if (timestamp === null || timestamp === undefined) {
// Move the hook call inside the function, just like in functions.js
return "";
}
// Convert to milliseconds if in seconds
if (String(timestamp).length === 10) {
timestamp *= 1000;
}
// Get user's current language from the translation hook (exactly like functions.js)
const { language, t } = useCometChatTranslation();
// Set the appropriate Day.js locale
dayjs.locale(language);
const now = dayjs();
const lastSeenTime = dayjs(timestamp);
const diffInMinutes = now.diff(lastSeenTime, "minute");
const diffInHours = now.diff(lastSeenTime, "hour");
const diffInDays = now.diff(lastSeenTime, "day");
// For very recent times (< 1 min) → "a few seconds ago"
if (diffInMinutes < 1) {
const relativeTimeString = lastSeenTime.fromNow();
// Day.js will give "a few seconds ago" localized
return `${t("LAST_SEEN")} ${relativeTimeString}`;
}
// For times less than 24 hours → relative ("X minutes ago", "X hours ago")
if (diffInHours < 24) {
const relativeTimeString = lastSeenTime.fromNow();
return `${t("LAST_SEEN")} ${relativeTimeString}`;
}
// For yesterday with time
if (diffInDays === 1) {
const timeFormat = localizedDateHelperInstance.getFormattedDate(
timestamp,
"timeFormat",
language
);
return `${t("LAST_SEEN")} ${t("YESTERDAY")} ${timeFormat}`;
}
// For dates within the past week → weekday + time
if (diffInDays < 7) {
const formattedDate = localizedDateHelperInstance.getFormattedDate(
timestamp,
"dayWeekDayDateTimeFormat",
language
);
return `${t("LAST_SEEN")} ${formattedDate}`;
}
// Older dates → full date + time
return `${t("LAST_SEEN")} ${localizedDateHelperInstance.getFormattedDate(
timestamp,
"dayDateTimeFormat",
language
)}`;
} catch (e) {
console.log(e);
return "";
}
}