From dc462a928da92f85b9c6224d25fdc26f77e7be7b Mon Sep 17 00:00:00 2001 From: xiaotiandada Date: Tue, 21 Dec 2021 12:39:46 +0800 Subject: [PATCH 1/5] feat: :airplane: split code, support generate seed pair --- .../components/DeleteLocalDraft/index.less | 2 +- .../components/DeleteLocalDraft/index.tsx | 78 +++++++++++++------ src/utils/gun.ts | 35 +++++++++ 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/src/pages/Settings/components/DeleteLocalDraft/index.less b/src/pages/Settings/components/DeleteLocalDraft/index.less index f134448..e125135 100644 --- a/src/pages/Settings/components/DeleteLocalDraft/index.less +++ b/src/pages/Settings/components/DeleteLocalDraft/index.less @@ -1,5 +1,5 @@ .list { - max-width: 600px; + max-width: 700px; :global { .ant-list-item-meta-avatar .anticon { font-size: 22px; diff --git a/src/pages/Settings/components/DeleteLocalDraft/index.tsx b/src/pages/Settings/components/DeleteLocalDraft/index.tsx index ba8a464..5031641 100644 --- a/src/pages/Settings/components/DeleteLocalDraft/index.tsx +++ b/src/pages/Settings/components/DeleteLocalDraft/index.tsx @@ -3,29 +3,36 @@ import { useIntl, useModel } from 'umi'; import { Typography, Button, Popconfirm, message, Space, Input, List, Dropdown } from 'antd'; import { DeleteOutlined, CloudSyncOutlined } from '@ant-design/icons'; import { dbPostsDeleteAll, dbMetadatasDeleteAll } from '@/db/db'; -import { fetchGunDraftsAndUpdateLocal, deleteDraft, twoWaySyncDrafts } from '@/utils/gun'; -import { storeGet, storeSet } from '@/utils/store'; -import { KEY_META_CMS_GUN_SEED, KEY_META_CMS_GUN_PAIR } from '../../../../../config'; +import { + fetchGunDraftsAndUpdateLocal, + deleteDraft, + twoWaySyncDrafts, + generateSeedAndPair, + getSeedAndPair, + saveSeedAndPair, +} from '@/utils/gun'; import styles from './index.less'; import type { KeyPair } from '@metaio/meta-signature-util'; import { generateKeys } from '@metaio/meta-signature-util'; +import { useMount } from 'ahooks'; const { Text } = Typography; -const ImportSeedAndPairComponents = () => { +interface ImportSeedAndPairComponentsState { + getSeedAndPairFn: () => void; +} + +const ImportSeedAndPairComponents: React.FC = ({ + getSeedAndPairFn, +}) => { const [seedAndPairInput, setSeedAndPairInput] = useState(''); // handle import const handleImport = useCallback(() => { - if (!seedAndPairInput) { - return; - } - - const [seed, pair] = JSON.parse(seedAndPairInput); - storeSet(KEY_META_CMS_GUN_SEED, seed); - storeSet(KEY_META_CMS_GUN_PAIR, pair); + saveSeedAndPair(seedAndPairInput); + getSeedAndPairFn(); message.success('导入成功'); - }, [seedAndPairInput]); + }, [seedAndPairInput, getSeedAndPairFn]); return ( setSeedAndPairInput(e.target.value)} value={seedAndPairInput} /> @@ -37,7 +44,8 @@ const ImportSeedAndPairComponents = () => { export default () => { const intl = useIntl(); const { initialState } = useModel('@@initialState'); - const [syncDraftsLoading, setSyncDraftsLoading] = useState(false); + const [syncDraftsLoading, setSyncDraftsLoading] = useState(false); + const [seedAndPair, setSeedAndPair] = useState(''); /** * handle delete all local draft @@ -80,22 +88,28 @@ export default () => { }, [initialState]); // sync seed and pair - const seedAndPair = useMemo(() => { - // TODO: 复制出来的格式并不好看,可以考虑加密成一串字符然后导入再解密 待考虑 - const seed = storeGet(KEY_META_CMS_GUN_SEED); - const pair = storeGet(KEY_META_CMS_GUN_PAIR); - return JSON.stringify([seed, pair]); + const getSeedAndPairFn = useCallback(() => { + const result = getSeedAndPair(); + setSeedAndPair(result); }, []); // sync seed public key const seedPublicKey = useMemo(() => { - const seed = JSON.parse(storeGet(KEY_META_CMS_GUN_SEED) || '[]'); - if (!seed.length) { + const _seedAndPair = JSON.parse(seedAndPair || '[]'); + if (!_seedAndPair.length) { return ''; } + const seed = JSON.parse(_seedAndPair[0] || '[]'); const keys: KeyPair = generateKeys(seed); return keys.public; - }, []); + }, [seedAndPair]); + + // generate seed pair fn + const generateSeedAndPairFn = useCallback(async () => { + await generateSeedAndPair(); + getSeedAndPairFn(); + message.success('生成成功'); + }, [getSeedAndPairFn]); const list = useMemo( () => [ @@ -134,7 +148,10 @@ export default () => { {seedPublicKey.slice(0, 6)}****{seedPublicKey.slice(-4)} , - } trigger={['click']}> + } + trigger={['click']} + > , { 同步 , + + + , ], }, ], [ handleDeleteAllLocalDraft, twoWaySyncDraftsFn, + generateSeedAndPairFn, intl, seedAndPair, seedPublicKey, @@ -167,6 +197,10 @@ export default () => { ], ); + useMount(() => { + getSeedAndPairFn(); + }); + return ( { const _gun = (window as any).gun.user().get(KEY_GUN_ROOT).get(KEY_GUN_ROOT_DRAFT); _gun.get(userScope).get(key).put(null); }; + +/** + * generate seed pair + */ +export const generateSeedAndPair = async () => { + const seed: string[] = generateSeed(); + const pair = await Gun.SEA.pair(); + + storeSet(KEY_META_CMS_GUN_SEED, JSON.stringify(seed)); + storeSet(KEY_META_CMS_GUN_PAIR, JSON.stringify(pair)); +}; + +/** + * get seed pair + * @returns + */ +export const getSeedAndPair = () => { + // TODO: 复制出来的格式并不好看,可以考虑加密成一串字符然后导入再解密 待考虑 + const seed = storeGet(KEY_META_CMS_GUN_SEED); + const pair = storeGet(KEY_META_CMS_GUN_PAIR); + return JSON.stringify([seed, pair]); +}; + +/** + * save seed pair + */ +export const saveSeedAndPair = (seedAndPair: string) => { + if (!seedAndPair) { + return; + } + + const [seed, pair] = JSON.parse(seedAndPair); + storeSet(KEY_META_CMS_GUN_SEED, seed); + storeSet(KEY_META_CMS_GUN_PAIR, pair); +}; From 3bc72b449bfc7b62fec2dbd360fbe0a36acc90a1 Mon Sep 17 00:00:00 2001 From: xiaotiandada Date: Tue, 21 Dec 2021 18:10:08 +0800 Subject: [PATCH 2/5] feat: :accept: optimization sync draft --- src/db/Posts.d.ts | 18 -- src/db/db.ts | 15 +- .../components/DeleteLocalDraft/index.tsx | 17 +- src/pages/content/drafts/Edit.tsx | 5 +- src/pages/content/drafts/List.tsx | 232 +++++++++--------- src/services/Gun.d.ts | 56 +++++ src/services/Posts.d.ts | 20 ++ src/utils/gun.ts | 117 +++++---- 8 files changed, 278 insertions(+), 202 deletions(-) delete mode 100644 src/db/Posts.d.ts create mode 100644 src/services/Gun.d.ts create mode 100644 src/services/Posts.d.ts diff --git a/src/db/Posts.d.ts b/src/db/Posts.d.ts deleted file mode 100644 index 36c4c65..0000000 --- a/src/db/Posts.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -export interface Posts { - id?: number; - cover: string; - title: string; - summary: string; - content: string; - hash: string; - status: 'pending' | 'publish'; - timestamp: number; - delete: boolean; - post: CMS.Post | null; - draft: CMS.Draft | null; - tags: string[]; - license: string; - userId: number; - createdAt: string; - updatedAt: string; -} diff --git a/src/db/db.ts b/src/db/db.ts index 7bb744b..1bc2ebc 100644 --- a/src/db/db.ts +++ b/src/db/db.ts @@ -1,12 +1,11 @@ import type { Table, Transaction } from 'dexie'; import Dexie from 'dexie'; -import type { Posts } from './Posts'; import type { Metadatas, MetadataTempDataState } from './Metadatas'; import moment from 'moment'; import { License } from '../../config'; export class StoreDB extends Dexie { - posts!: Table; + posts!: Table; metadatas!: Table; constructor() { super('StoreDB'); @@ -19,7 +18,7 @@ export class StoreDB extends Dexie { .upgrade((tx: Transaction | any) => { const time = moment().toISOString(); // TODO: modify typescript - tx.posts.toCollection().modify((post: Posts) => { + tx.posts.toCollection().modify((post: PostType.Posts) => { // console.log('post', post); post.cover = post.cover || ''; post.title = post.title || ''; @@ -62,7 +61,7 @@ export const dbPostsUpdate = async (id: number, data: T): Promise => * @param data * @returns */ -export const dbPostsAdd = async (data: Posts): Promise => { +export const dbPostsAdd = async (data: PostType.Posts): Promise => { return await db.posts.add(data); }; @@ -71,7 +70,7 @@ export const dbPostsAdd = async (data: Posts): Promise => { * @param id * @returns */ -export const dbPostsGet = async (id: number): Promise => { +export const dbPostsGet = async (id: number): Promise => { return await db.posts.get(id); }; @@ -95,7 +94,7 @@ export const dbPostsDeleteAll = async (): Promise => { * @param userId * @returns */ -export const dbPostsAll = async (userId: number): Promise => { +export const dbPostsAll = async (userId: number): Promise => { return await db.posts .filter((i) => !i.delete && i.userId === userId) .reverse() @@ -122,14 +121,14 @@ export const dbPostsWhereExist = async (id: number): Promise => { return result.some((post) => post.post && Number(post.post.id) === id); }; -export const dbPostsWhereByID = async (id: number): Promise => { +export const dbPostsWhereByID = async (id: number): Promise => { // 草稿删除了 允许重新编辑 const result = await db.posts.filter((i) => !i.delete).toArray(); return result.find((post) => post.post && Number(post.post.id) === id); }; // post data temp -export const PostTempData = (): Posts => ({ +export const PostTempData = (): PostType.Posts => ({ cover: '', title: '', summary: '', diff --git a/src/pages/Settings/components/DeleteLocalDraft/index.tsx b/src/pages/Settings/components/DeleteLocalDraft/index.tsx index 5031641..d591946 100644 --- a/src/pages/Settings/components/DeleteLocalDraft/index.tsx +++ b/src/pages/Settings/components/DeleteLocalDraft/index.tsx @@ -27,8 +27,8 @@ const ImportSeedAndPairComponents: React.FC = }) => { const [seedAndPairInput, setSeedAndPairInput] = useState(''); // handle import - const handleImport = useCallback(() => { - saveSeedAndPair(seedAndPairInput); + const handleImport = useCallback(async () => { + await saveSeedAndPair(seedAndPairInput); getSeedAndPairFn(); message.success('导入成功'); @@ -83,8 +83,13 @@ export default () => { } setSyncDraftsLoading(true); - await twoWaySyncDrafts(initialState.currentUser); - setSyncDraftsLoading(false); + try { + await twoWaySyncDrafts(initialState.currentUser); + } catch (e) { + console.error('e', e); + } finally { + setSyncDraftsLoading(false); + } }, [initialState]); // sync seed and pair @@ -157,9 +162,6 @@ export default () => { { handleDeleteAllLocalDraft, twoWaySyncDraftsFn, generateSeedAndPairFn, + getSeedAndPairFn, intl, seedAndPair, seedPublicKey, diff --git a/src/pages/content/drafts/Edit.tsx b/src/pages/content/drafts/Edit.tsx index 17d9883..1deed72 100644 --- a/src/pages/content/drafts/Edit.tsx +++ b/src/pages/content/drafts/Edit.tsx @@ -14,7 +14,6 @@ import { dbMetadatasAdd, MetadataTempData, } from '@/db/db'; -import type { Posts } from '@/db/Posts.d'; import { imageUploadByUrlAPI, getDefaultSiteConfigAPI } from '@/helpers'; import { assign, cloneDeep } from 'lodash'; // import type Vditor from 'vditor'; @@ -52,7 +51,7 @@ import { storeGet } from '@/utils/store'; const Edit: React.FC = () => { const intl = useIntl(); - const [postData, setPostData] = useState({} as Posts); + const [postData, setPostData] = useState({} as PostType.Posts); const [cover, setCover] = useState(''); const [title, setTitle] = useState(''); const [content, setContent] = useState(''); @@ -108,7 +107,7 @@ const Edit: React.FC = () => { // 解密 const msg = await Gun.SEA.verify(data, pair.pub); - const gunDraft = (await Gun.SEA.decrypt(msg, pair)) as Posts; + const gunDraft = (await Gun.SEA.decrypt(msg, pair)) as PostType.Posts; // 如果文章变动 if ( diff --git a/src/pages/content/drafts/List.tsx b/src/pages/content/drafts/List.tsx index 4ae10d0..d6c1aa6 100644 --- a/src/pages/content/drafts/List.tsx +++ b/src/pages/content/drafts/List.tsx @@ -1,16 +1,15 @@ -import { useState, useCallback, useEffect } from 'react'; +import { useState, useCallback, useEffect, useMemo } from 'react'; import { history, useIntl, useModel } from 'umi'; import { PageContainer } from '@ant-design/pro-layout'; import { Table, Tag, Button, Image, Space, Popconfirm, message } from 'antd'; import { dbPostsUpdate, dbMetadatasUpdateByPostId } from '@/db/db'; -import type { Posts } from '@/db/Posts'; import { strSlice } from '@/utils'; import { fetchGunDraftsAndUpdateLocal, deleteDraft } from '@/utils/gun'; -import type { GunDraft } from '@/utils/gun'; +import moment from 'moment'; export default () => { const intl = useIntl(); - const [postsList, setPostsList] = useState([]); + const [postsList, setPostsList] = useState([]); const { initialState } = useModel('@@initialState'); /** handle delete */ @@ -39,124 +38,129 @@ export default () => { const fetchPosts = useCallback(async () => { if (initialState?.currentUser) { const response = await fetchGunDraftsAndUpdateLocal(initialState.currentUser); - setPostsList(response); + const responseSort = response.sort((a, b) => + Number(moment(a.updatedAt).isBefore(b.updatedAt)), + ); + setPostsList(responseSort); } }, [initialState]); - const columns = [ - { - title: 'COVER', - dataIndex: 'cover', - key: 'cover', - width: 100, - render: (val: string) => ( - <> - {val ? ( - e.stopPropagation()} - width={100} - height={50} - src={val} - style={{ objectFit: 'cover' }} - /> - ) : ( -
- )} - - ), - }, - { - title: 'TITLE', - dataIndex: 'title', - key: 'title', - render: (val: string) => {val}, - }, - { - title: 'SUMMARY', - dataIndex: 'summary', - key: 'summary', - render: (val: string) => {strSlice(val, 40)}, - }, - { - title: 'STATUS', - dataIndex: 'status', - key: 'status', - width: 100, - render: (_: any, record: Posts) => ( - - {record.post - ? record.post.state === 'drafted' - ? intl.formatMessage({ - id: 'posts.table.status.cloudDraft', - }) - : record.post.state === 'pending' - ? intl.formatMessage({ - id: 'posts.table.status.pending', - }) - : record.post.state === 'published' - ? intl.formatMessage({ - id: 'posts.table.status.published', - }) + const columns = useMemo(() => { + return [ + { + title: 'COVER', + dataIndex: 'cover', + key: 'cover', + width: 100, + render: (val: string) => ( + <> + {val ? ( + e.stopPropagation()} + width={100} + height={50} + src={val} + style={{ objectFit: 'cover' }} + /> + ) : ( +
+ )} + + ), + }, + { + title: 'TITLE', + dataIndex: 'title', + key: 'title', + render: (val: string) => {val}, + }, + { + title: 'SUMMARY', + dataIndex: 'summary', + key: 'summary', + render: (val: string) => {strSlice(val, 40)}, + }, + { + title: 'STATUS', + dataIndex: 'status', + key: 'status', + width: 100, + render: (_: any, record: PostType.Posts) => ( + + {record.post + ? record.post.state === 'drafted' + ? intl.formatMessage({ + id: 'posts.table.status.cloudDraft', + }) + : record.post.state === 'pending' + ? intl.formatMessage({ + id: 'posts.table.status.pending', + }) + : record.post.state === 'published' + ? intl.formatMessage({ + id: 'posts.table.status.published', + }) + : intl.formatMessage({ + id: 'posts.table.status.localDraft', + }) : intl.formatMessage({ id: 'posts.table.status.localDraft', - }) - : intl.formatMessage({ - id: 'posts.table.status.localDraft', + })} + + ), + }, + { + title: 'ACTION', + dataIndex: 'status', + key: 'status', + width: 180, + render: (val: string, record: GunType.GunDraft) => ( + + {val === 'pending' ? ( + + ) : null} + - ), - }, - { - title: 'ACTION', - dataIndex: 'status', - key: 'status', - width: 180, - render: (val: string, record: GunDraft) => ( - - {val === 'pending' ? ( - - ) : null} - { - e?.stopPropagation(); - console.log(record); - await handleDelete(Number(record.id), record?.key); - await fetchPosts(); - }} - onCancel={(e) => e?.stopPropagation()} - okText={intl.formatMessage({ - id: 'component.button.yes', - })} - cancelText={intl.formatMessage({ - id: 'component.button.no', - })} - > - - - - ), - }, - ]; + > + + + + ), + }, + ]; + }, [fetchPosts, handleDelete, intl]); useEffect(() => { fetchPosts(); @@ -177,7 +181,7 @@ export default () => { } > String(record.id)} + rowKey={(record: PostType.Posts) => `${String(record.id)}}`} onRow={() => { return {}; }} diff --git a/src/services/Gun.d.ts b/src/services/Gun.d.ts new file mode 100644 index 0000000..d5d996a --- /dev/null +++ b/src/services/Gun.d.ts @@ -0,0 +1,56 @@ +declare namespace GunType { + type GunDraft = PostType.Posts & { key?: string }; + type FetchGunDraftsArgs = { + gunDraft: any; + scope: string; + userId: number; + }; + type SyncLocalDraftsArgs = { + drafts: PostType.Posts[]; + gunDrafts: GunDraft[]; + }; + type SyncGunDraftsArgs = { + drafts: GunDraft[]; + userId: number; + }; + type SyncNewDraftArgs = { + id: number; + userId: number; + }; + type SyncDraftArgs = { + userId: number; + key: string; + data: any; + }; + type DeleteDraftArgs = { + userId: number; + key: string; + }; + + type GunAuthSuccess = { + ack: number; + back: unknown; + get: string; + gun: unknown; + id: number; + on: unknown; + opt: unknown; + put: unknown; + root: unknown; + sea: unknown; + soul: string; + tag: unknown; + }; + type GunAuthFailure = { + err: 'Wrong user or password.'; + }; + type GunAuthCb = GunAuthSuccess & GunAuthFailure; + type GunCreateSuccess = { + ok: 0; + pub: string; + }; + type GunCreateFailure = { + err: 'User is already being created or authenticated!' | 'User already created!'; + }; + type GunCreateCb = GunCreateSuccess & GunCreateFailure; +} diff --git a/src/services/Posts.d.ts b/src/services/Posts.d.ts new file mode 100644 index 0000000..c3ecd6f --- /dev/null +++ b/src/services/Posts.d.ts @@ -0,0 +1,20 @@ +declare namespace PostType { + type Posts = { + id?: number; + cover: string; + title: string; + summary: string; + content: string; + hash: string; + status: 'pending' | 'publish'; + timestamp: number; + delete: boolean; + post: CMS.Post | null; + draft: CMS.Draft | null; + tags: string[]; + license: string; + userId: number; + createdAt: string; + updatedAt: string; + }; +} diff --git a/src/utils/gun.ts b/src/utils/gun.ts index 3f73084..55cf7cc 100644 --- a/src/utils/gun.ts +++ b/src/utils/gun.ts @@ -2,7 +2,6 @@ import { assign, cloneDeep } from 'lodash'; import moment from 'moment'; import Gun from 'gun'; import 'gun/sea'; -import type { Posts } from '@/db/Posts.d'; import { dbPostsUpdate, dbPostsAdd, dbPostsAll, dbPostsGet } from '@/db/db'; import { KEY_GUN_ROOT, @@ -15,41 +14,32 @@ import { storeGet, storeSet } from './store'; import { generateSeed, generateKeys } from '@metaio/meta-signature-util'; import type { KeyPair } from '@metaio/meta-signature-util'; -export type GunDraft = Posts & { key?: string }; -type FetchGunDraftsArgs = { - gunDraft: any; - scope: string; - userId: number; -}; -type SyncLocalDraftsArgs = { - drafts: Posts[]; - gunDrafts: GunDraft[]; -}; -type SyncGunDraftsArgs = { - drafts: GunDraft[]; - userId: number; -}; -type SyncNewDraftArgs = { - id: number; - userId: number; -}; -type SyncDraftArgs = { - userId: number; - key: string; - data: any; -}; -type DeleteDraftArgs = { - userId: number; - key: string; -}; - -export const signIn = (gun: any): Promise => { +export const signIn = (gun: any): Promise => { /** * 判断本地是否生成了用户 * 有 用户登录 * 没有 用户注册, 生成 pair */ + // TODO: 后面再来接入 + // const userGun = gun.user().recall({ sessionStorage: true }); + + const createUser = (user: string, pass: string): Promise => { + return new Promise((resolve, reject) => { + gun.user().create(user, pass, (ack: GunType.GunCreateCb) => { + if (ack.err) { + console.error('ack', ack); + reject(ack.err); + } else if (ack.ok === 0 || ack.pub) { + console.log('success'); + resolve('success'); + } else { + reject('未知错误'); + } + }); + }); + }; + return new Promise(async (resolve, reject) => { // pair const gunPair = JSON.parse(storeGet(KEY_META_CMS_GUN_PAIR) || '""'); @@ -57,7 +47,6 @@ export const signIn = (gun: any): Promise => { // } else { const pair = await Gun.SEA.pair(); - storeSet(KEY_META_CMS_GUN_PAIR, JSON.stringify(pair)); } @@ -65,23 +54,38 @@ export const signIn = (gun: any): Promise => { if (gunSeed.length) { const keys: KeyPair = generateKeys(gunSeed); - const user = gun.user().auth(keys.public, keys.private); - if (user.is) { - console.log('success'); - resolve(); - } else { - console.log('fail'); - reject(); - } + gun.user().auth(keys.public, keys.private, (at: GunType.GunAuthCb) => { + if (at.err) { + console.error('at', at); + if (at.err.includes('Wrong user or password.')) { + createUser(keys.public, keys.private) + .then((response) => { + resolve(response); + }) + .catch((e) => { + reject(e); + }); + } else { + reject(at.err); + } + } else { + console.log('auth success'); + resolve('success'); + } + }); } else { const seed: string[] = generateSeed(); const keys: KeyPair = generateKeys(seed); storeSet(KEY_META_CMS_GUN_SEED, JSON.stringify(seed)); - gun.user().create(keys.public, keys.private, () => { - resolve(); - }); + createUser(keys.public, keys.private) + .then((response) => { + resolve(response); + }) + .catch((e) => { + reject(e); + }); } }); }; @@ -105,7 +109,7 @@ export const fetchGunDrafts = ({ gunDraft, scope, userId, -}: FetchGunDraftsArgs): Promise => { +}: GunType.FetchGunDraftsArgs): Promise => { return new Promise((resolve, reject) => { try { gunDraft.get(scope).once(async (data: any) => { @@ -125,7 +129,7 @@ export const fetchGunDrafts = ({ if (data[key]) { // 解密 const msg = await Gun.SEA.verify(data[key], pair.pub); - const dec = (await Gun.SEA.decrypt(msg, pair)) as GunDraft; + const dec = (await Gun.SEA.decrypt(msg, pair)) as GunType.GunDraft; if (dec) { dec.key = key; @@ -149,7 +153,10 @@ export const fetchGunDrafts = ({ * @param param0 * @returns */ -export const syncLocalDrafts = ({ drafts, gunDrafts }: SyncLocalDraftsArgs): Promise => { +export const syncLocalDrafts = ({ + drafts, + gunDrafts, +}: GunType.SyncLocalDraftsArgs): Promise => { return new Promise(async (resolve, reject) => { try { const _draftsClone = cloneDeep(drafts); @@ -212,7 +219,7 @@ export const syncLocalDrafts = ({ drafts, gunDrafts }: SyncLocalDraftsArgs): Pro * @param param0 * @returns */ -export const syncNewDraft = async ({ id, userId }: SyncNewDraftArgs): Promise => { +export const syncNewDraft = async ({ id, userId }: GunType.SyncNewDraftArgs): Promise => { await signIn((window as any).gun); const userScope = `user_${userId}`; @@ -235,7 +242,7 @@ export const syncNewDraft = async ({ id, userId }: SyncNewDraftArgs): Promise => { +export const syncDraft = async ({ userId, key, data }: GunType.SyncDraftArgs): Promise => { await signIn((window as any).gun); const userScope = `user_${userId}`; @@ -258,7 +265,7 @@ export const syncDraft = async ({ userId, key, data }: SyncDraftArgs): Promise => { +export const syncGunDrafts = ({ drafts, userId }: GunType.SyncGunDraftsArgs): Promise => { return new Promise(async (resolve) => { const draftsClone = cloneDeep(drafts); for (let i = 0; i < draftsClone.length; i++) { @@ -286,7 +293,7 @@ export const syncGunDrafts = ({ drafts, userId }: SyncGunDraftsArgs): Promise => { +): Promise => { /** * 获取所有本地文章 * 获取 gun.js 所有文章 @@ -318,7 +325,7 @@ export const fetchGunDraftsAndUpdateLocal = async ( return allDrafts; }; -export const twoWaySyncDrafts = async (user: GLOBAL.CurrentUser): Promise => { +export const twoWaySyncDrafts = async (user: GLOBAL.CurrentUser): Promise => { /** * 获取所有本地文章 * 获取 gun.js 所有文章 @@ -361,7 +368,7 @@ export const twoWaySyncDrafts = async (user: GLOBAL.CurrentUser): Promise { +export const deleteDraft = async ({ userId, key }: GunType.DeleteDraftArgs) => { await signIn((window as any).gun); const userScope = `user_${userId}`; @@ -378,6 +385,9 @@ export const generateSeedAndPair = async () => { storeSet(KEY_META_CMS_GUN_SEED, JSON.stringify(seed)); storeSet(KEY_META_CMS_GUN_PAIR, JSON.stringify(pair)); + + sessionStorage.clear(); + await signIn((window as any).gun); }; /** @@ -394,7 +404,7 @@ export const getSeedAndPair = () => { /** * save seed pair */ -export const saveSeedAndPair = (seedAndPair: string) => { +export const saveSeedAndPair = async (seedAndPair: string) => { if (!seedAndPair) { return; } @@ -402,4 +412,7 @@ export const saveSeedAndPair = (seedAndPair: string) => { const [seed, pair] = JSON.parse(seedAndPair); storeSet(KEY_META_CMS_GUN_SEED, seed); storeSet(KEY_META_CMS_GUN_PAIR, pair); + + sessionStorage.clear(); + await signIn((window as any).gun); }; From 0731a325d574e4e23fa28791a0ed1c2fc7db7f92 Mon Sep 17 00:00:00 2001 From: xiaotiandada Date: Tue, 21 Dec 2021 18:16:28 +0800 Subject: [PATCH 3/5] feat: :+1: update editor tips text --- src/locales/en-US/editor.ts | 2 +- src/locales/zh-CN/editor.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/en-US/editor.ts b/src/locales/en-US/editor.ts index a28d6e1..c2d69fc 100644 --- a/src/locales/en-US/editor.ts +++ b/src/locales/en-US/editor.ts @@ -46,7 +46,7 @@ export default { 'editor.publish.item.gateway.label': 'Backup storage', 'editor.publish.item.gateway.description': 'Store all and cannot be deleted', 'editor.tips.content': - 'When you submit an article and choose to directly store your metadata in IPFS, it will not go through any backend or database of Meta Network, reducing the possibility of man-in-the-middle attacks. If you want the content to be displayed in your Meta Space, you need to return to the CMS for publishing after submission.', + 'When you submit an article and choose to directly store your metadata in IPFS, it will reducing the possibility of man-in-the-middle attacks as much as possible. If you want the content to be displayed in your Meta Space, you need to return to the CMS for publishing after submission.', 'editor.originalLink.title': 'Original link', 'editor.originalLink.noOriginalLink': 'No original link', 'editor.learn.content': 'Quickly learn the Meta Space editor', diff --git a/src/locales/zh-CN/editor.ts b/src/locales/zh-CN/editor.ts index d0cfe6e..e30ed10 100644 --- a/src/locales/zh-CN/editor.ts +++ b/src/locales/zh-CN/editor.ts @@ -41,7 +41,7 @@ export default { 'editor.publish.item.gateway.label': '备份存储', 'editor.publish.item.gateway.description': '存储全文,且无法删除', 'editor.tips.content': - '当您提交文章并选择在 IPFS 直接存证您的元数据时,不会经过 Meta Network 的任何后台或数据库,减少中间人攻击的可能性。若要让内容在您的 Meta Space 中显示,则需要您在提交完成后返回 CMS 进行发布。', + '当您提交文章并选择在 IPFS 直接存证您的元数据时,会最大可能减少中间人攻击的可能性。若要让内容在您的 Meta Space 中显示,则需要您在提交完成后返回 CMS 进行发布。', 'editor.originalLink.title': '原文链接', 'editor.originalLink.noOriginalLink': '没有原文链接', 'editor.learn.content': '快速学习 Meta Space 编辑器', From 5e30ceee6c417d61fbf3a515710df6fb8879aa12 Mon Sep 17 00:00:00 2001 From: xiaotiandada Date: Tue, 21 Dec 2021 19:20:29 +0800 Subject: [PATCH 4/5] feat: :100: set editor height --- src/components/Editor/index.tsx | 5 +++++ src/pages/content/drafts/Edit.less | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/Editor/index.tsx b/src/components/Editor/index.tsx index 195fbf3..52557b7 100644 --- a/src/components/Editor/index.tsx +++ b/src/components/Editor/index.tsx @@ -33,7 +33,12 @@ const Editor: React.FC = React.memo(function Editor({ asyncContentToDB }) }, []); const init = useCallback(() => { + const _height = + window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + const vditor = new Vditor('vditor', { + width: '100%', + height: _height - 206, cache: { enable: false, }, diff --git a/src/pages/content/drafts/Edit.less b/src/pages/content/drafts/Edit.less index 808c5a8..783fce0 100644 --- a/src/pages/content/drafts/Edit.less +++ b/src/pages/content/drafts/Edit.less @@ -19,6 +19,6 @@ margin: 0 auto; padding: 100px 10px 0 10px; @media screen and (max-width: 1420px) { - padding-top: 35px; + // padding-top: 35px; } } From a1b2ab6459f438c01513d78c84eef5131755d814 Mon Sep 17 00:00:00 2001 From: xiaotiandada Date: Tue, 21 Dec 2021 19:25:38 +0800 Subject: [PATCH 5/5] feat: :apple: modify editor width --- src/pages/content/drafts/Edit.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/content/drafts/Edit.less b/src/pages/content/drafts/Edit.less index 783fce0..48f1944 100644 --- a/src/pages/content/drafts/Edit.less +++ b/src/pages/content/drafts/Edit.less @@ -15,9 +15,9 @@ .edit { box-sizing: border-box; - max-width: 1020px; + max-width: 2080px; margin: 0 auto; - padding: 100px 10px 0 10px; + padding: 100px 40px 0 40px; @media screen and (max-width: 1420px) { // padding-top: 35px; }