Merge branch 'main' into fix_tz_issue

This commit is contained in:
Alec Armbruster 2023-06-28 23:06:12 -04:00 committed by GitHub
commit 64ce679736
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 159 additions and 165 deletions

View file

@ -198,9 +198,9 @@ blockquote {
.thumbnail { .thumbnail {
object-fit: cover; object-fit: cover;
aspect-ratio: 4/3; aspect-ratio: 1/1;
width: 100%; width: 5rem;
max-height: 6rem; height: 5rem;
} }
.thumbnail svg { .thumbnail svg {

View file

@ -84,6 +84,8 @@ export class ImageUploadForm extends Component<
if (res.state === "success") { if (res.state === "success") {
if (res.data.msg === "ok") { if (res.data.msg === "ok") {
i.props.onUpload(res.data.url as string); i.props.onUpload(res.data.url as string);
} else if (res.data.msg === "too_large") {
toast(I18NextService.i18n.t("upload_too_large"), "danger");
} else { } else {
toast(JSON.stringify(res), "danger"); toast(JSON.stringify(res), "danger");
} }

View file

@ -443,6 +443,10 @@ export class MarkdownTextArea extends Component<
const textarea: any = document.getElementById(i.id); const textarea: any = document.getElementById(i.id);
autosize.update(textarea); autosize.update(textarea);
pictrsDeleteToast(image.name, res.data.delete_url as string); pictrsDeleteToast(image.name, res.data.delete_url as string);
} else if (res.data.msg === "too_large") {
toast(I18NextService.i18n.t("upload_too_large"), "danger");
i.setState({ imageUploadStatus: undefined });
throw JSON.stringify(res.data);
} else { } else {
throw JSON.stringify(res.data); throw JSON.stringify(res.data);
} }

View file

@ -508,6 +508,8 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
{ form: form, index: index, overrideValue: res.data.url as string }, { form: form, index: index, overrideValue: res.data.url as string },
event event
); );
} else if (res.data.msg === "too_large") {
toast(I18NextService.i18n.t("upload_too_large"), "danger");
} else { } else {
toast(JSON.stringify(res), "danger"); toast(JSON.stringify(res), "danger");
} }

View file

@ -187,6 +187,8 @@ function handleImageUpload(i: PostForm, event: any) {
imageLoading: false, imageLoading: false,
imageDeleteUrl: res.data.delete_url as string, imageDeleteUrl: res.data.delete_url as string,
}); });
} else if (res.data.msg === "too_large") {
toast(I18NextService.i18n.t("upload_too_large"), "danger");
} else { } else {
toast(JSON.stringify(res), "danger"); toast(JSON.stringify(res), "danger");
} }

View file

@ -333,7 +333,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
return ( return (
<button <button
type="button" type="button"
className="d-inline-block position-relative mb-2 p-0 border-0" className="thumbnail rounded overflow-hidden d-inline-block position-relative mb-2 p-0 border-0"
data-tippy-content={I18NextService.i18n.t("expand_here")} data-tippy-content={I18NextService.i18n.t("expand_here")}
onClick={linkEvent(this, this.handleImageExpandClick)} onClick={linkEvent(this, this.handleImageExpandClick)}
aria-label={I18NextService.i18n.t("expand_here")} aria-label={I18NextService.i18n.t("expand_here")}
@ -348,7 +348,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
} else if (!this.props.hideImage && url && thumbnail && this.imageSrc) { } else if (!this.props.hideImage && url && thumbnail && this.imageSrc) {
return ( return (
<a <a
className="text-body d-inline-block position-relative mb-2" className="thumbnail rounded bg-light d-flex justify-content-center"
href={url} href={url}
rel={relTags} rel={relTags}
title={url} title={url}
@ -702,6 +702,50 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{(this.canMod_ || this.canAdmin_) && ( {(this.canMod_ || this.canAdmin_) && (
<li>{this.modRemoveButton}</li> <li>{this.modRemoveButton}</li>
)} )}
{this.canMod_ && (
<>
<li>
<hr className="dropdown-divider" />
</li>
{!this.creatorIsMod_ &&
(!post_view.creator_banned_from_community ? (
<li>{this.modBanFromCommunityButton}</li>
) : (
<li>{this.modUnbanFromCommunityButton}</li>
))}
{!post_view.creator_banned_from_community && (
<li>{this.addModToCommunityButton}</li>
)}
</>
)}
{(amCommunityCreator(post_view.creator.id, this.props.moderators) ||
this.canAdmin_) &&
this.creatorIsMod_ && <li>{this.transferCommunityButton}</li>}
{/* Admins can ban from all, and appoint other admins */}
{this.canAdmin_ && (
<>
<li>
<hr className="dropdown-divider" />
</li>
{!this.creatorIsAdmin_ && (
<>
{!isBanned(post_view.creator) ? (
<li>{this.modBanButton}</li>
) : (
<li>{this.modUnbanButton}</li>
)}
<li>{this.purgePersonButton}</li>
<li>{this.purgePostButton}</li>
</>
)}
{!isBanned(post_view.creator) && post_view.creator.local && (
<li>{this.toggleAdminButton}</li>
)}
</>
)}
</ul> </ul>
</div> </div>
</> </>
@ -969,9 +1013,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get modBanFromCommunityButton() { get modBanFromCommunityButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleModBanFromCommunityShow)} onClick={linkEvent(this, this.handleModBanFromCommunityShow)}
aria-label={I18NextService.i18n.t("ban_from_community")}
> >
{I18NextService.i18n.t("ban_from_community")} {I18NextService.i18n.t("ban_from_community")}
</button> </button>
@ -981,9 +1024,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get modUnbanFromCommunityButton() { get modUnbanFromCommunityButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleModBanFromCommunitySubmit)} onClick={linkEvent(this, this.handleModBanFromCommunitySubmit)}
aria-label={I18NextService.i18n.t("unban")}
> >
{this.state.banLoading ? <Spinner /> : I18NextService.i18n.t("unban")} {this.state.banLoading ? <Spinner /> : I18NextService.i18n.t("unban")}
</button> </button>
@ -993,20 +1035,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get addModToCommunityButton() { get addModToCommunityButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleAddModToCommunity)} onClick={linkEvent(this, this.handleAddModToCommunity)}
aria-label={
this.creatorIsMod_
? I18NextService.i18n.t("remove_as_mod")
: I18NextService.i18n.t("appoint_as_mod")
}
> >
{this.state.addModLoading ? ( {this.state.addModLoading ? (
<Spinner /> <Spinner />
) : this.creatorIsMod_ ? ( ) : this.creatorIsMod_ ? (
I18NextService.i18n.t("remove_as_mod") capitalizeFirstLetter(I18NextService.i18n.t("remove_as_mod"))
) : ( ) : (
I18NextService.i18n.t("appoint_as_mod") capitalizeFirstLetter(I18NextService.i18n.t("appoint_as_mod"))
)} )}
</button> </button>
); );
@ -1015,11 +1052,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get modBanButton() { get modBanButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleModBanShow)} onClick={linkEvent(this, this.handleModBanShow)}
aria-label={I18NextService.i18n.t("ban_from_site")}
> >
{I18NextService.i18n.t("ban_from_site")} {capitalizeFirstLetter(I18NextService.i18n.t("ban_from_site"))}
</button> </button>
); );
} }
@ -1027,14 +1063,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get modUnbanButton() { get modUnbanButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleModBanSubmit)} onClick={linkEvent(this, this.handleModBanSubmit)}
aria-label={I18NextService.i18n.t("unban_from_site")}
> >
{this.state.banLoading ? ( {this.state.banLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
I18NextService.i18n.t("unban_from_site") capitalizeFirstLetter(I18NextService.i18n.t("unban_from_site"))
)} )}
</button> </button>
); );
@ -1043,11 +1078,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get purgePersonButton() { get purgePersonButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handlePurgePersonShow)} onClick={linkEvent(this, this.handlePurgePersonShow)}
aria-label={I18NextService.i18n.t("purge_user")}
> >
{I18NextService.i18n.t("purge_user")} {capitalizeFirstLetter(I18NextService.i18n.t("purge_user"))}
</button> </button>
); );
} }
@ -1055,11 +1089,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get purgePostButton() { get purgePostButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handlePurgePostShow)} onClick={linkEvent(this, this.handlePurgePostShow)}
aria-label={I18NextService.i18n.t("purge_post")}
> >
{I18NextService.i18n.t("purge_post")} {capitalizeFirstLetter(I18NextService.i18n.t("purge_post"))}
</button> </button>
); );
} }
@ -1067,20 +1100,31 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
get toggleAdminButton() { get toggleAdminButton() {
return ( return (
<button <button
className="btn btn-link btn-animate text-muted py-0" className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleAddAdmin)} onClick={linkEvent(this, this.handleAddAdmin)}
> >
{this.state.addAdminLoading ? ( {this.state.addAdminLoading ? (
<Spinner /> <Spinner />
) : this.creatorIsAdmin_ ? ( ) : this.creatorIsAdmin_ ? (
I18NextService.i18n.t("remove_as_admin") capitalizeFirstLetter(I18NextService.i18n.t("remove_as_admin"))
) : ( ) : (
I18NextService.i18n.t("appoint_as_admin") capitalizeFirstLetter(I18NextService.i18n.t("appoint_as_admin"))
)} )}
</button> </button>
); );
} }
get transferCommunityButton() {
return (
<button
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
onClick={linkEvent(this, this.handleShowConfirmTransferCommunity)}
>
{capitalizeFirstLetter(I18NextService.i18n.t("transfer_community"))}
</button>
);
}
get modRemoveButton() { get modRemoveButton() {
const removed = this.postView.post.removed; const removed = this.postView.post.removed;
return ( return (
@ -1095,102 +1139,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.state.removeLoading ? ( {this.state.removeLoading ? (
<Spinner /> <Spinner />
) : !removed ? ( ) : !removed ? (
I18NextService.i18n.t("remove") capitalizeFirstLetter(I18NextService.i18n.t("remove_post"))
) : ( ) : (
I18NextService.i18n.t("restore") <>
{capitalizeFirstLetter(I18NextService.i18n.t("restore"))}{" "}
{I18NextService.i18n.t("post")}
</>
)} )}
</button> </button>
); );
} }
/**
* Mod/Admin actions to be taken against the author.
*/
userActionsLine() {
// TODO: make nicer
const post_view = this.postView;
return (
this.state.showAdvanced && (
<div className="mt-3">
{this.canMod_ && (
<>
{!this.creatorIsMod_ &&
(!post_view.creator_banned_from_community
? this.modBanFromCommunityButton
: this.modUnbanFromCommunityButton)}
{!post_view.creator_banned_from_community &&
this.addModToCommunityButton}
</>
)}
{/* Community creators and admins can transfer community to another mod */}
{(amCommunityCreator(post_view.creator.id, this.props.moderators) ||
this.canAdmin_) &&
this.creatorIsMod_ &&
(!this.state.showConfirmTransferCommunity ? (
<button
className="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(
this,
this.handleShowConfirmTransferCommunity
)}
aria-label={I18NextService.i18n.t("transfer_community")}
>
{I18NextService.i18n.t("transfer_community")}
</button>
) : (
<>
<button
className="d-inline-block me-1 btn btn-link btn-animate text-muted py-0"
aria-label={I18NextService.i18n.t("are_you_sure")}
>
{I18NextService.i18n.t("are_you_sure")}
</button>
<button
className="btn btn-link btn-animate text-muted py-0 d-inline-block me-1"
aria-label={I18NextService.i18n.t("yes")}
onClick={linkEvent(this, this.handleTransferCommunity)}
>
{this.state.transferLoading ? (
<Spinner />
) : (
I18NextService.i18n.t("yes")
)}
</button>
<button
className="btn btn-link btn-animate text-muted py-0 d-inline-block"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferCommunity
)}
aria-label={I18NextService.i18n.t("no")}
>
{I18NextService.i18n.t("no")}
</button>
</>
))}
{/* Admins can ban from all, and appoint other admins */}
{this.canAdmin_ && (
<>
{!this.creatorIsAdmin_ && (
<>
{!isBanned(post_view.creator)
? this.modBanButton
: this.modUnbanButton}
{this.purgePersonButton}
{this.purgePostButton}
</>
)}
{!isBanned(post_view.creator) &&
post_view.creator.local &&
this.toggleAdminButton}
</>
)}
</div>
)
);
}
removeAndBanDialogs() { removeAndBanDialogs() {
const post = this.postView; const post = this.postView;
const purgeTypeText = const purgeTypeText =
@ -1218,11 +1177,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
value={this.state.removeReason} value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)} onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/> />
<button <button type="submit" className="btn btn-secondary">
type="submit"
className="btn btn-secondary"
aria-label={I18NextService.i18n.t("remove_post")}
>
{this.state.removeLoading ? ( {this.state.removeLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
@ -1231,6 +1186,33 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
</button> </button>
</form> </form>
)} )}
{this.state.showConfirmTransferCommunity && (
<>
<button className="d-inline-block me-1 btn btn-link btn-animate text-muted py-0">
{I18NextService.i18n.t("are_you_sure")}
</button>
<button
className="btn btn-link btn-animate text-muted py-0 d-inline-block me-1"
onClick={linkEvent(this, this.handleTransferCommunity)}
>
{this.state.transferLoading ? (
<Spinner />
) : (
I18NextService.i18n.t("yes")
)}
</button>
<button
className="btn btn-link btn-animate text-muted py-0 d-inline-block"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferCommunity
)}
aria-label={I18NextService.i18n.t("no")}
>
{I18NextService.i18n.t("no")}
</button>
</>
)}
{this.state.showBanDialog && ( {this.state.showBanDialog && (
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}> <form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
<div className="mb-3 row col-12"> <div className="mb-3 row col-12">
@ -1284,11 +1266,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */} {/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
{/* </div> */} {/* </div> */}
<div className="mb-3 row"> <div className="mb-3 row">
<button <button type="submit" className="btn btn-secondary">
type="submit"
className="btn btn-secondary"
aria-label={I18NextService.i18n.t("ban")}
>
{this.state.banLoading ? ( {this.state.banLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
@ -1317,11 +1295,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
value={this.state.reportReason} value={this.state.reportReason}
onInput={linkEvent(this, this.handleReportReasonChange)} onInput={linkEvent(this, this.handleReportReasonChange)}
/> />
<button <button type="submit" className="btn btn-secondary">
type="submit"
className="btn btn-secondary"
aria-label={I18NextService.i18n.t("create_report")}
>
{this.state.reportLoading ? ( {this.state.reportLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
@ -1350,11 +1324,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.state.purgeLoading ? ( {this.state.purgeLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
<button <button type="submit" className="btn btn-secondary">
type="submit"
className="btn btn-secondary"
aria-label={purgeTypeText}
>
{this.state.purgeLoading ? <Spinner /> : { purgeTypeText }} {this.state.purgeLoading ? <Spinner /> : { purgeTypeText }}
</button> </button>
)} )}
@ -1409,7 +1379,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.mobileThumbnail()} {this.mobileThumbnail()}
{this.commentsLine(true)} {this.commentsLine(true)}
{this.userActionsLine()}
{this.duplicatesLine()} {this.duplicatesLine()}
{this.removeAndBanDialogs()} {this.removeAndBanDialogs()}
</div> </div>
@ -1433,15 +1402,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
)} )}
<div className="col flex-grow-1"> <div className="col flex-grow-1">
<div className="row"> <div className="row">
<div className="col-sm-3 col-lg-2 pe-0 post-media"> <div className="col flex-grow-0 px-0">
<div className="">{this.thumbnail()}</div> <div className="">{this.thumbnail()}</div>
</div> </div>
<div className="col-12 col-sm-9 col-lg-10"> <div className="col flex-grow-1">
{this.postTitleLine()} {this.postTitleLine()}
{this.createdLine()} {this.createdLine()}
{this.commentsLine()} {this.commentsLine()}
{this.duplicatesLine()} {this.duplicatesLine()}
{this.userActionsLine()}
{this.removeAndBanDialogs()} {this.removeAndBanDialogs()}
</div> </div>
</div> </div>

View file

@ -332,9 +332,7 @@ export class Search extends Component<any, SearchState> {
} }
async componentDidMount() { async componentDidMount() {
if ( if (!this.state.isIsomorphic) {
!(this.state.isIsomorphic || this.props.history.location.state?.searched)
) {
const promises = [this.fetchCommunities()]; const promises = [this.fetchCommunities()];
if (this.state.searchText) { if (this.state.searchText) {
promises.push(this.search()); promises.push(this.search());
@ -432,7 +430,15 @@ export class Search extends Component<any, SearchState> {
q: query, q: query,
auth, auth,
}; };
resolveObjectResponse = await client.resolveObject(resolveObjectForm); resolveObjectResponse = await HttpService.silent_client.resolveObject(
resolveObjectForm
);
// If we return this object with a state of failed, the catch-all-handler will redirect
// to an error page, so we ignore it by covering up the error with the empty state.
if (resolveObjectResponse.state === "failed") {
resolveObjectResponse = { state: "empty" };
}
} }
} }
} }
@ -950,7 +956,7 @@ export class Search extends Component<any, SearchState> {
if (auth) { if (auth) {
this.setState({ resolveObjectRes: { state: "loading" } }); this.setState({ resolveObjectRes: { state: "loading" } });
this.setState({ this.setState({
resolveObjectRes: await HttpService.client.resolveObject({ resolveObjectRes: await HttpService.silent_client.resolveObject({
q, q,
auth, auth,
}), }),
@ -1097,10 +1103,6 @@ export class Search extends Component<any, SearchState> {
sort: sort ?? urlSort, sort: sort ?? urlSort,
}; };
this.props.history.push(`/search${getQueryString(queryParams)}`, { this.props.history.push(`/search${getQueryString(queryParams)}`);
searched: true,
});
await this.search();
} }
} }

View file

@ -1,9 +1,9 @@
import { getHttpBase } from "@utils/env"; import { getHttpBase } from "@utils/env";
import { LemmyHttp } from "lemmy-js-client"; import { LemmyHttp } from "lemmy-js-client";
import { toast } from "../../shared/toast"; import { toast } from "../toast";
import { I18NextService } from "./I18NextService"; import { I18NextService } from "./I18NextService";
type EmptyRequestState = { export type EmptyRequestState = {
state: "empty"; state: "empty";
}; };
@ -45,7 +45,7 @@ export type WrappedLemmyHttp = {
class WrappedLemmyHttpClient { class WrappedLemmyHttpClient {
#client: LemmyHttp; #client: LemmyHttp;
constructor(client: LemmyHttp) { constructor(client: LemmyHttp, silent = false) {
this.#client = client; this.#client = client;
for (const key of Object.getOwnPropertyNames( for (const key of Object.getOwnPropertyNames(
@ -61,8 +61,10 @@ class WrappedLemmyHttpClient {
state: !(res === undefined || res === null) ? "success" : "empty", state: !(res === undefined || res === null) ? "success" : "empty",
}; };
} catch (error) { } catch (error) {
console.error(`API error: ${error}`); if (!silent) {
toast(I18NextService.i18n.t(error), "danger"); console.error(`API error: ${error}`);
toast(I18NextService.i18n.t(error), "danger");
}
return { return {
state: "failed", state: "failed",
msg: error, msg: error,
@ -74,16 +76,23 @@ class WrappedLemmyHttpClient {
} }
} }
export function wrapClient(client: LemmyHttp) { export function wrapClient(client: LemmyHttp, silent = false) {
return new WrappedLemmyHttpClient(client) as unknown as WrappedLemmyHttp; // unfortunately, this verbose cast is necessary // unfortunately, this verbose cast is necessary
return new WrappedLemmyHttpClient(
client,
silent
) as unknown as WrappedLemmyHttp;
} }
export class HttpService { export class HttpService {
static #_instance: HttpService; static #_instance: HttpService;
#silent_client: WrappedLemmyHttp;
#client: WrappedLemmyHttp; #client: WrappedLemmyHttp;
private constructor() { private constructor() {
this.#client = wrapClient(new LemmyHttp(getHttpBase())); const lemmyHttp = new LemmyHttp(getHttpBase());
this.#client = wrapClient(lemmyHttp);
this.#silent_client = wrapClient(lemmyHttp, true);
} }
static get #Instance() { static get #Instance() {
@ -93,4 +102,8 @@ export class HttpService {
public static get client() { public static get client() {
return this.#Instance.#client; return this.#Instance.#client;
} }
public static get silent_client() {
return this.#Instance.#silent_client;
}
} }

View file

@ -96,6 +96,7 @@ const createClientConfig = (_env, mode) => {
entry: "./src/client/index.tsx", entry: "./src/client/index.tsx",
output: { output: {
filename: "js/client.js", filename: "js/client.js",
publicPath: "/static/",
}, },
plugins: [ plugins: [
...base.plugins, ...base.plugins,
@ -106,7 +107,7 @@ const createClientConfig = (_env, mode) => {
"/": "/static/", "/": "/static/",
}, },
cacheId: "lemmy", cacheId: "lemmy",
include: [/(assets|styles)\/.+\..+|client\.js$/g], include: [/(assets|styles|js)\/.+\..+$/g],
inlineWorkboxRuntime: true, inlineWorkboxRuntime: true,
runtimeCaching: [ runtimeCaching: [
{ {