From 39f6c88f2f2c855eff8452a33fd91b28fc402f19 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Sun, 5 May 2024 21:48:05 -0500
Subject: [PATCH 01/11] Truncate github URL for max length, if needed (#1461)
---
src/core/AppCrash.tsx | 43 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 36 insertions(+), 7 deletions(-)
diff --git a/src/core/AppCrash.tsx b/src/core/AppCrash.tsx
index c76626ab0..f2b387168 100644
--- a/src/core/AppCrash.tsx
+++ b/src/core/AppCrash.tsx
@@ -39,7 +39,7 @@ export default function AppCrash({ error }: FallbackProps) {
const location = memoryHistory ? memoryHistory.location : window.location;
const loggedIn = loggedInSelector(store.getState());
- const crashData = `
+ let crashData = `
### Crash description
@@ -58,15 +58,15 @@ export default function AppCrash({ error }: FallbackProps) {
### Crash data
-Error: \`${error}\`
+Error: \`\`${error}\`\`
#### Stack trace
-\`\`\`
-${error instanceof Error ? error.stack : "Not available"}
\`\`\`
`.trim();
+ crashData = `${crashData}\n${error instanceof Error ? error.stack : "Not available"}`;
+
async function clearData() {
if (
!confirm(
@@ -94,9 +94,7 @@ ${error instanceof Error ? error.stack : "Not available"}
voluntarily submitting this crash for us to investigate.
);
}
+
+function generateCrashUrl(crashData: string): string {
+ return `https://github.com/aeharding/voyager/issues/new?title=Crash&body=${encodeURIComponent(
+ crashData,
+ )}`;
+}
+
+// The GitHub GET endpoint for opening a new issue
+// has a restriction for maximum length of a URL: 8192 bytes
+// https://github.com/cli/cli/pull/3271
+// https://github.com/cli/cli/issues/1575
+// https://github.com/cli/cli/blob/trunk/pkg/cmd/issue/create/create.go#L167
+// https://github.com/cli/cli/blob/trunk/utils/utils.go#L84
+const maxIssueBytes = 8150;
+
+function getStrByteLength(str: string): number {
+ return new TextEncoder().encode(str).length;
+}
+
+function generateTruncatedCrashUrl(crashData: string): string {
+ let url: string;
+ let strLength = 1;
+
+ do {
+ url = generateCrashUrl(crashData.slice(0, strLength));
+ if (strLength === crashData.length) return url;
+ strLength++;
+ } while (getStrByteLength(url) < maxIssueBytes);
+
+ return url;
+}
From 9b388b0546d841e0a49b1aa31ed5ce9930ffc593 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Sun, 5 May 2024 21:57:36 -0500
Subject: [PATCH 02/11] Fix NSFW messaging visible when image opened with
scaling animation (#1462)
---
src/features/media/gallery/GalleryProvider.tsx | 10 ++++++++--
.../post/inFeed/large/LargePostContents.tsx | 6 +++++-
.../inFeed/large/media/BlurOverlayMessage.tsx | 15 ++++++++++++++-
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/features/media/gallery/GalleryProvider.tsx b/src/features/media/gallery/GalleryProvider.tsx
index b8a0896b2..3286c453a 100644
--- a/src/features/media/gallery/GalleryProvider.tsx
+++ b/src/features/media/gallery/GalleryProvider.tsx
@@ -26,6 +26,8 @@ import type ZoomLevel from "photoswipe/dist/types/slide/zoom-level";
import PhotoSwipeLightbox from "photoswipe/lightbox";
import "photoswipe/style.css";
+import { findBlurOverlayContainer } from "../../post/inFeed/large/media/BlurOverlayMessage";
+import { compact } from "lodash";
interface IGalleryContext {
// used for determining whether page needs to be scrolled up first
@@ -173,13 +175,17 @@ export default function GalleryProvider({ children }: GalleryProviderProps) {
instance.on("openingAnimationStart", () => {
if (animationType !== "zoom") return;
- thumbEl.style.setProperty("visibility", "hidden");
+ compact([thumbEl, findBlurOverlayContainer(thumbEl)]).forEach((el) =>
+ el.style.setProperty("visibility", "hidden"),
+ );
});
const cleanupHideThumb = () => {
if (animationType !== "zoom") return;
- thumbEl.style.removeProperty("visibility");
+ compact([thumbEl, findBlurOverlayContainer(thumbEl)]).forEach((el) =>
+ el.style.removeProperty("visibility"),
+ );
};
instance.on("closingAnimationEnd", cleanupHideThumb);
diff --git a/src/features/post/inFeed/large/LargePostContents.tsx b/src/features/post/inFeed/large/LargePostContents.tsx
index 1536c2568..6c5a21b66 100644
--- a/src/features/post/inFeed/large/LargePostContents.tsx
+++ b/src/features/post/inFeed/large/LargePostContents.tsx
@@ -11,6 +11,10 @@ import { InFeedContext } from "../../../feed/Feed";
import useIsPostUrlMedia from "../../useIsPostUrlMedia";
import PostLink from "../../link/PostLink";
+// This is needed to hide NSFW messaging, etc when image is open
+export const LARGE_POST_MEDIA_CONTAINER_CLASSNAME =
+ "large-post-media-container";
+
const PostBody = styled.div`
font-size: 0.8em;
line-height: 1.25;
@@ -64,7 +68,7 @@ export default function LargePostContents({ post }: LargePostContentsProps) {
if (urlIsMedia || markdownLoneImage) {
return (
-
+
+
NSFW
Sensitive content — tap to view
);
}
+
+export function findBlurOverlayContainer(
+ imgEl: HTMLElement,
+): HTMLElement | undefined {
+ const el = imgEl
+ .closest(`.${LARGE_POST_MEDIA_CONTAINER_CLASSNAME}`)
+ ?.querySelector(`.${BLUR_OVERLAY_CONTAINER_CLASSNAME}`);
+
+ if (el instanceof HTMLElement) return el;
+}
From 2fd0d2c38bbec303d30ddb9d61c19174434da72e Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Mon, 6 May 2024 22:39:29 -0500
Subject: [PATCH 03/11] Add post appearance type toggle from feed, add share
home/all/local feeds (#1464)
---
src/features/community/MoreActions.tsx | 56 +++++-------
src/features/feed/SpecialFeedMoreActions.tsx | 86 +++++++++++++++----
.../settings/appearance/posts/PostSize.tsx | 5 ++
src/routes/pages/shared/SpecialFeedPage.tsx | 2 +-
4 files changed, 100 insertions(+), 49 deletions(-)
diff --git a/src/features/community/MoreActions.tsx b/src/features/community/MoreActions.tsx
index 8058dbfdb..1d115c1dd 100644
--- a/src/features/community/MoreActions.tsx
+++ b/src/features/community/MoreActions.tsx
@@ -1,4 +1,4 @@
-import { IonActionSheet, IonButton } from "@ionic/react";
+import { IonButton, useIonActionSheet } from "@ionic/react";
import {
createOutline,
heartDislikeOutline,
@@ -10,49 +10,30 @@ import {
eyeOffOutline,
shareOutline,
} from "ionicons/icons";
-import { useState } from "react";
import useHidePosts from "../feed/useHidePosts";
import useCommunityActions from "./useCommunityActions";
import { Community, CommunityView } from "lemmy-js-client";
import { useAppSelector } from "../../store";
import { compact } from "lodash";
import HeaderEllipsisIcon from "../shared/HeaderEllipsisIcon";
+import { buildTogglePostAppearanceButton } from "../feed/SpecialFeedMoreActions";
interface MoreActionsProps {
community: CommunityView | undefined;
}
export default function MoreActions({ community }: MoreActionsProps) {
- const [open, setOpen] = useState(false);
+ if (!community) return buildButtonJsx();
- return (
- <>
- setOpen(true)}>
-
-
-
- {community && (
-
- )}
- >
- );
+ return ;
}
interface MoreActionsActionSheetProps {
community: Community;
- open: boolean;
- setOpen: (open: boolean) => void;
}
-function MoreActionsActionSheet({
- community,
- open,
- setOpen,
-}: MoreActionsActionSheetProps) {
+function MoreActionsWithCommunity({ community }: MoreActionsActionSheetProps) {
+ const [presentActionSheet] = useIonActionSheet();
const {
isSubscribed,
isBlocked,
@@ -70,11 +51,10 @@ function MoreActionsActionSheet({
(state) => state.settings.general.posts.showHiddenInCommunities,
);
- return (
- setOpen(false)}
- />
+ ]),
+ });
+ }
+
+ return buildButtonJsx(present);
+}
+
+function buildButtonJsx(onClick?: () => void) {
+ return (
+
+
+
);
}
diff --git a/src/features/feed/SpecialFeedMoreActions.tsx b/src/features/feed/SpecialFeedMoreActions.tsx
index 2766906af..5e15b251b 100644
--- a/src/features/feed/SpecialFeedMoreActions.tsx
+++ b/src/features/feed/SpecialFeedMoreActions.tsx
@@ -1,27 +1,60 @@
import { IonButton, useIonActionSheet } from "@ionic/react";
-import { eyeOffOutline } from "ionicons/icons";
+import {
+ eyeOffOutline,
+ imageOutline,
+ listOutline,
+ shareOutline,
+} from "ionicons/icons";
import useHidePosts from "./useHidePosts";
import HeaderEllipsisIcon from "../shared/HeaderEllipsisIcon";
+import { Share } from "@capacitor/share";
+import { ListingType } from "lemmy-js-client";
+import store from "../../store";
+import { urlSelector } from "../auth/authSelectors";
+import {
+ OPostAppearanceType,
+ setPostAppearance,
+} from "../settings/settingsSlice";
-export default function SpecialFeedMoreActions() {
- const [presentActionSheet] = useIonActionSheet();
+interface SpecialFeedMoreActionsProps {
+ type: ListingType;
+}
+export default function SpecialFeedMoreActions({
+ type,
+}: SpecialFeedMoreActionsProps) {
+ const [presentActionSheet] = useIonActionSheet();
const hidePosts = useHidePosts();
function present() {
- presentActionSheet([
- {
- text: "Hide Read Posts",
- icon: eyeOffOutline,
- handler: () => {
- hidePosts();
+ presentActionSheet({
+ cssClass: "left-align-buttons",
+ buttons: [
+ {
+ text: "Hide Read Posts",
+ icon: eyeOffOutline,
+ handler: () => {
+ hidePosts();
+ },
},
- },
- {
- text: "Cancel",
- role: "cancel",
- },
- ]);
+ buildTogglePostAppearanceButton(),
+ {
+ text: "Share",
+ icon: shareOutline,
+ handler: () => {
+ const url = urlSelector(store.getState());
+
+ Share.share({
+ url: `https://${url}?dataType=Post&listingType=${type}`,
+ });
+ },
+ },
+ {
+ text: "Cancel",
+ role: "cancel",
+ },
+ ],
+ });
}
return (
@@ -30,3 +63,26 @@ export default function SpecialFeedMoreActions() {
);
}
+
+export function buildTogglePostAppearanceButton() {
+ const postAppearanceType = store.getState().settings.appearance.posts.type;
+
+ switch (postAppearanceType) {
+ case OPostAppearanceType.Compact:
+ return {
+ text: "Large Posts",
+ icon: imageOutline,
+ handler: () => {
+ store.dispatch(setPostAppearance(OPostAppearanceType.Large));
+ },
+ };
+ case OPostAppearanceType.Large:
+ return {
+ text: "Compact Posts",
+ icon: listOutline,
+ handler: () => {
+ store.dispatch(setPostAppearance(OPostAppearanceType.Compact));
+ },
+ };
+ }
+}
diff --git a/src/features/settings/appearance/posts/PostSize.tsx b/src/features/settings/appearance/posts/PostSize.tsx
index 7681f86dc..d069c09b3 100644
--- a/src/features/settings/appearance/posts/PostSize.tsx
+++ b/src/features/settings/appearance/posts/PostSize.tsx
@@ -1,6 +1,7 @@
import { OPostAppearanceType, setPostAppearance } from "../../settingsSlice";
import { useAppSelector } from "../../../../store";
import SettingSelector from "../../shared/SettingSelector";
+import { imageOutline, listOutline } from "ionicons/icons";
export default function PostSize() {
const postsAppearanceType = useAppSelector(
@@ -13,6 +14,10 @@ export default function PostSize() {
selected={postsAppearanceType}
setSelected={setPostAppearance}
options={OPostAppearanceType}
+ optionIcons={{
+ [OPostAppearanceType.Compact]: listOutline,
+ [OPostAppearanceType.Large]: imageOutline,
+ }}
/>
);
}
diff --git a/src/routes/pages/shared/SpecialFeedPage.tsx b/src/routes/pages/shared/SpecialFeedPage.tsx
index 35bcf20b5..5d3a212b1 100644
--- a/src/routes/pages/shared/SpecialFeedPage.tsx
+++ b/src/routes/pages/shared/SpecialFeedPage.tsx
@@ -109,7 +109,7 @@ export default function SpecialFeedPage({ type }: SpecialFeedProps) {
{type === "ModeratorView" && }
-
+
From 1d74518743d93a305b0ad308a38b49e8376a51fa Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Wed, 8 May 2024 22:50:49 -0500
Subject: [PATCH 04/11] Remember comment sort by community (#1465)
* Add remember comment sort
* Add migration
* Fallback for broken indexeddb
---
src/features/comment/CommentSort.tsx | 4 +-
src/features/feed/sort/feedSortSlice.tsx | 75 ++++++++++++++-----
src/features/feed/sort/useFeedSort.tsx | 47 ++++++++----
.../settings/general/comments/Comments.tsx | 2 +
.../comments/RememberCommunityCommentSort.tsx | 24 ++++++
src/features/settings/general/posts/Posts.tsx | 4 +-
...Sort.tsx => RememberCommunityPostSort.tsx} | 10 +--
src/features/settings/settingsSlice.tsx | 26 +++++--
src/routes/pages/posts/PostPage.tsx | 19 +++--
.../search/results/SearchCommunitiesPage.tsx | 4 +-
.../search/results/SearchFeedResultsPage.tsx | 4 +-
src/routes/pages/shared/CommunityPage.tsx | 4 +-
src/routes/pages/shared/SpecialFeedPage.tsx | 4 +-
src/services/db.ts | 11 ++-
14 files changed, 178 insertions(+), 60 deletions(-)
create mode 100644 src/features/settings/general/comments/RememberCommunityCommentSort.tsx
rename src/features/settings/general/posts/{RememberCommunitySort.tsx => RememberCommunityPostSort.tsx} (58%)
diff --git a/src/features/comment/CommentSort.tsx b/src/features/comment/CommentSort.tsx
index e14d64e4b..ebbb4a87d 100644
--- a/src/features/comment/CommentSort.tsx
+++ b/src/features/comment/CommentSort.tsx
@@ -36,7 +36,7 @@ const BUTTONS: ActionSheetButton[] = COMMENT_SORTS.map(
);
interface CommentSortProps {
- sort: CommentSortType;
+ sort: CommentSortType | undefined;
setSort: (sort: CommentSortType) => void;
}
@@ -44,6 +44,8 @@ export default function CommentSort({ sort, setSort }: CommentSortProps) {
const [open, setOpen] = useState(false);
const { activePageRef } = useContext(AppContext);
+ if (!sort) return;
+
return (
<>
setOpen(true)}>
diff --git a/src/features/feed/sort/feedSortSlice.tsx b/src/features/feed/sort/feedSortSlice.tsx
index 6f3e48dfd..8648e24dd 100644
--- a/src/features/feed/sort/feedSortSlice.tsx
+++ b/src/features/feed/sort/feedSortSlice.tsx
@@ -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";
@@ -8,34 +8,54 @@ interface PostSortState {
/**
* `null`: Loaded from database, but nothing there
*/
- sortByFeedName: Record;
+ sortByContextByFeedName: {
+ posts: Record;
+ comments: Record;
+ };
}
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) => {
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;
});
},
});
@@ -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) {
@@ -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";
+ }
+}
diff --git a/src/features/feed/sort/useFeedSort.tsx b/src/features/feed/sort/useFeedSort.tsx
index 1d828bb97..99a88958b 100644
--- a/src/features/feed/sort/useFeedSort.tsx
+++ b/src/features/feed/sort/useFeedSort.tsx
@@ -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(
+ const [sort, _setSort] = useState(
!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),
);
}
diff --git a/src/features/settings/general/comments/Comments.tsx b/src/features/settings/general/comments/Comments.tsx
index 7fe31bc51..97773f742 100644
--- a/src/features/settings/general/comments/Comments.tsx
+++ b/src/features/settings/general/comments/Comments.tsx
@@ -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 (
@@ -18,6 +19,7 @@ export default function Comments() {
+
diff --git a/src/features/settings/general/comments/RememberCommunityCommentSort.tsx b/src/features/settings/general/comments/RememberCommunityCommentSort.tsx
new file mode 100644
index 000000000..c1fff43c6
--- /dev/null
+++ b/src/features/settings/general/comments/RememberCommunityCommentSort.tsx
@@ -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 (
+
+
+ dispatch(setRememberCommunityCommentSort(e.detail.checked))
+ }
+ >
+ Remember Community Sort
+
+
+ );
+}
diff --git a/src/features/settings/general/posts/Posts.tsx b/src/features/settings/general/posts/Posts.tsx
index c65460bef..7d8fffa43 100644
--- a/src/features/settings/general/posts/Posts.tsx
+++ b/src/features/settings/general/posts/Posts.tsx
@@ -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() {
@@ -19,7 +19,7 @@ export default function Posts() {
-
+
diff --git a/src/features/settings/general/posts/RememberCommunitySort.tsx b/src/features/settings/general/posts/RememberCommunityPostSort.tsx
similarity index 58%
rename from src/features/settings/general/posts/RememberCommunitySort.tsx
rename to src/features/settings/general/posts/RememberCommunityPostSort.tsx
index 814aa8943..5290e45d0 100644
--- a/src/features/settings/general/posts/RememberCommunitySort.tsx
+++ b/src/features/settings/general/posts/RememberCommunityPostSort.tsx
@@ -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 (
- dispatch(setRememberCommunitySort(e.detail.checked))
+ dispatch(setRememberCommunityPostSort(e.detail.checked))
}
>
Remember Community Sort
diff --git a/src/features/settings/settingsSlice.tsx b/src/features/settings/settingsSlice.tsx
index a6720e480..6ec695729 100644
--- a/src/features/settings/settingsSlice.tsx
+++ b/src/features/settings/settingsSlice.tsx
@@ -110,6 +110,7 @@ interface SettingsState {
touchFriendlyLinks: boolean;
showCommentImages: boolean;
showCollapsed: boolean;
+ rememberCommunitySort: boolean;
};
posts: {
sort: SortType;
@@ -206,6 +207,7 @@ export const initialState: SettingsState = {
touchFriendlyLinks: true,
showCommentImages: true,
showCollapsed: false,
+ rememberCommunitySort: false,
},
posts: {
sort: "Active",
@@ -483,10 +485,15 @@ export const appearanceSlice = createSlice({
db.setSetting("upvote_on_save", action.payload);
},
- setRememberCommunitySort(state, action: PayloadAction) {
+ setRememberCommunityPostSort(state, action: PayloadAction) {
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) {
+ state.general.comments.rememberCommunitySort = action.payload;
+
+ db.setSetting("remember_community_comment_sort", action.payload);
},
setAutoplayMedia(state, action: PayloadAction) {
state.general.posts.autoplayMedia = action.payload;
@@ -673,8 +680,11 @@ export const fetchSettingsFromDatabase = createAsyncThunk(
);
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(
@@ -787,6 +797,9 @@ export const fetchSettingsFromDatabase = createAsyncThunk(
showCollapsed:
show_collapsed_comment ??
initialState.general.comments.showCollapsed,
+ rememberCommunitySort:
+ remember_community_comment_sort ??
+ initialState.general.comments.rememberCommunitySort,
},
posts: {
disableMarkingRead:
@@ -813,7 +826,7 @@ export const fetchSettingsFromDatabase = createAsyncThunk(
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,
@@ -893,7 +906,8 @@ export const {
setDisableAutoHideInCommunities,
setInfiniteScrolling,
setUpvoteOnSave,
- setRememberCommunitySort,
+ setRememberCommunityPostSort,
+ setRememberCommunityCommentSort,
setAutoplayMedia,
setTheme,
setEnableHapticFeedback,
diff --git a/src/routes/pages/posts/PostPage.tsx b/src/routes/pages/posts/PostPage.tsx
index 7061841ff..e6c9fb626 100644
--- a/src/routes/pages/posts/PostPage.tsx
+++ b/src/routes/pages/posts/PostPage.tsx
@@ -14,9 +14,8 @@ import {
import { useAppDispatch, useAppSelector } from "../../../store";
import { useParams } from "react-router";
import { styled } from "@linaria/react";
-import React, { memo, useCallback, useEffect, useState } from "react";
+import React, { memo, useCallback, useEffect } from "react";
import { getPost } from "../../../features/post/postSlice";
-import { CommentSortType } from "lemmy-js-client";
import { useBuildGeneralBrowseLink } from "../../../helpers/routes";
import CommentSort from "../../../features/comment/CommentSort";
import MoreActions from "../../../features/post/shared/MoreActions";
@@ -28,6 +27,8 @@ import MoreModActions from "../../../features/post/shared/MoreModAction";
import { useSetActivePage } from "../../../features/auth/AppContext";
import { useRef } from "react";
import AppHeader from "../../../features/shared/AppHeader";
+import useSortByFeed from "../../../features/feed/sort/useFeedSort";
+import { getRemoteHandleFromHandle } from "../../../helpers/lemmy";
export const CenteredSpinner = styled(IonSpinner)`
position: relative;
@@ -74,10 +75,16 @@ const PostPageContent = memo(function PostPageContent({
const post = useAppSelector((state) => state.post.postById[id]);
const client = useClient();
const dispatch = useAppDispatch();
- const defaultSort = useAppSelector(
- (state) => state.settings.general.comments.sort,
+
+ const connectedInstance = useAppSelector(
+ (state) => state.auth.connectedInstance,
);
- const [sort, setSort] = useState(defaultSort);
+ const [sort, setSort] = useSortByFeed("comments", {
+ remoteCommunityHandle: getRemoteHandleFromHandle(
+ community,
+ connectedInstance,
+ ),
+ });
const postDeletedById = useAppSelector((state) => state.post.postDeletedById);
const postIfFound = typeof post === "object" ? post : undefined;
@@ -135,6 +142,8 @@ const PostPageContent = memo(function PostPageContent({
Post not found
,
);
+ if (!sort) return;
+
return (
();
const buildGeneralBrowseLink = useBuildGeneralBrowseLink();
const client = useClient();
- const [sort, setSort] = useFeedSort();
+ const [sort, setSort] = useSortByFeed("posts");
const search = decodeURIComponent(_encodedSearch);
diff --git a/src/routes/pages/search/results/SearchFeedResultsPage.tsx b/src/routes/pages/search/results/SearchFeedResultsPage.tsx
index 20806ad4c..c3aa85a67 100644
--- a/src/routes/pages/search/results/SearchFeedResultsPage.tsx
+++ b/src/routes/pages/search/results/SearchFeedResultsPage.tsx
@@ -20,7 +20,7 @@ import { receivedPosts } from "../../../../features/post/postSlice";
import { receivedComments } from "../../../../features/comment/commentSlice";
import FeedContent from "../../shared/FeedContent";
import { getSortDuration } from "../../../../features/feed/endItems/EndPost";
-import useFeedSort from "../../../../features/feed/sort/useFeedSort";
+import useSortByFeed from "../../../../features/feed/sort/useFeedSort";
import AppHeader from "../../../../features/shared/AppHeader";
interface SearchPostsResultsProps {
@@ -37,7 +37,7 @@ export default function SearchFeedResultsPage({
}>();
const buildGeneralBrowseLink = useBuildGeneralBrowseLink();
const client = useClient();
- const [sort, setSort] = useFeedSort();
+ const [sort, setSort] = useSortByFeed("posts");
const search = decodeURIComponent(_encodedSearch);
diff --git a/src/routes/pages/shared/CommunityPage.tsx b/src/routes/pages/shared/CommunityPage.tsx
index 55d559bea..24ed3d0ba 100644
--- a/src/routes/pages/shared/CommunityPage.tsx
+++ b/src/routes/pages/shared/CommunityPage.tsx
@@ -34,7 +34,7 @@ import CommunitySearchResults from "../../../features/community/search/Community
import { getSortDuration } from "../../../features/feed/endItems/EndPost";
import ModActions from "../../../features/community/mod/ModActions";
import { useOptimizedIonRouter } from "../../../helpers/useOptimizedIonRouter";
-import useFeedSort from "../../../features/feed/sort/useFeedSort";
+import useSortByFeed from "../../../features/feed/sort/useFeedSort";
import { CenteredSpinner } from "../posts/PostPage";
import { getRemoteHandleFromHandle } from "../../../helpers/lemmy";
import { useAppSelector } from "../../../store";
@@ -155,7 +155,7 @@ const CommunityPageContent = memo(function CommunityPageContent({
(state) => state.settings.general.posts.showHiddenInCommunities,
);
- const [sort, setSort] = useFeedSort({
+ const [sort, setSort] = useSortByFeed("posts", {
remoteCommunityHandle: getRemoteHandleFromHandle(
community,
connectedInstance,
diff --git a/src/routes/pages/shared/SpecialFeedPage.tsx b/src/routes/pages/shared/SpecialFeedPage.tsx
index 5d3a212b1..bd367de84 100644
--- a/src/routes/pages/shared/SpecialFeedPage.tsx
+++ b/src/routes/pages/shared/SpecialFeedPage.tsx
@@ -22,7 +22,7 @@ import { followIdsSelector } from "../../../features/auth/siteSlice";
import { getHandle } from "../../../helpers/lemmy";
import { CenteredSpinner } from "../posts/PostPage";
import ModActions from "../../../features/community/mod/ModActions";
-import useFeedSort from "../../../features/feed/sort/useFeedSort";
+import useSortByFeed from "../../../features/feed/sort/useFeedSort";
import { PageTypeContext } from "../../../features/feed/PageTypeContext";
import AppHeader from "../../../features/shared/AppHeader";
@@ -34,7 +34,7 @@ export default function SpecialFeedPage({ type }: SpecialFeedProps) {
const buildGeneralBrowseLink = useBuildGeneralBrowseLink();
const client = useClient();
- const [sort, setSort] = useFeedSort({ listingType: type });
+ const [sort, setSort] = useSortByFeed("posts", { listingType: type });
const followIds = useAppSelector(followIdsSelector);
const communityByHandle = useAppSelector(
diff --git a/src/services/db.ts b/src/services/db.ts
index b886ee4cb..6e8950f66 100644
--- a/src/services/db.ts
+++ b/src/services/db.ts
@@ -306,6 +306,7 @@ export type SettingValueTypes = {
favorite_communities: string[];
migration_links: string[];
default_comment_sort: CommentDefaultSort;
+ default_comment_sort_by_feed: CommentDefaultSort;
disable_marking_posts_read: boolean;
mark_read_on_scroll: boolean;
show_hide_read_button: boolean;
@@ -338,7 +339,8 @@ export type SettingValueTypes = {
upvote_on_save: boolean;
default_post_sort: SortType;
default_post_sort_by_feed: SortType;
- remember_community_sort: boolean;
+ remember_community_post_sort: boolean;
+ remember_community_comment_sort: boolean;
embed_crossposts: boolean;
show_community_icons: boolean;
autoplay_media: AutoplayMediaType;
@@ -502,6 +504,13 @@ export class WefwefDB extends Dexie {
data
`,
});
+
+ this.version(8).upgrade(async () => {
+ await this.settings
+ .where("key")
+ .equals("remember_community_sort")
+ .modify({ key: "remember_community_post_sort" });
+ });
}
/*
From 0e10348025a945e76bc26837491b907407fc2ec6 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 17:32:46 -0500
Subject: [PATCH 05/11] Cleanup function definition
---
src/features/feed/sort/useFeedSort.tsx | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/features/feed/sort/useFeedSort.tsx b/src/features/feed/sort/useFeedSort.tsx
index 99a88958b..7a53d7af6 100644
--- a/src/features/feed/sort/useFeedSort.tsx
+++ b/src/features/feed/sort/useFeedSort.tsx
@@ -9,15 +9,15 @@ import {
setFeedSort,
} from "./feedSortSlice";
-type SortTypeByContext = {
- posts: SortType;
- comments: CommentSortType;
-};
+export default function useSortByFeed(
+ context: Context,
+ feed?: FeedSortFeed | undefined,
+) {
+ type Sort = {
+ posts: SortType;
+ comments: CommentSortType;
+ }[Context];
-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, context),
From ddf7600196b5422dbee443f0158731a10c0394c4 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 17:42:41 -0500
Subject: [PATCH 06/11] Fix cancel button on compose new private message alert
(#1467)
Fixes #1466
---
src/routes/pages/inbox/ComposeButton.tsx | 47 +++++++++++++-----------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/src/routes/pages/inbox/ComposeButton.tsx b/src/routes/pages/inbox/ComposeButton.tsx
index 205f44150..64b75a745 100644
--- a/src/routes/pages/inbox/ComposeButton.tsx
+++ b/src/routes/pages/inbox/ComposeButton.tsx
@@ -1,4 +1,4 @@
-import { IonAlert, IonButton, IonIcon, IonLoading } from "@ionic/react";
+import { IonButton, IonIcon, IonLoading, useIonAlert } from "@ionic/react";
import { createOutline } from "ionicons/icons";
import { useState } from "react";
import { useAppDispatch } from "../../../store";
@@ -10,10 +10,10 @@ import { isLemmyError } from "../../../helpers/lemmyErrors";
export default function ComposeButton() {
const [loading, setLoading] = useState(false);
- const [isAlertOpen, setIsAlertOpen] = useState(false);
const router = useOptimizedIonRouter();
const dispatch = useAppDispatch();
const presentToast = useAppToast();
+ const [presentAlert] = useIonAlert();
async function composeNew(handle: string) {
setLoading(true);
@@ -38,28 +38,33 @@ export default function ComposeButton() {
router.push(`/inbox/messages/${getHandle(user.person_view.person)}`);
}
+ function present() {
+ presentAlert({
+ header: "Compose new message",
+ inputs: [
+ {
+ name: "handle",
+ placeholder: "user@instance",
+ },
+ ],
+ buttons: [
+ {
+ text: "OK",
+ handler: (e) => {
+ if (!e.handle) return;
+
+ composeNew(e.handle);
+ },
+ },
+ { text: "Cancel", role: "cancel" },
+ ],
+ });
+ }
+
return (
<>
- {
- setIsAlertOpen(false);
-
- if (!e.detail.data) return;
-
- composeNew(e.detail.data.values.handle);
- }}
- inputs={[
- {
- name: "handle",
- placeholder: "user@instance",
- },
- ]}
- buttons={[{ text: "OK" }, { text: "Cancel", role: "cancel" }]}
- />
- setIsAlertOpen(true)}>
+
>
From 11e04fe930e23c3f69ac09a4b079ad71619501a2 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 17:52:58 -0500
Subject: [PATCH 07/11] (chore) Simplify native onboarding, install @ionic/cli
to dev deps (#1468)
---
CONTRIBUTING.md | 26 ++--
package.json | 1 +
pnpm-lock.yaml | 400 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 413 insertions(+), 14 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3c901342f..1d9c6f1bb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -49,37 +49,35 @@ pnpm run dev
If the feature you're working on is native-only, you can compile and run Voyager in an iOS Simulator or real device.
-To build the iOS native app:
+To build the iOS native app, install:
-1. Install [Node](https://nodejs.org/en)
-2. Install [Ionic CLI](https://ionicframework.com/docs/cli)
-3. Install [Xcode](https://developer.apple.com/xcode/)
-4. [Cocoapods](https://cocoapods.org/)
+1. [Node](https://nodejs.org)
+2. [Xcode](https://developer.apple.com/xcode/)
+3. [Cocoapods](https://cocoapods.org)
-Then, build the project and copy web dependencies over:
+Then, in Voyager's source code directory, build the project:
```sh
corepack enable
pnpm install
-ionic capacitor build ios
+pnpm exec ionic capacitor build ios
```
-Finally, can run the project with `CMD+R`.
+Xcode should automatically open. You can then run the project with `CMD+R`.
### Android Native App
-To build the Android native app:
+To build the Android native app, install:
-1. Install [Node](https://nodejs.org/en)
-2. Install [Ionic CLI](https://ionicframework.com/docs/cli)
-3. Install [Android Studio](https://developer.android.com/studio)
+1. [Node](https://nodejs.org)
+2. [Android Studio](https://developer.android.com/studio)
-In Voyager source code directory:
+Then, in Voyager's source code directory, build the project:
```sh
corepack enable
pnpm install
-ionic capacitor build android
+pnpm exec ionic capacitor build android
```
Android Studio should open.
diff --git a/package.json b/package.json
index b54691123..a9410ee87 100644
--- a/package.json
+++ b/package.json
@@ -113,6 +113,7 @@
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@capacitor/cli": "^6.0.0",
+ "@ionic/cli": "^7.2.0",
"@playwright/test": "^1.43.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^15.0.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1984ff407..5b6d88127 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -260,6 +260,9 @@ importers:
'@capacitor/cli':
specifier: ^6.0.0
version: 6.0.0
+ '@ionic/cli':
+ specifier: ^7.2.0
+ version: 7.2.0
'@playwright/test':
specifier: ^1.43.0
version: 1.43.1
@@ -1430,6 +1433,19 @@ packages:
resolution: {integrity: sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==}
engines: {node: '>=16.0.0'}
+ '@ionic/cli-framework-prompts@2.1.13':
+ resolution: {integrity: sha512-Yj1fz6p7OehreQ8C70bd9+M6tYP/rvzLw5JVj8pT/N9s0kQSjqEFRbs96LKr3lfd3TADZaS8OlZrQIqenFIUpg==}
+ engines: {node: '>=16.0.0'}
+
+ '@ionic/cli-framework@6.0.1':
+ resolution: {integrity: sha512-Fyix4eQt2HKTV+GoeoiziQGZyqIA8RfoMqjGyAS5XgNXLOYW0P27Ph348hQZh9Mphjf+m0lOYa6dWQTEPzUHiQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@ionic/cli@7.2.0':
+ resolution: {integrity: sha512-IEms9Df8mJOoWPqgvZEXmqKztttHDFAz+9ewDPZGYv8Xx66Cj7zSen13O2Vf4FuLXhl+U95HXT9sAs4lDwFmcQ==}
+ engines: {node: '>=16.0.0'}
+ hasBin: true
+
'@ionic/react-router@8.1.0':
resolution: {integrity: sha512-2f1OHS+1Dgeb7reh7OObl+IzbWzaZOO7IoVPAOg+HbmzzRA3Z/dMi89Mw+xnajOYfhXNPoRSzqYUqWD4OXqi0A==}
peerDependencies:
@@ -1460,6 +1476,10 @@ packages:
resolution: {integrity: sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==}
engines: {node: '>=16.0.0'}
+ '@ionic/utils-network@2.1.7':
+ resolution: {integrity: sha512-5Q3NdZtSLiLs7ufuX9X293BvAwo8CxaD93Hkp3ODPgctLYErv3nFibhq3j+eguEqUh2um9WNXEUOuQ8x+Sd1fw==}
+ engines: {node: '>=16.0.0'}
+
'@ionic/utils-object@2.1.5':
resolution: {integrity: sha512-XnYNSwfewUqxq+yjER1hxTKggftpNjFLJH0s37jcrNDwbzmbpFTQTVAp4ikNK4rd9DOebX/jbeZb8jfD86IYxw==}
engines: {node: '>=10.3.0'}
@@ -1488,6 +1508,10 @@ packages:
resolution: {integrity: sha512-4+Kitey1lTA1yGtnigeYNhV/0tggI3lWBMjC7tBs1K9GXa/q7q4CtOISppdh8QgtOhrhAXS2Igp8rbko/Cj+lA==}
engines: {node: '>=16.0.0'}
+ '@ionic/utils-stream@3.1.7':
+ resolution: {integrity: sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==}
+ engines: {node: '>=16.0.0'}
+
'@ionic/utils-subprocess@2.1.11':
resolution: {integrity: sha512-6zCDixNmZCbMCy5np8klSxOZF85kuDyzZSTTQKQP90ZtYNCcPYmuFSzaqDwApJT4r5L3MY3JrqK1gLkc6xiUPw==}
engines: {node: '>=10.3.0'}
@@ -1496,6 +1520,10 @@ packages:
resolution: {integrity: sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==}
engines: {node: '>=16.0.0'}
+ '@ionic/utils-subprocess@3.0.1':
+ resolution: {integrity: sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==}
+ engines: {node: '>=16.0.0'}
+
'@ionic/utils-terminal@2.3.3':
resolution: {integrity: sha512-RnuSfNZ5fLEyX3R5mtcMY97cGD1A0NVBbarsSQ6yMMfRJ5YHU7hHVyUfvZeClbqkBC/pAqI/rYJuXKCT9YeMCQ==}
engines: {node: '>=10.3.0'}
@@ -2842,6 +2870,10 @@ packages:
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
engines: {node: '>=6'}
+ cli-width@3.0.0:
+ resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
+ engines: {node: '>= 10'}
+
cli-width@4.1.0:
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
engines: {node: '>= 12'}
@@ -2916,6 +2948,9 @@ packages:
compare-versions@6.1.0:
resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==}
+ component-emitter@1.3.1:
+ resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
+
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@@ -3002,6 +3037,9 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookiejar@2.1.4:
+ resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==}
+
core-js-compat@3.37.0:
resolution: {integrity: sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==}
@@ -3312,6 +3350,9 @@ packages:
resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
engines: {node: '>=10'}
+ duplexer2@0.1.4:
+ resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
+
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@@ -3515,6 +3556,10 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ execa@4.1.0:
+ resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
+ engines: {node: '>=10'}
+
execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
@@ -3566,6 +3611,9 @@ packages:
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ fast-safe-stringify@2.1.1:
+ resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
+
fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
@@ -3579,6 +3627,10 @@ packages:
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
engines: {node: ^12.20 || >= 14.13}
+ figures@3.2.0:
+ resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
+ engines: {node: '>=8'}
+
file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@@ -3636,6 +3688,9 @@ packages:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
+ formidable@2.1.2:
+ resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==}
+
formidable@3.5.1:
resolution: {integrity: sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==}
@@ -3990,6 +4045,10 @@ packages:
resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==}
engines: {node: '>= 14'}
+ human-signals@1.1.1:
+ resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==}
+ engines: {node: '>=8.12.0'}
+
human-signals@2.1.0:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
@@ -4062,6 +4121,10 @@ packages:
inline-style-parser@0.2.3:
resolution: {integrity: sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==}
+ inquirer@7.3.3:
+ resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==}
+ engines: {node: '>=8.0.0'}
+
inquirer@9.2.19:
resolution: {integrity: sha512-WpxOT71HGsFya6/mj5PUue0sWwbpbiPfAR+332zLj/siB0QA1PZM8v3GepegFV1Op189UxHUCF6y8AySdtOMVA==}
engines: {node: '>=18'}
@@ -4531,6 +4594,9 @@ packages:
resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==}
engines: {node: '>=14.16'}
+ leek@0.0.24:
+ resolution: {integrity: sha512-6PVFIYXxlYF0o6hrAsHtGpTmi06otkwNrMcmQ0K96SeSRHPREPa9J3nJZ1frliVH7XT0XFswoJFQoXsDukzGNQ==}
+
lemmy-js-client@0.19.4-alpha.18:
resolution: {integrity: sha512-CUKRIiINZF2zOfK5WzBDF071LjMmRBFHwiSYBMGJyQP1zu8sPKCb/ptg25WWrf79Y4uOaVLctgHg3oEUXmSUmQ==}
@@ -4572,6 +4638,27 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ lodash._baseassign@3.2.0:
+ resolution: {integrity: sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ==}
+
+ lodash._basecopy@3.0.1:
+ resolution: {integrity: sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==}
+
+ lodash._bindcallback@3.0.1:
+ resolution: {integrity: sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==}
+
+ lodash._createassigner@3.1.1:
+ resolution: {integrity: sha512-LziVL7IDnJjQeeV95Wvhw6G28Z8Q6da87LWKOPWmzBLv4u6FAT/x5v00pyGW0u38UoogNF2JnD3bGgZZDaNEBw==}
+
+ lodash._getnative@3.9.1:
+ resolution: {integrity: sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==}
+
+ lodash._isiterateecall@3.0.9:
+ resolution: {integrity: sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==}
+
+ lodash.assign@3.2.0:
+ resolution: {integrity: sha512-/VVxzgGBmbphasTg51FrztxQJ/VgAUpol6zmJuSVSGcNg4g7FA4z7rQV8Ovr9V3vFBNWZhvKWHfpAytjTVUfFA==}
+
lodash.capitalize@4.2.1:
resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==}
@@ -4581,6 +4668,12 @@ packages:
lodash.escaperegexp@4.1.2:
resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==}
+ lodash.isarguments@3.1.0:
+ resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
+
+ lodash.isarray@3.0.4:
+ resolution: {integrity: sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==}
+
lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
@@ -4593,9 +4686,15 @@ packages:
lodash.isstring@4.0.1:
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+ lodash.keys@3.1.2:
+ resolution: {integrity: sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==}
+
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ lodash.restparam@3.6.1:
+ resolution: {integrity: sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==}
+
lodash.sortby@4.7.0:
resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
@@ -4655,6 +4754,10 @@ packages:
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
hasBin: true
+ macos-release@2.5.1:
+ resolution: {integrity: sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==}
+ engines: {node: '>=6'}
+
macos-release@3.2.0:
resolution: {integrity: sha512-fSErXALFNsnowREYZ49XCdOHF8wOPWuFOGQrAhP7x5J/BqQv+B02cNsTykGpDgRVx43EKg++6ANmTaGTtW+hUA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -4759,6 +4862,10 @@ packages:
mergexml@1.2.4:
resolution: {integrity: sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==}
+ methods@1.1.2:
+ resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
+ engines: {node: '>= 0.6'}
+
micromark-core-commonmark@2.0.0:
resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==}
@@ -4858,6 +4965,11 @@ packages:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mime@2.6.0:
+ resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
+ engines: {node: '>=4.0.0'}
+ hasBin: true
+
mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
@@ -4954,6 +5066,9 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ mute-stream@0.0.8:
+ resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
+
mute-stream@1.0.0:
resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
@@ -5131,6 +5246,10 @@ packages:
resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==}
engines: {node: '>=18'}
+ open@7.4.2:
+ resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==}
+ engines: {node: '>=8'}
+
open@8.4.2:
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
engines: {node: '>=12'}
@@ -5147,6 +5266,10 @@ packages:
resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==}
engines: {node: '>=18'}
+ os-name@4.0.1:
+ resolution: {integrity: sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==}
+ engines: {node: '>=10'}
+
os-name@5.1.0:
resolution: {integrity: sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -5451,6 +5574,10 @@ packages:
resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==}
engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
+ qs@6.12.1:
+ resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+ engines: {node: '>=0.6'}
+
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
@@ -5775,10 +5902,18 @@ packages:
rrweb-cssom@0.6.0:
resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
+ rsvp@3.6.2:
+ resolution: {integrity: sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==}
+ engines: {node: 0.12.* || 4.* || 6.* || >= 7.*}
+
run-applescript@7.0.0:
resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==}
engines: {node: '>=18'}
+ run-async@2.4.1:
+ resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
+ engines: {node: '>=0.12.0'}
+
run-async@3.0.0:
resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==}
engines: {node: '>=0.12.0'}
@@ -5786,6 +5921,10 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ rxjs@6.6.7:
+ resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==}
+ engines: {npm: '>=2.0.0'}
+
rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
@@ -5988,6 +6127,9 @@ packages:
sprintf-js@1.1.3:
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
+ ssh-config@1.1.6:
+ resolution: {integrity: sha512-ZPO9rECxzs5JIQ6G/2EfL1I9ho/BVZkx9HRKn8+0af7QgwAmumQ7XBFP1ggMyPMo+/tUbmv0HFdv4qifdO/9JA==}
+
stack-utils@2.0.6:
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
engines: {node: '>=10'}
@@ -6010,6 +6152,9 @@ packages:
resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==}
engines: {node: '>= 0.10.0'}
+ stream-combiner2@1.1.1:
+ resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==}
+
streamx@2.16.1:
resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==}
@@ -6098,6 +6243,11 @@ packages:
stylis@4.3.2:
resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==}
+ superagent@8.1.2:
+ resolution: {integrity: sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==}
+ engines: {node: '>=6.4.0 <13 || >=14'}
+ deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net
+
supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@@ -6273,6 +6423,9 @@ packages:
'@swc/wasm':
optional: true
+ tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
@@ -6737,6 +6890,10 @@ packages:
wildcard-match@5.1.3:
resolution: {integrity: sha512-a95hPUk+BNzSGLntNXYxsjz2Hooi5oL7xOfJR6CKwSsSALh7vUNuTlzsrZowtYy38JNduYFRVhFv19ocqNOZlg==}
+ windows-release@4.0.0:
+ resolution: {integrity: sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==}
+ engines: {node: '>=10'}
+
windows-release@5.1.1:
resolution: {integrity: sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -8673,6 +8830,66 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@ionic/cli-framework-prompts@2.1.13':
+ dependencies:
+ '@ionic/utils-terminal': 2.3.5
+ debug: 4.3.4(supports-color@8.1.1)
+ inquirer: 7.3.3
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@ionic/cli-framework@6.0.1':
+ dependencies:
+ '@ionic/cli-framework-output': 2.2.8
+ '@ionic/utils-array': 2.1.6
+ '@ionic/utils-fs': 3.1.7
+ '@ionic/utils-object': 2.1.6
+ '@ionic/utils-process': 2.1.12
+ '@ionic/utils-stream': 3.1.7
+ '@ionic/utils-subprocess': 3.0.1
+ '@ionic/utils-terminal': 2.3.5
+ chalk: 4.1.2
+ debug: 4.3.4(supports-color@8.1.1)
+ lodash: 4.17.21
+ minimist: 1.2.8
+ rimraf: 3.0.2
+ tslib: 2.6.2
+ write-file-atomic: 3.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@ionic/cli@7.2.0':
+ dependencies:
+ '@ionic/cli-framework': 6.0.1
+ '@ionic/cli-framework-output': 2.2.8
+ '@ionic/cli-framework-prompts': 2.1.13
+ '@ionic/utils-array': 2.1.6
+ '@ionic/utils-fs': 3.1.7
+ '@ionic/utils-network': 2.1.7
+ '@ionic/utils-process': 2.1.12
+ '@ionic/utils-stream': 3.1.7
+ '@ionic/utils-subprocess': 3.0.1
+ '@ionic/utils-terminal': 2.3.5
+ chalk: 4.1.2
+ debug: 4.3.4(supports-color@8.1.1)
+ diff: 4.0.2
+ elementtree: 0.1.7
+ leek: 0.0.24
+ lodash: 4.17.21
+ open: 7.4.2
+ os-name: 4.0.1
+ proxy-agent: 6.4.0
+ semver: 7.6.0
+ split2: 3.2.2
+ ssh-config: 1.1.6
+ stream-combiner2: 1.1.1
+ superagent: 8.1.2
+ tar: 6.2.1
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
'@ionic/react-router@8.1.0(react-dom@18.3.1(react@18.3.1))(react-router-dom@5.3.4(react@18.3.1))(react-router@5.3.4(react@18.3.1))(react@18.3.1)':
dependencies:
'@ionic/react': 8.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -8722,6 +8939,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@ionic/utils-network@2.1.7':
+ dependencies:
+ debug: 4.3.4(supports-color@8.1.1)
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
'@ionic/utils-object@2.1.5':
dependencies:
debug: 4.3.4(supports-color@8.1.1)
@@ -8783,6 +9007,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@ionic/utils-stream@3.1.7':
+ dependencies:
+ debug: 4.3.4(supports-color@8.1.1)
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
'@ionic/utils-subprocess@2.1.11':
dependencies:
'@ionic/utils-array': 2.1.5
@@ -8809,6 +9040,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@ionic/utils-subprocess@3.0.1':
+ dependencies:
+ '@ionic/utils-array': 2.1.6
+ '@ionic/utils-fs': 3.1.7
+ '@ionic/utils-process': 2.1.12
+ '@ionic/utils-stream': 3.1.7
+ '@ionic/utils-terminal': 2.3.5
+ cross-spawn: 7.0.3
+ debug: 4.3.4(supports-color@8.1.1)
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
'@ionic/utils-terminal@2.3.3':
dependencies:
'@types/slice-ansi': 4.0.0
@@ -10486,6 +10730,8 @@ snapshots:
cli-spinners@2.9.2: {}
+ cli-width@3.0.0: {}
+
cli-width@4.1.0: {}
cliui@6.0.0:
@@ -10555,6 +10801,8 @@ snapshots:
compare-versions@6.1.0: {}
+ component-emitter@1.3.1: {}
+
concat-map@0.0.1: {}
condense-newlines@0.2.1:
@@ -10681,6 +10929,8 @@ snapshots:
convert-source-map@2.0.0: {}
+ cookiejar@2.1.4: {}
+
core-js-compat@3.37.0:
dependencies:
browserslist: 4.23.0
@@ -10985,6 +11235,10 @@ snapshots:
dependencies:
is-obj: 2.0.0
+ duplexer2@0.1.4:
+ dependencies:
+ readable-stream: 2.3.8
+
eastasianwidth@0.2.0: {}
editorconfig@1.0.4:
@@ -11297,6 +11551,18 @@ snapshots:
esutils@2.0.3: {}
+ execa@4.1.0:
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 5.2.0
+ human-signals: 1.1.1
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
execa@5.1.1:
dependencies:
cross-spawn: 7.0.3
@@ -11371,6 +11637,8 @@ snapshots:
fast-levenshtein@2.0.6: {}
+ fast-safe-stringify@2.1.1: {}
+
fastq@1.17.1:
dependencies:
reusify: 1.0.4
@@ -11388,6 +11656,10 @@ snapshots:
node-domexception: 1.0.0
web-streams-polyfill: 3.3.3
+ figures@3.2.0:
+ dependencies:
+ escape-string-regexp: 1.0.5
+
file-entry-cache@6.0.1:
dependencies:
flat-cache: 3.2.0
@@ -11453,6 +11725,13 @@ snapshots:
dependencies:
fetch-blob: 3.2.0
+ formidable@2.1.2:
+ dependencies:
+ dezalgo: 1.0.4
+ hexoid: 1.0.0
+ once: 1.4.0
+ qs: 6.12.1
+
formidable@3.5.1:
dependencies:
dezalgo: 1.0.4
@@ -11980,6 +12259,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ human-signals@1.1.1: {}
+
human-signals@2.1.0: {}
human-signals@5.0.0: {}
@@ -12030,6 +12311,22 @@ snapshots:
inline-style-parser@0.2.3: {}
+ inquirer@7.3.3:
+ dependencies:
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ cli-cursor: 3.1.0
+ cli-width: 3.0.0
+ external-editor: 3.1.0
+ figures: 3.2.0
+ lodash: 4.17.21
+ mute-stream: 0.0.8
+ run-async: 2.4.1
+ rxjs: 6.6.7
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ through: 2.3.8
+
inquirer@9.2.19:
dependencies:
'@inquirer/figures': 1.0.1
@@ -12483,6 +12780,14 @@ snapshots:
dependencies:
package-json: 8.1.1
+ leek@0.0.24:
+ dependencies:
+ debug: 2.6.9
+ lodash.assign: 3.2.0
+ rsvp: 3.6.2
+ transitivePeerDependencies:
+ - supports-color
+
lemmy-js-client@0.19.4-alpha.18: {}
leven@3.1.0: {}
@@ -12534,12 +12839,41 @@ snapshots:
dependencies:
p-locate: 5.0.0
+ lodash._baseassign@3.2.0:
+ dependencies:
+ lodash._basecopy: 3.0.1
+ lodash.keys: 3.1.2
+
+ lodash._basecopy@3.0.1: {}
+
+ lodash._bindcallback@3.0.1: {}
+
+ lodash._createassigner@3.1.1:
+ dependencies:
+ lodash._bindcallback: 3.0.1
+ lodash._isiterateecall: 3.0.9
+ lodash.restparam: 3.6.1
+
+ lodash._getnative@3.9.1: {}
+
+ lodash._isiterateecall@3.0.9: {}
+
+ lodash.assign@3.2.0:
+ dependencies:
+ lodash._baseassign: 3.2.0
+ lodash._createassigner: 3.1.1
+ lodash.keys: 3.1.2
+
lodash.capitalize@4.2.1: {}
lodash.debounce@4.0.8: {}
lodash.escaperegexp@4.1.2: {}
+ lodash.isarguments@3.1.0: {}
+
+ lodash.isarray@3.0.4: {}
+
lodash.isequal@4.5.0: {}
lodash.ismatch@4.4.0: {}
@@ -12548,8 +12882,16 @@ snapshots:
lodash.isstring@4.0.1: {}
+ lodash.keys@3.1.2:
+ dependencies:
+ lodash._getnative: 3.9.1
+ lodash.isarguments: 3.1.0
+ lodash.isarray: 3.0.4
+
lodash.merge@4.6.2: {}
+ lodash.restparam@3.6.1: {}
+
lodash.sortby@4.7.0: {}
lodash.uniqby@4.7.0: {}
@@ -12604,6 +12946,8 @@ snapshots:
lz-string@1.5.0: {}
+ macos-release@2.5.1: {}
+
macos-release@3.2.0: {}
magic-string@0.25.9:
@@ -12842,6 +13186,8 @@ snapshots:
formidable: 3.5.1
xpath: 0.0.27
+ methods@1.1.2: {}
+
micromark-core-commonmark@2.0.0:
dependencies:
decode-named-character-reference: 1.0.2
@@ -13054,6 +13400,8 @@ snapshots:
dependencies:
mime-db: 1.52.0
+ mime@2.6.0: {}
+
mimic-fn@2.1.0: {}
mimic-fn@4.0.0: {}
@@ -13132,6 +13480,8 @@ snapshots:
ms@2.1.3: {}
+ mute-stream@0.0.8: {}
+
mute-stream@1.0.0: {}
nanoid@3.3.7: {}
@@ -13321,6 +13671,11 @@ snapshots:
is-inside-container: 1.0.0
is-wsl: 3.1.0
+ open@7.4.2:
+ dependencies:
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+
open@8.4.2:
dependencies:
define-lazy-prop: 2.0.0
@@ -13360,6 +13715,11 @@ snapshots:
string-width: 7.1.0
strip-ansi: 7.1.0
+ os-name@4.0.1:
+ dependencies:
+ macos-release: 2.5.1
+ windows-release: 4.0.0
+
os-name@5.1.0:
dependencies:
macos-release: 3.2.0
@@ -13707,6 +14067,10 @@ snapshots:
q@1.5.1: {}
+ qs@6.12.1:
+ dependencies:
+ side-channel: 1.0.6
+
querystringify@2.2.0: {}
queue-microtask@1.2.3: {}
@@ -14164,14 +14528,22 @@ snapshots:
rrweb-cssom@0.6.0: {}
+ rsvp@3.6.2: {}
+
run-applescript@7.0.0: {}
+ run-async@2.4.1: {}
+
run-async@3.0.0: {}
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
+ rxjs@6.6.7:
+ dependencies:
+ tslib: 1.14.1
+
rxjs@7.8.1:
dependencies:
tslib: 2.6.2
@@ -14382,6 +14754,8 @@ snapshots:
sprintf-js@1.1.3: {}
+ ssh-config@1.1.6: {}
+
stack-utils@2.0.6:
dependencies:
escape-string-regexp: 2.0.0
@@ -14398,6 +14772,11 @@ snapshots:
stream-buffers@2.2.0: {}
+ stream-combiner2@1.1.1:
+ dependencies:
+ duplexer2: 0.1.4
+ readable-stream: 2.3.8
+
streamx@2.16.1:
dependencies:
fast-fifo: 1.3.2
@@ -14510,6 +14889,21 @@ snapshots:
stylis@4.3.2: {}
+ superagent@8.1.2:
+ dependencies:
+ component-emitter: 1.3.1
+ cookiejar: 2.1.4
+ debug: 4.3.4(supports-color@8.1.1)
+ fast-safe-stringify: 2.1.1
+ form-data: 4.0.0
+ formidable: 2.1.2
+ methods: 1.1.2
+ mime: 2.6.0
+ qs: 6.12.1
+ semver: 7.6.0
+ transitivePeerDependencies:
+ - supports-color
+
supports-color@5.5.0:
dependencies:
has-flag: 3.0.0
@@ -14696,6 +15090,8 @@ snapshots:
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
+ tslib@1.14.1: {}
+
tslib@2.6.2: {}
tunnel-agent@0.6.0:
@@ -15200,6 +15596,10 @@ snapshots:
wildcard-match@5.1.3: {}
+ windows-release@4.0.0:
+ dependencies:
+ execa: 4.1.0
+
windows-release@5.1.1:
dependencies:
execa: 5.1.1
From 5b44f012f5db57a9e525382c99198d6d5a51c21b Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 19:25:04 -0500
Subject: [PATCH 08/11] (chore) Remove unused tsconfig.node.json (#1469)
---
Dockerfile | 2 +-
tsconfig.json | 3 +--
tsconfig.node.json | 9 ---------
3 files changed, 2 insertions(+), 12 deletions(-)
delete mode 100644 tsconfig.node.json
diff --git a/Dockerfile b/Dockerfile
index b90f0b7c2..956285fff 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,7 +26,7 @@ COPY patches ./patches
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --ignore-scripts
# Copy all source files
-COPY build.sh disable_in_app_purchases.sh index.html vite.config.ts manifest.json tsconfig.json tsconfig.node.json ./
+COPY build.sh disable_in_app_purchases.sh index.html vite.config.ts manifest.json tsconfig.json ./
COPY public ./public
COPY src ./src
diff --git a/tsconfig.json b/tsconfig.json
index 78cfa1a50..269ab3e73 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -18,6 +18,5 @@
"types": ["vite-plugin-svgr/client", "jest"],
"noUncheckedIndexedAccess": true
},
- "include": ["src"],
- "references": [{ "path": "./tsconfig.node.json" }]
+ "include": ["src"]
}
diff --git a/tsconfig.node.json b/tsconfig.node.json
deleted file mode 100644
index 9d31e2aed..000000000
--- a/tsconfig.node.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "compilerOptions": {
- "composite": true,
- "module": "ESNext",
- "moduleResolution": "Node",
- "allowSyntheticDefaultImports": true
- },
- "include": ["vite.config.ts"]
-}
From 6a9860ac25aeba6522caf90b5b9a030177c115de Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 19:32:39 -0500
Subject: [PATCH 09/11] Release 2.9.0
---
android/app/build.gradle | 4 ++--
ios/App/App/Info.plist | 4 ++--
package.json | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 007ffc9a2..9a9b898d3 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -7,8 +7,8 @@ android {
applicationId "app.vger.voyager"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 244
- versionName "2.8.1"
+ versionCode 245
+ versionName "2.9.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist
index 09b1ec7b5..e2ae4ea9b 100644
--- a/ios/App/App/Info.plist
+++ b/ios/App/App/Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 2.8.1
+ 2.9.0
CFBundleURLTypes
@@ -32,7 +32,7 @@
CFBundleVersion
- 244
+ 245
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/package.json b/package.json
index a9410ee87..dec23151c 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "voyager",
"description": "A progressive webapp Lemmy client",
"private": true,
- "version": "2.8.1",
+ "version": "2.9.0",
"type": "module",
"packageManager": "pnpm@9.0.6+sha256.0624e30eff866cdeb363b15061bdb7fd9425b17bc1bb42c22f5f4efdea21f6b3",
"scripts": {
From 2d46158f2bfc49fdb156e43533bc54cbcf887219 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 22:47:30 -0500
Subject: [PATCH 10/11] Fix DB failure causing post page to fail to load
(#1470)
---
src/features/feed/sort/useFeedSort.tsx | 39 +++++++++++++++-----------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/src/features/feed/sort/useFeedSort.tsx b/src/features/feed/sort/useFeedSort.tsx
index 7a53d7af6..3f0d6e094 100644
--- a/src/features/feed/sort/useFeedSort.tsx
+++ b/src/features/feed/sort/useFeedSort.tsx
@@ -1,5 +1,5 @@
import { CommentSortType, SortType } from "lemmy-js-client";
-import { useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { useAppDispatch, useAppSelector } from "../../../store";
import {
FeedSortFeed,
@@ -19,9 +19,11 @@ export default function useSortByFeed(
}[Context];
const dispatch = useAppDispatch();
- const feedSort = useAppSelector(
- getFeedSortSelectorBuilder(feed, context),
- ) as Sort;
+
+ const feedSort = useAppSelector(getFeedSortSelectorBuilder(feed, context)) as
+ | Sort
+ | null
+ | undefined;
const defaultSort = useAppSelector(
(state) => state.settings.general[context].sort,
) as Sort;
@@ -39,7 +41,7 @@ export default function useSortByFeed(
if (!feed) return;
try {
- await dispatch(getFeedSort({ feed, context }));
+ await dispatch(getFeedSort({ feed, context })).unwrap(); // unwrap to catch dispatched error (db failure)
} catch (error) {
_setSort((_sort) => _sort ?? defaultSort); // fallback if indexeddb unavailable
throw error;
@@ -55,19 +57,22 @@ export default function useSortByFeed(
_setSort(feedSort ?? defaultSort);
}, [feedSort, sort, defaultSort, rememberCommunitySort]);
- function setSort(sort: Sort) {
- if (rememberCommunitySort && feed) {
- dispatch(
- setFeedSort({
- feed,
- sort,
- context,
- } as SetSortActionPayload),
- );
- }
+ const setSort = useCallback(
+ (sort: Sort) => {
+ if (rememberCommunitySort && feed) {
+ dispatch(
+ setFeedSort({
+ feed,
+ sort,
+ context,
+ } as SetSortActionPayload),
+ );
+ }
- return _setSort(sort);
- }
+ return _setSort(sort);
+ },
+ [context, dispatch, feed, rememberCommunitySort],
+ );
return [sort, setSort] as const;
}
From beed4518e5e18d883a3ffd4f1ca1025485430485 Mon Sep 17 00:00:00 2001
From: Alexander Harding <2166114+aeharding@users.noreply.github.com>
Date: Thu, 9 May 2024 22:54:50 -0500
Subject: [PATCH 11/11] Release 2.9.1
---
android/app/build.gradle | 4 ++--
ios/App/App/Info.plist | 4 ++--
package.json | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9a9b898d3..3cb647aa3 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -7,8 +7,8 @@ android {
applicationId "app.vger.voyager"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 245
- versionName "2.9.0"
+ versionCode 246
+ versionName "2.9.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist
index e2ae4ea9b..33272ec7b 100644
--- a/ios/App/App/Info.plist
+++ b/ios/App/App/Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 2.9.0
+ 2.9.1
CFBundleURLTypes
@@ -32,7 +32,7 @@
CFBundleVersion
- 245
+ 246
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/package.json b/package.json
index dec23151c..431eb921a 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "voyager",
"description": "A progressive webapp Lemmy client",
"private": true,
- "version": "2.9.0",
+ "version": "2.9.1",
"type": "module",
"packageManager": "pnpm@9.0.6+sha256.0624e30eff866cdeb363b15061bdb7fd9425b17bc1bb42c22f5f4efdea21f6b3",
"scripts": {