diff --git a/OwnTube.tv/app/(home)/index.tsx b/OwnTube.tv/app/(home)/index.tsx
index c9bde11..85ada03 100644
--- a/OwnTube.tv/app/(home)/index.tsx
+++ b/OwnTube.tv/app/(home)/index.tsx
@@ -1,13 +1,13 @@
import { Link, useFocusEffect, useLocalSearchParams, useNavigation, useRouter } from "expo-router";
import { ROUTES, SOURCES, STORAGE } from "../../types";
import { readFromAsyncStorage, writeToAsyncStorage } from "../../utils";
-import { Loader } from "../../components";
+import { DeviceCapabilitiesModal, Loader } from "../../components";
import { useCallback, useState } from "react";
import Head from "expo-router/head";
import { HomeScreen } from "../../screens";
import { Feather } from "@expo/vector-icons";
import { useTheme } from "@react-navigation/native";
-import { StyleSheet } from "react-native";
+import { StyleSheet, View } from "react-native";
export default function index() {
const router = useRouter();
@@ -38,9 +38,12 @@ export default function index() {
navigation.setOptions({
title: `OwnTube.tv@${backend}`,
headerRight: () => (
-
-
-
+
+
+
+
+
+
),
});
}
@@ -68,4 +71,5 @@ const styles = StyleSheet.create({
headerButton: {
paddingHorizontal: 11,
},
+ headerControls: { alignItems: "center", flexDirection: "row", paddingRight: 11 },
});
diff --git a/OwnTube.tv/components/BuildInfoToast.tsx b/OwnTube.tv/components/BuildInfoToast.tsx
index d9859ac..c76ad8d 100644
--- a/OwnTube.tv/components/BuildInfoToast.tsx
+++ b/OwnTube.tv/components/BuildInfoToast.tsx
@@ -2,6 +2,7 @@ import { Linking, StyleSheet, View } from "react-native";
import { Typography } from "./Typography";
import build_info from "../build-info.json";
import { useTheme } from "@react-navigation/native";
+import { removeSecondsFromISODate } from "../utils";
export const BuildInfoToast = () => {
const { colors } = useTheme();
@@ -13,7 +14,7 @@ export const BuildInfoToast = () => {
Linking.openURL(build_info.COMMIT_URL)}>
{build_info.GITHUB_SHA_SHORT}
{" "}
- built at {`${build_info.BUILD_TIMESTAMP.slice(0, build_info.BUILD_TIMESTAMP.lastIndexOf(":"))}Z`} by{" "}
+ built at {removeSecondsFromISODate(build_info.BUILD_TIMESTAMP)} by{" "}
{
+ const { deviceCapabilities } = useAppConfigContext();
+ const { colors } = useTheme();
+
+ const handleCopyToClipboard = async () => {
+ await Clipboard.setStringAsync(JSON.stringify(deviceCapabilities));
+ };
+
+ return (
+
+
+ Device Capability info:
+
+
+
+
+
+
+ Player implementation:
+ {deviceCapabilities.playerImplementation}
+
+
+ Device type:
+ {deviceCapabilities.deviceType}
+
+
+ Operating system:
+ {deviceCapabilities.OS}
+
+ {deviceCapabilities.browser && (
+
+ Browser:
+ {deviceCapabilities.browser}
+
+ )}
+ {deviceCapabilities.device && (
+
+ Device:
+ {deviceCapabilities.device}
+
+ )}
+
+ Screen dimensions:
+ {deviceCapabilities.dimensions}
+
+
+ Orientation:
+ {deviceCapabilities.orientation}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ modalContainer: { borderRadius: 8, minWidth: "50%", padding: 16 },
+ modalHeader: { flexDirection: "row", gap: 16, justifyContent: "space-between" },
+ row: { flexWrap: "wrap", justifyContent: "space-between", marginVertical: 8, width: "100%" },
+});
diff --git a/OwnTube.tv/components/DeviceCapabilitiesModal.tsx b/OwnTube.tv/components/DeviceCapabilitiesModal.tsx
index 1030a8b..dc794e8 100644
--- a/OwnTube.tv/components/DeviceCapabilitiesModal.tsx
+++ b/OwnTube.tv/components/DeviceCapabilitiesModal.tsx
@@ -1,12 +1,9 @@
import { Ionicons } from "@expo/vector-icons";
import { useTheme } from "@react-navigation/native";
-import { Modal, Pressable, StyleSheet, View } from "react-native";
+import { Modal, Pressable, StyleSheet } from "react-native";
import { useState } from "react";
-import { Typography } from "./Typography";
-import { useAppConfigContext } from "../contexts";
-import { Spacer } from "./shared/Spacer";
-import * as Clipboard from "expo-clipboard";
import { colors } from "../colors";
+import { DeviceCapabilities } from "./DeviceCapabilities";
export const DeviceCapabilitiesModal = () => {
const { colors } = useTheme();
@@ -14,7 +11,6 @@ export const DeviceCapabilitiesModal = () => {
const toggleModal = () => {
setModalVisible((prevState) => !prevState);
};
- const { deviceCapabilities } = useAppConfigContext();
return (
<>
@@ -23,47 +19,7 @@ export const DeviceCapabilitiesModal = () => {
-
-
- Device Capability info:
- Clipboard.setStringAsync(JSON.stringify(deviceCapabilities))}>
-
-
-
-
-
- Player implementation:
- {deviceCapabilities.playerImplementation}
-
-
- Device type:
- {deviceCapabilities.deviceType}
-
-
- Operating system:
- {deviceCapabilities.OS}
-
- {deviceCapabilities.browser && (
-
- Browser:
- {deviceCapabilities.browser}
-
- )}
- {deviceCapabilities.device && (
-
- Device:
- {deviceCapabilities.device}
-
- )}
-
- Screen dimensions:
- {deviceCapabilities.dimensions}
-
-
- Orientation:
- {deviceCapabilities.orientation}
-
-
+
>
@@ -72,9 +28,6 @@ export const DeviceCapabilitiesModal = () => {
const styles = StyleSheet.create({
modal: { height: "100%" },
- modalContainer: { borderRadius: 8, minWidth: "50%", padding: 16 },
- modalHeader: { flexDirection: "row", gap: 16, justifyContent: "space-between" },
- row: { flexWrap: "wrap", justifyContent: "space-between", marginVertical: 8, width: "100%" },
showModalBtn: {
alignItems: "center",
backgroundColor: colors._50percentBlackTint,
diff --git a/OwnTube.tv/components/VideoView/VideoView.tsx b/OwnTube.tv/components/VideoView/VideoView.tsx
index a70c78f..a0a9b28 100644
--- a/OwnTube.tv/components/VideoView/VideoView.tsx
+++ b/OwnTube.tv/components/VideoView/VideoView.tsx
@@ -29,9 +29,10 @@ const VideoView = ({ uri, testID, handleSetTimeStamp, timestamp }: VideoViewProp
const handlePlaybackStatusUpdate = (status: AVPlaybackStatus) => {
if (status?.isLoaded) {
setPlaybackStatus(status);
- setPlayerImplementation(
- status.androidImplementation ? `Android ${status.androidImplementation}` : "iOS Native player",
- );
+
+ if (status.androidImplementation) {
+ setPlayerImplementation(`Android ${status.androidImplementation}`);
+ }
} else if (status?.error) {
console.error(status.error);
}
diff --git a/OwnTube.tv/components/VideoView/VideoView.web.tsx b/OwnTube.tv/components/VideoView/VideoView.web.tsx
index 0f5954d..d41c336 100644
--- a/OwnTube.tv/components/VideoView/VideoView.web.tsx
+++ b/OwnTube.tv/components/VideoView/VideoView.web.tsx
@@ -6,7 +6,6 @@ import { VideoViewProps } from "./VideoView";
import { styles } from "./styles";
import "./styles.web.css";
import videojs from "video.js";
-import { useAppConfigContext } from "../../contexts";
declare const window: {
videojs: typeof videojs;
@@ -25,7 +24,6 @@ const VideoView = ({ uri, testID, handleSetTimeStamp, timestamp }: VideoViewProp
duration: 1,
playableDuration: 0,
});
- const { setPlayerImplementation } = useAppConfigContext();
const updatePlaybackStatus = (updatedStatus: Partial) => {
setPlaybackStatus((prev) => ({ ...prev, ...updatedStatus }));
@@ -114,7 +112,6 @@ const VideoView = ({ uri, testID, handleSetTimeStamp, timestamp }: VideoViewProp
useEffect(() => {
if (!videojs) return;
- setPlayerImplementation("Web video.js");
if (!playerRef.current) {
const videoElement = document.createElement("video-js");
diff --git a/OwnTube.tv/components/index.ts b/OwnTube.tv/components/index.ts
index 1c678b1..8a5a20b 100644
--- a/OwnTube.tv/components/index.ts
+++ b/OwnTube.tv/components/index.ts
@@ -9,6 +9,8 @@ export * from "./VideoView/VideoView";
export * from "./VideoControlsOverlay";
export * from "./Loader";
export * from "./DeviceCapabilitiesModal";
+export * from "./DeviceCapabilities";
export * from "./BuildInfoToast";
export * from "./ClickableHeaderText";
export * from "./ResumeWatching";
+export * from "./ViewHistory";
diff --git a/OwnTube.tv/hooks/useDeviceCapabilities.ts b/OwnTube.tv/hooks/useDeviceCapabilities.ts
index 8113f35..b9ae1aa 100644
--- a/OwnTube.tv/hooks/useDeviceCapabilities.ts
+++ b/OwnTube.tv/hooks/useDeviceCapabilities.ts
@@ -3,6 +3,7 @@ import * as Device from "expo-device";
import { DeviceType } from "expo-device";
import { Platform, useWindowDimensions } from "react-native";
import UAParser from "ua-parser-js";
+import { capitalize } from "../utils";
export interface DeviceCapabilities {
playerImplementation: string;
@@ -15,7 +16,12 @@ export interface DeviceCapabilities {
}
export const useDeviceCapabilities = () => {
- const [playerImplementation, setPlayerImplementation] = useState("");
+ const [playerImplementation, setPlayerImplementation] = useState(
+ Platform.select({
+ web: "Web video.js",
+ default: capitalize(Platform.OS),
+ }),
+ );
const { height, width } = useWindowDimensions();
const getBrowserInfo = () => {
diff --git a/OwnTube.tv/screens/SettingsScreen/index.tsx b/OwnTube.tv/screens/SettingsScreen/index.tsx
index 25d3f89..1f51ecd 100644
--- a/OwnTube.tv/screens/SettingsScreen/index.tsx
+++ b/OwnTube.tv/screens/SettingsScreen/index.tsx
@@ -1,10 +1,9 @@
import { View, Switch } from "react-native";
-import { SourceSelect, Typography } from "../../components";
+import { SourceSelect, Typography, ViewHistory, DeviceCapabilities } from "../../components";
import { useAppConfigContext, useColorSchemeContext } from "../../contexts";
import { Screen } from "../../layouts";
import { styles } from "./styles";
import { useTheme } from "@react-navigation/native";
-import { ViewHistory } from "../../components/ViewHistory";
export const SettingsScreen = () => {
const { isDebugMode, setIsDebugMode } = useAppConfigContext();
@@ -13,15 +12,20 @@ export const SettingsScreen = () => {
return (
-
- Debug logging
-
+
+
+
+
+ Debug logging
+
+
+
+ Toggle Theme
+
+
+
+
-
- Toggle Theme
-
-
-
);
diff --git a/OwnTube.tv/screens/SettingsScreen/styles.ts b/OwnTube.tv/screens/SettingsScreen/styles.ts
index 87e9681..64eb414 100644
--- a/OwnTube.tv/screens/SettingsScreen/styles.ts
+++ b/OwnTube.tv/screens/SettingsScreen/styles.ts
@@ -6,8 +6,11 @@ export const styles = StyleSheet.create({
gap: 10,
padding: 20,
},
+ deviceInfoAndToggles: { flexDirection: "row", flexWrap: "wrap", gap: 16, width: "100%" },
option: {
+ alignItems: "center",
flexDirection: "row",
gap: 5,
},
+ togglesContainer: { flex: 1, minWidth: 200 },
});
diff --git a/OwnTube.tv/utils/common.test.tsx b/OwnTube.tv/utils/common.test.tsx
new file mode 100644
index 0000000..bafd5dd
--- /dev/null
+++ b/OwnTube.tv/utils/common.test.tsx
@@ -0,0 +1,7 @@
+import { capitalize } from "./common";
+
+describe("capitalize", () => {
+ it("should capitalize a string", () => {
+ expect(capitalize("testing")).toBe("Testing");
+ });
+});
diff --git a/OwnTube.tv/utils/common.ts b/OwnTube.tv/utils/common.ts
index faf47eb..825304d 100644
--- a/OwnTube.tv/utils/common.ts
+++ b/OwnTube.tv/utils/common.ts
@@ -7,3 +7,7 @@ export const getThumbnailDimensions = () => {
return { width, height };
};
+
+export const capitalize = (input: string) => {
+ return input.charAt(0).toUpperCase() + input.slice(1);
+};
diff --git a/OwnTube.tv/utils/time.test.ts b/OwnTube.tv/utils/time.test.ts
index 1c922f5..f38e199 100644
--- a/OwnTube.tv/utils/time.test.ts
+++ b/OwnTube.tv/utils/time.test.ts
@@ -1,4 +1,4 @@
-import { getHumanReadableDuration } from "./time";
+import { getHumanReadableDuration, removeSecondsFromISODate } from "./time";
describe("getHumanReadableDuration", () => {
it("should output 40m30s for 2_430_000 ms input", () => {
@@ -14,3 +14,9 @@ describe("getHumanReadableDuration", () => {
expect(getHumanReadableDuration(undefined)).not.toBe("NaN:NaN");
});
});
+
+describe("removeSecondsFromISODate", () => {
+ it("should remove seconds from an ISO formatted date", () => {
+ expect(removeSecondsFromISODate("1970-01-01T00:00:00Z")).toBe("1970-01-01T00:00Z");
+ });
+});
diff --git a/OwnTube.tv/utils/time.ts b/OwnTube.tv/utils/time.ts
index 2338a95..efa9f3d 100644
--- a/OwnTube.tv/utils/time.ts
+++ b/OwnTube.tv/utils/time.ts
@@ -7,3 +7,7 @@ export const getHumanReadableDuration = (ms: number = 0) => {
return hours > 0 ? `${String(hours).padStart(2, "0")}:${mmss}` : mmss;
};
+
+export const removeSecondsFromISODate = (isoDate: string) => {
+ return `${isoDate.slice(0, isoDate.lastIndexOf(":"))}Z`;
+};