diff --git a/src/components/layout/ThinContainer.tsx b/src/components/layout/ThinContainer.tsx
index 9f06f579..0076892f 100644
--- a/src/components/layout/ThinContainer.tsx
+++ b/src/components/layout/ThinContainer.tsx
@@ -18,6 +18,18 @@ export function ThinContainer(props: ThinContainerProps) {
);
}
+export function ThiccContainer(props: ThinContainerProps) {
+ return (
+
void;
+ children: React.ReactNode;
+ disabled?: boolean;
+}) {
+ return (
+
+ );
+}
+
+function ConfigValue(props: { name: string; children?: ReactNode }) {
+ return (
+ <>
+
+
{props.name}
+
{props.children}
+
+
+ >
+ );
+}
+
+async function getRecentPlayedItems() {
+ const response = await fetch("https://backend.sudo-flix.lol/metrics");
+ const text = await response.text();
+
+ const regex =
+ /mw_media_watch_count{tmdb_full_id="([^"]+)",provider_id="([^"]+)",title="([^"]+)",success="([^"]+)"} (\d+)/g;
+ let match;
+ const loop = true;
+ const items: { [key: string]: any } = {};
+
+ while (loop) {
+ match = regex.exec(text);
+ if (match === null) break;
+
+ const [_, tmdbFullId, providerId, title, success, count] = match;
+ if (items[tmdbFullId]) {
+ items[tmdbFullId].count += parseInt(count, 10);
+ } else {
+ items[tmdbFullId] = {
+ tmdbFullId,
+ providerId,
+ title,
+ success: success === "true",
+ count: parseInt(count, 10),
+ };
+ }
+ }
+
+ if (Object.keys(items).length > 0) {
+ return Object.values(items);
+ }
+ throw new Error("RECENT_PLAYED_ITEMS not found");
+}
+
+export function TopFlix() {
+ const [recentPlayedItems, setRecentPlayedItems] = useState
([]);
+ const [loading, setLoading] = useState(true);
+ const [currentPage, setCurrentPage] = useState(1);
+ const { t } = useTranslation();
+ const itemsPerPage = 10;
+
+ useEffect(() => {
+ getRecentPlayedItems()
+ .then((items) => {
+ const uniqueItems = items.filter(
+ (item, index, self) =>
+ index === self.findIndex((t2) => t2.tmdbFullId === item.tmdbFullId),
+ );
+
+ setRecentPlayedItems(uniqueItems);
+ })
+ .catch((error) => {
+ console.error("Error fetching recent played items:", error);
+ })
+ .finally(() => {
+ setLoading(false);
+ });
+ }, []);
+
+ function getItemsForCurrentPage() {
+ const sortedItems = recentPlayedItems.sort((a, b) => b.count - a.count);
+ const startIndex = (currentPage - 1) * itemsPerPage;
+ const endIndex = startIndex + itemsPerPage;
+ return sortedItems.slice(startIndex, endIndex);
+ }
+
+ if (loading) {
+ return (
+ Loading...
+ );
+ }
+
+ return (
+
+
+ Top flix
+
+ The most popular movies on sudo-flix.lol, this data is fetched from
+ the current backend deployment.
+
+
+
+
+ {getItemsForCurrentPage().map((item) => {
+ const successText = item.success ? "Yes" : "No"; // Convert bool to "Yes" or "No"
+ const coverUrl = getMediaPoster(item.tmdbFullId);
+ return (
+
+ {`${item.providerId} - Provided: ${successText}, Views: ${item.count}`}
+
+
+ );
+ })}
+
+
+
+ Page {currentPage} of{" "}
+ {Math.ceil(recentPlayedItems.length / itemsPerPage)}
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/admin/AdminPage.tsx b/src/pages/admin/AdminPage.tsx
index 6a9a7f1f..edebacc5 100644
--- a/src/pages/admin/AdminPage.tsx
+++ b/src/pages/admin/AdminPage.tsx
@@ -1,10 +1,4 @@
-import classNames from "classnames";
-import { ReactNode, useEffect, useState } from "react";
-import { useTranslation } from "react-i18next";
-
-import { Icon, Icons } from "@/components/Icon";
import { ThinContainer } from "@/components/layout/ThinContainer";
-import { Divider } from "@/components/utils/Divider";
import { Heading1, Heading2, Paragraph } from "@/components/utils/Text";
import { SubPageLayout } from "@/pages/layouts/SubPageLayout";
import { ConfigValuesPart } from "@/pages/parts/admin/ConfigValuesPart";
@@ -13,109 +7,7 @@ import { WorkerTestPart } from "@/pages/parts/admin/WorkerTestPart";
import { BackendTestPart } from "../parts/admin/BackendTestPart";
-function Button(props: {
- className: string;
- onClick?: () => void;
- children: React.ReactNode;
- disabled?: boolean;
-}) {
- return (
-
- );
-}
-
-function ConfigValue(props: { name: string; children?: ReactNode }) {
- return (
- <>
-
-
{props.name}
-
{props.children}
-
-
- >
- );
-}
-
-async function getRecentPlayedItems() {
- const response = await fetch("https://backend.sudo-flix.lol/metrics");
- const text = await response.text();
-
- const regex =
- /mw_media_watch_count{tmdb_full_id="([^"]+)",provider_id="([^"]+)",title="([^"]+)",success="([^"]+)"} (\d+)/g;
- let match;
- const loop = true;
- const items: { [key: string]: any } = {};
-
- while (loop) {
- match = regex.exec(text);
- if (match === null) break;
-
- const [_, tmdbFullId, providerId, title, success, count] = match;
- if (items[tmdbFullId]) {
- items[tmdbFullId].count += parseInt(count, 10);
- } else {
- items[tmdbFullId] = {
- tmdbFullId,
- providerId,
- title,
- success: success === "true",
- count: parseInt(count, 10),
- };
- }
- }
-
- if (Object.keys(items).length > 0) {
- return Object.values(items);
- }
- throw new Error("RECENT_PLAYED_ITEMS not found");
-}
-
export function AdminPage() {
- const [recentPlayedItems, setRecentPlayedItems] = useState([]);
- const [loading, setLoading] = useState(true);
- const [currentPage, setCurrentPage] = useState(1);
- const { t } = useTranslation();
- const itemsPerPage = 10;
-
- useEffect(() => {
- getRecentPlayedItems()
- .then((items) => {
- const uniqueItems = items.filter(
- (item, index, self) =>
- index === self.findIndex((t2) => t2.tmdbFullId === item.tmdbFullId),
- );
-
- setRecentPlayedItems(uniqueItems);
- })
- .catch((error) => {
- console.error("Error fetching recent played items:", error);
- })
- .finally(() => {
- setLoading(false);
- });
- }, []);
-
- function getItemsForCurrentPage() {
- const sortedItems = recentPlayedItems.sort((a, b) => b.count - a.count);
- const startIndex = (currentPage - 1) * itemsPerPage;
- const endIndex = startIndex + itemsPerPage;
- return sortedItems.slice(startIndex, endIndex);
- }
-
- if (loading) {
- return Loading...
;
- }
-
return (
@@ -126,43 +18,6 @@ export function AdminPage() {
-
-
Recently Played List
-
- This data is fetched from the current backend deployment.
-
- {getItemsForCurrentPage().map((item) => {
- const successText = item.success ? "Yes" : "No"; // Convert bool to "Yes" or "No"
- return (
-
- {`${item.providerId} - Provided: ${successText}, Views: ${item.count}`}
-
- );
- })}
-
-
-
- Page {currentPage} of{" "}
- {Math.ceil(recentPlayedItems.length / itemsPerPage)}
-
-
-
-
);
diff --git a/src/setup/App.tsx b/src/setup/App.tsx
index a2440ef8..9d54fbd7 100644
--- a/src/setup/App.tsx
+++ b/src/setup/App.tsx
@@ -25,6 +25,7 @@ import { OnboardingExtensionPage } from "@/pages/onboarding/OnboardingExtension"
import { OnboardingProxyPage } from "@/pages/onboarding/OnboardingProxy";
import { RegisterPage } from "@/pages/Register";
import { SupportPage } from "@/pages/Support";
+import { TopFlix } from "@/pages/TopFlix";
import { Layout } from "@/setup/Layout";
import { useHistoryListener } from "@/stores/history";
import { LanguageProvider } from "@/stores/language";
@@ -149,6 +150,8 @@ function App() {
) : null}
{/* Support page */}
} />
+ {/* Top flix page */}
+ } />
{/* Settings page */}