Compare commits

...

1180 Commits

Author SHA1 Message Date
Vivian Lim 442f0e76a5 Merge branch 'snoot' of ssh://vvn.space:2222/vivlim/pleroma-fe into snoot 2019-04-24 00:39:33 -07:00
Vivian Lim b3be1ef6ff Merge branch 'develop' into snoot 2019-04-24 00:36:45 -07:00
Vivian Lim 0790fbdf99 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into develop 2019-04-23 23:50:39 -07:00
Vivian Lim 46b5fcbddd configs 2019-04-23 23:45:14 -07:00
Shpuld Shpludson c8f967d5c0 Merge branch '500' into 'develop'
Set max-width of textarea in settings page

Closes #500

See merge request pleroma/pleroma-fe!761
2019-04-22 14:00:09 +00:00
Shpuld Shpludson 4b173b5182 Merge branch '487' into 'develop'
Fix broken Follow Export

Closes #487

See merge request pleroma/pleroma-fe!762
2019-04-22 13:59:12 +00:00
Shpuld Shpludson ffecbc2e79 Merge branch 'develop' into 'develop'
[i18n] Update for Occitan language

See merge request pleroma/pleroma-fe!765
2019-04-22 13:20:13 +00:00
Shpuld Shpludson 98742979c8 Merge branch '501' into 'develop'
Remove space in the timeline setting copy

Closes #501

See merge request pleroma/pleroma-fe!763
2019-04-22 13:15:07 +00:00
Shpuld Shpludson 9183c9e845 Merge branch 'change-pencil-to-wrentch' into 'develop'
Change pencil icon to wrentch

See merge request pleroma/pleroma-fe!764
2019-04-22 13:11:14 +00:00
Shpuld Shpludson b7c16ad68e Merge branch 'bugfix/user-card-emojis-2' into 'develop'
user_card.vue: Fix .emoji to apply to img

See merge request pleroma/pleroma-fe!766
2019-04-22 13:06:15 +00:00
taehoon f7baa6e190 set max-width of textarea in settings page 2019-04-21 14:06:32 -04:00
taehoon aefd4551a3 Remove space in the timeline setting copy 2019-04-21 14:06:10 -04:00
Haelwenn (lanodan) Monnier 14d506154e
user_card.vue: Fix .emoji to apply to img 2019-04-20 21:12:56 +02:00
Exilat ed9aa8df76 Update oc.json 2019-04-20 14:44:43 +00:00
Exilat 213891ac71 Update oc.json 2019-04-20 14:38:04 +00:00
Exilat 69468c7c41 Update oc.json 2019-04-20 14:35:14 +00:00
Exilat 44f18caf4d Update oc.json 2019-04-20 14:29:04 +00:00
Brenden Bice 6aee2ed63f replace pencil with wrench icon
# Conflicts:
#	src/components/user_card/user_card.vue
2019-04-19 13:24:35 -04:00
Brenden Bice d6be4fd921 rebuild fontello with wrench icon added
# Conflicts:
#	static/font/css/fontello-codes.css
#	static/font/css/fontello-embedded.css
#	static/font/css/fontello-ie7-codes.css
#	static/font/css/fontello-ie7.css
#	static/font/css/fontello.css
#	static/font/demo.html
#	static/font/font/fontello.eot
#	static/font/font/fontello.svg
#	static/font/font/fontello.ttf
#	static/font/font/fontello.woff
#	static/font/font/fontello.woff2
2019-04-19 13:20:02 -04:00
taehoon 3565b18712 fetch all friends using pagination 2019-04-19 00:27:06 -04:00
HJ 61d04b8823 Merge branch '497' into 'develop'
Stop fetching user relationship when user is unauthorized

Closes #497

See merge request pleroma/pleroma-fe!759
2019-04-18 06:16:36 +00:00
taehoon 992c8e1f77 stop fetching user relationship when user is unauthorized 2019-04-17 22:47:56 -04:00
Shpuld Shpludson ed0f10e9ee Merge branch '227-bulk-delete' into 'develop'
Add "bulk mute/unmute/block/unblock" feature

See merge request pleroma/pleroma-fe!733
2019-04-17 15:43:05 +00:00
taehoon de945e5f88 Revert "recover border between basic-user-card using list component"
This reverts commit 1d56d486f1f679e793e710969ad54cce5fdb1ebc.

# Conflicts:
#	src/components/follow_requests/follow_requests.vue
#	src/components/user_search/user_search.vue
#	src/components/who_to_follow/who_to_follow.vue
2019-04-17 11:32:49 -04:00
taehoon bd88a481c6 remove extra spacing 2019-04-17 11:32:49 -04:00
taehoon e67fecff0a code readability 2019-04-17 11:32:49 -04:00
taehoon bb38a43117 fix typos 2019-04-17 11:32:49 -04:00
taehoon a89236f67c clean up 2019-04-17 11:32:49 -04:00
taehoon 10ecc2c816 make sure to use filtered selected keys 2019-04-17 11:32:49 -04:00
taehoon ecff6acf2d support indeterminate checkbox state 2019-04-17 11:32:49 -04:00
taehoon 3f5e798de7 render span tag only if it has content 2019-04-17 11:32:49 -04:00
taehoon 988849116d update model and props properties 2019-04-17 11:32:49 -04:00
taehoon 8088043a0c import scss variables 2019-04-17 11:32:49 -04:00
taehoon 1144025f30 update checkbox importing path 2019-04-17 11:32:49 -04:00
taehoon 468aec0de1 rewrite checkbox component as non-functional 2019-04-17 11:32:49 -04:00
taehoon ac9ddfb1e2 support i18n 2019-04-17 11:32:49 -04:00
taehoon 7f6bd538f3 ui improvements 2019-04-17 11:32:49 -04:00
taehoon c81bde0c1d clean up 2019-04-17 11:32:49 -04:00
taehoon d3cad54aa3 add bulk mute/unmute buttons and wire up to vuex 2019-04-17 11:32:49 -04:00
taehoon 13c8f10f4b wire up bulk action buttons to vuex 2019-04-17 11:32:49 -04:00
taehoon 7e74a13fcf add a comment 2019-04-17 11:32:49 -04:00
taehoon 1afef1037e show list header only if there are items 2019-04-17 11:32:49 -04:00
taehoon ac62e47c70 pass down empty slot 2019-04-17 11:32:49 -04:00
taehoon 67919f95a6 make border of list header thicker 2019-04-17 11:32:49 -04:00
taehoon 8fa639f252 add bulk action buttons 2019-04-17 11:32:49 -04:00
taehoon 403c7bbe6c add reusable progress-button cmoponent 2019-04-17 11:32:49 -04:00
taehoon fe7766bc61 replace scope attributes by slot-scope 2019-04-17 11:32:49 -04:00
taehoon d4e43e0e26 add border-bottom to the header 2019-04-17 11:32:49 -04:00
taehoon 7a8ffcd79b support header slot 2019-04-17 11:32:49 -04:00
taehoon cf2c411db3 add header to selectable-list component 2019-04-17 11:32:49 -04:00
taehoon 83faa96f1b remove border-bottom of the last list item 2019-04-17 11:32:49 -04:00
taehoon ca26776b4e recover border between basic-user-card using list component 2019-04-17 11:32:49 -04:00
taehoon f066ccd28b show empty slot only if it has content 2019-04-17 11:32:49 -04:00
taehoon b8ec13c8fd let not selectable-list know about getKey prop 2019-04-17 11:32:49 -04:00
taehoon 32035217b8 clean up 2019-04-17 11:32:49 -04:00
taehoon 792ae1697e refactor selectable-list using list component 2019-04-17 11:32:49 -04:00
taehoon d806038ad3 add border-bottom style to the list component as well 2019-04-17 11:32:49 -04:00
taehoon 80d83b46d9 move border-bottom style to the list 2019-04-17 11:32:49 -04:00
taehoon 3a318dc373 add some styling to the selectable-list component 2019-04-17 11:32:48 -04:00
taehoon f6e9f28745 use key properly 2019-04-17 11:32:48 -04:00
taehoon e0b2463750 save selected items to the state 2019-04-17 11:32:48 -04:00
taehoon d9b3f5be47 use SelectableList for blocks/mutes list 2019-04-17 11:32:48 -04:00
taehoon 23b9d1eaa3 rename selectable_row to selectable_list 2019-04-17 11:32:48 -04:00
taehoon 39efe9c522 remove unused yarn package 2019-04-17 11:32:48 -04:00
taehoon 0bf451bb36 remove withList hoc 2019-04-17 11:32:48 -04:00
taehoon 738a3dc02d refactor using List component 2019-04-17 11:32:48 -04:00
taehoon 1cec2b6969 use reusable List vue component instead of withList hoc
Using slot is the preferred way in vue
2019-04-17 11:32:48 -04:00
taehoon 4b292564d8 add SelectableRow component 2019-04-17 11:32:48 -04:00
taehoon a509990937 add checkbox component 2019-04-17 11:32:48 -04:00
Shpuld Shpludson e9f4244b26 Merge branch '494' into 'develop'
Fix UserProfile showing wrong user card in the header

Closes #498 and #494

See merge request pleroma/pleroma-fe!757
2019-04-17 15:27:19 +00:00
taehoon 2e86a4eb4f fix mess in UserProfile component 2019-04-15 16:49:33 -04:00
Shpuld Shpludson 55410c91fa Merge branch '489' into 'develop'
Fix Blocked status inconsistency between Blocks setting tab and Following profile tab

Closes #489

See merge request pleroma/pleroma-fe!751
2019-04-15 19:58:15 +00:00
Shpuld Shpludson efa93d0829 Merge branch '227-quick-add' into 'develop'
Support user searching to mute/block directly in the mutes/blocks tab

See merge request pleroma/pleroma-fe!727
2019-04-15 18:21:52 +00:00
taehoon 329dc833b3 clean up 2019-04-14 23:44:50 -04:00
taehoon d874ca905c support i18n 2019-04-14 23:44:50 -04:00
taehoon 948baba9d3 add muted user to the mutes list in real time 2019-04-14 23:44:50 -04:00
taehoon d58e08cf52 add search to the mutes tab as well 2019-04-14 23:44:50 -04:00
taehoon 0bdb0e5a81 rename Autosuggest component 2019-04-14 23:44:49 -04:00
taehoon 1cf9780e05 make more generic 2019-04-14 23:44:49 -04:00
taehoon fc5f4fba8c make more generic 2019-04-14 23:44:49 -04:00
taehoon 8410add394 make UserAutoSuggest component more generic 2019-04-14 23:44:49 -04:00
taehoon 5c2c222252 add blocked user to the blocked list on real time 2019-04-14 23:44:49 -04:00
taehoon 9184435887 remove blocked one from the results on real time 2019-04-14 23:44:49 -04:00
taehoon 33467880ed improve ui 2019-04-14 23:44:49 -04:00
taehoon 60b07eeaa4 filter out blocked user or me from the results 2019-04-14 23:44:49 -04:00
taehoon 69f9ea987c make blocking functional in the search results 2019-04-14 23:44:49 -04:00
taehoon fd4289e45a improve ui 2019-04-14 23:44:49 -04:00
taehoon 787737c80d hide results on outside click 2019-04-14 23:44:49 -04:00
taehoon 6d3187b449 remove needless dependency 2019-04-14 23:44:49 -04:00
taehoon b2eb43e3c8 rename css classes 2019-04-14 23:44:49 -04:00
taehoon 94e67ff118 rewrite USerAutoSuggest without any dependency 2019-04-14 23:44:49 -04:00
taehoon da5844205c add user autosuggest component 2019-04-14 23:44:49 -04:00
taehoon d05bd31092 setup vue-autosuggest 2019-04-14 23:44:49 -04:00
taehoon e7010d73ac store friends/followers in the global user repository 2019-04-14 23:41:38 -04:00
Shpuld Shpludson 936eb23bdf Merge branch 'issues/pleroma-fe-496-following-follower-error' into 'develop'
Fix error message on no more data fetched

Closes #496

See merge request pleroma/pleroma-fe!756
2019-04-14 19:15:02 +00:00
Brenden Bice 41845389a9 display no message on empty data fetched from api 2019-04-12 23:12:22 -04:00
Brenden Bice 2ae0507575 remove error message on no more following 2019-04-12 23:09:05 -04:00
HJ fa33e3ec58 Merge branch 'fix-notif-user' into 'develop'
Fix wrong usercard notification

Closes #493

See merge request pleroma/pleroma-fe!755
2019-04-12 07:53:46 +00:00
Henry Jameson 7d01b3d8ba Fix wrong usercard notification 2019-04-12 10:49:22 +03:00
HJ fd3811d651 Merge branch '480-replies' into 'develop'
Display replies to statuses in real time

Closes #480

See merge request pleroma/pleroma-fe!737
2019-04-11 18:51:41 +00:00
taehoon ab7a418d80 maintain conversationsObject storage 2019-04-11 12:46:06 -04:00
taehoon fa16d66c52 remove unused importing 2019-04-11 07:56:26 -04:00
taehoon 724602bdc1 get statuses in a conversation from the global repository instead of local state 2019-04-11 07:56:26 -04:00
HJ 8c2efc5a5c Merge branch 'restore-yarnlock' into 'develop'
restore yarnlock

See merge request pleroma/pleroma-fe!749
2019-04-10 18:13:17 +00:00
Henry Jameson ab58b735cd restore yarnlock 2019-04-10 21:09:26 +03:00
HJ 84505e01f5 Merge branch 'issue-436-mastoapi-notifications' into 'develop'
#436: integrate mastoAPI notifications

Closes #436

See merge request pleroma/pleroma-fe!678
2019-04-10 17:28:42 +00:00
dave 76cd01e99b #436 - remove yarn.lock 2019-04-10 13:22:54 -04:00
dave 40e9eebf91 #436 - merge develop 2019-04-10 12:54:33 -04:00
HJ d94a7b6318 Merge branch 'fix-local' into 'develop'
Fix wrong property read in pleroma object

See merge request pleroma/pleroma-fe!747
2019-04-10 12:06:35 +00:00
Henry Jameson 18cb97a2bd Fix wrong local 2019-04-10 15:02:14 +03:00
Shpuld Shpludson ed3aceff5c Merge branch 'mastoapi/update-extension-support' into 'develop'
Update entity normalizer to include more pleroma-specific fields

See merge request pleroma/pleroma-fe!745
2019-04-10 03:14:58 +00:00
Shpuld Shpludson 25601c6873 Merge branch 'fix-emoji-picker' into 'develop'
support new custom emoji format

Closes #484

See merge request pleroma/pleroma-fe!746
2019-04-10 03:14:51 +00:00
Henry Jameson a25aabfa10 support new custom emoji format 2019-04-09 22:54:14 +03:00
dave d498a26af5 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-436-mastoapi-notifications 2019-04-09 15:42:05 -04:00
Henry Jameson dfd89b0bbc revert, it's still missing 2019-04-09 22:28:36 +03:00
Henry Jameson d95fc02810 add support for pleroma-specific fields 2019-04-09 22:26:57 +03:00
Shpuld Shpludson d7cf841dfe Merge branch '486-expand-button' into 'develop'
#486 - remove expand button on conversation page

Closes #486

See merge request pleroma/pleroma-fe!742
2019-04-09 18:52:18 +00:00
jared 5df049ca31 #486 - remove expand button on conversation page 2019-04-09 14:10:51 -04:00
Shpuld Shpludson b3ace226fb Merge branch 'fix/prevent-repeated-fetching' into 'develop'
#485 Prevent repeated fetching

Closes #485

See merge request pleroma/pleroma-fe!738
2019-04-09 18:05:46 +00:00
jasper 011f04c196 fix small bug 2019-04-09 09:19:48 -07:00
jasper b7d7c21617 Add await to login befor redirect to friends timeline 2019-04-09 08:57:41 -07:00
jasper 1570e779b1 Prevent repeated fetching 2019-04-09 08:38:13 -07:00
Shpuld Shpludson 1e9ddcb0da Merge branch 'fix/notification-bugs' into 'develop'
#474 Fix notification bugs

Closes #474

See merge request pleroma/pleroma-fe!728
2019-04-09 15:24:33 +00:00
dave d3218807b4 #436 - merge develop 2019-04-08 21:04:59 -04:00
Shpuld Shpludson 546ced43d9 Merge branch 'moderation-menu' into 'develop'
Moderation menu #310

See merge request pleroma/pleroma-fe!595
2019-04-08 19:01:40 +00:00
dave b0da32fea2 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-436-mastoapi-notifications 2019-04-08 14:29:12 -04:00
Shpuld Shpludson 2f725c570b Merge branch 'debug_message' into 'develop'
remove debug message

See merge request pleroma/pleroma-fe!735
2019-04-08 16:49:52 +00:00
Maksim 7259e02a10 remove debug message 2019-04-08 16:49:51 +00:00
Shpuld Shpludson 8c7f765dff Merge branch 'issue-469-safe-dm-from-BE' into 'develop'
Issue 469 safe dm from be

Closes #469

See merge request pleroma/pleroma-fe!726
2019-04-04 19:38:03 +00:00
jasper 1c04cd2036 Add space 2019-04-04 09:06:53 -07:00
jasper a1275be4c0 Separate timeline and notification 2019-04-04 09:03:56 -07:00
jasper 7c2b65e9a3 Remove useless codes 2019-04-03 09:08:23 -07:00
jasper ea27483f27 Fix notification bugs 2019-04-03 09:04:46 -07:00
dave fe756fe30d #436 - revert stripe html for notification 2019-04-03 11:17:23 -04:00
dave 6ed26ce65d #436 - notification html to text content 2019-04-03 10:58:39 -04:00
dave 6fa014505c #436 - revert notification silience config 2019-04-03 10:53:11 -04:00
dave 70071b870f #469 - update text copy 2019-04-02 12:46:22 -04:00
dave 67258571c5 #469 - update behavior of safe_dm 2019-04-02 11:19:45 -04:00
dave 9d5ed04147 #469 - clean up 2019-04-02 10:28:38 -04:00
dave c9a9b3122d #469 - DM warning text should vary based on BE setting 2019-04-02 10:26:14 -04:00
dave 8b3f037f87 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-436-mastoapi-notifications 2019-04-02 10:07:36 -04:00
eugenijm 6b6878bde0 Added moderation menu 2019-04-01 23:30:06 +03:00
Shpuld Shpludson ac28e8c2f9 Merge branch 'feature/mobile-improvements-3' into 'develop'
Mobile notifications in nav bar, separate mobile navbar to its own component

See merge request pleroma/pleroma-fe!703
2019-04-01 19:57:31 +00:00
Shpuld Shpludson a595febcb8 Merge branch 'develop' into 'develop'
[i18n] Update oc.json for !611 and !691

See merge request pleroma/pleroma-fe!712
2019-04-01 19:49:16 +00:00
shpuld 89c9448532 fix conflict 2019-04-01 22:47:37 +03:00
Shpuld Shpludson ae3b92ce85 Merge branch 'fix/sending-requests-when-loading' into 'develop'
#463 Add Promise.all to send requests when loading

Closes #463

See merge request pleroma/pleroma-fe!723
2019-04-01 19:45:08 +00:00
Shpuld Shpludson 3b38e1b8a7 Merge branch 'patch-2' into 'develop'
Update Polish translation

See merge request pleroma/pleroma-fe!719
2019-04-01 19:44:11 +00:00
shpuld 46de457f50 Merge branch 'develop' into feature/mobile-improvements-3 2019-04-01 22:42:06 +03:00
shpuld 2879495b8a remove window width copypasta 2019-04-01 22:41:34 +03:00
Shpuld Shpludson df366a586d Merge branch '471-timeline-since-id' into 'develop'
#471 - fix timeline fetch with since_id

Closes #471

See merge request pleroma/pleroma-fe!722
2019-04-01 19:33:45 +00:00
HJ 3c2931529e Merge branch 'minimal-scopes-mode' into 'develop'
Initial work on deprecating scopeModesEnabled in favor of minimalScopeMode

See merge request pleroma/pleroma-fe!633
2019-04-01 19:32:37 +00:00
jasper 90939f198b Fix login handling 2019-04-01 12:32:13 -07:00
HJ c17de4b638 Merge branch '470-toggle-subject-content' into 'develop'
Resolve "Handling subjects/spoiler_text/cw not working properly"

Closes #470

See merge request pleroma/pleroma-fe!721
2019-04-01 18:45:24 +00:00
jasper 8fc10dc177 Add Promise.all to send requests when loading 2019-04-01 10:46:30 -07:00
jared d856c2745c #471 - fix timeline fetch with since_id 2019-04-01 13:25:48 -04:00
jared dee9ab7bda #470 - update button text capitalization 2019-04-01 13:04:40 -04:00
jared 487a194f6d #470 - handle cases without subject 2019-04-01 13:01:28 -04:00
jared 6847e70a49 #470 - update i18n 2019-04-01 12:58:23 -04:00
jared 748b1ed167 #470 - fix subject and content toggle issue 2019-04-01 12:54:34 -04:00
dave 6482201dc9 #436 - sync notification & timeline users 2019-04-01 12:22:49 -04:00
dave 0af2f8e4fd #436 - merge develop & resolve conflict 2019-04-01 12:13:11 -04:00
Shpuld Shpludson 6c24ae9b0b Merge branch 'fix/user-card-buttons' into 'develop'
#467 Fix/Muted and Blocked not "pressed" on User Card

Closes #467

See merge request pleroma/pleroma-fe!720
2019-04-01 15:38:14 +00:00
jasper 80277e5571 Remove useless comma 2019-04-01 07:27:12 -07:00
jasper 4a2f676f2e Fix user card in notification 2019-04-01 07:26:13 -07:00
dave 21ea5adc8b #436 - apply patch and clean up 2019-03-31 21:59:18 -04:00
dave b909796683 #436 - update notification 2019-03-31 15:15:16 -04:00
dave 06fd3a9c5f #436 - apply patch 2019-03-31 14:50:34 -04:00
dave ecacc933e7 #436 - keep original naming 2019-03-31 13:47:23 -04:00
dave 0db66e2905 #436 - keep original naming 2019-03-31 13:41:22 -04:00
dave 8efcfc69e8 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-436-mastoapi-notifications 2019-03-31 11:03:43 -04:00
Marcin Mikołajczak 6828c7d74c Update Polish translation 2019-03-31 13:50:51 +00:00
Henry Jameson 0792732822 final touches 2019-03-30 12:42:42 +02:00
Henry Jameson 4dc64438e9 aaaaggghh 2019-03-30 12:41:42 +02:00
Henry Jameson 995daf70b7 fix lint 2019-03-30 12:34:13 +02:00
Henry Jameson 9f4a9bff46 Merge remote-tracking branch 'upstream/develop' into minimal-scopes-mode
* upstream/develop: (173 commits)
  Fix: Change condition
  fix typo
  update store according to retweeted status
  #433 - update sort by for conversation
  display replies_count right after reply icon
  expose replies_count from mastodon api
  Apparently, MastoAPI gives status in ancestors if you try opening a repeat...
  make side drawer use gesture service and fix its animations
  review/remove error hiding
  errata
  review
  #433 - sort conversation for retweets and clean up
  Revert "Merge branch 'revert-987b5162' into 'develop'"
  Revert "Merge branch 'mastoapi/friends-tl' into 'develop'"
  Add await to login action'
  Remove console log
  Fix warnings in user profile routing
  Add tests for gesture service, fix bug with perpendicular directions
  #255 - clean up autocomplete form
  #255 - clean up user settings page with self-closing html tags
  ...
2019-03-30 12:31:50 +02:00
Henry Jameson e89a622005 fix formatting 2019-03-30 12:29:28 +02:00
Henry Jameson beaf4fcf8a fix formatting 2019-03-30 12:26:53 +02:00
Henry Jameson bf927122df Review 2019-03-30 12:25:23 +02:00
Shpuld Shpludson 0117f6af9f Merge branch 'issues/#465' into 'develop'
update store according to retweeted status

Closes #465

See merge request pleroma/pleroma-fe!713
2019-03-29 15:33:16 +00:00
Shpuld Shpludson e329a362e0 Merge branch 'fix/warnings-in-user-profile' into 'develop'
#461 Fix warnings about user-profile

Closes #461

See merge request pleroma/pleroma-fe!708
2019-03-29 15:32:40 +00:00
dave 783cc00dd0 merge develop & resolve conflict 2019-03-29 10:11:28 -04:00
jasper e6f9b1517b Fix: Change condition 2019-03-28 18:43:03 -07:00
Shpuld Shpludson 25370083b6 Merge branch '255-emoji-input' into 'develop'
#255 - add emoji input component

Closes #255

See merge request pleroma/pleroma-fe!706
2019-03-28 21:09:48 +00:00
shpuld c06bcf3303 add gesture to close notifications drawer 2019-03-28 22:54:45 +02:00
shpuld 31010779f6 Merge branch 'develop' into feature/mobile-improvements-3 2019-03-28 22:25:40 +02:00
Shpuld Shpludson c829b1a5f4 Merge branch 'feat/gesture-service' into 'develop'
Add a gesture service for easier touch gestures

See merge request pleroma/pleroma-fe!714
2019-03-28 20:20:16 +00:00
shpuld 1e2c304f76 fix typo 2019-03-28 22:11:05 +02:00
Shpuld Shpludson ee9aa40001 Merge branch 'issues/#466' into 'develop'
show replies count right after reply icon

Closes #466

See merge request pleroma/pleroma-fe!716
2019-03-28 20:09:59 +00:00
Shpuld Shpludson 7e8c2acc98 Merge branch 'issue-433-status-reply-form' into 'develop'
Issue 433 status reply form

Closes #433

See merge request pleroma/pleroma-fe!674
2019-03-28 20:08:40 +00:00
Brenden Bice 8e4ddcb843 update store according to retweeted status 2019-03-28 13:20:09 -04:00
dave a39fc49e84 #433 - update sort by for conversation 2019-03-28 10:02:33 -04:00
dave e24145e233 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-433-status-reply-form 2019-03-28 09:54:55 -04:00
Brenden Bice 6b5a84e2b3 display replies_count right after reply icon 2019-03-28 03:47:00 -04:00
Brenden Bice 95639fbd63 expose replies_count from mastodon api 2019-03-28 03:46:41 -04:00
HJ e2e3a65c44 Merge branch 'fix/convos-masto' into 'develop'
Apparently, MastoAPI gives status in ancestors if you try opening a repeat...

Closes #460

See merge request pleroma/pleroma-fe!715
2019-03-27 20:55:24 +00:00
Henry Jameson 31a71ee3ee Apparently, MastoAPI gives status in ancestors if you try opening a repeat... 2019-03-27 22:50:19 +02:00
HJ 86696167b7 Merge branch 'issue-457-mastodon-tag-timeline' into 'develop'
#457 - update tag timeline endpoint to MastoAPI

Closes #457

See merge request pleroma/pleroma-fe!707
2019-03-27 20:44:58 +00:00
shpuld 0eff4bd0ac make side drawer use gesture service and fix its animations 2019-03-27 22:44:25 +02:00
dave 30084a1204 merge develop and resolve conflict 2019-03-27 16:41:05 -04:00
HJ aed0943678 Merge branch 'mastoapi/actions' into 'develop'
transition to MastoAPI: Basic user/statuses manipulation

See merge request pleroma/pleroma-fe!669
2019-03-27 20:28:55 +00:00
Henry Jameson 66ab131bd4 Merge remote-tracking branch 'upstream/develop' into mastoapi/actions
* upstream/develop:
  errata
  review
  Revert "Merge branch 'revert-987b5162' into 'develop'"
  Revert "Merge branch 'mastoapi/friends-tl' into 'develop'"
  Add await to login action'
  correctly paginate on MastoAPI
  #442 - update placeholder linebreak
  #442 - clean up Bio placeholder text
  wip support for follower/following, a bit broken and with regression
  switch direct messages to mastoapi
  switch public and TWKN to MastoAPI
  undo this change since BE returns empty object for relationship, add in a separate MR
  updates normalizer for proper user handling and adds support for friends tl via mastoapi
2019-03-27 22:24:38 +02:00
HJ 4d66b9cf45 Merge branch 'mastoapi/followers' into 'develop'
MastoAPI support for followers/friends(following)

See merge request pleroma/pleroma-fe!667
2019-03-27 20:18:44 +00:00
Henry Jameson c2c7e12aad review/remove error hiding 2019-03-27 22:18:43 +02:00
Henry Jameson a5e71d1dd1 Merge remote-tracking branch 'upstream/develop' into mastoapi/followers
* upstream/develop:
  Revert "Merge branch 'revert-987b5162' into 'develop'"
  Revert "Merge branch 'mastoapi/friends-tl' into 'develop'"
  Add await to login action'
  switch direct messages to mastoapi
  switch public and TWKN to MastoAPI
2019-03-27 22:14:26 +02:00
Henry Jameson ff18e339cf Merge remote-tracking branch 'upstream/develop' into mastoapi/followers
* upstream/develop:
  #442 - update placeholder linebreak
  #442 - clean up Bio placeholder text
  undo this change since BE returns empty object for relationship, add in a separate MR
  updates normalizer for proper user handling and adds support for friends tl via mastoapi
2019-03-27 22:12:51 +02:00
Henry Jameson 0a031aae20 errata 2019-03-27 22:04:59 +02:00
Henry Jameson fb2aca06de review 2019-03-27 22:02:46 +02:00
dave 43e97e590c #433 - sort conversation for retweets and clean up 2019-03-27 16:00:54 -04:00
HJ f6e779a084 Merge branch 'masto-api/direct' into 'develop'
switch direct messages to mastoapi

See merge request pleroma/pleroma-fe!649
2019-03-27 19:53:56 +00:00
HJ ea50f55148 Merge branch 'develop' into 'masto-api/direct'
# Conflicts:
#   src/services/api/api.service.js
2019-03-27 19:48:41 +00:00
HJ 3870adf51f Merge branch 'mastoapi/friends-tl' into 'develop'
Mastoapi/friends tl

See merge request pleroma/pleroma-fe!711
2019-03-27 19:40:51 +00:00
Exilat e1e0b8b254 Update oc.json for !611 and !691 2019-03-27 18:46:40 +00:00
dave 0e2931e7de Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-433-status-reply-form 2019-03-27 13:50:51 -04:00
Shpuld Shpludson 85e9e52090 Merge branch 'fix/add-await-to-login-request' into 'develop'
!701 Add await to login action in after_store

See merge request pleroma/pleroma-fe!709
2019-03-27 16:22:31 +00:00
jared 37b33fc615 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into 255-emoji-input 2019-03-27 11:13:06 -04:00
dave 578b412177 #457 - merge develop and resolve conflict 2019-03-27 11:09:30 -04:00
Henry Jameson b3a6bec17b Revert "Merge branch 'revert-987b5162' into 'develop'"
This reverts commit 96753e6a5f, reversing
changes made to 987b5162a7.
2019-03-27 11:17:04 +02:00
HJ e750b2f197 Merge branch 'mastoapi/public-tl' into 'develop'
switch public and TWKN to MastoAPI

See merge request pleroma/pleroma-fe!650
2019-03-27 08:54:57 +00:00
HJ 96753e6a5f Merge branch 'revert-987b5162' into 'develop'
Revert "Merge branch 'mastoapi/friends-tl' into 'develop'"

See merge request pleroma/pleroma-fe!710
2019-03-27 08:51:35 +00:00
HJ 95459ff0bc Revert "Merge branch 'mastoapi/friends-tl' into 'develop'"
This reverts merge request !647
2019-03-27 08:47:54 +00:00
jasper 2d05aef24b Add await to login action' 2019-03-26 14:26:26 -07:00
jasper 26955af60b Remove console log 2019-03-26 13:36:33 -07:00
jasper ab99d5ef95 Fix warnings in user profile routing 2019-03-26 13:35:08 -07:00
shpuld c50e64f8ee Add tests for gesture service, fix bug with perpendicular directions 2019-03-26 22:11:45 +02:00
jared 8fe9101f0b #255 - clean up autocomplete form 2019-03-26 14:53:27 -04:00
jared 6dc2cedab0 #255 - clean up user settings page with self-closing html tags 2019-03-26 13:42:27 -04:00
jared 2927454233 #255 - support textarea and update user settings page 2019-03-26 13:40:37 -04:00
Shpuld Shpludson 987b5162a7 Merge branch 'mastoapi/friends-tl' into 'develop'
Switch friends TL to MastoAPI

See merge request pleroma/pleroma-fe!647
2019-03-26 17:24:37 +00:00
dave 982be05873 #457 - update tag timeline endpoint to MastoAPI 2019-03-26 11:40:34 -04:00
dave 5fd589d5e7 merge develop & resolve conflict 2019-03-26 10:52:46 -04:00
jared 441deb405d Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into 255-emoji-input 2019-03-26 09:38:45 -04:00
jared b97a033839 #255 - add emoji input component 2019-03-25 22:38:15 -04:00
HJ 2f1e690478 Merge branch 'issue-442-placeholder-fix' into 'develop'
#442 - clean up Bio placeholder text

Closes #442

See merge request pleroma/pleroma-fe!689
2019-03-25 22:29:17 +00:00
shpuld e23c19468a somewhat functioning gesture service 2019-03-25 22:44:58 +02:00
dave 467647d5d7 #433 - fix retweet abnormal behavior 2019-03-25 16:09:40 -04:00
HJ 04217fc660 Merge branch 'develop' into 'mastoapi/friends-tl'
# Conflicts:
#   src/services/api/api.service.js
2019-03-25 19:21:48 +00:00
Henry Jameson d766059dee correctly update relationship on follow/unfollow 2019-03-25 21:19:24 +02:00
Henry Jameson 82f077feb9 fixup! Merge remote-tracking branch 'upstream/develop' into mastoapi/actions 2019-03-25 21:12:54 +02:00
Henry Jameson 0ffd43954e Merge remote-tracking branch 'upstream/develop' into mastoapi/actions
* upstream/develop: (87 commits)
  review
  Update attachment normalizer
  Add fallback for attachments uploaded via the other platforms
  Get correct mimetype through entity_normalizer
  Set default parameter
  Switch to mastoapi for posting status and uploading media
  Revert changes
  prevent text pasting if image is pasted
  remove border radius of suggested emojis
  #450 - dispatch login after saved state is loaded
  #448 - fix timeline fetch error when status text is null
  #451 - add class to username span
  No need to fetch mutes on load anymore 🙌
  switch to mastoapi
  switch to mastoapi
  masto api sends muted property now
  No need to fetch user data using old api anymore 🎉
  Switch to mastoapi
  reactivity fixes
  less hackery, more direct usage of mastoapi
  ...
2019-03-25 21:12:15 +02:00
dave c5ec4829a7 #433 - consider page on focused 2019-03-25 15:10:45 -04:00
HJ 3025532ecf Merge branch 'develop' into 'mastoapi/public-tl'
# Conflicts:
#   src/services/api/api.service.js
2019-03-25 19:09:22 +00:00
Henry Jameson 72749834f3 Merge remote-tracking branch 'upstream/develop' into masto-api/direct
* upstream/develop: (40 commits)
  review
  Update attachment normalizer
  Add fallback for attachments uploaded via the other platforms
  Get correct mimetype through entity_normalizer
  Set default parameter
  Switch to mastoapi for posting status and uploading media
  Revert changes
  prevent text pasting if image is pasted
  remove border radius of suggested emojis
  #450 - dispatch login after saved state is loaded
  #448 - fix timeline fetch error when status text is null
  #451 - add class to username span
  No need to fetch mutes on load anymore 🙌
  switch to mastoapi
  switch to mastoapi
  masto api sends muted property now
  No need to fetch user data using old api anymore 🎉
  Switch to mastoapi
  reactivity fixes
  less hackery, more direct usage of mastoapi
  ...
2019-03-25 21:06:58 +02:00
Henry Jameson 968e6c7fe8 correctly paginate on MastoAPI 2019-03-25 21:04:52 +02:00
dave 73dfb00be2 #433 - remove needless nesting/bloating 2019-03-25 14:59:47 -04:00
dave 1a68a9db36 #433 - Fix conversation page highlight, fetch conversation on converation page 2019-03-25 14:55:58 -04:00
dave 6143b1ce0f Resolve merge conflict,
Fix few issues (conversation page highlight, fetch conversation, ...)
2019-03-25 14:47:54 -04:00
Henry Jameson 50960c7cfc Merge remote-tracking branch 'upstream/develop' into mastoapi/followers
* upstream/develop: (87 commits)
  review
  Update attachment normalizer
  Add fallback for attachments uploaded via the other platforms
  Get correct mimetype through entity_normalizer
  Set default parameter
  Switch to mastoapi for posting status and uploading media
  Revert changes
  prevent text pasting if image is pasted
  remove border radius of suggested emojis
  #450 - dispatch login after saved state is loaded
  #448 - fix timeline fetch error when status text is null
  #451 - add class to username span
  No need to fetch mutes on load anymore 🙌
  switch to mastoapi
  switch to mastoapi
  masto api sends muted property now
  No need to fetch user data using old api anymore 🎉
  Switch to mastoapi
  reactivity fixes
  less hackery, more direct usage of mastoapi
  ...
2019-03-25 20:32:12 +02:00
shpuld b13a751926 start creating gesture service 2019-03-25 20:27:44 +02:00
HJ 854d0e8051 Merge branch 'mastoapi/convos' into 'develop'
Fetching convos via MastoAPI

See merge request pleroma/pleroma-fe!662
2019-03-25 18:17:53 +00:00
Henry Jameson cb122e3a99 review 2019-03-25 20:11:06 +02:00
Henry Jameson 3b5fc88989 Merge remote-tracking branch 'upstream/develop' into mastoapi/convos
* upstream/develop: (34 commits)
  Update attachment normalizer
  Add fallback for attachments uploaded via the other platforms
  Get correct mimetype through entity_normalizer
  Set default parameter
  Switch to mastoapi for posting status and uploading media
  Revert changes
  prevent text pasting if image is pasted
  remove border radius of suggested emojis
  #450 - dispatch login after saved state is loaded
  #448 - fix timeline fetch error when status text is null
  #451 - add class to username span
  No need to fetch mutes on load anymore 🙌
  switch to mastoapi
  switch to mastoapi
  masto api sends muted property now
  No need to fetch user data using old api anymore 🎉
  Switch to mastoapi
  Add comment
  Reset statusnet_blocking of all fetched users first while refreshing block list
  Add hideMutedPosts setting and wire up to post-returning endpoints
  ...
2019-03-25 19:54:15 +02:00
Shpuld Shpludson b02085f2ef Merge branch 'issue-450-user-data-populate' into 'develop'
#450 - dispatch login after saved state is loaded

Closes #450

See merge request pleroma/pleroma-fe!701
2019-03-25 16:57:05 +00:00
Shpuld Shpludson 57b82e9236 Merge branch 'file-paste' into 'develop'
#455 - prevent text pasting if image is pasted

Closes #455

See merge request pleroma/pleroma-fe!705
2019-03-25 16:52:25 +00:00
Shpuld Shpludson 182eab051d Merge branch 'develop' into 'develop'
Remove border radius of suggested emojis

See merge request pleroma/pleroma-fe!704
2019-03-25 16:52:01 +00:00
HJ 153ad57007 Merge branch '435-mastoapi-composing-new-post' into 'develop'
Transition to MastoAPI: composing new status and media upload

Closes #435

See merge request pleroma/pleroma-fe!686
2019-03-25 16:42:20 +00:00
taehoon 932652e335 Update attachment normalizer 2019-03-25 12:19:33 -04:00
dave 6a9159b255 #433 - fix broken conversation page 2019-03-25 10:50:09 -04:00
dave 4cec0d589d Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-433-status-reply-form 2019-03-25 10:22:16 -04:00
taehoon 6fdbc182ca Add fallback for attachments uploaded via the other platforms 2019-03-24 21:16:57 -04:00
taehoon 909c315a44 Get correct mimetype through entity_normalizer 2019-03-24 21:16:57 -04:00
taehoon 966add1b29 Set default parameter 2019-03-24 21:16:57 -04:00
taehoon 9802344603 Switch to mastoapi for posting status and uploading media 2019-03-24 21:16:56 -04:00
HJ 01d0531699 Merge branch '227-manage-blocks-mutes' into 'develop'
Transition to MastoAPI: Mute & Block and Add Mutes management tab

See merge request pleroma/pleroma-fe!611
2019-03-24 17:15:21 +00:00
taehoon f03747e841 Revert changes 2019-03-24 13:04:47 -04:00
nik b241539d4d prevent text pasting if image is pasted 2019-03-23 22:45:24 -05:00
nik 05634d222d remove border radius of suggested emojis 2019-03-23 22:26:31 -05:00
shpuld fd12263cac merge develop in 2019-03-23 22:21:57 +02:00
shpuld 85584021fb make notifications close on navigation 2019-03-23 22:03:38 +02:00
Shpuld Shpludson f86a5dc804 Merge branch 'issue-448-status-text-null' into 'develop'
#448 - fix timeline fetch error when status text is null

Closes #448

See merge request pleroma/pleroma-fe!700
2019-03-23 14:17:47 +00:00
Shpuld Shpludson e9b58f1af7 Merge branch 'issue-452-unfollow-button' into 'develop'
#452 - unfollow button issue

Closes #452

See merge request pleroma/pleroma-fe!698
2019-03-23 07:45:42 +00:00
Shpuld Shpludson f3f006c8e3 Merge branch 'issue-451-long-user-name' into 'develop'
#451 - long username on follow/follower tabs

Closes #451

See merge request pleroma/pleroma-fe!697
2019-03-23 07:45:04 +00:00
dave 31d09931c8 #450 - dispatch login after saved state is loaded 2019-03-22 14:04:22 -04:00
dave d70928792d #448 - fix timeline fetch error when status text is null 2019-03-22 13:15:11 -04:00
dave ed4540530b #451 - add class to username span 2019-03-22 10:42:21 -04:00
lambda 277790e462 Merge branch '438-mastoapi-user-search' into 'develop'
Transition to MastoAPI: user search

Closes #438

See merge request pleroma/pleroma-fe!677
2019-03-22 11:16:25 +00:00
taehoon 9fa1bc63b0 No need to fetch mutes on load anymore 🙌 2019-03-21 21:58:02 -04:00
taehoon a64e744c1b switch to mastoapi 2019-03-21 21:53:24 -04:00
taehoon 8702d23a13 switch to mastoapi 2019-03-21 21:44:59 -04:00
taehoon 379e33f6a5 masto api sends muted property now 2019-03-21 21:31:16 -04:00
taehoon 883a84b313 No need to fetch user data using old api anymore 🎉 2019-03-21 21:30:30 -04:00
taehoon af85a3f244 Switch to mastoapi 2019-03-21 21:27:10 -04:00
Henry Jameson e617ed285e reactivity fixes 2019-03-22 00:05:20 +02:00
Henry Jameson 67719e9a23 less hackery, more direct usage of mastoapi 2019-03-21 23:45:18 +02:00
Henry Jameson d6c62fa50f minor UI improvements - keep current behavior of showing originating post initially 2019-03-21 23:27:14 +02:00
Henry Jameson ee94a6732a why did i do that 2019-03-21 22:49:26 +02:00
Henry Jameson 307b4ba698 Merge remote-tracking branch 'upstream/develop' into mastoapi/convos
* upstream/develop: (47 commits)
  #449 - fix auth token fetch issue
  Make select tag use --inputText as text color
  #444 - remote follow clean up
  #444 - show `remote follow` button when logged out
  Add button to save without cropping
  post-merge fixes
  [i18n] Update oc.json
  after store: fix setting postFormats field
  fix user-card avatar falling into permament failed state
  fix flake id users not fetching correctly
  fix console error
  afterStoreSetup: Move log in and theme load to afterStoreSetup.
  afterStoreSetup: Handle 404 cases.
  afterStoreSetup: Emoji and nodeinfo refactor.
  afterStoreSetup: refactor TOS and panel fetching, handle 404s.
  afterStoreSetup: refactor.
  Load persistedStated with async/await.
  whoops
  レインせんぱいにサンキュー
  fix embedded relationship card parsing
  ...
2019-03-21 22:40:20 +02:00
taehoon a0bccbce94 Add comment 2019-03-21 16:39:41 -04:00
taehoon d7919109ec Reset statusnet_blocking of all fetched users first while refreshing block list 2019-03-21 16:39:41 -04:00
taehoon 9857002bf5 Add hideMutedPosts setting and wire up to post-returning endpoints 2019-03-21 16:33:02 -04:00
Henry Jameson fe13b1b75a Merge remote-tracking branch 'upstream/develop' into mastoapi/friends-tl
* upstream/develop: (47 commits)
  #449 - fix auth token fetch issue
  Make select tag use --inputText as text color
  #444 - remote follow clean up
  #444 - show `remote follow` button when logged out
  Add button to save without cropping
  post-merge fixes
  [i18n] Update oc.json
  after store: fix setting postFormats field
  fix user-card avatar falling into permament failed state
  fix flake id users not fetching correctly
  fix console error
  afterStoreSetup: Move log in and theme load to afterStoreSetup.
  afterStoreSetup: Handle 404 cases.
  afterStoreSetup: Emoji and nodeinfo refactor.
  afterStoreSetup: refactor TOS and panel fetching, handle 404s.
  afterStoreSetup: refactor.
  Load persistedStated with async/await.
  whoops
  レインせんぱいにサンキュー
  fix embedded relationship card parsing
  ...
2019-03-21 22:28:29 +02:00
taehoon 300259fd97 Add todo comment 2019-03-21 16:26:15 -04:00
taehoon 333afd2138 Minor code refactoring 2019-03-21 16:26:15 -04:00
taehoon d65422a6a5 Improve fetch error handling using a util 2019-03-21 16:26:13 -04:00
taehoon 9b690209d0 Reset old mutes state after fetching new mutes data 2019-03-21 16:21:28 -04:00
taehoon 302310a653 Remove old muting logic 2019-03-21 16:19:09 -04:00
taehoon a6ce191cbc Update MuteCard ui 2019-03-21 16:19:05 -04:00
taehoon 859ed4f34f Fetct full data of muted users after fetchMutes api call 2019-03-21 16:19:05 -04:00
taehoon f04cbc8875 Add mute/unmute mutations 2019-03-21 16:19:05 -04:00
taehoon 3255950b0e Add mute/unmute featrue and mutes management tab 2019-03-21 16:19:03 -04:00
Henry Jameson faef769b40 Merge remote-tracking branch 'upstream/develop' into masto-api/direct
* upstream/develop: (47 commits)
  #449 - fix auth token fetch issue
  Make select tag use --inputText as text color
  #444 - remote follow clean up
  #444 - show `remote follow` button when logged out
  Add button to save without cropping
  post-merge fixes
  [i18n] Update oc.json
  after store: fix setting postFormats field
  fix user-card avatar falling into permament failed state
  fix flake id users not fetching correctly
  fix console error
  afterStoreSetup: Move log in and theme load to afterStoreSetup.
  afterStoreSetup: Handle 404 cases.
  afterStoreSetup: Emoji and nodeinfo refactor.
  afterStoreSetup: refactor TOS and panel fetching, handle 404s.
  afterStoreSetup: refactor.
  Load persistedStated with async/await.
  whoops
  レインせんぱいにサンキュー
  fix embedded relationship card parsing
  ...
2019-03-21 22:11:02 +02:00
dave 23bae67146 #452 - update button class name 2019-03-21 15:03:54 -04:00
dave 8932c53706 #451 - update styling 2019-03-21 14:58:28 -04:00
dave dfcdf4f32c #452 - unfollow button issue 2019-03-21 13:19:10 -04:00
dave 1c6e5d3688 #451 - long username on follow/follower tabs 2019-03-21 13:06:37 -04:00
Shpuld Shpludson 66e60572bc Merge branch 'issue-449-auto-token-fetch' into 'develop'
#449 - fix auth token fetch issue

Closes #449

See merge request pleroma/pleroma-fe!696
2019-03-21 16:12:33 +00:00
dave db3b48d444 #449 - fix auth token fetch issue 2019-03-21 12:04:57 -04:00
Shpuld Shpludson c2b7aff325 Merge branch 'issue-444-remote-follow' into 'develop'
#444 - show `remote follow` button when logged out

Closes #444

See merge request pleroma/pleroma-fe!692
2019-03-21 15:46:05 +00:00
Shpuld Shpludson 9890e41440 Merge branch 'feature/bypass-avatar-cropper' into 'develop'
#443 Add button to save without cropping

Closes #443

See merge request pleroma/pleroma-fe!691
2019-03-21 15:44:26 +00:00
Shpuld Shpludson 9e17853b2c Merge branch 'patch-2' into 'develop'
[i18n] Update oc.json

See merge request pleroma/pleroma-fe!684
2019-03-21 15:38:19 +00:00
Shpuld Shpludson a284a267ce Merge branch 'develop' into 'develop'
Fixing typos and badly translated strings (Portuguese)

See merge request pleroma/pleroma-fe!676
2019-03-21 15:37:05 +00:00
Shpuld Shpludson 57cd6f8018 Merge branch 'feature/version-info' into 'develop'
Added new tab to display versions of BE/FE

Closes #397

See merge request pleroma/pleroma-fe!671
2019-03-21 15:25:59 +00:00
shpuld f389128e53 make mobile notifs drawer more like an actual drawer, make mobile nav buttons bigger to press, fix alert dot 2019-03-20 22:09:29 +02:00
HJ 0659d2fd3a Merge branch 'patch-1' into 'develop'
Make select tag use --inputText as text color

See merge request pleroma/pleroma-fe!693
2019-03-20 13:12:51 +00:00
Marcin Mikołajczak 4ace0866da Make select tag use --inputText as text color 2019-03-20 11:52:58 +00:00
dave 96c88b334c #444 - remote follow clean up 2019-03-19 14:41:50 -04:00
dave 07b8115a37 #444 - show `remote follow` button when logged out 2019-03-19 14:36:27 -04:00
jasper 3108722eda Add button to save without cropping 2019-03-18 18:19:42 -07:00
dave 13e727b5ee #436: sync notification with timeline 2019-03-18 14:42:09 -04:00
dave 060d3b0713 #436: implement is_seen logic 2019-03-18 12:30:34 -04:00
dave 55d7bd6d4e Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-436-mastoapi-notifications 2019-03-18 10:37:26 -04:00
dave 5717d97182 #442 - update placeholder linebreak 2019-03-18 10:35:13 -04:00
dave 543cc0d285 #442 - clean up Bio placeholder text 2019-03-17 16:59:08 -04:00
HJ 96f9eab700 Merge branch 'mastoapi/emojis' into 'develop'
MastoAPI: emoji support

See merge request pleroma/pleroma-fe!659
2019-03-17 14:08:01 +00:00
dave 241503346f #436: clean up based on comment 2019-03-17 10:08:01 -04:00
Henry Jameson 4cdfd5fb86 post-merge fixes 2019-03-17 14:41:05 +02:00
Henry Jameson 30c0cafff1 Merge remote-tracking branch 'upstream/develop' into mastoapi/emojis
* upstream/develop: (34 commits)
  after store: fix setting postFormats field
  fix user-card avatar falling into permament failed state
  fix flake id users not fetching correctly
  fix console error
  afterStoreSetup: Move log in and theme load to afterStoreSetup.
  afterStoreSetup: Handle 404 cases.
  afterStoreSetup: Emoji and nodeinfo refactor.
  afterStoreSetup: refactor TOS and panel fetching, handle 404s.
  afterStoreSetup: refactor.
  Load persistedStated with async/await.
  whoops
  レインせんぱいにサンキュー
  fix embedded relationship card parsing
  actually use embedded relationship if it's present
  instead of filtering nulls, let's just not have them in the first place
  #434 - fix plain text issue
  Add floating post-status button on mobile
  Update user settings icon to pencil
  I18n: Update Czech translation
  user_card.vue: Copy over .status-content img styling
  ...
2019-03-17 13:32:56 +02:00
Exilat 7babbce522 [i18n] Update oc.json 2019-03-15 17:23:30 +00:00
dave e5786f32a7 #436: merge develop 2019-03-15 11:28:33 -04:00
taehoon 6e60873a3d Switch to mastoapi for user search 2019-03-15 11:03:11 -04:00
HJ 9364964b01 Merge branch 'mastoapi/user-stuff' into 'develop'
Transition to MastoAPI: user data

See merge request pleroma/pleroma-fe!655
2019-03-15 13:14:41 +00:00
lambda 92eb55c7bc Merge branch 'bugfix/nodeinfo-post-formats' into 'develop'
after store: fix setting postFormats field

See merge request pleroma/pleroma-fe!683
2019-03-15 13:03:35 +00:00
lambda c626f84336 Merge branch 'afterstore-refactor' into 'develop'
afterStoreSetup: Move log in and theme load to afterStoreSetup.

See merge request pleroma/pleroma-fe!680
2019-03-15 13:03:19 +00:00
dave 8ade93bb4d #436: update test 2019-03-14 22:36:11 -04:00
dave 935aae054f #436: add is_local for statuses 2019-03-14 22:07:42 -04:00
HJ ebc6a75d30 Merge branch 'issue-434-plain-text' into 'develop'
#434 - fix plain text issue

Closes #434

See merge request pleroma/pleroma-fe!675
2019-03-14 22:03:33 +00:00
William Pitcock f93d4a3754 after store: fix setting postFormats field 2019-03-14 21:35:45 +00:00
Henry Jameson 71c12fa3a5 fix user-card avatar falling into permament failed state 2019-03-14 23:07:28 +02:00
Henry Jameson 6420c93e98 fix flake id users not fetching correctly 2019-03-14 23:07:28 +02:00
shpuld 0a86d39ba9 remove notifications from sidebar, make notifications appear on login only 2019-03-14 20:40:56 +02:00
dave 97a3f9c0f5 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-436-mastoapi-notifications 2019-03-14 14:24:23 -04:00
Henry Jameson 885a3a77df fix console error 2019-03-14 18:50:51 +02:00
dave 52326e6551 #436: remove clear & dismiss UI updates 2019-03-14 11:57:24 -04:00
shpuld f19284357e make nav bar slide, move mobile post status to mobile nav 2019-03-14 17:46:04 +02:00
dave 06fda27511 #436: update unit testing 2019-03-14 08:06:40 -04:00
dave e5e1d4c643 #436: fix notification order, follow type link issue, duplicate key 2019-03-14 07:55:39 -04:00
Edijs 3c5c09c74f Merge branch 'develop' into feature/version-info 2019-03-13 15:24:09 -07:00
dave 93a2510ede #436: update is_local 2019-03-13 15:43:48 -04:00
dave 78951964fb #436: update entity_normalizer 2019-03-13 15:34:45 -04:00
dave 2f7d890ad2 #436: add dismiss button, disable is_seen part 2019-03-13 14:08:03 -04:00
lain 5318227c37 afterStoreSetup: Move log in and theme load to afterStoreSetup. 2019-03-13 13:29:34 +01:00
lambda 9fd44e4a52 Merge branch 'afterstore-refactor' into 'develop'
Afterstore refactor

See merge request pleroma/pleroma-fe!679
2019-03-13 12:08:28 +00:00
lain 48ac96cfc7 afterStoreSetup: Handle 404 cases. 2019-03-13 12:41:39 +01:00
lain 446785ddce afterStoreSetup: Emoji and nodeinfo refactor. 2019-03-13 12:26:40 +01:00
lain f535ccd925 afterStoreSetup: refactor TOS and panel fetching, handle 404s. 2019-03-13 12:10:57 +01:00
lain c030e62254 afterStoreSetup: refactor. 2019-03-13 11:57:30 +01:00
lain 1387dfb889 Load persistedStated with async/await. 2019-03-13 11:29:45 +01:00
shpuld 7ce8fe9214 merge develop, add mobile nav component 2019-03-12 23:50:54 +02:00
dave cd9a7dd488 #436: integrate mastoAPI notifications 2019-03-12 17:16:57 -04:00
Henry Jameson 644eba87fe whoops 2019-03-12 22:14:41 +02:00
Henry Jameson 27cbe3ca65 レインせんぱいにサンキュー 2019-03-12 22:10:22 +02:00
Henry Jameson ce8b5fcd11 fix embedded relationship card parsing 2019-03-12 21:49:03 +02:00
Henry Jameson b9877a4323 actually use embedded relationship if it's present 2019-03-11 23:45:24 +02:00
Rond 03f1b95252 fixing typos and badly translated strings 2019-03-11 18:26:40 -03:00
Henry Jameson a6a162177b instead of filtering nulls, let's just not have them in the first place 2019-03-11 23:08:09 +02:00
dave 130fb7ae1e #434 - fix plain text issue 2019-03-11 16:48:27 -04:00
Henry Jameson 4efcda1b41 Added some tests 2019-03-11 22:41:08 +02:00
dave 63d7c7bd80 #433: persistency of status form 2019-03-11 16:24:37 -04:00
dave 19015a4ae7 Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into issue-433-status-reply-form 2019-03-11 13:41:55 -04:00
Shpuld Shpludson f397537642 Merge branch 'feature/mobile-improvements-2' into 'develop'
Add floating post-status button on mobile

See merge request pleroma/pleroma-fe!628
2019-03-11 16:51:37 +00:00
Shpuld Shpludson 4a27c6d8d3 Add floating post-status button on mobile 2019-03-11 16:51:37 +00:00
Shpuld Shpludson bb1a4e11f8 Merge branch '382-update-user-settings-icon' into 'develop'
Update user settings icon to pencil

Closes #382

See merge request pleroma/pleroma-fe!602
2019-03-11 16:48:16 +00:00
taehoon d8e938bb5e Update user settings icon to pencil 2019-03-11 11:52:49 -04:00
dave 4f455eefe5 #433: do not remove the reply dialog 2019-03-11 10:52:28 -04:00
lambda f52a33f711 Merge branch 'develop' into 'develop'
Only connect to chat upon authenticating

Closes #403

See merge request pleroma/pleroma-fe!666
2019-03-11 14:43:40 +00:00
lambda ed3bf6f027 Merge branch 'i18n-cs' into 'develop'
I18n: Update Czech translation

See merge request pleroma/pleroma-fe!651
2019-03-11 14:28:44 +00:00
Lorem Ipsum 3414fce53b I18n: Update Czech translation 2019-03-11 14:28:44 +00:00
HJ 89d684af4e Merge branch 'emoji-limit-profile' into 'develop'
user_card.vue: Set img.emoji to 32×32px

See merge request pleroma/pleroma-fe!665
2019-03-11 09:45:16 +00:00
Haelwenn (lanodan) Monnier d0e78df220
user_card.vue: Copy over .status-content img styling 2019-03-11 05:14:49 +01:00
Edijs 9c60934786 Code refactoring 2019-03-10 18:13:01 -07:00
Edijs 8952761370 Version links to BE/FE 2019-03-10 18:06:51 -07:00
Henry Jameson 06d39b62a8 fixed tests, review fixes, now storing local users with downcase screen name for
better compatibility
2019-03-11 02:17:58 +02:00
Edijs 068c9724e4 Added new tab to display versions of BE/FE 2019-03-10 16:58:12 -07:00
Shpuld Shpludson 151e200983 Merge branch 'fix/timeline-gaps-when-loading-older-after-showing-new' into 'develop'
Fix gaps in timeline when loading older after pressing show new

See merge request pleroma/pleroma-fe!670
2019-03-10 21:11:26 +00:00
shpuld 70d7ed3607 Make minId reset with minVisibleId to prevent gaps when showing new 2019-03-10 22:40:48 +02:00
slice e618c6ffb0
Only connect to chat when authenticating in the first place
To avoid duplication of the connection, the chat socket is destroyed
upon logging out.
2019-03-10 11:25:36 -07:00
Henry Jameson 4a5aef8883 basic user and status actions implemented 2019-03-10 19:15:07 +02:00
Henry Jameson 0b1506a4c0 wip support for follower/following, a bit broken and with regression 2019-03-10 18:05:51 +02:00
Shpuld Shpludson 841648676c Merge branch 'issue-432-dot-key' into 'develop'
#432 - prevent post status form textarea keydown event propagation

Closes #432

See merge request pleroma/pleroma-fe!658
2019-03-10 15:29:44 +00:00
slice a67881b096
Check for websocket token before connecting to chat
Closes #403. Previously, a socket to the chat channel would be opened if
chat is enabled, regardless if the user is logged in or not. This patch
only allows a connection to be opened if a wsToken (websocket token) is
present, which prevents websocket errors from unauthenticated users.
2019-03-10 01:54:26 -08:00
Haelwenn (lanodan) Monnier 07a46f7736
user_card.vue: Set img.emoji to 32×32px
Related to https://git.pleroma.social/pleroma/pleroma/merge_requests/792
2019-03-10 01:56:51 +01:00
Henry Jameson 49b0f0a04a Fetching convos via MastoAPI. Had to change conversation component a bit for
better support, since MastoAPI doesn't have coversation ids
2019-03-09 18:33:49 +02:00
Henry Jameson 489f840d84 fix error 2019-03-09 11:54:11 +02:00
Henry Jameson f3a9200b7c some test fixes, disabled one test for now since logic now is even more async in general 2019-03-09 02:47:20 +02:00
Henry Jameson 47211fb32c emoji adder 2019-03-09 02:23:50 +02:00
Henry Jameson a02a74e9b9 attempt at fixing switching to user TL 2019-03-09 01:51:36 +02:00
Henry Jameson fe624f6114 fix reply-to marker, also whoops console log 2019-03-09 01:34:15 +02:00
Henry Jameson 690c1dcd7a revert some stuff, turns out it's actually breaking. Fixed some local user things 2019-03-09 01:19:56 +02:00
Henry Jameson 4f3a220487 Since BE doesn't support fetching user by screen name over MastoAPI we'll gonna
just fetching it over QvitterAPI real quick :DDDDDDDDD
2019-03-08 22:40:57 +02:00
dave 3468c0fd04 #432 - prevent post status form textarea keydown event propagation 2019-03-08 13:53:46 -05:00
Henry Jameson 853e0bc26f switch to mastoapi for user timeline 2019-03-08 00:50:58 +02:00
Henry Jameson ee49409049 Partially transitioned user data to MastoAPI. Added support for fetching
relationship data. Upgraded code to be more resilient to nulls caused by missing
data in either APIs
2019-03-08 00:35:30 +02:00
Henry Jameson 6e2946f352 switch direct messages to mastoapi 2019-03-07 20:21:07 +02:00
Henry Jameson 8522063b2c switch public and TWKN to MastoAPI 2019-03-07 20:16:35 +02:00
Henry Jameson c038d0c12a undo this change since BE returns empty object for relationship, add in a
separate MR
2019-03-07 20:04:29 +02:00
Henry Jameson 2e59ab738b updates normalizer for proper user handling and adds support for friends tl via mastoapi 2019-03-07 19:49:41 +02:00
Shpuld Shpludson 09736691ea Merge branch '420-redo-user-card-content' into 'develop'
Re-do UserCardContent Component CSS

Closes #420

See merge request pleroma/pleroma-fe!642
2019-03-07 16:38:45 +00:00
Shpuld Shpludson 82cd1252b5 Merge branch '415-timeline' into 'develop'
Fix timeline updating bug when scrolled down

Closes #415

See merge request pleroma/pleroma-fe!644
2019-03-07 16:34:43 +00:00
Shpuld Shpludson 09b0f6dd87 Merge branch 'issue-392-other-user-stale-data' into 'develop'
#392: stale data served to new user account

Closes #392

See merge request pleroma/pleroma-fe!625
2019-03-07 16:33:22 +00:00
Shpuld Shpludson e3b3ef156b Merge branch 'fix/remove-posts-immediately-by-blocking-someone' into 'develop'
#330 Remove posts immediately by blocking someone

See merge request pleroma/pleroma-fe!589
2019-03-07 16:07:01 +00:00
Shpuld Shpludson 2baff88e3f Merge branch 'fix/gallery-css' into 'develop'
Fix gallery style - move hide button to top right

Closes #335

See merge request pleroma/pleroma-fe!579
2019-03-07 16:03:32 +00:00
Shpuld Shpludson bf1fa52e5e Merge branch 'fix/post-content-type' into 'develop'
#327: Load post status content type from instance config

Closes #327

See merge request pleroma/pleroma-fe!641
2019-03-07 16:03:06 +00:00
Shpuld Shpludson c44f0a9bde Merge branch 'fix/fetch-activities-by-last-id' into 'develop'
#406 Fetch activities by last id

See merge request pleroma/pleroma-fe!621
2019-03-07 05:06:43 +00:00
Edijs 292cdfb24b Merge content types translations 2019-03-06 20:13:04 -08:00
Shpuld Shpludson 423e1b3b12 Merge branch 'i18n-cs' into 'develop'
I18n: Add Czech translation

See merge request pleroma/pleroma-fe!627
2019-03-06 20:23:46 +00:00
Shpuld Shpludson de46ede8fd Merge branch 'issue-346-auto-post' into 'develop'
#346: Hyperlink is not included

Closes #346

See merge request pleroma/pleroma-fe!626
2019-03-06 20:22:12 +00:00
taehoon aca3b37134 Use a cross browser safe solution to get scroll top 2019-03-06 12:10:29 -05:00
Shpuld Shpludson 830f3762ef Merge branch 'emoji-limit' into 'develop'
compatibility with upcoming changes

See merge request pleroma/pleroma-fe!643
2019-03-06 05:11:07 +00:00
taehoon 5f51fe897d Revert modifier class notation 2019-03-05 21:52:04 -05:00
taehoon 37acb51df4 Update classname 2019-03-05 21:48:07 -05:00
taehoon 7cb13df8ad Update tests 2019-03-05 14:13:22 -05:00
taehoon 7bceabb5bd Rename UserCardContent to UserCard 2019-03-05 14:01:49 -05:00
taehoon baf603a506 Update block class name of BasicUserCard component 2019-03-05 13:56:40 -05:00
taehoon 43c52cb950 Update modifier class notation 2019-03-05 13:25:31 -05:00
Henry Jameson 68b2d9ef56 compatibility with upcoming changes 2019-03-05 20:15:18 +02:00
taehoon e0a66b989d Re-do UserCardContent css 2019-03-05 10:46:03 -05:00
Shpuld Shpludson 216073eb58 Merge branch 'fix/gallery-and-attachment-spacing' into 'develop'
Unify spacing between gallery/link preview/attachment components

See merge request pleroma/pleroma-fe!638
2019-03-05 14:40:20 +00:00
Shpuld Shpludson 8cda230fba Merge branch '419-avatar-cropper-png' into 'develop'
Generate cropped avatar image in the original file type

Closes #419

See merge request pleroma/pleroma-fe!640
2019-03-05 14:40:08 +00:00
Edijs f91e4a5801 Load post status content type from instance config 2019-03-04 21:29:56 -08:00
taehoon ff9e55ae42 Generate cropped avatar image in the original file type 2019-03-04 21:22:32 -05:00
Shpuld Shpludson 3e4d465eba Merge branch 'patch-2' into 'develop'
Update of the Occitan file.

See merge request pleroma/pleroma-fe!635
2019-03-04 19:27:38 +00:00
Exilat 5a273d528f Update oc.json 2019-03-04 18:53:16 +00:00
Shpuld Shpludson 4ab3e29877 Merge branch 'develop' into 'develop'
Portuguese translation update

See merge request pleroma/pleroma-fe!637
2019-03-04 18:21:14 +00:00
shpuld bd0485ad2f unify spacing between gallery/link preview/attachment components 2019-03-04 18:56:47 +02:00
Shpuld Shpludson d6e9ad3b61 Merge branch 'develop' into 'develop'
Update and complete the Esperanto translation

See merge request pleroma/pleroma-fe!630
2019-03-04 16:11:17 +00:00
Shpuld Shpludson 893767b780 Merge branch 'issue-417-profile-tab' into 'develop'
Issue 417 profile tab

Closes #417

See merge request pleroma/pleroma-fe!634
2019-03-04 16:09:23 +00:00
aaabulafiaaa a2a3bda1f6 more pt strings 2019-03-04 08:36:35 -03:00
aaabulafiaaa 116a51e949 more pt strings 2019-03-03 19:42:02 -03:00
aaabulafiaaa ae1a9a8626 More strings 2019-03-03 19:03:11 -03:00
rondnelly assis 793abed7ed Translating more strings 2019-03-03 21:55:16 +00:00
Shpuld Shpludson 42d36fc98b Merge branch 'issue-418-notification-timeago' into 'develop'
Issue 418 notification timeago

Closes #418

See merge request pleroma/pleroma-fe!636
2019-03-03 20:16:51 +00:00
dave 0ea9e4ca14 #418: update timeago margin to align with icons 2019-03-03 14:15:53 -05:00
dave f392668b73 #418: update notification timeago format 2019-03-03 14:11:38 -05:00
Exilat 3e16b5a2e0 Update of the Occitan file.
Not at 100% but more complete then what it was.
2019-03-03 19:06:32 +00:00
dave 5a0bb29f02 #417: reset tab from the outside 2019-03-03 13:38:48 -05:00
dave 3d30ad1dda #417: refresh tab on user profile only 2019-03-03 12:53:01 -05:00
dave 10711f9045 #417: reset tab status when active user changes 2019-03-03 12:15:55 -05:00
Shpuld Shpludson 3ed1eb5723 Merge branch 'hotfix-replies' into 'develop'
fix broken statuses

See merge request pleroma/pleroma-fe!632
2019-03-03 14:58:05 +00:00
shpuld c1ee7c028b Fix bug in replies 2019-03-03 16:43:41 +02:00
shpuld c7e180080a more work with notifications drawer 2019-03-03 16:33:40 +02:00
Henry Jameson 6184c88ac7 Initial work on deprecating scopeModesEnabled in favor of minimalScopeMode 2019-03-03 15:45:17 +02:00
Henry Jameson 6841f516fc fix broken statuses 2019-03-02 20:39:04 +02:00
Shpuld Shpludson cef0306428 Merge branch '416-name-font-size' into 'develop'
Update font-size of username in UserCardContent component

Closes #416

See merge request pleroma/pleroma-fe!631
2019-03-02 18:05:29 +00:00
taehoon 94b0321c71 Update font-size of username in UserCardContent component 2019-03-02 12:58:17 -05:00
Aditoo17 93f5f94698 I18n: Add Czech translation 2019-03-02 18:25:49 +01:00
Tirifto a884bbb6a6
Update and complete the Esperanto translation 2019-03-02 17:50:59 +01:00
Shpuld Shpludson 11113dd7c4 Merge branch 'feature/improve-status-header-and-spacing' into 'develop'
Re-do status header a bit, add more consistent spacing to status

Closes #264

See merge request pleroma/pleroma-fe!617
2019-03-02 16:35:38 +00:00
Shpuld Shpludson c4f8426349 Re-do status header a bit, add more consistent spacing to status 2019-03-02 16:35:38 +00:00
Shpuld Shpludson 6f903016a4 Merge branch 'fix/fetching-error-by-tag' into 'develop'
#402 Fix fetching error by tag

See merge request pleroma/pleroma-fe!622
2019-03-02 15:48:54 +00:00
shpuld 1d3b1ac934 start working on one tap notifications 2019-03-02 16:57:32 +02:00
shpuld 068da3cf9f Fix JS error when no statuses returned 2019-03-02 14:57:41 +02:00
jasper 81e89fed3d Fetch activites by last id 2019-03-01 12:53:24 -08:00
jasper c26f32ed92 Fix fetching error by tag 2019-03-01 10:20:25 -08:00
Shpuld Shpludson 53e104dc32 Merge branch 'issue-388-request-count-broken' into 'develop'
#388: get follow request on a real-time basis

Closes #388

See merge request pleroma/pleroma-fe!619
2019-03-01 18:03:30 +00:00
dave f3f9fbe302 #392: clean up notification stopping section 2019-03-01 11:59:50 -05:00
dave bbab1b1dc6 #346: Hyperlink is not included 2019-02-28 21:03:35 -05:00
dave bbe1821be7 #392: update object.entries 2019-02-28 14:44:43 -05:00
dave f5adb62e2e #392: update defaultState into a function 2019-02-28 14:27:47 -05:00
dave ba2e05bc63 #392: stale data served to new user account 2019-02-28 14:03:44 -05:00
Shpuld Shpludson bbe4f3e3af Merge branch 'issue-410-greyout-checkbox' into 'develop'
#410: disable checkbox when parent is disabled

Closes #410

See merge request pleroma/pleroma-fe!624
2019-02-28 18:02:15 +00:00
Shpuld Shpludson 88c7c8b114 Merge branch '398-rewrite-follow-list' into 'develop'
Split UserCard into FollowCard/FollowRequestCard and Rewrite FollowList using HOCs

Closes #398

See merge request pleroma/pleroma-fe!616
2019-02-28 17:53:40 +00:00
dave cccf33d6dd #388: update naming properly 2019-02-28 12:53:37 -05:00
taehoon 36460fd384 Fix layout overflow issue 2019-02-28 12:48:14 -05:00
taehoon a8d11b22e7 Add a class to screen name 2019-02-28 12:41:20 -05:00
taehoon 24e1adf6df Add back accidently removed logic 2019-02-28 12:41:20 -05:00
taehoon 0e86681aba Merge all slots of BasicUserCard into one 2019-02-28 12:41:20 -05:00
taehoon 6e41b4b546 Revert "Minor mobile layout improvement for BasicUserCard"
This reverts commit 1cd964bffff3ae4d324d0ab99e5c218eae7cd0ca.
2019-02-28 12:41:20 -05:00
taehoon d5f8e2b1ee Minor mobile layout improvement for BasicUserCard 2019-02-28 12:41:20 -05:00
taehoon 651c97153b Use native filter function 2019-02-28 12:41:20 -05:00
taehoon a6f2af4ad9 Shorten a classname 2019-02-28 12:41:20 -05:00
taehoon c5519fa587 Improve mobile layout of user card 2019-02-28 12:41:20 -05:00
taehoon 1fecac9ba6 Update naming 2019-02-28 12:41:20 -05:00
taehoon 8dd42cfc65 Add back some css 2019-02-28 12:41:20 -05:00
taehoon 30f5bf1463 Remove legacy class names in BasicUserCard 2019-02-28 12:41:20 -05:00
taehoon 0d283c3f17 Remove UserCard 2019-02-28 12:41:20 -05:00
taehoon 96e7e8235d Migrate UserCard to FollowCard and FollowRequestCard 2019-02-28 12:41:20 -05:00
taehoon 390b2bcfee Add FollowRequestCard component 2019-02-28 12:41:20 -05:00
taehoon 4b0a11acef Improve action button size and position in BasicUserCard 2019-02-28 12:41:20 -05:00
taehoon 8923492e68 Remove needless div wrapper 2019-02-28 12:41:20 -05:00
taehoon 9ca805a991 Add new FollowCard component 2019-02-28 12:41:20 -05:00
taehoon 1337e42b2d Add third slot area to BasicUserCard 2019-02-28 12:41:20 -05:00
taehoon 784523b8ec Use big avatar in BasicUserCard 2019-02-28 12:41:20 -05:00
taehoon 3ab42efbc3 Remove unused component local registration 2019-02-28 12:41:20 -05:00
taehoon 3f9fd07f93 Remove non-existing prop binding 2019-02-28 12:41:20 -05:00
taehoon bb1fac4bc2 Remove needless component local registration 2019-02-28 12:41:20 -05:00
taehoon 080786c945 Rewrite FollowList using hocs 2019-02-28 12:41:20 -05:00
taehoon cb383df517 Fix bug to get wrapped component prop name list 2019-02-28 12:40:22 -05:00
taehoon 5c43374588 Clean up addFollowers action 2019-02-28 12:40:22 -05:00
taehoon 3a689ef8ee Allow HOCs to accept additional props 2019-02-28 12:40:22 -05:00
dave 1c57a1c9b4 #410: disable checkbox when parent is disabled 2019-02-28 12:28:45 -05:00
Shpuld Shpludson dc01f90dde Merge branch '386-display-invalid-user-profile' into 'develop'
Show error message when visit profile page of invalid user

Closes #386

See merge request pleroma/pleroma-fe!606
2019-02-28 17:19:14 +00:00
Shpuld Shpludson 24f3770fb5 Merge branch 'keyboard-binding' into 'develop'
Keyboard binding

Closes #369

See merge request pleroma/pleroma-fe!593
2019-02-28 17:11:31 +00:00
Shpuld Shpludson efc4fa1099 Merge branch 'feature/oauth-tokens-in-settings' into 'develop'
Add OAuth Tokens management to settings

See merge request pleroma/pleroma-fe!572
2019-02-28 17:03:11 +00:00
Edijs 882e024331 Revert code 2019-02-28 11:16:16 +08:00
jasper 4d026baf17 Fix fetching error by tag 2019-02-27 18:14:42 -08:00
jasper 9aec49bacb Fetch activites by last id 2019-02-27 17:45:08 -08:00
Maxim Filippov 267952b4e7 "Are you sure?" -> i18n 2019-02-28 04:05:54 +03:00
Maxim Filippov c71f411ad6 Show only "app_name" and "valid_until" (OAuth tokens table) 2019-02-28 04:05:54 +03:00
Maxim Filippov afbe524a2e use translations 2019-02-28 04:04:26 +03:00
Maxim Filippov b9082fb13f Remove outdated test 2019-02-28 04:04:26 +03:00
Maxim Filippov c10a15386a Code style 2019-02-28 04:04:26 +03:00
Maxim Filippov 2c7406d9a8 Add OAuth Tokens management to settings 2019-02-28 04:04:26 +03:00
dave 9f1214555e #388: remove empty line 2019-02-27 14:40:21 -05:00
dave 7c6446a9de #388: get follow request on a real-time basis 2019-02-27 14:38:10 -05:00
Shpuld Shpludson 058238c3c6 Merge branch 'feat/max-attachments-configurable' into 'develop'
Fix #399 Make max attachments configurable

Closes #399

See merge request pleroma/pleroma-fe!618
2019-02-27 14:38:58 +00:00
Shpuld Shpludson 95fb768b5a Fix #399 Make max attachments configurable 2019-02-27 14:38:58 +00:00
jasper 7698a6fb0d Remove posts by blocking or unfollowing 2019-02-26 23:21:04 -08:00
taehoon b78227456e Better error handling 2019-02-26 12:26:04 -05:00
taehoon e687b58091 Show error message when visit profile page of invalid user 2019-02-26 11:08:13 -05:00
jasper 4e79300232 Remove posts by blocking or unfollowing 2019-02-25 14:35:47 -08:00
HJ d5348c13ff Merge branch 'issue-380-noification-unread' into 'develop'
#380: fix false alarm for unread notifications

Closes #380

See merge request pleroma/pleroma-fe!614
2019-02-25 20:08:45 +00:00
HJ fef0981bc4 Merge branch 'issue-396-registration-bio-field' into 'develop'
#396: update registration form

Closes #396

See merge request pleroma/pleroma-fe!612
2019-02-25 19:58:17 +00:00
dave 7dbbd8e270 #380: simply and remove redundancy 2019-02-25 14:57:56 -05:00
dave 4e8b696797 #380: fix false alarm for unread notifications 2019-02-25 12:12:49 -05:00
Shpuld Shpludson dbf46942d0 Merge branch 'fix/active-user-search-text-field' into 'develop'
#387 Activate user search text field after click button.

See merge request pleroma/pleroma-fe!608
2019-02-25 16:09:18 +00:00
Shpuld Shpludson baa09002b5 Merge branch 'issue-390-load-other-user-media-data' into 'develop'
#390: fixed the problem loading other user's media data

Closes #390

See merge request pleroma/pleroma-fe!613
2019-02-25 16:08:53 +00:00
dave 662e6bda14 #390: fixed the problem loading other user's media data 2019-02-25 10:21:17 -05:00
jasper bbd3e6b10f Update search input name 2019-02-25 06:08:52 -08:00
dave 20c68d33eb #396: update en.json 2019-02-24 15:44:06 -05:00
dave 8275f2aa9a #396: update registration form 2019-02-24 14:30:29 -05:00
Shpuld Shpludson 1dd7120e16 Merge branch 'issue-389-search-loading-icon' into 'develop'
#389: add loading icon in search panel

Closes #389

See merge request pleroma/pleroma-fe!610
2019-02-24 16:24:53 +00:00
Edijs 66a105a519 Revert 2019-02-22 13:53:43 -07:00
dave 9bedf96b98 #389: add loading icon in search panel 2019-02-22 13:37:02 -05:00
Shpuld Shpludson 99051f4a55 Merge branch 'fix/fetch-error-when-login' into 'develop'
#370 fix/fetch-error-when-login

See merge request pleroma/pleroma-fe!596
2019-02-22 15:17:17 +00:00
Shpuld Shpludson e34e1ccdae Merge branch '227-manage-blocks-mutes' into 'develop'
Add Blocks / Mutes management tabs under user settings page

See merge request pleroma/pleroma-fe!578
2019-02-22 14:54:12 +00:00
taehoon 22851a3a96 Remove needless code 2019-02-21 20:15:51 -05:00
jasper 34d723215b Activate user search text field 2019-02-21 11:20:46 -08:00
HJ 3768a4623f Merge branch 'fix-mutes' into 'develop'
bad defaults

Closes #384

See merge request pleroma/pleroma-fe!605
2019-02-21 17:56:41 +00:00
Henry Jameson 4136d9cdd1 bad defaults 2019-02-21 19:52:58 +02:00
Shpuld Shpludson c3fa2c90e2 Merge branch 'issue-376-no-statuses' into 'develop'
#376: update status timeline when it's empty

Closes #376

See merge request pleroma/pleroma-fe!601
2019-02-21 17:24:39 +00:00
Shpuld Shpludson 254b0afab7 Merge branch 'issue-383-content-type' into 'develop'
#383: content type error

Closes #383

See merge request pleroma/pleroma-fe!603
2019-02-21 17:06:10 +00:00
dave 09822cc15b #383: content type error 2019-02-21 11:16:11 -05:00
taehoon eb22e7f462 Use Object.entries instead of Object.keys 2019-02-20 21:50:10 -05:00
taehoon 37eec09b9b Comment out the mutes tab 2019-02-20 13:30:31 -05:00
taehoon 5bd36c6476 Remove needless css 2019-02-20 13:30:31 -05:00
taehoon 46e1f30347 Fix indent 2019-02-20 13:30:31 -05:00
taehoon 85d43d17f5 Add missing translation strings 2019-02-20 13:30:31 -05:00
taehoon 32c112bc96 Remove pagination logic in fetchBlocks api 2019-02-20 13:30:31 -05:00
taehoon 395d212904 Add new strings to i18n 2019-02-20 13:30:31 -05:00
taehoon a5162bd636 Add note for empty state to the lists using slot 2019-02-20 13:30:31 -05:00
taehoon b4a5b5203f Minor css improvements of hocs 2019-02-20 13:30:31 -05:00
taehoon 8680046c4e Pass down slots into wrapped components 2019-02-20 13:30:31 -05:00
taehoon 6d4d705c51 Rename some options and add comments to HOCs 2019-02-20 13:30:31 -05:00
taehoon 339373b495 Improve chaining hocs using vue-compose 2019-02-20 13:30:30 -05:00
taehoon f81b82b471 Use hoc definitions to be factor of factory 2019-02-20 13:30:30 -05:00
taehoon 8f608e060c Just save blocks/mutes instead of adding 2019-02-20 13:30:30 -05:00
taehoon 1fd9a1c7c0 Set blockIds and muteIds to the currentUser state only 2019-02-20 13:30:30 -05:00
taehoon e91a94ff9c Add mutes tab 2019-02-20 13:30:30 -05:00
taehoon 09315b2780 Add a prop to force-refresh data to withSubscription hoc 2019-02-20 13:30:30 -05:00
taehoon 8c8a6edc78 Remove pagination support from block-list 2019-02-20 13:30:30 -05:00
taehoon 159e84532e Add withSubscription hoc 2019-02-20 13:30:30 -05:00
taehoon 8270274865 Update hocs to pass parent-scope bindings to the wrapped component 2019-02-20 13:30:30 -05:00
taehoon 52913d8f87 Complete functionality of BlockCard 2019-02-20 13:30:30 -05:00
taehoon 0220d3d304 Finally, added BlockCard 2019-02-20 13:30:30 -05:00
taehoon 5d6e1864a5 Update BasicUserCard template and add a slot for customization 2019-02-20 13:30:30 -05:00
taehoon 94e6de11b7 Add withList hoc and remove UserList component 2019-02-20 13:30:30 -05:00
taehoon a817cc7cb4 Wire up ui to real blocks api data 2019-02-20 13:30:30 -05:00
taehoon a56d2dfeb1 Add blocks tab with test data to user settings page 2019-02-20 13:30:30 -05:00
taehoon 4a737cbe45 Add reusable BasicUserCard and UserList components 2019-02-20 13:30:30 -05:00
taehoon 12df967cb6 Add withLoadMore hoc 2019-02-20 13:30:30 -05:00
dave e20a7be3aa #376: update status timeline when it's empty 2019-02-20 10:13:28 -05:00
Shpuld Shpludson cfdd885e04 Merge branch 'issue-371-user-setting-notification' into 'develop'
#371: show notification when user setting's saved

Closes #371

See merge request pleroma/pleroma-fe!598
2019-02-20 14:42:27 +00:00
Shpuld Shpludson a49f6dbf65 Merge branch 'fix/follow-list' into 'develop'
Watch user change in follow-list

Closes #360

See merge request pleroma/pleroma-fe!584
2019-02-20 14:32:45 +00:00
Shpuld Shpludson 22a0858ef4 Merge branch 'issue-377-local-user-no-link' into 'develop'
#377: no exteral profile link for local users

Closes #377

See merge request pleroma/pleroma-fe!599
2019-02-19 19:35:44 +00:00
dave 0caf59a911 #377: no exteral profile link for local users 2019-02-19 13:49:04 -05:00
Shpuld Shpludson 40159324b4 Merge branch 'issue-364-register-freeze' into 'develop'
#364: update ap_id error with username

Closes #364

See merge request pleroma/pleroma-fe!597
2019-02-19 18:00:39 +00:00
jasper 1e43a47c3c Update: Fix fetch error when login 2019-02-19 09:42:53 -08:00
dave 63cfe051c7 #371: show notification when user setting's saved 2019-02-19 12:38:49 -05:00
Shpuld Shpludson 53484ae4bf Merge branch 'issue-344-css-refactor' into 'develop'
#344 - replace float: with flexbox, clean up

See merge request pleroma/pleroma-fe!566
2019-02-19 16:49:44 +00:00
Shpuld Shpludson 0e1295edea Merge branch 'follow-requests-for-locked-accounts' into 'develop'
Follow Request notification count for restricted accounts

See merge request pleroma/pleroma-fe!561
2019-02-19 16:38:05 +00:00
shpuld 32df77c16a Merge branch 'tae-hoon/pleroma-fe-323-improve-image-lightbox' into develop 2019-02-19 18:34:09 +02:00
shpuld 4e0f934301 Clean up CSS a bit 2019-02-19 18:33:40 +02:00
Shpuld Shpludson 7b9a6f8d43 Merge branch '256-avatar-crop-popup' into 'develop'
Add avatar cropper

Closes #256

See merge request pleroma/pleroma-fe!547
2019-02-19 15:37:01 +00:00
Shpuld Shpludson 8f96de2ba5 Merge branch 'patch-pleroma-615' into 'develop'
#336: Deleted static/bg2.jpg, static/bgalt.jpg files

See merge request pleroma/pleroma-fe!555
2019-02-19 15:27:54 +00:00
Shpuld Shpludson ed3c318be0 Merge branch 'edijs/pleroma-fe-fix/followers-ui' into 'develop'
Fix followers/follows UI, fix #343 fix #340

Closes #340 and #343

See merge request pleroma/pleroma-fe!590
2019-02-19 14:47:32 +00:00
dave 5251ccd708 #364: update ap_id error with username 2019-02-19 09:22:42 -05:00
Edijs d032ce2758 Validate if there are any new status to show 2019-02-18 18:32:20 -07:00
jasper b4709515f2 Fix error when login 2019-02-18 17:15:16 -08:00
jasper d4a2376e12 fix/fetch-error-when-login 2019-02-18 12:32:08 -08:00
jasper 24d7f9917b Remove posts by blocking or following 2019-02-18 11:39:35 -08:00
Edijs 0d2922afb3 Remove event listener when component destroy 2019-02-17 14:37:24 -07:00
Edijs 642b0be0b2 Bind a keyboard to show new status 2019-02-17 14:31:13 -07:00
HJ 962a33f887 Merge branch 'instance-specific-panel' into 'develop'
Hide ISP option if instance has panel disabled

Closes #368

See merge request pleroma/pleroma-fe!592
2019-02-17 21:27:58 +00:00
Edijs c30dabbdd4 Rename: instanceSpecificPanelPresent 2019-02-17 14:24:14 -07:00
Edijs e871e3f2ac Hide isp option if instance has panel disabled 2019-02-17 13:24:24 -07:00
shpuld e801d78e9d Take over branch and fix some issues 2019-02-17 18:54:22 +02:00
lambda a842cadd15 Parameter name changed. 2019-02-16 16:09:14 +00:00
Shpuld Shpludson 2fb768cfd8 Merge branch 'update-japanese-translation' into 'develop'
update japanese translation

See merge request pleroma/pleroma-fe!586
2019-02-16 15:45:04 +00:00
taehoon 3094c50ff9 Fix lint errors 2019-02-15 13:34:33 -05:00
taehoon 2de756aa0c Better error handling 2019-02-15 13:34:33 -05:00
taehoon 2132d58075 Remove cropped image size restriction 2019-02-15 13:34:33 -05:00
taehoon b6d197ce1d Remove modal component 2019-02-15 13:34:33 -05:00
taehoon b24db12e1c Make embedded image cropper 2019-02-15 13:34:33 -05:00
taehoon 546ba9eba9 Revert eslintrc changes 2019-02-15 13:34:33 -05:00
taehoon b458b2ae5f Check if variable exists before using 2019-02-15 13:34:33 -05:00
taehoon ddfdaf3284 Remove event listeners when destory ImageCropper 2019-02-15 13:34:33 -05:00
taehoon 228e6681e3 Localization of ImageCropper component 2019-02-15 13:34:33 -05:00
taehoon 205e38ffa9 Remove event listener when modal is destroyed 2019-02-15 13:34:33 -05:00
taehoon 09949fc7ee Crop avatar image using minWidth/minHeight 2019-02-15 13:34:33 -05:00
taehoon a001ffecf0 Add back the existing translation string 2019-02-15 13:34:33 -05:00
taehoon 13725f040b Add avatar crop popup 2019-02-15 13:34:33 -05:00
jasper 6c8ccf2733 Remove posts immediately by blocking 2019-02-15 07:52:34 -08:00
HJ 4f95371081 Merge branch 'issue-361-preview-background' into 'develop'
#361 - fix theme preview background

Closes #361

See merge request pleroma/pleroma-fe!588
2019-02-15 12:29:08 +00:00
dave 8f0e6b5045 #361 - fix theme preview background 2019-02-15 07:20:52 -05:00
HJ 7bc8fd1a5b Merge branch 'fix/maximum-call-stack-size-exceeded' into 'develop'
#362 Fix console error - maximum call stack size exceeded

Closes #362

See merge request pleroma/pleroma-fe!587
2019-02-15 10:09:33 +00:00
eugenijm d831b81912 Added follow requests counter to nav bar to make it visible behorehand 2019-02-15 12:49:00 +03:00
jasper daa10f3969 Fix console error - maximum call stack size exceeded 2019-02-15 00:01:13 -08:00
Hakaba Hitoyo 0f06cd6af5 update japanese translation 2019-02-15 13:16:34 +09:00
HJ 10990e1715 Merge branch 'fix-notifs' into 'develop'
unfuck notifications

Closes #356

See merge request pleroma/pleroma-fe!583
2019-02-14 20:43:48 +00:00
Edijs 3398817c25 watch only user 2019-02-14 13:25:22 -07:00
Edijs 0ca145ac95 Watch user change in follow-list 2019-02-14 13:19:00 -07:00
Henry Jameson f41341b79b fix notifications 2019-02-14 21:43:32 +02:00
HJ 8625a612cd Merge branch 'revert-2bc1cc9f' into 'develop'
Revert "Merge branch 'fix/no-autocomplete-in-non-post-forms' into 'develop'"

See merge request pleroma/pleroma-fe!582
2019-02-14 19:19:58 +00:00
HJ 5d73a1dd06 Revert "Merge branch 'fix/no-autocomplete-in-non-post-forms' into 'develop'"
This reverts merge request !551
2019-02-14 19:15:59 +00:00
HJ 98c5e4a9d0 Merge branch 'revert-d6f9f34a' into 'develop'
Revert "Merge branch 'fix/no-autocomplete-in-non-post-forms' into 'develop'"

See merge request pleroma/pleroma-fe!581
2019-02-14 19:15:03 +00:00
HJ 8d7ac0e14c Revert "Merge branch 'fix/no-autocomplete-in-non-post-forms' into 'develop'"
This reverts merge request !573
2019-02-14 19:11:17 +00:00
HJ dfecbe0ab7 Merge branch 'revert-295becd6' into 'develop'
Revert "Merge branch 'hotfix/issues-in-autocomplete' into 'develop'"

See merge request pleroma/pleroma-fe!580
2019-02-14 19:09:32 +00:00
HJ ee4c6f362b Revert "Merge branch 'hotfix/issues-in-autocomplete' into 'develop'"
This reverts merge request !574
2019-02-14 19:05:59 +00:00
Edijs 28660d6986 Issue #335 - place hide button on right hand 2019-02-14 10:21:10 -07:00
Edijs 50f0d21686 Use static height if gallery has single image 2019-02-14 09:52:23 -07:00
Shpuld Shpludson 295becd6c8 Merge branch 'hotfix/issues-in-autocomplete' into 'develop'
#355 hotfix/issues in autocomplete

Closes #355

See merge request pleroma/pleroma-fe!574
2019-02-14 14:50:58 +00:00
Shpuld Shpludson 40b51b659e Merge branch 'fix-convos' into 'develop'
fix convos

Closes #357

See merge request pleroma/pleroma-fe!575
2019-02-14 14:20:03 +00:00
Henry Jameson 688906a61e fix convos 2019-02-14 00:11:11 +02:00
Xiaofeng An 19dd36945a resolve focus issue in the auto-complete for name field 2019-02-13 15:39:37 -05:00
Xiaofeng An 98c27fd812 resolve issue related to event handler 2019-02-13 07:38:53 -05:00
Xiaofeng An 2100cb247d resolve issue in prop binding 2019-02-13 07:38:13 -05:00
Shpuld Shpludson d6f9f34ad8 Merge branch 'fix/no-autocomplete-in-non-post-forms' into 'develop'
hotfix/this fixes #350 - v-model binding issue

Closes #350

See merge request pleroma/pleroma-fe!573
2019-02-13 04:48:05 +00:00
Xiaofeng An 64fab9d7bc this fixes #350 - v-model binding issue 2019-02-12 13:55:00 -05:00
Shpuld Shpludson 26954cb3dd Merge branch 'issue-341-repeat-auto-scroll' into 'develop'
#341 - automatic scroll with repeats/reports

See merge request pleroma/pleroma-fe!568
2019-02-12 16:06:23 +00:00
Edijs 5d0e51cae3 Fix styling 2019-02-12 09:00:09 -07:00
dave 25bb80a982 #341 - fix naming 2019-02-12 10:35:54 -05:00
Shpuld Shpludson 6f4fbcffc0 Merge branch 'patch-2' into 'develop'
Update spanish translate - es.json

See merge request pleroma/pleroma-fe!564
2019-02-12 15:25:52 +00:00
Shpuld Shpludson 6d8862dc9a Merge branch '300-fixed-background-issue' into 'develop'
Fix fixed background issue

Closes #300

See merge request pleroma/pleroma-fe!518
2019-02-12 15:25:18 +00:00
Shpuld Shpludson 25cfb04873 Merge branch 'fix/profile-banner-preview-width' into 'develop'
#333 Fix max-width of profile banner in setting

See merge request pleroma/pleroma-fe!560
2019-02-12 15:05:26 +00:00
Shpuld Shpludson 2bc1cc9ff9 Merge branch 'fix/no-autocomplete-in-non-post-forms' into 'develop'
#255 - implement autocomplete in non post forms

See merge request pleroma/pleroma-fe!551
2019-02-12 14:55:18 +00:00
Shpuld Shpludson 8cce505cf5 Merge branch '345-long-username' into 'develop'
345 - fix long username issue in repeat status

Closes #345

See merge request pleroma/pleroma-fe!567
2019-02-12 14:45:54 +00:00
dave 493d542d92 #341 - automatic scroll with repeats/reports 2019-02-12 05:10:27 -05:00
jared 4d930c7c26 345 - fix long username issue in repeat status 2019-02-11 23:03:51 -05:00
dave f2ce2e9176 #344 - replace float: with flexbox, clean up 2019-02-11 22:35:24 -05:00
tarteka 2226f80076 Update spanish translate - es.json 2019-02-11 18:29:56 +00:00
Edijs dd1b256005 Fix typo 2019-02-11 11:08:25 -07:00
Edijs 9f3f1ee7cb Fix UI of followers list 2019-02-11 11:03:01 -07:00
Shpuld Shpludson 8efe30c2dc Merge branch 'hotfix/open-link' into 'develop'
Fix clicking link - open new tab unless tag or mention

See merge request pleroma/pleroma-fe!562
2019-02-11 15:01:15 +00:00
Edijs f3d2e41a9b Fix return 2019-02-11 07:45:22 -07:00
Edijs 9959c311a9 Fix clicking link - open new tab unless tag or mention 2019-02-11 07:38:12 -07:00
Shpuld Shpludson b6bac4d06d Merge branch 'fix/profile-not-loading-without-persisted-state' into 'develop'
Fix #324 Profiles sometimes not loading when there's no persisted state

Closes #324

See merge request pleroma/pleroma-fe!553
2019-02-11 13:34:03 +00:00
Shpuld Shpludson 0e6134b32e Merge branch 'issue-332-update-follow-tabs' into 'develop'
#332 - add follow/not follow button to follow list

See merge request pleroma/pleroma-fe!558
2019-02-11 13:29:58 +00:00
taehoon a20974faac Use correct syntax for pseudoelement 2019-02-11 06:56:46 -05:00
jasper db465ff839 Fix max-width of profile banner in setting 2019-02-11 00:06:37 -08:00
Shpuld Shpludson e1e9e50b98 Merge branch 'fix/hashtag-opening' into 'develop'
Open hashtag in same tab

See merge request pleroma/pleroma-fe!540
2019-02-11 04:19:17 +00:00
Edijs be77707381 Fix unit test 2019-02-10 19:32:01 -07:00
Edijs 7addd408a9 Typo 2019-02-10 12:06:13 -07:00
Edijs fc26f1852e Merge branch 'develop' into fix/hashtag-opening 2019-02-10 11:59:19 -07:00
taehoon 971e75aa64 Add translation strings 2019-02-10 13:26:08 -05:00
taehoon 750c308909 Support lightbox gallery navigation via arrow buttons and keyboard 2019-02-10 13:23:01 -05:00
dave 4b18989fef #332 - add follow/not follow button to follow list 2019-02-09 23:05:23 -05:00
Shpuld Shpludson 4bea3c525f Merge branch 'fix/subject-copying-composition-bug' into 'develop'
#326 Subject copying composition bug

See merge request pleroma/pleroma-fe!550
2019-02-09 20:47:29 +00:00
Shpuld Shpludson cf10fd623b Merge branch 'fix-user-profile-background-setting-preview' into 'develop'
Add quick css fix for user profile bg img preview

See merge request pleroma/pleroma-fe!554
2019-02-09 20:42:51 +00:00
jo 7743e3b277 Add quick css fix for user profile bg img preview 2019-02-09 20:42:51 +00:00
Lidar ce81a5f72e Deleted static/bg2.jpg, static/bgalt.jpg files 2019-02-09 16:26:54 +00:00
jasper 0a43546564 Switch into Lodash 2019-02-09 04:18:52 -08:00
jasper f75ec48a80 Switch into Lodash 2019-02-09 04:13:52 -08:00
shpuld 3fb531976a Change the async stuff to not render app before theme is loaded 2019-02-09 11:26:35 +02:00
Shpuld Shpludson d2d06983c9 Merge branch 'patch-2' into 'develop'
Update spanish translate

See merge request pleroma/pleroma-fe!549
2019-02-09 07:06:40 +00:00
Shpuld Shpludson 5296d41372 Merge branch 'fix/js-error-in-tag-page' into 'develop'
Fixed JS error in tag page

See merge request pleroma/pleroma-fe!543
2019-02-09 06:56:46 +00:00
Shpuld Shpludson 531f150dd3 Merge branch 'fix/add-option-to-hide-filtered-statues' into 'develop'
#254 Add option to hide filtered statuses

See merge request pleroma/pleroma-fe!539
2019-02-09 06:47:29 +00:00
feld 9768558e7c Merge branch 'fix/show-features-panel-not-working' into 'develop'
#322 Fix showFeaturesPanel option as instance

See merge request pleroma/pleroma-fe!552
2019-02-08 21:27:58 +00:00
jasper 5b52e020e3 fixing conflicts 2019-02-08 13:20:47 -08:00
jasper ced29a6482 fixing conflicts 2019-02-08 13:18:50 -08:00
jasper 92874b6902 Fxing conflicts 2019-02-08 13:13:11 -08:00
jasper 70c05a0c08 Fix showFeaturesPanel option as instance 2019-02-08 12:17:14 -08:00
Xiaofeng An 9f83aee1ed fix auto-complete field not taking the whole parent width in flex 2019-02-08 11:54:12 -05:00
Xiaofeng An 59cde429b9 fix naming 2019-02-08 11:40:54 -05:00
Xiaofeng An 63680227c1 select either textarea or input 2019-02-08 11:26:17 -05:00
jasper e90e7ce2db Subject copying composition bug 2019-02-08 08:25:53 -08:00
Xiaofeng An e8dc019afd remove rows attribute from input 2019-02-08 11:13:35 -05:00
Xiaofeng An dd8531f9c9 move styles for AutoCompleteInput 2019-02-08 11:13:35 -05:00
Xiaofeng An 17c70fc0ef add id & placeholder props to AutoCompleteInput component 2019-02-08 11:13:35 -05:00
Xiaofeng An 128dcc637e make name field auto-complete 2019-02-08 11:13:35 -05:00
Xiaofeng An 2d91c9d949 make bio field auto-complete 2019-02-08 11:13:35 -05:00
Xiaofeng An fb0cf64549 #255 - make AutoCompleteInput component 2019-02-08 11:13:35 -05:00
Shpuld Shpludson da0a5535eb Merge branch 'issue-291-disable-empty-tabs' into 'develop'
#291 - disable empty tabs in user profile panel

See merge request pleroma/pleroma-fe!548
2019-02-08 15:48:07 +00:00
dave 910b63624b #291 - fixed typo 2019-02-08 10:40:03 -05:00
dave d112d5b333 #291 - remove whitespace 2019-02-08 10:02:00 -05:00
dave 34169e692f #291 - enable media/favorite tabs with prefetched data 2019-02-08 09:56:45 -05:00
tarteka b129049fed Update spanish translate 2019-02-08 13:42:02 +00:00
jasper 7818d6786b Add option to hide filtered statuses 2019-02-08 05:17:20 -08:00
jasper 10c7365451 Add option to hide filtered statuses 2019-02-08 04:31:44 -08:00
dave b57b4c6e45 #291 - disable empty tabs in user profile panel 2019-02-08 05:31:06 -05:00
Edijs 0dc7c45f32 Code refactoring 2019-02-07 16:23:18 -07:00
HJ 62b3b9b8d4 Merge branch 'add-admin-and-moderator-fields-to-user-card-view' into 'develop'
Add admin and moderator indicators to the user profile

See merge request pleroma/pleroma-fe!519
2019-02-07 22:45:08 +00:00
eugenijm 19dbdd24b4 Update user settings text: staff badges are only visible in user profile
Use capitalized text in badges
2019-02-08 01:33:24 +03:00
Edijs d39e2643f5 Fix lint warning 2019-02-07 14:56:00 -07:00
Edijs e44d8ad71e Extract tag name from href and open in same tab 2019-02-07 14:54:49 -07:00
Edijs c0b833cb85 Added tag extractor method and spec 2019-02-07 14:46:10 -07:00
Shpuld Shpludson 9b49fa3c0c Merge branch '287-following-followers-tabs' into 'develop'
Hide Following/Followers tabs if user has them disabled

Closes #287

See merge request pleroma/pleroma-fe!515
2019-02-07 15:59:37 +00:00
Shpuld Shpludson 85e281d406 Merge branch 'feature/add-an-option-for-a-default-formatting' into 'develop'
#301 - add an option for a default formatting

See merge request pleroma/pleroma-fe!541
2019-02-07 15:55:54 +00:00
taehoon 55da7dbfde Fix naming 2019-02-07 10:53:36 -05:00
taehoon fae93217b8 Show back followees/followers counts 2019-02-07 10:48:47 -05:00
taehoon ea1d7f46b5 Always show my own followees/followers 2019-02-07 10:48:47 -05:00
taehoon 55fc31ea4d Hide followers and followees tabs when they are disabled 2019-02-07 10:48:47 -05:00
Shpuld Shpludson bfe2d8beaa Merge branch 'issue-137-heart-emoji' into 'develop'
#137 - add red heart emoji

See merge request pleroma/pleroma-fe!546
2019-02-07 15:45:00 +00:00
Shpuld Shpludson 05ef0432d3 Merge branch 'issue-315-csv-export' into 'develop'
#315 - export all follows as CSV

See merge request pleroma/pleroma-fe!538
2019-02-07 15:42:18 +00:00
dave 012ce7bad2 #137 - clean up emoji list 2019-02-07 10:29:23 -05:00
dave bd24c615d1 #315 - revert changes 2019-02-07 09:59:12 -05:00
dave 3128417176 #315 - separate export and fetch follows logic 2019-02-07 09:57:16 -05:00
dave 997c99e45d #137 - add red heart emoji 2019-02-07 06:26:51 -05:00
Edijs a215f6856d Always open tag in same instance 2019-02-06 21:26:32 -07:00
Shpuld Shpludson 9516d5dd73 Merge branch 'english-login' into 'develop'
Grammar

See merge request pleroma/pleroma-fe!542
2019-02-07 04:13:56 +00:00
Edijs 19870c0b6d Fix issue while fetching timelines for tag page 2019-02-06 19:19:43 -07:00
Edijs fafe258f2b Typo 2019-02-06 19:19:14 -07:00
Mark Felder b3823b79b4 Grammar 2019-02-06 22:00:31 +00:00
shpuld 4dbc6a3c56 Fix repeater html not showing properly 2019-02-06 22:17:06 +02:00
Xiaofeng An e107ed8ddc Merge branch 'develop' into feature/add-an-option-for-a-default-formatting 2019-02-06 14:28:50 -05:00
Xiaofeng An 460976c6e5 #301 - add an option for default formatting 2019-02-06 14:26:46 -05:00
jasper fbdb7d3d95 Add german translation for option label 2019-02-06 10:50:21 -08:00
Edijs a12397cf38 Hashtag opens in same tab 2019-02-06 11:34:21 -07:00
dave a3a9949a21 #315 - clean up the request 2019-02-06 13:18:54 -05:00
jasper a57f8bdd68 Add option to hide filtered statuses 2019-02-06 10:18:13 -08:00
Shpuld Shpludson 6cca15bade Merge branch 'fix/create-a-login-hint-on-mobile' into 'develop'
create a login hint on mobile

Closes #308

See merge request pleroma/pleroma-fe!530
2019-02-06 18:13:56 +00:00
Xiaofeng An a40d1eb3a0 remove unnecessary div 2019-02-06 11:53:51 -05:00
dave 2f12ac7ea4 #315 - export all follows as CSV 2019-02-06 11:17:23 -05:00
eugenijm fd4cd2e10a Make role badge visible only on user profile page 2019-02-06 18:07:37 +03:00
eugenijm 676e6da3a5 Add theming support for admin/moderator badges 2019-02-06 18:07:37 +03:00
eugenijm d00b74b607 Refactor visibleRole for better readability
Improve translation
2019-02-06 18:07:37 +03:00
eugenijm 648f635429 Allow to configure visibility for admin and moderator badges 2019-02-06 18:07:10 +03:00
eugenijm c714eb2600 Add admin and moderator indicators to the user card 2019-02-06 18:04:21 +03:00
Shpuld Shpludson 6a867f6ae3 Merge branch 'feature/split-hide-network-fixed' into 'develop'
Split hide_network into hide_followers & hide_followings

See merge request pleroma/pleroma-fe!536
2019-02-06 14:38:50 +00:00
Maxim Filippov 0c5c889850 Rename "hide_following" to "hide_follows" 2019-02-06 14:21:13 +03:00
Xiaofeng An f512ee2c3c move login hint into the main content 2019-02-06 05:01:32 -05:00
Xiaofeng An e4c0bbddd9 Merge branch 'develop' into fix/create-a-login-hint-on-mobile 2019-02-06 04:37:00 -05:00
Shpuld Shpludson 2d333f99e8 Merge branch 'patch-1' into 'develop'
Update es.json

See merge request pleroma/pleroma-fe!535
2019-02-06 04:29:30 +00:00
Shpuld Shpludson 68e5360229 Merge branch 'fix/add-option-to-hide-features-panel' into 'develop'
Add option to hide features panel

See merge request pleroma/pleroma-fe!529
2019-02-06 04:21:06 +00:00
Maxim Filippov 18594569bd Split hide_network into hide_followers & hide_followings 2019-02-06 02:59:59 +03:00
HJ 3d337a239e Merge branch 'fix/avatar-link' into 'develop'
Fix avatar link in search result

See merge request pleroma/pleroma-fe!534
2019-02-05 22:46:45 +00:00
tarteka 37c7d850f1 Update es.json 2019-02-05 22:20:45 +00:00
Edijs 52f5ffa862 Fix avatar link in search result 2019-02-05 15:11:17 -07:00
Xiaofeng An d2436fb9e5 move hint inside Timeline component 2019-02-05 15:43:56 -05:00
Shpuld Shpludson 2db7774a3a Merge branch 'issue-316-empty-username' into 'develop'
#316 - fix empty username issue

See merge request pleroma/pleroma-fe!531
2019-02-05 19:58:45 +00:00
dave 0b24454561 #316 - fix empty username issue 2019-02-05 14:33:16 -05:00
Xiaofeng An bf642ebab7 fix #308 - hide login hint on desktop 2019-02-05 13:48:12 -05:00
Xiaofeng An c758d103bd fix #308 - show login hint above timeline when user is not logged in 2019-02-05 13:47:27 -05:00
Shpuld Shpludson 8e51c78471 Merge branch 'issue-138-html-escaping' into 'develop'
#138 - escape html entities in BIO text

See merge request pleroma/pleroma-fe!522
2019-02-05 15:24:31 +00:00
shpuld 5974dfebfb Fix mishandled @error in stillImage 2019-02-05 17:17:50 +02:00
dev92341 e3da156162 Add option to hide features panel (About page) 2019-02-05 06:12:14 -08:00
dev92341 1ee762cf6e Add option to hide features panel 2019-02-05 04:32:00 -08:00
dev92341 f2c6dd6581 Add option to hide features panel 2019-02-05 03:57:11 -08:00
dave 94fdc2d583 #138 - fix lint error 2019-02-04 15:06:38 -05:00
dave e1f9298ef2 #138 - unescape user bio 2019-02-04 15:03:01 -05:00
dave c1883f5282 #138 - escape html entities in BIO text 2019-02-04 14:25:21 -05:00
Shpuld Shpludson 448317338e Merge branch '309-add-logo-to-hamburger-menu' into 'develop'
Add logo and sitename to the side drawer area

Closes #309

See merge request pleroma/pleroma-fe!517
2019-02-04 19:00:38 +00:00
taehoon 13ee624341 Do not use BEM 2019-02-04 13:34:07 -05:00
taehoon 5675b9326c Improve readability using v-if and v-else 2019-02-04 13:30:33 -05:00
taehoon 4528a4cbfa Show logo/sitename in the side drawer only if logged out 2019-02-04 13:30:33 -05:00
taehoon 537631002b Add logo and sitename to the side drawer area 2019-02-04 13:30:32 -05:00
Shpuld Shpludson 8c8eb99d73 Merge branch 'feat/follows-following-pagination' into 'develop'
Follows + followers pagination #285

See merge request pleroma/pleroma-fe!510
2019-02-04 17:54:48 +00:00
shpuld 54e7e0e31b merge develop and fix conflicts AGAIN 2019-02-04 19:49:23 +02:00
Shpuld Shpludson 3cd1deb133 Merge branch 'issue-154-shorten-cw-subject' into 'develop'
Issue #154 shorten subject

Closes #154

See merge request pleroma/pleroma-fe!520
2019-02-04 17:29:58 +00:00
Shpuld Shpludson d5757d44e5 Merge branch 'issue-312-media-upload' into 'develop'
#312 - media uploader not working with same file in adjacent order

See merge request pleroma/pleroma-fe!521
2019-02-04 16:48:13 +00:00
dave 97fbc1d402 #312 - media uploader not working with same file in adjacent order 2019-02-04 10:45:26 -05:00
dave 9d72c7e1bd #154 - update long subject determine logic, meaningful variable names 2019-02-04 09:28:14 -05:00
dave 887f1def2e handle poster attachment with tall subjects 2019-02-04 03:16:55 -05:00
dave 06cf8628e5 shorten incredibly long content warning or subject 2019-02-03 23:47:26 -05:00
Shpuld Shpludson bb335ea71b Merge branch 'fix/user-links-not-replaced-with-router-links-in-repeats' into 'develop'
#307 - replace user links with router links in repeats

See merge request pleroma/pleroma-fe!516
2019-02-04 04:22:33 +00:00
Shpuld Shpludson d6ee6e8394 Merge branch '275-avatar-placeholder' into 'develop'
Support avatar placeholder

Closes #275

See merge request pleroma/pleroma-fe!511
2019-02-04 04:17:11 +00:00
taehoon 0483f1d636 Revert a change which can break the theme preview 2019-02-03 20:12:22 -05:00
taehoon ee694d62eb Fix fixed background issue 2019-02-03 15:32:24 -05:00
Xiaofeng An abf53838e2 #307 - replace user links with router links in repeats 2019-02-03 14:08:04 -05:00
taehoon e7f43d6bc3 Use an existing image served by backend instead 2019-02-03 13:30:54 -05:00
Shpuld Shpludson 7115584882 Merge branch 'fix/conversation-arrow-smushed-in-notifications-panel' into 'develop'
#306 - fix conversation arrow smushed in notifications panel

See merge request pleroma/pleroma-fe!513
2019-02-03 15:10:19 +00:00
Xiaofeng An 6d3a7809be #306 - fix conversation arrow smushed in notifications panel 2019-02-03 09:59:32 -05:00
Xiaofeng An 965a578561 Revert "#306 - fix conversation arrow smushed in notifications panel"
This reverts commit 1e40e70efc.
2019-02-03 09:49:22 -05:00
Shpuld Shpludson 063b5ba52b Merge branch 'revert-886aa35e' into 'develop'
Revert "Merge branch 'feature/split-hide-network' into 'develop'"

See merge request pleroma/pleroma-fe!514
2019-02-03 14:37:54 +00:00
Shpuld Shpludson d4991d0162 Revert "Merge branch 'feature/split-hide-network' into 'develop'"
This reverts merge request !497
2019-02-03 14:32:23 +00:00
shpuld 18ae7bd5f3 Combine friends/followers 2019-02-03 11:58:49 +02:00
shpuld b614cb94e5 merge develop in 2019-02-03 10:13:09 +02:00
Shpuld Shpludson c7ee2ed831 Merge branch '238-add-avatar-size-suggestion' into 'develop'
Add avatar size instruction notice

Closes #238

See merge request pleroma/pleroma-fe!512
2019-02-03 07:05:38 +00:00
Shpuld Shpludson f0721ed83b Merge branch 'fix/default-inlined-videos' into 'develop'
Change video playing default without bothering making it an instance configurable

See merge request pleroma/pleroma-fe!505
2019-02-03 06:45:04 +00:00
Xiaofeng An 1e40e70efc #306 - fix conversation arrow smushed in notifications panel 2019-02-02 21:49:07 -05:00
taehoon d8ad494081 Add avatar size instruction notice 2019-02-02 20:39:41 -05:00
taehoon 4833f79cc2 Fix class ordering issues related to avatar 2019-02-02 15:50:25 -05:00
taehoon 0b66a43a83 Improve reusability of UserAvatar component 2019-02-02 15:33:02 -05:00
shpuld dbb16d56e2 follows/followers pagination ready for review 2019-02-02 22:29:10 +02:00
taehoon 89b9aed134 Move avatar css into a correct place 2019-02-02 14:33:13 -05:00
taehoon d607e4195a Migrate StillImage to UserAvatar for avatars 2019-02-02 14:23:52 -05:00
taehoon 9c4092dbd5 Use a correct avatar placeholder image 2019-02-02 14:17:00 -05:00
taehoon 95b735ff72 Show placeholder image if avatar image url is broken 2019-02-02 14:11:36 -05:00
HJ 815b9d2391 Merge branch 'fix-max-id-for-notifications' into 'develop'
Fix incorrect latest_id value in notifications_read request

See merge request pleroma/pleroma-fe!509
2019-02-02 15:51:06 +00:00
eugenijm b62d2c76e5 Use integer type of notitication ids (avoid redundant casting for getting maxId in addNewNotifications) 2019-02-02 18:40:47 +03:00
eugenijm 0ab2f17991 Explicitly cast notification ids to integers when using them for setting maxId
This fixes the bug where BE receives incorrect `since_id` when marking
notifications as read.
2019-02-02 17:04:09 +03:00
Shpuld Shpludson 0fba655cf0 Merge branch 'fix/repeats-dont-show-any-name-if-display-name-is-empty' into 'develop'
fix #157 show screen_name when name is empty in retweet

Closes #157

See merge request pleroma/pleroma-fe!508
2019-02-02 05:52:39 +00:00
Joshua Burch 7d93beb96d fix #157 show screen_name when name is empty in retweet 2019-02-01 17:40:06 -05:00
feld 75b8b5d1eb Merge branch 'fix/name-field-length-should-be-as-wide-as-the-bio-field' into 'develop'
fix #209 make name field length as wide as the bio field

Closes #209

See merge request pleroma/pleroma-fe!507
2019-02-01 21:32:31 +00:00
Joshua Burch 9eddaf6c3e fix #209 make name field length as wide as the bio field 2019-02-01 16:12:14 -05:00
Shpuld Shpludson 1a6207be1d Merge branch 'fix/add-option-to-not-render-background-tabs' into 'develop'
Fix #298 Add option to tab switcher to not render background tabs

Closes #298

See merge request pleroma/pleroma-fe!504
2019-01-31 19:21:49 +00:00
shpuld a8c6b3f538 Change video playing default without bothering making it an instance configurable 2019-01-31 21:19:41 +02:00
shpuld 8ce513ed09 initial draft for follows/following pagination 2019-01-31 21:11:28 +02:00
Shpuld Shpludson 3e4c598af4 Merge branch 'fix/statistics' into 'develop'
Fix statistics label visibility via configuration

See merge request pleroma/pleroma-fe!503
2019-01-31 15:11:29 +00:00
Shpuld Shpludson 59d47aa44a Merge branch 'patch-1' into 'develop'
Only generate mentions string if there are mentions

See merge request pleroma/pleroma-fe!502
2019-01-31 15:06:26 +00:00
shpuld 476bf0afe1 Fix media timeline attachments being small by adding an option to not render background tabs in tab switcher 2019-01-31 17:00:31 +02:00
Edijs 6a8d10f0bb Fix statistics label visibility via configuration 2019-01-30 18:53:34 -07:00
shadowfacts 3c4cf5ed11 Only generate mentions string if there are mentions
Otherwise, a user replying to themselves without mentioning anyone else will insert a space at the beginning of the reply text area, hiding the placeholder.
2019-01-31 00:50:19 +00:00
Shpuld Shpludson fbe7af3d56 Merge branch 'fix/css-margin-adjustments-for-attachments' into 'develop'
Adjust margins for attachments/previews

See merge request pleroma/pleroma-fe!501
2019-01-30 19:45:15 +00:00
shpuld aaa5f1a638 Adjust margins for attachments/previews 2019-01-30 21:41:07 +02:00
lambda 5b7b1dfebc Merge branch 'feat/media-modal' into 'develop'
modal for viewing attachments in-tab

See merge request pleroma/pleroma-fe!468
2019-01-30 18:58:08 +00:00
shpuld c7cffbb6c7 Merge branch 'develop' into feat/media-modal 2019-01-30 20:49:24 +02:00
lambda b1facdf7ad Merge branch 'fix/timeline-too-eager-flush' into 'develop'
Fix #290 Add a better check for fresh TL flushing

Closes #290

See merge request pleroma/pleroma-fe!494
2019-01-30 17:51:12 +00:00
lambda 1717e70046 Merge branch 'feat/dont-show-load-more-when-bottomed-out' into 'develop'
fix #292 dont show "load more" when bottomed out

Closes #292

See merge request pleroma/pleroma-fe!496
2019-01-30 17:49:27 +00:00
lambda 0bd77149a0 Merge branch 'fix/tall-statuses-v2' into 'develop'
More tall status related fixes that I didn't know was borkd

See merge request pleroma/pleroma-fe!498
2019-01-30 17:47:46 +00:00
lambda d0df98f99b Merge branch 'fix/reply-to-using-wrong-id' into 'develop'
Fix #295 reply-to link pointing to wrong id

Closes #295

See merge request pleroma/pleroma-fe!499
2019-01-30 17:46:52 +00:00
lambda 7b0e3dc471 Merge branch 'feat/make-mentions-use-internal-routing' into 'develop'
Fix #289 Make more user links use internal routing

Closes #289

See merge request pleroma/pleroma-fe!500
2019-01-30 17:46:18 +00:00
Shpuld Shpludson 886aa35eb6 Merge branch 'feature/split-hide-network' into 'develop'
Split hide_network into hide_followers & hide_followings

See merge request pleroma/pleroma-fe!497
2019-01-30 17:41:54 +00:00
shpuld 15603981f8 Capture clicks on statuses to hijack mention clicks, match mention href to user somehow 2019-01-30 19:24:47 +02:00
shpuld 16a5272726 Fix a simple typo 2019-01-30 16:57:19 +02:00
shpuld 0a39159fdf Adjust scrolling logic and document it, make sure to never show 'show less' if it's not a tall status 2019-01-30 16:38:28 +02:00
Maxim Filippov 298cea8f6d Split hide_network into hide_followers & hide_followings 2019-01-30 01:11:40 +03:00
shpuld 7666d50d8a Change panel-footing style to be more fitting 2019-01-29 21:11:00 +02:00
lambda 43c26a4cd0 Merge branch 'fix/favorites-timelines-fetching-on-direct-url' into 'develop'
Fix #286 favs timeline fetching when opening profile via direct url

Closes #286

See merge request pleroma/pleroma-fe!495
2019-01-29 19:10:33 +00:00
shpuld 62e9525724 Add loading indicator for notifications, make timelines indicate bottoming out when no more statuses 2019-01-29 21:04:52 +02:00
shpuld 0a0dffa793 Fix favs timeline fetching when opening profile via direct url 2019-01-29 19:12:47 +02:00
shpuld 89bfc41174 Add a better check for fresh TL flushing 2019-01-29 18:40:49 +02:00
lambda 3cfbf0141f Merge branch 'fix/nav-panel-shadow' into 'develop'
Add missing shadow to nav panel

See merge request pleroma/pleroma-fe!491
2019-01-29 15:57:52 +00:00
lambda bd6c446b33 Merge branch 'fix/dont-connect-ws-when-chat-disabled' into 'develop'
fix #288 - Don't connect WS when chat is disabled

Closes #288

See merge request pleroma/pleroma-fe!492
2019-01-29 15:57:36 +00:00
lambda 0e5fe7504f Merge branch 'fix/user-by-name-type-error' into 'develop'
Fix TypeError crash when using url of an invalid user

See merge request pleroma/pleroma-fe!493
2019-01-29 15:56:27 +00:00
shpuld b042c48fa7 Fix TypeError crash when using url of an invalid user 2019-01-29 17:38:55 +02:00
shpuld 41c4d59341 Connect only after-store instead of when user gets token 2019-01-29 17:16:25 +02:00
shpuld 1f3cf6d1fc add missing shadow to nav panel 2019-01-29 16:32:34 +02:00
lambda 4185452b52 Merge branch 'feature/link-preview' into 'develop'
link previews

See merge request pleroma/pleroma-fe!481
2019-01-29 14:12:18 +00:00
lambda de91998317 Merge branch 'fix/tall-status-handling' into 'develop'
Tall status fixes/improvements

See merge request pleroma/pleroma-fe!490
2019-01-28 20:09:40 +00:00
shpuld c3a931610a remove log 2019-01-28 22:03:25 +02:00
shpuld 0460728a8c Fix tall status expanding needing extra clicks, make tall status expand automatically in conversation when focused 2019-01-28 21:59:17 +02:00
lambda fcd99ebc5b Merge branch 'fix/make-user-by-name-case-insensitive' into 'develop'
Make userByName case-insensitive

See merge request pleroma/pleroma-fe!489
2019-01-28 19:25:25 +00:00
shpuld a593c2cb8c Make userByName case-insensitive 2019-01-28 21:21:11 +02:00
lambda d367ca9290 Merge branch 'fix/user-timeline-again' into 'develop'
Fix user TL getting stuck again

See merge request pleroma/pleroma-fe!487
2019-01-28 18:52:47 +00:00
Shpuld Shpludson b0b6ebee17 Merge branch 'rename-service-worker' into 'develop'
Rename service worker to not clash with mastodon sw.

See merge request pleroma/pleroma-fe!486
2019-01-28 18:20:27 +00:00
shpuld ca78623b34 fix user tl clearing and give it a test 2019-01-28 20:15:00 +02:00
lain 2ce6fba2ba Rename service worker to not clash with mastodon sw. 2019-01-28 18:03:24 +01:00
shpuld 51024a2c8a Merge branch 'develop' into feat/media-modal 2019-01-28 19:02:46 +02:00
lambda bb2ee04f04 Merge branch 'fix/dont-fetch-favorites-for-others' into 'develop'
fix/don't fetch favs if the profile isnt current user

See merge request pleroma/pleroma-fe!484
2019-01-28 16:22:03 +00:00
lambda 53712c1570 Merge branch 'fix/add-back-login-error' into 'develop'
Fix/add back login error

See merge request pleroma/pleroma-fe!485
2019-01-28 16:21:33 +00:00
shpuld 4d3907b86a Formatting 2019-01-28 17:48:00 +02:00
shpuld 1b76a5a9ea Add back that login error thing that someone removed 2019-01-28 17:43:51 +02:00
shpuld 82ef57cd59 dont fetch favs if profile isnt us 2019-01-28 16:59:01 +02:00
lambda 3b1cafc19f Merge branch 'fix/fix-warnings' into 'develop'
Fix annoying console warnings

See merge request pleroma/pleroma-fe!480
2019-01-28 10:52:24 +00:00
shpuld 96c36af731 refactor the FE parts 2019-01-28 05:50:12 +00:00
William Pitcock 2b86f6e883 status: only show link preview in main post view 2019-01-28 05:50:12 +00:00
William Pitcock 0924907c64 add link-preview component 2019-01-28 05:50:12 +00:00
William Pitcock b27ec058ca entity normalizer: add support for opengraph cards 2019-01-28 05:50:12 +00:00
Shpuld Shpludson 2585dfa4c2 Merge branch 'develop' into 'develop'
Add Dutch translation

See merge request pleroma/pleroma-fe!482
2019-01-28 04:32:55 +00:00
Shpuld Shpludson 8258c8b3f0 Merge branch 'fix-chat' into 'develop'
Properly handle websocket token (fixes chat).

See merge request pleroma/pleroma-fe!483
2019-01-27 20:49:09 +00:00
lain e4303da372 Properly handle websocket token (fixes chat). 2019-01-27 21:38:33 +01:00
spctrl d40a2f0429 Add Dutch translation 2019-01-27 19:44:17 +01:00
Shpuld Shpludson 6e945ee14b Merge branch 'fix/following-status-on-usercard' into 'develop'
Fix follow-button on usercard not showing following status correctly

See merge request pleroma/pleroma-fe!479
2019-01-27 14:14:59 +00:00
shpuld b9142e6fac Move following to qvitter only space 2019-01-27 16:10:55 +02:00
shpuld 20f113e811 Remove logs 2019-01-27 11:35:29 +02:00
shpuld ff5f5095df Fix replies to deleted posts/users pushing vue warnings 2019-01-27 11:31:23 +02:00
shpuld 2d94a49798 Fix registration path warning and translation warnings 2019-01-27 11:13:32 +02:00
shpuld 4c9f3b946d Add forgotten prop to entity normalizer 2019-01-27 08:42:34 +02:00
Shpuld Shpludson b7c13fd4b4 Merge branch 'feat/better-perf-side-drawer-anim' into 'develop'
use translate over margin animation (stupid me)

See merge request pleroma/pleroma-fe!478
2019-01-27 06:32:21 +00:00
shpuld 474fbf6bf4 use translate over margin animation (stupid me) 2019-01-27 08:27:41 +02:00
Shpuld Shpludson b82ba54add Merge branch 'feature/media-timeline' into 'develop'
media timeline

See merge request pleroma/pleroma-fe!472
2019-01-26 21:11:02 +00:00
shpuld 676acdbf82 Add default config for new options, fix firefox inline playing 2019-01-26 17:59:59 +02:00
shpuld 0ab828bb30 Merge develop and fix conflict 2019-01-26 17:50:41 +02:00
shpuld 3978aaef84 Redo everything in the MR 2019-01-26 17:45:03 +02:00
William Pitcock efad3ad0a5 attempt to fix tests 2019-01-26 13:51:07 +00:00
William Pitcock 7b296696a3 user profile: add media timeline 2019-01-26 13:49:24 +00:00
William Pitcock dbe0205a9c api service: add the ability to fetch a media-only timeline 2019-01-26 13:49:24 +00:00
HJ 8197c77f75 Merge branch 'hotifx-convos' into 'develop'
Fix ordering in convos

See merge request pleroma/pleroma-fe!477
2019-01-25 15:00:06 +00:00
Henry Jameson 9f914824cb i should take it easy 2019-01-25 17:55:56 +03:00
HJ a733a33d36 Merge branch 'hotfix-broken-convos' into 'develop'
Hotfix broken convos

See merge request pleroma/pleroma-fe!476
2019-01-25 13:29:24 +00:00
Henry Jameson eb33951186 hotfix 2019-01-25 16:24:41 +03:00
lambda 28d1571530 Merge branch 'hotfix/summary-html' into 'develop'
entity normalizer: provide summary_html property

See merge request pleroma/pleroma-fe!475
2019-01-25 10:10:27 +00:00
William Pitcock 5e68161d91 entity normalizer: provide summary_html property
Mastodon API returns HTML always in spoiler_text, while TwitterAPI sends both a
text version as well as an HTML version of the message subject, which we started
to use when we allowed custom emoji in message subjects.
2019-01-25 10:05:19 +00:00
Henry Jameson f48e3d0db8 quickfix 2019-01-25 01:39:19 +03:00
HJ 63df815dd9 Merge branch 'fixSortingSequentials' into 'develop'
Fix TL sorting

See merge request pleroma/pleroma-fe!474
2019-01-24 22:16:26 +00:00
Henry Jameson 9d0d6b86c8 this attempts converting id to number to sort them numerically, since "99" >
"100" while 99 < 100
2019-01-25 01:08:08 +03:00
HJ 03ffa7e84e Merge branch 'fix-custom-nsfw-image' into 'develop'
fix custom nsfwCensorImage not working

See merge request pleroma/pleroma-fe!469
2019-01-24 18:13:07 +00:00
HJ 8b7faa8106 Merge branch 'favorites-fixes' into 'develop'
fix reply-to tooltip being somewhat unreliable

See merge request pleroma/pleroma-fe!473
2019-01-24 18:05:09 +00:00
Henry Jameson f38da239d9 "spring" cleaning 2019-01-24 21:03:13 +03:00
Henry Jameson 416424d048 review 2019-01-24 20:27:20 +03:00
Shpuld Shpludson 3492ab6697 Merge branch 'fix-who-to-follow-panel-shuffling' into 'develop'
Fix who to follow panel shuffling

See merge request pleroma/pleroma-fe!470
2019-01-24 15:17:35 +00:00
Hakaba Hitoyo efa0c85ac0 Fix who to follow panel shuffling 2019-01-24 15:17:35 +00:00
HJ 9305dad005 Merge branch 'fix/hide-network-setting' into 'develop'
Always send "hide_network" when updating user profile

See merge request pleroma/pleroma-fe!471
2019-01-24 12:15:46 +00:00
Maxim Filippov 958557201a Always send "hide_network" when updating user profile 2019-01-23 19:46:35 +03:00
Henry Jameson ac64e90898 fix custom nsfwCensorImage not working 2019-01-23 00:15:24 +03:00
Henry Jameson 61c9ecd855 fix reply-to tooltip being somewhat unreliable 2019-01-23 00:10:26 +03:00
HJ c8caa477d7 Revert "fix reply-to tooltip being somewhat unreliable"
This reverts commit 66dc72deb2
2019-01-22 21:08:28 +00:00
Henry Jameson 66dc72deb2 fix reply-to tooltip being somewhat unreliable 2019-01-23 00:03:33 +03:00
Henry Jameson 8946ff9838 fix errors in console 2019-01-22 23:57:27 +03:00
HJ 3a3cf1d48a Merge branch 'favorites' into 'develop'
Add Favorites TL to user profile, add some initial support for MastoAPI

Closes #265 and #262

See merge request pleroma/pleroma-fe!462
2019-01-22 17:46:08 +00:00
Henry Jameson 92dedcd53e linting 2019-01-22 20:27:49 +03:00
Henry Jameson d405bfe6de update test names 2019-01-22 19:58:59 +03:00
Henry Jameson 42f8d01b66 confusion 2019-01-21 21:41:17 +03:00
Henry Jameson 031c044297 better handling of attachments 2019-01-21 16:28:36 +03:00
shpuld 8761e039d0 Merge dev fix conflicts 2019-01-20 15:52:35 +02:00
shpuld 485a061287 Polish for videos, smaller sizes, remove gif-looping options 2019-01-20 12:46:11 +02:00
lambda 7651290e2b Merge branch 'referrer-caching-fix' into 'develop'
Don't use referrerpolicy with media proxy.

See merge request pleroma/pleroma-fe!467
2019-01-20 10:26:20 +00:00
lain 0ed1828352 Linting. 2019-01-19 14:56:18 +01:00
lain 741ccfdc4a Don't use referrerpolicy with media proxy. 2019-01-19 14:45:56 +01:00
kaniini d8512bf6eb Merge branch 'develop' into 'develop'
update logo

See merge request pleroma/pleroma-fe!466
2019-01-19 07:29:49 +00:00
nik aed7c7096e update logo 2019-01-18 22:17:38 -06:00
Henry Jameson d231a45644 support for extended fields (for future, doesn't work yet), fix reply bug 2019-01-19 04:10:16 +03:00
lambda ee5fd0dd1a Merge branch 'package-updates' into 'develop'
Upgrade packages

See merge request pleroma/pleroma-fe!461
2019-01-18 18:50:41 +00:00
lambda 08b277aa8b Merge branch 'update-japanese-translation' into 'develop'
Update Japanese translation

See merge request pleroma/pleroma-fe!465
2019-01-18 18:50:21 +00:00
Henry Jameson bac7154bc6 more fields for users 2019-01-17 23:57:24 +03:00
Henry Jameson 6c70e9950c some more post fields 2019-01-17 23:57:24 +03:00
Henry Jameson af36f4915a support for CW/Subject. fix replies. 2019-01-17 23:57:24 +03:00
Henry Jameson 80a7035154 removing unnecessary conversions since it should already be converted in normalizer 2019-01-17 23:57:24 +03:00
Henry Jameson 8172eeb1e0 fix indents 2019-01-17 23:05:58 +03:00
Henry Jameson 8f4fbf8571 some consistency 2019-01-17 23:01:38 +03:00
Henry Jameson a680f7d684 localization strings 2019-01-17 22:49:33 +03:00
Henry Jameson 6e219c2961 add support for tab-switcher to automatically switch to first tab if asked index
is invalid
2019-01-17 22:46:41 +03:00
Henry Jameson 93cbb58212 fix login and favorites tab... 2019-01-17 22:11:51 +03:00
Henry Jameson cab87744c8 Revert "some initial work to make it possible to use "unregistered" timelines, i.e. not"
and some stuff to make favorites still work

This reverts commit 039a407400.
2019-01-17 21:46:03 +03:00
Henry Jameson 0f8baff5a3 forgot the file 2019-01-17 21:26:02 +03:00
Henry Jameson 1e61c8140b tests for the tests god! bugfixes for bugfixes throne! 2019-01-17 20:44:37 +03:00
Henry Jameson a2ef716f3b consistency in tests too 2019-01-17 19:27:57 +03:00
Henry Jameson 9682ee66ce added conversions to ids for consistency from the get-go 2019-01-17 19:23:14 +03:00
Henry Jameson 5251de317d Merge branch 'switch-to-string-ids' into favorites
with some changes/merge conflicts resolution

* switch-to-string-ids:
  fixx?????
  fix notifications?
  fix lint
  fix tests, removed one unused function, fix real problem that tests helped to surface
  added some more explicit to string conversion since BE seem to be sending numbers and it could cause an issue.
  Remove all explicit and implicit conversions of statusId to number, changed explicit ones so that they convert them to string
2019-01-17 19:16:45 +03:00
Henry Jameson 387bf794ff fixx????? 2019-01-16 18:52:30 +03:00
shpuld e1c3691a72 Add escape button support 2019-01-16 17:27:23 +02:00
Henry Jameson 7d15720339 fix notifications? 2019-01-16 17:30:47 +03:00
hakabahitoyo fc83d76ab5 update japanese translation 2019-01-16 18:14:15 +09:00
HJ ea1d21aafa Merge branch 'feature/show-who-to-follow-in-mobile-view' into 'develop'
Show who to follow in the mobile view

See merge request pleroma/pleroma-fe!452
2019-01-16 02:33:08 +00:00
Hakaba Hitoyo 05ead45fb7 Show who to follow in the mobile view 2019-01-16 02:33:08 +00:00
lambda 502a76be0a Merge branch 'summary-html' into 'develop'
Sync with backend: Use summary_html.

See merge request pleroma/pleroma-fe!463
2019-01-15 20:16:11 +00:00
lambda 85e2ca4a0a Merge branch 'reply-detection' into 'develop'
Remove reply detection hack

See merge request pleroma/pleroma-fe!464
2019-01-15 20:15:28 +00:00
Henry Jameson d7bd294666 migrated some tests to normalizer, fixed some potential bug, fixed tests to use
normalized naming instead of raw qvitter api objects. needs more tests tho.
2019-01-15 18:39:24 +03:00
Henry Jameson 966a9e78af cleanup 2019-01-14 22:59:44 +03:00
Henry Jameson fd27c78c4b fixes, guards 2019-01-14 22:58:23 +03:00
Henry Jameson 790fcf37d2 notifications now also undergo some parsing, hypothetically could use MastoAPI
notifications, maybe.
2019-01-14 22:38:37 +03:00
shpuld 17735943d5 Add media viewer module and media module component, modify attachment behavior 2019-01-14 19:23:13 +02:00
Henry Jameson e0fd6d12ed user normalizer works 2019-01-14 15:30:14 +03:00
Henry Jameson 5a3c9cfc9b post-merge fix 2019-01-13 22:25:48 +03:00
Henry Jameson f9fb85ee42 Merge remote-tracking branch 'upstream/develop' into favorites
* upstream/develop:
  Add Korean translation
  Change emptlyTl to take userId
  better fix
  fixes #265 and also that thin line below gradient on chrome (UGH)
  fix #262 part of user profiles not being able to load previous posts
  Retain userId on clearing user timeline, don't flush when empty timeline
2019-01-13 22:21:09 +03:00
Henry Jameson 519f49e29b separated normalization into a another file, removed catchall and added more stuff 2019-01-13 22:14:55 +03:00
scarlett de8dfef252 Remove reply detection hack 2019-01-13 13:41:02 +00:00
scarlett 0fd7e7eb68 Sync with backend: Use summary_html. 2019-01-13 13:38:00 +00:00
Henry Jameson 4be737b4df moved some stuff from statuses to api service. added initial adapter (currently
mastoapi status -> qvitter status, would change some naming in the future)

favorites timeline works somewhat, notifications are broken because they are
fetched using same code to fetch usual timeline/using old architechture
2019-01-13 01:26:24 +03:00
Henry Jameson 039a407400 some initial work to make it possible to use "unregistered" timelines, i.e. not
reserving a timeline by name, instead just passing timeline object itself.
2019-01-12 23:33:45 +03:00
Lambda 28cdf150fd Upgrade packages 2019-01-11 15:15:10 +01:00
Henry Jameson 22e0686395 fix lint 2019-01-11 03:41:57 +03:00
Henry Jameson b18e27c6d4 fix tests, removed one unused function, fix real problem that tests helped to
surface
2019-01-11 03:38:23 +03:00
Henry Jameson 48e811e6ed added some more explicit to string conversion since BE seem to be sending
numbers and it could cause an issue.
2019-01-11 03:00:11 +03:00
Henry Jameson ef2585e32b Remove all explicit and implicit conversions of statusId to number, changed
explicit ones so that they convert them to string
2019-01-11 02:40:17 +03:00
Shpuld Shpludson 52579b09b1 Merge branch 'translate-korean' into 'develop'
Add Korean translation

See merge request pleroma/pleroma-fe!457
2019-01-10 14:56:25 +00:00
kjwon15 d4eb3cb36b Add Korean translation 2019-01-10 14:56:05 +09:00
Shpuld Shpludson a51167fa72 Merge branch 'fix-265-fix-user-profiles-again' into 'develop'
fixes #265 and also that thin line below gradient on chrome (UGH)

Closes #265

See merge request pleroma/pleroma-fe!456
2019-01-09 20:57:00 +00:00
Shpuld Shpludson 499c6b85d4 Merge branch 'fix/user-timeline-not-loading' into 'develop'
Fix #262 user timelines bugging

Closes #262

See merge request pleroma/pleroma-fe!454
2019-01-09 20:56:09 +00:00
Shpuld Shpludson 4fbaffef53 Merge branch 'fix-262-load-older' into 'develop'
fix #262 part of user profiles not being able to load previous posts

Closes #262

See merge request pleroma/pleroma-fe!455
2019-01-09 20:55:36 +00:00
shpuld b8b18b198d Change emptlyTl to take userId 2019-01-09 22:19:02 +02:00
Henry Jameson f4b499b044 better fix 2019-01-09 16:31:53 +03:00
Henry Jameson d13f36a2ad fixes #265 and also that thin line below gradient on chrome (UGH) 2019-01-09 15:36:09 +03:00
Henry Jameson 0b8f616af1 fix #262 part of user profiles not being able to load previous posts 2019-01-09 14:18:36 +03:00
shpuld a8f6099be2 Retain userId on clearing user timeline, don't flush when empty timeline 2019-01-08 23:09:03 +02:00
Shpuld Shpludson 1fb9ceb59b Merge branch 'feature/add-about-page-for-mobile' into 'develop'
Add instance information page for mobile

See merge request pleroma/pleroma-fe!451
2019-01-07 17:26:47 +00:00
Hakaba Hitoyo a60fc390a0 Add instance information page for mobile 2019-01-07 17:26:47 +00:00
HJ 2184334ad9 Merge branch 'avoid-duplicates-in-who-to-follow-panel' into 'develop'
[Debug] Avoid duplicates in the who to follow panel

See merge request pleroma/pleroma-fe!441
2019-01-04 08:43:00 +00:00
Hakaba Hitoyo 702f013225 [Debug] Avoid duplicates in the who to follow panel 2019-01-04 08:43:00 +00:00
Shpuld Shpludson 35d75be1d6 Merge branch 'develop' into 'develop'
updated German translation

See merge request pleroma/pleroma-fe!449
2019-01-03 21:00:21 +00:00
Shpuld Shpludson d0414dcd2f Merge branch 'readme-update' into 'develop'
Update README

See merge request pleroma/pleroma-fe!446
2019-01-03 20:58:40 +00:00
Shpuld Shpludson 1ef913a128 Merge branch 'fix/captcha-string-typo' into 'develop'
Fix translation typo in registration.vue

Closes #257

See merge request pleroma/pleroma-fe!448
2019-01-03 20:58:04 +00:00
Vinzenz Vietzke 681b4e665d updated German translation
* added theme settings
 * added various missing single strings
2019-01-03 19:53:53 +01:00
rinpatch c25cf29533 Fix translation typo in registration.vue 2019-01-03 19:42:43 +01:00
Francis Dinh 7ad3cff862 Update README
Mention that the Pleroma frontend is already included with the Pleroma backend.
Also explicitly use `Pleroma-FE` when referring to the frontend.
2019-01-01 18:10:48 -05:00
Shpuld Shpludson 76cfb15b3c Merge branch 'feature/replace-panel-switcher' into 'develop'
Mobile side drawer

See merge request pleroma/pleroma-fe!443
2018-12-31 17:35:31 +00:00
HJ 7aa42c01eb Merge branch 'fix/profile-with-no-statuses-not-loading' into 'develop'
Fix profiles without statuses not loading

See merge request pleroma/pleroma-fe!445
2018-12-31 01:57:22 +00:00
Shpuld Shpludson fb8f774383 Fix profiles without statuses not loading 2018-12-31 01:57:22 +00:00
HJ 1316ed43a5 Merge branch 'fix/conversation-headings-in-user-profile' into 'develop'
Fix conflicting styles in conversation panels under user profile

See merge request pleroma/pleroma-fe!444
2018-12-31 01:41:37 +00:00
shpuld 354fd32e7b Fix conflicting styles 2018-12-30 22:41:31 +02:00
HJ a974d2ab85 Merge branch 'scope-copy-default' into 'develop'
scopeCopy → true by default

See merge request pleroma/pleroma-fe!439
2018-12-30 15:12:03 +00:00
shpuld ace042015e Remove commented out back button 2018-12-29 23:42:01 +02:00
shpuld 16c7bd0199 merge develop, fix conflicts, fix logged out bug 2018-12-29 16:25:45 +02:00
lambda 1555a5fef3 Merge branch 'restore-routes' into 'develop'
Restore old routes, enable user route as fallback.

See merge request pleroma/pleroma-fe!440
2018-12-29 13:27:59 +00:00
shpuld 747e4090ca Cleanup and remove divider element in side drawer 2018-12-29 12:44:21 +02:00
shpuld 650655709d fix conflict in user card content 2018-12-28 21:44:09 +02:00
shpuld 85c058e95c New routes, notifications, other impovements in side drwaer 2018-12-28 21:39:54 +02:00
HJ a86b80b054 Merge branch 'feature/no-attachment-links' into 'develop'
No attachment links

Closes #175

See merge request pleroma/pleroma-fe!442
2018-12-27 17:13:17 +00:00
Maxim Filippov 0f530de397 Add "noAttachmentLinks" to src/modules/instance.js 2018-12-27 19:59:56 +03:00
Maxim Filippov 85c487b933 Make "noAttachmentLinks" configurable 2018-12-27 13:25:11 +03:00
Maxim Filippov 13855f46e2 No attachment links 2018-12-27 02:37:36 +03:00
HJ 754cb23f35 Merge branch 'improve_push' into 'develop'
Improve web push notifications

Closes #231

See merge request pleroma/pleroma-fe!438
2018-12-26 13:58:11 +00:00
Lambda f35dbaf064 Treat reserved users like external users in the frontend. 2018-12-26 14:50:48 +01:00
Shpuld Shpludson 9ba969d90c Merge branch 'fix_notifications' into 'develop'
User Card Content fixes and updates

See merge request pleroma/pleroma-fe!437
2018-12-26 09:19:25 +00:00
HJ fa8ecb1c39 User Card Content fixes and updates 2018-12-26 09:19:25 +00:00
scarlett f2f7e2e766 scopeCopy → true by default 2018-12-25 17:44:05 +00:00
Lambda 24eba26c5b Restore old routes, enable user route as fallback. 2018-12-25 18:43:52 +01:00
Egor Kislitsyn c5847349e0 improve web push notifications 2018-12-25 20:43:18 +07:00
HJ 0ad837846a Merge branch 'push_fix' into 'develop'
Fixes for push notifications

Closes #235

See merge request pleroma/pleroma-fe!433
2018-12-25 11:33:00 +00:00
Henry Jameson 500b4bd374 fix 2018-12-25 14:28:49 +03:00
Shpuld Shpludson 2fe0af2af1 Merge branch 'update-japanese-translation' into 'develop'
Update japanese translation

See merge request pleroma/pleroma-fe!435
2018-12-25 09:03:05 +00:00
Hakaba Hitoyo 8ae3518a9a Update japanese translation 2018-12-25 09:03:05 +00:00
HJ a80c8fd24c Merge branch 'refactor-recommendations' into 'develop'
remove unneeded numbered variables who_to_follow

See merge request pleroma/pleroma-fe!436
2018-12-25 02:35:30 +00:00
Hannah Ward ed2393c970
fix inconsistencies within who_to_follow_panel 2018-12-25 01:32:20 +00:00
HJ 698328dfbe Merge branch 'fix_textfields' into 'develop'
Fix textarea not resizing correctly and probably cursor position

Closes #230

See merge request pleroma/pleroma-fe!430
2018-12-25 01:29:18 +00:00
Henry Jameson 18d7684f32 fix for non-shrinking main post form 2018-12-25 04:25:19 +03:00
Henry Jameson e3cac42cc7 Merge remote-tracking branch 'upstream/develop' into push_fix
* upstream/develop:
  Add a translation to the captcha strings in the registration form
  Small UI improvements for the CAPTCHA field
  Add encrypted captcha_answer_data for stateless captcha
  fixes many problems related to user profile
2018-12-25 03:46:51 +03:00
Henry Jameson a4f0902926 small refactor, added push unsub notice for BE 2018-12-25 03:46:19 +03:00
Hannah Ward 6fa993c122
remove unneeded numbered variables who_to_follow 2018-12-25 00:34:33 +00:00
shpuld 4752081818 Add closed-check for touchmove 2018-12-23 20:14:40 +02:00
shpuld e46b560ead move closing logic to drawer, add swipe to close 2018-12-23 19:50:19 +02:00
shpuld f72b1d048e Merge branch 'develop' into feature/replace-panel-switcher 2018-12-22 17:32:35 +02:00
shpuld 4836c8ac74 Add some more routes to side drawer 2018-12-22 17:32:07 +02:00
Shpuld Shpludson e59b67e119 Merge branch 'captcha' into 'develop'
Make captcha stateless

See merge request pleroma/pleroma-fe!434
2018-12-22 06:17:56 +00:00
Ekaterina Vaartis 10642df528 Add a translation to the captcha strings in the registration form 2018-12-21 15:12:46 +03:00
Ekaterina Vaartis 661efc51b7 Small UI improvements for the CAPTCHA field 2018-12-21 00:25:36 +03:00
Ekaterina Vaartis 8470856045 Add encrypted captcha_answer_data for stateless captcha 2018-12-21 00:25:09 +03:00
shpuld 67263cde05 works but hacky 2018-12-20 22:20:04 +02:00
Henry Jameson 957b2a6f7e simplified some code, made it possible to unregister serviceworker altogether 2018-12-20 09:17:59 +03:00
Henry Jameson d0b47488fb default webPush to false, because having it at true leads to some problems with
local dev mode. Instances can re-enable it, and BE can default it to true in config.exs
2018-12-20 09:17:51 +03:00
Shpuld Shpludson 2921a25cb4 Merge branch 'fix_followers' into 'develop'
fixes many problems related to user profile

Closes #239

See merge request pleroma/pleroma-fe!432
2018-12-20 06:12:14 +00:00
Henry Jameson b7962a224c fixes many problems related to user profile 2018-12-20 07:54:55 +03:00
Henry Jameson 5970bf4e85 fixed incorrect height when empty text 2018-12-20 07:27:29 +03:00
Henry Jameson afa2baec0c I suppose SOME browsers don't do this by default... 2018-12-20 07:17:54 +03:00
Henry Jameson ae7b96abbf Fix resize not working properly for textareas 2018-12-20 07:17:54 +03:00
HJ b65ac128c1 Merge branch 'remove_favorite_hacks' into 'develop'
no more "broken favorite"

Closes #218 and #145

See merge request pleroma/pleroma-fe!431
2018-12-19 14:57:25 +00:00
Shpuld Shpludson c54b1fd0c5 Merge branch 'fix_defaults' into 'develop'
Fixed some settings not using defaults from instance config.

Closes #228

See merge request pleroma/pleroma-fe!429
2018-12-19 04:51:21 +00:00
Henry Jameson 5c2030e467 no more "broken favorite" 2018-12-19 01:55:53 +03:00
Henry Jameson c7514be46f Fixed some settings not using defaults from instance config. Made some parts of
code more readable
2018-12-18 23:31:10 +03:00
shpuld 640a287892 Merge branch 'develop' into feature/replace-panel-switcher 2018-12-18 22:09:27 +02:00
HJ 562c68a51c Merge branch 'user-profile-overhault' into 'develop'
Small refactor for followers/friends, change display to use tabs instead of "leaky brains"

Closes #111

See merge request pleroma/pleroma-fe!427
2018-12-18 19:48:05 +00:00
Henry Jameson 81c83566cd Merge remote-tracking branch 'upstream/develop' into user-profile-overhault
* upstream/develop: (24 commits)
  Feature/bigger icons for mobile / #211
  Fix oauth url
  Make user profile page cleaner
  Redirect to /main/all
  Move userProfile link to methods
  Fix user profile test
  Add temporary redirects
  Add local profile test
  Implement user_profile.spec.js
  Use babel polyfill in karma
  Use 'userProfileLink' to generate user-profile link
  Rollback disableDotRule
  Use "-1" in indexOf
  Add generateProfileLink
  Use "~" as a route namespace symbol
  Disable dot rule
  Pass userName instead of userId
  Typo in tests
  Fix redirect paths
  Fix typo
  ...
2018-12-18 22:43:26 +03:00
Shpuld Shpludson f62ff2d894 Merge branch 'feature/bigger-icons-for-mobile' into 'develop'
Feature/bigger icons for mobile / #211

See merge request pleroma/pleroma-fe!423
2018-12-18 18:26:14 +00:00
Shpuld Shpludson 67c2a607aa Feature/bigger icons for mobile / #211 2018-12-18 18:26:14 +00:00
lambda 2f28bf95fd Merge branch 'feature/new-user-routes' into 'develop'
Make domain.com/username routes work

Closes pleroma#395

See merge request pleroma/pleroma-fe!392
2018-12-18 15:26:00 +00:00
lambda c1ff17ebb0 Merge branch 'clean-profile' into 'develop'
Make user profile page cleaner

Closes #225

See merge request pleroma/pleroma-fe!428
2018-12-17 19:57:16 +00:00
Maxim Filippov 63ad08050e Fix oauth url 2018-12-17 21:58:16 +03:00
Henry Jameson 485a531d57 clean up the unused stuff 2018-12-17 21:02:16 +03:00
Henry Jameson be27494ca1 Make user profile page cleaner 2018-12-17 20:42:14 +03:00
Henry Jameson 56fdbf18c5 missing string and unification with counters (order) 2018-12-17 19:21:05 +03:00
Henry Jameson bf805361d0 collateral fix for tab display 2018-12-17 19:18:57 +03:00
Henry Jameson 292ac59d08 Merge remote-tracking branch 'upstream/develop' into user-profile-overhault
* upstream/develop:
  Fix style
  Add a way to get new captcha on click
  Fix style
  Separate captcha into the backendInteractor
  more visual fixes
  changed bottom-shadow hiding method to be more compatible with overflow
  small fix for overflowing tab-switcher
  Support disabling captcha
  Base support for CAPTCHA (kocaptcha)
2018-12-17 19:18:35 +03:00
Henry Jameson 23d434c40c collateral fixes for user-card: use still-image, styles for custom emoji 2018-12-17 19:17:03 +03:00
Henry Jameson 8f255fbad4 Refactor follower/friends out of statuses/timeline into user_profile where it
belongs. Changed display of profile to single panel with tabs.
2018-12-17 19:14:38 +03:00
Shpuld Shpludson b124dbf44e Merge branch 'captcha' into 'develop'
Captcha

See merge request pleroma/pleroma-fe!424
2018-12-17 13:36:56 +00:00
Maxim Filippov f671adae37 Redirect to /main/all 2018-12-17 03:01:24 +03:00
Maxim Filippov ea6977cd4d Move userProfile link to methods 2018-12-17 02:52:27 +03:00
Maxim Filippov 5f10c5e786 Fix user profile test 2018-12-17 02:45:40 +03:00
Maxim Filippov 2211c533dd Merge branch 'develop' into feature/new-user-routes 2018-12-17 02:39:37 +03:00
Maxim Filippov 5fc0fe28e4 Add temporary redirects 2018-12-17 02:26:40 +03:00
Maxim Filippov b524e73a65 Add local profile test 2018-12-17 01:53:21 +03:00
Ekaterina Vaartis d2984b9bc5 Fix style 2018-12-16 22:55:11 +03:00
Ekaterina Vaartis ab6f1904fa Add a way to get new captcha on click 2018-12-16 22:47:52 +03:00
Ekaterina Vaartis 3c9c8052f7 Fix style 2018-12-16 20:55:09 +03:00
Ekaterina Vaartis a525df32c9 Separate captcha into the backendInteractor 2018-12-16 20:53:41 +03:00
Shpuld Shpludson ada4bd0d98 Merge branch 'fix-tab-scroll' into 'develop'
Fix tab scroll

See merge request pleroma/pleroma-fe!426
2018-12-16 07:56:29 +00:00
Henry Jameson 1b9a5a3efe more visual fixes 2018-12-16 02:40:32 +03:00
Henry Jameson a1d00b9398 changed bottom-shadow hiding method to be more compatible with overflow 2018-12-16 02:07:32 +03:00
Henry Jameson fc7cd6eaf6 small fix for overflowing tab-switcher 2018-12-16 02:02:49 +03:00
shpuld bd2ed617a7 Remove panel switcher, add rudimentary drawer 2018-12-15 19:13:01 +02:00
Maxim Filippov 828b1c78f9 Implement user_profile.spec.js 2018-12-15 06:16:44 +03:00
HJ eaf065c751 Merge branch 'fix-name' into 'develop'
Fix impossible to change name

See merge request pleroma/pleroma-fe!425
2018-12-15 00:38:47 +00:00
Henry Jameson 7d3385f349 fix 2018-12-15 03:30:39 +03:00
Ekaterina Vaartis 92de235f4e Support disabling captcha 2018-12-15 03:06:21 +03:00
Ekaterina Vaartis 9303bd5d36 Base support for CAPTCHA (kocaptcha) 2018-12-15 03:05:47 +03:00
Shpuld Shpludson 4b30ce64c9 Merge branch 'async_follow' into 'develop'
Better "follow" button behavior

Closes #133

See merge request pleroma/pleroma-fe!396
2018-12-14 17:33:11 +00:00
HJ 10a0296aac Merge branch 'fix-hide-network' into 'develop'
oof

See merge request pleroma/pleroma-fe!422
2018-12-14 14:51:59 +00:00
Henry Jameson 7346c54df4 oof 2018-12-14 17:47:48 +03:00
Henry Jameson 13fbef4550 slightly changed the code to have less mutations, added comments 2018-12-14 17:33:48 +03:00
HJ 70ff9ce2b5 Merge branch 'fix-preload-nsfw' into 'develop'
Fix preload images option being always disabled

See merge request pleroma/pleroma-fe!421
2018-12-14 14:25:16 +00:00
Henry Jameson d7973b0b80 Merge remote-tracking branch 'upstream/develop' into async_follow
* upstream/develop: (45 commits)
  fix chrome
  Prevent html-minifier to remove placeholder comment in index.html template
  Add placeholder to insert server generated metatags. Related to #430
  added condition to check for logined user
  fix gradients and minor artifacts
  keep track of new instance options
  fix old MR
  oof
  get rid of slots
  fix timeago font
  added hide_network option, fixed properties naming
  Fix fetching new users, add storing local users in usersObjects with their screen_name as well as id, so that they could be fetched zero-state with screen-name link.
  improve notification subscription
  Refactor arrays to individual options
  Reset enableFollowsExport to true after 2 sec when an export file is available to download
  Write a unit test for fileSizeFormatService
  add checkbox to disable web push
  I am dumb
  Handle errors from server
  Moved upload errors in user_settings to an array. Moved upload error strings to its separate section in i18n
  ...
2018-12-14 17:17:58 +03:00
HJ a158e75a04 Merge branch 'search-mobile-fixes' into 'develop'
Fixes for user-finder on mobile

Closes #188 and #179

See merge request pleroma/pleroma-fe!389
2018-12-14 14:15:26 +00:00
Henry Jameson b4b819f4f4 more damage control 2018-12-14 17:14:55 +03:00
Henry Jameson bd745543b6 Merge remote-tracking branch 'upstream/develop' into search-mobile-fixes
* upstream/develop: (176 commits)
  fix chrome
  Prevent html-minifier to remove placeholder comment in index.html template
  Add placeholder to insert server generated metatags. Related to #430
  added condition to check for logined user
  fix gradients and minor artifacts
  keep track of new instance options
  fix old MR
  oof
  get rid of slots
  fix timeago font
  added hide_network option, fixed properties naming
  Fix fetching new users, add storing local users in usersObjects with their screen_name as well as id, so that they could be fetched zero-state with screen-name link.
  improve notification subscription
  Fix typo that prevented scope copy from working.
  Refactor arrays to individual options
  Reset enableFollowsExport to true after 2 sec when an export file is available to download
  added check for activatePanel is function or not
  addressed PR comments
  activate panel on user screen click
  added not preload check so hidden toggles asap
  ...
2018-12-14 17:10:26 +03:00
HJ 5b6c1aa97c Merge branch 'fix-chrome' into 'develop'
fix chrome

See merge request pleroma/pleroma-fe!420
2018-12-14 11:40:23 +00:00
Henry Jameson ac80cf868f fix chrome 2018-12-14 14:35:56 +03:00
HJ 54e34c68fc Merge branch 'placeholder_for_server_generated_meta' into 'develop'
Add placeholder to insert server generated metatags

See merge request pleroma/pleroma-fe!419
2018-12-14 11:11:32 +00:00
raeno c5042c07ef Prevent html-minifier to remove placeholder comment in index.html template 2018-12-13 23:35:27 +01:00
raeno 107596339c Add placeholder to insert server generated metatags. Related to #430 2018-12-13 22:29:07 +01:00
HJ 99b2b7a203 Merge branch 'feature/file-size-checking' into 'develop'
[pleroma#36] Add errors when file uploading fails

See merge request pleroma/pleroma-fe!405
2018-12-13 21:02:17 +00:00
HJ dcca4617d5 Merge branch 'dev_vald_fe/its_you' into 'develop'
added condition to check for login user in user search

Closes #182

See merge request pleroma/pleroma-fe!417
2018-12-13 19:56:22 +00:00
ValD e2f825266a added condition to check for logined user 2018-12-13 23:20:59 +05:30
Shpuld Shpludson ad56c8e5bd Merge branch 'collateral-damage-control' into 'develop'
Collateral damage control

See merge request pleroma/pleroma-fe!418
2018-12-13 17:47:01 +00:00
Henry Jameson cc259411a7 fix gradients and minor artifacts 2018-12-13 20:41:23 +03:00
Henry Jameson e1b523016b keep track of new instance options 2018-12-13 20:41:01 +03:00
Maxim Filippov 1341a7bb9c Use babel polyfill in karma 2018-12-13 20:27:03 +03:00
Henry Jameson f87001c22f fix old MR 2018-12-13 20:25:46 +03:00
Maxim Filippov e4a34cc4d4 Use 'userProfileLink' to generate user-profile link 2018-12-13 19:57:11 +03:00
Maxim Filippov 70c48a076d Rollback disableDotRule 2018-12-13 19:53:14 +03:00
Shpuld Shpludson ac60550e07 Merge branch 'mobile-back' into 'develop'
Back button for mobile

Closes #197

See merge request pleroma/pleroma-fe!403
2018-12-13 15:12:27 +00:00
Shpuld Shpludson 915487072b Merge branch 'fix/reset-follows-export' into 'develop'
Reset enableFollowsExport when an export file is available to download

See merge request pleroma/pleroma-fe!412
2018-12-13 15:06:50 +00:00
Shpuld Shpludson aa7cff92aa Merge branch 'feature/configurable-nsfw-censor-image' into 'develop'
make nsfw censor image configurable

See merge request pleroma/pleroma-fe!243
2018-12-13 15:04:55 +00:00
Rinpatch dd6a9ae645 oof 2018-12-13 17:51:29 +03:00
Shpuld Shpludson 25a88da17a Merge branch 'fix_loading_flicker' into 'develop'
Throttle fetching old statuses to prevent spam, especially during scroll

Closes #176

See merge request pleroma/pleroma-fe!393
2018-12-13 14:51:27 +00:00
Henry Jameson 610724ffcd Merge remote-tracking branch 'upstream/develop' into mobile-back
* upstream/develop: (142 commits)
  fix timeago font
  added hide_network option, fixed properties naming
  Fix fetching new users, add storing local users in usersObjects with their screen_name as well as id, so that they could be fetched zero-state with screen-name link.
  improve notification subscription
  Fix typo that prevented scope copy from working.
  added check for activatePanel is function or not
  addressed PR comments
  activate panel on user screen click
  added not preload check so hidden toggles asap
  removed counters from left panel
  added router-links to all relavent links
  added activatePanel onclick for timeago button
  added PR comments
  add checkbox to disable web push
  removed brackets from condition
  resolved lint issue
  renamed config to preload images and add ident to config
  added config for preload and made attachment responsive to it
  preload nsfw image
  fix
  ...
2018-12-13 17:50:36 +03:00
rinpatch 457132fb37 get rid of slots 2018-12-13 15:44:37 +01:00
Shpuld Shpludson dbe79a3c26 Merge branch 'dev-qol' into 'develop'
Several fixes to make life of contributors a tiny bit easier.

See merge request pleroma/pleroma-fe!409
2018-12-13 14:42:58 +00:00
Shpuld Shpludson c824d25378 Merge branch 'fix_empty_profiles' into 'develop'
Improved user profile display

Closes #82

See merge request pleroma/pleroma-fe!414
2018-12-13 14:41:57 +00:00
Shpuld Shpludson ad905576fc Merge branch 'hide_network' into 'develop'
FE part of pleroma!490

See merge request pleroma/pleroma-fe!415
2018-12-13 14:40:49 +00:00
HJ f1c21be77c Merge branch 'fix-timeago' into 'develop'
fix timeago font

See merge request pleroma/pleroma-fe!416
2018-12-13 14:25:29 +00:00
Rinpatch 6de4dcc7c9 Resolve merge conflict 2018-12-13 17:22:19 +03:00
Henry Jameson ff36d34186 fix timeago font 2018-12-13 17:20:31 +03:00
Henry Jameson fa7c3c2097 Merge remote-tracking branch 'upstream/develop' into fix_empty_profiles
* upstream/develop: (121 commits)
  improve notification subscription
  Fix typo that prevented scope copy from working.
  added check for activatePanel is function or not
  addressed PR comments
  activate panel on user screen click
  added not preload check so hidden toggles asap
  removed counters from left panel
  added router-links to all relavent links
  added activatePanel onclick for timeago button
  added PR comments
  add checkbox to disable web push
  removed brackets from condition
  resolved lint issue
  renamed config to preload images and add ident to config
  added config for preload and made attachment responsive to it
  preload nsfw image
  fix
  fixed wrong height for selects
  better layouting for import-export, error display fixes
  added keep-colors option
  ...
2018-12-13 17:11:22 +03:00
HJ 8e4777ccc6 Merge branch 'feature/push-subscriptions' into 'develop'
add service worker and push notifications

See merge request pleroma/pleroma-fe!404
2018-12-13 13:46:57 +00:00
Henry Jameson 9dfff10717 Merge remote-tracking branch 'upstream/develop' into async_follow
* upstream/develop: (131 commits)
  Fix typo that prevented scope copy from working.
  added check for activatePanel is function or not
  addressed PR comments
  activate panel on user screen click
  added not preload check so hidden toggles asap
  removed counters from left panel
  added router-links to all relavent links
  added activatePanel onclick for timeago button
  added PR comments
  removed brackets from condition
  resolved lint issue
  renamed config to preload images and add ident to config
  added config for preload and made attachment responsive to it
  preload nsfw image
  fix
  fixed wrong height for selects
  better layouting for import-export, error display fixes
  added keep-colors option
  separated preview and exported from style_switcher
  revert that, it's actually used, i'm an idiot
  ...
2018-12-13 16:15:47 +03:00
Henry Jameson c52b8019ae added hide_network option, fixed properties naming 2018-12-13 16:04:22 +03:00
Henry Jameson 42bb348219 Fix fetching new users, add storing local users in usersObjects with their
screen_name as well as id, so that they could be fetched zero-state with
screen-name link.
2018-12-13 15:34:51 +03:00
Egor Kislitsyn a8521fc8d9 Merge commit 'e443716bcd616ad61efae161624dd970841a935c' into feature/push-subscriptions
# Conflicts:
#	src/i18n/en.json
#	src/modules/interface.js
#	src/modules/users.js
#	yarn.lock
2018-12-13 18:22:15 +07:00
Egor Kislitsyn b3455649c5 improve notification subscription 2018-12-13 18:04:09 +07:00
Maxim Filippov 7ffb7e6795 Use "-1" in indexOf 2018-12-13 13:51:47 +03:00
HJ e443716bcd Merge branch 'fix-scope-copy' into 'develop'
Fix typo that prevented scope copy from working.

Closes #214

See merge request pleroma/pleroma-fe!413
2018-12-13 10:39:50 +00:00
Henry Jameson 9f48055261 Fix typo that prevented scope copy from working. 2018-12-13 13:34:47 +03:00
Rinpatch 48edc0c8fc Refactor arrays to individual options 2018-12-13 11:25:03 +03:00
Maxim Filippov 24caa2cfcd Add generateProfileLink 2018-12-13 05:00:01 +03:00
link0ff 33c2d21bb7 Reset enableFollowsExport to true after 2 sec when an export file is available to download 2018-12-12 22:00:04 +02:00
HJ 2077927ff3 Merge branch 'dev_vald_fe/user_name_panel' into 'develop'
activate panel on user screen click

See merge request pleroma/pleroma-fe!408
2018-12-12 19:31:15 +00:00
ValD ce6d75331b added check for activatePanel is function or not 2018-12-13 00:56:04 +05:30
HJ 7325ff2e7a Merge branch 'dev_vald_fe/nsfw_preload' into 'develop'
preload nsfw image

Closes #193

See merge request pleroma/pleroma-fe!411
2018-12-12 19:01:53 +00:00
HJ f0fb6e6015 Merge branch 'dev_vald_fe/timeago_panel' into 'develop'
added activatePanel onclick for timeago button

See merge request pleroma/pleroma-fe!407
2018-12-12 18:47:56 +00:00
HJ 13ef05d5e6 Merge branch 'dev_vald_fe/user_panel_counts' into 'develop'
removed user_panel counts

See merge request pleroma/pleroma-fe!410
2018-12-12 18:47:09 +00:00
ValD 481c5ecba8 addressed PR comments 2018-12-13 00:14:47 +05:30
ValD e3848f6efb activate panel on user screen click 2018-12-13 00:13:47 +05:30
ValD b271957b4c added not preload check so hidden toggles asap 2018-12-13 00:11:01 +05:30
ValD 33b962b13e removed counters from left panel 2018-12-12 23:56:12 +05:30
ValD 7556efa04f added router-links to all relavent links 2018-12-12 23:34:22 +05:30
ValD 1623dcb417 added activatePanel onclick for timeago button 2018-12-12 23:34:22 +05:30
ValD 7c6c2cfb22 added PR comments 2018-12-12 23:29:13 +05:30
Rinpatch fa7fbe05de Write a unit test for fileSizeFormatService 2018-12-12 20:41:12 +03:00
Egor Kislitsyn 02c0e15781 add checkbox to disable web push 2018-12-13 00:03:50 +07:00
Rinpatch 9c24ac1d05 I am dumb 2018-12-12 20:01:37 +03:00
Rinpatch 5ca2e75df3 Handle errors from server 2018-12-12 19:31:16 +03:00
ValD 6d3bd95bfe removed brackets from condition 2018-12-12 15:07:07 +00:00
Rinpatch bf8bb9ce13 Moved upload errors in user_settings to an array. Moved upload error strings to its separate section in i18n 2018-12-12 16:38:01 +03:00
ValD de5d846ebd resolved lint issue 2018-12-12 03:44:45 +05:30
ValD 139659d42c renamed config to preload images and add ident to config 2018-12-12 03:42:29 +05:30
ValD 7b4e08dd93 added config for preload and made attachment responsive to it 2018-12-12 03:33:53 +05:30
ValD b195ce12e1 preload nsfw image 2018-12-12 02:28:36 +05:30
Henry Jameson c54eb1ecad fix 2018-12-11 19:01:08 +03:00
Henry Jameson 4eb075fae7 whoopsies 2018-12-11 18:57:24 +03:00
Henry Jameson b2d3b7e708 fix 2018-12-11 18:55:47 +03:00
Henry Jameson b839ba7870 Quality of Frontend Developer's Life: here to stay 2018-12-11 18:45:25 +03:00
Rinpatch 25a04f2294 Avatar, background, banner filesize errors 2018-12-11 16:02:35 +03:00
Egor Kislitsyn ee70ec4c7e fix race condition 2018-12-10 22:36:25 +07:00
Rinpatch 6a00854189 Count in binary bytes and remove i18 from file size format service 2018-12-10 17:06:32 +03:00
Rinpatch 88145c5934 Add a space between filesizes 2018-12-10 10:04:42 +03:00
Rinpatch 5c7a316df9 Lint 2018-12-10 09:56:07 +03:00
Rinpatch c69a8dc197 Add file size formating 2018-12-10 09:50:04 +03:00
Maxim Filippov ae8f0f36d8 Use "~" as a route namespace symbol 2018-12-10 01:21:52 +03:00
Egor Kislitsyn 73b17d70ec improve push notifications code 2018-12-09 19:25:43 +07:00
rinpatch 4fde987e34 Fix formating 2018-12-08 22:39:58 +01:00
rinpatch f69331e49d Improve error messages 2018-12-08 22:36:54 +01:00
rinpatch 788383d8a1 Make uploadlimit an object that stores upload limits for avatars, banners, backgrounds, general content 2018-12-08 21:56:00 +01:00
Rinpatch ba188eddab [pleroma#36] Add upload errors 2018-12-08 18:23:21 +03:00
Egor Kislitsyn 11716a7a53 second attempt to add subscribe module and fix race condition 2018-12-07 20:13:36 +07:00
Egor Kislitsyn a85d128d37 Revert "add subscribe module and fix race condition"
This reverts commit 07f1b8523e.
2018-12-07 18:53:40 +07:00
Egor Kislitsyn 07f1b8523e add subscribe module and fix race condition 2018-12-07 18:13:04 +07:00
Egor Kislitsyn 264da19f69 fix typo 2018-12-07 15:21:19 +07:00
Egor Kislitsyn bbae2e10f3 Add configuration to enable/disable web push notifications 2018-12-07 15:15:31 +07:00
Egor Kislitsyn ebe2a95140 improve web push notifications 2018-12-07 14:57:35 +07:00
Maxim Filippov 3d968e31da Disable dot rule 2018-12-06 22:10:46 +03:00
Maxim Filippov c1dc69a038 Pass userName instead of userId 2018-12-06 22:10:46 +03:00
Maxim Filippov e576f8cdad Typo in tests 2018-12-06 22:10:46 +03:00
Maxim Filippov 7d5794b9fa Fix redirect paths 2018-12-06 22:10:46 +03:00
Maxim Filippov 54c6438b17 Fix typo 2018-12-06 22:09:54 +03:00
Maxim Filippov eb4cd64152 Fix avatar styles 2018-12-06 22:09:54 +03:00
Maxim Filippov 6532462b95 Move old routes to /p, use /nickname for user profiles 2018-12-06 22:09:54 +03:00
Maxim Filippov c3c75e0702 Remove dummy component 2018-12-06 22:09:54 +03:00
Maxim Filippov 79d864c3f2 Move routes to the separate file -> make it testable 2018-12-06 22:09:54 +03:00
Egor Kislitsyn 09147cacea add service worker and push notifications 2018-12-06 20:34:00 +07:00
Henry Jameson 403c86e4d1 back button for mobile 2018-12-05 15:01:56 +03:00
Henry Jameson ca19025187 Added support for async following including delayed confirmation if we followed
user or not
2018-12-04 12:50:29 +03:00
Henry Jameson 8b1e1b182a throttle fetching old statuses to prevent spam, especially during scroll 2018-12-04 11:04:46 +03:00
Henry Jameson 7a13c530c7 Merge remote-tracking branch 'upstream/develop' into search-mobile-fixes
* upstream/develop:
  addressed PR comments
  added tooltip
  Add userId property to timelines so that we don't overwrite user timeline meant for another user
  Added option to auto-hide subject field when it's empty.
  removes hacks from notifications storage, adds api call to let server update is_seen attribute
  fixes vimium not giving retweet button a hint
2018-12-04 09:56:45 +03:00
Henry Jameson 6b3489a4d3 search button for user finder 2018-12-03 08:03:11 +03:00
Henry Jameson ea805bbbe6 hide logo when opening search bar on small screens 2018-12-03 07:49:14 +03:00
Vivian Lim 3193c58cc2 add source link 2018-06-23 18:59:24 -07:00
Vivian Lim cd5b252858 instance-specific panel 2018-06-23 18:57:45 -07:00
Vivian Lim 194edeea7e branding 2018-06-23 18:31:20 -07:00
Vivian Lim 00a52b0570 string changes & toggle on post visibility 2018-06-23 18:28:48 -07:00
Astra 9d3f888d5b prevent clobbering privacy level in replies 2018-06-08 20:32:20 -04:00
William Pitcock f4ee222e3c make nsfw censor image configurable 2018-04-22 09:10:10 -05:00
227 changed files with 17381 additions and 3670 deletions

View File

@ -11,7 +11,7 @@ module.exports = {
'html'
],
// add your custom rules here
'rules': {
rules: {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ test/unit/coverage
test/e2e/reports
selenium-debug.log
.idea/
config/local.json

10
BREAKING_CHANGES.md Normal file
View File

@ -0,0 +1,10 @@
# v1.0
## Removed features/radically changed behavior
### minimalScopesMode
As of !633, `scopeOptions` is no longer available and instead is changed for `minimalScopesMode` (default: `false`)
Reasoning is that scopeOptions option originally existed mostly as a backwards-compatibility with GNU Social which only had `public` scope available and using scope selector would''t work. Since at some point we dropped GNU Social support, this option was mostly a nuisance (being default `false`'), however some people think scopes are an annoyance to a certain degree and want as less of that feature as possible.
Solution - to only show minimal set among: *Direct*, *User default* and *Scope of post replying to*. This also makes it impossible to reply to a DM with a non-DM post from UI.
*This setting is admin-default, user-configurable. Admin can choose different default for their instance but user can override it.*

View File

@ -6,11 +6,12 @@
# For Translators
To translate Pleroma, add your language to [src/i18n/messages.js](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/i18n/messages.js). Pleroma will set your language by your browser locale, but you can temporarily force it in the code by changing the locale in main.js.
To translate Pleroma-FE, add your language to [src/i18n/messages.js](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/src/i18n/messages.js). Pleroma-FE will set your language by your browser locale, but you can temporarily force it in the code by changing the locale in main.js.
# FOR ADMINS
You don't need to build Pleroma yourself. Check out https://git.pleroma.social/pleroma/pleroma-fe/wikis/dual-boot-with-qvitter to see how to run Pleroma and Qvitter at the same time.
You don't need to build Pleroma-FE yourself. Those using the Pleroma backend will be able to use it out of the box.
For the GNU social backend, check out https://git.pleroma.social/pleroma/pleroma-fe/wikis/dual-boot-with-qvitter to see how to run Pleroma-FE and Qvitter at the same time.
## Build Setup
@ -29,9 +30,18 @@ npm run build
npm run unit
```
# For Contributors:
You can create file `/config/local.json` (see [example](https://git.pleroma.social/pleroma/pleroma-fe/blob/develop/config/local.example.json)) to enable some convenience dev options:
* `target`: makes local dev server redirect to some existing instance's BE instead of local BE, useful for testing things in near-production environment and searching for real-life use-cases.
* `staticConfigPreference`: makes FE's `/static/config.json` take preference of BE-served `/api/statusnet/config.json`. Only works in dev mode.
FE Build process also leaves current commit hash in global variable `___pleromafe_commit_hash` so that you can easily see which pleroma-fe commit instance is running, also helps pinpointing which commit was used when FE was bundled into BE.
# Configuration
Edit config.json for configuration. scopeOptionsEnabled gives you input fields for CWs and the scope settings.
Edit config.json for configuration.
## Options

View File

@ -2,6 +2,7 @@ var path = require('path')
var config = require('../config')
var utils = require('./utils')
var projectRoot = path.resolve(__dirname, '../')
var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin')
var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the
@ -91,5 +92,11 @@ module.exports = {
browsers: ['last 2 versions']
})
]
}
},
plugins: [
new ServiceWorkerWebpackPlugin({
entry: path.join(__dirname, '..', 'src/sw.js'),
filename: 'sw-pleroma.js'
})
]
}

View File

@ -18,7 +18,9 @@ module.exports = merge(baseWebpackConfig, {
devtool: '#eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
'process.env': config.dev.env,
'COMMIT_HASH': JSON.stringify('DEV'),
'DEV_OVERRIDES': JSON.stringify(config.dev.settings)
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.optimize.OccurenceOrderPlugin(),

View File

@ -7,8 +7,13 @@ var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: config.build.env
? require('../config/test.env')
: config.build.env
let commitHash = require('child_process')
.execSync('git rev-parse --short HEAD')
.toString();
console.log(commitHash)
var webpackConfig = merge(baseWebpackConfig, {
module: {
@ -29,7 +34,9 @@ var webpackConfig = merge(baseWebpackConfig, {
plugins: [
// http://vuejs.github.io/vue-loader/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
'process.env': env,
'COMMIT_HASH': JSON.stringify(commitHash),
'DEV_OVERRIDES': JSON.stringify(undefined)
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
@ -51,7 +58,8 @@ var webpackConfig = merge(baseWebpackConfig, {
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
removeAttributeQuotes: true,
ignoreCustomComments: [/server-generated-meta/]
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},

View File

@ -1,5 +1,15 @@
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
const path = require('path')
let settings = {}
try {
settings = require('./local.json')
console.log('Using local dev server settings (/config/local.json):')
console.log(JSON.stringify(settings, null, 2))
} catch (e) {
console.log('Local dev server settings not found (/config/local.json)')
}
const target = settings.target || 'http://localhost:4000/'
module.exports = {
build: {
@ -19,21 +29,22 @@ module.exports = {
dev: {
env: require('./dev.env'),
port: 8080,
settings,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://localhost:4000/',
target,
changeOrigin: true,
cookieDomainRewrite: 'localhost'
},
'/nodeinfo': {
target: 'http://localhost:4000/',
target,
changeOrigin: true,
cookieDomainRewrite: 'localhost'
},
'/socket': {
target: 'http://localhost:4000/',
target,
changeOrigin: true,
cookieDomainRewrite: 'localhost',
ws: true

View File

@ -0,0 +1,4 @@
{
"target": "https://pleroma.soykaf.com/",
"staticConfigPreference": false
}

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pleroma</title>
<!--server-generated-meta-->
<link rel="icon" type="image/png" href="/favicon.png">
<link rel="stylesheet" href="/static/font/css/fontello.css">
<link rel="stylesheet" href="/static/font/css/animation.css">

View File

@ -17,17 +17,21 @@
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-lodash": "^3.2.11",
"chromatism": "^3.0.0",
"cropperjs": "^1.4.3",
"diff": "^3.0.1",
"karma-mocha-reporter": "^2.2.1",
"localforage": "^1.5.0",
"node-sass": "^3.10.1",
"object-path": "^0.11.3",
"phoenix": "^1.3.0",
"popper.js": "^1.14.7",
"sanitize-html": "^1.13.0",
"sass-loader": "^4.0.2",
"v-click-outside": "^2.1.1",
"vue": "^2.5.13",
"vue-chat-scroll": "^1.2.1",
"vue-i18n": "^7.3.2",
"vue-popperjs": "^2.0.3",
"vue-router": "^3.0.1",
"vue-template-compiler": "^2.3.4",
"vue-timeago": "^3.1.2",
@ -36,6 +40,8 @@
"whatwg-fetch": "^2.0.3"
},
"devDependencies": {
"@babel/polyfill": "^7.0.0",
"@vue/test-utils": "^1.0.0-beta.26",
"autoprefixer": "^6.4.0",
"babel-core": "^6.0.0",
"babel-eslint": "^7.0.0",
@ -90,6 +96,7 @@
"raw-loader": "^0.5.1",
"selenium-server": "2.53.1",
"semver": "^5.3.0",
"serviceworker-webpack-plugin": "0.2.3",
"shelljs": "^0.7.4",
"sinon": "^1.17.3",
"sinon-chai": "^2.8.0",

View File

@ -6,6 +6,11 @@ import InstanceSpecificPanel from './components/instance_specific_panel/instance
import FeaturesPanel from './components/features_panel/features_panel.vue'
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
import ChatPanel from './components/chat_panel/chat_panel.vue'
import MediaModal from './components/media_modal/media_modal.vue'
import SideDrawer from './components/side_drawer/side_drawer.vue'
import MobilePostStatusModal from './components/mobile_post_status_modal/mobile_post_status_modal.vue'
import MobileNav from './components/mobile_nav/mobile_nav.vue'
import { windowWidth } from './services/window_utils/window_utils'
export default {
name: 'app',
@ -17,10 +22,15 @@ export default {
InstanceSpecificPanel,
FeaturesPanel,
WhoToFollowPanel,
ChatPanel
ChatPanel,
MediaModal,
SideDrawer,
MobilePostStatusModal,
MobileNav
},
data: () => ({
mobileActivePanel: 'timeline',
finderHidden: true,
supportsMask: window.CSS && window.CSS.supports && (
window.CSS.supports('mask-size', 'contain') ||
window.CSS.supports('-webkit-mask-size', 'contain') ||
@ -32,6 +42,10 @@ export default {
created () {
// Load the locale from the storage
this.$i18n.locale = this.$store.state.config.interfaceLanguage
window.addEventListener('resize', this.updateMobileState)
},
destroyed () {
window.removeEventListener('resize', this.updateMobileState)
},
computed: {
currentUser () { return this.$store.state.users.currentUser },
@ -53,33 +67,47 @@ export default {
},
logoBgStyle () {
return Object.assign({
'margin': `${this.$store.state.instance.logoMargin} 0`
'margin': `${this.$store.state.instance.logoMargin} 0`,
opacity: this.finderHidden ? 1 : 0
}, this.enableMask ? {} : {
'background-color': this.enableMask ? '' : 'transparent'
})
},
logo () { return this.$store.state.instance.logo },
style () {
bgStyle () {
return {
'--body-background-image': `url(${this.background})`,
'background-image': `url(${this.background})`
}
},
bgAppStyle () {
return {
'--body-background-image': `url(${this.background})`
}
},
sitename () { return this.$store.state.instance.name },
chat () { return this.$store.state.chat.channel.state === 'joined' },
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
showInstanceSpecificPanel () { return this.$store.state.instance.showInstanceSpecificPanel }
showInstanceSpecificPanel () { return this.$store.state.instance.showInstanceSpecificPanel },
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
isMobileLayout () { return this.$store.state.interface.mobileLayout }
},
methods: {
activatePanel (panelName) {
this.mobileActivePanel = panelName
},
scrollToTop () {
window.scrollTo(0, 0)
},
logout () {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
},
onFinderToggled (hidden) {
this.finderHidden = hidden
},
updateMobileState () {
const mobileLayout = windowWidth() <= 800
const changed = mobileLayout !== this.isMobileLayout
if (changed) {
this.$store.dispatch('setMobileLayout', mobileLayout)
}
}
}
}

View File

@ -6,6 +6,16 @@
overflow: hidden;
}
.app-bg-wrapper {
position: fixed;
z-index: -1;
height: 100%;
width: 100%;
background-size: cover;
background-repeat: no-repeat;
background-position: 0 50%;
}
i {
user-select: none;
}
@ -91,6 +101,14 @@ button {
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg)
}
&.danger {
// TODO: add better color variable
color: $fallback--text;
color: var(--alertErrorPanelText, $fallback--text);
background-color: $fallback--alertError;
background-color: var(--alertError, $fallback--alertError);
}
}
label.select {
@ -144,7 +162,7 @@ input, textarea, .select {
background: transparent;
border: none;
color: $fallback--text;
color: var(--text, $fallback--text);
color: var(--inputText, --text, $fallback--text);
margin: 0;
padding: 0 2em 0 .2em;
font-family: sans-serif;
@ -171,8 +189,7 @@ input, textarea, .select {
color: $fallback--text;
color: var(--text, $fallback--text);
}
&:disabled,
{
&:disabled {
&,
& + label,
& + label::before {
@ -224,31 +241,29 @@ i[class*=icon-] {
padding: 0 10px 0 10px;
}
.gaps {
margin: -1em 0 0 -1em;
}
.item {
flex: 1;
line-height: 50px;
height: 50px;
overflow: hidden;
display: flex;
flex-wrap: wrap;
.nav-icon {
font-size: 1.1em;
margin-left: 0.4em;
}
}
.gaps > .item {
padding: 1em 0 0 1em;
&.right {
justify-content: flex-end;
}
}
.auto-size {
flex: 1
}
nav {
.nav-bar {
padding: 0;
width: 100%;
align-items: center;
position: fixed;
@ -266,6 +281,9 @@ nav {
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;
@ -289,12 +307,13 @@ nav {
}
.inner-nav {
padding-left: 20px;
padding-right: 20px;
margin: auto;
box-sizing: border-box;
padding-left: 10px;
padding-right: 10px;
display: flex;
align-items: center;
flex-basis: 970px;
margin: auto;
height: 50px;
a, a i {
@ -419,6 +438,12 @@ main-router {
border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
.faint {
color: $fallback--faint;
color: var(--panelFaint, $fallback--faint);
}
a {
color: $fallback--link;
color: var(--panelLink, $fallback--link)
@ -448,6 +473,23 @@ nav {
color: var(--faint, $fallback--faint);
box-shadow: 0px 0px 4px rgba(0,0,0,.6);
box-shadow: var(--topBarShadow);
.back-button {
display: block;
max-width: 99px;
transition-property: opacity, max-width;
transition-duration: 300ms;
transition-timing-function: ease-out;
i {
margin: 0 1em;
}
&.hidden {
opacity: 0;
max-width: 5px;
}
}
}
.fade-enter-active, .fade-leave-active {
@ -458,7 +500,7 @@ nav {
}
.main {
flex-basis: 60%;
flex-basis: 50%;
flex-grow: 1;
flex-shrink: 1;
}
@ -478,23 +520,17 @@ nav {
display: none;
}
.panel-switcher {
display: none;
width: 100%;
height: 46px;
button {
display: block;
flex: 1;
max-height: 32px;
margin: 0.5em;
padding: 0.5em;
}
}
@media all and (min-width: 960px) {
@media all and (min-width: 800px) {
body {
overflow-y: scroll;
}
nav {
.back-button {
display: none;
}
}
.sidebar-bounds {
overflow: hidden;
max-height: 100vh;
@ -569,27 +605,23 @@ nav {
color: var(--faint, $fallback--faint);
}
@media all and (max-width: 959px) {
.mobile-hidden {
display: none;
}
.faint-link {
color: $fallback--faint;
color: var(--faint, $fallback--faint);
.panel-switcher {
display: flex;
&:hover {
text-decoration: underline;
}
}
.container {
padding: 0 0 0 0;
}
.panel {
margin: 0.5em 0 0.5em 0;
@media all and (min-width: 800px) {
.logo {
opacity: 1 !important;
}
}
.item.right {
text-align: right;
padding-right: 20px;
}
.visibility-tray {
@ -602,10 +634,6 @@ nav {
color: var(--lightText, $fallback--lightText);
}
.text-format {
float: right;
}
div {
padding-top: 5px;
}
@ -618,3 +646,151 @@ nav {
border-radius: $fallback--inputRadius;
border-radius: var(--inputRadius, $fallback--inputRadius);
}
@keyframes modal-background-fadein {
from {
background-color: rgba(0, 0, 0, 0);
}
to {
background-color: rgba(0, 0, 0, 0.5);
}
}
.modal-view {
z-index: 1000;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
animation-duration: 0.2s;
background-color: rgba(0, 0, 0, 0.5);
animation-name: modal-background-fadein;
}
.button-icon {
font-size: 1.2em;
}
@keyframes shakeError {
0% {
transform: translateX(0);
}
15% {
transform: translateX(0.375rem);
}
30% {
transform: translateX(-0.375rem);
}
45% {
transform: translateX(0.375rem);
}
60% {
transform: translateX(-0.375rem);
}
75% {
transform: translateX(0.375rem);
}
90% {
transform: translateX(-0.375rem);
}
100% {
transform: translateX(0);
}
}
@media all and (max-width: 800px) {
.mobile-hidden {
display: none;
}
.panel-switcher {
display: flex;
}
.container {
padding: 0;
}
.panel {
margin: 0.5em 0 0.5em 0;
}
.menu-button {
display: block;
margin-right: 0.8em;
}
}
.login-hint {
text-align: center;
@media all and (min-width: 801px) {
display: none;
}
a {
display: inline-block;
padding: 1em 0px;
width: 100%;
}
}
.btn.btn-default {
min-height: 28px;
}
.autocomplete {
&-panel {
position: relative;
&-body {
margin: 0 0.5em 0 0.5em;
border-radius: $fallback--tooltipRadius;
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
position: absolute;
z-index: 1;
box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
// this doesn't match original but i don't care, making it uniform.
box-shadow: var(--popupShadow);
min-width: 75%;
background: $fallback--bg;
background: var(--bg, $fallback--bg);
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
}
}
&-item {
cursor: pointer;
padding: 0.2em 0.4em 0.2em 0.4em;
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
display: flex;
img {
width: 24px;
height: 24px;
object-fit: contain;
}
span {
line-height: 24px;
margin: 0 0.1em 0 0.2em;
}
small {
margin-left: .5em;
color: $fallback--faint;
color: var(--faint, $fallback--faint);
}
&.highlighted {
background-color: $fallback--fg;
background-color: var(--lightBg, $fallback--fg);
}
}
}

View File

@ -1,47 +1,51 @@
<template>
<div id="app" v-bind:style="style">
<nav class='container' @click="scrollToTop()" id="nav">
<div id="app" v-bind:style="bgAppStyle">
<div class="app-bg-wrapper" v-bind:style="bgStyle"></div>
<MobileNav v-if="isMobileLayout" />
<nav v-else class='nav-bar container' @click="scrollToTop()" id="nav">
<div class='logo' :style='logoBgStyle'>
<div class='mask' :style='logoMaskStyle'></div>
<img :src='logo' :style='logoStyle'>
</div>
<div class='inner-nav'>
<div class='item'>
<router-link :to="{ name: 'root'}">{{sitename}}</router-link>
<router-link class="site-name" :to="{ name: 'root' }" active-class="home">{{sitename}}</router-link>
</div>
<div class='item right'>
<user-finder class="nav-icon"></user-finder>
<router-link @click.native="activatePanel('timeline')" :to="{ name: 'settings'}"><i class="icon-cog nav-icon" :title="$t('nav.preferences')"></i></router-link>
<a href="#" v-if="currentUser" @click.prevent="logout"><i class="icon-logout nav-icon" :title="$t('login.logout')"></i></a>
<user-finder class="button-icon nav-icon mobile-hidden" @toggled="onFinderToggled"></user-finder>
<router-link class="mobile-hidden" :to="{ name: 'settings'}"><i class="button-icon icon-cog nav-icon" :title="$t('nav.preferences')"></i></router-link>
<a href="#" class="mobile-hidden" v-if="currentUser" @click.prevent="logout"><i class="button-icon icon-logout nav-icon" :title="$t('login.logout')"></i></a>
</div>
</div>
</nav>
<div class="container" id="content">
<div class="panel-switcher">
<button @click="activatePanel('sidebar')">Sidebar</button>
<button @click="activatePanel('timeline')">Timeline</button>
</div>
<div class="sidebar-flexer" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar'}">
<div v-if="" class="container" id="content">
<div class="sidebar-flexer mobile-hidden" v-if="!isMobileLayout">
<div class="sidebar-bounds">
<div class="sidebar-scroller">
<div class="sidebar">
<user-panel :activatePanel="activatePanel"></user-panel>
<nav-panel :activatePanel="activatePanel"></nav-panel>
<user-panel></user-panel>
<nav-panel></nav-panel>
<instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel>
<features-panel v-if="!currentUser"></features-panel>
<features-panel v-if="!currentUser && showFeaturesPanel"></features-panel>
<who-to-follow-panel v-if="currentUser && suggestionsEnabled"></who-to-follow-panel>
<notifications v-if="currentUser"></notifications>
</div>
</div>
</div>
</div>
<div class="main" :class="{ 'mobile-hidden': mobileActivePanel != 'timeline' }">
<div class="main">
<div v-if="!currentUser" class="login-hint panel panel-default">
<router-link :to="{ name: 'login' }" class="panel-body">
{{ $t("login.hint") }}
</router-link>
</div>
<transition name="fade">
<router-view></router-view>
</transition>
</div>
<media-modal></media-modal>
</div>
<chat-panel v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel>
<chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel>
</div>
</template>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -1,175 +1,198 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
import App from '../App.vue'
import PublicTimeline from '../components/public_timeline/public_timeline.vue'
import PublicAndExternalTimeline from '../components/public_and_external_timeline/public_and_external_timeline.vue'
import FriendsTimeline from '../components/friends_timeline/friends_timeline.vue'
import TagTimeline from '../components/tag_timeline/tag_timeline.vue'
import ConversationPage from '../components/conversation-page/conversation-page.vue'
import Mentions from '../components/mentions/mentions.vue'
import DMs from '../components/dm_timeline/dm_timeline.vue'
import UserProfile from '../components/user_profile/user_profile.vue'
import Settings from '../components/settings/settings.vue'
import Registration from '../components/registration/registration.vue'
import UserSettings from '../components/user_settings/user_settings.vue'
import FollowRequests from '../components/follow_requests/follow_requests.vue'
import OAuthCallback from '../components/oauth_callback/oauth_callback.vue'
import UserSearch from '../components/user_search/user_search.vue'
import { windowWidth } from '../services/window_utils/window_utils'
const afterStoreSetup = ({store, i18n}) => {
window.fetch('/api/statusnet/config.json')
.then((res) => res.json())
.then((data) => {
const {name, closed: registrationClosed, textlimit, server} = data.site
const getStatusnetConfig = async ({ store }) => {
try {
const res = await window.fetch('/api/statusnet/config.json')
if (res.ok) {
const data = await res.json()
const { name, closed: registrationClosed, textlimit, uploadlimit, server, vapidPublicKey, safeDMMentionsEnabled } = data.site
store.dispatch('setInstanceOption', { name: 'name', value: name })
store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) })
store.dispatch('setInstanceOption', { name: 'server', value: server })
store.dispatch('setInstanceOption', { name: 'safeDM', value: safeDMMentionsEnabled !== '0' })
var apiConfig = data.site.pleromafe
// TODO: default values for this stuff, added if to not make it break on
// my dev config out of the box.
if (uploadlimit) {
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit.uploadlimit) })
store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadlimit.avatarlimit) })
store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadlimit.backgroundlimit) })
store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadlimit.bannerlimit) })
}
window.fetch('/static/config.json')
.then((res) => res.json())
.catch((err) => {
console.warn('Failed to load static/config.json, continuing without it.')
console.warn(err)
return {}
})
.then((staticConfig) => {
// This takes static config and overrides properties that are present in apiConfig
var config = Object.assign({}, staticConfig, apiConfig)
if (vapidPublicKey) {
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
}
var theme = (config.theme)
var background = (config.background)
var hidePostStats = (config.hidePostStats)
var hideUserStats = (config.hideUserStats)
var logo = (config.logo)
var logoMask = (typeof config.logoMask === 'undefined' ? true : config.logoMask)
var logoMargin = (typeof config.logoMargin === 'undefined' ? 0 : config.logoMargin)
var redirectRootNoLogin = (config.redirectRootNoLogin)
var redirectRootLogin = (config.redirectRootLogin)
var chatDisabled = (config.chatDisabled)
var showInstanceSpecificPanel = (config.showInstanceSpecificPanel)
var scopeOptionsEnabled = (config.scopeOptionsEnabled)
var formattingOptionsEnabled = (config.formattingOptionsEnabled)
var collapseMessageWithSubject = (config.collapseMessageWithSubject)
var loginMethod = (config.loginMethod)
var scopeCopy = (config.scopeCopy)
var subjectLineBehavior = (config.subjectLineBehavior)
var alwaysShowSubjectInput = (config.alwaysShowSubjectInput)
return data.site.pleromafe
} else {
throw (res)
}
} catch (error) {
console.error('Could not load statusnet config, potentially fatal')
console.error(error)
}
}
store.dispatch('setInstanceOption', { name: 'theme', value: theme })
store.dispatch('setInstanceOption', { name: 'background', value: background })
store.dispatch('setInstanceOption', { name: 'hidePostStats', value: hidePostStats })
store.dispatch('setInstanceOption', { name: 'hideUserStats', value: hideUserStats })
store.dispatch('setInstanceOption', { name: 'logo', value: logo })
store.dispatch('setInstanceOption', { name: 'logoMask', value: logoMask })
store.dispatch('setInstanceOption', { name: 'logoMargin', value: logoMargin })
store.dispatch('setInstanceOption', { name: 'redirectRootNoLogin', value: redirectRootNoLogin })
store.dispatch('setInstanceOption', { name: 'redirectRootLogin', value: redirectRootLogin })
store.dispatch('setInstanceOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel })
store.dispatch('setInstanceOption', { name: 'scopeOptionsEnabled', value: scopeOptionsEnabled })
store.dispatch('setInstanceOption', { name: 'formattingOptionsEnabled', value: formattingOptionsEnabled })
store.dispatch('setInstanceOption', { name: 'collapseMessageWithSubject', value: collapseMessageWithSubject })
store.dispatch('setInstanceOption', { name: 'loginMethod', value: loginMethod })
store.dispatch('setInstanceOption', { name: 'scopeCopy', value: scopeCopy })
store.dispatch('setInstanceOption', { name: 'subjectLineBehavior', value: subjectLineBehavior })
store.dispatch('setInstanceOption', { name: 'alwaysShowSubjectInput', value: alwaysShowSubjectInput })
if (chatDisabled) {
store.dispatch('disableChat')
}
const getStaticConfig = async () => {
try {
const res = await window.fetch('/static/config.json')
if (res.ok) {
return res.json()
} else {
throw (res)
}
} catch (error) {
console.warn('Failed to load static/config.json, continuing without it.')
console.warn(error)
return {}
}
}
const routes = [
{ name: 'root',
path: '/',
redirect: to => {
return (store.state.users.currentUser
? store.state.instance.redirectRootLogin
: store.state.instance.redirectRootNoLogin) || '/main/all'
}},
{ path: '/main/all', component: PublicAndExternalTimeline },
{ path: '/main/public', component: PublicTimeline },
{ path: '/main/friends', component: FriendsTimeline },
{ path: '/tag/:tag', component: TagTimeline },
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
{ name: 'user-profile', path: '/users/:id', component: UserProfile },
{ name: 'mentions', path: '/:username/mentions', component: Mentions },
{ name: 'dms', path: '/:username/dms', component: DMs },
{ name: 'settings', path: '/settings', component: Settings },
{ name: 'registration', path: '/registration', component: Registration },
{ name: 'registration', path: '/registration/:token', component: Registration },
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests },
{ name: 'user-settings', path: '/user-settings', component: UserSettings },
{ name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) },
{ name: 'user-search', path: '/user-search', component: UserSearch, props: (route) => ({ query: route.query.query }) }
]
const setSettings = async ({ apiConfig, staticConfig, store }) => {
const overrides = window.___pleromafe_dev_overrides || {}
const env = window.___pleromafe_mode.NODE_ENV
const router = new VueRouter({
mode: 'history',
routes,
scrollBehavior: (to, from, savedPosition) => {
if (to.matched.some(m => m.meta.dontScroll)) {
return false
}
return savedPosition || { x: 0, y: 0 }
}
})
// This takes static config and overrides properties that are present in apiConfig
let config = {}
if (overrides.staticConfigPreference && env === 'development') {
console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG')
config = Object.assign({}, apiConfig, staticConfig)
} else {
config = Object.assign({}, staticConfig, apiConfig)
}
/* eslint-disable no-new */
new Vue({
router,
store,
i18n,
el: '#app',
render: h => h(App)
})
})
})
const copyInstanceOption = (name) => {
store.dispatch('setInstanceOption', { name, value: config[name] })
}
window.fetch('/static/terms-of-service.html')
.then((res) => res.text())
.then((html) => {
copyInstanceOption('nsfwCensorImage')
copyInstanceOption('background')
copyInstanceOption('hidePostStats')
copyInstanceOption('hideUserStats')
copyInstanceOption('hideFilteredStatuses')
copyInstanceOption('logo')
store.dispatch('setInstanceOption', {
name: 'logoMask',
value: typeof config.logoMask === 'undefined'
? true
: config.logoMask
})
store.dispatch('setInstanceOption', {
name: 'logoMargin',
value: typeof config.logoMargin === 'undefined'
? 0
: config.logoMargin
})
copyInstanceOption('redirectRootNoLogin')
copyInstanceOption('redirectRootLogin')
copyInstanceOption('showInstanceSpecificPanel')
copyInstanceOption('minimalScopesMode')
copyInstanceOption('formattingOptionsEnabled')
copyInstanceOption('hideMutedPosts')
copyInstanceOption('collapseMessageWithSubject')
copyInstanceOption('loginMethod')
copyInstanceOption('scopeCopy')
copyInstanceOption('subjectLineBehavior')
copyInstanceOption('postContentType')
copyInstanceOption('alwaysShowSubjectInput')
copyInstanceOption('noAttachmentLinks')
copyInstanceOption('showFeaturesPanel')
if ((config.chatDisabled)) {
store.dispatch('disableChat')
} else {
store.dispatch('initializeSocket')
}
return store.dispatch('setTheme', config['theme'])
}
const getTOS = async ({ store }) => {
try {
const res = await window.fetch('/static/terms-of-service.html')
if (res.ok) {
const html = await res.text()
store.dispatch('setInstanceOption', { name: 'tos', value: html })
})
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load TOS")
console.warn(e)
}
}
window.fetch('/api/pleroma/emoji.json')
.then(
(res) => res.json()
.then(
(values) => {
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: values[key] }
})
store.dispatch('setInstanceOption', { name: 'customEmoji', value: emoji })
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: true })
},
(failure) => {
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: false })
}
),
(error) => console.log(error)
)
const getInstancePanel = async ({ store }) => {
try {
const res = await window.fetch('/instance/panel.html')
if (res.ok) {
const html = await res.text()
store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html })
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load instance panel")
console.warn(e)
}
}
window.fetch('/static/emoji.json')
.then((res) => res.json())
.then((values) => {
const getStaticEmoji = async ({ store }) => {
try {
const res = await window.fetch('/static/emoji.json')
if (res.ok) {
const values = await res.json()
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: false, 'utf': values[key] }
})
store.dispatch('setInstanceOption', { name: 'emoji', value: emoji })
})
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load static emoji")
console.warn(e)
}
}
window.fetch('/instance/panel.html')
.then((res) => res.text())
.then((html) => {
store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html })
})
// This is also used to indicate if we have a 'pleroma backend' or not.
// Somewhat weird, should probably be somewhere else.
const getCustomEmoji = async ({ store }) => {
try {
const res = await window.fetch('/api/pleroma/emoji.json')
if (res.ok) {
const result = await res.json()
const values = Array.isArray(result) ? Object.assign({}, ...result) : result
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: values[key].image_url || values[key] }
})
store.dispatch('setInstanceOption', { name: 'customEmoji', value: emoji })
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: true })
} else {
throw (res)
}
} catch (e) {
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: false })
console.warn("Can't load custom emojis, maybe not a Pleroma instance?")
console.warn(e)
}
}
window.fetch('/nodeinfo/2.0.json')
.then((res) => res.json())
.then((data) => {
const getNodeInfo = async ({ store }) => {
try {
const res = await window.fetch('/nodeinfo/2.0.json')
if (res.ok) {
const data = await res.json()
const metadata = data.metadata
const features = metadata.features
@ -177,10 +200,94 @@ const afterStoreSetup = ({store, i18n}) => {
store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') })
store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') })
store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames })
store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })
const suggestions = metadata.suggestions
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
const software = data.software
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
const frontendVersion = window.___pleromafe_commit_hash
store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
store.dispatch('setInstanceOption', { name: 'tagPolicyAvailable', value: metadata.federation.mrf_policies.includes('TagPolicy') })
} else {
throw (res)
}
} catch (e) {
console.warn('Could not load nodeinfo')
console.warn(e)
}
}
const setConfig = async ({ store }) => {
// apiConfig, staticConfig
const configInfos = await Promise.all([getStatusnetConfig({ store }), getStaticConfig()])
const apiConfig = configInfos[0]
const staticConfig = configInfos[1]
await setSettings({ store, apiConfig, staticConfig })
}
const checkOAuthToken = async ({ store }) => {
return new Promise(async (resolve, reject) => {
if (store.state.oauth.token) {
try {
await store.dispatch('loginUser', store.state.oauth.token)
} catch (e) {
console.log(e)
}
}
resolve()
})
}
const afterStoreSetup = async ({ store, i18n }) => {
if (store.state.config.customTheme) {
// This is a hack to deal with async loading of config.json and themes
// See: style_setter.js, setPreset()
window.themeLoaded = true
store.dispatch('setOption', {
name: 'customTheme',
value: store.state.config.customTheme
})
}
const width = windowWidth()
store.dispatch('setMobileLayout', width <= 800)
// Now we can try getting the server settings and logging in
await Promise.all([
checkOAuthToken({ store }),
setConfig({ store }),
getTOS({ store }),
getInstancePanel({ store }),
getStaticEmoji({ store }),
getCustomEmoji({ store }),
getNodeInfo({ store })
])
const router = new VueRouter({
mode: 'history',
routes: routes(store),
scrollBehavior: (to, _from, savedPosition) => {
if (to.matched.some(m => m.meta.dontScroll)) {
return false
}
return savedPosition || { x: 0, y: 0 }
}
})
/* eslint-disable no-new */
return new Vue({
router,
store,
i18n,
el: '#app',
render: h => h(App)
})
}
export default afterStoreSetup

53
src/boot/routes.js Normal file
View File

@ -0,0 +1,53 @@
import PublicTimeline from 'components/public_timeline/public_timeline.vue'
import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue'
import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue'
import TagTimeline from 'components/tag_timeline/tag_timeline.vue'
import ConversationPage from 'components/conversation-page/conversation-page.vue'
import Mentions from 'components/mentions/mentions.vue'
import DMs from 'components/dm_timeline/dm_timeline.vue'
import UserProfile from 'components/user_profile/user_profile.vue'
import Settings from 'components/settings/settings.vue'
import Registration from 'components/registration/registration.vue'
import UserSettings from 'components/user_settings/user_settings.vue'
import FollowRequests from 'components/follow_requests/follow_requests.vue'
import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
import UserSearch from 'components/user_search/user_search.vue'
import Notifications from 'components/notifications/notifications.vue'
import LoginForm from 'components/login_form/login_form.vue'
import ChatPanel from 'components/chat_panel/chat_panel.vue'
import WhoToFollow from 'components/who_to_follow/who_to_follow.vue'
import About from 'components/about/about.vue'
export default (store) => {
return [
{ name: 'root',
path: '/',
redirect: _to => {
return (store.state.users.currentUser
? store.state.instance.redirectRootLogin
: store.state.instance.redirectRootNoLogin) || '/main/all'
}
},
{ name: 'public-external-timeline', path: '/main/all', component: PublicAndExternalTimeline },
{ name: 'public-timeline', path: '/main/public', component: PublicTimeline },
{ name: 'friends', path: '/main/friends', component: FriendsTimeline },
{ name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline },
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
{ name: 'external-user-profile', path: '/users/:id', component: UserProfile },
{ name: 'mentions', path: '/users/:username/mentions', component: Mentions },
{ name: 'dms', path: '/users/:username/dms', component: DMs },
{ name: 'settings', path: '/settings', component: Settings },
{ name: 'registration', path: '/registration', component: Registration },
{ name: 'registration-token', path: '/registration/:token', component: Registration },
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests },
{ name: 'user-settings', path: '/user-settings', component: UserSettings },
{ name: 'notifications', path: '/:username/notifications', component: Notifications },
{ name: 'login', path: '/login', component: LoginForm },
{ name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) },
{ name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) },
{ name: 'user-search', path: '/user-search', component: UserSearch, props: (route) => ({ query: route.query.query }) },
{ name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow },
{ name: 'about', path: '/about', component: About },
{ name: 'user-profile', path: '/(users/)?:name', component: UserProfile }
]
}

View File

@ -0,0 +1,16 @@
import InstanceSpecificPanel from '../instance_specific_panel/instance_specific_panel.vue'
import FeaturesPanel from '../features_panel/features_panel.vue'
import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
const About = {
components: {
InstanceSpecificPanel,
FeaturesPanel,
TermsOfServicePanel
},
computed: {
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel }
}
}
export default About

View File

@ -0,0 +1,12 @@
<template>
<div class="sidebar">
<instance-specific-panel></instance-specific-panel>
<features-panel v-if="showFeaturesPanel"></features-panel>
<terms-of-service-panel></terms-of-service-panel>
</div>
</template>
<script src="./about.js" ></script>
<style lang="scss">
</style>

View File

@ -1,4 +1,5 @@
import StillImage from '../still-image/still-image.vue'
import VideoAttachment from '../video_attachment/video_attachment.vue'
import nsfwImage from '../../assets/nsfw.png'
import fileTypeService from '../../services/file_type/file_type.service.js'
@ -7,22 +8,32 @@ const Attachment = {
'attachment',
'nsfw',
'statusId',
'size'
'size',
'allowPlay',
'setMedia'
],
data () {
return {
nsfwImage,
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
hideNsfwLocal: this.$store.state.config.hideNsfw,
loopVideo: this.$store.state.config.loopVideo,
showHidden: false,
preloadImage: this.$store.state.config.preloadImage,
loading: false,
img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img')
img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'),
modalOpen: false,
showHidden: false
}
},
components: {
StillImage
StillImage,
VideoAttachment
},
computed: {
usePlaceHolder () {
return this.size === 'hide' || this.type === 'unknown'
},
referrerpolicy () {
return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer'
},
type () {
return fileTypeService.fileType(this.attachment.mimetype)
},
@ -36,7 +47,7 @@ const Attachment = {
return this.size === 'small'
},
fullwidth () {
return fileTypeService.fileType(this.attachment.mimetype) === 'html'
return this.type === 'html' || this.type === 'audio'
}
},
methods: {
@ -45,8 +56,25 @@ const Attachment = {
window.open(target.href, '_blank')
}
},
toggleHidden () {
if (this.img) {
openModal (event) {
const modalTypes = this.$store.state.config.playVideosInModal
? ['image', 'video']
: ['image']
if (fileTypeService.fileMatchesSomeType(modalTypes, this.attachment) ||
this.usePlaceHolder
) {
event.stopPropagation()
event.preventDefault()
this.setMedia()
this.$store.dispatch('setCurrent', this.attachment)
}
},
toggleHidden (event) {
if (this.$store.state.config.useOneClickNsfw && !this.showHidden) {
this.openModal(event)
return
}
if (this.img && !this.preloadImage) {
if (this.img.onload) {
this.img.onload()
} else {
@ -60,23 +88,6 @@ const Attachment = {
} else {
this.showHidden = !this.showHidden
}
},
onVideoDataLoad (e) {
if (typeof e.srcElement.webkitAudioDecodedByteCount !== 'undefined') {
// non-zero if video has audio track
if (e.srcElement.webkitAudioDecodedByteCount > 0) {
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
}
} else if (typeof e.srcElement.mozHasAudio !== 'undefined') {
// true if video has audio track
if (e.srcElement.mozHasAudio) {
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
}
} else if (typeof e.srcElement.audioTracks !== 'undefined') {
if (e.srcElement.audioTracks.length > 0) {
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
}
}
}
}
}

View File

@ -1,20 +1,39 @@
<template>
<div v-if="size==='hide'">
<a class="placeholder" v-if="type !== 'html'" target="_blank" :href="attachment.url">[{{nsfw ? "NSFW/" : ""}}{{type.toUpperCase()}}]</a>
<div v-if="usePlaceHolder" @click="openModal">
<a class="placeholder"
v-if="type !== 'html'"
target="_blank" :href="attachment.url"
>
[{{nsfw ? "NSFW/" : ""}}{{type.toUpperCase()}}]
</a>
</div>
<div v-else class="attachment" :class="{[type]: true, loading, 'small-attachment': isSmall, 'fullwidth': fullwidth, 'nsfw-placeholder': hidden}" v-show="!isEmpty">
<a class="image-attachment-placeholder" v-if="hidden" @click.prevent="toggleHidden()">
<img :key="nsfwImage" :src="nsfwImage"/>
<img class="nsfw" :key="nsfwImage" :src="nsfwImage" :class="{'small': isSmall}"/>
</a>
<div class="hider" v-if="nsfw && hideNsfwLocal && !hidden">
<a href="#" @click.prevent="toggleHidden()">Hide</a>
<a href="#" @click.prevent="toggleHidden">Hide</a>
</div>
<a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank" :title="attachment.description">
<StillImage :class="{'small': isSmall}" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
<a v-if="type === 'image' && (!hidden || preloadImage)"
@click="openModal"
class="image-attachment"
:class="{'hidden': hidden && preloadImage }"
:href="attachment.url" target="_blank"
:title="attachment.description"
>
<StillImage :referrerpolicy="referrerpolicy" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
</a>
<video :class="{'small': isSmall}" v-if="type === 'video' && !hidden" @loadeddata="onVideoDataLoad" :src="attachment.url" controls :loop="loopVideo" playsinline></video>
<a class="video-container"
@click="openModal"
v-if="type === 'video' && !hidden"
:class="{'small': isSmall}"
:href="allowPlay ? undefined : attachment.url"
>
<VideoAttachment class="video" :attachment="attachment" :controls="allowPlay" />
<i v-if="!allowPlay" class="play-icon icon-play-circled"></i>
</a>
<audio v-if="type === 'audio'" :src="attachment.url" controls></audio>
@ -41,12 +60,17 @@
.attachment.media-upload-container {
flex: 0 0 auto;
max-height: 300px;
max-height: 200px;
max-width: 100%;
display: flex;
video {
max-width: 100%;
}
}
.placeholder {
margin-right: 0.5em;
margin-right: 8px;
margin-bottom: 4px;
}
.nsfw-placeholder {
@ -57,17 +81,9 @@
}
}
.small-attachment {
&.image, &.video {
max-width: 35%;
}
max-height: 100px;
}
.attachment {
position: relative;
flex: 1 0 30%;
margin: 0.5em 0.7em 0.6em 0.0em;
margin-top: 0.5em;
align-self: flex-start;
line-height: 0;
@ -79,6 +95,28 @@
border-color: var(--border, $fallback--border);
overflow: hidden;
}
.non-gallery.attachment {
&.video {
flex: 1 0 40%;
}
.nsfw {
height: 260px;
}
.small {
height: 120px;
flex-grow: 0;
}
.video {
height: 260px;
display: flex;
}
video {
max-height: 100%;
object-fit: contain;
}
}
.fullwidth {
flex-basis: 100%;
}
@ -87,6 +125,28 @@
line-height: 0;
}
.video-container {
display: flex;
max-height: 100%;
}
.video {
width: 100%;
}
.play-icon {
position: absolute;
font-size: 64px;
top: calc(50% - 32px);
left: calc(50% - 32px);
color: rgba(255, 255, 255, 0.75);
text-shadow: 0 0 2px rgba(0, 0, 0, 0.4);
}
.play-icon::before {
margin: 0;
}
&.html {
flex-basis: 90%;
width: 100%;
@ -95,6 +155,8 @@
.hider {
position: absolute;
right: 0;
white-space: nowrap;
margin: 10px;
padding: 5px;
background: rgba(230,230,230,0.6);
@ -105,13 +167,7 @@
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
}
.small {
max-height: 100px;
}
video {
max-height: 500px;
height: 100%;
width: 100%;
z-index: 0;
}
@ -121,7 +177,7 @@
img.media-upload {
line-height: 0;
max-height: 300px;
max-height: 200px;
max-width: 100%;
}
@ -158,25 +214,20 @@
}
.image-attachment {
display: flex;
flex: 1;
width: 100%;
height: 100%;
.still-image {
&.hidden {
display: none;
}
.nsfw {
object-fit: cover;
width: 100%;
height: 100%;
}
.small {
img {
max-height: 100px;
}
}
img {
object-fit: contain;
width: 100%;
height: 100%; /* If this isn't here, chrome will stretch the images */
max-height: 500px;
image-orientation: from-image;
}
}

View File

@ -0,0 +1,52 @@
const debounceMilliseconds = 500
export default {
props: {
query: { // function to query results and return a promise
type: Function,
required: true
},
filter: { // function to filter results in real time
type: Function
},
placeholder: {
type: String,
default: 'Search...'
}
},
data () {
return {
term: '',
timeout: null,
results: [],
resultsVisible: false
}
},
computed: {
filtered () {
return this.filter ? this.filter(this.results) : this.results
}
},
watch: {
term (val) {
this.fetchResults(val)
}
},
methods: {
fetchResults (term) {
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.results = []
if (term) {
this.query(term).then((results) => { this.results = results })
}
}, debounceMilliseconds)
},
onInputClick () {
this.resultsVisible = true
},
onClickOutside () {
this.resultsVisible = false
}
}
}

View File

@ -0,0 +1,45 @@
<template>
<div class="autosuggest" v-click-outside="onClickOutside">
<input v-model="term" :placeholder="placeholder" @click="onInputClick" class="autosuggest-input" />
<div class="autosuggest-results" v-if="resultsVisible && filtered.length > 0">
<slot v-for="item in filtered" :item="item" />
</div>
</div>
</template>
<script src="./autosuggest.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.autosuggest {
position: relative;
&-input {
display: block;
width: 100%;
}
&-results {
position: absolute;
left: 0;
top: 100%;
right: 0;
max-height: 400px;
background-color: $fallback--lightBg;
background-color: var(--lightBg, $fallback--lightBg);
border-style: solid;
border-width: 1px;
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
border-radius: $fallback--inputRadius;
border-radius: var(--inputRadius, $fallback--inputRadius);
border-top-left-radius: 0;
border-top-right-radius: 0;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
box-shadow: var(--panelShadow);
overflow-y: auto;
z-index: 1;
}
}
</style>

View File

@ -0,0 +1,28 @@
import UserCard from '../user_card/user_card.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
const BasicUserCard = {
props: [
'user'
],
data () {
return {
userExpanded: false
}
},
components: {
UserCard,
UserAvatar
},
methods: {
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
},
userProfileLink (user) {
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
}
}
}
export default BasicUserCard

View File

@ -0,0 +1,62 @@
<template>
<div class="basic-user-card">
<router-link :to="userProfileLink(user)">
<UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/>
</router-link>
<div class="basic-user-card-expanded-content" v-if="userExpanded">
<UserCard :user="user" :rounded="true" :bordered="true"/>
</div>
<div class="basic-user-card-collapsed-content" v-else>
<div :title="user.name" class="basic-user-card-user-name">
<span v-if="user.name_html" class="basic-user-card-user-name-value" v-html="user.name_html"></span>
<span v-else class="basic-user-card-user-name-value">{{ user.name }}</span>
</div>
<div>
<router-link class="basic-user-card-screen-name" :to="userProfileLink(user)">
@{{user.screen_name}}
</router-link>
</div>
<slot></slot>
</div>
</div>
</template>
<script src="./basic_user_card.js"></script>
<style lang="scss">
.basic-user-card {
display: flex;
flex: 1 0;
margin: 0;
padding: 0.6em 1em;
&-collapsed-content {
margin-left: 0.7em;
text-align: left;
flex: 1;
min-width: 0;
}
&-user-name {
img {
object-fit: contain;
height: 16px;
width: 16px;
vertical-align: middle;
}
&-value {
display: inline-block;
max-width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
&-expanded-content {
flex: 1;
margin-left: 0.7em;
}
}
</style>

View File

@ -0,0 +1,37 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const BlockCard = {
props: ['userId'],
data () {
return {
progress: false
}
},
computed: {
user () {
return this.$store.getters.findUser(this.userId)
},
blocked () {
return this.user.statusnet_blocking
}
},
components: {
BasicUserCard
},
methods: {
unblockUser () {
this.progress = true
this.$store.dispatch('unblockUser', this.user.id).then(() => {
this.progress = false
})
},
blockUser () {
this.progress = true
this.$store.dispatch('blockUser', this.user.id).then(() => {
this.progress = false
})
}
}
}
export default BlockCard

View File

@ -0,0 +1,34 @@
<template>
<basic-user-card :user="user">
<div class="block-card-content-container">
<button class="btn btn-default" @click="unblockUser" :disabled="progress" v-if="blocked">
<template v-if="progress">
{{ $t('user_card.unblock_progress') }}
</template>
<template v-else>
{{ $t('user_card.unblock') }}
</template>
</button>
<button class="btn btn-default" @click="blockUser" :disabled="progress" v-else>
<template v-if="progress">
{{ $t('user_card.block_progress') }}
</template>
<template v-else>
{{ $t('user_card.block') }}
</template>
</button>
</div>
</basic-user-card>
</template>
<script src="./block_card.js"></script>
<style lang="scss">
.block-card-content-container {
margin-top: 0.5em;
text-align: right;
button {
width: 10em;
}
}
</style>

View File

@ -1,4 +1,7 @@
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
const chatPanel = {
props: [ 'floating' ],
data () {
return {
currentMessage: '',
@ -18,6 +21,9 @@ const chatPanel = {
},
togglePanel () {
this.collapsed = !this.collapsed
},
userProfileLink (user) {
return generateProfileLink(user.id, user.username, this.$store.state.instance.restrictedNicknames)
}
}
}

View File

@ -1,10 +1,10 @@
<template>
<div class="chat-panel" v-if="!this.collapsed">
<div class="chat-panel" v-if="!this.collapsed || !this.floating">
<div class="panel panel-default">
<div class="panel-heading timeline-heading chat-heading" @click.stop.prevent="togglePanel">
<div class="panel-heading timeline-heading" :class="{ 'chat-heading': floating }" @click.stop.prevent="togglePanel">
<div class="title">
{{$t('chat.title')}}
<i class="icon-cancel" style="float: right;"></i>
<span>{{$t('chat.title')}}</span>
<i class="icon-cancel" v-if="floating"></i>
</div>
</div>
<div class="chat-window" v-chat-scroll>
@ -13,8 +13,10 @@
<img :src="message.author.avatar" />
</span>
<div class="chat-content">
<router-link class="chat-name" :to="{ name: 'user-profile', params: { id: message.author.id } }">
{{message.author.username}}
<router-link
class="chat-name"
:to="userProfileLink(message.author)">
{{message.author.username}}
</router-link>
<br>
<span class="chat-text">
@ -50,6 +52,7 @@
right: 0px;
bottom: 0px;
z-index: 1000;
max-width: 25em;
}
.chat-heading {
@ -61,13 +64,13 @@
}
.chat-window {
width: 345px;
max-height: 40vh;
overflow-y: auto;
overflow-x: hidden;
max-height: 20em;
}
.chat-name {
.chat-window-container {
height: 100%;
}
.chat-message {
@ -95,4 +98,11 @@
resize: none;
}
}
.chat-panel {
.title {
display: flex;
justify-content: space-between;
}
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<label class="checkbox">
<input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)" :indeterminate.prop="indeterminate">
<i class="checkbox-indicator" />
<span v-if="!!$slots.default"><slot></slot></span>
</label>
</template>
<script>
export default {
model: {
prop: 'checked',
event: 'change'
},
props: ['checked', 'indeterminate']
}
</script>
<style lang="scss">
@import '../../_variables.scss';
.checkbox {
position: relative;
display: inline-block;
padding-left: 1.2em;
min-height: 1.2em;
&-indicator::before {
position: absolute;
left: 0;
top: 0;
display: block;
content: '✔';
transition: color 200ms;
width: 1.1em;
height: 1.1em;
border-radius: $fallback--checkboxRadius;
border-radius: var(--checkboxRadius, $fallback--checkboxRadius);
box-shadow: 0px 0px 2px black inset;
box-shadow: var(--inputShadow);
background-color: $fallback--fg;
background-color: var(--input, $fallback--fg);
vertical-align: top;
text-align: center;
line-height: 1.1em;
font-size: 1.1em;
color: transparent;
overflow: hidden;
box-sizing: border-box;
}
input[type=checkbox] {
display: none;
&:checked + .checkbox-indicator::before {
color: $fallback--text;
color: var(--text, $fallback--text);
}
&:indeterminate + .checkbox-indicator::before {
content: '';
color: $fallback--text;
color: var(--text, $fallback--text);
}
&:disabled + .checkbox-indicator::before {
opacity: .5;
}
}
& > span {
margin-left: .5em;
}
}
</style>

View File

@ -1,5 +1,4 @@
import Conversation from '../conversation/conversation.vue'
import { find, toInteger } from 'lodash'
const conversationPage = {
components: {
@ -7,9 +6,9 @@ const conversationPage = {
},
computed: {
statusoid () {
const id = toInteger(this.$route.params.id)
const statuses = this.$store.state.statuses.allStatuses
const status = find(statuses, {id})
const id = this.$route.params.id
const statuses = this.$store.state.statuses.allStatusesObject
const status = statuses[id]
return status
}

View File

@ -1,5 +1,9 @@
<template>
<conversation :collapsable="false" :statusoid="statusoid"></conversation>
<conversation
:collapsable="false"
isPage="true"
:statusoid="statusoid"
></conversation>
</template>
<script src="./conversation-page.js"></script>

View File

@ -1,38 +1,94 @@
import { reduce, filter, sortBy } from 'lodash'
import { statusType } from '../../modules/statuses.js'
import { reduce, filter, findIndex, clone } from 'lodash'
import Status from '../status/status.vue'
const sortAndFilterConversation = (conversation) => {
conversation = filter(conversation, (status) => statusType(status) !== 'retweet')
return sortBy(conversation, 'id')
const sortById = (a, b) => {
const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id
const idB = b.type === 'retweet' ? b.retweeted_status.id : b.id
const seqA = Number(idA)
const seqB = Number(idB)
const isSeqA = !Number.isNaN(seqA)
const isSeqB = !Number.isNaN(seqB)
if (isSeqA && isSeqB) {
return seqA < seqB ? -1 : 1
} else if (isSeqA && !isSeqB) {
return -1
} else if (!isSeqA && isSeqB) {
return 1
} else {
return idA < idB ? -1 : 1
}
}
const sortAndFilterConversation = (conversation, statusoid) => {
if (statusoid.type === 'retweet') {
conversation = filter(
conversation,
(status) => (status.type === 'retweet' || status.id !== statusoid.retweeted_status.id)
)
} else {
conversation = filter(conversation, (status) => status.type !== 'retweet')
}
return conversation.filter(_ => _).sort(sortById)
}
const conversation = {
data () {
return {
highlight: null
highlight: null,
expanded: false
}
},
props: [
'statusoid',
'collapsable'
'collapsable',
'isPage'
],
created () {
if (this.isPage) {
this.fetchConversation()
}
},
computed: {
status () { return this.statusoid },
status () {
return this.statusoid
},
statusId () {
if (this.statusoid.retweeted_status) {
return this.statusoid.retweeted_status.id
} else {
return this.statusoid.id
}
},
conversationId () {
if (this.statusoid.retweeted_status) {
return this.statusoid.retweeted_status.statusnet_conversation_id
} else {
return this.statusoid.statusnet_conversation_id
}
},
conversation () {
if (!this.status) {
return false
return []
}
const conversationId = this.status.statusnet_conversation_id
const statuses = this.$store.state.statuses.allStatuses
const conversation = filter(statuses, { statusnet_conversation_id: conversationId })
return sortAndFilterConversation(conversation)
if (!this.isExpanded) {
return [this.status]
}
const conversation = clone(this.$store.state.statuses.conversationsObject[this.conversationId])
const statusIndex = findIndex(conversation, { id: this.statusId })
if (statusIndex !== -1) {
conversation[statusIndex] = this.status
}
return sortAndFilterConversation(conversation, this.status)
},
replies () {
let i = 1
return reduce(this.conversation, (result, {id, in_reply_to_status_id}) => {
const irid = Number(in_reply_to_status_id)
/* eslint-disable camelcase */
const irid = in_reply_to_status_id
/* eslint-enable camelcase */
if (irid) {
result[irid] = result[irid] || []
result[irid].push({
@ -43,24 +99,31 @@ const conversation = {
i++
return result
}, {})
},
isExpanded () {
return this.expanded || this.isPage
}
},
components: {
Status
},
created () {
this.fetchConversation()
},
watch: {
'$route': 'fetchConversation'
'$route': 'fetchConversation',
expanded (value) {
if (value) {
this.fetchConversation()
}
}
},
methods: {
fetchConversation () {
if (this.status) {
const conversationId = this.status.statusnet_conversation_id
this.$store.state.api.backendInteractor.fetchConversation({id: conversationId})
.then((statuses) => this.$store.dispatch('addNewStatuses', { statuses }))
.then(() => this.setHighlight(this.statusoid.id))
this.$store.state.api.backendInteractor.fetchConversation({id: this.status.id})
.then(({ancestors, descendants}) => {
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
this.$store.dispatch('addNewStatuses', { statuses: descendants })
})
.then(() => this.setHighlight(this.statusId))
} else {
const id = this.$route.params.id
this.$store.state.api.backendInteractor.fetchStatus({id})
@ -69,18 +132,22 @@ const conversation = {
}
},
getReplies (id) {
id = Number(id)
return this.replies[id] || []
},
focused (id) {
if (this.statusoid.retweeted_status) {
return (id === this.statusoid.retweeted_status.id)
} else {
return (id === this.statusoid.id)
}
return (this.isExpanded) && id === this.status.id
},
setHighlight (id) {
this.highlight = Number(id)
this.highlight = id
},
getHighlight () {
return this.isExpanded ? this.highlight : null
},
toggleExpanded () {
this.expanded = !this.expanded
if (!this.expanded) {
this.setHighlight(null)
}
}
}
}

View File

@ -1,26 +1,42 @@
<template>
<div class="timeline panel panel-default">
<div class="panel-heading conversation-heading">
<div class="timeline panel-default" :class="[isExpanded ? 'panel' : 'panel-disabled']">
<div v-if="isExpanded" class="panel-heading conversation-heading">
<span class="title"> {{ $t('timeline.conversation') }} </span>
<span v-if="collapsable">
<a href="#" @click.prevent="$emit('toggleExpanded')">{{ $t('timeline.collapse') }}</a>
<a href="#" @click.prevent="toggleExpanded">{{ $t('timeline.collapse') }}</a>
</span>
</div>
<div class="panel-body">
<div class="timeline">
<status
v-for="status in conversation"
@goto="setHighlight" :key="status.id"
:inlineExpanded="collapsable" :statusoid="status"
:expandable='false' :focused="focused(status.id)"
:inConversation='true'
:highlight="highlight"
:replies="getReplies(status.id)"
class="status-fadein">
</status>
</div>
</div>
<status
v-for="status in conversation"
@goto="setHighlight"
@toggleExpanded="toggleExpanded"
:key="status.id"
:inlineExpanded="collapsable"
:statusoid="status"
:expandable='!isExpanded'
:focused="focused(status.id)"
:inConversation="isExpanded"
:highlight="getHighlight()"
:replies="getReplies(status.id)"
class="status-fadein panel-body"
/>
</div>
</template>
<script src="./conversation.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.timeline {
.panel-disabled {
.status-el {
border-left: none;
border-bottom-width: 1px;
border-bottom-style: solid;
border-color: var(--border, $fallback--border);
border-radius: 0;
}
}
}
</style>

View File

@ -10,7 +10,11 @@ const DeleteButton = {
},
computed: {
currentUser () { return this.$store.state.users.currentUser },
canDelete () { return this.currentUser && this.currentUser.rights.delete_others_notice || this.status.user.id === this.currentUser.id }
canDelete () {
if (!this.currentUser) { return }
const superuser = this.currentUser.rights.moderator || this.currentUser.rights.admin
return superuser || this.status.user.id === this.currentUser.id
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<div v-if="canDelete">
<a href="#" v-on:click.prevent="deleteStatus()">
<i class='icon-cancel delete-status'></i>
<i class='button-icon icon-cancel delete-status'></i>
</a>
</div>
</template>

View File

@ -0,0 +1,14 @@
const DialogModal = {
props: {
darkOverlay: {
default: true,
type: Boolean
},
onCancel: {
default: () => {},
type: Function
}
}
}
export default DialogModal

View File

@ -0,0 +1,92 @@
<template>
<span v-bind:class="{ 'dark-overlay': darkOverlay }" @click.self.stop='onCancel()'>
<div class="dialog-modal panel panel-default" @click.stop=''>
<div class="panel-heading dialog-modal-heading">
<div class="title">
<slot name="header"></slot>
</div>
</div>
<div class="dialog-modal-content">
<slot name="default"></slot>
</div>
<div class="dialog-modal-footer user-interactions panel-footer">
<slot name="footer"></slot>
</div>
</div>
</span>
</template>
<script src="./dialog_modal.js"></script>
<style lang="scss">
@import '../../_variables.scss';
// TODO: unify with other modals.
.dark-overlay {
&::before {
bottom: 0;
content: " ";
display: block;
cursor: default;
left: 0;
position: fixed;
right: 0;
top: 0;
background: rgba(27,31,35,.5);
z-index: 99;
}
}
.dialog-modal.panel {
top: 0;
left: 50%;
max-height: 80vh;
max-width: 90vw;
margin: 15vh auto;
position: fixed;
transform: translateX(-50%);
z-index: 999;
cursor: default;
display: block;
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg);
.dialog-modal-heading {
padding: .5em .5em;
margin-right: auto;
margin-bottom: 0;
white-space: nowrap;
color: var(--panelText);
background-color: $fallback--fg;
background-color: var(--panel, $fallback--fg);
.title {
margin-bottom: 0;
}
}
.dialog-modal-content {
margin: 0;
padding: 1rem 1rem;
background-color: $fallback--lightBg;
background-color: var(--lightBg, $fallback--lightBg);
white-space: normal;
}
.dialog-modal-footer {
margin: 0;
padding: .5em .5em;
background-color: $fallback--lightBg;
background-color: var(--lightBg, $fallback--lightBg);
border-top: 1px solid $fallback--bg;
border-top: 1px solid var(--bg, $fallback--bg);
justify-content: flex-end;
button {
width: auto;
margin-left: .5rem;
}
}
}
</style>

View File

@ -0,0 +1,107 @@
import Completion from '../../services/completion/completion.js'
import { take, filter, map } from 'lodash'
const EmojiInput = {
props: [
'value',
'placeholder',
'type',
'classname'
],
data () {
return {
highlighted: 0,
caret: 0
}
},
computed: {
suggestions () {
const firstchar = this.textAtCaret.charAt(0)
if (firstchar === ':') {
if (this.textAtCaret === ':') { return }
const matchedEmoji = filter(this.emoji.concat(this.customEmoji), (emoji) => emoji.shortcode.startsWith(this.textAtCaret.slice(1)))
if (matchedEmoji.length <= 0) {
return false
}
return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({
shortcode: `:${shortcode}:`,
utf: utf || '',
// eslint-disable-next-line camelcase
img: utf ? '' : this.$store.state.instance.server + image_url,
highlighted: index === this.highlighted
}))
} else {
return false
}
},
textAtCaret () {
return (this.wordAtCaret || {}).word || ''
},
wordAtCaret () {
const word = Completion.wordAtPosition(this.value, this.caret - 1) || {}
return word
},
emoji () {
return this.$store.state.instance.emoji || []
},
customEmoji () {
return this.$store.state.instance.customEmoji || []
}
},
methods: {
replace (replacement) {
const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement)
this.$emit('input', newValue)
this.caret = 0
},
replaceEmoji (e) {
const len = this.suggestions.length || 0
if (this.textAtCaret === ':' || e.ctrlKey) { return }
if (len > 0) {
e.preventDefault()
const emoji = this.suggestions[this.highlighted]
const replacement = emoji.utf || (emoji.shortcode + ' ')
const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement)
this.$emit('input', newValue)
this.caret = 0
this.highlighted = 0
}
},
cycleBackward (e) {
const len = this.suggestions.length || 0
if (len > 0) {
e.preventDefault()
this.highlighted -= 1
if (this.highlighted < 0) {
this.highlighted = this.suggestions.length - 1
}
} else {
this.highlighted = 0
}
},
cycleForward (e) {
const len = this.suggestions.length || 0
if (len > 0) {
if (e.shiftKey) { return }
e.preventDefault()
this.highlighted += 1
if (this.highlighted >= len) {
this.highlighted = 0
}
} else {
this.highlighted = 0
}
},
onKeydown (e) {
e.stopPropagation()
},
onInput (e) {
this.$emit('input', e.target.value)
},
setCaret ({target: {selectionStart}}) {
this.caret = selectionStart
}
}
}
export default EmojiInput

View File

@ -0,0 +1,64 @@
<template>
<div class="emoji-input">
<input
v-if="type !== 'textarea'"
:class="classname"
:type="type"
:value="value"
:placeholder="placeholder"
@input="onInput"
@click="setCaret"
@keyup="setCaret"
@keydown="onKeydown"
@keydown.down="cycleForward"
@keydown.up="cycleBackward"
@keydown.shift.tab="cycleBackward"
@keydown.tab="cycleForward"
@keydown.enter="replaceEmoji"
/>
<textarea
v-else
:class="classname"
:value="value"
:placeholder="placeholder"
@input="onInput"
@click="setCaret"
@keyup="setCaret"
@keydown="onKeydown"
@keydown.down="cycleForward"
@keydown.up="cycleBackward"
@keydown.shift.tab="cycleBackward"
@keydown.tab="cycleForward"
@keydown.enter="replaceEmoji"
></textarea>
<div class="autocomplete-panel" v-if="suggestions">
<div class="autocomplete-panel-body">
<div
v-for="(emoji, index) in suggestions"
:key="index"
@click="replace(emoji.utf || (emoji.shortcode + ' '))"
class="autocomplete-item"
:class="{ highlighted: emoji.highlighted }"
>
<span v-if="emoji.img">
<img :src="emoji.img" />
</span>
<span v-else>{{emoji.utf}}</span>
<span>{{emoji.shortcode}}</span>
</div>
</div>
</div>
</div>
</template>
<script src="./emoji-input.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.emoji-input {
.form-control {
width: 100%;
}
}
</style>

View File

@ -1,10 +1,10 @@
<template>
<div v-if="loggedIn">
<i :class='classes' class='favorite-button fav-active' @click.prevent='favorite()' :title="$t('tool_tip.favorite')"/>
<i :class='classes' class='button-icon favorite-button fav-active' @click.prevent='favorite()' :title="$t('tool_tip.favorite')"/>
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span>
</div>
<div v-else>
<i :class='classes' class='favorite-button' :title="$t('tool_tip.favorite')"/>
<i :class='classes' class='button-icon favorite-button' :title="$t('tool_tip.favorite')"/>
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span>
</div>
</template>

View File

@ -6,7 +6,7 @@ const FeaturesPanel = {
gopher: function () { return this.$store.state.instance.gopherAvailable },
whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled },
mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable },
scopeOptions: function () { return this.$store.state.instance.scopeOptionsEnabled },
minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode },
textlimit: function () { return this.$store.state.instance.textlimit }
}
}

View File

@ -12,7 +12,7 @@
<li v-if="gopher">{{$t('features_panel.gopher')}}</li>
<li v-if="whoToFollow">{{$t('features_panel.who_to_follow')}}</li>
<li v-if="mediaProxy">{{$t('features_panel.media_proxy')}}</li>
<li v-if="scopeOptions">{{$t('features_panel.scope_options')}}</li>
<li>{{$t('features_panel.scope_options')}}</li>
<li>{{$t('features_panel.text_limit')}} = {{textlimit}}</li>
</ul>
</div>

View File

@ -0,0 +1,50 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import RemoteFollow from '../remote_follow/remote_follow.vue'
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
const FollowCard = {
props: [
'user',
'noFollowsYou'
],
data () {
return {
inProgress: false,
requestSent: false,
updated: false
}
},
components: {
BasicUserCard,
RemoteFollow
},
computed: {
isMe () { return this.$store.state.users.currentUser.id === this.user.id },
following () { return this.updated ? this.updated.following : this.user.following },
showFollow () {
return !this.following || this.updated && !this.updated.following
},
loggedIn () {
return this.$store.state.users.currentUser
}
},
methods: {
followUser () {
this.inProgress = true
requestFollow(this.user, this.$store).then(({ sent, updated }) => {
this.inProgress = false
this.requestSent = sent
this.updated = updated
})
},
unfollowUser () {
this.inProgress = true
requestUnfollow(this.user, this.$store).then(({ updated }) => {
this.inProgress = false
this.updated = updated
})
}
}
}
export default FollowCard

View File

@ -0,0 +1,58 @@
<template>
<basic-user-card :user="user">
<div class="follow-card-content-container">
<span class="faint" v-if="!noFollowsYou && user.follows_you">
{{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }}
</span>
<div class="follow-card-follow-button" v-if="showFollow && !loggedIn">
<RemoteFollow :user="user" />
</div>
<button
v-if="showFollow && loggedIn"
class="btn btn-default follow-card-follow-button"
@click="followUser"
:disabled="inProgress"
:title="requestSent ? $t('user_card.follow_again') : ''"
>
<template v-if="inProgress">
{{ $t('user_card.follow_progress') }}
</template>
<template v-else-if="requestSent">
{{ $t('user_card.follow_sent') }}
</template>
<template v-else>
{{ $t('user_card.follow') }}
</template>
</button>
<button v-if="following" class="btn btn-default follow-card-follow-button pressed" @click="unfollowUser" :disabled="inProgress">
<template v-if="inProgress">
{{ $t('user_card.follow_progress') }}
</template>
<template v-else>
{{ $t('user_card.follow_unfollow') }}
</template>
</button>
</div>
</basic-user-card>
</template>
<script src="./follow_card.js"></script>
<style lang="scss">
.follow-card {
&-content-container {
flex-shrink: 0;
display: flex;
flex-direction: row;
justify-content: space-between;
flex-wrap: wrap;
line-height: 1.5em;
}
&-follow-button {
margin-top: 0.5em;
margin-left: auto;
width: 10em;
}
}
</style>

View File

@ -0,0 +1,20 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const FollowRequestCard = {
props: ['user'],
components: {
BasicUserCard
},
methods: {
approveUser () {
this.$store.state.api.backendInteractor.approveUser(this.user.id)
this.$store.dispatch('removeFollowRequest', this.user)
},
denyUser () {
this.$store.state.api.backendInteractor.denyUser(this.user.id)
this.$store.dispatch('removeFollowRequest', this.user)
}
}
}
export default FollowRequestCard

View File

@ -0,0 +1,29 @@
<template>
<basic-user-card :user="user">
<div class="follow-request-card-content-container">
<button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button>
<button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button>
</div>
</basic-user-card>
</template>
<script src="./follow_request_card.js"></script>
<style lang="scss">
.follow-request-card-content-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
button {
margin-top: 0.5em;
margin-right: 0.5em;
flex: 1 1;
max-width: 12em;
min-width: 8em;
&:last-child {
margin-right: 0;
}
}
}
</style>

View File

@ -1,22 +1,13 @@
import UserCard from '../user_card/user_card.vue'
import FollowRequestCard from '../follow_request_card/follow_request_card.vue'
const FollowRequests = {
components: {
UserCard
},
created () {
this.updateRequests()
FollowRequestCard
},
computed: {
requests () {
return this.$store.state.api.followRequests
}
},
methods: {
updateRequests () {
this.$store.state.api.backendInteractor.fetchFollowRequests()
.then((requests) => { this.$store.commit('setFollowRequests', requests) })
}
}
}

View File

@ -4,7 +4,7 @@
{{$t('nav.friend_requests')}}
</div>
<div class="panel-body">
<user-card v-for="request in requests" :key="request.id" :user="request" :showFollows="false" :showApproval="true"></user-card>
<FollowRequestCard v-for="request in requests" :key="request.id" :user="request" class="list-item"/>
</div>
</div>
</template>

View File

@ -0,0 +1,55 @@
import Attachment from '../attachment/attachment.vue'
import { chunk, last, dropRight } from 'lodash'
const Gallery = {
data: () => ({
width: 500
}),
props: [
'attachments',
'nsfw',
'setMedia'
],
components: { Attachment },
mounted () {
this.resize()
window.addEventListener('resize', this.resize)
},
destroyed () {
window.removeEventListener('resize', this.resize)
},
computed: {
rows () {
if (!this.attachments) {
return []
}
const rows = chunk(this.attachments, 3)
if (last(rows).length === 1 && rows.length > 1) {
// if 1 attachment on last row -> add it to the previous row instead
const lastAttachment = last(rows)[0]
const allButLastRow = dropRight(rows)
last(allButLastRow).push(lastAttachment)
return allButLastRow
}
return rows
},
rowHeight () {
return itemsPerRow => ({ 'height': `${(this.width / (itemsPerRow + 0.6))}px` })
},
useContainFit () {
return this.$store.state.config.useContainFit
}
},
methods: {
resize () {
// Quick optimization to make resizing not always trigger state change,
// only update attachment size in 10px steps
const width = Math.floor(this.$el.getBoundingClientRect().width / 10) * 10
if (this.width !== width) {
this.width = width
}
}
}
}
export default Gallery

View File

@ -0,0 +1,65 @@
<template>
<div ref="galleryContainer" style="width: 100%;">
<div class="gallery-row" v-for="row in rows" :style="rowHeight(row.length)" :class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }">
<attachment
v-for="attachment in row"
:setMedia="setMedia"
:nsfw="nsfw"
:attachment="attachment"
:allowPlay="false"
:key="attachment.id"
/>
</div>
</div>
</template>
<script src='./gallery.js'></script>
<style lang="scss">
@import '../../_variables.scss';
.gallery-row {
height: 200px;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: stretch;
flex-grow: 1;
margin-top: 0.5em;
.attachments, .attachment {
margin: 0 0.5em 0 0;
flex-grow: 1;
height: 100%;
box-sizing: border-box;
// to make failed images a bit more noticeable on chromium
min-width: 2em;
&:last-child {
margin: 0;
}
}
.image-attachment {
width: 100%;
height: 100%;
}
.video-container {
height: 100%;
}
&.contain-fit {
img, video {
object-fit: contain;
}
}
&.cover-fit {
img, video {
object-fit: cover;
}
}
}
</style>

View File

@ -0,0 +1,146 @@
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
const ImageCropper = {
props: {
trigger: {
type: [String, window.Element],
required: true
},
submitHandler: {
type: Function,
required: true
},
cropperOptions: {
type: Object,
default () {
return {
aspectRatio: 1,
autoCropArea: 1,
viewMode: 1,
movable: false,
zoomable: false,
guides: false
}
}
},
mimes: {
type: String,
default: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'
},
saveButtonLabel: {
type: String
},
saveWithoutCroppingButtonlabel: {
type: String
},
cancelButtonLabel: {
type: String
}
},
data () {
return {
cropper: undefined,
dataUrl: undefined,
filename: undefined,
submitting: false,
submitError: null
}
},
computed: {
saveText () {
return this.saveButtonLabel || this.$t('image_cropper.save')
},
saveWithoutCroppingText () {
return this.saveWithoutCroppingButtonlabel || this.$t('image_cropper.save_without_cropping')
},
cancelText () {
return this.cancelButtonLabel || this.$t('image_cropper.cancel')
},
submitErrorMsg () {
return this.submitError && this.submitError instanceof Error ? this.submitError.toString() : this.submitError
}
},
methods: {
destroy () {
if (this.cropper) {
this.cropper.destroy()
}
this.$refs.input.value = ''
this.dataUrl = undefined
this.$emit('close')
},
submit () {
this.submitting = true
this.avatarUploadError = null
this.submitHandler(this.cropper, this.file)
.then(() => this.destroy())
.catch((err) => {
this.submitError = err
})
.finally(() => {
this.submitting = false
})
},
submitWithoutCropping () {
this.submitting = true
this.avatarUploadError = null
this.submitHandler(false, this.dataUrl)
.then(() => this.destroy())
.catch((err) => {
this.submitError = err
})
.finally(() => {
this.submitting = false
})
},
pickImage () {
this.$refs.input.click()
},
createCropper () {
this.cropper = new Cropper(this.$refs.img, this.cropperOptions)
},
getTriggerDOM () {
return typeof this.trigger === 'object' ? this.trigger : document.querySelector(this.trigger)
},
readFile () {
const fileInput = this.$refs.input
if (fileInput.files != null && fileInput.files[0] != null) {
this.file = fileInput.files[0]
let reader = new window.FileReader()
reader.onload = (e) => {
this.dataUrl = e.target.result
this.$emit('open')
}
reader.readAsDataURL(this.file)
this.$emit('changed', this.file, reader)
}
},
clearError () {
this.submitError = null
}
},
mounted () {
// listen for click event on trigger
const trigger = this.getTriggerDOM()
if (!trigger) {
this.$emit('error', 'No image make trigger found.', 'user')
} else {
trigger.addEventListener('click', this.pickImage)
}
// listen for input file changes
const fileInput = this.$refs.input
fileInput.addEventListener('change', this.readFile)
},
beforeDestroy: function () {
// remove the event listeners
const trigger = this.getTriggerDOM()
if (trigger) {
trigger.removeEventListener('click', this.pickImage)
}
const fileInput = this.$refs.input
fileInput.removeEventListener('change', this.readFile)
}
}
export default ImageCropper

View File

@ -0,0 +1,47 @@
<template>
<div class="image-cropper">
<div v-if="dataUrl">
<div class="image-cropper-image-container">
<img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" />
</div>
<div class="image-cropper-buttons-wrapper">
<button class="btn" type="button" :disabled="submitting" @click="submit" v-text="saveText"></button>
<button class="btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText"></button>
<button class="btn" type="button" :disabled="submitting" @click="submitWithoutCropping" v-text="saveWithoutCroppingText"></button>
<i class="icon-spin4 animate-spin" v-if="submitting"></i>
</div>
<div class="alert error" v-if="submitError">
{{submitErrorMsg}}
<i class="button-icon icon-cancel" @click="clearError"></i>
</div>
</div>
<input ref="input" type="file" class="image-cropper-img-input" :accept="mimes">
</div>
</template>
<script src="./image_cropper.js"></script>
<style lang="scss">
.image-cropper {
&-img-input {
display: none;
}
&-image-container {
position: relative;
img {
display: block;
max-width: 100%;
}
}
&-buttons-wrapper {
margin-top: 10px;
button {
margin-top: 5px;
}
}
}
</style>

View File

@ -0,0 +1,21 @@
const LinkPreview = {
name: 'LinkPreview',
props: [
'card',
'size',
'nsfw'
],
computed: {
useImage () {
// 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
// exist.
return this.card.image && !this.nsfw && this.size !== 'hide'
},
useDescription () {
return this.card.description && /\S/.test(this.card.description)
}
}
}
export default LinkPreview

View File

@ -0,0 +1,76 @@
<template>
<div>
<a class="link-preview-card" :href="card.url" target="_blank" rel="noopener">
<div class="card-image" :class="{ 'small-image': size === 'small' }" v-if="useImage">
<img :src="card.image"></img>
</div>
<div class="card-content">
<span class="card-host faint">{{ card.provider_name }}</span>
<h4 class="card-title">{{ card.title }}</h4>
<p class="card-description" v-if="useDescription">{{ card.description }}</p>
</div>
</a>
</div>
</template>
<script src="./link-preview.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.link-preview-card {
display: flex;
flex-direction: row;
cursor: pointer;
overflow: hidden;
margin-top: 0.5em;
.card-image {
flex-shrink: 0;
width: 120px;
max-width: 25%;
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: $fallback--attachmentRadius;
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
}
}
.small-image {
width: 80px;
}
.card-content {
max-height: 100%;
margin: 0.5em;
display: flex;
flex-direction: column;
}
.card-host {
font-size: 12px;
}
.card-description {
margin: 0.5em 0 0 0;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
line-height: 1.2em;
// cap description at 3 lines, the 1px is to clean up some stray pixels
// TODO: fancier fade-out at the bottom to show off that it's too long?
max-height: calc(1.2em * 3 - 1px);
}
color: $fallback--text;
color: var(--text, $fallback--text);
border-style: solid;
border-width: 1px;
border-radius: $fallback--attachmentRadius;
border-radius: var(--attachmentRadius, $fallback--attachmentRadius);
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
}
</style>

View File

@ -0,0 +1,42 @@
<template>
<div class="list">
<div v-for="item in items" class="list-item" :key="getKey(item)">
<slot name="item" :item="item" />
</div>
<div class="list-empty-content faint" v-if="items.length === 0 && !!$slots.empty">
<slot name="empty" />
</div>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: () => []
},
getKey: {
type: Function,
default: item => item.id
}
}
}
</script>
<style lang="scss">
@import '../../_variables.scss';
.list {
&-item:not(:last-child) {
border-bottom: 1px solid;
border-bottom-color: $fallback--border;
border-bottom-color: var(--border, $fallback--border);
}
&-empty-content {
text-align: center;
padding: 10px;
}
}
</style>

View File

@ -22,19 +22,33 @@ const LoginForm = {
oauth: this.$store.state.oauth,
instance: this.$store.state.instance.server
}
this.clearError()
oauthApi.getOrCreateApp(data).then((app) => {
oauthApi.getTokenWithCredentials(
{
app,
instance: data.instance,
username: this.user.username,
password: this.user.password})
.then((result) => {
this.$store.commit('setToken', result.access_token)
this.$store.dispatch('loginUser', result.access_token)
this.$router.push('/main/friends')
})
password: this.user.password
}
).then(async (result) => {
if (result.error) {
this.authError = result.error
this.user.password = ''
return
}
this.$store.commit('setToken', result.access_token)
try {
await this.$store.dispatch('loginUser', result.access_token)
this.$router.push({name: 'friends'})
} catch (e) {
console.log(e)
}
})
})
},
clearError () {
this.authError = false
}
}
}

View File

@ -33,6 +33,13 @@
</div>
</div>
</form>
<div v-if="authError" class='form-group'>
<div class='alert error'>
{{authError}}
<i class="button-icon icon-cancel" @click="clearError"></i>
</div>
</div>
</div>
</div>
</template>
@ -48,10 +55,6 @@
width: 10em;
}
.error {
text-align: center;
}
.register {
flex: 1 1;
}
@ -64,4 +67,14 @@
justify-content: space-between;
}
}
.login {
.error {
text-align: center;
animation-name: shakeError;
animation-duration: 0.4s;
animation-timing-function: ease-in-out;
}
}
</style>

View File

@ -0,0 +1,73 @@
import StillImage from '../still-image/still-image.vue'
import VideoAttachment from '../video_attachment/video_attachment.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
const MediaModal = {
components: {
StillImage,
VideoAttachment
},
computed: {
showing () {
return this.$store.state.mediaViewer.activated
},
media () {
return this.$store.state.mediaViewer.media
},
currentIndex () {
return this.$store.state.mediaViewer.currentIndex
},
currentMedia () {
return this.media[this.currentIndex]
},
canNavigate () {
return this.media.length > 1
},
type () {
return this.currentMedia ? fileTypeService.fileType(this.currentMedia.mimetype) : null
}
},
methods: {
hide () {
this.$store.dispatch('closeMediaViewer')
},
goPrev () {
if (this.canNavigate) {
const prevIndex = this.currentIndex === 0 ? this.media.length - 1 : (this.currentIndex - 1)
this.$store.dispatch('setCurrent', this.media[prevIndex])
}
},
goNext () {
if (this.canNavigate) {
const nextIndex = this.currentIndex === this.media.length - 1 ? 0 : (this.currentIndex + 1)
this.$store.dispatch('setCurrent', this.media[nextIndex])
}
},
handleKeyupEvent (e) {
if (this.showing && e.keyCode === 27) { // escape
this.hide()
}
},
handleKeydownEvent (e) {
if (!this.showing) {
return
}
if (e.keyCode === 39) { // arrow right
this.goNext()
} else if (e.keyCode === 37) { // arrow left
this.goPrev()
}
}
},
mounted () {
document.addEventListener('keyup', this.handleKeyupEvent)
document.addEventListener('keydown', this.handleKeydownEvent)
},
destroyed () {
document.removeEventListener('keyup', this.handleKeyupEvent)
document.removeEventListener('keydown', this.handleKeydownEvent)
}
}
export default MediaModal

View File

@ -0,0 +1,102 @@
<template>
<div class="modal-view media-modal-view" v-if="showing" @click.prevent="hide">
<img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img>
<VideoAttachment
class="modal-image"
v-if="type === 'video'"
:attachment="currentMedia"
:controls="true"
@click.stop.native="">
</VideoAttachment>
<button
:title="$t('media_modal.previous')"
class="modal-view-button-arrow modal-view-button-arrow--prev"
v-if="canNavigate"
@click.stop.prevent="goPrev"
>
<i class="icon-left-open arrow-icon" />
</button>
<button
:title="$t('media_modal.next')"
class="modal-view-button-arrow modal-view-button-arrow--next"
v-if="canNavigate"
@click.stop.prevent="goNext"
>
<i class="icon-right-open arrow-icon" />
</button>
</div>
</template>
<script src="./media_modal.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.media-modal-view {
&:hover {
.modal-view-button-arrow {
opacity: 0.75;
&:focus,
&:hover {
outline: none;
box-shadow: none;
}
&:hover {
opacity: 1;
}
}
}
}
.modal-image {
max-width: 90%;
max-height: 90%;
box-shadow: 0px 5px 15px 0 rgba(0, 0, 0, 0.5);
}
.modal-view-button-arrow {
position: absolute;
display: block;
top: 50%;
margin-top: -50px;
width: 70px;
height: 100px;
border: 0;
padding: 0;
opacity: 0;
box-shadow: none;
background: none;
appearance: none;
overflow: visible;
cursor: pointer;
transition: opacity 333ms cubic-bezier(.4,0,.22,1);
.arrow-icon {
position: absolute;
top: 35px;
height: 30px;
width: 32px;
font-size: 14px;
line-height: 30px;
color: #FFF;
text-align: center;
background-color: rgba(0,0,0,.3);
}
&--prev {
left: 0;
.arrow-icon {
left: 6px;
}
}
&--next {
right: 0;
.arrow-icon {
right: 6px;
}
}
}
</style>

View File

@ -1,28 +1,26 @@
/* eslint-env browser */
import statusPosterService from '../../services/status_poster/status_poster.service.js'
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
const mediaUpload = {
mounted () {
const input = this.$el.querySelector('input')
input.addEventListener('change', ({target}) => {
for (var i = 0; i < target.files.length; i++) {
let file = target.files[i]
this.uploadFile(file)
}
})
},
data () {
return {
uploading: false
uploading: false,
uploadReady: true
}
},
methods: {
uploadFile (file) {
const self = this
const store = this.$store
if (file.size > store.state.instance.uploadlimit) {
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)
self.$emit('upload-failed', 'file_too_big', {filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit})
return
}
const formData = new FormData()
formData.append('media', file)
formData.append('file', file)
self.$emit('uploading')
self.uploading = true
@ -32,7 +30,7 @@ const mediaUpload = {
self.$emit('uploaded', fileData)
self.uploading = false
}, (error) => { // eslint-disable-line handle-callback-err
self.$emit('upload-failed')
self.$emit('upload-failed', 'default')
self.uploading = false
})
},
@ -49,6 +47,18 @@ const mediaUpload = {
} else {
e.dataTransfer.dropEffect = 'none'
}
},
clearFile () {
this.uploadReady = false
this.$nextTick(() => {
this.uploadReady = true
})
},
change ({target}) {
for (var i = 0; i < target.files.length; i++) {
let file = target.files[i]
this.uploadFile(file)
}
}
},
props: [

View File

@ -3,7 +3,7 @@
<label class="btn btn-default" :title="$t('tool_tip.media_upload')">
<i class="icon-spin4 animate-spin" v-if="uploading"></i>
<i class="icon-upload" v-if="!uploading"></i>
<input type="file" style="position: fixed; top: -100em" multiple="true"></input>
<input type="file" v-if="uploadReady" @change="change" style="position: fixed; top: -100em" multiple="true"></input>
</label>
</div>
</template>

View File

@ -0,0 +1,77 @@
import SideDrawer from '../side_drawer/side_drawer.vue'
import Notifications from '../notifications/notifications.vue'
import MobilePostStatusModal from '../mobile_post_status_modal/mobile_post_status_modal.vue'
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
import GestureService from '../../services/gesture_service/gesture_service'
const MobileNav = {
components: {
SideDrawer,
Notifications,
MobilePostStatusModal
},
data: () => ({
notificationsCloseGesture: undefined,
notificationsOpen: false
}),
created () {
this.notificationsCloseGesture = GestureService.swipeGesture(
GestureService.DIRECTION_RIGHT,
this.closeMobileNotifications,
50
)
},
computed: {
currentUser () {
return this.$store.state.users.currentUser
},
unseenNotifications () {
return unseenNotificationsFromStore(this.$store)
},
unseenNotificationsCount () {
return this.unseenNotifications.length
},
sitename () { return this.$store.state.instance.name }
},
methods: {
toggleMobileSidebar () {
this.$refs.sideDrawer.toggleDrawer()
},
openMobileNotifications () {
this.notificationsOpen = true
},
closeMobileNotifications () {
if (this.notificationsOpen) {
// make sure to mark notifs seen only when the notifs were open and not
// from close-calls.
this.notificationsOpen = false
this.markNotificationsAsSeen()
}
},
notificationsTouchStart (e) {
GestureService.beginSwipe(e, this.notificationsCloseGesture)
},
notificationsTouchMove (e) {
GestureService.updateSwipe(e, this.notificationsCloseGesture)
},
scrollToTop () {
window.scrollTo(0, 0)
},
logout () {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
},
markNotificationsAsSeen () {
this.$refs.notifications.markAsSeen()
}
},
watch: {
$route () {
// handles closing notificaitons when you press any router-link on the
// notifications.
this.closeMobileNotifications()
}
}
}
export default MobileNav

View File

@ -0,0 +1,140 @@
<template>
<nav class='nav-bar container' id="nav">
<div class='mobile-inner-nav' @click="scrollToTop()">
<div class='item'>
<a href="#" class="mobile-nav-button" @click.stop.prevent="toggleMobileSidebar()">
<i class="button-icon icon-menu"></i>
</a>
<router-link class="site-name" :to="{ name: 'root' }" active-class="home">{{sitename}}</router-link>
</div>
<div class='item right'>
<a class="mobile-nav-button" v-if="currentUser" href="#" @click.stop.prevent="openMobileNotifications()">
<i class="button-icon icon-bell-alt"></i>
<div class="alert-dot" v-if="unseenNotificationsCount"></div>
</a>
</div>
</div>
<SideDrawer ref="sideDrawer" :logout="logout"/>
<div v-if="currentUser"
class="mobile-notifications-drawer"
:class="{ 'closed': !notificationsOpen }"
@touchstart="notificationsTouchStart"
@touchmove="notificationsTouchMove"
>
<div class="mobile-notifications-header">
<span class="title">{{$t('notifications.notifications')}}</span>
<a class="mobile-nav-button" @click.stop.prevent="closeMobileNotifications()">
<i class="button-icon icon-cancel"/>
</a>
</div>
<div v-if="currentUser" class="mobile-notifications">
<Notifications ref="notifications" noHeading="true"/>
</div>
</div>
<MobilePostStatusModal />
</nav>
</template>
<script src="./mobile_nav.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.mobile-inner-nav {
width: 100%;
display: flex;
align-items: center;
}
.mobile-nav-button {
display: flex;
justify-content: center;
width: 50px;
position: relative;
cursor: pointer;
}
.alert-dot {
border-radius: 100%;
height: 8px;
width: 8px;
position: absolute;
left: calc(50% - 4px);
top: calc(50% - 4px);
margin-left: 6px;
margin-top: -6px;
background-color: $fallback--cRed;
background-color: var(--badgeNotification, $fallback--cRed);
}
.mobile-notifications-drawer {
width: 100%;
height: 100vh;
overflow-x: hidden;
position: fixed;
top: 0;
left: 0;
box-shadow: 1px 1px 4px rgba(0,0,0,.6);
box-shadow: var(--panelShadow);
transition-property: transform;
transition-duration: 0.25s;
transform: translateX(0);
&.closed {
transform: translateX(100%);
}
}
.mobile-notifications-header {
display: flex;
align-items: center;
justify-content: space-between;
z-index: 1;
width: 100%;
height: 50px;
line-height: 50px;
position: absolute;
color: var(--topBarText);
background-color: $fallback--fg;
background-color: var(--topBar, $fallback--fg);
box-shadow: 0px 0px 4px rgba(0,0,0,.6);
box-shadow: var(--topBarShadow);
.title {
font-size: 1.3em;
margin-left: 0.6em;
}
}
.mobile-notifications {
margin-top: 50px;
width: 100vw;
height: calc(100vh - 50px);
overflow-x: hidden;
overflow-y: scroll;
color: $fallback--text;
color: var(--text, $fallback--text);
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg);
.notifications {
padding: 0;
border-radius: 0;
box-shadow: none;
.panel {
border-radius: 0;
margin: 0;
box-shadow: none;
}
.panel:after {
border-radius: 0;
}
.panel .panel-heading {
border-radius: 0;
box-shadow: none;
}
}
}
</style>

View File

@ -0,0 +1,91 @@
import PostStatusForm from '../post_status_form/post_status_form.vue'
import { throttle } from 'lodash'
const MobilePostStatusModal = {
components: {
PostStatusForm
},
data () {
return {
hidden: false,
postFormOpen: false,
scrollingDown: false,
inputActive: false,
oldScrollPos: 0,
amountScrolled: 0
}
},
created () {
window.addEventListener('scroll', this.handleScroll)
window.addEventListener('resize', this.handleOSK)
},
destroyed () {
window.removeEventListener('scroll', this.handleScroll)
window.removeEventListener('resize', this.handleOSK)
},
computed: {
currentUser () {
return this.$store.state.users.currentUser
},
isHidden () {
return this.hidden || this.inputActive
}
},
methods: {
openPostForm () {
this.postFormOpen = true
this.hidden = true
const el = this.$el.querySelector('textarea')
this.$nextTick(function () {
el.focus()
})
},
closePostForm () {
this.postFormOpen = false
this.hidden = false
},
handleOSK () {
// This is a big hack: we're guessing from changed window sizes if the
// on-screen keyboard is active or not. This is only really important
// for phones in portrait mode and it's more important to show the button
// in normal scenarios on all phones, than it is to hide it when the
// keyboard is active.
// Guesswork based on https://www.mydevice.io/#compare-devices
// for example, iphone 4 and android phones from the same time period
const smallPhone = window.innerWidth < 350
const smallPhoneKbOpen = smallPhone && window.innerHeight < 345
const biggerPhone = !smallPhone && window.innerWidth < 450
const biggerPhoneKbOpen = biggerPhone && window.innerHeight < 560
if (smallPhoneKbOpen || biggerPhoneKbOpen) {
this.inputActive = true
} else {
this.inputActive = false
}
},
handleScroll: throttle(function () {
const scrollAmount = window.scrollY - this.oldScrollPos
const scrollingDown = scrollAmount > 0
if (scrollingDown !== this.scrollingDown) {
this.amountScrolled = 0
this.scrollingDown = scrollingDown
if (!scrollingDown) {
this.hidden = false
}
} else if (scrollingDown) {
this.amountScrolled += scrollAmount
if (this.amountScrolled > 100 && !this.hidden) {
this.hidden = true
}
}
this.oldScrollPos = window.scrollY
this.scrollingDown = scrollingDown
}, 100)
}
}
export default MobilePostStatusModal

View File

@ -0,0 +1,76 @@
<template>
<div v-if="currentUser">
<div
class="post-form-modal-view modal-view"
v-show="postFormOpen"
@click="closePostForm"
>
<div class="post-form-modal-panel panel" @click.stop="">
<div class="panel-heading">{{$t('post_status.new_status')}}</div>
<PostStatusForm class="panel-body" @posted="closePostForm"/>
</div>
</div>
<button
class="new-status-button"
:class="{ 'hidden': isHidden }"
@click="openPostForm"
>
<i class="icon-edit" />
</button>
</div>
</template>
<script src="./mobile_post_status_modal.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.post-form-modal-view {
max-height: 100%;
display: block;
}
.post-form-modal-panel {
flex-shrink: 0;
margin: 25% 0 4em 0;
width: 100%;
}
.new-status-button {
width: 5em;
height: 5em;
border-radius: 100%;
position: fixed;
bottom: 1.5em;
right: 1.5em;
// TODO: this needs its own color, it has to stand out enough and link color
// is not very optimal for this particular use.
background-color: $fallback--fg;
background-color: var(--btn, $fallback--fg);
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3), 0px 4px 6px rgba(0, 0, 0, 0.3);
z-index: 10;
transition: 0.35s transform;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
&.hidden {
transform: translateY(150%);
}
i {
font-size: 1.5em;
color: $fallback--text;
color: var(--text, $fallback--text);
}
}
@media all and (min-width: 801px) {
.new-status-button {
display: none;
}
}
</style>

View File

@ -0,0 +1,106 @@
import DialogModal from '../dialog_modal/dialog_modal.vue'
import Popper from 'vue-popperjs/src/component/popper.js.vue'
const FORCE_NSFW = 'mrf_tag:media-force-nsfw'
const STRIP_MEDIA = 'mrf_tag:media-strip'
const FORCE_UNLISTED = 'mrf_tag:force-unlisted'
const DISABLE_REMOTE_SUBSCRIPTION = 'mrf_tag:disable-remote-subscription'
const DISABLE_ANY_SUBSCRIPTION = 'mrf_tag:disable-any-subscription'
const SANDBOX = 'mrf_tag:sandbox'
const QUARANTINE = 'mrf_tag:quarantine'
const ModerationTools = {
props: [
'user'
],
data () {
return {
showDropDown: false,
tags: {
FORCE_NSFW,
STRIP_MEDIA,
FORCE_UNLISTED,
DISABLE_REMOTE_SUBSCRIPTION,
DISABLE_ANY_SUBSCRIPTION,
SANDBOX,
QUARANTINE
},
showDeleteUserDialog: false
}
},
components: {
DialogModal,
Popper
},
computed: {
tagsSet () {
return new Set(this.user.tags)
},
hasTagPolicy () {
return this.$store.state.instance.tagPolicyAvailable
}
},
methods: {
toggleMenu () {
this.showDropDown = !this.showDropDown
},
hasTag (tagName) {
return this.tagsSet.has(tagName)
},
toggleTag (tag) {
const store = this.$store
if (this.tagsSet.has(tag)) {
store.state.api.backendInteractor.untagUser(this.user, tag).then(response => {
if (!response.ok) { return }
store.commit('untagUser', {user: this.user, tag})
})
} else {
store.state.api.backendInteractor.tagUser(this.user, tag).then(response => {
if (!response.ok) { return }
store.commit('tagUser', {user: this.user, tag})
})
}
},
toggleRight (right) {
const store = this.$store
if (this.user.rights[right]) {
store.state.api.backendInteractor.deleteRight(this.user, right).then(response => {
if (!response.ok) { return }
store.commit('updateRight', {user: this.user, right: right, value: false})
})
} else {
store.state.api.backendInteractor.addRight(this.user, right).then(response => {
if (!response.ok) { return }
store.commit('updateRight', {user: this.user, right: right, value: true})
})
}
},
toggleActivationStatus () {
const store = this.$store
const status = !!this.user.deactivated
store.state.api.backendInteractor.setActivationStatus(this.user, status).then(response => {
if (!response.ok) { return }
store.commit('updateActivationStatus', {user: this.user, status: status})
})
},
deleteUserDialog (show) {
this.showDeleteUserDialog = show
},
deleteUser () {
const store = this.$store
const user = this.user
const {id, name} = user
store.state.api.backendInteractor.deleteUser(user)
.then(e => {
this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)
const isProfile = this.$route.name === 'external-user-profile' || this.$route.name === 'user-profile'
const isTargetUser = this.$route.params.name === name || this.$route.params.id === id
if (isProfile && isTargetUser) {
window.history.back()
}
})
}
}
}
export default ModerationTools

View File

@ -0,0 +1,158 @@
<template>
<div class='block' style='position: relative'>
<Popper
trigger="click"
@hide='showDropDown = false'
append-to-body
:options="{
placement: 'bottom-end',
modifiers: {
arrow: { enabled: true },
offset: { offset: '0, 5px' },
}
}">
<div class="popper-wrapper">
<div class="dropdown-menu">
<span v-if='user.is_local'>
<button class="dropdown-item" @click='toggleRight("admin")'>
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
</button>
<button class="dropdown-item" @click='toggleRight("moderator")'>
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
</button>
<div role="separator" class="dropdown-divider"></div>
</span>
<button class="dropdown-item" @click='toggleActivationStatus()'>
{{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }}
</button>
<button class="dropdown-item" @click='deleteUserDialog(true)'>
{{ $t('user_card.admin_menu.delete_account') }}
</button>
<div role="separator" class="dropdown-divider" v-if='hasTagPolicy'></div>
<span v-if='hasTagPolicy'>
<button class="dropdown-item" @click='toggleTag(tags.FORCE_NSFW)'>
{{ $t('user_card.admin_menu.force_nsfw') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"></span>
</button>
<button class="dropdown-item" @click='toggleTag(tags.STRIP_MEDIA)'>
{{ $t('user_card.admin_menu.strip_media') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"></span>
</button>
<button class="dropdown-item" @click='toggleTag(tags.FORCE_UNLISTED)'>
{{ $t('user_card.admin_menu.force_unlisted') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"></span>
</button>
<button class="dropdown-item" @click='toggleTag(tags.SANDBOX)'>
{{ $t('user_card.admin_menu.sandbox') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"></span>
</button>
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)'>
{{ $t('user_card.admin_menu.disable_remote_subscription') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"></span>
</button>
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)'>
{{ $t('user_card.admin_menu.disable_any_subscription') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"></span>
</button>
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.QUARANTINE)'>
{{ $t('user_card.admin_menu.quarantine') }}
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"></span>
</button>
</span>
</div>
</div>
<button slot="reference" v-bind:class="{ pressed: showDropDown }" @click='toggleMenu'>
{{ $t('user_card.admin_menu.moderation') }}
</button>
</Popper>
<DialogModal v-if="showDeleteUserDialog" :onCancel='deleteUserDialog.bind(this, false)'>
<span slot="header">{{ $t('user_card.admin_menu.delete_user') }}</span>
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
<span slot="footer">
<button @click='deleteUserDialog(false)'>
{{ $t('general.cancel') }}
</button>
<button class="danger" @click='deleteUser()'>
{{ $t('user_card.admin_menu.delete_user') }}
</button>
</span>
</DialogModal>
</div>
</template>
<script src="./moderation_tools.js"></script>
<style lang="scss">
@import '../../_variables.scss';
@import '../popper/popper.scss';
.dropdown-menu {
display: block;
padding: .5rem 0;
font-size: 1rem;
text-align: left;
list-style: none;
max-width: 100vw;
z-index: 10;
box-shadow: 1px 1px 4px rgba(0,0,0,.6);
box-shadow: var(--panelShadow);
border: none;
border-radius: $fallback--btnRadius;
border-radius: var(--btnRadius, $fallback--btnRadius);
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg);
.dropdown-divider {
height: 0;
margin: .5rem 0;
overflow: hidden;
border-top: 1px solid $fallback--border;
border-top: 1px solid var(--border, $fallback--border);
}
.dropdown-item {
line-height: 21px;
margin-right: 5px;
overflow: auto;
display: block;
padding: .25rem 1.0rem .25rem 1.5rem;
clear: both;
font-weight: 400;
text-align: inherit;
white-space: normal;
border: none;
border-radius: 0px;
background-color: transparent;
box-shadow: none;
width: 100%;
height: 100%;
&:hover {
// TODO: improve the look on breeze themes
background-color: $fallback--fg;
background-color: var(--btn, $fallback--fg);
box-shadow: none;
}
}
}
.menu-checkbox {
float: right;
min-width: 22px;
max-width: 22px;
min-height: 22px;
max-height: 22px;
line-height: 22px;
text-align: center;
border-radius: 0px;
background-color: $fallback--fg;
background-color: var(--input, $fallback--fg);
box-shadow: 0px 0px 2px black inset;
box-shadow: var(--inputShadow);
&.menu-checkbox-checked::after {
content: '✔';
}
}
</style>

View File

@ -0,0 +1,37 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const MuteCard = {
props: ['userId'],
data () {
return {
progress: false
}
},
computed: {
user () {
return this.$store.getters.findUser(this.userId)
},
muted () {
return this.user.muted
}
},
components: {
BasicUserCard
},
methods: {
unmuteUser () {
this.progress = true
this.$store.dispatch('unmuteUser', this.user.id).then(() => {
this.progress = false
})
},
muteUser () {
this.progress = true
this.$store.dispatch('muteUser', this.user.id).then(() => {
this.progress = false
})
}
}
}
export default MuteCard

View File

@ -0,0 +1,34 @@
<template>
<basic-user-card :user="user">
<div class="mute-card-content-container">
<button class="btn btn-default" @click="unmuteUser" :disabled="progress" v-if="muted">
<template v-if="progress">
{{ $t('user_card.unmute_progress') }}
</template>
<template v-else>
{{ $t('user_card.unmute') }}
</template>
</button>
<button class="btn btn-default" @click="muteUser" :disabled="progress" v-else>
<template v-if="progress">
{{ $t('user_card.mute_progress') }}
</template>
<template v-else>
{{ $t('user_card.mute') }}
</template>
</button>
</div>
</basic-user-card>
</template>
<script src="./mute_card.js"></script>
<style lang="scss">
.mute-card-content-container {
margin-top: 0.5em;
text-align: right;
button {
width: 10em;
}
}
</style>

View File

@ -1,11 +1,23 @@
import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
const NavPanel = {
props: [ 'activatePanel' ],
created () {
if (this.currentUser && this.currentUser.locked) {
const store = this.$store
const credentials = store.state.users.currentUser.credentials
followRequestFetcher.startFetching({ store, credentials })
}
},
computed: {
currentUser () {
return this.$store.state.users.currentUser
},
chat () {
return this.$store.state.chat.channel
},
followRequestCount () {
return this.$store.state.api.followRequests.length
}
}
}

View File

@ -3,32 +3,35 @@
<div class="panel panel-default">
<ul>
<li v-if='currentUser'>
<router-link @click.native="activatePanel('timeline')" to='/main/friends'>
<router-link :to="{ name: 'friends' }">
{{ $t("nav.timeline") }}
</router-link>
</li>
<li v-if='currentUser'>
<router-link @click.native="activatePanel('timeline')" :to="{ name: 'mentions', params: { username: currentUser.screen_name } }">
<router-link :to="{ name: 'mentions', params: { username: currentUser.screen_name } }">
{{ $t("nav.mentions") }}
</router-link>
</li>
<li v-if='currentUser'>
<router-link @click.native="activatePanel('timeline')" :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
{{ $t("nav.dms") }}
</router-link>
</li>
<li v-if='currentUser && currentUser.locked'>
<router-link @click.native="activatePanel('timeline')" to='/friend-requests'>
{{ $t("nav.friend_requests") }}
<router-link :to="{ name: 'friend-requests' }">
{{ $t("nav.friend_requests")}}
<span v-if='followRequestCount > 0' class="badge follow-request-count">
{{followRequestCount}}
</span>
</router-link>
</li>
<li>
<router-link @click.native="activatePanel('timeline')" to='/main/public'>
<router-link :to="{ name: 'public-timeline' }">
{{ $t("nav.public_tl") }}
</router-link>
</li>
<li>
<router-link @click.native="activatePanel('timeline')" to='/main/all'>
<router-link :to="{ name: 'public-external-timeline' }">
{{ $t("nav.twkn") }}
</router-link>
</li>
@ -44,6 +47,7 @@
.nav-panel .panel {
overflow: hidden;
box-shadow: var(--panelShadow);
}
.nav-panel ul {
list-style: none;
@ -51,6 +55,12 @@
padding: 0;
}
.follow-request-count {
margin: -6px 10px;
background-color: $fallback--bg;
background-color: var(--input, $fallback--faint);
}
.nav-panel li {
border-bottom: 1px solid;
border-color: $fallback--border;

View File

@ -1,7 +1,8 @@
import Status from '../status/status.vue'
import StillImage from '../still-image/still-image.vue'
import UserCardContent from '../user_card_content/user_card_content.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserCard from '../user_card/user_card.vue'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
const Notification = {
data () {
@ -10,25 +11,38 @@ const Notification = {
betterShadow: this.$store.state.interface.browserSupport.cssFilter
}
},
props: [
'notification'
],
props: [ 'notification' ],
components: {
Status, StillImage, UserCardContent
Status, UserAvatar, UserCard
},
methods: {
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
},
userProfileLink (user) {
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
},
getUser (notification) {
return this.$store.state.users.usersObject[notification.from_profile.id]
}
},
computed: {
userClass () {
return highlightClass(this.notification.action.user)
return highlightClass(this.notification.from_profile)
},
userStyle () {
const highlight = this.$store.state.config.highlight
const user = this.notification.action.user
const user = this.notification.from_profile
return highlightStyle(highlight[user.screen_name])
},
userInStore () {
return this.$store.getters.findUser(this.notification.from_profile.id)
},
user () {
if (this.userInStore) {
return this.userInStore
}
return this.notification.from_profile
}
}
}

View File

@ -1,17 +1,20 @@
<template>
<status v-if="notification.type === 'mention'" :compact="true" :statusoid="notification.status"></status>
<div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]"v-else>
<a class='avatar-container' :href="notification.action.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
<StillImage class='avatar-compact' :class="{'better-shadow': betterShadow}" :src="notification.action.user.profile_image_url_original"/>
<status
v-if="notification.type === 'mention'"
:compact="true"
:statusoid="notification.status"
>
</status>
<div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]" v-else>
<a class='avatar-container' :href="notification.from_profile.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
<UserAvatar :compact="true" :betterShadow="betterShadow" :src="notification.from_profile.profile_image_url_original" />
</a>
<div class='notification-right'>
<div class="usercard notification-usercard" v-if="userExpanded">
<user-card-content :user="notification.action.user" :switcher="false"></user-card-content>
</div>
<UserCard :user="getUser(notification)" :rounded="true" :bordered="true" v-if="userExpanded" />
<span class="notification-details">
<div class="name-and-action">
<span class="username" v-if="!!notification.action.user.name_html" :title="'@'+notification.action.user.screen_name" v-html="notification.action.user.name_html"></span>
<span class="username" v-else :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
<span class="username" v-if="!!notification.from_profile.name_html" :title="'@'+notification.from_profile.screen_name" v-html="notification.from_profile.name_html"></span>
<span class="username" v-else :title="'@'+notification.from_profile.screen_name">{{ notification.from_profile.name }}</span>
<span v-if="notification.type === 'like'">
<i class="fa icon-star lit"></i>
<small>{{$t('notifications.favorited_you')}}</small>
@ -25,16 +28,24 @@
<small>{{$t('notifications.followed_you')}}</small>
</span>
</div>
<small class="timeago"><router-link v-if="notification.status" :to="{ name: 'conversation', params: { id: notification.status.id } }"><timeago :since="notification.action.created_at" :auto-update="240"></timeago></router-link></small>
<div class="timeago" v-if="notification.type === 'follow'">
<span class="faint">
<timeago :since="notification.created_at" :auto-update="240"></timeago>
</span>
</div>
<div class="timeago" v-else>
<router-link v-if="notification.status" :to="{ name: 'conversation', params: { id: notification.status.id } }" class="faint-link">
<timeago :since="notification.created_at" :auto-update="240"></timeago>
</router-link>
</div>
</span>
<div class="follow-text" v-if="notification.type === 'follow'">
<router-link :to="{ name: 'user-profile', params: { id: notification.action.user.id } }">@{{notification.action.user.screen_name}}</router-link>
<router-link :to="userProfileLink(notification.from_profile)">
@{{notification.from_profile.screen_name}}
</router-link>
</div>
<template v-else>
<status v-if="notification.status" class="faint" :compact="true" :statusoid="notification.status" :noHeading="true"></status>
<div class="broken-favorite" v-else>
{{$t('notifications.broken_favorite')}}
</div>
<status class="faint" :compact="true" :statusoid="notification.action" :noHeading="true"></status>
</template>
</div>
</div>

View File

@ -1,41 +1,38 @@
import Notification from '../notification/notification.vue'
import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js'
import { sortBy, filter } from 'lodash'
import {
notificationsFromStore,
visibleNotificationsFromStore,
unseenNotificationsFromStore
} from '../../services/notification_utils/notification_utils.js'
const Notifications = {
created () {
const store = this.$store
const credentials = store.state.users.currentUser.credentials
notificationsFetcher.startFetching({ store, credentials })
props: [
'noHeading'
],
data () {
return {
bottomedOut: false
}
},
computed: {
visibleTypes () {
return [
this.$store.state.config.notificationVisibility.likes && 'like',
this.$store.state.config.notificationVisibility.mentions && 'mention',
this.$store.state.config.notificationVisibility.repeats && 'repeat',
this.$store.state.config.notificationVisibility.follows && 'follow'
].filter(_ => _)
},
notifications () {
return this.$store.state.statuses.notifications.data
return notificationsFromStore(this.$store)
},
error () {
return this.$store.state.statuses.notifications.error
},
unseenNotifications () {
return filter(this.visibleNotifications, ({seen}) => !seen)
return unseenNotificationsFromStore(this.$store)
},
visibleNotifications () {
// Don't know why, but sortBy([seen, -action.id]) doesn't work.
let sortedNotifications = sortBy(this.notifications, ({action}) => -action.id)
sortedNotifications = sortBy(sortedNotifications, 'seen')
return sortedNotifications.filter((notification) => this.visibleTypes.includes(notification.type))
return visibleNotificationsFromStore(this.$store)
},
unseenCount () {
return this.unseenNotifications.length
},
loading () {
return this.$store.state.statuses.notifications.loading
}
},
components: {
@ -52,15 +49,21 @@ const Notifications = {
},
methods: {
markAsSeen () {
this.$store.dispatch('markNotificationsAsSeen', this.visibleNotifications)
this.$store.dispatch('markNotificationsAsSeen')
},
fetchOlderNotifications () {
const store = this.$store
const credentials = store.state.users.currentUser.credentials
store.commit('setNotificationsLoading', { value: true })
notificationsFetcher.fetchAndUpdate({
store,
credentials,
older: true
}).then(notifs => {
store.commit('setNotificationsLoading', { value: false })
if (notifs.length === 0) {
this.bottomedOut = true
}
})
}
}

View File

@ -36,36 +36,7 @@
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
.broken-favorite {
border-radius: $fallback--tooltipRadius;
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
color: $fallback--text;
color: var(--alertErrorText, $fallback--text);
background-color: $fallback--alertError;
background-color: var(--alertError, $fallback--alertError);
padding: 2px .5em
}
.avatar-compact {
width: 32px;
height: 32px;
box-shadow: var(--avatarStatusShadow);
border-radius: $fallback--avatarAltRadius;
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
overflow: hidden;
line-height: 0;
&.better-shadow {
box-shadow: var(--avatarStatusShadowInset);
filter: var(--avatarStatusShadowFilter)
}
&.animated::before {
display: none;
}
}
&:hover .animated.avatar-compact {
&:hover .animated.avatar {
canvas {
display: none;
}
@ -74,10 +45,6 @@
}
}
.notification-usercard {
margin: 0;
}
.non-mention {
display: flex;
flex: 1;
@ -132,6 +99,7 @@
flex: 1 1 0;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
.name-and-action {
flex: 1;
@ -152,9 +120,9 @@
object-fit: contain
}
}
.timeago {
float: right;
font-size: 12px;
margin-right: .2em;
}
.icon-retweet.lit {

View File

@ -1,7 +1,7 @@
<template>
<div class="notifications">
<div class="panel panel-default">
<div class="panel-heading">
<div v-if="!noHeading" class="panel-heading">
<div class="title">
{{$t('notifications.notifications')}}
<span class="badge badge-notification unseen-count" v-if="unseenCount">{{unseenCount}}</span>
@ -12,16 +12,21 @@
<button v-if="unseenCount" @click.prevent="markAsSeen" class="read-button">{{$t('notifications.read')}}</button>
</div>
<div class="panel-body">
<div v-for="notification in visibleNotifications" :key="notification.action.id" class="notification" :class='{"unseen": !notification.seen}'>
<div v-for="notification in visibleNotifications" :key="notification.id" class="notification" :class='{"unseen": !notification.seen}'>
<div class="notification-overlay"></div>
<notification :notification="notification"></notification>
</div>
</div>
<div class="panel-footer">
<a href="#" v-on:click.prevent='fetchOlderNotifications()' v-if="!notifications.loading">
<div v-if="bottomedOut" class="new-status-notification text-center panel-footer faint">
{{$t('notifications.no_more_notifications')}}
</div>
<a v-else-if="!loading" href="#" v-on:click.prevent="fetchOlderNotifications()">
<div class="new-status-notification text-center panel-footer">{{$t('notifications.load_older')}}</div>
</a>
<div class="new-status-notification text-center panel-footer" v-else>...</div>
<div v-else class="new-status-notification text-center panel-footer">
<i class="icon-spin3 animate-spin"/>
</div>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@ const oac = {
}).then((result) => {
this.$store.commit('setToken', result.access_token)
this.$store.dispatch('loginUser', result.access_token)
this.$router.push('/main/friends')
this.$router.push({name: 'friends'})
})
}
}

View File

@ -0,0 +1,70 @@
@import '../../_variables.scss';
.popper-wrapper {
z-index: 8;
}
.popper-wrapper .popper__arrow {
width: 0;
height: 0;
border-style: solid;
position: absolute;
margin: 5px;
}
.popper-wrapper[x-placement^="top"] {
margin-bottom: 5px;
}
.popper-wrapper[x-placement^="top"] .popper__arrow {
border-width: 5px 5px 0 5px;
border-color: $fallback--bg transparent transparent transparent;
border-color: var(--bg, $fallback--bg) transparent transparent transparent;
bottom: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.popper-wrapper[x-placement^="bottom"] {
margin-top: 5px;
}
.popper-wrapper[x-placement^="bottom"] .popper__arrow {
border-width: 0 5px 5px 5px;
border-color: transparent transparent $fallback--bg transparent;
border-color: transparent transparent var(--bg, $fallback--bg) transparent;
top: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.popper-wrapper[x-placement^="right"] {
margin-left: 5px;
}
.popper-wrapper[x-placement^="right"] .popper__arrow {
border-width: 5px 5px 5px 0;
border-color: transparent $fallback--bg transparent transparent;
border-color: transparent var(--bg, $fallback--bg) transparent transparent;
left: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
.popper-wrapper[x-placement^="left"] {
margin-right: 5px;
}
.popper-wrapper[x-placement^="left"] .popper__arrow {
border-width: 5px 0 5px 5px;
border-color: transparent transparent transparent $fallback--bg;
border-color: transparent transparent transparent var(--bg, $fallback--bg);
right: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}

View File

@ -1,5 +1,7 @@
import statusPoster from '../../services/status_poster/status_poster.service.js'
import MediaUpload from '../media_upload/media_upload.vue'
import ScopeSelector from '../scope_selector/scope_selector.vue'
import EmojiInput from '../emoji-input/emoji-input.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
import Completion from '../../services/completion/completion.js'
import { take, filter, reject, map, uniqBy } from 'lodash'
@ -16,7 +18,7 @@ const buildMentionsString = ({user, attentions}, currentUser) => {
return `@${attention.screen_name}`
})
return mentions.join(' ') + ' '
return mentions.length > 0 ? mentions.join(' ') + ' ' : ''
}
const PostStatusForm = {
@ -28,10 +30,14 @@ const PostStatusForm = {
'subject'
],
components: {
MediaUpload
MediaUpload,
ScopeSelector,
EmojiInput
},
mounted () {
this.resize(this.$refs.textarea)
const textLength = this.$refs.textarea.value.length
this.$refs.textarea.setSelectionRange(textLength, textLength)
if (this.replyTo) {
this.$refs.textarea.focus()
@ -41,15 +47,23 @@ const PostStatusForm = {
const preset = this.$route.query.message
let statusText = preset || ''
const scopeCopy = typeof this.$store.state.config.scopeCopy === 'undefined'
? this.$store.state.instance.scopeCopy
: this.$store.state.config.scopeCopy
if (this.replyTo) {
const currentUser = this.$store.state.users.currentUser
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
const scope = (this.copyMessageScope && this.$store.state.config.copyScope || this.copyMessageScope === 'direct')
const scope = (this.copyMessageScope && scopeCopy || this.copyMessageScope === 'direct')
? this.copyMessageScope
: this.$store.state.users.currentUser.default_scope
const contentType = typeof this.$store.state.config.postContentType === 'undefined'
? this.$store.state.instance.postContentType
: this.$store.state.config.postContentType
return {
dropFiles: [],
submitDisabled: false,
@ -59,23 +73,15 @@ const PostStatusForm = {
newStatus: {
spoilerText: this.subject || '',
status: statusText,
contentType: 'text/plain',
nsfw: false,
files: [],
visibility: scope
visibility: scope,
contentType
},
caret: 0
}
},
computed: {
vis () {
return {
public: { selected: this.newStatus.visibility === 'public' },
unlisted: { selected: this.newStatus.visibility === 'unlisted' },
private: { selected: this.newStatus.visibility === 'private' },
direct: { selected: this.newStatus.visibility === 'direct' }
}
},
candidates () {
const firstchar = this.textAtCaret.charAt(0)
if (firstchar === '@') {
@ -123,6 +129,15 @@ const PostStatusForm = {
users () {
return this.$store.state.users.users
},
userDefaultScope () {
return this.$store.state.users.currentUser.default_scope
},
showAllScopes () {
const minimalScopesMode = typeof this.$store.state.config.minimalScopesMode === 'undefined'
? this.$store.state.instance.minimalScopesMode
: this.$store.state.config.minimalScopesMode
return !minimalScopesMode
},
emoji () {
return this.$store.state.instance.emoji || []
},
@ -147,8 +162,8 @@ const PostStatusForm = {
isOverLengthLimit () {
return this.hasStatusLengthLimit && (this.charactersLeft < 0)
},
scopeOptionsEnabled () {
return this.$store.state.instance.scopeOptionsEnabled
minimalScopesMode () {
return this.$store.state.instance.minimalScopesMode
},
alwaysShowSubject () {
if (typeof this.$store.state.config.alwaysShowSubjectInput !== 'undefined') {
@ -156,11 +171,17 @@ const PostStatusForm = {
} else if (typeof this.$store.state.instance.alwaysShowSubjectInput !== 'undefined') {
return this.$store.state.instance.alwaysShowSubjectInput
} else {
return this.$store.state.instance.scopeOptionsEnabled
return true
}
},
formattingOptionsEnabled () {
return this.$store.state.instance.formattingOptionsEnabled
},
postFormats () {
return this.$store.state.instance.postFormats || []
},
safeDMEnabled () {
return this.$store.state.instance.safeDM
}
},
methods: {
@ -209,6 +230,9 @@ const PostStatusForm = {
this.highlighted = 0
}
},
onKeydown (e) {
e.stopPropagation()
},
setCaret ({target: {selectionStart}}) {
this.caret = selectionStart
},
@ -244,9 +268,11 @@ const PostStatusForm = {
visibility: newStatus.visibility,
contentType: newStatus.contentType
}
this.$refs.mediaUpload.clearFile()
this.$emit('posted')
let el = this.$el.querySelector('textarea')
el.style.height = '16px'
el.style.height = 'auto'
el.style.height = undefined
this.error = null
} else {
this.error = data.error
@ -262,6 +288,11 @@ const PostStatusForm = {
let index = this.newStatus.files.indexOf(fileInfo)
this.newStatus.files.splice(index, 1)
},
uploadFailed (errString, templateArgs) {
templateArgs = templateArgs || {}
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
this.enableSubmit()
},
disableSubmit () {
this.submitDisabled = true
},
@ -273,6 +304,8 @@ const PostStatusForm = {
},
paste (e) {
if (e.clipboardData.files.length > 0) {
// prevent pasting of file as text
e.preventDefault()
// Strangely, files property gets emptied after event propagation
// Trying to wrap it in array doesn't work. Plus I doubt it's possible
// to hold more than one file in clipboard.
@ -289,13 +322,15 @@ const PostStatusForm = {
e.dataTransfer.dropEffect = 'copy'
},
resize (e) {
if (!e.target) { return }
const vertPadding = Number(window.getComputedStyle(e.target)['padding-top'].substr(0, 1)) +
Number(window.getComputedStyle(e.target)['padding-bottom'].substr(0, 1))
e.target.style.height = 'auto'
e.target.style.height = `${e.target.scrollHeight - vertPadding}px`
if (e.target.value === '') {
e.target.style.height = '16px'
const target = e.target || e
if (!(target instanceof window.Element)) { return }
const vertPadding = Number(window.getComputedStyle(target)['padding-top'].substr(0, 1)) +
Number(window.getComputedStyle(target)['padding-bottom'].substr(0, 1))
// Auto is needed to make textbox shrink when removing lines
target.style.height = 'auto'
target.style.height = `${target.scrollHeight - vertPadding}px`
if (target.value === '') {
target.style.height = null
}
},
clearError () {

View File

@ -3,23 +3,28 @@
<form @submit.prevent="postStatus(newStatus)">
<div class="form-group" >
<i18n
v-if="!this.$store.state.users.currentUser.locked && this.newStatus.visibility == 'private'"
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
path="post_status.account_not_locked_warning"
tag="p"
class="visibility-notice">
<router-link to="/user-settings">{{ $t('post_status.account_not_locked_warning_link') }}</router-link>
<router-link :to="{ name: 'user-settings' }">{{ $t('post_status.account_not_locked_warning_link') }}</router-link>
</i18n>
<p v-if="this.newStatus.visibility == 'direct'" class="visibility-notice">{{ $t('post_status.direct_warning') }}</p>
<input
<p v-if="newStatus.visibility === 'direct'" class="visibility-notice">
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
</p>
<EmojiInput
v-if="newStatus.spoilerText || alwaysShowSubject"
type="text"
:placeholder="$t('post_status.content_warning')"
v-model="newStatus.spoilerText"
class="form-cw">
classname="form-control"
/>
<textarea
ref="textarea"
@click="setCaret"
@keyup="setCaret" v-model="newStatus.status" :placeholder="$t('post_status.default')" rows="1" class="form-control"
@keydown="onKeydown"
@keydown.down="cycleForward"
@keydown.up="cycleBackward"
@keydown.shift.tab="cycleBackward"
@ -30,41 +35,47 @@
@drop="fileDrop"
@dragover.prevent="fileDrag"
@input="resize"
@paste="paste">
@paste="paste"
:disabled="posting"
>
</textarea>
<div class="visibility-tray">
<span class="text-format" v-if="formattingOptionsEnabled">
<label for="post-content-type" class="select">
<select id="post-content-type" v-model="newStatus.contentType" class="form-control">
<option value="text/plain">{{$t('post_status.content_type.plain_text')}}</option>
<option value="text/html">HTML</option>
<option value="text/markdown">Markdown</option>
<option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat">
{{$t(`post_status.content_type["${postFormat}"]`)}}
</option>
</select>
<i class="icon-down-open"></i>
</label>
</span>
<div v-if="scopeOptionsEnabled">
<i v-on:click="changeVis('direct')" class="icon-mail-alt" :class="vis.direct" :title="$t('post_status.scope.direct')"></i>
<i v-on:click="changeVis('private')" class="icon-lock" :class="vis.private" :title="$t('post_status.scope.private')"></i>
<i v-on:click="changeVis('unlisted')" class="icon-lock-open-alt" :class="vis.unlisted" :title="$t('post_status.scope.unlisted')"></i>
<i v-on:click="changeVis('public')" class="icon-globe" :class="vis.public" :title="$t('post_status.scope.public')"></i>
</div>
<scope-selector
:showAll="showAllScopes"
:userDefault="userDefaultScope"
:originalScope="copyMessageScope"
:initialScope="newStatus.visibility"
:onScopeChange="changeVis"/>
</div>
</div>
<div style="position:relative;" v-if="candidates">
<div class="autocomplete-panel">
<div v-for="candidate in candidates" @click="replace(candidate.utf || (candidate.screen_name + ' '))">
<div class="autocomplete" :class="{ highlighted: candidate.highlighted }">
<span v-if="candidate.img"><img :src="candidate.img"></img></span>
<span v-else>{{candidate.utf}}</span>
<span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
</div>
<div class="autocomplete-panel" v-if="candidates">
<div class="autocomplete-panel-body">
<div
v-for="(candidate, index) in candidates"
:key="index"
@click="replace(candidate.utf || (candidate.screen_name + ' '))"
class="autocomplete-item"
:class="{ highlighted: candidate.highlighted }"
>
<span v-if="candidate.img"><img :src="candidate.img" /></span>
<span v-else>{{candidate.utf}}</span>
<span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
</div>
</div>
</div>
<div class='form-bottom'>
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="enableSubmit" :drop-files="dropFiles"></media-upload>
<media-upload ref="mediaUpload" @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload>
<p v-if="isOverLengthLimit" class="error">{{ charactersLeft }}</p>
<p class="faint" v-else-if="hasStatusLengthLimit">{{ charactersLeft }}</p>
@ -75,16 +86,16 @@
</div>
<div class='alert error' v-if="error">
Error: {{ error }}
<i class="icon-cancel" @click="clearError"></i>
<i class="button-icon icon-cancel" @click="clearError"></i>
</div>
<div class="attachments">
<div class="media-upload-wrapper" v-for="file in newStatus.files">
<i class="fa icon-cancel" @click="removeMediaFile(file)"></i>
<i class="fa button-icon icon-cancel" @click="removeMediaFile(file)"></i>
<div class="media-upload-container attachment">
<img class="thumbnail media-upload" :src="file.image" v-if="type(file) === 'image'"></img>
<video v-if="type(file) === 'video'" :src="file.image" controls></video>
<audio v-if="type(file) === 'audio'" :src="file.image" controls></audio>
<a v-if="type(file) === 'unknown'" :href="file.image">{{file.url}}</a>
<img class="thumbnail media-upload" :src="file.url" v-if="type(file) === 'image'"></img>
<video v-if="type(file) === 'video'" :src="file.url" controls></video>
<audio v-if="type(file) === 'audio'" :src="file.url" controls></audio>
<a v-if="type(file) === 'unknown'" :href="file.url">{{file.url}}</a>
</div>
</div>
</div>
@ -118,6 +129,14 @@
}
}
.post-status-form {
.visibility-tray {
display: flex;
justify-content: space-between;
flex-direction: row-reverse;
}
}
.post-status-form, .login {
.form-bottom {
display: flex;
@ -250,52 +269,5 @@
cursor: pointer;
z-index: 4;
}
.autocomplete-panel {
margin: 0 0.5em 0 0.5em;
border-radius: $fallback--tooltipRadius;
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
position: absolute;
z-index: 1;
box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
// this doesn't match original but i don't care, making it uniform.
box-shadow: var(--popupShadow);
min-width: 75%;
background: $fallback--bg;
background: var(--bg, $fallback--bg);
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
}
.autocomplete {
cursor: pointer;
padding: 0.2em 0.4em 0.2em 0.4em;
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
display: flex;
img {
width: 24px;
height: 24px;
border-radius: $fallback--avatarRadius;
border-radius: var(--avatarRadius, $fallback--avatarRadius);
object-fit: contain;
}
span {
line-height: 24px;
margin: 0 0.1em 0 0.2em;
}
small {
margin-left: .5em;
color: $fallback--faint;
color: var(--faint, $fallback--faint);
}
&.highlighted {
background-color: $fallback--fg;
background-color: var(--lightBg, $fallback--fg);
}
}
}
</style>

View File

@ -0,0 +1,35 @@
<template>
<button :disabled="progress || disabled" @click="onClick">
<template v-if="progress">
<slot name="progress" />
</template>
<template v-else>
<slot />
</template>
</button>
</template>
<script>
export default {
props: {
disabled: {
type: Boolean
},
click: { // click event handler. Must return a promise
type: Function,
default: () => Promise.resolve()
}
},
data () {
return {
progress: false
}
},
methods: {
onClick () {
this.progress = true
this.click().then(() => { this.progress = false })
}
}
}
</script>

View File

@ -7,7 +7,7 @@ const PublicAndExternalTimeline = {
timeline () { return this.$store.state.statuses.timelines.publicAndExternal }
},
created () {
this.$store.dispatch('startFetching', 'publicAndExternal')
this.$store.dispatch('startFetchingTimeline', { timeline: 'publicAndExternal' })
},
destroyed () {
this.$store.dispatch('stopFetching', 'publicAndExternal')

View File

@ -1,5 +1,5 @@
<template>
<Timeline :title="$t('nav.twkn')"v-bind:timeline="timeline" v-bind:timeline-name="'publicAndExternal'"/>
<Timeline :title="$t('nav.twkn')" v-bind:timeline="timeline" v-bind:timeline-name="'publicAndExternal'"/>
</template>
<script src="./public_and_external_timeline.js"></script>

View File

@ -7,7 +7,7 @@ const PublicTimeline = {
timeline () { return this.$store.state.statuses.timelines.public }
},
created () {
this.$store.dispatch('startFetching', 'public')
this.$store.dispatch('startFetchingTimeline', { timeline: 'public' })
},
destroyed () {
this.$store.dispatch('stopFetching', 'public')

View File

@ -11,7 +11,8 @@ const registration = {
username: '',
password: '',
confirm: ''
}
},
captcha: {}
}),
validations: {
user: {
@ -27,11 +28,16 @@ const registration = {
},
created () {
if ((!this.registrationOpen && !this.token) || this.signedIn) {
this.$router.push('/main/all')
this.$router.push({name: 'root'})
}
this.setCaptcha()
},
computed: {
token () { return this.$route.params.token },
bioPlaceholder () {
return this.$t('registration.bio_placeholder').replace(/\s*\n\s*/g, ' \n')
},
...mapState({
registrationOpen: (state) => state.instance.registrationOpen,
signedIn: (state) => !!state.users.currentUser,
@ -41,21 +47,28 @@ const registration = {
})
},
methods: {
...mapActions(['signUp']),
...mapActions(['signUp', 'getCaptcha']),
async submit () {
this.user.nickname = this.user.username
this.user.token = this.token
this.user.captcha_solution = this.captcha.solution
this.user.captcha_token = this.captcha.token
this.user.captcha_answer_data = this.captcha.answer_data
this.$v.$touch()
if (!this.$v.$invalid) {
try {
await this.signUp(this.user)
this.$router.push('/main/friends')
this.$router.push({name: 'friends'})
} catch (error) {
console.warn('Registration failed: ' + error)
}
}
},
setCaptcha () {
this.getCaptcha().then(cpt => { this.captcha = cpt })
}
}
}

View File

@ -9,7 +9,7 @@
<div class='text-fields'>
<div class='form-group' :class="{ 'form-group--error': $v.user.username.$error }">
<label class='form--label' for='sign-up-username'>{{$t('login.username')}}</label>
<input :disabled="isPending" v-model.trim='$v.user.username.$model' class='form-control' id='sign-up-username' placeholder='e.g. lain'>
<input :disabled="isPending" v-model.trim='$v.user.username.$model' class='form-control' id='sign-up-username' :placeholder="$t('registration.username_placeholder')">
</div>
<div class="form-error" v-if="$v.user.username.$dirty">
<ul>
@ -21,7 +21,7 @@
<div class='form-group' :class="{ 'form-group--error': $v.user.fullname.$error }">
<label class='form--label' for='sign-up-fullname'>{{$t('registration.fullname')}}</label>
<input :disabled="isPending" v-model.trim='$v.user.fullname.$model' class='form-control' id='sign-up-fullname' placeholder='e.g. Lain Iwakura'>
<input :disabled="isPending" v-model.trim='$v.user.fullname.$model' class='form-control' id='sign-up-fullname' :placeholder="$t('registration.fullname_placeholder')">
</div>
<div class="form-error" v-if="$v.user.fullname.$dirty">
<ul>
@ -44,8 +44,8 @@
</div>
<div class='form-group'>
<label class='form--label' for='bio'>{{$t('registration.bio')}}</label>
<input :disabled="isPending" v-model='user.bio' class='form-control' id='bio'>
<label class='form--label' for='bio'>{{$t('registration.bio')}} ({{$t('general.optional')}})</label>
<textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="bioPlaceholder"></textarea>
</div>
<div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }">
@ -75,6 +75,20 @@
</ul>
</div>
<div class="form-group" id="captcha-group" v-if="captcha.type != 'none'">
<label class='form--label' for='captcha-label'>{{$t('captcha')}}</label>
<template v-if="captcha.type == 'kocaptcha'">
<img v-bind:src="captcha.url" v-on:click="setCaptcha">
<sub>{{$t('registration.new_captcha')}}</sub>
<input :disabled="isPending"
v-model='captcha.solution'
class='form-control' id='captcha-answer' type='text' autocomplete="off">
</template>
</div>
<div class='form-group' v-if='token' >
<label for='token'>{{$t('registration.token')}}</label>
<input disabled='true' v-model='token' class='form-control' id='token' type='text'>
@ -125,6 +139,10 @@ $validations-cRed: #f04124;
flex-direction: column;
}
textarea {
min-height: 100px;
}
.form-group {
display: flex;
flex-direction: column;
@ -133,24 +151,6 @@ $validations-cRed: #f04124;
margin-bottom: 1em;
}
@keyframes shakeError {
0% {
transform: translateX(0); }
15% {
transform: translateX(0.375rem); }
30% {
transform: translateX(-0.375rem); }
45% {
transform: translateX(0.375rem); }
60% {
transform: translateX(-0.375rem); }
75% {
transform: translateX(0.375rem); }
90% {
transform: translateX(-0.375rem); }
100% {
transform: translateX(0); } }
.form-group--error {
animation-name: shakeError;
animation-duration: .6s;
@ -201,7 +201,7 @@ $validations-cRed: #f04124;
}
}
@media all and (max-width: 959px) {
@media all and (max-width: 800px) {
.registration-form .container {
flex-direction: column-reverse;
}

View File

@ -0,0 +1,10 @@
export default {
props: [ 'user' ],
computed: {
subscribeUrl () {
// eslint-disable-next-line no-undef
const serverUrl = new URL(this.user.statusnet_profile_url)
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
}
}
}

View File

@ -0,0 +1,24 @@
<template>
<div class="remote-follow">
<form method="POST" :action='subscribeUrl'>
<input type="hidden" name="nickname" :value="user.screen_name">
<input type="hidden" name="profile" value="">
<button click="submit" class="remote-button">
{{ $t('user_card.remote_follow') }}
</button>
</form>
</div>
</template>
<script src="./remote_follow.js"></script>
<style lang="scss">
.remote-follow {
max-width: 220px;
.remote-button {
width: 100%;
min-height: 28px;
}
}
</style>

View File

@ -1,15 +1,15 @@
<template>
<div v-if="loggedIn">
<template v-if="visibility !== 'private' && visibility !== 'direct'">
<i :class='classes' class='retweet-button icon-retweet rt-active' v-on:click.prevent='retweet()' :title="$t('tool_tip.repeat')"></i>
<i :class='classes' class='button-icon retweet-button icon-retweet rt-active' v-on:click.prevent='retweet()' :title="$t('tool_tip.repeat')"></i>
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span>
</template>
<template v-else>
<i :class='classes' class='icon-lock' :title="$t('timeline.no_retweet_hint')"></i>
<i :class='classes' class='button-icon icon-lock' :title="$t('timeline.no_retweet_hint')"></i>
</template>
</div>
<div v-else-if="!loggedIn">
<i :class='classes' class='icon-retweet' :title="$t('tool_tip.repeat')"></i>
<i :class='classes' class='button-icon icon-retweet' :title="$t('tool_tip.repeat')"></i>
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span>
</div>
</template>

View File

@ -0,0 +1,54 @@
const ScopeSelector = {
props: [
'showAll',
'userDefault',
'originalScope',
'initialScope',
'onScopeChange'
],
data () {
return {
currentScope: this.initialScope
}
},
computed: {
showNothing () {
return !this.showPublic && !this.showUnlisted && !this.showPrivate && !this.showDirect
},
showPublic () {
return this.originalScope !== 'direct' && this.shouldShow('public')
},
showUnlisted () {
return this.originalScope !== 'direct' && this.shouldShow('unlisted')
},
showPrivate () {
return this.originalScope !== 'direct' && this.shouldShow('private')
},
showDirect () {
return this.shouldShow('direct')
},
css () {
return {
public: {selected: this.currentScope === 'public'},
unlisted: {selected: this.currentScope === 'unlisted'},
private: {selected: this.currentScope === 'private'},
direct: {selected: this.currentScope === 'direct'}
}
}
},
methods: {
shouldShow (scope) {
return this.showAll ||
this.currentScope === scope ||
this.originalScope === scope ||
this.userDefault === scope ||
scope === 'direct'
},
changeVis (scope) {
this.currentScope = scope
this.onScopeChange && this.onScopeChange(scope)
}
}
}
export default ScopeSelector

View File

@ -0,0 +1,30 @@
<template>
<div v-if="!showNothing">
<i class="icon-mail-alt"
:class="css.direct"
:title="$t('post_status.scope.direct')"
v-if="showDirect"
@click="changeVis('direct')">
</i>
<i class="icon-lock"
:class="css.private"
:title="$t('post_status.scope.private')"
v-if="showPrivate"
v-on:click="changeVis('private')">
</i>
<i class="icon-lock-open-alt"
:class="css.unlisted"
:title="$t('post_status.scope.unlisted')"
v-if="showUnlisted"
@click="changeVis('unlisted')">
</i>
<i class="icon-globe"
:class="css.public"
:title="$t('post_status.scope.public')"
v-if="showPublic"
@click="changeVis('public')">
</i>
</div>
</template>
<script src="./scope_selector.js"></script>

View File

@ -0,0 +1,66 @@
import List from '../list/list.vue'
import Checkbox from '../checkbox/checkbox.vue'
const SelectableList = {
components: {
List,
Checkbox
},
props: {
items: {
type: Array,
default: () => []
},
getKey: {
type: Function,
default: item => item.id
}
},
data () {
return {
selected: []
}
},
computed: {
allKeys () {
return this.items.map(this.getKey)
},
filteredSelected () {
return this.allKeys.filter(key => this.selected.indexOf(key) !== -1)
},
allSelected () {
return this.filteredSelected.length === this.items.length
},
noneSelected () {
return this.filteredSelected.length === 0
},
someSelected () {
return !this.allSelected && !this.noneSelected
}
},
methods: {
isSelected (item) {
return this.filteredSelected.indexOf(this.getKey(item)) !== -1
},
toggle (checked, item) {
const key = this.getKey(item)
const oldChecked = this.isSelected(key)
if (checked !== oldChecked) {
if (checked) {
this.selected.push(key)
} else {
this.selected.splice(this.selected.indexOf(key), 1)
}
}
},
toggleAll (value) {
if (value) {
this.selected = this.allKeys.slice(0)
} else {
this.selected = []
}
}
}
}
export default SelectableList

View File

@ -0,0 +1,59 @@
<template>
<div class="selectable-list">
<div class="selectable-list-header" v-if="items.length > 0">
<div class="selectable-list-checkbox-wrapper">
<Checkbox :checked="allSelected" @change="toggleAll" :indeterminate="someSelected">{{ $t('selectable_list.select_all') }}</Checkbox>
</div>
<div class="selectable-list-header-actions">
<slot name="header" :selected="filteredSelected" />
</div>
</div>
<List :items="items" :getKey="getKey">
<template slot="item" slot-scope="{item}">
<div class="selectable-list-item-inner" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }">
<div class="selectable-list-checkbox-wrapper">
<Checkbox :checked="isSelected(item)" @change="checked => toggle(checked, item)" />
</div>
<slot name="item" :item="item" />
</div>
</template>
<template slot="empty"><slot name="empty" /></template>
</List>
</div>
</template>
<script src="./selectable_list.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.selectable-list {
&-item-inner {
display: flex;
align-items: center;
}
&-item-selected-inner {
background-color: $fallback--lightBg;
background-color: var(--lightBg, $fallback--lightBg);
}
&-header {
display: flex;
align-items: center;
padding: 0.6em 0;
border-bottom: 2px solid;
border-bottom-color: $fallback--border;
border-bottom-color: var(--border, $fallback--border);
&-actions {
flex: 1;
}
}
&-checkbox-wrapper {
padding: 0 10px;
flex: none;
}
}
</style>

View File

@ -1,8 +1,13 @@
/* eslint-env browser */
import TabSwitcher from '../tab_switcher/tab_switcher.jsx'
import { filter, trim } from 'lodash'
import TabSwitcher from '../tab_switcher/tab_switcher.js'
import StyleSwitcher from '../style_switcher/style_switcher.vue'
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
import { filter, trim } from 'lodash'
import { extractCommit } from '../../services/version/version.service'
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
const settings = {
data () {
@ -12,47 +17,86 @@ const settings = {
return {
hideAttachmentsLocal: user.hideAttachments,
hideAttachmentsInConvLocal: user.hideAttachmentsInConv,
maxThumbnails: user.maxThumbnails,
hideNsfwLocal: user.hideNsfw,
useOneClickNsfw: user.useOneClickNsfw,
hideISPLocal: user.hideISP,
preloadImage: user.preloadImage,
hidePostStatsLocal: typeof user.hidePostStats === 'undefined'
? instance.hidePostStats
: user.hidePostStats,
hidePostStatsDefault: this.$t('settings.values.' + instance.hidePostStats),
hideUserStatsLocal: typeof user.hideUserStats === 'undefined'
? instance.hideUserStats
: user.hideUserStats,
hideUserStatsDefault: this.$t('settings.values.' + instance.hideUserStats),
hideFilteredStatusesLocal: typeof user.hideFilteredStatuses === 'undefined'
? instance.hideFilteredStatuses
: user.hideFilteredStatuses,
hideFilteredStatusesDefault: this.$t('settings.values.' + instance.hideFilteredStatuses),
notificationVisibilityLocal: user.notificationVisibility,
replyVisibilityLocal: user.replyVisibility,
loopVideoLocal: user.loopVideo,
loopVideoSilentOnlyLocal: user.loopVideoSilentOnly,
muteWordsString: user.muteWords.join('\n'),
autoLoadLocal: user.autoLoad,
streamingLocal: user.streaming,
pauseOnUnfocusedLocal: user.pauseOnUnfocused,
hoverPreviewLocal: user.hoverPreview,
hideMutedPostsLocal: typeof user.hideMutedPosts === 'undefined'
? instance.hideMutedPosts
: user.hideMutedPosts,
hideMutedPostsDefault: this.$t('settings.values.' + instance.hideMutedPosts),
collapseMessageWithSubjectLocal: typeof user.collapseMessageWithSubject === 'undefined'
? instance.collapseMessageWithSubject
: user.collapseMessageWithSubject,
collapseMessageWithSubjectDefault: this.$t('settings.values.' + instance.collapseMessageWithSubject),
subjectLineBehaviorLocal: typeof user.subjectLineBehavior === 'undefined'
? instance.subjectLineBehavior
: user.subjectLineBehavior,
subjectLineBehaviorDefault: instance.subjectLineBehavior,
postContentTypeLocal: typeof user.postContentType === 'undefined'
? instance.postContentType
: user.postContentType,
postContentTypeDefault: instance.postContentType,
alwaysShowSubjectInputLocal: typeof user.alwaysShowSubjectInput === 'undefined'
? instance.alwaysShowSubjectInput
: user.alwaysShowSubjectInput,
alwaysShowSubjectInputDefault: instance.alwaysShowSubjectInput,
scopeCopyLocal: user.scopeCopy,
alwaysShowSubjectInputDefault: this.$t('settings.values.' + instance.alwaysShowSubjectInput),
scopeCopyLocal: typeof user.scopeCopy === 'undefined'
? instance.scopeCopy
: user.scopeCopy,
scopeCopyDefault: this.$t('settings.values.' + instance.scopeCopy),
minimalScopesModeLocal: typeof user.minimalScopesMode === 'undefined'
? instance.minimalScopesMode
: user.minimalScopesMode,
minimalScopesModeDefault: this.$t('settings.values.' + instance.minimalScopesMode),
stopGifs: user.stopGifs,
webPushNotificationsLocal: user.webPushNotifications,
loopVideoSilentOnlyLocal: user.loopVideosSilentOnly,
loopSilentAvailable:
// Firefox
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
// Chrome-likes
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
// Future spec, still not supported in Nightly 63 as of 08/2018
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
playVideosInModal: user.playVideosInModal,
useContainFit: user.useContainFit,
backendVersion: instance.backendVersion,
frontendVersion: instance.frontendVersion
}
},
components: {
@ -66,6 +110,16 @@ const settings = {
},
currentSaveStateNotice () {
return this.$store.state.interface.settings.currentSaveStateNotice
},
postFormats () {
return this.$store.state.instance.postFormats || []
},
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
frontendVersionLink () {
return pleromaFeCommitUrl + this.frontendVersion
},
backendVersionLink () {
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
}
},
watch: {
@ -81,9 +135,18 @@ const settings = {
hideUserStatsLocal (value) {
this.$store.dispatch('setOption', { name: 'hideUserStats', value })
},
hideFilteredStatusesLocal (value) {
this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value })
},
hideNsfwLocal (value) {
this.$store.dispatch('setOption', { name: 'hideNsfw', value })
},
useOneClickNsfw (value) {
this.$store.dispatch('setOption', { name: 'useOneClickNsfw', value })
},
preloadImage (value) {
this.$store.dispatch('setOption', { name: 'preloadImage', value })
},
hideISPLocal (value) {
this.$store.dispatch('setOption', { name: 'hideISP', value })
},
@ -124,6 +187,9 @@ const settings = {
value = filter(value.split('\n'), (word) => trim(word).length > 0)
this.$store.dispatch('setOption', { name: 'muteWords', value })
},
hideMutedPostsLocal (value) {
this.$store.dispatch('setOption', { name: 'hideMutedPosts', value })
},
collapseMessageWithSubjectLocal (value) {
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
},
@ -136,8 +202,28 @@ const settings = {
subjectLineBehaviorLocal (value) {
this.$store.dispatch('setOption', { name: 'subjectLineBehavior', value })
},
postContentTypeLocal (value) {
this.$store.dispatch('setOption', { name: 'postContentType', value })
},
minimalScopesModeLocal (value) {
this.$store.dispatch('setOption', { name: 'minimalScopesMode', value })
},
stopGifs (value) {
this.$store.dispatch('setOption', { name: 'stopGifs', value })
},
webPushNotificationsLocal (value) {
this.$store.dispatch('setOption', { name: 'webPushNotifications', value })
if (value) this.$store.dispatch('registerPushNotifications')
},
playVideosInModal (value) {
this.$store.dispatch('setOption', { name: 'playVideosInModal', value })
},
useContainFit (value) {
this.$store.dispatch('setOption', { name: 'useContainFit', value })
},
maxThumbnails (value) {
value = this.maxThumbnails = Math.floor(Math.max(value, 0))
this.$store.dispatch('setOption', { name: 'maxThumbnails', value })
}
}
}

View File

@ -27,7 +27,7 @@
<li>
<interface-language-switcher />
</li>
<li>
<li v-if="instanceSpecificPanelPresent">
<input type="checkbox" id="hideISP" v-model="hideISPLocal">
<label for="hideISP">{{$t('settings.hide_isp')}}</label>
</li>
@ -36,11 +36,13 @@
<div class="setting-item">
<h2>{{$t('nav.timeline')}}</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="hideMutedPosts" v-model="hideMutedPostsLocal">
<label for="hideMutedPosts">{{$t('settings.hide_muted_posts')}} {{$t('settings.instance_default', { value: hideMutedPostsDefault })}}</label>
</li>
<li>
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
<label for="collapseMessageWithSubject">
{{$t('settings.collapse_subject')}} {{$t('settings.instance_default', { value: collapseMessageWithSubjectDefault })}}
</label>
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}} {{$t('settings.instance_default', { value: collapseMessageWithSubjectDefault })}}</label>
</li>
<li>
<input type="checkbox" id="streaming" v-model="streamingLocal">
@ -100,6 +102,26 @@
</label>
</div>
</li>
<li>
<div>
{{$t('settings.post_status_content_type')}}
<label for="postContentType" class="select">
<select id="postContentType" v-model="postContentTypeLocal">
<option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat">
{{$t(`post_status.content_type["${postFormat}"]`)}}
{{postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : ''}}
</option>
</select>
<i class="icon-down-open"/>
</label>
</div>
</li>
<li>
<input type="checkbox" id="minimalScopesMode" v-model="minimalScopesModeLocal">
<label for="minimalScopesMode">
{{$t('settings.minimal_scopes_mode')}} {{$t('settings.instance_default', { value: minimalScopesModeDefault })}}
</label>
</li>
</ul>
</div>
@ -114,10 +136,24 @@
<input type="checkbox" id="hideAttachmentsInConv" v-model="hideAttachmentsInConvLocal">
<label for="hideAttachmentsInConv">{{$t('settings.hide_attachments_in_convo')}}</label>
</li>
<li>
<label for="maxThumbnails">{{$t('settings.max_thumbnails')}}</label>
<input class="number-input" type="number" id="maxThumbnails" v-model.number="maxThumbnails" min="0" step="1">
</li>
<li>
<input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
</li>
<ul class="setting-list suboptions" >
<li>
<input :disabled="!hideNsfwLocal" type="checkbox" id="preloadImage" v-model="preloadImage">
<label for="preloadImage">{{$t('settings.preload_images')}}</label>
</li>
<li>
<input :disabled="!hideNsfwLocal" type="checkbox" id="useOneClickNsfw" v-model="useOneClickNsfw">
<label for="useOneClickNsfw">{{$t('settings.use_one_click_nsfw')}}</label>
</li>
</ul>
<li>
<input type="checkbox" id="stopGifs" v-model="stopGifs">
<label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
@ -135,6 +171,26 @@
</li>
</ul>
</li>
<li>
<input type="checkbox" id="playVideosInModal" v-model="playVideosInModal">
<label for="playVideosInModal">{{$t('settings.play_videos_in_modal')}}</label>
</li>
<li>
<input type="checkbox" id="useContainFit" v-model="useContainFit">
<label for="useContainFit">{{$t('settings.use_contain_fit')}}</label>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{$t('settings.notifications')}}</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="webPushNotifications" v-model="webPushNotificationsLocal">
<label for="webPushNotifications">
{{$t('settings.enable_web_push_notifications')}}
</label>
</li>
</ul>
</div>
</div>
@ -175,7 +231,6 @@
</label>
</li>
</ul>
</label>
</div>
<div>
{{$t('settings.replies_in_timeline')}}
@ -202,11 +257,40 @@
</div>
</div>
<div class="setting-item">
<p>{{$t('settings.filtering_explanation')}}</p>
<textarea id="muteWords" v-model="muteWordsString"></textarea>
<div>
<p>{{$t('settings.filtering_explanation')}}</p>
<textarea id="muteWords" v-model="muteWordsString"></textarea>
</div>
<div>
<input type="checkbox" id="hideFilteredStatuses" v-model="hideFilteredStatusesLocal">
<label for="hideFilteredStatuses">
{{$t('settings.hide_filtered_statuses')}} {{$t('settings.instance_default', { value: hideFilteredStatusesDefault })}}
</label>
</div>
</div>
</div>
<div :label="$t('settings.version.title')" >
<div class="setting-item">
<ul class="setting-list">
<li>
<p>{{$t('settings.version.backend_version')}}</p>
<ul class="option-list">
<li>
<a :href="backendVersionLink" target="_blank">{{backendVersion}}</a>
</li>
</ul>
</li>
<li>
<p>{{$t('settings.version.frontend_version')}}</p>
<ul class="option-list">
<li>
<a :href="frontendVersionLink" target="_blank">{{frontendVersion}}</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</tab-switcher>
</keep-alive>
</div>
@ -244,6 +328,7 @@
textarea {
width: 100%;
max-width: 100%;
height: 100px;
}
@ -253,25 +338,15 @@
color: $fallback--cRed;
}
.old-avatar {
width: 128px;
border-radius: $fallback--avatarRadius;
border-radius: var(--avatarRadius, $fallback--avatarRadius);
}
.new-avatar {
object-fit: cover;
width: 128px;
height: 128px;
border-radius: $fallback--avatarRadius;
border-radius: var(--avatarRadius, $fallback--avatarRadius);
}
.btn {
min-height: 28px;
min-width: 10em;
padding: 0 2em;
}
.number-input {
max-width: 6em;
}
}
.select-multiple {
display: flex;

View File

@ -0,0 +1,56 @@
import UserCard from '../user_card/user_card.vue'
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
import GestureService from '../../services/gesture_service/gesture_service'
const SideDrawer = {
props: [ 'logout' ],
data: () => ({
closed: true,
closeGesture: undefined
}),
created () {
this.closeGesture = GestureService.swipeGesture(GestureService.DIRECTION_LEFT, this.toggleDrawer)
},
components: { UserCard },
computed: {
currentUser () {
return this.$store.state.users.currentUser
},
chat () { return this.$store.state.chat.channel.state === 'joined' },
unseenNotifications () {
return unseenNotificationsFromStore(this.$store)
},
unseenNotificationsCount () {
return this.unseenNotifications.length
},
suggestionsEnabled () {
return this.$store.state.instance.suggestionsEnabled
},
logo () {
return this.$store.state.instance.logo
},
sitename () {
return this.$store.state.instance.name
},
followRequestCount () {
return this.$store.state.api.followRequests.length
}
},
methods: {
toggleDrawer () {
this.closed = !this.closed
},
doLogout () {
this.logout()
this.toggleDrawer()
},
touchStart (e) {
GestureService.beginSwipe(e, this.closeGesture)
},
touchMove (e) {
GestureService.updateSwipe(e, this.closeGesture)
}
}
}
export default SideDrawer

View File

@ -0,0 +1,222 @@
<template>
<div class="side-drawer-container"
:class="{ 'side-drawer-container-closed': closed, 'side-drawer-container-open': !closed }"
>
<div class="side-drawer-darken" :class="{ 'side-drawer-darken-closed': closed}" />
<div class="side-drawer"
:class="{'side-drawer-closed': closed}"
@touchstart="touchStart"
@touchmove="touchMove"
>
<div class="side-drawer-heading" @click="toggleDrawer">
<UserCard :user="currentUser" :hideBio="true" v-if="currentUser"/>
<div class="side-drawer-logo-wrapper" v-else>
<img :src="logo"/>
<span>{{sitename}}</span>
</div>
</div>
<ul>
<li v-if="!currentUser" @click="toggleDrawer">
<router-link :to="{ name: 'login' }">
{{ $t("login.login") }}
</router-link>
</li>
<li v-if="currentUser" @click="toggleDrawer">
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
{{ $t("nav.dms") }}
</router-link>
</li>
</ul>
<ul>
<li v-if="currentUser" @click="toggleDrawer">
<router-link :to="{ name: 'friends' }">
{{ $t("nav.timeline") }}
</router-link>
</li>
<li v-if="currentUser && currentUser.locked" @click="toggleDrawer">
<router-link to='/friend-requests'>
{{ $t("nav.friend_requests") }}
<span v-if='followRequestCount > 0' class="badge follow-request-count">
{{followRequestCount}}
</span>
</router-link>
</li>
<li @click="toggleDrawer">
<router-link to='/main/public'>
{{ $t("nav.public_tl") }}
</router-link>
</li>
<li @click="toggleDrawer">
<router-link to='/main/all'>
{{ $t("nav.twkn") }}
</router-link>
</li>
<li v-if="currentUser && chat" @click="toggleDrawer">
<router-link :to="{ name: 'chat' }">
{{ $t("nav.chat") }}
</router-link>
</li>
</ul>
<ul>
<li @click="toggleDrawer">
<router-link :to="{ name: 'user-search' }">
{{ $t("nav.user_search") }}
</router-link>
</li>
<li v-if="currentUser && suggestionsEnabled" @click="toggleDrawer">
<router-link :to="{ name: 'who-to-follow' }">
{{ $t("nav.who_to_follow") }}
</router-link>
</li>
<li @click="toggleDrawer">
<router-link :to="{ name: 'settings' }">
{{ $t("settings.settings") }}
</router-link>
</li>
<li @click="toggleDrawer">
<router-link :to="{ name: 'about'}">
{{ $t("nav.about") }}
</router-link>
</li>
<li v-if="currentUser" @click="toggleDrawer">
<a @click="doLogout" href="#">
{{ $t("login.logout") }}
</a>
</li>
</ul>
</div>
<div class="side-drawer-click-outside"
@click.stop.prevent="toggleDrawer"
:class="{'side-drawer-click-outside-closed': closed}"
></div>
</div>
</template>
<script src="./side_drawer.js" ></script>
<style lang="scss">
@import '../../_variables.scss';
.side-drawer-container {
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: stretch;
transition-duration: 0s;
transition-property: transform;
}
.side-drawer-container-open {
transform: translate(0%);
}
.side-drawer-container-closed {
transition-delay: 0.35s;
transform: translate(-100%);
}
.side-drawer-darken {
top: 0;
left: 0;
width: 100vw;
height: 100vh;
position: fixed;
z-index: -1;
transition: 0.35s;
transition-property: background-color;
background-color: rgba(0, 0, 0, 0.5);
}
.side-drawer-darken-closed {
background-color: rgba(0, 0, 0, 0);
}
.side-drawer-click-outside {
flex: 1 1 100%;
}
.side-drawer {
overflow-x: hidden;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
transition: 0.35s;
transition-property: transform;
margin: 0 0 0 -100px;
padding: 0 0 1em 100px;
width: 80%;
max-width: 20em;
flex: 0 0 80%;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
box-shadow: var(--panelShadow);
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg);
}
.side-drawer-logo-wrapper {
display: flex;
align-items: center;
padding: 0.85em;
img {
flex: none;
height: 50px;
margin-right: 0.85em;
}
span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.side-drawer-click-outside-closed {
flex: 0 0 0;
}
.side-drawer-closed {
transform: translate(-100%);
}
.side-drawer-heading {
background: transparent;
flex-direction: column;
align-items: stretch;
display: flex;
padding: 0;
margin: 0;
}
.side-drawer ul {
list-style: none;
margin: 0;
padding: 0;
border-bottom: 1px solid;
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
margin: 0.2em 0;
}
.side-drawer ul:last-child {
border: 0;
}
.side-drawer li {
padding: 0;
a {
display: block;
padding: 0.5em 0.85em;
&:hover {
background-color: $fallback--lightBg;
background-color: var(--lightBg, $fallback--lightBg);
}
}
}
</style>

View File

@ -3,10 +3,15 @@ import FavoriteButton from '../favorite_button/favorite_button.vue'
import RetweetButton from '../retweet_button/retweet_button.vue'
import DeleteButton from '../delete_button/delete_button.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue'
import UserCardContent from '../user_card_content/user_card_content.vue'
import StillImage from '../still-image/still-image.vue'
import { filter, find } from 'lodash'
import UserCard from '../user_card/user_card.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import Gallery from '../gallery/gallery.vue'
import LinkPreview from '../link-preview/link-preview.vue'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import fileType from 'src/services/file_type/file_type.service'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import { mentionMatchesUrl, extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
import { filter, find, unescape } from 'lodash'
const Status = {
name: 'Status',
@ -18,7 +23,7 @@ const Status = {
'highlight',
'compact',
'replies',
'noReplyLinks',
'isPreview',
'noHeading',
'inlineExpanded'
],
@ -30,7 +35,8 @@ const Status = {
userExpanded: false,
preview: null,
showPreview: false,
showingTall: false,
showingTall: this.inConversation && this.focused,
showingLongSubject: false,
expandingSubject: typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
? !this.$store.state.instance.collapseMessageWithSubject
: !this.$store.state.config.collapseMessageWithSubject,
@ -72,9 +78,18 @@ const Status = {
return (this.$store.state.config.hideAttachments && !this.inConversation) ||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)
},
userProfileLink () {
return this.generateUserProfileLink(this.status.user.id, this.status.user.screen_name)
},
replyProfileLink () {
if (this.isReply) {
return this.generateUserProfileLink(this.status.in_reply_to_user_id, this.replyToName)
}
},
retweet () { return !!this.statusoid.retweeted_status },
retweeter () { return this.statusoid.user.name },
retweeter () { return this.statusoid.user.name || this.statusoid.user.screen_name },
retweeterHtml () { return this.statusoid.user.name_html },
retweeterProfileLink () { return this.generateUserProfileLink(this.statusoid.user.id, this.statusoid.user.screen_name) },
status () {
if (this.retweet) {
return this.statusoid.retweeted_status
@ -94,6 +109,14 @@ const Status = {
return hits
},
muted () { return !this.unmuted && (this.status.user.muted || this.muteWordHits.length > 0) },
hideFilteredStatuses () {
return typeof this.$store.state.config.hideFilteredStatuses === 'undefined'
? this.$store.state.instance.hideFilteredStatuses
: this.$store.state.config.hideFilteredStatuses
},
hideStatus () {
return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses)
},
isFocused () {
// retweet or root of an expanded conversation
if (this.focused) {
@ -115,20 +138,19 @@ const Status = {
const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
return lengthScore > 20
},
longSubject () {
return this.status.summary.length > 900
},
isReply () {
if (this.status.in_reply_to_status_id) {
return true
return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)
},
replyToName () {
if (this.status.in_reply_to_screen_name) {
return this.status.in_reply_to_screen_name
} else {
const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
return user && user.screen_name
}
// For private replies where we can't see the OP, in_reply_to_status_id will be null.
// So instead, check that the post starts with a @mention.
if (this.status.visibility === 'private') {
var textBody = this.status.text
if (this.status.summary !== null) {
textBody = textBody.substring(this.status.summary.length, textBody.length)
}
return textBody.startsWith('@')
}
return false
},
hideReply () {
if (this.$store.state.config.replyVisibility === 'all') {
@ -140,7 +162,7 @@ const Status = {
if (this.status.user.id === this.$store.state.users.currentUser.id) {
return false
}
if (this.status.activity_type === 'repeat') {
if (this.status.type === 'retweet') {
return false
}
var checkFollowing = this.$store.state.config.replyVisibility === 'following'
@ -173,7 +195,7 @@ const Status = {
return this.tallStatus
},
showingMore () {
return this.showingTall || (this.status.summary && this.expandingSubject)
return (this.tallStatus && this.showingTall) || (this.status.summary && this.expandingSubject)
},
nsfwClickthrough () {
if (!this.status.nsfw) {
@ -186,24 +208,55 @@ const Status = {
},
replySubject () {
if (!this.status.summary) return ''
const behavior = this.$store.state.config.subjectLineBehavior
const startsWithRe = this.status.summary.match(/^re[: ]/i)
const decodedSummary = unescape(this.status.summary)
const behavior = typeof this.$store.state.config.subjectLineBehavior === 'undefined'
? this.$store.state.instance.subjectLineBehavior
: this.$store.state.config.subjectLineBehavior
const startsWithRe = decodedSummary.match(/^re[: ]/i)
if (behavior !== 'noop' && startsWithRe || behavior === 'masto') {
return this.status.summary
return decodedSummary
} else if (behavior === 'email') {
return 're: '.concat(this.status.summary)
return 're: '.concat(decodedSummary)
} else if (behavior === 'noop') {
return ''
}
},
attachmentSize () {
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)) {
(this.$store.state.config.hideAttachmentsInConv && this.inConversation) ||
(this.status.attachments.length > this.maxThumbnails)) {
return 'hide'
} else if (this.compact) {
return 'small'
}
return 'normal'
},
galleryTypes () {
if (this.attachmentSize === 'hide') {
return []
}
return this.$store.state.config.playVideosInModal
? ['image', 'video']
: ['image']
},
galleryAttachments () {
return this.status.attachments.filter(
file => fileType.fileMatchesSomeType(this.galleryTypes, file)
)
},
nonGalleryAttachments () {
return this.status.attachments.filter(
file => !fileType.fileMatchesSomeType(this.galleryTypes, file)
)
},
maxThumbnails () {
return this.$store.state.config.maxThumbnails
},
contentHtml () {
if (!this.status.summary_html) {
return this.status.statusnet_html
}
return this.status.summary_html + '<br />' + this.status.statusnet_html
}
},
components: {
@ -212,8 +265,10 @@ const Status = {
RetweetButton,
DeleteButton,
PostStatusForm,
UserCardContent,
StillImage
UserCard,
UserAvatar,
Gallery,
LinkPreview
},
methods: {
visibilityIcon (visibility) {
@ -228,11 +283,32 @@ const Status = {
return 'icon-globe'
}
},
linkClicked ({target}) {
linkClicked (event) {
let { target } = event
if (target.tagName === 'SPAN') {
target = target.parentNode
}
if (target.tagName === 'A') {
if (target.className.match(/mention/)) {
const href = target.href
const attn = this.status.attentions.find(attn => mentionMatchesUrl(attn, href))
if (attn) {
event.stopPropagation()
event.preventDefault()
const link = this.generateUserProfileLink(attn.id, attn.screen_name)
this.$router.push(link)
return
}
}
if (target.className.match(/hashtag/)) {
// Extract tag name from link url
const tag = extractTagFromUrl(target.href)
if (tag) {
const link = this.generateTagLink(tag)
this.$router.push(link)
return
}
}
window.open(target.href, '_blank')
}
},
@ -240,7 +316,6 @@ const Status = {
this.replying = !this.replying
},
gotoOriginal (id) {
// only handled by conversation, not status_or_conversation
if (this.inConversation) {
this.$emit('goto', id)
}
@ -257,17 +332,17 @@ const Status = {
toggleShowMore () {
if (this.showingTall) {
this.showingTall = false
} else if (this.expandingSubject) {
} else if (this.expandingSubject && this.status.summary) {
this.expandingSubject = false
} else if (this.hideTallStatus) {
this.showingTall = true
} else if (this.hideSubjectStatus) {
} else if (this.hideSubjectStatus && this.status.summary) {
this.expandingSubject = true
}
},
replyEnter (id, event) {
this.showPreview = true
const targetId = Number(id)
const targetId = id
const statuses = this.$store.state.statuses.allStatuses
if (!this.preview) {
@ -285,16 +360,30 @@ const Status = {
},
replyLeave () {
this.showPreview = false
},
generateUserProfileLink (id, name) {
return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)
},
generateTagLink (tag) {
return `/tag/${tag}`
},
setMedia () {
const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
return () => this.$store.dispatch('setMedia', attachments)
}
},
watch: {
'highlight': function (id) {
id = Number(id)
if (this.status.id === id) {
let rect = this.$el.getBoundingClientRect()
if (rect.top < 100) {
window.scrollBy(0, rect.top - 200)
// Post is above screen, match its top to screen top
window.scrollBy(0, rect.top - 100)
} else if (rect.height >= (window.innerHeight - 50)) {
// Post we want to see is taller than screen so match its top to screen top
window.scrollBy(0, rect.top - 100)
} else if (rect.bottom > window.innerHeight - 50) {
// Post is below screen, match its bottom to screen bottom
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
}
}

View File

@ -1,102 +1,142 @@
<template>
<div class="status-el" v-if="!hideReply && !deleted" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
<template v-if="muted && !noReplyLinks">
<div class="status-el" v-if="!hideStatus" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
<template v-if="muted && !isPreview">
<div class="media status container muted">
<small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
<small>
<router-link :to="userProfileLink">
{{status.user.screen_name}}
</router-link>
</small>
<small class="muteWords">{{muteWordHits.join(', ')}}</small>
<a href="#" class="unmute" @click.prevent="toggleMute"><i class="icon-eye-off"></i></a>
<a href="#" class="unmute" @click.prevent="toggleMute"><i class="button-icon icon-eye-off"></i></a>
</div>
</template>
<template v-else>
<div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
<StillImage v-if="retweet" class='avatar' :class='{ "better-shadow": betterShadow }' :src="statusoid.user.profile_image_url_original"/>
<div v-if="retweet && !noHeading && !inConversation" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
<UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :src="statusoid.user.profile_image_url_original"/>
<div class="media-body faint">
<a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a>
<a v-else :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
<span class="user-name">
<router-link v-if="retweeterHtml" :to="retweeterProfileLink" v-html="retweeterHtml"/>
<router-link v-else :to="retweeterProfileLink">{{retweeter}}</router-link>
</span>
<i class='fa icon-retweet retweeted' :title="$t('tool_tip.repeat')"></i>
{{$t('timeline.repeated')}}
</div>
</div>
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status">
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]" :style="[ userStyle ]" class="media status">
<div v-if="!noHeading" class="media-left">
<a :href="status.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
<StillImage class='avatar' :class="{'avatar-compact': compact, 'better-shadow': betterShadow}" :src="status.user.profile_image_url_original"/>
</a>
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
<UserAvatar :compact="compact" :betterShadow="betterShadow" :src="status.user.profile_image_url_original"/>
</router-link>
</div>
<div class="status-body">
<div class="usercard media-body" v-if="userExpanded">
<user-card-content :user="status.user" :switcher="false"></user-card-content>
</div>
<div v-if="!noHeading" class="media-body container media-heading">
<div class="media-heading-left">
<div class="name-and-links">
<UserCard :user="status.user" :rounded="true" :bordered="true" class="status-usercard" v-if="userExpanded"/>
<div v-if="!noHeading" class="media-heading">
<div class="heading-name-row">
<div class="name-and-account-name">
<h4 class="user-name" v-if="status.user.name_html" v-html="status.user.name_html"></h4>
<h4 class="user-name" v-else>{{status.user.name}}</h4>
<span class="links">
<router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link>
<span v-if="status.in_reply_to_screen_name" class="faint reply-info">
<i class="icon-right-open"></i>
<router-link :to="{ name: 'user-profile', params: { id: status.in_reply_to_user_id } }">
{{status.in_reply_to_screen_name}}
</router-link>
</span>
<a v-if="isReply && !noReplyLinks" href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)" :title="$t('tool_tip.reply')">
<i class="icon-reply" @mouseenter="replyEnter(status.in_reply_to_status_id, $event)" @mouseout="replyLeave()"></i>
<router-link class="account-name" :to="userProfileLink">
{{status.user.screen_name}}
</router-link>
</div>
<span class="heading-right">
<router-link class="timeago faint-link" :to="{ name: 'conversation', params: { id: status.id } }">
<timeago :since="status.created_at" :auto-update="60"></timeago>
</router-link>
<div class="button-icon visibility-icon" v-if="status.visibility">
<i :class="visibilityIcon(status.visibility)" :title="status.visibility | capitalize"></i>
</div>
<a :href="status.external_url" target="_blank" v-if="!status.is_local && !isPreview" class="source_url" title="Source">
<i class="button-icon icon-link-ext-alt"></i>
</a>
<template v-if="expandable && !isPreview">
<a href="#" @click.prevent="toggleExpanded" title="Expand">
<i class="button-icon icon-plus-squared"></i>
</a>
</template>
<a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="button-icon icon-eye-off"></i></a>
</span>
</div>
<div class="heading-reply-row">
<div v-if="isReply" class="reply-to-and-accountname">
<a class="reply-to"
href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)"
:aria-label="$t('tool_tip.reply')"
@mouseenter.prevent.stop="replyEnter(status.in_reply_to_status_id, $event)"
@mouseleave.prevent.stop="replyLeave()"
>
<i class="button-icon icon-reply" v-if="!isPreview"></i>
<span class="faint-link reply-to-text">{{$t('status.reply_to')}}</span>
</a>
<router-link :to="replyProfileLink">
{{replyToName}}
</router-link>
<span class="faint replies-separator" v-if="replies && replies.length">
-
</span>
</div>
<h4 class="replies" v-if="inConversation && !noReplyLinks">
<small v-if="replies.length">Replies:</small>
<small class="reply-link" v-for="reply in replies">
<a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}}&nbsp;</a>
</small>
</h4>
</div>
<div class="media-heading-right">
<router-link class="timeago" :to="{ name: 'conversation', params: { id: status.id } }">
<timeago :since="status.created_at" :auto-update="60"></timeago>
</router-link>
<div class="visibility-icon" v-if="status.visibility">
<i :class="visibilityIcon(status.visibility)" :title="status.visibility | capitalize"></i>
<div class="replies" v-if="inConversation && !isPreview">
<span class="faint" v-if="replies && replies.length">{{$t('status.replies_list')}}</span>
<span class="reply-link faint" v-if="replies" v-for="reply in replies">
<a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}}</a>
</span>
</div>
<a :href="status.external_url" target="_blank" v-if="!status.is_local" class="source_url" title="Source">
<i class="icon-link-ext-alt"></i>
</a>
<template v-if="expandable">
<a href="#" @click.prevent="toggleExpanded" title="Expand">
<i class="icon-plus-squared"></i>
</a>
</template>
<a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="icon-eye-off"></i></a>
</div>
</div>
<div v-if="showPreview" class="status-preview-container">
<status class="status-preview" v-if="preview" :noReplyLinks="true" :statusoid="preview" :compact=true></status>
<status class="status-preview" v-if="preview" :isPreview="true" :statusoid="preview" :compact=true></status>
<div class="status-preview status-preview-loading" v-else>
<i class="icon-spin4 animate-spin"></i>
</div>
</div>
<div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper">
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">Show more</a>
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html" v-if="!hideSubjectStatus"></div>
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.summary" v-else></div>
<a v-if="hideSubjectStatus" href="#" class="cw-status-hider" @click.prevent="toggleShowMore">Show more</a>
<a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">Show less</a>
<div class="status-content-wrapper" :class="{ 'tall-status': !showingLongSubject }" v-if="longSubject">
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="!showingLongSubject" href="#" @click.prevent="showingLongSubject=true">{{$t("general.show_more")}}</a>
<div @click.prevent="linkClicked" class="status-content media-body" v-html="contentHtml"></div>
<a v-if="showingLongSubject" href="#" class="status-unhider" @click.prevent="showingLongSubject=false">{{$t("general.show_less")}}</a>
</div>
<div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper" v-else>
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">{{$t("general.show_more")}}</a>
<div @click.prevent="linkClicked" class="status-content media-body" v-html="contentHtml" v-if="!hideSubjectStatus"></div>
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.summary_html" v-else></div>
<a v-if="hideSubjectStatus" href="#" class="cw-status-hider" @click.prevent="toggleShowMore">{{$t("general.show_more")}}</a>
<a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">{{$t("general.show_less")}}</a>
</div>
<div v-if='status.attachments && !hideSubjectStatus' class='attachments media-body'>
<attachment :size="attachmentSize" :status-id="status.id" :nsfw="nsfwClickthrough" :attachment="attachment" v-for="attachment in status.attachments" :key="attachment.id">
</attachment>
<div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body">
<attachment
class="non-gallery"
v-for="attachment in nonGalleryAttachments"
:size="attachmentSize"
:nsfw="nsfwClickthrough"
:attachment="attachment"
:allowPlay="true"
:setMedia="setMedia()"
:key="attachment.id"
/>
<gallery
v-if="galleryAttachments.length > 0"
:nsfw="nsfwClickthrough"
:attachments="galleryAttachments"
:setMedia="setMedia()"
/>
</div>
<div v-if="!noHeading && !noReplyLinks" class='status-actions media-body'>
<div v-if="status.card && !hideSubjectStatus && !noHeading" class="link-preview media-body">
<link-preview :card="status.card" :size="attachmentSize" :nsfw="nsfwClickthrough" />
</div>
<div v-if="!noHeading && !isPreview" class='status-actions media-body'>
<div v-if="loggedIn">
<a href="#" v-on:click.prevent="toggleReplying" :title="$t('tool_tip.reply')">
<i class="icon-reply" :class="{'icon-reply-active': replying}"></i>
</a>
<i class="button-icon icon-reply" v-on:click.prevent="toggleReplying" :title="$t('tool_tip.reply')" :class="{'icon-reply-active': replying}"></i>
<span v-if="status.replies_count > 0">{{status.replies_count}}</span>
</div>
<retweet-button :visibility='status.visibility' :loggedIn='loggedIn' :status='status'></retweet-button>
<favorite-button :loggedIn='loggedIn' :status='status'></favorite-button>
@ -116,6 +156,8 @@
<style lang="scss">
@import '../../_variables.scss';
$status-margin: 0.75em;
.status-body {
flex: 1;
min-width: 0;
@ -171,13 +213,16 @@
}
}
.media-left {
margin-right: $status-margin;
}
.status-el {
hyphens: auto;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-word;
border-left-width: 0px;
line-height: 18px;
min-width: 0;
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
@ -198,58 +243,89 @@
.media-body {
flex: 1;
padding: 0;
margin: 0 0 0.25em 0.8em;
}
.usercard {
margin-bottom: .7em
.status-usercard {
margin-bottom: $status-margin;
}
.user-name {
white-space: nowrap;
font-size: 14px;
overflow: hidden;
flex-shrink: 0;
max-width: 85%;
font-weight: bold;
img {
width: 14px;
height: 14px;
vertical-align: middle;
object-fit: contain
}
}
.media-heading {
flex-wrap: nowrap;
line-height: 18px;
}
.media-heading-left {
padding: 0;
vertical-align: bottom;
flex-basis: 100%;
margin-bottom: 0.5em;
a {
display: inline-block;
word-break: break-all;
}
small {
font-weight: lighter;
}
h4 {
white-space: nowrap;
font-size: 14px;
margin-right: 0.25em;
overflow: hidden;
text-overflow: ellipsis;
}
.name-and-links {
.heading-name-row {
padding: 0;
flex: 1 0;
display: flex;
flex-wrap: wrap;
align-items: baseline;
justify-content: space-between;
line-height: 18px;
.name-and-account-name {
display: flex;
min-width: 0;
}
.user-name {
margin-right: .45em;
flex-shrink: 1;
margin-right: 0.4em;
overflow: hidden;
text-overflow: ellipsis;
}
img {
width: 14px;
height: 14px;
vertical-align: middle;
object-fit: contain
}
.account-name {
min-width: 1.6em;
margin-right: 0.4em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1 1 0;
}
}
.links {
.heading-right {
display: flex;
flex-shrink: 0;
}
.timeago {
margin-right: 0.2em;
}
.heading-reply-row {
align-content: baseline;
font-size: 12px;
color: $fallback--link;
color: var(--link, $fallback--link);
line-height: 18px;
max-width: 100%;
display: flex;
flex-wrap: wrap;
align-items: stretch;
a {
max-width: 100%;
text-overflow: ellipsis;
@ -257,42 +333,49 @@
white-space: nowrap;
}
}
.reply-to-and-accountname {
display: flex;
height: 18px;
margin-right: 0.5em;
overflow: hidden;
max-width: 100%;
.icon-reply {
transform: scaleX(-1);
}
}
.reply-info {
display: flex;
}
.reply-to {
display: flex;
}
.reply-to-text {
overflow: hidden;
text-overflow: ellipsis;
margin: 0 0.4em 0 0.2em;
}
.replies-separator {
margin-left: 0.4em;
}
.replies {
line-height: 16px;
}
.reply-link {
margin-right: 0.2em;
}
}
.media-heading-right {
display: inline-flex;
flex-shrink: 0;
flex-wrap: nowrap;
margin-left: .25em;
align-self: baseline;
.timeago {
margin-right: 0.2em;
line-height: 18px;
font-size: 12px;
align-self: last baseline;
display: flex;
flex-wrap: wrap;
& > * {
margin-right: 0.4em;
}
}
> * {
margin-left: 0.2em;
.reply-link {
height: 17px;
}
a:hover i {
color: $fallback--text;
color: var(--text, $fallback--text);
}
}
a {
display: inline-block;
word-break: break-all;
}
.tall-status {
@ -303,6 +386,8 @@
}
.tall-status-hider {
display: inline-block;
word-break: break-all;
position: absolute;
height: 70px;
margin-top: 150px;
@ -320,17 +405,24 @@
.status-unhider, .cw-status-hider {
width: 100%;
text-align: center;
display: inline-block;
word-break: break-all;
}
.status-content {
margin-right: 0.5em;
font-family: var(--postFont, sans-serif);
line-height: 1.4em;
img, video {
max-width: 100%;
max-height: 400px;
vertical-align: middle;
object-fit: contain;
&.emoji {
width: 32px;
height: 32px;
}
}
blockquote {
@ -347,9 +439,11 @@
}
p {
margin: 0;
margin-top: 0.2em;
margin-bottom: 0.5em;
margin: 0 0 1em 0;
}
p:last-child {
margin: 0 0 0 0;
}
h1 {
@ -374,10 +468,10 @@
}
.retweet-info {
padding: 0.4em 0.6em 0 0.6em;
padding: 0.4em $status-margin;
margin: 0;
.avatar {
.avatar.still-image {
border-radius: $fallback--avatarAltRadius;
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
margin-left: 28px;
@ -395,6 +489,8 @@
.user-name {
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
img {
width: 14px;
@ -443,10 +539,10 @@
.status-actions {
width: 100%;
display: flex;
margin-top: $status-margin;
div, favorite-button {
padding-top: 0.25em;
max-width: 6em;
max-width: 4em;
flex: 1;
}
}
@ -454,6 +550,7 @@
.icon-reply:hover {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
cursor: pointer;
}
.icon-reply.icon-reply-active {
@ -461,46 +558,6 @@
color: var(--cBlue, $fallback--cBlue);
}
.status .avatar-compact {
width: 32px;
height: 32px;
box-shadow: var(--avatarStatusShadow);
border-radius: $fallback--avatarAltRadius;
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
&.better-shadow {
box-shadow: var(--avatarStatusShadowInset);
filter: var(--avatarStatusShadowFilter)
}
}
.avatar {
width: 48px;
height: 48px;
box-shadow: var(--avatarStatusShadow);
border-radius: $fallback--avatarRadius;
border-radius: var(--avatarRadius, $fallback--avatarRadius);
overflow: hidden;
position: relative;
&.better-shadow {
box-shadow: var(--avatarStatusShadowInset);
filter: var(--avatarStatusShadowFilter)
}
img {
width: 100%;
height: 100%;
}
&.animated::before {
display: none;
}
&.retweeted {
}
}
.status:hover .animated.avatar {
canvas {
display: none;
@ -512,9 +569,9 @@
.status {
display: flex;
padding: 0.6em;
padding: $status-margin;
&.is-retweet {
padding-top: 0.1em;
padding-top: 0;
}
}
@ -549,16 +606,16 @@ a.unmute {
.timeline > {
.status-el:last-child {
border-bottom-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-bottom: none;
}
}
@media all and (max-width: 960px) {
@media all and (max-width: 800px) {
.status-el {
.retweet-info {
.avatar {
.avatar.still-image {
margin-left: 20px;
}
}
@ -567,14 +624,14 @@ a.unmute {
max-width: 100%;
}
.status .avatar {
.status .avatar.still-image {
width: 40px;
height: 40px;
}
.status .avatar-compact {
width: 32px;
height: 32px;
&.avatar-compact {
width: 32px;
height: 32px;
}
}
}

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