Optout of display of images and video (show them as links) (#1358)
* optout of display of images/video * fix disableFreebies warning in settings * preview trusted images Co-authored-by: ekzyis <ek@stacker.news> --------- Co-authored-by: ekzyis <ek@stacker.news>
This commit is contained in:
parent
6f68a700ce
commit
07b98c3253
|
@ -84,6 +84,7 @@ export default gql`
|
|||
hideIsContributor: Boolean!
|
||||
hideWalletBalance: Boolean!
|
||||
imgproxyOnly: Boolean!
|
||||
showImagesAndVideos: Boolean!
|
||||
nostrCrossposting: Boolean!
|
||||
nostrPubkey: String
|
||||
nostrRelays: [String!]
|
||||
|
@ -155,6 +156,7 @@ export default gql`
|
|||
hideIsContributor: Boolean!
|
||||
hideWalletBalance: Boolean!
|
||||
imgproxyOnly: Boolean!
|
||||
showImagesAndVideos: Boolean!
|
||||
nostrCrossposting: Boolean!
|
||||
nostrPubkey: String
|
||||
nostrRelays: [String!]
|
||||
|
|
|
@ -19,13 +19,25 @@ export function decodeOriginalUrl (imgproxyUrl) {
|
|||
return originalUrl
|
||||
}
|
||||
|
||||
function ImageOriginal ({ src, topLevel, rel, tab, children, onClick, ...props }) {
|
||||
function LinkRaw ({ href, children, src, rel, onClick, ...props }) {
|
||||
const isRawURL = /^https?:\/\//.test(children?.[0])
|
||||
return (
|
||||
// eslint-disable-next-line
|
||||
<a
|
||||
target='_blank'
|
||||
rel={rel ?? UNKNOWN_LINK_REL}
|
||||
href={src}
|
||||
>{isRawURL || !children ? src : children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
function ImageOriginal ({ src, topLevel, tab, onClick, ...props }) {
|
||||
const me = useMe()
|
||||
const [showImage, setShowImage] = useState(false)
|
||||
const [showVideo, setShowVideo] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (me?.privates?.imgproxyOnly && tab !== 'preview') return
|
||||
// make sure it's not a false negative by trying to load URL as <img>
|
||||
const img = new window.Image()
|
||||
img.onload = () => setShowImage(true)
|
||||
|
@ -42,7 +54,9 @@ function ImageOriginal ({ src, topLevel, rel, tab, children, onClick, ...props }
|
|||
}
|
||||
}, [src, showImage])
|
||||
|
||||
if (showImage) {
|
||||
const showMedia = (tab === 'preview' || (me?.privates?.showImagesAndVideos !== false && !me?.privates?.imgproxyOnly))
|
||||
|
||||
if (showImage && showMedia) {
|
||||
return (
|
||||
<img
|
||||
className={topLevel ? styles.topLevel : undefined}
|
||||
|
@ -51,23 +65,14 @@ function ImageOriginal ({ src, topLevel, rel, tab, children, onClick, ...props }
|
|||
onError={() => setShowImage(false)}
|
||||
/>
|
||||
)
|
||||
} else if (showVideo) {
|
||||
} else if (showVideo && showMedia) {
|
||||
return <video src={src} controls />
|
||||
} else {
|
||||
// user is not okay with loading original url automatically or there was an error loading the image
|
||||
|
||||
// If element parsed by markdown is a raw URL, we use src as the text to not mislead users.
|
||||
// This will not be the case if [text](url) format is used. Then we will show what was chosen as text.
|
||||
const isRawURL = /^https?:\/\//.test(children?.[0])
|
||||
return (
|
||||
// eslint-disable-next-line
|
||||
<a
|
||||
target='_blank'
|
||||
rel={rel ?? UNKNOWN_LINK_REL}
|
||||
href={src}
|
||||
>{isRawURL || !children ? src : children}
|
||||
</a>
|
||||
)
|
||||
return <LinkRaw src={src} {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,6 +143,7 @@ const Image = memo(({ className, src, srcSet, sizes, width, height, onClick, onE
|
|||
|
||||
export default function ZoomableImage ({ src, srcSet, ...props }) {
|
||||
const showModal = useShowModal()
|
||||
const me = useMe()
|
||||
|
||||
// if `srcSet` is falsy, it means the image was not processed by worker yet
|
||||
const [trustedDomain, setTrustedDomain] = useState(!!srcSet || IMGPROXY_URL_REGEXP.test(src) || MEDIA_DOMAIN_REGEXP.test(src))
|
||||
|
@ -171,12 +177,16 @@ export default function ZoomableImage ({ src, srcSet, ...props }) {
|
|||
if (!src) return null
|
||||
|
||||
if (trustedDomain) {
|
||||
return (
|
||||
<TrustedImage
|
||||
src={src} srcSet={srcSet}
|
||||
onClick={handleClick} onError={handleError} {...props}
|
||||
/>
|
||||
)
|
||||
if (props.tab === 'preview' || !me || me.privates.showImagesAndVideos) {
|
||||
return (
|
||||
<TrustedImage
|
||||
src={src} srcSet={srcSet}
|
||||
onClick={handleClick} onError={handleError} {...props}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return <LinkRaw src={src} onClick={handleClick} {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
return <ImageOriginal src={originalUrl} onClick={handleClick} {...props} />
|
||||
|
|
|
@ -26,6 +26,7 @@ export const ME = gql`
|
|||
hideWalletBalance
|
||||
hideWelcomeBanner
|
||||
imgproxyOnly
|
||||
showImagesAndVideos
|
||||
lastCheckedJobs
|
||||
nostrCrossposting
|
||||
noteAllDescendants
|
||||
|
@ -98,6 +99,7 @@ export const SETTINGS_FIELDS = gql`
|
|||
hideTwitter
|
||||
hideIsContributor
|
||||
imgproxyOnly
|
||||
showImagesAndVideos
|
||||
hideWalletBalance
|
||||
diagnostics
|
||||
noReferralLinks
|
||||
|
|
|
@ -116,7 +116,7 @@ export default function Settings ({ ssrData }) {
|
|||
tipRandomMin: settings?.tipRandomMin || 1,
|
||||
tipRandomMax: settings?.tipRandomMax || 10,
|
||||
turboTipping: settings?.turboTipping,
|
||||
disableFreebies: settings?.disableFreebies,
|
||||
disableFreebies: settings?.disableFreebies || undefined,
|
||||
zapUndos: settings?.zapUndos || (settings?.tipDefault ? 100 * settings.tipDefault : 2100),
|
||||
zapUndosEnabled: settings?.zapUndos !== null,
|
||||
fiatCurrency: settings?.fiatCurrency || 'USD',
|
||||
|
@ -140,6 +140,7 @@ export default function Settings ({ ssrData }) {
|
|||
hideNostr: settings?.hideNostr,
|
||||
hideTwitter: settings?.hideTwitter,
|
||||
imgproxyOnly: settings?.imgproxyOnly,
|
||||
showImagesAndVideos: settings?.showImagesAndVideos,
|
||||
wildWestMode: settings?.wildWestMode,
|
||||
satsFilter: settings?.satsFilter,
|
||||
nsfwMode: settings?.nsfwMode,
|
||||
|
@ -508,6 +509,17 @@ export default function Settings ({ ssrData }) {
|
|||
required
|
||||
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
||||
/>
|
||||
<Checkbox
|
||||
label={
|
||||
<div className='d-flex align-items-center'>show images and video
|
||||
<Info>
|
||||
<p>disable to show images and videos as links instead of embedding them</p>
|
||||
</Info>
|
||||
</div>
|
||||
}
|
||||
name='showImagesAndVideos'
|
||||
groupClassName='mb-0'
|
||||
/>
|
||||
<Checkbox
|
||||
label={
|
||||
<div className='d-flex align-items-center'>wild west mode
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "users" ADD COLUMN "showImagesAndVideos" BOOLEAN NOT NULL DEFAULT true;
|
|
@ -63,6 +63,7 @@ model User {
|
|||
turboTipping Boolean @default(false)
|
||||
zapUndos Int?
|
||||
imgproxyOnly Boolean @default(false)
|
||||
showImagesAndVideos Boolean @default(true)
|
||||
hideWalletBalance Boolean @default(false)
|
||||
disableFreebies Boolean?
|
||||
referrerId Int?
|
||||
|
|
Loading…
Reference in New Issue