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
18 changed files with 147 additions and 167 deletions
-24
View File
@@ -1,24 +0,0 @@
# https://woodpecker-ci.org/docs/usage/workflow-syntax#when---global-workflow-conditions
when:
- event: push
branch: next
# https://goreleaser.com/ci/woodpecker/
# https://woodpecker-ci.org/docs/usage/workflow-syntax#clone
clone:
git:
image: woodpeckerci/plugin-git
settings:
tags: true
# https://woodpecker-ci.org/plugins/docker-buildx
steps:
publish:
image: woodpeckerci/plugin-docker-buildx:5.2.2
settings:
pull_image: true
username: gotosocial
password:
from_secret: gts_docker_password
repo: superseriousbusiness/masto-fe-standalone
tag: next
+1 -2
View File
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added documentation for `yarn dev` (#75)
- Added an .editorconfig (#78)
- Added a CHANGELOG.md based on “Keep a Changelog” (#80)
- Added a CHANGELOG.md basaed on “Keep a Changelog” (#80)
### Changed
@@ -29,7 +29,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated Yarn to 4.10.3 (#90)
- Updated Webpack to 5.102.1 (#83)
- Updated ESlint to 9.37.0 (#88)
- Fixed an issue where media items wouldnt show correctly (#109)
### Removed
+1
View File
@@ -27,6 +27,7 @@ RUN apk upgrade --update --no-cache
# Copy bigger nested stuff.
COPY --from=builder /build/public/packs/js/flavours/glitch /usr/share/nginx/html/packs/js/flavours/glitch
COPY --from=builder /build/public/packs/js/flavours/vanilla /usr/share/nginx/html/packs/js/flavours/vanilla
# Copy remaining files.
COPY --from=builder /build/public /usr/share/nginx/html/
@@ -1,10 +1,13 @@
import PropTypes from "prop-types";
import React from "react";
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";
@@ -15,9 +18,15 @@ interface Props {
others?: List<Account>,
localDomain?: string,
inline?: boolean,
nameLayout?: string,
}
export class DisplayName extends React.PureComponent<Props> {
static propTypes = {
onChange: PropTypes.func.isRequired,
nameLayout: ImmutablePropTypes.map.isRequired,
};
handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({
currentTarget,
}) => {
@@ -55,7 +64,7 @@ export class DisplayName extends React.PureComponent<Props> {
};
render() {
const { others, localDomain, inline } = this.props;
const { others, localDomain, inline, nameLayout } = this.props;
let displayName: React.ReactNode,
suffix: React.ReactNode,
@@ -73,7 +82,7 @@ export class DisplayName extends React.PureComponent<Props> {
.map((a) => (
<bdi key={a.get("id")}>
<strong
className='display-name__html'
className="display-name__html"
dangerouslySetInnerHTML={{ __html: a.get("display_name_html") }}
/>
</bdi>
@@ -93,39 +102,39 @@ export class DisplayName extends React.PureComponent<Props> {
displayName = (
<bdi>
<strong
className='display-name__html'
className="display-name__html"
dangerouslySetInnerHTML={{
__html: account.get("display_name_html"),
}}
/>
</bdi>
);
suffix = <span className='display-name__account'>@{acct}</span>;
suffix = <span className="display-name__account">@{acct}</span>;
} else {
displayName = (
<bdi>
<strong className='display-name__html'>
<Skeleton width='10ch' />
<strong className="display-name__html">
<Skeleton width="10ch" />
</strong>
</bdi>
);
suffix = (
<span className='display-name__account'>
<Skeleton width='7ch' />
<span className="display-name__account">
<Skeleton width="7ch" />
</span>
);
}
return (
<span
className={classNames("display-name", { inline })}
<div
className={classNames("display-name", { inline }, nameLayout)}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
>
{displayName}
{inline ? " " : null}
{suffix}
</span>
</div>
);
}
}
@@ -826,6 +826,7 @@ class Status extends ImmutablePureComponent {
friend={account}
collapsed={isCollapsed}
parseClick={parseClick}
settings={settings}
/>
) : null}
<StatusIcons
@@ -15,6 +15,7 @@ export default class StatusHeader extends PureComponent {
status: ImmutablePropTypes.map.isRequired,
friend: ImmutablePropTypes.map,
parseClick: PropTypes.func.isRequired,
settings: ImmutablePropTypes.map.isRequired,
};
// Handles clicks on account name/image
@@ -33,6 +34,7 @@ export default class StatusHeader extends PureComponent {
const {
status,
friend,
settings,
} = this.props;
const account = status.get("account");
@@ -62,7 +64,7 @@ export default class StatusHeader extends PureComponent {
onClick={this.handleAccountClick}
rel='noopener noreferrer'
>
<DisplayName account={account} />
<DisplayName account={account} nameLayout={settings.get("name_layout")} />
</a>
</div>
);
@@ -33,6 +33,10 @@ const messages = defineMessages({
unlisted: { id: "privacy.unlisted.short", defaultMessage: "Unlisted" },
private: { id: "privacy.private.short", defaultMessage: "Followers 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 {
@@ -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>
</LocalSettingsPageItem>
</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>
),
({ intl, onChange, settings }) => (
@@ -19,7 +19,7 @@ const Account = connect(state => ({
account: state.getIn(["accounts", me]),
}))(({ account }) => (
<Permalink href={account.get("url")} to={`/@${account.get("acct")}`} title={account.get("acct")}>
<Avatar account={account} size={34} />
<Avatar account={account} size={35} />
</Permalink>
));
@@ -108,7 +108,8 @@ class Header extends PureComponent {
return (
<div className='ui__header'>
<Link to='/' className='ui__header__logo'>
<Icon id='gts-simple' />
<WordmarkLogo />
<SymbolLogo />
</Link>
<div className='ui__header__links'>
@@ -53,6 +53,7 @@ const initialState = ImmutableMap({
pop_in_player : true,
pop_in_position : "right",
}),
name_layout : "both_y",
notifications : ImmutableMap({
favicon_badge : false,
tab_badge : true,
@@ -56,6 +56,57 @@
$ui-header-height: 55px;
.ui__header {
display: none;
box-sizing: border-box;
height: $ui-header-height;
position: sticky;
top: 0;
z-index: 3;
justify-content: space-between;
align-items: center;
&__logo {
display: inline-flex;
padding: 15px;
.logo {
height: $ui-header-height - 30px;
width: auto;
}
.logo--wordmark {
display: none;
}
@media screen and (width >= 320px) {
.logo--wordmark {
display: block;
}
.logo--icon {
display: none;
}
}
}
&__links {
display: flex;
align-items: center;
gap: 10px;
padding: 0 10px;
overflow: hidden;
.button {
flex: 0 0 auto;
}
.button-tertiary {
flex-shrink: 1;
}
}
}
.tabs-bar__wrapper {
background: darken($ui-base-color, 8%);
position: sticky;
@@ -64,7 +64,29 @@
line-height: 18px;
}
.media-gallery {
box-sizing: border-box;
overflow: hidden;
border-radius: 4px;
position: relative;
width: 100%;
min-height: 64px;
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%;
gap: 2px;
@include fullwidth-gallery;
}
.media-gallery__item {
border: 0;
box-sizing: border-box;
display: block;
position: relative;
border-radius: 4px;
overflow: hidden;
&--tall {
grid-row: span 2;
}
@@ -277,8 +277,8 @@
.layout-single-column .ui__header {
display: flex;
border-bottom: 1px solid lighten($ui-base-color, 8%);
background: $ui-base-color;
border-bottom: 1px solid lighten($ui-base-color, 8%);
}
.layout-single-column {
@@ -10,6 +10,4 @@
@import "sizes";
/* 🧩 Components */
@import "media-gallery";
@import "status";
@import "ui-header";
@@ -1,73 +1 @@
/* 🖼️ Media Gallery */
.media-gallery {
position: relative;
display: grid;
grid-template-columns: auto auto;
gap: var(--size-ui-gap);
overflow: hidden;
}
.media-gallery:not(.full-width) {
border-radius: var(--size-ui-radius);
}
.media-gallery.full-width {
margin-inline: -15px;
/* the `div` is there for specificity */
div.media-gallery__item {
border-radius: 0;
}
}
.media-gallery:not(.full-width) .spoiler-button__overlay {
border-radius: var(--size-ui-radius);
}
.media-gallery__item {
overflow: hidden;
}
/* Only one image */
.media-gallery__item:nth-child(2):nth-last-child(1) {
border-radius: var(--size-ui-radius);
}
/* First image in a set of two */
.media-gallery__item:nth-child(2):nth-last-child(2) {
border-top-left-radius: var(--size-ui-radius);
border-bottom-left-radius: var(--size-ui-radius);
}
/* Second image in a set of two */
.media-gallery__item:nth-child(3):nth-last-child(1) {
border-top-right-radius: var(--size-ui-radius);
border-bottom-right-radius: var(--size-ui-radius);
}
/* First image in a set of at least two */
.media-gallery__item:nth-child(2):not(:nth-last-child(1)) {
border-top-left-radius: var(--size-ui-radius);
}
/* Second image in a set of at least two */
.media-gallery__item:nth-child(3):not(:nth-last-child(1)) {
border-top-right-radius: var(--size-ui-radius);
}
/* Second to last image in an even set */
.media-gallery__item:nth-last-child(2):nth-child(even) {
border-bottom-left-radius: var(--size-ui-radius);
}
/* Last image in an even set */
.media-gallery__item:last-child:nth-child(odd) {
border-bottom-right-radius: var(--size-ui-radius);
}
/* Last image in an uneven set */
.media-gallery__item:last-child:nth-child(even) {
grid-column: 1/-1;
border-bottom-right-radius: var(--size-ui-radius);
border-bottom-left-radius: var(--size-ui-radius);
}
@@ -11,5 +11,4 @@
/* Components */
--size-avatar: 46px;
--size-icon: 20px;
--size-header-block: #{$ui-header-height};
}
@@ -31,11 +31,9 @@
color: var(--color-secondary-fg);
}
.status .mention {
&,
&:hover {
text-decoration: none;
}
.status .mention,
.status .mention:hover {
text-decoration: none;
}
.status .mention:is(:focus, :hover) span {
@@ -18,6 +18,16 @@
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 {
font-weight: 700;
}
@@ -27,7 +37,14 @@
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-color: currentColor;
text-decoration-thickness: 2px;
@@ -1,43 +0,0 @@
/* 🧑‍💻 UI: Header */
.ui__header {
position: sticky;
top: 0;
z-index: 3;
display: none;
align-items: center;
justify-content: space-between;
padding-inline-start: 7px;
height: var(--size-header-block);
box-sizing: border-box;
svg.gts-icon {
display: block;
}
}
.ui__header__logo {
--size-icon: 32px;
padding: 8px;
}
.ui__header__links {
display: flex;
align-items: center;
gap: 10px;
padding-inline: 10px;
overflow: hidden;
a {
display: flex;
align-items: center;
line-height: 20px;
}
.button {
flex: 0 0 auto;
}
.button-tertiary {
flex-shrink: 1;
}
}