mirror of
https://github.com/hyperspacedev/hyperspace
synced 2025-02-04 03:08:10 +01:00
Merge branch 'b2u3' of github.com:hyperspacedev/hyperspace into media-uploads
This commit is contained in:
commit
b89ff971f7
@ -20,7 +20,7 @@ import ComposeMediaAttachment from '../components/ComposeMediaAttachment';
|
||||
import EmojiPicker from '../components/EmojiPicker';
|
||||
import { DateTimePicker, MuiPickersUtilsProvider } from 'material-ui-pickers';
|
||||
import MomentUtils from '@date-io/moment';
|
||||
import { getUserDefaultVisibility } from '../utilities/settings';
|
||||
import { getUserDefaultVisibility, getConfig } from '../utilities/settings';
|
||||
|
||||
interface IComposerState {
|
||||
account: UAccount;
|
||||
@ -36,6 +36,7 @@ interface IComposerState {
|
||||
poll?: PollWizard;
|
||||
pollExpiresDate?: any;
|
||||
showEmojis: boolean;
|
||||
federated: boolean;
|
||||
}
|
||||
|
||||
class Composer extends Component<any, IComposerState> {
|
||||
@ -54,20 +55,26 @@ class Composer extends Component<any, IComposerState> {
|
||||
visibilityMenu: false,
|
||||
text: '',
|
||||
remainingChars: 500,
|
||||
showEmojis: false
|
||||
showEmojis: false,
|
||||
federated: true
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let state = this.getComposerParams(this.props);
|
||||
let text = state.acct? `@${state.acct}: `: '';
|
||||
getConfig().then((config: any) => {
|
||||
this.setState({
|
||||
federated: config.federated === "true",
|
||||
reply: state.reply,
|
||||
acct: state.acct,
|
||||
visibility: state.visibility,
|
||||
text,
|
||||
remainingChars: 500 - text.length
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props: any) {
|
||||
@ -500,7 +507,7 @@ class Composer extends Component<any, IComposerState> {
|
||||
<MenuItem onClick={() => this.changeVisibility('direct')}>Direct (direct message)</MenuItem>
|
||||
<MenuItem onClick={() => this.changeVisibility('private')}>Private (followers only)</MenuItem>
|
||||
<MenuItem onClick={() => this.changeVisibility('unlisted')}>Unlisted</MenuItem>
|
||||
<MenuItem onClick={() => this.changeVisibility('public')}>Public</MenuItem>
|
||||
{this.state.federated? <MenuItem onClick={() => this.changeVisibility('public')}>Public</MenuItem>: null}
|
||||
</Menu>
|
||||
</Toolbar>
|
||||
<DialogActions>
|
||||
|
@ -252,7 +252,7 @@ class NotificationsPage extends Component<any, INotificationsPageState> {
|
||||
</List>
|
||||
</Paper>
|
||||
</div>:
|
||||
<div>
|
||||
<div className={classes.pageLayoutEmptyTextConstraints}>
|
||||
<Typography variant="h4">All clear!</Typography>
|
||||
<Typography paragraph>It looks like you have no notifications. Why not get the conversation going with a new post?</Typography>
|
||||
</div>:
|
||||
|
@ -52,6 +52,10 @@ export const styles = (theme: Theme) => createStyles({
|
||||
marginLeft: 250,
|
||||
},
|
||||
},
|
||||
pageLayoutEmptyTextConstraints: {
|
||||
paddingLeft: theme.spacing.unit * 2,
|
||||
paddingRight: theme.spacing.unit * 2
|
||||
},
|
||||
pageHeroBackground: {
|
||||
position: 'relative',
|
||||
height: 'intrinsic',
|
||||
@ -174,5 +178,5 @@ export const styles = (theme: Theme) => createStyles({
|
||||
'& a': {
|
||||
color: theme.palette.primary.light
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
@ -201,7 +201,7 @@ class RecommendationsPage extends Component<IRecommendationsPageProps, IRecommen
|
||||
{
|
||||
this.state.requestedFollows && this.state.requestedFollows.length > 0?
|
||||
this.showFollowRequests():
|
||||
<div>
|
||||
<div className={classes.pageLayoutEmptyTextConstraints}>
|
||||
<Typography variant="h6">You don't have any follow requests.</Typography>
|
||||
<br/>
|
||||
</div>
|
||||
@ -210,7 +210,7 @@ class RecommendationsPage extends Component<IRecommendationsPageProps, IRecommen
|
||||
<br/>
|
||||
{
|
||||
this.state.followSuggestions && this.state.followSuggestions.length > 0? this.showFollowSuggestions():
|
||||
<div>
|
||||
<div className={classes.pageLayoutEmptyTextConstraints}>
|
||||
<Typography variant="h5">We don't have any suggestions for you.</Typography>
|
||||
<Typography paragraph>Why not interact with the fediverse a bit by creating a new post?</Typography>
|
||||
</div>
|
||||
|
@ -164,11 +164,12 @@ class SearchPage extends Component<any, ISearchPageState> {
|
||||
return (
|
||||
<div>
|
||||
<ListSubheader>Accounts</ListSubheader>
|
||||
|
||||
{
|
||||
this.state.results && this.state.results.accounts.length > 0?
|
||||
<Paper className={classes.pageListConstraints}>
|
||||
<List>
|
||||
{
|
||||
this.state.results?
|
||||
this.state.results.accounts.map((acct: Account) => {
|
||||
{ this.state.results.accounts.map((acct: Account) => {
|
||||
return (
|
||||
<ListItem key={acct.id}>
|
||||
<ListItemAvatar>
|
||||
@ -189,16 +190,19 @@ class SearchPage extends Component<any, ISearchPageState> {
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
}): null
|
||||
}
|
||||
})}
|
||||
</List>
|
||||
</Paper>
|
||||
</Paper>: <Typography variant="caption" className={classes.pageLayoutEmptyTextConstraints}>No results found</Typography>
|
||||
}
|
||||
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
showAllPostsFromQuery() {
|
||||
const {classes} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<ListSubheader>Posts</ListSubheader>
|
||||
@ -207,13 +211,14 @@ class SearchPage extends Component<any, ISearchPageState> {
|
||||
this.state.results.statuses.length > 0?
|
||||
this.state.results.statuses.map((post: Status) => {
|
||||
return <Post key={post.id} post={post} client={this.client}/>
|
||||
}): <Typography variant="caption">No results found.</Typography>: null
|
||||
}): <Typography variant="caption" className={classes.pageLayoutEmptyTextConstraints}>No results found.</Typography>: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
showAllPostsWithTag() {
|
||||
const {classes} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<ListSubheader>Tagged posts</ListSubheader>
|
||||
@ -222,7 +227,7 @@ class SearchPage extends Component<any, ISearchPageState> {
|
||||
this.state.tagResults.length > 0?
|
||||
this.state.tagResults.map((post: Status) => {
|
||||
return <Post key={post.id} post={post} client={this.client}/>
|
||||
}): <Typography variant="caption">No results found.</Typography>: null
|
||||
}): <Typography variant="caption" className={classes.pageLayoutEmptyTextConstraints}>No results found.</Typography>: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
} from '@material-ui/core';
|
||||
import OpenInNewIcon from '@material-ui/icons/OpenInNew';
|
||||
import {styles} from './PageLayout.styles';
|
||||
import {setUserDefaultBool, getUserDefaultBool, getUserDefaultTheme, setUserDefaultTheme, getUserDefaultVisibility, setUserDefaultVisibility} from '../utilities/settings';
|
||||
import {setUserDefaultBool, getUserDefaultBool, getUserDefaultTheme, setUserDefaultTheme, getUserDefaultVisibility, setUserDefaultVisibility, getConfig} from '../utilities/settings';
|
||||
import {canSendNotifications, browserSupportsNotificationRequests} from '../utilities/notifications';
|
||||
import {themes, defaultTheme} from '../types/HyperspaceTheme';
|
||||
import ThemePreview from '../components/ThemePreview';
|
||||
@ -43,6 +43,7 @@ interface ISettingsState {
|
||||
resetSettingsDialog: boolean;
|
||||
previewTheme: Theme;
|
||||
defaultVisibility: Visibility;
|
||||
federated: boolean;
|
||||
}
|
||||
|
||||
class SettingsPage extends Component<any, ISettingsState> {
|
||||
@ -61,7 +62,8 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||
resetHyperspaceDialog: false,
|
||||
resetSettingsDialog: false,
|
||||
previewTheme: setHyperspaceTheme(getUserDefaultTheme()) || setHyperspaceTheme(defaultTheme),
|
||||
defaultVisibility: getUserDefaultVisibility() || "public"
|
||||
defaultVisibility: getUserDefaultVisibility() || "public",
|
||||
federated: true
|
||||
}
|
||||
|
||||
this.toggleDarkMode = this.toggleDarkMode.bind(this);
|
||||
@ -75,6 +77,16 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||
this.setVisibility = this.setVisibility.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getFederatedStatus();
|
||||
}
|
||||
|
||||
getFederatedStatus() {
|
||||
getConfig().then((config: any) => {
|
||||
this.setState({ federated: config.federated === "true" });
|
||||
})
|
||||
}
|
||||
|
||||
toggleDarkMode() {
|
||||
this.setState({ darkModeEnabled: !this.state.darkModeEnabled });
|
||||
setUserDefaultBool('darkModeEnabled', !this.state.darkModeEnabled);
|
||||
@ -208,7 +220,7 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||
value={this.state.defaultVisibility}
|
||||
onChange={(e, value) => this.changeVisibility(value as Visibility)}
|
||||
>
|
||||
<FormControlLabel value={"public"} key={"public"} control={<Radio />} label={"Public"} />
|
||||
<FormControlLabel value={"public"} key={"public"} control={<Radio />} label={`Public ${this.state.federated? "": "(disabled by provider)"}`} disabled={!this.state.federated}/>
|
||||
<FormControlLabel value={"unlisted"} key={"unlisted"} control={<Radio />} label={"Unlisted"} />
|
||||
<FormControlLabel value={"private"} key={"private"} control={<Radio />} label={"Private (followers only)"} />
|
||||
<FormControlLabel value={"direct"} key={"direct"} control={<Radio />} label={"Direct"} />
|
||||
|
@ -34,6 +34,7 @@ interface IWelcomeState {
|
||||
openAuthDialog: boolean;
|
||||
authCode: string;
|
||||
emergencyMode: boolean;
|
||||
version: string;
|
||||
}
|
||||
|
||||
class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
@ -53,7 +54,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
defaultRedirectAddress: '',
|
||||
openAuthDialog: false,
|
||||
authCode: '',
|
||||
emergencyMode: false
|
||||
emergencyMode: false,
|
||||
version: ''
|
||||
}
|
||||
|
||||
getConfig().then((result: any) => {
|
||||
@ -68,7 +70,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
federates: result.federated? result.federated === "true": true,
|
||||
license: result.license.url,
|
||||
repo: result.repository,
|
||||
defaultRedirectAddress: result.location != "dynamic"? result.location: `https://${window.location.host}`
|
||||
defaultRedirectAddress: result.location != "dynamic"? result.location: `https://${window.location.host}`,
|
||||
version: result.version
|
||||
});
|
||||
}).catch(() => {
|
||||
console.error('config.json is missing. If you want to customize Hyperspace, please include config.json');
|
||||
@ -134,7 +137,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
}
|
||||
|
||||
getLoginUser(user: string) {
|
||||
if (user.includes("@")) {
|
||||
if (this.state.federates || user.includes("@")) {
|
||||
let newUser = user;
|
||||
this.setState({ user: newUser })
|
||||
return "https://" + newUser.split("@")[1];
|
||||
@ -222,17 +225,28 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
return true;
|
||||
} else {
|
||||
if (this.state.user.includes("@")) {
|
||||
if (this.state.federates && (this.state.federates === true)) {
|
||||
let baseUrl = this.state.user.split("@")[1];
|
||||
axios.get("https://" + baseUrl + "/api/v1/timelines/public").catch((err: Error) => {
|
||||
let userInputError = true;
|
||||
let userInputErrorMessage = "Instance name is invalid.";
|
||||
this.setState({ userInputError, userInputErrorMessage });
|
||||
return true;
|
||||
})
|
||||
});
|
||||
} else if (this.state.user.includes(this.state.registerBase? this.state.registerBase: "mastodon.social")) {
|
||||
this.setState({ userInputError, userInputErrorMessage });
|
||||
return false;
|
||||
} else {
|
||||
userInputError = true;
|
||||
userInputErrorMessage = "You cannot sign in with this username.";
|
||||
this.setState({ userInputError, userInputErrorMessage });
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
this.setState({ userInputError, userInputErrorMessage });
|
||||
return false;
|
||||
}
|
||||
this.setState({ userInputError, userInputErrorMessage });
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -276,9 +290,9 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
<div className={classes.middlePadding}/>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
label="Account name"
|
||||
label="Username"
|
||||
fullWidth
|
||||
placeholder="example@mastodon.host"
|
||||
placeholder="example@mastodon.example"
|
||||
onChange={(event) => this.updateUserInfo(event.target.value)}
|
||||
error={this.state.userInputError}
|
||||
onBlur={() => this.checkForErrors()}
|
||||
@ -288,13 +302,13 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
}
|
||||
<br/>
|
||||
{
|
||||
this.state.registerBase? <Typography variant="caption">If you are from <b>{this.state.registerBase? this.state.registerBase: "noinstance"}</b>, sign in with your username.</Typography>: null
|
||||
this.state.registerBase && this.state.federates? <Typography variant="caption">Not from <b>{this.state.registerBase? this.state.registerBase: "noinstance"}</b>? Sign in with your <Link href="https://docs.joinmastodon.org/usage/decentralization/#addressing-people" target="_blank" rel="noopener noreferrer" color="secondary">full username</Link>.</Typography>: null
|
||||
}
|
||||
<br/>
|
||||
{
|
||||
this.state.foundSavedLogin?
|
||||
<Typography>
|
||||
Signing in from a previous session? <Link onClick={() => this.resumeLogin()}>Continue login</Link>.
|
||||
Signing in from a previous session? <Link className={classes.welcomeLink} onClick={() => this.resumeLogin()}>Continue login</Link>.
|
||||
</Typography>: null
|
||||
}
|
||||
|
||||
@ -302,7 +316,6 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
<div style={{ display: "flex" }}>
|
||||
<Tooltip title="Create account on site">
|
||||
<Button
|
||||
color="primary"
|
||||
href={this.startRegistration()}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
@ -338,7 +351,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
<div className={classes.flexGrow}/>
|
||||
</div>
|
||||
<div className={classes.middlePadding}/>
|
||||
<Typography>Having trouble signing in? <Link onClick={() => this.startEmergencyLogin()}>Sign in with a code.</Link></Typography>
|
||||
<Typography>Having trouble signing in? <Link onClick={() => this.startEmergencyLogin()} className={classes.welcomeLink}>Sign in with a code.</Link></Typography>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -418,10 +431,16 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
|
||||
</Fade>
|
||||
<br/>
|
||||
<Typography variant="caption">
|
||||
© {new Date().getFullYear()} {this.state.brandName && this.state.brandName !== "Hyperspace"? `${this.state.brandName} developers and the `: ""}<Link href="https://hyperspace.marquiskurt.net" target="_blank" rel="noreferrer">Hyperspace</Link> developers. All rights reserved.
|
||||
© {new Date().getFullYear()} {this.state.brandName && this.state.brandName !== "Hyperspace"? `${this.state.brandName} developers and the `: ""} <Link className={classes.welcomeLink} href="https://hyperspace.marquiskurt.net" target="_blank" rel="noreferrer">Hyperspace</Link> developers. All rights reserved.
|
||||
</Typography>
|
||||
<Typography variant="caption">
|
||||
{ this.state.repo? <span><Link href={this.state.repo? this.state.repo: "https://github.com/hyperspacedev"} target="_blank" rel="noreferrer">Source code</Link> | </span>: null}<Link href={this.state.license? this.state.license: "https://www.apache.org/licenses/LICENSE-2.0"} target="_blank" rel="noreferrer">License</Link> | <Link href="https://github.com/hyperspacedev/hyperspace/issues/new" target="_blank" rel="noreferrer">File an Issue</Link>
|
||||
{ this.state.repo? <span>
|
||||
<Link className={classes.welcomeLink} href={this.state.repo? this.state.repo: "https://github.com/hyperspacedev"} target="_blank" rel="noreferrer">Source code</Link> | </span>: null}
|
||||
<Link className={classes.welcomeLink} href={this.state.license? this.state.license: "https://www.apache.org/licenses/LICENSE-2.0"} target="_blank" rel="noreferrer">License</Link> |
|
||||
<Link className={classes.welcomeLink} href="https://github.com/hyperspacedev/hyperspace/issues/new" target="_blank" rel="noreferrer">File an Issue</Link>
|
||||
</Typography>
|
||||
<Typography variant="caption" color="textSecondary">
|
||||
{this.state.brandName? this.state.brandName: "Hypersapce"} v.{this.state.version} {this.state.brandName && this.state.brandName !== "Hyperspace"? "(Hyperspace-like)": null}
|
||||
</Typography>
|
||||
</Paper>
|
||||
{this.showAuthDialog()}
|
||||
|
@ -34,9 +34,9 @@ export const styles = (theme: Theme) => createStyles({
|
||||
paddingRight: theme.spacing.unit * 4,
|
||||
paddingBottom: theme.spacing.unit * 6,
|
||||
textAlign: 'center',
|
||||
'& a': {
|
||||
},
|
||||
welcomeLink: {
|
||||
color: theme.palette.primary.light
|
||||
}
|
||||
},
|
||||
flexGrow: {
|
||||
flexGrow: 1
|
||||
|
@ -71,12 +71,16 @@ export const entertainerTheme: HyperspaceTheme = {
|
||||
}
|
||||
}
|
||||
|
||||
export const kingTheme: HyperspaceTheme = {
|
||||
key: "kingTheme",
|
||||
name: "Royal II",
|
||||
export const classicTheme: HyperspaceTheme = {
|
||||
key: "classicTheme",
|
||||
name: "Classic",
|
||||
palette: {
|
||||
primary: deepPurple,
|
||||
secondary: amber
|
||||
primary: {
|
||||
main: "#555555"
|
||||
},
|
||||
secondary: {
|
||||
main: "#5c2d91"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,12 +118,12 @@ export const attractTheme: HyperspaceTheme = {
|
||||
name: "Attract",
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#f5f5f5',
|
||||
main: '#E57373',
|
||||
},
|
||||
secondary: {
|
||||
main: "#1a237e",
|
||||
main: "#78909C",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const themes = [defaultTheme, gardenerTheme, teacherTheme, jokerTheme, guardTheme, entertainerTheme, kingTheme, dragonTheme, memoriumTheme, blissTheme, attractTheme]
|
||||
export const themes = [defaultTheme, gardenerTheme, teacherTheme, jokerTheme, guardTheme, entertainerTheme, classicTheme, dragonTheme, memoriumTheme, blissTheme, attractTheme]
|
Loading…
x
Reference in New Issue
Block a user