From 22b5938e95fe89e50c636aa1f8ab8d990b5703c9 Mon Sep 17 00:00:00 2001 From: blinko Date: Sat, 9 Nov 2024 14:08:54 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=9Ffeat:=20support=20share=20your=20bl?= =?UTF-8?q?inko!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/locales/de/translation.json | 5 ++- public/locales/en/translation.json | 5 ++- public/locales/es/translation.json | 5 ++- public/locales/fr/translation.json | 5 ++- public/locales/ja/translation.json | 5 ++- public/locales/ko/translation.json | 4 +- public/locales/pt/translation.json | 5 ++- public/locales/ru/translation.json | 5 ++- public/locales/zh-TW/translation.json | 7 +++- public/locales/zh/translation.json | 5 ++- src/components/BlinkoCard/index.tsx | 24 +++++++---- src/components/BlinkoRightClickMenu/index.tsx | 22 ++++++++++ src/components/Layout/index.tsx | 5 +-- src/pages/share.tsx | 41 +++++++++++++++++++ src/server/routers/note.ts | 20 ++++++++- src/store/blinkoStore.tsx | 6 +-- src/store/user.ts | 2 +- 17 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 src/pages/share.tsx diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 6101862d..780b7cbd 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -109,5 +109,8 @@ "model-provider": "Modell-Anbieter", "must-start-with-http-s-or-use-api-openai-as-default": "Muss mit http(s):// beginnen oder /api/openai als Standard verwenden", "recovery": "Erholung", - "reviewed": "Überprüft" + "reviewed": "Überprüft", + "created-in": "Erstellt in", + "set-as-public": "Als öffentlich festlegen", + "unset-as-public": "Nicht als öffentlich gekennzeichnet" } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 7b6fd30a..42571d3c 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -109,5 +109,8 @@ "show-less": "Show Less", "show-more": "Show More", "top": "Top", - "cancel-top": "Cancel Top" + "cancel-top": "Cancel Top", + "created-in": "Created in", + "set-as-public": "Set as Public", + "unset-as-public": "Unset as Public" } diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index 62bc7d2e..79ea89f9 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -109,5 +109,8 @@ "convert-to-note": "Convertir en nota", "import": "Importar", "create-successfully": "Crear con éxito", - "insert-sandpack": "Insertar saco de arena" + "insert-sandpack": "Insertar saco de arena", + "created-in": "Creado en", + "set-as-public": "Establecer como público", + "unset-as-public": "Desactivado como Público" } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 3506097c..3b54d468 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -109,5 +109,8 @@ "your-changes-have-been-saved": "Vos modifications ont été enregistrées !", "keep-sign-in": "Garder la connexion", "operation-failed": "L'opération a échoué.", - "reviewed": "Examiné" + "reviewed": "Examiné", + "created-in": "Créé en", + "set-as-public": "Définir comme public", + "unset-as-public": "Non défini comme public" } diff --git a/public/locales/ja/translation.json b/public/locales/ja/translation.json index c3d3208d..5652d936 100644 --- a/public/locales/ja/translation.json +++ b/public/locales/ja/translation.json @@ -109,5 +109,8 @@ "name": "名称", "schedule": "スケジュール", "sign-up": "会員登録", - "the-two-passwords-are-inconsistent": "2つのパスワードは矛盾している" + "the-two-passwords-are-inconsistent": "2つのパスワードは矛盾している", + "created-in": "で作成された。", + "set-as-public": "公開設定", + "unset-as-public": "公開未設定" } diff --git a/public/locales/ko/translation.json b/public/locales/ko/translation.json index aa499345..246d071a 100644 --- a/public/locales/ko/translation.json +++ b/public/locales/ko/translation.json @@ -109,5 +109,7 @@ "note": "참고", "sign-up": "가입하기", "upload-file": "파일 업로드", - "your-changes-have-been-saved": "변경 사항이 저장되었습니다!" + "your-changes-have-been-saved": "변경 사항이 저장되었습니다!", + "created-in": "에 생성됨", + "unset-as-public": "공개로 설정 해제" } diff --git a/public/locales/pt/translation.json b/public/locales/pt/translation.json index 492bbe39..2e2a49e2 100644 --- a/public/locales/pt/translation.json +++ b/public/locales/pt/translation.json @@ -108,5 +108,8 @@ "basic-information": "Informações básicas", "convert-to-blinko": "Converter para Blinko", "recovery": "Recuperação", - "detail": "Detalhes" + "detail": "Detalhes", + "created-in": "Criado em", + "set-as-public": "Definir como público", + "unset-as-public": "Não definido como público" } diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 88cc0d89..f58e68f5 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -109,5 +109,8 @@ "note": "Примечание", "sign-in": "Войти", "total": "Всего", - "model-provider": "Поставщик моделей" + "model-provider": "Поставщик моделей", + "created-in": "Создан в", + "set-as-public": "Установить как общедоступный", + "unset-as-public": "Не установлен как общественный" } diff --git a/public/locales/zh-TW/translation.json b/public/locales/zh-TW/translation.json index d2384650..247e0e97 100644 --- a/public/locales/zh-TW/translation.json +++ b/public/locales/zh-TW/translation.json @@ -109,5 +109,8 @@ "show-more": "展開", "top": "置頂", "cancel-top": "取消置頂", - "save": "保存" - } \ No newline at end of file + "save": "保存", + "created-in": "创建于", + "set-as-public": "设置为公开", + "unset-as-public": "取消公开" +} diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 0bbd1916..cef277ac 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -109,5 +109,8 @@ "show-more": "展开", "top": "置顶", "cancel-top": "取消置顶", - "save": "保存" + "save": "保存", + "created-in": "创建于", + "set-as-public": "设置为公开", + "unset-as-public": "取消公开" } diff --git a/src/components/BlinkoCard/index.tsx b/src/components/BlinkoCard/index.tsx index c2d38841..1e9b127a 100644 --- a/src/components/BlinkoCard/index.tsx +++ b/src/components/BlinkoCard/index.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react-lite"; import { BlinkoStore } from '@/store/blinkoStore'; -import { Card, Popover, PopoverContent, PopoverTrigger } from '@nextui-org/react'; +import { Card, Popover, PopoverContent, PopoverTrigger, Tooltip } from '@nextui-org/react'; import { _ } from '@/lib/lodash'; import { useTranslation } from 'react-i18next'; import { RootStore } from '@/store'; @@ -14,7 +14,7 @@ import { Note, NoteType } from '@/server/types'; import { LeftCickMenu } from "../BlinkoRightClickMenu"; import { useMediaQuery } from "usehooks-ts"; -export const BlinkoCard = observer(({ blinkoItem }: { blinkoItem: Note }) => { +export const BlinkoCard = observer(({ blinkoItem, isShareMode = false }: { blinkoItem: Note, isShareMode?: boolean }) => { const { t } = useTranslation(); const isPc = useMediaQuery('(min-width: 768px)') const blinko = RootStore.Get(BlinkoStore) @@ -32,10 +32,20 @@ export const BlinkoCard = observer(({ blinkoItem }: { blinkoItem: Note }) => { }}> !isPc && e.stopPropagation()} shadow='none' className={`hover:translate-y-1 mb-4 flex flex-col p-4 bg-background transition-all ${blinko.curMultiSelectIds?.includes(blinkoItem.id!) ? 'border-2 border-primary' : ''}`}> -
-
{dayjs(blinkoItem.updatedAt).fromNow()}
- {blinkoItem.isTop && } - { blinko.curSelectedNote = _.cloneDeep(blinkoItem) }} /> +
+
+ { + blinkoItem.isShare && !isShareMode && + + window.open('/share')} /> + + } +
{dayjs(blinkoItem.updatedAt).fromNow()}
+ {blinkoItem.isTop && } + { + !isShareMode && { blinko.curSelectedNote = _.cloneDeep(blinkoItem) }} /> + } +
{ @@ -58,7 +68,7 @@ export const BlinkoCard = observer(({ blinkoItem }: { blinkoItem: Note }) => {
} { - (dayjs(blinkoItem.createdAt).fromNow() !== dayjs(blinkoItem.updatedAt).fromNow()) &&
Created in {dayjs(blinkoItem.createdAt).fromNow()}
+ (dayjs(blinkoItem.createdAt).fromNow() !== dayjs(blinkoItem.updatedAt).fromNow()) &&
{t('created-in')} {dayjs(blinkoItem.createdAt).fromNow()}
}
diff --git a/src/components/BlinkoRightClickMenu/index.tsx b/src/components/BlinkoRightClickMenu/index.tsx index bbd42cab..841df09b 100644 --- a/src/components/BlinkoRightClickMenu/index.tsx +++ b/src/components/BlinkoRightClickMenu/index.tsx @@ -74,6 +74,20 @@ export const TopItem = observer(() => { }) +export const PublicItem = observer(() => { + const { t } = useTranslation(); + const blinko = RootStore.Get(BlinkoStore) + return
{ + blinko.upsertNote.call({ + id: blinko.curSelectedNote?.id, + isShare: !blinko.curSelectedNote?.isShare + }) + }}> + +
{blinko.curSelectedNote?.isShare ? t('unset-as-public') : t('set-as-public')}
+
+}) + export const ArchivedItem = observer(() => { const { t } = useTranslation(); const blinko = RootStore.Get(BlinkoStore) @@ -119,10 +133,15 @@ export const BlinkoRightClickMenu = observer(() => { + + + + + @@ -147,6 +166,9 @@ export const LeftCickMenu = observer(({ onTrigger, className }: { onTrigger: () + + + diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 9e502e5a..6c1a0f1c 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -36,11 +36,11 @@ export const CommonLayout = observer(({ const user = RootStore.Get(UserStore) const blinkoStore = RootStore.Get(BlinkoStore) const base = RootStore.Get(BaseStore) + let debounceSearch = _.debounce(() => { blinkoStore.noteList.resetAndCall({}) }) - blinkoStore.use() user.use() base.useInitApp(router) @@ -51,7 +51,7 @@ export const CommonLayout = observer(({ if (!isClient) return <> - if (router.pathname == '/signin' || router.pathname == '/signup' || router.pathname == '/api-doc') { + if (router.pathname == '/signin' || router.pathname == '/signup' || router.pathname == '/api-doc' || router.pathname == '/share') { return <>{children} } @@ -87,7 +87,6 @@ export const CommonLayout = observer(({
{blinkoStore.tagList.value?.listTags.length != 0 && blinkoStore.tagList.value?.listTags && <> - }
diff --git a/src/pages/share.tsx b/src/pages/share.tsx new file mode 100644 index 00000000..49bf5dcd --- /dev/null +++ b/src/pages/share.tsx @@ -0,0 +1,41 @@ +import { BlinkoCard } from "@/components/BlinkoCard"; +import { ScrollArea } from "@/components/Common/ScrollArea"; +import { api } from "@/lib/trpc"; +import { RootStore } from "@/store"; +import { PromisePageState } from "@/store/standard/PromiseState"; +import { observer } from "mobx-react-lite"; +import { useEffect } from "react"; +import Masonry from "react-masonry-css"; + +const Page = observer(() => { + const store = RootStore.Local(() => ({ + shareNoteList: new PromisePageState({ + function: async () => { + const notes = await api.notes.publicList.mutate({}) + return notes + } + }) + })) + + useEffect(() => { + store.shareNoteList.resetAndCall() + }, []) + + return store.shareNoteList.callNextPage()}> + + { + store.shareNoteList?.value?.map(i => { + return + }) + } + + +}); + +export default Page \ No newline at end of file diff --git a/src/server/routers/note.ts b/src/server/routers/note.ts index 6b881d19..e7bb7be1 100644 --- a/src/server/routers/note.ts +++ b/src/server/routers/note.ts @@ -1,4 +1,4 @@ -import { router, authProcedure, demoAuthMiddleware } from '../trpc'; +import { router, authProcedure, demoAuthMiddleware, publicProcedure } from '../trpc'; import { z } from 'zod'; import { prisma } from '../prisma'; import { Prisma } from '@prisma/client'; @@ -54,6 +54,20 @@ export const noteRouter = router({ include: { tags: true, attachments: true } }) }), + publicList: publicProcedure.input(z.object({ + page: z.number().optional().default(1), + size: z.number().optional().default(30) + })) + .mutation(async function ({ input }) { + const { page, size } = input + return await prisma.notes.findMany({ + where: { isShare: true }, + orderBy: [{ isTop: "desc" }, { updatedAt: 'desc' }], + skip: (page - 1) * size, + take: size, + include: { tags: true, attachments: true }, + }) + }), detail: authProcedure .input(z.object({ id: z.number(), @@ -84,9 +98,10 @@ export const noteRouter = router({ id: z.number().optional(), isArchived: z.union([z.boolean(), z.null()]).default(null), isTop: z.union([z.boolean(), z.null()]).default(null), + isShare: z.union([z.boolean(), z.null()]).default(null), })) .mutation(async function ({ input }) { - let { id, isArchived, type, attachments, content, isTop } = input + let { id, isArchived, type, attachments, content, isTop, isShare } = input if (content != null) { content = content?.replace(/\\/g, '').replace(/ /g, ' ') } @@ -113,6 +128,7 @@ export const noteRouter = router({ ...(type !== -1 && { type }), ...(isArchived !== null && { isArchived }), ...(isTop !== null && { isTop }), + ...(isShare !== null && { isShare }), ...(content != null && { content }) } diff --git a/src/store/blinkoStore.tsx b/src/store/blinkoStore.tsx index 271b608e..950ac6de 100644 --- a/src/store/blinkoStore.tsx +++ b/src/store/blinkoStore.tsx @@ -45,12 +45,12 @@ export class BlinkoStore implements Store { updateTicker = 0 fullNoteList: Note[] = [] upsertNote = new PromiseState({ - function: async ({ content = null, isArchived, type, id, attachments = [], refresh = true, isTop }: - { content?: string | null, isArchived?: boolean, type?: NoteType, id?: number, attachments?: Attachment[], refresh?: boolean, isTop?: boolean }) => { + function: async ({ content = null, isArchived, type, id, attachments = [], refresh = true, isTop, isShare }: + { content?: string | null, isArchived?: boolean, type?: NoteType, id?: number, attachments?: Attachment[], refresh?: boolean, isTop?: boolean, isShare?: boolean }) => { if (type == undefined) { type = this.noteTypeDefault } - const res = await api.notes.upsert.mutate({ content, type, isArchived, id, attachments, isTop }) + const res = await api.notes.upsert.mutate({ content, type, isArchived, id, attachments, isTop, isShare }) if (res?.id) { api.ai.embeddingUpsert.mutate({ id: res!.id, content: res!.content, type: id ? 'update' : 'insert' }, { context: { skipBatch: true } }) } diff --git a/src/store/user.ts b/src/store/user.ts index 6b83bf76..7d674365 100644 --- a/src/store/user.ts +++ b/src/store/user.ts @@ -59,7 +59,7 @@ export class UserStore implements User, Store { }, [session]); useEffect(() => { eventBus.on('user:signout', () => { - if (router.pathname == '/signup' || router.pathname == '/api-doc') { + if (router.pathname == '/signup' || router.pathname == '/api-doc' || router.pathname == '/share') { return } router.push('/signin')