diff --git a/src/Element/Avatar.tsx b/src/Element/Avatar.tsx index 691e5791..a2613505 100644 --- a/src/Element/Avatar.tsx +++ b/src/Element/Avatar.tsx @@ -2,22 +2,27 @@ import "./Avatar.css"; import Nostrich from "../nostrich.jpg"; import { CSSProperties } from "react"; import type { UserMetadata } from "Nostr"; +import { useSelector } from "react-redux"; +import { RootState } from "State/Store"; +import { ApiHost } from "Const"; +const Avatar = ({ user, ...rest }: { user?: UserMetadata, onClick?: () => void }) => { + const useImageProxy = useSelector((s: RootState) => s.login.preferences.useImageProxy); -const Avatar = ({ user, ...rest }: { user?: UserMetadata, onClick?: () => void}) => { - const avatarUrl = (user?.picture?.length ?? 0) === 0 ? Nostrich : user?.picture - const backgroundImage = `url(${avatarUrl})` - const domain = user?.nip05 && user.nip05.split('@')[1] - const style = { '--img-url': backgroundImage } as CSSProperties - return ( -
-
- ) + const avatarUrl = (user?.picture?.length ?? 0) === 0 ? Nostrich : + (useImageProxy ? `${ApiHost}/api/v1/imgproxy/${window.btoa(user!.picture!)}` : user?.picture) + const backgroundImage = `url(${avatarUrl})` + const domain = user?.nip05 && user.nip05.split('@')[1] + const style = { '--img-url': backgroundImage } as CSSProperties + return ( +
+
+ ) } export default Avatar diff --git a/src/Element/NoteReaction.tsx b/src/Element/NoteReaction.tsx index 2f7db624..b000c5cf 100644 --- a/src/Element/NoteReaction.tsx +++ b/src/Element/NoteReaction.tsx @@ -39,7 +39,7 @@ export default function NoteReaction(props: NoteReactionProps) { * Some clients embed the reposted note in the content */ function extractRoot() { - if (ev?.Kind === EventKind.Repost && ev.Content.length > 0) { + if (ev?.Kind === EventKind.Repost && ev.Content.length > 0 && ev.Content !== "#[0]") { try { let r: RawEvent = JSON.parse(ev.Content); return r as TaggedRawEvent; diff --git a/src/Pages/settings/Preferences.tsx b/src/Pages/settings/Preferences.tsx index ee1f50f2..f0acbe68 100644 --- a/src/Pages/settings/Preferences.tsx +++ b/src/Pages/settings/Preferences.tsx @@ -71,6 +71,15 @@ const PreferencesPage = () => { +
+
+
Image proxy
+ Use the caching image proxy to load avatars +
+
+ dispatch(setPreferences({ ...perf, useImageProxy: e.target.checked }))} /> +
+
Debug Menus
diff --git a/src/State/Login.ts b/src/State/Login.ts index d7c756db..59bcd7db 100644 --- a/src/State/Login.ts +++ b/src/State/Login.ts @@ -13,10 +13,10 @@ const RelayListKey = "last-relays"; const FollowList = "last-follows"; export interface NotificationRequest { - title: string - body: string - icon: string - timestamp: number + title: string + body: string + icon: string + timestamp: number } export interface UserPreferences { @@ -50,10 +50,15 @@ export interface UserPreferences { */ showDebugMenus: boolean, - /** - * File uploading service to upload attachments to - */ - fileUploader: "void.cat" | "nostr.build" + /** + * File uploading service to upload attachments to + */ + fileUploader: "void.cat" | "nostr.build", + + /** + * Use image proxy service to compress avatars + */ + useImageProxy: boolean, } export interface LoginStore { @@ -155,7 +160,8 @@ const InitState = { confirmReposts: false, showDebugMenus: false, autoShowLatest: false, - fileUploader: "void.cat" + fileUploader: "void.cat", + useImageProxy: true } } as LoginStore; @@ -279,21 +285,21 @@ const LoginSlice = createSlice({ window.localStorage.setItem(FollowList, JSON.stringify(state.follows)); }, - setMuted(state, action: PayloadAction<{createdAt: number, keys: HexKey[]}>) { - const { createdAt, keys } = action.payload - if (createdAt >= state.latestMuted) { - const muted = new Set([...keys]) - state.muted = Array.from(muted) - state.latestMuted = createdAt - } + setMuted(state, action: PayloadAction<{ createdAt: number, keys: HexKey[] }>) { + const { createdAt, keys } = action.payload + if (createdAt >= state.latestMuted) { + const muted = new Set([...keys]) + state.muted = Array.from(muted) + state.latestMuted = createdAt + } }, - setBlocked(state, action: PayloadAction<{createdAt: number, keys: HexKey[]}>) { - const { createdAt, keys } = action.payload - if (createdAt >= state.latestMuted) { - const blocked = new Set([...keys]) - state.blocked = Array.from(blocked) - state.latestMuted = createdAt - } + setBlocked(state, action: PayloadAction<{ createdAt: number, keys: HexKey[] }>) { + const { createdAt, keys } = action.payload + if (createdAt >= state.latestMuted) { + const blocked = new Set([...keys]) + state.blocked = Array.from(blocked) + state.latestMuted = createdAt + } }, addDirectMessage: (state, action: PayloadAction>) => { let n = action.payload; @@ -352,26 +358,26 @@ export const { } = LoginSlice.actions; export function sendNotification({ title, body, icon, timestamp }: NotificationRequest) { - return async (dispatch: AppDispatch, getState: () => RootState) => { - const state = getState() - const { readNotifications } = state.login - const hasPermission = "Notification" in window && Notification.permission === "granted" - const shouldShowNotification = hasPermission && timestamp > readNotifications - if (shouldShowNotification) { - try { - let worker = await navigator.serviceWorker.ready; - worker.showNotification(title, { - tag: "notification", - vibrate: [500], - body, - icon, - timestamp, - }); - } catch (error) { - console.warn(error) - } + return async (dispatch: AppDispatch, getState: () => RootState) => { + const state = getState() + const { readNotifications } = state.login + const hasPermission = "Notification" in window && Notification.permission === "granted" + const shouldShowNotification = hasPermission && timestamp > readNotifications + if (shouldShowNotification) { + try { + let worker = await navigator.serviceWorker.ready; + worker.showNotification(title, { + tag: "notification", + vibrate: [500], + body, + icon, + timestamp, + }); + } catch (error) { + console.warn(error) + } + } } - } } export const reducer = LoginSlice.reducer;