From 69712baa02726dde1c0bd3349cbd163a7683a64e Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 11:50:05 -0600 Subject: [PATCH 1/5] Normalizer: normalize required account & status fields --- app/soapbox/actions/importer/normalizer.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/soapbox/actions/importer/normalizer.js b/app/soapbox/actions/importer/normalizer.js index 66524b556..0f3f2da6e 100644 --- a/app/soapbox/actions/importer/normalizer.js +++ b/app/soapbox/actions/importer/normalizer.js @@ -15,6 +15,11 @@ const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => { export function normalizeAccount(account) { account = { ...account }; + // Some backends can return null, or omit these required fields + if (!account.emojis) account.emojis = []; + if (!account.display_name) account.display_name = ''; + if (!account.note) account.note = ''; + const emojiMap = makeEmojiMap(account); const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name; @@ -41,6 +46,10 @@ export function normalizeAccount(account) { export function normalizeStatus(status, normalOldStatus, expandSpoilers) { const normalStatus = { ...status }; + // Some backends can return null, or omit these required fields + if (!normalStatus.emojis) normalStatus.emojis = []; + if (!normalStatus.spoiler_text) normalStatus.spoiler_text = ''; + // Copy the pleroma object too, so we can modify our copy if (status.pleroma) { normalStatus.pleroma = { ...status.pleroma }; From c084a7a232a4a8df2913fe126c39b1feb9ea854b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 12:19:28 -0600 Subject: [PATCH 2/5] Mitra: handle status context endpoint as a list of statuses --- app/soapbox/__fixtures__/mitra-context.json | 107 ++++++++++++++++++ .../actions/__tests__/statuses-test.js | 29 +++++ app/soapbox/actions/statuses.js | 16 ++- 3 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 app/soapbox/__fixtures__/mitra-context.json create mode 100644 app/soapbox/actions/__tests__/statuses-test.js diff --git a/app/soapbox/__fixtures__/mitra-context.json b/app/soapbox/__fixtures__/mitra-context.json new file mode 100644 index 000000000..91b48420c --- /dev/null +++ b/app/soapbox/__fixtures__/mitra-context.json @@ -0,0 +1,107 @@ +[ + { + "id": "017ed503-bc96-301a-e871-2c23b30ddd05", + "uri": "https://mitra.social/objects/017ed503-bc96-301a-e871-2c23b30ddd05", + "created_at": "2022-02-07T16:28:18.966874Z", + "account": { + "id": "017ed4f9-c121-2ae6-0805-15516cce02c3", + "username": "alex", + "acct": "alex", + "url": "https://mitra.social/users/alex", + "display_name": null, + "created_at": "2022-02-07T16:17:24.769229Z", + "note": null, + "avatar": null, + "header": null, + "fields": [], + "followers_count": 1, + "following_count": 1, + "statuses_count": 3, + "source": null, + "wallet_address": null + }, + "content": "@silverpill sup!", + "in_reply_to_id": null, + "reblog": null, + "visibility": "public", + "replies_count": 1, + "favourites_count": 0, + "reblogs_count": 0, + "media_attachments": [], + "mentions": [ + { + "id": "dd4ebc18-269d-4c7b-a310-03d29c6ab551", + "username": "silverpill", + "acct": "silverpill", + "url": "https://mitra.social/users/silverpill" + } + ], + "tags": [], + "favourited": false, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null + }, + { + "id": "017ed505-5926-392f-256a-f86d5075df70", + "uri": "https://mitra.social/objects/017ed505-5926-392f-256a-f86d5075df70", + "created_at": "2022-02-07T16:30:04.582771Z", + "account": { + "id": "dd4ebc18-269d-4c7b-a310-03d29c6ab551", + "username": "silverpill", + "acct": "silverpill", + "url": "https://mitra.social/users/silverpill", + "display_name": "silverpill", + "created_at": "2021-11-06T21:08:57.441927Z", + "note": "Admin of mitra.social instance. It is running experimental ActivityPub server Mitra.", + "avatar": "https://mitra.social/media/6a785bf7dd05f61c3590e8935aa49156a499ac30fd1e402f79e7e164adb36e2c.png", + "header": null, + "fields": [ + { + "name": "Matrix", + "value": "@silverpill:poa.st" + }, + { + "name": "Alt", + "value": "@silverpill@poa.st" + }, + { + "name": "Code", + "value": "https://codeberg.org/silverpill/" + }, + { + "name": "$XMR", + "value": "884y9LmsWY7PQNsyR7bJy1dvj91tuF5spVabyCnPk4KfQtSuzFbQobTFC7xSemJgVW1FWAwnJbjTZX5zZWbBrfkv62DB62d" + } + ], + "followers_count": 27, + "following_count": 15, + "statuses_count": 110, + "source": null, + "wallet_address": null + }, + "content": "@alex welcome", + "in_reply_to_id": "017ed503-bc96-301a-e871-2c23b30ddd05", + "reblog": null, + "visibility": "public", + "replies_count": 0, + "favourites_count": 1, + "reblogs_count": 0, + "media_attachments": [], + "mentions": [ + { + "id": "017ed4f9-c121-2ae6-0805-15516cce02c3", + "username": "alex", + "acct": "alex", + "url": "https://mitra.social/users/alex" + } + ], + "tags": [], + "favourited": true, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null + } +] diff --git a/app/soapbox/actions/__tests__/statuses-test.js b/app/soapbox/actions/__tests__/statuses-test.js new file mode 100644 index 000000000..71a0596a4 --- /dev/null +++ b/app/soapbox/actions/__tests__/statuses-test.js @@ -0,0 +1,29 @@ +import { Map as ImmutableMap } from 'immutable'; + +import { STATUSES_IMPORT } from 'soapbox/actions/importer'; +import { __stub } from 'soapbox/api'; +import { mockStore } from 'soapbox/test_helpers'; + +import { fetchContext } from '../statuses'; + +describe('fetchContext()', () => { + it('handles Mitra context', done => { + const statuses = require('soapbox/__fixtures__/mitra-context.json'); + + __stub(mock => { + mock.onGet('/api/v1/statuses/017ed505-5926-392f-256a-f86d5075df70/context') + .reply(200, statuses); + }); + + const store = mockStore(ImmutableMap()); + + store.dispatch(fetchContext('017ed505-5926-392f-256a-f86d5075df70')).then(context => { + const actions = store.getActions(); + + expect(actions[3].type).toEqual(STATUSES_IMPORT); + expect(actions[3].statuses[0].id).toEqual('017ed503-bc96-301a-e871-2c23b30ddd05'); + + done(); + }).catch(console.error); + }); +}); diff --git a/app/soapbox/actions/statuses.js b/app/soapbox/actions/statuses.js index 150b6d8c7..12dfaa576 100644 --- a/app/soapbox/actions/statuses.js +++ b/app/soapbox/actions/statuses.js @@ -143,10 +143,18 @@ export function fetchContext(id) { dispatch({ type: CONTEXT_FETCH_REQUEST, id }); return api(getState).get(`/api/v1/statuses/${id}/context`).then(({ data: context }) => { - const { ancestors, descendants } = context; - const statuses = ancestors.concat(descendants); - dispatch(importFetchedStatuses(statuses)); - dispatch({ type: CONTEXT_FETCH_SUCCESS, id, ancestors, descendants }); + if (Array.isArray(context)) { + // Mitra: returns a list of statuses + dispatch(importFetchedStatuses(context)); + } else if (typeof context === 'object') { + // Standard Mastodon API returns a map with `ancestors` and `descendants` + const { ancestors, descendants } = context; + const statuses = ancestors.concat(descendants); + dispatch(importFetchedStatuses(statuses)); + dispatch({ type: CONTEXT_FETCH_SUCCESS, id, ancestors, descendants }); + } else { + throw context; + } return context; }).catch(error => { if (error.response && error.response.status === 404) { From 2c51054ae4189e98336c7fad77f047301b2b8852 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 12:20:03 -0600 Subject: [PATCH 3/5] UI: actually, don't wait for the streaming URL to render --- app/soapbox/features/ui/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index bfcfdb3cd..1e0ed2d51 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -670,14 +670,12 @@ class UI extends React.PureComponent { } render() { - const { streamingUrl, features, soapbox } = this.props; + const { features, soapbox } = this.props; const { draggingOver, mobile } = this.state; const { intl, children, location, dropdownMenuIsOpen, me } = this.props; // Wait for login to succeed or fail if (me === null) return null; - // If login didn't fail, wait for streaming to become available - if (me !== false && !streamingUrl) return null; const handlers = me ? { help: this.handleHotkeyToggleHelp, From c4bf347daebcd8d61ea7023ef2ee77ff9c0dfc03 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 12:26:11 -0600 Subject: [PATCH 4/5] MediaGallery: fall back on `url` when `preview_url` isn't provided --- app/soapbox/components/media_gallery.js | 2 +- app/soapbox/features/account_gallery/components/media_item.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/soapbox/components/media_gallery.js b/app/soapbox/components/media_gallery.js index bad4c1b48..34c79c140 100644 --- a/app/soapbox/components/media_gallery.js +++ b/app/soapbox/components/media_gallery.js @@ -168,7 +168,7 @@ class Item extends React.PureComponent { onClick={this.handleClick} target='_blank' > - + ); } else if (attachment.get('type') === 'gifv') { diff --git a/app/soapbox/features/account_gallery/components/media_item.js b/app/soapbox/features/account_gallery/components/media_item.js index 1cccfe070..0c5b0afdb 100644 --- a/app/soapbox/features/account_gallery/components/media_item.js +++ b/app/soapbox/features/account_gallery/components/media_item.js @@ -88,7 +88,7 @@ class MediaItem extends ImmutablePureComponent { thumbnail = ( From d260cc2e2c3bd241c74f3be1e25c9015bb7f676c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 13:06:20 -0600 Subject: [PATCH 5/5] Add fallback avatar --- app/images/avatar-missing.png | Bin 0 -> 14800 bytes app/images/avatar-missing.svg | 116 +++++++++++++++++++++ app/soapbox/actions/importer/normalizer.js | 2 + app/soapbox/components/avatar.js | 24 ++--- 4 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 app/images/avatar-missing.png create mode 100644 app/images/avatar-missing.svg diff --git a/app/images/avatar-missing.png b/app/images/avatar-missing.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e6b5709c611c8b26d18d3c55bac315ae46b176 GIT binary patch literal 14800 zcmch;Wl&sEv@Y1VTL>OJcmu&50zra1G~T#F@ZgrNb)M*ONlvxmO&V( z($V3h-m&?rC#>`-kXJmTrt^}DQ9P}qe^ELzxd?S^-q3Jwa5c@UZ{5 zf+4OV8=!{{7FWUw=gB16^kBIIO(*nNmz>`487_=!^+q z38&&tZA@F7W5Vi%-Dyp%^lu7el^+l3VjUT<9O*gI2brTsbW_705yv9?)B%3$8kj7G_Q2xR4ILw4ynkis!Jx*7% zfI`Gzv#k?SfiDmjzeL@Y=XHYFf5eW|rTtllt4pPFCLuMU(FdQFu*bOzt1SDMn~N4R zm-NSe6Gj=thQN`QPtPve*e^6JA0hXOsVAJ(|jr8k>i?W?yjnl>RInh_BAV5@tGOo@?8I_!t$ ziko(hN^q4c->%wxtnAT#_0Vh3zd5e*AfOAY_+^hYC;Wm=*6R@_4Qi51=-rz@ZBPnT z!(YAY(lV1OinJf(O|HmpHLZHD>)-?f=>`|_m0q6iOcd3hLdDyn*AIW}r$hWn7J8E(djj5?-a-tHsocU! z`btyKkA06ldLu=fri?aybhm#>1%|!44)d9S2gwr;U+taS-?t~y;)QxMwGADhM#;@~ zF2-I7@vz?A1ckk53_f=6DO_u7UR5FC4VNI-cu&_bPF@*$FR^h5!i$%E>0VA~c5sB$ zh8`_yrgAek%qlPsNrGUXyA2w5vN%OD9cPZt1g(cZp8n0=(8lD+WkU7TC7FDquz2Jo zb#-`1J&uye;OfkP^MNAVF&9tsNm@6GXCb-rRrp|vb+Qppg#{MzNgh>X z<5-|55&DOh>X=%QJn+%}BkJ~gw4#$O$+v_s&l#&%l>R}5^xMRRfyRXF`4l2p|9;Ea{Bt8%mrmdJJ9MgJ>3hu)l<7!_O8wAG7+iq1;U z7uxamlTH+4K@j9|Q=c8O?kbI^q{vF-VOz}d``43!Y8s5{TF@YyT-q?S8C2-`a_y>niq{oYdvQXfH}_J_*v*rvQ*fZTI-E zRa(Zm zkp)^fm!~WG?5V4(zY^{cxeJ5h2OI1j7syW|HPS=j zEHBO5aatCXhk-PEZ;SWLnl}{lSI9-&{Ik7siExk@XD`p|)Vc%0CjAFskym6o6>rCA#7mbB9dyio z3ehL_PN_Q1e*5(NHW>x>&A;JR?uk>yE^=c_B{83S?yr*+cbufuG;@Kr`CsY3%cpj& zKonHK1x0EbYZ;B=Z`JjFSH@mAc|+7Q&9D4igYOZA@ey5hO&DIH&rMAogi*H-g=z`d@t$5OxMPL%0GKZ(U$ayUD&|6`m&C?pl z`e+|m^?=B!<#|k|3^=M*?2}3|kM#WwNNU(HqS=dCjVnpyZ&^r3%{?@*+NTqro*oGX ziL>ybPUduJnA}qAaz|7dOg<_%1? zFDADbD>P8#Az{1Cdu)#a{erk%kIT<3Z_yz?bz@Vc32r&8li&EUs&;X~oGMQ`C4^n2 zLMaq3Oyt*v0Uv;ad_QhHhCiQeCEF6oIIfvSLy@y9%iaHq^O4ipgWq7YcwD~B+SNr% zu0OMOXTa?k11er~z1bRx5&cJtLISn)$rY*wEe)@*!>zNZB6Su%NIi{{8mj$l{}Kw9&qN&pfjmM_6hpV>>cUa8)cY-PQuWY!u?im#S*pMvZ>IRW4S+wv|!=E z6j)BSA*Za|qpK_2o*=P@{rOEfu-EkynmpIE%jsj)F0 zx*HzMx(7A}E-0mIt;|rCWaRN0sX!w7q&yu}EMkF0MokDkL5ANJGCou?{B&88ZQj2_ zKo_Vg;B_p`NBiqaOItACsYvA4d6*qD14v86o=m5-~ zpl7~KIa1Qev#>XDW|B(8c_<=g%}&OYnxb$SqnG+ORCG)MQn6Zk({*HyMM>c-$al~_ zp^y}_dl*?M9hRfTx;x<|c29oM#@3kb+j{;tipVRqI6)lK7~R|A^qXJ zr1PRl27{ZM%(lp{QNkBLOOG3^5IKWG!3h~q#VBY-87Bg((ziNiW*mQRc}3&G9W<<1A*`TN7KEye`+lYK*i@kQS|)tDt)YbzZhQ--tNi5$2S$$cXuT@7AtVZ>f^EhY5;b$B*e7PsbGy?Buq?swQplu)@BKW4 ze75$3B2lWJkkWJ?19|cgtQ@(=SDcES)73W<3) zKZ{avR^t=%(W~($1c*`taZ<>hN|<%REL6F;q}R+ToKP+h4x&UsU!D>bf@ivbllNbj|`q^nlIkp+)R#IuF*u#P~z!Zc5|9oD@7NIJmGfB1m}JEodLa91c~ zd9r-Mhf99J@om7~C-2jW8x94koxDUE>DML(9)!|qn4A`RI?lfYYIeXq0FEAf$GUY> z`hTd=a3*_lMn7o z$3!wBx(^=Y-^6q(-6E9oA|qkNETUGO!rlIH*E6e-KK;jWX`cgvDUoHn!zdPlpefY( zrsq}5jeg1l5*G=g?+#X)e4PD!J5oWGj@k=uT@HZGP7D>9EjZyZZAK^W?>JFc*j}O{ zLsVbk{kw@+v9TrBLDIT1j!doax~`1y_SPava^TI6i$OZjIEg&g(0y6l9dTXlNSv*O z7N>I^Jplql!nKA?PS`ii^|7~uYJzg)rhF93Y}d^5UJ#Z@=e)jAA)w$T(n)Z$O5GlA zJcvGtf&l^t%96g4ZSPLzJok_?PUDU1yz+G-PL#x+g%N|s!zI=(+w8Mx9B>C6iPOF9dr*VN5(+svfboapM9Km^YHZvQi2+ zBYe;Hxx4p0GJUP~NC4)!N;8pU>F$*n&0(q?GVF8vMvhXuQD~!E?|Q&pS?}o8Wjv5< z0i@#4?D(Qvxj3t|;#Z5ifJ~ip^f;li8YpOzJk)Xu4jAn255_+vl0BuU=&ua8tE}d@ zst6QNtJNHaBTPKF0h0eaIx11y;T90G>hDuHa84BpU(Rb;Yrm&!mt@-C1OqM$n!|u= z9ul%8k?>{1!`{5r-kNB}n*^b~M-n+iiMOFAgoF6#;&jDJa;ZqsJmkH7lL)un?UzNy zR^+WBL$O8JvpwncsUL0ixEBE4X=rgfj-B#FW*Go1L+&_9iRp!2Kh1OpbdthKeo` zsi)3^cXykhA$!+g2hR@)O<`^5VQxB8*n=m)+!8<&-=`LCF^|PRTG0fjxc8ClwfDn; zy?-U1V-zoWuGqsUz95!~yG~00z5;wd_U908_3S*x34$Y`)XdCXDS!w?WA8DbBNEe% z*v*fly8dMS`n3FO#ySmX+z$<=<~4KN#K!S)8iWQRr?s|FQ*)I?fSu5Xr?PiCuuNVJ zeGC0k(dyfI5bYE0NEKjSf-i6!J7YL%lpZa26&K)^_b$o3Q(`A%2b4ly$O@6H84p_D zBR-G&PVk;@Ey{gg4Kz-H2l2I%h6+eO+=!)00TqCbP@kid|L<+l;vyYUGU@y5T#|@& z!)d9E?e&T8*R)R`cjD-2u%t4MD}r!mU9tbTH{f@&{KWe;Tv(WX+VBCg{sz$`ZzlH=)5MF5N<~ z`+yLXGTHby|0BIeIaXzNdH(oc&%eaxuZ_3{)Xxv!ZFN^loX-&tqx%RbODmxn-q={7=(i&}O>3L)hPoC{~S7FuR7>atTe3?b_;b*K%|Jv6% z0pzVdBR6ZUQryFnyaG>Y8KX{&o;v#xt7m;LgN635e>iXAk*1Cb12iTK7(_VfMry6y zK0C){rufNvRH@b3SN`EFxVEb}~AAvks3&6KF0(0~<(H&-!Q4&M0%+KxU zDza0Pu01BTM$@P>Wp69F@vLo(v0{Dk5e^BTk3i5B-l2_X3#9mV^LPo8m}WvrAeiHM z6aK97Ie;)QQnH1k^Dsf|XxM{KrutCxI-YBa;<rY*;?0HRo%bZvxG(sn+bJ<-; zK@!j3F8-+dGec8LZApe=WQ-y_L8&=mq$(C89O(HIzOf%4P9Elfp_3OLA8&C%rYXqQ z3`IL8gstBSbHnpKFx;NHc#Ytpx#Plxejg+bbVv5EAAKI5bI4ZVY>-6C!g$Mz z-tgdA`^+K*S%ngOupVl!2-$~+G|2@oG~#qB2?{6@SNjcuDDhJFK?{6MTqA9=gXPHS zz~1K8cJr zj{0Mv>PPeR9ZdEmVKC3TGG5nqJi?JnxBi)et9RE`(PQkA5j1g;`Sgu~}h0PCcynCZrkN);2QTbZ?40~D0j zDFUqYE6h=}YLqo$xEbGeC02r2j>}kf8EQ-qMkBWzzAV_Jzadx17SH)^$Wx+P(8Nt3_)|&{V<#_qP>X@ES-q)vfyUzOB_8 zbNX>G^0!a4$|VeNUtckSB~tdFC5W_PFdO$y4<+Ep0S>{R%E$$S)8 z8{{mdi)BId=ML@YJGN1PIdlJ7gztTuE+ED=pK=+dpf@={V+p@ljnOc@_^x)Xk0eM^ zB*R7OGM-$&_4AJ{BB>4b*texmUHm6UCtmR{;?IeXwD;XDEj!+)t%8s1EJ`0e8>~^< zxj3Y5Jw_$neV};$YJ?;Vb)jg-1Ha=(#j{$j)Xp0PH0H)1Tfq+xS$|9^5fiVME_(N4 zy)uV9oR4#@6vAhDxmY?eIfYFBhf`J)o`vQFAkJ^1Mn{VWHVEZEwR>5AI0iY{0%UFEx+blq@<$l zrK)sN(3MxhGmdc)g8ttyA50x*# zR>szi`_b?Pe?S5^B_7rMjPt+~=Qz#@yi@Fz<}F;jzv=8-hc z3=Hs8q63xYOj9Y`*P_OYgtN|XtnKoI9)p0=fgcwJAjIM3`ro)7b8<)z0w;-fM*BvX zqXgXU6;LvjRD6$>E3NE=mWTq!mVGt1>SG-b*GAy9! z&%|LZ%hsf`gOc!N;kLJ2<}o2`e8s8^p$bMKG1M>7bYiBB*2y?zO{&CH48wF3Z73O7 z=x;eM3<#uiTuWy7Fb5ZKEqq|Hr{Yp#RrM-Tay62uwZ)|&hPwbk^6?TKa=qmuRESOh zY4gmzu#6JKgoP<7?ZsRwckmC@WsW#A7Cx zo+sxICoJkA6XD7-Z1QYM4#qXjmz*QTw^tnkV(>jCrxnM$o@tl7YKhGn(*hRy@5T+@X5~3T(v>_$;rv~_I5NGpWo#q zUo3@)p!-RhZq@!LA6sq)<(#*C4-dyRe0Iw!8XDZL2PzlDo12@w-cGY4zZ*TCoE%yb zLGlH0QAa=I=;yP)z9>~^@4zE7w8LJhg0V1Zad9zW5H$0T(F+@l);?G3y0|k{=~K0V zQkzb85t#`)pIwX8NGK`Aysi!iShTVPT=si|QQT^lCo}oNQ3iO}Q8WD>&xf^tKmYyR zoh$15uoEjr!DFLQp;h%7-GPg?Vt3n#$)WkHyWp@c6iDa{SvFT{OTWJ83AK{qINg=X zz3WLBq<^PJ8zy>WZ}U)j;a_e-ud6Pn{=TP8k1%~}GPt0h(CmqToLt1}`!}gb!fbx0 z?a@RAH^tSR;aL1vl?RI3VbPRg&+}ru4(t3Ck97kBlFseLxuL>;&Uc2#$H!5y-w+cJ z49+kob3gB%Q2^kd90yX^J5sTrsaNU-xr+%mo*UcN#Xx|BX!6il{BCRM<{R|W6_{6; zLBT_Wd(gBz*eW9Y^wfSdzQh=2kI9O8dPwf%U@I3Yh~&T?#*i-Oa8n_auY!BiOm^`byI(_G-DK$Is(Oc z2MVzLUQs@bHYI-G;V##H=4S6O50Go=Y3rmid7ltpH5jc{rl6>3(CWPRyZgm(xaVxM z^Z1ucW1G04q2Zi13nSyV&rJ0zkHZ9F0(+1yBa%W{t9pErtQsREL5 z3yaT5k`#staUZTy(-0tAUX~<~hcSDF8=-D?^nxX0fCA((unx)Xd1x23&}^y^B9pBt zRI_$=zUcdk@q4{heK@43s7STrdcI7(O#hvjSnf8`-<#9%F_!gqkJy0BA9`$-KP$Rb zSy?Bqsw)U7V0Eve8;F{;EkZf&FA9vBf|q*Ka55$TZWO!TLiz6_|E3wHT6_uZd8lTL z`kXYupr)ar;pusQy4HNWTz_cT9|)`KSaYo6DDnIVEaVd}@f?GpyPqGJGM``wCzpbO3xND~)C znWGcH3NbM;nVo)kuQFU7e`wE5S|*I(8DKe`quR}R|1*YMNUgOlG7_U5)d9A;s#~X# zG)nyS$B{;Ya-Huz4)`KV&lxh3?otDuEuVOL`K4zZ$#;(d2AV)L0+aSTfLqzQZMLT8 ziPv0F`UhNplGW&5l%~fYnw(^1XaD_heeAZr{G&IxOjue)1vh%K*vRjm?p>VP*@|(0 zh|^WjQnf)Qw{=1VOF_O6LPFFu7tbXwggPf8@?>v#}%;)Q@`K?qAynOd({L?dr zBxAm$!>W(0IDyx`s>F#6T0oRByS_b`DG;1G*&R(B@Th-GRi_tn-bL-ydn4)tVNO5$o7%_}^|^yJG|Z2WN4k4(->R#!i<`+q8?ojd)y6DvSC+UADD`Kw?e>^p0K+xo zT?8>AAX+IftkfGufu4Gb^=QhwkQ|(y8LFvC>_f;?Zis8#=Zl`1cQaNU-VvaEm9Ifprll+;6I>JaPU;ra)mrwqB z$2IdD9=JRGjXdz$!%ab4S=lQdT|hv<0T7kR;1V z;s|VZJa+Med9*Cqb!S*^NQj7r53#2zZhnSRs(Hd@XVsd{_#HQenLWT@aD%xJ5Y0oj z+wSNxzmIMh_8hI~PhUH%_S30e$>A@A#$Mn-ylcW_JWz2`O2%a(U-5Tv%&y9 zYK@-Nw}mL17*s1UYSJNO+r#O=uQY9XLQvw7rqIY9j$Gvh1Wv0If}9p@z}Zc2yMXW} z>{>^95=!X@*uNy;5nL^m!o-b(X2;(v1YKaT{$>u4n*wIP3A;?|ZYuu;kK+^L*Bccc zTfV80?YD<>p%ICLf2`ix>$N)5C3iLvRkg&9QiooR+;Gz_K@`?{NMTpw?%%!BNjine zYiv_-c=g=U(!q^v`YkG!44DEh^vPe3fVA7vBGd{_enhXgn5@(OnZuo=srx`J{RDmZ8OCo}zbSrq<8R<v(H9MHu8O8ugvezvq2$cWeMmrdIRy=STn8lHyrR_a*J$+dsAYe6I{GKI>@@A53u} zQNM1k9{IG@=4MNd1LopN#5vOp-rL{T^-1%4dN|M9a6elwQ!8V1u*l9LJRzp_u_7bN zFhUa(>FMULR4h5@R9GU;HU%SR{w-syM)Z_m+2+$xpi%JaK?dg8=FrY5I5a>3}x2y8jvgr3&iBsp2**pZF=2kpVnjc*`6!Sv!m8&>7%S8`85haIty0XMi7 z+QeX8l(N?LXZE6aHc~l%J61wlSnWoOQ$cAdBmZ3^xyRifV?EJn06Q7ozU}JjD!evi zrnT@WsEew?@mY`)Fqaz#Eu<#Gw_4DM+{%&SjxE_?v2GRK$_Wi4eOmfHj(pE(W};Nj zqi`h0bm%r5LvHUQ5%)0Dy1Kghvp=-^wH`FJ#(B4xT{Kv(NKRRqA=1i^m)x_Q&7e)? z&^Lq*18iYS6`VB(=35({tqcJqB;)GPf8?5XQ7x0hn^TrOkH5F=$R0gy_3wh@k}YBq zlIm@7C`I*~9Sm%2Z2He8W{c$QUohoUz<5uI4%`9)t@-(Vh78V?tLSgDZJj_?$q7dC zw53o>-^|6vmYU#ybQ~{H!?&2+EX8KGh3c;8SP}Y zK-pdBD?&B;DcM^aZgv`(o+I46#v>lOSEDzlYe2`V-~IQdy}jsOOuTO90$q}vB%PfZ zVGA#VK7F3fqt3GhgP*qF6w|j;L2Nm9;}$`(tjE<(WwwB8TkFF4hld2x=>48RgtSwM z=KfF|bphBDvt-M%m!nB=IKNCR3vtzl^rRV$*vwH|=#1z$_20f>QZgmqg$MpzK87ud zD}JqVhO68Qp5)fP_Ij!{9e(%gtF27Tn>_IfWIcg-J9#LcJf_y%6q%Ema~wp$TPYH= zqI;JIcGNHPp}@M^FilpxfNF5my4QjT1LdFw(<*-EzwiVic>8?*n%-f5?)K z7fWz-pj4DXocbcA_1i>_`ND5c#j`Mr%AK#i&@ve%JPz0pm=PFI zfK61`oVVg$oS%n2V~pRNtbBN0es}2MSTJ$ZQ;yS{94S^yk8`xO!0~&C%S-+Gz#1Nu z0%&$<%92LCWBkUWwW-6|F3<(aFEQ4ma!XCvYSYKZnwgZY4i*P_kKbk$ zegoZ0QDE=WOE8j7Y;Cpm=L3k{$mbmCpoed*(KdC|%)kaJCWf(j`<<8V21zS8zD$yS zKF^MHzW#R*5ifGGgW6;PCSNR5j5+OF!N}97~CS z@AGaJ&(qWMRk&NNyYJr{axuS-=zbY%%B!6bpe2uv3Aq;1IkzV#hOi=lcZmQf>VI=W zLejM;Y6GOtySUc%(Nh4G&dg|`9GIDzJ>LJyH8(d`e1TNFZ$v|o2YEq z_5%pLna@>xkDA!1;5uTn8ff`Oz~CbcTP)DLw$DXeytl%ops6VZd}Y-wRicy~!0O&v zo|N=@b>rvZ;fhs!jP+bG&r_s*A9oB27*JjD286Q)NELpZ{PYg0BW#hJoV;-Gw$*7z zI+NEvtph`+HLm+;+Cu@lxSGhItW~AE(BbJq-}$}TKxj5O+HlK+UtT(>w>O~ZAi;tx zVHp*|*3Leb!N3o&+#a_u;_N?dXqUfo{r&EKhH_f4m>U^w0o(mtsmc_tV!zz!?^50J=TNvsfWl1Cx|-ec z`&$)0>hgGZ9v6pO?7#9lVt#%euzT-Mn}2H_{2FpyPS&aU(H4`_=g?$u|F&=Q!#Q0}7mlPfI>N zJ{K1k00aaHcUt|L&duevel=LmOW2KUVQIQcazCa2qquoe zB9eiVQ>}D?@p&==JUqQZ8Vq=PfCl16D5L;<(Q&H_;5`zFENe*`b?s$kWj~;{OL_nK z5oqX0eXJUaT4nI+u9mF#+ff8;Qk<>t1A%tg{I+impttvot<@xxR&JIBYi^-Ic1N}EmgWTy-`I5^FpBlEcvVF6Obh0K>C{cW_ua7ac0 z*EKhWGs!jD#W=}Q&A2R@k0^_P_RzU(kCmYg(Udbf_KkqVqLZ5U?h#((AW(v%p`if_ zMIz=WtP_T(Y}p@zH30W`R8ixw-g5q<7vYHg0wCrRjR4*b^Z%sEb)21?F`Q`^Z+|m- zW$ePmP>75b##&70*x%P@DEN4bBfbPm6;q@Kj9uCJ-Xn9;d45IBfjgG+b&~D2Yj+=d zrRWgvCD~Q}Vg*E#3>?Cb6L61kgsMj9MRBfz1N09vt-P~oKqj4N-#=QY(CGSOK~F3|`sE6+#H)0bqj<`Bd9PTk`RAKSxc_^p)5}_BDlr%qJjC};)s7^Zhl!4*lNGN6$HQ@f2~~Q{b?x#`z|IE@@gxA#v$Ec>v$Nxt z_pYz6137Gj5-q07?Ui!$_RadpO?4Kw81UOVC4ipXXh`bXzQ4QEZ+DMw9|1{JKmEP! zetG`uj3sV2PR?feoRPK>|a{B-SSsHcMPu3da$*A8-N5oM}24>M7uB}S<=0f3+i?gEB?U3@!E)Bc&5e?>a!qOJ9YAQ>eTVTmtfOKVd%^7X zRJfK*aeClk2aHv83(X0hv{(~YhJ$w;%qY{{JAw9v(AX$5EC8(BBVXdC1y-i*${AcauWFT14QXeq2K8R zMEt73!NFi;EE=}7l9CeNb2HBL5!1L(>evSRHQsHC3+m~CnF5(I%4YihALFutO(br> zf=U^={PoglY|sH{9h}%V|JZCGs{#ZAi&kYChpDu?yF0+ECnP2o3@%p zjFXSYNElCuOw@}bi(fP7@=0IM2*s*%-jl1~Tu!p^TC*F0`}d@PVicf$RSTri*d{lD zD1F|KBbFuNeFM;!3`$wcm$9eIwWb>w($Dojw?=W|C~1M#mDDF|`w?_6VE<{k9sDpO z(u?5(Hh@XS`&RiVHs zx&Te(<>;D+o+gE~0AE=(sh5pg=-0wMHWZ8nEF$Fl)5XZ$`-;n(ChNKV$NS44Uwuyj ziitZyq8kwY=@DB0jYkF+?Bt+XDt=eFx>1=Wb^P+;;;!}fGShxNR0@9ZrIsM zuohs)!MfaQ3&w0`eq&=}fTTeXx3dO}n3tEwEm-0E<>ppO^@h~+-?-u&EosZQ-zSRS z6Ve031+rXAlVjICJ-`)j9*#GpgfI}yxW9q^_Za~}DZOjH&bAay{MG3ik!E%)hM}dJ zfxVix$875jxxv3d;i6<`wzYFX^)M~LEtaH_RZ^ngZS(!x#N~3d+3Ed7y{xRv zSwINu*gmOh>}Ky2_um8Q{kGY2bxo9$v`d%BqndM@$(Pcu)^{quDMEi2+Co{3fKm9||WB}^ON=y4F6j5$X zYXGxu*aB*^AYxv?y5_%NcYu_oPhmYJ;?K@S?fLn*y${VRgcZE z!z%S{>A%A(nS73HOia`mo!I1pX_FRf4Iq-YfTmuy9>bv&1h}TrRV8PeODRfX4vz1Ze+&FhJAocd;w`-2lZhXz`KC^p6_Qm z7C)Nq`p3PzeOdnVk^s29ohCU-bu{;W`*}!zV(=GHUclCoC2fsV`2aDwB*hlQ@h(w3 zWovQ=P~*mMF#o%|@Mc=J66xj-DO;3)F~}fGn_j?B;Yv zU%At(0-w}6b5}*ty13c?=p6!Jf&g=Ik8v76`5tG@gxq2XOMzqVD+AOS{O-Sj+bJs7 zVwW_c6ed#&@4OBQr_h)#wx4v#fU^o)uC7WzbW8bgC}C{nM5!*9q;+_pXJ96!kW~io zrOL`UWfksiG04Df44v&SQU!>rxchYxtzYkQQi0h242wABL+$oA;M}p#eAN^7jbS>uYsK+9zEn~0LI)99?Dg*vnd}2s$0N1_`wT^G^9wj zI_(YUXsuASunc|S_GpY&yw;7BH!qHsUq#(2`I!LEgNL0I12uc~B)~0-?DiD)03rZD zin<*9MBpOk7fA&?nqy4q%_RkwZ82|AJ zoE!t@{C92)nD{?GQGq{!17-gc!~S#Zf0^w6nDM{N^}jIa|MGDEIn{rCxc~fz|Et4* zLv;V;P5=93|K%0_9j^Oll>hlb|2s|l|FBU1du;n}vHx!~{SVgY`5(;zY>fZ+VP4tK aV(i#=ulV2_$bplZAXzCT$!ZB`(0>E8Zt?m6 literal 0 HcmV?d00001 diff --git a/app/images/avatar-missing.svg b/app/images/avatar-missing.svg new file mode 100644 index 000000000..7eb156089 --- /dev/null +++ b/app/images/avatar-missing.svg @@ -0,0 +1,116 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/soapbox/actions/importer/normalizer.js b/app/soapbox/actions/importer/normalizer.js index 0f3f2da6e..7c5aa8bd3 100644 --- a/app/soapbox/actions/importer/normalizer.js +++ b/app/soapbox/actions/importer/normalizer.js @@ -19,6 +19,8 @@ export function normalizeAccount(account) { if (!account.emojis) account.emojis = []; if (!account.display_name) account.display_name = ''; if (!account.note) account.note = ''; + if (!account.avatar) account.avatar = account.avatar_static || require('images/avatar-missing.png'); + if (!account.avatar_static) account.avatar_static = account.avatar; const emojiMap = makeEmojiMap(account); const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name; diff --git a/app/soapbox/components/avatar.js b/app/soapbox/components/avatar.js index d0df7959b..1bbca72cc 100644 --- a/app/soapbox/components/avatar.js +++ b/app/soapbox/components/avatar.js @@ -28,22 +28,14 @@ export default class Avatar extends React.PureComponent { height: `${size}px`, }; - // Only render the image if src is provided - if (account.get('avatar')) { - return ( - - ); - } else { - // Fall back on rendering an empty div - return ( -
- ); - } + return ( + + ); } }