Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-various-visual-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Various visual tweaks
2 changes: 1 addition & 1 deletion src/app/components/emoji-board/components/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export function GifItem({
>
{menuIcon(Star, {
weight: favorited ? 'fill' : 'regular',
color: favorited ? color.Warning.MainHover : color.Surface.OnContainer,
color: favorited ? color.Warning.MainHover : color.Secondary.OnContainer,
})}
</MenuItem>
<MenuItem
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/message/MsgTypeRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function BrokenContent({ body }: BrokenContentProps) {
);
}

function getIncomingMediaMxcUrl(url: unknown): string | undefined {
export function getIncomingMediaMxcUrl(url: unknown): string | undefined {
return typeof url === 'string' && url.startsWith('mxc://') ? url : undefined;
}

Expand Down
31 changes: 20 additions & 11 deletions src/app/components/message/content/ImageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ function thumbnailDimsForMaxEdge(
};
}

export function checkIfGif(url: string, mimetype?: string, body?: string) {
return (
mimetype === 'image/avif' ||
mimetype === 'image/gif' ||
mimetype === 'image/apng' ||
mimetype === 'image/webp' ||
(body ?? '').toLowerCase().endsWith('.avif') ||
(body ?? '').toLowerCase().endsWith('.gif') ||
(body ?? '').toLowerCase().endsWith('.apng') ||
(body ?? '').toLowerCase().endsWith('.webp') ||
url.toLowerCase().endsWith('.avif') ||
url.toLowerCase().endsWith('.gif') ||
url.toLowerCase().endsWith('.apng') ||
url.toLowerCase().endsWith('.webp') ||
false
);
}

type RenderViewerProps = {
src: string;
alt: string;
Expand Down Expand Up @@ -140,16 +158,7 @@ export const ImageContent = as<'div', ImageContentProps>(
favoritedContent.gifs.find((v) => v.url == url) != undefined
);

const isGif =
info?.mimetype === 'image/gif' ||
info?.mimetype === 'image/apng' ||
info?.mimetype === 'image/webp' ||
(body ?? '').toLowerCase().endsWith('.gif') ||
(body ?? '').toLowerCase().endsWith('.apng') ||
(body ?? '').toLowerCase().endsWith('.webp') ||
url.toLowerCase().endsWith('.gif') ||
url.toLowerCase().endsWith('.apng') ||
url.toLowerCase().endsWith('.webp');
const isGif = checkIfGif(url, info?.mimetype, body);

const [srcState, loadSrc] = useAsyncCallback(
useCallback(async () => {
Expand Down Expand Up @@ -464,7 +473,7 @@ export const ImageContent = as<'div', ImageContentProps>(
>
{menuIcon(Star, {
weight: favorited ? 'fill' : 'regular',
color: favorited ? color.Warning.MainHover : color.Surface.OnContainer,
color: favorited ? color.Warning.MainHover : color.Secondary.OnContainer,
})}
</MenuItem>
)}
Expand Down
80 changes: 79 additions & 1 deletion src/app/components/message/modals/Options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ import {
} from '$features/bookmarks';
import { CopyIcon } from '@phosphor-icons/react';
import * as OptionsCss from './Options.css';
import { MATRIX_SABLE_UNSTABLE_FAVORITE_GIFS } from '$unstable/prefixes';
import { useFavoriteGifs } from '$hooks/useFavoriteGifs';
import type { IImageInfo } from '$types/matrix/common';
import { getIncomingMediaMxcUrl } from '../MsgTypeRenderers';

function WrappedMessage({
isModal,
Expand Down Expand Up @@ -239,7 +243,9 @@ export const MessageBookmarkItem = as<
return (
<MenuItem
size="300"
after={menuIcon(BookmarkIcon)}
after={menuIcon(BookmarkIcon, {
weight: bookmarked ? 'fill' : 'regular',
})}
radii="300"
onClick={handleClick}
{...props}
Expand All @@ -252,6 +258,70 @@ export const MessageBookmarkItem = as<
);
});

export const MessageFavoriteGifItem = as<
'button',
{
room: Room;
mEvent: MatrixEvent;
onClose?: () => void;
}
>(({ room, mEvent, onClose, ...props }, ref) => {
const mx = useMatrixClient();
const content = mEvent.getContent();
const url = getIncomingMediaMxcUrl(content.file?.url ?? content.url) ?? '';
const favoritedContent = useFavoriteGifs();
const [favorited, setFavorited] = useState(
favoritedContent.gifs.find((v) => v.url == url) != undefined
);
const handleClick = async () => {
if (!favorited) {
const info: IImageInfo | undefined = content?.info;
const body = content?.body;
setFavorited(true);
await mx
.setAccountData(MATRIX_SABLE_UNSTABLE_FAVORITE_GIFS, {
gifs: [
...favoritedContent.gifs,
{
title: body ?? '',
url: url,
width: info?.w,
height: info?.h,
size: info?.size,
mimetype: info?.mimetype,
},
],
})
.catch(() => setFavorited(false));
} else {
setFavorited(false);
await mx
.setAccountData(MATRIX_SABLE_UNSTABLE_FAVORITE_GIFS, {
gifs: favoritedContent.gifs.filter((v) => v.url != url),
})
.catch(() => setFavorited(true));
}

onClose?.();
};
return (
<MenuItem
size="300"
after={menuIcon(Star, {
weight: favorited ? 'fill' : 'regular',
})}
radii="300"
onClick={handleClick}
{...props}
ref={ref}
>
<Text className={css.MessageMenuItemText} as="span" size="T300" truncate>
{favorited ? 'Unfavorite Gif' : 'Favorite Gif'}
</Text>
</MenuItem>
);
});

export type OptionEmojiMenuProps = {
mEvent: MatrixEvent;
closeMenu: () => void;
Expand Down Expand Up @@ -334,6 +404,7 @@ export function OptionQuickMenu({
menuAnchor,
imagePackRooms,
setIsEmoji,
isGif,
}: OptionMenuProps) {
const mx = useMatrixClient();
const isThreadedMessage = isThreadRelationEvent(mEvent, mEvent.threadRootId);
Expand Down Expand Up @@ -438,6 +509,7 @@ export function OptionQuickMenu({
setIsEmoji={setIsEmoji}
emojiBoardAnchor={menuAnchor}
canSendReaction={canSendReaction}
isGif={isGif}
/>
}
>
Expand Down Expand Up @@ -484,6 +556,7 @@ export type OptionMenuProps = {
canDelete?: boolean;
handleOpenMenu?: MouseEventHandler<HTMLButtonElement>;
menuAnchor?: RectCords | undefined;
isGif?: boolean;

emojiBoardAnchor?: RectCords;
imagePackRooms?: Room[];
Expand Down Expand Up @@ -511,6 +584,7 @@ export function OptionMenu({
ActualMessage,
isModal,
dragOpts,
isGif,
}: OptionMenuProps) {
const setModal = useSetAtom(modalAtom);
const store = useStore();
Expand Down Expand Up @@ -665,6 +739,9 @@ export function OptionMenu({
{relations && (
<MessageAllReactionItem room={room} relations={relations} closeMenu={closeMenu} />
)}
{isGif && isModal && (
<MessageFavoriteGifItem room={room} mEvent={mEvent} onClose={closeMenu} />
)}
<MenuItem
size="300"
after={menuIcon(ArrowBendUpLeftIcon)}
Expand Down Expand Up @@ -852,6 +929,7 @@ export function MobileOptionsInternal({ options }: { options: OptionMenuProps })
canSendReaction={options.canSendReaction}
isModal
dragOpts={dragOpts}
isGif={options.isGif}
/>
</Box>
</Box>
Expand Down
7 changes: 4 additions & 3 deletions src/app/components/user-profile/UserRoomProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,10 @@ function UserExtendedSection({

const catStatusText = useMemo(() => {
if (!renderAnimals) return null;
if (isAnimal && hasAnimal) return `${isAnimal} with ${hasAnimal}, give ${animalNeed}!`;
if (isAnimal) return `Is ${isAnimal}, give ${animalNeed}!`;
if (hasAnimal) return `Has ${hasAnimal}, give ${animalNeed}!`;
const animalGive = animalNeed ? `, give ${animalNeed}!` : '!';
if (isAnimal && hasAnimal) return `${isAnimal} with ${hasAnimal}${animalGive}`;
if (isAnimal) return `Is ${isAnimal}${animalGive}`;
if (hasAnimal) return `Has ${hasAnimal}${animalGive}`;
return null;
}, [renderAnimals, isAnimal, hasAnimal, animalNeed]);

Expand Down
9 changes: 9 additions & 0 deletions src/app/features/room/message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { useSetAtom } from 'jotai';
import {
AvatarBase,
BubbleLayout,
checkIfGif,
CompactLayout,
MessageBase,
ModernLayout,
Expand Down Expand Up @@ -381,6 +382,12 @@ function MessageInternal(
const setModal = useSetAtom(modalAtom);
const [contentVersion, setContentVersion] = useState(0);

const isGif = useMemo(() => {
const content = mEvent.getContent();
if (content.msgtype !== 'm.image') return false;
return checkIfGif(content?.info?.url ?? '', content?.info?.mimetype, content?.body);
}, [mEvent]);

useEffect(() => {
const triggerTimelineRegroup = () => {
// A Local Echo update seems to trigger a visual refresh without
Expand Down Expand Up @@ -848,6 +855,7 @@ function MessageInternal(
</div>
),
canSendReaction: canSendReaction,
isGif: isGif,
},
});
};
Expand Down Expand Up @@ -944,6 +952,7 @@ function MessageInternal(
imagePackRooms={imagePackRooms}
setIsEmoji={setIsEmoji}
canSendReaction={canSendReaction}
isGif={isGif}
/>
</div>
)}
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/client/profile/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,8 @@ export function ProfileMobile() {
<Line variant="Surface" size="300" />
<MenuItem
size="300"
variant="Background"
style={{ color: color.Critical.OnContainer }}
variant="Critical"
fill="None"
before={menuIcon(SignOutIcon)}
onClick={() => setLogout(true)}
>
Expand All @@ -267,7 +267,7 @@ export function ProfileMobile() {
</>
)}
</UseStateProvider>
<div style={{ height: toRem(132) }} />
<div style={{ height: '20vh' }} />
</Box>
</Menu>
</Box>
Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/client/sidebar/UserMenuTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export function AccountMenuOption({ isMobile, isRight }: { isMobile: boolean; is
background: isMobile
? color.Background.Container
: isOpen
? color.Secondary.Container
? color.Surface.ContainerHover
: color.Surface.Container,
}}
onClick={() => isMobile && setIsOpen(!isOpen)}
Expand Down Expand Up @@ -501,7 +501,7 @@ export function PresenceMenuOption({
background: isMobile
? color.Background.Container
: isOpen
? color.Secondary.Container
? color.Surface.ContainerHover
: color.Surface.Container,
}}
onClick={() => isMobile && setIsOpen(!isOpen)}
Expand Down
Loading