feat!: affine cloud support (#3813)

Co-authored-by: Hongtao Lye <codert.sn@gmail.com>
Co-authored-by: liuyi <forehalo@gmail.com>
Co-authored-by: LongYinan <lynweklm@gmail.com>
Co-authored-by: X1a0t <405028157@qq.com>
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
Co-authored-by: xiaodong zuo <53252747+zuoxiaodong0815@users.noreply.github.com>
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>
Co-authored-by: danielchim <kahungchim@gmail.com>
This commit is contained in:
Alex Yang
2023-08-29 05:07:05 -05:00
committed by GitHub
parent d0145c6f38
commit 2f6c4e3696
414 changed files with 19469 additions and 7591 deletions
@@ -0,0 +1,10 @@
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { useSession } from 'next-auth/react';
export function useCurrenLoginStatus():
| 'authenticated'
| 'unauthenticated'
| 'loading' {
const session = useSession();
return session.status;
}
@@ -0,0 +1,45 @@
import type { DefaultSession } from 'next-auth';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { useSession } from 'next-auth/react';
export type CheckedUser = {
id: string;
name: string;
email: string;
image: string;
hasPassword: boolean;
update: ReturnType<typeof useSession>['update'];
};
// FIXME: Should this namespace be here?
declare module 'next-auth' {
interface Session {
user: {
id: string;
hasPassword: boolean;
} & DefaultSession['user'];
}
}
/**
* This hook checks if the user is logged in.
* If not, it will throw an error.
*/
export function useCurrentUser(): CheckedUser {
const { data: session, status, update } = useSession();
// If you are seeing this error, it means that you are not logged in.
// This should be prohibited in the development environment, please re-write your component logic.
if (status === 'unauthenticated') {
throw new Error('session.status should be authenticated');
}
const user = session?.user;
return {
id: user?.id ?? 'REPLACE_ME_DEFAULT_ID',
name: user?.name ?? 'REPLACE_ME_DEFAULT_NAME',
email: user?.email ?? 'REPLACE_ME_DEFAULT_EMAIL',
image: user?.image ?? 'REPLACE_ME_DEFAULT_URL',
hasPassword: user?.hasPassword ?? false,
update,
};
}
@@ -0,0 +1,30 @@
import type { Permission } from '@affine/graphql';
import { inviteByEmailMutation } from '@affine/graphql';
import { useMutation } from '@affine/workspace/affine/gql';
import { useCallback } from 'react';
import { useMutateCloud } from './use-mutate-cloud';
export function useInviteMember(workspaceId: string) {
const { trigger, isMutating } = useMutation({
mutation: inviteByEmailMutation,
});
const mutate = useMutateCloud();
return {
invite: useCallback(
async (email: string, permission: Permission, sendInviteMail = false) => {
const res = await trigger({
workspaceId,
email,
permission,
sendInviteMail,
});
await mutate();
// return is successful
return res?.invite;
},
[mutate, trigger, workspaceId]
),
isMutating,
};
}
@@ -0,0 +1,57 @@
import {
getWorkspaceSharedPagesQuery,
revokePageMutation,
sharePageMutation,
} from '@affine/graphql';
import { useMutation, useQuery } from '@affine/workspace/affine/gql';
import { useCallback, useMemo } from 'react';
export function useIsSharedPage(
workspaceId: string,
pageId: string
): [isSharedPage: boolean, setSharedPage: (enable: boolean) => void] {
const { data, mutate } = useQuery({
query: getWorkspaceSharedPagesQuery,
variables: {
workspaceId,
},
});
const { trigger: enableSharePage } = useMutation({
mutation: sharePageMutation,
});
const { trigger: disableSharePage } = useMutation({
mutation: revokePageMutation,
});
return [
useMemo(
() => data.workspace.sharedPages.some(id => id === pageId),
[data.workspace.sharedPages, pageId]
),
useCallback(
(enable: boolean) => {
// todo: push notification
if (enable) {
enableSharePage({
workspaceId,
pageId,
})
.then(() => {
return mutate();
})
.catch(console.error);
} else {
disableSharePage({
workspaceId,
pageId,
})
.then(() => {
return mutate();
})
.catch(console.error);
}
mutate().catch(console.error);
},
[disableSharePage, enableSharePage, mutate, pageId, workspaceId]
),
];
}
@@ -0,0 +1,13 @@
import { getIsOwnerQuery } from '@affine/graphql';
import { useQuery } from '@affine/workspace/affine/gql';
export function useIsWorkspaceOwner(workspaceId: string) {
const { data } = useQuery({
query: getIsOwnerQuery,
variables: {
workspaceId,
},
});
return data.isOwner;
}
@@ -0,0 +1,23 @@
import { leaveWorkspaceMutation } from '@affine/graphql';
import { useMutation } from '@affine/workspace/affine/gql';
import { useCallback } from 'react';
import { useAppHelper } from '../use-workspaces';
export function useLeaveWorkspace() {
const { deleteWorkspaceMeta } = useAppHelper();
const { trigger: leaveWorkspace } = useMutation({
mutation: leaveWorkspaceMutation,
});
return useCallback(
async (workspaceId: string) => {
deleteWorkspaceMeta(workspaceId);
await leaveWorkspace({
workspaceId,
});
},
[deleteWorkspaceMeta, leaveWorkspace]
);
}
+19
View File
@@ -0,0 +1,19 @@
import {
type GetMembersByWorkspaceIdQuery,
getMembersByWorkspaceIdQuery,
} from '@affine/graphql';
import { useQuery } from '@affine/workspace/affine/gql';
export type Member = Omit<
GetMembersByWorkspaceIdQuery['workspace']['members'][number],
'__typename'
>;
export function useMembers(workspaceId: string) {
const { data } = useQuery({
query: getMembersByWorkspaceIdQuery,
variables: {
workspaceId,
},
});
return data.workspace.members;
}
@@ -0,0 +1,14 @@
import { useCallback } from 'react';
import { useSWRConfig } from 'swr';
export function useMutateCloud() {
const { mutate } = useSWRConfig();
return useCallback(async () => {
return mutate(key => {
if (Array.isArray(key)) {
return key[0] === 'cloud';
}
return false;
});
}, [mutate]);
}
@@ -0,0 +1,23 @@
import { revokeMemberPermissionMutation } from '@affine/graphql';
import { useMutation } from '@affine/workspace/affine/gql';
import { useCallback } from 'react';
import { useMutateCloud } from './use-mutate-cloud';
export function useRevokeMemberPermission(workspaceId: string) {
const mutate = useMutateCloud();
const { trigger } = useMutation({
mutation: revokeMemberPermissionMutation,
});
return useCallback(
async (userId: string) => {
await trigger({
workspaceId,
userId,
});
await mutate();
},
[mutate, trigger, workspaceId]
);
}
@@ -0,0 +1,15 @@
'use client';
import { useMemo } from 'react';
export function useShareLink(workspaceId: string): string {
return useMemo(() => {
if (environment.isServer) {
throw new Error('useShareLink is not available on server side');
}
if (environment.isDesktop) {
return '???';
} else {
return origin + '/share/' + workspaceId;
}
}, [workspaceId]);
}
@@ -0,0 +1,22 @@
import { setWorkspacePublicByIdMutation } from '@affine/graphql';
import { useMutation } from '@affine/workspace/affine/gql';
import { useCallback } from 'react';
import { useMutateCloud } from './use-mutate-cloud';
export function useToggleCloudPublic(workspaceId: string) {
const mutate = useMutateCloud();
const { trigger } = useMutation({
mutation: setWorkspacePublicByIdMutation,
});
return useCallback(
async (isPublic: boolean) => {
await trigger({
id: workspaceId,
public: isPublic,
});
await mutate();
},
[mutate, trigger, workspaceId]
);
}