feat: update Next.js configuration, add 'use client' directive to multiple components, and create new pages for music, editor, and videos
Some checks failed
GBCI / build (push) Failing after 1m45s
Some checks failed
GBCI / build (push) Failing after 1m45s
This commit is contained in:
parent
f3a659f8b0
commit
4e57232f08
31 changed files with 114 additions and 132 deletions
|
@ -1,20 +0,0 @@
|
|||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function POST() {
|
||||
try {
|
||||
const response = await fetch('https://generalbots.online/directline/PROD-GeneralBots006/conversations', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to create conversation' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const room = searchParams.get('room')
|
||||
const identity = searchParams.get('identity')
|
||||
|
||||
const response = await fetch(
|
||||
`https://generalbots.online/PROD-GeneralBots006/meeting-token?room=${room}&identity=${identity}`
|
||||
)
|
||||
const data = await response.json()
|
||||
|
||||
return NextResponse.json(data)
|
||||
}
|
|
@ -6,7 +6,6 @@ import '../../styles/chat.css';
|
|||
|
||||
export function ChatInput() {
|
||||
const [message, setMessage] = React.useState('');
|
||||
const [showEmoji, setShowEmoji] = React.useState(false);
|
||||
const { sendActivity } = useChat();
|
||||
const { playSound } = useSound();
|
||||
|
||||
|
@ -20,10 +19,6 @@ export function ChatInput() {
|
|||
setMessage('');
|
||||
};
|
||||
|
||||
const handleEmojiSelect = (emoji) => {
|
||||
playSound('click');
|
||||
setMessage((prev) => prev + emoji);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -33,7 +28,7 @@ export function ChatInput() {
|
|||
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" />
|
||||
</svg>
|
||||
</button>
|
||||
<button className="icon-button" onClick={() => setShowEmoji(true)}>
|
||||
<button className="icon-button">
|
||||
<svg className="icon" viewBox="0 0 24 24">
|
||||
<path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM8 14s1.5 2 4 2 4-2 4-2M9 9h.01M15 9h.01" />
|
||||
</svg>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||
import { User, ChatInstance } from '../types';
|
||||
import { User } from '../types';
|
||||
|
||||
const ChatContext = createContext(undefined);
|
||||
|
||||
|
@ -28,8 +28,8 @@ export function ChatProvider({ children }) {
|
|||
|
||||
const chatService = {
|
||||
activity$: { subscribe: () => {} },
|
||||
postActivity: (activity) => ({
|
||||
subscribe: (observer) => {
|
||||
postActivity: () => ({
|
||||
subscribe: () => {
|
||||
return { unsubscribe: () => {} };
|
||||
},
|
||||
}),
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
"use client";
|
||||
import React, { createContext, useContext, useCallback } from 'react';
|
||||
import React, { createContext, useCallback } from 'react';
|
||||
|
||||
const SoundContext = createContext(undefined);
|
||||
|
||||
export function SoundProvider({ children }) {
|
||||
const [enabled, setEnabled] = React.useState(true);
|
||||
|
||||
const playSound = useCallback((sound) => {
|
||||
const playSound = useCallback(() => {
|
||||
if (!enabled) return;
|
||||
const audio = new Audio();
|
||||
audio.play().catch((err) => console.error('Failed to play sound:', err));
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
'use client'
|
||||
|
||||
export default function MainPage() {
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-gray-50">
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import { ThemeProvider } from "@/components/ui/theme-provider";
|
||||
import { Metadata } from 'next';
|
||||
import { Nav } from './client-nav';
|
||||
import './globals.css';
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ import {
|
|||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip"
|
||||
import { Mail } from "./data"
|
||||
import { Mail } from "../data"
|
||||
|
||||
interface MailDisplayProps {
|
||||
mail: Mail | null
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"use client"
|
||||
|
||||
import NextLink from 'next/link'; // Changed from lucide-react
|
||||
import { Link as LinkIcon } from 'lucide-react'; // Renamed to avoid conflict
|
||||
import { LucideIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import Image from "next/image"
|
||||
|
||||
import { Mail } from "./components/mail"
|
||||
import { accounts, mails } from "./data"
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import { LiveKitRoom, VideoConference } from '@livekit/components-react'
|
||||
import { RoomEvent, Track } from 'livekit-client'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Card } from '@/components/ui/card'
|
||||
|
@ -12,11 +10,15 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
|||
import '@livekit/components-styles';
|
||||
import { Avatar, AvatarFallback } from '@/components/ui/avatar'
|
||||
import { Mic, MicOff, Video, VideoOff, Send, Bot } from 'lucide-react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function MeetingPage({ params }: { params: { room: string } }) {
|
||||
export default function MeetRoomPage() {
|
||||
|
||||
const [name, setName] = useState('');
|
||||
const router = useRouter()
|
||||
const [name, setName] = useState('')
|
||||
const [roomName, setRoomName] = useState(params.room || '')
|
||||
|
||||
const [roomName, setRoomName] = useState(router.query.slug || '');
|
||||
|
||||
const [token, setToken] = useState('')
|
||||
const [isConnected, setIsConnected] = useState(false)
|
||||
const [messages, setMessages] = useState<Array<{ sender: string, text: string, isBot: boolean }>>([])
|
||||
|
@ -25,15 +27,12 @@ export default function MeetingPage({ params }: { params: { room: string } }) {
|
|||
const [cameraEnabled, setCameraEnabled] = useState(true)
|
||||
const [botTyping, setBotTyping] = useState(false)
|
||||
const botConnectionRef = useRef<any>(null)
|
||||
const audioContextRef = useRef<AudioContext>()
|
||||
const processorRef = useRef<ScriptProcessorNode>()
|
||||
const participantsRef = useRef<Map<string, MediaStreamAudioSourceNode>>(new Map())
|
||||
|
||||
|
||||
// Connect to LiveKit room
|
||||
const connectToRoom = async () => {
|
||||
try {
|
||||
const resp = await fetch(`/api/get-token?room=${roomName}&identity=${name || 'user'}`)
|
||||
const resp = await fetch(`https://generalbots.online/PROD-GeneralBots006/meeting-token?room=${roomName}&identity=${name || 'user'}`)
|
||||
const data = await resp.json()
|
||||
setToken(data.token)
|
||||
setIsConnected(true)
|
||||
|
@ -48,19 +47,15 @@ export default function MeetingPage({ params }: { params: { room: string } }) {
|
|||
// Connect to Bot Framework via Next.js API proxy
|
||||
const connectBot = async () => {
|
||||
try {
|
||||
// First create a conversation through our API proxy
|
||||
const convResponse = await fetch('/api/bot/create-conversation', {
|
||||
|
||||
const response = await fetch('https://generalbots.online/directline/PROD-GeneralBots006/conversations', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const convData = await convResponse.json();
|
||||
|
||||
if (!convData.conversationId) {
|
||||
throw new Error('Failed to create conversation');
|
||||
}
|
||||
const data = await response.json()
|
||||
|
||||
// Then connect using WebSocket (which doesn't have CORS restrictions)
|
||||
const { DirectLine } = await import('botframework-directlinejs')
|
||||
|
@ -68,8 +63,8 @@ export default function MeetingPage({ params }: { params: { room: string } }) {
|
|||
|
||||
botConnectionRef.current = new DirectLine({
|
||||
domain: 'https://generalbots.online/directline/PROD-GeneralBots006',
|
||||
conversationId: convData.conversationId,
|
||||
userId: userId,
|
||||
conversationId: data.conversationId,
|
||||
webSocket: false // Force WebSocket connection
|
||||
} as any);
|
||||
botConnectionRef.current.setUserId(userId);
|
||||
|
@ -189,7 +184,7 @@ export default function MeetingPage({ params }: { params: { room: string } }) {
|
|||
<VideoConference className="absolute inset-0" />
|
||||
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex gap-2 bg-gray-800/80 backdrop-blur-sm p-2 rounded-full">
|
||||
<Button
|
||||
variant={micEnabled ? 'primary' : 'outline'}
|
||||
variant={micEnabled ? 'link' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => setMicEnabled(!micEnabled)}
|
||||
className="rounded-full h-10 w-10 hover:bg-gray-700 transition-colors"
|
||||
|
@ -197,7 +192,7 @@ export default function MeetingPage({ params }: { params: { room: string } }) {
|
|||
{micEnabled ? <Mic className="h-5 w-5" /> : <MicOff className="h-5 w-5" />}
|
||||
</Button>
|
||||
<Button
|
||||
variant={cameraEnabled ? 'primary' : 'outline'}
|
||||
variant={cameraEnabled ? 'link' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => setCameraEnabled(!cameraEnabled)}
|
||||
className="rounded-full h-10 w-10 hover:bg-gray-700 transition-colors"
|
|
@ -0,0 +1,8 @@
|
|||
'use client'
|
||||
|
||||
export default function MainPage() {
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-gray-50">
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
|
||||
"use client";
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"use client";
|
||||
import React from 'react';
|
||||
import { AccountForm } from './account-form';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { AppearanceForm } from './appearance-form';
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
'use client'; // Required for client-side interactivity
|
||||
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
|
||||
interface SidebarNavProps {
|
||||
items: {
|
||||
|
@ -9,17 +11,17 @@ interface SidebarNavProps {
|
|||
}
|
||||
|
||||
export function SidebarNav({ items }: SidebarNavProps) {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{items.map((item) => (
|
||||
<button
|
||||
key={item.href}
|
||||
onClick={() => navigate(item.href)}
|
||||
onClick={() => router.push(item.href)}
|
||||
className={`px-3 py-2 rounded-md text-sm font-medium ${
|
||||
location.pathname === item.href ? 'bg-gray-100' : 'hover:bg-gray-50'
|
||||
pathname === item.href ? 'bg-gray-100' : 'hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
{item.title}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
"use client";
|
||||
|
||||
|
||||
import React from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { DisplayForm } from './display-form';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { NotificationsForm } from './notifications-form';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
|
|
@ -60,13 +60,13 @@ function Page() {
|
|||
const config: RcloneConfig = {
|
||||
name: state.name,
|
||||
remote_path: `s3://${state.name}`,
|
||||
local_path: `${window.__TAURI__.path.homeDir}/General Bots/${state.name}`,
|
||||
local_path: `${window['__TAURI__'].path.homeDir}/General Bots/${state.name}`,
|
||||
access_key: state.access_key,
|
||||
secret_key: state.secret_key,
|
||||
};
|
||||
|
||||
try {
|
||||
await core.invoke("save_config", { config });
|
||||
await invoke("save_config", { config });
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
status_text: "New sync saved!",
|
||||
|
@ -85,13 +85,13 @@ function Page() {
|
|||
const config: RcloneConfig = {
|
||||
name: state.name || "example",
|
||||
remote_path: `s3://${state.name || "example"}`,
|
||||
local_path: `${window.__TAURI__.path.homeDir}/General Bots/${state.name || "example"}`,
|
||||
local_path: `${window['__TAURI__'].path.homeDir}/General Bots/${state.name || "example"}`,
|
||||
access_key: state.access_key || "dummy",
|
||||
secret_key: state.secret_key || "dummy",
|
||||
};
|
||||
|
||||
try {
|
||||
await core.invoke("start_sync", { config });
|
||||
await invoke("start_sync", { config });
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
status_text: "Sync started!"
|
||||
|
@ -106,7 +106,7 @@ function Page() {
|
|||
|
||||
const stopSync = async () => {
|
||||
try {
|
||||
await core.invoke("stop_sync");
|
||||
await invoke("stop_sync");
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
status_text: "Sync stopped."
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { core } from '@tauri-apps/api';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { api } from '@tauri-apps/api';
|
||||
|
||||
|
||||
|
||||
interface FileOperationsProps {
|
||||
|
@ -15,21 +13,6 @@ export function FileOperations({ currentPath, onRefresh }: FileOperationsProps)
|
|||
|
||||
const handleUpload = async () => {
|
||||
try {
|
||||
const selected = await open({
|
||||
multiple: false,
|
||||
directory: false,
|
||||
});
|
||||
|
||||
if (selected) {
|
||||
const filePath = Array.isArray(selected) ? selected[0] : selected;
|
||||
await core.invoke('upload_file', {
|
||||
srcPath: filePath,
|
||||
destPath: currentPath,
|
||||
onProgress: (progress: number) => setUploadProgress(progress)
|
||||
});
|
||||
onRefresh();
|
||||
alert('File uploaded successfully!');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Upload failed:', error);
|
||||
alert('Upload failed!');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { core } from '@tauri-apps/api';
|
||||
import { FileBrowser } from './FileBrowser';
|
||||
|
||||
interface FileItem {
|
||||
name: string;
|
||||
|
@ -47,7 +48,7 @@ export function FileTree({ onSelect }: FileTreeProps) {
|
|||
</div>
|
||||
{expanded[item.path] && (
|
||||
<div className="pl-4">
|
||||
<FileBrowser path={item.path} onSelect={onSelect} />
|
||||
<FileBrowser path={item.path} />
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
'use client'
|
||||
|
||||
export default function MainPage() {
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-gray-50">
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
|
||||
output: 'export',
|
||||
images: { unoptimized: true }
|
||||
}
|
||||
|
||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -59,7 +59,7 @@
|
|||
"react": "18.3.1",
|
||||
"react-day-picker": "^8.10.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-hook-form": "^7.53.2",
|
||||
"react-hook-form": "^7.56.1",
|
||||
"react-markdown": "10.1.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"tailwind-merge": "3.0.2",
|
||||
|
@ -12617,9 +12617,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.53.2",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.2.tgz",
|
||||
"integrity": "sha512-YVel6fW5sOeedd1524pltpHX+jgU2u3DSDtXEaBORNdqiNrsX/nUI/iGXONegttg0mJVnfrIkiV0cmTU6Oo2xw==",
|
||||
"version": "7.56.1",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.56.1.tgz",
|
||||
"integrity": "sha512-qWAVokhSpshhcEuQDSANHx3jiAEFzu2HAaaQIzi/r9FNPm1ioAvuJSD4EuZzWd7Al7nTRKcKPnBKO7sRn+zavQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
"react": "18.3.1",
|
||||
"react-day-picker": "^8.10.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-hook-form": "^7.53.2",
|
||||
"react-hook-form": "^7.56.1",
|
||||
"react-markdown": "10.1.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"tailwind-merge": "3.0.2",
|
||||
|
|
|
@ -7,5 +7,5 @@ export async function getServerCookie(key: string): Promise<string | undefined>
|
|||
if (process.env.NEXT_PHASE === 'phase-production-build') {
|
||||
return undefined;
|
||||
}
|
||||
return cookies().get(key)?.value;
|
||||
return (await cookies()).get(key)?.value;
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue