diff --git a/js/app/components/name-color-picker/name-color-picker.tsx b/js/app/components/name-color-picker/name-color-picker.tsx
index 40f20b10..966b7cf7 100644
--- a/js/app/components/name-color-picker/name-color-picker.tsx
+++ b/js/app/components/name-color-picker/name-color-picker.tsx
@@ -1,4 +1,9 @@
-import { Button, formatHandleWithAt, zero } from "@streamplace/components";
+import {
+ Button,
+ formatHandleWithAt,
+ Text,
+ zero,
+} from "@streamplace/components";
import { Palette, SwatchBook, X } from "lucide-react-native";
import { useEffect, useState } from "react";
import {
@@ -6,24 +11,52 @@ import {
Modal,
Platform,
Pressable,
- Text,
TouchableOpacity,
View,
} from "react-native";
import ColorPicker, {
HueSlider,
+ InputWidget,
Panel1,
- Preview,
Swatches,
} from "reanimated-color-picker";
import { useStore } from "store";
import { useChatProfile, useUserProfile } from "store/hooks";
import { PlaceStreamChatProfile } from "streamplace";
+/**
+ * Returns black or white depending on which contrasts better against the given color
+ */
+function getContrastColor(color: string): string {
+ let r: number, g: number, b: number;
+
+ if (color.startsWith("#")) {
+ const hex = color.replace("#", "");
+ r = parseInt(hex.substring(0, 2), 16);
+ g = parseInt(hex.substring(2, 4), 16);
+ b = parseInt(hex.substring(4, 6), 16);
+ } else if (color.startsWith("rgb")) {
+ const match = color.match(/(\d+),\s*(\d+),\s*(\d+)/);
+ if (match) {
+ r = parseInt(match[1]);
+ g = parseInt(match[2]);
+ b = parseInt(match[3]);
+ } else {
+ return "#fff";
+ }
+ } else {
+ return "#fff";
+ }
+
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
+ return luminance > 0.5 ? "#000" : "#fff";
+}
+
/**
* Parses an RGB color string and returns an object with red, green, and blue values
*/
function parseRgbString(rgbString: string): PlaceStreamChatProfile.Color {
+ console.log(rgbString);
if (
!rgbString ||
(!rgbString.startsWith("rgb(") && !rgbString.startsWith("rgba("))
@@ -45,6 +78,25 @@ function parseRgbString(rgbString: string): PlaceStreamChatProfile.Color {
};
}
+function rgbToHex(rgb: PlaceStreamChatProfile.Color) {
+ const hex = (
+ (1 << 24) +
+ (rgb.red << 16) +
+ (rgb.green << 8) +
+ rgb.blue
+ ).toString(16);
+ return `#${hex.slice(-6)}`;
+}
+
+// rgb(r, g, b) to hex
+function cssRgbToHex(rgb: string) {
+ if (rgb.startsWith("#")) {
+ return rgb;
+ }
+ const parsed = parseRgbString(rgb);
+ return rgbToHex(parsed);
+}
+
export function useNameColorPicker() {
const [modalVisible, setModalVisible] = useState(false);
const [tempColor, setTempColor] = useState("#bd6e86");
@@ -159,32 +211,77 @@ export function useNameColorPicker() {
zero.bg.gray[800],
zero.r.md,
zero.p[3],
- zero.mb[5],
+ zero.mb[3],
zero.layout.flex.alignCenter,
]}
>
-
- @{profile.handle}
-
-
- Preview
+
+ {formatHandleWithAt(profile)}
)}
{/* Color Picker */}
-
+
setTempColor(result.rgb)}
+ onChangeJS={(result) => setTempColor(result.rgb)}
>
-
-
+
+ {cssRgbToHex(currentColor) !== cssRgbToHex(tempColor) && (
+
+
+ {cssRgbToHex(currentColor)}
+
+
+ )}
+
+
+
@@ -250,47 +347,7 @@ export default function NameColorPicker({
text?: (color: string) => React.ReactNode;
buttonProps?: any;
}) {
- const [modalVisible, setModalVisible] = useState(false);
- const [tempColor, setTempColor] = useState("#bd6e86");
- const createChatProfileRecord = useStore(
- (state) => state.createChatProfileRecord,
- );
- const getChatProfileRecordFromPDS = useStore(
- (state) => state.getChatProfileRecordFromPDS,
- );
- const chatProfile = useChatProfile();
- const profile = useUserProfile();
- const isWeb = Platform.OS === "web";
-
- const currentColor = chatProfile?.profile?.color
- ? `rgb(${chatProfile.profile.color.red}, ${chatProfile.profile.color.green}, ${chatProfile.profile.color.blue})`
- : "#bd6e86";
-
- useEffect(() => {
- if (profile?.did && !chatProfile?.profile) {
- getChatProfileRecordFromPDS();
- }
- setTempColor(currentColor);
- }, [profile?.did, chatProfile?.profile?.color, currentColor]);
-
- const handleOpenModal = () => {
- if (!isWeb) {
- Keyboard.dismiss();
- }
- setTempColor(currentColor);
- setModalVisible(true);
- };
-
- const handleCloseModal = () => {
- setModalVisible(false);
- setTempColor(currentColor); // Reset to current color on cancel
- };
-
- const handleSaveColor = () => {
- setModalVisible(false);
- const parsed = parseRgbString(tempColor);
- createChatProfileRecord(parsed.red, parsed.green, parsed.blue);
- };
+ const { currentColor, openModal, modal } = useNameColorPicker();
return (
@@ -298,7 +355,7 @@ export default function NameColorPicker({
variant="secondary"
leftIcon={}
style={[buttonProps?.style]}
- onPress={handleOpenModal}
+ onPress={openModal}
{...buttonProps}
>
@@ -306,149 +363,7 @@ export default function NameColorPicker({
-
-
- e.stopPropagation()}
- >
- {/* Header */}
-
-
-
-
- Choose Color
-
-
-
-
-
-
-
- {/* User Preview */}
- {profile?.handle && (
-
-
- {formatHandleWithAt(profile)}
-
-
- Preview
-
-
- )}
-
- {/* Color Picker */}
-
- setTempColor(result.rgb)}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Actions */}
-
-
-
- Cancel
-
-
-
-
- Save Color
-
-
-
-
-
-
+ {modal}
{children}