mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-02 06:39:46 +08:00
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:
@@ -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]
|
||||
);
|
||||
}
|
||||
@@ -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]
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user