Skip to content

Commit

Permalink
Merge pull request #5 from yoshiya0503/development
Browse files Browse the repository at this point in the history
🎉Release v1.1
  • Loading branch information
yoshiya0503 authored Oct 17, 2023
2 parents 5887fbe + 5d4d6ea commit 192278f
Show file tree
Hide file tree
Showing 40 changed files with 539 additions and 188 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
![React](https://badges.aleen42.com/src/react.svg)
![Typescript](https://github.com/aleen42/badges/raw/master/src/typescript.svg)

**_Simple and beautiful bluesky client for web._**
**_Simple and beautiful bluesky client for web and smartphone._**

<img width="1388" alt="スクリーンショット 2023-10-09 15 33 54" src="https://github.com/yoshiya0503/rain/assets/5334715/0963573d-d586-42fa-86ec-867e62851bfe">

Expand Down
83 changes: 83 additions & 0 deletions src/components/BottomMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import _ from "lodash";
import { useNavigate, useLocation } from "react-router-dom";
import Avatar from "@mui/material/Avatar";
import Fab from "@mui/material/Fab";
import Paper from "@mui/material/Paper";
import BottomNavigation from "@mui/material/BottomNavigation";
import BottomNavigationAction from "@mui/material/BottomNavigationAction";
import Badge from "@mui/material/Badge";
import Home from "@mui/icons-material/HomeRounded";
import Search from "@mui/icons-material/SearchRounded";
import Tag from "@mui/icons-material/TagRounded";
import Notifications from "@mui/icons-material/NotificationsRounded";
import Create from "@mui/icons-material/CreateRounded";
import DialogPost from "@/components/DialogPost";
import useMe from "@/hooks/useMe";
import useRealtime from "@/hooks/useRealtime";
import useDialog from "@/hooks/useDialog";

export const BottomMenu = () => {
const me = useMe();
const { unreadCount, unreadTimeline } = useRealtime();
const navigate = useNavigate();
const location = useLocation();
const [isOpen, openPostDialog, closePostDialog] = useDialog();

const menus = [
{
name: "Home",
icon: (
<Badge color="primary" variant="dot" invisible={!_.size(unreadTimeline)}>
<Home sx={{ width: 32, height: 32 }} />
</Badge>
),
href: "/",
},
{ name: "Search", icon: <Search sx={{ width: 32, height: 32 }} />, href: "/search" },
{ name: "Feeds", icon: <Tag sx={{ width: 32, height: 32 }} />, href: "/feeds" },
{
name: "Notifications",
icon: (
<Badge badgeContent={unreadCount} color="primary">
<Notifications sx={{ width: 32, height: 32 }} />
</Badge>
),
href: "/notifications",
},
{ name: "Profile", icon: <Avatar sx={{ width: 32, height: 32 }} src={me.avatar} />, href: `/profile/${me.handle}` },
];

const onClickMenu = (href: string) => {
if (location.pathname !== href) {
navigate(href);
}
};

return (
<>
<Fab
sx={{ position: "absolute", bottom: 72, right: 32, width: 64, height: 64 }}
color="primary"
onClick={openPostDialog}
>
<Create />
</Fab>
<Paper sx={{ position: "fixed", bottom: 0, left: 0, right: 0, zIndex: 1 }} elevation={8}>
<BottomNavigation
sx={{ pb: 2 }}
value={location.pathname}
onChange={(_, href) => {
onClickMenu(href);
}}
>
{_.map(menus, (menu, key) => (
<BottomNavigationAction key={key} icon={menu.icon} value={menu.href} />
))}
</BottomNavigation>
</Paper>
<DialogPost title="Post" open={isOpen} onClose={closePostDialog} />
</>
);
};

export default BottomMenu;
93 changes: 93 additions & 0 deletions src/components/DrawerMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import _ from "lodash";
import { useNavigate, useLocation } from "react-router-dom";
import { grey } from "@mui/material/colors";
import Drawer from "@mui/material/SwipeableDrawer";
import IconButton from "@mui/material/IconButton";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import ListItemButton from "@mui/material/ListItemButton";
import Badge from "@mui/material/Badge";
import Home from "@mui/icons-material/HomeRounded";
import Search from "@mui/icons-material/SearchRounded";
import Tag from "@mui/icons-material/TagRounded";
import MenuRoundedIcon from "@mui/icons-material/MenuRounded";
import Notifications from "@mui/icons-material/NotificationsRounded";
import AccountCircle from "@mui/icons-material/AccountCircleRounded";
import Settings from "@mui/icons-material/SettingsRounded";
import ProfileHeader from "@/components/ProfileHeader";
import useMe from "@/hooks/useMe";
import useRealtime from "@/hooks/useRealtime";
import useDrawer from "@/hooks/useDrawer";

export const DrawerMenu = () => {
const me = useMe();
const { unreadCount, unreadTimeline } = useRealtime();
const navigate = useNavigate();
const location = useLocation();
const [open, onOpenDrawer, onCloseDrawer] = useDrawer();

const menus = [
{
name: "Home",
icon: (
<Badge color="primary" variant="dot" invisible={!_.size(unreadTimeline)}>
<Home />
</Badge>
),
href: "/",
},
{ name: "Search", icon: <Search />, href: "/search" },
{ name: "Feeds", icon: <Tag />, href: "/feeds" },
{
name: "Notifications",
icon: (
<Badge badgeContent={unreadCount} color="primary">
<Notifications />
</Badge>
),
href: "/notifications",
},
{ name: "Profile", icon: <AccountCircle />, href: `/profile/${me.handle}` },
{ name: "Settings", icon: <Settings />, href: "/settings" },
];

const onClickMenu = (href: string) => () => {
if (location.pathname !== href) {
navigate(href);
}
};

return (
<>
<IconButton onClick={onOpenDrawer}>
<MenuRoundedIcon sx={{ width: 32, height: 32, color: grey[400] }} />
</IconButton>
<Drawer
sx={{ zIndex: 1300 }}
component="nav"
anchor="left"
open={open}
onOpen={onOpenDrawer}
onClose={onCloseDrawer}
>
<List>
<ListItem>
<ProfileHeader profile={me} size="large" />
</ListItem>
{_.map(menus, (menu, key) => (
<ListItem key={key} onClick={onClickMenu(menu.href)}>
<ListItemButton sx={{ borderRadius: 6 }}>
<ListItemIcon>{menu.icon}</ListItemIcon>
<ListItemText primary={menu.name} />
</ListItemButton>
</ListItem>
))}
</List>
</Drawer>
</>
);
};

export default DrawerMenu;
6 changes: 3 additions & 3 deletions src/components/Feed.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import _ from "lodash";
import { useCallback } from "react";
import { useCallback, memo } from "react";
import { useNavigate } from "react-router-dom";
import { styled } from "@mui/material/styles";
import { grey, pink } from "@mui/material/colors";
Expand Down Expand Up @@ -41,7 +41,7 @@ type Props = {
expanded?: boolean;
};

export const Feed = (props: Props) => {
export const Feed = memo((props: Props) => {
const navigate = useNavigate();
const onChangeFeed = useCallback(() => {
props.onChangeFeed(props.feed);
Expand Down Expand Up @@ -137,6 +137,6 @@ export const Feed = (props: Props) => {
</AccordionDetails>
</FeedAccordion>
);
};
});

export default Feed;
6 changes: 3 additions & 3 deletions src/components/Follow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import _ from "lodash";
import { useCallback } from "react";
import { useCallback, memo } from "react";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Chip from "@mui/material/Chip";
Expand All @@ -16,7 +16,7 @@ type Props = {
profile: AppBskyActorDefs.ProfileView;
};

export const Follow = (props: Props) => {
export const Follow = memo((props: Props) => {
const { onFollow, onUnFollow } = useSocial();

const onToggleFollow = useCallback(() => {
Expand Down Expand Up @@ -62,6 +62,6 @@ export const Follow = (props: Props) => {
</Typography>
</Stack>
);
};
});

export default Follow;
71 changes: 71 additions & 0 deletions src/components/HeaderMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { useCallback } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { grey } from "@mui/material/colors";
import AppBar from "@mui/material/AppBar";
import Toolbar from "@mui/material/Toolbar";
import IconButton from "@mui/material/IconButton";
import Typography from "@mui/material/Typography";
import Settings from "@mui/icons-material/SettingsRounded";
import ArrowBackIosNewRoundedIcon from "@mui/icons-material/ArrowBackIosNewRounded";
import Search from "@/components/Search";
import DrawerMenu from "@/components/DrawerMenu";

type Props = {
search?: boolean;
history?: boolean;
menu?: boolean;
};

export const HeaderMenu = (props: Props) => {
const navigate = useNavigate();
const location = useLocation();
const theme = useTheme();
const isPhone = useMediaQuery(theme.breakpoints.down("sm"));

const back = useCallback(() => {
navigate(-1);
}, [navigate]);

const setting = useCallback(() => {
if (location.pathname !== "/settings") {
navigate("/settings");
}
}, [navigate, location]);

return (
<AppBar
sx={{
position: "sticky",
backdropFilter: "blur(12px)",
}}
component="nav"
elevation={0}
enableColorOnDark
color="transparent"
>
<Toolbar variant={isPhone ? undefined : "dense"} disableGutters={isPhone ? false : true}>
{props.history && (
<IconButton size="small" color="primary" onClick={back}>
<ArrowBackIosNewRoundedIcon fontSize="small" />
</IconButton>
)}
{props.menu && <DrawerMenu />}
{isPhone && !props.search && (
<Typography variant="h5" sx={{ flexGrow: 1, textAlign: "center" }}>
</Typography>
)}
{props.search && <Search />}
{isPhone && (
<IconButton onClick={setting}>
<Settings sx={{ width: 32, height: 32, color: grey[400] }} />
</IconButton>
)}
</Toolbar>
</AppBar>
);
};

export default HeaderMenu;
10 changes: 5 additions & 5 deletions src/components/Notification.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import _ from "lodash";
import { useCallback } from "react";
import { useCallback, memo } from "react";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
Expand Down Expand Up @@ -30,7 +30,7 @@ type Props = {
reasonReply?: AppBskyFeedDefs.PostView;
};

export const Post = (props: Props) => {
export const Notification = memo((props: Props) => {
const { onShare, onViewThread } = usePost();
const { fromNow } = useLocale();
// TODO フォローしてきた人のミニアバターを詳細にして出すとかいいかもしれない
Expand Down Expand Up @@ -71,7 +71,7 @@ export const Post = (props: Props) => {
}, [onViewThread, props.reasonSubject, props.reasonReply]);

return (
<Stack direction="row" spacing={1} onClick={onViewReason}>
<Stack sx={{ pr: 1, pl: 1 }} direction="row" spacing={1} onClick={onViewReason}>
<Divider
sx={{ bgcolor: "primary.main", borderRightWidth: 1.5, mb: 2 }}
orientation="vertical"
Expand Down Expand Up @@ -128,6 +128,6 @@ export const Post = (props: Props) => {
</Box>
</Stack>
);
};
});

export default Post;
export default Notification;
7 changes: 4 additions & 3 deletions src/components/Post.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { memo } from "react";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
Expand Down Expand Up @@ -30,7 +31,7 @@ type Props = {
};

// TODO mute threads
export const Post = (props: Props) => {
export const Post = memo((props: Props) => {
const { onDeletePost, onShare, onViewThread } = usePost();
const { fromNow } = useLocale();

Expand Down Expand Up @@ -98,7 +99,7 @@ export const Post = (props: Props) => {
];

return (
<Stack direction="row" spacing={1} onClick={onViewThread(props.post)}>
<Stack sx={{ pr: 1, pl: 1 }} direction="row" spacing={1} onClick={onViewThread(props.post)}>
<AvatarThread profile={props.post.author} hasReply={props.hasReply} />
<Box sx={{ width: "100%" }}>
{AppBskyFeedDefs.isReasonRepost(props.reason) && (
Expand Down Expand Up @@ -138,6 +139,6 @@ export const Post = (props: Props) => {
</Box>
</Stack>
);
};
});

export default Post;
2 changes: 1 addition & 1 deletion src/components/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const SideBar = () => {
<Divider />
{_.isEmpty(actors) && (
<ListItem>
<Typography sx={{ fontWeight: 600 }} color="gray">
<Typography sx={{ fontWeight: 600 }} color="grey">
No Suggestions, Please Reload The Page
</Typography>
</ListItem>
Expand Down
Loading

0 comments on commit 192278f

Please sign in to comment.