mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-30 14:21:04 +00:00
Compare commits
1 Commits
fix/librar
...
feat/LBX-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96b12cb27e |
@@ -35,27 +35,18 @@ export class DownloadManager {
|
|||||||
): string | undefined {
|
): string | undefined {
|
||||||
if (originalUrl?.includes("#")) {
|
if (originalUrl?.includes("#")) {
|
||||||
const hashPart = originalUrl.split("#")[1];
|
const hashPart = originalUrl.split("#")[1];
|
||||||
if (hashPart && !hashPart.startsWith("http") && hashPart.includes(".")) {
|
if (hashPart && !hashPart.startsWith("http")) return hashPart;
|
||||||
return hashPart;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.includes("#")) {
|
if (url.includes("#")) {
|
||||||
const hashPart = url.split("#")[1];
|
const hashPart = url.split("#")[1];
|
||||||
if (hashPart && !hashPart.startsWith("http") && hashPart.includes(".")) {
|
if (hashPart && !hashPart.startsWith("http")) return hashPart;
|
||||||
return hashPart;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const urlObj = new URL(url);
|
const urlObj = new URL(url);
|
||||||
const pathname = urlObj.pathname;
|
const filename = urlObj.pathname.split("/").pop();
|
||||||
const pathParts = pathname.split("/");
|
if (filename?.length) return filename;
|
||||||
const filename = pathParts[pathParts.length - 1];
|
|
||||||
|
|
||||||
if (filename?.includes(".") && filename.length > 0) {
|
|
||||||
return decodeURIComponent(filename);
|
|
||||||
}
|
|
||||||
} catch {
|
} catch {
|
||||||
// Invalid URL
|
// Invalid URL
|
||||||
}
|
}
|
||||||
@@ -64,7 +55,7 @@ export class DownloadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static sanitizeFilename(filename: string): string {
|
private static sanitizeFilename(filename: string): string {
|
||||||
return filename.replaceAll(/[<>:"/\\|?*]/g, "_");
|
return filename.replace(/[<>:"/\\|?*]/g, "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static createDownloadPayload(
|
private static createDownloadPayload(
|
||||||
@@ -73,19 +64,13 @@ export class DownloadManager {
|
|||||||
downloadId: string,
|
downloadId: string,
|
||||||
savePath: string
|
savePath: string
|
||||||
) {
|
) {
|
||||||
const filename =
|
const filename = this.extractFilename(directUrl, originalUrl);
|
||||||
this.extractFilename(originalUrl, directUrl) ||
|
|
||||||
this.extractFilename(directUrl);
|
|
||||||
const sanitizedFilename = filename
|
const sanitizedFilename = filename
|
||||||
? this.sanitizeFilename(filename)
|
? this.sanitizeFilename(filename)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
if (sanitizedFilename) {
|
if (sanitizedFilename) {
|
||||||
logger.log(`[DownloadManager] Using filename: ${sanitizedFilename}`);
|
logger.log(`[DownloadManager] Using filename: ${sanitizedFilename}`);
|
||||||
} else {
|
|
||||||
logger.log(
|
|
||||||
`[DownloadManager] No filename extracted, aria2 will use default`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -242,10 +227,10 @@ export class DownloadManager {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
gameFilesManager.extractDownloadedFile();
|
gameFilesManager.extractDownloadedFile();
|
||||||
} else if (download.folderName) {
|
} else {
|
||||||
gameFilesManager
|
gameFilesManager
|
||||||
.extractFilesInDirectory(
|
.extractFilesInDirectory(
|
||||||
path.join(download.downloadPath, download.folderName)
|
path.join(download.downloadPath, download.folderName!)
|
||||||
)
|
)
|
||||||
.then(() => gameFilesManager.setExtractionComplete());
|
.then(() => gameFilesManager.setExtractionComplete());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,26 +221,6 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cover-placeholder {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-width: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(255, 255, 255, 0.08) 0%,
|
|
||||||
rgba(255, 255, 255, 0.04) 50%,
|
|
||||||
rgba(255, 255, 255, 0.08) 100%
|
|
||||||
);
|
|
||||||
border-radius: 4px;
|
|
||||||
color: rgba(255, 255, 255, 0.3);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import { LibraryGame } from "@types";
|
import { LibraryGame } from "@types";
|
||||||
import { useGameCard } from "@renderer/hooks";
|
import { useGameCard } from "@renderer/hooks";
|
||||||
import { memo, useState } from "react";
|
import { memo } from "react";
|
||||||
import {
|
import { ClockIcon, AlertFillIcon, TrophyIcon } from "@primer/octicons-react";
|
||||||
ClockIcon,
|
|
||||||
AlertFillIcon,
|
|
||||||
TrophyIcon,
|
|
||||||
ImageIcon,
|
|
||||||
} from "@primer/octicons-react";
|
|
||||||
import "./library-game-card.scss";
|
import "./library-game-card.scss";
|
||||||
|
|
||||||
interface LibraryGameCardProps {
|
interface LibraryGameCardProps {
|
||||||
@@ -30,9 +25,14 @@ export const LibraryGameCard = memo(function LibraryGameCard({
|
|||||||
const { formatPlayTime, handleCardClick, handleContextMenuClick } =
|
const { formatPlayTime, handleCardClick, handleContextMenuClick } =
|
||||||
useGameCard(game, onContextMenu);
|
useGameCard(game, onContextMenu);
|
||||||
|
|
||||||
const coverImage = game.coverImageUrl?.replaceAll("\\", "/") ?? "";
|
const coverImage = (
|
||||||
|
game.customIconUrl ??
|
||||||
const [imageError, setImageError] = useState(false);
|
game.coverImageUrl ??
|
||||||
|
game.libraryImageUrl ??
|
||||||
|
game.libraryHeroImageUrl ??
|
||||||
|
game.iconUrl ??
|
||||||
|
""
|
||||||
|
).replaceAll("\\", "/");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
@@ -98,19 +98,12 @@ export const LibraryGameCard = memo(function LibraryGameCard({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{imageError || !coverImage ? (
|
<img
|
||||||
<div className="library-game-card__cover-placeholder">
|
src={coverImage ?? undefined}
|
||||||
<ImageIcon size={48} />
|
alt={game.title}
|
||||||
</div>
|
className="library-game-card__game-image"
|
||||||
) : (
|
loading="lazy"
|
||||||
<img
|
/>
|
||||||
src={coverImage}
|
|
||||||
alt={game.title}
|
|
||||||
className="library-game-card__game-image"
|
|
||||||
loading="lazy"
|
|
||||||
onError={() => setImageError(true)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -130,6 +130,32 @@ export default function Notifications() {
|
|||||||
return () => unsubscribe();
|
return () => unsubscribe();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubscribe = window.electron.onSyncNotificationCount(() => {
|
||||||
|
if (userDetails) {
|
||||||
|
fetchApiNotifications(0, false);
|
||||||
|
}
|
||||||
|
fetchLocalNotifications();
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => unsubscribe();
|
||||||
|
}, [userDetails, fetchApiNotifications, fetchLocalNotifications]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleVisibilityChange = () => {
|
||||||
|
if (!document.hidden && userDetails) {
|
||||||
|
fetchApiNotifications(0, false);
|
||||||
|
fetchLocalNotifications();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
};
|
||||||
|
}, [userDetails, fetchApiNotifications, fetchLocalNotifications]);
|
||||||
|
|
||||||
const mergedNotifications = useMemo<MergedNotification[]>(() => {
|
const mergedNotifications = useMemo<MergedNotification[]>(() => {
|
||||||
const sortByDate = (a: MergedNotification, b: MergedNotification) =>
|
const sortByDate = (a: MergedNotification, b: MergedNotification) =>
|
||||||
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
|
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
|
||||||
|
|||||||
@@ -116,5 +116,6 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user