Fix streaming, add poll support to composer
This commit is contained in:
parent
27b6c92c22
commit
4978af6b6e
|
@ -944,6 +944,21 @@
|
|||
"integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==",
|
||||
"dev": true
|
||||
},
|
||||
"@date-io/core": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@date-io/core/-/core-1.1.0.tgz",
|
||||
"integrity": "sha512-PyjhyR2fbp7Q8xpB5zoOyT3dqr8Bn4kXfREf1w6AnQalwdftNxChB2/p88fI1qsx8KNmHDJY12eCgLoZaPegTw==",
|
||||
"dev": true
|
||||
},
|
||||
"@date-io/moment": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-1.1.0.tgz",
|
||||
"integrity": "sha512-U7Vrhk7nlrKMtlLuNs7DAWmMsMBTgWFAvgpKg6Z5Opo/U7ab5DvI8nLks5dqJbeEFQDSlO+KCmJWfsL9hVI3Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@date-io/core": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"@material-ui/core": {
|
||||
"version": "3.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.9.3.tgz",
|
||||
|
@ -1290,6 +1305,15 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-text-mask": {
|
||||
"version": "5.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-text-mask/-/react-text-mask-5.4.4.tgz",
|
||||
"integrity": "sha512-mnwyDgUwFtJVAZ8f+tzPGmYjpH7TLXxHSGty338abca6aAjdjRLCOC4h+CxlvB8xrVAIU5pkNllpHhfJCA3hXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-transition-group": {
|
||||
"version": "2.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.0.16.tgz",
|
||||
|
@ -4152,6 +4176,12 @@
|
|||
"shallow-clone": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.0.3.tgz",
|
||||
"integrity": "sha512-xLoSw6DMp7YvbEeLrQJBcWWRRerdHrU1WHoL1hYJOKUeDpVMRq7pv7NI2JHQbCRAe5ptINNzhdYmtfN6MsdCUw==",
|
||||
"dev": true
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
|
@ -10806,6 +10836,20 @@
|
|||
"object-visit": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"material-ui-pickers": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/material-ui-pickers/-/material-ui-pickers-2.2.4.tgz",
|
||||
"integrity": "sha512-QCQh08Ylmnt+o4laW+rPs92QRAcESv3sPXl50YadLm++rAZAXAOh3K8lreGdynCMYFgZfdyu81Oz9xzTlAZNfw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react-text-mask": "^5.4.3",
|
||||
"clsx": "^1.0.2",
|
||||
"react-event-listener": "^0.6.6",
|
||||
"react-text-mask": "^5.4.3",
|
||||
"react-transition-group": "^2.5.3",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"math-random": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
|
||||
|
@ -15315,6 +15359,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"react-text-mask": {
|
||||
"version": "5.4.3",
|
||||
"resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.4.3.tgz",
|
||||
"integrity": "sha1-mR77QpnjDC5sLEbRP2FxaUY+DS0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prop-types": "^15.5.6"
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.7.1.tgz",
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
"react-web-share-api": "^0.0.2",
|
||||
"query-string": "^6.4.2",
|
||||
"file-dialog": "^0.0.7",
|
||||
"emoji-mart": "^2.8.2"
|
||||
"emoji-mart": "^2.8.2",
|
||||
"material-ui-pickers": "^2.2.4",
|
||||
"@date-io/moment": "^1.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "BROWSER='Safari Technology Preview' react-scripts start",
|
||||
|
|
|
@ -254,7 +254,7 @@ export class AppLayout extends Component<any, IAppLayoutState> {
|
|||
<ListItemText primary={this.state.currentUser.display_name || this.state.currentUser.acct} secondary={'@' + this.state.currentUser.acct}/>
|
||||
</LinkableListItem>
|
||||
<Divider/>
|
||||
<MenuItem>Switch account</MenuItem>
|
||||
{/* <MenuItem>Switch account</MenuItem> */}
|
||||
<MenuItem>Log out</MenuItem>
|
||||
</div>
|
||||
</ClickAwayListener>
|
||||
|
|
|
@ -80,5 +80,8 @@ export const styles = (theme: Theme) => createStyles({
|
|||
postAuthorEmoji: {
|
||||
height: theme.typography.fontSize,
|
||||
verticalAlign: "middle"
|
||||
},
|
||||
heading: {
|
||||
color: "inherit"
|
||||
}
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Typography, IconButton, Card, CardHeader, Avatar, CardContent, CardActions, withStyles, Menu, MenuItem, Chip, Divider, CardMedia, CardActionArea, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Zoom, Tooltip } from '@material-ui/core';
|
||||
import { Typography, IconButton, Card, CardHeader, Avatar, CardContent, CardActions, withStyles, Menu, MenuItem, Chip, Divider, CardMedia, CardActionArea, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Zoom, Tooltip, RadioGroup, Radio, FormControlLabel, Button } from '@material-ui/core';
|
||||
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||
import ReplyIcon from '@material-ui/icons/Reply';
|
||||
import FavoriteIcon from '@material-ui/icons/Favorite';
|
||||
|
@ -25,6 +25,7 @@ import { LinkableChip, LinkableMenuItem, LinkableIconButton } from '../../interf
|
|||
import {withSnackbar} from 'notistack';
|
||||
import ShareMenu from './PostShareMenu';
|
||||
import {emojifyString} from '../../utilities/emojis';
|
||||
import { PollOption, Poll } from '../../types/Poll';
|
||||
|
||||
interface IPostProps {
|
||||
post: Status;
|
||||
|
@ -36,6 +37,7 @@ interface IPostState {
|
|||
post: Status;
|
||||
media_slides?: number;
|
||||
menuIsOpen: boolean;
|
||||
myVote?: [number];
|
||||
}
|
||||
|
||||
export class Post extends React.Component<any, IPostState> {
|
||||
|
@ -59,6 +61,54 @@ export class Post extends React.Component<any, IPostState> {
|
|||
this.setState({ menuIsOpen: !this.state.menuIsOpen })
|
||||
}
|
||||
|
||||
findBiggestVote() {
|
||||
let poll = this.state.post.poll;
|
||||
let votes: number[] = [];
|
||||
let bv = "";
|
||||
if (poll) {
|
||||
poll.options.forEach((option: PollOption) => {
|
||||
votes.push(option.votes_count? option.votes_count: 0);
|
||||
});
|
||||
let biggestVote = Math.max.apply(null, votes);
|
||||
poll.options.forEach((option: PollOption) => {
|
||||
if (option.votes_count === biggestVote) {
|
||||
bv = option.title;
|
||||
};
|
||||
});
|
||||
return bv;
|
||||
} else {
|
||||
return "No poll option was the best.";
|
||||
}
|
||||
}
|
||||
|
||||
captureVote(option: any) {
|
||||
let poll = this.state.post.poll;
|
||||
let pollIndex: number = 0;
|
||||
if (poll) {
|
||||
poll.options.forEach((pollOption: PollOption, index: number) => {
|
||||
if (pollOption.title === option) {
|
||||
pollIndex = index;
|
||||
}
|
||||
})
|
||||
}
|
||||
this.setState({ myVote: [pollIndex] });
|
||||
}
|
||||
|
||||
submitVote() {
|
||||
let poll = this.state.post.poll;
|
||||
if (poll) {
|
||||
this.client.post(`/polls/${poll.id}/votes`, {choices: this.state.myVote}).then((resp: any) => {
|
||||
let post = this.state.post;
|
||||
post.poll = resp.data;
|
||||
this.setState({ post });
|
||||
this.props.enqueueSnackbar("Vote submitted.");
|
||||
}).catch((err: Error) => {
|
||||
this.props.enqueueSnackbar("Couldn't vote: " + err.name);
|
||||
console.error(err.message);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
materializeContent(status: Status) {
|
||||
const { classes } = this.props;
|
||||
|
||||
|
@ -105,22 +155,81 @@ export class Post extends React.Component<any, IPostState> {
|
|||
<AttachmentComponent media={status.media_attachments}/>:
|
||||
<span/>
|
||||
}
|
||||
{
|
||||
status.poll?
|
||||
status.poll.voted || status.poll.expired?
|
||||
<div>
|
||||
<Typography variant="caption">You can't vote on this poll. Below are the results of the poll.</Typography>
|
||||
<RadioGroup
|
||||
value={this.findBiggestVote()}
|
||||
>
|
||||
{
|
||||
status.poll.options.map((pollOption: PollOption) => {
|
||||
let x = <FormControlLabel
|
||||
disabled
|
||||
value={pollOption.title}
|
||||
control={<Radio />}
|
||||
label={`${pollOption.title} (${pollOption.votes_count} votes)`}
|
||||
key={pollOption.title+pollOption.votes_count}
|
||||
/>;
|
||||
return (x);
|
||||
|
||||
})
|
||||
}
|
||||
</RadioGroup>
|
||||
{
|
||||
status.poll && status.poll.expired?
|
||||
<Typography variant="caption">This poll has expired.</Typography>:
|
||||
<Typography variant="caption">This poll will expire on {moment(status.poll.expires_at? status.poll.expires_at: "").format('MMMM Do YYYY, [at] h:mm A')}.</Typography>
|
||||
}
|
||||
</div>:
|
||||
<div>
|
||||
<RadioGroup
|
||||
onChange={(event: any, option: any) => this.captureVote(option)}
|
||||
>
|
||||
{
|
||||
status.poll.options.map((pollOption: PollOption) => {
|
||||
let x = <FormControlLabel
|
||||
value={pollOption.title}
|
||||
control={<Radio />}
|
||||
label={pollOption.title}
|
||||
key={pollOption.title+pollOption.votes_count}
|
||||
/>;
|
||||
return (x);
|
||||
|
||||
})
|
||||
}
|
||||
</RadioGroup>
|
||||
<Button color="primary" onClick={(event: any) => this.submitVote()}>Vote</Button>
|
||||
</div>: null
|
||||
}
|
||||
</div>
|
||||
</CardContent>
|
||||
);
|
||||
}
|
||||
|
||||
spoilerContainsFlags(text: string): boolean {
|
||||
let unsafeFlags = ["NSFW", "nsfw", "lewd", "sex"];
|
||||
let result: boolean = false;
|
||||
unsafeFlags.forEach((flag: string) => {
|
||||
if (text.includes(flag)) {
|
||||
result = true;
|
||||
}
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
getSensitiveContent(spoiler_text: string, content: Status) {
|
||||
const { classes } = this.props;
|
||||
const warningText = spoiler_text || "Unmarked content";
|
||||
let icon;
|
||||
if (spoiler_text.includes("NSFW") || spoiler_text.includes("Spoiler") || warningText === "Unmarked content") {
|
||||
if (this.spoilerContainsFlags(spoiler_text) || spoiler_text.includes("Spoiler") || warningText === "Unmarked content") {
|
||||
icon = <WarningIcon className={classes.postWarningIcon}/>;
|
||||
}
|
||||
return (
|
||||
<ExpansionPanel className={spoiler_text.includes("NSFW")? classes.nsfwCard: classes.spoilerCard} color="inherit">
|
||||
<ExpansionPanel className={this.spoilerContainsFlags(spoiler_text)? classes.nsfwCard: classes.spoilerCard} color="inherit">
|
||||
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon/>} color="inherit">
|
||||
{icon}<Typography className={classes.heading} color="inherit">{warningText}</Typography>
|
||||
{icon}<Typography>{warningText}</Typography>
|
||||
</ExpansionPanelSummary>
|
||||
<ExpansionPanelDetails className={classes.postContent} color="inherit">
|
||||
{this.materializeContent(content)}
|
||||
|
|
|
@ -35,5 +35,14 @@ export const styles = (theme: Theme) => createStyles({
|
|||
[theme.breakpoints.up('sm')]: {
|
||||
display: "block"
|
||||
}
|
||||
},
|
||||
pollWizardOptionIcon: {
|
||||
marginRight: theme.spacing.unit * 2,
|
||||
marginTop: 4,
|
||||
marginBottom: 4,
|
||||
color: theme.palette.grey[700]
|
||||
},
|
||||
pollWizardFlexGrow: {
|
||||
flexGrow: 1
|
||||
}
|
||||
});
|
|
@ -9,14 +9,17 @@ import TagFacesIcon from '@material-ui/icons/TagFaces';
|
|||
import HowToVoteIcon from '@material-ui/icons/HowToVote';
|
||||
import VisibilityIcon from '@material-ui/icons/Visibility';
|
||||
import WarningIcon from '@material-ui/icons/Warning';
|
||||
import DeleteIcon from '@material-ui/icons/Delete';
|
||||
import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked';
|
||||
import Mastodon from 'megalodon';
|
||||
import {withSnackbar} from 'notistack';
|
||||
import { Attachment } from '../types/Attachment';
|
||||
import { PollWizard } from '../types/Poll';
|
||||
import { PollWizard, PollWizardOption } from '../types/Poll';
|
||||
import filedialog from 'file-dialog';
|
||||
import ComposeMediaAttachment from '../components/ComposeMediaAttachment';
|
||||
import EmojiPicker from '../components/EmojiPicker';
|
||||
|
||||
import { DateTimePicker, MuiPickersUtilsProvider } from 'material-ui-pickers';
|
||||
import MomentUtils from '@date-io/moment';
|
||||
|
||||
interface IComposerState {
|
||||
account: UAccount;
|
||||
|
@ -30,6 +33,7 @@ interface IComposerState {
|
|||
acct?: string;
|
||||
attachments?: [Attachment];
|
||||
poll?: PollWizard;
|
||||
pollExpiresDate?: any;
|
||||
showEmojis: boolean;
|
||||
}
|
||||
|
||||
|
@ -200,14 +204,120 @@ class Composer extends Component<any, IComposerState> {
|
|||
}
|
||||
}
|
||||
|
||||
createPoll() {
|
||||
if (this.state.poll === undefined) {
|
||||
let expiration = new Date();
|
||||
let current = new Date();
|
||||
expiration.setMinutes(expiration.getMinutes() + 30);
|
||||
let expiryDifference = (expiration.getTime() - current.getTime() / 1000);
|
||||
let temporaryPoll: PollWizard = {
|
||||
expires_at: expiryDifference.toString(),
|
||||
multiple: false,
|
||||
options: [{title: 'Option 1'}, {title: 'Option 2'}]
|
||||
}
|
||||
this.setState({
|
||||
poll: temporaryPoll,
|
||||
pollExpiresDate: expiration
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addPollItem() {
|
||||
if (this.state.poll !== undefined && this.state.poll.options.length < 4) {
|
||||
let newOption = {title: 'New option'}
|
||||
let options = this.state.poll.options;
|
||||
let poll = this.state.poll;
|
||||
options.push(newOption);
|
||||
poll.options = options;
|
||||
poll.multiple = true;
|
||||
this.setState({
|
||||
poll: poll
|
||||
})
|
||||
} else if (this.state.poll && this.state.poll.options.length == 4) {
|
||||
this.props.enqueueSnackbar("You've reached the options limit in your poll.", { variant: 'error' })
|
||||
}
|
||||
}
|
||||
|
||||
editPollItem(position: number, newTitle: any) {
|
||||
if (this.state.poll !== undefined) {
|
||||
let poll = this.state.poll;
|
||||
let options = this.state.poll.options;
|
||||
options.forEach((option: PollWizardOption) => {
|
||||
if (position === options.indexOf(option)) {
|
||||
option.title = newTitle.target.value;
|
||||
}
|
||||
});
|
||||
poll.options = options;
|
||||
this.setState({
|
||||
poll: poll
|
||||
});
|
||||
this.props.enqueueSnackbar('Option edited.');
|
||||
}
|
||||
}
|
||||
|
||||
removePollItem(item: string) {
|
||||
if (this.state.poll !== undefined && this.state.poll.options.length > 2) {
|
||||
let options = this.state.poll.options;
|
||||
let poll = this.state.poll;
|
||||
options.forEach((option: PollWizardOption) => {
|
||||
if (item === option.title) {
|
||||
options.splice(options.indexOf(option), 1);
|
||||
}
|
||||
});
|
||||
poll.options = options;
|
||||
if (options.length === 2) {
|
||||
poll.multiple = false;
|
||||
}
|
||||
this.setState({
|
||||
poll: poll
|
||||
})
|
||||
} else if (this.state.poll && this.state.poll.options.length <= 2) {
|
||||
this.props.enqueueSnackbar('Polls must have at least two items.', { variant: 'error'} );
|
||||
}
|
||||
}
|
||||
|
||||
setPollExpires(date: string) {
|
||||
let currentDate = new Date();
|
||||
let newDate = new Date(date);
|
||||
let poll = this.state.poll;
|
||||
if (poll) {
|
||||
let expiry = ((newDate.getTime() - currentDate.getTime()) / 1000);
|
||||
console.log(expiry);
|
||||
if (expiry >= 1800) {
|
||||
poll.expires_at = expiry.toString();
|
||||
this.setState({ poll, pollExpiresDate: date });
|
||||
this.props.enqueueSnackbar("Expiration updated.")
|
||||
} else {
|
||||
this.props.enqueueSnackbar("Expiration is too small (min. 30 minutes).", { variant: 'error' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removePoll() {
|
||||
this.setState({
|
||||
poll: undefined
|
||||
});
|
||||
}
|
||||
|
||||
post() {
|
||||
let pollOptions: string[] = [];
|
||||
if (this.state.poll) {
|
||||
this.state.poll.options.forEach((option: PollWizardOption) => {
|
||||
pollOptions.push(option.title);
|
||||
})
|
||||
}
|
||||
this.client.post('/statuses', {
|
||||
status: this.state.text,
|
||||
media_ids: this.getOnlyMediaIds(),
|
||||
visibility: this.state.visibility,
|
||||
sensitive: this.state.sensitive,
|
||||
spoiler_text: this.state.sensitiveText,
|
||||
in_reply_to_id: this.state.reply
|
||||
in_reply_to_id: this.state.reply,
|
||||
poll: this.state.poll? {
|
||||
options: pollOptions,
|
||||
expires_in: this.state.poll.expires_at,
|
||||
multiple: this.state.poll.multiple
|
||||
}: null
|
||||
}).then(() => {
|
||||
this.props.enqueueSnackbar('Posted!');
|
||||
window.history.back();
|
||||
|
@ -299,6 +409,44 @@ class Composer extends Component<any, IComposerState> {
|
|||
</GridList>
|
||||
</div>: null
|
||||
}
|
||||
{
|
||||
this.state.poll?
|
||||
<div style={{ marginTop: 4}}>
|
||||
|
||||
{
|
||||
this.state.poll?
|
||||
this.state.poll.options.map((option: PollWizardOption, index: number) => {
|
||||
let c = <div style={{ display: "flex" }} key={"compose_option_" + index.toString()}>
|
||||
<RadioButtonCheckedIcon className={classes.pollWizardOptionIcon}/>
|
||||
<TextField
|
||||
onBlur={(event: any) => this.editPollItem(index, event)}
|
||||
defaultValue={option.title}/>
|
||||
<div className={classes.pollWizardFlexGrow}/>
|
||||
<Tooltip title="Remove poll option">
|
||||
<IconButton onClick={() => this.removePollItem(option.title)}>
|
||||
<DeleteIcon/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
return c;
|
||||
}): null
|
||||
}
|
||||
<div style={{ display: "flex"}}>
|
||||
<MuiPickersUtilsProvider utils={MomentUtils}>
|
||||
<DateTimePicker
|
||||
value={this.state.pollExpiresDate? this.state.pollExpiresDate: new Date()}
|
||||
onChange={(date: any) => {
|
||||
this.setPollExpires(date.toISOString());
|
||||
}}
|
||||
label="Poll exipres on"
|
||||
disablePast
|
||||
/>
|
||||
</MuiPickersUtilsProvider>
|
||||
<div className={classes.pollWizardFlexGrow}/>
|
||||
<Button onClick={() => this.addPollItem()}>Add Option</Button>
|
||||
</div>
|
||||
</div>: null
|
||||
}
|
||||
</DialogContent>
|
||||
<Toolbar className={classes.dialogActions}>
|
||||
<Tooltip title="Add photos or videos">
|
||||
|
@ -320,7 +468,11 @@ class Composer extends Component<any, IComposerState> {
|
|||
<EmojiPicker onGetEmoji={(emoji: any) => this.insertEmoji(emoji)}/>
|
||||
</Menu>
|
||||
<Tooltip title="Add a poll">
|
||||
<IconButton disabled={this.state.attachments && this.state.attachments.length > 0} id="compose-poll">
|
||||
<IconButton disabled={this.state.attachments && this.state.attachments.length > 0} id="compose-poll" onClick={() => {
|
||||
this.state.poll?
|
||||
this.removePoll():
|
||||
this.createPoll()
|
||||
}}>
|
||||
<HowToVoteIcon/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { withStyles, CircularProgress, Typography, Paper, Button, Chip, Avatar,
|
|||
import {styles} from './PageLayout.styles';
|
||||
import Post from '../components/Post';
|
||||
import { Status } from '../types/Status';
|
||||
import Mastodon from 'megalodon';
|
||||
import Mastodon, { StreamListener } from 'megalodon';
|
||||
import {withSnackbar} from 'notistack';
|
||||
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
|
||||
|
||||
|
@ -20,7 +20,7 @@ interface IHomePageState {
|
|||
class HomePage extends Component<any, IHomePageState> {
|
||||
|
||||
client: Mastodon;
|
||||
streamListener: any;
|
||||
streamListener: StreamListener;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
@ -31,11 +31,11 @@ class HomePage extends Component<any, IHomePageState> {
|
|||
}
|
||||
|
||||
this.client = new Mastodon(localStorage.getItem('access_token') as string, localStorage.getItem('baseurl') as string + "/api/v1");
|
||||
this.streamListener = this.client.stream('/streaming/user');
|
||||
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.streamListener = this.client.stream('/streaming/user');
|
||||
|
||||
this.streamListener.on('connect', () => {
|
||||
this.client.get('/timelines/home', {limit: 40}).then((resp: any) => {
|
||||
|
@ -92,6 +92,10 @@ class HomePage extends Component<any, IHomePageState> {
|
|||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.streamListener.stop();
|
||||
}
|
||||
|
||||
insertBacklog() {
|
||||
window.scrollTo(0, 0);
|
||||
let posts = this.state.posts;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { withStyles, CircularProgress, Typography, Paper, Button, Chip, Avatar,
|
|||
import {styles} from './PageLayout.styles';
|
||||
import Post from '../components/Post';
|
||||
import { Status } from '../types/Status';
|
||||
import Mastodon from 'megalodon';
|
||||
import Mastodon, { StreamListener } from 'megalodon';
|
||||
import {withSnackbar} from 'notistack';
|
||||
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
|
||||
|
||||
|
@ -20,7 +20,7 @@ interface ILocalPageState {
|
|||
class LocalPage extends Component<any, ILocalPageState> {
|
||||
|
||||
client: Mastodon;
|
||||
streamListener: any;
|
||||
streamListener: StreamListener;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
@ -31,11 +31,11 @@ class LocalPage extends Component<any, ILocalPageState> {
|
|||
}
|
||||
|
||||
this.client = new Mastodon(localStorage.getItem('access_token') as string, localStorage.getItem('baseurl') as string + "/api/v1");
|
||||
this.streamListener = this.client.stream('/streaming/public/local');
|
||||
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.streamListener = this.client.stream('/streaming/public/local');
|
||||
|
||||
this.streamListener.on('connect', () => {
|
||||
this.client.get('/timelines/public', {limit: 40, local: true}).then((resp: any) => {
|
||||
|
@ -92,6 +92,10 @@ class LocalPage extends Component<any, ILocalPageState> {
|
|||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.streamListener.stop();
|
||||
}
|
||||
|
||||
insertBacklog() {
|
||||
window.scrollTo(0, 0);
|
||||
let posts = this.state.posts;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { withStyles, CircularProgress, Typography, Paper, Button, Chip, Avatar,
|
|||
import {styles} from './PageLayout.styles';
|
||||
import Post from '../components/Post';
|
||||
import { Status } from '../types/Status';
|
||||
import Mastodon from 'megalodon';
|
||||
import Mastodon, { StreamListener } from 'megalodon';
|
||||
import {withSnackbar} from 'notistack';
|
||||
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
|
||||
|
||||
|
@ -20,7 +20,7 @@ interface IPublicPageState {
|
|||
class PublicPage extends Component<any, IPublicPageState> {
|
||||
|
||||
client: Mastodon;
|
||||
streamListener: any;
|
||||
streamListener: StreamListener;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
@ -31,12 +31,11 @@ class PublicPage extends Component<any, IPublicPageState> {
|
|||
}
|
||||
|
||||
this.client = new Mastodon(localStorage.getItem('access_token') as string, localStorage.getItem('baseurl') as string + "/api/v1");
|
||||
this.streamListener = this.client.stream('/streaming/public');
|
||||
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.streamListener = this.client.stream('/streaming/public');
|
||||
|
||||
this.streamListener.on('connect', () => {
|
||||
this.client.get('/timelines/public', {limit: 40}).then((resp: any) => {
|
||||
let statuses: [Status] = resp.data;
|
||||
|
@ -92,6 +91,10 @@ class PublicPage extends Component<any, IPublicPageState> {
|
|||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.streamListener.stop();
|
||||
}
|
||||
|
||||
insertBacklog() {
|
||||
window.scrollTo(0, 0);
|
||||
let posts = this.state.posts;
|
||||
|
|
Loading…
Reference in New Issue