play
Seto Elkahfi committed
Aug 1, 2024 at 20:17 UTC
b68abcdf3d8b343ccb650e061313077738a5b9ea
22 files changed
+186
-320
frontend/splitfire-desktop/app/_lib/hooks/use-enter-submit.tsx
deleted
-23
@@ -1,23 +0,0 @@
1
-import { useRef, type RefObject } from 'react'
2
-
3
-export function useEnterSubmit(): {
4
- formRef: RefObject<HTMLFormElement>
5
- onKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void
6
-} {
7
- const formRef = useRef<HTMLFormElement>(null)
8
-
9
- const handleKeyDown = (
10
- event: React.KeyboardEvent<HTMLTextAreaElement>
11
- ): void => {
12
- if (
13
- event.key === 'Enter' &&
14
- !event.shiftKey &&
15
- !event.nativeEvent.isComposing
16
- ) {
17
- formRef.current?.requestSubmit()
18
- event.preventDefault()
19
- }
20
- }
21
-
22
- return { formRef, onKeyDown: handleKeyDown }
23
-}
frontend/splitfire-desktop/app/_lib/hooks/use-local-storage.ts
deleted
-24
@@ -1,24 +0,0 @@
1
-import { useEffect, useState } from 'react'
2
-
3
-export const useLocalStorage = <T>(
4
- key: string,
5
- initialValue: T
6
-): [T, (value: T) => void] => {
7
- const [storedValue, setStoredValue] = useState(initialValue)
8
-
9
- useEffect(() => {
10
- // Retrieve from localStorage
11
- const item = window.localStorage.getItem(key)
12
- if (item) {
13
- setStoredValue(JSON.parse(item))
14
- }
15
- }, [key])
16
-
17
- const setValue = (value: T) => {
18
- // Save state
19
- setStoredValue(value)
20
- // Save to localStorage
21
- window.localStorage.setItem(key, JSON.stringify(value))
22
- }
23
- return [storedValue, setValue]
24
-}
frontend/splitfire-desktop/app/_src/components/player/Player.tsx
+3
-1
@@ -8,11 +8,13 @@ import ErrorView from "../templates/Error"
8
import { LoadingView } from "../templates/LoadingView"
9
import { invoke } from '@tauri-apps/api'
10
import { UserContext } from "../../lib/CurrentUserContext"
11
-import { PlayerPrepareResponse, TAURI_PLAYER_RECORD, TAURI_PLAYER_SET_VOLUME, TAURI_PLAYER_PAUSED, TAURI_PLAYER_UNMOUNT, TAURI_PLAYER_PREPARE, TauriResponse, TAURI_PLAYER_STOP, TAURI_PLAYER_RESUMED, TAURI_PLAYER_PLAY, TAURI_PLAYER_RECORDING_LENGTH, TAURI_PLAYER_RECORD_STOP } from "../../lib/tauriHandler"
11
+import { TAURI_PLAYER_RECORD, TAURI_PLAYER_SET_VOLUME, TAURI_PLAYER_PAUSED, TAURI_PLAYER_UNMOUNT, TAURI_PLAYER_PREPARE, TAURI_PLAYER_STOP, TAURI_PLAYER_RESUMED, TAURI_PLAYER_PLAY, TAURI_PLAYER_RECORDING_LENGTH, TAURI_PLAYER_RECORD_STOP } from "../../lib/tauriHandler"
12
import { ControlButtonsView } from "./ControlButtons"
13
import { VolumeSliderView } from "./VolumeSliderView"
14
import { HideShowToggleView } from "./HideShowToggle"
15
import { RecordingView } from "./RecordingView"
16
+import { PlayerPrepareResponse } from "@/models/content"
17
+import { TauriResponse } from "@/models/shared"
18
19
enum State {
20
LOADING,
frontend/splitfire-desktop/app/_src/lib/tauriHandler.ts
+1
-11
@@ -19,15 +19,5 @@ export const TAURI_ACCOUNT_REGISTER = 'account_register'
19
20
// Contents
21
export const TAURI_CONTENT_CAROUSEL = 'content_carousel'
22
+export const TAURI_CONTENT_READY_TO_PLAY = 'content_ready_to_play'
23
23
-export enum TauriResponse {
24
- ERROR = 0,
25
- SUCCESS = 1
26
-}
27
-
28
-// Response from the Tauri API
29
-export interface PlayerPrepareResponse {
30
- status: TauriResponse,
31
- message: string,
32
- audio_file_name?: string,
33
-}
\ No newline at end of file
frontend/splitfire-desktop/app/_ui/components/chat-panel.tsx
deleted
-57
@@ -1,57 +0,0 @@
1
-'use client'
2
-
3
-import * as React from 'react'
4
-import { type UseChatHelpers } from 'ai/react'
5
-
6
-import { PromptForm } from './prompt-form'
7
-
8
-export interface ChatPanelProps
9
- extends Pick<
10
- UseChatHelpers,
11
- | 'append'
12
- | 'isLoading'
13
- | 'reload'
14
- | 'messages'
15
- | 'stop'
16
- | 'input'
17
- | 'setInput'
18
- > {
19
- id?: string
20
- title?: string
21
-}
22
-
23
-export function ChatPanel({
24
- id,
25
- title,
26
- isLoading,
27
- stop,
28
- append,
29
- reload,
30
- input,
31
- setInput,
32
- messages
33
-}: ChatPanelProps) {
34
- const [shareDialogOpen, setShareDialogOpen] = React.useState(false)
35
-
36
- return (
37
- <div className="fixed inset-x-0 bottom-0 w-full bg-gradient-to-b from-muted/30 from-0% to-muted/30 to-50% animate-in duration-300 ease-in-out dark:from-background/10 dark:from-10% dark:to-background/80 peer-[[data-state=open]]:group-[]:lg:pl-[250px] peer-[[data-state=open]]:group-[]:xl:pl-[300px]">
38
- <div className="mx-auto sm:max-w-2xl sm:px-4">
39
- <div className="flex items-center justify-center h-12"></div>
40
- <div className="px-4 py-2 space-y-4 border-t shadow-lg bg-background sm:rounded-t-xl sm:border md:py-4">
41
- <PromptForm
42
- onSubmit={async value => {
43
- await append({
44
- id,
45
- content: value,
46
- role: 'user'
47
- })
48
- }}
49
- input={input}
50
- setInput={setInput}
51
- isLoading={isLoading}
52
- />
53
- </div>
54
- </div>
55
- </div>
56
- )
57
-}
frontend/splitfire-desktop/app/_ui/components/empty-screen.tsx
deleted
-56
@@ -1,56 +0,0 @@
1
-import { UseChatHelpers } from 'ai/react'
2
-
3
-import { Button } from './button'
4
-import { ExternalLink } from './external-link'
5
-import { IconArrowRight } from './icons'
6
-
7
-const exampleMessages = [
8
- {
9
- heading: 'Explain technical concepts',
10
- message: `What is a "serverless function"?`
11
- },
12
- {
13
- heading: 'Summarize an article',
14
- message: 'Summarize the following article for a 2nd grader: \n'
15
- },
16
- {
17
- heading: 'Draft an email',
18
- message: `Draft an email to my boss about the following: \n`
19
- }
20
-]
21
-
22
-export function EmptyScreen({ setInput }: Pick<UseChatHelpers, 'setInput'>) {
23
- return (
24
- <div className="mx-auto max-w-2xl px-4">
25
- <div className="rounded-lg border bg-background p-8">
26
- <h1 className="mb-2 text-lg font-semibold">
27
- Welcome to Next.js AI Chatbot!
28
- </h1>
29
- <p className="mb-2 leading-normal text-muted-foreground">
30
- This is an open source AI chatbot app template built with{' '}
31
- <ExternalLink href="https://nextjs.org">Next.js</ExternalLink> and{' '}
32
- <ExternalLink href="https://vercel.com/storage/kv">
33
- Vercel KV
34
- </ExternalLink>
35
- .
36
- </p>
37
- <p className="leading-normal text-muted-foreground">
38
- You can start a conversation here or try the following examples:
39
- </p>
40
- <div className="mt-4 flex flex-col items-start space-y-2">
41
- {exampleMessages.map((message, index) => (
42
- <Button
43
- key={index}
44
- variant="link"
45
- className="h-auto p-0 text-base"
46
- onClick={() => setInput(message.message)}
47
- >
48
- <IconArrowRight className="mr-2 text-muted-foreground" />
49
- {message.heading}
50
- </Button>
51
- ))}
52
- </div>
53
- </div>
54
- </div>
55
- )
56
-}
frontend/splitfire-desktop/app/_ui/components/icons.tsx
+1
-1
@@ -1,6 +1,6 @@
1
'use client'
2
3
-import { cn } from '@/app/_lib/utils'
3
+import { cn } from '@/lib/utils'
4
import * as React from 'react'
5
6
function IconNextChat({
frontend/splitfire-desktop/app/_ui/components/prompt-form.tsx
deleted
-99
@@ -1,99 +0,0 @@
1
-'use client';
2
-
3
-import * as React from 'react'
4
-import Textarea from 'react-textarea-autosize'
5
-import { UseChatHelpers } from 'ai/react'
6
-import {
7
- Tooltip,
8
- TooltipContent,
9
- TooltipTrigger
10
-} from './tooltip'
11
-import { IconArrowElbow, IconPlus } from './icons'
12
-import { useRouter } from 'next/navigation'
13
-import { Button, buttonVariants } from './button';
14
-import { useEnterSubmit } from '@/app/_lib/hooks/use-enter-submit';
15
-import { cn } from '@/app/_lib/utils';
16
-
17
-export interface PromptProps
18
- extends Pick<UseChatHelpers, 'input' | 'setInput'> {
19
- onSubmit: (value: string) => void
20
- isLoading: boolean
21
-}
22
-
23
-export function PromptForm({
24
- onSubmit,
25
- input,
26
- setInput,
27
- isLoading
28
-}: PromptProps) {
29
- const { formRef, onKeyDown } = useEnterSubmit()
30
- const inputRef = React.useRef<HTMLTextAreaElement>(null)
31
- const router = useRouter()
32
- React.useEffect(() => {
33
- if (inputRef.current) {
34
- inputRef.current.focus()
35
- }
36
- }, [])
37
-
38
- return (
39
- <form
40
- onSubmit={async e => {
41
- e.preventDefault()
42
- if (!input?.trim()) {
43
- return
44
- }
45
- setInput('')
46
- await onSubmit(input)
47
- }}
48
- ref={formRef}
49
- >
50
- <div className="relative flex flex-col w-full px-8 overflow-hidden max-h-60 grow bg-background sm:rounded-md sm:border sm:px-12">
51
- <Tooltip>
52
- <TooltipTrigger asChild>
53
- <button
54
- onClick={e => {
55
- e.preventDefault()
56
- router.refresh()
57
- router.push('/')
58
- }}
59
- className={cn(
60
- buttonVariants({ size: 'sm', variant: 'outline' }),
61
- 'absolute left-0 top-4 size-8 rounded-full bg-background p-0 sm:left-4'
62
- )}
63
- >
64
- <IconPlus />
65
- <span className="sr-only">New Chat</span>
66
- </button>
67
- </TooltipTrigger>
68
- <TooltipContent>New Chat</TooltipContent>
69
- </Tooltip>
70
- <Textarea
71
- ref={inputRef}
72
- tabIndex={0}
73
- onKeyDown={onKeyDown}
74
- rows={1}
75
- value={input}
76
- onChange={e => setInput(e.target.value)}
77
- placeholder="Send a message."
78
- spellCheck={false}
79
- className="min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.3rem] focus-within:outline-none sm:text-sm"
80
- />
81
- <div className="absolute right-0 top-4 sm:right-4">
82
- <Tooltip>
83
- <TooltipTrigger asChild>
84
- <Button
85
- type="submit"
86
- size="icon"
87
- disabled={isLoading || input === ''}
88
- >
89
- <IconArrowElbow />
90
- <span className="sr-only">Send message</span>
91
- </Button>
92
- </TooltipTrigger>
93
- <TooltipContent>Send message</TooltipContent>
94
- </Tooltip>
95
- </div>
96
- </div>
97
- </form>
98
- )
99
-}
frontend/splitfire-desktop/app/_ui/global-nav.tsx
+2
-1
@@ -1,7 +1,7 @@
1
'use client';
2
3
-import { menus, type Item } from '../_lib/menus';
3
import Link from 'next/link';
4
+import { menus, type Item } from './menus';
5
import { useSelectedLayoutSegment } from 'next/navigation';
6
import { MenuAlt2Icon, XIcon } from '@heroicons/react/solid';
7
import clsx from 'clsx';
@@ -10,6 +10,7 @@ import Image from 'next/image';
10
import { UserContext } from '../_src/lib/CurrentUserContext';
11
12
13
+
14
export function GlobalNav() {
15
16
const [isOpen, setIsOpen] = useState(false);
frontend/splitfire-desktop/app/_ui/menus.ts
renamed
+2
-2
@@ -12,8 +12,8 @@ export const menus: { items: Item[] }[] = [
12
slug: '',
13
},
14
{
15
- name: 'Play',
16
- slug: 'play',
15
+ name: 'Ready to Play!',
16
+ slug: 'ready-to-play',
17
},
18
],
19
},
frontend/splitfire-desktop/app/_ui/skeleton-card.tsx
+8
-1
@@ -20,11 +20,18 @@ export const SkeletonCard = ({ isLoading }: { isLoading?: boolean }) => (
20
</div>
21
);
22
23
+export enum SongProviderPath {
24
+ PLAY = "play",
25
+ SPLIT = "split",
26
+}
27
+
28
// duplicate skeleton-card.tsx
29
export const SongProviderCard = ({
30
songProvider,
31
+ path,
32
}: {
33
songProvider: SongProvider;
34
+ path: SongProviderPath;
35
}) => {
36
const router = useRouter();
37
return (
@@ -33,7 +40,7 @@ export const SongProviderCard = ({
40
"relative overflow-hidden before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_1.5s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/10 before:to-transparent":
41
false,
42
})}
36
- onClick={() => router.push(`/split?songProviderId=${songProvider.id}`)}
43
+ onClick={() => router.push(`/${path}?songProviderId=${songProvider.id}`)}
44
>
45
<div className="space-y-3">
46
<Image
frontend/splitfire-desktop/app/login/page.tsx
+2
-1
@@ -2,7 +2,7 @@
2
3
import * as Form from "@radix-ui/react-form";
4
import { invoke } from "@tauri-apps/api/tauri";
5
-import { TAURI_ACCOUNT_LOGIN, TauriResponse } from "../_src/lib/tauriHandler";
5
+import { TAURI_ACCOUNT_LOGIN } from "../_src/lib/tauriHandler";
6
import { Button } from "../_ui/components/button";
7
import { useState } from "react";
8
import { UserContext } from "../_src/lib/CurrentUserContext";
@@ -11,6 +11,7 @@ import { AccountLoginResponse } from "@/models/account";
11
import { Mode } from "../_src/components/player/models/Mode";
12
import { LoadingView } from "../_src/components/templates/LoadingView";
13
import { useRouter } from "next/navigation";
14
+import { TauriResponse } from "@/models/shared";
15
16
enum State {
17
LOADING,
frontend/splitfire-desktop/app/page.tsx
+2
-2
@@ -1,7 +1,7 @@
1
"use client";
2
3
import { useEffect, useState } from "react";
4
-import { SkeletonCard, SongProviderCard } from "./_ui/skeleton-card";
4
+import { SkeletonCard, SongProviderCard, SongProviderPath } from "./_ui/skeleton-card";
5
import { invoke } from "@tauri-apps/api";
6
import { TAURI_CONTENT_CAROUSEL } from "./_src/lib/tauriHandler";
7
import { ContentCarouselResponse } from "@/models/content";
@@ -39,7 +39,7 @@ export default function Page() {
39
<SkeletonCard key={i} isLoading={true} />
40
))}
41
{ songProviders.length > 0 && songProviders.map((SongProvider, i) => (
42
- <SongProviderCard key={i} songProvider={SongProvider} />
42
+ <SongProviderCard key={i} songProvider={SongProvider} path={SongProviderPath.SPLIT} />
43
))}
44
</div>
45
</div>
frontend/splitfire-desktop/app/play/_components/player.tsx
new
+10
@@ -0,0 +1,10 @@
1
+
2
+export default async function Page() {
3
+ return (
4
+ <div className="prose prose-sm prose-invert max-w-none">
5
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
6
+ Splitting file
7
+ </div>
8
+ </div>
9
+ );
10
+}
frontend/splitfire-desktop/app/play/layout.tsx
+1
-15
@@ -1,25 +1,11 @@
1
-import { Metadata } from 'next';
1
import React from 'react';
2
4
-export const metadata: Metadata = {
5
- title: "Play",
6
- description: "an intelligent exression engine.",
7
-};
8
-
9
-
3
export default async function Layout({
4
children,
5
}: {
6
children: React.ReactNode;
7
}) {
8
return (
16
- <div className="space-y-9">
17
- <div className="flex justify-between">
18
- <div className="self-start">
19
- <h1 className="text-3xl font-bold">Ready to play!</h1>
20
- </div>
21
- </div>
22
- <div>{children}</div>
23
- </div>
9
+ <div className="space-y-9">{children}</div>
10
);
11
}
frontend/splitfire-desktop/app/play/page.tsx
+62
-17
@@ -1,25 +1,70 @@
1
-import { SkeletonCard } from '../_ui/skeleton-card';
1
+"use client";
2
3
-export async function generateStaticParams() {
4
- const posts = [
5
- { slug: "post-1" },
6
- { slug: "post-2" },
7
- { slug: "post-3" },
8
- ];
9
-
10
- return posts.map((post) => ({
11
- slug: post.slug,
12
- }))
3
+import { invoke } from "@tauri-apps/api";
4
+import { useEffect, useState } from "react";
5
+import { TAURI_PLAYER_PREPARE } from "../_src/lib/tauriHandler";
6
+import { useSearchParams } from "next/navigation";
7
+import { useLogger } from "../_src/lib/logger";
8
+import { IconSpinner } from "../_ui/components/icons";
9
+import { PlayerPrepareResponse } from "@/models/content";
10
+import { TauriResponse } from "@/models/shared";
11
+
12
+enum State {
13
+ LOADING,
14
+ LOADED,
15
+ ERROR,
16
}
17
18
export default function Page() {
19
+ const log = useLogger("Play");
20
+ const searchParams = useSearchParams();
21
+ const songProviderId = searchParams.get("songProviderId");
22
+ const [title, setTitle] = useState("Loading song...");
23
+ const [state, setState] = useState(State.LOADING);
24
+
25
+ useEffect(() => {
26
+ log.debug("Play page loaded.");
27
+ async function fetchData() {
28
+ try {
29
+ const result: PlayerPrepareResponse = await invoke(
30
+ TAURI_PLAYER_PREPARE,
31
+ { providerId: songProviderId }
32
+ );
33
+ log.debug("PreparePlayerResponse", result);
34
+ switch (result.status) {
35
+ case TauriResponse.SUCCESS:
36
+ if (result.audio_file_name) setTitle(result.audio_file_name);
37
+
38
+ setState(State.LOADED);
39
+ break;
40
+ case TauriResponse.ERROR:
41
+ setState(State.ERROR);
42
+ break;
43
+ }
44
+ } catch (error) {
45
+ log.error(error);
46
+ setState(State.ERROR);
47
+ }
48
+ }
49
+ fetchData();
50
+ }, []);
51
return (
17
- <div className="prose prose-sm prose-invert max-w-none">
18
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
19
- {Array.from({ length: 6 }).map((_, i) => (
20
- <SkeletonCard key={i} />
21
- ))}
52
+ <>
53
+ <div className="flex justify-between">
54
+ <div className="self-start">
55
+ <h1 className="text-3xl font-bold">{title}</h1>
56
+ </div>
57
+ </div>
58
+ <div className="prose prose-sm prose-invert max-w-none">
59
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
60
+ {state === State.LOADING && (
61
+ <IconSpinner className="w-10 h-10 animate-spin" />
62
+ )}
63
+ {state === State.ERROR && (
64
+ <div className="text-red-500">Failed to load song</div>
65
+ )}
66
+ </div>
67
</div>
23
- </div>
68
+ </>
69
);
70
}
frontend/splitfire-desktop/app/ready-to-play/layout.tsx
new
+18
@@ -0,0 +1,18 @@
1
+import React from 'react';
2
+
3
+export default async function Layout({
4
+ children,
5
+}: {
6
+ children: React.ReactNode;
7
+}) {
8
+ return (
9
+ <div className="space-y-9">
10
+ <div className="flex justify-between">
11
+ <div className="self-start">
12
+ <h1 className="text-3xl font-bold">Ready to play!</h1>
13
+ </div>
14
+ </div>
15
+ <div>{children}</div>
16
+ </div>
17
+ );
18
+}
frontend/splitfire-desktop/app/ready-to-play/page.tsx
new
+42
@@ -0,0 +1,42 @@
1
+"use client";
2
+
3
+import { ContentCarouselResponse } from "@/models/content";
4
+import { invoke } from "@tauri-apps/api";
5
+import { useEffect, useState } from "react";
6
+import { TAURI_CONTENT_READY_TO_PLAY } from "../_src/lib/tauriHandler";
7
+import { SkeletonCard, SongProviderCard, SongProviderPath } from "../_ui/skeleton-card";
8
+import { SongProvider } from "../_src/models/SongResponse";
9
+
10
+export default function Page() {
11
+ const [songProviders, setSongProviders] = useState<SongProvider[]>([]);
12
+
13
+ useEffect(() => {
14
+ console.log("Discover page loaded");
15
+ async function fetchData() {
16
+ try {
17
+ const response = await invoke<ContentCarouselResponse>(
18
+ TAURI_CONTENT_READY_TO_PLAY
19
+ );
20
+ console.log("Data", response);
21
+ setSongProviders(response.audio_files);
22
+ } catch (error) {
23
+ console.error("Failed to fetch data", error);
24
+ }
25
+ }
26
+ fetchData();
27
+ }, []);
28
+ return (
29
+ <div className="prose prose-sm prose-invert max-w-none">
30
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
31
+ {songProviders.length === 0 &&
32
+ Array.from({ length: 6 }).map((_, i) => (
33
+ <SkeletonCard key={i} isLoading={true} />
34
+ ))}
35
+ {songProviders.length > 0 &&
36
+ songProviders.map((SongProvider, i) => (
37
+ <SongProviderCard key={i} songProvider={SongProvider} path={SongProviderPath.PLAY} />
38
+ ))}
39
+ </div>
40
+ </div>
41
+ );
42
+}
frontend/splitfire-desktop/models/account.ts
+1
-1
@@ -1,5 +1,5 @@
1
-import { TauriResponse } from "@/app/_src/lib/tauriHandler";
1
import User from "@/app/_src/models/user";
2
+import { TauriResponse } from "./shared";
3
4
export interface AccountLoginResponse {
5
status: TauriResponse,
frontend/splitfire-desktop/models/content.ts
+8
-1
@@ -1,5 +1,5 @@
1
-import { TauriResponse } from "@/app/_src/lib/tauriHandler";
1
import { SongProvider } from "@/app/_src/models/SongResponse";
2
+import { TauriResponse } from "./shared";
3
4
export interface ContentCarouselResponse {
5
status: TauriResponse,
@@ -10,4 +10,11 @@ export interface ContentCarouselResponse {
10
export interface AccountRegisterResponse {
11
status: TauriResponse,
12
message: string,
13
+}
14
+
15
+// Response from the Tauri API
16
+export interface PlayerPrepareResponse {
17
+ status: TauriResponse,
18
+ message: string,
19
+ audio_file_name?: string,
20
}
\ No newline at end of file
frontend/splitfire-desktop/models/shared.ts
new
+4
@@ -0,0 +1,4 @@
1
+export enum TauriResponse {
2
+ ERROR = 0,
3
+ SUCCESS = 1
4
+}
\ No newline at end of file
frontend/splitfire-desktop/src-tauri/src/rest/content.rs
+19
-7
@@ -46,7 +46,7 @@ pub async fn content_carousel() -> ContentCarouselResponse {
46
}
47
48
#[tauri::command]
49
-pub async fn content_ready_to_play() -> Result<(), String> {
49
+pub async fn content_ready_to_play() -> ContentCarouselResponse {
50
let response = Client::new()
51
.get(content_url_builder(PATH_READY_TO_PLAY))
52
.send()
@@ -55,20 +55,32 @@ pub async fn content_ready_to_play() -> Result<(), String> {
55
let response = match response {
56
Ok(response) => response,
57
Err(e) => {
58
- println!("Failed to get response: {:?}", e);
59
- return Err("Failed to get response".to_string());
58
+ debug!("Failed to get response: {:?}", e);
59
+ return ContentCarouselResponse {
60
+ status: TauriResponse::Error,
61
+ message: e.to_string(),
62
+ audio_files: vec![],
63
+ };
64
}
65
};
66
let res: CarouselResponse = match response.json().await {
67
Ok(json) => json,
68
Err(e) => {
65
- println!("Failed to parse response: {:?}", e);
66
- return Err("Failed to parse response".to_string());
69
+ debug!("Failed to parse response: {:?}", e);
70
+ return ContentCarouselResponse {
71
+ status: TauriResponse::Error,
72
+ message: e.to_string(),
73
+ audio_files: vec![],
74
+ };
75
}
76
};
77
70
- println!("Ready to play: {:?}", res);
71
- Ok(())
78
+ debug!("Ready to play: {:?}", res);
79
+ ContentCarouselResponse {
80
+ status: TauriResponse::Success,
81
+ message: res.message,
82
+ audio_files: res.audio_files,
83
+ }
84
}
85
86
fn content_url_builder(path: &str) -> String {