Merge branch 'feat/support-get-encoded-collab-event' of https://github.com/AppFlowy-IO/AppFlowy into feat/support-get-encoded-collab-event

This commit is contained in:
Lucas.Xu 2024-07-03 10:21:20 +08:00
commit 38f49d617f
11 changed files with 102 additions and 24 deletions

View File

@ -68,20 +68,22 @@ const createServer = async (req) => {
publishName, publishName,
] = reqUrl.pathname.slice(1).split('/'); ] = reqUrl.pathname.slice(1).split('/');
logger.info(`Namespace: ${namespace}, Puganblish Name: ${publishName}`); logger.info(`Namespace: ${namespace}, Publish Name: ${publishName}`);
if (namespace === '' || !publishName) {
timer();
return new Response(null, {
status: 302,
headers: {
'Location': 'https://appflowy.io',
},
});
}
if (req.method === 'GET') { if (req.method === 'GET') {
if (namespace === '' || !publishName) {
timer();
return new Response(null, {
status: 302,
headers: {
'Location': 'https://appflowy.io',
},
});
}
let metaData; let metaData;
try { try {
metaData = await fetchMetaData(`${BASE_URL}/api/workspace/published/${namespace}/${publishName}`); metaData = await fetchMetaData(`${BASE_URL}/api/workspace/published/${namespace}/${publishName}`);
} catch (error) { } catch (error) {

View File

@ -42,3 +42,17 @@ export async function openCollabDB(docName: string): Promise<YDoc> {
return doc as YDoc; return doc as YDoc;
} }
export async function closeCollabDB(docName: string) {
const name = `${databasePrefix}_${docName}`;
if (openedSet.has(name)) {
openedSet.delete(name);
}
const doc = new Y.Doc();
const provider = new IndexeddbPersistence(name, doc);
await provider.destroy();
}

View File

@ -7,7 +7,7 @@ import {
YSharedRoot, YSharedRoot,
} from '@/application/collab.type'; } from '@/application/collab.type';
import { applyYDoc } from '@/application/ydoc/apply'; import { applyYDoc } from '@/application/ydoc/apply';
import { db, openCollabDB } from '@/application/db'; import { closeCollabDB, db, openCollabDB } from '@/application/db';
import { Fetcher, StrategyType } from '@/application/services/js-services/cache/types'; import { Fetcher, StrategyType } from '@/application/services/js-services/cache/types';
export function collabTypeToDBType(type: CollabType) { export function collabTypeToDBType(type: CollabType) {
@ -226,3 +226,13 @@ export async function getBatchCollabs(names: string[]) {
return collabs; return collabs;
} }
export async function deleteViewMeta(name: string) {
await db.view_metas.delete(name);
}
export async function deleteView(name: string) {
console.log('deleteView', name);
await deleteViewMeta(name);
await closeCollabDB(name);
}

View File

@ -1,5 +1,11 @@
import { YDoc } from '@/application/collab.type'; import { YDoc } from '@/application/collab.type';
import { getBatchCollabs, getPublishView, getPublishViewMeta } from '@/application/services/js-services/cache'; import {
deleteView,
getBatchCollabs,
getPublishView,
getPublishViewMeta,
hasViewMetaCache,
} from '@/application/services/js-services/cache';
import { StrategyType } from '@/application/services/js-services/cache/types'; import { StrategyType } from '@/application/services/js-services/cache/types';
import { fetchPublishView, fetchPublishViewMeta, fetchViewInfo } from '@/application/services/js-services/fetch'; import { fetchPublishView, fetchPublishViewMeta, fetchViewInfo } from '@/application/services/js-services/fetch';
import { AFService, AFServiceConfig } from '@/application/services/services.type'; import { AFService, AFServiceConfig } from '@/application/services/services.type';
@ -56,8 +62,20 @@ export class AFClientService implements AFService {
const isLoaded = this.publishViewLoaded.has(name); const isLoaded = this.publishViewLoaded.has(name);
const doc = await getPublishView( const doc = await getPublishView(
() => { async () => {
return fetchPublishView(namespace, publishName); try {
return await fetchPublishView(namespace, publishName);
} catch (e) {
void (async () => {
if (await hasViewMetaCache(name)) {
this.publishViewLoaded.delete(name);
void deleteView(name);
window.location.reload();
}
})();
return Promise.reject(e);
}
}, },
{ {
namespace, namespace,

View File

@ -8,6 +8,7 @@ const AppMain = withAppWrapper(() => {
return ( return (
<Routes> <Routes>
<Route path={'/:namespace/:publishName'} element={<PublishPage />} /> <Route path={'/:namespace/:publishName'} element={<PublishPage />} />
<Route path='/404' element={<NotFound />} />
<Route path='*' element={<NotFound />} /> <Route path='*' element={<NotFound />} />
</Routes> </Routes>
); );

View File

@ -41,7 +41,7 @@ export const LinkPreview = memo(
{data ? ( {data ? (
<div <div
className={ className={
'container-bg flex w-full cursor-pointer select-none items-center gap-4 rounded border border-line-divider bg-fill-list-active p-3' 'container-bg flex w-full cursor-pointer select-none items-center gap-4 overflow-hidden rounded border border-line-divider bg-fill-list-active p-3'
} }
> >
<img <img
@ -49,10 +49,22 @@ export const LinkPreview = memo(
alt={data.title} alt={data.title}
className={'container h-full w-[25%] rounded bg-cover bg-center'} className={'container h-full w-[25%] rounded bg-cover bg-center'}
/> />
<div className={'flex flex-col justify-center gap-2'}> <div className={'flex flex-col justify-center gap-2 overflow-hidden'}>
<div className={'text-base font-bold text-text-title'}>{data.title}</div> <div
<div className={'text-sm text-text-title'}>{data.description}</div> className={
<div className={'text-xs text-text-caption'}>{url}</div> 'max-h-[48px] overflow-hidden whitespace-pre-wrap break-words text-base font-bold text-text-title'
}
>
{data.title}
</div>
<div
className={
'max-h-[64px] overflow-hidden truncate whitespace-pre-wrap break-words text-sm text-text-title'
}
>
{data.description}
</div>
<div className={'truncate whitespace-nowrap text-xs text-text-caption'}>{url}</div>
</div> </div>
</div> </div>
) : ( ) : (

View File

@ -1,4 +1,9 @@
.table-block { .table-block {
::-webkit-scrollbar {
width: 8px !important;
height: 8px !important;
}
[id^=table-] { [id^=table-] {
width: fit-content; width: fit-content;
@apply border-t border-l border-line-border; @apply border-t border-l border-line-border;

View File

@ -19,6 +19,7 @@ const drawerWidth = 268;
export function PublishView({ namespace, publishName }: PublishViewProps) { export function PublishView({ namespace, publishName }: PublishViewProps) {
const [doc, setDoc] = useState<YDoc | undefined>(); const [doc, setDoc] = useState<YDoc | undefined>();
const [notFound, setNotFound] = useState<boolean>(false); const [notFound, setNotFound] = useState<boolean>(false);
const service = useContext(AFConfigContext)?.service; const service = useContext(AFConfigContext)?.service;
const openPublishView = useCallback(async () => { const openPublishView = useCallback(async () => {
let doc; let doc;
@ -58,6 +59,7 @@ export function PublishView({ namespace, publishName }: PublishViewProps) {
window.removeEventListener('keydown', onKeyDown); window.removeEventListener('keydown', onKeyDown);
}; };
}, [onKeyDown]); }, [onKeyDown]);
if (notFound && !doc) { if (notFound && !doc) {
return <NotFound />; return <NotFound />;
} }

View File

@ -57,7 +57,9 @@ function BreadcrumbItem({ crumb, disableClick = false }: { crumb: Crumb; disable
<SpaceIcon value={extraObj.space_icon || ''} /> <SpaceIcon value={extraObj.space_icon || ''} />
</span> </span>
) : ( ) : (
<span className={'icon'}>{icon || <ViewIcon layout={layout} size={'small'} />}</span> <span className={'icon flex h-5 w-5 items-center justify-center'}>
{icon || <ViewIcon layout={layout} size={'small'} />}
</span>
)} )}
<span <span

View File

@ -8,6 +8,8 @@ import { ReactComponent as MoonIcon } from '@/assets/moon.svg';
import { ReactComponent as SunIcon } from '@/assets/sun.svg'; import { ReactComponent as SunIcon } from '@/assets/sun.svg';
import { ReactComponent as ReportIcon } from '@/assets/report.svg'; import { ReactComponent as ReportIcon } from '@/assets/report.svg';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ReactComponent as Logo } from '@/assets/logo.svg';
import { ReactComponent as AppflowyLogo } from '@/assets/appflowy.svg';
function MoreActions() { function MoreActions() {
const { isDark, setDark } = useContext(ThemeModeContext) || {}; const { isDark, setDark } = useContext(ThemeModeContext) || {};
@ -45,7 +47,7 @@ function MoreActions() {
Icon: ReportIcon, Icon: ReportIcon,
label: t('publish.reportPage'), label: t('publish.reportPage'),
onClick: () => { onClick: () => {
void openUrl('', '_blank'); void openUrl('https://report.appflowy.io/', '_blank');
}, },
}, },
]; ];
@ -85,6 +87,16 @@ function MoreActions() {
<span>{action.label}</span> <span>{action.label}</span>
</button> </button>
))} ))}
<div
onClick={() => {
window.open('https://appflowy.io', '_blank');
}}
className={'flex w-full cursor-pointer items-center justify-center py-2 text-sm text-text-title opacity-50'}
>
Powered by
<Logo className={'ml-3 h-4 w-4'} />
<AppflowyLogo className={'w-20'} />
</div>
</div> </div>
</Popover> </Popover>
</> </>