highlight focused content

This commit is contained in:
balzack 2024-12-10 18:30:00 -08:00
parent 1cf4871ca4
commit c0319b0864
8 changed files with 59 additions and 25 deletions

View File

@ -1,9 +1,22 @@
.channel { .channel {
display: flex;
flex-direction: row;
align-items: center;
height: 100%; height: 100%;
gap: 8px;
.unfocused {
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
}
.focused {
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
background-color: var(--mantine-color-surface-3);
}
.details { .details {
display: flex; display: flex;
@ -14,6 +27,10 @@
} }
.cursor { .cursor {
padding-top: 8px;
padding-bottom: 8px;
padding-right: 16px;
padding-left: 16px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -25,6 +42,10 @@
} }
.nocursor { .nocursor {
padding-top: 8px;
padding-bottom: 8px;
padding-right: 16px;
padding-left: 16px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;

View File

@ -6,6 +6,7 @@ import { Colors } from '../constants/Colors'
export function Channel({ export function Channel({
className, className,
unread, unread,
focused,
imageUrl, imageUrl,
notesPlaceholder, notesPlaceholder,
subject, subject,
@ -16,6 +17,7 @@ export function Channel({
}: { }: {
className: string className: string
unread: boolean unread: boolean
focused: boolean
imageUrl: string imageUrl: string
notesPlaceholder: string notesPlaceholder: string
subject: (string | null)[] subject: (string | null)[]
@ -43,14 +45,16 @@ export function Channel({
return ( return (
<div className={className}> <div className={className}>
<div className={classes.channel}> <div className={classes.channel}>
<div className={select ? classes.cursor : classes.nocursor} onClick={select ? select : () => {}}> <div className={focused ? classes.focused : classes.unfocused}>
<Image radius="sm" className={classes.image} src={imageUrl} /> <div className={select ? classes.cursor : classes.nocursor} onClick={select ? select : () => {}}>
<div className={classes.details}> <Image radius="sm" className={classes.image} src={imageUrl} />
<span className={classes.subject}>{title}</span> <div className={classes.details}>
{message != null && <span className={classes.messageSet}>{message}</span>} <span className={classes.subject}>{title}</span>
{message == null && <span className={classes.messageUnset}>{messagePlaceholder}</span>} {message != null && <span className={classes.messageSet}>{message}</span>}
{message == null && <span className={classes.messageUnset}>{messagePlaceholder}</span>}
</div>
{unread && <div className={classes.unread} style={{ backgroundColor: Colors.connected }} />}
</div> </div>
{unread && <div className={classes.unread} style={{ backgroundColor: Colors.connected }} />}
</div> </div>
</div> </div>
</div> </div>

View File

@ -64,10 +64,6 @@
.channel { .channel {
width: 100%; width: 100%;
height: 48px; height: 48px;
padding-top: 8px;
padding-bottom: 8px;
padding-right: 16px;
padding-left: 16px;
border-bottom: 1px solid var(--mantine-color-text-8); border-bottom: 1px solid var(--mantine-color-text-8);
&:hover { &:hover {

View File

@ -74,6 +74,7 @@ export function Content() {
key={idx} key={idx}
className={classes.channel} className={classes.channel}
unread={channel.unread} unread={channel.unread}
focused={channel.focused}
imageUrl={channel.imageUrl} imageUrl={channel.imageUrl}
subject={channel.subject} subject={channel.subject}
messagePlaceholder={`[${state.strings.sealed}]`} messagePlaceholder={`[${state.strings.sealed}]`}

View File

@ -9,6 +9,7 @@ type ChannelParams = {
cardId: string cardId: string
channelId: string channelId: string
sealed: boolean sealed: boolean
focused: boolean
hosted: boolean hosted: boolean
unread: boolean unread: boolean
imageUrl: string imageUrl: string
@ -32,6 +33,7 @@ export function useContent() {
filter: '', filter: '',
topic: '', topic: '',
sealSet: false, sealSet: false,
focused: null as null|{cardId: null|string, channelId},
}) })
const compare = (a: Card, b: Card) => { const compare = (a: Card, b: Card) => {
@ -134,12 +136,13 @@ export function useContent() {
return '' return ''
} }
const focused = (state.focused?.cardId === cardId && state.focused?.channelId === channelId);
const hosted = cardId == null const hosted = cardId == null
const subject = data?.subject ? [data.subject] : buildSubject() const subject = data?.subject ? [data.subject] : buildSubject()
const message = getMessage() const message = getMessage()
const imageUrl = selectImage() const imageUrl = selectImage()
return { cardId, channelId, sealed, hosted, unread, imageUrl, subject, message } return { cardId, channelId, sealed, focused, hosted, unread, imageUrl, subject, message }
}) })
const search = state.filter?.toLowerCase() const search = state.filter?.toLowerCase()
@ -157,7 +160,16 @@ export function useContent() {
}) })
updateState({ filtered }) updateState({ filtered })
}, [state.sorted, state.cards, state.guid, state.filter]) }, [state.sorted, state.cards, state.guid, state.filter, state.focused])
useEffect(() => {
if (app.state.focus) {
const { cardId, channelId } = app.state.focus;
updateState({ focused: { cardId, channelId } });
} else {
updateState({ focused: null });
}
}, [app.state.focus]);
useEffect(() => { useEffect(() => {
const setConfig = (config: Config) => { const setConfig = (config: Config) => {

View File

@ -10,7 +10,7 @@ export function useAppContext() {
const sdk = useRef(databag) const sdk = useRef(databag)
const [state, setState] = useState({ const [state, setState] = useState({
session: null as null | Session, session: null as null | Session,
focus: null as null | Focus, focus: null as null | { cardId: null | string, channelId: string, thread: Focus },
}) })
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -84,8 +84,8 @@ export function useAppContext() {
}, },
setFocus: (cardId: string | null, channelId: string) => { setFocus: (cardId: string | null, channelId: string) => {
if (state.session) { if (state.session) {
const focus = state.session.setFocus(cardId, channelId); const thread = state.session.setFocus(cardId, channelId);
updateState({ focus }); updateState({ focus: {cardId, channelId, thread} });
} }
}, },
clearFocus: () => { clearFocus: () => {

View File

@ -34,7 +34,7 @@ export function useConversation() {
}, [display.state]) }, [display.state])
useEffect(() => { useEffect(() => {
const focus = app.state.focus; const focus = app.state.focus?.thread;
const { contact, identity } = app.state.session || { }; const { contact, identity } = app.state.session || { };
if (focus && contact && identity) { if (focus && contact && identity) {
const setTopics = (topics: Topic[]) => { const setTopics = (topics: Topic[]) => {
@ -87,7 +87,7 @@ export function useConversation() {
app.actions.clearFocus(); app.actions.clearFocus();
}, },
more: async () => { more: async () => {
const { focus } = app.state; const focus = app.state.focus?.thread;
if (focus) { if (focus) {
if (!state.loadingMore) { if (!state.loadingMore) {
updateState({ loadingMore: true }); updateState({ loadingMore: true });
@ -99,7 +99,7 @@ export function useConversation() {
} }
}, },
add: async (file: File) => { add: async (file: File) => {
const { focus } = app.state; const focus = app.state.focus?.thread;
if (focus) { if (focus) {
const asset = { const asset = {
name: 'topic', name: 'topic',

View File

@ -20,8 +20,8 @@ import { setContactChannelTopicSubject } from './net/setContactChannelTopicSubje
import { removeChannelTopic } from './net/removeChannelTopic'; import { removeChannelTopic } from './net/removeChannelTopic';
import { removeContactChannelTopic } from './net/removeContactChannelTopic'; import { removeContactChannelTopic } from './net/removeContactChannelTopic';
const BATCH_COUNT = 64; const BATCH_COUNT = 32;
const MIN_LOAD_SIZE = 32; const MIN_LOAD_SIZE = (BATCH_COUNT / 2);
const CLOSE_POLL_MS = 100; const CLOSE_POLL_MS = 100;
const RETRY_POLL_MS = 2000; const RETRY_POLL_MS = 2000;
const ENCRYPT_BLOCK_SIZE = 1048576; const ENCRYPT_BLOCK_SIZE = 1048576;