Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remember comment sort by community #1465

Merged
merged 3 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/features/comment/CommentSort.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ const BUTTONS: ActionSheetButton<CommentSortType>[] = COMMENT_SORTS.map(
);

interface CommentSortProps {
sort: CommentSortType;
sort: CommentSortType | undefined;
setSort: (sort: CommentSortType) => void;
}

export default function CommentSort({ sort, setSort }: CommentSortProps) {
const [open, setOpen] = useState(false);
const { activePageRef } = useContext(AppContext);

if (!sort) return;

return (
<>
<IonButton onClick={() => setOpen(true)}>
Expand Down
75 changes: 57 additions & 18 deletions src/features/feed/sort/feedSortSlice.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PayloadAction, createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { ListingType, SortType } from "lemmy-js-client";
import { CommentSortType, ListingType, SortType } from "lemmy-js-client";
import { db } from "../../../services/db";
import { RootState } from "../../../store";
import { getFeedUrlName } from "../../community/mod/ModActions";
Expand All @@ -8,34 +8,54 @@ interface PostSortState {
/**
* `null`: Loaded from database, but nothing there
*/
sortByFeedName: Record<string, SortType | null>;
sortByContextByFeedName: {
posts: Record<string, SortType | null>;
comments: Record<string, CommentSortType | null>;
};
}

const initialState: PostSortState = {
sortByFeedName: {},
sortByContextByFeedName: {
posts: {},
comments: {},
},
};

export type SetSortActionPayload =
| {
feed: FeedSortFeed;
sort: SortType;
context: "posts";
}
| {
feed: FeedSortFeed;
sort: CommentSortType;
context: "comments";
};

export const feedSortSlice = createSlice({
name: "feedSort",
initialState,
reducers: {
setFeedSort: (
state,
action: PayloadAction<{ feed: FeedSortFeed; sort: SortType }>,
) => {
setFeedSort: (state, action: PayloadAction<SetSortActionPayload>) => {
const feedName = serializeFeedName(action.payload.feed);
state.sortByFeedName[feedName] = action.payload.sort;
state.sortByContextByFeedName[action.payload.context][feedName] =
action.payload.sort;

db.setSetting("default_post_sort_by_feed", action.payload.sort, {
community: feedName,
});
db.setSetting(
getDefaultSortSettingForContext(action.payload.context),
action.payload.sort,
{
community: feedName,
},
);
},
},
extraReducers: (builder) => {
builder.addCase(getFeedSort.fulfilled, (state, action) => {
const { feedName, sort } = action.payload;
const { feedName, sort, context } = action.payload;

state.sortByFeedName[feedName] = sort;
state.sortByContextByFeedName[context][feedName] = sort;
});
},
});
Expand All @@ -55,23 +75,33 @@ export type FeedSortFeed =

export const getFeedSort = createAsyncThunk(
"feedSort/getFeedSort",
async (feed: FeedSortFeed) => {
async ({
feed,
context,
}: {
feed: FeedSortFeed;
context: "posts" | "comments";
}) => {
const feedName = serializeFeedName(feed);
const sort =
(await db.getSetting("default_post_sort_by_feed", {
(await db.getSetting(getDefaultSortSettingForContext(context), {
community: feedName,
})) ?? null;
})) ?? null; // null = loaded, but not found

return {
feedName,
sort,
context,
};
},
);

export const getFeedSortSelectorBuilder =
(feed: FeedSortFeed | undefined) => (state: RootState) =>
feed ? state.feedSort.sortByFeedName[serializeFeedName(feed)] : null;
(feed: FeedSortFeed | undefined, context: "posts" | "comments") =>
(state: RootState) =>
feed
? state.feedSort.sortByContextByFeedName[context][serializeFeedName(feed)]
: null;

function serializeFeedName(feed: FeedSortFeed): string {
switch (true) {
Expand All @@ -83,3 +113,12 @@ function serializeFeedName(feed: FeedSortFeed): string {
return feed;
}
}

function getDefaultSortSettingForContext(context: "posts" | "comments") {
switch (context) {
case "comments":
return "default_comment_sort_by_feed";
case "posts":
return "default_post_sort_by_feed";
}
}
47 changes: 33 additions & 14 deletions src/features/feed/sort/useFeedSort.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,68 @@
import { SortType } from "lemmy-js-client";
import { CommentSortType, SortType } from "lemmy-js-client";
import { useEffect, useState } from "react";
import { useAppDispatch, useAppSelector } from "../../../store";
import {
FeedSortFeed,
SetSortActionPayload,
getFeedSort,
getFeedSortSelectorBuilder,
setFeedSort,
} from "./feedSortSlice";

export default function useFeedSort(feed?: FeedSortFeed | undefined) {
type SortTypeByContext = {
posts: SortType;
comments: CommentSortType;
};

export default function useSortByFeed<
Context extends "posts" | "comments",
Sort extends SortTypeByContext[Context],
>(context: Context, feed?: FeedSortFeed | undefined) {
const dispatch = useAppDispatch();
const feedSort = useAppSelector(getFeedSortSelectorBuilder(feed));
const feedSort = useAppSelector(
getFeedSortSelectorBuilder(feed, context),
) as Sort;
const defaultSort = useAppSelector(
(state) => state.settings.general.posts.sort,
);
(state) => state.settings.general[context].sort,
) as Sort;
const rememberCommunitySort = useAppSelector(
(state) => state.settings.general.posts.rememberCommunitySort,
(state) => state.settings.general[context].rememberCommunitySort,
);

const [sort, _setSort] = useState<SortType | undefined>(
const [sort, _setSort] = useState<Sort | undefined>(
!rememberCommunitySort ? defaultSort : undefined,
);

useEffect(() => {
if (!rememberCommunitySort) return;
if (!feed) return;
(async () => {
if (!rememberCommunitySort) return;
if (!feed) return;

dispatch(getFeedSort(feed));
}, [feed, dispatch, rememberCommunitySort]);
try {
await dispatch(getFeedSort({ feed, context }));
} catch (error) {
_setSort((_sort) => _sort ?? defaultSort); // fallback if indexeddb unavailable
throw error;
}
})();
}, [feed, dispatch, rememberCommunitySort, context, defaultSort]);

useEffect(() => {
if (!rememberCommunitySort) return;
if (sort) return;
if (feedSort === undefined) return;
if (feedSort === undefined) return; // null = loaded, but custom community sort not found

_setSort(feedSort ?? defaultSort);
}, [feedSort, sort, defaultSort, rememberCommunitySort]);

function setSort(sort: SortType) {
function setSort(sort: Sort) {
if (rememberCommunitySort && feed) {
dispatch(
setFeedSort({
feed,
sort,
}),
context,
} as SetSortActionPayload),
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/features/settings/general/comments/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import TouchFriendlyLinks from "./TouchFriendlyLinks";
import TapToCollapse from "./TapToCollapse";
import ShowCommentImages from "./ShowCommentImages";
import ShowCollapsed from "./ShowCollapsed";
import RememberCommunityCommentSort from "./RememberCommunityCommentSort";

export default function Comments() {
return (
Expand All @@ -18,6 +19,7 @@ export default function Comments() {
</ListHeader>
<IonList inset>
<DefaultSort />
<RememberCommunityCommentSort />
<CollapsedByDefault />
<TapToCollapse />
<ShowJumpButton />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IonItem, IonToggle } from "@ionic/react";

import { useAppDispatch, useAppSelector } from "../../../../store";
import { setRememberCommunityCommentSort } from "../../settingsSlice";

export default function RememberCommunityCommentSort() {
const dispatch = useAppDispatch();
const rememberCommunitySort = useAppSelector(
(state) => state.settings.general.comments.rememberCommunitySort,
);

return (
<IonItem>
<IonToggle
checked={rememberCommunitySort}
onIonChange={(e) =>
dispatch(setRememberCommunityCommentSort(e.detail.checked))
}
>
Remember Community Sort
</IonToggle>
</IonItem>
);
}
4 changes: 2 additions & 2 deletions src/features/settings/general/posts/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ListHeader } from "../../shared/formatting";
import InfiniteScrolling from "./InfiniteScrolling";
import UpvoteOnSave from "./UpvoteOnSave";
import DefaultSort from "./DefaultSort";
import RememberCommunitySort from "./RememberCommunitySort";
import RememberCommunityPostSort from "./RememberCommunityPostSort";
import AutoplayMedia from "./AutoplayMedia";

export default function Posts() {
Expand All @@ -19,7 +19,7 @@ export default function Posts() {
</IonLabel>
</IonItem>
<DefaultSort />
<RememberCommunitySort />
<RememberCommunityPostSort />
<InfiniteScrolling />
<UpvoteOnSave />
<AutoplayMedia />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { IonItem, IonToggle } from "@ionic/react";

import { useAppDispatch, useAppSelector } from "../../../../store";
import { setRememberCommunitySort } from "../../settingsSlice";
import { setRememberCommunityPostSort } from "../../settingsSlice";

export default function RememberCommunitySort() {
export default function RememberCommunityPostSort() {
const dispatch = useAppDispatch();
const infiniteScrolling = useAppSelector(
const rememberCommunitySort = useAppSelector(
(state) => state.settings.general.posts.rememberCommunitySort,
);

return (
<IonItem>
<IonToggle
checked={infiniteScrolling}
checked={rememberCommunitySort}
onIonChange={(e) =>
dispatch(setRememberCommunitySort(e.detail.checked))
dispatch(setRememberCommunityPostSort(e.detail.checked))
}
>
Remember Community Sort
Expand Down
26 changes: 20 additions & 6 deletions src/features/settings/settingsSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ interface SettingsState {
touchFriendlyLinks: boolean;
showCommentImages: boolean;
showCollapsed: boolean;
rememberCommunitySort: boolean;
};
posts: {
sort: SortType;
Expand Down Expand Up @@ -206,6 +207,7 @@ export const initialState: SettingsState = {
touchFriendlyLinks: true,
showCommentImages: true,
showCollapsed: false,
rememberCommunitySort: false,
},
posts: {
sort: "Active",
Expand Down Expand Up @@ -483,10 +485,15 @@ export const appearanceSlice = createSlice({

db.setSetting("upvote_on_save", action.payload);
},
setRememberCommunitySort(state, action: PayloadAction<boolean>) {
setRememberCommunityPostSort(state, action: PayloadAction<boolean>) {
state.general.posts.rememberCommunitySort = action.payload;

db.setSetting("remember_community_sort", action.payload);
db.setSetting("remember_community_post_sort", action.payload);
},
setRememberCommunityCommentSort(state, action: PayloadAction<boolean>) {
state.general.comments.rememberCommunitySort = action.payload;

db.setSetting("remember_community_comment_sort", action.payload);
},
setAutoplayMedia(state, action: PayloadAction<AutoplayMediaType>) {
state.general.posts.autoplayMedia = action.payload;
Expand Down Expand Up @@ -673,8 +680,11 @@ export const fetchSettingsFromDatabase = createAsyncThunk<SettingsState>(
);
const infinite_scrolling = await db.getSetting("infinite_scrolling");
const upvote_on_save = await db.getSetting("upvote_on_save");
const remember_community_sort = await db.getSetting(
"remember_community_sort",
const remember_community_post_sort = await db.getSetting(
"remember_community_post_sort",
);
const remember_community_comment_sort = await db.getSetting(
"remember_community_comment_sort",
);
const autoplay_media = await db.getSetting("autoplay_media");
const enable_haptic_feedback = await db.getSetting(
Expand Down Expand Up @@ -787,6 +797,9 @@ export const fetchSettingsFromDatabase = createAsyncThunk<SettingsState>(
showCollapsed:
show_collapsed_comment ??
initialState.general.comments.showCollapsed,
rememberCommunitySort:
remember_community_comment_sort ??
initialState.general.comments.rememberCommunitySort,
},
posts: {
disableMarkingRead:
Expand All @@ -813,7 +826,7 @@ export const fetchSettingsFromDatabase = createAsyncThunk<SettingsState>(
upvote_on_save ?? initialState.general.posts.upvoteOnSave,
sort: default_post_sort ?? initialState.general.posts.sort,
rememberCommunitySort:
remember_community_sort ??
remember_community_post_sort ??
initialState.general.posts.rememberCommunitySort,
autoplayMedia:
autoplay_media ?? initialState.general.posts.autoplayMedia,
Expand Down Expand Up @@ -893,7 +906,8 @@ export const {
setDisableAutoHideInCommunities,
setInfiniteScrolling,
setUpvoteOnSave,
setRememberCommunitySort,
setRememberCommunityPostSort,
setRememberCommunityCommentSort,
setAutoplayMedia,
setTheme,
setEnableHapticFeedback,
Expand Down
Loading
Loading