chore: ui changes
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 ourongxing
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -4,6 +4,12 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "[email protected]+sha512.0a203ffaed5a3f63242cd064c8fb5892366c103e328079318f78062f24ea8c9d50bc6a47aa3567cabefd824d170e78fa2745ed1f16b132e16436146b7688f19b",
|
"packageManager": "[email protected]+sha512.0a203ffaed5a3f63242cd064c8fb5892366c103e328079318f78062f24ea8c9d50bc6a47aa3567cabefd824d170e78fa2745ed1f16b132e16436146b7688f19b",
|
||||||
|
"author": {
|
||||||
|
"url": "https://github.com/ourongxing/",
|
||||||
|
"email": "[email protected]",
|
||||||
|
"name": "Ou Rongxing"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/ourongxing/newsnow",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
* 缓存过期时间
|
* 缓存过期时间
|
||||||
*/
|
*/
|
||||||
|
import packageJSON from "../package.json"
|
||||||
|
|
||||||
export const TTL = 30 * 60 * 1000
|
export const TTL = 30 * 60 * 1000
|
||||||
/**
|
/**
|
||||||
* 默认刷新间隔, 10 min
|
* 默认刷新间隔, 10 min
|
||||||
*/
|
*/
|
||||||
export const Interval = 10 * 60 * 1000
|
export const Interval = 10 * 60 * 1000
|
||||||
|
|
||||||
|
export const Homepage = packageJSON.homepage
|
||||||
|
|
||||||
|
export const Version = packageJSON.version
|
||||||
|
export const Author = packageJSON.author
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useAtomValue, useSetAtom } from "jotai"
|
|||||||
import { useIsFetching } from "@tanstack/react-query"
|
import { useIsFetching } from "@tanstack/react-query"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import type { SourceID } from "@shared/types"
|
import type { SourceID } from "@shared/types"
|
||||||
|
import { Homepage, Version } from "@shared/consts"
|
||||||
import logo from "~/assets/react.svg"
|
import logo from "~/assets/react.svg"
|
||||||
import { useDark } from "~/hooks/useDark"
|
import { useDark } from "~/hooks/useDark"
|
||||||
import { currentSectionAtom, refetchSourcesAtom } from "~/atoms"
|
import { currentSectionAtom, refetchSourcesAtom } from "~/atoms"
|
||||||
@@ -20,6 +21,10 @@ function ThemeToggle() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GithubIcon() {
|
||||||
|
return <a className="i-ph-github-logo-duotone inline-block btn-pure" href={Homepage} />
|
||||||
|
}
|
||||||
|
|
||||||
function RefreshButton() {
|
function RefreshButton() {
|
||||||
const currentSection = useAtomValue(currentSectionAtom)
|
const currentSection = useAtomValue(currentSectionAtom)
|
||||||
const setRefetchSource = useSetAtom(refetchSourcesAtom)
|
const setRefetchSource = useSetAtom(refetchSourcesAtom)
|
||||||
@@ -44,15 +49,19 @@ function RefreshButton() {
|
|||||||
|
|
||||||
export function Header() {
|
export function Header() {
|
||||||
return (
|
return (
|
||||||
<header className="flex justify-between items-center bg-base p-4 md:(p-8)">
|
<>
|
||||||
<Link className="text-6 flex gap-2 items-center" to="/">
|
<Link className="text-6 flex gap-2 items-center" to="/">
|
||||||
<img src={logo} alt="logo" className="h-8" />
|
<img src={logo} alt="logo" className="h-8" />
|
||||||
<span className="font-mono">NewsNow</span>
|
<span className="font-mono">NewsNow</span>
|
||||||
|
<a className="btn-pure text-sm mt--2">
|
||||||
|
{`v${Version}`}
|
||||||
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2 items-center">
|
||||||
<RefreshButton />
|
<RefreshButton />
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
|
<GithubIcon />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,12 @@ export function NewsCard({ id, inView, isOverlay, handleListeners }: NewsCardPro
|
|||||||
className={clsx("flex justify-between p-2 items-center")}
|
className={clsx("flex justify-between p-2 items-center")}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<img src={`/icons/${id.split("-")[0]}.png`} className="w-4 h-4 rounded" alt={id} onError={e => e.currentTarget.hidden = true} />
|
<img
|
||||||
|
src={`/icons/${id.split("-")[0]}.png`}
|
||||||
|
className="w-4 h-4 rounded"
|
||||||
|
alt={id}
|
||||||
|
onError={e => e.currentTarget.hidden = true}
|
||||||
|
/>
|
||||||
<span className="text-md font-bold">
|
<span className="text-md font-bold">
|
||||||
{sources[id].name}
|
{sources[id].name}
|
||||||
</span>
|
</span>
|
||||||
@@ -118,14 +123,18 @@ export function NewsCard({ id, inView, isOverlay, handleListeners }: NewsCardPro
|
|||||||
</div>
|
</div>
|
||||||
<NewsList query={query} />
|
<NewsList query={query} />
|
||||||
<div className="p-2 flex items-center justify-between">
|
<div className="p-2 flex items-center justify-between">
|
||||||
<UpdateTime query={query} />
|
<span className="text-sm"><UpdateTime query={query} /></span>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={clsx("i-ph:arrow-clockwise", query.isFetching && "animate-spin")}
|
className={clsx("i-ph:arrow-clockwise", query.isFetching && "animate-spin")}
|
||||||
onClick={manualRefetch}
|
onClick={manualRefetch}
|
||||||
/>
|
/>
|
||||||
<button type="button" className={clsx(focusSources.includes(id) ? "i-ph:star-fill" : "i-ph:star", "color-primary")} onClick={addFocusList} />
|
<button
|
||||||
|
type="button"
|
||||||
|
className={clsx(focusSources.includes(id) ? "i-ph:star-fill" : "i-ph:star", "color-primary")}
|
||||||
|
onClick={addFocusList}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -134,14 +143,14 @@ export function NewsCard({ id, inView, isOverlay, handleListeners }: NewsCardPro
|
|||||||
|
|
||||||
function UpdateTime({ query }: Query) {
|
function UpdateTime({ query }: Query) {
|
||||||
const updatedTime = useRelativeTime(query.data?.updatedTime ?? "")
|
const updatedTime = useRelativeTime(query.data?.updatedTime ?? "")
|
||||||
if (updatedTime) return <span>{`${updatedTime}更新`}</span>
|
if (updatedTime) return `${updatedTime}更新`
|
||||||
if (query.isError) return <span>获取失败</span>
|
if (query.isError) return "获取失败"
|
||||||
|
return "加载中..."
|
||||||
}
|
}
|
||||||
|
|
||||||
function Num({ num }: { num: number }) {
|
function Num({ num }: { num: number }) {
|
||||||
const color = ["bg-red-900", "bg-red-500", "bg-red-400"]
|
|
||||||
return (
|
return (
|
||||||
<span className={clsx("bg-active min-w-6 flex justify-center items-center rounded-md", false && color[num - 1])}>
|
<span className={clsx("bg-gray/10 min-w-6 flex justify-center items-center rounded-md")}>
|
||||||
{num}
|
{num}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function Dnd() {
|
|||||||
return (
|
return (
|
||||||
<DndWrapper items={items} setItems={setItems}>
|
<DndWrapper items={items} setItems={setItems}>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="grid w-full gap-4"
|
className="grid w-full gap-6"
|
||||||
style={{
|
style={{
|
||||||
gridTemplateColumns: "repeat(auto-fill, minmax(325px, 1fr))",
|
gridTemplateColumns: "repeat(auto-fill, minmax(325px, 1fr))",
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function Section({ id }: { id: SectionID }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="w-full flex justify-center">
|
<div className="w-full flex justify-center">
|
||||||
<div className="flex gap-2 py-4">
|
<div className="flex gap-2 mb-6">
|
||||||
{sectionIds.map(section => (
|
{sectionIds.map(section => (
|
||||||
<Link
|
<Link
|
||||||
key={section}
|
key={section}
|
||||||
|
|||||||
+15
-1
@@ -4,6 +4,7 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
|||||||
import "~/styles/globals.css"
|
import "~/styles/globals.css"
|
||||||
import "virtual:uno.css"
|
import "virtual:uno.css"
|
||||||
import type { QueryClient } from "@tanstack/react-query"
|
import type { QueryClient } from "@tanstack/react-query"
|
||||||
|
import { Author, Homepage } from "@shared/consts"
|
||||||
import { Header } from "~/components/header"
|
import { Header } from "~/components/header"
|
||||||
import { useOnReload } from "~/hooks/useOnReload"
|
import { useOnReload } from "~/hooks/useOnReload"
|
||||||
import { OverlayScrollbar } from "~/components/common/overlay-scrollbar"
|
import { OverlayScrollbar } from "~/components/common/overlay-scrollbar"
|
||||||
@@ -26,9 +27,22 @@ function RootComponent() {
|
|||||||
useOnReload()
|
useOnReload()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<OverlayScrollbar className="md:p-8 p-4 h-full overflow-x-auto">
|
<OverlayScrollbar className="px-6 md:(px-16) h-full overflow-x-auto relative">
|
||||||
|
<header className="flex justify-between items-center sticky top-0 z-100 bg-base py-4 md:(pt-8)">
|
||||||
<Header />
|
<Header />
|
||||||
|
</header>
|
||||||
|
<main className="min-h-[calc(100vh-11rem)]">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
</main>
|
||||||
|
<footer className="py-6 flex flex-col items-center justify-center text-sm">
|
||||||
|
<a href={`${Homepage}/LICENCE`}>MIT LICENCE</a>
|
||||||
|
<span>
|
||||||
|
<span> © 2024 By </span>
|
||||||
|
<a href={Author.url}>
|
||||||
|
{Author.name}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</footer>
|
||||||
</OverlayScrollbar>
|
</OverlayScrollbar>
|
||||||
{import.meta.env.DEV && (
|
{import.meta.env.DEV && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ import { projectDir } from "./shared/dir"
|
|||||||
const isCF = process.env.CF_PAGES
|
const isCF = process.env.CF_PAGES
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
resolve: {
|
|
||||||
mainFields: ["module"],
|
|
||||||
},
|
|
||||||
plugins: [
|
plugins: [
|
||||||
TanStackRouterVite({
|
TanStackRouterVite({
|
||||||
autoCodeSplitting: true,
|
autoCodeSplitting: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user