sticky-horse
Version:
With StickyHorse allow your users to send feedback to your team.
201 lines (200 loc) • 10.6 kB
JavaScript
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))));
};
}
;