mirror of
https://github.com/ourongxing/newsnow.git
synced 2026-08-30 17:05:37 +08:00
fix: lock system tab ordering
This commit is contained in:
+8
-5
@@ -96,7 +96,7 @@ function getUpdatedSourceIds() {
|
||||
try {
|
||||
const baseRef = getVersionBaseRef()
|
||||
const ids = new Map<string, number>()
|
||||
if (!baseRef) return []
|
||||
if (!baseRef) return
|
||||
|
||||
const changedFiles = git(["diff", "--name-only", baseRef, "--", "server/sources"])
|
||||
.split("\n")
|
||||
@@ -115,7 +115,6 @@ function getUpdatedSourceIds() {
|
||||
.map(([id]) => id)
|
||||
} catch {
|
||||
consola.warn("Skip updated sources: failed to read git info.")
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,9 +139,13 @@ try {
|
||||
}
|
||||
|
||||
try {
|
||||
const updatedSourceIds = JSON.stringify(getUpdatedSourceIds(), undefined, 2)
|
||||
writeFileSync(join(projectDir, "./shared/updated-sources.ts"), `export const updatedSourceIds = ${updatedSourceIds} as const\n`)
|
||||
consola.info("Generated updated-sources.ts")
|
||||
const updatedSourceIds = getUpdatedSourceIds()
|
||||
if (updatedSourceIds) {
|
||||
writeFileSync(join(projectDir, "./shared/updated-sources.ts"), `export const updatedSourceIds = ${JSON.stringify(updatedSourceIds, undefined, 2)} as const\n`)
|
||||
consola.info("Generated updated-sources.ts")
|
||||
} else {
|
||||
consola.info("Skipped updated-sources.ts")
|
||||
}
|
||||
} catch {
|
||||
consola.error("Failed to generate updated-sources.ts")
|
||||
}
|
||||
|
||||
+9
-2
@@ -38,6 +38,13 @@ const updatedSourceIds = [..._updatedSourceIds] as SourceID[]
|
||||
export const fixedColumnIds = ["focus", "hottest", "realtime", "updated"] as const satisfies Partial<ColumnID>[]
|
||||
export const hiddenColumns = Object.keys(columns).filter(id => !fixedColumnIds.includes(id as any)) as HiddenColumnID[]
|
||||
|
||||
function getSortedSourceIds(type: "hottest" | "realtime") {
|
||||
return typeSafeObjectEntries(sources)
|
||||
.filter(([, v]) => v.type === type && !v.redirect)
|
||||
.map(([k]) => k)
|
||||
.sort((m, n) => m.localeCompare(n))
|
||||
}
|
||||
|
||||
export const metadata: Metadata = typeSafeObjectFromEntries(typeSafeObjectEntries(columns).map(([k, v]) => {
|
||||
switch (k) {
|
||||
case "focus":
|
||||
@@ -48,12 +55,12 @@ export const metadata: Metadata = typeSafeObjectFromEntries(typeSafeObjectEntrie
|
||||
case "hottest":
|
||||
return [k, {
|
||||
name: v.zh,
|
||||
sources: typeSafeObjectEntries(sources).filter(([, v]) => v.type === "hottest" && !v.redirect).map(([k]) => k),
|
||||
sources: getSortedSourceIds("hottest"),
|
||||
}]
|
||||
case "realtime":
|
||||
return [k, {
|
||||
name: v.zh,
|
||||
sources: typeSafeObjectEntries(sources).filter(([, v]) => v.type === "realtime" && !v.redirect).map(([k]) => k),
|
||||
sources: getSortedSourceIds("realtime"),
|
||||
}]
|
||||
case "updated":
|
||||
return [k, {
|
||||
|
||||
@@ -97,6 +97,7 @@ export const originSources = {
|
||||
color: "blue",
|
||||
home: "https://36kr.com",
|
||||
column: "tech",
|
||||
disable: "cf",
|
||||
sub: {
|
||||
quick: {
|
||||
title: "快讯",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"redirect": "36kr-quick",
|
||||
"name": "36氪",
|
||||
"type": "realtime",
|
||||
"disable": "cf",
|
||||
"column": "tech",
|
||||
"home": "https://36kr.com",
|
||||
"color": "blue",
|
||||
@@ -117,6 +118,7 @@
|
||||
"36kr-quick": {
|
||||
"name": "36氪",
|
||||
"type": "realtime",
|
||||
"disable": "cf",
|
||||
"column": "tech",
|
||||
"home": "https://36kr.com",
|
||||
"color": "blue",
|
||||
@@ -126,6 +128,7 @@
|
||||
"36kr-renqi": {
|
||||
"name": "36氪",
|
||||
"type": "hottest",
|
||||
"disable": "cf",
|
||||
"column": "tech",
|
||||
"home": "https://36kr.com",
|
||||
"color": "blue",
|
||||
|
||||
@@ -20,5 +20,5 @@ export const updatedSourceIds = [
|
||||
"bilibili-hot-video",
|
||||
"bilibili-ranking",
|
||||
"kuaishou",
|
||||
"toutiao",
|
||||
"toutiao"
|
||||
] as const
|
||||
|
||||
@@ -21,6 +21,7 @@ export const currentSourcesAtom = atom((get) => {
|
||||
const id = get(currentColumnIDAtom)
|
||||
return get(primitiveMetadataAtom).data[id]
|
||||
}, (get, set, update: Update<SourceID[]>) => {
|
||||
if (get(currentColumnIDAtom) !== "focus") return
|
||||
const _ = update instanceof Function ? update(get(currentSourcesAtom)) : update
|
||||
set(primitiveMetadataAtom, {
|
||||
updatedTime: Date.now(),
|
||||
|
||||
@@ -44,9 +44,7 @@ export function preprocessMetadata(target: PrimitiveMetadata) {
|
||||
.filter(([id]) => initialMetadata[id])
|
||||
.map(([id, s]) => {
|
||||
if (id === "focus") return [id, s.filter(k => sources[k]).map(k => sources[k].redirect ?? k)]
|
||||
const oldS = s.filter(k => initialMetadata[id].includes(k)).map(k => sources[k].redirect ?? k)
|
||||
const newS = initialMetadata[id].filter(k => !oldS.includes(k))
|
||||
return [id, [...oldS, ...newS]]
|
||||
return [id, initialMetadata[id]]
|
||||
}),
|
||||
),
|
||||
},
|
||||
|
||||
@@ -14,12 +14,14 @@ import { useSortable } from "../common/dnd/useSortable"
|
||||
import { OverlayScrollbar } from "../common/overlay-scrollbar"
|
||||
import type { ItemsProps } from "./card"
|
||||
import { CardWrapper } from "./card"
|
||||
import { currentSourcesAtom } from "~/atoms"
|
||||
import { currentColumnIDAtom, currentSourcesAtom } from "~/atoms"
|
||||
|
||||
const AnimationDuration = 200
|
||||
const WIDTH = 350
|
||||
export function Dnd() {
|
||||
const [items, setItems] = useAtom(currentSourcesAtom)
|
||||
const currentColumnID = useAtomValue(currentColumnIDAtom)
|
||||
const sortable = currentColumnID === "focus"
|
||||
const [parent] = useAutoAnimate({ duration: AnimationDuration })
|
||||
useEntireQuery(items)
|
||||
const { width } = useWindowSize()
|
||||
@@ -31,7 +33,7 @@ export function Dnd() {
|
||||
if (!items.length) return null
|
||||
|
||||
return (
|
||||
<DndWrapper items={items} setItems={setItems} isSingleColumn={isMobile}>
|
||||
<DndWrapper items={items} setItems={setItems} isSingleColumn={isMobile} sortable={sortable}>
|
||||
<OverlayScrollbar defer className="overflow-x-auto">
|
||||
<motion.ol
|
||||
className={isMobile
|
||||
@@ -80,7 +82,7 @@ export function Dnd() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SortableCardWrapper id={id} />
|
||||
<SortableCardWrapper id={id} sortable={sortable} />
|
||||
</motion.li>
|
||||
))}
|
||||
</motion.ol>
|
||||
@@ -94,10 +96,11 @@ export function Dnd() {
|
||||
)
|
||||
}
|
||||
|
||||
function DndWrapper({ items, setItems, isSingleColumn, children }: PropsWithChildren<{
|
||||
function DndWrapper({ items, setItems, isSingleColumn, sortable, children }: PropsWithChildren<{
|
||||
items: SourceID[]
|
||||
setItems: (items: SourceID[]) => void
|
||||
isSingleColumn: boolean
|
||||
sortable: boolean
|
||||
}>) {
|
||||
const onDropTargetChange = useCallback(({ location, source }: BaseEventPayload<ElementDragType>) => {
|
||||
const traget = location.current.dropTargets[0]
|
||||
@@ -122,6 +125,8 @@ function DndWrapper({ items, setItems, isSingleColumn, children }: PropsWithChil
|
||||
wait: AnimationDuration,
|
||||
})
|
||||
const { el } = useAtomValue(goToTopAtom)
|
||||
if (!sortable) return children
|
||||
|
||||
return (
|
||||
<DndContext onDropTargetChange={run} autoscroll={el ? { element: el } : undefined}>
|
||||
{children}
|
||||
@@ -166,7 +171,7 @@ function CardOverlay({ id }: { id: SourceID }) {
|
||||
)
|
||||
}
|
||||
|
||||
function SortableCardWrapper({ id }: ItemsProps) {
|
||||
function SortableCardWrapper({ id, sortable }: ItemsProps & { sortable: boolean }) {
|
||||
const {
|
||||
isDragging,
|
||||
setNodeRef,
|
||||
@@ -186,7 +191,7 @@ function SortableCardWrapper({ id }: ItemsProps) {
|
||||
ref={setNodeRef}
|
||||
id={id}
|
||||
isDragging={isDragging}
|
||||
setHandleRef={setHandleRef}
|
||||
setHandleRef={sortable ? setHandleRef : undefined}
|
||||
/>
|
||||
{OverlayContainer && createPortal(<CardOverlay id={id} />, OverlayContainer)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user