mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-02 00:07:56 +01:00
View Once UI Updates
This commit is contained in:
@@ -40,18 +40,10 @@
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
|
||||
@include mixins.light-theme {
|
||||
@include mixins.color-svg(
|
||||
'../images/icons/v3/mic/mic.svg',
|
||||
variables.$color-gray-75
|
||||
);
|
||||
}
|
||||
@include mixins.dark-theme {
|
||||
@include mixins.color-svg(
|
||||
'../images/icons/v3/mic/mic.svg',
|
||||
variables.$color-gray-15
|
||||
);
|
||||
}
|
||||
@include mixins.color-svg(
|
||||
'../images/icons/v3/mic/mic.svg',
|
||||
var(--color-label-primary)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
&__popper {
|
||||
@include mixins.module-composition-popper;
|
||||
& {
|
||||
color: var(--color-label-primary);
|
||||
padding-block: 12px;
|
||||
padding-inline: 16px;
|
||||
width: auto;
|
||||
@@ -42,7 +43,7 @@
|
||||
&--selected {
|
||||
@include mixins.color-svg(
|
||||
'../images/icons/v3/check/check-compact.svg',
|
||||
variables.$color-ultramarine
|
||||
currentColor
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@
|
||||
.FunButton__Icon--EmojiPicker {
|
||||
@include mixins.color-svg(
|
||||
'../images/icons/v3/emoji/emoji.svg',
|
||||
light-dark(variables.$color-gray-75, variables.$color-gray-15)
|
||||
var(--color-label-primary)
|
||||
);
|
||||
}
|
||||
|
||||
.FunButton__Icon--StickerPicker {
|
||||
@include mixins.color-svg(
|
||||
'../images/icons/v3/sticker/sticker.svg',
|
||||
light-dark(variables.$color-gray-75, variables.$color-gray-15)
|
||||
var(--color-label-primary)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ export namespace AxoIconButton {
|
||||
variant: Variant;
|
||||
size: Size;
|
||||
symbol: AxoSymbol.IconName;
|
||||
iconWeight?: AxoSymbol.Weight;
|
||||
|
||||
experimentalSpinner?: { 'aria-label': string } | null;
|
||||
|
||||
@@ -130,6 +131,7 @@ export namespace AxoIconButton {
|
||||
variant,
|
||||
size,
|
||||
symbol,
|
||||
iconWeight,
|
||||
experimentalSpinner,
|
||||
...rest
|
||||
} = props;
|
||||
@@ -166,6 +168,7 @@ export namespace AxoIconButton {
|
||||
size={Sizes[size].iconSize}
|
||||
symbol={symbol}
|
||||
label={null}
|
||||
weight={iconWeight}
|
||||
/>
|
||||
</span>
|
||||
{experimentalSpinner != null && (
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { FC } from 'react';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { Direction } from 'radix-ui';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import type { TailwindStyles } from './tw.dom.js';
|
||||
import { tw } from './tw.dom.js';
|
||||
import {
|
||||
getAxoSymbolIcon,
|
||||
@@ -21,15 +22,22 @@ const Namespace = 'AxoSymbol';
|
||||
export namespace AxoSymbol {
|
||||
const symbolStyles = tw('font-symbols select-none');
|
||||
const labelStyles = tw('select-none');
|
||||
export type Weight = 300 | 400 | 700;
|
||||
const WeightStyles = {
|
||||
300: tw('font-light'),
|
||||
400: tw(),
|
||||
700: tw('font-semibold'),
|
||||
} as const satisfies Record<Weight, TailwindStyles>;
|
||||
|
||||
function useRenderSymbol(
|
||||
glyph: string,
|
||||
label: string | null
|
||||
label: string | null,
|
||||
weight: Weight
|
||||
): React.JSX.Element {
|
||||
return useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<span aria-hidden className={symbolStyles}>
|
||||
<span aria-hidden className={tw(symbolStyles, WeightStyles[weight])}>
|
||||
{glyph}
|
||||
</span>
|
||||
{label != null && (
|
||||
@@ -37,7 +45,7 @@ export namespace AxoSymbol {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}, [glyph, label]);
|
||||
}, [glyph, label, weight]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +63,7 @@ export namespace AxoSymbol {
|
||||
export const InlineGlyph: FC<InlineGlyphProps> = memo(props => {
|
||||
const direction = useDirection();
|
||||
const glyph = getAxoSymbolInlineGlyph(props.symbol, direction);
|
||||
const content = useRenderSymbol(glyph, props.label);
|
||||
const content = useRenderSymbol(glyph, props.label, 400);
|
||||
return content;
|
||||
});
|
||||
|
||||
@@ -89,6 +97,7 @@ export namespace AxoSymbol {
|
||||
size: IconSize;
|
||||
symbol: IconName;
|
||||
label: string | null;
|
||||
weight?: Weight;
|
||||
}>;
|
||||
|
||||
const iconStyles = tw(
|
||||
@@ -98,8 +107,9 @@ export namespace AxoSymbol {
|
||||
export const Icon: FC<IconProps> = memo(props => {
|
||||
const config = IconSizes[props.size];
|
||||
const direction = useDirection();
|
||||
const weight = props.weight ?? 400;
|
||||
const glyph = getAxoSymbolIcon(props.symbol, direction);
|
||||
const content = useRenderSymbol(glyph, props.label);
|
||||
const content = useRenderSymbol(glyph, props.label, weight);
|
||||
|
||||
const style = useMemo(() => {
|
||||
return {
|
||||
|
||||
@@ -1084,6 +1084,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||
<AxoSymbol.Icon
|
||||
size={20}
|
||||
symbol={isViewOnceActive ? 'viewonce' : 'viewonce-slash'}
|
||||
weight={300}
|
||||
label={null}
|
||||
/>
|
||||
</button>
|
||||
|
||||
@@ -1380,6 +1380,7 @@ export function MediaEditor({
|
||||
i18n={i18n}
|
||||
isHighQuality={localIsHighQuality}
|
||||
onSelectQuality={handleSelectQuality}
|
||||
theme={pickerTheme}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -6,6 +6,7 @@ import React, { useCallback, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Popover } from 'radix-ui';
|
||||
import type { LocalizerType } from '../types/Util.std.js';
|
||||
import { ThemeType } from '../types/Util.std.js';
|
||||
import { AxoIconButton } from '../axo/AxoIconButton.dom.js';
|
||||
|
||||
export type PropsType = {
|
||||
@@ -13,6 +14,7 @@ export type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
isHighQuality: boolean;
|
||||
onSelectQuality: (conversationId: string, isHQ: boolean) => unknown;
|
||||
theme?: ThemeType;
|
||||
};
|
||||
|
||||
export function MediaQualitySelector({
|
||||
@@ -20,6 +22,7 @@ export function MediaQualitySelector({
|
||||
i18n,
|
||||
isHighQuality,
|
||||
onSelectQuality,
|
||||
theme,
|
||||
}: PropsType): React.JSX.Element {
|
||||
const [open, setOpen] = useState(false);
|
||||
const standardRef = useRef<HTMLButtonElement>(null);
|
||||
@@ -56,78 +59,88 @@ export function MediaQualitySelector({
|
||||
variant="borderless-secondary"
|
||||
size="md"
|
||||
symbol={isHighQuality ? 'hd' : 'hd-slash'}
|
||||
iconWeight={300}
|
||||
label={i18n('icu:MediaQualitySelector--button')}
|
||||
tooltip={false}
|
||||
/>
|
||||
</Popover.Trigger>
|
||||
{open && (
|
||||
<Popover.Portal>
|
||||
<Popover.Content
|
||||
className="MediaQualitySelector__popper"
|
||||
side="top"
|
||||
align="start"
|
||||
sideOffset={4}
|
||||
onOpenAutoFocus={handleOpenAutoFocus}
|
||||
onKeyDown={handleContentKeyDown}
|
||||
<div
|
||||
className={classNames({
|
||||
'light-theme': theme === ThemeType.light,
|
||||
'dark-theme': theme === ThemeType.dark,
|
||||
})}
|
||||
>
|
||||
<div className="MediaQualitySelector__title">
|
||||
{i18n('icu:MediaQualitySelector--title')}
|
||||
</div>
|
||||
<button
|
||||
ref={standardRef}
|
||||
aria-label={i18n(
|
||||
'icu:MediaQualitySelector--standard-quality-title'
|
||||
)}
|
||||
className="MediaQualitySelector__option"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onSelectQuality(conversationId, false);
|
||||
setOpen(false);
|
||||
}}
|
||||
<Popover.Content
|
||||
className="MediaQualitySelector__popper"
|
||||
side="top"
|
||||
align="start"
|
||||
sideOffset={4}
|
||||
onOpenAutoFocus={handleOpenAutoFocus}
|
||||
onKeyDown={handleContentKeyDown}
|
||||
>
|
||||
<div
|
||||
className={classNames({
|
||||
'MediaQualitySelector__option--checkmark': true,
|
||||
'MediaQualitySelector__option--selected': !isHighQuality,
|
||||
})}
|
||||
/>
|
||||
<div>
|
||||
<div className="MediaQualitySelector__option--title">
|
||||
{i18n('icu:MediaQualitySelector--standard-quality-title')}
|
||||
</div>
|
||||
<div className="MediaQualitySelector__option--description">
|
||||
{i18n(
|
||||
'icu:MediaQualitySelector--standard-quality-description'
|
||||
)}
|
||||
</div>
|
||||
<div className="MediaQualitySelector__title">
|
||||
{i18n('icu:MediaQualitySelector--title')}
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
ref={highRef}
|
||||
aria-label={i18n('icu:MediaQualitySelector--high-quality-title')}
|
||||
className="MediaQualitySelector__option"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onSelectQuality(conversationId, true);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={classNames({
|
||||
'MediaQualitySelector__option--checkmark': true,
|
||||
'MediaQualitySelector__option--selected': isHighQuality,
|
||||
})}
|
||||
/>
|
||||
<div>
|
||||
<div className="MediaQualitySelector__option--title">
|
||||
{i18n('icu:MediaQualitySelector--high-quality-title')}
|
||||
<button
|
||||
ref={standardRef}
|
||||
aria-label={i18n(
|
||||
'icu:MediaQualitySelector--standard-quality-title'
|
||||
)}
|
||||
className="MediaQualitySelector__option"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onSelectQuality(conversationId, false);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={classNames({
|
||||
'MediaQualitySelector__option--checkmark': true,
|
||||
'MediaQualitySelector__option--selected': !isHighQuality,
|
||||
})}
|
||||
/>
|
||||
<div>
|
||||
<div className="MediaQualitySelector__option--title">
|
||||
{i18n('icu:MediaQualitySelector--standard-quality-title')}
|
||||
</div>
|
||||
<div className="MediaQualitySelector__option--description">
|
||||
{i18n(
|
||||
'icu:MediaQualitySelector--standard-quality-description'
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="MediaQualitySelector__option--description">
|
||||
{i18n('icu:MediaQualitySelector--high-quality-description')}
|
||||
</button>
|
||||
<button
|
||||
ref={highRef}
|
||||
aria-label={i18n(
|
||||
'icu:MediaQualitySelector--high-quality-title'
|
||||
)}
|
||||
className="MediaQualitySelector__option"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onSelectQuality(conversationId, true);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={classNames({
|
||||
'MediaQualitySelector__option--checkmark': true,
|
||||
'MediaQualitySelector__option--selected': isHighQuality,
|
||||
})}
|
||||
/>
|
||||
<div>
|
||||
<div className="MediaQualitySelector__option--title">
|
||||
{i18n('icu:MediaQualitySelector--high-quality-title')}
|
||||
</div>
|
||||
<div className="MediaQualitySelector__option--description">
|
||||
{i18n('icu:MediaQualitySelector--high-quality-description')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</Popover.Content>
|
||||
</button>
|
||||
</Popover.Content>
|
||||
</div>
|
||||
</Popover.Portal>
|
||||
)}
|
||||
</Popover.Root>
|
||||
|
||||
Reference in New Issue
Block a user