1
0
mirror of https://github.com/hyperspacedev/hyperspace synced 2025-02-10 16:50:38 +01:00

Merge branch 'b2u3' of github.com:hyperspacedev/hyperspace into settings-icons

This commit is contained in:
Marquis Kurt 2019-04-28 15:56:12 -04:00
commit 747a71df6e
9 changed files with 103 additions and 52 deletions

View File

@ -20,7 +20,7 @@ import ComposeMediaAttachment from '../components/ComposeMediaAttachment';
import EmojiPicker from '../components/EmojiPicker'; import EmojiPicker from '../components/EmojiPicker';
import { DateTimePicker, MuiPickersUtilsProvider } from 'material-ui-pickers'; import { DateTimePicker, MuiPickersUtilsProvider } from 'material-ui-pickers';
import MomentUtils from '@date-io/moment'; import MomentUtils from '@date-io/moment';
import { getUserDefaultVisibility } from '../utilities/settings'; import { getUserDefaultVisibility, getConfig } from '../utilities/settings';
interface IComposerState { interface IComposerState {
account: UAccount; account: UAccount;
@ -36,6 +36,7 @@ interface IComposerState {
poll?: PollWizard; poll?: PollWizard;
pollExpiresDate?: any; pollExpiresDate?: any;
showEmojis: boolean; showEmojis: boolean;
federated: boolean;
} }
class Composer extends Component<any, IComposerState> { class Composer extends Component<any, IComposerState> {
@ -54,20 +55,26 @@ class Composer extends Component<any, IComposerState> {
visibilityMenu: false, visibilityMenu: false,
text: '', text: '',
remainingChars: 500, remainingChars: 500,
showEmojis: false showEmojis: false,
federated: true
} }
} }
componentDidMount() { componentDidMount() {
let state = this.getComposerParams(this.props); let state = this.getComposerParams(this.props);
let text = state.acct? `@${state.acct}: `: ''; let text = state.acct? `@${state.acct}: `: '';
this.setState({ getConfig().then((config: any) => {
reply: state.reply, this.setState({
acct: state.acct, federated: config.federated === "true",
visibility: state.visibility, reply: state.reply,
text, acct: state.acct,
remainingChars: 500 - text.length visibility: state.visibility,
text,
remainingChars: 500 - text.length
});
}) })
} }
componentWillReceiveProps(props: any) { componentWillReceiveProps(props: any) {
@ -499,7 +506,7 @@ class Composer extends Component<any, IComposerState> {
<MenuItem onClick={() => this.changeVisibility('direct')}>Direct (direct message)</MenuItem> <MenuItem onClick={() => this.changeVisibility('direct')}>Direct (direct message)</MenuItem>
<MenuItem onClick={() => this.changeVisibility('private')}>Private (followers only)</MenuItem> <MenuItem onClick={() => this.changeVisibility('private')}>Private (followers only)</MenuItem>
<MenuItem onClick={() => this.changeVisibility('unlisted')}>Unlisted</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> </Menu>
</Toolbar> </Toolbar>
<DialogActions> <DialogActions>

View File

@ -252,7 +252,7 @@ class NotificationsPage extends Component<any, INotificationsPageState> {
</List> </List>
</Paper> </Paper>
</div>: </div>:
<div> <div className={classes.pageLayoutEmptyTextConstraints}>
<Typography variant="h4">All clear!</Typography> <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> <Typography paragraph>It looks like you have no notifications. Why not get the conversation going with a new post?</Typography>
</div>: </div>:

View File

@ -52,6 +52,10 @@ export const styles = (theme: Theme) => createStyles({
marginLeft: 250, marginLeft: 250,
}, },
}, },
pageLayoutEmptyTextConstraints: {
paddingLeft: theme.spacing.unit * 2,
paddingRight: theme.spacing.unit * 2
},
pageHeroBackground: { pageHeroBackground: {
position: 'relative', position: 'relative',
height: 'intrinsic', height: 'intrinsic',
@ -174,5 +178,5 @@ export const styles = (theme: Theme) => createStyles({
'& a': { '& a': {
color: theme.palette.primary.light color: theme.palette.primary.light
} }
} },
}); });

View File

@ -201,7 +201,7 @@ class RecommendationsPage extends Component<IRecommendationsPageProps, IRecommen
{ {
this.state.requestedFollows && this.state.requestedFollows.length > 0? this.state.requestedFollows && this.state.requestedFollows.length > 0?
this.showFollowRequests(): this.showFollowRequests():
<div> <div className={classes.pageLayoutEmptyTextConstraints}>
<Typography variant="h6">You don't have any follow requests.</Typography> <Typography variant="h6">You don't have any follow requests.</Typography>
<br/> <br/>
</div> </div>
@ -210,7 +210,7 @@ class RecommendationsPage extends Component<IRecommendationsPageProps, IRecommen
<br/> <br/>
{ {
this.state.followSuggestions && this.state.followSuggestions.length > 0? this.showFollowSuggestions(): 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 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> <Typography paragraph>Why not interact with the fediverse a bit by creating a new post?</Typography>
</div> </div>

View File

@ -164,11 +164,12 @@ class SearchPage extends Component<any, ISearchPageState> {
return ( return (
<div> <div>
<ListSubheader>Accounts</ListSubheader> <ListSubheader>Accounts</ListSubheader>
<Paper className={classes.pageListConstraints}>
<List>
{ {
this.state.results? this.state.results && this.state.results.accounts.length > 0?
this.state.results.accounts.map((acct: Account) => { <Paper className={classes.pageListConstraints}>
<List>
{ this.state.results.accounts.map((acct: Account) => {
return ( return (
<ListItem key={acct.id}> <ListItem key={acct.id}>
<ListItemAvatar> <ListItemAvatar>
@ -189,16 +190,19 @@ class SearchPage extends Component<any, ISearchPageState> {
</ListItemSecondaryAction> </ListItemSecondaryAction>
</ListItem> </ListItem>
); );
}): null })}
</List>
</Paper>: <Typography variant="caption" className={classes.pageLayoutEmptyTextConstraints}>No results found</Typography>
} }
</List>
</Paper>
<br/> <br/>
</div> </div>
) )
} }
showAllPostsFromQuery() { showAllPostsFromQuery() {
const {classes} = this.props;
return ( return (
<div> <div>
<ListSubheader>Posts</ListSubheader> <ListSubheader>Posts</ListSubheader>
@ -207,13 +211,14 @@ class SearchPage extends Component<any, ISearchPageState> {
this.state.results.statuses.length > 0? this.state.results.statuses.length > 0?
this.state.results.statuses.map((post: Status) => { this.state.results.statuses.map((post: Status) => {
return <Post key={post.id} post={post} client={this.client}/> 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> </div>
); );
} }
showAllPostsWithTag() { showAllPostsWithTag() {
const {classes} = this.props;
return ( return (
<div> <div>
<ListSubheader>Tagged posts</ListSubheader> <ListSubheader>Tagged posts</ListSubheader>
@ -222,7 +227,7 @@ class SearchPage extends Component<any, ISearchPageState> {
this.state.tagResults.length > 0? this.state.tagResults.length > 0?
this.state.tagResults.map((post: Status) => { this.state.tagResults.map((post: Status) => {
return <Post key={post.id} post={post} client={this.client}/> 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> </div>
); );

View File

@ -24,7 +24,7 @@ import {
Typography Typography
} from '@material-ui/core'; } from '@material-ui/core';
import {styles} from './PageLayout.styles'; 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 {canSendNotifications, browserSupportsNotificationRequests} from '../utilities/notifications';
import {themes, defaultTheme} from '../types/HyperspaceTheme'; import {themes, defaultTheme} from '../types/HyperspaceTheme';
import ThemePreview from '../components/ThemePreview'; import ThemePreview from '../components/ThemePreview';
@ -54,6 +54,7 @@ interface ISettingsState {
resetSettingsDialog: boolean; resetSettingsDialog: boolean;
previewTheme: Theme; previewTheme: Theme;
defaultVisibility: Visibility; defaultVisibility: Visibility;
federated: boolean;
} }
class SettingsPage extends Component<any, ISettingsState> { class SettingsPage extends Component<any, ISettingsState> {
@ -72,7 +73,8 @@ class SettingsPage extends Component<any, ISettingsState> {
resetHyperspaceDialog: false, resetHyperspaceDialog: false,
resetSettingsDialog: false, resetSettingsDialog: false,
previewTheme: setHyperspaceTheme(getUserDefaultTheme()) || setHyperspaceTheme(defaultTheme), previewTheme: setHyperspaceTheme(getUserDefaultTheme()) || setHyperspaceTheme(defaultTheme),
defaultVisibility: getUserDefaultVisibility() || "public" defaultVisibility: getUserDefaultVisibility() || "public",
federated: true
} }
this.toggleDarkMode = this.toggleDarkMode.bind(this); this.toggleDarkMode = this.toggleDarkMode.bind(this);
@ -86,6 +88,16 @@ class SettingsPage extends Component<any, ISettingsState> {
this.setVisibility = this.setVisibility.bind(this); this.setVisibility = this.setVisibility.bind(this);
} }
componentDidMount() {
this.getFederatedStatus();
}
getFederatedStatus() {
getConfig().then((config: any) => {
this.setState({ federated: config.federated === "true" });
})
}
toggleDarkMode() { toggleDarkMode() {
this.setState({ darkModeEnabled: !this.state.darkModeEnabled }); this.setState({ darkModeEnabled: !this.state.darkModeEnabled });
setUserDefaultBool('darkModeEnabled', !this.state.darkModeEnabled); setUserDefaultBool('darkModeEnabled', !this.state.darkModeEnabled);
@ -219,7 +231,7 @@ class SettingsPage extends Component<any, ISettingsState> {
value={this.state.defaultVisibility} value={this.state.defaultVisibility}
onChange={(e, value) => this.changeVisibility(value as Visibility)} 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={"unlisted"} key={"unlisted"} control={<Radio />} label={"Unlisted"} />
<FormControlLabel value={"private"} key={"private"} control={<Radio />} label={"Private (followers only)"} /> <FormControlLabel value={"private"} key={"private"} control={<Radio />} label={"Private (followers only)"} />
<FormControlLabel value={"direct"} key={"direct"} control={<Radio />} label={"Direct"} /> <FormControlLabel value={"direct"} key={"direct"} control={<Radio />} label={"Direct"} />

View File

@ -34,6 +34,7 @@ interface IWelcomeState {
openAuthDialog: boolean; openAuthDialog: boolean;
authCode: string; authCode: string;
emergencyMode: boolean; emergencyMode: boolean;
version: string;
} }
class WelcomePage extends Component<IWelcomeProps, IWelcomeState> { class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
@ -53,7 +54,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
defaultRedirectAddress: '', defaultRedirectAddress: '',
openAuthDialog: false, openAuthDialog: false,
authCode: '', authCode: '',
emergencyMode: false emergencyMode: false,
version: ''
} }
getConfig().then((result: any) => { getConfig().then((result: any) => {
@ -68,7 +70,8 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
federates: result.federated? result.federated === "true": true, federates: result.federated? result.federated === "true": true,
license: result.license.url, license: result.license.url,
repo: result.repository, 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(() => { }).catch(() => {
console.error('config.json is missing. If you want to customize Hyperspace, please include config.json'); 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) { getLoginUser(user: string) {
if (user.includes("@")) { if (this.state.federates || user.includes("@")) {
let newUser = user; let newUser = user;
this.setState({ user: newUser }) this.setState({ user: newUser })
return "https://" + newUser.split("@")[1]; return "https://" + newUser.split("@")[1];
@ -222,17 +225,28 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
return true; return true;
} else { } else {
if (this.state.user.includes("@")) { if (this.state.user.includes("@")) {
let baseUrl = this.state.user.split("@")[1]; if (this.state.federates && (this.state.federates === true)) {
axios.get("https://" + baseUrl + "/api/v1/timelines/public").catch((err: Error) => { let baseUrl = this.state.user.split("@")[1];
let userInputError = true; axios.get("https://" + baseUrl + "/api/v1/timelines/public").catch((err: Error) => {
let userInputErrorMessage = "Instance name is invalid."; 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 }); this.setState({ userInputError, userInputErrorMessage });
return true; return true;
}) }
} else { } else {
this.setState({ userInputError, userInputErrorMessage }); this.setState({ userInputError, userInputErrorMessage });
return false; return false;
} }
this.setState({ userInputError, userInputErrorMessage });
return false; return false;
} }
@ -276,9 +290,9 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
<div className={classes.middlePadding}/> <div className={classes.middlePadding}/>
<TextField <TextField
variant="outlined" variant="outlined"
label="Account name" label="Username"
fullWidth fullWidth
placeholder="example@mastodon.host" placeholder="example@mastodon.example"
onChange={(event) => this.updateUserInfo(event.target.value)} onChange={(event) => this.updateUserInfo(event.target.value)}
error={this.state.userInputError} error={this.state.userInputError}
onBlur={() => this.checkForErrors()} onBlur={() => this.checkForErrors()}
@ -288,13 +302,13 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
} }
<br/> <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/> <br/>
{ {
this.state.foundSavedLogin? this.state.foundSavedLogin?
<Typography> <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 </Typography>: null
} }
@ -302,7 +316,6 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<Tooltip title="Create account on site"> <Tooltip title="Create account on site">
<Button <Button
color="primary"
href={this.startRegistration()} href={this.startRegistration()}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
@ -338,7 +351,7 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
<div className={classes.flexGrow}/> <div className={classes.flexGrow}/>
</div> </div>
<div className={classes.middlePadding}/> <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> </div>
); );
} }
@ -418,10 +431,16 @@ class WelcomePage extends Component<IWelcomeProps, IWelcomeState> {
</Fade> </Fade>
<br/> <br/>
<Typography variant="caption"> <Typography variant="caption">
&copy; {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. &copy; {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>
<Typography variant="caption"> <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> </Typography>
</Paper> </Paper>
{this.showAuthDialog()} {this.showAuthDialog()}

View File

@ -34,9 +34,9 @@ export const styles = (theme: Theme) => createStyles({
paddingRight: theme.spacing.unit * 4, paddingRight: theme.spacing.unit * 4,
paddingBottom: theme.spacing.unit * 6, paddingBottom: theme.spacing.unit * 6,
textAlign: 'center', textAlign: 'center',
'& a': { },
color: theme.palette.primary.light welcomeLink: {
} color: theme.palette.primary.light
}, },
flexGrow: { flexGrow: {
flexGrow: 1 flexGrow: 1

View File

@ -71,12 +71,16 @@ export const entertainerTheme: HyperspaceTheme = {
} }
} }
export const kingTheme: HyperspaceTheme = { export const classicTheme: HyperspaceTheme = {
key: "kingTheme", key: "classicTheme",
name: "Royal II", name: "Classic",
palette: { palette: {
primary: deepPurple, primary: {
secondary: amber main: "#555555"
},
secondary: {
main: "#5c2d91"
}
} }
} }
@ -114,12 +118,12 @@ export const attractTheme: HyperspaceTheme = {
name: "Attract", name: "Attract",
palette: { palette: {
primary: { primary: {
main: '#f5f5f5', main: '#E57373',
}, },
secondary: { 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]