feat: image proxy service
This commit is contained in:
parent
dbc853fd8a
commit
8115b541de
@ -2,22 +2,27 @@ import "./Avatar.css";
|
|||||||
import Nostrich from "../nostrich.jpg";
|
import Nostrich from "../nostrich.jpg";
|
||||||
import { CSSProperties } from "react";
|
import { CSSProperties } from "react";
|
||||||
import type { UserMetadata } from "Nostr";
|
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 :
|
||||||
const avatarUrl = (user?.picture?.length ?? 0) === 0 ? Nostrich : user?.picture
|
(useImageProxy ? `${ApiHost}/api/v1/imgproxy/${window.btoa(user!.picture!)}` : user?.picture)
|
||||||
const backgroundImage = `url(${avatarUrl})`
|
const backgroundImage = `url(${avatarUrl})`
|
||||||
const domain = user?.nip05 && user.nip05.split('@')[1]
|
const domain = user?.nip05 && user.nip05.split('@')[1]
|
||||||
const style = { '--img-url': backgroundImage } as CSSProperties
|
const style = { '--img-url': backgroundImage } as CSSProperties
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...rest}
|
{...rest}
|
||||||
style={style}
|
style={style}
|
||||||
className="avatar"
|
className="avatar"
|
||||||
data-domain={domain?.toLowerCase()}
|
data-domain={domain?.toLowerCase()}
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Avatar
|
export default Avatar
|
||||||
|
@ -39,7 +39,7 @@ export default function NoteReaction(props: NoteReactionProps) {
|
|||||||
* Some clients embed the reposted note in the content
|
* Some clients embed the reposted note in the content
|
||||||
*/
|
*/
|
||||||
function extractRoot() {
|
function extractRoot() {
|
||||||
if (ev?.Kind === EventKind.Repost && ev.Content.length > 0) {
|
if (ev?.Kind === EventKind.Repost && ev.Content.length > 0 && ev.Content !== "#[0]") {
|
||||||
try {
|
try {
|
||||||
let r: RawEvent = JSON.parse(ev.Content);
|
let r: RawEvent = JSON.parse(ev.Content);
|
||||||
return r as TaggedRawEvent;
|
return r as TaggedRawEvent;
|
||||||
|
@ -71,6 +71,15 @@ const PreferencesPage = () => {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="card flex">
|
||||||
|
<div className="flex f-col f-grow">
|
||||||
|
<div>Image proxy</div>
|
||||||
|
<small>Use the caching image proxy to load avatars</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" checked={perf.useImageProxy} onChange={e => dispatch(setPreferences({ ...perf, useImageProxy: e.target.checked }))} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="card flex">
|
<div className="card flex">
|
||||||
<div className="flex f-col f-grow">
|
<div className="flex f-col f-grow">
|
||||||
<div>Debug Menus</div>
|
<div>Debug Menus</div>
|
||||||
|
@ -13,10 +13,10 @@ const RelayListKey = "last-relays";
|
|||||||
const FollowList = "last-follows";
|
const FollowList = "last-follows";
|
||||||
|
|
||||||
export interface NotificationRequest {
|
export interface NotificationRequest {
|
||||||
title: string
|
title: string
|
||||||
body: string
|
body: string
|
||||||
icon: string
|
icon: string
|
||||||
timestamp: number
|
timestamp: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserPreferences {
|
export interface UserPreferences {
|
||||||
@ -50,10 +50,15 @@ export interface UserPreferences {
|
|||||||
*/
|
*/
|
||||||
showDebugMenus: boolean,
|
showDebugMenus: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File uploading service to upload attachments to
|
* File uploading service to upload attachments to
|
||||||
*/
|
*/
|
||||||
fileUploader: "void.cat" | "nostr.build"
|
fileUploader: "void.cat" | "nostr.build",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use image proxy service to compress avatars
|
||||||
|
*/
|
||||||
|
useImageProxy: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoginStore {
|
export interface LoginStore {
|
||||||
@ -155,7 +160,8 @@ const InitState = {
|
|||||||
confirmReposts: false,
|
confirmReposts: false,
|
||||||
showDebugMenus: false,
|
showDebugMenus: false,
|
||||||
autoShowLatest: false,
|
autoShowLatest: false,
|
||||||
fileUploader: "void.cat"
|
fileUploader: "void.cat",
|
||||||
|
useImageProxy: true
|
||||||
}
|
}
|
||||||
} as LoginStore;
|
} as LoginStore;
|
||||||
|
|
||||||
@ -279,21 +285,21 @@ const LoginSlice = createSlice({
|
|||||||
|
|
||||||
window.localStorage.setItem(FollowList, JSON.stringify(state.follows));
|
window.localStorage.setItem(FollowList, JSON.stringify(state.follows));
|
||||||
},
|
},
|
||||||
setMuted(state, action: PayloadAction<{createdAt: number, keys: HexKey[]}>) {
|
setMuted(state, action: PayloadAction<{ createdAt: number, keys: HexKey[] }>) {
|
||||||
const { createdAt, keys } = action.payload
|
const { createdAt, keys } = action.payload
|
||||||
if (createdAt >= state.latestMuted) {
|
if (createdAt >= state.latestMuted) {
|
||||||
const muted = new Set([...keys])
|
const muted = new Set([...keys])
|
||||||
state.muted = Array.from(muted)
|
state.muted = Array.from(muted)
|
||||||
state.latestMuted = createdAt
|
state.latestMuted = createdAt
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setBlocked(state, action: PayloadAction<{createdAt: number, keys: HexKey[]}>) {
|
setBlocked(state, action: PayloadAction<{ createdAt: number, keys: HexKey[] }>) {
|
||||||
const { createdAt, keys } = action.payload
|
const { createdAt, keys } = action.payload
|
||||||
if (createdAt >= state.latestMuted) {
|
if (createdAt >= state.latestMuted) {
|
||||||
const blocked = new Set([...keys])
|
const blocked = new Set([...keys])
|
||||||
state.blocked = Array.from(blocked)
|
state.blocked = Array.from(blocked)
|
||||||
state.latestMuted = createdAt
|
state.latestMuted = createdAt
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addDirectMessage: (state, action: PayloadAction<TaggedRawEvent | Array<TaggedRawEvent>>) => {
|
addDirectMessage: (state, action: PayloadAction<TaggedRawEvent | Array<TaggedRawEvent>>) => {
|
||||||
let n = action.payload;
|
let n = action.payload;
|
||||||
@ -352,26 +358,26 @@ export const {
|
|||||||
} = LoginSlice.actions;
|
} = LoginSlice.actions;
|
||||||
|
|
||||||
export function sendNotification({ title, body, icon, timestamp }: NotificationRequest) {
|
export function sendNotification({ title, body, icon, timestamp }: NotificationRequest) {
|
||||||
return async (dispatch: AppDispatch, getState: () => RootState) => {
|
return async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
const state = getState()
|
const state = getState()
|
||||||
const { readNotifications } = state.login
|
const { readNotifications } = state.login
|
||||||
const hasPermission = "Notification" in window && Notification.permission === "granted"
|
const hasPermission = "Notification" in window && Notification.permission === "granted"
|
||||||
const shouldShowNotification = hasPermission && timestamp > readNotifications
|
const shouldShowNotification = hasPermission && timestamp > readNotifications
|
||||||
if (shouldShowNotification) {
|
if (shouldShowNotification) {
|
||||||
try {
|
try {
|
||||||
let worker = await navigator.serviceWorker.ready;
|
let worker = await navigator.serviceWorker.ready;
|
||||||
worker.showNotification(title, {
|
worker.showNotification(title, {
|
||||||
tag: "notification",
|
tag: "notification",
|
||||||
vibrate: [500],
|
vibrate: [500],
|
||||||
body,
|
body,
|
||||||
icon,
|
icon,
|
||||||
timestamp,
|
timestamp,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error)
|
console.warn(error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const reducer = LoginSlice.reducer;
|
export const reducer = LoginSlice.reducer;
|
||||||
|
Loading…
Reference in New Issue
Block a user