Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
thalia
ThaliApp
Commits
f2d05d7f
Verified
Commit
f2d05d7f
authored
Jun 13, 2019
by
Sébastiaan Versteeg
Browse files
Finish profile picture update
parent
c51c51a2
Changes
30
Hide whitespace changes
Inline
Side-by-side
__tests__/actions/__snapshots__/profile.spec.js.snap
View file @
f2d05d7f
...
...
@@ -8,9 +8,7 @@ Object {
exports[`profile actions should create an action for a successful profile load 1`] = `
Object {
"payload": Object {
"profileData": "profile",
},
"payload": "profile",
"type": "PROFILE_SUCCESS",
}
`;
...
...
__tests__/actions/__snapshots__/session.spec.js.snap
View file @
f2d05d7f
...
...
@@ -49,6 +49,7 @@ Object {
"payload": Object {
"displayName": "displayName",
"photo": "photo",
"pk": "pk",
},
"type": "SESSION_SET_USER_INFO",
}
...
...
__tests__/actions/session.spec.js
View file @
f2d05d7f
...
...
@@ -36,6 +36,6 @@ describe('session actions', () => {
});
it
(
'
should create an action to set user info
'
,
()
=>
{
expect
(
actions
.
setUserInfo
(
'
displayName
'
,
'
photo
'
)).
toMatchSnapshot
();
expect
(
actions
.
setUserInfo
(
'
pk
'
,
'
displayName
'
,
'
photo
'
)).
toMatchSnapshot
();
});
});
\ No newline at end of file
});
__tests__/reducers/__snapshots__/profile.spec.js.snap
View file @
f2d05d7f
...
...
@@ -14,7 +14,6 @@ Object {
"birthday": "",
"display_name": "",
"membership_type": "",
"photo": "http://localhost:8000/static/members/images/default-avatar.jpg",
"pk": -1,
"profile_description": "",
"programme": "",
...
...
__tests__/reducers/__snapshots__/session.spec.js.snap
View file @
f2d05d7f
...
...
@@ -4,6 +4,7 @@ exports[`session reducer initially should return the initial state 1`] = `
Object {
"displayName": "",
"photo": "http://localhost:8000/static/members/images/default-avatar.jpg",
"pk": -1,
"status": "SIGNED_OUT",
"token": "",
"username": "",
...
...
__tests__/reducers/session.spec.js
View file @
f2d05d7f
...
...
@@ -54,9 +54,13 @@ describe('session reducer', () => {
describe
(
'
has retrieved user info
'
,
()
=>
{
const
state
=
reducer
(
emptyState
,
actions
.
setUserInfo
(
'
John Doe
'
,
'
imageUrl
'
),
actions
.
setUserInfo
(
'
pk
'
,
'
John Doe
'
,
'
imageUrl
'
),
);
it
(
'
should contain the primary key
'
,
()
=>
{
expect
(
state
).
toHaveProperty
(
'
pk
'
,
'
pk
'
);
});
it
(
'
should contain the display name
'
,
()
=>
{
expect
(
state
).
toHaveProperty
(
'
displayName
'
,
'
John Doe
'
);
});
...
...
__tests__/sagas/members.spec.js
View file @
f2d05d7f
...
...
@@ -142,19 +142,11 @@ describe('members saga', () => {
it
(
'
should load more members
'
,
()
=>
expectSaga
(
membersSaga
)
.
provide
([
[
select
(
tokenSelector
),
'
token
'
],
[
matchers
.
call
.
like
({
fn
:
apiRequest
,
args
:
[
'
moreUrl
'
]
}),
{
results
:
[{
pk
:
1
}],
next
:
'
moreUrl2
'
}],
])
.
dispatch
(
memberActions
.
more
(
'
moreUrl
'
))
.
silentRun
()
.
then
(()
=>
{
expect
(
fetch
).
toBeCalledWith
(
'
moreUrl
'
,
{
method
:
'
GET
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
'
Token token
'
,
},
});
}));
.
put
(
memberActions
.
moreSuccess
([{
pk
:
1
}],
'
moreUrl2
'
))
.
silentRun
());
it
(
'
should put the result data when the request succeeds
'
,
()
=>
{
const
response
=
{
...
...
__tests__/sagas/profile.spec.js
View file @
f2d05d7f
...
...
@@ -7,6 +7,12 @@ import { apiRequest } from '../../app/utils/url';
import
*
as
profileActions
from
'
../../app/actions/profile
'
;
import
{
tokenSelector
}
from
'
../../app/selectors/session
'
;
jest
.
mock
(
'
react-native-snackbar
'
,
()
=>
({
LENGTH_LONG
:
100
,
show
:
jest
.
fn
(),
dismiss
:
jest
.
fn
(),
}));
jest
.
mock
(
'
../../app/utils/url
'
,
()
=>
({
apiRequest
:
jest
.
fn
(()
=>
{}),
}));
...
...
@@ -57,4 +63,4 @@ describe('profile saga', () => {
method
:
'
GET
'
,
});
}));
});
\ No newline at end of file
});
__tests__/sagas/session.spec.js
View file @
f2d05d7f
...
...
@@ -119,7 +119,7 @@ describe('session saga', () => {
.
dispatch
(
sessionActions
.
signOut
())
.
silentRun
()
.
then
(()
=>
{
expect
(
AsyncStorage
.
clear
).
toBeCalled
();
expect
(
AsyncStorage
.
multiRemove
).
toBeCalled
();
}));
it
(
'
should put a push notification invalidation action
'
,
()
=>
expectSaga
(
sessionSaga
)
...
...
__tests__/utils/url.spec.js
View file @
f2d05d7f
import
DeviceInfo
from
'
react-native-device-info
'
;
import
{
apiRequest
,
apiUrl
,
...
...
@@ -7,20 +8,17 @@ import {
TokenInvalidError
,
}
from
'
../../app/utils/url
'
;
import
DeviceInfo
from
'
react-native-device-info
'
;
const
fetchPromiseResult
=
{
status
:
200
,
json
:
()
=>
Promise
.
resolve
(
'
responseJson
'
),
clone
:
global
.
fetch
,
json
:
()
=>
Promise
.
resolve
({
exampleJson
:
'
val
'
}),
};
global
.
fetch
=
jest
.
fn
().
mockReturnValue
(
Promise
.
resolve
(
fetchPromiseResult
),
);
fetchPromiseResult
.
clone
=
global
.
fetch
;
describe
(
'
url helper
'
,
()
=>
{
beforeEach
(()
=>
{
global
.
fetch
=
jest
.
fn
().
mockReturnValue
(
Promise
.
resolve
(
fetchPromiseResult
),
);
});
it
(
'
should expose the constants
'
,
()
=>
{
...
...
@@ -37,7 +35,7 @@ describe('url helper', () => {
.
then
((
response
)
=>
{
expect
(
global
.
fetch
).
toBeCalledWith
(
`
${
apiUrl
}
/route/`
,
{
headers
:
{
'
Accept-Language
'
:
'
en
'
}
});
expect
(
response
).
toEqual
(
'
responseJson
'
);
expect
(
response
).
toEqual
(
{
exampleJson
:
'
val
'
}
);
});
});
...
...
@@ -65,7 +63,7 @@ describe('url helper', () => {
.
then
((
response
)
=>
{
expect
(
global
.
fetch
).
toBeCalledWith
(
`
${
apiUrl
}
/route/`
,
{
headers
:
{
'
Accept-Language
'
:
'
en
'
}
});
expect
(
response
).
toEqual
(
'
responseJson
'
);
expect
(
response
).
toEqual
(
{
exampleJson
:
'
val
'
}
);
});
});
...
...
@@ -74,7 +72,6 @@ describe('url helper', () => {
const
response
=
{
status
:
404
,
json
:
()
=>
Promise
.
resolve
(
'
responseJson
'
),
clone
:
()
=>
({
status
:
404
}),
};
global
.
fetch
.
mockReturnValue
(
Promise
.
resolve
(
response
));
return
apiRequest
(
'
route
'
,
{},
null
)
...
...
@@ -86,7 +83,6 @@ describe('url helper', () => {
const
response
=
{
status
:
204
,
json
:
()
=>
Promise
.
resolve
(
'
responseJson
'
),
clone
:
()
=>
({
status
:
204
}),
};
global
.
fetch
.
mockReturnValue
(
Promise
.
resolve
(
response
));
return
apiRequest
(
'
route
'
,
{},
null
)
...
...
@@ -99,7 +95,6 @@ describe('url helper', () => {
status
:
403
,
headers
:
{
get
:
key
=>
(
key
===
'
content-language
'
?
'
en
'
:
'
nl
'
)
},
json
:
()
=>
Promise
.
resolve
({
detail
:
'
Invalid token.
'
}),
clone
:
()
=>
'
responseCopy
'
,
};
global
.
fetch
.
mockReturnValue
(
Promise
.
resolve
(
response
));
return
apiRequest
(
'
route
'
,
{},
null
)
...
...
@@ -112,7 +107,6 @@ describe('url helper', () => {
status
:
403
,
headers
:
{
get
:
key
=>
(
key
===
'
content-language
'
?
'
nl
'
:
'
en
'
)
},
json
:
()
=>
Promise
.
resolve
({
detail
:
'
Ongeldige token.
'
}),
clone
:
()
=>
'
responseCopy
'
,
};
global
.
fetch
.
mockReturnValue
(
Promise
.
resolve
(
response
));
return
apiRequest
(
'
route
'
,
{},
null
)
...
...
@@ -125,16 +119,14 @@ describe('url helper', () => {
status
:
403
,
headers
:
{
get
:
key
=>
(
key
===
'
content-language
'
?
'
en
'
:
'
nl
'
)
},
json
:
()
=>
Promise
.
resolve
({
detail
:
'
Not authorized.
'
}),
clone
:
()
=>
({
json
:
()
=>
'
jsonResult
'
}),
};
global
.
fetch
.
mockReturnValue
(
Promise
.
resolve
(
response
));
return
apiRequest
(
'
route
'
,
{},
null
)
.
then
(
res
=>
expect
(
res
).
toEqual
(
'
jsonResult
'
));
.
catch
(
res
=>
expect
(
res
).
toEqual
(
new
ServerError
(
'
Invalid status code: 403
'
)
));
});
it
(
'
should default to an English locales
'
,
()
=>
{
DeviceInfo
.
getDeviceLocale
=
()
=>
'
fr
'
;
expect
.
assertions
(
1
);
return
apiRequest
(
'
route
'
,
{},
null
)
.
then
(()
=>
{
expect
(
global
.
fetch
).
toBeCalledWith
(
`
${
apiUrl
}
/route/`
,
...
...
app/actions/profile.js
View file @
f2d05d7f
...
...
@@ -3,9 +3,7 @@ export const FETCHING = 'PROFILE_FETCHING';
export
const
SUCCESS
=
'
PROFILE_SUCCESS
'
;
export
const
FAILURE
=
'
PROFILE_FAILURE
'
;
export
const
UPDATE
=
'
PROFILE_UPDATE
'
;
export
const
UPDATING
=
'
PROFILE_UPDATING
'
;
export
const
UPDATE_SUCCESS
=
'
PROFILE_UPDATE_SUCCESS
'
;
export
const
UPDATE_FAIL
=
'
PROFILE_UPDATE_FAIL
'
;
export
const
CHANGE_AVATAR
=
'
PROFILE_CHANGE_AVATAR
'
;
export
function
profile
(
member
=
'
me
'
)
{
...
...
@@ -27,35 +25,17 @@ export function changeAvatar() {
};
}
export
function
update
()
{
return
{
type
:
UPDATE
,
};
}
export
function
updating
()
{
return
{
type
:
UPDATING
,
};
}
export
function
updateSuccess
(
profileData
)
{
return
{
type
:
UPDATE_SUCCESS
,
payload
:
{
profileData
},
};
}
export
function
updateFail
()
{
return
{
type
:
UPDATE_FAIL
,
payload
:
profileData
,
};
}
export
function
success
(
profileData
)
{
return
{
type
:
SUCCESS
,
payload
:
{
profileData
}
,
payload
:
profileData
,
};
}
...
...
app/reducers/profile.js
View file @
f2d05d7f
...
...
@@ -23,11 +23,10 @@ const initialState = {
},
success
:
false
,
hasLoaded
:
false
,
updating
:
false
,
};
export
default
function
profile
(
state
=
initialState
,
action
=
{})
{
switch
(
action
.
type
)
{
export
default
function
profile
(
state
=
initialState
,
{
type
,
payload
}
=
{})
{
switch
(
type
)
{
case
profileActions
.
FETCHING
:
return
{
...
state
,
...
...
@@ -36,7 +35,7 @@ export default function profile(state = initialState, action = {}) {
case
profileActions
.
SUCCESS
:
return
{
...
state
,
profile
:
action
.
payload
.
profileData
,
profile
:
payload
,
success
:
true
,
hasLoaded
:
true
,
};
...
...
@@ -46,16 +45,13 @@ export default function profile(state = initialState, action = {}) {
success
:
false
,
hasLoaded
:
true
,
};
case
profileActions
.
UPDATING
:
return
{
...
state
,
updating
:
true
,
};
case
profileActions
.
UPDATE_FAIL
:
case
profileActions
.
UPDATE_SUCCESS
:
return
{
...
state
,
updating
:
false
,
profile
:
{
...
state
.
profile
,
...
payload
,
},
};
default
:
return
state
;
...
...
app/sagas/calendar.js
View file @
f2d05d7f
import
{
call
,
put
,
select
,
takeEvery
,
}
from
'
redux-saga/effects
'
;
import
{
Sentry
}
from
'
react-native-sentry
'
;
import
{
apiRequest
}
from
'
../utils/url
'
;
import
*
as
calendarActions
from
'
../actions/calendar
'
;
import
{
tokenSelector
}
from
'
../selectors/session
'
;
import
reportError
from
'
../utils/errorReporting
'
;
const
calendar
=
function
*
calendar
()
{
const
token
=
yield
select
(
tokenSelector
);
...
...
@@ -31,17 +31,15 @@ const calendar = function* calendar() {
partner
:
true
,
}));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
}
yield
put
(
calendarActions
.
success
(
events
.
concat
(
partnerEvents
)));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
calendarActions
.
failure
());
}
};
const
calendarSaga
=
function
*
eventSaga
()
{
export
default
function
*
()
{
yield
takeEvery
(
calendarActions
.
REFRESH
,
calendar
);
};
export
default
calendarSaga
;
}
app/sagas/deepLinking.js
View file @
f2d05d7f
...
...
@@ -81,8 +81,6 @@ const deepLink = function* deepLink(action) {
}
};
const
deepLinkingSaga
=
function
*
deepLinkingSaga
()
{
export
default
function
*
()
{
yield
takeEvery
(
deepLinkingActions
.
DEEPLINK
,
deepLink
);
};
export
default
deepLinkingSaga
;
}
app/sagas/event.js
View file @
f2d05d7f
import
{
call
,
put
,
select
,
takeEvery
,
}
from
'
redux-saga/effects
'
;
import
{
Sentry
}
from
'
react-native-sentry
'
;
import
{
apiRequest
}
from
'
../utils/url
'
;
import
*
as
eventActions
from
'
../actions/event
'
;
import
{
tokenSelector
}
from
'
../selectors/session
'
;
import
reportError
from
'
../utils/errorReporting
'
;
function
*
event
(
action
)
{
const
{
pk
,
navigateToEventScreen
}
=
action
.
payload
;
...
...
@@ -40,7 +40,7 @@ function* event(action) {
eventRegistrations
,
));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
eventActions
.
failure
());
}
}
...
...
@@ -69,14 +69,12 @@ function* updateRegistration(action) {
yield
put
(
eventActions
.
done
());
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
eventActions
.
failure
());
}
}
function
*
eventSaga
()
{
export
default
function
*
()
{
yield
takeEvery
(
eventActions
.
EVENT
,
event
);
yield
takeEvery
(
eventActions
.
UPDATE_REGISTRATION
,
updateRegistration
);
}
export
default
eventSaga
;
app/sagas/index.js
View file @
f2d05d7f
...
...
@@ -13,7 +13,7 @@ import deepLinkingSaga from './deepLinking';
import
membersSaga
from
'
./members
'
;
import
settingsSaga
from
'
./settings
'
;
const
sagas
=
function
*
sagas
()
{
export
default
function
*
()
{
yield
all
([
fork
(
sessionSaga
),
fork
(
navigationSaga
),
...
...
@@ -28,6 +28,4 @@ const sagas = function* sagas() {
fork
(
membersSaga
),
fork
(
settingsSaga
),
]);
};
export
default
sagas
;
}
app/sagas/members.js
View file @
f2d05d7f
...
...
@@ -2,7 +2,6 @@ import { Dimensions } from 'react-native';
import
{
call
,
put
,
select
,
takeEvery
,
}
from
'
redux-saga/effects
'
;
import
{
Sentry
}
from
'
react-native-sentry
'
;
import
{
TOTAL_BAR_HEIGHT
}
from
'
../ui/components/standardHeader/style/StandardHeader
'
;
import
{
memberSize
}
from
'
../ui/screens/memberList/style/MemberList
'
;
...
...
@@ -10,6 +9,7 @@ import { memberSize } from '../ui/screens/memberList/style/MemberList';
import
{
apiRequest
}
from
'
../utils/url
'
;
import
*
as
memberActions
from
'
../actions/members
'
;
import
{
tokenSelector
}
from
'
../selectors/session
'
;
import
reportError
from
'
../utils/errorReporting
'
;
const
members
=
function
*
members
(
action
)
{
const
{
keywords
}
=
action
.
payload
;
...
...
@@ -40,7 +40,7 @@ const members = function* members(action) {
const
response
=
yield
call
(
apiRequest
,
'
members
'
,
data
,
params
);
yield
put
(
memberActions
.
success
(
response
.
results
,
response
.
next
,
keywords
));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
memberActions
.
failure
());
}
};
...
...
@@ -61,17 +61,15 @@ const more = function* more(action) {
};
try
{
const
response
Json
=
yield
fetch
(
url
,
data
).
then
(
response
=>
response
.
json
()
);
yield
put
(
memberActions
.
moreSuccess
(
response
Json
.
results
,
response
Json
.
next
));
const
response
=
yield
call
(
apiRequest
,
url
,
data
);
yield
put
(
memberActions
.
moreSuccess
(
response
.
results
,
response
.
next
));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
memberActions
.
moreSuccess
([],
null
));
}
};
const
membersSaga
=
function
*
membersSaga
()
{
export
default
function
*
()
{
yield
takeEvery
(
memberActions
.
MEMBERS
,
members
);
yield
takeEvery
(
memberActions
.
MORE
,
more
);
};
export
default
membersSaga
;
}
app/sagas/navigation.js
View file @
f2d05d7f
...
...
@@ -28,7 +28,7 @@ function openWebsite({ payload: url }) {
Linking
.
openURL
(
url
);
}
const
routerSaga
=
function
*
eventSaga
()
{
export
default
function
*
()
{
yield
takeEvery
(
navigationActions
.
BACK
,
back
);
yield
takeEvery
(
navigationActions
.
TOGGLE_DRAWER
,
toggleDrawer
);
yield
takeEvery
(
navigationActions
.
OPEN_WEBSITE
,
openWebsite
);
...
...
@@ -44,6 +44,4 @@ const routerSaga = function* eventSaga() {
yield
takeEvery
(
pizzaActions
.
PIZZA
,
navigate
,
'
Pizza
'
);
yield
takeEvery
(
sessionActions
.
SIGNED_IN
,
navigate
,
'
SignedIn
'
);
yield
takeEvery
([
sessionActions
.
TOKEN_INVALID
,
sessionActions
.
SIGN_OUT
],
navigate
,
'
Auth
'
);
};
export
default
routerSaga
;
}
app/sagas/pizza.js
View file @
f2d05d7f
import
{
call
,
put
,
select
,
takeEvery
,
}
from
'
redux-saga/effects
'
;
import
{
Sentry
}
from
'
react-native-sentry
'
;
import
{
apiRequest
}
from
'
../utils/url
'
;
import
*
as
pizzaActions
from
'
../actions/pizza
'
;
import
{
tokenSelector
}
from
'
../selectors/session
'
;
import
reportError
from
'
../utils/errorReporting
'
;
export
const
Payment
=
{
NONE
:
'
no_payment
'
,
...
...
@@ -39,7 +39,7 @@ const retrievePizzaInfo = function* retrievePizzaInfo() {
if
(
error
.
response
!==
null
&&
error
.
response
.
status
===
NOT_FOUND
)
{
yield
put
(
pizzaActions
.
success
(
event
,
null
,
pizzaList
));
}
else
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
pizzaActions
.
failure
());
}
}
...
...
@@ -47,7 +47,7 @@ const retrievePizzaInfo = function* retrievePizzaInfo() {
if
(
error
.
response
!==
null
&&
error
.
response
.
status
===
NOT_FOUND
)
{
yield
put
(
pizzaActions
.
success
(
null
,
null
,
[]));
}
else
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
pizzaActions
.
failure
());
}
}
...
...
@@ -68,7 +68,7 @@ const cancel = function* cancel() {
yield
call
(
apiRequest
,
'
pizzas/orders/me
'
,
data
);
yield
put
(
pizzaActions
.
cancelSuccess
());
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
pizzaActions
.
failure
());
}
};
...
...
@@ -93,15 +93,13 @@ const order = function* order(action) {
const
orderData
=
yield
call
(
apiRequest
,
route
,
data
);
yield
put
(
pizzaActions
.
orderSuccess
(
orderData
));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
pizzaActions
.
failure
());
}
};
const
pizzaSaga
=
function
*
pizzaSaga
()
{
export
default
function
*
()
{
yield
takeEvery
(
pizzaActions
.
PIZZA
,
retrievePizzaInfo
);
yield
takeEvery
(
pizzaActions
.
CANCEL
,
cancel
);
yield
takeEvery
(
pizzaActions
.
ORDER
,
order
);
};
export
default
pizzaSaga
;
}
app/sagas/profile.js
View file @
f2d05d7f
import
ImagePicker
from
'
react-native-image-picker
'
;
import
{
call
,
put
,
select
,
takeEvery
,
cps
call
,
put
,
select
,
takeEvery
,
}
from
'
redux-saga/effects
'
;
import
{
Sentry
}
from
'
react-native-sentry
'
;
import
{
Alert
,
Platform
}
from
'
react-native
'
;
import
Snackbar
from
'
react-native-snackbar
'
;
import
i18next
from
'
../utils/i18n
'
;
import
{
apiRequest
}
from
'
../utils/url
'
;
import
*
as
profileActions
from
'
../actions/profile
'
;
import
{
tokenSelector
}
from
'
../selectors/session
'
;
import
reportError
from
'
../utils/errorReporting
'
;
const
t
=
i18next
.
getFixedT
(
undefined
,
'
sagas/profile
'
);
const
openImageLibrary
=
options
=>
new
Promise
((
resolve
,
reject
)
=>
{
ImagePicker
.
launchImageLibrary
(
options
,
(
response
)
=>
{
ImagePicker
.
showImagePicker
(
options
,
(
response
)
=>
{
if
(
response
.
error
||
response
.
didCancel
)
{
reject
(
response
);
}
...
...
@@ -39,7 +41,7 @@ function* profile(action) {
const
profileData
=
yield
call
(
apiRequest
,
`members/
${
member
}
`
,
data
);
yield
put
(
profileActions
.
success
(
profileData
));
}
catch
(
error
)
{
Sentry
.
captureException
(
error
);
yield
call
(
reportError
,
error
);
yield
put
(
profileActions
.
failure
());
}
}
...
...
@@ -54,39 +56,50 @@ function* updateAvatar() {
};
try
{
const
response
=
yield
call
(
openImageLibrary
,
options
);
const
source
=
response
.
uri
;
console
.
log
(
source
);
const
photo
=
yield
call
(
openImageLibrary
,
options
);
const
formData
=
new
FormData
();
formData
.
append
(
'
photo
'
,
{
name
:
photo
.
fileName
,
type
:
photo
.
type
,
uri
:
Platform
.
OS
===
'
android
'
?
photo
.
uri
:
photo
.
uri
.
replace
(
'
file://
'
,
''
),
});
const
token
=
yield
select
(
tokenSelector
);
const
data
=
{
method
:
'
PATCH
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Token
${
token
}
`
,
},
body
:
formData
,
};
try
{
yield
call
([
Snackbar
,
'
show
'
],
{
title
:
t
(
'
Uploading your new profile picture...
'
),
duration
:
Snackbar
.
LENGTH_INDEFINITE
});
const
profileData
=
yield
call
(
apiRequest
,
'
members/me
'
,
data
);
yield
call
([
Snackbar
,
'
dismiss
'
]);
yield
put
(
profileActions
.
success
(
profileData
));
}
catch
(
error
)
{
yield
call
([
Snackbar
,
'
dismiss
'
]);
yield
call
(
reportError
,
error
);
if
(
'
photo
'
in
error
.
response
.
jsonData
)
{
yield
call
(
Alert
.
alert
,
t
(
'
Could not update profile picture
'
),
error
.
response
.
jsonData
.
photo
.
join
(
'
'
));
}
else
{
yield
call
([
Snackbar
,
'
show
'
],
{
title
:
t
(
'
Could not update profile picture
'
)
});
}
}
}
catch
(
e
)
{
// eat error, om nom nom
// error from the picker that we cannot do anything about
}