Fix gallery footer author image showing old image (#7910)
* Fix gallery footer author image showing old image * Fix tests * Address feedback * Fix tests and minor refactor
This commit is contained in:
parent
a6d043670a
commit
b98c184e7c
17 changed files with 422 additions and 389 deletions
|
|
@ -229,7 +229,7 @@ export async function fetchMyTeam(serverUrl: string, teamId: string, fetchOnly =
|
|||
}
|
||||
}
|
||||
|
||||
export const fetchAllTeams = async (serverUrl: string, page = 0, perPage = PER_PAGE_DEFAULT): Promise<{teams?: Team[]; error?: any}> => {
|
||||
export const fetchAllTeams = async (serverUrl: string, page = 0, perPage = PER_PAGE_DEFAULT): Promise<{teams?: Team[]; error?: unknown}> => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const teams = await client.getTeams(page, perPage);
|
||||
|
|
@ -475,3 +475,12 @@ export async function getTeamMembersByIds(serverUrl: string, teamId: string, use
|
|||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const buildTeamIconUrl = (serverUrl: string, teamId: string, timestamp = 0) => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
return client.getTeamIconUrl(teamId, timestamp);
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import {getCurrentUser, prepareUsers, queryAllUsers, queryUsersById, queryUsersB
|
|||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {getDeviceTimezone} from '@utils/timezone';
|
||||
import {getUserTimezoneProps, removeUserFromList} from '@utils/user';
|
||||
import {getLastPictureUpdate, getUserTimezoneProps, removeUserFromList} from '@utils/user';
|
||||
|
||||
import {fetchGroupsByNames} from './groups';
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
|
@ -796,6 +796,11 @@ export const buildProfileImageUrl = (serverUrl: string, userId: string, timestam
|
|||
}
|
||||
};
|
||||
|
||||
export const buildProfileImageUrlFromUser = (serverUrl: string, user: UserModel | UserProfile) => {
|
||||
const lastPictureUpdate = getLastPictureUpdate(user);
|
||||
return buildProfileImageUrl(serverUrl, user.id, lastPictureUpdate);
|
||||
};
|
||||
|
||||
export const autoUpdateTimezone = async (serverUrl: string) => {
|
||||
let database;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -6,16 +6,15 @@ import {useIntl} from 'react-intl';
|
|||
import {Keyboard, Platform, StyleSheet, TouchableOpacity, View} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import ProfilePicture from '@components/profile_picture';
|
||||
import {Screens, View as ViewConstant} from '@constants';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {openAsBottomSheet} from '@screens/navigation';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
|
|
@ -37,12 +36,6 @@ const Avatar = ({author, enablePostIconOverride, isAutoReponse, location, post}:
|
|||
const intl = useIntl();
|
||||
const theme = useTheme();
|
||||
const serverUrl = useServerUrl();
|
||||
let client: Client | undefined;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch {
|
||||
// do nothing, client is not set
|
||||
}
|
||||
|
||||
const fromWebHook = post.props?.from_webhook === 'true';
|
||||
const iconOverride = enablePostIconOverride && post.props?.use_user_icon !== 'true';
|
||||
|
|
@ -51,7 +44,7 @@ const Avatar = ({author, enablePostIconOverride, isAutoReponse, location, post}:
|
|||
const frameSize = ViewConstant.PROFILE_PICTURE_SIZE;
|
||||
const pictureSize = isEmoji ? ViewConstant.PROFILE_PICTURE_EMOJI_SIZE : ViewConstant.PROFILE_PICTURE_SIZE;
|
||||
const borderRadius = isEmoji ? 0 : ViewConstant.PROFILE_PICTURE_SIZE / 2;
|
||||
const overrideIconUrl = client?.getAbsoluteUrl(post.props?.override_icon_url);
|
||||
const overrideIconUrl = buildAbsoluteUrl(serverUrl, post.props?.override_icon_url);
|
||||
|
||||
let iconComponent: ReactNode;
|
||||
if (overrideIconUrl) {
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ import {Image as RNImage} from 'react-native';
|
|||
import FastImage, {type Source} from 'react-native-fast-image';
|
||||
import Animated from 'react-native-reanimated';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {ACCOUNT_OUTLINE_IMAGE} from '@constants/profile';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type Props = {
|
||||
|
|
@ -49,6 +49,15 @@ const Image = ({author, forwardRef, iconSize, size, source, url}: Props) => {
|
|||
width: size,
|
||||
}), [size]);
|
||||
|
||||
const imgSource = useMemo(() => {
|
||||
if (!author || typeof source === 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const pictureUrl = buildProfileImageUrlFromUser(serverUrl, author);
|
||||
return source ?? {uri: buildAbsoluteUrl(serverUrl, pictureUrl)};
|
||||
}, [author, serverUrl, source]);
|
||||
|
||||
if (typeof source === 'string') {
|
||||
return (
|
||||
<CompassIcon
|
||||
|
|
@ -59,38 +68,21 @@ const Image = ({author, forwardRef, iconSize, size, source, url}: Props) => {
|
|||
);
|
||||
}
|
||||
|
||||
let client: Client | undefined;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch {
|
||||
// handle below that the client is not set
|
||||
if (imgSource?.uri?.startsWith('file://')) {
|
||||
return (
|
||||
<AnimatedImage
|
||||
key={imgSource.uri}
|
||||
ref={forwardRef}
|
||||
style={fIStyle}
|
||||
source={{uri: imgSource.uri}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (author && client) {
|
||||
let lastPictureUpdate = 0;
|
||||
const isBot = ('isBot' in author) ? author.isBot : author.is_bot;
|
||||
if (isBot) {
|
||||
lastPictureUpdate = ('isBot' in author) ? author.props?.bot_last_icon_update : author.bot_last_icon_update || 0;
|
||||
} else {
|
||||
lastPictureUpdate = ('lastPictureUpdate' in author) ? author.lastPictureUpdate : author.last_picture_update || 0;
|
||||
}
|
||||
|
||||
const pictureUrl = client.getProfilePictureUrl(author.id, lastPictureUpdate);
|
||||
const imgSource = source ?? {uri: `${serverUrl}${pictureUrl}`};
|
||||
if (imgSource.uri?.startsWith('file://')) {
|
||||
return (
|
||||
<AnimatedImage
|
||||
key={pictureUrl}
|
||||
ref={forwardRef}
|
||||
style={fIStyle}
|
||||
source={{uri: imgSource.uri}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (imgSource) {
|
||||
return (
|
||||
<AnimatedFastImage
|
||||
key={pictureUrl}
|
||||
key={imgSource.uri}
|
||||
|
||||
// @ts-expect-error TS expects old type ref
|
||||
ref={forwardRef}
|
||||
|
|
@ -99,6 +91,7 @@ const Image = ({author, forwardRef, iconSize, size, source, url}: Props) => {
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<CompassIcon
|
||||
name={ACCOUNT_OUTLINE_IMAGE}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
|||
import {View, Text, type StyleProp, type TextStyle} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildTeamIconUrl} from '@actions/remote/team';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
|
|
@ -124,7 +126,7 @@ export default function TeamIcon({
|
|||
teamIconContent = (
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{uri: `${serverUrl}${client!.getTeamIconUrl(id, lastIconUpdate)}`}}
|
||||
source={{uri: buildAbsoluteUrl(serverUrl, buildTeamIconUrl(serverUrl, id, lastIconUpdate))}}
|
||||
onError={handleImageError}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,43 +9,7 @@ exports[`components/channel_list_row should show no results 1`] = `
|
|||
"flexGrow": 1,
|
||||
}
|
||||
}
|
||||
data={
|
||||
[
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"auth_service": "",
|
||||
"create_at": 1111,
|
||||
"delete_at": 0,
|
||||
"email": "john@doe.com",
|
||||
"first_name": "",
|
||||
"id": "1",
|
||||
"last_name": "",
|
||||
"locale": "",
|
||||
"nickname": "",
|
||||
"notify_props": {
|
||||
"channel": "true",
|
||||
"comments": "never",
|
||||
"desktop": "mention",
|
||||
"desktop_sound": "true",
|
||||
"email": "true",
|
||||
"first_name": "true",
|
||||
"highlight_keys": "",
|
||||
"mention_keys": "",
|
||||
"push": "mention",
|
||||
"push_status": "away",
|
||||
},
|
||||
"position": "",
|
||||
"roles": "",
|
||||
"update_at": 1111,
|
||||
"username": "johndoe",
|
||||
},
|
||||
],
|
||||
"first": true,
|
||||
"id": "J",
|
||||
},
|
||||
]
|
||||
}
|
||||
data={[]}
|
||||
getItem={[Function]}
|
||||
getItemCount={[Function]}
|
||||
initialNumToRender={15}
|
||||
|
|
@ -54,7 +18,6 @@ exports[`components/channel_list_row should show no results 1`] = `
|
|||
keyboardShouldPersistTaps="always"
|
||||
maxToRenderPerBatch={16}
|
||||
onContentSizeChange={[Function]}
|
||||
onEndReached={[Function]}
|
||||
onLayout={[Function]}
|
||||
onMomentumScrollBegin={[Function]}
|
||||
onMomentumScrollEnd={[Function]}
|
||||
|
|
@ -71,201 +34,194 @@ exports[`components/channel_list_row should show no results 1`] = `
|
|||
"flex": 1,
|
||||
}
|
||||
}
|
||||
testID="UserListRow.section_list"
|
||||
testID="UserListRow.flat_list"
|
||||
viewabilityConfigCallbackPairs={[]}
|
||||
>
|
||||
<View>
|
||||
<View
|
||||
onFocusCapture={[Function]}
|
||||
onLayout={[Function]}
|
||||
style={null}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": "center",
|
||||
"flexGrow": 1,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
{
|
||||
"paddingBottom": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "#ffffff",
|
||||
"alignItems": "center",
|
||||
"flexGrow": 1,
|
||||
"height": "100%",
|
||||
"justifyContent": "center",
|
||||
"paddingHorizontal": 32,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(63,67,80,0.08)",
|
||||
"height": 24,
|
||||
"justifyContent": "center",
|
||||
"paddingLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans-SemiBold",
|
||||
"fontSize": 12,
|
||||
"fontWeight": "600",
|
||||
"lineHeight": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
J
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
onFocusCapture={[Function]}
|
||||
onLayout={[Function]}
|
||||
style={null}
|
||||
>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onLayout={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
<RNSVGSvgView
|
||||
align="xMidYMid"
|
||||
bbHeight={149}
|
||||
bbWidth={140}
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={149}
|
||||
meetOrSlice={0}
|
||||
minX={0}
|
||||
minY={0}
|
||||
style={
|
||||
[
|
||||
[
|
||||
{
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"height": 40,
|
||||
"paddingBottom": 8,
|
||||
"paddingTop": 4,
|
||||
},
|
||||
{
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 20,
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
undefined,
|
||||
{
|
||||
"backgroundColor": "transparent",
|
||||
"borderWidth": 0,
|
||||
},
|
||||
{
|
||||
"flex": 0,
|
||||
"height": 149,
|
||||
"width": 140,
|
||||
},
|
||||
]
|
||||
}
|
||||
testID="create_direct_message.user_list.user_item.1.1"
|
||||
vbHeight={149}
|
||||
vbWidth={140}
|
||||
width={140}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
<RNSVGGroup
|
||||
fill={null}
|
||||
propList={
|
||||
[
|
||||
{
|
||||
"alignItems": "center",
|
||||
"justifyContent": "center",
|
||||
},
|
||||
{
|
||||
"height": 24,
|
||||
"width": 24,
|
||||
},
|
||||
{
|
||||
"marginRight": 12,
|
||||
},
|
||||
"fill",
|
||||
]
|
||||
}
|
||||
testID="create_direct_message.user_list.user_item.1.1.profile_picture"
|
||||
>
|
||||
<Icon
|
||||
name="account-outline"
|
||||
size={24}
|
||||
style={
|
||||
<RNSVGEllipse
|
||||
cx={70}
|
||||
cy={122.5}
|
||||
fill={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.48)",
|
||||
"payload": 4278190080,
|
||||
"type": 0,
|
||||
}
|
||||
}
|
||||
fillOpacity={0.06}
|
||||
propList={
|
||||
[
|
||||
"fill",
|
||||
"fillOpacity",
|
||||
]
|
||||
}
|
||||
rx={45}
|
||||
ry={3}
|
||||
/>
|
||||
<RNSVGPath
|
||||
d="M37.593 38.008c4.754-4.815 10.754-7.295 17.989-7.428 7.101.133 13.065 2.601 17.892 7.428 4.815 4.827 7.295 10.791 7.428 17.892-.133 7.235-2.601 13.223-7.428 17.99-4.827 4.754-10.791 7.27-17.892 7.512-7.235-.254-13.223-2.758-17.99-7.513-4.754-4.766-7.258-10.766-7.512-18 .254-7.102 2.758-13.066 7.513-17.881z"
|
||||
fill={
|
||||
{
|
||||
"payload": 4294967295,
|
||||
"type": 0,
|
||||
}
|
||||
}
|
||||
opacity={0.4}
|
||||
propList={
|
||||
[
|
||||
"fill",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
<RNSVGPath
|
||||
d="M78.887 51.382c-2.152-6.992-6.225-12.225-12.226-15.69-6.001-3.465-12.57-4.376-19.701-2.744-3.9.996-7.297 2.718-10.22 5.163 3.269-3.567 7.415-6.037 12.428-7.416 7.13-1.633 13.732-.703 19.787 2.793s10.16 8.748 12.313 15.74c1.322 5.037 1.256 9.862-.21 14.47-1.455 4.614-4.067 8.49-7.84 11.611 2.833-3.087 4.783-6.713 5.844-10.894 1.05-4.187.991-8.523-.175-13.033z"
|
||||
fill={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"payload": 4278190080,
|
||||
"type": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"flex": 0,
|
||||
"flexShrink": 1,
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
fillOpacity={0.4}
|
||||
propList={
|
||||
[
|
||||
"fill",
|
||||
"fillOpacity",
|
||||
]
|
||||
}
|
||||
/>
|
||||
<RNSVGPath
|
||||
d="M86.76 53.929c-.508-7.506-3.554-14.097-9.126-19.774-6.345-6.05-13.67-9.08-21.973-9.08-8.303 0-15.616 3.03-21.961 9.08-6.08 6.315-9.126 13.591-9.126 21.855 0 8.262 3.046 15.551 9.126 21.854 5.825 5.556 12.485 8.551 19.967 8.984 7.481.445 14.383-1.611 20.728-6.146l4.75 4.727 6.08-6.05-4.75-4.727c4.69-6.302 6.78-13.218 6.285-20.723zm-13.126 19.87c-4.823 4.726-10.782 7.228-17.876 7.468-7.228-.252-13.211-2.742-17.973-7.469-4.75-4.727-7.252-10.692-7.506-17.885.254-7.06 2.756-12.99 7.506-17.789 4.75-4.787 10.745-7.252 17.973-7.385 7.094.133 13.053 2.586 17.876 7.385 4.81 4.8 7.288 10.73 7.42 17.79-.132 7.192-2.598 13.157-7.42 17.884z"
|
||||
fill={
|
||||
{
|
||||
"payload": 4290428617,
|
||||
"type": 0,
|
||||
}
|
||||
testID="create_direct_message.user_list.user_item.1.1.display_name"
|
||||
>
|
||||
johndoe
|
||||
</Text>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
propList={
|
||||
[
|
||||
"fill",
|
||||
]
|
||||
}
|
||||
/>
|
||||
<RNSVGPath
|
||||
d="M106.202 114.187c-1.568.448-2.728.291-3.482-.472L78.06 86.651c-.754-.763-1.065-1.743-.945-2.954s.873-2.567 2.261-4.093c1.508-1.393 2.848-2.192 4.044-2.386 1.197-.193 2.166.158 2.92 1.054l26.921 24.957c.754.763.874 1.901.371 3.427-.502 1.525-1.448 3.051-2.824 4.577-1.495 1.526-3.039 2.506-4.606 2.954z"
|
||||
fill={
|
||||
{
|
||||
"payload": 4294949919,
|
||||
"type": 0,
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"justifyContent": "center",
|
||||
"marginLeft": 12,
|
||||
}
|
||||
}
|
||||
propList={
|
||||
[
|
||||
"fill",
|
||||
]
|
||||
}
|
||||
/>
|
||||
<RNSVGPath
|
||||
d="M108.007 98.343l-10.08 10.164-12.155-13.34 8.915-9.106 13.32 12.281z"
|
||||
fill={
|
||||
{
|
||||
"payload": 4286207488,
|
||||
"type": 0,
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
color="rgba(63,67,80,0.32)"
|
||||
name="circle-outline"
|
||||
size={28}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
}
|
||||
propList={
|
||||
[
|
||||
"fill",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</RNSVGGroup>
|
||||
</RNSVGSvgView>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "Metropolis-SemiBold",
|
||||
"fontSize": 20,
|
||||
"fontWeight": "600",
|
||||
"lineHeight": 28,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
No matches found for “some term”
|
||||
</Text>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.72)",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
"marginTop": 8,
|
||||
}
|
||||
}
|
||||
>
|
||||
Check the spelling or try another search.
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
onFocusCapture={[Function]}
|
||||
onLayout={[Function]}
|
||||
style={null}
|
||||
/>
|
||||
<View
|
||||
onLayout={[Function]}
|
||||
>
|
||||
|
|
@ -309,6 +265,7 @@ exports[`components/channel_list_row should show results and tutorial 1`] = `
|
|||
"first_name": "",
|
||||
"id": "1",
|
||||
"last_name": "",
|
||||
"last_picture_update": 123456,
|
||||
"locale": "",
|
||||
"nickname": "",
|
||||
"notify_props": {
|
||||
|
|
@ -480,15 +437,40 @@ exports[`components/channel_list_row should show results and tutorial 1`] = `
|
|||
}
|
||||
testID="create_direct_message.user_list.user_item.1.1.profile_picture"
|
||||
>
|
||||
<Icon
|
||||
name="account-outline"
|
||||
size={24}
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.48)",
|
||||
}
|
||||
[
|
||||
{
|
||||
"overflow": "hidden",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderRadius": 12,
|
||||
"height": 24,
|
||||
"width": 24,
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
>
|
||||
<FastImageView
|
||||
defaultSource={null}
|
||||
resizeMode="cover"
|
||||
source={
|
||||
{
|
||||
"uri": "https://community.mattermost.com/api/v4/users/1/image?_=123456",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"position": "absolute",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
|
|
@ -597,6 +579,7 @@ exports[`components/channel_list_row should show results no tutorial 1`] = `
|
|||
"first_name": "",
|
||||
"id": "1",
|
||||
"last_name": "",
|
||||
"last_picture_update": 123456,
|
||||
"locale": "",
|
||||
"nickname": "",
|
||||
"notify_props": {
|
||||
|
|
@ -768,15 +751,40 @@ exports[`components/channel_list_row should show results no tutorial 1`] = `
|
|||
}
|
||||
testID="create_direct_message.user_list.user_item.1.1.profile_picture"
|
||||
>
|
||||
<Icon
|
||||
name="account-outline"
|
||||
size={24}
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.48)",
|
||||
}
|
||||
[
|
||||
{
|
||||
"overflow": "hidden",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderRadius": 12,
|
||||
"height": 24,
|
||||
"width": 24,
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
>
|
||||
<FastImageView
|
||||
defaultSource={null}
|
||||
resizeMode="cover"
|
||||
source={
|
||||
{
|
||||
"uri": "https://community.mattermost.com/api/v4/users/1/image?_=123456",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"position": "absolute",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
|
|
@ -885,6 +893,7 @@ exports[`components/channel_list_row should show results no tutorial 2 users 1`]
|
|||
"first_name": "",
|
||||
"id": "1",
|
||||
"last_name": "",
|
||||
"last_picture_update": 123456,
|
||||
"locale": "",
|
||||
"nickname": "",
|
||||
"notify_props": {
|
||||
|
|
@ -918,6 +927,7 @@ exports[`components/channel_list_row should show results no tutorial 2 users 1`]
|
|||
"first_name": "",
|
||||
"id": "2",
|
||||
"last_name": "",
|
||||
"last_picture_update": 123456,
|
||||
"locale": "",
|
||||
"nickname": "",
|
||||
"notify_props": {
|
||||
|
|
@ -1089,15 +1099,40 @@ exports[`components/channel_list_row should show results no tutorial 2 users 1`]
|
|||
}
|
||||
testID="create_direct_message.user_list.user_item.1.1.profile_picture"
|
||||
>
|
||||
<Icon
|
||||
name="account-outline"
|
||||
size={24}
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.48)",
|
||||
}
|
||||
[
|
||||
{
|
||||
"overflow": "hidden",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderRadius": 12,
|
||||
"height": 24,
|
||||
"width": 24,
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
>
|
||||
<FastImageView
|
||||
defaultSource={null}
|
||||
resizeMode="cover"
|
||||
source={
|
||||
{
|
||||
"uri": "https://community.mattermost.com/api/v4/users/1/image?_=123456",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"position": "absolute",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
|
|
@ -1281,15 +1316,40 @@ exports[`components/channel_list_row should show results no tutorial 2 users 1`]
|
|||
}
|
||||
testID="create_direct_message.user_list.user_item.2.2.profile_picture"
|
||||
>
|
||||
<Icon
|
||||
name="account-outline"
|
||||
size={24}
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.48)",
|
||||
}
|
||||
[
|
||||
{
|
||||
"overflow": "hidden",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderRadius": 12,
|
||||
"height": 24,
|
||||
"width": 24,
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
>
|
||||
<FastImageView
|
||||
defaultSource={null}
|
||||
resizeMode="cover"
|
||||
source={
|
||||
{
|
||||
"uri": "https://community.mattermost.com/api/v4/users/2/image?_=123456",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"position": "absolute",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {Image} from 'react-native';
|
||||
|
||||
import {renderWithEverything} from '@test/intl-test-helper';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
|
@ -10,6 +11,18 @@ import UserList from '.';
|
|||
|
||||
import type Database from '@nozbe/watermelondb/Database';
|
||||
|
||||
const mockClient = TestHelper.createClient();
|
||||
|
||||
jest.mock('@managers/network_manager', () => {
|
||||
const original = jest.requireActual('@managers/network_manager');
|
||||
return {
|
||||
...original,
|
||||
getClient: () => {
|
||||
return mockClient;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('components/channel_list_row', () => {
|
||||
let database: Database;
|
||||
const user: UserProfile = {
|
||||
|
|
@ -26,6 +39,7 @@ describe('components/channel_list_row', () => {
|
|||
position: '',
|
||||
roles: '',
|
||||
locale: '',
|
||||
last_picture_update: 123456,
|
||||
notify_props: {
|
||||
channel: 'true',
|
||||
comments: 'never',
|
||||
|
|
@ -54,6 +68,7 @@ describe('components/channel_list_row', () => {
|
|||
position: '',
|
||||
roles: '',
|
||||
locale: '',
|
||||
last_picture_update: 123456,
|
||||
notify_props: {
|
||||
channel: 'true',
|
||||
comments: 'never',
|
||||
|
|
@ -68,15 +83,26 @@ describe('components/channel_list_row', () => {
|
|||
},
|
||||
};
|
||||
|
||||
const originalResolveAssetSource = Image.resolveAssetSource;
|
||||
|
||||
beforeAll(async () => {
|
||||
const server = await TestHelper.setupServerDatabase();
|
||||
database = server.database;
|
||||
|
||||
// This is needed to properly populate the URLs until
|
||||
// https://github.com/facebook/react-native/pull/43497
|
||||
// gets into React Native Jest code.
|
||||
Image.resolveAssetSource = jest.fn().mockImplementation((source) => source);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
Image.resolveAssetSource = originalResolveAssetSource;
|
||||
});
|
||||
|
||||
it('should show no results', () => {
|
||||
const wrapper = renderWithEverything(
|
||||
<UserList
|
||||
profiles={[user]}
|
||||
profiles={[]}
|
||||
testID='UserListRow'
|
||||
currentUserId={'1'}
|
||||
handleSelectProfile={() => {
|
||||
|
|
@ -87,6 +113,7 @@ describe('components/channel_list_row', () => {
|
|||
}}
|
||||
loading={true}
|
||||
selectedIds={{}}
|
||||
term={'some term'}
|
||||
showNoResults={true}
|
||||
tutorialWatched={true}
|
||||
/>,
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import React from 'react';
|
|||
import {View} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type Props = {
|
||||
|
|
@ -37,23 +37,15 @@ const Group = ({theme, users}: Props) => {
|
|||
const serverUrl = useServerUrl();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
let client: Client | undefined;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rows = chunk(users, 5);
|
||||
const groups = rows.map((c, k) => {
|
||||
const group = c.map((u, i) => {
|
||||
const pictureUrl = client!.getProfilePictureUrl(u.id, u.lastPictureUpdate);
|
||||
const pictureUrl = buildProfileImageUrlFromUser(serverUrl, u);
|
||||
return (
|
||||
<FastImage
|
||||
key={pictureUrl + i.toString()}
|
||||
style={[styles.profile, {transform: [{translateX: -(i * 24)}]}]}
|
||||
source={{uri: `${serverUrl}${pictureUrl}`}}
|
||||
source={{uri: buildAbsoluteUrl(serverUrl, pictureUrl)}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ import React from 'react';
|
|||
import {View} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type Props = {
|
||||
|
|
@ -37,21 +37,13 @@ const GroupAvatars = ({users}: Props) => {
|
|||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
let client: Client | undefined;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const group = users.map((u, i) => {
|
||||
const pictureUrl = client!.getProfilePictureUrl(u.id, u.lastPictureUpdate);
|
||||
const pictureUrl = buildProfileImageUrlFromUser(serverUrl, u);
|
||||
return (
|
||||
<FastImage
|
||||
key={pictureUrl + i.toString()}
|
||||
style={[styles.profile, {transform: [{translateX: -(i * 12)}]}]}
|
||||
source={{uri: `${serverUrl}${pictureUrl}`}}
|
||||
source={{uri: buildAbsoluteUrl(serverUrl, pictureUrl)}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,17 +4,16 @@
|
|||
import React, {useCallback, useMemo, useState} from 'react';
|
||||
import {Platform, View} from 'react-native';
|
||||
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import ProfileImage from '@components/profile_picture';
|
||||
import {ACCOUNT_OUTLINE_IMAGE} from '@constants/profile';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import useDidUpdate from '@hooks/did_update';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import ProfileImagePicker from './profile_image_picker';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type ChangeProfilePictureProps = {
|
||||
|
|
@ -47,24 +46,18 @@ const EditProfilePicture = ({user, onUpdateProfilePicture}: ChangeProfilePicture
|
|||
const serverUrl = useServerUrl();
|
||||
const theme = useTheme();
|
||||
|
||||
let client: Client | undefined;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch {
|
||||
// does nothing
|
||||
}
|
||||
|
||||
const [pictureUrl, setPictureUrl] = useState<string|undefined>(client?.getProfilePictureUrl(user.id, user.lastPictureUpdate));
|
||||
const [pictureUrl, setPictureUrl] = useState<string|undefined>(() => {
|
||||
return buildProfileImageUrlFromUser(serverUrl, user);
|
||||
});
|
||||
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
useDidUpdate(() => {
|
||||
const url = user.id && client ? client.getProfilePictureUrl(user.id, user.lastPictureUpdate) : undefined;
|
||||
const url = user.id ? buildProfileImageUrlFromUser(serverUrl, user) : undefined;
|
||||
if (url !== pictureUrl) {
|
||||
setPictureUrl(url);
|
||||
}
|
||||
}, [user.id, user.lastPictureUpdate]);
|
||||
}, [user]);
|
||||
|
||||
const handleProfileImage = useCallback((images?: FileInfo[]) => {
|
||||
let isRemoved = true;
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import {useIntl} from 'react-intl';
|
|||
import {TouchableOpacity} from 'react-native';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {ITEM_HEIGHT} from '@components/slide_up_panel_item';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {TITLE_HEIGHT} from '@screens/bottom_sheet/content';
|
||||
import PanelItem from '@screens/edit_profile/components/panel_item';
|
||||
import {bottomSheet} from '@screens/navigation';
|
||||
|
|
@ -22,7 +22,6 @@ import {preventDoubleTap} from '@utils/tap';
|
|||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const hitSlop = {top: 100, bottom: 20, right: 20, left: 100};
|
||||
|
|
@ -57,21 +56,9 @@ type ImagePickerProps = {
|
|||
};
|
||||
|
||||
const hasPictureUrl = (user: UserModel, serverUrl: string) => {
|
||||
const {id, lastPictureUpdate} = user;
|
||||
|
||||
let client: Client | undefined;
|
||||
let profileImageUrl: string | undefined;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
profileImageUrl = client.getProfilePictureUrl(id, lastPictureUpdate);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if image url includes query string for timestamp. If so,
|
||||
// it means the image has been updated from the default, i.e. '.../image?_=1544159746868'
|
||||
return Boolean(profileImageUrl?.includes('image?_'));
|
||||
return buildProfileImageUrlFromUser(serverUrl, user).includes('image?_');
|
||||
};
|
||||
|
||||
const ProfileImagePicker = ({
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useMemo} from 'react';
|
||||
import React from 'react';
|
||||
import {StyleSheet, View} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrl} from '@actions/remote/user';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import {useServerUrl} from '@app/context/server';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {changeOpacity} from '@utils/theme';
|
||||
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type Props = {
|
||||
authorId?: string;
|
||||
author?: UserModel;
|
||||
overrideIconUrl?: string;
|
||||
}
|
||||
|
||||
|
|
@ -32,28 +34,22 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const Avatar = ({authorId, overrideIconUrl}: Props) => {
|
||||
const Avatar = ({
|
||||
author,
|
||||
overrideIconUrl,
|
||||
}: Props) => {
|
||||
const serverUrl = useServerUrl();
|
||||
const avatarUri = useMemo(() => {
|
||||
try {
|
||||
if (overrideIconUrl) {
|
||||
return buildAbsoluteUrl(serverUrl, overrideIconUrl);
|
||||
} else if (authorId) {
|
||||
const pictureUrl = buildProfileImageUrl(serverUrl, authorId);
|
||||
return `${serverUrl}${pictureUrl}`;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}, [serverUrl, authorId, overrideIconUrl]);
|
||||
let uri = overrideIconUrl;
|
||||
if (!uri && author) {
|
||||
uri = buildProfileImageUrlFromUser(serverUrl, author);
|
||||
}
|
||||
|
||||
let picture;
|
||||
if (avatarUri) {
|
||||
if (uri) {
|
||||
picture = (
|
||||
<FastImage
|
||||
source={{uri: avatarUri}}
|
||||
source={{uri: buildAbsoluteUrl(serverUrl, uri)}}
|
||||
style={[styles.avatar, styles.avatarRadius]}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -125,10 +125,10 @@ const Footer = ({
|
|||
<View style={styles.container}>
|
||||
<View style={styles.details}>
|
||||
{item.type !== 'avatar' &&
|
||||
<Avatar
|
||||
authorId={author?.id}
|
||||
overrideIconUrl={overrideIconUrl}
|
||||
/>
|
||||
<Avatar
|
||||
author={author}
|
||||
overrideIconUrl={overrideIconUrl}
|
||||
/>
|
||||
}
|
||||
<Details
|
||||
channelName={item.type === 'avatar' ? '' : channelName}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import React from 'react';
|
|||
import {Image, StyleSheet, View} from 'react-native';
|
||||
import FastImage, {type Source} from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {observeConfigBooleanValue} from '@queries/servers/system';
|
||||
import {observeUser} from '@queries/servers/user';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
|
|
@ -36,17 +36,10 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
const NotificationIcon = ({author, enablePostIconOverride, fromWebhook, overrideIconUrl, serverUrl, useUserIcon}: NotificationIconProps) => {
|
||||
let client: Client | undefined;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch {
|
||||
// do nothing, client is not set
|
||||
}
|
||||
|
||||
let icon;
|
||||
if (client && fromWebhook && !useUserIcon && enablePostIconOverride) {
|
||||
if (fromWebhook && !useUserIcon && enablePostIconOverride) {
|
||||
if (overrideIconUrl) {
|
||||
const source: Source = {uri: client.getAbsoluteUrl(overrideIconUrl)};
|
||||
const source: Source = {uri: buildAbsoluteUrl(serverUrl, overrideIconUrl)};
|
||||
icon = (
|
||||
<FastImage
|
||||
source={source}
|
||||
|
|
@ -61,13 +54,13 @@ const NotificationIcon = ({author, enablePostIconOverride, fromWebhook, override
|
|||
/>
|
||||
);
|
||||
}
|
||||
} else if (author && client) {
|
||||
const pictureUrl = client.getProfilePictureUrl(author.id, author.lastPictureUpdate);
|
||||
} else if (author) {
|
||||
const pictureUrl = buildProfileImageUrlFromUser(serverUrl, author);
|
||||
icon = (
|
||||
<FastImage
|
||||
key={pictureUrl}
|
||||
style={{width: IMAGE_SIZE, height: IMAGE_SIZE, borderRadius: (IMAGE_SIZE / 2)}}
|
||||
source={{uri: `${serverUrl}${pictureUrl}`}}
|
||||
source={{uri: buildAbsoluteUrl(serverUrl, pictureUrl)}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import {useIntl} from 'react-intl';
|
|||
import {Text, TouchableOpacity, View} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import {GalleryInit} from '@context/gallery';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import {useGalleryItem} from '@hooks/gallery';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {openGalleryAtIndex} from '@utils/gallery';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
|
@ -93,14 +94,8 @@ const UserProfileTitle = ({
|
|||
if (enablePostIconOverride && userIconOverride) {
|
||||
imageUrl = userIconOverride;
|
||||
} else {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const lastPictureUpdate = user.isBot ? (user.props?.bot_last_icon_update || 0) : user.lastPictureUpdate;
|
||||
const pictureUrl = client.getProfilePictureUrl(user.id, lastPictureUpdate);
|
||||
imageUrl = `${serverUrl}${pictureUrl}`;
|
||||
} catch {
|
||||
// handle below that the client is not set
|
||||
}
|
||||
const pictureUrl = buildProfileImageUrlFromUser(serverUrl, user);
|
||||
imageUrl = buildAbsoluteUrl(serverUrl, pictureUrl);
|
||||
}
|
||||
|
||||
if (imageUrl) {
|
||||
|
|
|
|||
|
|
@ -380,3 +380,11 @@ export const getEmailIntervalTexts = (interval: string) => {
|
|||
};
|
||||
return intervalTexts[interval];
|
||||
};
|
||||
|
||||
export const getLastPictureUpdate = (user: UserModel | UserProfile) => {
|
||||
if ('isBot' in user) {
|
||||
return user.isBot ? user.props?.bot_last_icon_update : user.lastPictureUpdate || 0;
|
||||
}
|
||||
|
||||
return user.is_bot ? user.bot_last_icon_update : user.last_picture_update || 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ import React from 'react';
|
|||
import {View} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {buildAbsoluteUrl} from '@actions/remote/file';
|
||||
import {buildProfileImageUrlFromUser} from '@actions/remote/user';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {ACCOUNT_OUTLINE_IMAGE} from '@constants/profile';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {useShareExtensionServerUrl} from '@share/state';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
|
|
@ -34,7 +35,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
|||
const Avatar = ({author, theme}: Props) => {
|
||||
const serverUrl = useShareExtensionServerUrl();
|
||||
const style = getStyleSheet(theme);
|
||||
const isBot = author?.isBot || false;
|
||||
let pictureUrl = '';
|
||||
|
||||
if (author?.deleteAt) {
|
||||
|
|
@ -48,24 +48,12 @@ const Avatar = ({author, theme}: Props) => {
|
|||
}
|
||||
|
||||
if (author && serverUrl) {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
let lastPictureUpdate = 0;
|
||||
if (isBot) {
|
||||
lastPictureUpdate = author?.props?.bot_last_icon_update || 0;
|
||||
} else {
|
||||
lastPictureUpdate = author?.lastPictureUpdate || 0;
|
||||
}
|
||||
|
||||
pictureUrl = client.getProfilePictureUrl(author.id, lastPictureUpdate);
|
||||
} catch {
|
||||
// handle below that the client is not set
|
||||
}
|
||||
pictureUrl = buildProfileImageUrlFromUser(serverUrl, author);
|
||||
}
|
||||
|
||||
let icon;
|
||||
if (pictureUrl) {
|
||||
const imgSource = {uri: `${serverUrl}${pictureUrl}`};
|
||||
if (pictureUrl && serverUrl) {
|
||||
const imgSource = {uri: buildAbsoluteUrl(serverUrl, pictureUrl)};
|
||||
icon = (
|
||||
<FastImage
|
||||
key={pictureUrl}
|
||||
|
|
|
|||
Loading…
Reference in a new issue