feat: remove ai daily report

This commit is contained in:
DIYgod 2025-08-29 21:18:21 +08:00
parent d8bd4f6730
commit 651bc4d099
No known key found for this signature in database
17 changed files with 9 additions and 720 deletions

View File

@ -1,42 +0,0 @@
import { cn } from "@follow/utils/utils"
import { useSetAtom } from "jotai"
import type { FC } from "react"
import { use } from "react"
import { EntryContentPlaceholderContext } from "~/modules/app-layout/entry-content/EntryContentPlaceholderContext"
import { DayOf } from "./constants"
import { DailyReportTitle } from "./daily"
import type { DailyItemProps, DailyView } from "./types"
import { useParseDailyDate } from "./useParseDailyDate"
export const EntryPlaceholderDaily = ({
view,
className,
}: {
view: DailyView
className?: string
}) => (
<div className={cn(className, "mx-auto flex w-full max-w-[75ch] flex-col gap-6")}>
<NormalDailyReportTitle day={DayOf.Today} view={view} />
<NormalDailyReportTitle day={DayOf.Yesterday} view={view} />
</div>
)
const NormalDailyReportTitle: FC<DailyItemProps> = ({ day }) => {
const { title, startDate, endDate } = useParseDailyDate(day)
const setOpenedSummary = useSetAtom(use(EntryContentPlaceholderContext).openedSummary)
return (
<button
type="button"
onClick={() => {
setOpenedSummary(day)
}}
className="border-b last:border-b-0"
>
<DailyReportTitle title={title} startDate={startDate} endDate={endDate} />
</button>
)
}

View File

@ -1,43 +0,0 @@
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@follow/components/ui/tabs/index.jsx"
import { FeedViewType } from "@follow/constants"
import { DayOf } from "./constants"
import { DailyReportModalContent, DailyReportTitle } from "./daily"
import { useParseDailyDate } from "./useParseDailyDate"
const tabs = [DayOf.Today, DayOf.Yesterday]
export const FeedDailyModalContent = () => {
const today = useParseDailyDate(DayOf.Today)
const yesterday = useParseDailyDate(DayOf.Yesterday)
return (
<Tabs defaultValue={DayOf.Today as any} className="flex h-full flex-col">
<TabsList className="w-full">
{tabs.map((tab: any) => (
<TabsTrigger key={tab} value={tab}>
<DailyReportTitle
containerClassName="pb-0"
{...(tab === DayOf.Today ? today : yesterday)}
/>
</TabsTrigger>
))}
</TabsList>
<div className="-mx-2 flex grow flex-col items-center overflow-auto lg:mx-0">
{tabs.map((tab: any) => (
<TabsContent
key={tab}
value={tab}
className="flex grow flex-col data-[state=inactive]:hidden"
>
<DailyReportModalContent
view={FeedViewType.SocialMedia}
{...(tab === DayOf.Today ? today : yesterday)}
/>
</TabsContent>
))}
</div>
</Tabs>
)
}

View File

@ -1,4 +0,0 @@
export enum DayOf {
Today = 1,
Yesterday,
}

View File

@ -1,294 +0,0 @@
import { Spring } from "@follow/components/constants/spring.js"
import { EmptyIcon } from "@follow/components/icons/empty.jsx"
import { CollapseControlled } from "@follow/components/ui/collapse/Collapse.js"
import type { LinkProps } from "@follow/components/ui/link/LinkWithTooltip.js"
import { LoadingCircle } from "@follow/components/ui/loading/index.jsx"
import { ScrollArea } from "@follow/components/ui/scroll-area/index.js"
import {
Tooltip,
TooltipContent,
TooltipPortal,
TooltipTrigger,
} from "@follow/components/ui/tooltip/index.jsx"
import { cn, isBizId } from "@follow/utils/utils"
import { noop } from "foxact/noop"
import type { Components } from "hast-util-to-jsx-runtime"
import { m } from "motion/react"
import { useMemo, useState } from "react"
import { Trans, useTranslation } from "react-i18next"
import { useGeneralSettingSelector } from "~/atoms/settings/general"
import { Markdown } from "~/components/ui/markdown/Markdown"
import { MarkdownLink } from "~/components/ui/markdown/renderers"
import { usePeekModal } from "~/hooks/biz/usePeekModal"
import { useAuthQuery } from "~/hooks/common"
import { apiClient } from "~/lib/api-fetch"
import { defineQuery } from "~/lib/defineQuery"
import { remarkSnowflakeId } from "./plugins/parse-snowflake"
import type { DailyItemProps, DailyView } from "./types"
import { useParseDailyDate } from "./useParseDailyDate"
export const DailyItem = ({
view,
day,
className,
onClick,
isOpened,
}: DailyItemProps & {
isOpened: boolean
onClick: () => void
}) => {
const { title, startDate, endDate } = useParseDailyDate(day)
return (
<CollapseControlled
isOpened={isOpened}
onOpenChange={noop}
collapseId={`${day}`}
hideArrow
contentClassName="flex-1 flex flex-col"
title={
<button type="button" className="container" onClick={onClick}>
<DailyReportTitle title={title} startDate={startDate} endDate={endDate} />
</button>
}
className={cn(className, "mx-auto w-full max-w-lg border-b last:border-b-0")}
>
<DailyReportContent endDate={endDate} view={view} startDate={startDate} />
</CollapseControlled>
)
}
export const DailyReportTitle = ({
endDate,
startDate,
title,
containerClassName,
}: {
title: string
startDate: number
endDate: number
containerClassName?: string
}) => {
const { t } = useTranslation()
const language = useGeneralSettingSelector((s) => s.language)
const locale = useMemo(() => {
try {
return new Intl.Locale(language)
} catch {
return new Intl.Locale("en-US")
}
}, [language])
return (
<m.div
className={cn("flex items-center justify-center gap-2 pb-6 text-base", containerClassName)}
layoutId={`daily-report-title-${title}`}
transition={Spring.presets.smooth}
>
<i className="i-mgc-ai-cute-re" />
<div className="font-medium">{t("ai_daily.title", { title })}</div>
<Tooltip>
<TooltipTrigger asChild>
<i className="i-mgc-question-cute-re text-sm" />
</TooltipTrigger>
<TooltipPortal>
<TooltipContent>
<ul className="list-outside list-decimal text-wrap pl-6 text-left text-sm">
<li>
<Trans
i18nKey="ai_daily.tooltip.content"
components={{
From: (
<span>
{new Date(startDate).toLocaleTimeString(locale, {
weekday: "short",
hour: "numeric",
minute: "numeric",
})}
</span>
),
To: (
<span>
{new Date(endDate + 1).toLocaleTimeString(locale, {
weekday: "short",
hour: "numeric",
minute: "numeric",
})}
</span>
),
}}
/>
</li>
<li>{t("ai_daily.tooltip.update_schedule")}</li>
</ul>
</TooltipContent>
</TooltipPortal>
</Tooltip>
</m.div>
)
}
const useQueryData = ({
endDate,
startDate,
view,
}: Pick<DailyReportContentProps, "view" | "startDate" | "endDate">) =>
useAuthQuery(
defineQuery(["daily", view, startDate, endDate], async () => {
const res = await apiClient.ai.daily.$get({
query: {
startDate: `${+startDate}`,
view: `${view}`,
},
})
return res.data
}),
{
meta: {
persist: true,
},
},
)
interface DailyReportContentProps {
view: DailyView
startDate: number
endDate: number
}
const DailyReportContent: Component<DailyReportContentProps> = ({
endDate,
startDate,
view,
}) => {
const content = useQueryData({ endDate, startDate, view })
const RelatedEntryLink = useState(() => createRelatedEntryLink("modal"))[0]
return (
<div className="relative h-0 flex-1 grow">
<div className="absolute inset-0 flex">
<ScrollArea.ScrollArea mask flex viewportClassName="grow" rootClassName="grow">
{content.isLoading ? (
<LoadingCircle size="large" className="center flex h-[calc(100vh-176px)] text-center" />
) : (
!!content.data && (
<m.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={Spring.smooth(0.35)}
className="overflow-hidden"
>
<Markdown
applyMiddleware={(pipeline) => {
pipeline.use(remarkSnowflakeId)
return pipeline
}}
components={
{
"snowflake-id": SnowflakeId,
a: RelatedEntryLink as Components["a"],
} as any as Components
}
className="prose-sm prose-p:my-1 prose-ul:my-1 prose-ul:list-outside prose-ul:list-disc prose-li:marker:text-accent mt-4 px-6"
>
{content.data}
</Markdown>
</m.div>
)
)}
</ScrollArea.ScrollArea>
</div>
</div>
)
}
export const DailyReportModalContent: Component<DailyReportContentProps> = ({
endDate,
startDate,
view,
}) => {
const content = useQueryData({ endDate, startDate, view })
const { t } = useTranslation()
const RelatedEntryLink = useState(() => createRelatedEntryLink("toast"))[0]
if (!content.data && !content.isLoading)
return (
<div className="center pointer-events-none inset-0 my-8 flex-col gap-4 opacity-80 lg:absolute lg:my-0 lg:translate-y-6">
<EmptyIcon />
<p>{t("ai_daily.no_found")}</p>
</div>
)
return (
<div className="center grow flex-col">
<div className="flex grow flex-col">
{content.isLoading ? (
<LoadingCircle
size="large"
className="center pointer-events-none h-24 text-center lg:absolute lg:inset-0 lg:mt-8 lg:h-auto"
/>
) : content.data ? (
<Markdown
components={{
a: RelatedEntryLink as Components["a"],
}}
className="prose-sm prose-p:my-1 prose-ul:my-1 prose-ul:list-outside prose-ul:list-disc prose-li:marker:text-accent mt-4 grow overflow-auto px-2 lg:h-0 lg:px-6"
>
{content.data}
</Markdown>
) : null}
</div>
</div>
)
}
const createRelatedEntryLink = (variant: "toast" | "modal") => (props: LinkProps) => {
const { href, children } = props
const entryId = isBizId(href) ? href : null
const peekModal = usePeekModal()
if (!entryId) {
return <MarkdownLink {...props} />
}
return (
<button
type="button"
className="follow-link--underline text-text cursor-pointer font-semibold no-underline"
onClick={() => {
peekModal(entryId, variant)
}}
>
{children}
<i className="i-mgc-arrow-right-up-cute-re size-[0.9em] translate-y-[2px] opacity-70" />
</button>
)
}
interface SnowflakeIdProps {
id: string
children?: React.ReactNode
index: number
}
const SnowflakeId: React.FC<SnowflakeIdProps> = ({ id: entryId, index }) => {
const peekModal = usePeekModal()
return (
<button
type="button"
className="follow-link--underline text-text cursor-pointer font-semibold no-underline"
onClick={() => {
peekModal(entryId, "modal")
}}
>
<sup className="inline-flex items-center gap-0.5 font-medium">
<span className="text-[0.65rem] opacity-70">{index}</span>
</sup>
</button>
)
}

View File

@ -1,82 +0,0 @@
import type { Parent } from "mdast"
import type { Node } from "unist"
import { visit } from "unist-util-visit"
interface SnowflakeOptions {
component?: string
}
const SNOWFLAKE_PATTERN = /\[(\d{15,20})\]/g
function isTextNode(node: Node): node is { type: "text"; value: string } {
return node.type === "text"
}
export function remarkSnowflakeId(options: SnowflakeOptions = {}) {
const { component = "snowflake-id" } = options
return (tree: Node) => {
let idIndex = 1
visit(tree, "text", (node, index, parent: Parent) => {
if (!isTextNode(node) || !parent) return
const { value } = node as { value: string }
const matches = Array.from(value.matchAll(SNOWFLAKE_PATTERN))
if (matches.length === 0) return
const result: (Node | string)[] = []
let lastIndex = 0
for (const match of matches) {
if (!Array.isArray(match)) continue
const [fullMatch, snowflakeId] = match
const matchIndex = match.index!
// Add text before the match
if (matchIndex > lastIndex) {
result.push({
type: "text",
// @ts-expect-error
value: value.slice(lastIndex, matchIndex),
})
}
// Add snowflake node
result.push({
type: "snowflakeId",
data: {
hName: component,
hProperties: {
id: snowflakeId,
index: idIndex++,
},
},
// @ts-expect-error
children: [
{
type: "text",
value: fullMatch,
},
],
})
lastIndex = matchIndex + fullMatch.length
}
// Add any remaining text after the last match
if (lastIndex < value.length) {
result.push({
type: "text",
// @ts-expect-error
value: value.slice(lastIndex),
})
}
// Replace the current node with the new nodes
// @ts-expect-error
parent.children.splice(index, 1, ...result)
})
}
}

View File

@ -1,11 +0,0 @@
import type { FeedViewType } from "@follow/constants"
import type { DayOf } from "./constants"
export type DailyView = Extract<FeedViewType, FeedViewType.Articles | FeedViewType.SocialMedia>
export interface DailyItemProps {
view: DailyView
day: DayOf
className?: string
}

View File

@ -1,22 +0,0 @@
import { useCallback } from "react"
import { useTranslation } from "react-i18next"
import { useModalStack } from "~/components/ui/modal/stacked/hooks"
import { FeedDailyModalContent } from "./FeedDailyModalContent"
export const useAIDailyReportModal = () => {
const { present } = useModalStack()
const { t } = useTranslation()
return useCallback(() => {
present({
content: () => <FeedDailyModalContent />,
title: t("ai_daily.header"),
resizeable: true,
clickOutsideToDismiss: true,
resizeDefaultSize: { width: 660, height: 450 },
})
}, [present, t])
}

View File

@ -1,61 +0,0 @@
import { useMemo } from "react"
import { useTranslation } from "react-i18next"
import { DayOf } from "./constants"
export const useParseDailyDate = (day: DayOf) => {
const { t } = useTranslation("common")
return useMemo(() => {
const dateObj = new Date()
const nowHour = dateObj.getHours()
let startDate: number
let endDate: number
let title: string
const today8AM = dateObj.setHours(8, 0, 0, 0)
const today8PM = dateObj.setHours(20, 0, 0, 0)
dateObj.setDate(dateObj.getDate() - 1)
const yesterday8AM = dateObj.setHours(8, 0, 0, 0)
const yesterday8PM = dateObj.setHours(20, 0, 0, 0)
dateObj.setDate(dateObj.getDate() - 1)
const dayBeforeYesterday8PM = dateObj.setHours(20, 0, 0, 0)
const isToday = day === DayOf.Today
// For index 0, get the last past 8 AM or 8 PM; for index 1, get the second last past 8 AM or 8 PM.
if (nowHour >= 20) {
if (isToday) {
endDate = today8PM - 1
startDate = today8AM
title = t("time.today")
} else {
endDate = today8AM - 1
startDate = yesterday8PM
title = t("time.last_night")
}
} else if (nowHour >= 8) {
if (isToday) {
endDate = today8AM - 1
startDate = yesterday8PM
title = t("time.last_night")
} else {
endDate = yesterday8PM - 1
startDate = yesterday8AM
title = t("time.yesterday")
}
} else {
if (isToday) {
endDate = yesterday8PM - 1
startDate = yesterday8AM
title = t("time.yesterday")
} else {
endDate = yesterday8AM - 1
startDate = dayBeforeYesterday8PM
title = t("time.the_night_before_last")
}
}
return { title, startDate, endDate }
}, [day, t])
}

View File

@ -1,106 +1,19 @@
import { CollapseGroup } from "@follow/components/ui/collapse/Collapse.js"
import { FeedViewType } from "@follow/constants"
import { cn } from "@follow/utils/utils"
import { atom, useAtomValue, useSetAtom } from "jotai"
import { AnimatePresence, LayoutGroup, m } from "motion/react"
import * as React from "react"
import { GlassButton } from "~/components/ui/button/GlassButton"
import { ROUTE_FEED_PENDING } from "~/constants"
import { useRouteParams } from "~/hooks/biz/useRouteParams"
import { DayOf } from "~/modules/ai-daily/constants"
import { DailyItem } from "~/modules/ai-daily/daily"
import { EntryPlaceholderDaily } from "~/modules/ai-daily/EntryPlaceholderDaily"
import type { DailyView } from "~/modules/ai-daily/types"
import { EntryPlaceholderLogo } from "~/modules/entry-content/components/EntryPlaceholderLogo"
import type { EntryContentPlaceholderContextValue } from "./EntryContentPlaceholderContext"
import { EntryContentPlaceholderContext } from "./EntryContentPlaceholderContext"
export const EntryContentPlaceholder = () => {
const { feedId, view } = useRouteParams()
const ctxValue = React.useMemo<EntryContentPlaceholderContextValue>(
() => ({
openedSummary: atom<null | DayOf>(null),
}),
[],
)
const openedSummary = useAtomValue(ctxValue.openedSummary)
return (
<LayoutGroup>
<EntryContentPlaceholderContext value={ctxValue}>
<AnimatePresence>
{openedSummary === null ? (
<m.div
className="center size-full flex-col"
initial={{ opacity: 0.01, y: 300 }}
animate={{ opacity: 1, y: 0 }}
>
<EntryPlaceholderLogo />
{feedId === ROUTE_FEED_PENDING && view === FeedViewType.Articles && (
<EntryPlaceholderDaily view={view} />
)}
</m.div>
) : (
<SummaryDetailContent />
)}
</AnimatePresence>
</EntryContentPlaceholderContext>
<AnimatePresence>
<m.div
className="center size-full flex-col"
initial={{ opacity: 0.01, y: 300 }}
animate={{ opacity: 1, y: 0 }}
>
<EntryPlaceholderLogo />
</m.div>
</AnimatePresence>
</LayoutGroup>
)
}
const SummaryDetailContent = () => {
const { view } = useRouteParams()
const ctxValue = React.use(EntryContentPlaceholderContext)
const openedSummary = useAtomValue(ctxValue.openedSummary)
const setOpenedSummary = useSetAtom(ctxValue.openedSummary)
return (
<>
<div className="fade-in-0 absolute right-4 top-4 duration-200">
<GlassButton
description="Back"
onClick={() => setOpenedSummary(null)}
size="sm"
className="opacity-100"
variant="flat"
>
<i className="i-mgc-close-cute-re" />
</GlassButton>
</div>
<CollapseGroup defaultOpenId={`${openedSummary}`}>
<DailyItem
isOpened={openedSummary === DayOf.Today}
onClick={() => {
if (openedSummary === DayOf.Today) {
setOpenedSummary(null)
} else {
setOpenedSummary(DayOf.Today)
}
}}
day={DayOf.Today}
view={view as DailyView}
className={cn(openedSummary === DayOf.Today && "grow", "pt-6")}
/>
<DailyItem
isOpened={openedSummary === DayOf.Yesterday}
onClick={() => {
if (openedSummary === DayOf.Yesterday) {
setOpenedSummary(null)
} else {
setOpenedSummary(DayOf.Yesterday)
}
}}
day={DayOf.Yesterday}
view={view as DailyView}
className={cn(openedSummary === DayOf.Yesterday && "grow", "pt-6")}
/>
</CollapseGroup>
</>
)
}

View File

@ -1,12 +0,0 @@
import type { PrimitiveAtom } from "jotai"
import { createContext } from "react"
import type { DayOf } from "~/modules/ai-daily/constants"
export const EntryContentPlaceholderContext = createContext<EntryContentPlaceholderContextValue>(
null!,
)
export type EntryContentPlaceholderContextValue = {
openedSummary: PrimitiveAtom<null | DayOf>
}

View File

@ -30,7 +30,6 @@ import { useFeedHeaderTitle } from "~/store/feed/hooks"
import { MarkAllReadButton } from "../components/mark-all-button"
import { useIsPreviewFeed } from "../hooks/useIsPreviewFeed"
import { AppendTaildingDivider } from "./AppendTaildingDivider"
import { DailyReportButton } from "./buttons/DailyReportButton"
import { SwitchToMasonryButton } from "./buttons/SwitchToMasonryButton"
import { WideModeButton } from "./buttons/WideModeButton"
@ -99,7 +98,6 @@ export const EntryListHeader: FC<{
<AppendTaildingDivider>
{!views[view]!.wideMode && !aiEnabled && <WideModeButton />}
{view === FeedViewType.SocialMedia && <DailyReportButton />}
{view === FeedViewType.Pictures && <SwitchToMasonryButton />}
</AppendTaildingDivider>

View File

@ -1,23 +0,0 @@
import { ActionButton } from "@follow/components/ui/button/action-button.js"
import { tracker } from "@follow/tracker"
import type { FC } from "react"
import { useTranslation } from "react-i18next"
import { useAIDailyReportModal } from "~/modules/ai-daily/useAIDailyReportModal"
export const DailyReportButton: FC = () => {
const present = useAIDailyReportModal()
const { t } = useTranslation()
return (
<ActionButton
onClick={() => {
present()
tracker.dailyReportModal()
}}
tooltip={t("entry_list_header.daily_report")}
>
<i className="i-mgc-ai-cute-re" />
</ActionButton>
)
}

View File

@ -26,11 +26,6 @@
"activation.plan.title": "Upgrade Plan",
"activation.plan.upgrade": "Upgrade",
"activation.title": "Invitation Code",
"ai_daily.header": "AI Daily Report",
"ai_daily.no_found": "No AI news found for this period.",
"ai_daily.title": "Top News - {{title}}",
"ai_daily.tooltip.content": "Here is news selected by AI from your timeline (<From /> - <To />) that may be important to you.",
"ai_daily.tooltip.update_schedule": "Update daily at 8 AM and 8 PM.",
"app.copy_logo_svg": "Copy Logo SVG",
"app.copy_logo_text_svg": "Copy Logo Text SVG",
"app.toggle_sidebar": "Toggle Sidebar",
@ -188,7 +183,6 @@
"entry_content.support_creator": "Support Creator",
"entry_content.web_app_notice": "Maybe web app doesn't support this content type. But you can download the desktop app.",
"entry_list.zero_unread": "Zero Unread",
"entry_list_header.daily_report": "Daily Report",
"entry_list_header.grid": "Grid",
"entry_list_header.items": "items",
"entry_list_header.masonry": "Masonry",

View File

@ -26,11 +26,6 @@
"activation.plan.title": "プランのアップグレード",
"activation.plan.upgrade": "アップグレード",
"activation.title": "招待コード",
"ai_daily.header": "AI デイリーリポート",
"ai_daily.no_found": "この期間の AI ニュースはありません。",
"ai_daily.title": "トップニュース - {{title}}",
"ai_daily.tooltip.content": "こちらは、AI があなたのタイムラインから選んだニュースです(<From /> - <To />)。あなたにとって重要なニュースかもしれません。",
"ai_daily.tooltip.update_schedule": "毎日午前 8 時と午後 8 時に更新されます。",
"app.copy_logo_svg": "ロゴ SVG をコピー",
"app.copy_logo_text_svg": "ロゴテキスト SVG をコピー",
"app.toggle_sidebar": "サイドバーを切り替え",
@ -188,7 +183,6 @@
"entry_content.support_creator": "作成者をサポート",
"entry_content.web_app_notice": "このコンテンツタイプはウェブアプリではサポートされていないかもしれません。デスクトップアプリをダウンロードしてください。",
"entry_list.zero_unread": "未読ゼロ",
"entry_list_header.daily_report": "日報",
"entry_list_header.grid": "グリッド",
"entry_list_header.items": "項目",
"entry_list_header.masonry": "メイソンリー",

View File

@ -26,11 +26,6 @@
"activation.plan.title": "升级计划",
"activation.plan.upgrade": "升级",
"activation.title": "邀请码",
"ai_daily.header": "AI 日报",
"ai_daily.no_found": "在此期间未找到 AI 新闻。",
"ai_daily.title": "热点 - {{title}}",
"ai_daily.tooltip.content": "AI 根据时间线(<From /> - <To />)提取的重点信息。",
"ai_daily.tooltip.update_schedule": "每天 8:00 和 20:00 定时更新。",
"app.copy_logo_svg": "复制 Logo SVG",
"app.copy_logo_text_svg": "复制徽标 SVG 文本",
"app.toggle_sidebar": "切换侧边栏",
@ -188,7 +183,6 @@
"entry_content.support_creator": "支持作者",
"entry_content.web_app_notice": "网页版不支持展示此类型,请下载客户端查看。",
"entry_list.zero_unread": "全部已读",
"entry_list_header.daily_report": "每日总结",
"entry_list_header.grid": "网格布局",
"entry_list_header.items": "内容",
"entry_list_header.masonry": "瀑布流布局",

View File

@ -23,11 +23,6 @@
"activation.activate": "啟用",
"activation.description": "在公開測試階段,您需要邀請碼才能使用此功能。",
"activation.title": "邀請碼",
"ai_daily.header": "AI 日報",
"ai_daily.no_found": "該期間未找到 AI 新聞",
"ai_daily.title": "頭條新聞 - {{title}}",
"ai_daily.tooltip.content": "以下是 AI 從您的時間軸中選擇的新聞(<From /> - <To />),可能對您很重要。",
"ai_daily.tooltip.update_schedule": "每天早上 8 點和晚上 8 點更新。",
"app.copy_logo_svg": "複製 Logo SVG",
"app.copy_logo_text_svg": "複製圖標 SVG 文字",
"app.toggle_sidebar": "切換側邊欄",
@ -173,7 +168,6 @@
"entry_content.support_creator": "贊助作者",
"entry_content.web_app_notice": "Web 應用程式不支援此類型內容。您可以下載桌面應用程式。",
"entry_list.zero_unread": "全部已讀",
"entry_list_header.daily_report": "每日報告",
"entry_list_header.grid": "格線佈局",
"entry_list_header.items": "內容",
"entry_list_header.masonry": "瀑布式佈局",

View File

@ -43,10 +43,6 @@ export class TrackerPoints {
this.track(TrackerMapper.Integration, props)
}
dailyReportModal() {
this.track(TrackerMapper.DailyReportModal)
}
switchToMasonry() {
this.track(TrackerMapper.SwitchToMasonry)
}