Compare commits

...

399 Commits

Author SHA1 Message Date
Shpuld Shpludson a39866308c Merge branch 'rc/2.2.2' into 'master'
prepare master for 2.2.2

See merge request pleroma/pleroma-fe!1315
2020-12-22 16:00:12 +00:00
Shpuld Shpludson 00cb8d9dce Merge branch 'master' into 'rc/2.2.2'
# Conflicts:
#   CHANGELOG.md
2020-12-22 15:51:18 +00:00
Shpuld Shpuldson 19bde84f6d mark unreleased as 2.2.2 in changelog 2020-12-22 17:49:13 +02:00
HJ 8d9bf3efc8 Merge branch 'plain-bg' into 'develop'
Solid color wallpaper support

See merge request pleroma/pleroma-fe!1314
2020-12-18 08:37:01 +00:00
Henry Jameson 93af7ee36a simplified code, review 2020-12-18 01:01:58 +02:00
Shpuld Shpludson 3359d4ddf6 Merge branch 'fix/timeline-bar-clickables-offset' into 'develop'
Fix #923 block clicks in blank area of timeline menu, fix 'up-to-date' align

Closes #923

See merge request pleroma/pleroma-fe!1300
2020-12-16 17:57:59 +00:00
Shpuld Shpludson a2f1ad93f5 Merge branch 'develop' into 'fix/timeline-bar-clickables-offset'
# Conflicts:
#   CHANGELOG.md
2020-12-16 17:49:11 +00:00
Shpuld Shpludson 10399c193a Merge branch 'feat/move-external-source-button-to-extra-buttons' into 'develop'
Move external source link to extra buttons, expand the expand button

See merge request pleroma/pleroma-fe!1303
2020-12-16 17:46:15 +00:00
Shpuld Shpludson 466fc84e82 Merge branch 'fix/fix-error-handling-in-profile-tab' into 'develop'
fix #1020 fix error handling in profile tab

Closes #1020

See merge request pleroma/pleroma-fe!1299
2020-12-16 16:51:03 +00:00
Henry Jameson 0cf06cb9ec Merge remote-tracking branch 'origin/develop' into plain-bg
* origin/develop:
  fix remote follow button style
  Disable horizontal textarea resize
  Add uk.json in messages.js
  Display upload limit on the Features panel
  use title html for poll options before vote
  fix recent mistakes in react button
2020-12-16 18:43:38 +02:00
Henry Jameson 81bac9f8ac change your log 2020-12-16 18:33:54 +02:00
Henry Jameson 5cb41c7175 theme ui 2020-12-16 18:28:10 +02:00
Henry Jameson c197756767 Basic no-wallpaper support 2020-12-16 18:25:07 +02:00
Shpuld Shpludson 34c65e3bcf Merge branch 'fix/remote-follow-button-style' into 'develop'
fix remote follow button style

See merge request pleroma/pleroma-fe!1313
2020-12-16 10:14:10 +00:00
Shpuld Shpuldson 6a469963b0 fix remote follow button style 2020-12-16 12:05:13 +02:00
Shpuld Shpludson e8cebb568b Merge branch 'develop' into 'fix/timeline-bar-clickables-offset'
# Conflicts:
#   CHANGELOG.md
2020-12-15 19:54:00 +00:00
Shpuld Shpludson 22546ea813 Merge branch 'develop' into 'feat/move-external-source-button-to-extra-buttons'
# Conflicts:
#   CHANGELOG.md
2020-12-15 19:50:59 +00:00
Shpuld Shpludson 5077549c73 Merge branch 'fix/no-emoji-in-poll-when-voting' into 'develop'
fix #1026 use title html for poll options before vote

Closes #1026

See merge request pleroma/pleroma-fe!1307
2020-12-15 19:49:32 +00:00
HJ 32ed09bae5 Merge branch 'prevent-textarea-resize-in-bio' into 'develop'
Disable horizontal textarea resize

Closes #741

See merge request pleroma/pleroma-fe!1312
2020-12-15 18:27:59 +00:00
eugenijm 6d9c79fb6d Disable horizontal textarea resize 2020-12-15 21:18:59 +03:00
HJ 39c4672175 Merge branch 'patch-1' into 'develop'
Add uk.json in messages.js

See merge request pleroma/pleroma-fe!1311
2020-12-14 20:03:45 +00:00
W. W 4451ac9f7c Add uk.json in messages.js 2020-12-14 19:52:07 +00:00
Shpuld Shpludson bdb994d450 Merge branch 'file-limit-info' into 'develop'
Display the upload limit on the Features panel

Closes #785

See merge request pleroma/pleroma-fe!1308
2020-12-12 14:39:46 +00:00
eugenijm 51e6f5e255 Display upload limit on the Features panel 2020-12-11 17:16:59 +03:00
Shpuld Shpuldson 415119cda9 use title html for poll options before vote 2020-12-07 00:11:21 +02:00
Shpuld Shpludson 99e12091b7 Merge branch 'fix/react-button-whoops' into 'develop'
fix #1025 recent mistakes in react button

Closes #1025

See merge request pleroma/pleroma-fe!1306
2020-12-06 21:54:31 +00:00
Shpuld Shpuldson 83bc74de0a fix recent mistakes in react button 2020-12-06 23:45:34 +02:00
HJ 674c302350 Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1298
2020-12-04 14:46:53 +00:00
ZEN 45e08f83aa Translated using Weblate (Ukrainian)
Currently translated at 94.6% (635 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-04 13:04:15 +00:00
rinpatch 3b037218b2 Translated using Weblate (Russian)
Currently translated at 76.9% (516 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-12-04 13:04:14 +00:00
Митець 506cf0902e Translated using Weblate (Ukrainian)
Currently translated at 94.1% (632 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-04 10:56:24 +00:00
Anonymous bfeb8ed14b Translated using Weblate (Ukrainian)
Currently translated at 93.8% (630 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-04 06:54:47 +00:00
ZEN ffd0bbbf16 Translated using Weblate (Ukrainian)
Currently translated at 93.8% (630 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-04 06:54:46 +00:00
rinpatch ff93f43468 Translated using Weblate (Russian)
Currently translated at 76.1% (511 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-12-03 22:18:56 +00:00
ZEN 56927c5a09 Translated using Weblate (Ukrainian)
Currently translated at 90.4% (607 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 21:38:54 +00:00
Митець c74ee1153d Translated using Weblate (Ukrainian)
Currently translated at 90.4% (607 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 21:38:53 +00:00
Митець ccf357c206 Translated using Weblate (Ukrainian)
Currently translated at 90.1% (605 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 20:24:08 +00:00
Митець 99c1fb0068 Translated using Weblate (Ukrainian)
Currently translated at 85.6% (575 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 18:02:32 +00:00
ZEN dc90db91fd Translated using Weblate (Ukrainian)
Currently translated at 85.6% (575 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 18:02:31 +00:00
ZEN 0c3f62642b Translated using Weblate (Ukrainian)
Currently translated at 85.5% (574 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 17:49:21 +00:00
Anonymous 6b7f82174c Translated using Weblate (Ukrainian)
Currently translated at 85.5% (574 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 17:49:01 +00:00
ZEN a8d3ce4671 Translated using Weblate (Ukrainian)
Currently translated at 85.5% (574 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 17:49:00 +00:00
Anonymous 95b911d7a0 Translated using Weblate (Ukrainian)
Currently translated at 84.6% (568 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 17:24:42 +00:00
Митець f1066c393f Translated using Weblate (Ukrainian)
Currently translated at 84.5% (567 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 17:01:57 +00:00
ZEN 215e3753e1 Translated using Weblate (Ukrainian)
Currently translated at 84.5% (567 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 17:01:56 +00:00
Митець 426441b51c Translated using Weblate (Ukrainian)
Currently translated at 81.3% (546 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:57:18 +00:00
Shpuld Shpludson fc4a17aa8c Merge branch 'develop' into 'fix/fix-error-handling-in-profile-tab'
# Conflicts:
#   CHANGELOG.md
2020-12-03 14:41:55 +00:00
Anonymous f30450be12 Translated using Weblate (Ukrainian)
Currently translated at 81.0% (544 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 17abcda2aa Translated using Weblate (Ukrainian)
Currently translated at 81.0% (544 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
rinpatch 0f8587463c Translated using Weblate (Russian)
Currently translated at 72.1% (484 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-12-03 14:30:36 +00:00
Anonymous 3d8af7256b Translated using Weblate (Ukrainian)
Currently translated at 80.7% (542 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Митець 60598f9bda Translated using Weblate (Ukrainian)
Currently translated at 80.7% (542 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 800964ea6b Translated using Weblate (Ukrainian)
Currently translated at 80.1% (538 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Митець 06d05b7b82 Translated using Weblate (Ukrainian)
Currently translated at 80.1% (538 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous ac45e410d3 Translated using Weblate (Ukrainian)
Currently translated at 80.0% (537 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Митець 4667137fff Translated using Weblate (Ukrainian)
Currently translated at 80.0% (537 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 037185a463 Translated using Weblate (Ukrainian)
Currently translated at 79.8% (536 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Митець 33e3ada7da Translated using Weblate (Ukrainian)
Currently translated at 79.8% (536 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 00c762474f Translated using Weblate (Ukrainian)
Currently translated at 79.8% (536 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Митець ee0748bff5 Translated using Weblate (Ukrainian)
Currently translated at 79.5% (534 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 2bbb01e751 Translated using Weblate (Ukrainian)
Currently translated at 79.5% (534 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 2ac23d8318 Translated using Weblate (Ukrainian)
Currently translated at 74.8% (502 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W 3dcbc2c294 Translated using Weblate (Ukrainian)
Currently translated at 74.8% (502 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W 0f2841a98a Translated using Weblate (Ukrainian)
Currently translated at 66.4% (446 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 8a260f4102 Translated using Weblate (Ukrainian)
Currently translated at 66.4% (446 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous c20c418e6d Translated using Weblate (Ukrainian)
Currently translated at 63.1% (424 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN fdcd4828ed Translated using Weblate (Ukrainian)
Currently translated at 63.1% (424 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 6923d5f983 Translated using Weblate (Ukrainian)
Currently translated at 63.0% (423 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 35773e2339 Translated using Weblate (Ukrainian)
Currently translated at 63.0% (423 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 291d9929f8 Translated using Weblate (Ukrainian)
Currently translated at 62.7% (421 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN a3f6476ae1 Translated using Weblate (Ukrainian)
Currently translated at 62.7% (421 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W be2e6f39aa Translated using Weblate (Ukrainian)
Currently translated at 62.5% (420 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 6111affc61 Translated using Weblate (Ukrainian)
Currently translated at 62.5% (420 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 4f54b0123a Translated using Weblate (Ukrainian)
Currently translated at 62.5% (420 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous a5b961ed31 Translated using Weblate (Ukrainian)
Currently translated at 61.9% (416 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN ed5c1c0a4c Translated using Weblate (Ukrainian)
Currently translated at 61.9% (416 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 061a500e0a Translated using Weblate (Ukrainian)
Currently translated at 61.6% (414 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 78b052b6fc Translated using Weblate (Ukrainian)
Currently translated at 61.6% (414 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous 66ad886e33 Translated using Weblate (Ukrainian)
Currently translated at 59.7% (401 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN c823800a67 Translated using Weblate (Ukrainian)
Currently translated at 59.7% (401 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
Anonymous d9b4c87dda Translated using Weblate (Ukrainian)
Currently translated at 58.8% (395 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 60121775f2 Translated using Weblate (Ukrainian)
Currently translated at 58.8% (395 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
rinpatch 8fbf91f3e8 Translated using Weblate (Russian)
Currently translated at 68.5% (460 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-12-03 14:30:36 +00:00
rinpatch e713e17e9d Translated using Weblate (Russian)
Currently translated at 68.5% (460 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-12-03 14:30:36 +00:00
ZEN a4a0695c57 Translated using Weblate (Ukrainian)
Currently translated at 58.4% (392 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 9657a5a098 Translated using Weblate (Ukrainian)
Currently translated at 58.4% (392 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W 55b0b81252 Translated using Weblate (Ukrainian)
Currently translated at 51.5% (346 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN ae3ded9185 Translated using Weblate (Ukrainian)
Currently translated at 51.5% (346 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W 8140501e37 Translated using Weblate (Ukrainian)
Currently translated at 45.0% (302 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 71b0ef8f1b Translated using Weblate (Ukrainian)
Currently translated at 39.3% (264 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 0dc0c816ea Translated using Weblate (Ukrainian)
Currently translated at 35.4% (238 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 2478b5a306 Translated using Weblate (Ukrainian)
Currently translated at 34.5% (232 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W a464135cbd Translated using Weblate (Ukrainian)
Currently translated at 30.2% (203 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 3f452a5462 Translated using Weblate (Ukrainian)
Currently translated at 30.2% (203 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
rinpatch 431e9369c2 Translated using Weblate (Russian)
Currently translated at 60.8% (408 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-12-03 14:30:36 +00:00
W.W c789db82df Translated using Weblate (Ukrainian)
Currently translated at 24.4% (164 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 171462b246 Translated using Weblate (Ukrainian)
Currently translated at 24.2% (163 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 0cccb39710 Translated using Weblate (Ukrainian)
Currently translated at 23.9% (161 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN a7b2c5cdad Translated using Weblate (Ukrainian)
Currently translated at 23.3% (157 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W a6c93c5eab Translated using Weblate (Ukrainian)
Currently translated at 23.3% (157 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN badbd27e27 Translated using Weblate (Ukrainian)
Currently translated at 21.4% (144 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
ZEN 1116b2cd32 Translated using Weblate (Ukrainian)
Currently translated at 21.3% (143 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
W.W 9cb83648e3 Translated using Weblate (Ukrainian)
Currently translated at 21.3% (143 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-12-03 14:30:36 +00:00
lain 42c747a342 Merge branch 'fix/own-chat-messages-disappearing' into 'develop'
fix #1021: own chat messages disappearing

Closes #1021

See merge request pleroma/pleroma-fe!1304
2020-12-03 14:30:25 +00:00
Shpuld Shpuldson 2427757184 fix your own chat messages disappearing 2020-12-03 16:09:40 +02:00
Shpuld Shpuldson 5d95376bef update changelog 2020-12-03 12:03:23 +02:00
Shpuld Shpuldson 46320090e3 move external source button to extra buttons, make expand button easier to click and highlight on hover 2020-12-03 11:57:17 +02:00
Shpuld Shpuldson fa01030641 make click blocking actually work 2020-12-03 10:07:42 +02:00
Shpuld Shpuldson f4b18df644 block clicks in blank area of timeline menu, fix 'up-to-date' align 2020-12-02 16:07:31 +02:00
Shpuld Shpuldson 15ea735006 remove vertical align, update changelog 2020-12-02 12:58:13 +02:00
Shpuld Shpuldson 0d53af786b fix the close button on global notices 2020-12-02 12:55:14 +02:00
Shpuld Shpuldson b537032e6d Merge branch 'develop' into fix/fix-error-handling-in-profile-tab 2020-12-02 12:48:21 +02:00
Shpuld Shpuldson 4dde9c4d52 refactor error handling in profile tab 2020-12-02 12:46:31 +02:00
Shpuld Shpludson fdfb8810c1 Merge branch 'fix/use-semantically-correct-buttons' into 'develop'
Fix #1001 Accessibility: Use semantically correct buttons (almost) everywhere

Closes #1001

See merge request pleroma/pleroma-fe!1293
2020-12-01 11:02:46 +00:00
Shpuld Shpludson c655699935 Merge branch 'feat/react-picker-titles-support-filter-by-emoji' into 'develop'
Fix #1014 add titles in react picker, support filtering by emoji itself

Closes #1014

See merge request pleroma/pleroma-fe!1294
2020-12-01 11:01:29 +00:00
Shpuld Shpludson 10e2648142 Merge branch 'develop' into 'feat/react-picker-titles-support-filter-by-emoji'
# Conflicts:
#   CHANGELOG.md
2020-12-01 10:54:29 +00:00
Shpuld Shpludson 655d985a82 Merge branch 'develop' into 'fix/use-semantically-correct-buttons'
# Conflicts:
#   CHANGELOG.md
2020-12-01 10:47:10 +00:00
Shpuld Shpludson 133294dc2a Merge branch 'feat/add-missing-emoji-and-script' into 'develop'
Update emoji.json, add script that merges new emoji from another source

See merge request pleroma/pleroma-fe!1295
2020-12-01 10:40:33 +00:00
HJ 397622078f Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1297
2020-11-30 20:16:03 +00:00
W.W f1b36f3b1a Translated using Weblate (Ukrainian)
Currently translated at 10.5% (71 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-11-30 19:41:30 +00:00
HJ c4b098be0e Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1296
2020-11-30 19:37:42 +00:00
Anonymous cf3ad0632a Translated using Weblate (Russian)
Currently translated at 55.8% (375 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-11-30 19:28:53 +00:00
rinpatch 848b77acaa Translated using Weblate (Russian)
Currently translated at 55.8% (375 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-11-30 19:28:52 +00:00
ZEN bd1564765c Translated using Weblate (Ukrainian)
Currently translated at 8.3% (56 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-11-30 19:28:00 +00:00
W.W c17a0523d5 Translated using Weblate (Ukrainian)
Currently translated at 8.3% (56 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/uk/
2020-11-30 19:27:58 +00:00
HJ e0d08490a4 Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1269
2020-11-30 19:04:15 +00:00
W.W 2506b2629a Added translation using Weblate (Ukrainian) 2020-11-30 17:57:16 +00:00
Shpuld Shpuldson e98e285f50 changelog 2020-11-30 14:46:37 +02:00
Shpuld Shpuldson 767db567ad update emoji.json, add script that merges new emoji from another source 2020-11-30 14:43:39 +02:00
Shpuld Shpuldson a4e76067db changelog 2020-11-28 15:36:48 +02:00
Shpuld Shpuldson 8f118c01a4 add titles in react picker, support filtering by emoji itself 2020-11-28 15:27:58 +02:00
Ben Is 00b93c0947 Translated using Weblate (Italian)
Currently translated at 100.0% (671 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/it/
2020-11-27 13:57:44 +00:00
tarteka 95ad9efff3 Translated using Weblate (Spanish)
Currently translated at 100.0% (671 of 671 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/es/
2020-11-27 13:57:44 +00:00
Kana aec6dc7858 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-11-27 13:57:44 +00:00
Kana 6fbd6ee9ea Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-11-27 13:57:44 +00:00
Guy Sheffer 83319904c7 Translated using Weblate (Hebrew)
Currently translated at 48.1% (322 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/he/
2020-11-27 13:57:44 +00:00
Tirifto a68899b4a9 Translated using Weblate (Esperanto)
Currently translated at 100.0% (669 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eo/
2020-11-27 13:57:44 +00:00
tarteka 4ac2bc1c44 Translated using Weblate (Spanish)
Currently translated at 100.0% (669 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/es/
2020-11-27 13:57:44 +00:00
Shpuld Shpludson 32f77cfbd7 Merge branch 'fix/make-autocomplete-wait-for-request-to-finish' into 'develop'
Fix #1011 Make autocomplete wait for user search to finish before suggesting

Closes #1011

See merge request pleroma/pleroma-fe!1289
2020-11-27 13:57:36 +00:00
Shpuld Shpuldson e6e3b752d6 review fixes 2020-11-27 15:51:58 +02:00
Shpuld Shpuldson 276ef31145 fix alternative icons having wrong offsets 2020-11-26 23:01:16 +02:00
Shpuld Shpuldson 5dfcf2acac updated changelog 2020-11-26 18:40:39 +02:00
Shpuld Shpuldson 1172feaa72 Add changelog mention for changed button sizes 2020-11-26 18:38:36 +02:00
Shpuld Shpuldson aea172a6f7 forgot to save a file 2020-11-26 18:25:21 +02:00
Shpuld Shpuldson bee77ffdb2 fix retweet event handler, fix text being selectable for status action counters 2020-11-26 18:23:53 +02:00
Shpuld Shpuldson ebe3b38a90 fix nav bar button active style 2020-11-26 17:05:38 +02:00
Shpuld Shpuldson 2137d6395a fix wrong button style, add new option for popover to better deal with different layouts 2020-11-25 18:33:08 +02:00
Shpuld Shpuldson e771fd8f13 fix missing button style 2020-11-25 10:36:14 +02:00
Shpuld Shpuldson 1d178b7341 fix too big hide button, fix weird 28px hack 2020-11-24 21:35:14 +02:00
Shpuld Shpuldson 04af772c1e address missing button style, fix remaining warning 2020-11-24 17:47:37 +02:00
Shpuld Shpuldson a6e495e413 fix warnings 2020-11-24 16:10:03 +02:00
Shpuld Shpuldson 38c32c7f7a renames and removals of cursor: pointer 2020-11-24 15:22:01 +02:00
Shpuld Shpuldson 8b775f94a9 more fixes, add fullwidth 2020-11-24 14:52:01 +02:00
Shpuld Shpuldson 7b99d98c55 Replace all use of <a> + href='#' with proper buttons 2020-11-24 12:32:42 +02:00
HJ 14ce0c1c07 Merge branch 'fix/RED-LINE' into 'develop'
fix #1010 Add back conversation red line

Closes #1010

See merge request pleroma/pleroma-fe!1292
2020-11-21 12:10:39 +00:00
Shpuld Shpuldson 11f7b818b4 try another approach 2020-11-20 16:20:08 +02:00
Shpuld Shpuldson f5186e1a33 add back red line 2020-11-20 16:02:47 +02:00
Shpuld Shpludson 838cbd8715 Merge branch 'nsfw-link-preview' into 'develop'
Click-to-reveal cover for link previews in NSFW posts

Closes #973

See merge request pleroma/pleroma-fe!1287
2020-11-20 07:54:26 +00:00
HJ 4922a8ded9 Merge branch 'features/video-preload-metadata' into 'develop'
video_attachment: Only preload metadata

See merge request pleroma/pleroma-fe!1291
2020-11-19 18:13:58 +00:00
eugenijm 45180d4069 Added the NSFW alert to the link preview. 2020-11-19 20:08:56 +03:00
Haelwenn (lanodan) Monnier 0089d1e8d1 video_attachment: Only preload metadata
This hints browsers that only the metadata and maybe the first few frames are
needed. Which avoids downloading the entire video, which isn't really needed
in our case.
2020-11-19 18:01:21 +01:00
HJ 9684bf6e94 Merge branch 'fix/missing-play-circle-icon' into 'develop'
add missing play-circle icon

See merge request pleroma/pleroma-fe!1290
2020-11-19 12:51:40 +00:00
Shpuld Shpuldson 4001c075d4 add missing play-circle icon 2020-11-19 14:19:03 +02:00
Shpuld Shpuldson b1ab09b348 fix merge conflict 2020-11-19 12:38:35 +02:00
Shpuld Shpuldson 419df9d446 update some documentation 2020-11-19 12:35:21 +02:00
Shpuld Shpuldson 1cd222d85c changelog mention 2020-11-19 11:42:30 +02:00
Shpuld Shpuldson 1495db084a fix keyboard highlight 2020-11-19 11:37:06 +02:00
Shpuld Shpuldson 0f386ccbc7 use users state + fetching with delay 2020-11-18 18:43:24 +02:00
Shpuld Shpludson d770bab1b0 Merge branch 'fix/timeline-error-handling-fixes' into 'develop'
Various timeline fixes

See merge request pleroma/pleroma-fe!1283
2020-11-18 11:49:54 +00:00
HJ cd784396e7 Merge branch 'fix-pinned' into 'develop'
Fix pinned statuses and perhaps some other stuff

See merge request pleroma/pleroma-fe!1288
2020-11-17 18:41:43 +00:00
Henry Jameson b66b4124f4 Merge remote-tracking branch 'origin/develop' into fix-pinned
* origin/develop:
  change favicon dimensions for high res, add handling when favicon isn't available
  remove the favicon changes
  make badge just a ball, make it use theming
  add favicon badge for unread notifs
2020-11-17 20:32:56 +02:00
Henry Jameson 5c47aeeccf changelong 2020-11-17 20:32:39 +02:00
Shpuld Shpludson d905a6cb70 Merge branch 'feat/favicon-badge' into 'develop'
Add favicon badge for unread notifs

See merge request pleroma/pleroma-fe!1273
2020-11-17 18:25:05 +00:00
Shpuld Shpuldson dd3c8631bf store failed experiment 2020-11-17 17:46:26 +02:00
Henry Jameson 49f7c84e3f Fix pinned statuses and perhaps some other stuff 2020-11-17 15:25:38 +02:00
Shpuld Shpludson fa2884a805 Merge branch 'chore/update-changelog-to-match-release' into 'develop'
Update develop changelog to contain 2.2.1 release

See merge request pleroma/pleroma-fe!1286
2020-11-11 21:13:09 +00:00
Shpuld Shpuldson 6cdf347ed1 update changelog 2020-11-11 23:04:07 +02:00
Shpuld Shpludson fb5d3d3292 Merge branch 'develop' into 'fix/timeline-error-handling-fixes'
# Conflicts:
#   CHANGELOG.md
2020-11-11 20:58:47 +00:00
HJ 3e1c828ba9 Merge branch 'fix/html-title-name' into 'develop'
Remove title from index.html, title is now from server generated meta

See merge request pleroma/pleroma-fe!1285
2020-11-11 20:51:12 +00:00
Shpuld Shpuldson a7567ce6d0 set patch date to correct 2020-11-11 22:32:44 +02:00
Sean King 476154d0ee Remove title from index.html, title is now from server generated meta 2020-11-11 11:57:42 -07:00
HJ 563377b59c Merge branch 'fix/field-name-emoji-parsing' into 'develop'
fix #999  emoji not working in profile field names

Closes #999

See merge request pleroma/pleroma-fe!1284
2020-11-11 10:15:29 +00:00
Shpuld Shpuldson b536c6e3c5 changelog mention 2020-11-11 10:42:13 +02:00
Shpuld Shpuldson 41dbdc2b28 fix emoji not working in profile field names 2020-11-11 10:40:26 +02:00
Shpuld Shpuldson 1d2ba946b6 make notifications also use the popup errors, remove all error from status/notif state 2020-11-10 14:28:10 +02:00
Shpuld Shpuldson d150dae5d1 fixes to timeline error handling 2020-11-10 12:52:54 +02:00
Shpuld Shpludson e6ca489d30 Merge branch 'fix/fix-1px-scroll-on-input' into 'develop'
Fix that 1px scroll on input for real this time maybe

See merge request pleroma/pleroma-fe!1282
2020-11-09 13:18:35 +00:00
Shpuld Shpuldson c1c207788a change method of fix to rounding 2020-11-09 15:02:48 +02:00
Shpuld Shpuldson fb80dbbc77 changelog 2020-11-09 14:47:42 +02:00
Shpuld Shpuldson 553155fc49 prevent call to scroll if the value doesn't change because firefox is stupid 2020-11-09 14:42:16 +02:00
Shpuld Shpuldson 8e87e3d88b Update MASTER with develop for 2.2.1 2020-11-09 11:13:49 +02:00
Shpuld Shpludson 3963f240d5 Merge branch 'patch-1' into 'develop'
Update CHANGELOG.md

See merge request pleroma/pleroma-fe!1281
2020-11-09 09:08:41 +00:00
Shpuld Shpludson 9ff48b88bf Update CHANGELOG.md 2020-11-09 09:01:16 +00:00
Shpuld Shpludson 3220e72eb9 Merge branch 'patch-1' into 'develop'
Update CHANGELOG.md to match master

See merge request pleroma/pleroma-fe!1279
2020-11-09 08:58:17 +00:00
HJ def1bd0676 Merge branch 'fix/react-menu-overflow-fix' into 'develop'
Fix #994 react popover overflowing

Closes #994

See merge request pleroma/pleroma-fe!1280
2020-11-09 08:40:59 +00:00
Shpuld Shpuldson 9f96b592d4 wrap react button icon to a span to fix popover overflow 2020-11-09 09:40:20 +02:00
Shpuld Shpludson 82f17961d1 Update CHANGELOG.md to match master 2020-11-06 17:36:43 +00:00
Shpuld Shpuldson 6aa276374f update changelog for 2.2.0 2020-11-06 19:35:01 +02:00
Shpuld Shpludson 23232e1c8f Merge branch 'develop' into 'master'
Merge develop into master for 2.2.0

See merge request pleroma/pleroma-fe!1278
2020-11-06 17:27:25 +00:00
Shpuld Shpuldson 56c1d65384 Merge branch 'develop' into feat/favicon-badge 2020-11-06 14:57:50 +02:00
Shpuld Shpludson 60983ae42b Merge branch 'chat-fix-for-vertical-screen' into 'develop'
Chat scroll fix for vertical screen

Closes #997

See merge request pleroma/pleroma-fe!1277
2020-11-06 12:55:57 +00:00
eugenijm 15ea9d8c91 Fix the chat scroll behavior for vertical screens.
Fetch the messages until the scrollbar becomes visible, so that the user
always has the ability to scroll up and load new messages.
2020-11-06 11:11:19 +03:00
Shpuld Shpludson dbeecd18ac Merge branch 'advanced-misclick-guard' into 'develop'
Instead of blocking all interaction, only block interaction in places that matter

See merge request pleroma/pleroma-fe!1276
2020-11-04 06:04:19 +00:00
Shpuld Shpludson b485d21ba9 Merge branch 'fix-chat-badge' into 'develop'
Few more minor fixes

See merge request pleroma/pleroma-fe!1275
2020-11-03 17:09:10 +00:00
Henry Jameson 4e4b258c54 fix mobile badge alignment 2020-11-03 18:45:23 +02:00
Henry Jameson d126eddfca change approach to disable all, enable some 2020-11-03 18:39:46 +02:00
Shpuld Shpludson 22bc0c0840 Merge branch 'svg-logo' into 'develop'
change logo to svg

See merge request pleroma/pleroma-fe!1274
2020-11-03 11:05:33 +00:00
Shpuld Shpuldson 0206b2bcc5 change favicon dimensions for high res, add handling when favicon isn't available 2020-11-03 11:55:29 +02:00
Henry Jameson 979efb301a fix mobile navbar hitboxes 2020-11-03 11:37:11 +02:00
Shpuld Shpuldson 19fd1d4a1e remove the favicon changes 2020-11-03 10:29:03 +02:00
Henry Jameson e351665bb3 Instead of blocking all interaction, only block interaction in places
that matter
2020-11-02 23:43:32 +02:00
Henry Jameson b6a8ca44ef added comment 2020-11-02 21:08:22 +02:00
Henry Jameson bdf2f36f11 fix chat heading not being aligned and using wrong styles 2020-11-02 21:03:55 +02:00
Henry Jameson 08e6e66642 fix chat badge and unify styles across all badges including follow
request count.
2020-11-02 20:51:38 +02:00
Henry Jameson 3db218dec1 change logo to svg 2020-11-02 19:37:01 +02:00
Shpuld Shpuldson 1fa046126e make badge just a ball, make it use theming 2020-11-02 16:45:15 +02:00
Shpuld Shpuldson 350eb489c2 add favicon badge for unread notifs 2020-11-02 15:46:49 +02:00
HJ f0a66448ee Merge branch 'chchchchangechangelog' into 'develop'
Update CHANGELOG.md

See merge request pleroma/pleroma-fe!1272
2020-11-02 09:43:44 +00:00
HJ a1e7852c10 Update CHANGELOG.md 2020-11-02 09:36:23 +00:00
Shpuld Shpludson 5ab1b0ab0e Merge branch 'update-changelog' into 'develop'
update changelog for optimistic chat posting

See merge request pleroma/pleroma-fe!1271
2020-11-02 08:51:40 +00:00
Shpuld Shpuldson 279205ade5 update changelog for optimistic chat posting 2020-11-02 10:42:38 +02:00
HJ bcb6ee328f Merge branch 'fix/use-ids-for-chat-last-seen' into 'develop'
Fix: Use ids for chat last seen instead of timestamp

See merge request pleroma/pleroma-fe!1270
2020-11-02 08:35:22 +00:00
Shpuld Shpuldson 757706425a fix test 2020-11-02 09:42:09 +02:00
Shpuld Shpuldson 5e8db7ed93 move from using timestamps to ids when tracking last seen in chats 2020-11-02 09:15:13 +02:00
Shpuld Shpludson 5254fdba75 Merge branch 'optimistic-chat-posting' into 'develop'
Optimistic / nonblocking message posting for chats

See merge request pleroma/pleroma-fe!1228
2020-11-02 05:36:42 +00:00
HJ 590f8e1754 Merge branch 'various-css-fixes' into 'develop'
Various css fixes

Closes #992

See merge request pleroma/pleroma-fe!1267
2020-11-01 20:50:02 +00:00
Eugenij 78e5a63922 Apply 1 suggestion(s) to 1 file(s) 2020-11-01 23:36:58 +03:00
eugenijm e798e9a417 Optimistic message sending for chat 2020-11-01 23:36:58 +03:00
Shpuld Shpludson 148789767a Merge branch 'fix/chat-misc-fixes' into 'develop'
Misc Chat fixes

See merge request pleroma/pleroma-fe!1265
2020-11-01 17:50:43 +00:00
Shpuld Shpludson 40ce3a9bd8 Merge branch 'fix/block-misclicks-when-timeline-shifts' into 'develop'
block clicks for a second on timeline when timeline moves

See merge request pleroma/pleroma-fe!1266
2020-11-01 17:44:16 +00:00
HJ 8ae77e14d0 Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1264
2020-11-01 15:18:08 +00:00
Henry Jameson 64da9a8e69 fix build warnings 2020-11-01 16:47:17 +02:00
Henry Jameson 8b1213ea1e lint 2020-11-01 16:44:57 +02:00
Henry Jameson 994b49ddfe Merge remote-tracking branch 'origin/develop' into various-css-fixes
* origin/develop:
  remove 'md' size that doesn't exist
2020-11-01 16:44:15 +02:00
Henry Jameson 02bb015c4f fix #992 2020-11-01 16:40:23 +02:00
Tirifto 4cf4de8d28 Translated using Weblate (Esperanto)
Currently translated at 100.0% (669 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eo/
2020-11-01 14:33:22 +00:00
Tirifto 5095143c47 Translated using Weblate (Esperanto)
Currently translated at 99.1% (663 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eo/
2020-11-01 14:33:22 +00:00
Tirifto 1c7ec321d9 Translated using Weblate (Esperanto)
Currently translated at 98.9% (662 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eo/
2020-11-01 14:33:22 +00:00
Kana 599256a6be Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-11-01 14:33:22 +00:00
Kana 66d07b6d08 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-11-01 14:33:22 +00:00
Kana ea300a7a1c Translated using Weblate (Chinese (Traditional))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hant/
2020-11-01 14:33:22 +00:00
Kana 891593169f Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-11-01 14:33:22 +00:00
Tirifto 6040c1ebfc Translated using Weblate (Esperanto)
Currently translated at 98.2% (657 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eo/
2020-11-01 14:33:22 +00:00
Tirifto 9d1d695627 Translated using Weblate (Esperanto)
Currently translated at 97.7% (654 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eo/
2020-11-01 14:33:22 +00:00
HJ 918563d15c Merge branch 'fix/extra-buttons-icon-errors' into 'develop'
Fix errors: remove 'md' size that doesn't exist

See merge request pleroma/pleroma-fe!1268
2020-11-01 14:33:14 +00:00
Shpuld Shpuldson 8c5586dda4 remove 'md' size that doesn't exist 2020-11-01 11:53:20 +02:00
Henry Jameson fb00f8459c fix chat count 2020-10-31 13:59:58 +02:00
Henry Jameson 0653f18994 fix play-on-hover gifs issues 2020-10-29 22:54:28 +02:00
Henry Jameson 4e1f2aeabc fix preview spinner 2020-10-29 22:54:28 +02:00
Henry Jameson 633349ddff Refactor desktop navbar into a component, change layout to grid for
better compatibility with search field and simpler CSS
2020-10-29 22:54:28 +02:00
Henry Jameson 0f8a7037ea fix lain's issue in reaction picker 2020-10-29 20:06:13 +02:00
Henry Jameson 8225717a7c Update and fix avatar shadow in user card 2020-10-29 20:03:53 +02:00
Shpuld Shpuldson 3ead79ddb4 document thie this. check 2020-10-29 12:45:44 +02:00
Shpuld Shpuldson 6acb61f296 fix conflict, keep the touchable button big 2020-10-29 08:55:54 +02:00
Shpuld Shpuldson 93f9ab6f2b Merge branch 'fix/block-misclicks-when-timeline-shifts' of git.pleroma.social:pleroma/pleroma-fe into fix/block-misclicks-when-timeline-shifts 2020-10-29 08:37:31 +02:00
Shpuld Shpuldson cb3578fcca fix conflicts 2020-10-29 08:36:39 +02:00
HJ a84db4bd8f Merge branch 'fontawesome5' into 'develop'
FontAwesome 5

Closes #982

See merge request pleroma/pleroma-fe!1260
2020-10-28 21:21:35 +00:00
Henry Jameson ef36ca44f6 >boxes 2020-10-28 22:52:20 +02:00
Henry Jameson 2e6c51dfd4 better icon for picker 2020-10-28 22:49:53 +02:00
Henry Jameson 0ac9d81788 fix settings tabs on mobile, update follow request badge 2020-10-28 21:55:08 +02:00
Henry Jameson fc7dfb3b9e update & unify the navbars heights 2020-10-28 21:47:42 +02:00
Henry Jameson 7c4af4ce3f improved side-drawer alignments 2020-10-28 21:41:42 +02:00
Henry Jameson b6cf2bcefd improved the semantics for our icon scale, fixed preview, fixed navbar desktop 2020-10-28 21:31:16 +02:00
Shpuld Shpludson 6d7ecd7d80 Apply 1 suggestion(s) to 1 file(s) 2020-10-28 10:02:51 +00:00
Shpuld Shpuldson 7007659e05 change input blocking to use css 2020-10-28 08:53:23 +02:00
Shpuld Shpuldson 24d85ce6dc update changelog 2020-10-27 13:24:05 +02:00
Shpuld Shpuldson 85dc4002a1 update changelog 2020-10-27 13:17:49 +02:00
Shpuld Shpuldson 1403f20f9f block clicks for a second when timeline moves 2020-10-27 12:59:50 +02:00
Shpuld Shpuldson 2c441c7922 fix back button size, fix missing chat notifications being marked as read too eagerly, fix promiseinterval erroring when not getting a promise 2020-10-27 10:03:04 +02:00
HJ e2c4816feb Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1262
2020-10-22 18:53:25 +00:00
shironeko 22f3801be7 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (668 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-22 18:25:04 +00:00
Shpuld Shpludson 9ef4d473cb Merge branch 'fixlainsissueforgood' into 'develop'
make subjectline input use size=1 for compatibility with CJK fonts

Closes #922

See merge request pleroma/pleroma-fe!1261
2020-10-21 06:18:25 +00:00
Henry Jameson 048e67f5fc make subjectline input use size=1 for compatibility with CJK fonts 2020-10-21 02:07:05 +03:00
Henry Jameson eb04ed865e fontello aftermath 2020-10-21 01:56:21 +03:00
Henry Jameson 1b50d700aa bye bye fontello 2020-10-21 00:34:42 +03:00
Henry Jameson f561e75553 lint 2020-10-21 00:31:16 +03:00
Henry Jameson 1ec41302f7 rotate the shackle of the lock for better accessibility 2020-10-21 00:28:24 +03:00
Henry Jameson 6aa7445ea7 come on and slam 2020-10-21 00:25:59 +03:00
Henry Jameson 7495c6b698 fix attachment remove pointer 2020-10-21 00:02:58 +03:00
Henry Jameson a50cd7e37d remaining changes... 2020-10-21 00:01:28 +03:00
Henry Jameson 3cbaa00449 more replacements + small renames 2020-10-20 22:54:43 +03:00
Henry Jameson b19c2eb0fb More stuff. Buttons in user card's corner now have MUCH bigger hitboxes 2020-10-20 22:13:19 +03:00
Henry Jameson 046c60cb61 cancel -> times 2020-10-20 21:18:23 +03:00
Henry Jameson e8650d3409 chevrons-downs, settings 2020-10-20 21:03:46 +03:00
Henry Jameson 8b3a7ae8c0 more FA5 stuff with small related refactoring 2020-10-20 20:28:11 +03:00
Henry Jameson 3814218277 Some initial work on replacing icons with FA5 2020-10-20 20:28:11 +03:00
HJ 350f25016f Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1259
2020-10-20 17:24:49 +00:00
Marcin Mikołajczak cf65ecb99d Translated using Weblate (Polish)
Currently translated at 100.0% (669 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/pl/
2020-10-20 15:56:12 +00:00
HJ f31df6406a Merge branch 'docs_split_up_user_guide' into 'develop'
DOCS: Split up user guide

See merge request pleroma/pleroma-fe!1179
2020-10-20 10:45:05 +00:00
Ilja 54987b0bc8 Split up user guide
* I split up the user guide into seperate section to make it more clear/orderly
* I added a general overview page for the FE from where it links to the other sections that give more detailed information
* I updated outdated information and added new information where I felt was required
* I fixed broken links in other parts of the docs as well
2020-10-20 10:45:05 +00:00
HJ 750680d1d8 Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1258
2020-10-20 09:27:01 +00:00
Kana 4835f567d4 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.7% (667 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-18 10:46:51 +00:00
Ben Is 81a59feab1 Translated using Weblate (Italian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/it/
2020-10-17 19:40:44 +00:00
HJ 76a9a51620 Merge branch 'fixfontello' into 'develop'
fix fontello

See merge request pleroma/pleroma-fe!1256
2020-10-17 18:25:14 +00:00
Henry Jameson c7dddb1ec3 fix fontello 2020-10-17 21:09:51 +03:00
HJ 4df033a3ba Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1254
2020-10-16 20:54:14 +00:00
Anonymous 85326ee9e2 Translated using Weblate (Russian)
Currently translated at 55.0% (368 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ru/
2020-10-16 20:41:05 +00:00
Ben Is def04380da Translated using Weblate (Italian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/it/
2020-10-16 20:41:03 +00:00
Shpuld Shpludson 0e14cd6102 Merge branch 'feat/reorder-emojis-by-position-of-keyword' into 'develop'
feat/reorder-emojis-by-position-of-keyword

See merge request pleroma/pleroma-fe!1240
2020-10-13 15:00:06 +00:00
Shpuld Shpludson d86cd3e850 Merge branch 'feat/masto-ws-deletes' into 'develop'
Support for WS deletes

See merge request pleroma/pleroma-fe!1227
2020-10-12 06:05:21 +00:00
HJ 3ca729d098 Merge branch 'fix/leftover-emoji-checkboxes-in-settings' into 'develop'
fix/leftover-emoji-checkboxes-in-settings

See merge request pleroma/pleroma-fe!1248
2020-10-11 18:00:13 +00:00
Dym Sohin e5bd1c20b0 fix/leftover-emoji-checkboxes-in-settings 2020-10-11 02:03:45 +02:00
Shpuld Shpludson 069a4b0801 Merge branch 'fix/nsfw-hider-closing-preview' into 'develop'
Stop click propagation when unhiding nsfw

See merge request pleroma/pleroma-fe!1245
2020-10-09 16:15:30 +00:00
Shpuld Shpludson e7a67e33ad Merge branch 'fix/follow-requests-title' into 'develop'
Fix Follow Requests title style

See merge request pleroma/pleroma-fe!1243
2020-10-09 16:14:43 +00:00
HJ 6a3c775006 Merge branch 'weblate-pleroma-pleroma-fe' into 'develop'
Translations update from Weblate

See merge request pleroma/pleroma-fe!1232
2020-10-08 15:49:27 +00:00
feld 09da102a4c Apply 1 suggestion(s) to 1 file(s) 2020-10-06 16:18:30 +00:00
tarteka 20bdf32658 Translated using Weblate (Spanish)
Currently translated at 100.0% (668 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/es/
2020-10-06 15:28:18 +00:00
nickiii ba25c618cc Translated using Weblate (Persian)
Currently translated at 15.1% (101 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/fa/
2020-10-05 11:43:55 +00:00
nickiii 0042cf3809 Translated using Weblate (Persian)
Currently translated at 15.1% (101 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/fa/
2020-10-04 23:08:33 +00:00
Jędrzej Tomaszewski 3e86b891e1 Translated using Weblate (Polish)
Currently translated at 100.0% (668 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/pl/
2020-10-02 18:39:51 +00:00
Shpuld Shpuldson 6cf15dce96 update changelog 2020-10-02 12:23:04 +03:00
Shpuld Shpuldson a0da6c31d9 Stop click propagation when unhiding nsfw 2020-10-02 12:21:56 +03:00
Mark Felder ff2fe5c68c Fix Follow Requests title style 2020-10-01 17:05:46 -05:00
nickiii 6dec154450 Translated using Weblate (Persian)
Currently translated at 2.6% (18 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/fa/
2020-10-01 13:20:25 +00:00
nickiii b12b6a84a4 Translated using Weblate (Persian)
Currently translated at 2.5% (17 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/fa/
2020-10-01 13:20:25 +00:00
Haelwenn (lanodan) Monnier 14dc0eef3b Translated using Weblate (French)
Currently translated at 92.0% (615 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/fr/
2020-10-01 13:20:25 +00:00
nickiii 7e4d1b0abb Added translation using Weblate (Persian) 2020-10-01 13:20:25 +00:00
Snow dff7e38154 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (668 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hant/
2020-10-01 13:20:25 +00:00
Snow f110258fa1 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.6% (659 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
Ben Is 71fca987a8 Translated using Weblate (Italian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/it/
2020-10-01 13:20:25 +00:00
hj e9f13895b9 Translated using Weblate (English)
Currently translated at 100.0% (661 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/en/
2020-10-01 13:20:25 +00:00
Not HJ d11ecc5987 Translated using Weblate (English)
Currently translated at 100.0% (661 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/en/
2020-10-01 13:20:25 +00:00
tarteka 38fa2111f9 Translated using Weblate (Basque)
Currently translated at 83.3% (551 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eu/
2020-10-01 13:20:25 +00:00
tarteka c9033e0351 Translated using Weblate (Spanish)
Currently translated at 100.0% (661 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/es/
2020-10-01 13:20:25 +00:00
tarteka f10abd29f0 Translated using Weblate (Basque)
Currently translated at 77.6% (513 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/eu/
2020-10-01 13:20:25 +00:00
Kana cd6adac59a Translated using Weblate (Chinese (Simplified))
Currently translated at 99.6% (659 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
Kana fffce4aa98 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.6% (659 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
Snow 14a2328b85 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (661 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hant/
2020-10-01 13:20:25 +00:00
Snow b3e1cb81a3 Translated using Weblate (Chinese (Traditional))
Currently translated at 72.1% (477 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hant/
2020-10-01 13:20:25 +00:00
Kana 970bfa2bdd Translated using Weblate (Chinese (Simplified))
Currently translated at 97.7% (646 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
Kana beec425cce Translated using Weblate (Chinese (Simplified))
Currently translated at 90.4% (598 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
Snow c55e09a513 Translated using Weblate (Chinese (Traditional))
Currently translated at 67.1% (444 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hant/
2020-10-01 13:20:25 +00:00
Kana 887ff4dec3 Translated using Weblate (Chinese (Simplified))
Currently translated at 90.0% (595 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
snow 32ddb38736 Translated using Weblate (Chinese (Traditional))
Currently translated at 18.9% (125 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hant/
2020-10-01 13:20:25 +00:00
snow ad6b7148d4 Translated using Weblate (Chinese (Simplified))
Currently translated at 83.2% (550 of 661 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/zh_Hans/
2020-10-01 13:20:25 +00:00
snow aca8570b86 Added translation using Weblate (Chinese (Traditional)) 2020-10-01 13:20:25 +00:00
titizen 3f119c6875 Translated using Weblate (Catalan)
Currently translated at 48.7% (323 of 662 strings)

Translation: Pleroma/Pleroma-FE
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/ca/
2020-10-01 13:20:25 +00:00
Shpuld Shpludson 6bd38c7d6f Merge branch 'fix/wait-for-request-before-starting-interval' into 'develop'
Fix/wait for request before starting interval - fix #937

Closes #937

See merge request pleroma/pleroma-fe!1222
2020-10-01 13:20:14 +00:00
Shpuld Shpuldson 414558665f lint fix 2020-10-01 16:01:57 +03:00
Shpuld Shpludson 8a34ff2957 Merge branch 'develop' into 'feat/masto-ws-deletes'
# Conflicts:
#   CHANGELOG.md
#   src/components/status/status.js
#   src/components/status/status.scss
2020-10-01 12:54:54 +00:00
Shpuld Shpludson 68c2a5b18f Merge branch 'fix/excessive-underline-in-sidebar' into 'develop'
fix excessive underline in sidebar

See merge request pleroma/pleroma-fe!1238
2020-09-30 06:59:09 +00:00
Dym Sohin c17012cfe1 fix appended 0.65em on wrong line 2020-09-29 13:20:16 +02:00
Dym Sohin 1675f1a133 scoped back margin-right on icons 2020-09-29 13:13:42 +02:00
Shpuld Shpludson 91778a0276 Merge branch 'feat/custom-virtual-scrolling' into 'develop'
Timeline virtual scrolling

See merge request pleroma/pleroma-fe!1043
2020-09-29 10:18:37 +00:00
Shpuld Shpludson f174f289a9 Timeline virtual scrolling 2020-09-29 10:18:37 +00:00
Shpuld Shpludson 3781e521e6 Merge branch 'feature/import_export_mutes' into 'develop'
[#2099] Added import/export mutes [FE]

See merge request pleroma/pleroma-fe!1229
2020-09-29 08:18:02 +00:00
Shpuld Shpludson 787f52e06e Merge branch 'remove-bio-tables-max-width' into 'develop'
remove bio-table's max-width

See merge request pleroma/pleroma-fe!1241
2020-09-29 06:19:20 +00:00
Dym Sohin 3dacef944c remove bio-table's max-width 2020-09-24 12:05:51 +02:00
Dym Sohin bb59b8ee56 fixed copy-pasting leftovers 2020-09-21 18:13:31 +02:00
Dym Sohin cff202241b improved algorithm, possibly speed too 2020-09-21 18:10:55 +02:00
Dym Sohin f1e1f20a8d fix 8x spaces inside this paren 2020-09-21 17:42:17 +02:00
Dym Sohin fee654f1ee feat/reorder-emojis-by-position-of-keyword 2020-09-21 17:29:36 +02:00
HJ 0c0722a092 Merge branch 'fix/overflow-for-chat-unread' into 'develop'
fix/overflow-for-chat-unread

See merge request pleroma/pleroma-fe!1239
2020-09-19 19:59:57 +00:00
Dym Sohin 20362546d1 fix/overflow-for-chat-unread 2020-09-19 21:50:56 +02:00
Dym Sohin f9977dbb3c fix excessive underline in sidebar 2020-09-19 21:28:03 +02:00
Maksim Pechnikov 5942001626 updated changelog 2020-09-18 22:09:05 +03:00
Maksim Pechnikov 3dbc1bedbf Merge branch 'develop' into feature/import_export_mutes 2020-09-18 22:04:01 +03:00
Maksim Pechnikov b725df6352 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-09-18 22:03:11 +03:00
HJ 0fee9a8fe7 Merge branch 'fix/case--in-sensitive--emoji--search' into 'develop'
fix case in/sensitive emoji search

See merge request pleroma/pleroma-fe!1237
2020-09-18 09:37:17 +00:00
Dym Sohin 70a5619496 [fix] case in/sensitive emoji search 2020-09-18 11:07:38 +02:00
Shpuld Shpludson b225c3578f Merge branch 'rc/2.1.2' into 'master'
Merge 2.1.2 to MASTER

See merge request pleroma/pleroma-fe!1236
2020-09-17 17:26:22 +00:00
Shpuld Shpludson 30efbaab34 Merge branch 'master' into 'rc/2.1.2'
# Conflicts:
#   CHANGELOG.md
2020-09-17 17:17:21 +00:00
Shpuld Shpuldson 8ca0586c0f update changelog for 2.1.2 2020-09-17 20:15:08 +03:00
lain ee620f6028 Merge branch 'fix/use-shoutbox-name-in-sidedrawer' into 'develop'
change side drawer to use shoutbox name - fix #956

Closes #956

See merge request pleroma/pleroma-fe!1235
2020-09-16 09:22:05 +00:00
Shpuld Shpuldson 20d33c2fbc change icon to a megaphone 2020-09-16 11:53:54 +03:00
Shpuld Shpuldson 1b811d8b93 change side drawer to use shoutbox name 2020-09-16 11:29:10 +03:00
Shpuld Shpuldson d6fe4f6a4f update changelog 2020-09-16 10:27:31 +03:00
Shpuld Shpludson 38189ee838 Merge branch 'fix-chat-message-list-fetch' into 'develop'
Fix chat messages being missed sometimes when the streaming is disabled and the messages are sent by both participants simultaneously

Closes #957

See merge request pleroma/pleroma-fe!1233
2020-09-16 07:13:31 +00:00
Shpuld Shpludson c00c20a31f Merge branch 'fix-chat-list-order' into 'develop'
Fix the chat list order update

Closes #955

See merge request pleroma/pleroma-fe!1234
2020-09-16 06:59:04 +00:00
eugenijm 8c4514013d Fix chat messages being missed when the streaming is disabled and the messages are sent by both participants simultaneously 2020-09-16 09:21:24 +03:00
eugenijm 92caaa2d7f Fix the chat list order and last message timestamp updates 2020-09-16 05:10:09 +03:00
Shpuld Shpludson 679a1f5e1c Merge branch 'fix/fix-vue-errors' into 'develop'
fix vue warnings and errors

See merge request pleroma/pleroma-fe!1230
2020-09-09 10:21:54 +00:00
Shpuld Shpuldson afb2241a5b change a eslint disable to nextline only 2020-09-08 16:29:10 +03:00
Shpuld Shpuldson 8975589bca fix vue warnings and errors 2020-09-08 10:44:08 +03:00
Maksim Pechnikov 947d7cd6f2 added import/export mutes 2020-09-08 09:41:42 +03:00
Shpuld Shpuldson fa91766519 rename to gravestone 2020-09-08 09:32:43 +03:00
Shpuld Shpludson 1ec9cde963 Apply 1 suggestion(s) to 1 file(s) 2020-09-08 06:31:02 +00:00
Shpuld Shpuldson 0758569625 change i18n phrasing 2020-09-07 10:39:30 +03:00
Shpuld Shpuldson f9ac23b9a9 separate reply button to its own component, add changelog entry 2020-09-07 10:35:49 +03:00
Maksim Pechnikov fa2b680855 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-09-07 09:47:17 +03:00
Shpuld Shpuldson 40ca0b394e add basic deletes support that works with masto WS 2020-09-06 15:28:09 +03:00
Shpuld Shpludson e331db79e5 Merge branch 'develop' into 'fix/wait-for-request-before-starting-interval'
# Conflicts:
#   CHANGELOG.md
2020-09-04 08:38:13 +00:00
Shpuld Shpuldson c89ac79140 fix chat fetcher stops, change fetcher code 2020-09-04 11:22:14 +03:00
Shpuld Shpuldson 3fb35e8123 rename to promiseInterval 2020-09-04 11:19:53 +03:00
Shpuld Shpuldson 5b403ba7d1 fix timeline showimmediately being set wrongly 2020-09-02 22:12:50 +03:00
Shpuld Shpuldson 4d080a1654 add mention to changelog 2020-09-02 21:26:02 +03:00
Shpuld Shpuldson d939f2ffbc document makeFetcher a bit 2020-09-02 21:08:06 +03:00
Shpuld Shpuldson 1b6eee0497 change chats to use custom makeFetcher 2020-09-02 21:01:31 +03:00
Shpuld Shpuldson 2d914c331e replace setInterval for timelne, notifications and follow requests 2020-09-02 20:40:47 +03:00
Maksim Pechnikov 12519a54b5 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-06-29 09:16:00 +03:00
Maksim Pechnikov 08444c3903 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-06-18 08:47:50 +03:00
Maksim Pechnikov e3d0b2f137 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-02-13 09:32:45 +03:00
Maksim Pechnikov a52ae1ebeb Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-02-10 21:09:36 +03:00
Maksim Pechnikov 64c180c838 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-02-04 10:07:20 +03:00
Maksim Pechnikov f892b26d73 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-01-14 22:08:24 +03:00
Maksim Pechnikov 40c4a49223 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-01-14 16:14:51 +03:00
Maksim Pechnikov 99db89fa17 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-01-13 14:45:43 +03:00
Maksim Pechnikov 2810f10d14 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop 2020-01-06 15:47:36 +03:00
Maksim Pechnikov 50bb8865c5 dd 2019-12-18 21:17:06 +03:00
225 changed files with 12289 additions and 3738 deletions
+69 -1
View File
@@ -3,16 +3,84 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
## [2.2.2] - 2020-12-22
### Added
- Mouseover titles for emojis in reaction picker
- Support to input emoji into the search box in reaction picker
- Added some missing unicode emoji
- Added the upload limit to the Features panel in the About page
- Support for solid color wallpaper, instance doesn't have to define a wallpaper anymore
### Fixed
- Fixed the occasional bug where screen would scroll 1px when typing into a reply form
- Fixed timeline errors locking timelines
- Fixed missing highlighted border in expanded conversations
- Fixed custom emoji not working in profile field names
- Fixed pinned statuses not appearing in user profiles
- Fixed some elements not being keyboard navigation friendly
- Fixed error handling when updating various profile images
- Fixed your latest chat messages disappearing when closing chat view and opening it again during the same session
- Fixed custom emoji not showing in poll options before voting
- Fixed link color not applied to instance name in topbar
### Changed
- Errors when fetching are now shown with popup errors instead of "Error fetching updates" in panel headers
- Made reply/fav/repeat etc buttons easier to hit
- Adjusted timeline menu clickable area to match the visible button
- Moved external source link from status heading to the ellipsis menu
- Disabled horizontal textarea resize
- Wallpaper is now top-aligned, horizontally centered.
## [2.2.1] - 2020-11-11
### Fixed
- Fixed regression in react popup alignment and overflowing
## [2.2.0] - 2020-11-06
### Added
- New option to optimize timeline rendering to make the site more responsive (enabled by default)
- New instance option `logoLeft` to move logo to the left side in desktop nav bar
- Import/export a muted users
- Proper handling of deletes when using websocket streaming
- Added optimistic chat message sending, so you can start writing next message before the previous one has been sent
- Added a small red badge to the favicon when there's unread notifications
- Added the NSFW alert to link previews
### Fixed
- Fixed clicking NSFW hider through status popover
- Fixed chat-view back button being hard to click
- Fixed fresh chat notifications being cleared immediately while leaving the chat view and not having time to actually see the messages
- Fixed multiple regressions in CSS styles
- Fixed multiple issues with input fields when using CJK font as default
- Fixed search field in navbar infringing into logo in some cases
- Fixed not being able to load the chat history in vertical screens when the message list doesn't take the full height of the scrollable container on the first fetch.
### Changed
- Clicking immediately when timeline shifts is now blocked to prevent misclicks
- Icons changed from fontello (FontAwesome 4 + others) to FontAwesome 5 due to problems with fontello.
- Some icons changed for better accessibility (lock, globe)
- Logo is now clickable
- Changed default logo to SVG version
## [2.1.2] - 2020-09-17
### Fixed
- Fixed chats list not updating its order when new messages come in
- Fixed chat messages sometimes getting lost when you receive a message at the same time
## [2.1.1] - 2020-09-08 ## [2.1.1] - 2020-09-08
### Changed ### Changed
- Polls will be hidden with status content if "Collapse posts with subjects" is enabled and the post is collapsed. - Polls will be hidden with status content if "Collapse posts with subjects" is enabled and the post is collapsed.
### Fixed ### Fixed
- Network fetches don't pile up anymore but wait for previous ones to finish to reduce throttling.
- Autocomplete won't stop at the second @, so it'll still work with "@lain@l" and not start over. - Autocomplete won't stop at the second @, so it'll still work with "@lain@l" and not start over.
- Fixed weird autocomplete behavior when you write ":custom_emoji: ?" - Fixed weird autocomplete behavior when you write ":custom_emoji: ?"
## [2.1.0] - 2020-08-28 ## [2.1.0] - 2020-08-28
### Added ### Added
- Autocomplete domains from list of known instances - Autocomplete domains from list of known instances
-9
View File
@@ -3,7 +3,6 @@ var config = require('../config')
var utils = require('./utils') var utils = require('./utils')
var projectRoot = path.resolve(__dirname, '../') var projectRoot = path.resolve(__dirname, '../')
var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin') var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin')
var FontelloPlugin = require("fontello-webpack-plugin")
var env = process.env.NODE_ENV var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the // check env & config/index.js to decide weither to enable CSS Sourcemaps for the
@@ -94,14 +93,6 @@ module.exports = {
new ServiceWorkerWebpackPlugin({ new ServiceWorkerWebpackPlugin({
entry: path.join(__dirname, '..', 'src/sw.js'), entry: path.join(__dirname, '..', 'src/sw.js'),
filename: 'sw-pleroma.js' filename: 'sw-pleroma.js'
}),
new FontelloPlugin({
config: require('../static/fontello.json'),
name: 'fontello',
output: {
css: 'static/[name].' + now + '.css', // [hash] is not supported. Use the current timestamp instead for versioning.
font: 'static/font/[name].' + now + '.[ext]'
}
}) })
] ]
} }
+2 -2
View File
@@ -1,13 +1,13 @@
# Pleroma-FE configuration and customization for instance administrators # Pleroma-FE configuration and customization for instance administrators
* *For user configuration, see [Pleroma-FE user guide](USER_GUIDE.md)* * *For user configuration, see [Pleroma-FE user guide](../user_guide)*
* *For local development server configuration, see [Hacking, tweaking, contributing](HACKING.md)* * *For local development server configuration, see [Hacking, tweaking, contributing](HACKING.md)*
## Where configuration is stored ## Where configuration is stored
PleromaFE gets its configuration from several sources, in order of preference (the one above overrides ones below it) PleromaFE gets its configuration from several sources, in order of preference (the one above overrides ones below it)
1. `/api/statusnet/config.json` - this is generated on Backend and contains multiple things including instance name, char limit etc. It also contains FE/Client-specific data, PleromaFE uses `pleromafe` field of it. For more info on changing config on BE, look [here](https://docs-develop.pleroma.social/config.html#frontend_configurations) 1. `/api/statusnet/config.json` - this is generated on Backend and contains multiple things including instance name, char limit etc. It also contains FE/Client-specific data, PleromaFE uses `pleromafe` field of it. For more info on changing config on BE, look [here](../backend/configuration/cheatsheet.md#frontend_configurations)
2. `/static/config.json` - this is a static FE-provided file, containing only FE specific configuration. This file is completely optional and could be removed but is useful as a fallback if some configuration JSON property isn't present in BE-provided config. It's also a reference point to check what default configuration are and what JSON properties even exist. In local dev mode it could be used to override BE configuration, more about that in HACKING.md. File is located [here](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/static/config.json). 2. `/static/config.json` - this is a static FE-provided file, containing only FE specific configuration. This file is completely optional and could be removed but is useful as a fallback if some configuration JSON property isn't present in BE-provided config. It's also a reference point to check what default configuration are and what JSON properties even exist. In local dev mode it could be used to override BE configuration, more about that in HACKING.md. File is located [here](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/static/config.json).
3. Built-in defaults. Those are hard-coded defaults that are used when `/static/config.json` is not available and BE-provided configuration JSON is missing some JSON properties. ( [Code](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/modules/instance.js) ) 3. Built-in defaults. Those are hard-coded defaults that are used when `/static/config.json` is not available and BE-provided configuration JSON is missing some JSON properties. ( [Code](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/modules/instance.js) )
+3 -3
View File
@@ -25,7 +25,7 @@ This could be a bit trickier, you basically need steps 1-4 from *develop build*
### Replacing your instance's frontend with custom FE build ### Replacing your instance's frontend with custom FE build
This is the most easiest way to use and test FE build: you just need to copy or symlink contents of `dist` folder into backend's [static directory](https://docs.pleroma.social/static_dir.html), by default it is located in `instance/static`, or in `/var/lib/pleroma/static` for OTP release installations, create it if it doesn't exist already. Be aware that running `yarn build` wipes the contents of `dist` folder. This is the most easiest way to use and test FE build: you just need to copy or symlink contents of `dist` folder into backend's [static directory](../backend/configuration/static_dir.md), by default it is located in `instance/static`, or in `/var/lib/pleroma/static` for OTP release installations, create it if it doesn't exist already. Be aware that running `yarn build` wipes the contents of `dist` folder.
### Running production build locally or on a separate server ### Running production build locally or on a separate server
@@ -67,9 +67,9 @@ server {
### API, Data, Operations ### API, Data, Operations
In 99% cases PleromaFE uses [MastoAPI](https://docs.joinmastodon.org/api/) with [Pleroma Extensions](https://docs-develop.pleroma.social/differences_in_mastoapi_responses.html) to fetch the data. The rest is either QvitterAPI leftovers or pleroma-exclusive APIs. QvitterAPI doesn't exactly have documentation and uses different JSON structure and sometimes different parameters and workflows, [this](https://twitter-api.readthedocs.io/en/latest/index.html) could be a good reference though. Some pleroma-exclusive API may still be using QvitterAPI JSON structure. In 99% cases PleromaFE uses [MastoAPI](https://docs.joinmastodon.org/api/) with [Pleroma Extensions](../backend/API/differences_in_mastoapi_responses.md) to fetch the data. The rest is either QvitterAPI leftovers or pleroma-exclusive APIs. QvitterAPI doesn't exactly have documentation and uses different JSON structure and sometimes different parameters and workflows, [this](https://twitter-api.readthedocs.io/en/latest/index.html) could be a good reference though. Some pleroma-exclusive API may still be using QvitterAPI JSON structure.
PleromaFE supports both formats by transforming them into internal format which is basically QvitterAPI one with some additions and renaming. All data is passed trough [Entity Normalizer](/src/services/entity_normalizer/entity_normalizer.service.js) which can serve as a reference of API and what's actually used, it's also a host for all the hacks and data transformation. PleromaFE supports both formats by transforming them into internal format which is basically QvitterAPI one with some additions and renaming. All data is passed trough [Entity Normalizer](https://git.pleroma.social/pleroma/pleroma-fe/-/blob/develop/src/services/entity_normalizer/entity_normalizer.service.js) which can serve as a reference of API and what's actually used, it's also a host for all the hacks and data transformation.
For most part, PleromaFE tries to store all the info it can get in global vuex store - every user and post are passed trough updating mechanism where data is either added or merged with existing data, reactively updating the information throughout UI, so if in newest request user's post counter increased, it will be instantly updated in open user profile cards. This is also used to find users, posts and sometimes to build timelines and/or request parameters. For most part, PleromaFE tries to store all the info it can get in global vuex store - every user and post are passed trough updating mechanism where data is either added or merged with existing data, reactively updating the information throughout UI, so if in newest request user's post counter increased, it will be instantly updated in open user profile cards. This is also used to find users, posts and sometimes to build timelines and/or request parameters.
-207
View File
@@ -1,207 +0,0 @@
# Pleroma-FE user guide
> Be prepared for breaking changes, unexpected behavior and this user guide becoming obsolete and wrong.
> If there was no insanity
>
> it would be necessary to create it.
>
> --Catbag
## Posting, reading, basic functions.
After registering and logging in you're presented with your timeline in right column and new post form with timeline list and notifications in the left column.
Posts will contain the text you are posting, but some content will be modified:
1. Mentions: Mentions have the form of @user or @user<span></span>@instance.tld. These will become links to the user's profile. In addition, the mentioned user will always get a notification about the post they have been mentioned in, so only mention users that you want to receive this message.
2. URLs: URLs like `http://example.com` will be automatically be turned into a clickable links.
3. Hashtags: Hashtags like #cofe will also be turned into links.
**Depending on your instance some of the options might not be available or have different defaults**
Let's clear up some basic stuff. When you post something it's called a **post** or it could be called a **status** or even a **toot** or a **prööt** depending on whom you ask. Post has body/content but it also has some other stuff in it - from attachments, visibility scope, subject line.
* **Emoji** are small images embedded in text, there are two major types of emoji: [unicode emoji](https://en.wikipedia.org/wiki/Emoji) and custom emoji. While unicode emoji are universal and standardized, they can appear differently depending on where you are using them or may not appear at all on older systems. Custom emoji are more *fun* kind - instance administrator can define many images as *custom emoji* for their users. This works very simple - custom emoji is defined by its *shortcode* and an image, so that any shortcode enclosed in colons get replaced with image if such shortcode exist.
Let's say there's `:pleroma:` emoji defined on instance. That means
> First time using :pleroma: pleroma!
will become
> First time using ![pleroma](./example_emoji.png) pleroma!
Note that you can only use emoji defined on your instance, you cannot "copy" someone else's emoji, and will have to ask your administrator to copy emoji from other instance to yours.
Lastly, there's two convenience options for emoji: an emoji picker (smiley face to the right of "submit" button) and autocomplete suggestions - when you start typing :shortcode: it will automatically try to suggest you emoj and complete the shortcode for you if you select one. **Note** that if emoji doesn't show up in suggestions nor in emoji picker it means there's no such emoji on your instance, if shortcode doesn't match any defined emoji it will appear as text.
* **Attachments** are fairly simple - you can attach any file to a post as long as the file is within maximum size limits. If you're uploading explicit material you can mark all of your attachments as sensitive (or add `#nsfw` tag) - it will hide the images and videos behind a warning so that it won't be displayed instantly.
* **Subject line** also known as **CW** (Content Warning) could be used as a header to the post and/or to warn others about contents of the post having something that might upset somebody or something among those lines. Several applications allow to hide post content leaving only subject line visible. Using a subject line will not mark your images as sensitive, you will have to do that explicitly (see above).
* **Visiblity scope** controls who will be able to see your posts. There are four scopes available:
1. `Public`: This is the default, and some fediverse software like GNU Social only supports this. This means that your post is accessible by anyone and will be shown in the public timelines.
2. `Unlisted`: This is the same as public, but your post won't appear in the public timelines. The post will still be accessible by anyone who comes across it (for example, by looking at your profile) or by direct linking. They will also appear in public searches.
3. `Followers only`: This will show your post only to your followers. Only they will be able to interact with it. Be careful: When somebody follows you, they will be able to see all your previous `followers only` posts as well! If you want to restrict who can follow you, consider [locking your account down to only approved followers](#profle).
4. `Direct`: This will only send the message to the people explicitly mentioned in the post.
A few things to consider about the security and usage of these scopes:
- None of these options will change the fact that the messages are all saved in the database unencrypted. They will be visible to your server admin and to any other admin of a server who receives this post. Do not share information that you would consider secret or dangerous. Use encrypted messaging systems for these things.
- Follower-only posts can lead to fragmented conversations. If you post a follower-only post and somebody else replies to it with a follower-only post, only people following both of you will see the whole conversation thread. Everybody else will only see half of it. Keep this in mind and keep conversations public if possible.
- Changing scopes during a thread or adding people to a direct message will not retroactively make them see the whole conversation. If you add someone to a direct message conversation, they will not see the post that happened before they were mentioned.
* **Reply-to** if you are replying to someone, your post will also contain a note that your post is referring to the post you're replying to. Person you're replying to will receive a notification *even* if you remove them from mentioned people. You won't receive notifications when replying to your own posts, but it's useful to reply to your own posts to provide people some context if it's a follow-up to a previous post. There's a small "Reply to ..." label under post author's name which you can hover on to see what post it's referring to.
Sometimes you may encounter posts that seem different than what they are supposed to. For example, you might see a direct message without any mentions in the text. This can happen because internally, the Fediverse has a different addressing mechanism similar to email, with `to` and `cc` fields. While these are not directly accessible in PleromaFE, other software in the Fediverse might generate those posts. Do not worry in these cases, these are normal and not a bug.
#### Rich text
By default new posts you make are plaintext, meaning you can't make text **bold** or add custom links or make lists or anything like that. However if your instance allows it you can use Markdown or BBCode or HTML to spice up your text, however there are certain limitations to what HTML tags and what features of Markdown you can use.
this section will be expanded later
### Other actions
In addition to posting you can also *favorite* post also known as *liking* them and *repeat* posts (also known as *retweeting*, *boosting* and even *reprööting*). Favoriting a post increments a counter on it, notifies post author of your affection towards that post and also adds that post to your "favorited" posts list (in your own profile, "Favorites" tab). Reprööting a post does all that and also repeats this post to your followers and your profile page with a note "*user* repeated post".
Your own posts can be deleted, but this will only reliably delete the post from your own instance. Other instances will receive a deletion notice, but there's no way to force them to actually delete a post. In addition, not all instances that contain the message might even receive the deletion notice, because they might be offline or not known to have the post because they received it through a repeat. Lastly, deletion notice might not reach certain frontends and clients - post will be visible for them until page refresh or cache clear, they probably won't be able to interact with it apart from replying to it (which will have reply-to mark missing).
If you are a moderator, you can also delete posts by other people. If those people are on your instance, it will delete the post and send out the deletion notice to other servers. If they are not on your instance, it will just remove the post from your local instance.
There's also an option to report a user via a post (if the feature is available on your instance) which could be used to notify your (and probably other instance's) admin that someone is being naughty.
## Users
When you see someone, you can click on their user picture to view their profile, and click on the userpic in that to see *full* profile. You can *follow* them, *mute* and *block* them. Following is self-explanatory, it adds them t your Home Timeline, lists you as a follower and gives you access to follower-only posts if they have any. Muting makes posts and notifications made by them very tiny, giving you an option to see the post if you're curious. However on clients other than PleromaFE their posts will be completely removed. *Blocking* a user removes them from your timeline and notifications and prevents them from following you (automatically unfollows them from you).
Please note that some users can be "locked", meaning instead of following them you send a follow request they need to approve for you to become their follower.
## Timelines
Currently you have several timelines to browse trough:
* **Timeline** aka Home Timeline - this timeline contains all posts by people you follow and your own posts, as well as posts mentioning you directly.
* **Interactions** all interactions you've had with people on the network, basically same as notifications except grouped in convenient way - mentions separate from favorites with repeats separate from follows
* **Direct Messages** all posts with `direct` scope addressed to you or mentioning you.
* **Public Timelines** all posts made by users on instance you're on
* **The Whole Known Network** also known as **TWKN** or **Federated Timeline** - all posts on the network by everyone, almost. Due to nature of the network your instance may not know *all** the instances on the network, so only posts originating from known instances are shown there.
## Your profile
By clicking wrench icon above the post form you can access the profile edit or "user settings" screen.
### Profle
Here you can set up how you appear to other users among with some other settings:
- Name: this is text that displays next to your avatar in posts. Please note that you **cannot** change your *@<span></span>handle*
- Bio: this will be displayed under your profile - you can put anything you want there you want for everyone to see.
- Restrict your account to approved followers only: this makes your account "locked", when people follow you - you have to approve or deny their follow requests, this gives more control over who sees your followers only posts.
- Default visibility scope: this chooses your default post scope for new posts
- Strip rich text from all posts: this strips rich text formatting (bold/italics/lists etc) from all incoming posts. Will only affect newly fetched posts.
If you're admin or moderator on your instance you also get "Show [role] badge in my profile" - this controls whether to show "Admin" or "Moderator** label on your profile page.
**For all options mentioned above you have to click "Submit" button for changes to take place**
- Avatar: this changes picture next to your posts. Your avatar shouldn't exceed 2 MiB (2097152 bytes) or it could cause problems with certain instances.
- Banner: this changes background on your profile card. Same as avatar it shouldn't exceed 2 MiB limit.
- Profile Background: this changes background picture for UI. It isn't shown to anyone else **yet**, but some time later it will be shown when viewing your profile.
### Security
Here you can change your password, revoke access tokens, configure 2-factor authentication (if available).
### Notifications
This screen allows more fine-grained control over what notifications to show to you based on whom it comes from
### Data Import/Export
This allows you to export and import a list of people you follow, in case instance's database gets reverted or if you want to move to another server. Note that you **CANNOT export/import list of people who *follow you***, they'll just need to follow you back after you move.
### Blocks and Mutes
These screens give access to full list of people you block/mute, useful for *un*blocking/*un*muting people because blocking/muting them most likely removes them out of your sight completely.
## Other stuff
By default you can see **ALL** posts made by other users on your Home Timeline, this contrast behavior of Twitter and Mastodon, which shows you only non-reply posts and replies to people you follow. You can set it up to replicate the said behavior, however the option is currently broken.
You can view other people's profiles and search for users (top-right corner, person with a plus icon). Tag search is possible but not implemented properly yet, right now you can click on tag link in a post to see posts tagged with that post.
You can also view posts you've favorited on your own profile, but you cannot see favorites by other people.
Due to nature of how Pleroma (backend) operates you might see old posts appear as if they are new, this is because instance just learned about that post (i.e. your instance is younger that some other ones) and someone interacted with old post. Posts are sorted by date of when they are received, not date they have been posted because it's very easy to spoof the date, so a post claiming it "was" made in year 2077 could hand at top of your TL forever.
# Customization and configuration
Clicking on the cog icon in the upper right will go to the settings screen.
## General
### Interface
- Language: Here you can set the interface language. The default language is the one that you set in your browser settings.
- Hide instance-specific panel: This hides the panel in the lower left that usually contains general information about the server.
### Timeline
- Hide posts of muted users: If this is set, 'muting' a user will completely hide their posts instead of collapsing them.
- Collapse posts with subjects: This will collapse posts that contain a subject, hiding their content. Subjects are also sometimes called content warnings.
- Enable automatic streaming of new posts when scrolled to the top: With this enabled, new posts will automatically stream in when you are scrolled to the top. Otherwise, you will see a button on the timeline that will let you display the new posts.
- Pause streaming when tab is not focused: This pauses the automatic streaming that the previous option enables when the tab is out of focus. This is useful if you don't want to miss any new posts.
- Enable automatic loading when scrolled to the bottom: When this is disabled, a button will be shown on the bottom of the timeline that will let you load older posts.
- Enable reply-link preview on hover: Status posts in the timeline and notifications contain links to replies and to the post they are a reply to. If this setting is enabled, hovering over that link will display that linked post in a small hovering overlay.
### Composing
- Copy scope when replying: When this is activated, the scope of a reply will be the same as the scope of the post it is replying to. This is useful to prevent accidentally moving private discussions to public, or vice versa.
- Always show subject field: Whether or not to display the 'subject' input field in the post form. If you do not want to use subjects, you can deactivate this.
- Copy subject when replying: This controls if the subject of a post will be copied from the post it is replying to.
- Post status content type: Selects the default content type of your post. The options are: Plain text, HTML, BBCode and Markdown.
- Minimize scope selection options: Selecting this will reduce the visibility scopes to 'direct', your default post scope and post scope of post you're replying to.
- Automatically hide New Post button: Mobile interface only: hide floating "New post" button when scrolling
### Attachments
- Hide attachments in timeline: Do not display attachments in timelines. They will still display in expanded conversations. This is useful to save bandwidth and for browsing in public.
- Hide attachments in conversations: Also hide attachments in expanded conversations.
- Maximum amount of thumbnails per post: Exactly that :)
- Enable clickthrough NSFW attachment hiding: Hide attachments that are marked as NSFW/sensitive behind a click-through image.`
- Preload images: This will preload the hidden images so that they display faster when clicking through.
- Open NSFW attachments with just one click: Directly open NSFW attachments in a maximised state instead of revealing the image thumbnail.
- Play-on-hover GIFs: With this activated, GIFs images and avatars will only be animated on mouse hover. Otherwise, they will be always animated. This is very useful if your timeline looks too flashy from people's animated avatars and eases the CPU load.
- Loop videos: Whether to loop videos indefinitely.
- Loop only videos without sound: Some instances will use videos without sounds instead of GIFs. This will make only those videos autoplay.
- Play videos directly in the media viewer: Play videos right in the timeline instead of opening it in a modal
- Don't crop the attachment in thumbnails: if enabled, images in attachments will be fit entirely inside the container instead of being zoomed in and cropped.
### Notifications
- Enable web push notifications: this enables Web Push notifications, to allow receiving notifications even when the page isn't opened, doesn't affect regular notifications.
## Theme
You can change the look and feel of Pleroma Frontend here. You can choose from several instance-provided presets and you can load one from file and save current theme to file. Before you apply new theme you can see what it will look like approximately in preview section.
Themes engine was made to be easy to use while giving an option for powerful in-depth customization - you can just tweak colors on "Common" tab and leave everything else as is.
If there's a little check box next to a color picker it means that color is optional and unless checked will be automatically picked based on some other color or defaults.
For some features you can also adjust transparency of it by changing its opacity, you just need to tick checkbox next to it, otherwise it will be using default opacity.
Contrast information is also provided - you can see how readable text is based on contrast between text color and background, icons under color pickers represent contrast rating based on [WCAG](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast) - thumbs up means AAA rating (good), half-filled circle means AA rating (acceptable) and warning icon means it doesn't pass the minimal contrast requirement and probably will be less readable, especially for vision-challenged people, you can hover over icon to see more detailed information. *Please note* that if background is not opaque (opacity != 1) contrast will be measured based on "worst case scenario", i.e. behind semi-transparent background lies some solid color that makes text harder to read, this however is still inaccurate because it doesn't account that background can be noisy/busy, making text even harder to read.
Apart from colors you can also tweak shadow and lighting, which is used mostly to give buttons proper relief based on their state, give panes their shade, make things glow etc. It's quite powerful, and basically provides somewhat convenient interface for [CSS Shadows](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow).
Another thing you can tweak is theme's roundness - some people like sharp edges, some want things more rounded. This is also used if you want circled or square avatars.
Lastly, you can redefine fonts used in UI without changing fonts in your browser or system, this however requires you to enter font's full name and having that font installed on your system.
## Filtering
- Types of notifications to show: This controls what kind of notifications will appear in notification column and which notifications to get in your system outside the web page
- Replies in timeline: You may know that other social networks like Twitter will often not display replies to other people in your timeline, even if you are following the poster. Pleroma usually will show these posts to you to encourage conversation. If you do not like this behavior, you can change it here.
- Hide post statistics: This hides the number of favorites, number of replies, etc.
- Hide user statistics: This hides the number of followers, friends, etc.
- Muted words: A list of words that will be muted (i.e. displayed in a collapsed state) on the timeline and in notifications. An easy way to tune down noise in your timeline. Posts can always be expanded when you actually want to see them.
- Hide filtered statuses: Selecting this will hide the filtered / muted posts completely instead of collapsing them.
## Version
Just displays the backend and frontend version. Useful to mention in bug reports.

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+1 -1
View File
@@ -5,4 +5,4 @@ Pleroma-FE is the default user-facing frontend for Pleroma. It's user interface
## How can I use it? ## How can I use it?
If your instance uses Pleroma-FE, you can acces it by going to your instance (e.g. <https://pleroma.soykaf.com>). You can read more about it's basic functionality in the [Pleroma-FE User Guide](./USER_GUIDE.md). We also have [a guide for administrators](./CONFIGURATION.md) and for [hackers/contributors](./HACKING.md). If your instance uses Pleroma-FE, you can acces it by going to your instance (e.g. <https://pleroma.soykaf.com>). You can read more about it's basic functionality in the [Pleroma-FE User Guide](./user_guide/). We also have [a guide for administrators](./CONFIGURATION.md) and for [hackers/contributors](./HACKING.md).
+44
View File
@@ -0,0 +1,44 @@
# General overview
> Be prepared for breaking changes, unexpected behavior and this user guide becoming obsolete and wrong.
> If there was no insanity
>
> it would be necessary to create it.
>
> --Catbag
Pleroma-FE is the default user-facing frontend for Pleroma. If your instance uses Pleroma-FE, you can access it by going to your instance (e.g. <https://pleroma.soykaf.com>). After logging in you will have two columns in front of you. Here we're going to keep it to the default behaviour, but some instances swap the left and right columns. If you're on such an instance what we refer to as the left column will be on your right and vice versa.
### Left column
- first block: This section is dedicated to [posting](posting_reading_basic_functions.md)
- second block: Here you can switch between the different views for the right column.
- Optional third block: This is the Instance panel that can be activated, but is deactivated by default. It's fully customisable by instance admins and by default has links to the Pleroma-FE and Mastodon-FE.
- fourth block: This is the Notifications block, here you will get notified whenever somebody mentions you, follows you, repeats or favorites one of your statuses
### Right column
This is where the interesting stuff happens! There are different views depending on what you choose in the second block of the left panel.
- **Timelines** Depending on the [timeline](timelines.md) you will see different statuses, but each status has a standard structure:
- Profile pic, name and link to profile. An optional left-arrow if it's a reply to another status (hovering will reveal the reply-to status). Clicking on the profile pic will uncollapse the user's profile where you can find information about the account and can [follow, mute or block the account](users_follow_mute_block.md).
- An arrow icon on the right side allows you to open the status on the instance where it's originating from.
- A `+` button on the rightmost side allows you to Expand/Collapse an entire discussion thread.
- The text of the status, including mentions and attachments. If you click on a mention, it will automatically open the profile page of that person.
- Four buttons (left to right): Reply, Repeat, Favorite and Add Reaction. The three dots next to it are a dropdown menu for extra options including simple moderation, bookmarking, deleting posts, pinning your own posts to your profile and more.
- **Interactions** shows all interactions you've had with people on the network, basically same as notifications except grouped in convenient way.
- **Chats** is the chat feature. You can find your friends and start chatting with them. At the moment chat are only one-on-one, but once groups are introduced groupchats will also be possible.
- **About** is the about-page and lists the staff, the TOS, activated MRF's, and enabled features
### Top right
- The magnifier icon opens the search screen
- You can search for statuses, people and hashtags.
- You can import statuses from remote servers by pasting the url to the post in the search field.
- If you want to search for users that your instance doesn't know about yet, you can search for them using the full `name@instance.tld` handle. You can also use the full url from their remote profile.
- The gear icon gives you [settings](settings.md)
- If you have admin rights, you'll see an icon that opens the admin interface
- The last icon is to log out
### Bottom right
On the bottom right you have the Shoutbox. Here you can communicate with people on the same instance in realtime. It is local-only, very basic and will most probably be removed once the Chats functionality allows group chats.
@@ -0,0 +1,76 @@
# Posting, reading, basic functions.
!!! warning
Depending on your instance some of the options might not be available or have different defaults
After registering and logging in you're presented with your timeline in right column and new post form with timeline list and notifications in the left column.
Posts will contain the text you are posting, but some content will be modified:
1. Mentions: Mentions have the form of @user or @user<span></span>@instance.tld. These will become links to the user's profile. In addition, the mentioned user will always get a notification about the post they have been mentioned in, so only mention users that you want to receive this message.
2. URLs: URLs like `http://example.com` will be automatically be turned into a clickable links.
3. Hashtags: Hashtags like #cofe will also be turned into links.
4. There is a default character limit of 5000 characters.
Let's clear up some basic stuff. When you post something it's called a **post** or it could be called a **status** or even a **toot** or a **prööt** depending on whom you ask. Post has body/content but it also has some other stuff in it - from attachments, visibility scope, subject line...
**Emoji** are small images embedded in text, there are two major types of emoji: [unicode emoji](https://en.wikipedia.org/wiki/Emoji) and custom emoji. While unicode emoji are universal and standardized, they can appear differently depending on where you are using them or may not appear at all on older systems. Custom emoji are a more *fun* kind - instance administrator can define many images as *custom emoji* for their users. This works very simple - custom emoji is defined by its *shortcode* and an image, so that any shortcode enclosed in colons get replaced with image if such shortcode exist.
Let's say there's a `:pleroma:` emoji defined on an instance. That means
> First time using :pleroma: pleroma!
will become
> First time using ![pleroma](../assets/example_emoji.png) pleroma!
Note that you can only use emoji defined on your instance, you cannot "copy" someone else's emoji, and will have to ask your administrator to copy emoji from other instance to yours.
Lastly, there's two convenience options for emoji: an emoji picker (smiley face to the right of "submit" button) and autocomplete suggestions - when you start typing :shortcode: it will automatically try to suggest you emoji and complete the shortcode for you if you select one. If emoji doesn't show up in suggestions nor in emoji picker it means there's no such emoji on your instance, if shortcode doesn't match any defined emoji it will appear as text.
**Attachments** are fairly simple - you can attach any file to a post as long as the file is within maximum size limits. If you're uploading explicit material you can mark all of your attachments as sensitive (or add the `#nsfw` tag) - it will hide the images and videos behind a warning so that it won't be displayed instantly.
**Subject line** also known as **CW** (Content Warning) could be used as a header to the post and/or to warn others about contents of the post having something that might upset somebody or something among those lines. Several applications allow to hide post content leaving only subject line visible. Using a subject line will not mark your images as sensitive, you will have to do that explicitly (see above).
**Visiblity scope** controls who will be able to see your posts. There are four scopes available:
1. `Public`: This is the default, and some fediverse software, like GNU Social, only supports this. This means that your post is accessible by anyone and will be shown in the public timelines.
2. `Unlisted`: This is the same as public, but your post won't appear in the public timelines. The post will still be accessible by anyone who comes across it (for example, by looking at your profile) or by direct linking. They will also appear in public searches.
3. `Followers only`: This will show your post only to your followers. Only they will be able to interact with it. Be careful: When somebody follows you, they will be able to see all your previous `followers only` posts as well! If you want to restrict who can follow you, consider [locking your account down to only approved followers](../settings#profile).
4. `Direct`: This will only send the message to the people explicitly mentioned in the post.
A few things to consider about the security and usage of these scopes:
- None of these options will change the fact that the messages are all saved in the database unencrypted. They will be visible to your server admin and to any other admin of a server who receives this post. Do not share information that you would consider secret or dangerous. Use encrypted messaging systems for these things.
- Follower-only posts can lead to fragmented conversations. If you post a follower-only post and somebody else replies to it with a follower-only post, only people following both of you will see the whole conversation thread. Everybody else will only see half of it. Keep this in mind and keep conversations public if possible.
- Changing scopes during a thread or adding people to a direct message will not retroactively make them see the whole conversation. If you add someone to a direct message conversation, they will not see the post that happened before they were mentioned.
* **Reply-to** if you are replying to someone, your post will also contain a note that your post is referring to the post you're replying to. Person you're replying to will receive a notification *even* if you remove them from mentioned people. You won't receive notifications when replying to your own posts, but it's useful to reply to your own posts to provide people some context if it's a follow-up to a previous post. There's a small "Reply to ..." label under post author's name which you can hover on to see what post it's referring to.
Sometimes you may encounter posts that seem different than what they are supposed to. For example, you might see a direct message without any mentions in the text. This can happen because internally, the Fediverse has a different addressing mechanism similar to email, with `to` and `cc` fields. While these are not directly accessible in PleromaFE, other software in the Fediverse might generate those posts. Do not worry in these cases, these are normal and not a bug.
## Rich text
By default new posts you make are plaintext, meaning you can't make text **bold** or add custom links or make lists or anything like that. However if your instance allows it you can use Markdown or BBCode or HTML to spice up your text, however there are certain limitations to what HTML tags and what features of Markdown you can use.
Here is a small example of some text in markdown.
```
This is an example of markdown text using **bold** and *cursive* text.
To get a newline we add two spaces at the end of the previous line.
Let's also add a list
* with
* some
* items
```
If you set the input-method to Markdown, and post this, it will look something like
![example_markdown](../assets/example_markdown.png)
## Other actions
In addition to posting you can also *favorite* posts also known as *liking* them and *repeat* posts (also known as *retweeting*, *boosting* and even *reprööting*). Favoriting a post increments a counter on it, notifies the post author of your affection towards that post and also adds that post to your "favorited" posts list (in your own profile, "Favorites" tab). Reprööting a post does all that and also repeats this post to your followers and your profile page with a note "*user* repeated post".
Your own posts can be deleted, but this will only reliably delete the post from your own instance. Other instances will receive a deletion notice, but there's no way to force them to actually delete a post. In addition, not all instances that contain the message might even receive the deletion notice, because they might be offline or not known to have the post because they received it through a repeat. Lastly, deletion notice might not reach certain frontends and clients - post will be visible for them until page refresh or cache clear, they probably won't be able to interact with it apart from replying to it (which will have reply-to mark missing).
If you are a moderator, you can also delete posts by other people. If those people are on your instance, it will delete the post and send out the deletion notice to other servers. If they are not on your instance, it will just remove the post from your local instance.
There's also an option to report a user's post which can be used to notify your (and optionally the other instance's) admin that someone is being naughty.
+116
View File
@@ -0,0 +1,116 @@
# Settings
On the top-right you will see a gear icon. Click it to open the settings.
## General
### Interface
- **Interface language** is where you can set the interface language. The default language is the one that you set in your browser settings.
- **Hide instance-specific panel** hides the panel in the lower left that usually contains general information about the server. This will only be visible if your admin has activated this panel and is deactivated by default.
### Timeline
- **Hide posts of muted users** If this is set, 'muting' a user will completely hide their posts instead of collapsing them.
- **Collapse posts with subjects** This will collapse posts that contain a subject, hiding their content. Subjects are also sometimes called content warnings.
- **Enable automatic streaming of new posts when scrolled to the top** With this enabled, new posts will automatically stream in when you are scrolled to the top. Otherwise, you will see a button on the timeline that will let you display the new posts.
- **Pause streaming when tab is not focused** This pauses the automatic streaming that the previous option enables when the tab is out of focus. This is useful if you don't want to miss any new posts.
- **Enable automatic loading when scrolled to the bottom** When this is disabled, a button will be shown on the bottom of the timeline that will let you load older posts.
- **Enable reply-link preview on hover** Status posts in the timeline and notifications contain links to replies and to the post they are a reply to. If this setting is enabled, hovering over that link will display that linked post in a small hovering overlay.
### Composing
- **Copy scope when replying** makes the scope of a reply be the same as the scope of the post it is replying to. This is useful to prevent accidentally moving private discussions to public, or vice versa.
- **Always show subject field** Whether or not to display the 'subject' input field in the post form. If you do not want to use subjects, you can deactivate this.
- **Copy subject when replying** controls if the subject of a post will be copied from the post it is replying to.
- **Post status content type** selects the default content type of your post. The options are: Plain text, HTML, BBCode and Markdown.
- **Minimize scope selection options** will reduce the visibility scopes to 'direct', your default post scope and post scope of post you're replying to.
- **Automatically hide New Post button** hides the floating "New post" button when scrolling on mobile view.
- **Pad emoji with spaces when adding from picker** Will add spaces around emoji you select it from the picker.
### Attachments
- **Hide attachments in timeline** Do not display attachments in timelines. They will still display in expanded conversations. This is useful to save bandwidth and for browsing in public.
- **Hide attachments in conversations** Also hide attachments in expanded conversations.
- **Maximum amount of thumbnails per post** Exactly that :)
- **Enable clickthrough NSFW attachment hiding** Hide attachments that are marked as NSFW/sensitive behind a click-through image.`
- **Preload images** This will preload the hidden images so that they display faster when clicking through.
- **Open NSFW attachments with just one click** Directly open NSFW attachments in a maximised state instead of revealing the image thumbnail.
- **Play-on-hover GIFs** With this activated, GIFs images and avatars will only be animated on mouse hover. Otherwise, they will be always animated. This is very useful if your timeline looks too flashy from people's animated avatars and eases the CPU load.
- **Loop videos** Whether to loop videos indefinitely.
- **Loop only videos without sound** Some instances will use videos without sounds instead of GIFs. This will make only those videos autoplay.
- **Play videos directly in the media viewer** Play videos right in the timeline instead of opening it in a modal
- **Don't crop the attachment in thumbnails** if enabled, images in attachments will be fit entirely inside the container instead of being zoomed in and cropped.
### Notifications
- **Enable web push notifications** this enables Web Push notifications, to allow receiving notifications even when the page isn't opened, doesn't affect regular notifications.
### Fun
- **Meme arrows** will make `> greentext` be shown in green (using the "green" from the theme that is used).
## Profile
Here you can set up how you appear to other users among with some other settings:
- **Name** is text that displays next to your avatar in posts. Please note that you **cannot** change your *@handle*
- **Bio** will be displayed under your profile - you can put anything you want there you want for everyone to see.
- **Restrict your account to approved followers only** makes your account "locked", when people follow you - you have to approve or deny their follow requests, this gives more control over who sees your followers only posts.
- **Default visibility scope** is your default post scope for new posts
- **Strip rich text from all posts** strips rich text formatting (bold/italics/lists etc) from all incoming posts. This will only affect newly fetched posts.
If you're admin or moderator on your instance you also get **Show [role] badge in my profile** - this controls whether to show "Admin" or "Moderator** label on your profile page.
**For all options mentioned above you have to click "Submit" button for changes to take place**
- **Avatar** this changes picture next to your posts. Your avatar shouldn't exceed 2 MiB (2097152 bytes) or it could cause problems with certain instances.
- **Banner** this changes background on your profile card. Same as avatar it shouldn't exceed 2 MiB limit.
- **Profile Background** this changes background picture for UI. It isn't shown to anyone else *yet*, but some time later it will be shown when viewing your profisle.
## Security
Here you can change your password, revoke access tokens, configure 2-factor authentication (if available).
## Filtering
- **Types of notifications to show** This controls what kind of notifications will appear in notification column and which notifications to get in your system outside the web page
- **Replies in timeline** You may know that other social networks like Twitter will often not display replies to other people in your timeline, even if you are following the poster. Pleroma usually will show these posts to you to encourage conversation. If you do not like this behavior, you can change it here.
- **Hide post statistics** This hides the number of favorites, number of replies, etc.
- **Hide user statistics** This hides the number of followers, friends, etc.
- **Muted words** allows a list of words that will be muted (i.e. displayed in a collapsed state) on the timeline and in notifications. An easy way to tune down noise in your timeline. By default posts can be expanded if you want to see them.
- **Hide filtered statuses** will hide the filtered / muted posts completely instead of collapsing them.
## Theme
Here you can change the look and feel of Pleroma-FE. You can choose from several instance-provided presets and you can load one from file and save current theme to file. Before you apply new theme you can see what it will look like approximately in preview section.
The themes engine was made to be easy to use while giving an option for powerful in-depth customization - you can just tweak colors on "Common" tab and leave everything else as is.
If there's a little check box next to a color picker it means that color is optional and unless checked will be automatically picked based on some other color or defaults.
For some features you can also adjust transparency of it by changing its opacity, you just need to tick checkbox next to it, otherwise it will be using default opacity.
Contrast information is also provided - you can see how readable text is based on contrast between text color and background, icons under color pickers represent contrast rating based on [WCAG](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast) - thumbs up means AAA rating (good), half-filled circle means AA rating (acceptable) and warning icon means it doesn't pass the minimal contrast requirement and probably will be less readable, especially for vision-challenged people, you can hover over icon to see more detailed information. *Please note* that if background is not opaque (opacity != 1) contrast will be measured based on "worst case scenario", i.e. behind semi-transparent background lies some solid color that makes text harder to read, this however is still inaccurate because it doesn't account that background can be noisy/busy, making text even harder to read.
Apart from colors you can also tweak shadow and lighting, which is used mostly to give buttons proper relief based on their state, give panes their shade, make things glow etc. It's quite powerful, and basically provides somewhat convenient interface for [CSS Shadows](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow).
Another thing you can tweak is theme's roundness - some people like sharp edges, some want things more rounded. This is also used if you want circled or square avatars.
Lastly, you can redefine fonts used in UI without changing fonts in your browser or system, this however requires you to enter font's full name and having that font installed on your system.
## Notifications
This screen allows more fine-grained control over what notifications to show to you based on whom it comes from.
## Data Import/Export
This allows you to export and import a list of people you follow and block, in case instance's database gets reverted or if you want to move to another server. Note that you **CANNOT export/import list of people who *follow you***, they'll need to follow you back themselves.
## Mutes and Blocks
These screens give access to full list of people you block/mute, useful for *un*blocking/*un*muting people because blocking/muting them most likely removes them out of your sight completely.
## Version
Just displays the backend and frontend version. Useful to mention in bug reports.
+13
View File
@@ -0,0 +1,13 @@
# Timelines
You have several timelines to browse trough
- **Timeline** aka Home Timeline - this timeline contains all posts by people you follow and your own posts, as well as posts mentioning you directly.
- **Bookmarks** all the posts you've bookmarked. You can bookmark a post by clicking the three dots on the bottom right of the post and choose Bookmark.
- **Direct Messages** all posts with `direct` scope addressed to you or mentioning you.
- **Public Timelines** all public posts made by users on the instance you're on
- **The Whole Known Network** also known as **TWKN** or **Federated Timeline** - all public posts known by your instance. Due to nature of the network your instance may not know *all* the posts on the network, so only posts known by your instance are shown there.
Note that by default you will see all posts made by other users on your Home Timeline, this contrast behavior of Twitter and Mastodon, which shows you only non-reply posts and replies to people you follow. You can change said behavior in the [settings](settings.md#filtering).
By default instances will try to send activities (e.g. posts, favorites, etc.) up to 7 days or until the target server received them. For this reason posts that are up to 7 days old and your server didn't know about yet can pop up on your timeline. This is the default behaviour and can be changed by your admin.
@@ -0,0 +1,11 @@
# Users: follow, mute, block
When you see someone, you can click on their user picture to view their profile, and click on the userpic in that to see *full* profile. You can **follow** them, **mute** and **block** them.
**Following** is self-explanatory, it adds them to your Home Timeline, lists you as a follower and gives you access to follower-only posts if they have any.
**Muting** collapses posts and notifications made by them, giving you an option to see the post if you're curious. Clients other than PleromaFE may completely remove their posts.
**Blocking** a user removes them from your timeline and notifications and prevents them from following you (automatically unfollows them from you).
Please note that some users can be "locked", meaning instead of following them you send a follow request they need to approve for you to become their follower.
-1
View File
@@ -3,7 +3,6 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
<title>Pleroma</title>
<!--server-generated-meta--> <!--server-generated-meta-->
<link rel="icon" type="image/png" href="/favicon.png"> <link rel="icon" type="image/png" href="/favicon.png">
</head> </head>
+4 -1
View File
@@ -18,6 +18,10 @@
"dependencies": { "dependencies": {
"@babel/runtime": "^7.7.6", "@babel/runtime": "^7.7.6",
"@chenfengyuan/vue-qrcode": "^1.0.0", "@chenfengyuan/vue-qrcode": "^1.0.0",
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-regular-svg-icons": "^5.15.1",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/vue-fontawesome": "^2.0.0",
"body-scroll-lock": "^2.6.4", "body-scroll-lock": "^2.6.4",
"chromatism": "^3.0.0", "chromatism": "^3.0.0",
"cropperjs": "^1.4.3", "cropperjs": "^1.4.3",
@@ -68,7 +72,6 @@
"eventsource-polyfill": "^0.9.6", "eventsource-polyfill": "^0.9.6",
"express": "^4.13.3", "express": "^4.13.3",
"file-loader": "^3.0.1", "file-loader": "^3.0.1",
"fontello-webpack-plugin": "https://github.com/w3geo/fontello-webpack-plugin.git#6149eac8f2672ab6da089e8802fbfcac98487186",
"function-bind": "^1.0.2", "function-bind": "^1.0.2",
"html-webpack-plugin": "^3.0.0", "html-webpack-plugin": "^3.0.0",
"http-proxy-middleware": "^0.17.2", "http-proxy-middleware": "^0.17.2",
+14 -56
View File
@@ -1,7 +1,6 @@
import UserPanel from './components/user_panel/user_panel.vue' import UserPanel from './components/user_panel/user_panel.vue'
import NavPanel from './components/nav_panel/nav_panel.vue' import NavPanel from './components/nav_panel/nav_panel.vue'
import Notifications from './components/notifications/notifications.vue' import Notifications from './components/notifications/notifications.vue'
import SearchBar from './components/search_bar/search_bar.vue'
import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue' import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
import FeaturesPanel from './components/features_panel/features_panel.vue' import FeaturesPanel from './components/features_panel/features_panel.vue'
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue' import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
@@ -11,10 +10,12 @@ import MediaModal from './components/media_modal/media_modal.vue'
import SideDrawer from './components/side_drawer/side_drawer.vue' import SideDrawer from './components/side_drawer/side_drawer.vue'
import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue' import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
import MobileNav from './components/mobile_nav/mobile_nav.vue' import MobileNav from './components/mobile_nav/mobile_nav.vue'
import DesktopNav from './components/desktop_nav/desktop_nav.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue' import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
import PostStatusModal from './components/post_status_modal/post_status_modal.vue' import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue' import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
import { windowWidth, windowHeight } from './services/window_utils/window_utils' import { windowWidth, windowHeight } from './services/window_utils/window_utils'
import { mapGetters } from 'vuex'
export default { export default {
name: 'app', name: 'app',
@@ -22,7 +23,6 @@ export default {
UserPanel, UserPanel,
NavPanel, NavPanel,
Notifications, Notifications,
SearchBar,
InstanceSpecificPanel, InstanceSpecificPanel,
FeaturesPanel, FeaturesPanel,
WhoToFollowPanel, WhoToFollowPanel,
@@ -31,21 +31,14 @@ export default {
SideDrawer, SideDrawer,
MobilePostStatusButton, MobilePostStatusButton,
MobileNav, MobileNav,
DesktopNav,
SettingsModal, SettingsModal,
UserReportingModal, UserReportingModal,
PostStatusModal, PostStatusModal,
GlobalNoticeList GlobalNoticeList
}, },
data: () => ({ data: () => ({
mobileActivePanel: 'timeline', mobileActivePanel: 'timeline'
searchBarHidden: true,
supportsMask: window.CSS && window.CSS.supports && (
window.CSS.supports('mask-size', 'contain') ||
window.CSS.supports('-webkit-mask-size', 'contain') ||
window.CSS.supports('-moz-mask-size', 'contain') ||
window.CSS.supports('-ms-mask-size', 'contain') ||
window.CSS.supports('-o-mask-size', 'contain')
)
}), }),
created () { created () {
// Load the locale from the storage // Load the locale from the storage
@@ -58,44 +51,21 @@ export default {
}, },
computed: { computed: {
currentUser () { return this.$store.state.users.currentUser }, currentUser () { return this.$store.state.users.currentUser },
background () { userBackground () { return this.currentUser.background_image },
return this.currentUser.background_image || this.$store.state.instance.background instanceBackground () {
return this.mergedConfig.hideInstanceWallpaper
? null
: this.$store.state.instance.background
}, },
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask }, background () { return this.userBackground || this.instanceBackground },
logoStyle () {
return {
'visibility': this.enableMask ? 'hidden' : 'visible'
}
},
logoMaskStyle () {
return this.enableMask ? {
'mask-image': `url(${this.$store.state.instance.logo})`
} : {
'background-color': this.enableMask ? '' : 'transparent'
}
},
logoBgStyle () {
return Object.assign({
'margin': `${this.$store.state.instance.logoMargin} 0`,
opacity: this.searchBarHidden ? 1 : 0
}, this.enableMask ? {} : {
'background-color': this.enableMask ? '' : 'transparent'
})
},
logo () { return this.$store.state.instance.logo },
bgStyle () { bgStyle () {
return { if (this.background) {
'background-image': `url(${this.background})`
}
},
bgAppStyle () {
return { return {
'--body-background-image': `url(${this.background})` '--body-background-image': `url(${this.background})`
} }
}
}, },
sitename () { return this.$store.state.instance.name },
chat () { return this.$store.state.chat.channel.state === 'joined' }, chat () { return this.$store.state.chat.channel.state === 'joined' },
hideSitename () { return this.$store.state.instance.hideSitename },
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled }, suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
showInstanceSpecificPanel () { showInstanceSpecificPanel () {
return this.$store.state.instance.showInstanceSpecificPanel && return this.$store.state.instance.showInstanceSpecificPanel &&
@@ -109,22 +79,10 @@ export default {
return { return {
'order': this.$store.state.instance.sidebarRight ? 99 : 0 'order': this.$store.state.instance.sidebarRight ? 99 : 0
} }
} },
...mapGetters(['mergedConfig'])
}, },
methods: { methods: {
scrollToTop () {
window.scrollTo(0, 0)
},
logout () {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
},
onSearchBarToggled (hidden) {
this.searchBarHidden = hidden
},
openSettingsModal () {
this.$store.dispatch('openSettingsModal')
},
updateMobileState () { updateMobileState () {
const mobileLayout = windowWidth() <= 800 const mobileLayout = windowWidth() <= 800
const layoutHeight = windowHeight() const layoutHeight = windowHeight()
+81 -158
View File
@@ -14,7 +14,9 @@
right: -20px; right: -20px;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 50%; background-color: var(--wallpaper);
background-image: var(--body-background-image);
background-position: 50% 50px;
} }
i[class^='icon-'] { i[class^='icon-'] {
@@ -33,6 +35,7 @@ h4 {
max-width: 980px; max-width: 980px;
align-content: flex-start; align-content: flex-start;
} }
.underlay { .underlay {
background-color: rgba(0,0,0,0.15); background-color: rgba(0,0,0,0.15);
background-color: var(--underlay, rgba(0,0,0,0.15)); background-color: var(--underlay, rgba(0,0,0,0.15));
@@ -69,7 +72,7 @@ a {
color: var(--link, $fallback--link); color: var(--link, $fallback--link);
} }
button { .button-default {
user-select: none; user-select: none;
color: $fallback--text; color: $fallback--text;
color: var(--btnText, $fallback--text); color: var(--btnText, $fallback--text);
@@ -85,7 +88,8 @@ button {
font-family: sans-serif; font-family: sans-serif;
font-family: var(--interfaceFont, sans-serif); font-family: var(--interfaceFont, sans-serif);
i[class*=icon-] { i[class*=icon-],
.svg-inline--fa {
color: $fallback--text; color: $fallback--text;
color: var(--btnText, $fallback--text); color: var(--btnText, $fallback--text);
} }
@@ -106,6 +110,8 @@ button {
color: var(--btnPressedText, $fallback--text); color: var(--btnPressedText, $fallback--text);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--btnPressed, $fallback--fg); background-color: var(--btnPressed, $fallback--fg);
svg,
i { i {
color: $fallback--text; color: $fallback--text;
color: var(--btnPressedText, $fallback--text); color: var(--btnPressedText, $fallback--text);
@@ -118,6 +124,8 @@ button {
color: var(--btnDisabledText, $fallback--text); color: var(--btnDisabledText, $fallback--text);
background-color: $fallback--fg; background-color: $fallback--fg;
background-color: var(--btnDisabled, $fallback--fg); background-color: var(--btnDisabled, $fallback--fg);
svg,
i { i {
color: $fallback--text; color: $fallback--text;
color: var(--btnDisabledText, $fallback--text); color: var(--btnDisabledText, $fallback--text);
@@ -131,6 +139,8 @@ button {
background-color: var(--btnToggled, $fallback--fg); background-color: var(--btnToggled, $fallback--fg);
box-shadow: 0px 0px 4px 0px rgba(255, 255, 255, 0.3), 0px 1px 0px 0px rgba(0, 0, 0, 0.2) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.2) inset; box-shadow: 0px 0px 4px 0px rgba(255, 255, 255, 0.3), 0px 1px 0px 0px rgba(0, 0, 0, 0.2) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.2) inset;
box-shadow: var(--buttonPressedShadow); box-shadow: var(--buttonPressedShadow);
svg,
i { i {
color: $fallback--text; color: $fallback--text;
color: var(--btnToggledText, $fallback--text); color: var(--btnToggledText, $fallback--text);
@@ -146,6 +156,30 @@ button {
} }
} }
.button-unstyled {
background: none;
border: none;
outline: none;
display: inline;
text-align: initial;
font-size: 100%;
font-family: inherit;
padding: 0;
line-height: unset;
cursor: pointer;
box-sizing: content-box;
color: inherit;
&.-link {
color: $fallback--link;
color: var(--link, $fallback--link);
}
&.-fullwidth {
width: 100%;
}
}
input, textarea, .select, .input { input, textarea, .select, .input {
&.unstyled { &.unstyled {
@@ -185,7 +219,7 @@ input, textarea, .select, .input {
opacity: 0.5; opacity: 0.5;
} }
.icon-down-open { .select-down-icon {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
@@ -279,7 +313,7 @@ input, textarea, .select, .input {
+ label::before { + label::before {
flex-shrink: 0; flex-shrink: 0;
display: inline-block; display: inline-block;
content: ''; content: '';
transition: color 200ms; transition: color 200ms;
width: 1.1em; width: 1.1em;
height: 1.1em; height: 1.1em;
@@ -300,6 +334,10 @@ input, textarea, .select, .input {
box-sizing: border-box; box-sizing: border-box;
} }
} }
&.resize-height {
resize: vertical;
}
} }
option { option {
@@ -318,7 +356,7 @@ option {
} }
} }
i[class*=icon-] { i[class*=icon-], .svg-inline--fa {
color: $fallback--icon; color: $fallback--icon;
color: var(--icon, $fallback--icon); color: var(--icon, $fallback--icon);
} }
@@ -356,117 +394,10 @@ i[class*=icon-] {
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
} }
.item {
flex: 1;
line-height: 50px;
height: 50px;
overflow: hidden;
display: flex;
flex-wrap: wrap;
.nav-icon {
margin-left: 0.4em;
}
&.right {
justify-content: flex-end;
}
}
.auto-size { .auto-size {
flex: 1 flex: 1
} }
.nav-bar {
padding: 0;
width: 100%;
align-items: center;
position: fixed;
height: 50px;
box-sizing: border-box;
button {
&, i[class*=icon-] {
color: $fallback--text;
color: var(--btnTopBarText, $fallback--text);
}
&:active {
background-color: $fallback--fg;
background-color: var(--btnPressedTopBar, $fallback--fg);
color: $fallback--text;
color: var(--btnPressedTopBarText, $fallback--text);
}
&:disabled {
color: $fallback--text;
color: var(--btnDisabledTopBarText, $fallback--text);
}
&.toggled {
color: $fallback--text;
color: var(--btnToggledTopBarText, $fallback--text);
background-color: $fallback--fg;
background-color: var(--btnToggledTopBar, $fallback--fg)
}
}
.logo {
display: flex;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
align-items: stretch;
justify-content: center;
flex: 0 0 auto;
z-index: -1;
transition: opacity;
transition-timing-function: ease-out;
transition-duration: 100ms;
.mask {
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
background-color: $fallback--fg;
background-color: var(--topBarText, $fallback--fg);
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
img {
height: 100%;
object-fit: contain;
display: block;
flex: 0;
}
}
.inner-nav {
position: relative;
margin: auto;
box-sizing: border-box;
padding-left: 10px;
padding-right: 10px;
display: flex;
align-items: center;
flex-basis: 970px;
height: 50px;
a, a i {
color: $fallback--link;
color: var(--topBarLink, $fallback--link);
}
}
}
main-router { main-router {
flex: 1; flex: 1;
} }
@@ -546,6 +477,7 @@ main-router {
color: $fallback--faint; color: $fallback--faint;
color: var(--panelFaint, $fallback--faint); color: var(--panelFaint, $fallback--faint);
} }
.faint-link { .faint-link {
color: $fallback--faint; color: $fallback--faint;
color: var(--faintLink, $fallback--faint); color: var(--faintLink, $fallback--faint);
@@ -557,11 +489,8 @@ main-router {
overflow-x: hidden; overflow-x: hidden;
} }
button { .button-default,
flex-shrink: 0; .alert {
}
button, .alert {
// height: 100%; // height: 100%;
line-height: 21px; line-height: 21px;
min-height: 0; min-height: 0;
@@ -572,8 +501,11 @@ main-router {
align-self: stretch; align-self: stretch;
} }
button { .button-default {
&, i[class*=icon-] { flex-shrink: 0;
&,
i[class*=icon-] {
color: $fallback--text; color: $fallback--text;
color: var(--btnPanelText, $fallback--text); color: var(--btnPanelText, $fallback--text);
} }
@@ -596,7 +528,8 @@ main-router {
} }
} }
a { a,
.-link {
color: $fallback--link; color: $fallback--link;
color: var(--panelLink, $fallback--link) color: var(--panelLink, $fallback--link)
} }
@@ -611,15 +544,15 @@ main-router {
border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius); border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
.faint { .faint {
color: $fallback--faint; color: $fallback--faint;
color: var(--panelFaint, $fallback--faint); color: var(--panelFaint, $fallback--faint);
} }
a { a,
.-link {
color: $fallback--link; color: $fallback--link;
color: var(--panelLink, $fallback--link) color: var(--panelLink, $fallback--link);
} }
} }
@@ -707,19 +640,24 @@ nav {
flex-grow: 0; flex-grow: 0;
} }
} }
.badge { .badge {
box-sizing: border-box;
display: inline-block; display: inline-block;
border-radius: 99px; border-radius: 99px;
min-width: 22px; max-width: 10em;
max-width: 22px; min-width: 1.7em;
min-height: 22px; height: 1.3em;
max-height: 22px; padding: 0.15em 0.15em;
font-size: 15px;
line-height: 22px;
text-align: center;
vertical-align: middle; vertical-align: middle;
font-weight: normal;
font-style: normal;
font-size: 0.9em;
line-height: 1;
text-align: center;
white-space: nowrap; white-space: nowrap;
padding: 0; overflow: hidden;
text-overflow: ellipsis;
&.badge-notification { &.badge-notification {
background-color: $fallback--cRed; background-color: $fallback--cRed;
@@ -776,16 +714,6 @@ nav {
} }
} }
@media all and (min-width: 800px) {
.logo {
opacity: 1 !important;
}
}
.item.right {
text-align: right;
}
.visibility-notice { .visibility-notice {
padding: .5em; padding: .5em;
border: 1px solid $fallback--faint; border: 1px solid $fallback--faint;
@@ -807,8 +735,16 @@ nav {
} }
} }
.button-icon { .fa-scale-110 {
font-size: 1.2em; &.svg-inline--fa {
font-size: 1.1em;
}
}
.fa-old-padding {
&.svg-inline--fa {
padding: 0 0.3em;
}
} }
@keyframes shakeError { @keyframes shakeError {
@@ -898,7 +834,7 @@ nav {
} }
} }
.btn.btn-default { .btn.button-default {
min-height: 28px; min-height: 28px;
} }
@@ -930,19 +866,6 @@ nav {
background-color: var(--panel, $fallback--fg); background-color: var(--panel, $fallback--fg);
} }
.unread-chat-count {
font-size: 0.9em;
font-weight: bolder;
font-style: normal;
position: absolute;
right: 0.6rem;
padding: 0 0.3em;
min-width: 1.3rem;
min-height: 1.3rem;
max-height: 1.3rem;
line-height: 1.3rem;
}
.chat-layout { .chat-layout {
// Needed for smoother chat navigation in the desktop Safari (otherwise the chat layout "jumps" as the chat opens). // Needed for smoother chat navigation in the desktop Safari (otherwise the chat layout "jumps" as the chat opens).
overflow: hidden; overflow: hidden;
+2 -70
View File
@@ -1,82 +1,14 @@
<template> <template>
<div <div
id="app" id="app"
:style="bgAppStyle" :style="bgStyle"
> >
<div <div
id="app_bg_wrapper" id="app_bg_wrapper"
class="app-bg-wrapper" class="app-bg-wrapper"
:style="bgStyle"
/> />
<MobileNav v-if="isMobileLayout" /> <MobileNav v-if="isMobileLayout" />
<nav <DesktopNav v-else />
v-else
id="nav"
class="nav-bar container"
@click="scrollToTop()"
>
<div class="inner-nav">
<div
class="logo"
:style="logoBgStyle"
>
<div
class="mask"
:style="logoMaskStyle"
/>
<img
:src="logo"
:style="logoStyle"
>
</div>
<div class="item">
<router-link
v-if="!hideSitename"
class="site-name"
:to="{ name: 'root' }"
active-class="home"
>
{{ sitename }}
</router-link>
</div>
<div class="item right">
<search-bar
v-if="currentUser || !privateMode"
class="nav-icon mobile-hidden"
@toggled="onSearchBarToggled"
@click.stop.native
/>
<a
href="#"
class="mobile-hidden"
@click.stop="openSettingsModal"
>
<i
class="button-icon icon-cog nav-icon"
:title="$t('nav.preferences')"
/>
</a>
<a
v-if="currentUser && currentUser.role === 'admin'"
href="/pleroma/admin/#/login-pleroma"
class="mobile-hidden"
target="_blank"
><i
class="button-icon icon-gauge nav-icon"
:title="$t('nav.administration')"
/></a>
<a
v-if="currentUser"
href="#"
class="mobile-hidden"
@click.prevent="logout"
><i
class="button-icon icon-logout nav-icon"
:title="$t('login.logout')"
/></a>
</div>
</div>
</nav>
<div class="app-bg-wrapper app-container-wrapper" /> <div class="app-bg-wrapper app-container-wrapper" />
<div <div
id="content" id="content"
+4
View File
@@ -7,6 +7,7 @@ import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js' import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import { applyTheme } from '../services/style_setter/style_setter.js' import { applyTheme } from '../services/style_setter/style_setter.js'
import FaviconService from '../services/favicon_service/favicon_service.js'
let staticInitialResults = null let staticInitialResults = null
@@ -130,6 +131,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
? 0 ? 0
: config.logoMargin : config.logoMargin
}) })
copyInstanceOption('logoLeft')
store.commit('authFlow/setInitialStrategy', config.loginMethod) store.commit('authFlow/setInitialStrategy', config.loginMethod)
copyInstanceOption('redirectRootNoLogin') copyInstanceOption('redirectRootNoLogin')
@@ -325,6 +327,8 @@ const afterStoreSetup = async ({ store, i18n }) => {
const width = windowWidth() const width = windowWidth()
store.dispatch('setMobileLayout', width <= 800) store.dispatch('setMobileLayout', width <= 800)
FaviconService.initFaviconService()
const overrides = window.___pleromafe_dev_overrides || {} const overrides = window.___pleromafe_dev_overrides || {}
const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin
store.dispatch('setInstanceOption', { name: 'server', value: server }) store.dispatch('setInstanceOption', { name: 'server', value: server })
@@ -1,6 +1,14 @@
import { mapState } from 'vuex' import { mapState } from 'vuex'
import ProgressButton from '../progress_button/progress_button.vue' import ProgressButton from '../progress_button/progress_button.vue'
import Popover from '../popover/popover.vue' import Popover from '../popover/popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faEllipsisV
} from '@fortawesome/free-solid-svg-icons'
library.add(
faEllipsisV
)
const AccountActions = { const AccountActions = {
props: [ props: [
@@ -1,9 +1,10 @@
<template> <template>
<div class="account-actions"> <div class="AccountActions">
<Popover <Popover
trigger="click" trigger="click"
placement="bottom" placement="bottom"
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
remove-padding
> >
<div <div
slot="content" slot="content"
@@ -13,14 +14,14 @@
<template v-if="relationship.following"> <template v-if="relationship.following">
<button <button
v-if="relationship.showing_reblogs" v-if="relationship.showing_reblogs"
class="btn btn-default dropdown-item" class="btn button-default dropdown-item"
@click="hideRepeats" @click="hideRepeats"
> >
{{ $t('user_card.hide_repeats') }} {{ $t('user_card.hide_repeats') }}
</button> </button>
<button <button
v-if="!relationship.showing_reblogs" v-if="!relationship.showing_reblogs"
class="btn btn-default dropdown-item" class="btn button-default dropdown-item"
@click="showRepeats" @click="showRepeats"
> >
{{ $t('user_card.show_repeats') }} {{ $t('user_card.show_repeats') }}
@@ -32,27 +33,27 @@
</template> </template>
<button <button
v-if="relationship.blocking" v-if="relationship.blocking"
class="btn btn-default btn-block dropdown-item" class="btn button-default btn-block dropdown-item"
@click="unblockUser" @click="unblockUser"
> >
{{ $t('user_card.unblock') }} {{ $t('user_card.unblock') }}
</button> </button>
<button <button
v-else v-else
class="btn btn-default btn-block dropdown-item" class="btn button-default btn-block dropdown-item"
@click="blockUser" @click="blockUser"
> >
{{ $t('user_card.block') }} {{ $t('user_card.block') }}
</button> </button>
<button <button
class="btn btn-default btn-block dropdown-item" class="btn button-default btn-block dropdown-item"
@click="reportUser" @click="reportUser"
> >
{{ $t('user_card.report') }} {{ $t('user_card.report') }}
</button> </button>
<button <button
v-if="pleromaChatMessagesAvailable" v-if="pleromaChatMessagesAvailable"
class="btn btn-default btn-block dropdown-item" class="btn button-default btn-block dropdown-item"
@click="openChat" @click="openChat"
> >
{{ $t('user_card.message') }} {{ $t('user_card.message') }}
@@ -61,9 +62,12 @@
</div> </div>
<div <div
slot="trigger" slot="trigger"
class="btn btn-default ellipsis-button" class="ellipsis-button"
> >
<i class="icon-ellipsis trigger-button" /> <FAIcon
class="icon"
icon="ellipsis-v"
/>
</div> </div>
</Popover> </Popover>
</div> </div>
@@ -73,22 +77,22 @@
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
.account-actions { .AccountActions {
margin: 0 .8em; button.dropdown-item {
}
.account-actions button.dropdown-item {
margin-left: 0; margin-left: 0;
} }
.account-actions .trigger-button { .ellipsis-button {
cursor: pointer;
width: 2.5em;
margin: -0.5em 0;
padding: 0.5em 0;
text-align: center;
&:not(:hover) .icon {
color: $fallback--lightText; color: $fallback--lightText;
color: var(--lightText, $fallback--lightText); color: var(--lightText, $fallback--lightText);
opacity: .8; }
cursor: pointer;
&:hover {
color: $fallback--text;
color: var(--text, $fallback--text);
} }
} }
</style> </style>
@@ -8,7 +8,7 @@
{{ $t('general.error_retry') }} {{ $t('general.error_retry') }}
</p> </p>
<button <button
class="btn" class="btn button-default"
@click="retry" @click="retry"
> >
{{ $t('general.retry') }} {{ $t('general.retry') }}
+22 -4
View File
@@ -3,6 +3,24 @@ import VideoAttachment from '../video_attachment/video_attachment.vue'
import nsfwImage from '../../assets/nsfw.png' import nsfwImage from '../../assets/nsfw.png'
import fileTypeService from '../../services/file_type/file_type.service.js' import fileTypeService from '../../services/file_type/file_type.service.js'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faFile,
faMusic,
faImage,
faVideo,
faPlayCircle,
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faFile,
faMusic,
faImage,
faVideo,
faPlayCircle,
faTimes
)
const Attachment = { const Attachment = {
props: [ props: [
@@ -39,10 +57,10 @@ const Attachment = {
return this.attachment.description return this.attachment.description
}, },
placeholderIconClass () { placeholderIconClass () {
if (this.type === 'image') return 'icon-picture' if (this.type === 'image') return 'image'
if (this.type === 'video') return 'icon-video' if (this.type === 'video') return 'video'
if (this.type === 'audio') return 'icon-music' if (this.type === 'audio') return 'music'
return 'icon-doc' return 'file'
}, },
referrerpolicy () { referrerpolicy () {
return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer' return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer'
+34 -18
View File
@@ -12,7 +12,7 @@
:alt="attachment.description" :alt="attachment.description"
:title="attachment.description" :title="attachment.description"
> >
<span :class="placeholderIconClass" /> <FAIcon :icon="placeholderIconClass" />
<b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }} <b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }}
</a> </a>
</div> </div>
@@ -28,7 +28,7 @@
:href="attachment.url" :href="attachment.url"
:alt="attachment.description" :alt="attachment.description"
:title="attachment.description" :title="attachment.description"
@click.prevent="toggleHidden" @click.prevent.stop="toggleHidden"
> >
<img <img
:key="nsfwImage" :key="nsfwImage"
@@ -36,20 +36,19 @@
:src="nsfwImage" :src="nsfwImage"
:class="{'small': isSmall}" :class="{'small': isSmall}"
> >
<i <FAIcon
v-if="type === 'video'" v-if="type === 'video'"
class="play-icon icon-play-circled" class="play-icon"
icon="play-circle"
/> />
</a> </a>
<div <button
v-if="nsfw && hideNsfwLocal && !hidden" v-if="nsfw && hideNsfwLocal && !hidden"
class="hider" class="button-unstyled hider"
>
<a
href="#"
@click.prevent="toggleHidden" @click.prevent="toggleHidden"
>Hide</a> >
</div> <FAIcon icon="times" />
</button>
<a <a
v-if="type === 'image' && (!hidden || preloadImage)" v-if="type === 'image' && (!hidden || preloadImage)"
@@ -80,10 +79,13 @@
class="video" class="video"
:attachment="attachment" :attachment="attachment"
:controls="allowPlay" :controls="allowPlay"
@play="$emit('play')"
@pause="$emit('pause')"
/> />
<i <FAIcon
v-if="!allowPlay" v-if="!allowPlay"
class="play-icon icon-play-circled" class="play-icon"
icon="play-circle"
/> />
</a> </a>
@@ -93,6 +95,8 @@
:alt="attachment.description" :alt="attachment.description"
:title="attachment.description" :title="attachment.description"
controls controls
@play="$emit('play')"
@pause="$emit('pause')"
/> />
<div <div
@@ -138,6 +142,10 @@
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: 100%; max-width: 100%;
svg {
color: inherit;
}
} }
.nsfw-placeholder { .nsfw-placeholder {
@@ -224,15 +232,23 @@
.hider { .hider {
position: absolute; position: absolute;
right: 0; right: 0;
white-space: nowrap;
margin: 10px; margin: 10px;
padding: 5px; padding: 0;
background: rgba(230,230,230,0.6);
font-weight: bold;
z-index: 4; z-index: 4;
line-height: 1;
border-radius: $fallback--tooltipRadius; border-radius: $fallback--tooltipRadius;
border-radius: var(--tooltipRadius, $fallback--tooltipRadius); border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
text-align: center;
width: 2em;
height: 2em;
font-size: 1.25em;
// TODO: theming? hard to theme with unknown background image color
background: rgba(230, 230, 230, 0.7);
.svg-inline--fa {
color: rgba(0, 0, 0, 0.6);
}
&:hover .svg-inline--fa {
color: rgba(0, 0, 0, 0.9);
}
} }
video { video {
+2 -2
View File
@@ -3,7 +3,7 @@
<div class="block-card-content-container"> <div class="block-card-content-container">
<button <button
v-if="blocked" v-if="blocked"
class="btn btn-default" class="btn button-default"
:disabled="progress" :disabled="progress"
@click="unblockUser" @click="unblockUser"
> >
@@ -16,7 +16,7 @@
</button> </button>
<button <button
v-else v-else
class="btn btn-default" class="btn button-default"
:disabled="progress" :disabled="progress"
@click="blockUser" @click="blockUser"
> >
+96 -28
View File
@@ -5,11 +5,25 @@ import ChatMessage from '../chat_message/chat_message.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue' import PostStatusForm from '../post_status_form/post_status_form.vue'
import ChatTitle from '../chat_title/chat_title.vue' import ChatTitle from '../chat_title/chat_title.vue'
import chatService from '../../services/chat_service/chat_service.js' import chatService from '../../services/chat_service/chat_service.js'
import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContainerHeight } from './chat_layout_utils.js' import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
import { getScrollPosition, getNewTopPosition, isBottomedOut, scrollableContainerHeight, isScrollable } from './chat_layout_utils.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faChevronDown,
faChevronLeft
} from '@fortawesome/free-solid-svg-icons'
import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
library.add(
faChevronDown,
faChevronLeft
)
const BOTTOMED_OUT_OFFSET = 10 const BOTTOMED_OUT_OFFSET = 10
const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 150 const JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET = 150
const SAFE_RESIZE_TIME_OFFSET = 100 const SAFE_RESIZE_TIME_OFFSET = 100
const MARK_AS_READ_DELAY = 1500
const MAX_RETRIES = 10
const Chat = { const Chat = {
components: { components: {
@@ -23,7 +37,8 @@ const Chat = {
hoveredMessageChainId: undefined, hoveredMessageChainId: undefined,
lastScrollPosition: {}, lastScrollPosition: {},
scrollableContainerHeight: '100%', scrollableContainerHeight: '100%',
errorLoadingChat: false errorLoadingChat: false,
messageRetriers: {}
} }
}, },
created () { created () {
@@ -93,7 +108,7 @@ const Chat = {
const bottomedOutBeforeUpdate = this.bottomedOut(BOTTOMED_OUT_OFFSET) const bottomedOutBeforeUpdate = this.bottomedOut(BOTTOMED_OUT_OFFSET)
this.$nextTick(() => { this.$nextTick(() => {
if (bottomedOutBeforeUpdate) { if (bottomedOutBeforeUpdate) {
this.scrollDown({ forceRead: !document.hidden }) this.scrollDown()
} }
}) })
}, },
@@ -199,15 +214,18 @@ const Chat = {
this.$nextTick(() => { this.$nextTick(() => {
scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior }) scrollable.scrollTo({ top: scrollable.scrollHeight, left: 0, behavior })
}) })
if (forceRead || this.newMessageCount > 0) { if (forceRead) {
this.readChat() this.readChat()
} }
}, },
readChat () { readChat () {
if (!(this.currentChatMessageService && this.currentChatMessageService.lastMessage)) { return } if (!(this.currentChatMessageService && this.currentChatMessageService.maxId)) { return }
if (document.hidden) { return } if (document.hidden) { return }
const lastReadId = this.currentChatMessageService.lastMessage.id const lastReadId = this.currentChatMessageService.maxId
this.$store.dispatch('readChat', { id: this.currentChat.id, lastReadId }) this.$store.dispatch('readChat', {
id: this.currentChat.id,
lastReadId
})
}, },
bottomedOut (offset) { bottomedOut (offset) {
return isBottomedOut(this.$refs.scrollable, offset) return isBottomedOut(this.$refs.scrollable, offset)
@@ -224,12 +242,18 @@ const Chat = {
} else if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) { } else if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) {
this.jumpToBottomButtonVisible = false this.jumpToBottomButtonVisible = false
if (this.newMessageCount > 0) { if (this.newMessageCount > 0) {
this.readChat() // Use a delay before marking as read to prevent situation where new messages
// arrive just as you're leaving the view and messages that you didn't actually
// get to see get marked as read.
window.setTimeout(() => {
// Don't mark as read if the element doesn't exist, user has left chat view
if (this.$el) this.readChat()
}, MARK_AS_READ_DELAY)
} }
} else { } else {
this.jumpToBottomButtonVisible = true this.jumpToBottomButtonVisible = true
} }
}, 100), }, 200),
handleScrollUp (positionBeforeLoading) { handleScrollUp (positionBeforeLoading) {
const positionAfterLoading = getScrollPosition(this.$refs.scrollable) const positionAfterLoading = getScrollPosition(this.$refs.scrollable)
this.$refs.scrollable.scrollTo({ this.$refs.scrollable.scrollTo({
@@ -244,9 +268,9 @@ const Chat = {
const chatId = chatMessageService.chatId const chatId = chatMessageService.chatId
const fetchOlderMessages = !!maxId const fetchOlderMessages = !!maxId
const sinceId = fetchLatest && chatMessageService.lastMessage && chatMessageService.lastMessage.id const sinceId = fetchLatest && chatMessageService.maxId
this.backendInteractor.chatMessages({ id: chatId, maxId, sinceId }) return this.backendInteractor.chatMessages({ id: chatId, maxId, sinceId })
.then((messages) => { .then((messages) => {
// Clear the current chat in case we're recovering from a ws connection loss. // Clear the current chat in case we're recovering from a ws connection loss.
if (isFirstFetch) { if (isFirstFetch) {
@@ -263,6 +287,14 @@ const Chat = {
if (isFirstFetch) { if (isFirstFetch) {
this.updateScrollableContainerHeight() this.updateScrollableContainerHeight()
} }
// In vertical screens, the first batch of fetched messages may not always take the
// full height of the scrollable container.
// If this is the case, we want to fetch the messages until the scrollable container
// is fully populated so that the user has the ability to scroll up and load the history.
if (!isScrollable(this.$refs.scrollable) && messages.length > 0) {
this.fetchChat({ maxId: this.currentChatMessageService.minId })
}
}) })
}) })
}) })
@@ -287,23 +319,11 @@ const Chat = {
}, },
doStartFetching () { doStartFetching () {
this.$store.dispatch('startFetchingCurrentChat', { this.$store.dispatch('startFetchingCurrentChat', {
fetcher: () => setInterval(() => this.fetchChat({ fetchLatest: true }), 5000) fetcher: () => promiseInterval(() => this.fetchChat({ fetchLatest: true }), 5000)
}) })
this.fetchChat({ isFirstFetch: true }) this.fetchChat({ isFirstFetch: true })
}, },
sendMessage ({ status, media }) { handleAttachmentPosting () {
const params = {
id: this.currentChat.id,
content: status
}
if (media[0]) {
params.mediaId = media[0].id
}
return this.backendInteractor.sendChatMessage(params)
.then(data => {
this.$store.dispatch('addChatMessages', { chatId: this.currentChat.id, messages: [data] }).then(() => {
this.$nextTick(() => { this.$nextTick(() => {
this.handleResize() this.handleResize()
// When the posting form size changes because of a media attachment, we need an extra resize // When the posting form size changes because of a media attachment, we need an extra resize
@@ -313,16 +333,64 @@ const Chat = {
}, SAFE_RESIZE_TIME_OFFSET) }, SAFE_RESIZE_TIME_OFFSET)
this.scrollDown({ forceRead: true }) this.scrollDown({ forceRead: true })
}) })
},
sendMessage ({ status, media, idempotencyKey }) {
const params = {
id: this.currentChat.id,
content: status,
idempotencyKey
}
if (media[0]) {
params.mediaId = media[0].id
}
const fakeMessage = buildFakeMessage({
attachments: media,
chatId: this.currentChat.id,
content: status,
userId: this.currentUser.id,
idempotencyKey
})
this.$store.dispatch('addChatMessages', {
chatId: this.currentChat.id,
messages: [fakeMessage]
}).then(() => {
this.handleAttachmentPosting()
})
return this.doSendMessage({ params, fakeMessage, retriesLeft: MAX_RETRIES })
},
doSendMessage ({ params, fakeMessage, retriesLeft = MAX_RETRIES }) {
if (retriesLeft <= 0) return
this.backendInteractor.sendChatMessage(params)
.then(data => {
this.$store.dispatch('addChatMessages', {
chatId: this.currentChat.id,
updateMaxId: false,
messages: [{ ...data, fakeId: fakeMessage.id }]
}) })
return data return data
}) })
.catch(error => { .catch(error => {
console.error('Error sending message', error) console.error('Error sending message', error)
return { this.$store.dispatch('handleMessageError', {
error: this.$t('chats.error_sending_message') chatId: this.currentChat.id,
} fakeId: fakeMessage.id,
isRetry: retriesLeft !== MAX_RETRIES
}) })
if ((error.statusCode >= 500 && error.statusCode < 600) || error.message === 'Failed to fetch') {
this.messageRetriers[fakeMessage.id] = setTimeout(() => {
this.doSendMessage({ params, fakeMessage, retriesLeft: retriesLeft - 1 })
}, 1000 * (2 ** (MAX_RETRIES - retriesLeft)))
}
return {}
})
return Promise.resolve(fakeMessage)
}, },
goBack () { goBack () {
this.$router.push({ name: 'chats', params: { username: this.currentUser.screen_name } }) this.$router.push({ name: 'chats', params: { username: this.currentUser.screen_name } })
+16 -8
View File
@@ -25,7 +25,7 @@
min-height: 100%; min-height: 100%;
margin: 0 0 0 0; margin: 0 0 0 0;
border-radius: 10px 10px 0 0; border-radius: 10px 10px 0 0;
border-radius: var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0 ; border-radius: var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0;
&::after { &::after {
border-radius: 0; border-radius: 0;
@@ -58,12 +58,10 @@
.go-back-button { .go-back-button {
cursor: pointer; cursor: pointer;
margin-right: 1.4em; width: 28px;
text-align: center;
i { padding: 0.6em;
display: flex; margin: -0.6em 0.6em -0.6em -0.6em;
align-items: center;
}
} }
.jump-to-bottom-button { .jump-to-bottom-button {
@@ -78,7 +76,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), 0px 2px 4px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3);
z-index: 10; z-index: 10;
transition: 0.35s all; transition: 0.35s all;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1); transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
@@ -140,11 +138,21 @@
} }
.chat-view-heading { .chat-view-heading {
box-sizing: border-box;
position: static; position: static;
z-index: 9999; z-index: 9999;
top: 0; top: 0;
margin-top: 0; margin-top: 0;
border-radius: 0; border-radius: 0;
/* This practically overlays the panel heading color over panel background
* color. This is needed because we allow transparent panel background and
* it doesn't work well in this "disjointed panel header" case
*/
background:
linear-gradient(to top, var(--panel), var(--panel)),
linear-gradient(to top, var(--bg), var(--bg));
height: 50px;
} }
.scrollable-message-list { .scrollable-message-list {
+8 -3
View File
@@ -14,7 +14,10 @@
class="go-back-button" class="go-back-button"
@click="goBack" @click="goBack"
> >
<i class="button-icon icon-left-open" /> <FAIcon
size="lg"
icon="chevron-left"
/>
</a> </a>
<div class="title text-center"> <div class="title text-center">
<ChatTitle <ChatTitle
@@ -58,14 +61,15 @@
:class="{ 'visible': jumpToBottomButtonVisible }" :class="{ 'visible': jumpToBottomButtonVisible }"
@click="scrollDown({ behavior: 'smooth' })" @click="scrollDown({ behavior: 'smooth' })"
> >
<i class="icon-down-open"> <span>
<FAIcon icon="chevron-down" />
<div <div
v-if="newMessageCount" v-if="newMessageCount"
class="badge badge-notification unread-chat-count unread-message-count" class="badge badge-notification unread-chat-count unread-message-count"
> >
{{ newMessageCount }} {{ newMessageCount }}
</div> </div>
</i> </span>
</div> </div>
<PostStatusForm <PostStatusForm
:disable-subject="true" :disable-subject="true"
@@ -76,6 +80,7 @@
:disable-sensitivity-checkbox="true" :disable-sensitivity-checkbox="true"
:disable-submit="errorLoadingChat || !currentChat" :disable-submit="errorLoadingChat || !currentChat"
:disable-preview="true" :disable-preview="true"
:optimistic-posting="true"
:post-handler="sendMessage" :post-handler="sendMessage"
:submit-on-enter="!mobileLayout" :submit-on-enter="!mobileLayout"
:preserve-focus="!mobileLayout" :preserve-focus="!mobileLayout"
+7
View File
@@ -24,3 +24,10 @@ export const isBottomedOut = (el, offset = 0) => {
export const scrollableContainerHeight = (inner, header, footer) => { export const scrollableContainerHeight = (inner, header, footer) => {
return inner.offsetHeight - header.clientHeight - footer.clientHeight return inner.offsetHeight - header.clientHeight - footer.clientHeight
} }
// Returns whether or not the scrollbar is visible.
export const isScrollable = (el) => {
if (!el) return
return el.scrollHeight > el.clientHeight
}
+4 -1
View File
@@ -10,7 +10,10 @@
<span class="title"> <span class="title">
{{ $t("chats.chats") }} {{ $t("chats.chats") }}
</span> </span>
<button @click="newChat"> <button
class="button-default"
@click="newChat"
>
{{ $t("chats.new") }} {{ $t("chats.new") }}
</button> </button>
</div> </div>
@@ -21,6 +21,12 @@
/> />
</span> </span>
<span class="heading-right" /> <span class="heading-right" />
<div class="time-wrapper">
<Timeago
:time="chat.updated_at"
:auto-update="60"
/>
</div>
</div> </div>
<div class="chat-preview"> <div class="chat-preview">
<StatusContent <StatusContent
@@ -35,12 +41,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="time-wrapper">
<Timeago
:time="chat.updated_at"
:auto-update="60"
/>
</div>
</div> </div>
</template> </template>
@@ -7,6 +7,16 @@ import LinkPreview from '../link-preview/link-preview.vue'
import StatusContent from '../status_content/status_content.vue' import StatusContent from '../status_content/status_content.vue'
import ChatMessageDate from '../chat_message_date/chat_message_date.vue' import ChatMessageDate from '../chat_message_date/chat_message_date.vue'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes,
faEllipsisH
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes,
faEllipsisH
)
const ChatMessage = { const ChatMessage = {
name: 'ChatMessage', name: 'ChatMessage',
+14 -4
View File
@@ -24,16 +24,13 @@
} }
} }
.icon-ellipsis { .menu-icon {
cursor: pointer; cursor: pointer;
&:hover, .extra-button-popover.open & { &:hover, .extra-button-popover.open & {
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
} }
border-radius: $fallback--chatMessageRadius;
border-radius: var(--chatMessageRadius, $fallback--chatMessageRadius);
} }
.popover { .popover {
@@ -101,6 +98,19 @@
} }
} }
.pending {
.status-content.media-body, .created-at {
color: var(--faint);
}
}
.error {
.status-content.media-body, .created-at {
color: $fallback--cRed;
color: var(--badgeNotification, $fallback--cRed);
}
}
.incoming { .incoming {
a { a {
color: var(--chatMessageIncomingLink, $fallback--link); color: var(--chatMessageIncomingLink, $fallback--link);
+5 -4
View File
@@ -32,7 +32,7 @@
> >
<div <div
class="media status" class="media status"
:class="{ 'without-attachment': !hasAttachment }" :class="{ 'without-attachment': !hasAttachment, 'pending': chatViewItem.data.pending, 'error': chatViewItem.data.error }"
style="position: relative" style="position: relative"
@mouseenter="hovered = true" @mouseenter="hovered = true"
@mouseleave="hovered = false" @mouseleave="hovered = false"
@@ -53,18 +53,19 @@
<div slot="content"> <div slot="content">
<div class="dropdown-menu"> <div class="dropdown-menu">
<button <button
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click="deleteMessage" @click="deleteMessage"
> >
<i class="icon-cancel" /> {{ $t("chats.delete") }} <FAIcon icon="times" /> {{ $t("chats.delete") }}
</button> </button>
</div> </div>
</div> </div>
<button <button
slot="trigger" slot="trigger"
class="button-default menu-icon"
:title="$t('chats.more')" :title="$t('chats.more')"
> >
<i class="icon-ellipsis" /> <FAIcon icon="ellipsis-h" />
</button> </button>
</Popover> </Popover>
</div> </div>
+10
View File
@@ -1,6 +1,16 @@
import { mapState, mapGetters } from 'vuex' import { mapState, mapGetters } from 'vuex'
import BasicUserCard from '../basic_user_card/basic_user_card.vue' import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import UserAvatar from '../user_avatar/user_avatar.vue' import UserAvatar from '../user_avatar/user_avatar.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faSearch,
faChevronLeft
} from '@fortawesome/free-solid-svg-icons'
library.add(
faSearch,
faChevronLeft
)
const chatNew = { const chatNew = {
components: { components: {
+5 -3
View File
@@ -8,9 +8,7 @@
} }
} }
.icon-search { .search-icon {
font-size: 1.5em;
float: right;
margin-right: 0.3em; margin-right: 0.3em;
} }
@@ -25,5 +23,9 @@
.go-back-button { .go-back-button {
cursor: pointer; cursor: pointer;
width: 28px;
text-align: center;
padding: 0.6em;
margin: -0.6em 0.6em -0.6em -0.6em;
} }
} }
+8 -2
View File
@@ -11,12 +11,18 @@
class="go-back-button" class="go-back-button"
@click="goBack" @click="goBack"
> >
<i class="button-icon icon-left-open" /> <FAIcon
size="lg"
icon="chevron-left"
/>
</a> </a>
</div> </div>
<div class="input-wrap"> <div class="input-wrap">
<div class="input-search"> <div class="input-search">
<i class="button-icon icon-search" /> <FAIcon
class="search-icon fa-scale-110 fa-old-padding"
icon="search"
/>
</div> </div>
<input <input
ref="search" ref="search"
+10
View File
@@ -1,4 +1,14 @@
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faBullhorn,
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faBullhorn,
faTimes
)
const chatPanel = { const chatPanel = {
props: [ 'floating' ], props: [ 'floating' ],
+8 -4
View File
@@ -11,9 +11,9 @@
> >
<div class="title"> <div class="title">
<span>{{ $t('shoutbox.title') }}</span> <span>{{ $t('shoutbox.title') }}</span>
<i <FAIcon
v-if="floating" v-if="floating"
class="icon-cancel" icon="times"
/> />
</div> </div>
</div> </div>
@@ -63,7 +63,10 @@
@click.stop.prevent="togglePanel" @click.stop.prevent="togglePanel"
> >
<div class="title"> <div class="title">
<i class="icon-comment-empty" /> <FAIcon
class="icon"
icon="bullhorn"
/>
{{ $t('shoutbox.title') }} {{ $t('shoutbox.title') }}
</div> </div>
</div> </div>
@@ -87,7 +90,8 @@
.chat-panel { .chat-panel {
.chat-heading { .chat-heading {
cursor: pointer; cursor: pointer;
.icon-comment-empty {
.icon {
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
} }
@@ -8,13 +8,13 @@
class="rating" class="rating"
> >
<span v-if="contrast.aaa"> <span v-if="contrast.aaa">
<i class="icon-thumbs-up-alt" /> <FAIcon icon="thumbs-up" />
</span> </span>
<span v-if="!contrast.aaa && contrast.aa"> <span v-if="!contrast.aaa && contrast.aa">
<i class="icon-adjust" /> <FAIcon icon="adjust" />
</span> </span>
<span v-if="!contrast.aaa && !contrast.aa"> <span v-if="!contrast.aaa && !contrast.aa">
<i class="icon-attention" /> <FAIcon icon="exclamation-triangle" />
</span> </span>
</span> </span>
<span <span
@@ -23,29 +23,45 @@
:title="hint_18pt" :title="hint_18pt"
> >
<span v-if="contrast.laaa"> <span v-if="contrast.laaa">
<i class="icon-thumbs-up-alt" /> <FAIcon icon="thumbs-up" />
</span> </span>
<span v-if="!contrast.laaa && contrast.laa"> <span v-if="!contrast.laaa && contrast.laa">
<i class="icon-adjust" /> <FAIcon icon="adjust" />
</span> </span>
<span v-if="!contrast.laaa && !contrast.laa"> <span v-if="!contrast.laaa && !contrast.laa">
<i class="icon-attention" /> <FAIcon icon="exclamation-triangle" />
</span> </span>
</span> </span>
</span> </span>
</template> </template>
<script> <script>
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faAdjust,
faExclamationTriangle,
faThumbsUp
} from '@fortawesome/free-solid-svg-icons'
library.add(
faAdjust,
faExclamationTriangle,
faThumbsUp
)
export default { export default {
props: { props: {
large: { large: {
required: false required: false,
type: Boolean,
default: false
}, },
// TODO: Make theme switcher compute theme initially so that contrast // TODO: Make theme switcher compute theme initially so that contrast
// component won't be called without contrast data // component won't be called without contrast data
contrast: { contrast: {
required: false, required: false,
type: Object type: Object,
default: () => ({})
} }
}, },
computed: { computed: {
@@ -82,6 +98,7 @@ export default {
.rating { .rating {
display: inline-block; display: inline-block;
text-align: center; text-align: center;
margin-left: 0.5em;
} }
} }
</style> </style>
+19 -1
View File
@@ -44,7 +44,8 @@ const conversation = {
'isPage', 'isPage',
'pinnedStatusIdsObject', 'pinnedStatusIdsObject',
'inProfile', 'inProfile',
'profileUserId' 'profileUserId',
'virtualHidden'
], ],
created () { created () {
if (this.isPage) { if (this.isPage) {
@@ -52,6 +53,13 @@ const conversation = {
} }
}, },
computed: { computed: {
hideStatus () {
if (this.$refs.statusComponent && this.$refs.statusComponent[0]) {
return this.virtualHidden && this.$refs.statusComponent[0].suspendable
} else {
return this.virtualHidden
}
},
status () { status () {
return this.$store.state.statuses.allStatusesObject[this.statusId] return this.$store.state.statuses.allStatusesObject[this.statusId]
}, },
@@ -102,6 +110,10 @@ const conversation = {
}, },
isExpanded () { isExpanded () {
return this.expanded || this.isPage return this.expanded || this.isPage
},
hiddenStyle () {
const height = (this.status && this.status.virtualHeight) || '120px'
return this.virtualHidden ? { height } : {}
} }
}, },
components: { components: {
@@ -121,6 +133,12 @@ const conversation = {
if (value) { if (value) {
this.fetchConversation() this.fetchConversation()
} }
},
virtualHidden (value) {
this.$store.dispatch(
'setVirtualHeight',
{ statusId: this.statusId, height: `${this.$el.clientHeight}px` }
)
} }
}, },
methods: { methods: {
+13 -12
View File
@@ -1,5 +1,7 @@
<template> <template>
<div <div
v-if="!hideStatus"
:style="hiddenStyle"
class="Conversation" class="Conversation"
:class="{ '-expanded' : isExpanded, 'panel' : isExpanded }" :class="{ '-expanded' : isExpanded, 'panel' : isExpanded }"
> >
@@ -8,16 +10,18 @@
class="panel-heading conversation-heading" class="panel-heading conversation-heading"
> >
<span class="title"> {{ $t('timeline.conversation') }} </span> <span class="title"> {{ $t('timeline.conversation') }} </span>
<span v-if="collapsable"> <button
<a v-if="collapsable"
href="#" class="button-unstyled -link"
@click.prevent="toggleExpanded" @click.prevent="toggleExpanded"
>{{ $t('timeline.collapse') }}</a> >
</span> {{ $t('timeline.collapse') }}
</button>
</div> </div>
<status <status
v-for="status in conversation" v-for="status in conversation"
:key="status.id" :key="status.id"
ref="statusComponent"
:inline-expanded="collapsable && isExpanded" :inline-expanded="collapsable && isExpanded"
:statusoid="status" :statusoid="status"
:expandable="!isExpanded" :expandable="!isExpanded"
@@ -33,6 +37,10 @@
@toggleExpanded="toggleExpanded" @toggleExpanded="toggleExpanded"
/> />
</div> </div>
<div
v-else
:style="hiddenStyle"
/>
</template> </template>
<script src="./conversation.js"></script> <script src="./conversation.js"></script>
@@ -50,13 +58,6 @@
} }
&.-expanded { &.-expanded {
.conversation-status {
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
border-left: 4px solid $fallback--cRed;
border-left: 4px solid var(--cRed, $fallback--cRed);
}
.conversation-status:last-child { .conversation-status:last-child {
border-bottom: none; border-bottom: none;
border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
+89
View File
@@ -0,0 +1,89 @@
import SearchBar from 'components/search_bar/search_bar.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faSignInAlt,
faSignOutAlt,
faHome,
faComments,
faBell,
faUserPlus,
faBullhorn,
faSearch,
faTachometerAlt,
faCog,
faInfoCircle
} from '@fortawesome/free-solid-svg-icons'
library.add(
faSignInAlt,
faSignOutAlt,
faHome,
faComments,
faBell,
faUserPlus,
faBullhorn,
faSearch,
faTachometerAlt,
faCog,
faInfoCircle
)
export default {
components: {
SearchBar
},
data: () => ({
searchBarHidden: true,
supportsMask: window.CSS && window.CSS.supports && (
window.CSS.supports('mask-size', 'contain') ||
window.CSS.supports('-webkit-mask-size', 'contain') ||
window.CSS.supports('-moz-mask-size', 'contain') ||
window.CSS.supports('-ms-mask-size', 'contain') ||
window.CSS.supports('-o-mask-size', 'contain')
)
}),
computed: {
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
logoStyle () {
return {
'visibility': this.enableMask ? 'hidden' : 'visible'
}
},
logoMaskStyle () {
return this.enableMask ? {
'mask-image': `url(${this.$store.state.instance.logo})`
} : {
'background-color': this.enableMask ? '' : 'transparent'
}
},
logoBgStyle () {
return Object.assign({
'margin': `${this.$store.state.instance.logoMargin} 0`,
opacity: this.searchBarHidden ? 1 : 0
}, this.enableMask ? {} : {
'background-color': this.enableMask ? '' : 'transparent'
})
},
logo () { return this.$store.state.instance.logo },
sitename () { return this.$store.state.instance.name },
hideSitename () { return this.$store.state.instance.hideSitename },
logoLeft () { return this.$store.state.instance.logoLeft },
currentUser () { return this.$store.state.users.currentUser },
privateMode () { return this.$store.state.instance.private }
},
methods: {
scrollToTop () {
window.scrollTo(0, 0)
},
logout () {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
},
onSearchBarToggled (hidden) {
this.searchBarHidden = hidden
},
openSettingsModal () {
this.$store.dispatch('openSettingsModal')
}
}
}
+117
View File
@@ -0,0 +1,117 @@
@import '../../_variables.scss';
.DesktopNav {
height: 50px;
width: 100%;
position: fixed;
a {
color: var(--topBarLink, $fallback--link);
}
.inner-nav {
display: grid;
grid-template-rows: 50px;
grid-template-columns: 2fr auto 2fr;
grid-template-areas: "sitename logo actions";
box-sizing: border-box;
padding: 0 1.2em;
margin: auto;
max-width: 980px;
}
&.-logoLeft {
grid-template-columns: auto 2fr 2fr;
grid-template-areas: "logo sitename actions";
}
.button-default {
&, svg {
color: $fallback--text;
color: var(--btnTopBarText, $fallback--text);
}
&:active {
background-color: $fallback--fg;
background-color: var(--btnPressedTopBar, $fallback--fg);
color: $fallback--text;
color: var(--btnPressedTopBarText, $fallback--text);
}
&:disabled {
color: $fallback--text;
color: var(--btnDisabledTopBarText, $fallback--text);
}
&.toggled {
color: $fallback--text;
color: var(--btnToggledTopBarText, $fallback--text);
background-color: $fallback--fg;
background-color: var(--btnToggledTopBar, $fallback--fg)
}
}
.logo {
grid-area: logo;
position: relative;
transition: opacity;
transition-timing-function: ease-out;
transition-duration: 100ms;
@media all and (min-width: 800px) {
opacity: 1 !important;
}
.mask {
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
background-color: $fallback--fg;
background-color: var(--topBarText, $fallback--fg);
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
img {
display: inline-block;
height: 50px;
}
}
.nav-icon {
margin-left: 0.2em;
width: 2em;
height: 100%;
text-align: center;
.svg-inline--fa {
color: $fallback--link;
color: var(--topBarLink, $fallback--link);
}
}
.sitename {
grid-area: sitename;
}
.actions {
grid-area: actions;
}
.item {
flex: 1;
line-height: 50px;
height: 50px;
overflow: hidden;
display: flex;
flex-wrap: wrap;
&.right {
justify-content: flex-end;
text-align: right;
}
}
}
@@ -0,0 +1,81 @@
<template>
<nav
id="nav"
class="DesktopNav"
:class="{ '-logoLeft': logoLeft }"
@click="scrollToTop()"
>
<div class="inner-nav">
<div class="item sitename">
<router-link
v-if="!hideSitename"
class="site-name"
:to="{ name: 'root' }"
active-class="home"
>
{{ sitename }}
</router-link>
</div>
<router-link
class="logo"
:to="{ name: 'root' }"
:style="logoBgStyle"
>
<div
class="mask"
:style="logoMaskStyle"
/>
<img
:src="logo"
:style="logoStyle"
>
</router-link>
<div class="item right actions">
<search-bar
v-if="currentUser || !privateMode"
@toggled="onSearchBarToggled"
@click.stop.native
/>
<button
class="button-unstyled nav-icon"
@click.stop="openSettingsModal"
>
<FAIcon
fixed-width
class="fa-scale-110 fa-old-padding"
icon="cog"
:title="$t('nav.preferences')"
/>
</button>
<a
v-if="currentUser && currentUser.role === 'admin'"
href="/pleroma/admin/#/login-pleroma"
class="nav-icon"
target="_blank"
>
<FAIcon
fixed-width
class="fa-scale-110 fa-old-padding"
icon="tachometer-alt"
:title="$t('nav.administration')"
/>
</a>
<button
v-if="currentUser"
class="button-unstyled nav-icon"
@click.prevent="logout"
>
<FAIcon
fixed-width
class="fa-scale-110 fa-old-padding"
icon="sign-out-alt"
:title="$t('login.logout')"
/>
</button>
</div>
</div>
</nav>
</template>
<script src="./desktop_nav.js"></script>
<style src="./desktop_nav.scss" lang="scss"></style>
@@ -6,7 +6,7 @@
<ProgressButton <ProgressButton
v-if="muted" v-if="muted"
:click="unmuteDomain" :click="unmuteDomain"
class="btn btn-default" class="btn button-default"
> >
{{ $t('domain_mute_card.unmute') }} {{ $t('domain_mute_card.unmute') }}
<template slot="progress"> <template slot="progress">
@@ -16,7 +16,7 @@
<ProgressButton <ProgressButton
v-else v-else
:click="muteDomain" :click="muteDomain"
class="btn btn-default" class="btn button-default"
> >
{{ $t('domain_mute_card.mute') }} {{ $t('domain_mute_card.mute') }}
<template slot="progress"> <template slot="progress">
+28 -16
View File
@@ -3,6 +3,15 @@ import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import { take } from 'lodash' import { take } from 'lodash'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faSmileBeam
} from '@fortawesome/free-regular-svg-icons'
library.add(
faSmileBeam
)
/** /**
* EmojiInput - augmented inputs for emoji and autocomplete support in inputs * EmojiInput - augmented inputs for emoji and autocomplete support in inputs
* without having to give up the comfort of <input/> and <textarea/> elements * without having to give up the comfort of <input/> and <textarea/> elements
@@ -105,7 +114,8 @@ const EmojiInput = {
showPicker: false, showPicker: false,
temporarilyHideSuggestions: false, temporarilyHideSuggestions: false,
keepOpen: false, keepOpen: false,
disableClickOutside: false disableClickOutside: false,
suggestions: []
} }
}, },
components: { components: {
@@ -115,21 +125,6 @@ const EmojiInput = {
padEmoji () { padEmoji () {
return this.$store.getters.mergedConfig.padEmoji return this.$store.getters.mergedConfig.padEmoji
}, },
suggestions () {
const firstchar = this.textAtCaret.charAt(0)
if (this.textAtCaret === firstchar) { return [] }
const matchedSuggestions = this.suggest(this.textAtCaret)
if (matchedSuggestions.length <= 0) {
return []
}
return take(matchedSuggestions, 5)
.map(({ imageUrl, ...rest }, index) => ({
...rest,
// eslint-disable-next-line camelcase
img: imageUrl || '',
highlighted: index === this.highlighted
}))
},
showSuggestions () { showSuggestions () {
return this.focused && return this.focused &&
this.suggestions && this.suggestions &&
@@ -179,6 +174,23 @@ const EmojiInput = {
watch: { watch: {
showSuggestions: function (newValue) { showSuggestions: function (newValue) {
this.$emit('shown', newValue) this.$emit('shown', newValue)
},
textAtCaret: async function (newWord) {
const firstchar = newWord.charAt(0)
this.suggestions = []
if (newWord === firstchar) return
const matchedSuggestions = await this.suggest(newWord)
// Async: cancel if textAtCaret has changed during wait
if (this.textAtCaret !== newWord) return
if (matchedSuggestions.length <= 0) return
this.suggestions = take(matchedSuggestions, 5)
.map(({ imageUrl, ...rest }) => ({
...rest,
img: imageUrl || ''
}))
},
suggestions (newValue) {
this.$nextTick(this.resize)
} }
}, },
methods: { methods: {
+5 -5
View File
@@ -6,13 +6,13 @@
> >
<slot /> <slot />
<template v-if="enableEmojiPicker"> <template v-if="enableEmojiPicker">
<div <button
v-if="!hideEmojiButton" v-if="!hideEmojiButton"
class="emoji-picker-icon" class="button-unstyled emoji-picker-icon"
@click.prevent="togglePicker" @click.prevent="togglePicker"
> >
<i class="icon-smile" /> <FAIcon :icon="['far', 'smile-beam']" />
</div> </button>
<EmojiPicker <EmojiPicker
v-if="enableEmojiPicker" v-if="enableEmojiPicker"
ref="picker" ref="picker"
@@ -37,7 +37,7 @@
v-for="(suggestion, index) in suggestions" v-for="(suggestion, index) in suggestions"
:key="index" :key="index"
class="autocomplete-item" class="autocomplete-item"
:class="{ highlighted: suggestion.highlighted }" :class="{ highlighted: index === highlighted }"
@click.stop.prevent="onClick($event, suggestion)" @click.stop.prevent="onClick($event, suggestion)"
> >
<span class="image"> <span class="image">
+48 -24
View File
@@ -1,4 +1,3 @@
import { debounce } from 'lodash'
/** /**
* suggest - generates a suggestor function to be used by emoji-input * suggest - generates a suggestor function to be used by emoji-input
* data: object providing source information for specific types of suggestions: * data: object providing source information for specific types of suggestions:
@@ -11,19 +10,19 @@ import { debounce } from 'lodash'
* doesn't support user linking you can just provide only emoji. * doesn't support user linking you can just provide only emoji.
*/ */
const debounceUserSearch = debounce((data, input) => { export default data => {
data.updateUsersList(input) const emojiCurry = suggestEmoji(data.emoji)
}, 500) const usersCurry = data.store && suggestUsers(data.store)
return input => {
export default data => input => {
const firstChar = input[0] const firstChar = input[0]
if (firstChar === ':' && data.emoji) { if (firstChar === ':' && data.emoji) {
return suggestEmoji(data.emoji)(input) return emojiCurry(input)
} }
if (firstChar === '@' && data.users) { if (firstChar === '@' && usersCurry) {
return suggestUsers(data)(input) return usersCurry(input)
} }
return [] return []
}
} }
export const suggestEmoji = emojis => input => { export const suggestEmoji = emojis => input => {
@@ -57,19 +56,46 @@ export const suggestEmoji = emojis => input => {
}) })
} }
export const suggestUsers = data => input => { export const suggestUsers = ({ dispatch, state }) => {
const noPrefix = input.toLowerCase().substr(1) // Keep some persistent values in closure, most importantly for the
const users = data.users // custom debounce to work. Lodash debounce does not return a promise.
let suggestions = []
let previousQuery = ''
let timeout = null
let cancelUserSearch = null
const newUsers = users.filter( const userSearch = (query) => dispatch('searchUsers', { query })
const debounceUserSearch = (query) => {
cancelUserSearch && cancelUserSearch()
return new Promise((resolve, reject) => {
timeout = setTimeout(() => {
userSearch(query).then(resolve).catch(reject)
}, 300)
cancelUserSearch = () => {
clearTimeout(timeout)
resolve([])
}
})
}
return async input => {
const noPrefix = input.toLowerCase().substr(1)
if (previousQuery === noPrefix) return suggestions
suggestions = []
previousQuery = noPrefix
// Fetch more and wait, don't fetch if there's the 2nd @ because
// the backend user search can't deal with it.
// Reference semantics make it so that we get the updated data after
// the await.
if (!noPrefix.includes('@')) {
await debounceUserSearch(noPrefix)
}
const newSuggestions = state.users.users.filter(
user => user =>
user.screen_name.toLowerCase().startsWith(noPrefix) || user.screen_name.toLowerCase().startsWith(noPrefix) ||
user.name.toLowerCase().startsWith(noPrefix) user.name.toLowerCase().startsWith(noPrefix)
/* taking only 20 results so that sorting is a bit cheaper, we display
* only 5 anyway. could be inaccurate, but we ideally we should query
* backend anyway
*/
).slice(0, 20).sort((a, b) => { ).slice(0, 20).sort((a, b) => {
let aScore = 0 let aScore = 0
let bScore = 0 let bScore = 0
@@ -96,11 +122,9 @@ export const suggestUsers = data => input => {
imageUrl: profile_image_url_original, imageUrl: profile_image_url_original,
replacement: '@' + screen_name + ' ' replacement: '@' + screen_name + ' '
})) }))
// BE search users to get more comprehensive results
if (data.updateUsersList) {
debounceUserSearch(data, noPrefix)
}
return newUsers
/* eslint-enable camelcase */ /* eslint-enable camelcase */
suggestions = newSuggestions || []
return suggestions
}
} }
+28 -3
View File
@@ -1,4 +1,16 @@
import Checkbox from '../checkbox/checkbox.vue' import Checkbox from '../checkbox/checkbox.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faBoxOpen,
faStickyNote,
faSmileBeam
} from '@fortawesome/free-solid-svg-icons'
library.add(
faBoxOpen,
faStickyNote,
faSmileBeam
)
// At widest, approximately 20 emoji are visible in a row, // At widest, approximately 20 emoji are visible in a row,
// loading 3 rows, could be overkill for narrow picker // loading 3 rows, could be overkill for narrow picker
@@ -8,7 +20,20 @@ const LOAD_EMOJI_BY = 60
const LOAD_EMOJI_MARGIN = 64 const LOAD_EMOJI_MARGIN = 64
const filterByKeyword = (list, keyword = '') => { const filterByKeyword = (list, keyword = '') => {
return list.filter(x => x.displayText.includes(keyword)) if (keyword === '') return list
const keywordLowercase = keyword.toLowerCase()
let orderedEmojiList = []
for (const emoji of list) {
const indexOfKeyword = emoji.displayText.toLowerCase().indexOf(keywordLowercase)
if (indexOfKeyword > -1) {
if (!Array.isArray(orderedEmojiList[indexOfKeyword])) {
orderedEmojiList[indexOfKeyword] = []
}
orderedEmojiList[indexOfKeyword].push(emoji)
}
}
return orderedEmojiList.flat()
} }
const EmojiPicker = { const EmojiPicker = {
@@ -164,13 +189,13 @@ const EmojiPicker = {
{ {
id: 'custom', id: 'custom',
text: this.$t('emoji.custom'), text: this.$t('emoji.custom'),
icon: 'icon-smile', icon: 'smile-beam',
emojis: customEmojis emojis: customEmojis
}, },
{ {
id: 'standard', id: 'standard',
text: this.$t('emoji.unicode'), text: this.$t('emoji.unicode'),
icon: 'icon-picture', icon: 'box-open',
emojis: filterByKeyword(standardEmojis, this.keyword) emojis: filterByKeyword(standardEmojis, this.keyword)
} }
] ]
@@ -82,7 +82,7 @@
&.active { &.active {
border-bottom: 4px solid; border-bottom: 4px solid;
i { svg {
color: $fallback--lightText; color: $fallback--lightText;
color: var(--lightText, $fallback--lightText); color: var(--lightText, $fallback--lightText);
} }
+8 -2
View File
@@ -13,7 +13,10 @@
:title="group.text" :title="group.text"
@click.prevent="highlight(group.id)" @click.prevent="highlight(group.id)"
> >
<i :class="group.icon" /> <FAIcon
:icon="group.icon"
fixed-width
/>
</span> </span>
</span> </span>
<span <span
@@ -26,7 +29,10 @@
:title="$t('emoji.stickers')" :title="$t('emoji.stickers')"
@click.prevent="toggleStickers" @click.prevent="toggleStickers"
> >
<i class="icon-star" /> <FAIcon
icon="sticky-note"
fixed-width
/>
</span> </span>
</span> </span>
</div> </div>
@@ -6,7 +6,7 @@
:users="accountsForEmoji[reaction.name]" :users="accountsForEmoji[reaction.name]"
> >
<button <button
class="emoji-reaction btn btn-default" class="emoji-reaction btn button-default"
:class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }" :class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }"
@click="emojiOnClick(reaction.name, $event)" @click="emojiOnClick(reaction.name, $event)"
@mouseenter="fetchEmojiReactionsByIfMissing()" @mouseenter="fetchEmojiReactionsByIfMissing()"
@@ -2,13 +2,13 @@
<div class="import-export-container"> <div class="import-export-container">
<slot name="before" /> <slot name="before" />
<button <button
class="btn" class="btn button-default"
@click="exportData" @click="exportData"
> >
{{ exportLabel }} {{ exportLabel }}
</button> </button>
<button <button
class="btn" class="btn button-default"
@click="importData" @click="importData"
> >
{{ importLabel }} {{ importLabel }}
+7
View File
@@ -1,3 +1,10 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
library.add(
faCircleNotch
)
const Exporter = { const Exporter = {
props: { props: {
getContent: { getContent: {
+7 -3
View File
@@ -1,12 +1,17 @@
<template> <template>
<div class="exporter"> <div class="exporter">
<div v-if="processing"> <div v-if="processing">
<i class="icon-spin4 animate-spin exporter-processing" /> <FAIcon
icon="circle-notch"
size="lg"
spin
/>
<span>{{ processingMessage }}</span> <span>{{ processingMessage }}</span>
</div> </div>
<button <button
v-else v-else
class="btn btn-default" class="btn button-default"
@click="process" @click="process"
> >
{{ exportButtonLabel }} {{ exportButtonLabel }}
@@ -19,7 +24,6 @@
<style lang="scss"> <style lang="scss">
.exporter { .exporter {
&-processing { &-processing {
font-size: 1.5em;
margin: 0.25em; margin: 0.25em;
} }
} }
@@ -1,4 +1,26 @@
import Popover from '../popover/popover.vue' import Popover from '../popover/popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faEllipsisH,
faBookmark,
faEyeSlash,
faThumbtack,
faShareAlt,
faExternalLinkAlt
} from '@fortawesome/free-solid-svg-icons'
import {
faBookmark as faBookmarkReg
} from '@fortawesome/free-regular-svg-icons'
library.add(
faEllipsisH,
faBookmark,
faBookmarkReg,
faEyeSlash,
faThumbtack,
faShareAlt,
faExternalLinkAlt
)
const ExtraButtons = { const ExtraButtons = {
props: [ 'status' ], props: [ 'status' ],
+69 -23
View File
@@ -1,9 +1,11 @@
<template> <template>
<Popover <Popover
class="ExtraButtons"
trigger="click" trigger="click"
placement="top" placement="top"
class="extra-button-popover" :offset="{ y: 5 }"
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
remove-padding
> >
<div <div
slot="content" slot="content"
@@ -12,71 +14,112 @@
<div class="dropdown-menu"> <div class="dropdown-menu">
<button <button
v-if="canMute && !status.thread_muted" v-if="canMute && !status.thread_muted"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="muteConversation" @click.prevent="muteConversation"
> >
<i class="icon-eye-off" /><span>{{ $t("status.mute_conversation") }}</span> <FAIcon
fixed-width
icon="eye-slash"
/><span>{{ $t("status.mute_conversation") }}</span>
</button> </button>
<button <button
v-if="canMute && status.thread_muted" v-if="canMute && status.thread_muted"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="unmuteConversation" @click.prevent="unmuteConversation"
> >
<i class="icon-eye-off" /><span>{{ $t("status.unmute_conversation") }}</span> <FAIcon
fixed-width
icon="eye-slash"
/><span>{{ $t("status.unmute_conversation") }}</span>
</button> </button>
<button <button
v-if="!status.pinned && canPin" v-if="!status.pinned && canPin"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="pinStatus" @click.prevent="pinStatus"
@click="close" @click="close"
> >
<i class="icon-pin" /><span>{{ $t("status.pin") }}</span> <FAIcon
fixed-width
icon="thumbtack"
/><span>{{ $t("status.pin") }}</span>
</button> </button>
<button <button
v-if="status.pinned && canPin" v-if="status.pinned && canPin"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="unpinStatus" @click.prevent="unpinStatus"
@click="close" @click="close"
> >
<i class="icon-pin" /><span>{{ $t("status.unpin") }}</span> <FAIcon
fixed-width
icon="thumbtack"
/><span>{{ $t("status.unpin") }}</span>
</button> </button>
<button <button
v-if="!status.bookmarked" v-if="!status.bookmarked"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="bookmarkStatus" @click.prevent="bookmarkStatus"
@click="close" @click="close"
> >
<i class="icon-bookmark-empty" /><span>{{ $t("status.bookmark") }}</span> <FAIcon
fixed-width
:icon="['far', 'bookmark']"
/><span>{{ $t("status.bookmark") }}</span>
</button> </button>
<button <button
v-if="status.bookmarked" v-if="status.bookmarked"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="unbookmarkStatus" @click.prevent="unbookmarkStatus"
@click="close" @click="close"
> >
<i class="icon-bookmark" /><span>{{ $t("status.unbookmark") }}</span> <FAIcon
fixed-width
icon="bookmark"
/><span>{{ $t("status.unbookmark") }}</span>
</button> </button>
<button <button
v-if="canDelete" v-if="canDelete"
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="deleteStatus" @click.prevent="deleteStatus"
@click="close" @click="close"
> >
<i class="icon-cancel" /><span>{{ $t("status.delete") }}</span> <FAIcon
fixed-width
icon="times"
/><span>{{ $t("status.delete") }}</span>
</button> </button>
<button <button
class="dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@click.prevent="copyLink" @click.prevent="copyLink"
@click="close" @click="close"
> >
<i class="icon-share" /><span>{{ $t("status.copy_link") }}</span> <FAIcon
fixed-width
icon="share-alt"
/><span>{{ $t("status.copy_link") }}</span>
</button> </button>
<a
v-if="!status.is_local"
class="button-default dropdown-item dropdown-item-icon"
title="Source"
:href="status.external_url"
target="_blank"
>
<FAIcon
fixed-width
icon="external-link-alt"
/><span>{{ $t("status.external_source") }}</span>
</a>
</div> </div>
</div> </div>
<i <span
slot="trigger" slot="trigger"
class="icon-ellipsis button-icon" class="popover-trigger"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="ellipsis-h"
/> />
</span>
</Popover> </Popover>
</template> </template>
@@ -85,13 +128,16 @@
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
.icon-ellipsis { .ExtraButtons {
cursor: pointer; .popover-trigger {
position: static;
padding: 10px;
margin: -10px;
&:hover, &:hover .svg-inline--fa {
.extra-button-popover.open & {
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
} }
}
} }
</style> </style>
@@ -1,4 +1,14 @@
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faStar } from '@fortawesome/free-solid-svg-icons'
import {
faStar as faStarRegular
} from '@fortawesome/free-regular-svg-icons'
library.add(
faStar,
faStarRegular
)
const FavoriteButton = { const FavoriteButton = {
props: ['status', 'loggedIn'], props: ['status', 'loggedIn'],
@@ -21,13 +31,6 @@ const FavoriteButton = {
} }
}, },
computed: { computed: {
classes () {
return {
'icon-star-empty': !this.status.favorited,
'icon-star': this.status.favorited,
'animate-spin': this.animated
}
},
...mapGetters(['mergedConfig']) ...mapGetters(['mergedConfig'])
} }
} }
@@ -1,20 +1,31 @@
<template> <template>
<div v-if="loggedIn"> <div class="FavoriteButton">
<i <button
:class="classes" v-if="loggedIn"
class="button-icon favorite-button fav-active" class="button-unstyled interactive"
:class="status.favorited && '-favorited'"
:title="$t('tool_tip.favorite')" :title="$t('tool_tip.favorite')"
@click.prevent="favorite()" @click.prevent="favorite()"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
:icon="[status.favorited ? 'fas' : 'far', 'star']"
:spin="animated"
/> />
<span v-if="!mergedConfig.hidePostStats && status.fave_num > 0">{{ status.fave_num }}</span> </button>
</div> <span v-else>
<div v-else> <FAIcon
<i class="fa-scale-110 fa-old-padding"
:class="classes"
class="button-icon favorite-button"
:title="$t('tool_tip.favorite')" :title="$t('tool_tip.favorite')"
:icon="['far', 'star']"
/> />
<span v-if="!mergedConfig.hidePostStats && status.fave_num > 0">{{ status.fave_num }}</span> </span>
<span
v-if="!mergedConfig.hidePostStats && status.fave_num > 0"
class="action-counter"
>
{{ status.fave_num }}
</span>
</div> </div>
</template> </template>
@@ -23,18 +34,29 @@
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
.fav-active { .FavoriteButton {
cursor: pointer; display: flex;
animation-duration: 0.6s;
&:hover { > :first-child {
padding: 10px;
margin: -10px -8px -10px -10px;
}
.action-counter {
pointer-events: none;
user-select: none;
}
.interactive {
.svg-inline--fa {
animation-duration: 0.6s;
}
&:hover .svg-inline--fa,
&.-favorited .svg-inline--fa {
color: $fallback--cOrange; color: $fallback--cOrange;
color: var(--cOrange, $fallback--cOrange); color: var(--cOrange, $fallback--cOrange);
} }
} }
.favorite-button.icon-star {
color: $fallback--cOrange;
color: var(--cOrange, $fallback--cOrange);
} }
</style> </style>
@@ -1,3 +1,5 @@
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
const FeaturesPanel = { const FeaturesPanel = {
computed: { computed: {
chat: function () { return this.$store.state.instance.chatAvailable }, chat: function () { return this.$store.state.instance.chatAvailable },
@@ -6,7 +8,8 @@ const FeaturesPanel = {
whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled }, whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled },
mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable }, mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable },
minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode }, minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode },
textlimit: function () { return this.$store.state.instance.textlimit } textlimit: function () { return this.$store.state.instance.textlimit },
uploadlimit: function () { return fileSizeFormatService.fileSizeFormat(this.$store.state.instance.uploadlimit) }
} }
} }
@@ -25,6 +25,7 @@
</li> </li>
<li>{{ $t('features_panel.scope_options') }}</li> <li>{{ $t('features_panel.scope_options') }}</li>
<li>{{ $t('features_panel.text_limit') }} = {{ textlimit }}</li> <li>{{ $t('features_panel.text_limit') }} = {{ textlimit }}</li>
<li>{{ $t('features_panel.upload_limit') }} = {{ uploadlimit.num }} {{ $t('upload.file_size_units.' + uploadlimit.unit) }}</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -1,6 +1,6 @@
<template> <template>
<button <button
class="btn btn-default follow-button" class="btn button-default follow-button"
:class="{ toggled: isPressed }" :class="{ toggled: isPressed }"
:disabled="inProgress" :disabled="inProgress"
:title="title" :title="title"
@@ -2,13 +2,13 @@
<basic-user-card :user="user"> <basic-user-card :user="user">
<div class="follow-request-card-content-container"> <div class="follow-request-card-content-container">
<button <button
class="btn btn-default" class="btn button-default"
@click="approveUser" @click="approveUser"
> >
{{ $t('user_card.approve') }} {{ $t('user_card.approve') }}
</button> </button>
<button <button
class="btn btn-default" class="btn button-default"
@click="denyUser" @click="denyUser"
> >
{{ $t('user_card.deny') }} {{ $t('user_card.deny') }}
@@ -1,8 +1,10 @@
<template> <template>
<div class="settings panel panel-default"> <div class="settings panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<div class="title">
{{ $t('nav.friend_requests') }} {{ $t('nav.friend_requests') }}
</div> </div>
</div>
<div class="panel-body"> <div class="panel-body">
<FollowRequestCard <FollowRequestCard
v-for="request in requests" v-for="request in requests"
@@ -1,4 +1,12 @@
import { set } from 'vue' import { set } from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faChevronDown
} from '@fortawesome/free-solid-svg-icons'
library.add(
faChevronDown
)
export default { export default {
props: [ props: [
+4 -1
View File
@@ -41,7 +41,10 @@
{{ option === 'custom' ? $t('settings.style.fonts.custom') : option }} {{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
</option> </option>
</select> </select>
<i class="icon-down-open" /> <FAIcon
class="select-down-icon"
icon="chevron-down"
/>
</label> </label>
<input <input
v-if="isCustom" v-if="isCustom"
@@ -1,3 +1,11 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes
)
const GlobalNoticeList = { const GlobalNoticeList = {
computed: { computed: {
@@ -9,10 +9,15 @@
<div class="notice-message"> <div class="notice-message">
{{ $t(notice.messageKey, notice.messageArgs) }} {{ $t(notice.messageKey, notice.messageArgs) }}
</div> </div>
<i <button
class="button-icon icon-cancel" class="button-unstyled close-notice"
@click="closeNotice(notice)" @click="closeNotice(notice)"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="times"
/> />
</button>
</div> </div>
</div> </div>
</template> </template>
@@ -53,7 +58,7 @@
.global-error { .global-error {
background-color: var(--alertPopupError, $fallback--cRed); background-color: var(--alertPopupError, $fallback--cRed);
color: var(--alertPopupErrorText, $fallback--text); color: var(--alertPopupErrorText, $fallback--text);
i { .svg-inline--fa {
color: var(--alertPopupErrorText, $fallback--text); color: var(--alertPopupErrorText, $fallback--text);
} }
} }
@@ -61,7 +66,7 @@
.global-warning { .global-warning {
background-color: var(--alertPopupWarning, $fallback--cOrange); background-color: var(--alertPopupWarning, $fallback--cOrange);
color: var(--alertPopupWarningText, $fallback--text); color: var(--alertPopupWarningText, $fallback--text);
i { .svg-inline--fa {
color: var(--alertPopupWarningText, $fallback--text); color: var(--alertPopupWarningText, $fallback--text);
} }
} }
@@ -69,9 +74,16 @@
.global-info { .global-info {
background-color: var(--alertPopupNeutral, $fallback--fg); background-color: var(--alertPopupNeutral, $fallback--fg);
color: var(--alertPopupNeutralText, $fallback--text); color: var(--alertPopupNeutralText, $fallback--text);
i { .svg-inline--fa {
color: var(--alertPopupNeutralText, $fallback--text); color: var(--alertPopupNeutralText, $fallback--text);
} }
} }
.close-notice {
padding-right: 0.2em;
.svg-inline--fa:hover {
opacity: 0.6;
}
}
} }
</style> </style>
+9 -12
View File
@@ -1,5 +1,13 @@
import Cropper from 'cropperjs' import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css' import 'cropperjs/dist/cropper.css'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCircleNotch
} from '@fortawesome/free-solid-svg-icons'
library.add(
faCircleNotch
)
const ImageCropper = { const ImageCropper = {
props: { props: {
@@ -43,8 +51,7 @@ const ImageCropper = {
cropper: undefined, cropper: undefined,
dataUrl: undefined, dataUrl: undefined,
filename: undefined, filename: undefined,
submitting: false, submitting: false
submitError: null
} }
}, },
computed: { computed: {
@@ -56,9 +63,6 @@ const ImageCropper = {
}, },
cancelText () { cancelText () {
return this.cancelButtonLabel || this.$t('image_cropper.cancel') return this.cancelButtonLabel || this.$t('image_cropper.cancel')
},
submitErrorMsg () {
return this.submitError && this.submitError instanceof Error ? this.submitError.toString() : this.submitError
} }
}, },
methods: { methods: {
@@ -72,12 +76,8 @@ const ImageCropper = {
}, },
submit (cropping = true) { submit (cropping = true) {
this.submitting = true this.submitting = true
this.avatarUploadError = null
this.submitHandler(cropping && this.cropper, this.file) this.submitHandler(cropping && this.cropper, this.file)
.then(() => this.destroy()) .then(() => this.destroy())
.catch((err) => {
this.submitError = err
})
.finally(() => { .finally(() => {
this.submitting = false this.submitting = false
}) })
@@ -103,9 +103,6 @@ const ImageCropper = {
reader.readAsDataURL(this.file) reader.readAsDataURL(this.file)
this.$emit('changed', this.file, reader) this.$emit('changed', this.file, reader)
} }
},
clearError () {
this.submitError = null
} }
}, },
mounted () { mounted () {
+6 -15
View File
@@ -11,39 +11,30 @@
</div> </div>
<div class="image-cropper-buttons-wrapper"> <div class="image-cropper-buttons-wrapper">
<button <button
class="btn" class="button-default btn"
type="button" type="button"
:disabled="submitting" :disabled="submitting"
@click="submit()" @click="submit()"
v-text="saveText" v-text="saveText"
/> />
<button <button
class="btn" class="button-default btn"
type="button" type="button"
:disabled="submitting" :disabled="submitting"
@click="destroy" @click="destroy"
v-text="cancelText" v-text="cancelText"
/> />
<button <button
class="btn" class="button-default btn"
type="button" type="button"
:disabled="submitting" :disabled="submitting"
@click="submit(false)" @click="submit(false)"
v-text="saveWithoutCroppingText" v-text="saveWithoutCroppingText"
/> />
<i <FAIcon
v-if="submitting" v-if="submitting"
class="icon-spin4 animate-spin" spin
/> icon="circle-notch"
</div>
<div
v-if="submitError"
class="alert error"
>
{{ submitErrorMsg }}
<i
class="button-icon icon-cancel"
@click="clearError"
/> />
</div> </div>
</div> </div>
+11
View File
@@ -1,3 +1,14 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCircleNotch,
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faCircleNotch,
faTimes
)
const Importer = { const Importer = {
props: { props: {
submitHandler: { submitHandler: {
+9 -7
View File
@@ -7,27 +7,29 @@
@change="change" @change="change"
> >
</form> </form>
<i <FAIcon
v-if="submitting" v-if="submitting"
class="icon-spin4 animate-spin importer-uploading" class="importer-uploading"
spin
icon="circle-notch"
/> />
<button <button
v-else v-else
class="btn btn-default" class="btn button-default"
@click="submit" @click="submit"
> >
{{ submitButtonLabel }} {{ submitButtonLabel }}
</button> </button>
<div v-if="success"> <div v-if="success">
<i <FAIcon
class="icon-cross" icon="times"
@click="dismiss" @click="dismiss"
/> />
<p>{{ successMessage }}</p> <p>{{ successMessage }}</p>
</div> </div>
<div v-else-if="error"> <div v-else-if="error">
<i <FAIcon
class="icon-cross" icon="times"
@click="dismiss" @click="dismiss"
/> />
<p>{{ errorMessage }}</p> <p>{{ errorMessage }}</p>
@@ -19,7 +19,10 @@
{{ languageNames[i] }} {{ languageNames[i] }}
</option> </option>
</select> </select>
<i class="icon-down-open" /> <FAIcon
class="select-down-icon"
icon="chevron-down"
/>
</label> </label>
</div> </div>
</template> </template>
@@ -28,6 +31,14 @@
import languagesObject from '../../i18n/messages' import languagesObject from '../../i18n/messages'
import ISO6391 from 'iso-639-1' import ISO6391 from 'iso-639-1'
import _ from 'lodash' import _ from 'lodash'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faChevronDown
} from '@fortawesome/free-solid-svg-icons'
library.add(
faChevronDown
)
export default { export default {
computed: { computed: {
+13 -2
View File
@@ -1,3 +1,5 @@
import { mapGetters } from 'vuex'
const LinkPreview = { const LinkPreview = {
name: 'LinkPreview', name: 'LinkPreview',
props: [ props: [
@@ -15,11 +17,20 @@ const LinkPreview = {
// Currently BE shoudn't give cards if tagged NSFW, this is a bit paranoid // Currently BE shoudn't give cards if tagged NSFW, this is a bit paranoid
// as it makes sure to hide the image if somehow NSFW tagged preview can // as it makes sure to hide the image if somehow NSFW tagged preview can
// exist. // exist.
return this.card.image && !this.nsfw && this.size !== 'hide' return this.card.image && !this.censored && this.size !== 'hide'
},
censored () {
return this.nsfw && this.hideNsfwConfig
}, },
useDescription () { useDescription () {
return this.card.description && /\S/.test(this.card.description) return this.card.description && /\S/.test(this.card.description)
} },
hideNsfwConfig () {
return this.mergedConfig.hideNsfw
},
...mapGetters([
'mergedConfig'
])
}, },
created () { created () {
if (this.useImage) { if (this.useImage) {
+11 -6
View File
@@ -9,12 +9,17 @@
<div <div
v-if="useImage && imageLoaded" v-if="useImage && imageLoaded"
class="card-image" class="card-image"
:class="{ 'small-image': size === 'small' }"
> >
<img :src="card.image"> <img :src="card.image">
</div> </div>
<div class="card-content"> <div class="card-content">
<span class="card-host faint">{{ card.provider_name }}</span> <span class="card-host faint">
<span
v-if="censored"
class="nsfw-alert alert warning"
>{{ $t('status.nsfw') }}</span>
{{ card.provider_name }}
</span>
<h4 class="card-title">{{ card.title }}</h4> <h4 class="card-title">{{ card.title }}</h4>
<p <p
v-if="useDescription" v-if="useDescription"
@@ -50,10 +55,6 @@
} }
} }
.small-image {
width: 80px;
}
.card-content { .card-content {
max-height: 100%; max-height: 100%;
margin: 0.5em; margin: 0.5em;
@@ -76,6 +77,10 @@
max-height: calc(1.2em * 3 - 1px); max-height: calc(1.2em * 3 - 1px);
} }
.nsfw-alert {
margin: 2em 0;
}
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
border-style: solid; border-style: solid;
+8
View File
@@ -1,5 +1,13 @@
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex' import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import oauthApi from '../../services/new_api/oauth.js' import oauthApi from '../../services/new_api/oauth.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes
)
const LoginForm = { const LoginForm = {
data: () => ({ data: () => ({
+4 -3
View File
@@ -61,7 +61,7 @@
<button <button
:disabled="loggingIn" :disabled="loggingIn"
type="submit" type="submit"
class="btn btn-default" class="btn button-default"
> >
{{ $t('login.login') }} {{ $t('login.login') }}
</button> </button>
@@ -76,8 +76,9 @@
> >
<div class="alert error"> <div class="alert error">
{{ error }} {{ error }}
<i <FAIcon
class="button-icon icon-cancel" class="fa-scale-110 fa-old-padding"
icon="times"
@click="clearError" @click="clearError"
/> />
</div> </div>
+10
View File
@@ -3,6 +3,16 @@ import VideoAttachment from '../video_attachment/video_attachment.vue'
import Modal from '../modal/modal.vue' import Modal from '../modal/modal.vue'
import fileTypeService from '../../services/file_type/file_type.service.js' import fileTypeService from '../../services/file_type/file_type.service.js'
import GestureService from '../../services/gesture_service/gesture_service' import GestureService from '../../services/gesture_service/gesture_service'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faChevronLeft,
faChevronRight
} from '@fortawesome/free-solid-svg-icons'
library.add(
faChevronLeft,
faChevronRight
)
const MediaModal = { const MediaModal = {
components: { components: {
+8 -2
View File
@@ -34,7 +34,10 @@
class="modal-view-button-arrow modal-view-button-arrow--prev" class="modal-view-button-arrow modal-view-button-arrow--prev"
@click.stop.prevent="goPrev" @click.stop.prevent="goPrev"
> >
<i class="icon-left-open arrow-icon" /> <FAIcon
class="arrow-icon"
icon="chevron-left"
/>
</button> </button>
<button <button
v-if="canNavigate" v-if="canNavigate"
@@ -42,7 +45,10 @@
class="modal-view-button-arrow modal-view-button-arrow--next" class="modal-view-button-arrow modal-view-button-arrow--next"
@click.stop.prevent="goNext" @click.stop.prevent="goNext"
> >
<i class="icon-right-open arrow-icon" /> <FAIcon
class="arrow-icon"
icon="chevron-right"
/>
</button> </button>
</Modal> </Modal>
</template> </template>
@@ -2,6 +2,14 @@
import statusPosterService from '../../services/status_poster/status_poster.service.js' import statusPosterService from '../../services/status_poster/status_poster.service.js'
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js' import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faUpload, faCircleNotch } from '@fortawesome/free-solid-svg-icons'
library.add(
faUpload,
faCircleNotch
)
const mediaUpload = { const mediaUpload = {
data () { data () {
return { return {
+8 -25
View File
@@ -1,19 +1,19 @@
<template> <template>
<div <label
class="media-upload" class="media-upload"
:class="{ disabled: disabled }" :class="{ disabled: disabled }"
>
<label
class="label"
:title="$t('tool_tip.media_upload')" :title="$t('tool_tip.media_upload')"
> >
<i <FAIcon
v-if="uploading" v-if="uploading"
class="progress-icon icon-spin4 animate-spin" class="progress-icon"
icon="circle-notch"
spin
/> />
<i <FAIcon
v-if="!uploading" v-if="!uploading"
class="new-icon icon-upload" class="new-icon"
icon="upload"
/> />
<input <input
v-if="uploadReady" v-if="uploadReady"
@@ -24,7 +24,6 @@
@change="change" @change="change"
> >
</label> </label>
</div>
</template> </template>
<script src="./media_upload.js" ></script> <script src="./media_upload.js" ></script>
@@ -33,22 +32,6 @@
@import '../../_variables.scss'; @import '../../_variables.scss';
.media-upload { .media-upload {
.label {
display: inline-block;
}
.new-icon {
cursor: pointer; cursor: pointer;
}
.progress-icon {
display: inline-block;
line-height: 0;
&::before {
/* Overriding fontello to achieve the perfect speeeen */
margin: 0;
line-height: 0;
}
}
} }
</style> </style>
+8
View File
@@ -1,5 +1,13 @@
import mfaApi from '../../services/new_api/mfa.js' import mfaApi from '../../services/new_api/mfa.js'
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex' import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes
)
export default { export default {
data: () => ({ data: () => ({
+10 -9
View File
@@ -23,23 +23,23 @@
<div class="form-group"> <div class="form-group">
<div class="login-bottom"> <div class="login-bottom">
<div> <div>
<a <button
href="#" class="button-unstyled -link"
@click.prevent="requireTOTP" @click.prevent="requireTOTP"
> >
{{ $t('login.enter_two_factor_code') }} {{ $t('login.enter_two_factor_code') }}
</a> </button>
<br> <br>
<a <button
href="#" class="button-unstyled -link"
@click.prevent="abortMFA" @click.prevent="abortMFA"
> >
{{ $t('general.cancel') }} {{ $t('general.cancel') }}
</a> </button>
</div> </div>
<button <button
type="submit" type="submit"
class="btn btn-default" class="btn button-default"
> >
{{ $t('general.verify') }} {{ $t('general.verify') }}
</button> </button>
@@ -54,8 +54,9 @@
> >
<div class="alert error"> <div class="alert error">
{{ error }} {{ error }}
<i <FAIcon
class="button-icon icon-cancel" class="fa-scale-110 fa-old-padding"
icon="times"
@click="clearError" @click="clearError"
/> />
</div> </div>
+9
View File
@@ -1,5 +1,14 @@
import mfaApi from '../../services/new_api/mfa.js' import mfaApi from '../../services/new_api/mfa.js'
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex' import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes
)
export default { export default {
data: () => ({ data: () => ({
code: null, code: null,
+11 -9
View File
@@ -25,23 +25,23 @@
<div class="form-group"> <div class="form-group">
<div class="login-bottom"> <div class="login-bottom">
<div> <div>
<a <button
href="#" class="button-unstyled -link"
@click.prevent="requireRecovery" @click.prevent="requireRecovery"
> >
{{ $t('login.enter_recovery_code') }} {{ $t('login.enter_recovery_code') }}
</a> </button>
<br> <br>
<a <button
href="#" class="button-unstyled -link"
@click.prevent="abortMFA" @click.prevent="abortMFA"
> >
{{ $t('general.cancel') }} {{ $t('general.cancel') }}
</a> </button>
</div> </div>
<button <button
type="submit" type="submit"
class="btn btn-default" class="btn button-default"
> >
{{ $t('general.verify') }} {{ $t('general.verify') }}
</button> </button>
@@ -56,8 +56,10 @@
> >
<div class="alert error"> <div class="alert error">
{{ error }} {{ error }}
<i <FAIcon
class="button-icon icon-cancel" size="lg"
class="fa-scale-110 fa-old-padding"
icon="times"
@click="clearError" @click="clearError"
/> />
</div> </div>
+12
View File
@@ -3,6 +3,18 @@ import Notifications from '../notifications/notifications.vue'
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils' import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
import GestureService from '../../services/gesture_service/gesture_service' import GestureService from '../../services/gesture_service/gesture_service'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes,
faBell,
faBars
} from '@fortawesome/free-solid-svg-icons'
library.add(
faTimes,
faBell,
faBars
)
const MobileNav = { const MobileNav = {
components: { components: {
+59 -31
View File
@@ -1,26 +1,27 @@
<template> <template>
<div> <div
class="MobileNav"
>
<nav <nav
id="nav" id="nav"
class="nav-bar container" class="mobile-nav"
:class="{ 'mobile-hidden': isChat }" :class="{ 'mobile-hidden': isChat }"
>
<div
class="mobile-inner-nav"
@click="scrollToTop()" @click="scrollToTop()"
> >
<div class="item"> <div class="item">
<a <button
href="#" class="button-unstyled mobile-nav-button"
class="mobile-nav-button"
@click.stop.prevent="toggleMobileSidebar()" @click.stop.prevent="toggleMobileSidebar()"
> >
<i class="button-icon icon-menu" /> <FAIcon
class="fa-scale-110 fa-old-padding"
icon="bars"
/>
<div <div
v-if="unreadChatCount" v-if="unreadChatCount"
class="alert-dot" class="alert-dot"
/> />
</a> </button>
<router-link <router-link
v-if="!hideSitename" v-if="!hideSitename"
class="site-name" class="site-name"
@@ -31,19 +32,20 @@
</router-link> </router-link>
</div> </div>
<div class="item right"> <div class="item right">
<a <button
v-if="currentUser" v-if="currentUser"
class="mobile-nav-button" class="button-unstyled mobile-nav-button"
href="#"
@click.stop.prevent="openMobileNotifications()" @click.stop.prevent="openMobileNotifications()"
> >
<i class="button-icon icon-bell-alt" /> <FAIcon
class="fa-scale-110 fa-old-padding"
icon="bell"
/>
<div <div
v-if="unseenNotificationsCount" v-if="unseenNotificationsCount"
class="alert-dot" class="alert-dot"
/> />
</a> </button>
</div>
</div> </div>
</nav> </nav>
<div <div
@@ -59,7 +61,10 @@
class="mobile-nav-button" class="mobile-nav-button"
@click.stop.prevent="closeMobileNotifications()" @click.stop.prevent="closeMobileNotifications()"
> >
<i class="button-icon icon-cancel" /> <FAIcon
class="fa-scale-110 fa-old-padding"
icon="times"
/>
</a> </a>
</div> </div>
<div <div
@@ -84,21 +89,43 @@
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
.mobile-inner-nav { .MobileNav {
.mobile-nav {
display: grid;
line-height: 50px;
height: 50px;
grid-template-rows: 50px;
grid-template-columns: 2fr auto;
width: 100%;
position: fixed;
box-sizing: border-box;
}
.mobile-inner-nav {
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.mobile-nav-button { .mobile-nav-button {
display: flex; display: inline-block;
justify-content: center; text-align: center;
width: 50px; padding: 0 1em;
position: relative; position: relative;
cursor: pointer; cursor: pointer;
} }
.alert-dot { .site-name {
padding: 0 .3em;
display: inline-block;
}
.item {
/* moslty just to get rid of extra whitespaces */
display: flex;
}
.alert-dot {
border-radius: 100%; border-radius: 100%;
height: 8px; height: 8px;
width: 8px; width: 8px;
@@ -109,9 +136,9 @@
margin-top: -6px; margin-top: -6px;
background-color: $fallback--cRed; background-color: $fallback--cRed;
background-color: var(--badgeNotification, $fallback--cRed); background-color: var(--badgeNotification, $fallback--cRed);
} }
.mobile-notifications-drawer { .mobile-notifications-drawer {
width: 100%; width: 100%;
height: 100vh; height: 100vh;
overflow-x: hidden; overflow-x: hidden;
@@ -129,9 +156,9 @@
&.closed { &.closed {
transform: translateX(100%); transform: translateX(100%);
} }
} }
.mobile-notifications-header { .mobile-notifications-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -150,9 +177,9 @@
font-size: 1.3em; font-size: 1.3em;
margin-left: 0.6em; margin-left: 0.6em;
} }
} }
.mobile-notifications { .mobile-notifications {
margin-top: 50px; margin-top: 50px;
width: 100vw; width: 100vw;
height: calc(100vh - 50px); height: calc(100vh - 50px);
@@ -181,6 +208,7 @@
box-shadow: none; box-shadow: none;
} }
} }
}
} }
</style> </style>
@@ -1,4 +1,12 @@
import { debounce } from 'lodash' import { debounce } from 'lodash'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faPen
} from '@fortawesome/free-solid-svg-icons'
library.add(
faPen
)
const HIDDEN_FOR_PAGES = new Set([ const HIDDEN_FOR_PAGES = new Set([
'chats', 'chats',
@@ -1,11 +1,11 @@
<template> <template>
<div v-if="isLoggedIn"> <div v-if="isLoggedIn">
<button <button
class="new-status-button" class="button-default new-status-button"
:class="{ 'hidden': isHidden }" :class="{ 'hidden': isHidden }"
@click="openPostForm" @click="openPostForm"
> >
<i class="icon-edit" /> <FAIcon icon="pen" />
</button> </button>
</div> </div>
</template> </template>
@@ -39,7 +39,7 @@
transform: translateY(150%); transform: translateY(150%);
} }
i { svg {
font-size: 1.5em; font-size: 1.5em;
color: $fallback--text; color: $fallback--text;
color: var(--text, $fallback--text); color: var(--text, $fallback--text);
@@ -12,13 +12,13 @@
<div class="dropdown-menu"> <div class="dropdown-menu">
<span v-if="user.is_local"> <span v-if="user.is_local">
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleRight(&quot;admin&quot;)" @click="toggleRight(&quot;admin&quot;)"
> >
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }} {{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
</button> </button>
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleRight(&quot;moderator&quot;)" @click="toggleRight(&quot;moderator&quot;)"
> >
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }} {{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
@@ -29,13 +29,13 @@
/> />
</span> </span>
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleActivationStatus()" @click="toggleActivationStatus()"
> >
{{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }} {{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }}
</button> </button>
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="deleteUserDialog(true)" @click="deleteUserDialog(true)"
> >
{{ $t('user_card.admin_menu.delete_account') }} {{ $t('user_card.admin_menu.delete_account') }}
@@ -47,7 +47,7 @@
/> />
<span v-if="hasTagPolicy"> <span v-if="hasTagPolicy">
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.FORCE_NSFW)" @click="toggleTag(tags.FORCE_NSFW)"
> >
{{ $t('user_card.admin_menu.force_nsfw') }} {{ $t('user_card.admin_menu.force_nsfw') }}
@@ -57,7 +57,7 @@
/> />
</button> </button>
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.STRIP_MEDIA)" @click="toggleTag(tags.STRIP_MEDIA)"
> >
{{ $t('user_card.admin_menu.strip_media') }} {{ $t('user_card.admin_menu.strip_media') }}
@@ -67,7 +67,7 @@
/> />
</button> </button>
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.FORCE_UNLISTED)" @click="toggleTag(tags.FORCE_UNLISTED)"
> >
{{ $t('user_card.admin_menu.force_unlisted') }} {{ $t('user_card.admin_menu.force_unlisted') }}
@@ -77,7 +77,7 @@
/> />
</button> </button>
<button <button
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.SANDBOX)" @click="toggleTag(tags.SANDBOX)"
> >
{{ $t('user_card.admin_menu.sandbox') }} {{ $t('user_card.admin_menu.sandbox') }}
@@ -88,7 +88,7 @@
</button> </button>
<button <button
v-if="user.is_local" v-if="user.is_local"
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)" @click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)"
> >
{{ $t('user_card.admin_menu.disable_remote_subscription') }} {{ $t('user_card.admin_menu.disable_remote_subscription') }}
@@ -99,7 +99,7 @@
</button> </button>
<button <button
v-if="user.is_local" v-if="user.is_local"
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)" @click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)"
> >
{{ $t('user_card.admin_menu.disable_any_subscription') }} {{ $t('user_card.admin_menu.disable_any_subscription') }}
@@ -110,7 +110,7 @@
</button> </button>
<button <button
v-if="user.is_local" v-if="user.is_local"
class="dropdown-item" class="button-default dropdown-item"
@click="toggleTag(tags.QUARANTINE)" @click="toggleTag(tags.QUARANTINE)"
> >
{{ $t('user_card.admin_menu.quarantine') }} {{ $t('user_card.admin_menu.quarantine') }}
@@ -124,7 +124,7 @@
</div> </div>
<button <button
slot="trigger" slot="trigger"
class="btn btn-default btn-block" class="btn button-default btn-block"
:class="{ toggled }" :class="{ toggled }"
> >
{{ $t('user_card.admin_menu.moderation') }} {{ $t('user_card.admin_menu.moderation') }}
@@ -141,13 +141,13 @@
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p> <p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
<template slot="footer"> <template slot="footer">
<button <button
class="btn btn-default" class="btn button-default"
@click="deleteUserDialog(false)" @click="deleteUserDialog(false)"
> >
{{ $t('general.cancel') }} {{ $t('general.cancel') }}
</button> </button>
<button <button
class="btn btn-default danger" class="btn button-default danger"
@click="deleteUser()" @click="deleteUser()"
> >
{{ $t('user_card.admin_menu.delete_user') }} {{ $t('user_card.admin_menu.delete_user') }}
@@ -178,7 +178,7 @@
box-shadow: var(--inputShadow); box-shadow: var(--inputShadow);
&.menu-checkbox-checked::after { &.menu-checkbox-checked::after {
content: ''; content: '';
} }
} }
+2 -2
View File
@@ -3,7 +3,7 @@
<div class="mute-card-content-container"> <div class="mute-card-content-container">
<button <button
v-if="muted" v-if="muted"
class="btn btn-default" class="btn button-default"
:disabled="progress" :disabled="progress"
@click="unmuteUser" @click="unmuteUser"
> >
@@ -16,7 +16,7 @@
</button> </button>
<button <button
v-else v-else
class="btn btn-default" class="btn button-default"
:disabled="progress" :disabled="progress"
@click="muteUser" @click="muteUser"
> >
+23
View File
@@ -1,6 +1,29 @@
import { timelineNames } from '../timeline_menu/timeline_menu.js' import { timelineNames } from '../timeline_menu/timeline_menu.js'
import { mapState, mapGetters } from 'vuex' import { mapState, mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faUsers,
faGlobe,
faBookmark,
faEnvelope,
faHome,
faComments,
faBell,
faInfoCircle
} from '@fortawesome/free-solid-svg-icons'
library.add(
faUsers,
faGlobe,
faBookmark,
faEnvelope,
faHome,
faComments,
faBell,
faInfoCircle
)
const NavPanel = { const NavPanel = {
created () { created () {
if (this.currentUser && this.currentUser.locked) { if (this.currentUser && this.currentUser.locked) {
+55 -27
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="nav-panel"> <div class="NavPanel">
<div class="panel panel-default"> <div class="panel panel-default">
<ul> <ul>
<li v-if="currentUser || !privateMode"> <li v-if="currentUser || !privateMode">
@@ -7,31 +7,47 @@
:to="{ name: timelinesRoute }" :to="{ name: timelinesRoute }"
:class="onTimelineRoute && 'router-link-active'" :class="onTimelineRoute && 'router-link-active'"
> >
<i class="button-icon icon-home-2" /> {{ $t("nav.timelines") }} <FAIcon
fixed-width
class="fa-scale-110"
icon="home"
/>{{ $t("nav.timelines") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser"> <li v-if="currentUser">
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }"> <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
<i class="button-icon icon-bell-alt" /> {{ $t("nav.interactions") }} <FAIcon
fixed-width
class="fa-scale-110"
icon="bell"
/>{{ $t("nav.interactions") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser && pleromaChatMessagesAvailable"> <li v-if="currentUser && pleromaChatMessagesAvailable">
<router-link :to="{ name: 'chats', params: { username: currentUser.screen_name } }"> <router-link :to="{ name: 'chats', params: { username: currentUser.screen_name } }">
<div <div
v-if="unreadChatCount" v-if="unreadChatCount"
class="badge badge-notification unread-chat-count" class="badge badge-notification"
> >
{{ unreadChatCount }} {{ unreadChatCount }}
</div> </div>
<i class="button-icon icon-chat" /> {{ $t("nav.chats") }} <FAIcon
fixed-width
class="fa-scale-110"
icon="comments"
/>{{ $t("nav.chats") }}
</router-link> </router-link>
</li> </li>
<li v-if="currentUser && currentUser.locked"> <li v-if="currentUser && currentUser.locked">
<router-link :to="{ name: 'friend-requests' }"> <router-link :to="{ name: 'friend-requests' }">
<i class="button-icon icon-user-plus" /> {{ $t("nav.friend_requests") }} <FAIcon
fixed-width
class="fa-scale-110"
icon="user-plus"
/>{{ $t("nav.friend_requests") }}
<span <span
v-if="followRequestCount > 0" v-if="followRequestCount > 0"
class="badge follow-request-count" class="badge badge-notification"
> >
{{ followRequestCount }} {{ followRequestCount }}
</span> </span>
@@ -39,7 +55,11 @@
</li> </li>
<li> <li>
<router-link :to="{ name: 'about' }"> <router-link :to="{ name: 'about' }">
<i class="button-icon icon-info-circled" /> {{ $t("nav.about") }} <FAIcon
fixed-width
class="fa-scale-110"
icon="info-circle"
/>{{ $t("nav.about") }}
</router-link> </router-link>
</li> </li>
</ul> </ul>
@@ -52,23 +72,20 @@
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
.nav-panel .panel { .NavPanel {
.panel {
overflow: hidden; overflow: hidden;
box-shadow: var(--panelShadow); box-shadow: var(--panelShadow);
} }
.nav-panel ul {
ul {
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.follow-request-count { li {
margin: -6px 10px; position: relative;
background-color: $fallback--bg;
background-color: var(--input, $fallback--faint);
}
.nav-panel li {
border-bottom: 1px solid; border-bottom: 1px solid;
border-color: $fallback--border; border-color: $fallback--border;
border-color: var(--border, $fallback--border); border-color: var(--border, $fallback--border);
@@ -87,15 +104,19 @@
border-bottom-left-radius: $fallback--panelRadius; border-bottom-left-radius: $fallback--panelRadius;
border-bottom-left-radius: var(--panelRadius, $fallback--panelRadius); border-bottom-left-radius: var(--panelRadius, $fallback--panelRadius);
} }
} }
.nav-panel li:last-child { li:last-child {
border: none; border: none;
} }
.nav-panel a { a {
display: block; display: block;
padding: 0.8em 0.85em; box-sizing: border-box;
align-items: stretch;
height: 3.5em;
line-height: 3.5em;
padding: 0 1em;
&:hover { &:hover {
background-color: $fallback--lightBg; background-color: $fallback--lightBg;
@@ -123,9 +144,16 @@
text-decoration: underline; text-decoration: underline;
} }
} }
} }
.nav-panel .button-icon:before { .fa-scale-110 {
width: 1.1em; margin-right: 0.8em;
}
.badge {
position: absolute;
right: 0.6rem;
top: 1.25em;
}
} }
</style> </style>
@@ -7,6 +7,28 @@ import Timeago from '../timeago/timeago.vue'
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js' import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCheck,
faTimes,
faStar,
faRetweet,
faUserPlus,
faEyeSlash,
faUser,
faSuitcaseRolling
} from '@fortawesome/free-solid-svg-icons'
library.add(
faCheck,
faTimes,
faStar,
faRetweet,
faUserPlus,
faUser,
faEyeSlash,
faSuitcaseRolling
)
const Notification = { const Notification = {
data () { data () {
@@ -1,3 +1,5 @@
@import '../../_variables.scss';
// TODO Copypaste from Status, should unify it somehow // TODO Copypaste from Status, should unify it somehow
.Notification { .Notification {
&.-muted { &.-muted {
@@ -49,4 +51,34 @@
display: block; display: block;
} }
} }
.type-icon {
margin: 0 0.1em;
}
&.-type--repeat .type-icon {
color: $fallback--cGreen;
color: var(--cGreen, $fallback--cGreen);
}
&.-type--follow .type-icon {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
&.-type--follow-request .type-icon {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
&.-type--like .type-icon {
color: orange;
color: $fallback--cOrange;
color: var(--cOrange, $fallback--cOrange);
}
&.-type--move .type-icon {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
} }
+44 -20
View File
@@ -1,5 +1,5 @@
<template> <template>
<status <Status
v-if="notification.type === 'mention'" v-if="notification.type === 'mention'"
:compact="true" :compact="true"
:statusoid="notification.status" :statusoid="notification.status"
@@ -14,16 +14,20 @@
{{ notification.from_profile.screen_name }} {{ notification.from_profile.screen_name }}
</router-link> </router-link>
</small> </small>
<a <button
href="#" class="button-unstyled unmute"
class="unmute"
@click.prevent="toggleMute" @click.prevent="toggleMute"
><i class="button-icon icon-eye-off" /></a> >
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="eye-slash"
/>
</button>
</div> </div>
<div <div
v-else v-else
class="non-mention" class="Notification non-mention"
:class="[userClass, { highlighted: userStyle }]" :class="[userClass, { highlighted: userStyle }, '-type--' + notification.type]"
:style="[ userStyle ]" :style="[ userStyle ]"
> >
<a <a
@@ -60,26 +64,39 @@
:title="'@'+notification.from_profile.screen_name" :title="'@'+notification.from_profile.screen_name"
>{{ notification.from_profile.name }}</span> >{{ notification.from_profile.name }}</span>
<span v-if="notification.type === 'like'"> <span v-if="notification.type === 'like'">
<i class="fa icon-star lit" /> <FAIcon
class="type-icon"
icon="star"
/>
<small>{{ $t('notifications.favorited_you') }}</small> <small>{{ $t('notifications.favorited_you') }}</small>
</span> </span>
<span v-if="notification.type === 'repeat'"> <span v-if="notification.type === 'repeat'">
<i <FAIcon
class="fa icon-retweet lit" class="type-icon"
icon="retweet"
:title="$t('tool_tip.repeat')" :title="$t('tool_tip.repeat')"
/> />
<small>{{ $t('notifications.repeated_you') }}</small> <small>{{ $t('notifications.repeated_you') }}</small>
</span> </span>
<span v-if="notification.type === 'follow'"> <span v-if="notification.type === 'follow'">
<i class="fa icon-user-plus lit" /> <FAIcon
class="type-icon"
icon="user-plus"
/>
<small>{{ $t('notifications.followed_you') }}</small> <small>{{ $t('notifications.followed_you') }}</small>
</span> </span>
<span v-if="notification.type === 'follow_request'"> <span v-if="notification.type === 'follow_request'">
<i class="fa icon-user lit" /> <FAIcon
class="type-icon"
icon="user"
/>
<small>{{ $t('notifications.follow_request') }}</small> <small>{{ $t('notifications.follow_request') }}</small>
</span> </span>
<span v-if="notification.type === 'move'"> <span v-if="notification.type === 'move'">
<i class="fa icon-arrow-curved lit" /> <FAIcon
class="type-icon"
icon="suitcase-rolling"
/>
<small>{{ $t('notifications.migrated_to') }}</small> <small>{{ $t('notifications.migrated_to') }}</small>
</span> </span>
<span v-if="notification.type === 'pleroma:emoji_reaction'"> <span v-if="notification.type === 'pleroma:emoji_reaction'">
@@ -116,11 +133,16 @@
/> />
</span> </span>
</div> </div>
<a <button
v-if="needMute" v-if="needMute"
href="#" class="button-unstyled"
@click.prevent="toggleMute" @click.prevent="toggleMute"
><i class="button-icon icon-eye-off" /></a> >
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="eye-slash"
/>
</button>
</span> </span>
<div <div
v-if="notification.type === 'follow' || notification.type === 'follow_request'" v-if="notification.type === 'follow' || notification.type === 'follow_request'"
@@ -136,13 +158,15 @@
v-if="notification.type === 'follow_request'" v-if="notification.type === 'follow_request'"
style="white-space: nowrap;" style="white-space: nowrap;"
> >
<i <FAIcon
class="icon-ok button-icon follow-request-accept" icon="check"
class="fa-scale-110 fa-old-padding follow-request-accept"
:title="$t('tool_tip.accept_follow_request')" :title="$t('tool_tip.accept_follow_request')"
@click="approveUser()" @click="approveUser()"
/> />
<i <FAIcon
class="icon-cancel button-icon follow-request-reject" icon="times"
class="fa-scale-110 fa-old-padding follow-request-reject"
:title="$t('tool_tip.reject_follow_request')" :title="$t('tool_tip.reject_follow_request')"
@click="denyUser()" @click="denyUser()"
/> />
@@ -6,6 +6,13 @@ import {
filteredNotificationsFromStore, filteredNotificationsFromStore,
unseenNotificationsFromStore unseenNotificationsFromStore
} from '../../services/notification_utils/notification_utils.js' } from '../../services/notification_utils/notification_utils.js'
import FaviconService from '../../services/favicon_service/favicon_service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
library.add(
faCircleNotch
)
const DEFAULT_SEEN_TO_DISPLAY_COUNT = 30 const DEFAULT_SEEN_TO_DISPLAY_COUNT = 30
@@ -69,8 +76,10 @@ const Notifications = {
watch: { watch: {
unseenCountTitle (count) { unseenCountTitle (count) {
if (count > 0) { if (count > 0) {
FaviconService.drawFaviconBadge()
this.$store.dispatch('setPageTitle', `(${count})`) this.$store.dispatch('setPageTitle', `(${count})`)
} else { } else {
FaviconService.clearFaviconBadge()
this.$store.dispatch('setPageTitle', '') this.$store.dispatch('setPageTitle', '')
} }
} }
@@ -158,37 +158,6 @@
margin-right: .2em; margin-right: .2em;
} }
.icon-retweet.lit {
color: $fallback--cGreen;
color: var(--cGreen, $fallback--cGreen);
}
.icon-user.lit {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
.icon-user-plus.lit {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
.icon-reply.lit {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
.icon-star.lit {
color: orange;
color: $fallback--cOrange;
color: var(--cOrange, $fallback--cOrange);
}
.icon-arrow-curved.lit {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
.status-content { .status-content {
margin: 0; margin: 0;
max-height: 300px; max-height: 300px;
+9 -12
View File
@@ -15,16 +15,9 @@
class="badge badge-notification unseen-count" class="badge badge-notification unseen-count"
>{{ unseenCount }}</span> >{{ unseenCount }}</span>
</div> </div>
<div
v-if="error"
class="loadmore-error alert error"
@click.prevent
>
{{ $t('timeline.error_fetching') }}
</div>
<button <button
v-if="unseenCount" v-if="unseenCount"
class="read-button" class="button-default read-button"
@click.prevent="markAsSeen" @click.prevent="markAsSeen"
> >
{{ $t('notifications.read') }} {{ $t('notifications.read') }}
@@ -48,20 +41,24 @@
> >
{{ $t('notifications.no_more_notifications') }} {{ $t('notifications.no_more_notifications') }}
</div> </div>
<a <button
v-else-if="!loading" v-else-if="!loading"
href="#" class="button-unstyled -link -fullwidth"
@click.prevent="fetchOlderNotifications()" @click.prevent="fetchOlderNotifications()"
> >
<div class="new-status-notification text-center panel-footer"> <div class="new-status-notification text-center panel-footer">
{{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }} {{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }}
</div> </div>
</a> </button>
<div <div
v-else v-else
class="new-status-notification text-center panel-footer" class="new-status-notification text-center panel-footer"
> >
<i class="icon-spin3 animate-spin" /> <FAIcon
icon="circle-notch"
spin
size="lg"
/>
</div> </div>
</div> </div>
</div> </div>

Some files were not shown because too many files have changed in this diff Show More