From e58c5d3669d507a4e47b48eae6b7e7cd074d2d9c Mon Sep 17 00:00:00 2001 From: Alexander Harding <2166114+aeharding@users.noreply.github.com> Date: Sat, 10 Aug 2024 00:09:37 -0500 Subject: [PATCH 1/3] Add subscribed icon Resolves #504 --- src/features/labels/links/CommunityLink.tsx | 52 +++++++++++++++++-- src/features/labels/links/PersonLink.tsx | 1 + src/features/settings/general/other/Other.tsx | 2 + .../settings/general/other/SubscribedIcon.tsx | 24 +++++++++ src/features/settings/settingsSlice.tsx | 13 +++++ .../settings/shared/SettingSelector.tsx | 1 + src/routes/pages/shared/SpecialFeedPage.tsx | 21 ++++---- src/services/db.ts | 10 ++++ 8 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 src/features/settings/general/other/SubscribedIcon.tsx diff --git a/src/features/labels/links/CommunityLink.tsx b/src/features/labels/links/CommunityLink.tsx index 4ba9f41c4c..10b8282c78 100644 --- a/src/features/labels/links/CommunityLink.tsx +++ b/src/features/labels/links/CommunityLink.tsx @@ -4,16 +4,17 @@ import { Community, SubscribedType } from "lemmy-js-client"; import { renderHandle } from "../Handle"; import { LinkContainer, StyledLink, hideCss } from "./shared"; import ItemIcon from "../img/ItemIcon"; -import { useIonActionSheet } from "@ionic/react"; +import { IonIcon, useIonActionSheet } from "@ionic/react"; import { LongPressOptions, useLongPress } from "use-long-press"; import { + heart, heartDislikeOutline, heartOutline, removeCircleOutline, tabletPortraitOutline, } from "ionicons/icons"; import useCommunityActions from "../../community/useCommunityActions"; -import { useCallback, useContext } from "react"; +import { createContext, useCallback, useContext } from "react"; import { ShareImageContext } from "../../share/asImage/ShareAsImage"; import { preventOnClickNavigationBug, @@ -22,12 +23,28 @@ import { import { styled } from "@linaria/react"; import { cx } from "@linaria/core"; import { useAppSelector } from "../../../store"; +import { OShowSubscribedIcon } from "../../../services/db"; const StyledItemIcon = styled(ItemIcon)` margin-right: 0.4rem; vertical-align: middle; `; +const SubscribedIcon = styled(IonIcon)` + color: var(--ion-color-danger); + vertical-align: middle; + font-size: 0.85em; + + margin-bottom: 2px; + margin-left: 2px; + + opacity: 0.3; + + .ion-palette-dark & { + opacity: 0.5; + } +`; + interface CommunityLinkProps { community: Community; showInstanceWhenRemote?: boolean; @@ -55,6 +72,7 @@ export default function CommunityLink({ const showCommunityIcons = useAppSelector( (state) => state.settings.appearance.posts.showCommunityIcons, ); + const showSubscribed = useShowSubscribedIcon(); const { isSubscribed, isBlocked, subscribe, block, sidebar } = useCommunityActions(community, subscribed); @@ -106,6 +124,13 @@ export default function CommunityLink({ showInstanceWhenRemote, }); + const end = ( + <> + {instance} + {showSubscribed && isSubscribed && } + + ); + return ( {showCommunityIcons && !hideCommunity && !hideIcon && ( )} {name} - {!disableInstanceClick && instance} + {!disableInstanceClick && end} - {disableInstanceClick && instance} + {disableInstanceClick && end} ); } @@ -133,3 +159,21 @@ export default function CommunityLink({ const onStart: LongPressOptions["onStart"] = (e) => { e.stopPropagation(); }; + +function useShowSubscribedIcon() { + const feedEnabled = useContext(ShowSubscribedIconContext); + const subscribedIcon = useAppSelector( + (state) => state.settings.general.subscribedIcon, + ); + + switch (subscribedIcon) { + case OShowSubscribedIcon.OnlyAllLocal: + return feedEnabled; + case OShowSubscribedIcon.Never: + return false; + case OShowSubscribedIcon.Everywhere: + return true; + } +} + +export const ShowSubscribedIconContext = createContext(false); diff --git a/src/features/labels/links/PersonLink.tsx b/src/features/labels/links/PersonLink.tsx index be72e08e5a..6c52ce0ee3 100644 --- a/src/features/labels/links/PersonLink.tsx +++ b/src/features/labels/links/PersonLink.tsx @@ -148,6 +148,7 @@ export default function PersonLink({ e.stopPropagation(); preventOnClickNavigationBug(e); }} + draggable={false} > {prefix ? ( <> diff --git a/src/features/settings/general/other/Other.tsx b/src/features/settings/general/other/Other.tsx index 1664099bc6..a2acf6c6f6 100644 --- a/src/features/settings/general/other/Other.tsx +++ b/src/features/settings/general/other/Other.tsx @@ -9,6 +9,7 @@ import OpenNativeApps from "./OpenNativeApps"; import ClearCache from "./ClearCache"; import BackupSettings from "./backup/BackupSettings"; import Thumbnailinator from "./Thumbnailinator"; +import SubscribedIcon from "./SubscribedIcon"; export default function Other() { return ( @@ -24,6 +25,7 @@ export default function Other() { + diff --git a/src/features/settings/general/other/SubscribedIcon.tsx b/src/features/settings/general/other/SubscribedIcon.tsx new file mode 100644 index 0000000000..8bd3d7733b --- /dev/null +++ b/src/features/settings/general/other/SubscribedIcon.tsx @@ -0,0 +1,24 @@ +import { startCase } from "lodash"; +import { OShowSubscribedIcon } from "../../../../services/db"; +import { useAppSelector } from "../../../../store"; +import { setSubscribedIcon } from "../../settingsSlice"; +import SettingSelector from "../../shared/SettingSelector"; + +export default function SubscribedIcon() { + const subscribedIcon = useAppSelector( + (state) => state.settings.general.subscribedIcon, + ); + + return ( + { + if (option === OShowSubscribedIcon.OnlyAllLocal) return "All/Local"; + return startCase(option); + }} + /> + ); +} diff --git a/src/features/settings/settingsSlice.tsx b/src/features/settings/settingsSlice.tsx index 4bcde086af..ac1664fcf3 100644 --- a/src/features/settings/settingsSlice.tsx +++ b/src/features/settings/settingsSlice.tsx @@ -40,6 +40,8 @@ import { OAutoplayMediaType, CommentsThemeType, VotesThemeType, + ShowSubscribedIcon, + OShowSubscribedIcon, } from "../../services/db"; import { LOCALSTORAGE_KEYS, get, set } from "./syncStorage"; import { Mode } from "@ionic/core"; @@ -136,6 +138,7 @@ interface SettingsState { defaultFeed: DefaultFeedType | undefined; noSubscribedInFeed: boolean; thumbnailinatorEnabled: boolean; + subscribedIcon: ShowSubscribedIcon; }; blocks: { keywords: string[]; @@ -222,6 +225,7 @@ export const initialState: SettingsState = { defaultFeed: undefined, noSubscribedInFeed: false, thumbnailinatorEnabled: true, + subscribedIcon: OShowSubscribedIcon.Never, }, blocks: { keywords: [], @@ -532,6 +536,11 @@ export const appearanceSlice = createSlice({ db.setSetting("prefer_native_apps", action.payload); }, + setSubscribedIcon(state, action: PayloadAction) { + state.general.subscribedIcon = action.payload; + + db.setSetting("subscribed_icon", action.payload); + }, resetSettings: () => ({ ...initialState, @@ -722,6 +731,7 @@ export const fetchSettingsFromDatabase = createAsyncThunk( const quick_switch_dark_mode = await db.getSetting( "quick_switch_dark_mode", ); + const subscribed_icon = await db.getSetting("subscribed_icon"); return { ...state.settings, @@ -864,6 +874,8 @@ export const fetchSettingsFromDatabase = createAsyncThunk( thumbnailinatorEnabled: thumbnailinator_enabled ?? initialState.general.thumbnailinatorEnabled, + subscribedIcon: + subscribed_icon ?? initialState.general.subscribedIcon, }, blocks: { keywords: filtered_keywords ?? initialState.blocks.keywords, @@ -944,6 +956,7 @@ export const { setAlwaysUseReaderMode, setShowCollapsedComment, setQuickSwitchDarkMode, + setSubscribedIcon, } = appearanceSlice.actions; export default appearanceSlice.reducer; diff --git a/src/features/settings/shared/SettingSelector.tsx b/src/features/settings/shared/SettingSelector.tsx index 0df01239e0..645009ed84 100644 --- a/src/features/settings/shared/SettingSelector.tsx +++ b/src/features/settings/shared/SettingSelector.tsx @@ -83,6 +83,7 @@ export default function SettingSelector< {title} {getSelectedLabel?.(selected) ?? + getOptionLabel?.(selected) ?? (typeof selected === "string" ? startCase(selected) : selected)} ; return ( - - - - - + + + + + + + ); })(); diff --git a/src/services/db.ts b/src/services/db.ts index ce287c5c6e..87b9a48765 100644 --- a/src/services/db.ts +++ b/src/services/db.ts @@ -172,6 +172,15 @@ export const OLinkHandlerType = { InApp: "in-app", } as const; +export type ShowSubscribedIcon = + (typeof OShowSubscribedIcon)[keyof typeof OShowSubscribedIcon]; + +export const OShowSubscribedIcon = { + Never: "never", + OnlyAllLocal: "all-local", + Everywhere: "everywhere", +} as const; + export type DefaultFeedType = | { type: @@ -351,6 +360,7 @@ export type SettingValueTypes = { autoplay_media: AutoplayMediaType; show_collapsed_comment: boolean; quick_switch_dark_mode: boolean; + subscribed_icon: ShowSubscribedIcon; }; export interface ISettingItem { From 9f144239f87aa2b8030e24da4884b6b52bc68171 Mon Sep 17 00:00:00 2001 From: Alexander Harding <2166114+aeharding@users.noreply.github.com> Date: Sat, 10 Aug 2024 11:47:56 -0500 Subject: [PATCH 2/3] tweak --- src/features/labels/links/CommunityLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/labels/links/CommunityLink.tsx b/src/features/labels/links/CommunityLink.tsx index 10b8282c78..cca55c7a81 100644 --- a/src/features/labels/links/CommunityLink.tsx +++ b/src/features/labels/links/CommunityLink.tsx @@ -35,7 +35,7 @@ const SubscribedIcon = styled(IonIcon)` vertical-align: middle; font-size: 0.85em; - margin-bottom: 2px; + margin-bottom: 1px; margin-left: 2px; opacity: 0.3; From 7a896fef7e6c9ba2a65a86e05c06d07ef55b2456 Mon Sep 17 00:00:00 2001 From: Alexander Harding <2166114+aeharding@users.noreply.github.com> Date: Sat, 10 Aug 2024 12:07:08 -0500 Subject: [PATCH 3/3] tweak --- src/features/labels/links/CommunityLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/labels/links/CommunityLink.tsx b/src/features/labels/links/CommunityLink.tsx index cca55c7a81..7b63a98ead 100644 --- a/src/features/labels/links/CommunityLink.tsx +++ b/src/features/labels/links/CommunityLink.tsx @@ -38,7 +38,7 @@ const SubscribedIcon = styled(IonIcon)` margin-bottom: 1px; margin-left: 2px; - opacity: 0.3; + opacity: 0.4; .ion-palette-dark & { opacity: 0.5;