mirror of https://github.com/mastodon/mastodon
Add new onboarding flow to web UI (#24619)
parent
9d75b03ba4
commit
0461f83320
@ -0,0 +1,57 @@
|
||||
<svg width="293" height="264" viewBox="0 0 293 264" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M34.1 204.9C28.1 210.7 22.3 209.9 15.9 204.3C13.4 202.1 11.3 205.2 15.3 209.2C19.3 213.2 28.8 217.5 37.3 210" fill="#E09C5C"/>
|
||||
<path d="M34.1 204.9C28.1 210.7 22.3 209.9 15.9 204.3C13.4 202.1 11.3 205.2 15.3 209.2C19.3 213.2 28.8 217.5 37.3 210" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M197.2 1.90002H137.4C122.4 1.90002 110.1 14.2 110.1 29.2V42.1C110.1 48.4 112.3 54.2 115.9 58.9C109.2 72.6 94.5 75.8 94.5 75.8C113.4 78.1 119.1 72.3 125.2 66.6C128.9 68.4 133 69.5 137.4 69.5H197.2C212.2 69.5 224.5 57.2 224.5 42.2V29.3C224.6 14.2 212.3 1.90002 197.2 1.90002Z" fill="white" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M78.3 210.9C78.2 222.8 75.9 232 86.2 232.1C96.5 232.2 99.4 229.6 99.3 222C99.2 214.4 98.7 201 98.7 201" fill="#E09C5C"/>
|
||||
<path d="M78.3 210.9C78.2 222.8 75.9 232 86.2 232.1C96.5 232.2 99.4 229.6 99.3 222C99.2 214.4 98.7 201 98.7 201" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M63.8 104.2C43.6 104.2 28.7 111.8 28.7 140.2C28.7 168.6 28.7 186.5 28.7 194.5C28.7 202.5 33.1 216.3 50.5 216.3C67.9 216.3 66.1 216.3 74.6 216.3C83.1 216.3 90.9 213.5 97.1 206.9C103.3 200.3 106.3 193.6 106.3 181.4C106.3 169.2 106.3 134.8 106.3 134.8C106.3 134.8 126.7 134.3 135.7 121.5C144.6 108.7 142.6 93.3001 141.4 88.9001C141.4 88.9001 146.5 88.4 145.4 84.5C144.3 80.6 138.1 81.2001 135.3 83.4001C135.3 83.4001 133.7 81.6 128.3 81.7C122.9 81.8 124.6 87.9001 129 88.4001C129 88.4001 131.4 102.2 124.4 107.1C117.4 112 103 113.7 94.6 109.8C86.1 106.1 83.3 104.2 63.8 104.2Z" fill="#FBC16C" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M50.5 215.2C30.4 215.2 29.9 196.7 29.9 194.6V171.5C42.9 171.6 48.7 173 48.7 183.9C48.7 197.1 50.9 203.7 62.6 203.7H90.4C91.1 203.7 91.7 203.7 92.3 203.7C92.9 203.7 93.4 203.7 94 203.7C95.7 203.7 97.4 203.6 99 203C98.2 204 97.3 205.1 96.3 206.2C90.7 212.2 83.4 215.2 74.7 215.2H50.5Z" fill="#E09C5C"/>
|
||||
<path d="M56.8 110.5C47.2 107.6 42.1 105.6 45 97.2C47.9 88.8 62 90.6 69.7 94.5C69.7 94.5 73.7 92.1 76 91.2C78.3 90.3 82.6 89.9001 82.7 92.9001C82.7 92.9001 88.1 93.5001 87.1 97.8001C87.1 97.8001 93.5 101.5 79 108.5" fill="#FBC16C"/>
|
||||
<path d="M56.8 110.5C47.2 107.6 42.1 105.6 45 97.2C47.9 88.8 62 90.6 69.7 94.5C69.7 94.5 73.7 92.1 76 91.2C78.3 90.3 82.6 89.9001 82.7 92.9001C82.7 92.9001 88.1 93.5001 87.1 97.8001C87.1 97.8001 93.5 101.5 79 108.5" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M40.5 119.9C40.5 113.5 36.7 109.6 28.7 109.6C20.7 109.6 13.9 117.1 15.7 128.3C17.5 139.5 11.4 148.2 18.5 153.2C25.6 158.2 32.9 155.1 35.2 151.3C35.2 151.3 42.8 153.3 42.2 141.4" fill="#FBC16C"/>
|
||||
<path d="M40.5 119.9C40.5 113.5 36.7 109.6 28.7 109.6C20.7 109.6 13.9 117.1 15.7 128.3C17.5 139.5 11.4 148.2 18.5 153.2C25.6 158.2 32.9 155.1 35.2 151.3C35.2 151.3 42.8 153.3 42.2 141.4" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M69.3 134.2C63.6 134.2 60.5 138.6 61.8 144.4C63.1 150.1 66.8 154.4 73.2 154.6C79.6 154.7 85.7 152.5 87.6 143.2C89.5 133.9 86 133.8 83.2 133.8C80.4 133.8 69.3 134.2 69.3 134.2Z" fill="#544024" stroke="#3B3024" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M78.8 147.3C78.8 140.6 73.4 135.1 66.6 135.1C66 135.1 65.5001 135.2 64.9001 135.2C62.1001 136.8 60.8 140.2 61.7 144.3C63 150 66.7 154.3 73.1 154.5C74.2 154.5 75.3001 154.5 76.4001 154.3C78.0001 152.3 78.8 149.9 78.8 147.3Z" fill="#693131" stroke="#381916" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M83.1 140.9V133.7C80.1 133.7 69.3 134.1 69.3 134.1C64.8 134.1 61.9 136.9 61.5 140.9H83.1Z" fill="white" stroke="#7D7D65" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M48.2 149.1C54.2 154.9 62.5 154.9 66.3 151.7C70.1 148.5 72.1 140.3 69 139.5C65.9 138.7 66.6 144.2 63.8 145.8C61 147.4 57.8 147 54.8 145.1C51.9 143.2 48.9 141.9 47.4 143.7C46.1 145.7 46.8 147.7 48.2 149.1Z" fill="white" stroke="#7D7D65" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M251.4 179.1C245.7 185.3 237.4 185.7 233.4 182.7C229.4 179.7 227 171.7 230 170.7C233 169.7 232.7 175.2 235.5 176.7C238.3 178.2 241.6 177.6 244.4 175.6C247.2 173.6 250.1 172 251.7 173.9C253.3 175.8 252.8 177.7 251.4 179.1Z" stroke="black" stroke-width="0.5707" stroke-miterlimit="10"/>
|
||||
<path d="M36.3 153.7L15.8 153.8C15.8 153.8 15.1 150.4 12 150.9C8.90001 151.4 8.19998 153.2 8.09998 154.3C8.09998 154.3 1.30002 154.7 1.20002 161.5C1.10002 168.3 6.1 171 13.3 170.6C20.5 170.2 37.7 170.6 37.7 170.6" fill="#FBC16C"/>
|
||||
<path d="M36.3 153.7L15.8 153.8C15.8 153.8 15.1 150.4 12 150.9C8.90001 151.4 8.19998 153.2 8.09998 154.3C8.09998 154.3 1.30002 154.7 1.20002 161.5C1.10002 168.3 6.1 171 13.3 170.6C20.5 170.2 37.7 170.6 37.7 170.6" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M37.4 210.9C37.3 222.8 35 232 45.3 232.1C55.6 232.2 58.5 229.6 58.4 222C58.3 214.4 58.2 211.6 58.2 211.6" fill="#E09C5C"/>
|
||||
<path d="M37.4 210.9C37.3 222.8 35 232 45.3 232.1C55.6 232.2 58.5 229.6 58.4 222C58.3 214.4 58.2 211.6 58.2 211.6" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M54.7 138.2C53.8 138.2 53.1 137.5 53.1 136.6V125.7C53.1 124.8 53.8 124.1 54.7 124.1C55.6 124.1 56.3 124.8 56.3 125.7V136.6C56.3 137.5 55.6 138.2 54.7 138.2Z" fill="#402F19"/>
|
||||
<path d="M196.8 191.4C189.6 192.3 180.1 190.7 175.2 189.6C170.3 188.5 167.4 193.9 166.7 199.1C166 204.3 178.4 213.2 199.4 207.8" fill="#FBE6C6"/>
|
||||
<path d="M196.8 191.4C189.6 192.3 180.1 190.7 175.2 189.6C170.3 188.5 167.4 193.9 166.7 199.1C166 204.3 178.4 213.2 199.4 207.8" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M265 188.6C278.1 192.7 287.2 200.3 287 208.9C286.8 217.5 277.4 223.1 270.5 224.4C263.6 225.7 260.7 218.3 261.6 213.3C262.5 208.3 265 206.7 265 206.7" fill="#FBE6C6"/>
|
||||
<path d="M265 188.6C278.1 192.7 287.2 200.3 287 208.9C286.8 217.5 277.4 223.1 270.5 224.4C263.6 225.7 260.7 218.3 261.6 213.3C262.5 208.3 265 206.7 265 206.7" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M260 204C265 206.6 270.1 209.4 270.1 209.4Z" fill="#FBE6C6"/>
|
||||
<path d="M260 204C265 206.6 270.1 209.4 270.1 209.4" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M266 150.4C266 144 269.8 140.1 277.8 140.1C285.8 140.1 292.6 147.6 290.8 158.8C289 170 295.1 178.7 288 183.7C280.9 188.6 273.6 185.6 271.3 181.8C271.3 181.8 263.7 183.8 264.3 171.9" fill="#FBE6C6"/>
|
||||
<path d="M266 150.4C266 144 269.8 140.1 277.8 140.1C285.8 140.1 292.6 147.6 290.8 158.8C289 170 295.1 178.7 288 183.7C280.9 188.6 273.6 185.6 271.3 181.8C271.3 181.8 263.7 183.8 264.3 171.9" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M230.1 133.7C200.4 133.4 195.7 141.6 188.1 148.1C180.5 154.7 170.5 166.9 151.5 167.6C151.5 167.6 149 164.1 146.3 166.6C143.6 169.1 144.1 172.5 146 173.8C146 173.8 142.3 177.5 146.2 181.4C150.1 185.3 153.4 181.4 153.4 181.4C153.4 181.4 167.8 182.7 179.3 177.4C190.7 172 194.4 174.1 194.4 174.1C194.4 174.1 194.4 208.7 194.4 224.5C194.4 240.3 201.6 246.5 220.3 246.5C239 246.5 257.1 248.2 264.8 240.3C272.5 232.4 271.2 221.1 270.7 211.1C270.2 201.1 270.7 183 270.7 167.6C270.7 152.2 269.3 134 230.1 133.7Z" fill="#FBE6C6" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M242.3 244C242.3 248.8 241.8 250.6 242.1 254.1C240.5 255.2 239.9 257.1 240.4 258.7C241 260.7 244 262.7 250.3 262.6C260.7 262.7 263.5 260.1 263.4 252.5C263.3 249 263.2 244.3 263.1 240.3" fill="#DCCEB5"/>
|
||||
<path d="M242.3 244C242.3 248.8 241.8 250.6 242.1 254.1C240.5 255.2 239.9 257.1 240.4 258.7C241 260.7 244 262.7 250.3 262.6C260.7 262.7 263.5 260.1 263.4 252.5C263.3 249 263.2 244.3 263.1 240.3" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M236.5 245.4C233.9 245.4 231.4 245.4 228.6 245.3C225.8 245.3 223 245.2 220.2 245.2C202.2 245.2 195.5 239.5 195.5 224.3C195.5 221.8 199.8 219.5 204.5 219.5C206.8 219.5 211.1 220.1 213.7 223.8C217.5 229 222.6 230.9 230 230.9C234.5 230.9 244.5 231.1 247.9 228.5C252.4 225.2 253.7 220.6 261.2 218.9C264.2 218.2 266.8 217.7 269.8 218.5C270 227.8 268.5 235.7 263.9 239.3C258.4 243.7 249.4 245.4 236.5 245.4Z" fill="#DCCEB5"/>
|
||||
<path d="M243.9 141.2C250.9 141.1 254.6 136.8 254.1 132.6C253.5 128.5 250.6 122.7 237.5 123.4C231.7 123.7 228.8 127.5 226 127.5C223.2 127.4 217.7 119.4 212.9 119.9C208.1 120.4 207.8 123.8 208.6 125.4C208.6 125.4 204.3 126.7 206.7 132.3C209.1 137.9 214 139.8 218.8 140.4" fill="#FBE6C6"/>
|
||||
<path d="M243.9 141.2C250.9 141.1 254.6 136.8 254.1 132.6C253.5 128.5 250.6 122.7 237.5 123.4C231.7 123.7 228.8 127.5 226 127.5C223.2 127.4 217.7 119.4 212.9 119.9C208.1 120.4 207.8 123.8 208.6 125.4C208.6 125.4 204.3 126.7 206.7 132.3C209.1 137.9 214 139.8 218.8 140.4" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M203.7 241.5C203.7 246.3 203.2 250.7 203.5 254.2C201.9 255.3 201.3 257.2 201.8 258.8C202.4 260.8 205.4 262.8 211.7 262.7C222.1 262.8 224.9 260.2 224.8 252.6C224.8 249.7 224.7 248.9 224.6 245.4" fill="#DCCEB5"/>
|
||||
<path d="M203.7 241.5C203.7 246.3 203.2 250.7 203.5 254.2C201.9 255.3 201.3 257.2 201.8 258.8C202.4 260.8 205.4 262.8 211.7 262.7C222.1 262.8 224.9 260.2 224.8 252.6C224.8 249.7 224.7 248.9 224.6 245.4" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M194.8 22.9H140.2C138.3 22.9 136.8 21.4 136.8 19.5C136.8 17.6 138.3 16.1 140.2 16.1H194.8C196.7 16.1 198.2 17.6 198.2 19.5C198.2 21.4 196.7 22.9 194.8 22.9Z" fill="#4A4439"/>
|
||||
<path d="M194.8 39.8H140.2C138.3 39.8 136.8 38.3 136.8 36.4C136.8 34.5 138.3 33 140.2 33H194.8C196.7 33 198.2 34.5 198.2 36.4C198.2 38.2 196.7 39.8 194.8 39.8Z" fill="#4A4439"/>
|
||||
<path d="M194.8 56.6H140.2C138.3 56.6 136.8 55.1 136.8 53.2C136.8 51.3 138.3 49.8 140.2 49.8H194.8C196.7 49.8 198.2 51.3 198.2 53.2C198.2 55.1 196.7 56.6 194.8 56.6Z" fill="#4A4439"/>
|
||||
<path d="M205.9 150.4C205.9 144 209.7 140.1 217.7 140.1C225.7 140.1 232.5 147.6 230.7 158.8C228.9 170 235 178.7 227.9 183.7C220.8 188.6 213.5 185.6 211.2 181.8C211.2 181.8 203.6 183.8 204.2 171.9" fill="#FBE6C6"/>
|
||||
<path d="M205.9 150.4C205.9 144 209.7 140.1 217.7 140.1C225.7 140.1 232.5 147.6 230.7 158.8C228.9 170 235 178.7 227.9 183.7C220.8 188.6 213.5 185.6 211.2 181.8C211.2 181.8 203.6 183.8 204.2 171.9" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M104.3 166C115.9 165.4 125.9 161.4 131 156.7C136.8 151.4 139.9 146.2 134.7 141.6C129.6 137.1 124.6 141.5 124.6 141.5C124.6 141.5 122.6 138.4 119.6 140.7C116.6 143 118.8 145.2 118.8 145.2C118.8 145.2 115.2 150.2 103.9 150.7" fill="#FBC16C"/>
|
||||
<path d="M104.3 166C115.9 165.4 125.9 161.4 131 156.7C136.8 151.4 139.9 146.2 134.7 141.6C129.6 137.1 124.6 141.5 124.6 141.5C124.6 141.5 122.6 138.4 119.6 140.7C116.6 143 118.8 145.2 118.8 145.2C118.8 145.2 115.2 150.2 103.9 150.7" stroke="#946F3A" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M49 139L45.5 139.6C44.5 139.8 43.5001 139.1 43.4001 138.1C43.2001 137.1 43.9001 136.1 44.9001 136L48.4001 135.4C49.4001 135.2 50.4 135.9 50.5 136.9C50.7 137.9 50.1 138.9 49 139Z" fill="#E68A4C"/>
|
||||
<path d="M119.7 114.2C120.4 114 120.7 113.8 121.3 113.5" stroke="#FBD7A3" stroke-width="2.8533" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M114.5 115.6C115.4 115.4 114.9 115.6 115.7 115.4" stroke="#FBD7A3" stroke-width="2.8533" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M102.2 115.8C104.4 116.1 106.6 116.2 108.8 116.2" stroke="#FBD7A3" stroke-width="2.8533" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M88.1 111.8C90.5 112.9 93.1 113.8 95.8 114.5" stroke="#FBD7A3" stroke-width="2.8533" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M207.1 140.8C207.8 140.5 208.4 140.3 209 140" stroke="white" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M201.6 143.5C202.5 143 202.5 142.9 203.4 142.4" stroke="white" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M193.8 148.9C195.4 147.7 196.3 147 197.9 146" stroke="white" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M186.1 156.2C187.3 154.9 188.7 153.6 190.1 152.3" stroke="white" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M262.1 235.4C268.1 241.2 273.9 240.4 280.3 234.8C282.8 232.6 284.9 235.7 280.9 239.7C276.9 243.7 267.4 248 258.9 240.5" fill="#DCCEB5"/>
|
||||
<path d="M262.1 235.4C268.1 241.2 273.9 240.4 280.3 234.8C282.8 232.6 284.9 235.7 280.9 239.7C276.9 243.7 267.4 248 258.9 240.5" stroke="#668794" stroke-width="2.2827" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
|
||||
class VerifiedBadge extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
link: PropTypes.string.isRequired,
|
||||
verifiedAt: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { link } = this.props;
|
||||
|
||||
return (
|
||||
<span className='verified-badge'>
|
||||
<Icon id='check' className='verified-badge__mark' />
|
||||
<span dangerouslySetInnerHTML={{ __html: link }} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default VerifiedBadge;
|
@ -1,85 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeGetAccount } from 'mastodon/selectors';
|
||||
import Avatar from 'mastodon/components/avatar';
|
||||
import DisplayName from 'mastodon/components/display_name';
|
||||
import { Link } from 'react-router-dom';
|
||||
import IconButton from 'mastodon/components/icon_button';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import { followAccount, unfollowAccount } from 'mastodon/actions/accounts';
|
||||
|
||||
const messages = defineMessages({
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
account: getAccount(state, props.id),
|
||||
});
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const getFirstSentence = str => {
|
||||
const arr = str.split(/(([.?!]+\s)|[.。?!\n•])/);
|
||||
|
||||
return arr[0];
|
||||
};
|
||||
|
||||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
handleFollow = () => {
|
||||
const { account, dispatch } = this.props;
|
||||
|
||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||
dispatch(unfollowAccount(account.get('id')));
|
||||
} else {
|
||||
dispatch(followAccount(account.get('id')));
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { account, intl } = this.props;
|
||||
|
||||
let button;
|
||||
|
||||
if (account.getIn(['relationship', 'following'])) {
|
||||
button = <IconButton icon='check' title={intl.formatMessage(messages.unfollow)} active onClick={this.handleFollow} />;
|
||||
} else {
|
||||
button = <IconButton icon='plus' title={intl.formatMessage(messages.follow)} onClick={this.handleFollow} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account follow-recommendations-account'>
|
||||
<div className='account__wrapper'>
|
||||
<Link className='account__display-name account__display-name--with-note' title={account.get('acct')} to={`/@${account.get('acct')}`}>
|
||||
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
|
||||
|
||||
<DisplayName account={account} />
|
||||
|
||||
<div className='account__note'>{getFirstSentence(account.get('note_plain'))}</div>
|
||||
</Link>
|
||||
|
||||
<div className='account__relationship'>
|
||||
{button}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(makeMapStateToProps)(injectIntl(Account));
|
@ -1,117 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { connect } from 'react-redux';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { fetchSuggestions } from 'mastodon/actions/suggestions';
|
||||
import { changeSetting, saveSettings } from 'mastodon/actions/settings';
|
||||
import { requestBrowserPermission } from 'mastodon/actions/notifications';
|
||||
import { markAsPartial } from 'mastodon/actions/timelines';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
import Account from './components/account';
|
||||
import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
|
||||
import Button from 'mastodon/components/button';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
suggestions: state.getIn(['suggestions', 'items']),
|
||||
isLoading: state.getIn(['suggestions', 'isLoading']),
|
||||
});
|
||||
|
||||
class FollowRecommendations extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
const { dispatch, suggestions } = this.props;
|
||||
|
||||
// Don't re-fetch if we're e.g. navigating backwards to this page,
|
||||
// since we don't want followed accounts to disappear from the list
|
||||
|
||||
if (suggestions.size === 0) {
|
||||
dispatch(fetchSuggestions(true));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
// Force the home timeline to be reloaded when the user navigates
|
||||
// to it; if the user is new, it would've been empty before
|
||||
|
||||
dispatch(markAsPartial('home'));
|
||||
}
|
||||
|
||||
handleDone = () => {
|
||||
const { dispatch } = this.props;
|
||||
const { router } = this.context;
|
||||
|
||||
dispatch(requestBrowserPermission((permission) => {
|
||||
if (permission === 'granted') {
|
||||
dispatch(changeSetting(['notifications', 'alerts', 'follow'], true));
|
||||
dispatch(changeSetting(['notifications', 'alerts', 'favourite'], true));
|
||||
dispatch(changeSetting(['notifications', 'alerts', 'reblog'], true));
|
||||
dispatch(changeSetting(['notifications', 'alerts', 'mention'], true));
|
||||
dispatch(changeSetting(['notifications', 'alerts', 'poll'], true));
|
||||
dispatch(changeSetting(['notifications', 'alerts', 'status'], true));
|
||||
dispatch(saveSettings());
|
||||
}
|
||||
}));
|
||||
|
||||
router.history.push('/home');
|
||||
};
|
||||
|
||||
render () {
|
||||
const { suggestions, isLoading } = this.props;
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<div className='scrollable follow-recommendations-container'>
|
||||
<div className='column-title'>
|
||||
<svg viewBox='0 0 79 79' className='logo'>
|
||||
<use xlinkHref='#logo-symbol-icon' />
|
||||
</svg>
|
||||
|
||||
<h3><FormattedMessage id='follow_recommendations.heading' defaultMessage="Follow people you'd like to see posts from! Here are some suggestions." /></h3>
|
||||
<p><FormattedMessage id='follow_recommendations.lead' defaultMessage="Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!" /></p>
|
||||
</div>
|
||||
|
||||
{!isLoading && (
|
||||
<React.Fragment>
|
||||
<div className='column-list'>
|
||||
{suggestions.size > 0 ? suggestions.map(suggestion => (
|
||||
<Account key={suggestion.get('account')} id={suggestion.get('account')} />
|
||||
)) : (
|
||||
<div className='column-list__empty-message'>
|
||||
<FormattedMessage id='empty_column.follow_recommendations' defaultMessage='Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.' />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='column-actions'>
|
||||
<img src={imageGreeting} alt='' className='column-actions__background' />
|
||||
<Button onClick={this.handleDone}><FormattedMessage id='follow_recommendations.done' defaultMessage='Done' /></Button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Helmet>
|
||||
<meta name='robots' content='noindex' />
|
||||
</Helmet>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(FollowRecommendations);
|
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
const ArrowSmallRight = () => (
|
||||
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='currentColor'>
|
||||
<path fillRule='evenodd' d='M5 10a.75.75 0 01.75-.75h6.638L10.23 7.29a.75.75 0 111.04-1.08l3.5 3.25a.75.75 0 010 1.08l-3.5 3.25a.75.75 0 11-1.04-1.08l2.158-1.96H5.75A.75.75 0 015 10z' clipRule='evenodd' />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default ArrowSmallRight;
|
@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Check from 'mastodon/components/check';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const ProgressIndicator = ({ steps, completed }) => (
|
||||
<div className='onboarding__progress-indicator'>
|
||||
{(new Array(steps)).fill().map((_, i) => (
|
||||
<React.Fragment key={i}>
|
||||
{i > 0 && <div className={classNames('onboarding__progress-indicator__line', { active: completed > i })} />}
|
||||
|
||||
<div className={classNames('onboarding__progress-indicator__step', { active: completed > i })}>
|
||||
{completed > i && <Check />}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
ProgressIndicator.propTypes = {
|
||||
steps: PropTypes.number.isRequired,
|
||||
completed: PropTypes.number,
|
||||
};
|
||||
|
||||
export default ProgressIndicator;
|
@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
import Check from 'mastodon/components/check';
|
||||
|
||||
const Step = ({ label, description, icon, completed, onClick, href }) => {
|
||||
const content = (
|
||||
<>
|
||||
<div className='onboarding__steps__item__icon'>
|
||||
<Icon id={icon} />
|
||||
</div>
|
||||
|
||||
<div className='onboarding__steps__item__description'>
|
||||
<h6>{label}</h6>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
|
||||
{completed && (
|
||||
<div className='onboarding__steps__item__progress'>
|
||||
<Check />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<a href={href} onClick={onClick} target='_blank' rel='noopener' className='onboarding__steps__item'>
|
||||
{content}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button onClick={onClick} className='onboarding__steps__item'>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
Step.propTypes = {
|
||||
label: PropTypes.node,
|
||||
description: PropTypes.node,
|
||||
icon: PropTypes.string,
|
||||
completed: PropTypes.bool,
|
||||
href: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Step;
|
@ -0,0 +1,79 @@
|
||||
import React from 'react';
|
||||
import Column from 'mastodon/components/column';
|
||||
import ColumnBackButton from 'mastodon/components/column_back_button';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchSuggestions } from 'mastodon/actions/suggestions';
|
||||
import { markAsPartial } from 'mastodon/actions/timelines';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Account from 'mastodon/containers/account_container';
|
||||
import EmptyAccount from 'mastodon/components/account';
|
||||
import { FormattedMessage, FormattedHTMLMessage } from 'react-intl';
|
||||
import { makeGetAccount } from 'mastodon/selectors';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
import ProgressIndicator from './components/progress_indicator';
|
||||
|
||||
const mapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
return state => ({
|
||||
account: getAccount(state, me),
|
||||
suggestions: state.getIn(['suggestions', 'items']),
|
||||
isLoading: state.getIn(['suggestions', 'isLoading']),
|
||||
});
|
||||
};
|
||||
|
||||
class Follows extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
onBack: PropTypes.func,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
account: ImmutablePropTypes.map,
|
||||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(fetchSuggestions(true));
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(markAsPartial('home'));
|
||||
}
|
||||
|
||||
render () {
|
||||
const { onBack, isLoading, suggestions, account } = this.props;
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<ColumnBackButton onClick={onBack} />
|
||||
|
||||
<div className='scrollable privacy-policy'>
|
||||
<div className='column-title'>
|
||||
<h3><FormattedMessage id='onboarding.follows.title' defaultMessage='Popular on Mastodon' /></h3>
|
||||
<p><FormattedMessage id='onboarding.follows.lead' defaultMessage='You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!' /></p>
|
||||
</div>
|
||||
|
||||
<ProgressIndicator steps={7} completed={account.get('following_count') * 1} />
|
||||
|
||||
<div className='follow-recommendations'>
|
||||
{isLoading ? (new Array(8)).fill().map((_, i) => <EmptyAccount key={i} />) : suggestions.map(suggestion => (
|
||||
<Account id={suggestion.get('account')} key={suggestion.get('account')} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' values={{ strong: text => <strong>{text}</strong> }} /></p>
|
||||
|
||||
<div className='onboarding__footer'>
|
||||
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.actions.back' defaultMessage='Take me back' /></button>
|
||||
</div>
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Follows);
|
@ -0,0 +1,141 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { connect } from 'react-redux';
|
||||
import { focusCompose } from 'mastodon/actions/compose';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import illustration from 'mastodon/../images/elephant_ui_conversation.svg';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
import { makeGetAccount } from 'mastodon/selectors';
|
||||
import { closeOnboarding } from 'mastodon/actions/onboarding';
|
||||
import { fetchAccount } from 'mastodon/actions/accounts';
|
||||
import Follows from './follows';
|
||||
import Share from './share';
|
||||
import Step from './components/step';
|
||||
import ArrowSmallRight from './components/arrow_small_right';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
const mapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
return state => ({
|
||||
account: getAccount(state, me),
|
||||
});
|
||||
};
|
||||
|
||||
class Onboarding extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
state = {
|
||||
step: null,
|
||||
profileClicked: false,
|
||||
shareClicked: false,
|
||||
};
|
||||
|
||||
handleClose = () => {
|
||||
const { dispatch } = this.props;
|
||||
const { router } = this.context;
|
||||
|
||||
dispatch(closeOnboarding());
|
||||
router.history.push('/home');
|
||||
};
|
||||
|
||||
handleProfileClick = () => {
|
||||
this.setState({ profileClicked: true });
|
||||
};
|
||||
|
||||
handleFollowClick = () => {
|
||||
this.setState({ step: 'follows' });
|
||||
};
|
||||
|
||||
handleComposeClick = () => {
|
||||
const { dispatch } = this.props;
|
||||
const { router } = this.context;
|
||||
|
||||
dispatch(focusCompose(router.history));
|
||||
};
|
||||
|
||||
handleShareClick = () => {
|
||||
this.setState({ step: 'share', shareClicked: true });
|
||||
};
|
||||
|
||||
handleBackClick = () => {
|
||||
this.setState({ step: null });
|
||||
};
|
||||
|
||||
handleWindowFocus = debounce(() => {
|
||||
const { dispatch, account } = this.props;
|
||||
dispatch(fetchAccount(account.get('id')));
|
||||
}, 1000, { trailing: true });
|
||||
|
||||
componentDidMount () {
|
||||
window.addEventListener('focus', this.handleWindowFocus, false);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
window.removeEventListener('focus', this.handleWindowFocus);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { account } = this.props;
|
||||
const { step, shareClicked } = this.state;
|
||||
|
||||
switch(step) {
|
||||
case 'follows':
|
||||
return <Follows onBack={this.handleBackClick} />;
|
||||
case 'share':
|
||||
return <Share onBack={this.handleBackClick} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<div className='scrollable privacy-policy'>
|
||||
<div className='column-title'>
|
||||
<img src={illustration} alt='' className='onboarding__illustration' />
|
||||
<h3><FormattedMessage id='onboarding.start.title' defaultMessage="You've made it!" /></h3>
|
||||
<p><FormattedMessage id='onboarding.start.lead' defaultMessage="Your new Mastodon account is ready to go. Here's how you can make the most of it:" /></p>
|
||||
</div>
|
||||
|
||||
<div className='onboarding__steps'>
|
||||
<Step onClick={this.handleProfileClick} href='/settings/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} />
|
||||
<Step onClick={this.handleFollowClick} completed={(account.get('following_count') * 1) >= 7} icon='user-plus' label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Follow {count, plural, one {one person} other {# people}}' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage='You curate your own feed. Lets fill it with interesting people.' />} />
|
||||
<Step onClick={this.handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' />} />
|
||||
<Step onClick={this.handleShareClick} completed={shareClicked} icon='copy' label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} />
|
||||
</div>
|
||||
|
||||
<p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage='Want to skip right ahead?' /></p>
|
||||
|
||||
<div className='onboarding__links'>
|
||||
<Link to='/explore' className='onboarding__link'>
|
||||
<ArrowSmallRight />
|
||||
<FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage="See what's trending" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className='onboarding__footer'>
|
||||
<button className='link-button' onClick={this.handleClose}><FormattedMessage id='onboarding.actions.close' defaultMessage="Don't show this screen again" /></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Helmet>
|
||||
<meta name='robots' content='noindex' />
|
||||
</Helmet>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Onboarding);
|
@ -0,0 +1,132 @@
|
||||
import React from 'react';
|
||||
import Column from 'mastodon/components/column';
|
||||
import ColumnBackButton from 'mastodon/components/column_back_button';
|
||||
import PropTypes from 'prop-types';
|
||||
import { me, domain } from 'mastodon/initial_state';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
import ArrowSmallRight from './components/arrow_small_right';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const messages = defineMessages({
|
||||
shareableMessage: { id: 'onboarding.share.message', defaultMessage: 'I\'m {username} on Mastodon! Come follow me at {url}' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
account: state.getIn(['accounts', me]),
|
||||
});
|
||||
|
||||
class CopyPasteText extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
state = {
|
||||
copied: false,
|
||||
focused: false,
|
||||
};
|
||||
|
||||
setRef = c => {
|
||||
this.input = c;
|
||||
};
|
||||
|
||||
handleInputClick = () => {
|
||||
this.setState({ copied: false });
|
||||
this.input.focus();
|
||||
this.input.select();
|
||||
this.input.setSelectionRange(0, this.props.value.length);
|
||||
};
|
||||
|
||||
handleButtonClick = e => {
|
||||
e.stopPropagation();
|
||||
|
||||
const { value } = this.props;
|
||||
navigator.clipboard.writeText(value);
|
||||
this.input.blur();
|
||||
this.setState({ copied: true });
|
||||
this.timeout = setTimeout(() => this.setState({ copied: false }), 700);
|
||||
};
|
||||
|
||||
handleFocus = () => {
|
||||
this.setState({ focused: true });
|
||||
};
|
||||
|
||||
handleBlur = () => {
|
||||
this.setState({ focused: false });
|
||||
};
|
||||
|
||||
componentWillUnmount () {
|
||||
if (this.timeout) clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { value } = this.props;
|
||||
const { copied, focused } = this.state;
|
||||
|
||||
return (
|
||||
<div className={classNames('copy-paste-text', { copied, focused })} tabIndex='0' role='button' onClick={this.handleInputClick}>
|
||||
<textarea readOnly value={value} ref={this.setRef} onClick={this.handleInputClick} onFocus={this.handleFocus} onBlur={this.handleBlur} />
|
||||
|
||||
<button className='button' onClick={this.handleButtonClick}>
|
||||
<Icon id='copy' /> {copied ? <FormattedMessage id='copypaste.copied' defaultMessage='Copied' /> : <FormattedMessage id='copypaste.copy_to_clipboard' defaultMessage='Copy to clipboard' />}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Share extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
onBack: PropTypes.func,
|
||||
account: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { onBack, account, intl } = this.props;
|
||||
|
||||
const url = (new URL(`/@${account.get('username')}`, document.baseURI)).href;
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<ColumnBackButton onClick={onBack} />
|
||||
|
||||
<div className='scrollable privacy-policy'>
|
||||
<div className='column-title'>
|
||||
<h3><FormattedMessage id='onboarding.share.title' defaultMessage='Share your profile' /></h3>
|
||||
<p><FormattedMessage id='onboarding.share.lead' defaultMessage='Let people know how they can find you on Mastodon!' /></p>
|
||||
</div>
|
||||
|
||||
<CopyPasteText value={intl.formatMessage(messages.shareableMessage, { username: `@${account.get('username')}@${domain}`, url })} />
|
||||
|
||||
<p className='onboarding__lead'><FormattedMessage id='onboarding.share.next_steps' defaultMessage='Possible next steps:' /></p>
|
||||
|
||||
<div className='onboarding__links'>
|
||||
<Link to='/home' className='onboarding__link'>
|
||||
<ArrowSmallRight />
|
||||
<FormattedMessage id='onboarding.actions.go_to_home' defaultMessage='Go to your home feed' />
|
||||
</Link>
|
||||
|
||||
<Link to='/explore' className='onboarding__link'>
|
||||
<ArrowSmallRight />
|
||||
<FormattedMessage id='onboarding.actions.go_to_explore' defaultMessage="See what's trending" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className='onboarding__footer'>
|
||||
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.action.back' defaultMessage='Take me back' /></button>
|
||||
</div>
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(Share));
|
Loading…
Reference in New Issue