diff --git a/package-lock.json b/package-lock.json index 78a43d3..c7016bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@tauri-apps/api": "^1.3.0", "@types/lodash": "^4.14.195", "async-wait-until": "^2.0.12", + "date-fns": "^2.30.0", "dompurify": "^3.0.4", "gray-matter": "^4.0.3", "lodash": "^4.17.21", @@ -3357,6 +3358,21 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "devOptional": true }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -9256,6 +9272,14 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "devOptional": true }, + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index 279bd12..7b0f5a9 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@tauri-apps/api": "^1.3.0", "@types/lodash": "^4.14.195", "async-wait-until": "^2.0.12", + "date-fns": "^2.30.0", "dompurify": "^3.0.4", "gray-matter": "^4.0.3", "lodash": "^4.17.21", diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index 723f175..ab19225 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src/components/NewsSection/NewsEntry/NewsEntry.module.css b/src/components/NewsSection/NewsEntry/NewsEntry.module.css index 8475b3a..a4bdb0f 100644 --- a/src/components/NewsSection/NewsEntry/NewsEntry.module.css +++ b/src/components/NewsSection/NewsEntry/NewsEntry.module.css @@ -7,7 +7,7 @@ margin: 8px 0px 8px 0px; background: rgba(0, 0, 0, 0); - border-radius: 8px; + border-radius: 20px; /* 8px (internal border-radius) + 12px (padding) */ transition: background 0.1s; } @@ -73,4 +73,18 @@ height: 100px; align-self: stretch; background: #D9D9D9; +} + +.releaseDate { + color: #ACACAC; + font-size: 12px; + font-weight: 400; + display: flex; + align-items: center; + gap: 5px; + transition: margin-right 0.1s; +} + +.container:hover .releaseDate { + margin-right: 1em; } \ No newline at end of file diff --git a/src/components/NewsSection/NewsEntry/index.tsx b/src/components/NewsSection/NewsEntry/index.tsx index bc88b36..bfa9772 100644 --- a/src/components/NewsSection/NewsEntry/index.tsx +++ b/src/components/NewsSection/NewsEntry/index.tsx @@ -4,6 +4,8 @@ import { ArticleData } from "@app/hooks/useNews"; import { Link } from "react-router-dom"; import { Img } from "react-image"; import UnknownUserIcon from "@app/assets/Icons/UnknownUser.svg"; +import { TimeIcon } from "@app/assets/Icons"; +import { intlFormatDistance } from "date-fns"; interface Props { article: ArticleData; @@ -17,6 +19,14 @@ const NewsEntry: React.FC = ({ article }: Props) => {
{article.type} + { + article.release ? ( +
+ + { intlFormatDistance(new Date(article.release), new Date()) } +
+ ) : "" + }
{article.title}
@@ -25,6 +35,7 @@ const NewsEntry: React.FC = ({ article }: Props) => { height={24} alt={`${article.author}'s avatar`} src={[`https://raw.githubusercontent.com/YARC-Official/News/master/images/avatars/${article.avatar}`, UnknownUserIcon]} + style={{borderRadius: "50%"}} />
By: {article.author} diff --git a/src/components/Queue/QueueEntry/YARG.tsx b/src/components/Queue/QueueEntry/YARG.tsx index 91517e5..f255bad 100644 --- a/src/components/Queue/QueueEntry/YARG.tsx +++ b/src/components/Queue/QueueEntry/YARG.tsx @@ -1,6 +1,8 @@ import { YARGDownload } from "@app/utils/Download/Processors/YARG"; import BaseQueue from "./base"; -import YARGIcon from "@app/assets/StableYARGIcon.png"; +import StableYARGIcon from "@app/assets/StableYARGIcon.png"; +import NightlyYARGIcon from "@app/assets/NightlyYARGIcon.png"; +import { YARGChannels } from "@app/hooks/useYARGRelease"; interface Props { downloader: YARGDownload, @@ -8,11 +10,17 @@ interface Props { } const YARGQueue: React.FC = ({ downloader, bannerMode }: Props) => { + + const channelIconPath: {[key in YARGChannels]: string} = { + "stable": StableYARGIcon, + "nightly": NightlyYARGIcon + }; + return } + icon={} version={downloader.version} - versionChannel="TODO" + versionChannel={downloader.channel.toUpperCase()} bannerMode={bannerMode} />; }; diff --git a/src/components/Sidebar/Versions/Setlist.tsx b/src/components/Sidebar/Versions/Setlist.tsx index 8927963..d908d8b 100644 --- a/src/components/Sidebar/Versions/Setlist.tsx +++ b/src/components/Sidebar/Versions/Setlist.tsx @@ -1,7 +1,7 @@ import { SetlistID, useSetlistRelease } from "@app/hooks/useSetlistRelease"; import { SetlistStates, useSetlistData } from "@app/hooks/useSetlistData"; import BaseVersion, { VersionType } from "./Base"; -import { Link } from "react-router-dom"; +import { NavLink } from "react-router-dom"; import OfficialIcon from "@app/assets/SourceIcons/Official.png"; interface Props { @@ -13,7 +13,7 @@ const SetlistVersion: React.FC = ({ channel }: Props) => { const { state } = useSetlistData(setlistData); return ( - + } // TO-DO: create a util/sourceIcon to get source icon from type={VersionType.SONG} @@ -21,7 +21,7 @@ const SetlistVersion: React.FC = ({ channel }: Props) => { versionChannel={`${setlistData?.songs?.length} songs`} updateAvailable={state === SetlistStates.NEW_UPDATE} /> - + ); }; diff --git a/src/components/Sidebar/Versions/YARG.tsx b/src/components/Sidebar/Versions/YARG.tsx index eadea84..60d2bf9 100644 --- a/src/components/Sidebar/Versions/YARG.tsx +++ b/src/components/Sidebar/Versions/YARG.tsx @@ -3,7 +3,7 @@ import { YARGStates, useYARGVersion } from "@app/hooks/useYARGVersion"; import BaseVersion from "./Base"; import NightlyYARGIcon from "@app/assets/NightlyYARGIcon.png"; import StableYARGIcon from "@app/assets/StableYARGIcon.png"; -import { Link } from "react-router-dom"; +import { NavLink } from "react-router-dom"; interface Props { channel: "stable" | "nightly"; @@ -32,7 +32,7 @@ const YARGVersion: React.FC = ({ channel }: Props) => { } return ( - + } programName="YARG" @@ -40,7 +40,7 @@ const YARGVersion: React.FC = ({ channel }: Props) => { version={releaseData?.tag_name} updateAvailable={state === YARGStates.NEW_UPDATE} /> - + ); }; diff --git a/src/components/Sidebar/Versions/styles/Application.module.css b/src/components/Sidebar/Versions/styles/Application.module.css index 6dd3fdf..7be7c88 100644 --- a/src/components/Sidebar/Versions/styles/Application.module.css +++ b/src/components/Sidebar/Versions/styles/Application.module.css @@ -3,14 +3,16 @@ gap: 10px; align-items: center; --border-radius: 8px; + --padding: 5px; - padding: 5px; + padding: var(--padding); background: rgba(255, 255, 255, 0); - border-radius: var(--border-radius); + border-radius: calc(var(--border-radius) + var(--padding)); transition: background 0.1s; } +[aria-current="page"] > .selector, .selector:hover { background: rgba(255, 255, 255, 0.025); } diff --git a/src/components/Sidebar/Versions/styles/Song.module.css b/src/components/Sidebar/Versions/styles/Song.module.css index 76ef9e7..5570b70 100644 --- a/src/components/Sidebar/Versions/styles/Song.module.css +++ b/src/components/Sidebar/Versions/styles/Song.module.css @@ -3,14 +3,16 @@ gap: 10px; align-items: center; --border-radius: 8px; + --padding: 5px; - padding: 5px; + padding: var(--padding); background: rgba(255, 255, 255, 0); - border-radius: var(--border-radius); + border-radius: calc(var(--border-radius) + var(--padding)); transition: background 0.1s; } +[aria-current="page"] > .selector, .selector:hover { background: rgba(255, 255, 255, 0.025); } diff --git a/src/hooks/useYARGRelease.ts b/src/hooks/useYARGRelease.ts index 8e38eaf..df1fcd0 100644 --- a/src/hooks/useYARGRelease.ts +++ b/src/hooks/useYARGRelease.ts @@ -2,20 +2,26 @@ import { useQuery } from "@tanstack/react-query"; import { Endpoints } from "@octokit/types"; import { invoke } from "@tauri-apps/api/tauri"; -export type ReleaseData = Endpoints["GET /repos/{owner}/{repo}/releases/latest"]["response"]["data"]; +export type YARGChannels = "stable"|"nightly"; -export const useYARGRelease = (version: "stable" | "nightly") => { +type ReleaseData = Endpoints["GET /repos/{owner}/{repo}/releases/latest"]["response"]["data"]; +export type ExtendedReleaseData = ReleaseData & { + channel: YARGChannels +}; + +export const useYARGRelease = (channel: YARGChannels) => { const repositoryName = { "stable": "YARG", "nightly": "YARG-BleedingEdge" }; return useQuery({ - queryKey: ["YARG", version], + queryKey: ["YARG", channel], queryFn: async (): Promise => await fetch( - `https://api.github.com/repos/YARC-Official/${repositoryName[version]}/releases/latest`) - .then(res => res.json()) - }).data as ReleaseData; + `https://api.github.com/repos/YARC-Official/${repositoryName[channel]}/releases/latest`) + .then(res => res.json()), + select: (data): ExtendedReleaseData => ({...data, channel: channel}) + }).data as ExtendedReleaseData; }; export const getYARGReleaseZip = async (releaseData: ReleaseData) => { diff --git a/src/hooks/useYARGVersion.ts b/src/hooks/useYARGVersion.ts index 571a641..750d0f0 100644 --- a/src/hooks/useYARGVersion.ts +++ b/src/hooks/useYARGVersion.ts @@ -1,5 +1,5 @@ import { useEffect } from "react"; -import { ReleaseData, getYARGReleaseZip, getYARGReleaseSig } from "./useYARGRelease"; +import { ExtendedReleaseData, getYARGReleaseZip, getYARGReleaseSig } from "./useYARGRelease"; import { invoke } from "@tauri-apps/api/tauri"; import { useYARGState } from "@app/stores/YARGStateStore"; import { useDownloadClient } from "@app/utils/Download/provider"; @@ -24,7 +24,7 @@ export type YARGVersion = { payload?: DownloadPayload } -export const useYARGVersion = (releaseData: ReleaseData, profileName: string) => { +export const useYARGVersion = (releaseData: ExtendedReleaseData, profileName: string) => { const { state, setState } = useYARGState(releaseData?.tag_name); const downloadClient = useDownloadClient(); @@ -83,6 +83,7 @@ export const useYARGVersion = (releaseData: ReleaseData, profileName: string) => const downloader = new YARGDownload( zipUrl, sigUrl, + releaseData.channel, releaseData.tag_name, profileName, () => { setState(YARGStates.AVAILABLE); } diff --git a/src/routes/NewsPage/NewsPage.module.css b/src/routes/NewsPage/NewsPage.module.css index 595ffb8..5af65df 100644 --- a/src/routes/NewsPage/NewsPage.module.css +++ b/src/routes/NewsPage/NewsPage.module.css @@ -68,6 +68,7 @@ height: 48px; aspect-ratio: 1; border-radius: 50%; + overflow: hidden; } .author .authorInformation { diff --git a/src/routes/NewsPage/index.tsx b/src/routes/NewsPage/index.tsx index 62395b4..0751614 100644 --- a/src/routes/NewsPage/index.tsx +++ b/src/routes/NewsPage/index.tsx @@ -9,6 +9,7 @@ import { CSSProperties } from "react"; import { BackIcon, TimeIcon } from "@app/assets/Icons"; import { Img } from "react-image"; import UnknownUserIcon from "@app/assets/Icons/UnknownUser.svg"; +import { intlFormatDistance } from "date-fns"; function NewsPage() { const { md } = useParams(); @@ -49,10 +50,14 @@ function NewsPage() {
{articleData.role}
- {/*
- - 16 minutes ago -
*/} + { + articleData.release ? ( +
+ + { intlFormatDistance(new Date(articleData.release), new Date()) } +
+ ) : "" + } diff --git a/src/utils/Download/Processors/YARG.tsx b/src/utils/Download/Processors/YARG.tsx index 6ab97f7..d6cd5ba 100644 --- a/src/utils/Download/Processors/YARG.tsx +++ b/src/utils/Download/Processors/YARG.tsx @@ -1,18 +1,21 @@ import { invoke } from "@tauri-apps/api/tauri"; import { BaseDownload, IBaseDownload } from "./base"; import YARGQueue from "@app/components/Queue/QueueEntry/YARG"; +import { YARGChannels } from "@app/hooks/useYARGRelease"; export class YARGDownload extends BaseDownload implements IBaseDownload { zipUrl: string; sigUrl?: string; + channel: YARGChannels; version: string; profile: string; onFinish: () => void; - constructor(zipUrl: string, sigUrl: string | undefined, version: string, profile: string, onFinish: () => void) { + constructor(zipUrl: string, sigUrl: string | undefined, channel: YARGChannels, version: string, profile: string, onFinish: () => void) { super(generateYARGUUID(version)); this.zipUrl = zipUrl; this.sigUrl = sigUrl; + this.channel = channel; this.version = version; this.profile = profile; this.onFinish = onFinish;