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[],