Merge remote-tracking branch 'origin/develop' into ts-redux-first
|
@ -24,7 +24,7 @@ yarn-error.log*
|
||||||
!/custom/**/.gitkeep
|
!/custom/**/.gitkeep
|
||||||
|
|
||||||
# surge.sh
|
# surge.sh
|
||||||
CNAME
|
/CNAME
|
||||||
AUTH
|
/AUTH
|
||||||
CORS
|
/CORS
|
||||||
ROUTER
|
/ROUTER
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Soapbox FE** is a frontend for Pleroma with a focus on custom branding and ease of use.
|
**Soapbox FE** is a frontend for Mastodon and Pleroma with a focus on custom branding and ease of use.
|
||||||
It's part of the [Soapbox](https://soapbox.pub) project.
|
It's part of the [Soapbox](https://soapbox.pub) project.
|
||||||
|
|
||||||
# :rocket: Deploy on Pleroma
|
## Try it out
|
||||||
|
|
||||||
|
Visit https://fe.soapbox.pub/ and point it to your favorite instance.
|
||||||
|
|
||||||
|
## :rocket: Deploy on Pleroma
|
||||||
|
|
||||||
Installing Soapbox FE on an existing Pleroma server is extremely easy.
|
Installing Soapbox FE on an existing Pleroma server is extremely easy.
|
||||||
Just ssh into the server and download a .zip of the latest build:
|
Just ssh into the server and download a .zip of the latest build:
|
||||||
|
|
Przed Szerokość: | Wysokość: | Rozmiar: 14 KiB Po Szerokość: | Wysokość: | Rozmiar: 4.0 KiB |
|
@ -1,116 +1,30 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg
|
<svg
|
||||||
inkscape:export-ydpi="240"
|
height="100px"
|
||||||
inkscape:export-xdpi="240"
|
width="100px"
|
||||||
inkscape:export-filename="/home/alex/Projects/docker-tribe/avi.png"
|
fill="#000000"
|
||||||
sodipodi:docname="avatar.svg"
|
|
||||||
width="120"
|
|
||||||
height="120"
|
|
||||||
viewBox="0 0 31.75 31.750001"
|
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg8"
|
x="0px"
|
||||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
y="0px"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
viewBox="0 0 95 95"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
enable-background="new 0 0 95 95"
|
||||||
|
xml:space="preserve"
|
||||||
|
id="svg4"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
|
||||||
<defs
|
id="metadata10"><rdf:RDF><cc:Work
|
||||||
id="defs2" />
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
<sodipodi:namedview
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
inkscape:window-maximized="1"
|
id="defs8" /><rect
|
||||||
inkscape:window-y="30"
|
style="opacity:1;vector-effect:none;fill:#f2f2f2;fill-opacity:1;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
inkscape:window-x="0"
|
id="rect819"
|
||||||
inkscape:window-height="1019"
|
width="95"
|
||||||
inkscape:window-width="1920"
|
height="95"
|
||||||
id="base"
|
x="0"
|
||||||
pagecolor="#ffffff"
|
y="0" /><path
|
||||||
bordercolor="#666666"
|
d="m 74.797528,31.305083 c 0,-6.160943 -4.994325,-11.155269 -11.155268,-11.155269 -6.130227,0 -11.101359,4.946683 -11.150255,11.064999 l -9.000067,1.203603 c -1.129004,-3.458478 -4.374972,-5.95909 -8.209576,-5.95909 -4.769905,0 -8.637734,3.867202 -8.637734,8.637734 0,3.824574 2.488074,7.063018 5.932134,8.198919 l -1.269425,9.24455 c -6.137749,0.02821 -11.103865,5.009371 -11.103865,11.152762 0,6.160942 4.994325,11.155895 11.155268,11.155895 6.147779,0 11.130822,-4.973638 11.152762,-11.115149 l 10.417436,-1.439935 c 1.139662,3.438419 4.374972,5.922103 8.195786,5.922103 4.769903,0 8.637732,-3.867202 8.637732,-8.637733 0,-3.967502 -2.678644,-7.301859 -6.323932,-8.314891 l 0.786104,-8.832065 c 5.889506,-0.305288 10.5729,-5.16233 10.5729,-11.126433 z M 52.506424,59.187928 42.075823,60.630371 c -1.05566,-3.697944 -3.965621,-6.6054 -7.66482,-7.657925 l 1.269425,-9.257087 c 4.440795,-0.203734 7.998945,-3.751856 8.216472,-8.18889 l 9.013859,-1.205483 c 1.090765,3.890396 4.23267,6.91445 8.19077,7.837838 l -0.786104,8.822035 c -4.26088,0.396186 -7.614044,3.888516 -7.809001,8.207069 z"
|
||||||
borderopacity="1.0"
|
id="path2"
|
||||||
inkscape:pageopacity="0.0"
|
style="fill:#0482d8;fill-opacity:1;stroke-width:0.62687665;opacity:0.3" /></svg>
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="4.3194033"
|
|
||||||
inkscape:cx="79.987899"
|
|
||||||
inkscape:cy="64.129228"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
inkscape:document-rotation="0"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:snap-midpoints="true"
|
|
||||||
inkscape:snap-object-midpoints="true"
|
|
||||||
inkscape:snap-center="true"
|
|
||||||
inkscape:snap-global="false"
|
|
||||||
inkscape:pagecheckerboard="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata5">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0.80272198,1.2346106)">
|
|
||||||
<rect
|
|
||||||
style="fill:#10b3d1;fill-opacity:1;stroke:none;stroke-width:1.53052;stroke-miterlimit:4;stroke-dasharray:none"
|
|
||||||
id="rect853"
|
|
||||||
width="31.75"
|
|
||||||
height="31.75"
|
|
||||||
x="-0.80272198"
|
|
||||||
y="-1.2346106" />
|
|
||||||
<path
|
|
||||||
id="path857"
|
|
||||||
style="fill:#f4962a;fill-opacity:1;stroke:#000000;stroke-width:1.48265;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="M 15.051525,3.9344041 A 10.434797,10.434797 0 0 0 4.6372555,14.368944 a 10.434797,10.434797 0 0 0 0,0.02075 v 0.03137 a 1.7839264,2.3625556 0 0 0 -0.9503056,-0.363423 1.7839264,2.3625556 0 0 0 -1.7838141,2.362493 1.7839264,2.3625556 0 0 0 1.7838141,2.362491 1.7839264,2.3625556 0 0 0 0.9503056,-0.363423 v 23.74268 H 25.507302 v -23.74268 a 1.7839264,2.3625556 0 0 0 0.950305,0.363423 1.7839264,2.3625556 0 0 0 1.783814,-2.362491 1.7839264,2.3625556 0 0 0 -1.783814,-2.362493 1.7839264,2.3625556 0 0 0 -0.950305,0.362941 v -0.05164 A 10.434797,10.434797 0 0 0 15.072278,3.9344041 a 10.434797,10.434797 0 0 0 -0.02075,0 z" />
|
|
||||||
<circle
|
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.900495;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path881-6"
|
|
||||||
cx="11.218504"
|
|
||||||
cy="13.292331"
|
|
||||||
r="1.3086123" />
|
|
||||||
<circle
|
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.900495;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path881-7"
|
|
||||||
cx="18.926052"
|
|
||||||
cy="13.292331"
|
|
||||||
r="1.3086123" />
|
|
||||||
<ellipse
|
|
||||||
style="fill:#f2f2f2;fill-opacity:1;stroke:#000000;stroke-width:0.88959;stroke-miterlimit:4;stroke-dasharray:none"
|
|
||||||
id="path917"
|
|
||||||
cx="15.072279"
|
|
||||||
cy="18.343904"
|
|
||||||
rx="7.1666903"
|
|
||||||
ry="4.0659413" />
|
|
||||||
<path
|
|
||||||
id="path957"
|
|
||||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.88959;stroke-miterlimit:4;stroke-dasharray:none"
|
|
||||||
d="m 21.900069,17.108362 a 7.1666903,4.0659412 0 0 1 -6.82779,2.8304 7.1666903,4.0659412 0 0 1 -6.8277959,-2.830413" />
|
|
||||||
<path
|
|
||||||
id="path1003"
|
|
||||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.88959;stroke-miterlimit:4;stroke-dasharray:none"
|
|
||||||
inkscape:transform-center-y="-0.79831289"
|
|
||||||
d="m 13.062455,16.997512 c 0.457808,-1.227486 1.336486,-2.475611 2.009822,-2.475611 0.673338,0 1.552013,1.248125 2.009824,2.475611" />
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="m 24.842957,6.3249745 c -1.070225,-0.4344716 -2.309802,0.1182843 -2.464817,1.0590207 0,0 -1.627232,-1.9230616 1.219705,-3.5847621"
|
|
||||||
id="path1030"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
|
Przed Szerokość: | Wysokość: | Rozmiar: 4.8 KiB Po Szerokość: | Wysokość: | Rozmiar: 2.2 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 81 B |
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"id": "106801667066418367",
|
||||||
|
"username": "benis911",
|
||||||
|
"acct": "benis911",
|
||||||
|
"display_name": "",
|
||||||
|
"locked": false,
|
||||||
|
"bot": false,
|
||||||
|
"discoverable": null,
|
||||||
|
"group": false,
|
||||||
|
"created_at": "2021-08-22T00:00:00.000Z",
|
||||||
|
"note": "",
|
||||||
|
"url": "https://mastodon.social/@benis911",
|
||||||
|
"avatar": "https://mastodon.social/avatars/original/missing.png",
|
||||||
|
"avatar_static": "https://mastodon.social/avatars/original/missing.png",
|
||||||
|
"header": "https://mastodon.social/headers/original/missing.png",
|
||||||
|
"header_static": "https://mastodon.social/headers/original/missing.png",
|
||||||
|
"followers_count": 1,
|
||||||
|
"following_count": 0,
|
||||||
|
"statuses_count": 5,
|
||||||
|
"last_status_at": "2022-02-23",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": []
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
{
|
||||||
|
"uri": "mastodon.social",
|
||||||
|
"title": "Mastodon",
|
||||||
|
"short_description": "Server run by the main developers of the project <img draggable=\"false\" alt=\"🐘\" class=\"emojione\" src=\"https://mastodon.social/emoji/1f418.svg\" /> It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!",
|
||||||
|
"description": "Server run by the main developers of the project <img draggable=\"false\" alt=\"🐘\" class=\"emojione\" src=\"https://mastodon.social/emoji/1f418.svg\" /> It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!",
|
||||||
|
"email": "staff@mastodon.social",
|
||||||
|
"version": "3.5.0rc1",
|
||||||
|
"urls": {
|
||||||
|
"streaming_api": "wss://mastodon.social"
|
||||||
|
},
|
||||||
|
"stats": {
|
||||||
|
"user_count": 635078,
|
||||||
|
"status_count": 34700866,
|
||||||
|
"domain_count": 21989
|
||||||
|
},
|
||||||
|
"thumbnail": "https://files.mastodon.social/site_uploads/files/000/000/001/original/vlcsnap-2018-08-27-16h43m11s127.png",
|
||||||
|
"languages": [
|
||||||
|
"en"
|
||||||
|
],
|
||||||
|
"registrations": true,
|
||||||
|
"approval_required": false,
|
||||||
|
"invites_enabled": true,
|
||||||
|
"configuration": {
|
||||||
|
"statuses": {
|
||||||
|
"max_characters": 500,
|
||||||
|
"max_media_attachments": 4,
|
||||||
|
"characters_reserved_per_url": 23
|
||||||
|
},
|
||||||
|
"media_attachments": {
|
||||||
|
"supported_mime_types": [
|
||||||
|
"image/jpeg",
|
||||||
|
"image/png",
|
||||||
|
"image/gif",
|
||||||
|
"video/webm",
|
||||||
|
"video/mp4",
|
||||||
|
"video/quicktime",
|
||||||
|
"video/ogg",
|
||||||
|
"audio/wave",
|
||||||
|
"audio/wav",
|
||||||
|
"audio/x-wav",
|
||||||
|
"audio/x-pn-wave",
|
||||||
|
"audio/ogg",
|
||||||
|
"audio/vorbis",
|
||||||
|
"audio/mpeg",
|
||||||
|
"audio/mp3",
|
||||||
|
"audio/webm",
|
||||||
|
"audio/flac",
|
||||||
|
"audio/aac",
|
||||||
|
"audio/m4a",
|
||||||
|
"audio/x-m4a",
|
||||||
|
"audio/mp4",
|
||||||
|
"audio/3gpp",
|
||||||
|
"video/x-ms-asf"
|
||||||
|
],
|
||||||
|
"image_size_limit": 10485760,
|
||||||
|
"image_matrix_limit": 16777216,
|
||||||
|
"video_size_limit": 41943040,
|
||||||
|
"video_frame_rate_limit": 60,
|
||||||
|
"video_matrix_limit": 2304000
|
||||||
|
},
|
||||||
|
"polls": {
|
||||||
|
"max_options": 4,
|
||||||
|
"max_characters_per_option": 50,
|
||||||
|
"min_expiration": 300,
|
||||||
|
"max_expiration": 2629746
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact_account": {
|
||||||
|
"id": "1",
|
||||||
|
"username": "Gargron",
|
||||||
|
"acct": "Gargron",
|
||||||
|
"display_name": "Eugen",
|
||||||
|
"locked": false,
|
||||||
|
"bot": false,
|
||||||
|
"discoverable": true,
|
||||||
|
"group": false,
|
||||||
|
"created_at": "2016-03-16T00:00:00.000Z",
|
||||||
|
"note": "<p>Founder, CEO and lead developer <span class=\"h-card\"><a href=\"https://mastodon.social/@Mastodon\" class=\"u-url mention\">@<span>Mastodon</span></a></span>, Germany.</p>",
|
||||||
|
"url": "https://mastodon.social/@Gargron",
|
||||||
|
"avatar": "https://files.mastodon.social/accounts/avatars/000/000/001/original/ccb05a778962e171.png",
|
||||||
|
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/000/001/original/ccb05a778962e171.png",
|
||||||
|
"header": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg",
|
||||||
|
"header_static": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg",
|
||||||
|
"followers_count": 99760,
|
||||||
|
"following_count": 274,
|
||||||
|
"statuses_count": 71657,
|
||||||
|
"last_status_at": "2022-03-17",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Patreon",
|
||||||
|
"value": "<a href=\"https://www.patreon.com/mastodon\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://www.</span><span class=\"\">patreon.com/mastodon</span><span class=\"invisible\"></span></a>",
|
||||||
|
"verified_at": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"text": "Sexually explicit or violent media must be marked as sensitive when posting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"text": "No racism, sexism, homophobia, transphobia, xenophobia, or casteism"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"text": "No incitement of violence or promotion of violent ideologies"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"text": "No harassment, dogpiling or doxxing of other users"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5",
|
||||||
|
"text": "No content illegal in Germany"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7",
|
||||||
|
"text": "Do not share intentionally false or misleading information"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"acct": "alex@fedibird.com",
|
||||||
|
"avatar": "https://gleasonator.com/images/avi.png",
|
||||||
|
"avatar_static": "https://gleasonator.com/images/avi.png",
|
||||||
|
"bot": false,
|
||||||
|
"created_at": "2022-01-24T21:25:37.000Z",
|
||||||
|
"display_name": "alex@fedibird.com",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": [],
|
||||||
|
"followers_count": 2,
|
||||||
|
"following_count": 1,
|
||||||
|
"fqn": "alex@fedibird.com",
|
||||||
|
"header": "https://gleasonator.com/images/banner.png",
|
||||||
|
"header_static": "https://gleasonator.com/images/banner.png",
|
||||||
|
"id": "AFmHQ18XZ7Lco68MW8",
|
||||||
|
"last_status_at": "2022-03-16T22:07:53",
|
||||||
|
"locked": false,
|
||||||
|
"note": "<p></p>",
|
||||||
|
"pleroma": {
|
||||||
|
"accepts_chat_messages": null,
|
||||||
|
"also_known_as": [],
|
||||||
|
"ap_id": "https://fedibird.com/users/alex",
|
||||||
|
"background_image": null,
|
||||||
|
"birthday": "1993-07-03",
|
||||||
|
"deactivated": false,
|
||||||
|
"favicon": "https://gleasonator.com/proxy/HzfsidHss3CuA7aM2zxXN-tAjF8/aHR0cHM6Ly9mZWRpYmlyZC5jb20vZmF2aWNvbi5pY28/favicon.ico",
|
||||||
|
"hide_favorites": true,
|
||||||
|
"hide_followers": false,
|
||||||
|
"hide_followers_count": false,
|
||||||
|
"hide_follows": false,
|
||||||
|
"hide_follows_count": false,
|
||||||
|
"is_admin": false,
|
||||||
|
"is_confirmed": true,
|
||||||
|
"is_moderator": false,
|
||||||
|
"is_suggested": false,
|
||||||
|
"location": "Texas, USA",
|
||||||
|
"relationship": {},
|
||||||
|
"skip_thread_containment": false,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"fields": [],
|
||||||
|
"note": "",
|
||||||
|
"pleroma": {
|
||||||
|
"actor_type": "Person",
|
||||||
|
"discoverable": false
|
||||||
|
},
|
||||||
|
"sensitive": false
|
||||||
|
},
|
||||||
|
"statuses_count": 5,
|
||||||
|
"url": "https://fedibird.com/@alex",
|
||||||
|
"username": "alex"
|
||||||
|
},
|
||||||
|
"created_at": "2022-03-17T00:08:48.000Z",
|
||||||
|
"id": "406814",
|
||||||
|
"pleroma": {
|
||||||
|
"is_muted": false,
|
||||||
|
"is_seen": true
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"acct": "benis911",
|
||||||
|
"avatar": "https://gleasonator.com/images/avi.png",
|
||||||
|
"avatar_static": "https://gleasonator.com/images/avi.png",
|
||||||
|
"bot": false,
|
||||||
|
"created_at": "2021-03-26T20:42:11.000Z",
|
||||||
|
"display_name": "benis911",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": [],
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"fqn": "benis911@gleasonator.com",
|
||||||
|
"header": "https://media.gleasonator.com/fc595bbbcf5aabefecd1c2adfe5b7f5457db59847992881668653a0338ba25bd.jpg",
|
||||||
|
"header_static": "https://media.gleasonator.com/fc595bbbcf5aabefecd1c2adfe5b7f5457db59847992881668653a0338ba25bd.jpg",
|
||||||
|
"id": "A5c5LK7EJTFR0u26Pg",
|
||||||
|
"last_status_at": "2022-03-16T22:01:57",
|
||||||
|
"locked": false,
|
||||||
|
"note": "hello world 2",
|
||||||
|
"pleroma": {
|
||||||
|
"accepts_chat_messages": true,
|
||||||
|
"also_known_as": [
|
||||||
|
"https://gleasonator.com/users/alex",
|
||||||
|
"https://poa.st/users/alex",
|
||||||
|
"https://fedibird.com/users/alex"
|
||||||
|
],
|
||||||
|
"ap_id": "https://gleasonator.com/users/benis911",
|
||||||
|
"background_image": null,
|
||||||
|
"birthday": "2000-01-25",
|
||||||
|
"deactivated": false,
|
||||||
|
"favicon": "https://gleasonator.com/favicon.png",
|
||||||
|
"hide_favorites": true,
|
||||||
|
"hide_followers": true,
|
||||||
|
"hide_followers_count": true,
|
||||||
|
"hide_follows": true,
|
||||||
|
"hide_follows_count": true,
|
||||||
|
"is_admin": false,
|
||||||
|
"is_confirmed": true,
|
||||||
|
"is_moderator": false,
|
||||||
|
"is_suggested": false,
|
||||||
|
"location": null,
|
||||||
|
"relationship": {},
|
||||||
|
"skip_thread_containment": false,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"fields": [],
|
||||||
|
"note": "hello world 2",
|
||||||
|
"pleroma": {
|
||||||
|
"actor_type": "Person",
|
||||||
|
"discoverable": false
|
||||||
|
},
|
||||||
|
"sensitive": false
|
||||||
|
},
|
||||||
|
"statuses_count": 172,
|
||||||
|
"url": "https://gleasonator.com/users/benis911",
|
||||||
|
"username": "benis911"
|
||||||
|
},
|
||||||
|
"type": "move"
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"acct": "alex",
|
||||||
|
"avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png",
|
||||||
|
"avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png",
|
||||||
|
"bot": false,
|
||||||
|
"created_at": "2020-01-08T01:25:43.000Z",
|
||||||
|
"display_name": "Alex Gleason",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Website",
|
||||||
|
"value": "<a href=\"https://alexgleason.me\" rel=\"ugc\">https://alexgleason.me</a>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Soapbox",
|
||||||
|
"value": "<a href=\"https://soapbox.pub\" rel=\"ugc\">https://soapbox.pub</a>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Email",
|
||||||
|
"value": "alex@alexgleason.me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gender identity",
|
||||||
|
"value": "Soyboy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Donate (PayPal)",
|
||||||
|
"value": "<a href=\"https://paypal.me/gleasonator\" rel=\"ugc\">https://paypal.me/gleasonator</a>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$BTC",
|
||||||
|
"value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$ETH",
|
||||||
|
"value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$DOGE",
|
||||||
|
"value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$XMR",
|
||||||
|
"value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"follow_requests_count": 0,
|
||||||
|
"followers_count": 2489,
|
||||||
|
"following_count": 1586,
|
||||||
|
"fqn": "alex@gleasonator.com",
|
||||||
|
"header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png",
|
||||||
|
"header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png",
|
||||||
|
"id": "9v5bmRalQvjOy0ECcC",
|
||||||
|
"last_status_at": "2022-03-16T21:57:17",
|
||||||
|
"locked": false,
|
||||||
|
"note": "I create Fediverse software that empowers people online.<br/><br/>I'm vegan btw<br/><br/>Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.",
|
||||||
|
"pleroma": {
|
||||||
|
"accepts_chat_messages": true,
|
||||||
|
"accepts_email_list": true,
|
||||||
|
"allow_following_move": true,
|
||||||
|
"also_known_as": [
|
||||||
|
"https://mitra.social/users/alex"
|
||||||
|
],
|
||||||
|
"ap_id": "https://gleasonator.com/users/alex",
|
||||||
|
"background_image": null,
|
||||||
|
"birthday": "1993-07-03",
|
||||||
|
"deactivated": false,
|
||||||
|
"email": "alex@alexgleason.me",
|
||||||
|
"favicon": "https://gleasonator.com/favicon.png",
|
||||||
|
"hide_favorites": true,
|
||||||
|
"hide_followers": false,
|
||||||
|
"hide_followers_count": false,
|
||||||
|
"hide_follows": false,
|
||||||
|
"hide_follows_count": false,
|
||||||
|
"is_admin": true,
|
||||||
|
"is_confirmed": true,
|
||||||
|
"is_moderator": false,
|
||||||
|
"is_suggested": true,
|
||||||
|
"location": null,
|
||||||
|
"notification_settings": {
|
||||||
|
"block_from_strangers": false,
|
||||||
|
"hide_notification_contents": false
|
||||||
|
},
|
||||||
|
"relationship": {},
|
||||||
|
"skip_thread_containment": false,
|
||||||
|
"tags": [],
|
||||||
|
"unread_conversation_count": 392,
|
||||||
|
"unread_notifications_count": 2
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Website",
|
||||||
|
"value": "https://alexgleason.me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Soapbox",
|
||||||
|
"value": "https://soapbox.pub"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Email",
|
||||||
|
"value": "alex@alexgleason.me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gender identity",
|
||||||
|
"value": "Soyboy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Donate (PayPal)",
|
||||||
|
"value": "https://paypal.me/gleasonator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$BTC",
|
||||||
|
"value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$ETH",
|
||||||
|
"value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$DOGE",
|
||||||
|
"value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$XMR",
|
||||||
|
"value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"note": "I create Fediverse software that empowers people online.\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.",
|
||||||
|
"pleroma": {
|
||||||
|
"actor_type": "Person",
|
||||||
|
"discoverable": false,
|
||||||
|
"no_rich_text": false,
|
||||||
|
"show_birthday": true,
|
||||||
|
"show_role": true
|
||||||
|
},
|
||||||
|
"privacy": "public",
|
||||||
|
"sensitive": false
|
||||||
|
},
|
||||||
|
"statuses_count": 23695,
|
||||||
|
"url": "https://gleasonator.com/users/alex",
|
||||||
|
"username": "alex"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"name": "Soapbox FE",
|
||||||
|
"website": "https://soapbox.pub/"
|
||||||
|
},
|
||||||
|
"bookmarked": false,
|
||||||
|
"card": null,
|
||||||
|
"content": "<p>I am going to delete this post for testing purposes</p>",
|
||||||
|
"created_at": "2022-03-16T21:57:16.000Z",
|
||||||
|
"emojis": [],
|
||||||
|
"favourited": false,
|
||||||
|
"favourites_count": 3,
|
||||||
|
"id": "AHU2RrX0wdcwzCYjFQ",
|
||||||
|
"in_reply_to_account_id": null,
|
||||||
|
"in_reply_to_id": null,
|
||||||
|
"language": null,
|
||||||
|
"media_attachments": [
|
||||||
|
{
|
||||||
|
"blurhash": "eWGlL@?b~q%MRj4nt7IUof%M%MIURjRjIUM{IUM{Rjayxut7j[j[xu",
|
||||||
|
"description": "",
|
||||||
|
"id": "508107650",
|
||||||
|
"meta": {
|
||||||
|
"original": {
|
||||||
|
"aspect": 1,
|
||||||
|
"height": 1024,
|
||||||
|
"width": 1024
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pleroma": {
|
||||||
|
"mime_type": "image/png"
|
||||||
|
},
|
||||||
|
"preview_url": "https://media.gleasonator.com/2b9ddcd8b27cad786fd34bc2cfe02c1b63aa1b8e7b8d72379b5c9375fb61f199.png",
|
||||||
|
"remote_url": "https://media.gleasonator.com/2b9ddcd8b27cad786fd34bc2cfe02c1b63aa1b8e7b8d72379b5c9375fb61f199.png",
|
||||||
|
"text_url": "https://media.gleasonator.com/2b9ddcd8b27cad786fd34bc2cfe02c1b63aa1b8e7b8d72379b5c9375fb61f199.png",
|
||||||
|
"type": "image",
|
||||||
|
"url": "https://media.gleasonator.com/2b9ddcd8b27cad786fd34bc2cfe02c1b63aa1b8e7b8d72379b5c9375fb61f199.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mentions": [],
|
||||||
|
"muted": false,
|
||||||
|
"pinned": false,
|
||||||
|
"pleroma": {
|
||||||
|
"content": {
|
||||||
|
"text/plain": "I am going to delete this post for testing purposes"
|
||||||
|
},
|
||||||
|
"content_type": "text/markdown",
|
||||||
|
"conversation_id": "AHU2RrUB7BMIqPESpM",
|
||||||
|
"direct_conversation_id": null,
|
||||||
|
"emoji_reactions": [
|
||||||
|
{
|
||||||
|
"count": 1,
|
||||||
|
"me": false,
|
||||||
|
"name": "😭"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"count": 1,
|
||||||
|
"me": false,
|
||||||
|
"name": "❔"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expires_at": null,
|
||||||
|
"in_reply_to_account_acct": null,
|
||||||
|
"local": true,
|
||||||
|
"parent_visible": false,
|
||||||
|
"pinned_at": null,
|
||||||
|
"quote": null,
|
||||||
|
"quote_url": null,
|
||||||
|
"quote_visible": false,
|
||||||
|
"spoiler_text": {
|
||||||
|
"text/plain": ""
|
||||||
|
},
|
||||||
|
"thread_muted": false
|
||||||
|
},
|
||||||
|
"poll": null,
|
||||||
|
"reblog": null,
|
||||||
|
"reblogged": false,
|
||||||
|
"reblogs_count": 1,
|
||||||
|
"replies_count": 2,
|
||||||
|
"sensitive": false,
|
||||||
|
"spoiler_text": "",
|
||||||
|
"tags": [],
|
||||||
|
"text": "I am going to delete this post for testing purposes",
|
||||||
|
"uri": "https://gleasonator.com/objects/205ec868-d28d-4668-a56a-33321f7e285e",
|
||||||
|
"url": "https://gleasonator.com/notice/AHU2RrX0wdcwzCYjFQ",
|
||||||
|
"visibility": "public"
|
||||||
|
}
|
|
@ -6,11 +6,10 @@
|
||||||
* @see module:soapbox/actions/oauth
|
* @see module:soapbox/actions/oauth
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
|
||||||
|
|
||||||
import { createApp } from 'soapbox/actions/apps';
|
import { createApp } from 'soapbox/actions/apps';
|
||||||
import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
|
import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
|
||||||
import { obtainOAuthToken } from 'soapbox/actions/oauth';
|
import { obtainOAuthToken } from 'soapbox/actions/oauth';
|
||||||
|
import { normalizeInstance } from 'soapbox/normalizers';
|
||||||
import { parseBaseURL } from 'soapbox/utils/auth';
|
import { parseBaseURL } from 'soapbox/utils/auth';
|
||||||
import sourceCode from 'soapbox/utils/code';
|
import sourceCode from 'soapbox/utils/code';
|
||||||
import { getWalletAndSign } from 'soapbox/utils/ethereum';
|
import { getWalletAndSign } from 'soapbox/utils/ethereum';
|
||||||
|
@ -22,12 +21,12 @@ import { baseClient } from '../api';
|
||||||
const fetchExternalInstance = baseURL => {
|
const fetchExternalInstance = baseURL => {
|
||||||
return baseClient(null, baseURL)
|
return baseClient(null, baseURL)
|
||||||
.get('/api/v1/instance')
|
.get('/api/v1/instance')
|
||||||
.then(({ data: instance }) => fromJS(instance))
|
.then(({ data: instance }) => normalizeInstance(instance))
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
// Authenticated fetch is enabled.
|
// Authenticated fetch is enabled.
|
||||||
// Continue with a limited featureset.
|
// Continue with a limited featureset.
|
||||||
return ImmutableMap({ version: '0.0.0' });
|
return normalizeInstance({});
|
||||||
} else {
|
} else {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
import { getFeatures, parseVersion } from 'soapbox/utils/features';
|
||||||
import { shouldHaveCard } from 'soapbox/utils/status';
|
import { shouldHaveCard } from 'soapbox/utils/status';
|
||||||
|
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
|
@ -99,8 +99,7 @@ export function fetchStatus(id) {
|
||||||
|
|
||||||
export function redraft(status, raw_text, content_type) {
|
export function redraft(status, raw_text, content_type) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const { instance } = getState();
|
||||||
const instance = state.get('instance');
|
|
||||||
const { explicitAddressing } = getFeatures(instance);
|
const { explicitAddressing } = getFeatures(instance);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -109,6 +108,7 @@ export function redraft(status, raw_text, content_type) {
|
||||||
raw_text,
|
raw_text,
|
||||||
explicitAddressing,
|
explicitAddressing,
|
||||||
content_type,
|
content_type,
|
||||||
|
v: parseVersion(instance.version),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ export const SUGGESTIONS_V2_FETCH_REQUEST = 'SUGGESTIONS_V2_FETCH_REQUEST';
|
||||||
export const SUGGESTIONS_V2_FETCH_SUCCESS = 'SUGGESTIONS_V2_FETCH_SUCCESS';
|
export const SUGGESTIONS_V2_FETCH_SUCCESS = 'SUGGESTIONS_V2_FETCH_SUCCESS';
|
||||||
export const SUGGESTIONS_V2_FETCH_FAIL = 'SUGGESTIONS_V2_FETCH_FAIL';
|
export const SUGGESTIONS_V2_FETCH_FAIL = 'SUGGESTIONS_V2_FETCH_FAIL';
|
||||||
|
|
||||||
export function fetchSuggestionsV1() {
|
export function fetchSuggestionsV1(params = {}) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch({ type: SUGGESTIONS_FETCH_REQUEST, skipLoading: true });
|
dispatch({ type: SUGGESTIONS_FETCH_REQUEST, skipLoading: true });
|
||||||
return api(getState).get('/api/v1/suggestions').then(({ data: accounts }) => {
|
return api(getState).get('/api/v1/suggestions', { params }).then(({ data: accounts }) => {
|
||||||
dispatch(importFetchedAccounts(accounts));
|
dispatch(importFetchedAccounts(accounts));
|
||||||
dispatch({ type: SUGGESTIONS_FETCH_SUCCESS, accounts, skipLoading: true });
|
dispatch({ type: SUGGESTIONS_FETCH_SUCCESS, accounts, skipLoading: true });
|
||||||
return accounts;
|
return accounts;
|
||||||
|
@ -30,10 +30,10 @@ export function fetchSuggestionsV1() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchSuggestionsV2() {
|
export function fetchSuggestionsV2(params = {}) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch({ type: SUGGESTIONS_V2_FETCH_REQUEST, skipLoading: true });
|
dispatch({ type: SUGGESTIONS_V2_FETCH_REQUEST, skipLoading: true });
|
||||||
return api(getState).get('/api/v2/suggestions').then(({ data: suggestions }) => {
|
return api(getState).get('/api/v2/suggestions', { params }).then(({ data: suggestions }) => {
|
||||||
const accounts = suggestions.map(({ account }) => account);
|
const accounts = suggestions.map(({ account }) => account);
|
||||||
dispatch(importFetchedAccounts(accounts));
|
dispatch(importFetchedAccounts(accounts));
|
||||||
dispatch({ type: SUGGESTIONS_V2_FETCH_SUCCESS, suggestions, skipLoading: true });
|
dispatch({ type: SUGGESTIONS_V2_FETCH_SUCCESS, suggestions, skipLoading: true });
|
||||||
|
@ -45,21 +45,21 @@ export function fetchSuggestionsV2() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchSuggestions() {
|
export function fetchSuggestions(params = { limit: 50 }) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const instance = state.get('instance');
|
const instance = state.get('instance');
|
||||||
const features = getFeatures(instance);
|
const features = getFeatures(instance);
|
||||||
|
|
||||||
if (features.suggestionsV2) {
|
if (features.suggestionsV2) {
|
||||||
dispatch(fetchSuggestionsV2())
|
dispatch(fetchSuggestionsV2(params))
|
||||||
.then(suggestions => {
|
.then(suggestions => {
|
||||||
const accountIds = suggestions.map(({ account }) => account.id);
|
const accountIds = suggestions.map(({ account }) => account.id);
|
||||||
dispatch(fetchRelationships(accountIds));
|
dispatch(fetchRelationships(accountIds));
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
} else if (features.suggestions) {
|
} else if (features.suggestions) {
|
||||||
dispatch(fetchSuggestionsV1())
|
dispatch(fetchSuggestionsV1(params))
|
||||||
.then(accounts => {
|
.then(accounts => {
|
||||||
const accountIds = accounts.map(({ id }) => id);
|
const accountIds = accounts.map(({ id }) => id);
|
||||||
dispatch(fetchRelationships(accountIds));
|
dispatch(fetchRelationships(accountIds));
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import DatePicker from 'react-datepicker';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
|
||||||
|
|
||||||
import IconButton from 'soapbox/components/icon_button';
|
import IconButton from 'soapbox/components/icon_button';
|
||||||
|
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||||
|
import { DatePicker } from 'soapbox/features/ui/util/async-components';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
import { getFeatures } from 'soapbox/utils/features';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -112,16 +112,18 @@ class BirthdayInput extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className='datepicker__input'>
|
<div className='datepicker__input'>
|
||||||
<DatePicker
|
<BundleContainer fetchComponent={DatePicker}>
|
||||||
selected={value}
|
{Component => (<Component
|
||||||
wrapperClassName='react-datepicker-wrapper'
|
selected={value}
|
||||||
onChange={onChange}
|
wrapperClassName='react-datepicker-wrapper'
|
||||||
placeholderText={intl.formatMessage(messages.birthdayPlaceholder)}
|
onChange={onChange}
|
||||||
minDate={new Date('1900-01-01')}
|
placeholderText={intl.formatMessage(messages.birthdayPlaceholder)}
|
||||||
maxDate={maxDate}
|
minDate={new Date('1900-01-01')}
|
||||||
required={required}
|
maxDate={maxDate}
|
||||||
renderCustomHeader={this.renderHeader}
|
required={required}
|
||||||
/>
|
renderCustomHeader={this.renderHeader}
|
||||||
|
/>)}
|
||||||
|
</BundleContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
import DatePicker from 'react-datepicker';
|
||||||
|
import 'react-datepicker/dist/react-datepicker.css';
|
||||||
|
|
||||||
|
export default DatePicker;
|
|
@ -3,12 +3,12 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import DatePicker from 'react-datepicker';
|
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
|
||||||
import IconButton from 'soapbox/components/icon_button';
|
import IconButton from 'soapbox/components/icon_button';
|
||||||
|
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||||
|
import { DatePicker } from 'soapbox/features/ui/util/async-components';
|
||||||
|
|
||||||
import { setSchedule, removeSchedule } from '../../../actions/compose';
|
import { setSchedule, removeSchedule } from '../../../actions/compose';
|
||||||
|
|
||||||
|
@ -104,18 +104,20 @@ class ScheduleForm extends React.Component {
|
||||||
<FormattedMessage id='datepicker.hint' defaultMessage='Scheduled to post at…' />
|
<FormattedMessage id='datepicker.hint' defaultMessage='Scheduled to post at…' />
|
||||||
</div>
|
</div>
|
||||||
<div className='datepicker__input'>
|
<div className='datepicker__input'>
|
||||||
<DatePicker
|
<BundleContainer fetchComponent={DatePicker}>
|
||||||
selected={scheduledAt}
|
{Component => (<Component
|
||||||
showTimeSelect
|
selected={scheduledAt}
|
||||||
dateFormat='MMMM d, yyyy h:mm aa'
|
showTimeSelect
|
||||||
timeIntervals={15}
|
dateFormat='MMMM d, yyyy h:mm aa'
|
||||||
wrapperClassName='react-datepicker-wrapper'
|
timeIntervals={15}
|
||||||
onChange={this.setSchedule}
|
wrapperClassName='react-datepicker-wrapper'
|
||||||
placeholderText={this.props.intl.formatMessage(messages.schedule)}
|
onChange={this.setSchedule}
|
||||||
filterDate={this.isCurrentOrFutureDate}
|
placeholderText={this.props.intl.formatMessage(messages.schedule)}
|
||||||
filterTime={this.isFiveMinutesFromNow}
|
filterDate={this.isCurrentOrFutureDate}
|
||||||
ref={this.setRef}
|
filterTime={this.isFiveMinutesFromNow}
|
||||||
/>
|
ref={this.setRef}
|
||||||
|
/>)}
|
||||||
|
</BundleContainer>
|
||||||
<div className='datepicker__cancel'>
|
<div className='datepicker__cancel'>
|
||||||
<IconButton title={intl.formatMessage(messages.remove)} src={require('@tabler/icons/icons/x.svg')} onClick={this.handleRemove} />
|
<IconButton title={intl.formatMessage(messages.remove)} src={require('@tabler/icons/icons/x.svg')} onClick={this.handleRemove} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -465,3 +465,7 @@ export function CreateApp() {
|
||||||
export function SettingsStore() {
|
export function SettingsStore() {
|
||||||
return import(/* webpackChunkName: "features/developers" */'../../developers/settings_store');
|
return import(/* webpackChunkName: "features/developers" */'../../developers/settings_store');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function DatePicker() {
|
||||||
|
return import(/* webpackChunkName: "date_picker" */'../../birthdays/date_picker');
|
||||||
|
}
|
||||||
|
|
|
@ -3,25 +3,27 @@ import { Record as ImmutableRecord, fromJS } from 'immutable';
|
||||||
import { normalizeAccount } from '../account';
|
import { normalizeAccount } from '../account';
|
||||||
|
|
||||||
const AVATAR_MISSING = require('images/avatar-missing.png');
|
const AVATAR_MISSING = require('images/avatar-missing.png');
|
||||||
|
const HEADER_MISSING = require('images/header-missing.png');
|
||||||
|
|
||||||
describe('normalizeAccount()', () => {
|
describe('normalizeAccount()', () => {
|
||||||
it('adds base fields', () => {
|
it('adds base fields', () => {
|
||||||
const account = fromJS({});
|
const account = {};
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||||
expect(result.acct).toEqual('');
|
expect(result.acct).toEqual('');
|
||||||
expect(result.note).toEqual('');
|
expect(result.note).toEqual('');
|
||||||
expect(result.avatar).toEqual(AVATAR_MISSING);
|
expect(result.avatar).toEqual(AVATAR_MISSING);
|
||||||
|
expect(result.header_static).toEqual(HEADER_MISSING);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes a mention', () => {
|
it('normalizes a mention', () => {
|
||||||
const mention = fromJS({
|
const mention = {
|
||||||
acct: 'NEETzsche@iddqd.social',
|
acct: 'NEETzsche@iddqd.social',
|
||||||
id: '9v5bw7hEGBPc9nrpzc',
|
id: '9v5bw7hEGBPc9nrpzc',
|
||||||
url: 'https://iddqd.social/users/NEETzsche',
|
url: 'https://iddqd.social/users/NEETzsche',
|
||||||
username: 'NEETzsche',
|
username: 'NEETzsche',
|
||||||
});
|
};
|
||||||
|
|
||||||
const result = normalizeAccount(mention);
|
const result = normalizeAccount(mention);
|
||||||
expect(result.emojis).toEqual(fromJS([]));
|
expect(result.emojis).toEqual(fromJS([]));
|
||||||
|
@ -32,21 +34,21 @@ describe('normalizeAccount()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Fedibird birthday', () => {
|
it('normalizes Fedibird birthday', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/fedibird-account.json'));
|
const account = require('soapbox/__fixtures__/fedibird-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
expect(result.birthday).toEqual('1993-07-03');
|
expect(result.birthday).toEqual('1993-07-03');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Pleroma birthday', () => {
|
it('normalizes Pleroma birthday', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/pleroma-account.json'));
|
const account = require('soapbox/__fixtures__/pleroma-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
expect(result.birthday).toEqual('1993-07-03');
|
expect(result.birthday).toEqual('1993-07-03');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Pleroma legacy fields', () => {
|
it('normalizes Pleroma legacy fields', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/pleroma-2.2.2-account.json'));
|
const account = require('soapbox/__fixtures__/pleroma-2.2.2-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
expect(result.getIn(['pleroma', 'is_active'])).toBe(true);
|
expect(result.getIn(['pleroma', 'is_active'])).toBe(true);
|
||||||
|
@ -57,7 +59,7 @@ describe('normalizeAccount()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prefers new Pleroma fields', () => {
|
it('prefers new Pleroma fields', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/pleroma-account.json'));
|
const account = require('soapbox/__fixtures__/pleroma-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
expect(result.getIn(['pleroma', 'is_active'])).toBe(true);
|
expect(result.getIn(['pleroma', 'is_active'])).toBe(true);
|
||||||
|
@ -66,76 +68,82 @@ describe('normalizeAccount()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes a verified Pleroma user', () => {
|
it('normalizes a verified Pleroma user', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/mk.json'));
|
const account = require('soapbox/__fixtures__/mk.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.verified).toBe(true);
|
expect(result.verified).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes an unverified Pleroma user', () => {
|
it('normalizes an unverified Pleroma user', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/pleroma-account.json'));
|
const account = require('soapbox/__fixtures__/pleroma-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.verified).toBe(false);
|
expect(result.verified).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes a verified Truth Social user', () => {
|
it('normalizes a verified Truth Social user', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/realDonaldTrump.json'));
|
const account = require('soapbox/__fixtures__/realDonaldTrump.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.verified).toBe(true);
|
expect(result.verified).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Fedibird location', () => {
|
it('normalizes Fedibird location', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/fedibird-account.json'));
|
const account = require('soapbox/__fixtures__/fedibird-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.location).toBe('Texas, USA');
|
expect(result.location).toBe('Texas, USA');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Truth Social location', () => {
|
it('normalizes Truth Social location', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/truthsocial-account.json'));
|
const account = require('soapbox/__fixtures__/truthsocial-account.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.location).toBe('Texas');
|
expect(result.location).toBe('Texas');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('normalizes Truth Social website', () => {
|
||||||
|
const account = require('soapbox/__fixtures__/truthsocial-account.json');
|
||||||
|
const result = normalizeAccount(account);
|
||||||
|
expect(result.website).toBe('https://soapbox.pub');
|
||||||
|
});
|
||||||
|
|
||||||
it('sets display_name from username', () => {
|
it('sets display_name from username', () => {
|
||||||
const account = fromJS({ username: 'alex' });
|
const account = { username: 'alex' };
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.display_name).toBe('alex');
|
expect(result.display_name).toBe('alex');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets display_name from acct', () => {
|
it('sets display_name from acct', () => {
|
||||||
const account = fromJS({ acct: 'alex@gleasonator.com' });
|
const account = { acct: 'alex@gleasonator.com' };
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.display_name).toBe('alex');
|
expect(result.display_name).toBe('alex');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('overrides a whitespace display_name', () => {
|
it('overrides a whitespace display_name', () => {
|
||||||
const account = fromJS({ username: 'alex', display_name: ' ' });
|
const account = { username: 'alex', display_name: ' ' };
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
expect(result.display_name).toBe('alex');
|
expect(result.display_name).toBe('alex');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emojifies display name as `display_name_html`', () => {
|
it('emojifies display name as `display_name_html`', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
|
const account = require('soapbox/__fixtures__/account-with-emojis.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
const expected = 'Alex Gleason <img draggable="false" class="emojione" alt="😂" title=":joy:" src="/packs/emoji/1f602.svg" /> <img draggable="false" class="emojione" alt=":soapbox:" title=":soapbox:" src="https://gleasonator.com/emoji/Gleasonator/soapbox.png" /> <img draggable="false" class="emojione" alt=":ablobcatrainbow:" title=":ablobcatrainbow:" src="https://gleasonator.com/emoji/blobcat/ablobcatrainbow.png" />';
|
const expected = 'Alex Gleason <img draggable="false" class="emojione" alt="😂" title=":joy:" src="/packs/emoji/1f602.svg" /> <img draggable="false" class="emojione" alt=":soapbox:" title=":soapbox:" src="https://gleasonator.com/emoji/Gleasonator/soapbox.png" /> <img draggable="false" class="emojione" alt=":ablobcatrainbow:" title=":ablobcatrainbow:" src="https://gleasonator.com/emoji/blobcat/ablobcatrainbow.png" />';
|
||||||
expect(result.display_name_html).toBe(expected);
|
expect(result.display_name_html).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emojifies note as `note_emojified`', () => {
|
it('emojifies note as `note_emojified`', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
|
const account = require('soapbox/__fixtures__/account-with-emojis.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
const expected = 'I create Fediverse software that empowers people online. <img draggable="false" class="emojione" alt=":soapbox:" title=":soapbox:" src="https://gleasonator.com/emoji/Gleasonator/soapbox.png" /><br/><br/>I'm vegan btw<br/><br/>Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.';
|
const expected = 'I create Fediverse software that empowers people online. <img draggable="false" class="emojione" alt=":soapbox:" title=":soapbox:" src="https://gleasonator.com/emoji/Gleasonator/soapbox.png" /><br/><br/>I'm vegan btw<br/><br/>Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.';
|
||||||
expect(result.note_emojified).toBe(expected);
|
expect(result.note_emojified).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('unescapes HTML note as `note_plain`', () => {
|
it('unescapes HTML note as `note_plain`', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
|
const account = require('soapbox/__fixtures__/account-with-emojis.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
const expected = 'I create Fediverse software that empowers people online. :soapbox:\n\nI\'m vegan btw\n\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.';
|
const expected = 'I create Fediverse software that empowers people online. :soapbox:\n\nI\'m vegan btw\n\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.';
|
||||||
expect(result.note_plain).toBe(expected);
|
expect(result.note_plain).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emojifies custom profile field', () => {
|
it('emojifies custom profile field', () => {
|
||||||
const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
|
const account = require('soapbox/__fixtures__/account-with-emojis.json');
|
||||||
const result = normalizeAccount(account);
|
const result = normalizeAccount(account);
|
||||||
const field = result.fields.get(1);
|
const field = result.fields.get(1);
|
||||||
|
|
||||||
|
@ -143,4 +151,21 @@ describe('normalizeAccount()', () => {
|
||||||
expect(field.value_emojified).toBe('<a href="https://soapbox.pub" rel="ugc">https://soapbox.pub</a> <img draggable="false" class="emojione" alt=":soapbox:" title=":soapbox:" src="https://gleasonator.com/emoji/Gleasonator/soapbox.png" />');
|
expect(field.value_emojified).toBe('<a href="https://soapbox.pub" rel="ugc">https://soapbox.pub</a> <img draggable="false" class="emojione" alt=":soapbox:" title=":soapbox:" src="https://gleasonator.com/emoji/Gleasonator/soapbox.png" />');
|
||||||
expect(field.value_plain).toBe('https://soapbox.pub :soapbox:');
|
expect(field.value_plain).toBe('https://soapbox.pub :soapbox:');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('adds default avatar and banner to GoToSocial account', () => {
|
||||||
|
const account = require('soapbox/__fixtures__/gotosocial-account.json');
|
||||||
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
|
expect(result.avatar).toEqual(AVATAR_MISSING);
|
||||||
|
expect(result.avatar_static).toEqual(AVATAR_MISSING);
|
||||||
|
expect(result.header).toEqual(HEADER_MISSING);
|
||||||
|
expect(result.header_static).toEqual(HEADER_MISSING);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds fqn to Mastodon account', () => {
|
||||||
|
const account = require('soapbox/__fixtures__/mastodon-account.json');
|
||||||
|
const result = normalizeAccount(account);
|
||||||
|
|
||||||
|
expect(result.fqn).toEqual('benis911@mastodon.social');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Record as ImmutableRecord, fromJS } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
|
|
||||||
import { normalizeAttachment } from '../attachment';
|
import { normalizeAttachment } from '../attachment';
|
||||||
|
|
||||||
describe('normalizeAttachment()', () => {
|
describe('normalizeAttachment()', () => {
|
||||||
it('adds base fields', () => {
|
it('adds base fields', () => {
|
||||||
const attachment = fromJS({});
|
const attachment = {};
|
||||||
const result = normalizeAttachment(attachment);
|
const result = normalizeAttachment(attachment);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||||
|
@ -13,7 +13,7 @@ describe('normalizeAttachment()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('infers preview_url from url', () => {
|
it('infers preview_url from url', () => {
|
||||||
const attachment = fromJS({ url: 'https://site.fedi/123.png' });
|
const attachment = { url: 'https://site.fedi/123.png' };
|
||||||
const result = normalizeAttachment(attachment);
|
const result = normalizeAttachment(attachment);
|
||||||
|
|
||||||
expect(result.preview_url).toEqual('https://site.fedi/123.png');
|
expect(result.preview_url).toEqual('https://site.fedi/123.png');
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Record as ImmutableRecord, fromJS } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
|
|
||||||
import { normalizeCard } from '../card';
|
import { normalizeCard } from '../card';
|
||||||
|
|
||||||
describe('normalizeCard()', () => {
|
describe('normalizeCard()', () => {
|
||||||
it('adds base fields', () => {
|
it('adds base fields', () => {
|
||||||
const card = fromJS({});
|
const card = {};
|
||||||
const result = normalizeCard(card);
|
const result = normalizeCard(card);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||||
|
|
|
@ -59,7 +59,7 @@ describe('normalizeInstance()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Pleroma instance with Mastodon configuration format', () => {
|
it('normalizes Pleroma instance with Mastodon configuration format', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/pleroma-instance.json'));
|
const instance = require('soapbox/__fixtures__/pleroma-instance.json');
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
configuration: {
|
configuration: {
|
||||||
|
@ -81,7 +81,7 @@ describe('normalizeInstance()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Mastodon instance with retained configuration', () => {
|
it('normalizes Mastodon instance with retained configuration', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/mastodon-instance.json'));
|
const instance = require('soapbox/__fixtures__/mastodon-instance.json');
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
configuration: {
|
configuration: {
|
||||||
|
@ -111,7 +111,7 @@ describe('normalizeInstance()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Mastodon 3.0.0 instance with default configuration', () => {
|
it('normalizes Mastodon 3.0.0 instance with default configuration', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/mastodon-3.0.0-instance.json'));
|
const instance = require('soapbox/__fixtures__/mastodon-3.0.0-instance.json');
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
configuration: {
|
configuration: {
|
||||||
|
@ -133,18 +133,18 @@ describe('normalizeInstance()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Fedibird instance', () => {
|
it('normalizes Fedibird instance', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/fedibird-instance.json'));
|
const instance = require('soapbox/__fixtures__/fedibird-instance.json');
|
||||||
const result = normalizeInstance(instance);
|
const result = normalizeInstance(instance);
|
||||||
|
|
||||||
// Sets description_limit
|
// Sets description_limit
|
||||||
expect(result.description_limit).toEqual(1500);
|
expect(result.description_limit).toEqual(1500);
|
||||||
|
|
||||||
// Preserves fedibird_capabilities
|
// Preserves fedibird_capabilities
|
||||||
expect(result.fedibird_capabilities).toEqual(instance.get('fedibird_capabilities'));
|
expect(result.fedibird_capabilities).toEqual(fromJS(instance.fedibird_capabilities));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Mitra instance', () => {
|
it('normalizes Mitra instance', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/mitra-instance.json'));
|
const instance = require('soapbox/__fixtures__/mitra-instance.json');
|
||||||
const result = normalizeInstance(instance);
|
const result = normalizeInstance(instance);
|
||||||
|
|
||||||
// Adds configuration and description_limit
|
// Adds configuration and description_limit
|
||||||
|
@ -153,7 +153,7 @@ describe('normalizeInstance()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes GoToSocial instance', () => {
|
it('normalizes GoToSocial instance', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/gotosocial-instance.json'));
|
const instance = require('soapbox/__fixtures__/gotosocial-instance.json');
|
||||||
const result = normalizeInstance(instance);
|
const result = normalizeInstance(instance);
|
||||||
|
|
||||||
// Normalizes max_toot_chars
|
// Normalizes max_toot_chars
|
||||||
|
@ -166,7 +166,7 @@ describe('normalizeInstance()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Friendica instance', () => {
|
it('normalizes Friendica instance', () => {
|
||||||
const instance = fromJS(require('soapbox/__fixtures__/friendica-instance.json'));
|
const instance = require('soapbox/__fixtures__/friendica-instance.json');
|
||||||
const result = normalizeInstance(instance);
|
const result = normalizeInstance(instance);
|
||||||
|
|
||||||
// Normalizes max_toot_chars
|
// Normalizes max_toot_chars
|
||||||
|
@ -177,4 +177,11 @@ describe('normalizeInstance()', () => {
|
||||||
expect(result.get('configuration') instanceof ImmutableMap).toBe(true);
|
expect(result.get('configuration') instanceof ImmutableMap).toBe(true);
|
||||||
expect(result.get('description_limit')).toBe(1500);
|
expect(result.get('description_limit')).toBe(1500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('normalizes a Mastodon RC version', () => {
|
||||||
|
const instance = require('soapbox/__fixtures__/mastodon-instance-rc.json');
|
||||||
|
const result = normalizeInstance(instance);
|
||||||
|
|
||||||
|
expect(result.version).toEqual('3.5.0-rc1');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Record as ImmutableRecord, fromJS } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
|
|
||||||
import { normalizeMention } from '../mention';
|
import { normalizeMention } from '../mention';
|
||||||
|
|
||||||
describe('normalizeMention()', () => {
|
describe('normalizeMention()', () => {
|
||||||
it('adds base fields', () => {
|
it('adds base fields', () => {
|
||||||
const account = fromJS({});
|
const account = {};
|
||||||
const result = normalizeMention(account);
|
const result = normalizeMention(account);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||||
|
@ -15,7 +15,7 @@ describe('normalizeMention()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('infers username from acct', () => {
|
it('infers username from acct', () => {
|
||||||
const account = fromJS({ acct: 'alex@gleasonator.com' });
|
const account = { acct: 'alex@gleasonator.com' };
|
||||||
const result = normalizeMention(account);
|
const result = normalizeMention(account);
|
||||||
|
|
||||||
expect(result.username).toEqual('alex');
|
expect(result.username).toEqual('alex');
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Record as ImmutableRecord, fromJS } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
|
|
||||||
import { normalizeNotification } from '../notification';
|
import { normalizeNotification } from '../notification';
|
||||||
|
|
||||||
describe('normalizeNotification()', () => {
|
describe('normalizeNotification()', () => {
|
||||||
it('normalizes an empty map', () => {
|
it('normalizes an empty map', () => {
|
||||||
const notification = fromJS({});
|
const notification = {};
|
||||||
const result = normalizeNotification(notification);
|
const result = normalizeNotification(notification);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Record as ImmutableRecord, fromJS } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
|
|
||||||
import { normalizePoll } from '../poll';
|
import { normalizePoll } from '../poll';
|
||||||
|
|
||||||
describe('normalizePoll()', () => {
|
describe('normalizePoll()', () => {
|
||||||
it('adds base fields', () => {
|
it('adds base fields', () => {
|
||||||
const poll = fromJS({ options: [{ title: 'Apples' }] });
|
const poll = { options: [{ title: 'Apples' }] };
|
||||||
const result = normalizePoll(poll);
|
const result = normalizePoll(poll);
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
|
@ -25,7 +25,7 @@ describe('normalizePoll()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes a Pleroma logged-out poll', () => {
|
it('normalizes a Pleroma logged-out poll', () => {
|
||||||
const poll = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll.json')).get('poll');
|
const { poll } = require('soapbox/__fixtures__/pleroma-status-with-poll.json');
|
||||||
const result = normalizePoll(poll);
|
const result = normalizePoll(poll);
|
||||||
|
|
||||||
// Adds logged-in fields
|
// Adds logged-in fields
|
||||||
|
@ -34,7 +34,7 @@ describe('normalizePoll()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes poll with emojis', () => {
|
it('normalizes poll with emojis', () => {
|
||||||
const poll = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json')).get('poll');
|
const { poll } = require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json');
|
||||||
const result = normalizePoll(poll);
|
const result = normalizePoll(poll);
|
||||||
|
|
||||||
// Emojifies poll options
|
// Emojifies poll options
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { normalizeStatus } from '../status';
|
||||||
|
|
||||||
describe('normalizeStatus()', () => {
|
describe('normalizeStatus()', () => {
|
||||||
it('adds base fields', () => {
|
it('adds base fields', () => {
|
||||||
const status = fromJS({});
|
const status = {};
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||||
|
@ -17,7 +17,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fixes the order of mentions', () => {
|
it('fixes the order of mentions', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/status-unordered-mentions.json'));
|
const status = require('soapbox/__fixtures__/status-unordered-mentions.json');
|
||||||
|
|
||||||
const expected = ['NEETzsche', 'alex', 'Lumeinshin', 'sneeden'];
|
const expected = ['NEETzsche', 'alex', 'Lumeinshin', 'sneeden'];
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds mention to self in self-reply on Mastodon', () => {
|
it('adds mention to self in self-reply on Mastodon', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/mastodon-reply-to-self.json'));
|
const status = require('soapbox/__fixtures__/mastodon-reply-to-self.json');
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
id: '106801667066418367',
|
id: '106801667066418367',
|
||||||
|
@ -48,7 +48,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes mentions with only acct', () => {
|
it('normalizes mentions with only acct', () => {
|
||||||
const status = fromJS({ mentions: [{ acct: 'alex@gleasonator.com' }] });
|
const status = { mentions: [{ acct: 'alex@gleasonator.com' }] };
|
||||||
|
|
||||||
const expected = [{
|
const expected = [{
|
||||||
id: '',
|
id: '',
|
||||||
|
@ -63,7 +63,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Mitra attachments', () => {
|
it('normalizes Mitra attachments', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/mitra-status-with-attachments.json'));
|
const status = require('soapbox/__fixtures__/mitra-status-with-attachments.json');
|
||||||
|
|
||||||
const expected = [{
|
const expected = [{
|
||||||
id: '017eeb0e-e5df-30a4-77a7-a929145cb836',
|
id: '017eeb0e-e5df-30a4-77a7-a929145cb836',
|
||||||
|
@ -97,7 +97,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('leaves Pleroma attachments alone', () => {
|
it('leaves Pleroma attachments alone', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-attachments.json'));
|
const status = require('soapbox/__fixtures__/pleroma-status-with-attachments.json');
|
||||||
const result = normalizeStatus(status).media_attachments;
|
const result = normalizeStatus(status).media_attachments;
|
||||||
|
|
||||||
expect(result.size).toBe(4);
|
expect(result.size).toBe(4);
|
||||||
|
@ -108,15 +108,15 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Pleroma quote post', () => {
|
it('normalizes Pleroma quote post', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/pleroma-quote-post.json'));
|
const status = require('soapbox/__fixtures__/pleroma-quote-post.json');
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
expect(result.quote).toEqual(status.getIn(['pleroma', 'quote']));
|
expect(result.quote).toEqual(fromJS(status.pleroma.quote));
|
||||||
expect(result.pleroma.get('quote')).toBe(undefined);
|
expect(result.pleroma.get('quote')).toBe(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes GoToSocial status', () => {
|
it('normalizes GoToSocial status', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/gotosocial-status.json'));
|
const status = require('soapbox/__fixtures__/gotosocial-status.json');
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
// Adds missing fields
|
// Adds missing fields
|
||||||
|
@ -132,7 +132,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes Friendica status', () => {
|
it('normalizes Friendica status', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/friendica-status.json'));
|
const status = require('soapbox/__fixtures__/friendica-status.json');
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
// Adds missing fields
|
// Adds missing fields
|
||||||
|
@ -145,7 +145,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes poll and poll options', () => {
|
it('normalizes poll and poll options', () => {
|
||||||
const status = fromJS({ poll: { options: [{ title: 'Apples' }] } });
|
const status = { poll: { options: [{ title: 'Apples' }] } };
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
|
@ -166,7 +166,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes a Pleroma logged-out poll', () => {
|
it('normalizes a Pleroma logged-out poll', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll.json'));
|
const status = require('soapbox/__fixtures__/pleroma-status-with-poll.json');
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
// Adds logged-in fields
|
// Adds logged-in fields
|
||||||
|
@ -175,7 +175,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes poll with emojis', () => {
|
it('normalizes poll with emojis', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json'));
|
const status = require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json');
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
// Emojifies poll options
|
// Emojifies poll options
|
||||||
|
@ -188,7 +188,7 @@ describe('normalizeStatus()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes a card', () => {
|
it('normalizes a card', () => {
|
||||||
const status = fromJS(require('soapbox/__fixtures__/status-with-card.json'));
|
const status = require('soapbox/__fixtures__/status-with-card.json');
|
||||||
const result = normalizeStatus(status);
|
const result = normalizeStatus(status);
|
||||||
|
|
||||||
expect(ImmutableRecord.isRecord(result.card)).toBe(true);
|
expect(ImmutableRecord.isRecord(result.card)).toBe(true);
|
||||||
|
|
|
@ -8,16 +8,18 @@ import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
|
|
||||||
import emojify from 'soapbox/features/emoji/emoji';
|
import emojify from 'soapbox/features/emoji/emoji';
|
||||||
import { normalizeEmoji } from 'soapbox/normalizers/emoji';
|
import { normalizeEmoji } from 'soapbox/normalizers/emoji';
|
||||||
import { IAccount } from 'soapbox/types';
|
import { IAccount } from 'soapbox/types';
|
||||||
|
import { acctFull } from 'soapbox/utils/accounts';
|
||||||
import { unescapeHTML } from 'soapbox/utils/html';
|
import { unescapeHTML } from 'soapbox/utils/html';
|
||||||
import { mergeDefined, makeEmojiMap } from 'soapbox/utils/normalizers';
|
import { mergeDefined, makeEmojiMap } from 'soapbox/utils/normalizers';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/account/
|
// https://docs.joinmastodon.org/entities/account/
|
||||||
const AccountRecord = ImmutableRecord({
|
export const AccountRecord = ImmutableRecord({
|
||||||
acct: '',
|
acct: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
avatar_static: '',
|
avatar_static: '',
|
||||||
|
@ -44,6 +46,7 @@ const AccountRecord = ImmutableRecord({
|
||||||
uri: '',
|
uri: '',
|
||||||
url: '',
|
url: '',
|
||||||
username: '',
|
username: '',
|
||||||
|
website: '',
|
||||||
verified: false,
|
verified: false,
|
||||||
|
|
||||||
// Internal fields
|
// Internal fields
|
||||||
|
@ -56,7 +59,7 @@ const AccountRecord = ImmutableRecord({
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/field/
|
// https://docs.joinmastodon.org/entities/field/
|
||||||
const FieldRecord = ImmutableRecord({
|
export const FieldRecord = ImmutableRecord({
|
||||||
name: '',
|
name: '',
|
||||||
value: '',
|
value: '',
|
||||||
verified_at: null,
|
verified_at: null,
|
||||||
|
@ -95,6 +98,18 @@ const normalizeAvatar = (account: ImmutableMap<string, any>) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add header, if missing
|
||||||
|
const normalizeHeader = (account: ImmutableMap<string, any>) => {
|
||||||
|
const header = account.get('header');
|
||||||
|
const headerStatic = account.get('header_static');
|
||||||
|
const missing = require('images/header-missing.png');
|
||||||
|
|
||||||
|
return account.withMutations(account => {
|
||||||
|
account.set('header', header || headerStatic || missing);
|
||||||
|
account.set('header_static', headerStatic || header || missing);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Normalize custom fields
|
// Normalize custom fields
|
||||||
const normalizeFields = (account: ImmutableMap<string, any>) => {
|
const normalizeFields = (account: ImmutableMap<string, any>) => {
|
||||||
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
|
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
|
||||||
|
@ -132,11 +147,12 @@ const normalizeVerified = (account: ImmutableMap<string, any>) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize Fedibird/Truth Social location
|
// Normalize Fedibird/Truth Social/Pleroma location
|
||||||
const normalizeLocation = (account: ImmutableMap<string, any>) => {
|
const normalizeLocation = (account: ImmutableMap<string, any>) => {
|
||||||
return account.update('location', location => {
|
return account.update('location', location => {
|
||||||
return [
|
return [
|
||||||
location,
|
location,
|
||||||
|
account.getIn(['pleroma', 'location']),
|
||||||
account.getIn(['other_settings', 'location']),
|
account.getIn(['other_settings', 'location']),
|
||||||
].find(Boolean);
|
].find(Boolean);
|
||||||
});
|
});
|
||||||
|
@ -180,16 +196,22 @@ const addInternalFields = (account: ImmutableMap<string, any>) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const normalizeAccount = (account: ImmutableMap<string, any>): IAccount => {
|
const normalizeFqn = (account: ImmutableMap<string, any>) => {
|
||||||
|
return account.set('fqn', acctFull(account));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const normalizeAccount = (account: Record<string, any>): IAccount => {
|
||||||
return AccountRecord(
|
return AccountRecord(
|
||||||
account.withMutations(account => {
|
ImmutableMap(fromJS(account)).withMutations(account => {
|
||||||
normalizePleromaLegacyFields(account);
|
normalizePleromaLegacyFields(account);
|
||||||
normalizeEmojis(account);
|
normalizeEmojis(account);
|
||||||
normalizeAvatar(account);
|
normalizeAvatar(account);
|
||||||
|
normalizeHeader(account);
|
||||||
normalizeFields(account);
|
normalizeFields(account);
|
||||||
normalizeVerified(account);
|
normalizeVerified(account);
|
||||||
normalizeBirthday(account);
|
normalizeBirthday(account);
|
||||||
normalizeLocation(account);
|
normalizeLocation(account);
|
||||||
|
normalizeFqn(account);
|
||||||
fixUsername(account);
|
fixUsername(account);
|
||||||
fixDisplayName(account);
|
fixDisplayName(account);
|
||||||
addInternalFields(account);
|
addInternalFields(account);
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
import {
|
import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
|
|
||||||
import { mergeDefined } from 'soapbox/utils/normalizers';
|
import { mergeDefined } from 'soapbox/utils/normalizers';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/attachment/
|
// https://docs.joinmastodon.org/entities/attachment/
|
||||||
const AttachmentRecord = ImmutableRecord({
|
export const AttachmentRecord = ImmutableRecord({
|
||||||
blurhash: undefined,
|
blurhash: undefined,
|
||||||
description: '',
|
description: '',
|
||||||
id: '',
|
id: '',
|
||||||
|
@ -29,7 +30,7 @@ const AttachmentRecord = ImmutableRecord({
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ensure attachments have required fields
|
// Ensure attachments have required fields
|
||||||
export const normalizeAttachment = (attachment: ImmutableMap<string, any>) => {
|
const normalizeUrls = (attachment: ImmutableMap<string, any>) => {
|
||||||
const url = [
|
const url = [
|
||||||
attachment.get('url'),
|
attachment.get('url'),
|
||||||
attachment.get('preview_url'),
|
attachment.get('preview_url'),
|
||||||
|
@ -41,5 +42,11 @@ export const normalizeAttachment = (attachment: ImmutableMap<string, any>) => {
|
||||||
preview_url: url,
|
preview_url: url,
|
||||||
});
|
});
|
||||||
|
|
||||||
return AttachmentRecord(attachment.mergeWith(mergeDefined, base));
|
return attachment.mergeWith(mergeDefined, base);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const normalizeAttachment = (attachment: Record<string, any>) => {
|
||||||
|
return AttachmentRecord(
|
||||||
|
normalizeUrls(ImmutableMap(fromJS(attachment))),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
* Converts API cards into our internal format.
|
* Converts API cards into our internal format.
|
||||||
* @see {@link https://docs.joinmastodon.org/entities/card/}
|
* @see {@link https://docs.joinmastodon.org/entities/card/}
|
||||||
*/
|
*/
|
||||||
import { Record as ImmutableRecord, Map as ImmutableMap } from 'immutable';
|
import { Record as ImmutableRecord, Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/card/
|
// https://docs.joinmastodon.org/entities/card/
|
||||||
const CardRecord = ImmutableRecord({
|
export const CardRecord = ImmutableRecord({
|
||||||
author_name: '',
|
author_name: '',
|
||||||
author_url: '',
|
author_url: '',
|
||||||
blurhash: null,
|
blurhash: null,
|
||||||
|
@ -23,6 +23,8 @@ const CardRecord = ImmutableRecord({
|
||||||
width: 0,
|
width: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const normalizeCard = (card: ImmutableMap<string, any>) => {
|
export const normalizeCard = (card: Record<string, any>) => {
|
||||||
return CardRecord(card);
|
return CardRecord(
|
||||||
|
ImmutableMap(fromJS(card)),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
* Converts API emojis into our internal format.
|
* Converts API emojis into our internal format.
|
||||||
* @see {@link https://docs.joinmastodon.org/entities/emoji/}
|
* @see {@link https://docs.joinmastodon.org/entities/emoji/}
|
||||||
*/
|
*/
|
||||||
import { Record as ImmutableRecord, Map as ImmutableMap } from 'immutable';
|
import { Record as ImmutableRecord, Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/emoji/
|
// https://docs.joinmastodon.org/entities/emoji/
|
||||||
const EmojiRecord = ImmutableRecord({
|
export const EmojiRecord = ImmutableRecord({
|
||||||
category: '',
|
category: '',
|
||||||
shortcode: '',
|
shortcode: '',
|
||||||
static_url: '',
|
static_url: '',
|
||||||
|
@ -14,6 +14,8 @@ const EmojiRecord = ImmutableRecord({
|
||||||
visible_in_picker: true,
|
visible_in_picker: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const normalizeEmoji = (emoji: ImmutableMap<string, any>) => {
|
export const normalizeEmoji = (emoji: Record<string, any>) => {
|
||||||
return EmojiRecord(emoji);
|
return EmojiRecord(
|
||||||
|
ImmutableMap(fromJS(emoji)),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
export { AccountRecord, FieldRecord, normalizeAccount } from './account';
|
||||||
|
export { AttachmentRecord, normalizeAttachment } from './attachment';
|
||||||
|
export { CardRecord, normalizeCard } from './card';
|
||||||
|
export { EmojiRecord, normalizeEmoji } from './emoji';
|
||||||
|
export { InstanceRecord, normalizeInstance } from './instance';
|
||||||
|
export { MentionRecord, normalizeMention } from './mention';
|
||||||
|
export { NotificationRecord, normalizeNotification } from './notification';
|
||||||
|
export { PollRecord, PollOptionRecord, normalizePoll } from './poll';
|
||||||
|
export { StatusRecord, normalizeStatus } from './status';
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
|
|
||||||
import { parseVersion, PLEROMA } from 'soapbox/utils/features';
|
import { parseVersion, PLEROMA } from 'soapbox/utils/features';
|
||||||
|
@ -15,7 +16,7 @@ import { isNumber } from 'soapbox/utils/numbers';
|
||||||
|
|
||||||
// Use Mastodon defaults
|
// Use Mastodon defaults
|
||||||
// https://docs.joinmastodon.org/entities/instance/
|
// https://docs.joinmastodon.org/entities/instance/
|
||||||
const InstanceRecord = ImmutableRecord({
|
export const InstanceRecord = ImmutableRecord({
|
||||||
approval_required: false,
|
approval_required: false,
|
||||||
contact_account: ImmutableMap(),
|
contact_account: ImmutableMap(),
|
||||||
configuration: ImmutableMap({
|
configuration: ImmutableMap({
|
||||||
|
@ -83,13 +84,25 @@ const pleromaToMastodonConfig = (instance: ImmutableMap<string, any>) => {
|
||||||
// Get the software's default attachment limit
|
// Get the software's default attachment limit
|
||||||
const getAttachmentLimit = (software: string) => software === PLEROMA ? Infinity : 4;
|
const getAttachmentLimit = (software: string) => software === PLEROMA ? Infinity : 4;
|
||||||
|
|
||||||
// Normalize instance (Pleroma, Mastodon, etc.) to Mastodon's format
|
// Normalize version
|
||||||
export const normalizeInstance = (instance: ImmutableMap<string, any>) => {
|
const normalizeVersion = (instance: ImmutableMap<string, any>) => {
|
||||||
const { software } = parseVersion(instance.get('version'));
|
return instance.update('version', '0.0.0', version => {
|
||||||
const mastodonConfig = pleromaToMastodonConfig(instance);
|
// Handle Mastodon release candidates
|
||||||
|
if (new RegExp(/[0-9\.]+rc[0-9]+/g).test(version)) {
|
||||||
|
return version.split('rc').join('-rc');
|
||||||
|
} else {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Normalize instance (Pleroma, Mastodon, etc.) to Mastodon's format
|
||||||
|
export const normalizeInstance = (instance: Record<string, any>) => {
|
||||||
return InstanceRecord(
|
return InstanceRecord(
|
||||||
instance.withMutations(instance => {
|
ImmutableMap(fromJS(instance)).withMutations((instance: ImmutableMap<string, any>) => {
|
||||||
|
const { software } = parseVersion(instance.get('version'));
|
||||||
|
const mastodonConfig = pleromaToMastodonConfig(instance);
|
||||||
|
|
||||||
// Merge configuration
|
// Merge configuration
|
||||||
instance.update('configuration', ImmutableMap(), configuration => (
|
instance.update('configuration', ImmutableMap(), configuration => (
|
||||||
configuration.mergeDeepWith(mergeDefined, mastodonConfig)
|
configuration.mergeDeepWith(mergeDefined, mastodonConfig)
|
||||||
|
@ -100,6 +113,9 @@ export const normalizeInstance = (instance: ImmutableMap<string, any>) => {
|
||||||
return isNumber(value) ? value : getAttachmentLimit(software);
|
return isNumber(value) ? value : getAttachmentLimit(software);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Normalize version
|
||||||
|
normalizeVersion(instance);
|
||||||
|
|
||||||
// Merge defaults
|
// Merge defaults
|
||||||
instance.mergeDeepWith(mergeDefined, InstanceRecord());
|
instance.mergeDeepWith(mergeDefined, InstanceRecord());
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -3,22 +3,19 @@
|
||||||
* Converts API mentions into our internal format.
|
* Converts API mentions into our internal format.
|
||||||
* @see {@link https://docs.joinmastodon.org/entities/mention/}
|
* @see {@link https://docs.joinmastodon.org/entities/mention/}
|
||||||
*/
|
*/
|
||||||
import {
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
Map as ImmutableMap,
|
|
||||||
Record as ImmutableRecord,
|
|
||||||
} from 'immutable';
|
|
||||||
|
|
||||||
import { normalizeAccount } from 'soapbox/normalizers/account';
|
import { normalizeAccount } from 'soapbox/normalizers/account';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/mention/
|
// https://docs.joinmastodon.org/entities/mention/
|
||||||
const MentionRecord = ImmutableRecord({
|
export const MentionRecord = ImmutableRecord({
|
||||||
id: '',
|
id: '',
|
||||||
acct: '',
|
acct: '',
|
||||||
username: '',
|
username: '',
|
||||||
url: '',
|
url: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const normalizeMention = (mention: ImmutableMap<string, any>) => {
|
export const normalizeMention = (mention: Record<string, any>) => {
|
||||||
// Simply normalize it as an account then cast it as a mention ¯\_(ツ)_/¯
|
// Simply normalize it as an account then cast it as a mention ¯\_(ツ)_/¯
|
||||||
return MentionRecord(normalizeAccount(mention));
|
return MentionRecord(normalizeAccount(mention));
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
import {
|
import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/notification/
|
// https://docs.joinmastodon.org/entities/notification/
|
||||||
const NotificationRecord = ImmutableRecord({
|
export const NotificationRecord = ImmutableRecord({
|
||||||
account: null,
|
account: null,
|
||||||
chat_message: null, // pleroma:chat_mention
|
chat_message: null, // pleroma:chat_mention
|
||||||
created_at: new Date(),
|
created_at: new Date(),
|
||||||
|
@ -20,6 +21,8 @@ const NotificationRecord = ImmutableRecord({
|
||||||
type: '',
|
type: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const normalizeNotification = (notification: ImmutableMap<string, any>) => {
|
export const normalizeNotification = (notification: Record<string, any>) => {
|
||||||
return NotificationRecord(notification);
|
return NotificationRecord(
|
||||||
|
ImmutableMap(fromJS(notification)),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
|
|
||||||
import emojify from 'soapbox/features/emoji/emoji';
|
import emojify from 'soapbox/features/emoji/emoji';
|
||||||
|
@ -15,7 +16,7 @@ import { normalizeEmoji } from 'soapbox/normalizers/emoji';
|
||||||
import { makeEmojiMap } from 'soapbox/utils/normalizers';
|
import { makeEmojiMap } from 'soapbox/utils/normalizers';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/poll/
|
// https://docs.joinmastodon.org/entities/poll/
|
||||||
const PollRecord = ImmutableRecord({
|
export const PollRecord = ImmutableRecord({
|
||||||
emojis: ImmutableList(),
|
emojis: ImmutableList(),
|
||||||
expired: false,
|
expired: false,
|
||||||
expires_at: new Date(),
|
expires_at: new Date(),
|
||||||
|
@ -29,7 +30,7 @@ const PollRecord = ImmutableRecord({
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sub-entity of Poll
|
// Sub-entity of Poll
|
||||||
const PollOptionRecord = ImmutableRecord({
|
export const PollOptionRecord = ImmutableRecord({
|
||||||
title: '',
|
title: '',
|
||||||
votes_count: 0,
|
votes_count: 0,
|
||||||
|
|
||||||
|
@ -76,9 +77,9 @@ const normalizePollVoted = (poll: ImmutableMap<string, any>) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const normalizePoll = (poll: ImmutableMap<string, any>) => {
|
export const normalizePoll = (poll: Record<string, any>) => {
|
||||||
return PollRecord(
|
return PollRecord(
|
||||||
poll.withMutations((poll: ImmutableMap<string, any>) => {
|
ImmutableMap(fromJS(poll)).withMutations((poll: ImmutableMap<string, any>) => {
|
||||||
normalizeEmojis(poll);
|
normalizeEmojis(poll);
|
||||||
normalizePollOptions(poll);
|
normalizePollOptions(poll);
|
||||||
normalizePollOwnVotes(poll);
|
normalizePollOwnVotes(poll);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
|
|
||||||
import { normalizeAttachment } from 'soapbox/normalizers/attachment';
|
import { normalizeAttachment } from 'soapbox/normalizers/attachment';
|
||||||
|
@ -17,7 +18,7 @@ import { normalizePoll } from 'soapbox/normalizers/poll';
|
||||||
import { IStatus } from 'soapbox/types';
|
import { IStatus } from 'soapbox/types';
|
||||||
|
|
||||||
// https://docs.joinmastodon.org/entities/status/
|
// https://docs.joinmastodon.org/entities/status/
|
||||||
const StatusRecord = ImmutableRecord({
|
export const StatusRecord = ImmutableRecord({
|
||||||
account: null,
|
account: null,
|
||||||
application: null,
|
application: null,
|
||||||
bookmarked: false,
|
bookmarked: false,
|
||||||
|
@ -135,9 +136,9 @@ const fixQuote = (status: ImmutableMap<string, any>) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const normalizeStatus = (status: ImmutableMap<string, any>): IStatus => {
|
export const normalizeStatus = (status: Record<string, any>): IStatus => {
|
||||||
return StatusRecord(
|
return StatusRecord(
|
||||||
status.withMutations(status => {
|
ImmutableMap(fromJS(status)).withMutations(status => {
|
||||||
normalizeAttachments(status);
|
normalizeAttachments(status);
|
||||||
normalizeMentions(status);
|
normalizeMentions(status);
|
||||||
normalizeEmojis(status);
|
normalizeEmojis(status);
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
import * as actions from 'soapbox/actions/compose';
|
import * as actions from 'soapbox/actions/compose';
|
||||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
||||||
import { SETTING_CHANGE } from 'soapbox/actions/settings';
|
import { SETTING_CHANGE } from 'soapbox/actions/settings';
|
||||||
//import { REDRAFT } from 'soapbox/actions/statuses';
|
import { REDRAFT } from 'soapbox/actions/statuses';
|
||||||
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
||||||
|
import { normalizeStatus } from 'soapbox/normalizers/status';
|
||||||
|
|
||||||
import reducer from '../compose';
|
import reducer from '../compose';
|
||||||
|
|
||||||
|
@ -38,6 +39,29 @@ describe('compose reducer', () => {
|
||||||
expect(state.get('idempotencyKey').length === 36);
|
expect(state.get('idempotencyKey').length === 36);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('REDRAFT', () => {
|
||||||
|
it('strips Pleroma integer attachments', () => {
|
||||||
|
const action = {
|
||||||
|
type: REDRAFT,
|
||||||
|
status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
|
||||||
|
v: { software: 'Pleroma' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = reducer(undefined, action);
|
||||||
|
expect(result.get('media_attachments').isEmpty()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('leaves non-Pleroma integer attachments alone', () => {
|
||||||
|
const action = {
|
||||||
|
type: REDRAFT,
|
||||||
|
status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = reducer(undefined, action);
|
||||||
|
expect(result.getIn(['media_attachments', 0, 'id'])).toEqual('508107650');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('uses \'public\' scope as default', () => {
|
it('uses \'public\' scope as default', () => {
|
||||||
const action = {
|
const action = {
|
||||||
type: actions.COMPOSE_REPLY,
|
type: actions.COMPOSE_REPLY,
|
||||||
|
@ -325,30 +349,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle COMPOSE_UPLOAD_UNDO', () => {
|
|
||||||
// const state = ImmutableMap({
|
|
||||||
// media_attachments: ImmutableList([
|
|
||||||
// description: null,
|
|
||||||
// id: '1375732379',
|
|
||||||
// pleroma: {
|
|
||||||
// mime_type: 'image/jpeg'
|
|
||||||
// },
|
|
||||||
// preview_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
|
|
||||||
// remote_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
|
|
||||||
// text_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
|
|
||||||
// type: 'image',
|
|
||||||
// url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg'
|
|
||||||
// ]),
|
|
||||||
// });
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_UPLOAD_UNDO,
|
|
||||||
// mediaId: '1375732379',
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action)).toEqual({
|
|
||||||
// media_attachments: [],
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should handle COMPOSE_UPLOAD_PROGRESS', () => {
|
it('should handle COMPOSE_UPLOAD_PROGRESS', () => {
|
||||||
const state = ImmutableMap({ progress: 0 });
|
const state = ImmutableMap({ progress: 0 });
|
||||||
const action = {
|
const action = {
|
||||||
|
@ -361,203 +361,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle COMPOSE_MENTION', () => {
|
|
||||||
// const state = ImmutableMap({});
|
|
||||||
// const account = {
|
|
||||||
// '9w1HhmenIAKBHJiUs4': {
|
|
||||||
// header_static: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
|
|
||||||
// display_name_html: 'Alex Gleason',
|
|
||||||
// bot: false,
|
|
||||||
// display_name: 'Alex Gleason',
|
|
||||||
// created_at: '2020-06-12T21:47:28.000Z',
|
|
||||||
// locked: false,
|
|
||||||
// emojis: [],
|
|
||||||
// header: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
|
|
||||||
// url: 'https://gleasonator.com/users/alex',
|
|
||||||
// note: 'Fediverse developer. I come in peace. <a class="hashtag" data-tag="vegan" href="https://gleasonator.com/tag/vegan">#vegan</a> <a class="hashtag" data-tag="freeculture" href="https://gleasonator.com/tag/freeculture">#freeculture</a> <a class="hashtag" data-tag="atheist" href="https://gleasonator.com/tag/atheist">#atheist</a> <a class="hashtag" data-tag="antiporn" href="https://gleasonator.com/tag/antiporn">#antiporn</a> <a class="hashtag" data-tag="gendercritical" href="https://gleasonator.com/tag/gendercritical">#gendercritical</a>. Boosts ≠ endorsements.',
|
|
||||||
// acct: 'alex@gleasonator.com',
|
|
||||||
// avatar_static: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
|
|
||||||
// username: 'alex',
|
|
||||||
// avatar: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
|
|
||||||
// fields: [
|
|
||||||
// {
|
|
||||||
// name: 'Website',
|
|
||||||
// value: '<a href="https://alexgleason.me" rel="ugc">https://alexgleason.me</a>',
|
|
||||||
// name_emojified: 'Website',
|
|
||||||
// value_emojified: '<a href="https://alexgleason.me" rel="ugc">https://alexgleason.me</a>',
|
|
||||||
// value_plain: 'https://alexgleason.me'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Pleroma+Soapbox',
|
|
||||||
// value: '<a href="https://soapbox.pub" rel="ugc">https://soapbox.pub</a>',
|
|
||||||
// name_emojified: 'Pleroma+Soapbox',
|
|
||||||
// value_emojified: '<a href="https://soapbox.pub" rel="ugc">https://soapbox.pub</a>',
|
|
||||||
// value_plain: 'https://soapbox.pub'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Email',
|
|
||||||
// value: 'alex@alexgleason.me',
|
|
||||||
// name_emojified: 'Email',
|
|
||||||
// value_emojified: 'alex@alexgleason.me',
|
|
||||||
// value_plain: 'alex@alexgleason.me'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Gender identity',
|
|
||||||
// value: 'Soyboy',
|
|
||||||
// name_emojified: 'Gender identity',
|
|
||||||
// value_emojified: 'Soyboy',
|
|
||||||
// value_plain: 'Soyboy'
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// pleroma: {
|
|
||||||
// hide_follows: false,
|
|
||||||
// hide_followers_count: false,
|
|
||||||
// background_image: null,
|
|
||||||
// confirmation_pending: false,
|
|
||||||
// is_moderator: false,
|
|
||||||
// hide_follows_count: false,
|
|
||||||
// hide_followers: false,
|
|
||||||
// relationship: {
|
|
||||||
// showing_reblogs: true,
|
|
||||||
// followed_by: false,
|
|
||||||
// subscribing: false,
|
|
||||||
// blocked_by: false,
|
|
||||||
// requested: false,
|
|
||||||
// domain_blocking: false,
|
|
||||||
// following: false,
|
|
||||||
// endorsed: false,
|
|
||||||
// blocking: false,
|
|
||||||
// muting: false,
|
|
||||||
// id: '9w1HhmenIAKBHJiUs4',
|
|
||||||
// muting_notifications: false
|
|
||||||
// },
|
|
||||||
// tags: [],
|
|
||||||
// hide_favorites: true,
|
|
||||||
// is_admin: false,
|
|
||||||
// skip_thread_containment: false
|
|
||||||
// },
|
|
||||||
// source: {
|
|
||||||
// fields: [],
|
|
||||||
// note: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts ≠ endorsements.',
|
|
||||||
// pleroma: {
|
|
||||||
// actor_type: 'Person',
|
|
||||||
// discoverable: false
|
|
||||||
// },
|
|
||||||
// sensitive: false
|
|
||||||
// },
|
|
||||||
// id: '9w1HhmenIAKBHJiUs4',
|
|
||||||
// note_emojified: 'Fediverse developer. I come in peace. <a class="hashtag" data-tag="vegan" href="https://gleasonator.com/tag/vegan">#vegan</a> <a class="hashtag" data-tag="freeculture" href="https://gleasonator.com/tag/freeculture">#freeculture</a> <a class="hashtag" data-tag="atheist" href="https://gleasonator.com/tag/atheist">#atheist</a> <a class="hashtag" data-tag="antiporn" href="https://gleasonator.com/tag/antiporn">#antiporn</a> <a class="hashtag" data-tag="gendercritical" href="https://gleasonator.com/tag/gendercritical">#gendercritical</a>. Boosts ≠ endorsements.'
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_MENTION,
|
|
||||||
// account: account,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// text: '@alex@gleasonator.com',
|
|
||||||
// caretPosition: null,
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should handle COMPOSE_DIRECT', () => {
|
|
||||||
// const state = ImmutableMap({});
|
|
||||||
// const account = {
|
|
||||||
// '9w1HhmenIAKBHJiUs4': {
|
|
||||||
// header_static: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
|
|
||||||
// display_name_html: 'Alex Gleason',
|
|
||||||
// bot: false,
|
|
||||||
// display_name: 'Alex Gleason',
|
|
||||||
// created_at: '2020-06-12T21:47:28.000Z',
|
|
||||||
// locked: false,
|
|
||||||
// emojis: [],
|
|
||||||
// header: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
|
|
||||||
// url: 'https://gleasonator.com/users/alex',
|
|
||||||
// note: 'Fediverse developer. I come in peace. <a class="hashtag" data-tag="vegan" href="https://gleasonator.com/tag/vegan">#vegan</a> <a class="hashtag" data-tag="freeculture" href="https://gleasonator.com/tag/freeculture">#freeculture</a> <a class="hashtag" data-tag="atheist" href="https://gleasonator.com/tag/atheist">#atheist</a> <a class="hashtag" data-tag="antiporn" href="https://gleasonator.com/tag/antiporn">#antiporn</a> <a class="hashtag" data-tag="gendercritical" href="https://gleasonator.com/tag/gendercritical">#gendercritical</a>. Boosts ≠ endorsements.',
|
|
||||||
// acct: 'alex@gleasonator.com',
|
|
||||||
// avatar_static: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
|
|
||||||
// username: 'alex',
|
|
||||||
// avatar: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
|
|
||||||
// fields: [
|
|
||||||
// {
|
|
||||||
// name: 'Website',
|
|
||||||
// value: '<a href="https://alexgleason.me" rel="ugc">https://alexgleason.me</a>',
|
|
||||||
// name_emojified: 'Website',
|
|
||||||
// value_emojified: '<a href="https://alexgleason.me" rel="ugc">https://alexgleason.me</a>',
|
|
||||||
// value_plain: 'https://alexgleason.me'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Pleroma+Soapbox',
|
|
||||||
// value: '<a href="https://soapbox.pub" rel="ugc">https://soapbox.pub</a>',
|
|
||||||
// name_emojified: 'Pleroma+Soapbox',
|
|
||||||
// value_emojified: '<a href="https://soapbox.pub" rel="ugc">https://soapbox.pub</a>',
|
|
||||||
// value_plain: 'https://soapbox.pub'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Email',
|
|
||||||
// value: 'alex@alexgleason.me',
|
|
||||||
// name_emojified: 'Email',
|
|
||||||
// value_emojified: 'alex@alexgleason.me',
|
|
||||||
// value_plain: 'alex@alexgleason.me'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Gender identity',
|
|
||||||
// value: 'Soyboy',
|
|
||||||
// name_emojified: 'Gender identity',
|
|
||||||
// value_emojified: 'Soyboy',
|
|
||||||
// value_plain: 'Soyboy'
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// pleroma: {
|
|
||||||
// hide_follows: false,
|
|
||||||
// hide_followers_count: false,
|
|
||||||
// background_image: null,
|
|
||||||
// confirmation_pending: false,
|
|
||||||
// is_moderator: false,
|
|
||||||
// hide_follows_count: false,
|
|
||||||
// hide_followers: false,
|
|
||||||
// relationship: {
|
|
||||||
// showing_reblogs: true,
|
|
||||||
// followed_by: false,
|
|
||||||
// subscribing: false,
|
|
||||||
// blocked_by: false,
|
|
||||||
// requested: false,
|
|
||||||
// domain_blocking: false,
|
|
||||||
// following: false,
|
|
||||||
// endorsed: false,
|
|
||||||
// blocking: false,
|
|
||||||
// muting: false,
|
|
||||||
// id: '9w1HhmenIAKBHJiUs4',
|
|
||||||
// muting_notifications: false
|
|
||||||
// },
|
|
||||||
// tags: [],
|
|
||||||
// hide_favorites: true,
|
|
||||||
// is_admin: false,
|
|
||||||
// skip_thread_containment: false
|
|
||||||
// },
|
|
||||||
// source: {
|
|
||||||
// fields: [],
|
|
||||||
// note: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts ≠ endorsements.',
|
|
||||||
// pleroma: {
|
|
||||||
// actor_type: 'Person',
|
|
||||||
// discoverable: false
|
|
||||||
// },
|
|
||||||
// sensitive: false
|
|
||||||
// },
|
|
||||||
// id: '9w1HhmenIAKBHJiUs4',
|
|
||||||
// note_emojified: 'Fediverse developer. I come in peace. <a class="hashtag" data-tag="vegan" href="https://gleasonator.com/tag/vegan">#vegan</a> <a class="hashtag" data-tag="freeculture" href="https://gleasonator.com/tag/freeculture">#freeculture</a> <a class="hashtag" data-tag="atheist" href="https://gleasonator.com/tag/atheist">#atheist</a> <a class="hashtag" data-tag="antiporn" href="https://gleasonator.com/tag/antiporn">#antiporn</a> <a class="hashtag" data-tag="gendercritical" href="https://gleasonator.com/tag/gendercritical">#gendercritical</a>. Boosts ≠ endorsements.'
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_DIRECT,
|
|
||||||
// account: account,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// text: '@alex@gleasonator.com',
|
|
||||||
// caretPosition: null,
|
|
||||||
// privacy: 'direct',
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
it('should handle COMPOSE_SUGGESTIONS_CLEAR', () => {
|
it('should handle COMPOSE_SUGGESTIONS_CLEAR', () => {
|
||||||
const state = ImmutableMap({ });
|
const state = ImmutableMap({ });
|
||||||
const action = {
|
const action = {
|
||||||
|
@ -570,28 +373,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle COMPOSE_SUGGESTIONS_READY', () => {
|
|
||||||
// const state = ImmutableMap({ default_privacy: 'public', privacy: 'public'});
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_SUGGESTIONS_READY,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// default_privacy: 'unlisted',
|
|
||||||
// privacy: 'public',
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// it('should handle COMPOSE_SUGGESTION_SELECT', () => {
|
|
||||||
// const state = ImmutableMap({ default_privacy: 'public', privacy: 'public'});
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_SUGGESTION_SELECT,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// default_privacy: 'unlisted',
|
|
||||||
// privacy: 'public',
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
it('should handle COMPOSE_SUGGESTION_TAGS_UPDATE', () => {
|
it('should handle COMPOSE_SUGGESTION_TAGS_UPDATE', () => {
|
||||||
const state = ImmutableMap({ tagHistory: [ 'hashtag' ] });
|
const state = ImmutableMap({ tagHistory: [ 'hashtag' ] });
|
||||||
const action = {
|
const action = {
|
||||||
|
@ -627,42 +408,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle COMPOSE_EMOJI_INSERT', () => {
|
|
||||||
// const state = ImmutableMap({ text: 'this is my' });
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_EMOJI_INSERT,
|
|
||||||
// position: 11,
|
|
||||||
// emoji: [],
|
|
||||||
// needsSpace, true,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// text: 'this is my :emoji:',
|
|
||||||
// caretPosition: 15,
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// it('should handle COMPOSE_UPLOAD_CHANGE_SUCCESS', () => {
|
|
||||||
// const state = ImmutableMap({ default_privacy: 'public' });
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_UPLOAD_CHANGE_SUCCESS,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// default_privacy: 'unlisted',
|
|
||||||
// privacy: 'public',
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// it('should handle REDRAFT', () => {
|
|
||||||
// const state = ImmutableMap({ default_privacy: 'public' });
|
|
||||||
// const action = {
|
|
||||||
// type: REDRAFT,
|
|
||||||
// };
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// default_privacy: 'unlisted',
|
|
||||||
// privacy: 'public',
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
it('should handle COMPOSE_POLL_ADD', () => {
|
it('should handle COMPOSE_POLL_ADD', () => {
|
||||||
const state = ImmutableMap({ poll: null });
|
const state = ImmutableMap({ poll: null });
|
||||||
const initialPoll = Object({
|
const initialPoll = Object({
|
||||||
|
@ -691,34 +436,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle COMPOSE_POLL_OPTION_ADD', () => {
|
|
||||||
// const initialPoll = Object({
|
|
||||||
// options: [
|
|
||||||
// 'option 1',
|
|
||||||
// 'option 2',
|
|
||||||
// ],
|
|
||||||
// expires_in: 86400,
|
|
||||||
// multiple: false
|
|
||||||
// });
|
|
||||||
// const state = ImmutableMap({ poll: initialPoll });
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_POLL_OPTION_ADD,
|
|
||||||
// title: 'option 3',
|
|
||||||
// };
|
|
||||||
// const updatedPoll = Object({
|
|
||||||
// options: [
|
|
||||||
// 'option 1',
|
|
||||||
// 'option 2',
|
|
||||||
// 'option 3',
|
|
||||||
// ],
|
|
||||||
// expires_in: 86400,
|
|
||||||
// multiple: false,
|
|
||||||
// });
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// poll: updatedPoll,
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should handle COMPOSE_POLL_OPTION_CHANGE', () => {
|
it('should handle COMPOSE_POLL_OPTION_CHANGE', () => {
|
||||||
const initialPoll = Object({
|
const initialPoll = Object({
|
||||||
options: [
|
options: [
|
||||||
|
@ -747,32 +464,6 @@ describe('compose reducer', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should handle COMPOSE_POLL_OPTION_REMOVE', () => {
|
|
||||||
// const initialPoll = Object({
|
|
||||||
// options: [
|
|
||||||
// 'option 1',
|
|
||||||
// 'option 2',
|
|
||||||
// ],
|
|
||||||
// expires_in: 86400,
|
|
||||||
// multiple: false,
|
|
||||||
// });
|
|
||||||
// const state = ImmutableMap({ poll: initialPoll });
|
|
||||||
// const action = {
|
|
||||||
// type: actions.COMPOSE_POLL_OPTION_REMOVE,
|
|
||||||
// index: 1,
|
|
||||||
// };
|
|
||||||
// const updatedPoll = Object({
|
|
||||||
// options: [
|
|
||||||
// 'option 1',
|
|
||||||
// ],
|
|
||||||
// expires_in: 86400,
|
|
||||||
// multiple: false,
|
|
||||||
// });
|
|
||||||
// expect(reducer(state, action).toJS()).toMatchObject({
|
|
||||||
// poll: updatedPoll,
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('sets the post content-type', () => {
|
it('sets the post content-type', () => {
|
||||||
const action = {
|
const action = {
|
||||||
type: actions.COMPOSE_TYPE_CHANGE,
|
type: actions.COMPOSE_TYPE_CHANGE,
|
||||||
|
|
|
@ -93,6 +93,22 @@ describe('notifications reducer', () => {
|
||||||
expect(result.items.size).toEqual(1);
|
expect(result.items.size).toEqual(1);
|
||||||
expect(result.items.get('4').id).toEqual('4');
|
expect(result.items.get('4').id).toEqual('4');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('imports move notification', () => {
|
||||||
|
const action = {
|
||||||
|
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
||||||
|
notifications: [
|
||||||
|
require('soapbox/__fixtures__/pleroma-notification-move.json'),
|
||||||
|
],
|
||||||
|
next: null,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = reducer(undefined, action).items.get('406814');
|
||||||
|
|
||||||
|
expect(result.account).toEqual('AFmHQ18XZ7Lco68MW8');
|
||||||
|
expect(result.target).toEqual('A5c5LK7EJTFR0u26Pg');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('NOTIFICATIONS_EXPAND_REQUEST', () => {
|
describe('NOTIFICATIONS_EXPAND_REQUEST', () => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ const minifyAccount = account => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const fixAccount = (state, account) => {
|
const fixAccount = (state, account) => {
|
||||||
const normalized = minifyAccount(normalizeAccount(fromJS(account)));
|
const normalized = minifyAccount(normalizeAccount(account));
|
||||||
return state.set(account.id, normalized);
|
return state.set(account.id, normalized);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ const removePermission = (state, accountIds, permissionGroup) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildAccount = adminUser => normalizeAccount(fromJS({
|
const buildAccount = adminUser => normalizeAccount({
|
||||||
id: adminUser.get('id'),
|
id: adminUser.get('id'),
|
||||||
username: adminUser.get('nickname').split('@')[0],
|
username: adminUser.get('nickname').split('@')[0],
|
||||||
acct: adminUser.get('nickname'),
|
acct: adminUser.get('nickname'),
|
||||||
|
@ -142,7 +142,7 @@ const buildAccount = adminUser => normalizeAccount(fromJS({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
should_refetch: true,
|
should_refetch: true,
|
||||||
}));
|
});
|
||||||
|
|
||||||
const mergeAdminUser = (account, adminUser) => {
|
const mergeAdminUser = (account, adminUser) => {
|
||||||
return account.withMutations(account => {
|
return account.withMutations(account => {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
||||||
|
|
||||||
import { tagHistory } from 'soapbox/settings';
|
import { tagHistory } from 'soapbox/settings';
|
||||||
|
import { PLEROMA } from 'soapbox/utils/features';
|
||||||
|
import { hasIntegerMediaIds } from 'soapbox/utils/status';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
COMPOSE_MOUNT,
|
COMPOSE_MOUNT,
|
||||||
|
@ -431,13 +433,17 @@ export default function compose(state = initialState, action) {
|
||||||
map.set('to', action.explicitAddressing ? getExplicitMentions(action.status.get('account', 'id'), action.status) : undefined);
|
map.set('to', action.explicitAddressing ? getExplicitMentions(action.status.get('account', 'id'), action.status) : undefined);
|
||||||
map.set('in_reply_to', action.status.get('in_reply_to_id'));
|
map.set('in_reply_to', action.status.get('in_reply_to_id'));
|
||||||
map.set('privacy', action.status.get('visibility'));
|
map.set('privacy', action.status.get('visibility'));
|
||||||
// TODO: Actually fix this rather than just removing it
|
|
||||||
// map.set('media_attachments', action.status.get('media_attachments'));
|
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
map.set('caretPosition', null);
|
map.set('caretPosition', null);
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
map.set('content_type', action.content_type || 'text/plain');
|
map.set('content_type', action.content_type || 'text/plain');
|
||||||
|
|
||||||
|
if (action.v?.software === PLEROMA && hasIntegerMediaIds(action.status)) {
|
||||||
|
map.set('media_attachments', ImmutableList());
|
||||||
|
} else {
|
||||||
|
map.set('media_attachments', action.status.get('media_attachments'));
|
||||||
|
}
|
||||||
|
|
||||||
if (action.status.get('spoiler_text').length > 0) {
|
if (action.status.get('spoiler_text').length > 0) {
|
||||||
map.set('spoiler', true);
|
map.set('spoiler', true);
|
||||||
map.set('spoiler_text', action.status.get('spoiler_text'));
|
map.set('spoiler_text', action.status.get('spoiler_text'));
|
||||||
|
|
|
@ -116,7 +116,7 @@ const reducers = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build a default state from all reducers: it has the key and `undefined`
|
// Build a default state from all reducers: it has the key and `undefined`
|
||||||
const StateRecord = ImmutableRecord(
|
export const StateRecord = ImmutableRecord(
|
||||||
Object.keys(reducers).reduce((params, reducer) => {
|
Object.keys(reducers).reduce((params, reducer) => {
|
||||||
params[reducer] = undefined;
|
params[reducer] = undefined;
|
||||||
return params;
|
return params;
|
||||||
|
|
|
@ -56,6 +56,7 @@ const comparator = (a, b) => {
|
||||||
const minifyNotification = notification => {
|
const minifyNotification = notification => {
|
||||||
return notification.mergeWith((o, n) => n || o, {
|
return notification.mergeWith((o, n) => n || o, {
|
||||||
account: notification.getIn(['account', 'id']),
|
account: notification.getIn(['account', 'id']),
|
||||||
|
target: notification.getIn(['target', 'id']),
|
||||||
status: notification.getIn(['status', 'id']),
|
status: notification.getIn(['status', 'id']),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import { POLLS_IMPORT } from 'soapbox/actions/importer';
|
import { POLLS_IMPORT } from 'soapbox/actions/importer';
|
||||||
import { normalizeStatus } from 'soapbox/normalizers/status';
|
import { normalizeStatus } from 'soapbox/normalizers/status';
|
||||||
|
@ -6,7 +6,7 @@ import { normalizeStatus } from 'soapbox/normalizers/status';
|
||||||
// HOTFIX: Convert the poll into a fake status to normalize it...
|
// HOTFIX: Convert the poll into a fake status to normalize it...
|
||||||
// TODO: get rid of POLLS_IMPORT and use STATUS_IMPORT here.
|
// TODO: get rid of POLLS_IMPORT and use STATUS_IMPORT here.
|
||||||
const normalizePoll = poll => {
|
const normalizePoll = poll => {
|
||||||
const status = fromJS({ poll });
|
const status = { poll };
|
||||||
return normalizeStatus(status).poll;
|
return normalizeStatus(status).poll;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { isIntegerId } from '../numbers';
|
||||||
|
|
||||||
|
test('isIntegerId()', () => {
|
||||||
|
expect(isIntegerId('0')).toBe(true);
|
||||||
|
expect(isIntegerId('1')).toBe(true);
|
||||||
|
expect(isIntegerId('508107650')).toBe(true);
|
||||||
|
expect(isIntegerId('-1764036199')).toBe(true);
|
||||||
|
expect(isIntegerId('106801667066418367')).toBe(true);
|
||||||
|
expect(isIntegerId('9v5bmRalQvjOy0ECcC')).toBe(false);
|
||||||
|
expect(isIntegerId(null)).toBe(false);
|
||||||
|
expect(isIntegerId(undefined)).toBe(false);
|
||||||
|
expect(isIntegerId()).toBe(false);
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { fromJS } from 'immutable';
|
||||||
|
|
||||||
|
import { normalizeStatus } from 'soapbox/normalizers/status';
|
||||||
|
|
||||||
|
import { hasIntegerMediaIds } from '../status';
|
||||||
|
|
||||||
|
describe('hasIntegerMediaIds()', () => {
|
||||||
|
it('returns true for a Pleroma deleted status', () => {
|
||||||
|
const status = normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json')));
|
||||||
|
expect(hasIntegerMediaIds(status)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -10,14 +10,14 @@ const getDomainFromURL = (account: ImmutableMap<string, any>): string => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDomain = (account: ImmutableMap<string, any>): string => {
|
export const getDomain = (account: ImmutableMap<string, any>): string => {
|
||||||
const domain = account.get('acct').split('@')[1];
|
const domain = account.get('acct', '').split('@')[1];
|
||||||
return domain ? domain : getDomainFromURL(account);
|
return domain ? domain : getDomainFromURL(account);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const guessFqn = (account: ImmutableMap<string, any>): string => {
|
export const guessFqn = (account: ImmutableMap<string, any>): string => {
|
||||||
const [user, domain] = account.get('acct').split('@');
|
const [user, domain] = account.get('acct', '').split('@');
|
||||||
if (!domain) return [user, getDomainFromURL(account)].join('@');
|
if (!domain) return [user, getDomainFromURL(account)].join('@');
|
||||||
return account.get('acct');
|
return account.get('acct', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getBaseURL = (account: ImmutableMap<string, any>): string => {
|
export const getBaseURL = (account: ImmutableMap<string, any>): string => {
|
||||||
|
@ -31,7 +31,7 @@ export const getBaseURL = (account: ImmutableMap<string, any>): string => {
|
||||||
|
|
||||||
// user@domain even for local users
|
// user@domain even for local users
|
||||||
export const acctFull = (account: ImmutableMap<string, any>): string => (
|
export const acctFull = (account: ImmutableMap<string, any>): string => (
|
||||||
account.get('fqn') || guessFqn(account)
|
account.get('fqn') || guessFqn(account) || ''
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getAcct = (account: ImmutableMap<string, any>, displayFqn: boolean): string => (
|
export const getAcct = (account: ImmutableMap<string, any>, displayFqn: boolean): string => (
|
||||||
|
|
|
@ -12,3 +12,5 @@ export const shortNumberFormat = number => {
|
||||||
return <span><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</span>;
|
return <span><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</span>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isIntegerId = id => new RegExp(/^-?[0-9]+$/g).test(id);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { isIntegerId } from 'soapbox/utils/numbers';
|
||||||
|
|
||||||
export const getFirstExternalLink = status => {
|
export const getFirstExternalLink = status => {
|
||||||
try {
|
try {
|
||||||
// Pulled from Pleroma's media parser
|
// Pulled from Pleroma's media parser
|
||||||
|
@ -13,3 +15,8 @@ export const getFirstExternalLink = status => {
|
||||||
export const shouldHaveCard = status => {
|
export const shouldHaveCard = status => {
|
||||||
return Boolean(getFirstExternalLink(status));
|
return Boolean(getFirstExternalLink(status));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://gitlab.com/soapbox-pub/soapbox-fe/-/merge_requests/1087
|
||||||
|
export const hasIntegerMediaIds = status => {
|
||||||
|
return status.media_attachments.some(({ id }) => isIntegerId(id));
|
||||||
|
};
|
||||||
|
|
|
@ -487,6 +487,7 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
max-height: 19px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--highlight-text-color);
|
color: var(--highlight-text-color);
|
||||||
|
|
Przed Szerokość: | Wysokość: | Rozmiar: 116 KiB Po Szerokość: | Wysokość: | Rozmiar: 160 KiB |
|
@ -3003,9 +3003,9 @@ caniuse-api@^3.0.0:
|
||||||
lodash.uniq "^4.5.0"
|
lodash.uniq "^4.5.0"
|
||||||
|
|
||||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001252, caniuse-lite@^1.0.30001254:
|
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001252, caniuse-lite@^1.0.30001254:
|
||||||
version "1.0.30001257"
|
version "1.0.30001317"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz#150aaf649a48bee531104cfeda57f92ce587f6e5"
|
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz"
|
||||||
integrity sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==
|
integrity sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==
|
||||||
|
|
||||||
catharsis@^0.9.0:
|
catharsis@^0.9.0:
|
||||||
version "0.9.0"
|
version "0.9.0"
|
||||||
|
|