Skip to content

Commit

Permalink
fix: mobile import (#1940)
Browse files Browse the repository at this point in the history
* fix: mobile import

* format:fix

* lint fix

* format fix
  • Loading branch information
RiXelanya authored Feb 4, 2024
1 parent de6df79 commit 4f11211
Show file tree
Hide file tree
Showing 4 changed files with 306 additions and 10 deletions.
35 changes: 27 additions & 8 deletions src/components/Mobile/Bottombar/Bottombar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,20 @@ export const BottombarComponent: React.FC<SearchBoxContainerProps> = props => {
const { instance } = useInstances();

const [createPostOpened, setCreatePostOpened] = React.useState(false);
const [imported, setImported] = React.useState(false);
const [actived, setActived] = React.useState<TimelineType>();

const handleOpenCreatePost = () => {
setPopOpen(false);
setCreatePostOpened(true);
};

const handleOpenImportPost = () => {
setPopOpen(false);
setImported(true);
setCreatePostOpened(true);
};

const handleOpenPopover = () => {
setPopOpen(true);
};
Expand All @@ -102,6 +109,7 @@ export const BottombarComponent: React.FC<SearchBoxContainerProps> = props => {

const handleCloseCreatePost = () => {
setCreatePostOpened(false);
setImported(false);
};

const openMenu = useCallback(
Expand Down Expand Up @@ -146,6 +154,7 @@ export const BottombarComponent: React.FC<SearchBoxContainerProps> = props => {
<PostCreateContainer
open={createPostOpened}
onClose={handleCloseCreatePost}
imported={imported}
/>

<Grid
Expand Down Expand Up @@ -213,14 +222,24 @@ export const BottombarComponent: React.FC<SearchBoxContainerProps> = props => {
<SvgIcon className={style.fillButtonCreate} component={PlusIcon} />
</IconButton>
<Modal open={popOpen} onClose={handleClose}>
<IconButton
onClick={handleOpenCreatePost}
className={style.popoverbuttonCreate}>
<SvgIcon
className={style.fillButtonCreate}
component={PencilIcon}
/>
</IconButton>
<div>
<IconButton
onClick={handleOpenCreatePost}
className={style.popoverbuttonCreate}>
<SvgIcon
className={style.fillButtonCreate}
component={PencilIcon}
/>
</IconButton>
<IconButton
onClick={handleOpenImportPost}
className={style.popoverbuttonImport}>
<SvgIcon
className={style.fillButtonCreate}
component={PlusIcon}
/>
</IconButton>
</div>
</Modal>
</div>
)}
Expand Down
12 changes: 12 additions & 0 deletions src/components/Mobile/Bottombar/bottombar.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ export const useStyles = makeStyles((theme: Theme) =>
opacity: 0.8,
},
},
popoverbuttonImport: {
backgroundColor: '#862AE9',
position: 'absolute',
bottom: 142,
right: 7,
width: '40px',
height: '40px',
'&:hover': {
backgroundColor: '#862AE9',
opacity: 0.8,
},
},
popover: {
position: 'relative',
top: -40,
Expand Down
213 changes: 213 additions & 0 deletions src/components/PostCreate/MobilePostImport.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import React, { useEffect, useState } from 'react';

import { Paper, Typography, Menu, MenuItem } from '@material-ui/core';

import { Modal } from '../atoms/Modal';
import { useStyles } from './MobilePostCreate.styles';

import { PostImport } from 'components/PostImport';
import { SocialAvatar } from 'components/atoms/SocialAvatar';
import { FaChevronDown } from 'react-icons/fa';
import { Experience, UserExperience } from 'src/interfaces/experience';
import { Post, PostVisibility } from 'src/interfaces/post';
import { User } from 'src/interfaces/user';
import * as ExperienceAPI from 'src/lib/api/experience';
import i18n from 'src/locale';

type MobilePostImportProps = {
user: User;
open: boolean;
isMobile?: boolean;
onClose: () => void;
onSearchPeople: (query: string) => void;
onSubmit: (
post: Partial<Post> | string,
attributes?: Pick<Post, 'NSFWTag' | 'visibility' | 'selectedTimelineIds'>,
) => void;
};

type PostCreateType = 'create' | 'import';

const initialPost = {
visibility: PostVisibility.PUBLIC,
isNSFW: false,
};

export const MobilePostImport: React.FC<MobilePostImportProps> = props => {
const { open, user, isMobile, onClose, onSubmit } = props;
const styles = useStyles();
const [post, setPost] = useState<Partial<Post>>(initialPost);
const [, setEditorValue] = useState<string>('');
const [showExclusive, setShowExclusive] = useState<boolean>(false);
const [, setShowTimelineCreate] = useState<boolean>(false);
const [, setTimelineId] = useState<string[]>([]);
const [, setExperienceVisibility] = useState<string[]>([]);
const [, setCommonUser] = useState<string[]>([]);
const [userExperiences, setUserExperiences] = useState<UserExperience[]>([]);
const [page, setPage] = useState<number>(1);
const [selectedTimeline, setSelectedTimeline] = useState<Experience>();
const [anchorEl, setAnchorEl] = React.useState<null | SVGElement>(null);
const [importUrl, setImport] = useState<string | undefined>();

const header: Record<PostCreateType, { title: string; subtitle: string }> = {
create: {
title: i18n.t('Post_Create.Title'),
subtitle: i18n.t('Post_Create.Subtitle'),
},
import: {
title: i18n.t('Post_Import.Title'),
subtitle: i18n.t('Post_Import.Subtitle'),
},
};

const handleOpenMenu = (event: React.MouseEvent<SVGElement>) => {
setAnchorEl(event.currentTarget);
};

const handlePostUrlChange = (url: string | null) => {
setImport(url);
setEditorValue(url);
};

const handleErrorImport = () => {
setImport(undefined);
};

const handleMenuClose = () => {
setAnchorEl(null);
};

const handleExperienceChange = (item: UserExperience) => {
return () => {
setSelectedTimeline(item.experience);
};
};

const handleImagePaste = event => {
if (event.clipboardData.getData('image') != '') {
event.preventDefault();
}
};

const handleSubmit = async () => {
onSubmit(importUrl, {
NSFWTag: post.NSFWTag,
visibility: post.visibility ?? PostVisibility.PUBLIC,
selectedTimelineIds: [selectedTimeline?.id],
});
};

const handleClose = () => {
setPost(initialPost);
setShowExclusive(false);
setShowTimelineCreate(false);
setEditorValue('');
setTimelineId([]);
setExperienceVisibility([]);
setCommonUser([]);
onClose();
};

const handleTitleModal: () => { title: string; subtitle: string } = () => {
const title = !showExclusive
? header['create'].title
: i18n.t('ExclusiveContent.Add');
const subtitle = !showExclusive ? header['create'].subtitle : '';

return {
title,
subtitle,
};
};

const fetchUserExperiences = async () => {
const { meta, data: experiences } = await ExperienceAPI.getUserExperiences(
user.id,
'personal',
page,
);

setUserExperiences([...experiences]);
if (experiences.length !== 0)
setSelectedTimeline(experiences[0].experience);

if (meta.currentPage < meta.totalPageCount) setPage(page + 1);
};

const resetExperiences = () => {
setPage(1);
setUserExperiences([]);
};

useEffect(() => {
if (open) fetchUserExperiences();
else resetExperiences();
}, [open, page]);
return (
<Modal
title={handleTitleModal().title}
subtitle={handleTitleModal().subtitle}
onClose={handleClose}
onPaste={handleImagePaste}
open={open}
fullScreen={isMobile}
maxWidth="md"
className={styles.root}>
<div>
<button className={styles.postbutton} onClick={handleSubmit}>
import
</button>
</div>
<div>
<Paper className={styles.timelinePaper}>
<div className={styles.avatar}>
<SocialAvatar
avatar={user ? user.profilePictureURL : ''}
origin="myriad"
onClick={() => {
console.log;
}}
name="avatar"
/>
</div>
{selectedTimeline && (
<div className={styles.cardUserName}>
<Typography>{selectedTimeline.name}</Typography>
</div>
)}
<FaChevronDown
size={15}
onClick={handleOpenMenu}
style={{ position: 'absolute', right: 16, top: 22 }}
/>
<Menu
anchorEl={anchorEl}
id="account-menu"
open={Boolean(anchorEl)}
onClose={handleMenuClose}
onClick={handleMenuClose}
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}>
{userExperiences.map(item => (
<MenuItem
key={item.experience.name}
onClick={handleExperienceChange(item)}>
{item.experience.name}
</MenuItem>
))}
</Menu>
<PostImport
value={importUrl}
onChange={handlePostUrlChange}
onError={handleErrorImport}
/>
</Paper>
</div>

{/* Select Timeline */}
{/* Timeline list */}
</Modal>
);
};

export default MobilePostImport;
56 changes: 54 additions & 2 deletions src/components/PostCreate/PostCreate.container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useTheme } from '@material-ui/core/styles';

import { PromptComponent } from '../atoms/Prompt/prompt.component';
import MobilePostCreate from './MobilePostCreate';
import MobilePostImport from './MobilePostImport';

import useConfirm from 'components/common/Confirm/use-confirm.hook';
import { useEnqueueSnackbar } from 'components/common/Snackbar/useEnqueueSnackbar.hook';
Expand All @@ -23,13 +24,14 @@ import { createPost, importPost } from 'src/reducers/timeline/actions';

type PostCreateContainerType = {
open: boolean;
imported?: boolean;
onClose: () => void;
};

const PostCreate = dynamic(() => import('./PostCreate'), { ssr: false });

export const PostCreateContainer: React.FC<PostCreateContainerType> = props => {
const { open, onClose } = props;
const { open, onClose, imported } = props;
const confirm = useConfirm();
const router = useRouter();
const dispatch = useDispatch();
Expand Down Expand Up @@ -179,7 +181,7 @@ export const PostCreateContainer: React.FC<PostCreateContainerType> = props => {
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);
if (!redirect && isMobile) {
if (!redirect && isMobile && !imported) {
return (
<>
<MobilePostCreate
Expand Down Expand Up @@ -229,6 +231,56 @@ export const PostCreateContainer: React.FC<PostCreateContainerType> = props => {
</>
);
}
if (!redirect && isMobile && imported) {
return (
<>
<MobilePostImport
user={user}
open={open}
onClose={onClose}
onSearchPeople={handleSearchPeople}
onSubmit={submitPost}
isMobile={isMobile}
/>
<PromptComponent
title={i18n.t('Home.RichText.Prompt_Import.Title')}
subtitle={dialogFailedImport.message}
open={dialogFailedImport.open}
icon="warning"
onCancel={() =>
setDialogFailedImport({ ...dialogFailedImport, open: false })
}>
<div
style={{
marginTop: 32,
display: 'flex',
justifyContent: 'center',
gap: '20px',
}}>
<Button
size="small"
variant="outlined"
color="secondary"
onClick={() =>
setDialogFailedImport({ ...dialogFailedImport, open: false })
}>
{i18n.t('General.OK')}
</Button>
{/* TODO: Added translation */}
<Button
size="small"
variant="contained"
color="primary"
onClick={() =>
router.push({ pathname: `/post/${dialogFailedImport.postId}` })
}>
See post
</Button>
</div>
</PromptComponent>
</>
);
}

if (!user) return null;
if (!redirect) {
Expand Down

0 comments on commit 4f11211

Please sign in to comment.