Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
DIYgod 2023-04-16 20:48:29 +01:00
commit 1d7de9723a
No known key found for this signature in database
35 changed files with 1151 additions and 530 deletions

View File

@ -0,0 +1,133 @@
name: "Next.js Bundle Analysis"
on:
pull_request:
push:
branches:
- "**"
workflow_dispatch:
defaults:
run:
# change this if your nextjs app does not live at the root of the repo
working-directory: ./
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up node
uses: actions/setup-node@v3
with:
node-version: "18.x"
- name: Cache pnpm modules
uses: actions/cache@v3
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }}
- uses: actions/cache@v3
with:
path: |
${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
- uses: pnpm/action-setup@v2.2.4
with:
version: 8.x.x
run_install: true
- name: Restore next build
uses: actions/cache@v3
id: restore-build-cache
env:
cache-name: cache-next-build
with:
# if you use a custom build directory, replace all instances of `.next` in this file with your build directory
# ex: if your app builds to `dist`, replace `.next` with `dist`
path: .next/cache
# change this if you prefer a more strict cache
key: ${{ runner.os }}-build-${{ env.cache-name }}
- name: Build next.js app
# change this if your site requires a custom build command
run: ./node_modules/.bin/next build
# Here's the first place where next-bundle-analysis' own script is used
# This step pulls the raw bundle stats for the current bundle
- name: Analyze bundle
run: npx -p nextjs-bundle-analysis report
- name: Upload bundle
uses: actions/upload-artifact@v3
with:
name: bundle
path: .next/analyze/__bundle_analysis.json
- name: Download base branch bundle stats
uses: dawidd6/action-download-artifact@v2
continue-on-error: true
if: success() && github.event.number
with:
workflow: nextjs_bundle_analysis.yml
branch: ${{ github.event.pull_request.base.ref }}
path: .next/analyze/base
# And here's the second place - this runs after we have both the current and
# base branch bundle stats, and will compare them to determine what changed.
# There are two configurable arguments that come from package.json:
#
# - budget: optional, set a budget (bytes) against which size changes are measured
# it's set to 350kb here by default, as informed by the following piece:
# https://infrequently.org/2021/03/the-performance-inequality-gap/
#
# - red-status-percentage: sets the percent size increase where you get a red
# status indicator, defaults to 20%
#
# Either of these arguments can be changed or removed by editing the `nextBundleAnalysis`
# entry in your package.json file.
- name: Compare with base branch bundle
if: success() && github.event.number
continue-on-error: true
run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare
- name: Get comment body
id: get-comment-body
if: success() && github.event.number
run: |
body=$(cat .next/analyze/__bundle_analysis_comment.txt)
body="${body//'%'/'%25'}"
body="${body//$'\n'/'%0A'}"
body="${body//$'\r'/'%0D'}"
echo ::set-output name=body::$body
- name: Find Comment
uses: peter-evans/find-comment@v2
if: success() && github.event.number
id: fc
with:
issue-number: ${{ github.event.number }}
body-includes: "<!-- __NEXTJS_BUNDLE -->"
- name: Create Comment
uses: peter-evans/create-or-update-comment@v2.1.1
if: success() && github.event.number && steps.fc.outputs.comment-id == 0
with:
issue-number: ${{ github.event.number }}
body: ${{ steps.get-comment-body.outputs.body }}
- name: Update Comment
uses: peter-evans/create-or-update-comment@v2.1.1
if: success() && github.event.number && steps.fc.outputs.comment-id != 0
with:
issue-number: ${{ github.event.number }}
body: ${{ steps.get-comment-body.outputs.body }}
comment-id: ${{ steps.fc.outputs.comment-id }}
edit-mode: replace

4
.gitignore vendored
View File

@ -8,13 +8,15 @@ dist
.env.production
generated/
test-results/
tsconfig.tsbuildinfo
# IDE Specific
.idea
.vscode
.vim
public/sw.js
public/sw.js.map
public/workbox-*.js
public/workbox-*.js.map
public/worker-*.js
public/worker-*.js

93
cspell.json Normal file
View File

@ -0,0 +1,93 @@
{
"version": "0.1",
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"dictionaries": ["typescript", "node", "html", "css", "fonts"],
"ignorePaths": [
"tsconfig.tsbuildinfo",
"pnpm-lock.yaml",
"package.json",
"src/generated/*",
"*.svg",
"*.sql"
],
"words": [
"alicloud",
"atrule",
"Backlinks",
"bilibili",
"cacheable",
"Caddyfile",
"codemirror",
"crossbell",
"crosslog",
"Darkmode",
"datasource",
"Frontmatter",
"gtag",
"headlessui",
"heroicons",
"ipfs",
"jike",
"jsonfeed",
"Katex",
"langchain",
"lastmod",
"mantine",
"mingcute",
"MINTABLE",
"MORALIS",
"nextjs",
"nftscan",
"nocheck",
"nprogress",
"onclickoutside",
"envsubst",
"OPENAI",
"pixiv",
"playstation",
"pnpm",
"poap",
"prefetch",
"proselog",
"Raycast",
"rehype",
"rehyper",
"scroller",
"sortablejs",
"Strikethrough",
"subcomment",
"subfeatures",
"Substack",
"tailwindcss",
"tanstack",
"tokenomics",
"Topbar",
"Unfollow",
"unidata",
"unist",
"unocss",
"urlset",
"wagmi",
"webxr",
"XCHAR",
"xlog",
"zustand",
"keymap",
"autoscaler",
"keyval"
],
"ignoreRegExpList": ["/@servie/", "/[A-Za-z0-9]{46,59}/"],
"ignoreWords": [
"mdast",
"clsx",
"urql",
"ddietr",
"zhtw",
"kindjeff",
"tlsredis",
"aown",
"axfm",
"aincentive"
],
"overrides": []
}

8
global.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
declare module "react" {
export interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
"data-hide-print"?: boolean
"aria-hidden"?: boolean
}
}
export {}

View File

@ -36,6 +36,7 @@ const withPWA = require("next-pwa")({
},
},
{
// cspell:ignore Fipfs
urlPattern: /\/_next\/image\?url=.+%2Fipfs%2F([^/?#]+)$/i,
handler: "CacheFirst",
options: {

View File

@ -18,7 +18,9 @@
"prisma:migrate:resolve": "prisma migrate resolve --preview-feature",
"prisma:generate": "prisma generate",
"prisma:studio": "prisma studio",
"docker:db": "docker-compose -f docker-compose.db.yml up -d"
"docker:db": "docker-compose -f docker-compose.db.yml up -d",
"spell-check": "cspell lint . --no-progress",
"analyze": "NODE_ENV=production ANALYZE=true BUNDLE_ANALYZE=browser next build"
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
@ -150,6 +152,7 @@
"autoprefixer": "10.4.14",
"babel-loader": "^9.1.2",
"cross-spawn": "7.0.3",
"cspell": "^6.31.1",
"esbuild": "0.17.16",
"esbuild-register": "3.4.2",
"eslint": "8.38.0",

File diff suppressed because it is too large Load Diff

View File

@ -26,4 +26,4 @@
"Open text": "xLog offers import and export tools, as well as rich <strong>APIs</strong> and third-party <strong>integrations</strong>. All code is <strong>open source</strong> on GitHub, and all data is <strong>transparent</strong> on the blockchain. xLog has nothing to hide.",
"Creator Incentives text": "In the early stages, xLog provides <aincentive>incentives</aincentive> in <strong>USDC</strong>. We are actively constructing the tokenomics to ensure xLog remain the best place to publish high-quality content.",
"DAO text": "An xLog DAO will be in place, where creators vote with <strong>tokens</strong>."
}
}

View File

@ -31,8 +31,8 @@
"ago": "{{time}}前",
"joined ago": "{{time}}に参加した",
"Mint to an NFT": "NFTとしてミント",
"Like successfull": "いいね済",
"Mint successfull": "ミント済",
"Like successfully": "いいね済",
"Mint successfully": "ミント済",
"like stored": "いいねは安全にブロックチェーンに保存されました。 <2>Crossbell Scan</2> で確認できます。",
"mint stored": "この記事をNFTとしてミントしました。 <2>xChar</2> または <6>Crossbell Scan</6> で確認できます。",
"Got it, thanks!": "了解しました、ありがとうございます!",

View File

@ -36,8 +36,8 @@
"obtained ago": "{{time}}前獲得",
"Like": "點讚",
"Mint to an NFT": "珍藏為 NFT",
"Like successfull": "點讚成功",
"Mint successfull": "珍藏完成~",
"Like successfully": "點讚成功",
"Mint successfully": "珍藏完成~",
"like stored": "你的點讚已被安全地儲存在區塊鏈上,可以在 <2>Crossbell Scan</2> 上查看",
"mint stored": "你已將這篇文章珍藏成 NFT可以在 <2>xChar</2> 或 <6>Crossbell Scan</6> 上查看",
"Got it, thanks!": "知道啦,感恩的心~",
@ -71,11 +71,11 @@
"Tip the post: {{name}}": "贊助文章:{{name}}",
"Custom": "自訂",
"Mintable": "Mintable",
"Comming soon": "即將推出",
"Successfully followed": "嘿!你已經開始<2>追蹤他們的最新動態</2>囉。",
"Enable AI Filtering": "AI 過濾",
"Filter out possible low-quality content based on AI ratings.": "基於 AI 評分過濾可能不佳的內容",
"Refreshing": "重新載入中",
"Search for your interest": "搜你所想",
"results": "項結果"
}
"results": "項結果",
"My xLog": "你的 xLog"
}

View File

@ -175,7 +175,7 @@
"Join xLog's Discord channel": "加入 xLog 的 Discord 頻道",
"Participate in the development of xLog": "參與 xLog 的發展",
"Follow xLog's Twitter": "追蹤 xLog 的 Twitter",
"Check out the updates of other bloggers": "看看其他 Bloger 的更新",
"Check out the updates of other bloggers": "看看其他 Blogger 的更新",
"You have already imported them, please enter the post page to create a new post!": "已經匯入完成了哦,請到文章頁面新增新的內容!",
"Today": "今天",
"This month": "本月",

View File

@ -36,8 +36,8 @@
"obtained ago": "{{time}}前获得",
"Like": "点赞",
"Mint to an NFT": "珍藏为 NFT",
"Like successfull": "点赞成功",
"Mint successfull": "珍藏成功",
"Like successfully": "点赞成功",
"Mint successfully": "珍藏成功",
"like stored": "你的点赞已被安全地存储在区块链上,可以在 <2>Crossbell Scan</2> 上查看",
"mint stored": "你已将此篇文章珍藏成NFT, 可以在 <2>xChar</2> 或 <6>Crossbell Scan</6> 上查看",
"Got it, thanks!": "好的,谢谢!",
@ -71,7 +71,6 @@
"Tip the post: {{name}}": "赞赏文章:{{name}}",
"Custom": "自定义",
"Mintable": "可铸造",
"Comming soon": "即将推出",
"Successfully followed": "嘿!你已经准备好<2>在这里跟上你关注的博主的最新动态</2>了。",
"Enable AI Filtering": "启用 AI 过滤",
"Filter out possible low-quality content based on AI ratings.": "基于 AI 评分过滤可能质量不佳的内容。",
@ -79,4 +78,4 @@
"Search for your interest": "搜索你感兴趣的内容",
"results": "条结果",
"My xLog": "我的 xLog"
}
}

View File

@ -1,7 +1,7 @@
import type { AchievementSection } from "~/models/site.model"
import { Image } from "~/components/ui/Image"
import { AchievementModal } from "~/components/common/AchievementModal"
import { useEffect, useState } from "react"
import { useState } from "react"
import { Indicator } from "@mantine/core"
import { useDate } from "~/hooks/useDate"
import { useTranslation } from "next-i18next"
@ -50,14 +50,14 @@ export const AchievementItem: React.FC<{
? group.items.filter((item) => item.status === "MINTABLE").pop()
: null
const achievementComming = isOwner
? group.items.filter((item) => item.status === "COMMING").pop()
const achievementComing = isOwner
? group.items.filter((item) => item.status === "COMING").pop()
: null
const [opened, setOpened] = useState(false)
if (isOwner) {
if (!achievement && !achievementMintable && !achievementComming) {
if (!achievement && !achievementMintable && !achievementComing) {
return null
}
} else {
@ -78,7 +78,7 @@ export const AchievementItem: React.FC<{
>
<Badge
media={
(achievement || achievementMintable || achievementComming)!.info
(achievement || achievementMintable || achievementComing)!.info
.media
}
className={`mb-1 ${!achievement && "grayscale"}`}
@ -122,7 +122,7 @@ export const AchievementItem: React.FC<{
)
.humanize(),
})
: t(achievementMintable ? "Mintable" : "Comming soon")}
: t(achievementMintable ? "Mintable" : "Coming soon")}
</span>
</div>
</div>

View File

@ -5,7 +5,6 @@ import Tilt from "react-parallax-tilt"
import { Badge } from "~/components/common/AchievementItem"
import { Button } from "~/components/ui/Button"
import { useMintAchievement } from "~/queries/site"
import { useRouter } from "next/router"
import { BlockchainIcon } from "~/components/icons/BlockchainIcon"
import { useDate } from "~/hooks/useDate"
import { useTranslation } from "next-i18next"
@ -30,15 +29,15 @@ export const AchievementModal: React.FC<{
? group.items.filter((item) => item.status === "MINTABLE").pop()
: null
const achievementComming = isOwner
? group.items.filter((item) => item.status === "COMMING").pop()
const achievementComing = isOwner
? group.items.filter((item) => item.status === "COMING").pop()
: null
const mintAchievement = useMintAchievement()
const mint = async (tokenId: number) => {
if (characterId) {
await mintAchievement.mutate({
mintAchievement.mutate({
characterId,
achievementId: tokenId,
})
@ -73,8 +72,7 @@ export const AchievementModal: React.FC<{
<div
className="inline-flex flex-col text-center items-center text-white"
key={
(achievement || achievementMintable || achievementComming)!.info
.name
(achievement || achievementMintable || achievementComing)!.info.name
}
>
<Tilt
@ -93,7 +91,7 @@ export const AchievementModal: React.FC<{
fill
alt="achievement"
src={
(achievement || achievementMintable || achievementComming)!.info
(achievement || achievementMintable || achievementComing)!.info
.media
}
className="relative w-full h-full"
@ -108,7 +106,7 @@ export const AchievementModal: React.FC<{
</span>
<span className="text-lg text-black capitalize truncate">
{
(achievement || achievementMintable || achievementComming)!.info
(achievement || achievementMintable || achievementComing)!.info
.description
}
</span>
@ -138,7 +136,7 @@ export const AchievementModal: React.FC<{
</span>
</>
) : (
t(achievementMintable ? "Mintable" : "Comming soon")
t(achievementMintable ? "Mintable" : "Coming soon")
)}
</span>
</div>

View File

@ -21,6 +21,7 @@ export const BlockchainInfo: React.FC<{
<Disclosure.Button
className="flex w-full justify-between items-center rounded-lg px-4 py-2 text-left text-gray-900 hover:bg-hover transition-colors md:rounded-xl"
aria-label="toggle chain info"
data-hide-print
>
<span className="flex items-center">
<BlockchainIcon className="mr-1" />

View File

@ -47,7 +47,7 @@ export const CharacterList: React.FC<{
href={getSiteLink({
subdomain: character?.handle,
})}
className="flex items-center space-x-2 text-sm"
className="flex items-center space-x-2 text-sm min-w-0"
>
<CharacterFloatCard siteId={character?.handle}>
<Avatar

View File

@ -16,7 +16,11 @@ export const Comment: React.FC<{
const { t } = useTranslation("common")
return (
<div className={cn("xlog-comment comment", className)} id="comments">
<div
className={cn("xlog-comment comment", className)}
id="comments"
data-hide-print
>
<div className="xlog-comment-count border-b pb-2 mb-6">
<span>
{comments.isLoading

View File

@ -119,6 +119,7 @@ export const Reactions: React.FC<{
window.innerHeight,
},
shapes: ["star"],
// cspell:disable-next-line
colors: ["FFE400", "FFBD00", "E89400", "FFCA6C", "FDFFB8"],
})
}
@ -154,6 +155,7 @@ export const Reactions: React.FC<{
size === "sm" ? "text-sm space-x-3" : "space-x-6 sm:space-x-10",
className,
)}
data-hide-print
>
<div className={cn("xlog-reactions-like flex items-center sm:mb-0")}>
<Button
@ -329,7 +331,7 @@ export const Reactions: React.FC<{
<Modal
open={isLikeOpen}
setOpen={setIsLikeOpen}
title={t("Like successfull") || ""}
title={t("Like successfully") || ""}
>
<div className="p-5">
<Trans i18nKey="like stored">
@ -351,7 +353,7 @@ export const Reactions: React.FC<{
<Modal
open={isMintOpen}
setOpen={setIsMintOpen}
title={t("Mint successfull") || ""}
title={t("Mint successfully") || ""}
>
<div className="p-5">
<Trans i18nKey="mint stored">

View File

@ -1,6 +1,6 @@
import { cn } from "~/lib/utils"
import { useRouter } from "next/router"
import React, { useEffect, useState } from "react"
import React, { useEffect } from "react"
import { DISCORD_LINK, APP_NAME } from "~/lib/env"
import { getSiteLink } from "~/lib/helpers"

View File

@ -1,4 +1,4 @@
import { APP_NAME, SITE_URL } from "~/lib/env"
import { SITE_URL } from "~/lib/env"
import { UniLink } from "../ui/UniLink"
import { Profile, Note } from "~/lib/types"
import Script from "next/script"

View File

@ -66,7 +66,7 @@ export const Editor: React.FC<{
for (let i = 0; i < items.length; i++) {
const file = items[i]?.getAsFile()
if (file) {
await handleDropFile?.(file)
handleDropFile?.(file)
}
}
})()
@ -79,7 +79,7 @@ export const Editor: React.FC<{
{
;(async () => {
for (let i = 0; i < items.length; i++) {
await handleDropFile?.(items[i])
handleDropFile?.(items[i])
}
})()
}

View File

@ -13,7 +13,7 @@ type InputProps<TMultiline extends boolean> = {
} & React.ComponentPropsWithRef<TMultiline extends true ? "textarea" : "input">
export const Input = forwardRef(function Input<
TMutliline extends boolean = false,
TMultiline extends boolean = false,
>(
{
label,
@ -25,8 +25,8 @@ export const Input = forwardRef(function Input<
help,
multiline,
...inputProps
}: InputProps<TMutliline>,
ref: TMutliline extends true
}: InputProps<TMultiline>,
ref: TMultiline extends true
? React.ForwardedRef<HTMLTextAreaElement>
: React.ForwardedRef<HTMLInputElement>,
) {

View File

@ -4,5 +4,6 @@
@import "./code.css";
@import "./prism-dark.css";
@import "./css-var.css";
@import "./print.css";
@import url("https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css");

8
src/css/print.css Normal file
View File

@ -0,0 +1,8 @@
@media print {
nav,
header,
footer,
*[data-hide-print] {
display: none !important;
}
}

View File

@ -1,4 +1,4 @@
/** based on prism tomorror */
/** based on prism tomorrow */
pre,
code {

View File

@ -1,4 +1,3 @@
import { EditorSelection } from "@codemirror/state"
import { ICommand, wrapExecute } from "."
export const Bold: ICommand = {

View File

@ -18,9 +18,9 @@ const useMediaStore = create<IMediaStore>(() => {
const isServerSide = () => typeof window === "undefined"
interface DarkModeConfig {
classNameDark?: string // A className to set "dark mode". Default = "dark-mode".
classNameLight?: string // A className to set "light mode". Default = "light-mode".
element?: HTMLElement | undefined | null // The element to apply the className. Default = `document.body`
classNameDark?: string // A className to set "dark mode". Default = "dark".
classNameLight?: string // A className to set "light mode". Default = "light".
element?: HTMLElement | undefined | null // The element to apply the className. Default = `document.body`.
storageKey?: string // Specify the `localStorage` key. Default = "darkMode". set to `undefined` to disable persistent storage.
}
const darkModeKey = "darkMode"
@ -67,21 +67,28 @@ const useDarkModeInternal = (
}
}
const focusHandler = () => {
const storageValue = getStorage(storageKey)
// if back to page and not storage color mode, switch to follow system
const storageHandler = () => {
const storageValue = getStorage(storageKey, true)
// if not storage color mode, switch to follow system
if (storageValue === undefined) {
setDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches)
} else {
// make multiple pages to switch to dark mode together.
if (storageValue === "true") {
setDarkMode(true)
} else if (storageValue === "false") {
setDarkMode(false)
}
}
}
window.addEventListener("focus", focusHandler)
window.addEventListener("storage", storageHandler)
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", handler)
return () => {
window.removeEventListener("focus", focusHandler)
window.removeEventListener("storage", storageHandler)
window
.matchMedia("(prefers-color-scheme: dark)")
.removeEventListener("change", handler)

View File

@ -1,4 +1,3 @@
import { GetServerSideProps } from "next"
import { fetchGetSite } from "~/queries/site.server"
import { fetchGetPagesBySite } from "~/queries/page.server"
import { PageVisibilityEnum } from "~/lib/types"

View File

@ -11,7 +11,12 @@ export const getKeys = (key: string) => {
return Object.keys(data).filter((k) => k.startsWith(key))
}
export const getStorage = (key: string) => {
export const getStorage = (key: string, noCache?: boolean) => {
if (noCache) {
try {
data = JSON.parse(localStorage.getItem(namespace) || "{}")
} catch (error) {}
}
return data[key]
}

View File

@ -565,7 +565,7 @@ export type AchievementSection = {
items: {
tokenId: number
name: string
status: "INACTIVE" | "MINTABLE" | "MINTED" | "COMMING"
status: "INACTIVE" | "MINTABLE" | "MINTED" | "COMING"
mintedAt: string | null
transactionHash: string | null
info: {
@ -616,7 +616,7 @@ export async function getAchievements(characterId: string) {
},
tokenId: 0,
name: "showcase-superstar",
status: "COMMING",
status: "COMING",
mintedAt: null,
transactionHash: null,
},
@ -644,7 +644,7 @@ export async function getAchievements(characterId: string) {
},
tokenId: 0,
name: "mirror-xyz-migrator",
status: "COMMING",
status: "COMING",
mintedAt: null,
transactionHash: null,
},

View File

@ -4,7 +4,6 @@ import "~/generated/uno.css"
import { Toaster } from "react-hot-toast"
import { createClient, WagmiConfig } from "wagmi"
import { Hydrate, QueryClient } from "@tanstack/react-query"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"
import {
ConnectKitProvider,

View File

@ -161,7 +161,7 @@ export default function SubdomainEditor() {
}
setValues(newValues)
},
[setValues, values, draftKey, isPost, queryClient, subdomain],
[setValues, values, draftKey, isPost, queryClient, subdomain, t],
)
const createOrUpdatePage = useCreateOrUpdatePage()
@ -434,30 +434,30 @@ export default function SubdomainEditor() {
const position = computedPosition()
let selfElement
let selfPostion
let selfPosition
let targetElement
let targetPosition
if (area === "preview") {
selfElement = previewRef.current.parentElement
selfPostion = position.previewElementList
selfPosition = position.previewElementList
targetElement = view.scrollDOM
targetPosition = position.editorElementList
} else {
selfElement = view.scrollDOM
selfPostion = position.editorElementList
selfPosition = position.editorElementList
targetElement = previewRef.current.parentElement
targetPosition = position.previewElementList
}
let scrollElementIndex = 0
for (let i = 0; i < selfPostion.length; i++) {
if (scrollTop < selfPostion[i]) {
for (let i = 0; i < selfPosition.length; i++) {
if (scrollTop < selfPosition[i]) {
scrollElementIndex = i - 1
break
}
}
// scroll to buttom
// scroll to bottom
if (scrollTop >= selfElement.scrollHeight - selfElement.clientHeight) {
targetElement.scrollTop =
targetElement.scrollHeight - targetElement.clientHeight
@ -467,9 +467,9 @@ export default function SubdomainEditor() {
// scroll to position
if (scrollElementIndex >= 0) {
let ratio =
(scrollTop - selfPostion[scrollElementIndex]) /
(selfPostion[scrollElementIndex + 1] -
selfPostion[scrollElementIndex])
(scrollTop - selfPosition[scrollElementIndex]) /
(selfPosition[scrollElementIndex + 1] -
selfPosition[scrollElementIndex])
targetElement.scrollTop =
ratio *
(targetPosition[scrollElementIndex + 1] -

View File

@ -42,7 +42,7 @@ export default function ImportMarkdownPage() {
const mirrorXyz = useGetMirrorXyz({
address: site.data?.metadata?.owner,
})
const checkeMirror = useCheckMirror(site.data?.metadata?.proof)
const checkMirror = useCheckMirror(site.data?.metadata?.proof)
const notes = mirrorXyz?.data?.map((note) => ({
title: note.title,
@ -84,7 +84,7 @@ export default function ImportMarkdownPage() {
return (
<DashboardMain title="Import from Mirror.xyz">
{checkeMirror?.data ? (
{checkMirror?.data ? (
<form onSubmit={handleSubmit}>
<div className="min-w-[270px] max-w-screen-lg flex flex-col space-y-4">
<div>

View File

@ -3,7 +3,7 @@ import { DashboardLayout } from "~/components/dashboard/DashboardLayout"
import { DashboardMain } from "~/components/dashboard/DashboardMain"
import { UniLink } from "~/components/ui/UniLink"
import { Image } from "~/components/ui/Image"
import { DISCORD_LINK, TWITTER_LINK, GITHUB_LINK, APP_NAME } from "~/lib/env"
import { DISCORD_LINK, TWITTER_LINK, GITHUB_LINK } from "~/lib/env"
import { getSiteLink } from "~/lib/helpers"
import type { ReactElement } from "react"
import { useGetSite, useGetStat } from "~/queries/site"
@ -91,7 +91,7 @@ export default function SubdomainIndex() {
<div className="prose p-6 bg-slate-50 rounded-lg relative">
<Trans
i18nKey="hello.welcome"
defaults="<p>👋 Hello there,</p><p>Welcome to use xLog!</p><p>Here're some useful links to get started:</p>"
defaults="<p>👋 Hello there,</p><p>Welcome to use xLog!</p><p>Here are some useful links to get started:</p>"
components={{
p: <p />,
}}

View File

@ -6,7 +6,7 @@ import { Button } from "~/components/ui/Button"
import { useAccountState, useConnectedAction } from "@crossbell/connect-kit"
import { useRefCallback } from "@crossbell/util-hooks"
import { useRouter } from "next/router"
import { GITHUB_LINK, APP_NAME, CSB_SCAN, OUR_DOMAIN } from "~/lib/env"
import { GITHUB_LINK, CSB_SCAN } from "~/lib/env"
import { getSiteLink } from "~/lib/helpers"
import { Link, Element } from "react-scroll"
import { Image } from "~/components/ui/Image"
@ -363,7 +363,7 @@ function Home() {
</p>
</div>
<ul className="pt-10 grid grid-cols-1 sm:grid-cols-3 gap-8">
{feature.subfeatures.map((item, index) => (
{feature.subfeatures.map((item) => (
<li
className="border rounded-xl overflow-hidden bg-white hover:shadow-md hover:scale-105 transition duration-300 cursor-default"
key={item.title}