Merge branch 'main' into fix/thumb-action-button-alignment

This commit is contained in:
Jay Sitter 2023-06-27 11:42:31 -04:00 committed by GitHub
commit 1e4e468e5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 90 additions and 90 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "lemmy-ui", "name": "lemmy-ui",
"version": "0.18.0", "version": "0.18.1-rc.1",
"description": "An isomorphic UI for lemmy", "description": "An isomorphic UI for lemmy",
"repository": "https://github.com/LemmyNet/lemmy-ui", "repository": "https://github.com/LemmyNet/lemmy-ui",
"license": "AGPL-3.0", "license": "AGPL-3.0",

View file

@ -4,6 +4,7 @@ import {
Component, Component,
InfernoKeyboardEvent, InfernoKeyboardEvent,
InfernoMouseEvent, InfernoMouseEvent,
InfernoNode,
linkEvent, linkEvent,
} from "inferno"; } from "inferno";
import { import {
@ -13,6 +14,7 @@ import {
Instance, Instance,
ListingType, ListingType,
} from "lemmy-js-client"; } from "lemmy-js-client";
import deepEqual from "lodash.isequal";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon, Spinner } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { ImageUploadForm } from "../common/image-upload-form"; import { ImageUploadForm } from "../common/image-upload-form";
@ -55,6 +57,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
initSiteForm(): EditSite { initSiteForm(): EditSite {
const site = this.props.siteRes.site_view.site; const site = this.props.siteRes.site_view.site;
const ls = this.props.siteRes.site_view.local_site; const ls = this.props.siteRes.site_view.local_site;
return { return {
name: site.name, name: site.name,
sidebar: site.sidebar, sidebar: site.sidebar,
@ -619,6 +622,19 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
); );
} }
componentDidUpdate(
prevProps: Readonly<{ children?: InfernoNode } & SiteFormProps>
) {
if (
!(
deepEqual(prevProps.allowedInstances, this.props.allowedInstances) ||
deepEqual(prevProps.blockedInstances, this.props.blockedInstances)
)
) {
this.setState({ siteForm: this.initSiteForm() });
}
}
federatedInstanceSelect(key: InstanceKey) { federatedInstanceSelect(key: InstanceKey) {
const id = `create_site_${key}`; const id = `create_site_${key}`;
const value = this.state.instance_select[key]; const value = this.state.instance_select[key];

View file

@ -692,6 +692,8 @@ export class Profile extends Component<
> >
{I18NextService.i18n.t("cancel")} {I18NextService.i18n.t("cancel")}
</button> </button>
</div>
<div className="mb-3 row">
<button <button
type="submit" type="submit"
className="btn btn-secondary" className="btn btn-secondary"

View file

@ -8,60 +8,54 @@ interface MetadataCardProps {
post: Post; post: Post;
} }
interface MetadataCardState { export class MetadataCard extends Component<MetadataCardProps> {
expanded: boolean;
}
export class MetadataCard extends Component<
MetadataCardProps,
MetadataCardState
> {
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
} }
render() { render() {
const post = this.props.post; const post = this.props.post;
return (
<> if (post.embed_title && post.url) {
{post.embed_title && post.url && ( return (
<div className="post-metadata-card card border-secondary mt-3 mb-2"> <div className="post-metadata-card card border-secondary mt-3 mb-2">
<div className="row"> <div className="row">
<div className="col-12"> <div className="col-12">
<div className="card-body"> <div className="card-body">
{post.name !== post.embed_title && ( {post.name !== post.embed_title && (
<> <>
<h5 className="card-title d-inline"> <h5 className="card-title d-inline">
<a className="text-body" href={post.url} rel={relTags}> <a className="text-body" href={post.url} rel={relTags}>
{post.embed_title} {post.embed_title}
</a> </a>
</h5> </h5>
<span className="d-inline-block ms-2 mb-2 small text-muted"> <span className="d-inline-block ms-2 mb-2 small text-muted">
<a <a
className="text-muted fst-italic" className="text-muted fst-italic"
href={post.url} href={post.url}
rel={relTags} rel={relTags}
> >
{new URL(post.url).hostname} {new URL(post.url).hostname}
<Icon icon="external-link" classes="ms-1" /> <Icon icon="external-link" classes="ms-1" />
</a> </a>
</span> </span>
</> </>
)} )}
{post.embed_description && ( {post.embed_description && (
<div <div
className="card-text small text-muted md-div" className="card-text small text-muted md-div"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: sanitizeHtml(post.embed_description), __html: sanitizeHtml(post.embed_description),
}} }}
/> />
)} )}
</div>
</div> </div>
</div> </div>
</div> </div>
)} </div>
</> );
); } else {
return <></>;
}
} }
} }

View file

@ -49,7 +49,7 @@ import {
PurgeType, PurgeType,
VoteContentType, VoteContentType,
} from "../../interfaces"; } from "../../interfaces";
import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown"; import { mdToHtml, mdToHtmlInline } from "../../markdown";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { setupTippy } from "../../tippy"; import { setupTippy } from "../../tippy";
import { Icon, PurgeWarning, Spinner } from "../common/icon"; import { Icon, PurgeWarning, Spinner } from "../common/icon";
@ -105,6 +105,9 @@ interface PostListingProps {
allLanguages: Language[]; allLanguages: Language[];
siteLanguages: number[]; siteLanguages: number[];
showCommunity?: boolean; showCommunity?: boolean;
/**
* Controls whether to show both the body *and* the metadata preview card
*/
showBody?: boolean; showBody?: boolean;
hideImage?: boolean; hideImage?: boolean;
enableDownvotes?: boolean; enableDownvotes?: boolean;
@ -200,7 +203,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<> <>
{this.listing()} {this.listing()}
{this.state.imageExpanded && !this.props.hideImage && this.img} {this.state.imageExpanded && !this.props.hideImage && this.img}
{post.url && this.state.showBody && post.embed_title && ( {this.showBody && post.url && post.embed_title && (
<MetadataCard post={post} /> <MetadataCard post={post} />
)} )}
{this.showBody && this.body()} {this.showBody && this.body()}
@ -488,6 +491,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
)} )}
</h5> </h5>
{/**
* If there is a URL, an embed title, and we were not told to show the
* body by the parent component, show the MetadataCard/body toggle.
*/}
{!this.props.showBody &&
post.url &&
post.embed_title &&
this.showPreviewButton()}
{post.removed && ( {post.removed && (
<small className="ms-2 badge text-bg-secondary"> <small className="ms-2 badge text-bg-secondary">
{I18NextService.i18n.t("removed")} {I18NextService.i18n.t("removed")}
@ -630,27 +642,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
); );
} }
showPreviewButton() {
const post_view = this.postView;
const body = post_view.post.body;
return (
<button
className="btn btn-sm btn-animate text-muted py-0"
data-tippy-content={body && mdNoImages.render(body)}
data-tippy-allowHtml={true}
onClick={linkEvent(this, this.handleShowBody)}
>
<Icon
icon="book-open"
classes={classNames("icon-inline me-1", {
"text-success": this.state.showBody,
})}
/>
</button>
);
}
postActions() { postActions() {
// Possible enhancement: Priority+ pattern instead of just hard coding which get hidden behind the show more button. // Possible enhancement: Priority+ pattern instead of just hard coding which get hidden behind the show more button.
// Possible enhancement: Make each button a component. // Possible enhancement: Make each button a component.
@ -662,14 +653,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.saveButton} {this.saveButton}
{this.crossPostButton} {this.crossPostButton}
{/** {this.props.showBody && post_view.post.body && this.viewSourceButton}
* If there is a URL, or if the post has a body and we were told not to
* show the body, show the MetadataCard/body toggle.
*/}
{(post.url || (post.body && !this.props.showBody)) &&
this.showPreviewButton()}
{this.showBody && post_view.post.body && this.viewSourceButton}
<div className="dropdown"> <div className="dropdown">
<button <button
@ -1393,15 +1377,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
); );
} }
showBodyPreview() { showPreviewButton() {
const { body, id } = this.postView.post; return (
<button
return !this.showBody && body ? ( type="button"
<Link className="text-body mt-2 d-block" to={`/post/${id}`}> className="btn btn-sm btn-link link-dark link-opacity-75 link-opacity-100-hover py-0 align-baseline"
<div className="md-div mb-1 preview-lines">{body}</div> onClick={linkEvent(this, this.handleShowBody)}
</Link> >
) : ( <Icon
<></> icon={!this.state.showBody ? "plus-square" : "minus-square"}
classes="icon-inline"
/>
</button>
); );
} }

View file

@ -21,7 +21,7 @@ export const markdownFieldCharacterLimit = 50000;
export const maxUploadImages = 20; export const maxUploadImages = 20;
export const concurrentImageUpload = 4; export const concurrentImageUpload = 4;
export const updateUnreadCountsInterval = 30000; export const updateUnreadCountsInterval = 30000;
export const fetchLimit = 40; export const fetchLimit = 20;
export const relTags = "noopener nofollow"; export const relTags = "noopener nofollow";
export const emDash = "\u2014"; export const emDash = "\u2014";

View file

@ -6,8 +6,7 @@ const CopyPlugin = require("copy-webpack-plugin");
const RunNodeWebpackPlugin = require("run-node-webpack-plugin"); const RunNodeWebpackPlugin = require("run-node-webpack-plugin");
const merge = require("lodash.merge"); const merge = require("lodash.merge");
const { ServiceWorkerPlugin } = require("service-worker-webpack"); const { ServiceWorkerPlugin } = require("service-worker-webpack");
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const banner = ` const banner = `
hash:[contentHash], chunkhash:[chunkhash], name:[name], filebase:[base], query:[query], file:[file] hash:[contentHash], chunkhash:[chunkhash], name:[name], filebase:[base], query:[query], file:[file]
Source code: https://github.com/LemmyNet/lemmy-ui Source code: https://github.com/LemmyNet/lemmy-ui
@ -156,6 +155,8 @@ const createClientConfig = (_env, mode) => {
}); });
if (mode === "none") { if (mode === "none") {
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
config.plugins.push(new BundleAnalyzerPlugin()); config.plugins.push(new BundleAnalyzerPlugin());
} }