diff --git a/front/packages/models/src/index.ts b/front/packages/models/src/index.ts
index 16f6aaba..759ce88a 100644
--- a/front/packages/models/src/index.ts
+++ b/front/packages/models/src/index.ts
@@ -27,5 +27,6 @@ export * from "./page";
export * from "./kyoo-errors";
export * from "./utils";
export * from "./login";
+export * from "./issue";
export * from "./query";
diff --git a/front/packages/models/src/issue.ts b/front/packages/models/src/issue.ts
new file mode 100644
index 00000000..c519db97
--- /dev/null
+++ b/front/packages/models/src/issue.ts
@@ -0,0 +1,48 @@
+/*
+ * 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 { z } from "zod";
+import { zdate } from "./utils";
+
+export const IssueP = z.object({
+ /**
+ * The type of issue (for example, "Scanner" if this issue was created due to scanning error).
+ */
+ domain: z.string(),
+ /**
+ * Why this issue was caused? An unique cause that can be used to identify this issue.
+ * For the scanner, a cause should be a video path.
+ */
+ cause: z.string(),
+ /**
+ * A human readable string explaining why this issue occured.
+ */
+ reason: z.string(),
+ /**
+ * Some extra data that could store domain-specific info.
+ */
+ extra: z.record(z.string(), z.any()),
+ /**
+ * The date the issue was reported.
+ */
+ addedDate: zdate(),
+});
+
+export type Issue = z.infer;
diff --git a/front/packages/ui/src/admin/index.tsx b/front/packages/ui/src/admin/index.tsx
index 73ff5498..ef5769b8 100644
--- a/front/packages/ui/src/admin/index.tsx
+++ b/front/packages/ui/src/admin/index.tsx
@@ -23,11 +23,13 @@ import { ts } from "@kyoo/primitives";
import { ScrollView } from "react-native";
import { DefaultLayout } from "../layout";
import { UserList } from "./users";
+import { Scanner } from "./scanner";
export const AdminPage: QueryPage = () => {
return (
+
);
};
diff --git a/front/packages/ui/src/admin/scanner.tsx b/front/packages/ui/src/admin/scanner.tsx
new file mode 100644
index 00000000..59d0af30
--- /dev/null
+++ b/front/packages/ui/src/admin/scanner.tsx
@@ -0,0 +1,77 @@
+/*
+ * 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 { Issue, IssueP, QueryIdentifier, useFetch } from "@kyoo/models";
+import { useTranslation } from "react-i18next";
+import { SettingsContainer } from "../settings/base";
+import { Icon, P, Skeleton, tooltip, ts } from "@kyoo/primitives";
+import { ErrorView } from "../errors";
+import { z } from "zod";
+import { View } from "react-native";
+import { useYoshiki } from "yoshiki/native";
+
+import Info from "@material-symbols/svg-400/outlined/info.svg";
+
+export const Scanner = () => {
+ const { css } = useYoshiki();
+ const { t } = useTranslation();
+ const { data, error } = useFetch(Scanner.query());
+
+ return (
+
+ <>
+ {error != null ? (
+
+ ) : (
+ (data ?? [...Array(3)])?.map((x, i) => (
+
+
+
+ {x &&