7 Commits

Author SHA1 Message Date
Zoë Bijl 4414bdc369 [bugfix] set type for nameLayout 2025-10-21 01:32:28 +02:00
Zoë Bijl 276bd114eb [feature] toggle sections based on setting 2025-10-21 00:43:29 +02:00
Zoë Bijl 4cb3e9c107 [chore] undo change to Immutable 2025-10-21 00:42:36 +02:00
Zoë Bijl 3cffe98969 [chore] refactor css 2025-10-21 00:42:35 +02:00
Zoë Bijl 9f4f83f383 [chore] lint 2025-10-21 00:42:35 +02:00
Zoë Bijl 2f1851e8f9 change to ImmutablePureComponent 2025-10-21 00:42:35 +02:00
Zoë Bijl 7631089507 [feature] add “Name Layout” setting 2025-10-21 00:42:35 +02:00
7 changed files with 68 additions and 20 deletions
@@ -1,10 +1,13 @@
import PropTypes from "prop-types";
import React from "react"; import React from "react";
import classNames from "classnames"; import classNames from "classnames";
import { type List } from "immutable"; import ImmutablePropTypes from "react-immutable-proptypes";
import { type Account } from "flavours/glitch/types/resources"; import { type List } from "immutable";
import { type Account } from "flavours/glitch/types/resources";
import { autoPlayGif } from "../initial_state"; import { autoPlayGif } from "../initial_state";
@@ -15,9 +18,15 @@ interface Props {
others?: List<Account>, others?: List<Account>,
localDomain?: string, localDomain?: string,
inline?: boolean, inline?: boolean,
nameLayout?: string,
} }
export class DisplayName extends React.PureComponent<Props> { export class DisplayName extends React.PureComponent<Props> {
static propTypes = {
onChange: PropTypes.func.isRequired,
nameLayout: ImmutablePropTypes.map.isRequired,
};
handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({ handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({
currentTarget, currentTarget,
}) => { }) => {
@@ -55,7 +64,7 @@ export class DisplayName extends React.PureComponent<Props> {
}; };
render() { render() {
const { others, localDomain, inline } = this.props; const { others, localDomain, inline, nameLayout } = this.props;
let displayName: React.ReactNode, let displayName: React.ReactNode,
suffix: React.ReactNode, suffix: React.ReactNode,
@@ -73,7 +82,7 @@ export class DisplayName extends React.PureComponent<Props> {
.map((a) => ( .map((a) => (
<bdi key={a.get("id")}> <bdi key={a.get("id")}>
<strong <strong
className='display-name__html' className="display-name__html"
dangerouslySetInnerHTML={{ __html: a.get("display_name_html") }} dangerouslySetInnerHTML={{ __html: a.get("display_name_html") }}
/> />
</bdi> </bdi>
@@ -93,39 +102,39 @@ export class DisplayName extends React.PureComponent<Props> {
displayName = ( displayName = (
<bdi> <bdi>
<strong <strong
className='display-name__html' className="display-name__html"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: account.get("display_name_html"), __html: account.get("display_name_html"),
}} }}
/> />
</bdi> </bdi>
); );
suffix = <span className='display-name__account'>@{acct}</span>; suffix = <span className="display-name__account">@{acct}</span>;
} else { } else {
displayName = ( displayName = (
<bdi> <bdi>
<strong className='display-name__html'> <strong className="display-name__html">
<Skeleton width='10ch' /> <Skeleton width="10ch" />
</strong> </strong>
</bdi> </bdi>
); );
suffix = ( suffix = (
<span className='display-name__account'> <span className="display-name__account">
<Skeleton width='7ch' /> <Skeleton width="7ch" />
</span> </span>
); );
} }
return ( return (
<span <div
className={classNames("display-name", { inline })} className={classNames("display-name", { inline }, nameLayout)}
onMouseEnter={this.handleMouseEnter} onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave} onMouseLeave={this.handleMouseLeave}
> >
{displayName} {displayName}
{inline ? " " : null} {inline ? " " : null}
{suffix} {suffix}
</span> </div>
); );
} }
} }
@@ -826,6 +826,7 @@ class Status extends ImmutablePureComponent {
friend={account} friend={account}
collapsed={isCollapsed} collapsed={isCollapsed}
parseClick={parseClick} parseClick={parseClick}
settings={settings}
/> />
) : null} ) : null}
<StatusIcons <StatusIcons
@@ -15,6 +15,7 @@ export default class StatusHeader extends PureComponent {
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
friend: ImmutablePropTypes.map, friend: ImmutablePropTypes.map,
parseClick: PropTypes.func.isRequired, parseClick: PropTypes.func.isRequired,
settings: ImmutablePropTypes.map.isRequired,
}; };
// Handles clicks on account name/image // Handles clicks on account name/image
@@ -33,6 +34,7 @@ export default class StatusHeader extends PureComponent {
const { const {
status, status,
friend, friend,
settings,
} = this.props; } = this.props;
const account = status.get("account"); const account = status.get("account");
@@ -62,7 +64,7 @@ export default class StatusHeader extends PureComponent {
onClick={this.handleAccountClick} onClick={this.handleAccountClick}
rel='noopener noreferrer' rel='noopener noreferrer'
> >
<DisplayName account={account} /> <DisplayName account={account} nameLayout={settings.get("name_layout")} />
</a> </a>
</div> </div>
); );
@@ -33,6 +33,10 @@ const messages = defineMessages({
unlisted: { id: "privacy.unlisted.short", defaultMessage: "Unlisted" }, unlisted: { id: "privacy.unlisted.short", defaultMessage: "Unlisted" },
private: { id: "privacy.private.short", defaultMessage: "Followers only" }, private: { id: "privacy.private.short", defaultMessage: "Followers only" },
direct: { id: "privacy.direct.short", defaultMessage: "Mentioned people only" }, direct: { id: "privacy.direct.short", defaultMessage: "Mentioned people only" },
namelayout_display: { id: "namelayout.display", defaultMessage: "Display name" },
namelayout_handle: { id: "namelayout.handle", defaultMessage: "Handle" },
namelayout_both_y: { id: "namelayout.both.vertical", defaultMessage: "Both (Vertical)" },
namelayout_both_x: { id: "namelayout.both.horizontal", defaultMessage: "Both (Horizontal)" },
}); });
class LocalSettingsPage extends PureComponent { class LocalSettingsPage extends PureComponent {
@@ -198,6 +202,22 @@ class LocalSettingsPage extends PureComponent {
<span className='hint'><FormattedMessage id='settings.wide_view_hint' defaultMessage='Stretches columns to better fill the available space.' /></span> <span className='hint'><FormattedMessage id='settings.wide_view_hint' defaultMessage='Stretches columns to better fill the available space.' /></span>
</LocalSettingsPageItem> </LocalSettingsPageItem>
</section> </section>
<section>
<h2><FormattedMessage id='settings.name_layout' defaultMessage='Name layout' /></h2>
<LocalSettingsPageItem
settings={settings}
item={["name_layout"]}
id='mastodon-settings--status-username-inline'
onChange={onChange}
options={[
{ value: "display", message: intl.formatMessage(messages.namelayout_display) },
{ value: "handle", message: intl.formatMessage(messages.namelayout_handle) },
{ value: "both_y", message: intl.formatMessage(messages.namelayout_both_y) },
{ value: "both_x", message: intl.formatMessage(messages.namelayout_both_x) },
]}
>
</LocalSettingsPageItem>
</section>
</div> </div>
), ),
({ intl, onChange, settings }) => ( ({ intl, onChange, settings }) => (
@@ -53,6 +53,7 @@ const initialState = ImmutableMap({
pop_in_player : true, pop_in_player : true,
pop_in_position : "right", pop_in_position : "right",
}), }),
name_layout : "both_y",
notifications : ImmutableMap({ notifications : ImmutableMap({
favicon_badge : false, favicon_badge : false,
tab_badge : true, tab_badge : true,
@@ -31,11 +31,9 @@
color: var(--color-secondary-fg); color: var(--color-secondary-fg);
} }
.status .mention { .status .mention,
&, .status .mention:hover {
&:hover { text-decoration: none;
text-decoration: none;
}
} }
.status .mention:is(:focus, :hover) span { .status .mention:is(:focus, :hover) span {
@@ -18,6 +18,16 @@
line-height: max(21px, 1.4em); line-height: max(21px, 1.4em);
} }
.display-name.both_x {
display: flex;
gap: var(--size-ui-gap);
}
.display-name.handle bdi,
.display-name.display .display-name__account {
display: none;
}
.display-name__html { .display-name__html {
font-weight: 700; font-weight: 700;
} }
@@ -27,7 +37,14 @@
font-weight: 400; font-weight: 400;
} }
&:hover .display-name__html { .display-name.handle .display-name__account {
color: currentcolor;
font-size: inherit;
font-weight: 700;
}
&:hover .display-name__html,
&:hover .display-name.handle .display-name__account {
text-decoration-line: underline; text-decoration-line: underline;
text-decoration-color: currentColor; text-decoration-color: currentColor;
text-decoration-thickness: 2px; text-decoration-thickness: 2px;