@rimori/react-client 0.4.18-next.0 → 0.4.18-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ai/Avatar.js +1 -1
- package/dist/components/ai/BuddyAssistant.js +2 -2
- package/dist/providers/PluginProvider.d.ts +4 -6
- package/dist/providers/PluginProvider.js +18 -13
- package/package.json +3 -3
- package/src/components/ai/Avatar.tsx +1 -1
- package/src/components/ai/BuddyAssistant.tsx +2 -2
- package/src/providers/PluginProvider.tsx +27 -19
|
@@ -9,7 +9,7 @@ import { getFirstMessages } from './utils';
|
|
|
9
9
|
import { useTheme } from '../../hooks/ThemeSetter';
|
|
10
10
|
export function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, circleSize = '300px', className, cache = false, prompt, promptVariables, }) {
|
|
11
11
|
const { ai, event, plugin, userInfo } = useRimori();
|
|
12
|
-
const { isDark: isDarkThemeValue } = useTheme(plugin.theme);
|
|
12
|
+
const { isDark: isDarkThemeValue } = useTheme(plugin.theme, true);
|
|
13
13
|
const [agentReplying, setAgentReplying] = useState(false);
|
|
14
14
|
const [isProcessingMessage, setIsProcessingMessage] = useState(false);
|
|
15
15
|
const dialectTtsInstruction = (userInfo === null || userInfo === void 0 ? void 0 : userInfo.dialect)
|
|
@@ -11,7 +11,7 @@ const genId = () => `ba-${++idCounter}`;
|
|
|
11
11
|
export function BuddyAssistant({ prompt, promptVariables, autoStartConversation, circleSize = '160px', chatPlaceholder, bottomAction, className, voiceSpeed = 1, tools, showName = false, }) {
|
|
12
12
|
const { ai, event, plugin, userInfo } = useRimori();
|
|
13
13
|
const ttsEnabled = plugin.ttsEnabled;
|
|
14
|
-
const { isDark } = useTheme(plugin.theme);
|
|
14
|
+
const { isDark } = useTheme(plugin.theme, true);
|
|
15
15
|
const buddy = userInfo.study_buddy;
|
|
16
16
|
const dialect = userInfo === null || userInfo === void 0 ? void 0 : userInfo.dialect;
|
|
17
17
|
const dialectTtsInstruction = dialect ? `Speak with a ${dialect} accent and pronunciation.` : undefined;
|
|
@@ -99,7 +99,7 @@ export function BuddyAssistant({ prompt, promptVariables, autoStartConversation,
|
|
|
99
99
|
triggerAI(newMessages);
|
|
100
100
|
};
|
|
101
101
|
const lastAssistantMessage = [...messages].filter((m) => m.role === 'assistant').pop();
|
|
102
|
-
return (_jsxs("div", { className: `flex flex-col items-center ${className || ''}`, children: [_jsx(CircleAudioAvatar, { width: circleSize, imageUrl: buddy.avatarUrl, isDarkTheme: isDark, className: "mx-auto" }), showName && (_jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-3xl font-semibold", children: buddy.name }) })), !ttsEnabled ? (_jsx("div", { className: "w-full rounded-xl bg-gray-200/70 dark:bg-gray-800/70 px-4 py-3 text-sm text-gray-800 dark:text-gray-200 leading-relaxed border border-gray-300/40 dark:border-gray-700/40 mt-4", children: !(lastAssistantMessage === null || lastAssistantMessage === void 0 ? void 0 : lastAssistantMessage.content) && isLoading ? (_jsxs("span", { className: "inline-flex gap-1 py-0.5", children: [_jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-gray-400 animate-bounce" }), _jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-gray-400 animate-bounce", style: { animationDelay: '0.15s' } }), _jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-gray-400 animate-bounce", style: { animationDelay: '0.3s' } })] })) : (_jsx("span", { className: "whitespace-pre-wrap", children: lastAssistantMessage === null || lastAssistantMessage === void 0 ? void 0 : lastAssistantMessage.content })) })) : null, _jsxs("div", { className: 'w-full relative mt-4 ' + (ttsEnabled ? 'max-w-md' : ''), children: [_jsx("input", { value: chatInput, onChange: (e) => setChatInput(e.target.value), onKeyDown: (e) => {
|
|
102
|
+
return (_jsxs("div", { className: `flex flex-col items-center ${className || ''}`, children: [_jsx(CircleAudioAvatar, { width: circleSize, imageUrl: buddy.avatarUrl, isDarkTheme: isDark, className: "mx-auto" }), showName && (_jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-3xl font-semibold", children: buddy.name }) })), !plugin.ttsEnabled && messages.length > 1 ? (_jsx("div", { className: "w-full rounded-xl bg-gray-200/70 dark:bg-gray-800/70 px-4 py-3 text-sm text-gray-800 dark:text-gray-200 leading-relaxed border border-gray-300/40 dark:border-gray-700/40 mt-4", children: !(lastAssistantMessage === null || lastAssistantMessage === void 0 ? void 0 : lastAssistantMessage.content) && isLoading ? (_jsxs("span", { className: "inline-flex gap-1 py-0.5", children: [_jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-gray-400 animate-bounce" }), _jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-gray-400 animate-bounce", style: { animationDelay: '0.15s' } }), _jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-gray-400 animate-bounce", style: { animationDelay: '0.3s' } })] })) : (_jsx("span", { className: "whitespace-pre-wrap", children: lastAssistantMessage === null || lastAssistantMessage === void 0 ? void 0 : lastAssistantMessage.content })) })) : null, _jsxs("div", { className: 'w-full relative mt-4 ' + (ttsEnabled ? 'max-w-md' : ''), children: [_jsx("input", { value: chatInput, onChange: (e) => setChatInput(e.target.value), onKeyDown: (e) => {
|
|
103
103
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
104
104
|
e.preventDefault();
|
|
105
105
|
sendMessage(chatInput);
|
|
@@ -4,14 +4,12 @@ import type { UserInfo } from '@rimori/client';
|
|
|
4
4
|
interface PluginProviderProps {
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
pluginId: string;
|
|
7
|
+
/** Pre-constructed RimoriClient (federation mode). When provided, skips the handshake entirely. */
|
|
8
|
+
client?: RimoriClient;
|
|
9
|
+
/** Pre-loaded user info (federation mode). Required when client is provided. */
|
|
10
|
+
userInfo?: UserInfo;
|
|
7
11
|
settings?: {
|
|
8
12
|
disableContextMenu?: boolean;
|
|
9
|
-
disableThemeSetting?: boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Skip the scrollbar detection that emits 'session.triggerScrollbarChange'.
|
|
12
|
-
* In federation mode, the host (FederatedPluginRenderer) handles this instead.
|
|
13
|
-
*/
|
|
14
|
-
disableScrollbarDetection?: boolean;
|
|
15
13
|
};
|
|
16
14
|
}
|
|
17
15
|
export declare const PluginProvider: React.FC<PluginProviderProps>;
|
|
@@ -14,13 +14,14 @@ import posthog from 'posthog-js';
|
|
|
14
14
|
import ContextMenu from '../components/ContextMenu';
|
|
15
15
|
import { useTheme } from '../hooks/ThemeSetter';
|
|
16
16
|
const PluginContext = createContext(null);
|
|
17
|
-
export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
18
|
-
const
|
|
17
|
+
export const PluginProvider = ({ children, pluginId, client: injectedClient, userInfo: injectedUserInfo, settings, }) => {
|
|
18
|
+
const isFederated = !!injectedClient;
|
|
19
|
+
const [client, setClient] = useState(injectedClient !== null && injectedClient !== void 0 ? injectedClient : null);
|
|
19
20
|
const [standaloneClient, setStandaloneClient] = useState(false);
|
|
20
21
|
const [applicationMode, setApplicationMode] = useState(null);
|
|
21
22
|
const [theme, setTheme] = useState(undefined);
|
|
22
|
-
const [userInfo, setUserInfo] = useState(null);
|
|
23
|
-
useTheme(theme,
|
|
23
|
+
const [userInfo, setUserInfo] = useState(injectedUserInfo !== null && injectedUserInfo !== void 0 ? injectedUserInfo : null);
|
|
24
|
+
useTheme(theme, isFederated);
|
|
24
25
|
// Init PostHog once per plugin iframe
|
|
25
26
|
useEffect(() => {
|
|
26
27
|
if (!posthog.__loaded) {
|
|
@@ -40,6 +41,9 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
40
41
|
const isSidebar = applicationMode === 'sidebar';
|
|
41
42
|
const isSettings = applicationMode === 'settings';
|
|
42
43
|
useEffect(() => {
|
|
44
|
+
// In federation mode the client is already ready — skip handshake
|
|
45
|
+
if (isFederated)
|
|
46
|
+
return;
|
|
43
47
|
initEventBus(pluginId);
|
|
44
48
|
// Check if we're in an iframe context - if not, we're standalone
|
|
45
49
|
const standaloneDetected = window === window.parent;
|
|
@@ -51,7 +55,6 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
51
55
|
if ((!standaloneDetected && !client) || (standaloneDetected && standaloneClient === true)) {
|
|
52
56
|
void RimoriClient.getInstance(pluginId).then((client) => {
|
|
53
57
|
setClient(client);
|
|
54
|
-
// Set initial userInfo
|
|
55
58
|
setUserInfo(client.plugin.getUserInfo());
|
|
56
59
|
// Get applicationMode and theme from MessageChannel query params
|
|
57
60
|
if (!standaloneDetected) {
|
|
@@ -61,7 +64,7 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
61
64
|
}
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
|
-
}, [pluginId, standaloneClient, client]);
|
|
67
|
+
}, [pluginId, standaloneClient, client, isFederated]);
|
|
65
68
|
// Identify user in PostHog when userInfo is available
|
|
66
69
|
useEffect(() => {
|
|
67
70
|
if (userInfo === null || userInfo === void 0 ? void 0 : userInfo.user_id) {
|
|
@@ -73,7 +76,7 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
73
76
|
if (!client)
|
|
74
77
|
return;
|
|
75
78
|
const unsubscribe = client.plugin.onRimoriInfoUpdate((info) => {
|
|
76
|
-
console.log('[PluginProvider] Received RimoriInfo update, updating userInfo');
|
|
79
|
+
// console.log('[PluginProvider] Received RimoriInfo update, updating userInfo + ttsEnabled:', info.ttsEnabled);
|
|
77
80
|
setUserInfo(info.profile);
|
|
78
81
|
});
|
|
79
82
|
return () => unsubscribe();
|
|
@@ -83,6 +86,8 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
83
86
|
return;
|
|
84
87
|
if (isSidebar)
|
|
85
88
|
return; //sidebar pages should not report url changes
|
|
89
|
+
if (isFederated)
|
|
90
|
+
return; // federation mode: host handles URL sync
|
|
86
91
|
// react router overwrites native pushstate so it gets wrapped to detect url changes
|
|
87
92
|
const originalPushState = history.pushState;
|
|
88
93
|
history.pushState = (...args) => {
|
|
@@ -90,11 +95,11 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
90
95
|
client.event.emit('session.triggerUrlChange', { url: location.hash });
|
|
91
96
|
return result;
|
|
92
97
|
};
|
|
93
|
-
}, [client, isSidebar]);
|
|
98
|
+
}, [client, isSidebar, isFederated]);
|
|
94
99
|
useEffect(() => {
|
|
95
100
|
if (!client)
|
|
96
101
|
return;
|
|
97
|
-
if (
|
|
102
|
+
if (isFederated)
|
|
98
103
|
return;
|
|
99
104
|
const checkScrollbar = () => {
|
|
100
105
|
const hasScrollbar = document.documentElement.scrollHeight > window.innerHeight;
|
|
@@ -111,7 +116,7 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
|
|
|
111
116
|
window.removeEventListener('resize', checkScrollbar);
|
|
112
117
|
resizeObserver.disconnect();
|
|
113
118
|
};
|
|
114
|
-
}, [client,
|
|
119
|
+
}, [client, isFederated]);
|
|
115
120
|
if (standaloneClient instanceof StandaloneClient) {
|
|
116
121
|
return (_jsx(StandaloneAuth, { onLogin: (email, password) => __awaiter(void 0, void 0, void 0, function* () {
|
|
117
122
|
if (yield standaloneClient.login(email, password))
|
|
@@ -128,9 +133,9 @@ export const useRimori = () => {
|
|
|
128
133
|
if (context === null) {
|
|
129
134
|
throw new Error('useRimori must be used within an PluginProvider');
|
|
130
135
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
return Object.assign(context.client, {
|
|
137
|
+
userInfo: context.userInfo,
|
|
138
|
+
});
|
|
134
139
|
};
|
|
135
140
|
function getUrlParam(name) {
|
|
136
141
|
// First try to get from URL hash query params (for compatibility)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimori/react-client",
|
|
3
|
-
"version": "0.4.18-next.
|
|
3
|
+
"version": "0.4.18-next.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"format": "prettier --write ."
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@rimori/client": "
|
|
28
|
+
"@rimori/client": "2.5.29-next.1",
|
|
29
29
|
"react": "^18.1.0",
|
|
30
30
|
"react-dom": "^18.1.0"
|
|
31
31
|
},
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@eslint/js": "^9.37.0",
|
|
52
|
-
"@rimori/client": "
|
|
52
|
+
"@rimori/client": "2.5.29-next.1",
|
|
53
53
|
"@types/react": "^18.3.21",
|
|
54
54
|
"eslint-config-prettier": "^10.1.8",
|
|
55
55
|
"eslint-plugin-prettier": "^5.5.4",
|
|
@@ -37,7 +37,7 @@ export function Avatar({
|
|
|
37
37
|
promptVariables,
|
|
38
38
|
}: Props) {
|
|
39
39
|
const { ai, event, plugin, userInfo } = useRimori();
|
|
40
|
-
const { isDark: isDarkThemeValue } = useTheme(plugin.theme);
|
|
40
|
+
const { isDark: isDarkThemeValue } = useTheme(plugin.theme, true);
|
|
41
41
|
const [agentReplying, setAgentReplying] = useState(false);
|
|
42
42
|
const [isProcessingMessage, setIsProcessingMessage] = useState(false);
|
|
43
43
|
const dialectTtsInstruction = userInfo?.dialect
|
|
@@ -48,7 +48,7 @@ export function BuddyAssistant({
|
|
|
48
48
|
}: BuddyAssistantProps): JSX.Element {
|
|
49
49
|
const { ai, event, plugin, userInfo } = useRimori();
|
|
50
50
|
const ttsEnabled = plugin.ttsEnabled;
|
|
51
|
-
const { isDark } = useTheme(plugin.theme);
|
|
51
|
+
const { isDark } = useTheme(plugin.theme, true);
|
|
52
52
|
const buddy = userInfo.study_buddy;
|
|
53
53
|
const dialect = userInfo?.dialect;
|
|
54
54
|
const dialectTtsInstruction = dialect ? `Speak with a ${dialect} accent and pronunciation.` : undefined;
|
|
@@ -158,7 +158,7 @@ export function BuddyAssistant({
|
|
|
158
158
|
</div>
|
|
159
159
|
)}
|
|
160
160
|
|
|
161
|
-
{!ttsEnabled ? (
|
|
161
|
+
{!plugin.ttsEnabled && messages.length > 1 ? (
|
|
162
162
|
<div className="w-full rounded-xl bg-gray-200/70 dark:bg-gray-800/70 px-4 py-3 text-sm text-gray-800 dark:text-gray-200 leading-relaxed border border-gray-300/40 dark:border-gray-700/40 mt-4">
|
|
163
163
|
{!lastAssistantMessage?.content && isLoading ? (
|
|
164
164
|
<span className="inline-flex gap-1 py-0.5">
|
|
@@ -9,14 +9,12 @@ import { Theme } from '@rimori/client';
|
|
|
9
9
|
interface PluginProviderProps {
|
|
10
10
|
children: ReactNode;
|
|
11
11
|
pluginId: string;
|
|
12
|
+
/** Pre-constructed RimoriClient (federation mode). When provided, skips the handshake entirely. */
|
|
13
|
+
client?: RimoriClient;
|
|
14
|
+
/** Pre-loaded user info (federation mode). Required when client is provided. */
|
|
15
|
+
userInfo?: UserInfo;
|
|
12
16
|
settings?: {
|
|
13
17
|
disableContextMenu?: boolean;
|
|
14
|
-
disableThemeSetting?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Skip the scrollbar detection that emits 'session.triggerScrollbarChange'.
|
|
17
|
-
* In federation mode, the host (FederatedPluginRenderer) handles this instead.
|
|
18
|
-
*/
|
|
19
|
-
disableScrollbarDetection?: boolean;
|
|
20
18
|
};
|
|
21
19
|
}
|
|
22
20
|
|
|
@@ -27,14 +25,21 @@ interface PluginContextValue {
|
|
|
27
25
|
|
|
28
26
|
const PluginContext = createContext<PluginContextValue | null>(null);
|
|
29
27
|
|
|
30
|
-
export const PluginProvider: React.FC<PluginProviderProps> = ({
|
|
31
|
-
|
|
28
|
+
export const PluginProvider: React.FC<PluginProviderProps> = ({
|
|
29
|
+
children,
|
|
30
|
+
pluginId,
|
|
31
|
+
client: injectedClient,
|
|
32
|
+
userInfo: injectedUserInfo,
|
|
33
|
+
settings,
|
|
34
|
+
}) => {
|
|
35
|
+
const isFederated = !!injectedClient;
|
|
36
|
+
const [client, setClient] = useState<RimoriClient | null>(injectedClient ?? null);
|
|
32
37
|
const [standaloneClient, setStandaloneClient] = useState<StandaloneClient | boolean>(false);
|
|
33
38
|
const [applicationMode, setApplicationMode] = useState<string | null>(null);
|
|
34
39
|
const [theme, setTheme] = useState<Theme | undefined>(undefined);
|
|
35
|
-
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
|
|
40
|
+
const [userInfo, setUserInfo] = useState<UserInfo | null>(injectedUserInfo ?? null);
|
|
36
41
|
|
|
37
|
-
useTheme(theme,
|
|
42
|
+
useTheme(theme, isFederated);
|
|
38
43
|
|
|
39
44
|
// Init PostHog once per plugin iframe
|
|
40
45
|
useEffect(() => {
|
|
@@ -57,6 +62,9 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
57
62
|
const isSettings = applicationMode === 'settings';
|
|
58
63
|
|
|
59
64
|
useEffect(() => {
|
|
65
|
+
// In federation mode the client is already ready — skip handshake
|
|
66
|
+
if (isFederated) return;
|
|
67
|
+
|
|
60
68
|
initEventBus(pluginId);
|
|
61
69
|
|
|
62
70
|
// Check if we're in an iframe context - if not, we're standalone
|
|
@@ -71,7 +79,6 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
71
79
|
if ((!standaloneDetected && !client) || (standaloneDetected && standaloneClient === true)) {
|
|
72
80
|
void RimoriClient.getInstance(pluginId).then((client) => {
|
|
73
81
|
setClient(client);
|
|
74
|
-
// Set initial userInfo
|
|
75
82
|
setUserInfo(client.plugin.getUserInfo());
|
|
76
83
|
|
|
77
84
|
// Get applicationMode and theme from MessageChannel query params
|
|
@@ -82,7 +89,7 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
82
89
|
}
|
|
83
90
|
});
|
|
84
91
|
}
|
|
85
|
-
}, [pluginId, standaloneClient, client]);
|
|
92
|
+
}, [pluginId, standaloneClient, client, isFederated]);
|
|
86
93
|
|
|
87
94
|
// Identify user in PostHog when userInfo is available
|
|
88
95
|
useEffect(() => {
|
|
@@ -96,7 +103,7 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
96
103
|
if (!client) return;
|
|
97
104
|
|
|
98
105
|
const unsubscribe = client.plugin.onRimoriInfoUpdate((info) => {
|
|
99
|
-
console.log('[PluginProvider] Received RimoriInfo update, updating userInfo');
|
|
106
|
+
// console.log('[PluginProvider] Received RimoriInfo update, updating userInfo + ttsEnabled:', info.ttsEnabled);
|
|
100
107
|
setUserInfo(info.profile);
|
|
101
108
|
});
|
|
102
109
|
|
|
@@ -106,6 +113,7 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
106
113
|
useEffect(() => {
|
|
107
114
|
if (!client) return;
|
|
108
115
|
if (isSidebar) return; //sidebar pages should not report url changes
|
|
116
|
+
if (isFederated) return; // federation mode: host handles URL sync
|
|
109
117
|
|
|
110
118
|
// react router overwrites native pushstate so it gets wrapped to detect url changes
|
|
111
119
|
const originalPushState = history.pushState;
|
|
@@ -114,11 +122,11 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
114
122
|
client.event.emit('session.triggerUrlChange', { url: location.hash });
|
|
115
123
|
return result;
|
|
116
124
|
};
|
|
117
|
-
}, [client, isSidebar]);
|
|
125
|
+
}, [client, isSidebar, isFederated]);
|
|
118
126
|
|
|
119
127
|
useEffect(() => {
|
|
120
128
|
if (!client) return;
|
|
121
|
-
if (
|
|
129
|
+
if (isFederated) return;
|
|
122
130
|
|
|
123
131
|
const checkScrollbar = (): void => {
|
|
124
132
|
const hasScrollbar = document.documentElement.scrollHeight > window.innerHeight;
|
|
@@ -140,7 +148,7 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
140
148
|
window.removeEventListener('resize', checkScrollbar);
|
|
141
149
|
resizeObserver.disconnect();
|
|
142
150
|
};
|
|
143
|
-
}, [client,
|
|
151
|
+
}, [client, isFederated]);
|
|
144
152
|
|
|
145
153
|
if (standaloneClient instanceof StandaloneClient) {
|
|
146
154
|
return (
|
|
@@ -169,9 +177,9 @@ export const useRimori = (): RimoriClient & { userInfo: UserInfo } => {
|
|
|
169
177
|
if (context === null) {
|
|
170
178
|
throw new Error('useRimori must be used within an PluginProvider');
|
|
171
179
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
180
|
+
return Object.assign(context.client, {
|
|
181
|
+
userInfo: context.userInfo,
|
|
182
|
+
}) as RimoriClient & { userInfo: UserInfo };
|
|
175
183
|
};
|
|
176
184
|
|
|
177
185
|
function getUrlParam(name: string): string | null {
|