diff --git a/assets/locales/en/messages.json b/assets/locales/en/messages.json
index 134697b..b97e8e9 100644
--- a/assets/locales/en/messages.json
+++ b/assets/locales/en/messages.json
@@ -148,5 +148,11 @@
},
"current": {
"message": "Current"
+ },
+ "paginationPrevious": {
+ "message": "Previous"
+ },
+ "paginationNext": {
+ "message": "Next"
}
}
diff --git a/assets/locales/zh_CN/messages.json b/assets/locales/zh_CN/messages.json
index 2da34e1..76d2d32 100644
--- a/assets/locales/zh_CN/messages.json
+++ b/assets/locales/zh_CN/messages.json
@@ -148,5 +148,11 @@
},
"current": {
"message": "当前"
+ },
+ "paginationPrevious": {
+ "message": "上一页"
+ },
+ "paginationNext": {
+ "message": "下一页"
}
}
diff --git a/src/lib/components/Pagination.tsx b/src/lib/components/Pagination.tsx
new file mode 100644
index 0000000..4884710
--- /dev/null
+++ b/src/lib/components/Pagination.tsx
@@ -0,0 +1,102 @@
+import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
+import * as React from "react"
+
+import { Button, type ButtonProps } from "~/lib/components/Button"
+import { cn } from "~/lib/utils"
+
+const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
+
+)
+Pagination.displayName = "Pagination"
+
+const PaginationContent = React.forwardRef<
+ HTMLUListElement,
+ React.ComponentProps<"ul">
+>(({ className, ...props }, ref) => (
+
+))
+PaginationContent.displayName = "PaginationContent"
+
+const PaginationItem = React.forwardRef<
+ HTMLLIElement,
+ React.ComponentProps<"li">
+>(({ className, ...props }, ref) => (
+
+))
+PaginationItem.displayName = "PaginationItem"
+
+type PaginationLinkProps = {
+ isActive?: boolean
+} & Omit
+
+const PaginationLink = ({ isActive, ...props }: PaginationLinkProps) => (
+
+)
+PaginationLink.displayName = "PaginationLink"
+
+const PaginationPrevious = ({
+ className,
+ ...props
+}: React.ComponentProps) => (
+
+
+ {chrome.i18n.getMessage("paginationPrevious")}
+
+)
+PaginationPrevious.displayName = "PaginationPrevious"
+
+const PaginationNext = ({
+ className,
+ ...props
+}: React.ComponentProps) => (
+
+ {chrome.i18n.getMessage("paginationNext")}
+
+
+)
+PaginationNext.displayName = "PaginationNext"
+
+const PaginationEllipsis = ({
+ className,
+ ...props
+}: React.ComponentProps<"span">) => (
+
+
+
+)
+PaginationEllipsis.displayName = "PaginationEllipsis"
+
+export {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+}
diff --git a/src/options/routes/Rules.tsx b/src/options/routes/Rules.tsx
index 3808667..8f26d9d 100644
--- a/src/options/routes/Rules.tsx
+++ b/src/options/routes/Rules.tsx
@@ -1,5 +1,5 @@
import _ from "lodash"
-import { useEffect, useState } from "react"
+import { useEffect, useMemo, useState } from "react"
import { sendToBackground } from "@plasmohq/messaging"
@@ -9,13 +9,139 @@ import {
AccordionItem,
AccordionTrigger,
} from "~/lib/components/Accordion"
-import { Card, CardContent } from "~/lib/components/Card"
+import { Card, CardContent, CardFooter } from "~/lib/components/Card"
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "~/lib/components/Pagination"
import report from "~/lib/report"
import { getRulesCount, parseRules } from "~/lib/rules"
import type { Rules as IRules } from "~/lib/types"
+function RulesPagination({
+ currentPage,
+ setCurrentPage,
+ pageSize,
+ itemsCount,
+}: {
+ currentPage: number
+ setCurrentPage: (page: number) => void
+ pageSize: number
+ itemsCount: number
+}) {
+ const totalPage = Math.ceil(itemsCount / pageSize)
+ return (
+
+
+
+ setCurrentPage(currentPage - 1)}
+ />
+
+ {Array.from({ length: totalPage }).map((_, index) => {
+ const page = index + 1
+ if (
+ page === 1 ||
+ page === totalPage ||
+ (page >= currentPage - 1 && page <= currentPage + 1)
+ ) {
+ return (
+
+ setCurrentPage(page)}
+ >
+ {page}
+
+
+ )
+ } else if (page === currentPage - 2 || page === currentPage + 2) {
+ return (
+
+
+
+ )
+ }
+ })}
+
+ = totalPage}
+ onClick={() => setCurrentPage(currentPage + 1)}
+ />
+
+
+
+ )
+}
+
+function RulesList({
+ rules,
+ start,
+ end,
+}: {
+ rules: IRules
+ start: number
+ end: number
+}) {
+ const rulesKeys = useMemo(() => Object.keys(rules), [rules])
+
+ return rulesKeys.slice(start, end).map((key) => {
+ const rule = rules[key]
+ return (
+
+
+
+
+
+ {rule._name} - {key}
+
+
+
+
+ {Object.keys(rule).map((item) => {
+ const subdomainRules = rule[item]
+ if (Array.isArray(subdomainRules)) {
+ return subdomainRules.map((subdomainRule, index) => {
+ return (
+
+
+
+
+ {subdomainRule.title}
+
+
+
+
+ )
+ })
+ } else {
+ return null
+ }
+ })}
+
+
+
+
+
+ )
+ })
+}
+
+const pageSize = 20
+
function Rules() {
const [rules, setRules] = useState({})
+ const rulesCount = useMemo(() => getRulesCount(rules), [rules])
+
+ const [currentPage, setCurrentPage] = useState(1)
+ const itemsCount = useMemo(() => Object.keys(rules).length, [rules])
+
useEffect(() => {
sendToBackground({
name: "requestDisplayedRules",
@@ -25,11 +151,6 @@ function Rules() {
})
}, [])
- const [count, setCount] = useState(0)
- useEffect(() => {
- setCount(getRulesCount(rules))
- }, [rules])
-
return (
@@ -37,7 +158,7 @@ function Rules() {
- {chrome.i18n.getMessage("totalNumberOfRules")}: {count}
+ {chrome.i18n.getMessage("totalNumberOfRules")}: {rulesCount}
- {Object.keys(rules).map((key) => {
- const rule = rules[key]
- return (
-
-
-
-
-
- {rule._name} - {key}
-
-
-
-
- {Object.keys(rule).map((item) => {
- const subdomainRules = rule[item]
- if (Array.isArray(subdomainRules)) {
- return subdomainRules.map(
- (subdomainRule, index) => {
- return (
-
-
-
-
- {subdomainRule.title}
-
-
-
-
- )
- },
- )
- } else {
- return null
- }
- })}
-
-
-
-
-
- )
- })}
+
+
+
+