diff options
-rw-r--r-- | app/javascript/mastodon/features/account/components/header.js | 94 | ||||
-rw-r--r-- | app/javascript/styles/components.scss | 41 |
2 files changed, 124 insertions, 11 deletions
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 3239b1085..b728c66e2 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -16,6 +16,57 @@ const messages = defineMessages({ requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, }); +/* + THIS IS A MESS BECAUSE EFFING MASTODON AND ITS EFFING HTML BIOS + INSTEAD OF JUST STORING EVERYTHING IN PLAIN EFFING TEXT ! ! ! ! + BLANK LINES ALSO WON'T WORK BECAUSE RIGHT NOW MASTODON CONVERTS + THOSE INTO `<P>` ELEMENTS INSTEAD OF LEAVING IT AS `<BR><BR>` ! + TL:DR; THIS IS LARGELY A HACK. WITH BETTER BACKEND STUFF WE CAN + IMPROVE THIS BY BETTER PREDICTING HOW THE METADATA WILL BE SENT + WHILE MAINTAINING BASIC PLAIN-TEXT PROCESSING. THE OTHER OPTION + IS TO TURN ALL BIOS INTO PLAIN-TEXT VIA A TREE-WALKER, AND THEN + PROCESS THE YAML AND LINKS AND EVERYTHING OURSELVES. THIS WOULD + BE INCREDIBLY COMPLICATED, AND IT WOULD BE A MILLION TIMES LESS + DIFFICULT IF MASTODON JUST GAVE US PLAIN-TEXT BIOS (WHICH QUITE + FRANKLY MAKES THE MOST SENSE SINCE THAT'S WHAT USERS PROVIDE IN + SETTINGS) TO BEGIN WITH AND LEFT ALL PROCESSING TO THE FRONTEND + TO HANDLE ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! + ANYWAY I KNOW WHAT NEEDS TO BE DONE REGARDING BACKEND STUFF BUT + I'M NOT SMART ENOUGH TO FIGURE OUT HOW TO ACTUALLY IMPLEMENT IT + SO FEEL FREE TO @ ME IF YOU NEED MY IDEAS REGARDING THAT. UNTIL + THEN WE'LL JUST HAVE TO MAKE DO WITH THIS MESSY AND UNFORTUNATE + HACKING ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! + + with love, + @kibi@glitch.social <3 +*/ + +const NEW_LINE = /(?:^|\r?\n|<br\s*\/?>)/g +const YAML_OPENER = /---/; +const YAML_CLOSER = /(?:---|\.\.\.)/; +const YAML_STRING = /(?:"(?:[^"\n]){1,32}"|'(?:[^'\n]){1,32}'|(?:[^'":\n]){1,32})/g; +const YAML_LINE = new RegExp("\\s*" + YAML_STRING.source + "\\s*:\\s*" + YAML_STRING.source + "\\s*", "g"); +const BIO_REGEX = new RegExp(NEW_LINE.source + "*" + YAML_OPENER.source + NEW_LINE.source + "+(?:" + YAML_LINE.source + NEW_LINE.source + "+){0,4}" + YAML_CLOSER.source + NEW_LINE.source + "*"); + +const processBio = (data) => { + let props = {text: data, metadata: []}; + let yaml = data.match(BIO_REGEX); + if (!yaml) return props; + else yaml = yaml[0]; + let start = props.text.indexOf(yaml); + let end = start + yaml.length; + props.text = props.text.substr(0, start) + props.text.substr(end); + yaml = yaml.replace(NEW_LINE, "\n"); + let metadata = (yaml ? yaml.match(YAML_LINE) : []) || []; + for (let i = 0; i < metadata.length; i++) { + let result = metadata[i].match(YAML_STRING); + if (result[0][0] === '"' || result[0][0] === "'") result[0] = result[0].substr(1, result[0].length - 2); + if (result[1][0] === '"' || result[1][0] === "'") result[0] = result[1].substr(1, result[1].length - 2); + props.metadata.push(result); + } + return props; +}; + const makeMapStateToProps = () => { const mapStateToProps = state => ({ autoPlayGif: state.getIn(['meta', 'auto_play_gif']), @@ -122,21 +173,44 @@ export default class Header extends ImmutablePureComponent { lockedIcon = <i className='fa fa-lock' />; } - const content = { __html: emojify(account.get('note')) }; - const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) }; + const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) }; + const { text, metadata } = processBio(account.get('note')); return ( - <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}> - <div> - <Avatar account={account} autoPlayGif={this.props.autoPlayGif} /> + <div className='account__header__wrapper'> + <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}> + <div> + <Avatar account={account} autoPlayGif={this.props.autoPlayGif} /> - <span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} /> - <span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span> - <div className='account__header__content' dangerouslySetInnerHTML={content} /> + <span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} /> + <span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span> + <div className='account__header__content' dangerouslySetInnerHTML={{__html: emojify(text)}} /> - {info} - {actionBtn} + {info} + {actionBtn} + </div> </div> + + {metadata.length && ( + <div className='account__metadata'> + {(() => { + let data = []; + for (let i = 0; i < metadata.length; i++) { + data.push( + <div + className='account__metadata-item' + title={metadata[i][0] + ":" + metadata[i][1]} + key={i} + > + <span dangerouslySetInnerHTML={{__html: emojify(metadata[i][0])}} /> + <strong dangerouslySetInnerHTML={{__html: emojify(metadata[i][1])}} /> + </div> + ); + } + return data; + })()} + </div> + ) || null} </div> ); } diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss index c2062c398..10ce06940 100644 --- a/app/javascript/styles/components.scss +++ b/app/javascript/styles/components.scss @@ -820,9 +820,12 @@ padding: 10px; } -.account__header { +.account__header__wrapper { flex: 0 0 auto; background: lighten($ui-base-color, 4%); +} + +.account__header { text-align: center; background-size: cover; background-position: center; @@ -887,6 +890,42 @@ } } +.account__metadata { + display: block; + font-size: 15px; + line-height: 36px; + overflow: hidden; + + .account__metadata-item { + display: flex; + flex-direction: row; + border-top: 1px solid lighten($ui-base-color, 8%); + + & > span, & > strong { + display: inline-block; + padding: 10px 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + & > span { + flex: 0 0 auto; + width: 120px; + color: $ui-primary-color; + background: lighten($ui-base-color, 13%); + font-variant: small-caps; + } + + & > strong { + flex: auto; + color: $primary-text-color; + background: $ui-base-color; + font-weight: bold; + } + } +} + .account__action-bar { border-top: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%); |