diff --git a/front/apps/mobile/app/(app)/(tabs)/_layout.tsx b/front/apps/mobile/app/(app)/(tabs)/_layout.tsx
index 641fdf67..814bb0aa 100644
--- a/front/apps/mobile/app/(app)/(tabs)/_layout.tsx
+++ b/front/apps/mobile/app/(app)/(tabs)/_layout.tsx
@@ -22,6 +22,7 @@ import { Icon } from "@kyoo/primitives";
import { Tabs } from "expo-router";
import Home from "@material-symbols/svg-400/rounded/home-fill.svg";
import Browse from "@material-symbols/svg-400/rounded/browse-fill.svg";
+import Downloading from "@material-symbols/svg-400/rounded/downloading-fill.svg";
export default function TabsLayout() {
return (
@@ -44,6 +45,13 @@ export default function TabsLayout() {
tabBarIcon: ({ color, size }) => ,
}}
/>
+ ,
+ }}
+ />
);
}
diff --git a/front/apps/mobile/app/(app)/(tabs)/downloads.tsx b/front/apps/mobile/app/(app)/(tabs)/downloads.tsx
new file mode 100644
index 00000000..dfb44d79
--- /dev/null
+++ b/front/apps/mobile/app/(app)/(tabs)/downloads.tsx
@@ -0,0 +1,23 @@
+/*
+ * Kyoo - A portable and vast media library solution.
+ * Copyright (c) Kyoo.
+ *
+ * See AUTHORS.md and LICENSE file in the project root for full license information.
+ *
+ * Kyoo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * Kyoo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kyoo. If not, see .
+ */
+
+import { DownloadPage } from "@kyoo/ui";
+
+export default DownloadPage;
diff --git a/front/apps/mobile/app/_layout.tsx b/front/apps/mobile/app/_layout.tsx
index 29a177d9..bb140bc5 100644
--- a/front/apps/mobile/app/_layout.tsx
+++ b/front/apps/mobile/app/_layout.tsx
@@ -48,6 +48,7 @@ import "@formatjs/intl-displaynames/locale-data/fr";
import en from "../../../translations/en.json";
import fr from "../../../translations/fr.json";
import { useTheme } from "yoshiki/native";
+import { DownloadProvider } from "@kyoo/ui";
i18next.use(initReactI18next).init({
interpolation: {
@@ -103,9 +104,11 @@ export default function Root() {
>
-
-
-
+
+
+
+
+
diff --git a/front/packages/primitives/src/text.tsx b/front/packages/primitives/src/text.tsx
index ee339f82..405e795b 100644
--- a/front/packages/primitives/src/text.tsx
+++ b/front/packages/primitives/src/text.tsx
@@ -52,6 +52,7 @@ const styleText = (
{
marginVertical: rem(0.5),
color: type === "header" ? theme.heading : theme.paragraph,
+ flexShrink: 1,
fontSize: rem(1),
fontFamily: theme.font.normal,
},
diff --git a/front/packages/ui/src/components/context-menus.tsx b/front/packages/ui/src/components/context-menus.tsx
index 8eaab777..1aef55e5 100644
--- a/front/packages/ui/src/components/context-menus.tsx
+++ b/front/packages/ui/src/components/context-menus.tsx
@@ -27,7 +27,7 @@ import Download from "@material-symbols/svg-400/rounded/download.svg";
import { WatchStatusV, queryFn, useAccount } from "@kyoo/models";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { watchListIcon } from "./watchlist-info";
-import { downloadFile } from "../downloads/download";
+import { downloadFile } from "../downloads/state";
export const EpisodesContext = ({
type = "episode",
diff --git a/front/packages/ui/src/downloads/index.tsx b/front/packages/ui/src/downloads/index.tsx
new file mode 100644
index 00000000..39485cc1
--- /dev/null
+++ b/front/packages/ui/src/downloads/index.tsx
@@ -0,0 +1,22 @@
+/*
+ * Kyoo - A portable and vast media library solution.
+ * Copyright (c) Kyoo.
+ *
+ * See AUTHORS.md and LICENSE file in the project root for full license information.
+ *
+ * Kyoo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * Kyoo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kyoo. If not, see .
+ */
+
+export { DownloadPage } from "./page";
+export { DownloadProvider } from "./state";
diff --git a/front/packages/ui/src/downloads/page.tsx b/front/packages/ui/src/downloads/page.tsx
new file mode 100644
index 00000000..8cd2a6cc
--- /dev/null
+++ b/front/packages/ui/src/downloads/page.tsx
@@ -0,0 +1,39 @@
+/*
+ * Kyoo - A portable and vast media library solution.
+ * Copyright (c) Kyoo.
+ *
+ * See AUTHORS.md and LICENSE file in the project root for full license information.
+ *
+ * Kyoo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * Kyoo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kyoo. If not, see .
+ */
+
+import { useAtomValue } from "jotai";
+import { downloadAtom } from "./state";
+import { FlashList } from "@shopify/flash-list";
+import { View } from "react-native";
+
+export const DownloadPage = () => {
+ const downloads = useAtomValue(downloadAtom);
+
+ return (
+ {
+ {item.data.name};
+ }}
+ keyExtractor={(x) => x.data.id}
+ numColumns={1}
+ />
+ );
+};
diff --git a/front/packages/ui/src/downloads/download.tsx b/front/packages/ui/src/downloads/state.tsx
similarity index 91%
rename from front/packages/ui/src/downloads/download.tsx
rename to front/packages/ui/src/downloads/state.tsx
index 1b24e2ad..f7641769 100644
--- a/front/packages/ui/src/downloads/download.tsx
+++ b/front/packages/ui/src/downloads/state.tsx
@@ -18,13 +18,8 @@
* along with Kyoo. If not, see .
*/
-import {
- download,
- completeHandler,
- directories,
- DownloadTask,
- checkForExistingDownloads,
- ensureDownloadsAreRunning,
+import RNBackgroundDownloader, {
+ type DownloadTask,
} from "@kesha-antonov/react-native-background-downloader";
import { deleteAsync } from "expo-file-system";
import {
@@ -39,7 +34,7 @@ import {
import { Player } from "../player";
import { atom, useSetAtom, PrimitiveAtom, useStore } from "jotai";
import { getCurrentAccount, storage } from "@kyoo/models/src/account-internal";
-import { useEffect } from "react";
+import { ReactNode, useEffect } from "react";
type State = {
status: "DOWNLOADING" | "PAUSED" | "DONE" | "FAILED" | "STOPPED";
@@ -53,7 +48,7 @@ type State = {
play: () => void;
};
-const downloadAtom = atom<
+export const downloadAtom = atom<
{
data: Episode | Movie;
info: WatchInfo;
@@ -116,7 +111,7 @@ const setupDownloadTask = (
update((x) => ({ ...x, percent: 100, status: "DONE" }));
// apparently this is needed for ios /shrug i'm totaly gona forget this
// if i ever implement ios so keeping this here
- completeHandler(task.id);
+ RNBackgroundDownloader.completeHandler(task.id);
})
.error((error) => update((x) => ({ ...x, status: "FAILED", error })));
@@ -158,8 +153,8 @@ export const useDownloader = () => {
]);
// TODO: support custom paths
- const path = `${directories.documents}/${slug}-${data.id}.${info.extension}`;
- const task = download({
+ const path = `${RNBackgroundDownloader.directories.documents}/${slug}-${data.id}.${info.extension}`;
+ const task = RNBackgroundDownloader.download({
id: data.id,
// TODO: support variant qualities
url: `${account.apiUrl}/api/video/${type}/${slug}/direct`,
@@ -175,14 +170,14 @@ export const useDownloader = () => {
};
};
-export const DownloadProvider = () => {
+export const DownloadProvider = ({ children }: { children: ReactNode }) => {
const store = useStore();
useEffect(() => {
async function run() {
if (store.get(downloadAtom).length) return;
- const tasks = await checkForExistingDownloads();
+ const tasks = await RNBackgroundDownloader.checkForExistingDownloads();
const dls: { data: Episode | Movie; info: WatchInfo; path: string; state: State }[] =
JSON.parse(storage.getString("downloads") ?? "[]");
const downloads = dls.map((dl) => {
@@ -214,8 +209,10 @@ export const DownloadProvider = () => {
for (const t of tasks) {
if (!downloads.find((x) => x.data.id === t.id)) t.stop();
}
- ensureDownloadsAreRunning();
+ RNBackgroundDownloader.ensureDownloadsAreRunning();
}
run();
}, [store]);
+
+ return children;
};
diff --git a/front/packages/ui/src/downloads/download.web.tsx b/front/packages/ui/src/downloads/state.web.tsx
similarity index 100%
rename from front/packages/ui/src/downloads/download.web.tsx
rename to front/packages/ui/src/downloads/state.web.tsx
diff --git a/front/packages/ui/src/index.ts b/front/packages/ui/src/index.ts
index 91a77a6e..f4053f5f 100644
--- a/front/packages/ui/src/index.ts
+++ b/front/packages/ui/src/index.ts
@@ -26,3 +26,4 @@ export { CollectionPage } from "./collection";
export { Player } from "./player";
export { SearchPage } from "./search";
export { LoginPage, RegisterPage } from "./login";
+export { DownloadPage, DownloadProvider } from "./downloads";