diff --git a/assets/icons/floppyDisk_stroke2_corner0_rounded.svg b/assets/icons/floppyDisk_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..b9a42f7594 --- /dev/null +++ b/assets/icons/floppyDisk_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index fe8cf9a789..3a02bb3af1 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -27,6 +27,18 @@ export const atoms = { right: 0, bottom: 0, }, + top_0: { + top: 0, + }, + left_0: { + left: 0, + }, + right_0: { + right: 0, + }, + bottom_0: { + bottom: 0, + }, z_10: { zIndex: 10, }, @@ -48,14 +60,20 @@ export const atoms = { }, /* - * Width + * Height / Width */ w_full: { width: '100%', }, + max_w_full: { + maxWidth: '100%', + }, h_full: { height: '100%', }, + max_h_full: { + maxHeight: '100%', + }, h_full_vh: web({ height: '100vh', }), @@ -878,6 +896,9 @@ export const atoms = { pointer_events_auto: { pointerEvents: 'auto', }, + pointer_events_box_none: { + pointerEvents: 'box-none', + }, user_select_none: { userSelect: 'none', }, @@ -935,4 +956,23 @@ export const atoms = { transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)', transitionDuration: '100ms', }), + + /* + * Opacity + */ + opacity_0: { + opacity: 0, + }, + opacity_25: { + opacity: 0.25, + }, + opacity_50: { + opacity: 0.5, + }, + opacity_75: { + opacity: 0.75, + }, + opacity_100: { + opacity: 1, + }, } as const diff --git a/src/components/icons/FloppyDisk.tsx b/src/components/icons/FloppyDisk.tsx new file mode 100644 index 0000000000..7fb938089a --- /dev/null +++ b/src/components/icons/FloppyDisk.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const FloppyDisk_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M3 4a1 1 0 0 1 1-1h13a1 1 0 0 1 .707.293l3 3A1 1 0 0 1 21 7v13a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4Zm6 15h6v-5H9v5Zm8 0v-6a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v6H5V5h2v3a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V5.414l2 2V19h-2ZM15 5H9v2h6V5Z', +}) diff --git a/src/view/com/lightbox/ImageViewing/index.tsx b/src/view/com/lightbox/ImageViewing/index.tsx index ab8306b36a..9ca4101e4d 100644 --- a/src/view/com/lightbox/ImageViewing/index.tsx +++ b/src/view/com/lightbox/ImageViewing/index.tsx @@ -9,13 +9,7 @@ // https://github.com/jobtoday/react-native-image-viewing import React, {useCallback, useState} from 'react' -import { - LayoutAnimation, - PixelRatio, - Platform, - StyleSheet, - View, -} from 'react-native' +import {LayoutAnimation, PixelRatio, Platform, View} from 'react-native' import {Gesture} from 'react-native-gesture-handler' import PagerView from 'react-native-pager-view' import Animated, { @@ -39,16 +33,18 @@ import { useSafeAreaFrame, useSafeAreaInsets, } from 'react-native-safe-area-context' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {Trans} from '@lingui/macro' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' import {Dimensions} from '#/lib/media/types' -import {colors, s} from '#/lib/styles' import {isIOS} from '#/platform/detection' import {Lightbox} from '#/state/lightbox' -import {Button} from '#/view/com/util/forms/Button' -import {Text} from '#/view/com/util/text/Text' import {ScrollView} from '#/view/com/util/Views' +import {atoms as a, ThemeProvider, useTheme} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ShareIcon} from '#/components/icons/ArrowOutOfBox' +import {FloppyDisk_Stroke2_Corner0_Rounded as SaveIcon} from '#/components/icons/FloppyDisk' +import {Text} from '#/components/Typography' import {PlatformInfo} from '../../../../../modules/expo-bluesky-swiss-army' import {ImageSource, Transform} from './@types' import ImageDefaultHeader from './components/ImageDefaultHeader' @@ -124,28 +120,34 @@ export default function ImageViewRoot({ }, [onRequestClose, openProgress]) return ( - // Keep it always mounted to avoid flicker on the first frame. - - - {activeLightbox && ( - - )} - - + + {/* Keep it always mounted to avoid flicker on the first frame. */} + + + {activeLightbox && ( + + )} + + + ) } @@ -208,11 +210,7 @@ function ImageView({ show && openProgress.value === 1 ? 1 : 0, FAST_SPRING, ), - transform: [ - { - translateY: withClampedSpring(show ? 0 : -30, FAST_SPRING), - }, - ], + transform: [{translateY: withClampedSpring(show ? 0 : -30, FAST_SPRING)}], } }) const animatedFooterStyle = useAnimatedStyle(() => { @@ -224,11 +222,7 @@ function ImageView({ show && openProgress.value === 1 ? 1 : 0, FAST_SPRING, ), - transform: [ - { - translateY: withClampedSpring(show ? 0 : 30, FAST_SPRING), - }, - ], + transform: [{translateY: withClampedSpring(show ? 0 : 30, FAST_SPRING)}], } }) @@ -261,9 +255,14 @@ function ImageView({ ) return ( - + + style={[a.flex_1]}> {images.map((imageSrc, i) => ( ))} - + @@ -486,11 +492,20 @@ function LightboxFooter({ onPressSave: (uri: string) => void onPressShare: (uri: string) => void }) { + const {_} = useLingui() + const t = useTheme() const {alt: altText, uri} = images[index] const isMomentumScrolling = React.useRef(false) return ( { isMomentumScrolling.current = true @@ -498,15 +513,12 @@ function LightboxFooter({ onMomentumScrollEnd={() => { isMomentumScrolling.current = false }} - contentContainerStyle={{ - paddingVertical: 12, - paddingHorizontal: 24, - }}> + contentContainerStyle={[a.py_md, a.px_2xl]}> {altText ? ( - + { @@ -524,104 +536,37 @@ function LightboxFooter({ ) : null} - - - - + + + + + + ) } -const styles = StyleSheet.create({ - screen: { - position: 'absolute', - top: 0, - left: 0, - bottom: 0, - right: 0, - }, - screenHidden: { - opacity: 0, - pointerEvents: 'none', - }, - container: { - flex: 1, - }, - backdrop: { - backgroundColor: '#000', - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - controls: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - gap: 20, - zIndex: 1, - pointerEvents: 'box-none', - }, - pager: { - flex: 1, - }, - header: { - position: 'absolute', - width: '100%', - top: 0, - pointerEvents: 'box-none', - }, - footer: { - position: 'absolute', - width: '100%', - maxHeight: '100%', - bottom: 0, - }, - footerScrollView: { - backgroundColor: '#000d', - flex: 1, - position: 'absolute', - bottom: 0, - width: '100%', - maxHeight: '100%', - }, - footerText: { - paddingBottom: isIOS ? 20 : 16, - }, - footerBtns: { - flexDirection: 'row', - justifyContent: 'center', - gap: 8, - }, - footerBtn: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - backgroundColor: 'transparent', - borderColor: colors.white, - }, -}) - function interpolatePx( px: number, inputRange: readonly number[],