mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2026-01-25 05:51:04 -08:00
220 lines
7.1 KiB
TypeScript
220 lines
7.1 KiB
TypeScript
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
import Promise from 'bluebird';
|
|
import React, { useState, useEffect, useMemo } from 'react';
|
|
import styled from 'styled-components';
|
|
import { useQuery, useMutation, GraphQLClient, ClientContext } from 'graphql-hooks';
|
|
import { trim } from 'lodash';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import TextField from '@material-ui/core/TextField';
|
|
import FolderIcon from '@material-ui/icons/Folder';
|
|
import LinearProgress from '@material-ui/core/LinearProgress';
|
|
import List from '@material-ui/core/List';
|
|
import ListItem from '@material-ui/core/ListItem';
|
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
|
import ListItemText from '@material-ui/core/ListItemText';
|
|
import Button from '@material-ui/core/Button';
|
|
import CachedIcon from '@material-ui/icons/Cached';
|
|
import CreateNewFolderIcon from '@material-ui/icons/CreateNewFolder';
|
|
|
|
import type { IAuthingUserInfo } from '@services/types';
|
|
import { GITHUB_GRAPHQL_API } from '@/constants/auth';
|
|
|
|
const RepoSearchInput = styled(TextField)``;
|
|
const ReloadButton = styled(Button)`
|
|
white-space: nowrap;
|
|
width: 100%;
|
|
`;
|
|
|
|
const SEARCH_REPO_QUERY = `
|
|
query SearchRepo($queryString: String!, $login: String!) {
|
|
repositoryOwner(login: $login) {
|
|
id
|
|
}
|
|
search(query: $queryString, type: REPOSITORY, first: 10) {
|
|
repositoryCount
|
|
edges {
|
|
node {
|
|
... on Repository {
|
|
name
|
|
url
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`;
|
|
const CREATE_REPO_MUTATION = `
|
|
mutation CreateRepository($repoName: String!, $homepageUrl: URI, $ownerId: ID!, $visibility: RepositoryVisibility!) {
|
|
createRepository (input: {
|
|
name: $repoName,
|
|
description: "A non-linear Wiki created using TiddlyGit-Desktop.",
|
|
hasIssuesEnabled: true,
|
|
hasWikiEnabled: false,
|
|
homepageUrl: $homepageUrl,
|
|
ownerId: $ownerId,
|
|
visibility: $visibility
|
|
}) {
|
|
repository {
|
|
name
|
|
homepageUrl
|
|
}
|
|
}
|
|
}
|
|
`;
|
|
|
|
interface Props {
|
|
accessToken?: string;
|
|
githubWikiUrl: string;
|
|
currentTab: string;
|
|
githubWikiUrlSetter: (string) => void;
|
|
wikiFolderNameSetter: (string) => void;
|
|
userInfo: IAuthingUserInfo;
|
|
isCreateMainWorkspace: boolean;
|
|
}
|
|
export default function SearchRepo({
|
|
accessToken,
|
|
githubWikiUrl,
|
|
currentTab,
|
|
githubWikiUrlSetter,
|
|
wikiFolderNameSetter,
|
|
userInfo,
|
|
isCreateMainWorkspace,
|
|
}: Props): JSX.Element {
|
|
const graphqlClient = useMemo(
|
|
() =>
|
|
new GraphQLClient({
|
|
url: GITHUB_GRAPHQL_API,
|
|
}),
|
|
);
|
|
const [githubRepoSearchString, githubRepoSearchStringSetter] = useState('wiki');
|
|
const loadCount = 10;
|
|
const githubUsername = userInfo?.login || '';
|
|
const { loading, error, data, refetch } = useQuery(SEARCH_REPO_QUERY, {
|
|
variables: {
|
|
first: loadCount,
|
|
queryString: `user:${githubUsername} ${githubRepoSearchString}`,
|
|
login: githubUsername,
|
|
},
|
|
skipCache: true,
|
|
});
|
|
// clear list on logout, which will cause accessToken change
|
|
useEffect(() => {
|
|
const timeoutHandle = setTimeout(() => {
|
|
refetch();
|
|
}, 100);
|
|
return () => clearTimeout(timeoutHandle);
|
|
}, [refetch, githubUsername, accessToken]);
|
|
// try refetch on error
|
|
const [retryInterval, retryIntervalSetter] = useState(100);
|
|
useEffect(() => {
|
|
if (error && githubUsername && accessToken) {
|
|
const timeoutHandle = setTimeout(() => {
|
|
refetch();
|
|
retryIntervalSetter(retryInterval * 10);
|
|
}, retryInterval);
|
|
return () => clearTimeout(timeoutHandle);
|
|
}
|
|
return () => {};
|
|
}, [error, refetch, githubUsername, accessToken, retryInterval]);
|
|
|
|
const [createRepository] = useMutation(CREATE_REPO_MUTATION);
|
|
|
|
const repositoryCount = data?.search?.repositoryCount;
|
|
let repoList = [];
|
|
if (repositoryCount) {
|
|
repoList = data.search.edges.map(({ node }: any) => node);
|
|
}
|
|
const { t } = useTranslation();
|
|
let helperText = '';
|
|
const notLogin = !githubUsername || !accessToken;
|
|
if (notLogin) {
|
|
helperText = t('AddWorkspace.WaitForLogin');
|
|
} else if (error) {
|
|
helperText = t('AddWorkspace.CanNotLoadList');
|
|
}
|
|
if (repositoryCount > loadCount) {
|
|
helperText = t('AddWorkspace.OmitMoreResult', { loadCount });
|
|
}
|
|
|
|
const [isCreatingRepo, isCreatingRepoSetter] = useState(false);
|
|
const githubUserID = data?.repositoryOwner?.id;
|
|
const wikiUrlToCreate = `https://github.com/${userInfo?.login || '???'}/${githubRepoSearchString}`;
|
|
const isCreateNewRepo = trim(githubWikiUrl) === wikiUrlToCreate;
|
|
const githubPagesUrl = `https://${userInfo?.login || '???'}.github.io/${githubRepoSearchString}`;
|
|
|
|
return (
|
|
<ClientContext.Provider value={graphqlClient}>
|
|
<RepoSearchInput
|
|
fullWidth
|
|
onChange={(event) => {
|
|
githubRepoSearchStringSetter(event.target.value);
|
|
}}
|
|
label={t('AddWorkspace.SearchGithubRepoName')}
|
|
value={githubRepoSearchString}
|
|
helperText={helperText}
|
|
/>
|
|
{(loading || isCreatingRepo) && <LinearProgress variant="query" />}
|
|
<List component="nav" aria-label="main mailbox folders">
|
|
{repoList.map(({ name, url }: any) => (
|
|
<ListItem
|
|
button
|
|
key={url}
|
|
onClick={() => {
|
|
githubWikiUrlSetter(url);
|
|
wikiFolderNameSetter(name);
|
|
}}
|
|
selected={trim(githubWikiUrl) === trim(url)}>
|
|
<ListItemIcon>
|
|
<FolderIcon />
|
|
</ListItemIcon>
|
|
<ListItemText primary={name} />
|
|
</ListItem>
|
|
))}
|
|
{userInfo &&
|
|
currentTab !== 'CloneOnlineWiki' &&
|
|
!notLogin &&
|
|
!error &&
|
|
!loading &&
|
|
!isCreatingRepo &&
|
|
!repoList.some(({ url }: any) => trim(url) === wikiUrlToCreate) &&
|
|
githubRepoSearchString && (
|
|
<ListItem
|
|
button
|
|
key={wikiUrlToCreate}
|
|
onClick={async () => {
|
|
isCreatingRepoSetter(true);
|
|
await createRepository({
|
|
variables: {
|
|
repoName: githubRepoSearchString,
|
|
homePageUrl: isCreateMainWorkspace ? githubPagesUrl : undefined,
|
|
ownerId: githubUserID,
|
|
visibility: isCreateMainWorkspace ? 'PUBLIC' : 'PRIVATE',
|
|
},
|
|
});
|
|
// wait for Github update their db
|
|
await Promise.delay(1000);
|
|
await refetch();
|
|
isCreatingRepoSetter(false);
|
|
githubWikiUrlSetter(wikiUrlToCreate);
|
|
}}
|
|
selected={isCreateNewRepo}>
|
|
<ListItemIcon>
|
|
<CreateNewFolderIcon />
|
|
</ListItemIcon>
|
|
<ListItemText
|
|
primary={`${
|
|
isCreateMainWorkspace ? t('AddWorkspace.CreatePublicRepository') : t('AddWorkspace.CreatePrivateRepository')
|
|
} ${githubRepoSearchString}`}
|
|
/>
|
|
</ListItem>
|
|
)}
|
|
</List>
|
|
{repoList.length === 0 && !notLogin && (
|
|
<ReloadButton color="secondary" endIcon={<CachedIcon />} onClick={() => refetch()}>
|
|
{t('AddWorkspace.Reload')}
|
|
</ReloadButton>
|
|
)}
|
|
</ClientContext.Provider>
|
|
);
|
|
}
|