Compare commits
No commits in common. "main" and "v0.0.15" have entirely different histories.
7 changed files with 447 additions and 686 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "has",
|
"name": "has",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.19",
|
"version": "0.0.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "has"
|
name = "has"
|
||||||
version = "0.0.19"
|
version = "0.0.15"
|
||||||
description = "has"
|
description = "has"
|
||||||
authors = ["autli"]
|
authors = ["autli"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "has",
|
"productName": "has",
|
||||||
"version": "0.0.19",
|
"version": "0.0.15",
|
||||||
"identifier": "com.has.tauri-app",
|
"identifier": "com.has.tauri-app",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|
|
||||||
31
src/App.tsx
31
src/App.tsx
|
|
@ -27,6 +27,8 @@ const isTauri = () => {
|
||||||
// Helper for Smart TV / Android TV detection
|
// Helper for Smart TV / Android TV detection
|
||||||
const detectTvEnvironment = (): boolean => {
|
const detectTvEnvironment = (): boolean => {
|
||||||
if (typeof window === "undefined") return false;
|
if (typeof window === "undefined") return false;
|
||||||
|
const saved = localStorage.getItem("has_tv_mode");
|
||||||
|
if (saved !== null) return saved === "true";
|
||||||
const ua = (navigator.userAgent || "").toLowerCase();
|
const ua = (navigator.userAgent || "").toLowerCase();
|
||||||
const isTvUa =
|
const isTvUa =
|
||||||
ua.includes("android tv") ||
|
ua.includes("android tv") ||
|
||||||
|
|
@ -53,17 +55,6 @@ const detectTvEnvironment = (): boolean => {
|
||||||
const isAndroid = ua.includes("android");
|
const isAndroid = ua.includes("android");
|
||||||
const noTouch = !("ontouchstart" in window) && navigator.maxTouchPoints === 0;
|
const noTouch = !("ontouchstart" in window) && navigator.maxTouchPoints === 0;
|
||||||
if (isAndroid && noTouch) return true;
|
if (isAndroid && noTouch) return true;
|
||||||
|
|
||||||
// On pure desktop (macOS / Windows / Desktop Linux), default to desktop PC mode
|
|
||||||
const isDesktop =
|
|
||||||
(ua.includes("windows nt") || ua.includes("macintosh") || (ua.includes("linux") && !ua.includes("android"))) &&
|
|
||||||
!isTvUa;
|
|
||||||
if (isDesktop) {
|
|
||||||
return localStorage.getItem("has_tv_mode_manual") === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
const saved = localStorage.getItem("has_tv_mode");
|
|
||||||
if (saved !== null) return saved === "true";
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -153,6 +144,21 @@ export default function App() {
|
||||||
checkDatabase();
|
checkDatabase();
|
||||||
}, [isTvEnvironment]);
|
}, [isTvEnvironment]);
|
||||||
|
|
||||||
|
// Activate TV mode immediately upon any remote control key press
|
||||||
|
useEffect(() => {
|
||||||
|
const handleRemoteKey = (e: KeyboardEvent) => {
|
||||||
|
const isRemoteKey =
|
||||||
|
[19, 20, 21, 22, 23, 4, 82, 85, 179].includes(e.keyCode) ||
|
||||||
|
["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key);
|
||||||
|
if (isRemoteKey && !isTvEnvironment) {
|
||||||
|
setIsTvEnvironment(true);
|
||||||
|
localStorage.setItem("has_tv_mode", "true");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", handleRemoteKey);
|
||||||
|
return () => window.removeEventListener("keydown", handleRemoteKey);
|
||||||
|
}, [isTvEnvironment]);
|
||||||
|
|
||||||
// Countdown timer for OTP re-send in resetStage 2
|
// Countdown timer for OTP re-send in resetStage 2
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (resetStage !== 2) return;
|
if (resetStage !== 2) return;
|
||||||
|
|
@ -519,7 +525,6 @@ export default function App() {
|
||||||
dbInfo={dbInfo}
|
dbInfo={dbInfo}
|
||||||
dbStatus={dbStatus}
|
dbStatus={dbStatus}
|
||||||
onLogout={handleLogout}
|
onLogout={handleLogout}
|
||||||
isTvEnvironment={isTvEnvironment}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
@ -537,7 +542,6 @@ export default function App() {
|
||||||
onSwitchToDesktop={() => {
|
onSwitchToDesktop={() => {
|
||||||
setIsTvEnvironment(false);
|
setIsTvEnvironment(false);
|
||||||
localStorage.setItem("has_tv_mode", "false");
|
localStorage.setItem("has_tv_mode", "false");
|
||||||
localStorage.setItem("has_tv_mode_manual", "false");
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
@ -808,7 +812,6 @@ export default function App() {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsTvEnvironment(true);
|
setIsTvEnvironment(true);
|
||||||
localStorage.setItem("has_tv_mode", "true");
|
localStorage.setItem("has_tv_mode", "true");
|
||||||
localStorage.setItem("has_tv_mode_manual", "true");
|
|
||||||
}}
|
}}
|
||||||
title="Перейти в режим Android TV (выбор профилей)"
|
title="Перейти в режим Android TV (выбор профилей)"
|
||||||
style={{
|
style={{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ interface UpdaterBannerProps {
|
||||||
// Helper for Smart TV / Android TV detection
|
// Helper for Smart TV / Android TV detection
|
||||||
const detectTvEnvironment = (): boolean => {
|
const detectTvEnvironment = (): boolean => {
|
||||||
if (typeof window === "undefined") return false;
|
if (typeof window === "undefined") return false;
|
||||||
|
const saved = localStorage.getItem("has_tv_mode");
|
||||||
|
if (saved !== null) return saved === "true";
|
||||||
const ua = (navigator.userAgent || "").toLowerCase();
|
const ua = (navigator.userAgent || "").toLowerCase();
|
||||||
const isTvUa =
|
const isTvUa =
|
||||||
ua.includes("android tv") ||
|
ua.includes("android tv") ||
|
||||||
|
|
@ -48,17 +50,6 @@ const detectTvEnvironment = (): boolean => {
|
||||||
const isAndroid = ua.includes("android");
|
const isAndroid = ua.includes("android");
|
||||||
const noTouch = !("ontouchstart" in window) && navigator.maxTouchPoints === 0;
|
const noTouch = !("ontouchstart" in window) && navigator.maxTouchPoints === 0;
|
||||||
if (isAndroid && noTouch) return true;
|
if (isAndroid && noTouch) return true;
|
||||||
|
|
||||||
// On pure desktop (macOS / Windows / Desktop Linux), default to desktop PC mode
|
|
||||||
const isDesktop =
|
|
||||||
(ua.includes("windows nt") || ua.includes("macintosh") || (ua.includes("linux") && !ua.includes("android"))) &&
|
|
||||||
!isTvUa;
|
|
||||||
if (isDesktop) {
|
|
||||||
return localStorage.getItem("has_tv_mode_manual") === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
const saved = localStorage.getItem("has_tv_mode");
|
|
||||||
if (saved !== null) return saved === "true";
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -97,7 +88,7 @@ const isNewerSemver = (remote: string, current: string): boolean => {
|
||||||
|
|
||||||
export function UpdaterBanner({ isTvEnvironment }: UpdaterBannerProps = {}) {
|
export function UpdaterBanner({ isTvEnvironment }: UpdaterBannerProps = {}) {
|
||||||
const [isTv, setIsTv] = useState<boolean>(() => isTvEnvironment ?? detectTvEnvironment());
|
const [isTv, setIsTv] = useState<boolean>(() => isTvEnvironment ?? detectTvEnvironment());
|
||||||
const [currentAppVersion, setCurrentAppVersion] = useState<string>("0.0.19");
|
const [currentAppVersion, setCurrentAppVersion] = useState<string>("0.0.15");
|
||||||
const [updateAvailable, setUpdateAvailable] = useState(false);
|
const [updateAvailable, setUpdateAvailable] = useState(false);
|
||||||
const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);
|
const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);
|
||||||
const [downloading, setDownloading] = useState(false);
|
const [downloading, setDownloading] = useState(false);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -55,7 +55,6 @@ interface DashboardProps {
|
||||||
dbInfo: SafeDbInfo | null;
|
dbInfo: SafeDbInfo | null;
|
||||||
dbStatus: DbStatus | null;
|
dbStatus: DbStatus | null;
|
||||||
onLogout: () => void;
|
onLogout: () => void;
|
||||||
isTvEnvironment?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NavTab = "cinema" | "home" | "users" | "settings" | "profile" | "help";
|
type NavTab = "cinema" | "home" | "users" | "settings" | "profile" | "help";
|
||||||
|
|
@ -63,6 +62,8 @@ type NavTab = "cinema" | "home" | "users" | "settings" | "profile" | "help";
|
||||||
// Helper for Smart TV / Android TV detection
|
// Helper for Smart TV / Android TV detection
|
||||||
const detectTvEnvironment = (): boolean => {
|
const detectTvEnvironment = (): boolean => {
|
||||||
if (typeof window === "undefined") return false;
|
if (typeof window === "undefined") return false;
|
||||||
|
const saved = localStorage.getItem("has_tv_mode");
|
||||||
|
if (saved !== null) return saved === "true";
|
||||||
const ua = (navigator.userAgent || "").toLowerCase();
|
const ua = (navigator.userAgent || "").toLowerCase();
|
||||||
const isTvUa =
|
const isTvUa =
|
||||||
ua.includes("android tv") ||
|
ua.includes("android tv") ||
|
||||||
|
|
@ -89,17 +90,6 @@ const detectTvEnvironment = (): boolean => {
|
||||||
const isAndroid = ua.includes("android");
|
const isAndroid = ua.includes("android");
|
||||||
const noTouch = !("ontouchstart" in window) && navigator.maxTouchPoints === 0;
|
const noTouch = !("ontouchstart" in window) && navigator.maxTouchPoints === 0;
|
||||||
if (isAndroid && noTouch) return true;
|
if (isAndroid && noTouch) return true;
|
||||||
|
|
||||||
// On pure desktop (macOS / Windows / Desktop Linux), default to desktop PC mode
|
|
||||||
const isDesktop =
|
|
||||||
(ua.includes("windows nt") || ua.includes("macintosh") || (ua.includes("linux") && !ua.includes("android"))) &&
|
|
||||||
!isTvUa;
|
|
||||||
if (isDesktop) {
|
|
||||||
return localStorage.getItem("has_tv_mode_manual") === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
const saved = localStorage.getItem("has_tv_mode");
|
|
||||||
if (saved !== null) return saved === "true";
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -108,23 +98,13 @@ export default function Dashboard({
|
||||||
dbInfo,
|
dbInfo,
|
||||||
dbStatus,
|
dbStatus,
|
||||||
onLogout,
|
onLogout,
|
||||||
isTvEnvironment: propIsTv,
|
|
||||||
}: DashboardProps) {
|
}: DashboardProps) {
|
||||||
const [currentUser, setCurrentUser] = useState<UserDto>(user);
|
const [currentUser, setCurrentUser] = useState<UserDto>(user);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentUser(user);
|
setCurrentUser(user);
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
const [isTvEnvironment, setIsTvEnvironment] = useState<boolean>(() => {
|
const [isTvEnvironment, setIsTvEnvironment] = useState<boolean>(detectTvEnvironment);
|
||||||
return propIsTv !== undefined ? propIsTv : detectTvEnvironment();
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (propIsTv !== undefined && propIsTv !== isTvEnvironment) {
|
|
||||||
setIsTvEnvironment(propIsTv);
|
|
||||||
}
|
|
||||||
}, [propIsTv, isTvEnvironment]);
|
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState<NavTab>("cinema");
|
const [activeTab, setActiveTab] = useState<NavTab>("cinema");
|
||||||
const [serverUsers, setServerUsers] = useState<ServerUserDto[]>([]);
|
const [serverUsers, setServerUsers] = useState<ServerUserDto[]>([]);
|
||||||
const [loadingUsers, setLoadingUsers] = useState(false);
|
const [loadingUsers, setLoadingUsers] = useState(false);
|
||||||
|
|
@ -133,6 +113,21 @@ export default function Dashboard({
|
||||||
});
|
});
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
// Dynamic D-Pad Remote Control Key Listener (Auto-detects TV when user presses remote buttons)
|
||||||
|
useEffect(() => {
|
||||||
|
const handleRemoteDpadKey = (e: KeyboardEvent) => {
|
||||||
|
const isRemoteKey =
|
||||||
|
[19, 20, 21, 22, 23, 4, 82, 85, 179].includes(e.keyCode) ||
|
||||||
|
["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key);
|
||||||
|
if (isRemoteKey && !isTvEnvironment) {
|
||||||
|
setIsTvEnvironment(true);
|
||||||
|
localStorage.setItem("has_tv_mode", "true");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", handleRemoteDpadKey);
|
||||||
|
return () => window.removeEventListener("keydown", handleRemoteDpadKey);
|
||||||
|
}, [isTvEnvironment]);
|
||||||
|
|
||||||
const handleNavClick = (tab: NavTab) => {
|
const handleNavClick = (tab: NavTab) => {
|
||||||
setActiveTab(tab);
|
setActiveTab(tab);
|
||||||
setMobileMenuOpen(false);
|
setMobileMenuOpen(false);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue