feat: live feed toggle
This commit is contained in:
parent
89bb9ad2d0
commit
917fcd9839
26 changed files with 130 additions and 26 deletions
28
src/components/LiveFeedToggle/index.tsx
Normal file
28
src/components/LiveFeedToggle/index.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
||||||
|
import { Radio } from 'lucide-react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
export function LiveFeedToggle() {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { enableLiveFeed, updateEnableLiveFeed } = useUserPreferences()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="titlebar-icon"
|
||||||
|
title={t(enableLiveFeed ? 'Disable live feed' : 'Enable live feed')}
|
||||||
|
onClick={() => updateEnableLiveFeed(!enableLiveFeed)}
|
||||||
|
>
|
||||||
|
<Radio
|
||||||
|
className={cn(
|
||||||
|
'size-4',
|
||||||
|
enableLiveFeed
|
||||||
|
? 'text-green-400 focus:text-green-300 animate-pulse'
|
||||||
|
: 'text-muted-foreground focus:text-foreground'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,8 @@ import { TFeedSubRequest, TNoteListMode } from '@/types'
|
||||||
import { useMemo, useRef, useState } from 'react'
|
import { useMemo, useRef, useState } from 'react'
|
||||||
import KindFilter from '../KindFilter'
|
import KindFilter from '../KindFilter'
|
||||||
import { RefreshButton } from '../RefreshButton'
|
import { RefreshButton } from '../RefreshButton'
|
||||||
|
import { LiveFeedToggle } from '../LiveFeedToggle'
|
||||||
|
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
||||||
|
|
||||||
export default function NormalFeed({
|
export default function NormalFeed({
|
||||||
subRequests,
|
subRequests,
|
||||||
|
|
@ -28,6 +30,7 @@ export default function NormalFeed({
|
||||||
isPubkeyFeed?: boolean
|
isPubkeyFeed?: boolean
|
||||||
}) {
|
}) {
|
||||||
const { showKinds } = useKindFilter()
|
const { showKinds } = useKindFilter()
|
||||||
|
const { enableLiveFeed } = useUserPreferences()
|
||||||
const [temporaryShowKinds, setTemporaryShowKinds] = useState(showKinds)
|
const [temporaryShowKinds, setTemporaryShowKinds] = useState(showKinds)
|
||||||
const [listMode, setListMode] = useState<TNoteListMode>(() => storage.getNoteListMode())
|
const [listMode, setListMode] = useState<TNoteListMode>(() => storage.getNoteListMode())
|
||||||
const supportTouch = useMemo(() => isTouchDevice(), [])
|
const supportTouch = useMemo(() => isTouchDevice(), [])
|
||||||
|
|
@ -85,7 +88,8 @@ export default function NormalFeed({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<TrustScoreFilter onOpenChange={handleTrustFilterOpenChange} />
|
<LiveFeedToggle />
|
||||||
|
{!isPubkeyFeed && <TrustScoreFilter onOpenChange={handleTrustFilterOpenChange} />}
|
||||||
{showKindsFilter && (
|
{showKindsFilter && (
|
||||||
<KindFilter
|
<KindFilter
|
||||||
showKinds={temporaryShowKinds}
|
showKinds={temporaryShowKinds}
|
||||||
|
|
@ -105,6 +109,7 @@ export default function NormalFeed({
|
||||||
areAlgoRelays={areAlgoRelays}
|
areAlgoRelays={areAlgoRelays}
|
||||||
showRelayCloseReason={showRelayCloseReason}
|
showRelayCloseReason={showRelayCloseReason}
|
||||||
isPubkeyFeed={isPubkeyFeed}
|
isPubkeyFeed={isPubkeyFeed}
|
||||||
|
showNewNotesDirectly={enableLiveFeed}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<NoteList
|
<NoteList
|
||||||
|
|
@ -115,6 +120,7 @@ export default function NormalFeed({
|
||||||
areAlgoRelays={areAlgoRelays}
|
areAlgoRelays={areAlgoRelays}
|
||||||
showRelayCloseReason={showRelayCloseReason}
|
showRelayCloseReason={showRelayCloseReason}
|
||||||
isPubkeyFeed={isPubkeyFeed}
|
isPubkeyFeed={isPubkeyFeed}
|
||||||
|
showNewNotesDirectly={enableLiveFeed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@ import { generateBech32IdFromETag } from '@/lib/tag'
|
||||||
import { isTouchDevice } from '@/lib/utils'
|
import { isTouchDevice } from '@/lib/utils'
|
||||||
import { useKindFilter } from '@/providers/KindFilterProvider'
|
import { useKindFilter } from '@/providers/KindFilterProvider'
|
||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
|
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
||||||
import client from '@/services/client.service'
|
import client from '@/services/client.service'
|
||||||
import storage from '@/services/local-storage.service'
|
import storage from '@/services/local-storage.service'
|
||||||
import relayInfoService from '@/services/relay-info.service'
|
import relayInfoService from '@/services/relay-info.service'
|
||||||
import { TFeedSubRequest, TNoteListMode } from '@/types'
|
import { TFeedSubRequest, TNoteListMode } from '@/types'
|
||||||
import { NostrEvent } from 'nostr-tools'
|
import { NostrEvent } from 'nostr-tools'
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
|
import { LiveFeedToggle } from '../LiveFeedToggle'
|
||||||
import { RefreshButton } from '../RefreshButton'
|
import { RefreshButton } from '../RefreshButton'
|
||||||
|
|
||||||
export default function ProfileFeed({
|
export default function ProfileFeed({
|
||||||
|
|
@ -24,6 +26,7 @@ export default function ProfileFeed({
|
||||||
search?: string
|
search?: string
|
||||||
}) {
|
}) {
|
||||||
const { pubkey: myPubkey, pinListEvent: myPinListEvent } = useNostr()
|
const { pubkey: myPubkey, pinListEvent: myPinListEvent } = useNostr()
|
||||||
|
const { enableLiveFeed } = useUserPreferences()
|
||||||
const { showKinds } = useKindFilter()
|
const { showKinds } = useKindFilter()
|
||||||
const [temporaryShowKinds, setTemporaryShowKinds] = useState(showKinds)
|
const [temporaryShowKinds, setTemporaryShowKinds] = useState(showKinds)
|
||||||
const [listMode, setListMode] = useState<TNoteListMode>(() => {
|
const [listMode, setListMode] = useState<TNoteListMode>(() => {
|
||||||
|
|
@ -164,6 +167,7 @@ export default function ProfileFeed({
|
||||||
options={
|
options={
|
||||||
<>
|
<>
|
||||||
{!supportTouch && <RefreshButton onClick={() => noteListRef.current?.refresh()} />}
|
{!supportTouch && <RefreshButton onClick={() => noteListRef.current?.refresh()} />}
|
||||||
|
<LiveFeedToggle />
|
||||||
<KindFilter showKinds={temporaryShowKinds} onShowKindsChange={handleShowKindsChange} />
|
<KindFilter showKinds={temporaryShowKinds} onShowKindsChange={handleShowKindsChange} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +179,7 @@ export default function ProfileFeed({
|
||||||
hideReplies={listMode === 'posts'}
|
hideReplies={listMode === 'posts'}
|
||||||
filterMutedNotes={false}
|
filterMutedNotes={false}
|
||||||
pinnedEventIds={listMode === 'you' || !!search ? [] : pinnedEventIds}
|
pinnedEventIds={listMode === 'you' || !!search ? [] : pinnedEventIds}
|
||||||
showNewNotesDirectly={myPubkey === pubkey}
|
showNewNotesDirectly={myPubkey === pubkey || enableLiveFeed}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ export default function TrustScoreFilter({
|
||||||
>
|
>
|
||||||
{minTrustScore < 100 ? <Shield size={16} /> : <ShieldCheck size={16} />}
|
{minTrustScore < 100 ? <Shield size={16} /> : <ShieldCheck size={16} />}
|
||||||
{minTrustScore > 0 && minTrustScore < 100 && (
|
{minTrustScore > 0 && minTrustScore < 100 && (
|
||||||
<div className="absolute inset-0 w-full h-full flex flex-col items-center justify-center text-[0.55rem] font-mono font-bold">
|
<div className="absolute inset-0 w-full h-full flex flex-col items-center justify-center text-[0.5rem] font-mono font-bold">
|
||||||
{minTrustScore}
|
{minTrustScore}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ const UserAggregationList = forwardRef<
|
||||||
areAlgoRelays?: boolean
|
areAlgoRelays?: boolean
|
||||||
showRelayCloseReason?: boolean
|
showRelayCloseReason?: boolean
|
||||||
isPubkeyFeed?: boolean
|
isPubkeyFeed?: boolean
|
||||||
|
showNewNotesDirectly?: boolean
|
||||||
}
|
}
|
||||||
>(
|
>(
|
||||||
(
|
(
|
||||||
|
|
@ -63,7 +64,8 @@ const UserAggregationList = forwardRef<
|
||||||
filterMutedNotes = true,
|
filterMutedNotes = true,
|
||||||
areAlgoRelays = false,
|
areAlgoRelays = false,
|
||||||
showRelayCloseReason = false,
|
showRelayCloseReason = false,
|
||||||
isPubkeyFeed = false
|
isPubkeyFeed = false,
|
||||||
|
showNewNotesDirectly = false
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -176,9 +178,13 @@ const UserAggregationList = forwardRef<
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNew: (event) => {
|
onNew: (event) => {
|
||||||
setNewEvents((oldEvents) =>
|
if (showNewNotesDirectly) {
|
||||||
[event, ...oldEvents].sort((a, b) => b.created_at - a.created_at)
|
setEvents((oldEvents) => [event, ...oldEvents])
|
||||||
)
|
} else {
|
||||||
|
setNewEvents((oldEvents) =>
|
||||||
|
[event, ...oldEvents].sort((a, b) => b.created_at - a.created_at)
|
||||||
|
)
|
||||||
|
}
|
||||||
threadService.addRepliesToThread([event])
|
threadService.addRepliesToThread([event])
|
||||||
},
|
},
|
||||||
onClose: (url, reason) => {
|
onClose: (url, reason) => {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ export const StorageKey = {
|
||||||
QUICK_REACTION_EMOJI: 'quickReactionEmoji',
|
QUICK_REACTION_EMOJI: 'quickReactionEmoji',
|
||||||
NSFW_DISPLAY_POLICY: 'nsfwDisplayPolicy',
|
NSFW_DISPLAY_POLICY: 'nsfwDisplayPolicy',
|
||||||
MIN_TRUST_SCORE: 'minTrustScore',
|
MIN_TRUST_SCORE: 'minTrustScore',
|
||||||
|
ENABLE_LIVE_FEED: 'enableLiveFeed',
|
||||||
HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes', // deprecated
|
HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes', // deprecated
|
||||||
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions', // deprecated
|
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions', // deprecated
|
||||||
HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications', // deprecated
|
HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications', // deprecated
|
||||||
|
|
|
||||||
|
|
@ -651,6 +651,8 @@ export default {
|
||||||
'trust-filter.hide-bottom-percent':
|
'trust-filter.hide-bottom-percent':
|
||||||
'تصفية أدنى {{score}}٪ من المستخدمين حسب تصنيف الثقة',
|
'تصفية أدنى {{score}}٪ من المستخدمين حسب تصنيف الثقة',
|
||||||
'trust-filter.trust-score-description': 'محسوبة بناءً على سمعة المستخدم والنسبة المئوية للشبكة الاجتماعية',
|
'trust-filter.trust-score-description': 'محسوبة بناءً على سمعة المستخدم والنسبة المئوية للشبكة الاجتماعية',
|
||||||
'Auto-load profile pictures': 'تحميل صور الملف الشخصي تلقائيًا'
|
'Auto-load profile pictures': 'تحميل صور الملف الشخصي تلقائيًا',
|
||||||
|
'Disable live feed': 'تعطيل التغذية المباشرة',
|
||||||
|
'Enable live feed': 'تفعيل التغذية المباشرة'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -673,6 +673,8 @@ export default {
|
||||||
'Untere {{score}}% der Benutzer nach Vertrauensrang filtern',
|
'Untere {{score}}% der Benutzer nach Vertrauensrang filtern',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'Berechnet basierend auf Benutzerreputation und sozialem Netzwerk-Perzentil',
|
'Berechnet basierend auf Benutzerreputation und sozialem Netzwerk-Perzentil',
|
||||||
'Auto-load profile pictures': 'Profilbilder automatisch laden'
|
'Auto-load profile pictures': 'Profilbilder automatisch laden',
|
||||||
|
'Disable live feed': 'Live-Feed deaktivieren',
|
||||||
|
'Enable live feed': 'Live-Feed aktivieren'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -656,6 +656,8 @@ export default {
|
||||||
'trust-filter.hide-bottom-percent':
|
'trust-filter.hide-bottom-percent':
|
||||||
'Filter out bottom {{score}}% of users by trust rank',
|
'Filter out bottom {{score}}% of users by trust rank',
|
||||||
'trust-filter.trust-score-description': 'Calculated based on user reputation and social network percentile',
|
'trust-filter.trust-score-description': 'Calculated based on user reputation and social network percentile',
|
||||||
'Auto-load profile pictures': 'Auto-load profile pictures'
|
'Auto-load profile pictures': 'Auto-load profile pictures',
|
||||||
|
'Disable live feed': 'Disable live feed',
|
||||||
|
'Enable live feed': 'Enable live feed'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -667,6 +667,8 @@ export default {
|
||||||
'Filtrar el {{score}}% inferior de usuarios por clasificación de confianza',
|
'Filtrar el {{score}}% inferior de usuarios por clasificación de confianza',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'Calculado según la reputación del usuario y el percentil de la red social',
|
'Calculado según la reputación del usuario y el percentil de la red social',
|
||||||
'Auto-load profile pictures': 'Cargar imágenes de perfil automáticamente'
|
'Auto-load profile pictures': 'Cargar imágenes de perfil automáticamente',
|
||||||
|
'Disable live feed': 'Desactivar feed en vivo',
|
||||||
|
'Enable live feed': 'Activar feed en vivo'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -663,6 +663,8 @@ export default {
|
||||||
'فیلتر کردن {{score}}٪ پایینترین کاربران بر اساس رتبه اعتماد',
|
'فیلتر کردن {{score}}٪ پایینترین کاربران بر اساس رتبه اعتماد',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'بر اساس شهرت کاربر و صدک شبکه اجتماعی محاسبه میشود',
|
'بر اساس شهرت کاربر و صدک شبکه اجتماعی محاسبه میشود',
|
||||||
'Auto-load profile pictures': 'بارگذاری خودکار تصاویر پروفایل'
|
'Auto-load profile pictures': 'بارگذاری خودکار تصاویر پروفایل',
|
||||||
|
'Disable live feed': 'غیرفعال کردن فید زنده',
|
||||||
|
'Enable live feed': 'فعال کردن فید زنده'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -671,6 +671,8 @@ export default {
|
||||||
'Filtrer les {{score}}% inférieurs des utilisateurs par classement de confiance',
|
'Filtrer les {{score}}% inférieurs des utilisateurs par classement de confiance',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
"Calculé en fonction de la réputation et du réseau social de l'utilisateur",
|
"Calculé en fonction de la réputation et du réseau social de l'utilisateur",
|
||||||
'Auto-load profile pictures': 'Charger les images de profil automatiquement'
|
'Auto-load profile pictures': 'Charger les images de profil automatiquement',
|
||||||
|
'Disable live feed': 'Désactiver le flux en direct',
|
||||||
|
'Enable live feed': 'Activer le flux en direct'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -663,6 +663,8 @@ export default {
|
||||||
'विश्वास रैंक द्वारा निचले {{score}}% उपयोगकर्ताओं को फ़िल्टर करें',
|
'विश्वास रैंक द्वारा निचले {{score}}% उपयोगकर्ताओं को फ़िल्टर करें',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'उपयोगकर्ता की प्रतिष्ठा और सामाजिक नेटवर्क प्रतिशतक के आधार पर गणना की गई',
|
'उपयोगकर्ता की प्रतिष्ठा और सामाजिक नेटवर्क प्रतिशतक के आधार पर गणना की गई',
|
||||||
'Auto-load profile pictures': 'प्रोफ़ाइल चित्र स्वतः लोड करें'
|
'Auto-load profile pictures': 'प्रोफ़ाइल चित्र स्वतः लोड करें',
|
||||||
|
'Disable live feed': 'लाइव फ़ीड अक्षम करें',
|
||||||
|
'Enable live feed': 'लाइव फ़ीड सक्षम करें'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -656,6 +656,8 @@ export default {
|
||||||
'Alsó {{score}}% felhasználók szűrése bizalmi rangsor szerint',
|
'Alsó {{score}}% felhasználók szűrése bizalmi rangsor szerint',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'A felhasználó hírneve és a közösségi hálózat percentilise alapján számítva',
|
'A felhasználó hírneve és a közösségi hálózat percentilise alapján számítva',
|
||||||
'Auto-load profile pictures': 'Profilképek automatikus betöltése'
|
'Auto-load profile pictures': 'Profilképek automatikus betöltése',
|
||||||
|
'Disable live feed': 'Élő hírfolyam letiltása',
|
||||||
|
'Enable live feed': 'Élő hírfolyam engedélyezése'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -667,6 +667,8 @@ export default {
|
||||||
'Filtra il {{score}}% inferiore degli utenti per classifica di fiducia',
|
'Filtra il {{score}}% inferiore degli utenti per classifica di fiducia',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
"Calcolato in base alla reputazione dell'utente e al percentile del social network",
|
"Calcolato in base alla reputazione dell'utente e al percentile del social network",
|
||||||
'Auto-load profile pictures': 'Caricamento automatico immagini di profilo'
|
'Auto-load profile pictures': 'Caricamento automatico immagini di profilo',
|
||||||
|
'Disable live feed': 'Disattiva feed live',
|
||||||
|
'Enable live feed': 'Attiva feed live'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -662,6 +662,8 @@ export default {
|
||||||
'信頼ランク下位 {{score}}% のユーザーをフィルタリング',
|
'信頼ランク下位 {{score}}% のユーザーをフィルタリング',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'ユーザーの評判とソーシャルネットワークに基づいて信頼度パーセンタイルを計算',
|
'ユーザーの評判とソーシャルネットワークに基づいて信頼度パーセンタイルを計算',
|
||||||
'Auto-load profile pictures': 'プロフィール画像を自動読み込み'
|
'Auto-load profile pictures': 'プロフィール画像を自動読み込み',
|
||||||
|
'Disable live feed': 'ライブフィードを無効にする',
|
||||||
|
'Enable live feed': 'ライブフィードを有効にする'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -656,6 +656,8 @@ export default {
|
||||||
'trust-filter.only-show-wot': '신뢰 네트워크만 표시 (팔로우 + 팔로우의 팔로우)',
|
'trust-filter.only-show-wot': '신뢰 네트워크만 표시 (팔로우 + 팔로우의 팔로우)',
|
||||||
'trust-filter.hide-bottom-percent': '신뢰도 하위 {{score}}% 사용자 필터링',
|
'trust-filter.hide-bottom-percent': '신뢰도 하위 {{score}}% 사용자 필터링',
|
||||||
'trust-filter.trust-score-description': '사용자의 평판과 소셜 네트워크를 기반으로 신뢰도 백분위수 계산',
|
'trust-filter.trust-score-description': '사용자의 평판과 소셜 네트워크를 기반으로 신뢰도 백분위수 계산',
|
||||||
'Auto-load profile pictures': '프로필 사진 자동 로드'
|
'Auto-load profile pictures': '프로필 사진 자동 로드',
|
||||||
|
'Disable live feed': '라이브 피드 비활성화',
|
||||||
|
'Enable live feed': '라이브 피드 활성화'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -668,6 +668,8 @@ export default {
|
||||||
'Filtruj dolne {{score}}% użytkowników według rankingu zaufania',
|
'Filtruj dolne {{score}}% użytkowników według rankingu zaufania',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'Obliczany na podstawie reputacji użytkownika i percentyla sieci społecznościowej',
|
'Obliczany na podstawie reputacji użytkownika i percentyla sieci społecznościowej',
|
||||||
'Auto-load profile pictures': 'Automatyczne ładowanie zdjęć profilowych'
|
'Auto-load profile pictures': 'Automatyczne ładowanie zdjęć profilowych',
|
||||||
|
'Disable live feed': 'Wyłącz kanał na żywo',
|
||||||
|
'Enable live feed': 'Włącz kanał na żywo'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -664,6 +664,8 @@ export default {
|
||||||
'Filtrar os {{score}}% inferiores de usuários por classificação de confiança',
|
'Filtrar os {{score}}% inferiores de usuários por classificação de confiança',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'Calculado com base na reputação do usuário e no percentil da rede social',
|
'Calculado com base na reputação do usuário e no percentil da rede social',
|
||||||
'Auto-load profile pictures': 'Carregar fotos de perfil automaticamente'
|
'Auto-load profile pictures': 'Carregar fotos de perfil automaticamente',
|
||||||
|
'Disable live feed': 'Desativar feed ao vivo',
|
||||||
|
'Enable live feed': 'Ativar feed ao vivo'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -667,6 +667,8 @@ export default {
|
||||||
'Filtrar os {{score}}% inferiores de utilizadores por classificação de confiança',
|
'Filtrar os {{score}}% inferiores de utilizadores por classificação de confiança',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'Calculado com base na reputação do utilizador e no percentil da rede social',
|
'Calculado com base na reputação do utilizador e no percentil da rede social',
|
||||||
'Auto-load profile pictures': 'Carregar fotos de perfil automaticamente'
|
'Auto-load profile pictures': 'Carregar fotos de perfil automaticamente',
|
||||||
|
'Disable live feed': 'Desativar feed ao vivo',
|
||||||
|
'Enable live feed': 'Ativar feed ao vivo'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -667,6 +667,8 @@ export default {
|
||||||
'Отфильтровать нижние {{score}}% пользователей по рейтингу доверия',
|
'Отфильтровать нижние {{score}}% пользователей по рейтингу доверия',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'Рассчитывается на основе репутации пользователя и процентиля социальной сети',
|
'Рассчитывается на основе репутации пользователя и процентиля социальной сети',
|
||||||
'Auto-load profile pictures': 'Автозагрузка аватаров'
|
'Auto-load profile pictures': 'Автозагрузка аватаров',
|
||||||
|
'Disable live feed': 'Отключить прямую трансляцию',
|
||||||
|
'Enable live feed': 'Включить прямую трансляцию'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -653,6 +653,8 @@ export default {
|
||||||
'กรอง {{score}}% ล่างสุดของผู้ใช้ตามอันดับความไว้วางใจ',
|
'กรอง {{score}}% ล่างสุดของผู้ใช้ตามอันดับความไว้วางใจ',
|
||||||
'trust-filter.trust-score-description':
|
'trust-filter.trust-score-description':
|
||||||
'คำนวณจากชื่อเสียงของผู้ใช้และเปอร์เซ็นไทล์ของเครือข่ายสังคม',
|
'คำนวณจากชื่อเสียงของผู้ใช้และเปอร์เซ็นไทล์ของเครือข่ายสังคม',
|
||||||
'Auto-load profile pictures': 'โหลดรูปโปรไฟล์อัตโนมัติ'
|
'Auto-load profile pictures': 'โหลดรูปโปรไฟล์อัตโนมัติ',
|
||||||
|
'Disable live feed': 'ปิดฟีดสด',
|
||||||
|
'Enable live feed': 'เปิดฟีดสด'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -636,6 +636,8 @@ export default {
|
||||||
'trust-filter.only-show-wot': '僅顯示你的信任網路(關注的人 + 他們關注的人)',
|
'trust-filter.only-show-wot': '僅顯示你的信任網路(關注的人 + 他們關注的人)',
|
||||||
'trust-filter.hide-bottom-percent': '過濾掉信任度排名後 {{score}}% 的使用者',
|
'trust-filter.hide-bottom-percent': '過濾掉信任度排名後 {{score}}% 的使用者',
|
||||||
'trust-filter.trust-score-description': '基於使用者的聲譽和社交網路計算信任度百分位',
|
'trust-filter.trust-score-description': '基於使用者的聲譽和社交網路計算信任度百分位',
|
||||||
'Auto-load profile pictures': '自動載入大頭照'
|
'Auto-load profile pictures': '自動載入大頭照',
|
||||||
|
'Disable live feed': '停用即時推送',
|
||||||
|
'Enable live feed': '啟用即時推送'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -641,6 +641,8 @@ export default {
|
||||||
'trust-filter.only-show-wot': '仅显示你的信任网络(关注的人 + 他们关注的人)',
|
'trust-filter.only-show-wot': '仅显示你的信任网络(关注的人 + 他们关注的人)',
|
||||||
'trust-filter.hide-bottom-percent': '过滤掉信任度排名后 {{score}}% 的用户',
|
'trust-filter.hide-bottom-percent': '过滤掉信任度排名后 {{score}}% 的用户',
|
||||||
'trust-filter.trust-score-description': '基于用户的声誉和社交网络计算信任度百分位',
|
'trust-filter.trust-score-description': '基于用户的声誉和社交网络计算信任度百分位',
|
||||||
'Auto-load profile pictures': '自动加载头像'
|
'Auto-load profile pictures': '自动加载头像',
|
||||||
|
'Disable live feed': '禁用实时推送',
|
||||||
|
'Enable live feed': '启用实时推送'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ type TUserPreferencesContext = {
|
||||||
|
|
||||||
quickReactionEmoji: string | TEmoji
|
quickReactionEmoji: string | TEmoji
|
||||||
updateQuickReactionEmoji: (emoji: string | TEmoji) => void
|
updateQuickReactionEmoji: (emoji: string | TEmoji) => void
|
||||||
|
|
||||||
|
enableLiveFeed: boolean
|
||||||
|
updateEnableLiveFeed: (enable: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserPreferencesContext = createContext<TUserPreferencesContext | undefined>(undefined)
|
const UserPreferencesContext = createContext<TUserPreferencesContext | undefined>(undefined)
|
||||||
|
|
@ -45,6 +48,7 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
|
||||||
)
|
)
|
||||||
const [quickReaction, setQuickReaction] = useState(storage.getQuickReaction())
|
const [quickReaction, setQuickReaction] = useState(storage.getQuickReaction())
|
||||||
const [quickReactionEmoji, setQuickReactionEmoji] = useState(storage.getQuickReactionEmoji())
|
const [quickReactionEmoji, setQuickReactionEmoji] = useState(storage.getQuickReactionEmoji())
|
||||||
|
const [enableLiveFeed, setEnableLiveFeed] = useState(storage.getEnableLiveFeed())
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isSmallScreen && enableSingleColumnLayout) {
|
if (!isSmallScreen && enableSingleColumnLayout) {
|
||||||
|
|
@ -79,6 +83,11 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
|
||||||
storage.setQuickReactionEmoji(emoji)
|
storage.setQuickReactionEmoji(emoji)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateEnableLiveFeed = (enable: boolean) => {
|
||||||
|
setEnableLiveFeed(enable)
|
||||||
|
storage.setEnableLiveFeed(enable)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserPreferencesContext.Provider
|
<UserPreferencesContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|
@ -93,7 +102,9 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
|
||||||
quickReaction,
|
quickReaction,
|
||||||
updateQuickReaction,
|
updateQuickReaction,
|
||||||
quickReactionEmoji,
|
quickReactionEmoji,
|
||||||
updateQuickReactionEmoji
|
updateQuickReactionEmoji,
|
||||||
|
enableLiveFeed,
|
||||||
|
updateEnableLiveFeed
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ class LocalStorageService {
|
||||||
private quickReactionEmoji: string | TEmoji = '+'
|
private quickReactionEmoji: string | TEmoji = '+'
|
||||||
private nsfwDisplayPolicy: TNsfwDisplayPolicy = NSFW_DISPLAY_POLICY.HIDE_CONTENT
|
private nsfwDisplayPolicy: TNsfwDisplayPolicy = NSFW_DISPLAY_POLICY.HIDE_CONTENT
|
||||||
private minTrustScore: number = 40
|
private minTrustScore: number = 40
|
||||||
|
private enableLiveFeed: boolean = false
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
if (!LocalStorageService.instance) {
|
if (!LocalStorageService.instance) {
|
||||||
|
|
@ -275,6 +276,8 @@ class LocalStorageService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.enableLiveFeed = window.localStorage.getItem(StorageKey.ENABLE_LIVE_FEED) === 'true'
|
||||||
|
|
||||||
// Clean up deprecated data
|
// Clean up deprecated data
|
||||||
window.localStorage.removeItem(StorageKey.PINNED_PUBKEYS)
|
window.localStorage.removeItem(StorageKey.PINNED_PUBKEYS)
|
||||||
window.localStorage.removeItem(StorageKey.ACCOUNT_PROFILE_EVENT_MAP)
|
window.localStorage.removeItem(StorageKey.ACCOUNT_PROFILE_EVENT_MAP)
|
||||||
|
|
@ -612,6 +615,15 @@ class LocalStorageService {
|
||||||
window.localStorage.setItem(StorageKey.MIN_TRUST_SCORE, score.toString())
|
window.localStorage.setItem(StorageKey.MIN_TRUST_SCORE, score.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEnableLiveFeed() {
|
||||||
|
return this.enableLiveFeed
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnableLiveFeed(enable: boolean) {
|
||||||
|
this.enableLiveFeed = enable
|
||||||
|
window.localStorage.setItem(StorageKey.ENABLE_LIVE_FEED, enable.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = new LocalStorageService()
|
const instance = new LocalStorageService()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue