mirror of
https://github.com/Terreii/andromeda-viewer.git
synced 2026-08-14 00:57:49 +00:00
refactor(AvatarName): remove AvatarName class
This commit is contained in:
@@ -34,6 +34,7 @@ import {
|
||||
selectLocalChat
|
||||
} from '../bundles/localChat'
|
||||
import {
|
||||
addMissing,
|
||||
selectAvatarNameById,
|
||||
selectOwnAvatarName,
|
||||
getFullNameString,
|
||||
@@ -916,7 +917,14 @@ export function startNewIMChat (chatType, targetId, name) {
|
||||
try {
|
||||
name = getNameString(selectAvatarNameById(getState(), targetId.toString()))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
if (name) {
|
||||
dispatch(addMissing({
|
||||
id: targetId,
|
||||
fallback: name
|
||||
}))
|
||||
} else {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1060,6 +1060,13 @@ describe('save, loading and sending IMs', () => {
|
||||
|
||||
expect(store.getActions()).toEqual([
|
||||
// Personal
|
||||
{
|
||||
type: 'names/addMissing',
|
||||
payload: {
|
||||
id: 'f2373437-a2ef-4435-82b9-68d283538bb2',
|
||||
fallback: 'Tester FuryTest'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'im/create',
|
||||
payload: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
displayNamesStartLoading,
|
||||
displayNamesLoaded,
|
||||
selectNames,
|
||||
selectIdOfNamesToLoad,
|
||||
selectDisplayNamesURL,
|
||||
selectOwnAvatarName,
|
||||
selectAvatarNameById,
|
||||
@@ -82,12 +83,10 @@ export function doHandleFriendOnlineStateChange (msg) {
|
||||
|
||||
export function getDisplayName () {
|
||||
return (dispatch, getState) => {
|
||||
const names = selectNames(getState())
|
||||
const namesToLoad = selectIdOfNamesToLoad(getState())
|
||||
|
||||
const toLoad = Object.keys(names).filter(id => !names[id].willHaveDisplayName())
|
||||
|
||||
if (toLoad.length > 0) {
|
||||
dispatch(loadDisplayNames(toLoad))
|
||||
if (namesToLoad.length > 0) {
|
||||
dispatch(loadDisplayNames(namesToLoad))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,15 @@ import {
|
||||
|
||||
// Actions for the session of an avatar
|
||||
|
||||
// Logon the user. It will post using fetch to the server.
|
||||
/**
|
||||
* Logon the user. It will post using fetch to the server.
|
||||
* @param {import('../bundles/names').MinimalAvatarName} avatarName Avatar Name
|
||||
* @param {string} password Password of the avatar.
|
||||
* @param {import('../types/viewer').Grid} grid Grid info
|
||||
* @param {boolean} save Should the avatar be saved.
|
||||
* @param {boolean} isNew Is this avatar new. False if this avatar was saved.
|
||||
* @returns {import('../store/configureStore').AppThunk}
|
||||
*/
|
||||
export function login (avatarName, password, grid, save, isNew) {
|
||||
return async (dispatch, getState, extra) => {
|
||||
if (selectIsLoggedIn(getState())) throw new Error('There is already an avatar logged in!')
|
||||
@@ -61,8 +69,8 @@ export function login (avatarName, password, grid, save, isNew) {
|
||||
const circuit = import('../network/circuit')
|
||||
|
||||
const body = grid.isLLSDLogin
|
||||
? await loginWithLLSD(viewerData, avatarName.first, avatarName.last, finalPassword)
|
||||
: await loginWithXmlRpc(viewerData, avatarName.first, avatarName.last, finalPassword)
|
||||
? await loginWithLLSD(viewerData, avatarName.firstName, avatarName.lastName, finalPassword)
|
||||
: await loginWithXmlRpc(viewerData, avatarName.firstName, avatarName.lastName, finalPassword)
|
||||
|
||||
if (body.login !== 'true') {
|
||||
dispatch(loginFailed({ error: body.message }))
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
selectSavedGrids,
|
||||
selectSavedGridsAreLoaded
|
||||
} from '../bundles/account'
|
||||
import { getFullNameString } from '../bundles/names'
|
||||
import { selectIsLoggedIn } from '../bundles/session'
|
||||
import { createCryptoStore, getUserDatabaseName, startSyncing } from '../store/db'
|
||||
|
||||
@@ -45,7 +46,7 @@ export function saveAvatar (name, agentId, grid) {
|
||||
return cryptoStore.withIdPrefix('avatars/').add({
|
||||
dataSaveId: uuid(),
|
||||
avatarIdentifier,
|
||||
name: name.getFullName(),
|
||||
name: getFullNameString(name),
|
||||
grid: gridName
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
isSignedIn
|
||||
} from './viewerAccount'
|
||||
|
||||
import AvatarName from '../avatarName'
|
||||
import { parseNameString } from '../bundles/names'
|
||||
|
||||
let localDB
|
||||
let remoteDB
|
||||
@@ -291,7 +291,7 @@ describe('avatars', () => {
|
||||
|
||||
const avatarIdentifier = v4()
|
||||
const result = await store.dispatch(saveAvatar(
|
||||
new AvatarName('Tester'),
|
||||
parseNameString('Tester'),
|
||||
avatarIdentifier,
|
||||
'Second Life'
|
||||
))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createSlice, createSelector, PayloadAction, Action } from '@reduxjs/toolkit'
|
||||
|
||||
import { RootState } from '../store/configureStore'
|
||||
import type { LoginAction } from './session'
|
||||
import { AvatarData, SavedAvatarData, Grid, HoodieObject } from '../types/viewer'
|
||||
|
||||
// Reducer for viewer-account and state
|
||||
@@ -100,13 +101,14 @@ const accountSlice = createSlice({
|
||||
},
|
||||
|
||||
extraReducers: {
|
||||
'session/login' (state, action: PayloadAction<any>) {
|
||||
if (!action.payload.save) { // Anonym
|
||||
'session/login' (state, action: PayloadAction<LoginAction>) {
|
||||
const { save, grid, name, avatarIdentifier, dataSaveId } = action.payload
|
||||
if (!save) { // Anonym
|
||||
state.anonymAvatarData = {
|
||||
grid: action.payload.grid.name,
|
||||
name: action.payload.name.getFullName(),
|
||||
avatarIdentifier: action.payload.avatarIdentifier,
|
||||
dataSaveId: action.payload.dataSaveId
|
||||
grid: grid.name,
|
||||
name: name.firstName + ' ' + name.lastName,
|
||||
avatarIdentifier,
|
||||
dataSaveId
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+23
-7
@@ -39,10 +39,13 @@ import {
|
||||
NotificationTypes
|
||||
} from '../types/chat'
|
||||
|
||||
export interface AvatarName {
|
||||
id: string,
|
||||
export interface MinimalAvatarName {
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
lastName: string
|
||||
}
|
||||
|
||||
export interface AvatarName extends MinimalAvatarName {
|
||||
id: string,
|
||||
displayName: string,
|
||||
isDisplayNameDefault: boolean,
|
||||
didLoadDisplayName: boolean,
|
||||
@@ -153,8 +156,8 @@ const nameSlice = createSlice({
|
||||
[login.type] (state, action: PayloadAction<LoginAction>) {
|
||||
namesAdapter.addOne(state.names, {
|
||||
id: action.payload.uuid,
|
||||
firstName: action.payload.name.first,
|
||||
lastName: action.payload.name.last,
|
||||
firstName: action.payload.name.firstName,
|
||||
lastName: action.payload.name.lastName,
|
||||
displayName: '',
|
||||
isDisplayNameDefault: false,
|
||||
didLoadDisplayName: false,
|
||||
@@ -351,6 +354,19 @@ export const selectAvatarDisplayName = (state: RootState, id: string): string =>
|
||||
return getDisplayName(name)
|
||||
}
|
||||
|
||||
export const selectIdOfNamesToLoad = createSelector(
|
||||
[
|
||||
selectNames
|
||||
],
|
||||
names => Object.values(names || {})
|
||||
.filter(name => name && !(
|
||||
name.didLoadDisplayName ||
|
||||
name.isLoadingDisplayName ||
|
||||
name.displayName.length > 0
|
||||
))
|
||||
.map(name => name!.id)
|
||||
)
|
||||
|
||||
export function selectDisplayNamesURL (state: RootState): string {
|
||||
return state.names.getDisplayNamesURL
|
||||
}
|
||||
@@ -401,7 +417,7 @@ export function parseNameString (name: string, last?: string): {
|
||||
}
|
||||
}
|
||||
|
||||
export function getNameString (name: AvatarName): string {
|
||||
export function getNameString (name: MinimalAvatarName & { id: string }): string {
|
||||
if (
|
||||
name.lastName.length === 0 ||
|
||||
name.lastName === 'Resident' ||
|
||||
@@ -412,7 +428,7 @@ export function getNameString (name: AvatarName): string {
|
||||
return `${name.firstName} ${name.lastName}`
|
||||
}
|
||||
|
||||
export function getFullNameString (name: AvatarName): string {
|
||||
export function getFullNameString (name: MinimalAvatarName): string {
|
||||
return name.firstName + ' ' + name.lastName
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createSlice, createSelector, PayloadAction, Action } from '@reduxjs/toolkit'
|
||||
|
||||
import { selectIsSignedIn, selectSavedAvatars, selectAnonymAvatarData } from './account'
|
||||
import AvatarName from '../avatarName'
|
||||
import type { MinimalAvatarName } from './names'
|
||||
|
||||
import { RootState } from '../store/configureStore'
|
||||
import { LocalChatMessage } from '../types/chat'
|
||||
@@ -15,7 +15,10 @@ const sessionSlice = createSlice({
|
||||
initialState: getDefaultState(),
|
||||
|
||||
reducers: {
|
||||
startLogin (state, action: PayloadAction<{ name: AvatarName, grid: Grid, sync: boolean }>) {},
|
||||
startLogin (
|
||||
state,
|
||||
action: PayloadAction<{ name: MinimalAvatarName, grid: Grid, sync: boolean }>
|
||||
) {},
|
||||
|
||||
// didLogin
|
||||
login (state, action: PayloadAction<LoginAction>) {
|
||||
@@ -177,7 +180,7 @@ export interface LoginAction {
|
||||
/**
|
||||
* Name of the logged in avatar
|
||||
*/
|
||||
name: AvatarName
|
||||
name: MinimalAvatarName
|
||||
/**
|
||||
* Should the avatar and its data be saved and synced?
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,6 @@ import thunk from 'redux-thunk'
|
||||
import { render, fireEvent } from '@testing-library/react'
|
||||
|
||||
import ChatDialog from './chatDialog'
|
||||
import AvatarName from '../avatarName'
|
||||
|
||||
function configureStore (state = {}) {
|
||||
const store = configureMockStore([thunk])
|
||||
|
||||
@@ -8,7 +8,7 @@ import configureStore from '../store/configureStore'
|
||||
|
||||
import { LocalChatSourceType } from '../types/chat'
|
||||
|
||||
jest.mock('../reactors/index.js', () => [])
|
||||
jest.mock('../reactors/index.ts', () => [])
|
||||
|
||||
function getTimeString (timeSting) {
|
||||
const date = new Date(timeSting)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
import AvatarName from '../../avatarName'
|
||||
import { parseNameString, getNameString } from '../../bundles/names'
|
||||
|
||||
import { useAutoFocus } from '../../hooks/utils'
|
||||
|
||||
@@ -11,6 +11,9 @@ export default function AvatarLogin ({ avatar, grid, isLoggingIn, onLogin, isSel
|
||||
}, [isSelected])
|
||||
|
||||
const doAutoFocus = useAutoFocus()
|
||||
const name = parseNameString(avatar.name)
|
||||
name.id = avatar.avatarIdentifier
|
||||
const nameString = getNameString(name)
|
||||
|
||||
if (!isSelected) {
|
||||
return (
|
||||
@@ -23,7 +26,7 @@ export default function AvatarLogin ({ avatar, grid, isLoggingIn, onLogin, isSel
|
||||
>
|
||||
<button className='flex flex-col text-white btn--transparent focus:outline-none'>
|
||||
<h2 className='block m-1 text-center'>
|
||||
<span className='text-2xl'>{new AvatarName(avatar.name).getDisplayName()}</span>
|
||||
<span className='text-2xl'>{nameString}</span>
|
||||
<span className='inline-block ml-3'>@{grid.name}</span>
|
||||
</h2>
|
||||
|
||||
@@ -49,7 +52,7 @@ export default function AvatarLogin ({ avatar, grid, isLoggingIn, onLogin, isSel
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<h2 className='block m-1 text-center'>
|
||||
<span className='text-2xl'>{new AvatarName(avatar.name).getDisplayName()}</span>
|
||||
<span className='text-2xl'>{nameString}</span>
|
||||
<span className='inline-block ml-3'>@{grid.name}</span>
|
||||
</h2>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect, Fragment } from 'react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
import { selectSavedAvatars, selectGridsByName } from '../../bundles/account'
|
||||
import { parseNameString } from '../../bundles/names'
|
||||
|
||||
import { login } from '../../actions/sessionActions'
|
||||
import { useSelector, useDispatch } from '../../hooks/store'
|
||||
@@ -9,7 +10,6 @@ import { useSelector, useDispatch } from '../../hooks/store'
|
||||
import LoginNewAvatar from './newAvatarLogin'
|
||||
import AvatarLogin from './avatarLogin'
|
||||
import SignIn from './signIn'
|
||||
import AvatarName from '../../avatarName'
|
||||
|
||||
export default function LoginForm ({ isSignedIn }) {
|
||||
const dispatch = useDispatch()
|
||||
@@ -99,7 +99,7 @@ export default function LoginForm ({ isSignedIn }) {
|
||||
return
|
||||
}
|
||||
|
||||
const avatarName = new AvatarName(name)
|
||||
const avatarName = parseNameString(name)
|
||||
setIsLoggingIn(name)
|
||||
|
||||
await dispatch(login(avatarName, password, grid, save, isNew))
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
selectAvatarDisplayName
|
||||
} from '../bundles/names'
|
||||
|
||||
jest.mock('../reactors/index.js', () => [])
|
||||
jest.mock('../reactors/index.ts', () => [])
|
||||
|
||||
/**
|
||||
* Create a Store with names.
|
||||
|
||||
@@ -2,13 +2,13 @@ import { createSelector } from 'reselect'
|
||||
|
||||
import { getDisplayName } from '../actions/friendsActions'
|
||||
|
||||
import { selectNames } from '../bundles/names'
|
||||
import { selectIdOfNamesToLoad } from '../bundles/names'
|
||||
|
||||
export const loadNames = createSelector(
|
||||
[
|
||||
selectNames
|
||||
selectIdOfNamesToLoad
|
||||
],
|
||||
names => Object.values(names).some(name => !name.willHaveDisplayName())
|
||||
namesToLoad => namesToLoad.length > 0
|
||||
? getDisplayName()
|
||||
: null
|
||||
)
|
||||
@@ -14,7 +14,6 @@ import configureReactors from './configureReactors'
|
||||
import { createLocalDB, createCryptoStore, createRemoteDB } from './db'
|
||||
import { proxyFetch, fetchLLSD } from './llsdFetch'
|
||||
|
||||
import AvatarName from '../avatarName'
|
||||
import type Circuit from '../network/circuit'
|
||||
|
||||
export type RootState = ReturnType<typeof rootReducer>
|
||||
@@ -142,9 +141,7 @@ export function createStoreCore (
|
||||
extraArgument: ExtraArguments
|
||||
) {
|
||||
const serializableCheck: SerializableStateInvariantMiddlewareOptions = {
|
||||
isSerializable: value => isPlain(value) ||
|
||||
value instanceof Uint8Array ||
|
||||
value instanceof AvatarName
|
||||
isSerializable: value => isPlain(value) || value instanceof Uint8Array
|
||||
}
|
||||
const middleware = getDefaultMiddleware({
|
||||
thunk: {
|
||||
|
||||
+4
-4
@@ -5,10 +5,10 @@ import auth from 'pouchdb-authentication'
|
||||
import hoodieApi from 'pouchdb-hoodie-api'
|
||||
import { NIL } from 'uuid'
|
||||
|
||||
import AvatarName from './avatarName'
|
||||
import connectCircuit from './actions/connectCircuit'
|
||||
import { isSignedIn, loadSavedAvatars, loadSavedGrids } from './actions/viewerAccount'
|
||||
import { signInStatus } from './bundles/account'
|
||||
import { parseNameString } from './bundles/names'
|
||||
import { startLogin, login } from './bundles/session'
|
||||
import { createExtraArgument, createStoreCore } from './store/configureStore'
|
||||
|
||||
@@ -345,7 +345,7 @@ async function setStateToConnectedToGrid (
|
||||
store: ReturnType<typeof createStoreCore>,
|
||||
extraArgument: ReturnType<typeof createExtraArgument>
|
||||
) {
|
||||
const name = new AvatarName('AndromedaViewerTester')
|
||||
const name = parseNameString('AndromedaViewerTester')
|
||||
const grid = {
|
||||
_id: 'second_life',
|
||||
name: 'Second Life',
|
||||
@@ -364,8 +364,8 @@ async function setStateToConnectedToGrid (
|
||||
sessionInfo: {
|
||||
login: 'true',
|
||||
andromedaSessionId: 'e95ecf9b-9104-4d6b-9a4d-09de71e956e8',
|
||||
first_name: `"${name.first}"`,
|
||||
last_name: name.last,
|
||||
first_name: `"${name.firstName}"`,
|
||||
last_name: name.lastName,
|
||||
account_type: 'Base',
|
||||
account_level_benefits: {
|
||||
lastname_change_allowed: '',
|
||||
|
||||
Reference in New Issue
Block a user