mirror of
https://github.com/ourongxing/newsnow.git
synced 2025-12-20 01:11:34 +08:00
chore: ui changes
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -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",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.11.0+sha512.0a203ffaed5a3f63242cd064c8fb5892366c103e328079318f78062f24ea8c9d50bc6a47aa3567cabefd824d170e78fa2745ed1f16b132e16436146b7688f19b",
|
||||
"author": {
|
||||
"url": "https://github.com/ourongxing/",
|
||||
"email": "orongxing@gmail.com",
|
||||
"name": "Ou Rongxing"
|
||||
},
|
||||
"homepage": "https://github.com/ourongxing/newsnow",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
/**
|
||||
* 缓存过期时间
|
||||
*/
|
||||
import packageJSON from "../package.json"
|
||||
|
||||
export const TTL = 30 * 60 * 1000
|
||||
/**
|
||||
* 默认刷新间隔, 10 min
|
||||
*/
|
||||
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 clsx from "clsx"
|
||||
import type { SourceID } from "@shared/types"
|
||||
import { Homepage, Version } from "@shared/consts"
|
||||
import logo from "~/assets/react.svg"
|
||||
import { useDark } from "~/hooks/useDark"
|
||||
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() {
|
||||
const currentSection = useAtomValue(currentSectionAtom)
|
||||
const setRefetchSource = useSetAtom(refetchSourcesAtom)
|
||||
@@ -44,15 +49,19 @@ function RefreshButton() {
|
||||
|
||||
export function Header() {
|
||||
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="/">
|
||||
<img src={logo} alt="logo" className="h-8" />
|
||||
<span className="font-mono">NewsNow</span>
|
||||
<a className="btn-pure text-sm mt--2">
|
||||
{`v${Version}`}
|
||||
</a>
|
||||
</Link>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
<RefreshButton />
|
||||
<ThemeToggle />
|
||||
<GithubIcon />
|
||||
</div>
|
||||
</header>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -102,7 +102,12 @@ export function NewsCard({ id, inView, isOverlay, handleListeners }: NewsCardPro
|
||||
className={clsx("flex justify-between p-2 items-center")}
|
||||
>
|
||||
<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">
|
||||
{sources[id].name}
|
||||
</span>
|
||||
@@ -118,14 +123,18 @@ export function NewsCard({ id, inView, isOverlay, handleListeners }: NewsCardPro
|
||||
</div>
|
||||
<NewsList query={query} />
|
||||
<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">
|
||||
<button
|
||||
type="button"
|
||||
className={clsx("i-ph:arrow-clockwise", query.isFetching && "animate-spin")}
|
||||
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>
|
||||
</>
|
||||
@@ -134,14 +143,14 @@ export function NewsCard({ id, inView, isOverlay, handleListeners }: NewsCardPro
|
||||
|
||||
function UpdateTime({ query }: Query) {
|
||||
const updatedTime = useRelativeTime(query.data?.updatedTime ?? "")
|
||||
if (updatedTime) return <span>{`${updatedTime}更新`}</span>
|
||||
if (query.isError) return <span>获取失败</span>
|
||||
if (updatedTime) return `${updatedTime}更新`
|
||||
if (query.isError) return "获取失败"
|
||||
return "加载中..."
|
||||
}
|
||||
|
||||
function Num({ num }: { num: number }) {
|
||||
const color = ["bg-red-900", "bg-red-500", "bg-red-400"]
|
||||
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}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ export function Dnd() {
|
||||
return (
|
||||
<DndWrapper items={items} setItems={setItems}>
|
||||
<motion.div
|
||||
className="grid w-full gap-4"
|
||||
className="grid w-full gap-6"
|
||||
style={{
|
||||
gridTemplateColumns: "repeat(auto-fill, minmax(325px, 1fr))",
|
||||
}}
|
||||
|
||||
@@ -16,7 +16,7 @@ export function Section({ id }: { id: SectionID }) {
|
||||
return (
|
||||
<>
|
||||
<div className="w-full flex justify-center">
|
||||
<div className="flex gap-2 py-4">
|
||||
<div className="flex gap-2 mb-6">
|
||||
{sectionIds.map(section => (
|
||||
<Link
|
||||
key={section}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
||||
import "~/styles/globals.css"
|
||||
import "virtual:uno.css"
|
||||
import type { QueryClient } from "@tanstack/react-query"
|
||||
import { Author, Homepage } from "@shared/consts"
|
||||
import { Header } from "~/components/header"
|
||||
import { useOnReload } from "~/hooks/useOnReload"
|
||||
import { OverlayScrollbar } from "~/components/common/overlay-scrollbar"
|
||||
@@ -26,11 +27,24 @@ function RootComponent() {
|
||||
useOnReload()
|
||||
return (
|
||||
<>
|
||||
<OverlayScrollbar className="md:p-8 p-4 h-full overflow-x-auto">
|
||||
<Header />
|
||||
<Outlet />
|
||||
<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>
|
||||
<main className="min-h-[calc(100vh-11rem)]">
|
||||
<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>
|
||||
{ import.meta.env.DEV && (
|
||||
{import.meta.env.DEV && (
|
||||
<>
|
||||
<ReactQueryDevtools buttonPosition="bottom-left" />
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
|
||||
@@ -11,9 +11,6 @@ import { projectDir } from "./shared/dir"
|
||||
const isCF = process.env.CF_PAGES
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
mainFields: ["module"],
|
||||
},
|
||||
plugins: [
|
||||
TanStackRouterVite({
|
||||
autoCodeSplitting: true,
|
||||
|
||||
Reference in New Issue
Block a user