UNPKG

sticky-horse

Version:

With StickyHorse allow your users to send feedback to your team.

201 lines (200 loc) 10.6 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useSocket = void 0; exports.withTracking = withTracking; var react_1 = __importStar(require("react")); var useCursorTracking_1 = require("../hooks/useCursorTracking"); var usePageTracking_1 = require("../hooks/usePageTracking"); var CursorOverlay_1 = require("./CursorOverlay"); var LaserCursorTrail_1 = __importDefault(require("./LaserCursorTrail")); var socket_1 = require("../utils/socket"); var getUserId_1 = require("../utils/getUserId"); var trackingUtils_1 = require("../utils/trackingUtils"); var SocketContext = (0, react_1.createContext)({ socket: null, isConnected: false, users: [] }); var useSocket = function () { return (0, react_1.useContext)(SocketContext); }; exports.useSocket = useSocket; function withTracking(WrappedComponent, pagePath, socketUrl, userId) { return function TrackingComponent(props) { var _a = (0, react_1.useState)(null), socket = _a[0], setSocket = _a[1]; var _b = (0, react_1.useState)(false), isConnected = _b[0], setIsConnected = _b[1]; var _c = (0, react_1.useState)([]), users = _c[0], setUsers = _c[1]; var _d = (0, react_1.useState)(userId), currentUserId = _d[0], setCurrentUserId = _d[1]; var _e = (0, react_1.useState)(null), trackedUserId = _e[0], setTrackedUserId = _e[1]; var _f = (0, react_1.useState)(null), trackedCursor = _f[0], setTrackedCursor = _f[1]; var _g = (0, react_1.useState)(null), adminCursor = _g[0], setAdminCursor = _g[1]; var _h = (0, react_1.useState)(false), isFollowing = _h[0], setIsFollowing = _h[1]; var _j = (0, react_1.useState)(false), showButtons = _j[0], setShowButtons = _j[1]; var _k = (0, react_1.useState)(false), isActive = _k[0], setIsActive = _k[1]; (0, useCursorTracking_1.useCursorTracking)(userId); (0, usePageTracking_1.usePageTracking)(pagePath, userId); (0, react_1.useEffect)(function () { // Check tracking params immediately var isTrackingMode = (0, trackingUtils_1.checkTrackingParams)(); console.log('withTracking - Tracking mode check:', isTrackingMode); var urlParams = new URLSearchParams(window.location.search); var isTracking = urlParams.get('tracking') === 'true'; var targetId = urlParams.get('targetId'); var localUserId = (0, getUserId_1.getUserId)(); console.log('withTracking - Init params:', { isTracking: isTracking, targetId: targetId, localUserId: localUserId }); var socketIo = (0, socket_1.getSocket)(); if (!socketIo) { socketIo = (0, socket_1.initializeSocket)(localUserId, { isTracking: isTracking, targetId: targetId || undefined, page: window.location.pathname }); } // Handle cursor movement var handleMouseMove = function (e) { if (!socketIo) return; var cursorData = { userId: localUserId, cursor: { x: e.clientX, y: e.clientY }, timestamp: Date.now(), page: window.location.pathname, isAdmin: isTracking, // Set true if this is the tracking window targetId: targetId // Include targetId if we're tracking }; socketIo.emit('cursor_move', cursorData); }; // Add cursor tracking window.addEventListener('mousemove', handleMouseMove); // Handle incoming cursor updates socketIo === null || socketIo === void 0 ? void 0 : socketIo.on('cursor_move', function (data) { console.log('Cursor move received: fuvk fuck fuck ', data); if (data.isAdmin) { setAdminCursor(data.cursor); setShowButtons(true); } else { // (data.userId === targetId) setTrackedCursor(data.cursor); setShowButtons(true); } setUsers(function (prev) { var updated = prev.map(function (user) { return user.userId === data.userId ? __assign(__assign({}, user), { cursor: data.cursor }) : user; }); if (!updated.find(function (u) { return u.userId === data.userId; })) { updated.push({ userId: data.userId, cursor: data.cursor, connectionTime: new Date().toISOString() }); } return updated; }); }); // Initialize tracking if needed if (isTracking && targetId) { socketIo === null || socketIo === void 0 ? void 0 : socketIo.emit('initialize_tracking', { userId: localUserId, targetId: targetId, page: window.location.pathname }); } // Cleanup return function () { window.removeEventListener('mousemove', handleMouseMove); if (socketIo) { socketIo.off('cursor_move'); if (isTracking && targetId) { socketIo.emit('end_tracking', { userId: localUserId, targetId: targetId }); } } }; }, []); // Empty dependency array since we want this to run once var handleTrackUser = (0, react_1.useCallback)(function (userId) { if (socket) { if (trackedUserId === userId) { socket.emit('stop_tracking'); setTrackedUserId(null); setTrackedCursor(null); setShowButtons(false); setIsFollowing(false); } else { socket.emit('track_user', userId); setTrackedUserId(userId); setShowButtons(true); } } }, [socket, trackedUserId]); var trackingProps = { activeUsers: users, isConnected: isConnected, currentUserId: currentUserId, trackedUserId: trackedUserId, onTrackUser: handleTrackUser, isLoading: !socket, }; // Only show tracking UI if this is an admin tracking session var isAdminTracking = !!localStorage.getItem('sticky_horse_tracking'); return (react_1.default.createElement(SocketContext.Provider, { value: { socket: socket, isConnected: isConnected, users: users } }, isAdminTracking && showButtons && (react_1.default.createElement("div", { className: "fixed top-[10%] left-40 z-50 flex gap-2 items-center" }, react_1.default.createElement("button", { onClick: function () { return setIsFollowing(!isFollowing); }, className: "px-2 py-1 rounded ".concat(isFollowing ? 'bg-red-500' : 'bg-green-500', " text-white") }, isFollowing ? 'Stop Following' : 'Start Following'), react_1.default.createElement("button", { onClick: function () { return setIsActive(!isActive); }, className: "px-2 py-1 rounded ".concat(isActive ? 'bg-red-500' : 'bg-green-500', " text-white") }, isActive ? 'Deactivate' : 'Activate', " Laser"))), react_1.default.createElement(CursorOverlay_1.CursorOverlay, { users: users.map(function (user) { return (__assign(__assign({}, user), { cursor: user.userId === trackedUserId ? trackedCursor : user.cursor })); }), currentUserId: currentUserId, trackedUserId: trackedUserId, adminCursor: adminCursor, showUserInfo: true }), isActive && react_1.default.createElement(LaserCursorTrail_1.default, { isAdmin: false, isActive: isActive, laserPosition: { x: 0, y: 0 } }), isAdminTracking && isFollowing && (react_1.default.createElement("div", { className: "fixed inset-0 pointer-events-none z-[100]" }, react_1.default.createElement("div", { className: "absolute inset-0 border-8 border-red-500/50" }), react_1.default.createElement("div", { className: "absolute top-4 left-1/2 -translate-x-1/2 bg-red-500 text-white px-4 py-2 rounded-full" }, "Following User"))), react_1.default.createElement(WrappedComponent, __assign({}, props, trackingProps)))); }; }