Adding a post title only filter to the search page. (#2695)

* Adding a post title only filter to the search page.

- Also fixing restore data on unban.
- Accounting for newly removed block views.

* Only show post title button for All and Post searches.

* Addressing PR comments.
This commit is contained in:
Dessalines 2024-09-20 09:20:39 -04:00 committed by GitHub
parent 5f535e7dad
commit 8a44c4d38f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 120 additions and 83 deletions

@ -1 +1 @@
Subproject commit 37c437e753b52b1a61b225df9d4ffd99ddf17314 Subproject commit 7ba4cac33e47b712227c2b8a133c489abed7c727

View file

@ -60,7 +60,7 @@
"inferno-router": "^8.2.3", "inferno-router": "^8.2.3",
"inferno-server": "^8.2.3", "inferno-server": "^8.2.3",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"lemmy-js-client": "0.19.6-beta.1", "lemmy-js-client": "0.20.0-alpha.7",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"markdown-it-bidi": "^0.1.0", "markdown-it-bidi": "^0.1.0",

View file

@ -114,8 +114,8 @@ importers:
specifier: ^4.0.0 specifier: ^4.0.0
version: 4.0.0 version: 4.0.0
lemmy-js-client: lemmy-js-client:
specifier: 0.19.6-beta.1 specifier: 0.20.0-alpha.7
version: 0.19.6-beta.1 version: 0.20.0-alpha.7
lodash.isequal: lodash.isequal:
specifier: ^4.5.0 specifier: ^4.5.0
version: 4.5.0 version: 4.5.0
@ -3063,8 +3063,8 @@ packages:
leac@0.6.0: leac@0.6.0:
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
lemmy-js-client@0.19.6-beta.1: lemmy-js-client@0.20.0-alpha.7:
resolution: {integrity: sha512-CiTbTpqKA7t1daBMdkKVLVXUrpy2wSuxkoWrnK5sVvmBrlFq1jpqC9h9SgNngiVqSgx6Tvsg3asmvne7OaEZRQ==} resolution: {integrity: sha512-lhPs8gJFLX0EvlwkkgtTF2F/v22lKjcQ81u7u5CShrO05Dii33fZ5x9SrEJYHD0qw4FIN/jpfKucN9QnndScpA==}
leven@3.1.0: leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
@ -7834,7 +7834,7 @@ snapshots:
leac@0.6.0: {} leac@0.6.0: {}
lemmy-js-client@0.19.6-beta.1: {} lemmy-js-client@0.20.0-alpha.7: {}
leven@3.1.0: {} leven@3.1.0: {}

View file

@ -637,7 +637,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
async handleBanFromCommunity({ async handleBanFromCommunity({
daysUntilExpires, daysUntilExpires,
reason, reason,
shouldRemove, shouldRemoveOrRestoreData,
}: BanUpdateForm) { }: BanUpdateForm) {
const { const {
creator: { id: person_id }, creator: { id: person_id },
@ -646,10 +646,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
} = this.commentView; } = this.commentView;
const ban = !creator_banned_from_community; const ban = !creator_banned_from_community;
// If its an unban, restore all their data // If its an unban, restore all their data
if (ban === false) { if (ban === false) {
shouldRemove = false; shouldRemoveOrRestoreData = true;
} }
const expires = futureDaysToUnixTime(daysUntilExpires); const expires = futureDaysToUnixTime(daysUntilExpires);
@ -657,7 +656,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
community_id, community_id,
person_id, person_id,
ban, ban,
remove_data: shouldRemove, remove_or_restore_data: shouldRemoveOrRestoreData,
reason, reason,
expires, expires,
}); });
@ -666,7 +665,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
async handleBanFromSite({ async handleBanFromSite({
daysUntilExpires, daysUntilExpires,
reason, reason,
shouldRemove, shouldRemoveOrRestoreData,
}: BanUpdateForm) { }: BanUpdateForm) {
const { const {
creator: { id: person_id, banned }, creator: { id: person_id, banned },
@ -676,14 +675,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
// If its an unban, restore all their data // If its an unban, restore all their data
if (ban === false) { if (ban === false) {
shouldRemove = false; shouldRemoveOrRestoreData = true;
} }
const expires = futureDaysToUnixTime(daysUntilExpires); const expires = futureDaysToUnixTime(daysUntilExpires);
this.props.onBanPerson({ this.props.onBanPerson({
person_id, person_id,
ban, ban,
remove_data: shouldRemove, remove_or_restore_data: shouldRemoveOrRestoreData,
reason, reason,
expires, expires,
}); });

View file

@ -16,7 +16,7 @@ import { modalMixin } from "../../mixins/modal-mixin";
export interface BanUpdateForm { export interface BanUpdateForm {
reason?: string; reason?: string;
shouldRemove?: boolean; shouldRemoveOrRestoreData?: boolean;
daysUntilExpires?: number; daysUntilExpires?: number;
} }
@ -69,7 +69,7 @@ interface ModActionFormFormState {
loading: boolean; loading: boolean;
reason: string; reason: string;
daysUntilExpire?: number; daysUntilExpire?: number;
shouldRemoveData?: boolean; shouldRemoveOrRestoreData?: boolean;
shouldPermaBan?: boolean; shouldPermaBan?: boolean;
} }
@ -84,7 +84,7 @@ function handleExpiryChange(i: ModActionFormModal, event: any) {
function handleToggleRemove(i: ModActionFormModal) { function handleToggleRemove(i: ModActionFormModal) {
i.setState(prev => ({ i.setState(prev => ({
...prev, ...prev,
shouldRemoveData: !prev.shouldRemoveData, shouldRemoveOrRestoreData: !prev.shouldRemoveOrRestoreData,
})); }));
} }
@ -104,7 +104,7 @@ async function handleSubmit(i: ModActionFormModal, event: any) {
await i.props.onSubmit({ await i.props.onSubmit({
reason: i.state.reason, reason: i.state.reason,
daysUntilExpires: i.state.daysUntilExpire!, daysUntilExpires: i.state.daysUntilExpire!,
shouldRemove: i.state.shouldRemoveData!, shouldRemoveOrRestoreData: i.state.shouldRemoveOrRestoreData!,
} as BanUpdateForm & string); // Need to & string to handle type weirdness } as BanUpdateForm & string); // Need to & string to handle type weirdness
} else { } else {
await i.props.onSubmit(i.state.reason); await i.props.onSubmit(i.state.reason);
@ -135,7 +135,7 @@ export default class ModActionFormModal extends Component<
this.reasonRef = createRef(); this.reasonRef = createRef();
if (this.isBanModal) { if (this.isBanModal) {
this.state.shouldRemoveData = false; this.state.shouldRemoveOrRestoreData = false;
} }
} }
@ -144,7 +144,7 @@ export default class ModActionFormModal extends Component<
loading, loading,
reason, reason,
daysUntilExpire, daysUntilExpire,
shouldRemoveData, shouldRemoveOrRestoreData,
shouldPermaBan, shouldPermaBan,
} = this.state; } = this.state;
const reasonId = `mod-form-reason-${randomStr()}`; const reasonId = `mod-form-reason-${randomStr()}`;
@ -249,7 +249,7 @@ export default class ModActionFormModal extends Component<
<input <input
className="form-check-input user-select-none" className="form-check-input user-select-none"
type="checkbox" type="checkbox"
checked={shouldRemoveData} checked={shouldRemoveOrRestoreData}
onChange={linkEvent(this, handleToggleRemove)} onChange={linkEvent(this, handleToggleRemove)}
/> />
{I18NextService.i18n.t("remove_content")} {I18NextService.i18n.t("remove_content")}

View file

@ -64,7 +64,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
description: site.description, description: site.description,
enable_downvotes: ls.enable_downvotes, enable_downvotes: ls.enable_downvotes,
registration_mode: ls.registration_mode, registration_mode: ls.registration_mode,
enable_nsfw: ls.enable_nsfw,
community_creation_admin_only: ls.community_creation_admin_only, community_creation_admin_only: ls.community_creation_admin_only,
icon: site.icon, icon: site.icon,
banner: site.banner, banner: site.banner,

View file

@ -119,7 +119,7 @@ interface ProfileState {
banReason?: string; banReason?: string;
banExpireDays?: number; banExpireDays?: number;
showBanDialog: boolean; showBanDialog: boolean;
removeData: boolean; removeOrRestoreData: boolean;
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
isIsomorphic: boolean; isIsomorphic: boolean;
showRegistrationDialog: boolean; showRegistrationDialog: boolean;
@ -182,7 +182,7 @@ function isPersonBlocked(personRes: RequestState<GetPersonDetailsResponse>) {
return ( return (
(personRes.state === "success" && (personRes.state === "success" &&
UserService.Instance.myUserInfo?.person_blocks.some( UserService.Instance.myUserInfo?.person_blocks.some(
({ target: { id } }) => id === personRes.data.person_view.person.id, ({ id }) => id === personRes.data.person_view.person.id,
)) ?? )) ??
false false
); );
@ -206,7 +206,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
personBlocked: false, personBlocked: false,
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
showBanDialog: false, showBanDialog: false,
removeData: false, removeOrRestoreData: false,
isIsomorphic: false, isIsomorphic: false,
showRegistrationDialog: false, showRegistrationDialog: false,
registrationRes: EMPTY_REQUEST, registrationRes: EMPTY_REQUEST,
@ -891,7 +891,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
className="form-check-input" className="form-check-input"
id="mod-ban-remove-data" id="mod-ban-remove-data"
type="checkbox" type="checkbox"
checked={this.state.removeData} checked={this.state.removeOrRestoreData}
onChange={linkEvent(this, this.handleModRemoveDataChange)} onChange={linkEvent(this, this.handleModRemoveDataChange)}
/> />
<label <label
@ -980,7 +980,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
} }
handleModRemoveDataChange(i: Profile, event: any) { handleModRemoveDataChange(i: Profile, event: any) {
i.setState({ removeData: event.target.checked }); i.setState({ removeOrRestoreData: event.target.checked });
} }
handleModBanSubmitCancel(i: Profile) { handleModBanSubmitCancel(i: Profile) {
@ -1015,7 +1015,7 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
async handleModBanSubmit(i: Profile, event: any) { async handleModBanSubmit(i: Profile, event: any) {
event.preventDefault(); event.preventDefault();
const { removeData, banReason, banExpireDays } = i.state; const { banReason, banExpireDays } = i.state;
const personRes = i.state.personRes; const personRes = i.state.personRes;
@ -1025,13 +1025,13 @@ export class Profile extends Component<ProfileRouteProps, ProfileState> {
// If its an unban, restore all their data // If its an unban, restore all their data
if (!ban) { if (!ban) {
i.setState({ removeData: false }); i.setState({ removeOrRestoreData: true });
} }
const res = await HttpService.client.banPerson({ const res = await HttpService.client.banPerson({
person_id: person.id, person_id: person.id,
ban, ban,
remove_data: removeData, remove_or_restore_data: i.state.removeOrRestoreData,
reason: banReason, reason: banReason,
expires: futureDaysToUnixTime(banExpireDays), expires: futureDaysToUnixTime(banExpireDays),
}); });

View file

@ -22,16 +22,15 @@ import {
BlockCommunityResponse, BlockCommunityResponse,
BlockInstanceResponse, BlockInstanceResponse,
BlockPersonResponse, BlockPersonResponse,
CommunityBlockView, Community,
GenerateTotpSecretResponse, GenerateTotpSecretResponse,
GetFederatedInstancesResponse, GetFederatedInstancesResponse,
GetSiteResponse, GetSiteResponse,
Instance, Instance,
InstanceBlockView,
LemmyHttp, LemmyHttp,
ListingType, ListingType,
LoginResponse, LoginResponse,
PersonBlockView, Person,
SortType, SortType,
SuccessResponse, SuccessResponse,
UpdateTotpResponse, UpdateTotpResponse,
@ -125,9 +124,9 @@ interface SettingsState {
delete_content?: boolean; delete_content?: boolean;
password?: string; password?: string;
}; };
personBlocks: PersonBlockView[]; personBlocks: Person[];
communityBlocks: CommunityBlockView[]; communityBlocks: Community[];
instanceBlocks: InstanceBlockView[]; instanceBlocks: Instance[];
currentTab: string; currentTab: string;
themeList: string[]; themeList: string[];
deleteAccountShowConfirm: boolean; deleteAccountShowConfirm: boolean;
@ -556,14 +555,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
<> <>
<h2 className="h5">{I18NextService.i18n.t("blocked_users")}</h2> <h2 className="h5">{I18NextService.i18n.t("blocked_users")}</h2>
<ul className="list-unstyled mb-0"> <ul className="list-unstyled mb-0">
{this.state.personBlocks.map(pb => ( {this.state.personBlocks.map(p => (
<li key={pb.target.id}> <li key={p.id}>
<span> <span>
<PersonListing person={pb.target} /> <PersonListing person={p} />
<button <button
className="btn btn-sm" className="btn btn-sm"
onClick={linkEvent( onClick={linkEvent(
{ ctx: this, recipientId: pb.target.id }, { ctx: this, recipientId: p.id },
this.handleUnblockPerson, this.handleUnblockPerson,
)} )}
data-tippy-content={I18NextService.i18n.t("unblock_user")} data-tippy-content={I18NextService.i18n.t("unblock_user")}
@ -600,14 +599,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
<> <>
<h2 className="h5">{I18NextService.i18n.t("blocked_communities")}</h2> <h2 className="h5">{I18NextService.i18n.t("blocked_communities")}</h2>
<ul className="list-unstyled mb-0"> <ul className="list-unstyled mb-0">
{this.state.communityBlocks.map(cb => ( {this.state.communityBlocks.map(c => (
<li key={cb.community.id}> <li key={c.id}>
<span> <span>
<CommunityLink community={cb.community} /> <CommunityLink community={c} />
<button <button
className="btn btn-sm" className="btn btn-sm"
onClick={linkEvent( onClick={linkEvent(
{ ctx: this, communityId: cb.community.id }, { ctx: this, communityId: c.id },
this.handleUnblockCommunity, this.handleUnblockCommunity,
)} )}
data-tippy-content={I18NextService.i18n.t( data-tippy-content={I18NextService.i18n.t(
@ -645,14 +644,14 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
<> <>
<h2 className="h5">{I18NextService.i18n.t("blocked_instances")}</h2> <h2 className="h5">{I18NextService.i18n.t("blocked_instances")}</h2>
<ul className="list-unstyled mb-0"> <ul className="list-unstyled mb-0">
{this.state.instanceBlocks.map(ib => ( {this.state.instanceBlocks.map(i => (
<li key={ib.instance.id}> <li key={i.id}>
<span> <span>
{ib.instance.domain} {i.domain}
<button <button
className="btn btn-sm" className="btn btn-sm"
onClick={linkEvent( onClick={linkEvent(
{ ctx: this, instanceId: ib.instance.id }, { ctx: this, instanceId: i.id },
this.handleUnblockInstance, this.handleUnblockInstance,
)} )}
data-tippy-content={I18NextService.i18n.t("unblock_instance")} data-tippy-content={I18NextService.i18n.t("unblock_instance")}
@ -1349,7 +1348,7 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
instance => instance =>
instance.domain.toLowerCase().includes(text.toLowerCase()) && instance.domain.toLowerCase().includes(text.toLowerCase()) &&
!this.state.instanceBlocks.some( !this.state.instanceBlocks.some(
blockedInstance => blockedInstance.instance.id === instance.id, blockedInstance => blockedInstance.id === instance.id,
), ),
) ?? []; ) ?? [];
} }
@ -1751,7 +1750,6 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
interface_language, interface_language,
show_avatars, show_avatars,
show_bot_accounts, show_bot_accounts,
show_scores,
show_read_posts, show_read_posts,
send_notifications_to_email, send_notifications_to_email,
email, email,
@ -1795,7 +1793,6 @@ export class Settings extends Component<SettingsRouteProps, SettingsState> {
open_links_in_new_tab, open_links_in_new_tab,
send_notifications_to_email, send_notifications_to_email,
show_read_posts, show_read_posts,
show_scores,
}, },
})); }));
} }

View file

@ -1023,7 +1023,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
handleModBanFromCommunity({ handleModBanFromCommunity({
daysUntilExpires, daysUntilExpires,
reason, reason,
shouldRemove, shouldRemoveOrRestoreData,
}: BanUpdateForm) { }: BanUpdateForm) {
const { const {
creator: { id: person_id }, creator: { id: person_id },
@ -1034,7 +1034,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
// If its an unban, restore all their data // If its an unban, restore all their data
if (ban === false) { if (ban === false) {
shouldRemove = false; shouldRemoveOrRestoreData = true;
} }
const expires = futureDaysToUnixTime(daysUntilExpires); const expires = futureDaysToUnixTime(daysUntilExpires);
@ -1042,7 +1042,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
community_id, community_id,
person_id, person_id,
ban, ban,
remove_data: shouldRemove, remove_or_restore_data: shouldRemoveOrRestoreData,
reason, reason,
expires, expires,
}); });
@ -1051,7 +1051,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
handleModBanFromSite({ handleModBanFromSite({
daysUntilExpires, daysUntilExpires,
reason, reason,
shouldRemove, shouldRemoveOrRestoreData,
}: BanUpdateForm) { }: BanUpdateForm) {
const { const {
creator: { id: person_id, banned }, creator: { id: person_id, banned },
@ -1060,14 +1060,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
// If its an unban, restore all their data // If its an unban, restore all their data
if (ban === false) { if (ban === false) {
shouldRemove = false; shouldRemoveOrRestoreData = true;
} }
const expires = futureDaysToUnixTime(daysUntilExpires); const expires = futureDaysToUnixTime(daysUntilExpires);
return this.props.onBanPerson({ return this.props.onBanPerson({
person_id, person_id,
ban, ban,
remove_data: shouldRemove, remove_or_restore_data: shouldRemoveOrRestoreData,
reason, reason,
expires, expires,
}); });

View file

@ -18,6 +18,7 @@ import {
dedupByProperty, dedupByProperty,
getIdFromString, getIdFromString,
getPageFromString, getPageFromString,
getBoolFromString,
getQueryParams, getQueryParams,
getQueryString, getQueryString,
numToSI, numToSI,
@ -77,6 +78,7 @@ interface SearchProps {
type: SearchType; type: SearchType;
sort: SortType; sort: SortType;
listingType: ListingType; listingType: ListingType;
postTitleOnly?: boolean;
communityId?: number; communityId?: number;
creatorId?: number; creatorId?: number;
page: number; page: number;
@ -122,6 +124,7 @@ export function getSearchQueryParams(source?: string): SearchProps {
type: getSearchTypeFromQuery, type: getSearchTypeFromQuery,
sort: getSortTypeFromQuery, sort: getSortTypeFromQuery,
listingType: getListingTypeFromQuery, listingType: getListingTypeFromQuery,
postTitleOnly: getBoolFromString,
communityId: getIdFromString, communityId: getIdFromString,
creatorId: getIdFromString, creatorId: getIdFromString,
page: getPageFromString, page: getPageFromString,
@ -283,6 +286,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
this.handleCommunityFilterChange = this.handleCommunityFilterChange =
this.handleCommunityFilterChange.bind(this); this.handleCommunityFilterChange.bind(this);
this.handleCreatorFilterChange = this.handleCreatorFilterChange.bind(this); this.handleCreatorFilterChange = this.handleCreatorFilterChange.bind(this);
this.handlePostTitleChange = this.handlePostTitleChange.bind(this);
// Only fetch the data if coming from another route // Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) { if (FirstLoadService.isFirstLoad) {
@ -469,6 +473,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
type: searchType, type: searchType,
sort, sort,
listingType: listing_type, listingType: listing_type,
postTitleOnly: post_title_only,
communityId: community_id, communityId: community_id,
creatorId: creator_id, creatorId: creator_id,
page, page,
@ -514,6 +519,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
type_: searchType, type_: searchType,
sort, sort,
listing_type, listing_type,
post_title_only,
page, page,
limit: fetchLimit, limit: fetchLimit,
}; };
@ -635,7 +641,8 @@ export class Search extends Component<SearchRouteProps, SearchState> {
} }
get selects() { get selects() {
const { type, listingType, sort, communityId, creatorId } = this.props; const { type, listingType, postTitleOnly, sort, communityId, creatorId } =
this.props;
const { const {
communitySearchOptions, communitySearchOptions,
creatorSearchOptions, creatorSearchOptions,
@ -673,6 +680,23 @@ export class Search extends Component<SearchRouteProps, SearchState> {
onChange={this.handleListingTypeChange} onChange={this.handleListingTypeChange}
/> />
</div> </div>
{(type === "All" || type === "Posts") && (
<div className="col">
<input
className="btn-check"
id="post-title-only"
type="checkbox"
checked={postTitleOnly}
onChange={this.handlePostTitleChange}
/>
<label
className="btn btn-outline-secondary"
htmlFor="post-title-only"
>
{I18NextService.i18n.t("post_title_only")}
</label>
</div>
)}
<div className="col"> <div className="col">
<SortSelect <SortSelect
sort={sort} sort={sort}
@ -1043,7 +1067,16 @@ export class Search extends Component<SearchRouteProps, SearchState> {
searchToken?: symbol; searchToken?: symbol;
async search(props: SearchRouteProps) { async search(props: SearchRouteProps) {
const token = (this.searchToken = Symbol()); const token = (this.searchToken = Symbol());
const { q, communityId, creatorId, type, sort, listingType, page } = props; const {
q,
communityId,
creatorId,
type,
sort,
listingType,
postTitleOnly,
page,
} = props;
if (q) { if (q) {
this.setState({ searchRes: LOADING_REQUEST }); this.setState({ searchRes: LOADING_REQUEST });
@ -1054,6 +1087,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
type_: type, type_: type,
sort, sort,
listing_type: listingType, listing_type: listingType,
post_title_only: postTitleOnly,
page, page,
limit: fetchLimit, limit: fetchLimit,
}); });
@ -1122,6 +1156,11 @@ export class Search extends Component<SearchRouteProps, SearchState> {
this.updateUrl({ sort, page: 1, q: this.getQ() }); this.updateUrl({ sort, page: 1, q: this.getQ() });
} }
handlePostTitleChange(event: any) {
const postTitleOnly = event.target.checked;
this.updateUrl({ postTitleOnly, q: this.getQ() });
}
handleTypeChange(i: Search, event: any) { handleTypeChange(i: Search, event: any) {
const type = event.target.value as SearchType; const type = event.target.value as SearchType;
@ -1170,7 +1209,16 @@ export class Search extends Component<SearchRouteProps, SearchState> {
} }
async updateUrl(props: Partial<SearchProps>) { async updateUrl(props: Partial<SearchProps>) {
const { q, type, listingType, sort, communityId, creatorId, page } = { const {
q,
type,
listingType,
postTitleOnly,
sort,
communityId,
creatorId,
page,
} = {
...this.props, ...this.props,
...props, ...props,
}; };
@ -1179,6 +1227,7 @@ export class Search extends Component<SearchRouteProps, SearchState> {
q, q,
type: type, type: type,
listingType: listingType, listingType: listingType,
postTitleOnly: postTitleOnly?.toString(),
communityId: communityId?.toString(), communityId: communityId?.toString(),
creatorId: creatorId?.toString(), creatorId: creatorId?.toString(),
page: page?.toString(), page: page?.toString(),

View file

@ -1,5 +1,5 @@
import { GetSiteResponse } from "lemmy-js-client"; import { GetSiteResponse } from "lemmy-js-client";
export default function enableNsfw(siteRes: GetSiteResponse): boolean { export default function enableNsfw(siteRes: GetSiteResponse): boolean {
return siteRes.site_view.local_site.enable_nsfw; return !!siteRes.site_view.site.content_warning;
} }

View file

@ -6,12 +6,8 @@ export default function isPostBlocked(
myUserInfo: MyUserInfo | undefined = UserService.Instance.myUserInfo, myUserInfo: MyUserInfo | undefined = UserService.Instance.myUserInfo,
): boolean { ): boolean {
return ( return (
(myUserInfo?.community_blocks (myUserInfo?.community_blocks.some(c => c.id === pv.community.id) ||
.map(c => c.community.id) myUserInfo?.person_blocks.some(p => p.id === pv.creator.id)) ??
.includes(pv.community.id) ||
myUserInfo?.person_blocks
.map(p => p.target.id)
.includes(pv.creator.id)) ??
false false
); );
} }

View file

@ -8,10 +8,7 @@ export default function updateCommunityBlock(
) { ) {
if (myUserInfo) { if (myUserInfo) {
if (data.blocked) { if (data.blocked) {
myUserInfo.community_blocks.push({ myUserInfo.community_blocks.push(data.community_view.community);
person: myUserInfo.local_user_view.person,
community: data.community_view.community,
});
toast( toast(
`${I18NextService.i18n.t("blocked")} ${ `${I18NextService.i18n.t("blocked")} ${
data.community_view.community.name data.community_view.community.name
@ -19,7 +16,7 @@ export default function updateCommunityBlock(
); );
} else { } else {
myUserInfo.community_blocks = myUserInfo.community_blocks.filter( myUserInfo.community_blocks = myUserInfo.community_blocks.filter(
i => i.community.id !== data.community_view.community.id, c => c.id !== data.community_view.community.id,
); );
toast( toast(
`${I18NextService.i18n.t("unblocked")} ${ `${I18NextService.i18n.t("unblocked")} ${

View file

@ -12,14 +12,11 @@ export default function updateInstanceBlock(
const instance = linkedInstances.find(i => i.id === id)!; const instance = linkedInstances.find(i => i.id === id)!;
if (data.blocked) { if (data.blocked) {
myUserInfo.instance_blocks.push({ myUserInfo.instance_blocks.push(instance);
person: myUserInfo.local_user_view.person,
instance,
});
toast(`${I18NextService.i18n.t("blocked")} ${instance.domain}`); toast(`${I18NextService.i18n.t("blocked")} ${instance.domain}`);
} else { } else {
myUserInfo.instance_blocks = myUserInfo.instance_blocks.filter( myUserInfo.instance_blocks = myUserInfo.instance_blocks.filter(
i => i.instance.id !== id, i => i.id !== id,
); );
toast(`${I18NextService.i18n.t("unblocked")} ${instance.domain}`); toast(`${I18NextService.i18n.t("unblocked")} ${instance.domain}`);
} }

View file

@ -8,16 +8,13 @@ export default function updatePersonBlock(
) { ) {
if (myUserInfo) { if (myUserInfo) {
if (data.blocked) { if (data.blocked) {
myUserInfo.person_blocks.push({ myUserInfo.person_blocks.push(data.person_view.person);
person: myUserInfo.local_user_view.person,
target: data.person_view.person,
});
toast( toast(
`${I18NextService.i18n.t("blocked")} ${data.person_view.person.name}`, `${I18NextService.i18n.t("blocked")} ${data.person_view.person.name}`,
); );
} else { } else {
myUserInfo.person_blocks = myUserInfo.person_blocks.filter( myUserInfo.person_blocks = myUserInfo.person_blocks.filter(
i => i.target.id !== data.person_view.person.id, p => p.id !== data.person_view.person.id,
); );
toast( toast(
`${I18NextService.i18n.t("unblocked")} ${data.person_view.person.name}`, `${I18NextService.i18n.t("unblocked")} ${data.person_view.person.name}`,

View file

@ -5,7 +5,6 @@ export default function voteDisplayMode(
): LocalUserVoteDisplayMode { ): LocalUserVoteDisplayMode {
return ( return (
siteRes?.my_user?.local_user_view.local_user_vote_display_mode ?? { siteRes?.my_user?.local_user_view.local_user_vote_display_mode ?? {
local_user_id: -1,
upvotes: true, upvotes: true,
downvotes: true, downvotes: true,
score: false, score: false,

View file

@ -0,0 +1,5 @@
export default function getBoolFromString(
boolStr?: string,
): boolean | undefined {
return boolStr ? boolStr.toLowerCase() === "true" : undefined;
}

View file

@ -5,6 +5,7 @@ import editListImmutable from "./edit-list-immutable";
import formatPastDate from "./format-past-date"; import formatPastDate from "./format-past-date";
import futureDaysToUnixTime from "./future-days-to-unix-time"; import futureDaysToUnixTime from "./future-days-to-unix-time";
import getIdFromString from "./get-id-from-string"; import getIdFromString from "./get-id-from-string";
import getBoolFromString from "./get-bool-from-string";
import getPageFromString from "./get-page-from-string"; import getPageFromString from "./get-page-from-string";
import getQueryParams from "./get-query-params"; import getQueryParams from "./get-query-params";
import getQueryString from "./get-query-string"; import getQueryString from "./get-query-string";
@ -36,6 +37,7 @@ export {
formatPastDate, formatPastDate,
futureDaysToUnixTime, futureDaysToUnixTime,
getIdFromString, getIdFromString,
getBoolFromString,
getPageFromString, getPageFromString,
getQueryParams, getQueryParams,
getQueryString, getQueryString,