Skip to content

feat: select from recent repos #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/app/(app)/[repo]/_components/repo-contents.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Input, InputIcon, InputRoot } from '@/components/ui/input';
import useRecentRepos from '@/hooks/use-recent-repos';
import useRepoContents from '@/hooks/use-repo-contents';
import { useStableSession } from '@/hooks/use-stable-session';
import { getRepoConfig } from '@/lib/api/github';
Expand All @@ -21,6 +22,7 @@ export default function RepoContents({ repo, setIsConfigDialogOpen }: Props) {
const { setConfig, setIsValid } = useRepoStore((state) => state);
const { contents, isLoading, navigateTo, navigateBack, canGoBack, breadcrumbs, navigateBackTo } =
useRepoContents(repo);
const { addRecentRepo } = useRecentRepos();

const loadConfigFilePromise = useCallback(
() =>
Expand All @@ -33,12 +35,13 @@ export default function RepoContents({ repo, setIsConfigDialogOpen }: Props) {

if (_config === null) {
reject();
setIsConfigDialogOpen(true);
setIsValid(false);
setIsConfigDialogOpen(true); // open dialog to create config
setIsValid(false); // make invalid
} else {
resolve();
setConfig(_config);
setIsValid(true);
setIsValid(true); // make currrent repo valid
addRecentRepo(repo); // add to recent repos (localstorage)
}
}),
[session, repo, setIsConfigDialogOpen, setIsValid, setConfig],
Expand Down
39 changes: 39 additions & 0 deletions src/app/(app)/new/_components/recent-repo-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use client';

import GitHubIcon from '@/components/icons/github';
import { buttonVariants } from '@/components/ui/button';
import useRecentRepos from '@/hooks/use-recent-repos';
import { cn } from '@/lib/utils';
import Link from 'next/link';

export default function RecentRepoList() {
const { recentRepos } = useRecentRepos();

return (
<div className="bg-card/50 divide-y rounded-md border">
{recentRepos.map((repo) => (
<div key={repo} className="flex h-14 items-center gap-2 px-3">
<GitHubIcon className="fill-muted-foreground size-5" />
<a
href={repo}
target="_blank"
rel="noreferrer noopener"
className="text-sm font-medium hover:underline"
>
{repo}
</a>
{/* {repo.private && <Lock className="text-muted-foreground size-3.5" />} */}
{/* <span className="text-muted-foreground text-sm">
{datetime(repo.updated_at).fromNow()}
</span> */}
<Link
href={`/@${repo}`}
className={cn('ml-auto', buttonVariants({ variant: 'outline' }))}
>
Import
</Link>
</div>
))}
</div>
);
}
16 changes: 4 additions & 12 deletions src/app/(app)/new/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Construction } from 'lucide-react';
import { Metadata } from 'next';
import RecentRepoList from './_components/recent-repo-list';
import RepoList from './_components/repo-list';

export const metadata: Metadata = {
Expand All @@ -20,17 +20,9 @@ export default async function Page() {
<h5 className="text-xl font-bold">Import Git Repo</h5>
<RepoList />
</div>
<div className="flex flex-col gap-4 rounded-lg border p-4">
<div>
<h5 className="text-xl font-bold">Clone Template</h5>
<span className="text-muted-foreground text-sm">
Clone from our starter collection.
</span>
</div>
<div className="flex flex-1 flex-col items-center justify-center gap-2">
<Construction className="text-muted-foreground size-10 stroke-1" />
<span className="text-muted-foreground text-sm">(Feature comin&apos; soon)</span>
</div>
<div className="space-y-4 rounded-lg border p-4">
<h5 className="text-xl font-bold">Recent Repos</h5>
<RecentRepoList />
</div>
</div>
</div>
Expand Down
6 changes: 5 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { Config } from './types/config';

export const LOCAL_STORAGE_KEYS = {
LAST_USED_REPO: 'gitloom:last-used-repo',
RECENT_REPOS: 'gitloom:recent-repos',
} as const;

// ===== config =====
export const CONFIG_PATH = '.gitloom/config.json';

export const DEFAULT_CONFIG = {
$schema: 'https://cdn.jsdelivr.net/npm/@gitloom/config@1.0.1/schema.json',
__v: '1.0.0',
contentTypes: {},
} satisfies Config;

// ===== limits =====
export const MAX_RECENT_REPOS = 5;
29 changes: 29 additions & 0 deletions src/hooks/use-recent-repos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { LOCAL_STORAGE_KEYS, MAX_RECENT_REPOS } from '@/constants';
import { useEffect, useState } from 'react';

export default function useRecentRepos() {
const [recentRepos, setRecentRepos] = useState<string[]>([]);

useEffect(() => {
const item = localStorage.getItem(LOCAL_STORAGE_KEYS.RECENT_REPOS);
if (!item) return;

const parsed = JSON.parse(item);
if (Array.isArray(parsed)) setRecentRepos(parsed);
}, []);

function addRecentRepo(repo: string) {
setRecentRepos((prev) => {
const newRepos = [repo, ...prev.filter((r) => r !== repo)].slice(0, MAX_RECENT_REPOS);
// update localStorage
localStorage.setItem(LOCAL_STORAGE_KEYS.RECENT_REPOS, JSON.stringify(newRepos));

return newRepos;
});
}

return {
recentRepos,
addRecentRepo,
};
}