diff --git a/icons/UserAvatar.tsx b/icons/UserAvatar.tsx
deleted file mode 100644
index ab39982..0000000
--- a/icons/UserAvatar.tsx
+++ /dev/null
@@ -1,484 +0,0 @@
-// https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/view/com/util/UserAvatar.tsx
-import React, {memo, useMemo} from 'react'
-import {Image, Pressable, StyleSheet, View} from 'react-native'
-import {Image as RNImage} from 'react-native-image-crop-picker'
-import Svg, {Circle, Path, Rect} from 'react-native-svg'
-import {AppBskyActorDefs, ModerationUI} from '@atproto/api'
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {useQueryClient} from '@tanstack/react-query'
-
-import {usePalette} from '#/lib/hooks/usePalette'
-import {
- useCameraPermission,
- usePhotoLibraryPermission,
-} from '#/lib/hooks/usePermissions'
-import {makeProfileLink} from '#/lib/routes/links'
-import {colors} from '#/lib/styles'
-import {logger} from '#/logger'
-import {isAndroid, isNative, isWeb} from '#/platform/detection'
-import {precacheProfile} from '#/state/queries/profile'
-import {HighPriorityImage} from '#/view/com/util/images/Image'
-import {tokens, useTheme} from '#/alf'
-import {useSheetWrapper} from '#/components/Dialog/sheet-wrapper'
-import {
- Camera_Filled_Stroke2_Corner0_Rounded as CameraFilled,
- Camera_Stroke2_Corner0_Rounded as Camera,
-} from '#/components/icons/Camera'
-import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
-import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
-import {Link} from '#/components/Link'
-import {MediaInsetBorder} from '#/components/MediaInsetBorder'
-import * as Menu from '#/components/Menu'
-import {ProfileHoverCard} from '#/components/ProfileHoverCard'
-import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
-
-export type UserAvatarType = 'user' | 'algo' | 'list' | 'labeler'
-
-interface BaseUserAvatarProps {
- type?: UserAvatarType
- shape?: 'circle' | 'square'
- size: number
- avatar?: string | null
-}
-
-interface UserAvatarProps extends BaseUserAvatarProps {
- moderation?: ModerationUI
- usePlainRNImage?: boolean
- onLoad?: () => void
-}
-
-interface EditableUserAvatarProps extends BaseUserAvatarProps {
- onSelectNewAvatar: (img: RNImage | null) => void
-}
-
-interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
- moderation?: ModerationUI
- profile: AppBskyActorDefs.ProfileViewBasic
- disableHoverCard?: boolean
- onBeforePress?: () => void
-}
-
-const BLUR_AMOUNT = isWeb ? 5 : 100
-
-let DefaultAvatar = ({
- type,
- shape: overrideShape,
- size,
-}: {
- type: UserAvatarType
- shape?: 'square' | 'circle'
- size: number
-}): React.ReactNode => {
- const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
- if (type === 'algo') {
- // TODO: shape=circle
- // Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
- return (
-
- )
- }
- if (type === 'list') {
- // TODO: shape=circle
- // Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
- return (
-
- )
- }
- if (type === 'labeler') {
- return (
-
- )
- }
- // TODO: shape=square
- return (
-
- )
-}
-DefaultAvatar = memo(DefaultAvatar)
-export {DefaultAvatar}
-
-let UserAvatar = ({
- type = 'user',
- shape: overrideShape,
- size,
- avatar,
- moderation,
- usePlainRNImage = false,
- onLoad,
-}: UserAvatarProps): React.ReactNode => {
- const pal = usePalette('default')
- const backgroundColor = pal.colors.backgroundLight
- const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
-
- const aviStyle = useMemo(() => {
- if (finalShape === 'square') {
- return {
- width: size,
- height: size,
- borderRadius: size > 32 ? 8 : 3,
- backgroundColor,
- }
- }
- return {
- width: size,
- height: size,
- borderRadius: Math.floor(size / 2),
- backgroundColor,
- }
- }, [finalShape, size, backgroundColor])
-
- const alert = useMemo(() => {
- if (!moderation?.alert) {
- return null
- }
- return (
-
-
-
- )
- }, [moderation?.alert, size, pal])
-
- return avatar &&
- !((moderation?.blur && isAndroid) /* android crashes with blur */) ? (
-
- {usePlainRNImage ? (
-
- ) : (
-
- )}
-
- {alert}
-
- ) : (
-
-
- {alert}
-
- )
-}
-UserAvatar = memo(UserAvatar)
-export {UserAvatar}
-
-let EditableUserAvatar = ({
- type = 'user',
- size,
- avatar,
- onSelectNewAvatar,
-}: EditableUserAvatarProps): React.ReactNode => {
- const t = useTheme()
- const pal = usePalette('default')
- const {_} = useLingui()
- const {requestCameraAccessIfNeeded} = useCameraPermission()
- const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
- const sheetWrapper = useSheetWrapper()
-
- const aviStyle = useMemo(() => {
- if (type === 'algo' || type === 'list') {
- return {
- width: size,
- height: size,
- borderRadius: size > 32 ? 8 : 3,
- }
- }
- return {
- width: size,
- height: size,
- borderRadius: Math.floor(size / 2),
- }
- }, [type, size])
-
- const onOpenCamera = React.useCallback(async () => {
- if (!(await requestCameraAccessIfNeeded())) {
- return
- }
-
- onSelectNewAvatar(
- await openCamera({
- width: 1000,
- height: 1000,
- cropperCircleOverlay: true,
- }),
- )
- }, [onSelectNewAvatar, requestCameraAccessIfNeeded])
-
- const onOpenLibrary = React.useCallback(async () => {
- if (!(await requestPhotoAccessIfNeeded())) {
- return
- }
-
- const items = await sheetWrapper(
- openPicker({
- aspect: [1, 1],
- }),
- )
- const item = items[0]
- if (!item) {
- return
- }
-
- try {
- const croppedImage = await openCropper({
- mediaType: 'photo',
- cropperCircleOverlay: true,
- height: 1000,
- width: 1000,
- path: item.path,
- webAspectRatio: 1,
- webCircularCrop: true,
- })
-
- onSelectNewAvatar(croppedImage)
- } catch (e: any) {
- // Don't log errors for cancelling selection to sentry on ios or android
- if (!String(e).toLowerCase().includes('cancel')) {
- logger.error('Failed to crop banner', {error: e})
- }
- }
- }, [onSelectNewAvatar, requestPhotoAccessIfNeeded, sheetWrapper])
-
- const onRemoveAvatar = React.useCallback(() => {
- onSelectNewAvatar(null)
- }, [onSelectNewAvatar])
-
- return (
-
-
- {({props}) => (
-
- {avatar ? (
- 0), }}
- accessibilityRole="image"
- />
- ) : (
-
- )}
-
-
-
-
- )}
-
-
-
- {isNative && (
-
-
- Upload from Camera
-
-
-
- )}
-
-
-
- {isNative ? (
- Upload from Library
- ) : (
- Upload from Files
- )}
-
-
-
-
- {!!avatar && (
- <>
-
-
-
-
- Remove Avatar
-
-
-
-
- >
- )}
-
-
- )
-}
-EditableUserAvatar = memo(EditableUserAvatar)
-export {EditableUserAvatar}
-
-let PreviewableUserAvatar = ({
- moderation,
- profile,
- disableHoverCard,
- onBeforePress,
- ...rest
-}: PreviewableUserAvatarProps): React.ReactNode => {
- const {_} = useLingui()
- const queryClient = useQueryClient()
-
- const onPress = React.useCallback(() => {
- onBeforePress?.()
- precacheProfile(queryClient, profile)
- }, [profile, queryClient, onBeforePress])
-
- return (
-
-
-
-
-
- )
-}
-PreviewableUserAvatar = memo(PreviewableUserAvatar)
-export {PreviewableUserAvatar}
-
-// HACK
-// We have started serving smaller avis but haven't updated lexicons to give the data properly
-// manually string-replace to use the smaller ones
-// -prf
-function hackModifyThumbnailPath(uri: string, isEnabled: boolean): string {
- return isEnabled
-// ? uri.replace('/img/avatar/plain/', '/img/avatar_thumbnail/plain/')
- ? uri.replace('https://cdn.bsky.app/img/avatar/plain/', 'https://bsky.syu.is/img/avatar/plain/')
- : uri
-}
-
-const styles = StyleSheet.create({
- editButtonContainer: {
- position: 'absolute',
- width: 24,
- height: 24,
- bottom: 0,
- right: 0,
- borderRadius: 12,
- alignItems: 'center',
- justifyContent: 'center',
- backgroundColor: colors.gray5,
- },
- alertIconContainer: {
- position: 'absolute',
- right: 0,
- bottom: 0,
- borderRadius: 100,
- },
- alertIcon: {
- color: colors.red3,
- },
-})
diff --git a/install.zsh b/install.zsh
index 6638e41..58823ba 100755
--- a/install.zsh
+++ b/install.zsh
@@ -194,19 +194,21 @@ run_update() {
}
web_write() {
- echo $d/repos/social-app/src
- cd $d/repos/social-app/src
- grep -R bsky.social .|cut -d : -f 1|sort -u|xargs sed -i "s/bsky.social/syu.is/g"
- grep -R bsky.app .|cut -d : -f 1|sort -u|xargs sed -i "s/bsky.app/web.syu.is/g"
- grep -R public.api.syu.is ./lib/constants.ts | cut -d : -f 1|sort -u|xargs sed -i "s/public.api/bsky/g"
+ dt=$d/repos/social-app/src
+ cd $dt
+ grep -R bsky.social .|cut -d : -f 1|sort -u|xargs sed -i "s/bsky.social/syu.is/g"
+ grep -R bsky.app .|cut -d : -f 1|sort -u|xargs sed -i "s/bsky.app/web.syu.is/g"
+ grep -R public.api.syu.is ./lib/constants.ts | cut -d : -f 1|sort -u|xargs sed -i "s/public.api/bsky/g"
- f=./view/icons/Logotype.tsx
- o=$d/icons/Logotype.tsx
- cp -rf $o $f
+ f=$dt/view/icons/Logotype.tsx
+ o=$d/icons/Logotype.tsx
+ cp -rf $o $f
- f=./view/com/util/UserAvatar.tsx
- o=$d/icons/UserAvatar.tsx
- cp -rf $o $f
+ #curl -sL https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/view/com/util/UserAvatar.tsx -o $f
+ f=$dt/view/com/util/UserAvatar.tsx
+ sed -i $t "s#/img/avatar/plain/#https://cdn.bsky.app/img/avatar/plain/#g" $f
+ sed -i $t "s#/img/avatar_thumbnail/plain/#https://bsky.syu.is/img/avatar/plain/#g" $f
+ sed -i $t "s#source={{uri: avatar}}#source={{ uri: hackModifyThumbnailPath(avatar, 1 > 0), }}#g" $f
}
case $1 in
diff --git a/repos/indigo b/repos/indigo
new file mode 160000
index 0000000..c130614
--- /dev/null
+++ b/repos/indigo
@@ -0,0 +1 @@
+Subproject commit c130614850e554f9862d8e649373b53cee86dd3b
diff --git a/repos/social-app b/repos/social-app
deleted file mode 160000
index f6649e2..0000000
--- a/repos/social-app
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit f6649e22a762fa8f4d3060da0a274f3b83ecb06f